summaryrefslogtreecommitdiff
path: root/libgo/go/net/tcpsock_posix.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/tcpsock_posix.go')
-rw-r--r--libgo/go/net/tcpsock_posix.go99
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
}