for _, tt := range udpConnLocalNameTests {
c, err := ListenUDP(tt.net, tt.laddr)
if err != nil {
- t.Errorf("ListenUDP failed: %v", err)
- return
+ t.Fatalf("ListenUDP failed: %v", err)
}
defer c.Close()
la := c.LocalAddr()
if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
- t.Errorf("got %v; expected a proper address with non-zero port number", la)
- return
+ t.Fatalf("got %v; expected a proper address with non-zero port number", la)
+ }
+ }
+}
+
+func TestUDPConnLocalAndRemoteNames(t *testing.T) {
+ for _, laddr := range []string{"", "127.0.0.1:0"} {
+ c1, err := ListenPacket("udp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("ListenUDP failed: %v", err)
+ }
+ defer c1.Close()
+
+ var la *UDPAddr
+ if laddr != "" {
+ var err error
+ if la, err = ResolveUDPAddr("udp", laddr); err != nil {
+ t.Fatalf("ResolveUDPAddr failed: %v", err)
+ }
+ }
+ c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr))
+ if err != nil {
+ t.Fatalf("DialUDP failed: %v", err)
+ }
+ defer c2.Close()
+
+ var connAddrs = [4]struct {
+ got Addr
+ ok bool
+ }{
+ {c1.LocalAddr(), true},
+ {c1.(*UDPConn).RemoteAddr(), false},
+ {c2.LocalAddr(), true},
+ {c2.RemoteAddr(), true},
+ }
+ for _, ca := range connAddrs {
+ if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 {
+ t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got)
+ }
}
}
}
off := make(chan bool)
data := [5]byte{1, 2, 3, 4, 5}
-
go func() {
defer func() { off <- true }()
s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
n, from, err := c.ReadFrom(b)
if err != nil {
- t.Errorf("UnixConn.ReadFrom failed: %v", err)
- return
+ t.Fatalf("UnixConn.ReadFrom failed: %v", err)
}
if from != nil {
- t.Errorf("neighbor address is %v", from)
+ t.Fatalf("neighbor address is %v", from)
}
if !bytes.Equal(b[:n], data[:]) {
- t.Errorf("got %v, want %v", b[:n], data[:])
- return
+ t.Fatalf("got %v, want %v", b[:n], data[:])
}
}
<-off
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
- var peer Addr
- if _, peer, err = c.ReadFrom(nil); err != nil {
- t.Errorf("UnixConn.ReadFrom failed: %v", err)
- return
+ _, from, err := c.ReadFrom(nil)
+ if err != nil {
+ t.Fatalf("UnixConn.ReadFrom failed: %v", err)
}
- if peer != nil {
- t.Errorf("peer adddress is %v", peer)
+ if from != nil {
+ t.Fatalf("neighbor address is %v", from)
}
}
// retrieve the autobind address
autoAddr := c1.LocalAddr().(*UnixAddr)
if len(autoAddr.Name) <= 1 {
- t.Fatalf("Invalid autobind address: %v", autoAddr)
+ t.Fatalf("invalid autobind address: %v", autoAddr)
}
if autoAddr.Name[0] != '@' {
- t.Fatalf("Invalid autobind address: %v", autoAddr)
+ t.Fatalf("invalid autobind address: %v", autoAddr)
}
c2, err := DialUnix("unixgram", nil, autoAddr)
defer c2.Close()
if !reflect.DeepEqual(c1.LocalAddr(), c2.RemoteAddr()) {
- t.Fatalf("Expected autobind address %v, got %v", c1.LocalAddr(), c2.RemoteAddr())
+ t.Fatalf("expected autobind address %v, got %v", c1.LocalAddr(), c2.RemoteAddr())
+ }
+}
+
+func TestUnixConnLocalAndRemoteNames(t *testing.T) {
+ for _, laddr := range []string{"", testUnixAddr()} {
+ taddr := testUnixAddr()
+ ta, err := ResolveUnixAddr("unix", taddr)
+ if err != nil {
+ t.Fatalf("ResolveUnixAddr failed: %v", err)
+ }
+ ln, err := ListenUnix("unix", ta)
+ if err != nil {
+ t.Fatalf("ListenUnix failed: %v", err)
+ }
+ defer func() {
+ ln.Close()
+ os.Remove(taddr)
+ }()
+
+ done := make(chan int)
+ go transponder(t, ln, done)
+
+ la, err := ResolveUnixAddr("unix", laddr)
+ if err != nil {
+ t.Fatalf("ResolveUnixAddr failed: %v", err)
+ }
+ c, err := DialUnix("unix", la, ta)
+ if err != nil {
+ t.Fatalf("DialUnix failed: %v", err)
+ }
+ defer func() {
+ c.Close()
+ if la != nil {
+ defer os.Remove(laddr)
+ }
+ }()
+ if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
+ t.Fatalf("UnixConn.Write failed: %v", err)
+ }
+
+ if runtime.GOOS == "linux" && laddr == "" {
+ laddr = "@" // autobind feature
+ }
+ var connAddrs = [3]struct{ got, want Addr }{
+ {ln.Addr(), ta},
+ {c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
+ {c.RemoteAddr(), ta},
+ }
+ for _, ca := range connAddrs {
+ if !reflect.DeepEqual(ca.got, ca.want) {
+ t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
+ }
+ }
+
+ <-done
+ }
+}
+
+func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
+ for _, laddr := range []string{"", testUnixAddr()} {
+ taddr := testUnixAddr()
+ ta, err := ResolveUnixAddr("unixgram", taddr)
+ if err != nil {
+ t.Fatalf("ResolveUnixAddr failed: %v", err)
+ }
+ c1, err := ListenUnixgram("unixgram", ta)
+ if err != nil {
+ t.Fatalf("ListenUnixgram failed: %v", err)
+ }
+ defer func() {
+ c1.Close()
+ os.Remove(taddr)
+ }()
+
+ var la *UnixAddr
+ if laddr != "" {
+ var err error
+ if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
+ t.Fatalf("ResolveUnixAddr failed: %v", err)
+ }
+ }
+ c2, err := DialUnix("unixgram", la, ta)
+ if err != nil {
+ t.Fatalf("DialUnix failed: %v", err)
+ }
+ defer func() {
+ c2.Close()
+ if la != nil {
+ defer os.Remove(laddr)
+ }
+ }()
+
+ if runtime.GOOS == "linux" && laddr == "" {
+ laddr = "@" // autobind feature
+ }
+ var connAddrs = [4]struct{ got, want Addr }{
+ {c1.LocalAddr(), ta},
+ {c1.RemoteAddr(), nil},
+ {c2.LocalAddr(), &UnixAddr{Name: laddr, Net: "unixgram"}},
+ {c2.RemoteAddr(), ta},
+ }
+ for _, ca := range connAddrs {
+ if !reflect.DeepEqual(ca.got, ca.want) {
+ t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
+ }
+ }
}
}
"time"
)
+func (a *UnixAddr) isUnnamed() bool {
+ if a == nil || a.Name == "" {
+ return true
+ }
+ return false
+}
+
func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.Time) (*netFD, error) {
var sotype int
switch net {
var la, ra syscall.Sockaddr
switch mode {
case "dial":
- if laddr != nil {
+ if !laddr.isUnnamed() {
la = &syscall.SockaddrUnix{Name: laddr.Name}
}
if raddr != nil {
ra = &syscall.SockaddrUnix{Name: raddr.Name}
- } else if sotype != syscall.SOCK_DGRAM || laddr == nil {
+ } else if sotype != syscall.SOCK_DGRAM || laddr.isUnnamed() {
return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
}
case "listen":
func sockaddrToUnix(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok {
- return &UnixAddr{s.Name, "unix"}
+ return &UnixAddr{Name: s.Name, Net: "unix"}
}
return nil
}
func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok {
- return &UnixAddr{s.Name, "unixgram"}
+ return &UnixAddr{Name: s.Name, Net: "unixgram"}
}
return nil
}
func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok {
- return &UnixAddr{s.Name, "unixpacket"}
+ return &UnixAddr{Name: s.Name, Net: "unixpacket"}
}
return nil
}
switch sotype {
case syscall.SOCK_STREAM:
return "unix"
- case syscall.SOCK_SEQPACKET:
- return "unixpacket"
case syscall.SOCK_DGRAM:
return "unixgram"
+ case syscall.SOCK_SEQPACKET:
+ return "unixpacket"
default:
panic("sotypeToNet unknown socket type")
}
switch sa := sa.(type) {
case *syscall.SockaddrUnix:
if sa.Name != "" {
- addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
+ addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
}
}
return
switch sa := sa.(type) {
case *syscall.SockaddrUnix:
if sa.Name != "" {
- addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
+ addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
}
}
return