]> Cypherpunks repositories - gostls13.git/commitdiff
add Addr() string to net.Listener interface.
authorRuss Cox <rsc@golang.org>
Thu, 18 Jun 2009 04:44:26 +0000 (21:44 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 18 Jun 2009 04:44:26 +0000 (21:44 -0700)
use it to avoid use of fixed ports in tests.
convert google/net/rpc to gotest

R=r
DELTA=523  (275 added, 229 deleted, 19 changed)
OCL=30458
CL=30460

src/pkg/Makefile
src/pkg/net/fd.go
src/pkg/net/net.go
src/pkg/net/server_test.go
src/pkg/syscall/syscall_darwin.go
src/pkg/syscall/syscall_linux.go
src/pkg/syscall/syscall_linux_386.go
src/pkg/syscall/syscall_linux_amd64.go
src/pkg/syscall/zsyscall_darwin_386.go
src/pkg/syscall/zsyscall_darwin_amd64.go
src/pkg/syscall/zsyscall_linux_amd64.go

index 3339a9d3697b08b959c3eec499218e6b916d554c..b8eb8641ab9cba85f56940e746005d2999803ce4 100644 (file)
@@ -70,12 +70,14 @@ TEST=\
        archive/tar\
        bignum\
        bufio\
+       bytes\
        compress/flate\
        compress/gzip\
        container/list\
        container/vector\
        crypto/aes\
        crypto/block\
+       crypto/hmac\
        crypto/md5\
        crypto/sha1\
        datafmt\
index 9404ed0bd43a7388a6fe390b921f7cff0969ea48..befcd554fe7f3f681a97617c30cb761d0526d320 100644 (file)
@@ -427,3 +427,12 @@ func (fd *netFD) accept() (nfd *netFD, err os.Error) {
        return nfd, nil
 }
 
+func (fd *netFD) addr() string {
+       sa, err := syscall.Getsockname(fd.fd);
+       if err != 0 {
+               return "";
+       }
+       // TODO(rsc): woud like to say err not err1 but 6g complains
+       addr, err1 := sockaddrToString(sa);
+       return addr;
+}
index 5c442e6a4555a643da01b2632c2dbac49711495c..8d7e7ba3285fa879a822d38fbcea7af29bdfa573 100644 (file)
@@ -440,18 +440,15 @@ func internetSocket(net, laddr, raddr string, proto int, mode string) (fd *netFD
        // Parse addresses (unless they are empty).
        var lip, rip IP;
        var lport, rport int;
-       var lerr, rerr os.Error;
 
        if laddr != "" {
-               lip, lport, lerr = hostPortToIP(net, laddr, mode);
-               if lerr != nil {
-                       return nil, lerr
+               if lip, lport, err = hostPortToIP(net, laddr, mode); err != nil {
+                       return
                }
        }
        if raddr != "" {
-               rip, rport, rerr = hostPortToIP(net, raddr, mode);
-               if rerr != nil {
-                       return nil, rerr
+               if rip, rport, err = hostPortToIP(net, raddr, mode); err != nil {
+                       return
                }
        }
 
@@ -482,15 +479,13 @@ func internetSocket(net, laddr, raddr string, proto int, mode string) (fd *netFD
 
        var la, ra syscall.Sockaddr;
        if lip != nil {
-               la, lerr = ipToSockaddr(family, lip, lport);
-               if lerr != nil {
-                       return nil, lerr
+               if la, err = ipToSockaddr(family, lip, lport); err != nil {
+                       return
                }
        }
        if rip != nil {
-               ra, rerr = ipToSockaddr(family, rip, rport);
-               if rerr != nil {
-                       return nil, rerr
+               if ra, err = ipToSockaddr(family, rip, rport); err != nil {
+                       return
                }
        }
 
@@ -727,6 +722,11 @@ func (l *ListenerUnix) Close() os.Error {
        return err;
 }
 
+// Addr returns the listener's network address.
+func (l *ListenerUnix) Addr() string {
+       return l.fd.addr();
+}
+
 // Dial connects to the remote address raddr on the network net.
 // If the string laddr is not empty, it is used as the local address
 // for the connection.
@@ -776,6 +776,7 @@ func Dial(net, laddr, raddr string) (c Conn, err os.Error) {
 type Listener interface {
        Accept() (c Conn, raddr string, err os.Error);
        Close() os.Error;
+       Addr() string;  // Listener's network address
 }
 
 // ListenerTCP is a TCP network listener.
@@ -783,11 +784,12 @@ type Listener interface {
 // instead of assuming TCP.
 type ListenerTCP struct {
        fd *netFD;
-       laddr string
 }
 
 // ListenTCP announces on the TCP address laddr and returns a TCP listener.
 // Net must be "tcp", "tcp4", or "tcp6".
+// If laddr has a port of 0, it means to listen on some available port.
+// The caller can use l.Addr() to retrieve the chosen address.
 func ListenTCP(net, laddr string) (l *ListenerTCP, err os.Error) {
        fd, e := internetSocket(net, laddr, "", syscall.SOCK_STREAM, "listen");
        if e != nil {
@@ -835,6 +837,11 @@ func (l *ListenerTCP) Close() os.Error {
        return l.fd.Close()
 }
 
+// Addr returns the listener's network address.
+func (l *ListenerTCP) Addr() string {
+       return l.fd.addr();
+}
+
 // Listen announces on the local network address laddr.
 // The network string net must be "tcp", "tcp4", "tcp6",
 // "unix", or "unix-dgram".
index 586b553659921a0d288c83f5d43d13d882c339ef..f1c7134e441984b375199afaae24bbb0610ba526 100644 (file)
@@ -8,6 +8,7 @@ import (
        "io";
        "net";
        "os";
+       "strings";
        "syscall";
        "testing";
 )
@@ -25,12 +26,12 @@ func runEcho(fd io.ReadWriter, done chan<- int) {
        done <- 1
 }
 
-func runServe(t *testing.T, network, addr string, listening, done chan<- int) {
+func runServe(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
        l, err := net.Listen(network, addr);
        if err != nil {
                t.Fatalf("net.Listen(%q, %q) = _, %v", network, addr, err);
        }
-       listening <- 1;
+       listening <- l.Addr();
 
        for {
                fd, addr, err := l.Accept();
@@ -68,20 +69,26 @@ func connect(t *testing.T, network, addr string) {
 
 func doTest(t *testing.T, network, listenaddr, dialaddr string) {
        t.Logf("Test %s %s %s\n", network, listenaddr, dialaddr);
-       listening := make(chan int);
+       listening := make(chan string);
        done := make(chan int);
+       if network == "tcp" {
+               listenaddr += ":0";     // any available port
+       }
        go runServe(t, network, listenaddr, listening, done);
-       <-listening;    // wait for server to start
+       addr := <-listening;    // wait for server to start
+       if network == "tcp" {
+               dialaddr += addr[strings.LastIndex(addr, ":"):len(addr)];
+       }
        connect(t, network, dialaddr);
        <-done; // make sure server stopped
 }
 
 func TestTcpServer(t *testing.T) {
-       doTest(t,  "tcp", "0.0.0.0:9997", "127.0.0.1:9997");
-       doTest(t, "tcp", "[::]:9997", "[::ffff:127.0.0.1]:9997");
-       doTest(t, "tcp", "[::]:9997", "127.0.0.1:9997");
-       doTest(t, "tcp", ":9997", "127.0.0.1:9997");
-       doTest(t, "tcp", "0.0.0.0:9997", "[::ffff:127.0.0.1]:9997");
+       doTest(t,  "tcp", "0.0.0.0", "127.0.0.1");
+       doTest(t, "tcp", "[::]", "[::ffff:127.0.0.1]");
+       doTest(t, "tcp", "[::]", "127.0.0.1");
+       doTest(t, "tcp", "", "127.0.0.1");
+       doTest(t, "tcp", "0.0.0.0", "[::ffff:127.0.0.1]");
 }
 
 func TestUnixServer(t *testing.T) {
index 8ea78c66755427e787b35780927ff25e01650d76..dcb92e0aca18a340f223e047f55e990154e76cb6 100644 (file)
@@ -164,6 +164,8 @@ func Sleep(ns int64) (errno int) {
 //sys  connect(s int, addr uintptr, addrlen _Socklen) (errno int)
 //sys  socket(domain int, typ int, proto int) (fd int, errno int)
 //sys  setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int)
+//sys  getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
+//sys  getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
 
 // For testing: clients can set this flag to force
 // creation of IPv6 sockets to return EAFNOSUPPORT.
@@ -292,6 +294,24 @@ func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
        return;
 }
 
+func Getsockname(fd int) (sa Sockaddr, errno int) {
+       var rsa RawSockaddrAny;
+       var len _Socklen = SizeofSockaddrAny;
+       if errno = getsockname(fd, &rsa, &len); errno != 0 {
+               return;
+       }
+       return anyToSockaddr(&rsa);
+}
+
+func Getpeername(fd int) (sa Sockaddr, errno int) {
+       var rsa RawSockaddrAny;
+       var len _Socklen = SizeofSockaddrAny;
+       if errno = getpeername(fd, &rsa, &len); errno != 0 {
+               return;
+       }
+       return anyToSockaddr(&rsa);
+}
+
 func Bind(fd int, sa Sockaddr) (errno int) {
        ptr, n, err := sa.sockaddr();
        if err != 0 {
@@ -345,8 +365,6 @@ func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno
 //     Acct(name nil-string) (errno int)
 //     Futimes(fd int, timeval *Timeval) (errno int)   // Pointer to 2 timevals!
 //     Gethostuuid(uuid *byte, timeout *Timespec) (errno int)
-//     Getpeername(fd int, addr *Sockaddr, addrlen *int) (errno int)
-//     Getsockname(fd int, addr *Sockaddr, addrlen *int) (errno int)
 //     Getsockopt(s int, level int, name int, val *byte, vallen *int) (errno int)
 //     Madvise(addr *byte, len int, behav int) (errno int)
 //     Mprotect(addr *byte, len int, prot int) (errno int)
index ae3eee777c2632c236c266105cf91dd509d9fb88..4c9ac287564dc98200cfe389021324fbe7eeebf3 100644 (file)
@@ -324,6 +324,24 @@ func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
        return;
 }
 
+func Getsockname(fd int) (sa Sockaddr, errno int) {
+       var rsa RawSockaddrAny;
+       var len _Socklen = SizeofSockaddrAny;
+       if errno = getsockname(fd, &rsa, &len); errno != 0 {
+               return;
+       }
+       return anyToSockaddr(&rsa);
+}
+
+func Getpeername(fd int) (sa Sockaddr, errno int) {
+       var rsa RawSockaddrAny;
+       var len _Socklen = SizeofSockaddrAny;
+       if errno = getpeername(fd, &rsa, &len); errno != 0 {
+               return;
+       }
+       return anyToSockaddr(&rsa);
+}
+
 func Bind(fd int, sa Sockaddr) (errno int) {
        ptr, n, err := sa.sockaddr();
        if err != 0 {
index f20ec106149c463e90668a0ec95c7c087d08eb44..b44428e119556812d13f1bec5adca71fa822625d 100644 (file)
@@ -99,6 +99,18 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
        return;
 }
 
+func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+       var _ int;
+       _, errno = socketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0);
+       return;
+}
+
+func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+       var _ int;
+       _, errno = socketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0);
+       return;
+}
+
 func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
        var _ int;
        _, errno = socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0);
@@ -127,4 +139,3 @@ func Listen(s int, n int) (errno int) {
        _, errno = socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0);
        return;
 }
-
index 3455184796fa35a08bfd002f859cc422a15f7e58..4f7b33bc12adf735d0eb1674db6d7370159c6962 100644 (file)
@@ -36,6 +36,8 @@ import "syscall"
 //sys  setgroups(n int, list *_Gid_t) (errno int)
 //sys  setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int)
 //sys  socket(domain int, typ int, proto int) (fd int, errno int)
+//sys  getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
+//sys  getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
 
 func Getpagesize() int {
        return 4096
index 6974c83bf832829dff3339625b0083f9059b0221..6241efa51453b6f71cdb6c29ccd179b9abd16987 100644 (file)
@@ -68,6 +68,18 @@ func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int)
        return;
 }
 
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+       r0, r1, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
+       errno = int(e1);
+       return;
+}
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+       r0, r1, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
+       errno = int(e1);
+       return;
+}
+
 func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
        r0, r1, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)));
        n = int(r0);
index e6b99916e4f66e42efd296c820fbfddb36c2d6f2..49e17d43b13a0d4aa6b3c8f75c307bdb605f2b16 100644 (file)
@@ -68,6 +68,18 @@ func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int)
        return;
 }
 
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+       r0, r1, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
+       errno = int(e1);
+       return;
+}
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+       r0, r1, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
+       errno = int(e1);
+       return;
+}
+
 func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
        r0, r1, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)));
        n = int(r0);
index 0766b8318f6c18f07a09256922129b955e2d3c1e..09f21df2ab052a7658ed64717583cd2a39897adc 100644 (file)
@@ -760,5 +760,17 @@ func socket(domain int, typ int, proto int) (fd int, errno int) {
        return;
 }
 
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+       r0, r1, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
+       errno = int(e1);
+       return;
+}
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+       r0, r1, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
+       errno = int(e1);
+       return;
+}
+