diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-09 08:19:58 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-09 08:19:58 +0000 |
commit | 94252f4bcc0a3f487b804ce535cb77b8bef4db83 (patch) | |
tree | 7ca86535c5a6b99d4cc432ba5cfddabc5ee4ea16 /libgo/go/net | |
parent | cd6368115dbd75d9187877097c48a0d8d4c04fd4 (diff) | |
download | gcc-94252f4bcc0a3f487b804ce535cb77b8bef4db83.zip gcc-94252f4bcc0a3f487b804ce535cb77b8bef4db83.tar.gz gcc-94252f4bcc0a3f487b804ce535cb77b8bef4db83.tar.bz2 |
libgo: Update to weekly.2012-02-07.
From-SVN: r184034
Diffstat (limited to 'libgo/go/net')
56 files changed, 756 insertions, 589 deletions
diff --git a/libgo/go/net/dial_test.go b/libgo/go/net/dial_test.go index 16b7263..de35ec9 100644 --- a/libgo/go/net/dial_test.go +++ b/libgo/go/net/dial_test.go @@ -43,18 +43,17 @@ func TestDialTimeout(t *testing.T) { errc <- err }() } - case "darwin": + case "darwin", "windows": // At least OS X 10.7 seems to accept any number of // connections, ignoring listen's backlog, so resort // to connecting to a hopefully-dead 127/8 address. + // Same for windows. go func() { _, err := DialTimeout("tcp", "127.0.71.111:80", 200*time.Millisecond) errc <- err }() default: - // TODO(bradfitz): this probably doesn't work on - // Windows? SOMAXCONN is huge there. I'm not sure how - // listen works there. + // TODO(bradfitz): // OpenBSD may have a reject route to 10/8. // FreeBSD likely works, but is untested. t.Logf("skipping test on %q; untested.", runtime.GOOS) diff --git a/libgo/go/net/dnsconfig.go b/libgo/go/net/dnsconfig.go index c0ab802..bb46cc9 100644 --- a/libgo/go/net/dnsconfig.go +++ b/libgo/go/net/dnsconfig.go @@ -17,19 +17,6 @@ type dnsConfig struct { rotate bool // round robin among servers } -var dnsconfigError error - -type DNSConfigError struct { - Err error -} - -func (e *DNSConfigError) Error() string { - return "error reading DNS config: " + e.Err.Error() -} - -func (e *DNSConfigError) Timeout() bool { return false } -func (e *DNSConfigError) Temporary() bool { return false } - // See resolv.conf(5) on a Linux machine. // TODO(rsc): Supposed to call uname() and chop the beginning // of the host name to get the default search domain. diff --git a/libgo/go/net/dnsmsg.go b/libgo/go/net/dnsmsg.go index 7595aa2..97c5062 100644 --- a/libgo/go/net/dnsmsg.go +++ b/libgo/go/net/dnsmsg.go @@ -4,7 +4,7 @@ // DNS packet assembly. See RFC 1035. // -// This is intended to support name resolution during net.Dial. +// This is intended to support name resolution during Dial. // It doesn't have to be blazing fast. // // Rather than write the usual handful of routines to pack and diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go index 495ef00..2352d22 100644 --- a/libgo/go/net/fd.go +++ b/libgo/go/net/fd.go @@ -43,12 +43,6 @@ type netFD struct { ncr, ncw int } -type InvalidConnError struct{} - -func (e *InvalidConnError) Error() string { return "invalid net.Conn" } -func (e *InvalidConnError) Temporary() bool { return false } -func (e *InvalidConnError) Timeout() bool { return false } - // A pollServer helps FDs determine when to retry a non-blocking // read or write after they get EAGAIN. When an FD needs to wait, // send the fd on s.cr (for a read) or s.cw (for a write) to pass the @@ -275,20 +269,20 @@ func startServer() { pollserver = p } -func newFD(fd, family, sotype int, net string) (f *netFD, err error) { +func newFD(fd, family, sotype int, net string) (*netFD, error) { onceStartServer.Do(startServer) - if e := syscall.SetNonblock(fd, true); e != nil { - return nil, e + if err := syscall.SetNonblock(fd, true); err != nil { + return nil, err } - f = &netFD{ + netfd := &netFD{ sysfd: fd, family: family, sotype: sotype, net: net, } - f.cr = make(chan bool, 1) - f.cw = make(chan bool, 1) - return f, nil + netfd.cr = make(chan bool, 1) + netfd.cw = make(chan bool, 1) + return netfd, nil } func (fd *netFD) setAddr(laddr, raddr Addr) { @@ -304,8 +298,8 @@ func (fd *netFD) setAddr(laddr, raddr Addr) { fd.sysfile = os.NewFile(fd.sysfd, fd.net+":"+ls+"->"+rs) } -func (fd *netFD) connect(ra syscall.Sockaddr) (err error) { - err = syscall.Connect(fd.sysfd, ra) +func (fd *netFD) connect(ra syscall.Sockaddr) error { + err := syscall.Connect(fd.sysfd, ra) if err == syscall.EINPROGRESS { pollserver.WaitWrite(fd) var e int @@ -466,7 +460,7 @@ func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S return } -func (fd *netFD) Write(p []byte) (n int, err error) { +func (fd *netFD) Write(p []byte) (int, error) { if fd == nil { return 0, os.EINVAL } @@ -477,8 +471,9 @@ func (fd *netFD) Write(p []byte) (n int, err error) { if fd.sysfile == nil { return 0, os.EINVAL } - nn := 0 + var err error + nn := 0 for { var n int n, err = syscall.Write(fd.sysfile.Fd(), p[nn:]) @@ -565,7 +560,7 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob return } -func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err error) { +func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) { if fd == nil || fd.sysfile == nil { return nil, os.EINVAL } @@ -600,13 +595,13 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() - if nfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { + if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { syscall.Close(s) return nil, err } - lsa, _ := syscall.Getsockname(nfd.sysfd) - nfd.setAddr(toAddr(lsa), toAddr(rsa)) - return nfd, nil + lsa, _ := syscall.Getsockname(netfd.sysfd) + netfd.setAddr(toAddr(lsa), toAddr(rsa)) + return netfd, nil } func (fd *netFD) dup() (f *os.File, err error) { diff --git a/libgo/go/net/fd_linux.go b/libgo/go/net/fd_linux.go index c8df9c9..a1d62ac 100644 --- a/libgo/go/net/fd_linux.go +++ b/libgo/go/net/fd_linux.go @@ -35,17 +35,15 @@ type pollster struct { func newpollster() (p *pollster, err error) { p = new(pollster) - var e error - - if p.epfd, e = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); e != nil { - if e != syscall.ENOSYS { - return nil, os.NewSyscallError("epoll_create1", e) + if p.epfd, err = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); err != nil { + if err != syscall.ENOSYS { + return nil, os.NewSyscallError("epoll_create1", err) } // The arg to epoll_create is a hint to the kernel // about the number of FDs we will care about. // We don't know, and since 2.6.8 the kernel ignores it anyhow. - if p.epfd, e = syscall.EpollCreate(16); e != nil { - return nil, os.NewSyscallError("epoll_create", e) + if p.epfd, err = syscall.EpollCreate(16); err != nil { + return nil, os.NewSyscallError("epoll_create", err) } syscall.CloseOnExec(p.epfd) } @@ -74,8 +72,8 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { } else { op = syscall.EPOLL_CTL_ADD } - if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != nil { - return false, os.NewSyscallError("epoll_ctl", e) + if err := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); err != nil { + return false, os.NewSyscallError("epoll_ctl", err) } p.events[fd] = p.ctlEvent.Events return false, nil @@ -103,13 +101,13 @@ func (p *pollster) StopWaiting(fd int, bits uint) { if int32(events)&^syscall.EPOLLONESHOT != 0 { p.ctlEvent.Fd = int32(fd) p.ctlEvent.Events = events - if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); e != nil { - print("Epoll modify fd=", fd, ": ", e.Error(), "\n") + if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); err != nil { + print("Epoll modify fd=", fd, ": ", err.Error(), "\n") } p.events[fd] = events } else { - if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != nil { - print("Epoll delete fd=", fd, ": ", e.Error(), "\n") + if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil { + print("Epoll delete fd=", fd, ": ", err.Error(), "\n") } delete(p.events, fd) } @@ -144,14 +142,14 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err erro } s.Unlock() - n, e := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec) + n, err := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec) s.Lock() - if e != nil { - if e == syscall.EAGAIN || e == syscall.EINTR { + if err != nil { + if err == syscall.EAGAIN || err == syscall.EINTR { continue } - return -1, 0, os.NewSyscallError("epoll_wait", e) + return -1, 0, os.NewSyscallError("epoll_wait", err) } if n == 0 { return -1, 0, nil diff --git a/libgo/go/net/fd_netbsd.go b/libgo/go/net/fd_netbsd.go index 31d0744..35d84c3 100644 --- a/libgo/go/net/fd_netbsd.go +++ b/libgo/go/net/fd_netbsd.go @@ -49,12 +49,12 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { } syscall.SetKevent(ev, fd, kmode, flags) - n, e := syscall.Kevent(p.kq, p.kbuf[:], nil, nil) - if e != nil { - return false, os.NewSyscallError("kevent", e) + n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil) + if err != nil { + return false, os.NewSyscallError("kevent", err) } if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode { - return false, os.NewSyscallError("kqueue phase error", e) + return false, os.NewSyscallError("kqueue phase error", err) } if ev.Data != 0 { return false, syscall.Errno(int(ev.Data)) @@ -88,19 +88,19 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err erro } s.Unlock() - nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[:], t) + n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t) s.Lock() - if e != nil { - if e == syscall.EINTR { + if err != nil { + if err == syscall.EINTR { continue } - return -1, 0, os.NewSyscallError("kevent", e) + return -1, 0, os.NewSyscallError("kevent", err) } - if nn == 0 { + if n == 0 { return -1, 0, nil } - p.events = p.eventbuf[0:nn] + p.events = p.eventbuf[:n] } ev := &p.events[0] p.events = p.events[1:] diff --git a/libgo/go/net/fd_openbsd.go b/libgo/go/net/fd_openbsd.go index 31d0744..35d84c3 100644 --- a/libgo/go/net/fd_openbsd.go +++ b/libgo/go/net/fd_openbsd.go @@ -49,12 +49,12 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { } syscall.SetKevent(ev, fd, kmode, flags) - n, e := syscall.Kevent(p.kq, p.kbuf[:], nil, nil) - if e != nil { - return false, os.NewSyscallError("kevent", e) + n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil) + if err != nil { + return false, os.NewSyscallError("kevent", err) } if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode { - return false, os.NewSyscallError("kqueue phase error", e) + return false, os.NewSyscallError("kqueue phase error", err) } if ev.Data != 0 { return false, syscall.Errno(int(ev.Data)) @@ -88,19 +88,19 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err erro } s.Unlock() - nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[:], t) + n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t) s.Lock() - if e != nil { - if e == syscall.EINTR { + if err != nil { + if err == syscall.EINTR { continue } - return -1, 0, os.NewSyscallError("kevent", e) + return -1, 0, os.NewSyscallError("kevent", err) } - if nn == 0 { + if n == 0 { return -1, 0, nil } - p.events = p.eventbuf[0:nn] + p.events = p.eventbuf[:n] } ev := &p.events[0] p.events = p.events[1:] diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go index f00459f..78168eb 100644 --- a/libgo/go/net/fd_windows.go +++ b/libgo/go/net/fd_windows.go @@ -14,12 +14,6 @@ import ( "unsafe" ) -type InvalidConnError struct{} - -func (e *InvalidConnError) Error() string { return "invalid net.Conn" } -func (e *InvalidConnError) Temporary() bool { return false } -func (e *InvalidConnError) Timeout() bool { return false } - var initErr error func init() { @@ -30,7 +24,7 @@ func init() { } } -func closesocket(s syscall.Handle) (err error) { +func closesocket(s syscall.Handle) error { return syscall.Closesocket(s) } @@ -38,7 +32,7 @@ func closesocket(s syscall.Handle) (err error) { type anOpIface interface { Op() *anOp Name() string - Submit() (err error) + Submit() error } // IO completion result parameters. @@ -153,24 +147,25 @@ func (s *ioSrv) ProcessRemoteIO() { // inline, or, if a deadline is employed, passes the request onto // a special goroutine and waits for completion or cancels request. // deadline is unix nanos. -func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (n int, err error) { - var e error +func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (int, error) { + var err error o := oi.Op() if deadline != 0 { // Send request to a special dedicated thread, // so it can stop the io with CancelIO later. s.submchan <- oi - e = <-o.errnoc + err = <-o.errnoc } else { - e = oi.Submit() + err = oi.Submit() } - switch e { + switch err { case nil: // IO completed immediately, but we need to get our completion message anyway. case syscall.ERROR_IO_PENDING: // IO started, and we have to wait for its completion. + err = nil default: - return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, e} + return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err} } // Wait for our request to complete. var r ioResult @@ -245,25 +240,25 @@ type netFD struct { wio sync.Mutex } -func allocFD(fd syscall.Handle, family, sotype int, net string) (f *netFD) { - f = &netFD{ +func allocFD(fd syscall.Handle, family, sotype int, net string) *netFD { + netfd := &netFD{ sysfd: fd, family: family, sotype: sotype, net: net, } - runtime.SetFinalizer(f, (*netFD).Close) - return f + runtime.SetFinalizer(netfd, (*netFD).Close) + return netfd } -func newFD(fd syscall.Handle, family, proto int, net string) (f *netFD, err error) { +func newFD(fd syscall.Handle, family, proto int, net string) (*netFD, error) { if initErr != nil { return nil, initErr } onceStartServer.Do(startServer) // Associate our socket with resultsrv.iocp. - if _, e := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); e != nil { - return nil, e + if _, err := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); err != nil { + return nil, err } return allocFD(fd, family, proto, net), nil } @@ -273,7 +268,7 @@ func (fd *netFD) setAddr(laddr, raddr Addr) { fd.raddr = raddr } -func (fd *netFD) connect(ra syscall.Sockaddr) (err error) { +func (fd *netFD) connect(ra syscall.Sockaddr) error { return syscall.Connect(fd.sysfd, ra) } @@ -340,7 +335,7 @@ type readOp struct { bufOp } -func (o *readOp) Submit() (err error) { +func (o *readOp) Submit() error { var d, f uint32 return syscall.WSARecv(syscall.Handle(o.fd.sysfd), &o.buf, 1, &d, &f, &o.o, nil) } @@ -349,7 +344,7 @@ func (o *readOp) Name() string { return "WSARecv" } -func (fd *netFD) Read(buf []byte) (n int, err error) { +func (fd *netFD) Read(buf []byte) (int, error) { if fd == nil { return 0, os.EINVAL } @@ -362,11 +357,11 @@ func (fd *netFD) Read(buf []byte) (n int, err error) { } var o readOp o.Init(fd, buf, 'r') - n, err = iosrv.ExecIO(&o, fd.rdeadline) + n, err := iosrv.ExecIO(&o, fd.rdeadline) if err == nil && n == 0 { err = io.EOF } - return + return n, err } // ReadFrom from network. @@ -377,7 +372,7 @@ type readFromOp struct { rsan int32 } -func (o *readFromOp) Submit() (err error) { +func (o *readFromOp) Submit() error { var d, f uint32 return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &d, &f, &o.rsa, &o.rsan, &o.o, nil) } @@ -417,7 +412,7 @@ type writeOp struct { bufOp } -func (o *writeOp) Submit() (err error) { +func (o *writeOp) Submit() error { var d uint32 return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &d, 0, &o.o, nil) } @@ -426,7 +421,7 @@ func (o *writeOp) Name() string { return "WSASend" } -func (fd *netFD) Write(buf []byte) (n int, err error) { +func (fd *netFD) Write(buf []byte) (int, error) { if fd == nil { return 0, os.EINVAL } @@ -449,7 +444,7 @@ type writeToOp struct { sa syscall.Sockaddr } -func (o *writeToOp) Submit() (err error) { +func (o *writeToOp) Submit() error { var d uint32 return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &d, 0, o.sa, &o.o, nil) } @@ -458,7 +453,7 @@ func (o *writeToOp) Name() string { return "WSASendto" } -func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err error) { +func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { if fd == nil { return 0, os.EINVAL } @@ -486,7 +481,7 @@ type acceptOp struct { attrs [2]syscall.RawSockaddrAny // space for local and remote address only } -func (o *acceptOp) Submit() (err error) { +func (o *acceptOp) Submit() error { var d uint32 l := uint32(unsafe.Sizeof(o.attrs[0])) return syscall.AcceptEx(o.fd.sysfd, o.newsock, @@ -497,7 +492,7 @@ func (o *acceptOp) Name() string { return "AcceptEx" } -func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err error) { +func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) { if fd == nil || fd.sysfd == syscall.InvalidHandle { return nil, os.EINVAL } @@ -507,18 +502,18 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err // Get new socket. // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() - s, e := syscall.Socket(fd.family, fd.sotype, 0) - if e != nil { + s, err := syscall.Socket(fd.family, fd.sotype, 0) + if err != nil { syscall.ForkLock.RUnlock() - return nil, e + return nil, err } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Associate our new socket with IOCP. onceStartServer.Do(startServer) - if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != nil { - return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, e} + if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); err != nil { + return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, err} } // Submit accept request. @@ -532,10 +527,10 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err } // Inherit properties of the listening socket. - e = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) - if e != nil { + err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) + if err != nil { closesocket(s) - return nil, e + return nil, err } // Get local and peer addr out of AcceptEx buffer. @@ -547,14 +542,14 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err lsa, _ := lrsa.Sockaddr() rsa, _ := rrsa.Sockaddr() - nfd = allocFD(s, fd.family, fd.sotype, fd.net) - nfd.setAddr(toAddr(lsa), toAddr(rsa)) - return nfd, nil + netfd := allocFD(s, fd.family, fd.sotype, fd.net) + netfd.setAddr(toAddr(lsa), toAddr(rsa)) + return netfd, nil } // Unimplemented functions. -func (fd *netFD) dup() (f *os.File, err error) { +func (fd *netFD) dup() (*os.File, error) { // TODO: Implement this return nil, os.NewSyscallError("dup", syscall.EWINDOWS) } diff --git a/libgo/go/net/file.go b/libgo/go/net/file.go index 4ac280b..901b856 100644 --- a/libgo/go/net/file.go +++ b/libgo/go/net/file.go @@ -11,15 +11,15 @@ import ( "syscall" ) -func newFileFD(f *os.File) (nfd *netFD, err error) { - fd, errno := syscall.Dup(f.Fd()) - if errno != nil { - return nil, os.NewSyscallError("dup", errno) +func newFileFD(f *os.File) (*netFD, error) { + fd, err := syscall.Dup(f.Fd()) + if err != nil { + return nil, os.NewSyscallError("dup", err) } - proto, errno := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE) - if errno != nil { - return nil, os.NewSyscallError("getsockopt", errno) + proto, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE) + if err != nil { + return nil, os.NewSyscallError("getsockopt", err) } family := syscall.AF_UNSPEC @@ -56,11 +56,12 @@ func newFileFD(f *os.File) (nfd *netFD, err error) { sa, _ = syscall.Getpeername(fd) raddr := toAddr(sa) - if nfd, err = newFD(fd, family, proto, laddr.Network()); err != nil { + netfd, err := newFD(fd, family, proto, laddr.Network()) + if err != nil { return nil, err } - nfd.setAddr(laddr, raddr) - return nfd, nil + netfd.setAddr(laddr, raddr) + return netfd, nil } // FileConn returns a copy of the network connection corresponding to diff --git a/libgo/go/net/http/cgi/host.go b/libgo/go/net/http/cgi/host.go index 73a9b6e..d27cc4d 100644 --- a/libgo/go/net/http/cgi/host.go +++ b/libgo/go/net/http/cgi/host.go @@ -217,7 +217,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { defer cmd.Wait() defer stdoutRead.Close() - linebody, _ := bufio.NewReaderSize(stdoutRead, 1024) + linebody := bufio.NewReaderSize(stdoutRead, 1024) headers := make(http.Header) statusCode := 0 for { diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go index c9f0240..5d45025 100644 --- a/libgo/go/net/http/client.go +++ b/libgo/go/net/http/client.go @@ -245,7 +245,11 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) { } method := ireq.Method - err = &url.Error{method[0:1] + strings.ToLower(method[1:]), urlStr, err} + err = &url.Error{ + Op: method[0:1] + strings.ToLower(method[1:]), + URL: urlStr, + Err: err, + } return } @@ -274,7 +278,11 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, return nil, err } req.Header.Set("Content-Type", bodyType) - return send(req, c.Transport) + r, err = send(req, c.Transport) + if err == nil && c.Jar != nil { + c.Jar.SetCookies(req.URL, r.Cookies()) + } + return r, err } // PostForm issues a POST to the specified URL, diff --git a/libgo/go/net/http/fcgi/fcgi.go b/libgo/go/net/http/fcgi/fcgi.go index d35aa84..06bba04 100644 --- a/libgo/go/net/http/fcgi/fcgi.go +++ b/libgo/go/net/http/fcgi/fcgi.go @@ -240,7 +240,7 @@ func (w *bufWriter) Close() error { func newWriter(c *conn, recType recType, reqId uint16) *bufWriter { s := &streamWriter{c: c, recType: recType, reqId: reqId} - w, _ := bufio.NewWriterSize(s, maxWrite) + w := bufio.NewWriterSize(s, maxWrite) return &bufWriter{s, w} } diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go index 85cad3e..feea920 100644 --- a/libgo/go/net/http/fs_test.go +++ b/libgo/go/net/http/fs_test.go @@ -190,7 +190,7 @@ func TestDirJoin(t *testing.T) { if err != nil { t.Fatalf("stat of %s: %v", name, err) } - if !gfi.(*os.FileStat).SameFile(wfi.(*os.FileStat)) { + if !os.SameFile(gfi, wfi) { t.Errorf("%s got different file", name) } } diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go index b8a98ee..c853066 100644 --- a/libgo/go/net/http/httputil/dump.go +++ b/libgo/go/net/http/httputil/dump.go @@ -5,8 +5,8 @@ package httputil import ( + "bufio" "bytes" - "errors" "fmt" "io" "io/ioutil" @@ -47,40 +47,59 @@ func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil } // DumpRequestOut is like DumpRequest but includes // headers that the standard http.Transport adds, // such as User-Agent. -func DumpRequestOut(req *http.Request, body bool) (dump []byte, err error) { +func DumpRequestOut(req *http.Request, body bool) ([]byte, error) { save := req.Body if !body || req.Body == nil { req.Body = nil } else { + var err error save, req.Body, err = drainBody(req.Body) if err != nil { - return + return nil, err } } - var b bytes.Buffer - dialed := false + // Use the actual Transport code to record what we would send + // on the wire, but not using TCP. Use a Transport with a + // customer dialer that returns a fake net.Conn that waits + // for the full input (and recording it), and then responds + // with a dummy response. + var buf bytes.Buffer // records the output + pr, pw := io.Pipe() + dr := &delegateReader{c: make(chan io.Reader)} + // Wait for the request before replying with a dummy response: + go func() { + http.ReadRequest(bufio.NewReader(pr)) + dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\n\r\n") + }() + t := &http.Transport{ - Dial: func(net, addr string) (c net.Conn, err error) { - if dialed { - return nil, errors.New("unexpected second dial") - } - c = &dumpConn{ - Writer: &b, - Reader: strings.NewReader("HTTP/1.1 500 Fake Error\r\n\r\n"), - } - return + Dial: func(net, addr string) (net.Conn, error) { + return &dumpConn{io.MultiWriter(pw, &buf), dr}, nil }, } - _, err = t.RoundTrip(req) + _, err := t.RoundTrip(req) req.Body = save if err != nil { - return + return nil, err } - dump = b.Bytes() - return + return buf.Bytes(), nil +} + +// delegateReader is a reader that delegates to another reader, +// once it arrives on a channel. +type delegateReader struct { + c chan io.Reader + r io.Reader // nil until received from c +} + +func (r *delegateReader) Read(p []byte) (int, error) { + if r.r == nil { + r.r = <-r.c + } + return r.r.Read(p) } // Return value if nonempty, def otherwise. diff --git a/libgo/go/net/http/httputil/persist.go b/libgo/go/net/http/httputil/persist.go index 1266bd3..c065ccf 100644 --- a/libgo/go/net/http/httputil/persist.go +++ b/libgo/go/net/http/httputil/persist.go @@ -18,8 +18,8 @@ import ( ) var ( - ErrPersistEOF = &http.ProtocolError{"persistent connection closed"} - ErrPipeline = &http.ProtocolError{"pipeline error"} + ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"} + ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"} ) // This is an API usage error - the local side is closed. diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go index 1072e2e..9c4bd6e 100644 --- a/libgo/go/net/http/httputil/reverseproxy.go +++ b/libgo/go/net/http/httputil/reverseproxy.go @@ -55,11 +55,16 @@ func singleJoiningSlash(a, b string) string { // target's path is "/base" and the incoming request was for "/dir", // the target request will be for /base/dir. func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy { + targetQuery := target.RawQuery director := func(req *http.Request) { req.URL.Scheme = target.Scheme req.URL.Host = target.Host req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path) - req.URL.RawQuery = target.RawQuery + if targetQuery == "" || req.URL.RawQuery == "" { + req.URL.RawQuery = targetQuery + req.URL.RawQuery + } else { + req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery + } } return &ReverseProxy{Director: director} } diff --git a/libgo/go/net/http/httputil/reverseproxy_test.go b/libgo/go/net/http/httputil/reverseproxy_test.go index 655784b..28e9c90 100644 --- a/libgo/go/net/http/httputil/reverseproxy_test.go +++ b/libgo/go/net/http/httputil/reverseproxy_test.go @@ -69,3 +69,41 @@ func TestReverseProxy(t *testing.T) { t.Errorf("got body %q; expected %q", g, e) } } + +var proxyQueryTests = []struct { + baseSuffix string // suffix to add to backend URL + reqSuffix string // suffix to add to frontend's request URL + want string // what backend should see for final request URL (without ?) +}{ + {"", "", ""}, + {"?sta=tic", "?us=er", "sta=tic&us=er"}, + {"", "?us=er", "us=er"}, + {"?sta=tic", "", "sta=tic"}, +} + +func TestReverseProxyQuery(t *testing.T) { + backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Got-Query", r.URL.RawQuery) + w.Write([]byte("hi")) + })) + defer backend.Close() + + for i, tt := range proxyQueryTests { + backendURL, err := url.Parse(backend.URL + tt.baseSuffix) + if err != nil { + t.Fatal(err) + } + frontend := httptest.NewServer(NewSingleHostReverseProxy(backendURL)) + req, _ := http.NewRequest("GET", frontend.URL+tt.reqSuffix, nil) + req.Close = true + res, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("%d. Get: %v", i, err) + } + if g, e := res.Header.Get("X-Got-Query"), tt.want; g != e { + t.Errorf("%d. got query %q; expected %q", i, g, e) + } + res.Body.Close() + frontend.Close() + } +} diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go index 5f8c000..0bbec53 100644 --- a/libgo/go/net/http/request.go +++ b/libgo/go/net/http/request.go @@ -272,7 +272,7 @@ func valueOrDefault(value, def string) string { const defaultUserAgent = "Go http package" // Write writes an HTTP/1.1 request -- header and body -- in wire format. -// This method consults the following fields of req: +// This method consults the following fields of the request: // Host // URL // Method (defaults to "GET") @@ -284,18 +284,18 @@ const defaultUserAgent = "Go http package" // If Body is present, Content-Length is <= 0 and TransferEncoding // hasn't been set to "identity", Write adds "Transfer-Encoding: // chunked" to the header. Body is closed after it is sent. -func (req *Request) Write(w io.Writer) error { - return req.write(w, false, nil) +func (r *Request) Write(w io.Writer) error { + return r.write(w, false, nil) } // WriteProxy is like Write but writes the request in the form // expected by an HTTP proxy. In particular, WriteProxy writes the // initial Request-URI line of the request with an absolute URI, per -// section 5.1.2 of RFC 2616, including the scheme and host. In -// either case, WriteProxy also writes a Host header, using either -// req.Host or req.URL.Host. -func (req *Request) WriteProxy(w io.Writer) error { - return req.write(w, true, nil) +// section 5.1.2 of RFC 2616, including the scheme and host. +// In either case, WriteProxy also writes a Host header, using +// either r.Host or r.URL.Host. +func (r *Request) WriteProxy(w io.Writer) error { + return r.write(w, true, nil) } // extraHeaders may be nil diff --git a/libgo/go/net/http/response.go b/libgo/go/net/http/response.go index ae314b5..b790220 100644 --- a/libgo/go/net/http/response.go +++ b/libgo/go/net/http/response.go @@ -174,7 +174,7 @@ func (r *Response) ProtoAtLeast(major, minor int) bool { } // Writes the response (header, body and trailer) in wire format. This method -// consults the following fields of resp: +// consults the following fields of the response: // // StatusCode // ProtoMajor @@ -186,28 +186,28 @@ func (r *Response) ProtoAtLeast(major, minor int) bool { // ContentLength // Header, values for non-canonical keys will have unpredictable behavior // -func (resp *Response) Write(w io.Writer) error { +func (r *Response) Write(w io.Writer) error { // RequestMethod should be upper-case - if resp.Request != nil { - resp.Request.Method = strings.ToUpper(resp.Request.Method) + if r.Request != nil { + r.Request.Method = strings.ToUpper(r.Request.Method) } // Status line - text := resp.Status + text := r.Status if text == "" { var ok bool - text, ok = statusText[resp.StatusCode] + text, ok = statusText[r.StatusCode] if !ok { - text = "status code " + strconv.Itoa(resp.StatusCode) + text = "status code " + strconv.Itoa(r.StatusCode) } } - io.WriteString(w, "HTTP/"+strconv.Itoa(resp.ProtoMajor)+".") - io.WriteString(w, strconv.Itoa(resp.ProtoMinor)+" ") - io.WriteString(w, strconv.Itoa(resp.StatusCode)+" "+text+"\r\n") + io.WriteString(w, "HTTP/"+strconv.Itoa(r.ProtoMajor)+".") + io.WriteString(w, strconv.Itoa(r.ProtoMinor)+" ") + io.WriteString(w, strconv.Itoa(r.StatusCode)+" "+text+"\r\n") // Process Body,ContentLength,Close,Trailer - tw, err := newTransferWriter(resp) + tw, err := newTransferWriter(r) if err != nil { return err } @@ -217,7 +217,7 @@ func (resp *Response) Write(w io.Writer) error { } // Rest of header - err = resp.Header.WriteSubset(w, respExcludeHeader) + err = r.Header.WriteSubset(w, respExcludeHeader) if err != nil { return err } diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go index 147c216..e2860c3 100644 --- a/libgo/go/net/http/serve_test.go +++ b/libgo/go/net/http/serve_test.go @@ -504,8 +504,9 @@ func Test304Responses(t *testing.T) { } // TestHeadResponses verifies that responses to HEAD requests don't -// declare that they're chunking in their response headers and aren't -// allowed to produce output. +// declare that they're chunking in their response headers, aren't +// allowed to produce output, and don't set a Content-Type since +// the real type of the body data cannot be inferred. func TestHeadResponses(t *testing.T) { ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { _, err := w.Write([]byte("Ignored body")) @@ -527,6 +528,10 @@ func TestHeadResponses(t *testing.T) { if len(res.TransferEncoding) > 0 { t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding) } + ct := res.Header.Get("Content-Type") + if ct != "" { + t.Errorf("expected no Content-Type; got %s", ct) + } body, err := ioutil.ReadAll(res.Body) if err != nil { t.Error(err) diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go index bad3bcb..288539b 100644 --- a/libgo/go/net/http/server.go +++ b/libgo/go/net/http/server.go @@ -341,7 +341,7 @@ func (w *response) WriteHeader(code int) { } } else { // If no content type, apply sniffing algorithm to body. - if w.header.Get("Content-Type") == "" { + if w.header.Get("Content-Type") == "" && w.req.Method != "HEAD" { w.needSniff = true } } @@ -1078,8 +1078,8 @@ func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Han // of the server's certificate followed by the CA's certificate. // // If srv.Addr is blank, ":https" is used. -func (s *Server) ListenAndServeTLS(certFile, keyFile string) error { - addr := s.Addr +func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { + addr := srv.Addr if addr == "" { addr = ":https" } @@ -1101,7 +1101,7 @@ func (s *Server) ListenAndServeTLS(certFile, keyFile string) error { } tlsListener := tls.NewListener(conn, config) - return s.Serve(tlsListener) + return srv.Serve(tlsListener) } // TimeoutHandler returns a Handler that runs h with the given time limit. diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go index 4de070f..693215e 100644 --- a/libgo/go/net/http/transport.go +++ b/libgo/go/net/http/transport.go @@ -535,7 +535,9 @@ func (pc *persistConn) readLoop() { } resp, err := ReadResponse(pc.br, rc.req) - if err == nil { + if err != nil { + pc.close() + } else { hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0 if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" { resp.Header.Del("Content-Encoding") diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go index 321da52..caf81d6 100644 --- a/libgo/go/net/http/transport_test.go +++ b/libgo/go/net/http/transport_test.go @@ -441,7 +441,11 @@ func TestRoundTripGzip(t *testing.T) { } if accept == "gzip" { rw.Header().Set("Content-Encoding", "gzip") - gz, _ := gzip.NewWriter(rw) + gz, err := gzip.NewWriter(rw) + if err != nil { + t.Errorf("gzip NewWriter: %v", err) + return + } gz.Write([]byte(responseBody)) gz.Close() } else { @@ -460,7 +464,11 @@ func TestRoundTripGzip(t *testing.T) { res, err := DefaultTransport.RoundTrip(req) var body []byte if test.compressed { - gzip, _ := gzip.NewReader(res.Body) + gzip, err := gzip.NewReader(res.Body) + if err != nil { + t.Errorf("%d. gzip NewReader: %v", i, err) + continue + } body, err = ioutil.ReadAll(gzip) res.Body.Close() } else { diff --git a/libgo/go/net/interface_bsd.go b/libgo/go/net/interface_bsd.go index 907f80a..7f090d8 100644 --- a/libgo/go/net/interface_bsd.go +++ b/libgo/go/net/interface_bsd.go @@ -15,11 +15,9 @@ import ( ) // If the ifindex is zero, interfaceTable returns mappings of all -// network interfaces. Otheriwse it returns a mapping of a specific +// network interfaces. Otherwise it returns a mapping of a specific // interface. func interfaceTable(ifindex int) ([]Interface, error) { - var ift []Interface - tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex) if err != nil { return nil, os.NewSyscallError("route rib", err) @@ -30,6 +28,7 @@ func interfaceTable(ifindex int) ([]Interface, error) { return nil, os.NewSyscallError("route message", err) } + var ift []Interface for _, m := range msgs { switch v := m.(type) { case *syscall.InterfaceMessage: @@ -42,18 +41,16 @@ func interfaceTable(ifindex int) ([]Interface, error) { } } } - return ift, nil } func newLink(m *syscall.InterfaceMessage) ([]Interface, error) { - var ift []Interface - sas, err := syscall.ParseRoutingSockaddr(m) if err != nil { return nil, os.NewSyscallError("route sockaddr", err) } + var ift []Interface for _, s := range sas { switch v := s.(type) { case *syscall.SockaddrDatalink: @@ -75,7 +72,6 @@ func newLink(m *syscall.InterfaceMessage) ([]Interface, error) { ift = append(ift, ifi) } } - return ift, nil } @@ -103,8 +99,6 @@ func linkFlags(rawFlags int32) Flags { // for all network interfaces. Otherwise it returns addresses // for a specific interface. func interfaceAddrTable(ifindex int) ([]Addr, error) { - var ifat []Addr - tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex) if err != nil { return nil, os.NewSyscallError("route rib", err) @@ -115,6 +109,7 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) { return nil, os.NewSyscallError("route message", err) } + var ifat []Addr for _, m := range msgs { switch v := m.(type) { case *syscall.InterfaceAddrMessage: @@ -127,18 +122,16 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) { } } } - return ifat, nil } func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) { - ifa := &IPNet{} - sas, err := syscall.ParseRoutingSockaddr(m) if err != nil { return nil, os.NewSyscallError("route sockaddr", err) } + ifa := &IPNet{} for i, s := range sas { switch v := s.(type) { case *syscall.SockaddrInet4: @@ -166,6 +159,5 @@ func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) { } } } - return ifa, nil } diff --git a/libgo/go/net/interface_darwin.go b/libgo/go/net/interface_darwin.go index 2da447a..0b5fb5fb 100644 --- a/libgo/go/net/interface_darwin.go +++ b/libgo/go/net/interface_darwin.go @@ -15,23 +15,17 @@ import ( // addresses for all network interfaces. Otherwise it returns // addresses for a specific interface. func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { - var ( - tab []byte - e error - msgs []syscall.RoutingMessage - ifmat []Addr - ) - - tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifindex) - if e != nil { - return nil, os.NewSyscallError("route rib", e) + tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifindex) + if err != nil { + return nil, os.NewSyscallError("route rib", err) } - msgs, e = syscall.ParseRoutingMessage(tab) - if e != nil { - return nil, os.NewSyscallError("route message", e) + msgs, err := syscall.ParseRoutingMessage(tab) + if err != nil { + return nil, os.NewSyscallError("route message", err) } + var ifmat []Addr for _, m := range msgs { switch v := m.(type) { case *syscall.InterfaceMulticastAddrMessage: @@ -44,18 +38,16 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { } } } - return ifmat, nil } func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) { - var ifmat []Addr - - sas, e := syscall.ParseRoutingSockaddr(m) - if e != nil { - return nil, os.NewSyscallError("route sockaddr", e) + sas, err := syscall.ParseRoutingSockaddr(m) + if err != nil { + return nil, os.NewSyscallError("route sockaddr", err) } + var ifmat []Addr for _, s := range sas { switch v := s.(type) { case *syscall.SockaddrInet4: @@ -75,6 +67,5 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) ifmat = append(ifmat, ifma.toAddr()) } } - return ifmat, nil } diff --git a/libgo/go/net/interface_freebsd.go b/libgo/go/net/interface_freebsd.go index a12877e..3cba28f 100644 --- a/libgo/go/net/interface_freebsd.go +++ b/libgo/go/net/interface_freebsd.go @@ -15,23 +15,17 @@ import ( // addresses for all network interfaces. Otherwise it returns // addresses for a specific interface. func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { - var ( - tab []byte - e error - msgs []syscall.RoutingMessage - ifmat []Addr - ) - - tab, e = syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifindex) - if e != nil { - return nil, os.NewSyscallError("route rib", e) + tab, err := syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifindex) + if err != nil { + return nil, os.NewSyscallError("route rib", err) } - msgs, e = syscall.ParseRoutingMessage(tab) - if e != nil { - return nil, os.NewSyscallError("route message", e) + msgs, err := syscall.ParseRoutingMessage(tab) + if err != nil { + return nil, os.NewSyscallError("route message", err) } + var ifmat []Addr for _, m := range msgs { switch v := m.(type) { case *syscall.InterfaceMulticastAddrMessage: @@ -44,18 +38,16 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { } } } - return ifmat, nil } func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) { - var ifmat []Addr - - sas, e := syscall.ParseRoutingSockaddr(m) - if e != nil { - return nil, os.NewSyscallError("route sockaddr", e) + sas, err := syscall.ParseRoutingSockaddr(m) + if err != nil { + return nil, os.NewSyscallError("route sockaddr", err) } + var ifmat []Addr for _, s := range sas { switch v := s.(type) { case *syscall.SockaddrInet4: @@ -75,6 +67,5 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) ifmat = append(ifmat, ifma.toAddr()) } } - return ifmat, nil } diff --git a/libgo/go/net/interface_linux.go b/libgo/go/net/interface_linux.go index c0887c5..21038c6 100644 --- a/libgo/go/net/interface_linux.go +++ b/libgo/go/net/interface_linux.go @@ -17,8 +17,6 @@ import ( // network interfaces. Otheriwse it returns a mapping of a specific // interface. func interfaceTable(ifindex int) ([]Interface, error) { - var ift []Interface - tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC) if err != nil { return nil, os.NewSyscallError("netlink rib", err) @@ -29,6 +27,7 @@ func interfaceTable(ifindex int) ([]Interface, error) { return nil, os.NewSyscallError("netlink message", err) } + var ift []Interface for _, m := range msgs { switch m.Header.Type { case syscall.NLMSG_DONE: @@ -45,7 +44,6 @@ func interfaceTable(ifindex int) ([]Interface, error) { } } } - done: return ift, nil } @@ -111,13 +109,11 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) { if err != nil { return nil, err } - return ifat, nil } func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) { var ifat []Addr - for _, m := range msgs { switch m.Header.Type { case syscall.NLMSG_DONE: @@ -133,7 +129,6 @@ func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) { } } } - done: return ifat, nil } @@ -165,32 +160,28 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { err error ifi *Interface ) - if ifindex > 0 { ifi, err = InterfaceByIndex(ifindex) if err != nil { return nil, err } } - ifmat4 := parseProcNetIGMP(ifi) ifmat6 := parseProcNetIGMP6(ifi) - return append(ifmat4, ifmat6...), nil } func parseProcNetIGMP(ifi *Interface) []Addr { - var ( - ifmat []Addr - name string - ) - fd, err := open("/proc/net/igmp") if err != nil { return nil } defer fd.close() + var ( + ifmat []Addr + name string + ) fd.readLine() // skip first line b := make([]byte, IPv4len) for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { @@ -206,19 +197,17 @@ func parseProcNetIGMP(ifi *Interface) []Addr { name = f[1] } } - return ifmat } func parseProcNetIGMP6(ifi *Interface) []Addr { - var ifmat []Addr - fd, err := open("/proc/net/igmp6") if err != nil { return nil } defer fd.close() + var ifmat []Addr b := make([]byte, IPv6len) for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { f := getFields(l) @@ -229,6 +218,5 @@ func parseProcNetIGMP6(ifi *Interface) []Addr { } } - return ifmat } diff --git a/libgo/go/net/interface_windows.go b/libgo/go/net/interface_windows.go index add3dd3..d0c9753 100644 --- a/libgo/go/net/interface_windows.go +++ b/libgo/go/net/interface_windows.go @@ -25,31 +25,31 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) { b := make([]byte, 1000) l := uint32(len(b)) a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0])) - e := syscall.GetAdaptersInfo(a, &l) - if e == syscall.ERROR_BUFFER_OVERFLOW { + err := syscall.GetAdaptersInfo(a, &l) + if err == syscall.ERROR_BUFFER_OVERFLOW { b = make([]byte, l) a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0])) - e = syscall.GetAdaptersInfo(a, &l) + err = syscall.GetAdaptersInfo(a, &l) } - if e != nil { - return nil, os.NewSyscallError("GetAdaptersInfo", e) + if err != nil { + return nil, os.NewSyscallError("GetAdaptersInfo", err) } return a, nil } func getInterfaceList() ([]syscall.InterfaceInfo, error) { - s, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) - if e != nil { - return nil, os.NewSyscallError("Socket", e) + s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) + if err != nil { + return nil, os.NewSyscallError("Socket", err) } defer syscall.Closesocket(s) ii := [20]syscall.InterfaceInfo{} ret := uint32(0) size := uint32(unsafe.Sizeof(ii)) - e = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0) - if e != nil { - return nil, os.NewSyscallError("WSAIoctl", e) + err = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0) + if err != nil { + return nil, os.NewSyscallError("WSAIoctl", err) } c := ret / uint32(unsafe.Sizeof(ii[0])) return ii[:c-1], nil @@ -59,14 +59,14 @@ func getInterfaceList() ([]syscall.InterfaceInfo, error) { // network interfaces. Otheriwse it returns a mapping of a specific // interface. func interfaceTable(ifindex int) ([]Interface, error) { - ai, e := getAdapterList() - if e != nil { - return nil, e + ai, err := getAdapterList() + if err != nil { + return nil, err } - ii, e := getInterfaceList() - if e != nil { - return nil, e + ii, err := getInterfaceList() + if err != nil { + return nil, err } var ift []Interface @@ -130,9 +130,9 @@ func interfaceTable(ifindex int) ([]Interface, error) { // for all network interfaces. Otherwise it returns addresses // for a specific interface. func interfaceAddrTable(ifindex int) ([]Addr, error) { - ai, e := getAdapterList() - if e != nil { - return nil, e + ai, err := getAdapterList() + if err != nil { + return nil, err } var ifat []Addr diff --git a/libgo/go/net/iprawsock_plan9.go b/libgo/go/net/iprawsock_plan9.go index 859153c..382a440 100644 --- a/libgo/go/net/iprawsock_plan9.go +++ b/libgo/go/net/iprawsock_plan9.go @@ -15,17 +15,17 @@ import ( // interfaces for IP network connections. type IPConn bool -// SetDeadline implements the net.Conn SetDeadline method. +// SetDeadline implements the Conn SetDeadline method. func (c *IPConn) SetDeadline(t time.Time) error { return os.EPLAN9 } -// SetReadDeadline implements the net.Conn SetReadDeadline method. +// SetReadDeadline implements the Conn SetReadDeadline method. func (c *IPConn) SetReadDeadline(t time.Time) error { return os.EPLAN9 } -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *IPConn) SetWriteDeadline(t time.Time) error { return os.EPLAN9 } diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go index 9234f5a..bfbce18 100644 --- a/libgo/go/net/ipsock.go +++ b/libgo/go/net/ipsock.go @@ -99,16 +99,12 @@ func JoinHostPort(host, port string) string { // Convert "host:port" into IP address and port. func hostPortToIP(net, hostport string) (ip IP, iport int, err error) { - var ( - addr IP - p, i int - ok bool - ) host, port, err := SplitHostPort(hostport) if err != nil { - goto Error + return nil, 0, err } + var addr IP if host != "" { // Try as an IP address. addr = ParseIP(host) @@ -121,34 +117,29 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err error) { filter = ipv6only } // Not an IP address. Try as a DNS name. - addrs, err1 := LookupHost(host) - if err1 != nil { - err = err1 - goto Error + addrs, err := LookupHost(host) + if err != nil { + return nil, 0, err } addr = firstFavoriteAddr(filter, addrs) if addr == nil { // should not happen - err = &AddrError{"LookupHost returned no suitable address", addrs[0]} - goto Error + return nil, 0, &AddrError{"LookupHost returned no suitable address", addrs[0]} } } } - p, i, ok = dtoi(port, 0) + p, i, ok := dtoi(port, 0) if !ok || i != len(port) { p, err = LookupPort(net, port) if err != nil { - goto Error + return nil, 0, err } } if p < 0 || p > 0xFFFF { - err = &AddrError{"invalid port", port} - goto Error + return nil, 0, &AddrError{"invalid port", port} } return addr, p, nil -Error: - return nil, 0, err } diff --git a/libgo/go/net/ipsock_plan9.go b/libgo/go/net/ipsock_plan9.go index 09d8d6b..597b127 100644 --- a/libgo/go/net/ipsock_plan9.go +++ b/libgo/go/net/ipsock_plan9.go @@ -22,33 +22,22 @@ func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { // parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80). func parsePlan9Addr(s string) (ip IP, iport int, err error) { - var ( - addr IP - p, i int - ok bool - ) - addr = IPv4zero // address contains port only - i = byteIndex(s, '!') + addr := IPv4zero // address contains port only + i := byteIndex(s, '!') if i >= 0 { addr = ParseIP(s[:i]) if addr == nil { - err = errors.New("net: parsing IP failed") - goto Error + return nil, 0, errors.New("net: parsing IP failed") } } - p, _, ok = dtoi(s[i+1:], 0) + p, _, ok := dtoi(s[i+1:], 0) if !ok { - err = errors.New("net: parsing port failed") - goto Error + return nil, 0, errors.New("net: parsing port failed") } if p < 0 || p > 0xFFFF { - err = &AddrError{"invalid port", string(p)} - goto Error + return nil, 0, &AddrError{"invalid port", string(p)} } return addr, p, nil - -Error: - return nil, 0, err } func readPlan9Addr(proto, filename string) (addr Addr, err error) { @@ -91,7 +80,7 @@ func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil } // Implementation of the Conn interface - see Conn for documentation. -// Read implements the net.Conn Read method. +// Read implements the Conn Read method. func (c *plan9Conn) Read(b []byte) (n int, err error) { if !c.ok() { return 0, os.EINVAL @@ -110,7 +99,7 @@ func (c *plan9Conn) Read(b []byte) (n int, err error) { return } -// Write implements the net.Conn Write method. +// Write implements the Conn Write method. func (c *plan9Conn) Write(b []byte) (n int, err error) { if !c.ok() { return 0, os.EINVAL @@ -157,17 +146,17 @@ func (c *plan9Conn) RemoteAddr() Addr { return c.raddr } -// SetDeadline implements the net.Conn SetDeadline method. +// SetDeadline implements the Conn SetDeadline method. func (c *plan9Conn) SetDeadline(t time.Time) error { return os.EPLAN9 } -// SetReadDeadline implements the net.Conn SetReadDeadline method. +// SetReadDeadline implements the Conn SetReadDeadline method. func (c *plan9Conn) SetReadDeadline(t time.Time) error { return os.EPLAN9 } -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *plan9Conn) SetWriteDeadline(t time.Time) error { return os.EPLAN9 } diff --git a/libgo/go/net/lookup_windows.go b/libgo/go/net/lookup_windows.go index dfe2ff6..99783e9 100644 --- a/libgo/go/net/lookup_windows.go +++ b/libgo/go/net/lookup_windows.go @@ -21,9 +21,9 @@ var ( func lookupProtocol(name string) (proto int, err error) { protoentLock.Lock() defer protoentLock.Unlock() - p, e := syscall.GetProtoByName(name) - if e != nil { - return 0, os.NewSyscallError("GetProtoByName", e) + p, err := syscall.GetProtoByName(name) + if err != nil { + return 0, os.NewSyscallError("GetProtoByName", err) } return int(p.Proto), nil } @@ -43,9 +43,9 @@ func lookupHost(name string) (addrs []string, err error) { func lookupIP(name string) (addrs []IP, err error) { hostentLock.Lock() defer hostentLock.Unlock() - h, e := syscall.GetHostByName(name) - if e != nil { - return nil, os.NewSyscallError("GetHostByName", e) + h, err := syscall.GetHostByName(name) + if err != nil { + return nil, os.NewSyscallError("GetHostByName", err) } switch h.AddrType { case syscall.AF_INET: @@ -70,9 +70,9 @@ func lookupPort(network, service string) (port int, err error) { } serventLock.Lock() defer serventLock.Unlock() - s, e := syscall.GetServByName(service, network) - if e != nil { - return 0, os.NewSyscallError("GetServByName", e) + s, err := syscall.GetServByName(service, network) + if err != nil { + return 0, os.NewSyscallError("GetServByName", err) } return int(syscall.Ntohs(s.Port)), nil } diff --git a/libgo/go/net/multicast_test.go b/libgo/go/net/multicast_test.go index 183d5a8..bf0fe4d 100644 --- a/libgo/go/net/multicast_test.go +++ b/libgo/go/net/multicast_test.go @@ -5,47 +5,40 @@ package net import ( - "flag" "os" "runtime" "testing" ) -var multicast = flag.Bool("multicast", false, "enable multicast tests") - -var multicastUDPTests = []struct { +var listenMulticastUDPTests = []struct { net string - laddr IP - gaddr IP + gaddr *UDPAddr flags Flags ipv6 bool }{ // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers - {"udp", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false}, - {"udp4", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false}, - {"udp", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true}, - {"udp6", IPv6unspecified, ParseIP("ff01::114"), (FlagUp | FlagLoopback), true}, - {"udp6", IPv6unspecified, ParseIP("ff02::114"), (FlagUp | FlagLoopback), true}, - {"udp6", IPv6unspecified, ParseIP("ff04::114"), (FlagUp | FlagLoopback), true}, - {"udp6", IPv6unspecified, ParseIP("ff05::114"), (FlagUp | FlagLoopback), true}, - {"udp6", IPv6unspecified, ParseIP("ff08::114"), (FlagUp | FlagLoopback), true}, - {"udp6", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true}, + {"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false}, + {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false}, + {"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true}, } -func TestMulticastUDP(t *testing.T) { - if runtime.GOOS == "plan9" || runtime.GOOS == "windows" { - return - } - if !*multicast { - t.Logf("test disabled; use --multicast to enable") +func TestListenMulticastUDP(t *testing.T) { + switch runtime.GOOS { + case "netbsd", "openbsd", "plan9", "windows": return + case "linux": + if runtime.GOARCH == "arm" { + return + } } - for _, tt := range multicastUDPTests { - var ( - ifi *Interface - found bool - ) + for _, tt := range listenMulticastUDPTests { if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) { continue } @@ -53,6 +46,7 @@ func TestMulticastUDP(t *testing.T) { if err != nil { t.Fatalf("Interfaces failed: %v", err) } + var ifi *Interface for _, x := range ift { if x.Flags&tt.flags == tt.flags { ifi = &x @@ -63,14 +57,11 @@ func TestMulticastUDP(t *testing.T) { t.Logf("an appropriate multicast interface not found") return } - c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr}) + c, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) if err != nil { - t.Fatalf("ListenUDP failed: %v", err) - } - defer c.Close() - if err := c.JoinGroup(ifi, tt.gaddr); err != nil { - t.Fatalf("JoinGroup failed: %v", err) + t.Fatalf("ListenMulticastUDP failed: %v", err) } + defer c.Close() // test to listen concurrently across multiple listeners if !tt.ipv6 { testIPv4MulticastSocketOptions(t, c.fd, ifi) } else { @@ -80,8 +71,9 @@ func TestMulticastUDP(t *testing.T) { if err != nil { t.Fatalf("MulticastAddrs failed: %v", err) } + var found bool for _, ifma := range ifmat { - if ifma.(*IPAddr).IP.Equal(tt.gaddr) { + if ifma.(*IPAddr).IP.Equal(tt.gaddr.IP) { found = true break } @@ -89,23 +81,16 @@ func TestMulticastUDP(t *testing.T) { if !found { t.Fatalf("%q not found in RIB", tt.gaddr.String()) } - if err := c.LeaveGroup(ifi, tt.gaddr); err != nil { - t.Fatalf("LeaveGroup failed: %v", err) - } } } -func TestSimpleMulticastUDP(t *testing.T) { - if runtime.GOOS == "plan9" { - return - } - if !*multicast { - t.Logf("test disabled; use --multicast to enable") +func TestSimpleListenMulticastUDP(t *testing.T) { + switch runtime.GOOS { + case "plan9": return } - for _, tt := range multicastUDPTests { - var ifi *Interface + for _, tt := range listenMulticastUDPTests { if tt.ipv6 { continue } @@ -114,6 +99,7 @@ func TestSimpleMulticastUDP(t *testing.T) { if err != nil { t.Fatalf("Interfaces failed: %v", err) } + var ifi *Interface for _, x := range ift { if x.Flags&tt.flags == tt.flags { ifi = &x @@ -124,17 +110,11 @@ func TestSimpleMulticastUDP(t *testing.T) { t.Logf("an appropriate multicast interface not found") return } - c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr}) + c, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) if err != nil { - t.Fatalf("ListenUDP failed: %v", err) - } - defer c.Close() - if err := c.JoinGroup(ifi, tt.gaddr); err != nil { - t.Fatalf("JoinGroup failed: %v", err) - } - if err := c.LeaveGroup(ifi, tt.gaddr); err != nil { - t.Fatalf("LeaveGroup failed: %v", err) + t.Fatalf("ListenMulticastUDP failed: %v", err) } + c.Close() } } diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go index 609fee2..79d36a2 100644 --- a/libgo/go/net/net.go +++ b/libgo/go/net/net.go @@ -23,12 +23,12 @@ type Addr interface { // Conn is a generic stream-oriented network connection. type Conn interface { // Read reads data from the connection. - // Read can be made to time out and return a net.Error with Timeout() == true + // Read can be made to time out and return a Error with Timeout() == true // after a fixed time limit; see SetDeadline and SetReadDeadline. Read(b []byte) (n int, err error) // Write writes data to the connection. - // Write can be made to time out and return a net.Error with Timeout() == true + // Write can be made to time out and return a Error with Timeout() == true // after a fixed time limit; see SetDeadline and SetWriteDeadline. Write(b []byte) (n int, err error) @@ -201,3 +201,15 @@ type UnknownNetworkError string func (e UnknownNetworkError) Error() string { return "unknown network " + string(e) } func (e UnknownNetworkError) Temporary() bool { return false } func (e UnknownNetworkError) Timeout() bool { return false } + +// DNSConfigError represents an error reading the machine's DNS configuration. +type DNSConfigError struct { + Err error +} + +func (e *DNSConfigError) Error() string { + return "error reading DNS config: " + e.Err.Error() +} + +func (e *DNSConfigError) Timeout() bool { return false } +func (e *DNSConfigError) Temporary() bool { return false } diff --git a/libgo/go/net/net_test.go b/libgo/go/net/net_test.go index d09ebf0..1bc9977 100644 --- a/libgo/go/net/net_test.go +++ b/libgo/go/net/net_test.go @@ -71,15 +71,15 @@ func TestDialError(t *testing.T) { return } for i, tt := range dialErrorTests { - c, e := Dial(tt.Net, tt.Raddr) + c, err := Dial(tt.Net, tt.Raddr) if c != nil { c.Close() } - if e == nil { + if err == nil { t.Errorf("#%d: nil error, want match for %#q", i, tt.Pattern) continue } - s := e.Error() + s := err.Error() match, _ := regexp.MatchString(tt.Pattern, s) if !match { t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern) @@ -111,16 +111,16 @@ var revAddrTests = []struct { func TestReverseAddress(t *testing.T) { for i, tt := range revAddrTests { - a, e := reverseaddr(tt.Addr) - if len(tt.ErrPrefix) > 0 && e == nil { + a, err := reverseaddr(tt.Addr) + if len(tt.ErrPrefix) > 0 && err == nil { t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix) continue } - if len(tt.ErrPrefix) == 0 && e != nil { - t.Errorf("#%d: expected <nil>, got %q (error)", i, e) + if len(tt.ErrPrefix) == 0 && err != nil { + t.Errorf("#%d: expected <nil>, got %q (error)", i, err) } - if e != nil && e.(*DNSError).Err != tt.ErrPrefix { - t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, e.(*DNSError).Err) + if err != nil && err.(*DNSError).Err != tt.ErrPrefix { + t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err) } if a != tt.Reverse { t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a) diff --git a/libgo/go/net/newpollserver.go b/libgo/go/net/newpollserver.go index a410bb6..06bc24c 100644 --- a/libgo/go/net/newpollserver.go +++ b/libgo/go/net/newpollserver.go @@ -36,7 +36,11 @@ func newPollServer() (s *pollServer, err error) { return s, nil Errno: - err = &os.PathError{"setnonblock", s.pr.Name(), err} + err = &os.PathError{ + Op: "setnonblock", + Path: s.pr.Name(), + Err: err, + } Error: s.pr.Close() s.pw.Close() diff --git a/libgo/go/net/rpc/client.go b/libgo/go/net/rpc/client.go index abc1e59..34f9ae3 100644 --- a/libgo/go/net/rpc/client.go +++ b/libgo/go/net/rpc/client.go @@ -31,8 +31,7 @@ type Call struct { Args interface{} // The argument to the function (*struct). Reply interface{} // The reply from the function (*struct). Error error // After completion, the error status. - Done chan *Call // Strobes when call is complete; value is the error status. - seq uint64 + Done chan *Call // Strobes when call is complete. } // Client represents an RPC Client. @@ -65,28 +64,33 @@ type ClientCodec interface { Close() error } -func (client *Client) send(c *Call) { +func (client *Client) send(call *Call) { + client.sending.Lock() + defer client.sending.Unlock() + // Register this call. client.mutex.Lock() if client.shutdown { - c.Error = ErrShutdown + call.Error = ErrShutdown client.mutex.Unlock() - c.done() + call.done() return } - c.seq = client.seq + seq := client.seq client.seq++ - client.pending[c.seq] = c + client.pending[seq] = call client.mutex.Unlock() // Encode and send the request. - client.sending.Lock() - defer client.sending.Unlock() - client.request.Seq = c.seq - client.request.ServiceMethod = c.ServiceMethod - if err := client.codec.WriteRequest(&client.request, c.Args); err != nil { - c.Error = err - c.done() + client.request.Seq = seq + client.request.ServiceMethod = call.ServiceMethod + err := client.codec.WriteRequest(&client.request, call.Args) + if err != nil { + client.mutex.Lock() + delete(client.pending, seq) + client.mutex.Unlock() + call.Error = err + call.done() } } @@ -104,36 +108,39 @@ func (client *Client) input() { } seq := response.Seq client.mutex.Lock() - c := client.pending[seq] + call := client.pending[seq] delete(client.pending, seq) client.mutex.Unlock() if response.Error == "" { - err = client.codec.ReadResponseBody(c.Reply) + err = client.codec.ReadResponseBody(call.Reply) if err != nil { - c.Error = errors.New("reading body " + err.Error()) + call.Error = errors.New("reading body " + err.Error()) } } else { // We've got an error response. Give this to the request; // any subsequent requests will get the ReadResponseBody // error if there is one. - c.Error = ServerError(response.Error) + call.Error = ServerError(response.Error) err = client.codec.ReadResponseBody(nil) if err != nil { err = errors.New("reading error body: " + err.Error()) } } - c.done() + call.done() } // Terminate pending calls. + client.sending.Lock() client.mutex.Lock() client.shutdown = true + closing := client.closing for _, call := range client.pending { call.Error = err call.done() } client.mutex.Unlock() - if err != io.EOF || !client.closing { + client.sending.Unlock() + if err != io.EOF || !closing { log.Println("rpc: client protocol error:", err) } } @@ -225,7 +232,12 @@ func DialHTTPPath(network, address, path string) (*Client, error) { err = errors.New("unexpected HTTP response: " + resp.Status) } conn.Close() - return nil, &net.OpError{"dial-http", network + " " + address, nil, err} + return nil, &net.OpError{ + Op: "dial-http", + Net: network + " " + address, + Addr: nil, + Err: err, + } } // Dial connects to an RPC server at the specified network address. @@ -269,20 +281,12 @@ func (client *Client) Go(serviceMethod string, args interface{}, reply interface } } call.Done = done - if client.shutdown { - call.Error = ErrShutdown - call.done() - return call - } client.send(call) return call } // Call invokes the named function, waits for it to complete, and returns its error status. func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error { - if client.shutdown { - return ErrShutdown - } call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done return call.Error } diff --git a/libgo/go/net/rpc/server_test.go b/libgo/go/net/rpc/server_test.go index b05c63c..8cfa033 100644 --- a/libgo/go/net/rpc/server_test.go +++ b/libgo/go/net/rpc/server_test.go @@ -442,8 +442,9 @@ func countMallocs(dial func() (*Client, error), t *testing.T) uint64 { } args := &Args{7, 8} reply := new(Reply) - runtime.UpdateMemStats() - mallocs := 0 - runtime.MemStats.Mallocs + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + mallocs := 0 - memstats.Mallocs const count = 100 for i := 0; i < count; i++ { err := client.Call("Arith.Add", args, reply) @@ -454,8 +455,8 @@ func countMallocs(dial func() (*Client, error), t *testing.T) uint64 { t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B) } } - runtime.UpdateMemStats() - mallocs += runtime.MemStats.Mallocs + runtime.ReadMemStats(memstats) + mallocs += memstats.Mallocs return mallocs / count } diff --git a/libgo/go/net/sendfile_linux.go b/libgo/go/net/sendfile_linux.go index e9ab066..7f51519 100644 --- a/libgo/go/net/sendfile_linux.go +++ b/libgo/go/net/sendfile_linux.go @@ -48,23 +48,23 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) { if int64(n) > remain { n = int(remain) } - n, errno := syscall.Sendfile(dst, src, nil, n) + n, err1 := syscall.Sendfile(dst, src, nil, n) if n > 0 { written += int64(n) remain -= int64(n) } - if n == 0 && errno == nil { + if n == 0 && err1 == nil { break } - if errno == syscall.EAGAIN && c.wdeadline >= 0 { + if err1 == syscall.EAGAIN && c.wdeadline >= 0 { pollserver.WaitWrite(c) continue } - if errno != nil { + if err1 != nil { // This includes syscall.ENOSYS (no kernel // support) and syscall.EINVAL (fd types which // don't implement sendfile together) - err = &OpError{"sendfile", c.net, c.raddr, errno} + err = &OpError{"sendfile", c.net, c.raddr, err1} break } } diff --git a/libgo/go/net/smtp/smtp.go b/libgo/go/net/smtp/smtp.go index 8d935ff..f600cc8 100644 --- a/libgo/go/net/smtp/smtp.go +++ b/libgo/go/net/smtp/smtp.go @@ -155,7 +155,7 @@ func (c *Client) Auth(a Auth) error { // the last message isn't base64 because it isn't a challenge msg = []byte(msg64) default: - err = &textproto.Error{code, msg64} + err = &textproto.Error{Code: code, Msg: msg64} } resp, err = a.Next(msg, code == 334) if err != nil { diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go index 867e328..70064c3 100644 --- a/libgo/go/net/sock.go +++ b/libgo/go/net/sock.go @@ -10,7 +10,6 @@ package net import ( "io" - "reflect" "syscall" ) @@ -28,9 +27,18 @@ func socket(net string, f, t, p int, la, ra syscall.Sockaddr, toAddr func(syscal syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() - setDefaultSockopts(s, f, t) + err = setDefaultSockopts(s, f, t) + if err != nil { + closesocket(s) + return nil, err + } if la != nil { + la, err = listenerSockaddr(s, f, la, toAddr) + if err != nil { + closesocket(s) + return nil, err + } err = syscall.Bind(s, la) if err != nil { closesocket(s) @@ -61,14 +69,6 @@ func socket(net string, f, t, p int, la, ra syscall.Sockaddr, toAddr func(syscal return fd, nil } -type UnknownSocketError struct { - sa syscall.Sockaddr -} - -func (e *UnknownSocketError) Error() string { - return "unknown socket address type " + reflect.TypeOf(e.sa).String() -} - type writerOnly struct { io.Writer } diff --git a/libgo/go/net/sock_bsd.go b/libgo/go/net/sock_bsd.go index 630a91e..7c693a2 100644 --- a/libgo/go/net/sock_bsd.go +++ b/libgo/go/net/sock_bsd.go @@ -31,3 +31,27 @@ func maxListenerBacklog() int { } return int(n) } + +func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) { + a := toAddr(la) + if a == nil { + return la, nil + } + switch v := a.(type) { + case *UDPAddr: + if v.IP.IsMulticast() { + err := setDefaultMulticastSockopts(s) + if err != nil { + return nil, err + } + switch f { + case syscall.AF_INET: + v.IP = IPv4zero + case syscall.AF_INET6: + v.IP = IPv6unspecified + } + return v.sockaddr(f) + } + } + return la, nil +} diff --git a/libgo/go/net/sock_linux.go b/libgo/go/net/sock_linux.go index 2cbc34f..0743843 100644 --- a/libgo/go/net/sock_linux.go +++ b/libgo/go/net/sock_linux.go @@ -25,3 +25,27 @@ func maxListenerBacklog() int { } return n } + +func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) { + a := toAddr(la) + if a == nil { + return la, nil + } + switch v := a.(type) { + case *UDPAddr: + if v.IP.IsMulticast() { + err := setDefaultMulticastSockopts(s) + if err != nil { + return nil, err + } + switch f { + case syscall.AF_INET: + v.IP = IPv4zero + case syscall.AF_INET6: + v.IP = IPv6unspecified + } + return v.sockaddr(f) + } + } + return la, nil +} diff --git a/libgo/go/net/sock_windows.go b/libgo/go/net/sock_windows.go index 2d803de..434122c 100644 --- a/libgo/go/net/sock_windows.go +++ b/libgo/go/net/sock_windows.go @@ -12,3 +12,27 @@ func maxListenerBacklog() int { // TODO: Implement this return syscall.SOMAXCONN } + +func listenerSockaddr(s syscall.Handle, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) { + a := toAddr(la) + if a == nil { + return la, nil + } + switch v := a.(type) { + case *UDPAddr: + if v.IP.IsMulticast() { + err := setDefaultMulticastSockopts(s) + if err != nil { + return nil, err + } + switch f { + case syscall.AF_INET: + v.IP = IPv4zero + case syscall.AF_INET6: + v.IP = IPv6unspecified + } + return v.sockaddr(f) + } + } + return la, nil +} diff --git a/libgo/go/net/sockopt.go b/libgo/go/net/sockopt.go index 3d0f8dd..b5b75a2 100644 --- a/libgo/go/net/sockopt.go +++ b/libgo/go/net/sockopt.go @@ -135,8 +135,8 @@ func setWriteDeadline(fd *netFD, t time.Time) error { } func setDeadline(fd *netFD, t time.Time) error { - if e := setReadDeadline(fd, t); e != nil { - return e + if err := setReadDeadline(fd, t); err != nil { + return err } return setWriteDeadline(fd, t) } diff --git a/libgo/go/net/sockopt_bsd.go b/libgo/go/net/sockopt_bsd.go index 2093e08..bc76465 100644 --- a/libgo/go/net/sockopt_bsd.go +++ b/libgo/go/net/sockopt_bsd.go @@ -9,37 +9,55 @@ package net import ( + "os" "syscall" ) -func setDefaultSockopts(s, f, t int) { +func setDefaultSockopts(s, f, t int) error { switch f { case syscall.AF_INET6: // Allow both IP versions even if the OS default is otherwise. + // Note that some operating systems never admit this option. syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) } if f == syscall.AF_UNIX || (f == syscall.AF_INET || f == syscall.AF_INET6) && t == syscall.SOCK_STREAM { // Allow reuse of recently-used addresses. - syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } // Allow reuse of recently-used ports. // This option is supported only in descendants of 4.4BSD, // to make an effective multicast application and an application // that requires quick draw possible. - syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) + err = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } } // Allow broadcast. - syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) + err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + + return nil } -func setDefaultMulticastSockopts(fd *netFD) { - fd.incref() - defer fd.decref() +func setDefaultMulticastSockopts(s int) error { // Allow multicast UDP and raw IP datagram sockets to listen // concurrently across multiple listeners. - syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) - syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) + err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + err = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + return nil } diff --git a/libgo/go/net/sockopt_linux.go b/libgo/go/net/sockopt_linux.go index 9dbb4e5..67c1dc8 100644 --- a/libgo/go/net/sockopt_linux.go +++ b/libgo/go/net/sockopt_linux.go @@ -7,31 +7,43 @@ package net import ( + "os" "syscall" ) -func setDefaultSockopts(s, f, t int) { +func setDefaultSockopts(s, f, t int) error { switch f { case syscall.AF_INET6: // Allow both IP versions even if the OS default is otherwise. + // Note that some operating systems never admit this option. syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) } if f == syscall.AF_UNIX || (f == syscall.AF_INET || f == syscall.AF_INET6) && t == syscall.SOCK_STREAM { // Allow reuse of recently-used addresses. - syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + } // Allow broadcast. - syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) + err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + return nil } -func setDefaultMulticastSockopts(fd *netFD) { - fd.incref() - defer fd.decref() +func setDefaultMulticastSockopts(s int) error { // Allow multicast UDP and raw IP datagram sockets to listen // concurrently across multiple listeners. - syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + return nil } diff --git a/libgo/go/net/sockopt_windows.go b/libgo/go/net/sockopt_windows.go index a7b5606..842bccc 100644 --- a/libgo/go/net/sockopt_windows.go +++ b/libgo/go/net/sockopt_windows.go @@ -7,13 +7,15 @@ package net import ( + "os" "syscall" ) -func setDefaultSockopts(s syscall.Handle, f, t int) { +func setDefaultSockopts(s syscall.Handle, f, t int) error { switch f { case syscall.AF_INET6: // Allow both IP versions even if the OS default is otherwise. + // Note that some operating systems never admit this option. syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) } @@ -26,13 +28,15 @@ func setDefaultSockopts(s syscall.Handle, f, t int) { // Allow broadcast. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) - + return nil } -func setDefaultMulticastSockopts(fd *netFD) { - fd.incref() - defer fd.decref() +func setDefaultMulticastSockopts(s syscall.Handle) error { // Allow multicast UDP and raw IP datagram sockets to listen // concurrently across multiple listeners. - syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + return nil } diff --git a/libgo/go/net/sockoptip_windows.go b/libgo/go/net/sockoptip_windows.go index 3320e76..a8a9d1c 100644 --- a/libgo/go/net/sockoptip_windows.go +++ b/libgo/go/net/sockoptip_windows.go @@ -7,6 +7,7 @@ package net import ( + "os" "syscall" ) @@ -16,8 +17,19 @@ func ipv4MulticastInterface(fd *netFD) (*Interface, error) { } func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { - // TODO: Implement this - return syscall.EWINDOWS + ip, err := interfaceToIPv4Addr(ifi) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + var x [4]byte + copy(x[:], ip.To4()) + fd.incref() + defer fd.decref() + err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + return nil } func ipv4MulticastTTL(fd *netFD) (int, error) { @@ -26,8 +38,14 @@ func ipv4MulticastTTL(fd *netFD) (int, error) { } func setIPv4MulticastTTL(fd *netFD, v int) error { - // TODO: Implement this - return syscall.EWINDOWS + fd.incref() + defer fd.decref() + err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + return nil + } func ipv4MulticastLoopback(fd *netFD) (bool, error) { @@ -36,8 +54,14 @@ func ipv4MulticastLoopback(fd *netFD) (bool, error) { } func setIPv4MulticastLoopback(fd *netFD, v bool) error { - // TODO: Implement this - return syscall.EWINDOWS + fd.incref() + defer fd.decref() + err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)) + if err != nil { + return os.NewSyscallError("setsockopt", err) + } + return nil + } func ipv4ReceiveInterface(fd *netFD) (bool, error) { diff --git a/libgo/go/net/tcpsock_plan9.go b/libgo/go/net/tcpsock_plan9.go index f2444a4..1287661 100644 --- a/libgo/go/net/tcpsock_plan9.go +++ b/libgo/go/net/tcpsock_plan9.go @@ -17,17 +17,17 @@ type TCPConn struct { plan9Conn } -// SetDeadline implements the net.Conn SetDeadline method. +// SetDeadline implements the Conn SetDeadline method. func (c *TCPConn) SetDeadline(t time.Time) error { return os.EPLAN9 } -// SetReadDeadline implements the net.Conn SetReadDeadline method. +// SetReadDeadline implements the Conn SetReadDeadline method. func (c *TCPConn) SetReadDeadline(t time.Time) error { return os.EPLAN9 } -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *TCPConn) SetWriteDeadline(t time.Time) error { return os.EPLAN9 } diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go index 65ec493..51a5d6f 100644 --- a/libgo/go/net/tcpsock_posix.go +++ b/libgo/go/net/tcpsock_posix.go @@ -67,7 +67,7 @@ func (c *TCPConn) ok() bool { return c != nil && c.fd != nil } // Implementation of the Conn interface - see Conn for documentation. -// Read implements the net.Conn Read method. +// Read implements the Conn Read method. func (c *TCPConn) Read(b []byte) (n int, err error) { if !c.ok() { return 0, os.EINVAL @@ -83,7 +83,7 @@ func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) { return genericReadFrom(c, r) } -// Write implements the net.Conn Write method. +// Write implements the Conn Write method. func (c *TCPConn) Write(b []byte) (n int, err error) { if !c.ok() { return 0, os.EINVAL @@ -135,7 +135,7 @@ func (c *TCPConn) RemoteAddr() Addr { return c.fd.raddr } -// SetDeadline implements the net.Conn SetDeadline method. +// SetDeadline implements the Conn SetDeadline method. func (c *TCPConn) SetDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -143,7 +143,7 @@ func (c *TCPConn) SetDeadline(t time.Time) error { return setDeadline(c.fd, t) } -// SetReadDeadline implements the net.Conn SetReadDeadline method. +// SetReadDeadline implements the Conn SetReadDeadline method. func (c *TCPConn) SetReadDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -151,7 +151,7 @@ func (c *TCPConn) SetReadDeadline(t time.Time) error { return setReadDeadline(c.fd, t) } -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *TCPConn) SetWriteDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -223,13 +223,13 @@ func (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() } // DialTCP connects to the remote address raddr on the network net, // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used // as the local address for the connection. -func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) { +func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) { if raddr == nil { return nil, &OpError{"dial", net, nil, errMissingAddress} } - fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) - if e != nil { - return nil, e + fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) + if err != nil { + return nil, err } return newTCPConn(fd), nil } @@ -245,7 +245,7 @@ type TCPListener struct { // 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 string, laddr *TCPAddr) (l *TCPListener, err error) { +func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP) if err != nil { return nil, err @@ -255,7 +255,7 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) { closesocket(fd.sysfd) return nil, &OpError{"listen", net, laddr, err} } - l = new(TCPListener) + l := new(TCPListener) l.fd = fd return l, nil } diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go index 573438f..f90a5fe 100644 --- a/libgo/go/net/udpsock_plan9.go +++ b/libgo/go/net/udpsock_plan9.go @@ -18,17 +18,17 @@ type UDPConn struct { plan9Conn } -// SetDeadline implements the net.Conn SetDeadline method. +// SetDeadline implements the Conn SetDeadline method. func (c *UDPConn) SetDeadline(t time.Time) error { return os.EPLAN9 } -// SetReadDeadline implements the net.Conn SetReadDeadline method. +// SetReadDeadline implements the Conn SetReadDeadline method. func (c *UDPConn) SetReadDeadline(t time.Time) error { return os.EPLAN9 } -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UDPConn) SetWriteDeadline(t time.Time) error { return os.EPLAN9 } @@ -66,7 +66,7 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) { return n, &UDPAddr{h.raddr, int(h.rport)}, nil } -// ReadFrom implements the net.PacketConn ReadFrom method. +// ReadFrom implements the PacketConn ReadFrom method. func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) { if !c.ok() { return 0, nil, os.EINVAL @@ -103,7 +103,7 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) { return c.data.Write(buf) } -// WriteTo implements the net.PacketConn WriteTo method. +// WriteTo implements the PacketConn WriteTo method. func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) { if !c.ok() { return 0, os.EINVAL @@ -186,20 +186,10 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) { return &UDPConn{*l.plan9Conn()}, nil } -// JoinGroup joins the IP multicast group named by addr on ifi, -// which specifies the interface to join. JoinGroup uses the -// default multicast interface if ifi is nil. -func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) error { - if !c.ok() { - return os.EINVAL - } - return os.EPLAN9 -} - -// LeaveGroup exits the IP multicast group named by addr on ifi. -func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error { - if !c.ok() { - return os.EINVAL - } - return os.EPLAN9 +// ListenMulticastUDP listens for incoming multicast UDP packets +// addressed to the group address gaddr on ifi, which specifies +// the interface to join. ListenMulticastUDP uses default +// multicast interface if ifi is nil. +func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) { + return nil, os.EPLAN9 } diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go index fa3d29a..6108373 100644 --- a/libgo/go/net/udpsock_posix.go +++ b/libgo/go/net/udpsock_posix.go @@ -60,16 +60,16 @@ func (c *UDPConn) ok() bool { return c != nil && c.fd != nil } // Implementation of the Conn interface - see Conn for documentation. -// Read implements the net.Conn Read method. -func (c *UDPConn) Read(b []byte) (n int, err error) { +// Read implements the Conn Read method. +func (c *UDPConn) Read(b []byte) (int, error) { if !c.ok() { return 0, os.EINVAL } return c.fd.Read(b) } -// Write implements the net.Conn Write method. -func (c *UDPConn) Write(b []byte) (n int, err error) { +// Write implements the Conn Write method. +func (c *UDPConn) Write(b []byte) (int, error) { if !c.ok() { return 0, os.EINVAL } @@ -102,7 +102,7 @@ func (c *UDPConn) RemoteAddr() Addr { return c.fd.raddr } -// SetDeadline implements the net.Conn SetDeadline method. +// SetDeadline implements the Conn SetDeadline method. func (c *UDPConn) SetDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -110,7 +110,7 @@ func (c *UDPConn) SetDeadline(t time.Time) error { return setDeadline(c.fd, t) } -// SetReadDeadline implements the net.Conn SetReadDeadline method. +// SetReadDeadline implements the Conn SetReadDeadline method. func (c *UDPConn) SetReadDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -118,7 +118,7 @@ func (c *UDPConn) SetReadDeadline(t time.Time) error { return setReadDeadline(c.fd, t) } -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UDPConn) SetWriteDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -166,8 +166,8 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) { return } -// ReadFrom implements the net.PacketConn ReadFrom method. -func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) { +// ReadFrom implements the PacketConn ReadFrom method. +func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { if !c.ok() { return 0, nil, os.EINVAL } @@ -195,7 +195,7 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { return c.fd.WriteTo(b, sa) } -// WriteTo implements the net.PacketConn WriteTo method. +// WriteTo implements the PacketConn WriteTo method. func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) { if !c.ok() { return 0, os.EINVAL @@ -207,10 +207,15 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) { return c.WriteToUDP(b, a) } +// File returns a copy of the underlying os.File, set to blocking mode. +// It is the caller's responsibility to close f when finished. +// Closing c does not affect f, and closing f does not affect c. +func (c *UDPConn) File() (f *os.File, err error) { return c.fd.dup() } + // DialUDP connects to the remote address raddr on the network net, // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used // as the local address for the connection. -func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) { +func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) { switch net { case "udp", "udp4", "udp6": default: @@ -219,9 +224,9 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) { if raddr == nil { return nil, &OpError{"dial", net, nil, errMissingAddress} } - fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP) - if e != nil { - return nil, e + fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP) + if err != nil { + return nil, err } return newUDPConn(fd), nil } @@ -246,36 +251,75 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) { return newUDPConn(fd), nil } -// File returns a copy of the underlying os.File, set to blocking mode. -// It is the caller's responsibility to close f when finished. -// Closing c does not affect f, and closing f does not affect c. -func (c *UDPConn) File() (f *os.File, err error) { return c.fd.dup() } +// ListenMulticastUDP listens for incoming multicast UDP packets +// addressed to the group address gaddr on ifi, which specifies +// the interface to join. ListenMulticastUDP uses default +// multicast interface if ifi is nil. +func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) { + switch net { + case "udp", "udp4", "udp6": + default: + return nil, UnknownNetworkError(net) + } + if gaddr == nil || gaddr.IP == nil { + return nil, &OpError{"listenmulticastudp", "udp", nil, errMissingAddress} + } + fd, err := internetSocket(net, gaddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP) + if err != nil { + return nil, err + } + c := newUDPConn(fd) + ip4 := gaddr.IP.To4() + if ip4 != nil { + err := listenIPv4MulticastUDP(c, ifi, ip4) + if err != nil { + c.Close() + return nil, err + } + } else { + err := listenIPv6MulticastUDP(c, ifi, gaddr.IP) + if err != nil { + c.Close() + return nil, err + } + } + return c, nil +} -// JoinGroup joins the IP multicast group named by addr on ifi, -// which specifies the interface to join. JoinGroup uses the -// default multicast interface if ifi is nil. -func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) error { - if !c.ok() { - return os.EINVAL +func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error { + if ifi != nil { + err := setIPv4MulticastInterface(c.fd, ifi) + if err != nil { + return err + } + } + err := setIPv4MulticastLoopback(c.fd, false) + if err != nil { + return err } - setDefaultMulticastSockopts(c.fd) - ip := addr.To4() - if ip != nil { - return joinIPv4GroupUDP(c, ifi, ip) + err = joinIPv4GroupUDP(c, ifi, ip) + if err != nil { + return err } - return joinIPv6GroupUDP(c, ifi, addr) + return nil } -// LeaveGroup exits the IP multicast group named by addr on ifi. -func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error { - if !c.ok() { - return os.EINVAL +func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error { + if ifi != nil { + err := setIPv6MulticastInterface(c.fd, ifi) + if err != nil { + return err + } } - ip := addr.To4() - if ip != nil { - return leaveIPv4GroupUDP(c, ifi, ip) + err := setIPv6MulticastLoopback(c.fd, false) + if err != nil { + return err + } + err = joinIPv6GroupUDP(c, ifi, ip) + if err != nil { + return err } - return leaveIPv6GroupUDP(c, ifi, addr) + return nil } func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error { diff --git a/libgo/go/net/unixsock_plan9.go b/libgo/go/net/unixsock_plan9.go index e8087d0..1d9d757 100644 --- a/libgo/go/net/unixsock_plan9.go +++ b/libgo/go/net/unixsock_plan9.go @@ -17,12 +17,12 @@ type UnixConn bool // Implementation of the Conn interface - see Conn for documentation. -// Read implements the net.Conn Read method. +// Read implements the Conn Read method. func (c *UnixConn) Read(b []byte) (n int, err error) { return 0, os.EPLAN9 } -// Write implements the net.Conn Write method. +// Write implements the Conn Write method. func (c *UnixConn) Write(b []byte) (n int, err error) { return 0, os.EPLAN9 } @@ -45,28 +45,28 @@ func (c *UnixConn) RemoteAddr() Addr { return nil } -// SetDeadline implements the net.Conn SetDeadline method. +// SetDeadline implements the Conn SetDeadline method. func (c *UnixConn) SetDeadline(t time.Time) error { return os.EPLAN9 } -// SetReadDeadline implements the net.Conn SetReadDeadline method. +// SetReadDeadline implements the Conn SetReadDeadline method. func (c *UnixConn) SetReadDeadline(t time.Time) error { return os.EPLAN9 } -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UnixConn) SetWriteDeadline(t time.Time) error { return os.EPLAN9 } -// ReadFrom implements the net.PacketConn ReadFrom method. +// ReadFrom implements the PacketConn ReadFrom method. func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) { err = os.EPLAN9 return } -// WriteTo implements the net.PacketConn WriteTo method. +// WriteTo implements the PacketConn WriteTo method. func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) { err = os.EPLAN9 return diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go index e500ddb..10b7966 100644 --- a/libgo/go/net/unixsock_posix.go +++ b/libgo/go/net/unixsock_posix.go @@ -120,7 +120,7 @@ func (c *UnixConn) ok() bool { return c != nil && c.fd != nil } // Implementation of the Conn interface - see Conn for documentation. -// Read implements the net.Conn Read method. +// Read implements the Conn Read method. func (c *UnixConn) Read(b []byte) (n int, err error) { if !c.ok() { return 0, os.EINVAL @@ -128,7 +128,7 @@ func (c *UnixConn) Read(b []byte) (n int, err error) { return c.fd.Read(b) } -// Write implements the net.Conn Write method. +// Write implements the Conn Write method. func (c *UnixConn) Write(b []byte) (n int, err error) { if !c.ok() { return 0, os.EINVAL @@ -165,7 +165,7 @@ func (c *UnixConn) RemoteAddr() Addr { return c.fd.raddr } -// SetDeadline implements the net.Conn SetDeadline method. +// SetDeadline implements the Conn SetDeadline method. func (c *UnixConn) SetDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -173,7 +173,7 @@ func (c *UnixConn) SetDeadline(t time.Time) error { return setDeadline(c.fd, t) } -// SetReadDeadline implements the net.Conn SetReadDeadline method. +// SetReadDeadline implements the Conn SetReadDeadline method. func (c *UnixConn) SetReadDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -181,7 +181,7 @@ func (c *UnixConn) SetReadDeadline(t time.Time) error { return setReadDeadline(c.fd, t) } -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UnixConn) SetWriteDeadline(t time.Time) error { if !c.ok() { return os.EINVAL @@ -226,7 +226,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) { return } -// ReadFrom implements the net.PacketConn ReadFrom method. +// ReadFrom implements the PacketConn ReadFrom method. func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) { if !c.ok() { return 0, nil, os.EINVAL @@ -252,7 +252,7 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) { return c.fd.WriteTo(b, sa) } -// WriteTo implements the net.PacketConn WriteTo method. +// WriteTo implements the PacketConn WriteTo method. func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) { if !c.ok() { return 0, os.EINVAL @@ -298,10 +298,10 @@ func (c *UnixConn) File() (f *os.File, err error) { return c.fd.dup() } // DialUnix connects to the remote address raddr on the network net, // which must be "unix" or "unixgram". If laddr is not nil, it is used // as the local address for the connection. -func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error) { - fd, e := unixSocket(net, laddr, raddr, "dial") - if e != nil { - return nil, e +func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) { + fd, err := unixSocket(net, laddr, raddr, "dial") + if err != nil { + return nil, err } return newUnixConn(fd), nil } @@ -337,15 +337,15 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) { // AcceptUnix accepts the next incoming call and returns the new connection // and the remote address. -func (l *UnixListener) AcceptUnix() (c *UnixConn, err error) { +func (l *UnixListener) AcceptUnix() (*UnixConn, error) { if l == nil || l.fd == nil { return nil, os.EINVAL } - fd, e := l.fd.accept(sockaddrToUnix) - if e != nil { - return nil, e + fd, err := l.fd.accept(sockaddrToUnix) + if err != nil { + return nil, err } - c = newUnixConn(fd) + c := newUnixConn(fd) return c, nil } @@ -405,7 +405,7 @@ func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() } // local address laddr. The returned connection c's ReadFrom // and WriteTo methods can be used to receive and send UDP // packets with per-packet addressing. The network net must be "unixgram". -func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err error) { +func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error) { switch net { case "unixgram": default: @@ -414,9 +414,9 @@ func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err error) { if laddr == nil { return nil, &OpError{"listen", net, nil, errMissingAddress} } - fd, e := unixSocket(net, laddr, nil, "listen") - if e != nil { - return nil, e + fd, err := unixSocket(net, laddr, nil, "listen") + if err != nil { + return nil, err } return newUDPConn(fd), nil } diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go index 0068e98..a9ce3b3 100644 --- a/libgo/go/net/url/url.go +++ b/libgo/go/net/url/url.go @@ -431,30 +431,30 @@ func ParseWithReference(rawurlref string) (url *URL, err error) { return url, nil } -// String reassembles url into a valid URL string. -func (url *URL) String() string { +// String reassembles the URL into a valid URL string. +func (u *URL) String() string { // TODO: Rewrite to use bytes.Buffer result := "" - if url.Scheme != "" { - result += url.Scheme + ":" + if u.Scheme != "" { + result += u.Scheme + ":" } - if url.Opaque != "" { - result += url.Opaque + if u.Opaque != "" { + result += u.Opaque } else { - if url.Host != "" || url.User != nil { + if u.Host != "" || u.User != nil { result += "//" - if u := url.User; u != nil { + if u := u.User; u != nil { result += u.String() + "@" } - result += url.Host + result += u.Host } - result += escape(url.Path, encodePath) + result += escape(u.Path, encodePath) } - if url.RawQuery != "" { - result += "?" + url.RawQuery + if u.RawQuery != "" { + result += "?" + u.RawQuery } - if url.Fragment != "" { - result += "#" + escape(url.Fragment, encodeFragment) + if u.Fragment != "" { + result += "#" + escape(u.Fragment, encodeFragment) } return result } @@ -585,8 +585,8 @@ func resolvePath(basepath string, refpath string) string { } // IsAbs returns true if the URL is absolute. -func (url *URL) IsAbs() bool { - return url.Scheme != "" +func (u *URL) IsAbs() bool { + return u.Scheme != "" } // Parse parses a URL in the context of a base URL. The URL in ref |