mirror of
https://github.com/golang/go
synced 2024-11-21 21:04:41 -07:00
net: add unixpacket
R=golang-dev, rsc, rsc1 CC=golang-dev https://golang.org/cl/2309043
This commit is contained in:
parent
eb56a79e99
commit
01fad6a6b0
@ -59,7 +59,7 @@ func Dial(net, laddr, raddr string) (c Conn, err os.Error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
case "unix", "unixgram":
|
case "unix", "unixgram", "unixpacket":
|
||||||
var la, ra *UnixAddr
|
var la, ra *UnixAddr
|
||||||
if raddr != "" {
|
if raddr != "" {
|
||||||
if ra, err = ResolveUnixAddr(net, raddr); err != nil {
|
if ra, err = ResolveUnixAddr(net, raddr); err != nil {
|
||||||
@ -102,7 +102,7 @@ Error:
|
|||||||
|
|
||||||
// Listen announces on the local network address laddr.
|
// Listen announces on the local network address laddr.
|
||||||
// The network string net must be a stream-oriented
|
// The network string net must be a stream-oriented
|
||||||
// network: "tcp", "tcp4", "tcp6", or "unix".
|
// network: "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
|
||||||
func Listen(net, laddr string) (l Listener, err os.Error) {
|
func Listen(net, laddr string) (l Listener, err os.Error) {
|
||||||
switch net {
|
switch net {
|
||||||
case "tcp", "tcp4", "tcp6":
|
case "tcp", "tcp4", "tcp6":
|
||||||
@ -117,7 +117,7 @@ func Listen(net, laddr string) (l Listener, err os.Error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return l, nil
|
return l, nil
|
||||||
case "unix":
|
case "unix", "unixpacket":
|
||||||
var la *UnixAddr
|
var la *UnixAddr
|
||||||
if laddr != "" {
|
if laddr != "" {
|
||||||
if la, err = ResolveUnixAddr(net, laddr); err != nil {
|
if la, err = ResolveUnixAddr(net, laddr); err != nil {
|
||||||
|
@ -52,6 +52,14 @@ var dialErrorTests = []DialErrorTest{
|
|||||||
"unix", "", "/etc/",
|
"unix", "", "/etc/",
|
||||||
"dial unix /etc/: (permission denied|socket operation on non-socket|connection refused)",
|
"dial unix /etc/: (permission denied|socket operation on non-socket|connection refused)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"unixpacket", "", "/etc/file-not-found",
|
||||||
|
"dial unixpacket /etc/file-not-found: no such file or directory",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"unixpacket", "", "/etc/",
|
||||||
|
"dial unixpacket /etc/: (permission denied|socket operation on non-socket|connection refused)",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDialError(t *testing.T) {
|
func TestDialError(t *testing.T) {
|
||||||
|
@ -116,9 +116,14 @@ func TestUnixServer(t *testing.T) {
|
|||||||
os.Remove("/tmp/gotest.net")
|
os.Remove("/tmp/gotest.net")
|
||||||
doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
|
doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
|
||||||
os.Remove("/tmp/gotest.net")
|
os.Remove("/tmp/gotest.net")
|
||||||
|
if syscall.OS != "darwin" {
|
||||||
|
doTest(t, "unixpacket", "/tmp/gotest.net", "/tmp/gotest.net")
|
||||||
|
os.Remove("/tmp/gotest.net")
|
||||||
|
}
|
||||||
if syscall.OS == "linux" {
|
if syscall.OS == "linux" {
|
||||||
// Test abstract unix domain socket, a Linux-ism
|
// Test abstract unix domain socket, a Linux-ism
|
||||||
doTest(t, "unix", "@gotest/net", "@gotest/net")
|
doTest(t, "unix", "@gotest/net", "@gotest/net")
|
||||||
|
doTest(t, "unixpacket", "@gotest/net", "@gotest/net")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
|
|||||||
proto = syscall.SOCK_STREAM
|
proto = syscall.SOCK_STREAM
|
||||||
case "unixgram":
|
case "unixgram":
|
||||||
proto = syscall.SOCK_DGRAM
|
proto = syscall.SOCK_DGRAM
|
||||||
|
case "unixpacket":
|
||||||
|
proto = syscall.SOCK_SEQPACKET
|
||||||
}
|
}
|
||||||
|
|
||||||
var la, ra syscall.Sockaddr
|
var la, ra syscall.Sockaddr
|
||||||
@ -48,9 +50,12 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
f := sockaddrToUnix
|
f := sockaddrToUnix
|
||||||
if proto != syscall.SOCK_STREAM {
|
if proto == syscall.SOCK_DGRAM {
|
||||||
f = sockaddrToUnixgram
|
f = sockaddrToUnixgram
|
||||||
|
} else if proto == syscall.SOCK_SEQPACKET {
|
||||||
|
f = sockaddrToUnixpacket
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f)
|
fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f)
|
||||||
if oserr != nil {
|
if oserr != nil {
|
||||||
goto Error
|
goto Error
|
||||||
@ -67,30 +72,48 @@ Error:
|
|||||||
|
|
||||||
// UnixAddr represents the address of a Unix domain socket end point.
|
// UnixAddr represents the address of a Unix domain socket end point.
|
||||||
type UnixAddr struct {
|
type UnixAddr struct {
|
||||||
Name string
|
Name string
|
||||||
Datagram bool
|
Net string
|
||||||
}
|
}
|
||||||
|
|
||||||
func sockaddrToUnix(sa syscall.Sockaddr) Addr {
|
func sockaddrToUnix(sa syscall.Sockaddr) Addr {
|
||||||
if s, ok := sa.(*syscall.SockaddrUnix); ok {
|
if s, ok := sa.(*syscall.SockaddrUnix); ok {
|
||||||
return &UnixAddr{s.Name, false}
|
return &UnixAddr{s.Name, "unix"}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
|
func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
|
||||||
if s, ok := sa.(*syscall.SockaddrUnix); ok {
|
if s, ok := sa.(*syscall.SockaddrUnix); ok {
|
||||||
return &UnixAddr{s.Name, true}
|
return &UnixAddr{s.Name, "unixgram"}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
|
||||||
|
if s, ok := sa.(*syscall.SockaddrUnix); ok {
|
||||||
|
return &UnixAddr{s.Name, "unixpacket"}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func protoToNet(proto int) string {
|
||||||
|
switch proto {
|
||||||
|
case syscall.SOCK_STREAM:
|
||||||
|
return "unix"
|
||||||
|
case syscall.SOCK_SEQPACKET:
|
||||||
|
return "unixpacket"
|
||||||
|
case syscall.SOCK_DGRAM:
|
||||||
|
return "unixgram"
|
||||||
|
default:
|
||||||
|
panic("protoToNet unknown protocol")
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// Network returns the address's network name, "unix" or "unixgram".
|
// Network returns the address's network name, "unix" or "unixgram".
|
||||||
func (a *UnixAddr) Network() string {
|
func (a *UnixAddr) Network() string {
|
||||||
if a == nil || !a.Datagram {
|
return a.Net
|
||||||
return "unix"
|
|
||||||
}
|
|
||||||
return "unixgram"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *UnixAddr) String() string {
|
func (a *UnixAddr) String() string {
|
||||||
@ -108,17 +131,17 @@ func (a *UnixAddr) toAddr() Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ResolveUnixAddr parses addr as a Unix domain socket address.
|
// ResolveUnixAddr parses addr as a Unix domain socket address.
|
||||||
// The string net gives the network name, "unix" or "unixgram".
|
// The string net gives the network name, "unix", "unixgram" or
|
||||||
|
// "unixpacket".
|
||||||
func ResolveUnixAddr(net, addr string) (*UnixAddr, os.Error) {
|
func ResolveUnixAddr(net, addr string) (*UnixAddr, os.Error) {
|
||||||
var datagram bool
|
|
||||||
switch net {
|
switch net {
|
||||||
case "unix":
|
case "unix":
|
||||||
|
case "unixpacket":
|
||||||
case "unixgram":
|
case "unixgram":
|
||||||
datagram = true
|
|
||||||
default:
|
default:
|
||||||
return nil, UnknownNetworkError(net)
|
return nil, UnknownNetworkError(net)
|
||||||
}
|
}
|
||||||
return &UnixAddr{addr, datagram}, nil
|
return &UnixAddr{addr, net}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnixConn is an implementation of the Conn interface
|
// UnixConn is an implementation of the Conn interface
|
||||||
@ -234,7 +257,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err os.Error)
|
|||||||
n, sa, err := c.fd.ReadFrom(b)
|
n, sa, err := c.fd.ReadFrom(b)
|
||||||
switch sa := sa.(type) {
|
switch sa := sa.(type) {
|
||||||
case *syscall.SockaddrUnix:
|
case *syscall.SockaddrUnix:
|
||||||
addr = &UnixAddr{sa.Name, c.fd.proto == syscall.SOCK_DGRAM}
|
addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -258,7 +281,7 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) {
|
|||||||
if !c.ok() {
|
if !c.ok() {
|
||||||
return 0, os.EINVAL
|
return 0, os.EINVAL
|
||||||
}
|
}
|
||||||
if addr.Datagram != (c.fd.proto == syscall.SOCK_DGRAM) {
|
if addr.Net != protoToNet(c.fd.proto) {
|
||||||
return 0, os.EAFNOSUPPORT
|
return 0, os.EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
sa := &syscall.SockaddrUnix{Name: addr.Name}
|
sa := &syscall.SockaddrUnix{Name: addr.Name}
|
||||||
@ -284,7 +307,7 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
|
|||||||
n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
|
n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
|
||||||
switch sa := sa.(type) {
|
switch sa := sa.(type) {
|
||||||
case *syscall.SockaddrUnix:
|
case *syscall.SockaddrUnix:
|
||||||
addr = &UnixAddr{sa.Name, c.fd.proto == syscall.SOCK_DGRAM}
|
addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -294,7 +317,7 @@ func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err
|
|||||||
return 0, 0, os.EINVAL
|
return 0, 0, os.EINVAL
|
||||||
}
|
}
|
||||||
if addr != nil {
|
if addr != nil {
|
||||||
if addr.Datagram != (c.fd.proto == syscall.SOCK_DGRAM) {
|
if addr.Net != protoToNet(c.fd.proto) {
|
||||||
return 0, 0, os.EAFNOSUPPORT
|
return 0, 0, os.EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
sa := &syscall.SockaddrUnix{Name: addr.Name}
|
sa := &syscall.SockaddrUnix{Name: addr.Name}
|
||||||
@ -330,11 +353,11 @@ type UnixListener struct {
|
|||||||
// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
|
// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
|
||||||
// Net must be "unix" (stream sockets).
|
// Net must be "unix" (stream sockets).
|
||||||
func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
|
func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
|
||||||
if net != "unix" && net != "unixgram" {
|
if net != "unix" && net != "unixgram" && net != "unixpacket" {
|
||||||
return nil, UnknownNetworkError(net)
|
return nil, UnknownNetworkError(net)
|
||||||
}
|
}
|
||||||
if laddr != nil {
|
if laddr != nil {
|
||||||
laddr = &UnixAddr{laddr.Name, net == "unixgram"} // make our own copy
|
laddr = &UnixAddr{laddr.Name, net} // make our own copy
|
||||||
}
|
}
|
||||||
fd, err := unixSocket(net, laddr, nil, "listen")
|
fd, err := unixSocket(net, laddr, nil, "listen")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user