1
0
mirror of https://github.com/golang/go synced 2024-11-18 10:54:40 -07:00

add Addr() string to net.Listener interface.

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
This commit is contained in:
Russ Cox 2009-06-17 21:44:26 -07:00
parent f39fcd7e42
commit 5d2ee9d90a
11 changed files with 136 additions and 26 deletions

View 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\

View 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;
}

View 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".

View 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) {

View 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)

View 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 {

View 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;
}

View 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

View 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);

View 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);

View 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;
}