diff options
Diffstat (limited to 'libgo/go/net/tcpsock_posix.go')
-rw-r--r-- | libgo/go/net/tcpsock_posix.go | 99 |
1 files changed, 67 insertions, 32 deletions
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go index dd78aefa773..7e49b769e1c 100644 --- a/libgo/go/net/tcpsock_posix.go +++ b/libgo/go/net/tcpsock_posix.go @@ -13,11 +13,6 @@ import ( "time" ) -// BUG(rsc): On OpenBSD, listening on the "tcp" network does not listen for -// both IPv4 and IPv6 connections. This is due to the fact that IPv4 traffic -// will not be routed to an IPv6 socket - two separate sockets are required -// if both AFs are to be supported. See inet6(4) on OpenBSD for details. - func sockaddrToTCP(sa syscall.Sockaddr) Addr { switch sa := sa.(type) { case *syscall.SockaddrInet4: @@ -38,13 +33,6 @@ func (a *TCPAddr) family() int { return syscall.AF_INET6 } -func (a *TCPAddr) isWildcard() bool { - if a == nil || a.IP == nil { - return true - } - return a.IP.IsUnspecified() -} - func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) { if a == nil { return nil, nil @@ -60,16 +48,23 @@ type TCPConn struct { func newTCPConn(fd *netFD) *TCPConn { c := &TCPConn{conn{fd}} - c.SetNoDelay(true) + setNoDelay(c.fd, true) return c } // ReadFrom implements the io.ReaderFrom ReadFrom method. func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) { if n, err, handled := sendFile(c.fd, r); handled { + if err != nil && err != io.EOF { + err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } return n, err } - return genericReadFrom(c, r) + n, err := genericReadFrom(c, r) + if err != nil && err != io.EOF { + err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return n, err } // CloseRead shuts down the reading side of the TCP connection. @@ -78,7 +73,11 @@ func (c *TCPConn) CloseRead() error { if !c.ok() { return syscall.EINVAL } - return c.fd.closeRead() + err := c.fd.closeRead() + if err != nil { + err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return err } // CloseWrite shuts down the writing side of the TCP connection. @@ -87,7 +86,11 @@ func (c *TCPConn) CloseWrite() error { if !c.ok() { return syscall.EINVAL } - return c.fd.closeWrite() + err := c.fd.closeWrite() + if err != nil { + err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return err } // SetLinger sets the behavior of Close on a connection which still @@ -106,7 +109,10 @@ func (c *TCPConn) SetLinger(sec int) error { if !c.ok() { return syscall.EINVAL } - return setLinger(c.fd, sec) + if err := setLinger(c.fd, sec); err != nil { + return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return nil } // SetKeepAlive sets whether the operating system should send @@ -115,7 +121,10 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) error { if !c.ok() { return syscall.EINVAL } - return setKeepAlive(c.fd, keepalive) + if err := setKeepAlive(c.fd, keepalive); err != nil { + return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return nil } // SetKeepAlivePeriod sets period between keep alives. @@ -123,7 +132,10 @@ func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error { if !c.ok() { return syscall.EINVAL } - return setKeepAlivePeriod(c.fd, d) + if err := setKeepAlivePeriod(c.fd, d); err != nil { + return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return nil } // SetNoDelay controls whether the operating system should delay @@ -134,7 +146,10 @@ func (c *TCPConn) SetNoDelay(noDelay bool) error { if !c.ok() { return syscall.EINVAL } - return setNoDelay(c.fd, noDelay) + if err := setNoDelay(c.fd, noDelay); err != nil { + return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return nil } // DialTCP connects to the remote address raddr on the network net, @@ -144,10 +159,10 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) { switch net { case "tcp", "tcp4", "tcp6": default: - return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)} + return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)} } if raddr == nil { - return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: errMissingAddress} + return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress} } return dialTCP(net, laddr, raddr, noDeadline) } @@ -170,7 +185,7 @@ func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e // see this happen, rather than expose the buggy effect to users, we // close the fd and try again. If it happens twice more, we relent and // use the result. See also: - // http://golang.org/issue/2690 + // https://golang.org/issue/2690 // http://stackoverflow.com/questions/4949858/ // // The opposite can also happen: if we ask the kernel to pick an appropriate @@ -187,7 +202,7 @@ func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e } if err != nil { - return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err} + return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err} } return newTCPConn(fd), nil } @@ -215,8 +230,13 @@ func selfConnect(fd *netFD, err error) bool { } func spuriousENOTAVAIL(err error) bool { - e, ok := err.(*OpError) - return ok && e.Err == syscall.EADDRNOTAVAIL + if op, ok := err.(*OpError); ok { + err = op.Err + } + if sys, ok := err.(*os.SyscallError); ok { + err = sys.Err + } + return err == syscall.EADDRNOTAVAIL } // TCPListener is a TCP network listener. Clients should typically @@ -233,7 +253,7 @@ func (l *TCPListener) AcceptTCP() (*TCPConn, error) { } fd, err := l.fd.accept() if err != nil { - return nil, err + return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err} } return newTCPConn(fd), nil } @@ -254,10 +274,16 @@ func (l *TCPListener) Close() error { if l == nil || l.fd == nil { return syscall.EINVAL } - return l.fd.Close() + err := l.fd.Close() + if err != nil { + err = &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err} + } + return err } // Addr returns the listener's network address, a *TCPAddr. +// The Addr returned is shared by all invocations of Addr, so +// do not modify it. func (l *TCPListener) Addr() Addr { return l.fd.laddr } // SetDeadline sets the deadline associated with the listener. @@ -266,7 +292,10 @@ func (l *TCPListener) SetDeadline(t time.Time) error { if l == nil || l.fd == nil { return syscall.EINVAL } - return l.fd.setDeadline(t) + if err := l.fd.setDeadline(t); err != nil { + return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err} + } + return nil } // File returns a copy of the underlying os.File, set to blocking @@ -276,7 +305,13 @@ func (l *TCPListener) SetDeadline(t time.Time) error { // The returned os.File's file descriptor is different from the // connection's. Attempting to change properties of the original // using this duplicate may or may not have the desired effect. -func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() } +func (l *TCPListener) File() (f *os.File, err error) { + f, err = l.fd.dup() + if err != nil { + err = &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err} + } + return +} // ListenTCP announces on the TCP address laddr and returns a TCP // listener. Net must be "tcp", "tcp4", or "tcp6". If laddr has a @@ -286,14 +321,14 @@ func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { switch net { case "tcp", "tcp4", "tcp6": default: - return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)} + return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)} } if laddr == nil { laddr = &TCPAddr{} } fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_STREAM, 0, "listen") if err != nil { - return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err} + return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err} } return &TCPListener{fd}, nil } |