]> Cypherpunks repositories - gostls13.git/commitdiff
net: add Source field to OpError
authorMikio Hara <mikioh.mikioh@gmail.com>
Tue, 21 Apr 2015 13:53:47 +0000 (22:53 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Wed, 29 Apr 2015 22:37:30 +0000 (22:37 +0000)
Not only by network, transport-layer intermediaries but by
virtualization stuff in a node, it is hard to identify the root cause of
weird faults without information of packet flows after disaster
happened.

This change adds Source field to OpError to be able to represent a
5-tuple of internet transport protocols for helping dealing with
complicated systems.

Also clarifies the usage of Source and Addr fields.

Updates #4856.

Change-Id: I96a523fe391ed14406bfb21604c461d4aac2fa19
Reviewed-on: https://go-review.googlesource.com/9231
Reviewed-by: Ian Lance Taylor <iant@golang.org>
16 files changed:
src/net/dial.go
src/net/dial_gen.go
src/net/error_test.go
src/net/file.go
src/net/interface.go
src/net/iprawsock_plan9.go
src/net/iprawsock_posix.go
src/net/ipsock_plan9.go
src/net/net.go
src/net/pipe.go
src/net/tcpsock_plan9.go
src/net/tcpsock_posix.go
src/net/udpsock_plan9.go
src/net/udpsock_posix.go
src/net/unixsock_plan9.go
src/net/unixsock_posix.go

index feca759f827cac0971744fd3a31ff8cad778c75b..4f0c6cb0eac4f6327361aed23940b0876255b884 100644 (file)
@@ -161,7 +161,7 @@ func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
 func (d *Dialer) Dial(network, address string) (Conn, error) {
        addrs, err := resolveAddrList("dial", network, address, d.deadline())
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: network, Addr: nil, Err: err}
+               return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err}
        }
        var dialer func(deadline time.Time) (Conn, error)
        if d.DualStack && network == "tcp" {
@@ -235,7 +235,7 @@ func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Con
 // the destination address.
 func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
        if la != nil && la.Network() != ra.Network() {
-               return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
+               return nil, &OpError{Op: "dial", Net: net, Source: la, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
        }
        switch ra := ra.(type) {
        case *TCPAddr:
@@ -251,7 +251,7 @@ func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err
                la, _ := la.(*UnixAddr)
                c, err = dialUnix(net, la, ra, deadline)
        default:
-               return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}}
+               return nil, &OpError{Op: "dial", Net: net, Source: la, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}}
        }
        if err != nil {
                return nil, err // c is non-nil interface containing nil pointer
@@ -266,7 +266,7 @@ func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err
 func Listen(net, laddr string) (Listener, error) {
        addrs, err := resolveAddrList("listen", net, laddr, noDeadline)
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err}
        }
        var l Listener
        switch la := addrs.first(isIPv4).(type) {
@@ -275,7 +275,7 @@ func Listen(net, laddr string) (Listener, error) {
        case *UnixAddr:
                l, err = ListenUnix(net, la)
        default:
-               return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
        }
        if err != nil {
                return nil, err // l is non-nil interface containing nil pointer
@@ -290,7 +290,7 @@ func Listen(net, laddr string) (Listener, error) {
 func ListenPacket(net, laddr string) (PacketConn, error) {
        addrs, err := resolveAddrList("listen", net, laddr, noDeadline)
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err}
        }
        var l PacketConn
        switch la := addrs.first(isIPv4).(type) {
@@ -301,7 +301,7 @@ func ListenPacket(net, laddr string) (PacketConn, error) {
        case *UnixAddr:
                l, err = ListenUnixgram(net, la)
        default:
-               return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
        }
        if err != nil {
                return nil, err // l is non-nil interface containing nil pointer
index 3816844b2603353dad9e0300ab81eeca73ffbbe2..a628f7148351d9a3ef267275432a5fbd35ba1029 100644 (file)
@@ -17,7 +17,7 @@ func dialChannel(net string, ra Addr, dialer func(time.Time) (Conn, error), dead
        }
        timeout := deadline.Sub(time.Now())
        if timeout <= 0 {
-               return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errTimeout}
+               return nil, &OpError{Op: "dial", Net: net, Source: nil, Addr: ra, Err: errTimeout}
        }
        t := time.NewTimer(timeout)
        defer t.Stop()
@@ -33,7 +33,7 @@ func dialChannel(net string, ra Addr, dialer func(time.Time) (Conn, error), dead
        }()
        select {
        case <-t.C:
-               return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errTimeout}
+               return nil, &OpError{Op: "dial", Net: net, Source: nil, Addr: ra, Err: errTimeout}
        case racer := <-ch:
                return racer.Conn, racer.error
        }
index 03c646c7c99b01e81328250e7c57851d6f608e2d..75b125d435a237e739e01c9a9a385d5ba7a471b2 100644 (file)
@@ -32,34 +32,13 @@ func (e *OpError) isValid() error {
        if e.Net == "" {
                return fmt.Errorf("OpError.Net is empty: %v", e)
        }
-       switch addr := e.Addr.(type) {
-       case *TCPAddr:
-               if addr == nil {
-                       return fmt.Errorf("OpError.Addr is empty: %v", e)
-               }
-       case *UDPAddr:
-               if addr == nil {
-                       return fmt.Errorf("OpError.Addr is empty: %v", e)
-               }
-       case *IPAddr:
-               if addr == nil {
-                       return fmt.Errorf("OpError.Addr is empty: %v", e)
-               }
-       case *IPNet:
-               if addr == nil {
-                       return fmt.Errorf("OpError.Addr is empty: %v", e)
-               }
-       case *UnixAddr:
-               if addr == nil {
-                       return fmt.Errorf("OpError.Addr is empty: %v", e)
-               }
-       case *pipeAddr:
-               if addr == nil {
-                       return fmt.Errorf("OpError.Addr is empty: %v", e)
-               }
-       case fileAddr:
-               if addr == "" {
-                       return fmt.Errorf("OpError.Addr is empty: %v", e)
+       for _, addr := range []Addr{e.Source, e.Addr} {
+               if addr != nil {
+                       switch addr.(type) {
+                       case *TCPAddr, *UDPAddr, *IPAddr, *IPNet, *UnixAddr, *pipeAddr, fileAddr:
+                       default:
+                               return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
+                       }
                }
        }
        if e.Err == nil {
index be93e2c6c0953e76142669f29c5a016b984930cb..1aad477400c2d0494709e87eceb23b68fe2d78ca 100644 (file)
@@ -18,7 +18,7 @@ func (f fileAddr) String() string { return string(f) }
 func FileConn(f *os.File) (c Conn, err error) {
        c, err = fileConn(f)
        if err != nil {
-               err = &OpError{Op: "file", Net: "file+net", Addr: fileAddr(f.Name()), Err: err}
+               err = &OpError{Op: "file", Net: "file+net", Source: nil, Addr: fileAddr(f.Name()), Err: err}
        }
        return
 }
@@ -30,7 +30,7 @@ func FileConn(f *os.File) (c Conn, err error) {
 func FileListener(f *os.File) (ln Listener, err error) {
        ln, err = fileListener(f)
        if err != nil {
-               err = &OpError{Op: "file", Net: "file+net", Addr: fileAddr(f.Name()), Err: err}
+               err = &OpError{Op: "file", Net: "file+net", Source: nil, Addr: fileAddr(f.Name()), Err: err}
        }
        return
 }
@@ -42,7 +42,7 @@ func FileListener(f *os.File) (ln Listener, err error) {
 func FilePacketConn(f *os.File) (c PacketConn, err error) {
        c, err = filePacketConn(f)
        if err != nil {
-               err = &OpError{Op: "file", Net: "file+net", Addr: fileAddr(f.Name()), Err: err}
+               err = &OpError{Op: "file", Net: "file+net", Source: nil, Addr: fileAddr(f.Name()), Err: err}
        }
        return
 }
index e6d874f53840307864bb603ab1dbe33b118e790d..9c7b5da8fe9153eeed290faae9aee24970fbe1b5 100644 (file)
@@ -62,11 +62,11 @@ func (f Flags) String() string {
 // Addrs returns interface addresses for a specific interface.
 func (ifi *Interface) Addrs() ([]Addr, error) {
        if ifi == nil {
-               return nil, &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: errInvalidInterface}
+               return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
        }
        ifat, err := interfaceAddrTable(ifi)
        if err != nil {
-               err = &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: err}
+               err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
        }
        return ifat, err
 }
@@ -75,11 +75,11 @@ func (ifi *Interface) Addrs() ([]Addr, error) {
 // a specific interface.
 func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
        if ifi == nil {
-               return nil, &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: errInvalidInterface}
+               return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
        }
        ifat, err := interfaceMulticastAddrTable(ifi)
        if err != nil {
-               err = &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: err}
+               err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
        }
        return ifat, err
 }
@@ -88,7 +88,7 @@ func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
 func Interfaces() ([]Interface, error) {
        ift, err := interfaceTable(0)
        if err != nil {
-               err = &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: err}
+               err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
        }
        return ift, err
 }
@@ -98,7 +98,7 @@ func Interfaces() ([]Interface, error) {
 func InterfaceAddrs() ([]Addr, error) {
        ifat, err := interfaceAddrTable(nil)
        if err != nil {
-               err = &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: err}
+               err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
        }
        return ifat, err
 }
@@ -106,15 +106,15 @@ func InterfaceAddrs() ([]Addr, error) {
 // InterfaceByIndex returns the interface specified by index.
 func InterfaceByIndex(index int) (*Interface, error) {
        if index <= 0 {
-               return nil, &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: errInvalidInterfaceIndex}
+               return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex}
        }
        ift, err := interfaceTable(index)
        if err != nil {
-               return nil, &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: err}
+               return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
        }
        ifi, err := interfaceByIndex(ift, index)
        if err != nil {
-               err = &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: err}
+               err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
        }
        return ifi, err
 }
@@ -131,16 +131,16 @@ func interfaceByIndex(ift []Interface, index int) (*Interface, error) {
 // InterfaceByName returns the interface specified by name.
 func InterfaceByName(name string) (*Interface, error) {
        if name == "" {
-               return nil, &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: errInvalidInterfaceName}
+               return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceName}
        }
        ift, err := interfaceTable(0)
        if err != nil {
-               return nil, &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: err}
+               return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
        }
        for _, ifi := range ift {
                if name == ifi.Name {
                        return &ifi, nil
                }
        }
-       return nil, &OpError{Op: "route", Net: "ip+net", Addr: nil, Err: errNoSuchInterface}
+       return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errNoSuchInterface}
 }
index a3d86496066acbcb03a1d52cdc9f174d8a3b071a..079629064e59bb5001636a2f61dc304571a86a2d 100644 (file)
@@ -23,12 +23,12 @@ type IPConn struct {
 // Timeout() == true after a fixed time limit; see SetDeadline and
 // SetReadDeadline.
 func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
-       return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // ReadFrom implements the PacketConn ReadFrom method.
 func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
-       return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // ReadMsgIP reads a packet from c, copying the payload into b and the
@@ -36,7 +36,7 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
 // bytes copied into b, the number of bytes copied into oob, the flags
 // that were set on the packet and the source address of the packet.
 func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
-       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // WriteToIP writes an IP packet to addr via c, copying the payload
@@ -47,19 +47,19 @@ func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err
 // SetWriteDeadline.  On packet-oriented connections, write timeouts
 // are rare.
 func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
-       return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EPLAN9}
+       return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
 }
 
 // WriteTo implements the PacketConn WriteTo method.
 func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
-       return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EPLAN9}
+       return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
 }
 
 // WriteMsgIP writes a packet to addr via c, copying the payload from
 // b and the associated out-of-band data from oob.  It returns the
 // number of payload and out-of-band bytes written.
 func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
-       return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EPLAN9}
+       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
 }
 
 // DialIP connects to the remote address raddr on the network protocol
@@ -70,7 +70,7 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
 }
 
 func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
-       return nil, syscall.EPLAN9
+       return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: syscall.EPLAN9}
 }
 
 // ListenIP listens for incoming IP packets addressed to the local
@@ -78,5 +78,5 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
 // methods can be used to receive and send IP packets with per-packet
 // addressing.
 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
-       return nil, syscall.EPLAN9
+       return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr, Err: syscall.EPLAN9}
 }
index 26ef05ff570509b427057a02a9b9709b3cab7883..1102823ef656efaf0615ef88c07dc5f5ff266671 100644 (file)
@@ -81,7 +81,7 @@ func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
                addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
        }
        if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return n, addr, err
 }
@@ -130,7 +130,7 @@ func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err
                addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
        }
        if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return
 }
@@ -147,18 +147,18 @@ func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
                return 0, syscall.EINVAL
        }
        if c.fd.isConnected {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
        }
        sa, err := addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        n, err := c.fd.writeTo(b, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        return n, err
 }
@@ -170,7 +170,7 @@ func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
        }
        a, ok := addr.(*IPAddr)
        if !ok {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EINVAL}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
        }
        return c.WriteToIP(b, a)
 }
@@ -183,19 +183,19 @@ func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error
                return 0, 0, syscall.EINVAL
        }
        if c.fd.isConnected {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
        }
        if addr == nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
        }
        var sa syscall.Sockaddr
        sa, err = addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        n, oobn, err = c.fd.writeMsg(b, oob, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        return
 }
@@ -210,19 +210,19 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
 func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
        net, proto, err := parseNetwork(netProto)
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: err}
        }
        switch net {
        case "ip", "ip4", "ip6":
        default:
-               return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: UnknownNetworkError(netProto)}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: UnknownNetworkError(netProto)}
        }
        if raddr == nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Addr: nil, Err: errMissingAddress}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: errMissingAddress}
        }
        fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial")
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: err}
        }
        return newIPConn(fd), nil
 }
@@ -234,16 +234,16 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
        net, proto, err := parseNetwork(netProto)
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Addr: laddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: nil, Addr: laddr, Err: err}
        }
        switch net {
        case "ip", "ip4", "ip6":
        default:
-               return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: UnknownNetworkError(netProto)}
+               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr, Err: UnknownNetworkError(netProto)}
        }
        fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen")
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: err}
+               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr, Err: err}
        }
        return newIPConn(fd), nil
 }
index 1c2932d1c1be8a887a89a5821e9d41c9dbcd72f3..11b6b32e0b41fee364b69e39bd2c32f48c24674d 100644 (file)
@@ -152,23 +152,23 @@ func dialPlan9(net string, laddr, raddr Addr) (fd *netFD, err error) {
        defer func() { netErr(err) }()
        f, dest, proto, name, err := startPlan9(net, raddr)
        if err != nil {
-               return nil, &OpError{"dial", net, raddr, err}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: err}
        }
        _, err = f.WriteString("connect " + dest)
        if err != nil {
                f.Close()
-               return nil, &OpError{"dial", f.Name(), raddr, err}
+               return nil, &OpError{Op: "dial", Net: f.Name(), Source: laddr, Addr: raddr, Err: err}
        }
        data, err := os.OpenFile(netdir+"/"+proto+"/"+name+"/data", os.O_RDWR, 0)
        if err != nil {
                f.Close()
-               return nil, &OpError{"dial", net, raddr, err}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: err}
        }
        laddr, err = readPlan9Addr(proto, netdir+"/"+proto+"/"+name+"/local")
        if err != nil {
                data.Close()
                f.Close()
-               return nil, &OpError{"dial", proto, raddr, err}
+               return nil, &OpError{Op: "dial", Net: proto, Source: laddr, Addr: raddr, Err: err}
        }
        return newFD(proto, name, f, data, laddr, raddr)
 }
@@ -177,52 +177,52 @@ func listenPlan9(net string, laddr Addr) (fd *netFD, err error) {
        defer func() { netErr(err) }()
        f, dest, proto, name, err := startPlan9(net, laddr)
        if err != nil {
-               return nil, &OpError{"listen", net, laddr, err}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
        }
        _, err = f.WriteString("announce " + dest)
        if err != nil {
                f.Close()
-               return nil, &OpError{"announce", proto, laddr, err}
+               return nil, &OpError{Op: "announce", Net: proto, Source: nil, Addr: laddr, Err: err}
        }
        laddr, err = readPlan9Addr(proto, netdir+"/"+proto+"/"+name+"/local")
        if err != nil {
                f.Close()
-               return nil, &OpError{Op: "listen", Net: net, Err: err}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
        }
        return newFD(proto, name, f, nil, laddr, nil)
 }
 
-func (l *netFD) netFD() (*netFD, error) {
-       return newFD(l.net, l.n, l.ctl, l.data, l.laddr, l.raddr)
+func (fd *netFD) netFD() (*netFD, error) {
+       return newFD(fd.net, fd.n, fd.ctl, fd.data, fd.laddr, fd.raddr)
 }
 
-func (l *netFD) acceptPlan9() (fd *netFD, err error) {
+func (fd *netFD) acceptPlan9() (nfd *netFD, err error) {
        defer func() { netErr(err) }()
-       if err := l.readLock(); err != nil {
+       if err := fd.readLock(); err != nil {
                return nil, err
        }
-       defer l.readUnlock()
-       f, err := os.Open(l.dir + "/listen")
+       defer fd.readUnlock()
+       f, err := os.Open(fd.dir + "/listen")
        if err != nil {
-               return nil, &OpError{"accept", l.dir + "/listen", l.laddr, err}
+               return nil, &OpError{Op: "accept", Net: fd.dir + "/listen", Source: nil, Addr: fd.laddr, Err: err}
        }
        var buf [16]byte
        n, err := f.Read(buf[:])
        if err != nil {
                f.Close()
-               return nil, &OpError{"accept", l.dir + "/listen", l.laddr, err}
+               return nil, &OpError{Op: "accept", Net: fd.dir + "/listen", Source: nil, Addr: fd.laddr, Err: err}
        }
        name := string(buf[:n])
-       data, err := os.OpenFile(netdir+"/"+l.net+"/"+name+"/data", os.O_RDWR, 0)
+       data, err := os.OpenFile(netdir+"/"+fd.net+"/"+name+"/data", os.O_RDWR, 0)
        if err != nil {
                f.Close()
-               return nil, &OpError{"accept", l.net, l.laddr, err}
+               return nil, &OpError{Op: "accept", Net: fd.net, Source: nil, Addr: fd.laddr, Err: err}
        }
-       raddr, err := readPlan9Addr(l.net, netdir+"/"+l.net+"/"+name+"/remote")
+       raddr, err := readPlan9Addr(fd.net, netdir+"/"+fd.net+"/"+name+"/remote")
        if err != nil {
                data.Close()
                f.Close()
-               return nil, &OpError{"accept", l.net, l.laddr, err}
+               return nil, &OpError{Op: "accept", Net: fd.net, Source: nil, Addr: fd.laddr, Err: err}
        }
-       return newFD(l.net, name, f, data, l.laddr, raddr)
+       return newFD(fd.net, name, f, data, fd.laddr, raddr)
 }
index 41fc0815dee5905c4071554826b02e0cad87bf21..955d0185d22172feb4cbe35fa9ac2e0dee0ac18b 100644 (file)
@@ -123,12 +123,7 @@ func (c *conn) Read(b []byte) (int, error) {
        }
        n, err := c.fd.Read(b)
        if err != nil && err != io.EOF {
-               err = &OpError{Op: "read", Net: c.fd.net, Err: err}
-               if c.fd.raddr != nil {
-                       err.(*OpError).Addr = c.fd.raddr
-               } else {
-                       err.(*OpError).Addr = c.fd.laddr // for unconnected-mode sockets
-               }
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return n, err
 }
@@ -140,12 +135,7 @@ func (c *conn) Write(b []byte) (int, error) {
        }
        n, err := c.fd.Write(b)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Err: err}
-               if c.fd.raddr != nil {
-                       err.(*OpError).Addr = c.fd.raddr
-               } else {
-                       err.(*OpError).Addr = c.fd.laddr // for unconnected-mode sockets
-               }
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return n, err
 }
@@ -157,12 +147,7 @@ func (c *conn) Close() error {
        }
        err := c.fd.Close()
        if err != nil {
-               err = &OpError{Op: "close", Net: c.fd.net, Err: err}
-               if c.fd.raddr != nil {
-                       err.(*OpError).Addr = c.fd.raddr
-               } else {
-                       err.(*OpError).Addr = c.fd.laddr // for unconnected-mode sockets
-               }
+               err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return err
 }
@@ -193,7 +178,7 @@ func (c *conn) SetDeadline(t time.Time) error {
                return syscall.EINVAL
        }
        if err := c.fd.setDeadline(t); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
        }
        return nil
 }
@@ -204,7 +189,7 @@ func (c *conn) SetReadDeadline(t time.Time) error {
                return syscall.EINVAL
        }
        if err := c.fd.setReadDeadline(t); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
        }
        return nil
 }
@@ -215,7 +200,7 @@ func (c *conn) SetWriteDeadline(t time.Time) error {
                return syscall.EINVAL
        }
        if err := c.fd.setWriteDeadline(t); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
        }
        return nil
 }
@@ -227,7 +212,7 @@ func (c *conn) SetReadBuffer(bytes int) error {
                return syscall.EINVAL
        }
        if err := setReadBuffer(c.fd, bytes); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
        }
        return nil
 }
@@ -239,7 +224,7 @@ func (c *conn) SetWriteBuffer(bytes int) error {
                return syscall.EINVAL
        }
        if err := setWriteBuffer(c.fd, bytes); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
        }
        return nil
 }
@@ -254,7 +239,7 @@ func (c *conn) SetWriteBuffer(bytes int) error {
 func (c *conn) File() (f *os.File, err error) {
        f, err = c.fd.dup()
        if err != nil {
-               err = &OpError{Op: "file", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return
 }
@@ -352,7 +337,17 @@ type OpError struct {
        // such as "tcp" or "udp6".
        Net string
 
-       // Addr is the network address on which this error occurred.
+       // For operations involving a remote network connection, like
+       // Dial, Read, or Write, Source is the corresponding local
+       // network address.
+       Source Addr
+
+       // Addr is the network address for which this error occurred.
+       // For local operations, like Listen or SetDeadline, Addr is
+       // the address of the local endpoint being manipulated.
+       // For operations involving a remote network connection, like
+       // Dial, Read, or Write, Addr is the remote address of that
+       // connection.
        Addr Addr
 
        // Err is the error that occurred during the operation.
@@ -367,8 +362,16 @@ func (e *OpError) Error() string {
        if e.Net != "" {
                s += " " + e.Net
        }
+       if e.Source != nil {
+               s += " " + e.Source.String()
+       }
        if e.Addr != nil {
-               s += " " + e.Addr.String()
+               if e.Source != nil {
+                       s += "->"
+               } else {
+                       s += " "
+               }
+               s += e.Addr.String()
        }
        s += ": " + e.Err.Error()
        return s
index f1a2eca4e8847b4321af226e7c43a493d0cdeb81..5fc830b7408976582070e4870fb5dd1a61e48621 100644 (file)
@@ -55,13 +55,13 @@ func (p *pipe) RemoteAddr() Addr {
 }
 
 func (p *pipe) SetDeadline(t time.Time) error {
-       return errors.New("net.Pipe does not support deadlines")
+       return &OpError{Op: "set", Net: "pipe", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
 }
 
 func (p *pipe) SetReadDeadline(t time.Time) error {
-       return errors.New("net.Pipe does not support deadlines")
+       return &OpError{Op: "set", Net: "pipe", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
 }
 
 func (p *pipe) SetWriteDeadline(t time.Time) error {
-       return errors.New("net.Pipe does not support deadlines")
+       return &OpError{Op: "set", Net: "pipe", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
 }
index a0b2630910548a1b3cacaacc96f8603392ec91a4..bc3f8fc4dd12fc8e5307ef2903e51702e2fb7090 100644 (file)
@@ -25,7 +25,7 @@ func newTCPConn(fd *netFD) *TCPConn {
 func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
        n, err := genericReadFrom(c, r)
        if err != nil && err != io.EOF {
-               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               err = &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return n, err
 }
@@ -38,7 +38,7 @@ func (c *TCPConn) CloseRead() error {
        }
        err := c.fd.closeRead()
        if err != nil {
-               err = &OpError{Op: "close", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               err = &OpError{Op: "close", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return err
 }
@@ -51,7 +51,7 @@ func (c *TCPConn) CloseWrite() error {
        }
        err := c.fd.closeWrite()
        if err != nil {
-               err = &OpError{Op: "close", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               err = &OpError{Op: "close", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return err
 }
@@ -69,7 +69,7 @@ func (c *TCPConn) CloseWrite() error {
 // some operating systems after sec seconds have elapsed any remaining
 // unsent data may be discarded.
 func (c *TCPConn) SetLinger(sec int) error {
-       return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return &OpError{Op: "set", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // SetKeepAlive sets whether the operating system should send
@@ -79,7 +79,7 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) error {
                return syscall.EPLAN9
        }
        if err := setKeepAlive(c.fd, keepalive); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return nil
 }
@@ -90,7 +90,7 @@ func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
                return syscall.EPLAN9
        }
        if err := setKeepAlivePeriod(c.fd, d); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return nil
 }
@@ -100,7 +100,7 @@ func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
 // algorithm).  The default is true (no delay), meaning that data is
 // sent as soon as possible after a Write.
 func (c *TCPConn) SetNoDelay(noDelay bool) error {
-       return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return &OpError{Op: "set", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // DialTCP connects to the remote address raddr on the network net,
@@ -117,10 +117,10 @@ func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
        switch net {
        case "tcp", "tcp4", "tcp6":
        default:
-               return nil, &OpError{"dial", net, raddr, UnknownNetworkError(net)}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
        }
        if raddr == nil {
-               return nil, &OpError{"dial", net, nil, errMissingAddress}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: errMissingAddress}
        }
        fd, err := dialPlan9(net, laddr, raddr)
        if err != nil {
@@ -169,11 +169,11 @@ func (l *TCPListener) Close() error {
        }
        if _, err := l.fd.ctl.WriteString("hangup"); err != nil {
                l.fd.ctl.Close()
-               return &OpError{Op: "close", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               return &OpError{Op: "close", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        err := l.fd.ctl.Close()
        if err != nil {
-               err = &OpError{Op: "close", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               err = &OpError{Op: "close", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return err
 }
@@ -190,7 +190,7 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
                return syscall.EINVAL
        }
        if err := l.fd.setDeadline(t); err != nil {
-               return &OpError{Op: "set", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return nil
 }
@@ -205,7 +205,7 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
 func (l *TCPListener) File() (f *os.File, err error) {
        f, err = l.dup()
        if err != nil {
-               err = &OpError{Op: "file", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               err = &OpError{Op: "file", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return
 }
@@ -218,7 +218,7 @@ func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
        switch net {
        case "tcp", "tcp4", "tcp6":
        default:
-               return nil, &OpError{"listen", net, laddr, UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
                laddr = &TCPAddr{}
index 62f9ee1c3fc99d48e2130e5b182a7981c47bdb1d..1f43521a9e70aaf3e931c6e723d5e4b6634225d7 100644 (file)
@@ -61,13 +61,13 @@ func newTCPConn(fd *netFD) *TCPConn {
 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, Addr: c.fd.raddr, Err: err}
+                       err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
                }
                return n, err
        }
        n, err := genericReadFrom(c, r)
        if err != nil && err != io.EOF {
-               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return n, err
 }
@@ -80,7 +80,7 @@ func (c *TCPConn) CloseRead() error {
        }
        err := c.fd.closeRead()
        if err != nil {
-               err = &OpError{Op: "close", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return err
 }
@@ -93,7 +93,7 @@ func (c *TCPConn) CloseWrite() error {
        }
        err := c.fd.closeWrite()
        if err != nil {
-               err = &OpError{Op: "close", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return err
 }
@@ -115,7 +115,7 @@ func (c *TCPConn) SetLinger(sec int) error {
                return syscall.EINVAL
        }
        if err := setLinger(c.fd, sec); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return nil
 }
@@ -127,7 +127,7 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) error {
                return syscall.EINVAL
        }
        if err := setKeepAlive(c.fd, keepalive); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return nil
 }
@@ -138,7 +138,7 @@ func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
                return syscall.EINVAL
        }
        if err := setKeepAlivePeriod(c.fd, d); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return nil
 }
@@ -152,7 +152,7 @@ func (c *TCPConn) SetNoDelay(noDelay bool) error {
                return syscall.EINVAL
        }
        if err := setNoDelay(c.fd, noDelay); err != nil {
-               return &OpError{Op: "set", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return nil
 }
@@ -164,10 +164,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, Addr: raddr, 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, Addr: raddr, Err: errMissingAddress}
        }
        return dialTCP(net, laddr, raddr, noDeadline)
 }
@@ -207,7 +207,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, Addr: raddr, Err: err}
        }
        return newTCPConn(fd), nil
 }
@@ -253,7 +253,7 @@ func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
        }
        fd, err := l.fd.accept()
        if err != nil {
-               return nil, &OpError{Op: "accept", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return newTCPConn(fd), nil
 }
@@ -276,7 +276,7 @@ func (l *TCPListener) Close() error {
        }
        err := l.fd.Close()
        if err != nil {
-               err = &OpError{Op: "close", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               err = &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return err
 }
@@ -293,7 +293,7 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
                return syscall.EINVAL
        }
        if err := l.fd.setDeadline(t); err != nil {
-               return &OpError{Op: "set", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return nil
 }
@@ -308,7 +308,7 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
 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, Addr: l.fd.laddr, Err: err}
+               err = &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return
 }
@@ -321,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, 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
 }
index 8acbb2016374efebfecd17a45619509cf250e290..949f666d740ea9b5409d7a8f7196cd53e7097ab0 100644 (file)
@@ -33,10 +33,10 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
        buf := make([]byte, udpHeaderSize+len(b))
        m, err := c.fd.data.Read(buf)
        if err != nil {
-               return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        if m < udpHeaderSize {
-               return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: errors.New("short read reading UDP header")}
+               return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: errors.New("short read reading UDP header")}
        }
        buf = buf[:m]
 
@@ -59,7 +59,7 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
 // flags that were set on the packet and the source address of the
 // packet.
 func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
-       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // WriteToUDP writes a UDP packet to addr via c, copying the payload
@@ -74,7 +74,7 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
                return 0, syscall.EINVAL
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.dir, Addr: nil, Err: errMissingAddress}
+               return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
        }
        h := new(udpHeader)
        h.raddr = addr.IP.To16()
@@ -87,7 +87,7 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
        i := copy(buf, h.Bytes())
        copy(buf[i:], b)
        if _, err := c.fd.data.Write(buf); err != nil {
-               return 0, &OpError{Op: "write", Net: c.fd.dir, Addr: addr, Err: err}
+               return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        return len(b), nil
 }
@@ -99,7 +99,7 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
        }
        a, ok := addr.(*UDPAddr)
        if !ok {
-               return 0, &OpError{Op: "write", Net: c.fd.dir, Addr: addr, Err: syscall.EINVAL}
+               return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
        }
        return c.WriteToUDP(b, a)
 }
@@ -110,7 +110,7 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
 // out-of-band data is copied from oob.  It returns the number of
 // payload and out-of-band bytes written.
 func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
-       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Addr: addr, Err: syscall.EPLAN9}
+       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
 }
 
 // DialUDP connects to the remote address raddr on the network net,
@@ -127,10 +127,10 @@ func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, e
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, UnknownNetworkError(net)
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
        }
        if raddr == nil {
-               return nil, &OpError{"dial", net, nil, errMissingAddress}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: errMissingAddress}
        }
        fd, err := dialPlan9(net, laddr, raddr)
        if err != nil {
@@ -178,7 +178,7 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, UnknownNetworkError(net)
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
                laddr = &UDPAddr{}
@@ -189,11 +189,11 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
        }
        _, err = l.ctl.WriteString("headers")
        if err != nil {
-               return nil, err
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
        }
        l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0)
        if err != nil {
-               return nil, err
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
        }
        fd, err := l.netFD()
        return newUDPConn(fd), err
@@ -204,5 +204,5 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 // interface to join.  ListenMulticastUDP uses default multicast
 // interface if ifi is nil.
 func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
-       return nil, syscall.EPLAN9
+       return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: gaddr, Err: syscall.EPLAN9}
 }
index c4bd0bc06a218cc9277cac5c12d961184b4d863a..2e43068be37054b03dcc896c21c40f83f5128058 100644 (file)
@@ -66,7 +66,7 @@ func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) {
                addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
        }
        if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return n, addr, err
 }
@@ -101,7 +101,7 @@ func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr,
                addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
        }
        if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return
 }
@@ -118,18 +118,18 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
                return 0, syscall.EINVAL
        }
        if c.fd.isConnected {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
        }
        sa, err := addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        n, err := c.fd.writeTo(b, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        return n, err
 }
@@ -141,7 +141,7 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
        }
        a, ok := addr.(*UDPAddr)
        if !ok {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EINVAL}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
        }
        return c.WriteToUDP(b, a)
 }
@@ -156,19 +156,19 @@ func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er
                return 0, 0, syscall.EINVAL
        }
        if c.fd.isConnected && addr != nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
        }
        if !c.fd.isConnected && addr == nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
        }
        var sa syscall.Sockaddr
        sa, err = addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        n, oobn, err = c.fd.writeMsg(b, oob, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        return
 }
@@ -180,10 +180,10 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, 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, Addr: raddr, Err: errMissingAddress}
        }
        return dialUDP(net, laddr, raddr, noDeadline)
 }
@@ -191,7 +191,7 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
 func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
        fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_DGRAM, 0, "dial")
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: err}
        }
        return newUDPConn(fd), nil
 }
@@ -207,14 +207,14 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
                laddr = &UDPAddr{}
        }
        fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_DGRAM, 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 newUDPConn(fd), nil
 }
@@ -227,25 +227,25 @@ func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, e
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: gaddr, Err: UnknownNetworkError(net)}
        }
        if gaddr == nil || gaddr.IP == nil {
-               return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: gaddr, Err: errMissingAddress}
        }
        fd, err := internetSocket(net, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen")
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: err}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: gaddr, Err: err}
        }
        c := newUDPConn(fd)
        if ip4 := gaddr.IP.To4(); ip4 != nil {
                if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
                        c.Close()
-                       return nil, &OpError{Op: "listen", Net: net, Addr: &IPAddr{IP: ip4}, Err: err}
+                       return nil, &OpError{Op: "listen", Net: net, Source: c.fd.laddr, Addr: &IPAddr{IP: ip4}, Err: err}
                }
        } else {
                if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
                        c.Close()
-                       return nil, &OpError{Op: "listen", Net: net, Addr: &IPAddr{IP: gaddr.IP}, Err: err}
+                       return nil, &OpError{Op: "listen", Net: net, Source: c.fd.laddr, Addr: &IPAddr{IP: gaddr.IP}, Err: err}
                }
        }
        return c, nil
index a2fb86278f55e9c4bac1d6c70ec3eb6a2ed6e000..c31907b0be2daa7bbe55a16e1c0201b5de416667 100644 (file)
@@ -24,12 +24,12 @@ type UnixConn struct {
 // Timeout() == true after a fixed time limit; see SetDeadline and
 // SetReadDeadline.
 func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
-       return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // ReadFrom implements the PacketConn ReadFrom method.
 func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
-       return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // ReadMsgUnix reads a packet from c, copying the payload into b and
@@ -37,7 +37,7 @@ func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
 // bytes copied into b, the number of bytes copied into oob, the flags
 // that were set on the packet, and the source address of the packet.
 func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
-       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+       return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // WriteToUnix writes a packet to addr via c, copying the payload from b.
@@ -47,31 +47,31 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
 // SetWriteDeadline.  On packet-oriented connections, write timeouts
 // are rare.
 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
-       return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EPLAN9}
+       return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
 }
 
 // WriteTo implements the PacketConn WriteTo method.
 func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
-       return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EPLAN9}
+       return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
 }
 
 // WriteMsgUnix writes a packet to addr via c, copying the payload
 // from b and the associated out-of-band data from oob.  It returns
 // the number of payload and out-of-band bytes written.
 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
-       return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EPLAN9}
+       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
 }
 
 // CloseRead shuts down the reading side of the Unix domain connection.
 // Most callers should just use Close.
 func (c *UnixConn) CloseRead() error {
-       return &OpError{Op: "close", Net: c.fd.net, Addr: c.fd.raddr, Err: syscall.EPLAN9}
+       return &OpError{Op: "close", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // CloseWrite shuts down the writing side of the Unix domain connection.
 // Most callers should just use Close.
 func (c *UnixConn) CloseWrite() error {
-       return &OpError{Op: "close", Net: c.fd.net, Addr: c.fd.raddr, Err: syscall.EPLAN9}
+       return &OpError{Op: "close", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // DialUnix connects to the remote address raddr on the network net,
@@ -82,36 +82,38 @@ func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
 }
 
 func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
-       return nil, syscall.EPLAN9
+       return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: syscall.EPLAN9}
 }
 
 // UnixListener is a Unix domain socket listener.  Clients should
 // typically use variables of type Listener instead of assuming Unix
 // domain sockets.
-type UnixListener struct{}
+type UnixListener struct {
+       fd *netFD
+}
 
 // ListenUnix announces on the Unix domain socket laddr and returns a
 // Unix listener.  The network net must be "unix" or "unixpacket".
 func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
-       return nil, syscall.EPLAN9
+       return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: syscall.EPLAN9}
 }
 
 // AcceptUnix accepts the next incoming call and returns the new
 // connection.
 func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
-       return nil, &OpError{Op: "accept", Net: "<nil>", Addr: nil, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "accept", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // Accept implements the Accept method in the Listener interface; it
 // waits for the next call and returns a generic Conn.
 func (l *UnixListener) Accept() (Conn, error) {
-       return nil, &OpError{Op: "accept", Net: "<nil>", Addr: nil, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "accept", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // Close stops listening on the Unix address.  Already accepted
 // connections are not closed.
 func (l *UnixListener) Close() error {
-       return &OpError{Op: "close", Net: "<nil>", Addr: nil, Err: syscall.EPLAN9}
+       return &OpError{Op: "close", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // Addr returns the listener's network address.
@@ -122,7 +124,7 @@ func (l *UnixListener) Addr() Addr { return nil }
 // SetDeadline sets the deadline associated with the listener.
 // A zero time value disables the deadline.
 func (l *UnixListener) SetDeadline(t time.Time) error {
-       return &OpError{Op: "set", Net: "<nil>", Addr: nil, Err: syscall.EPLAN9}
+       return &OpError{Op: "set", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // File returns a copy of the underlying os.File, set to blocking
@@ -133,7 +135,7 @@ func (l *UnixListener) SetDeadline(t time.Time) error {
 // connection's.  Attempting to change properties of the original
 // using this duplicate may or may not have the desired effect.
 func (l *UnixListener) File() (*os.File, error) {
-       return nil, &OpError{Op: "file", Net: "<nil>", Addr: nil, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "file", Net: l.fd.dir, Source: nil, Addr: l.fd.laddr, Err: syscall.EPLAN9}
 }
 
 // ListenUnixgram listens for incoming Unix datagram packets addressed
@@ -141,5 +143,5 @@ func (l *UnixListener) File() (*os.File, error) {
 // The returned connection's ReadFrom and WriteTo methods can be used
 // to receive and send packets with per-packet addressing.
 func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
-       return nil, syscall.EPLAN9
+       return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: syscall.EPLAN9}
 }
index ed5ffd391fb33c295e4f2b8494cd5b395c36306a..005d2486a858e583e0c4d3d332222d7db66a5827 100644 (file)
@@ -126,7 +126,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
                }
        }
        if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return n, addr, err
 }
@@ -159,7 +159,7 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
                }
        }
        if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return
 }
@@ -175,18 +175,18 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
                return 0, syscall.EINVAL
        }
        if c.fd.isConnected {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
        }
        if addr.Net != sotypeToNet(c.fd.sotype) {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EAFNOSUPPORT}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EAFNOSUPPORT}
        }
        sa := &syscall.SockaddrUnix{Name: addr.Name}
        n, err := c.fd.writeTo(b, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        return n, err
 }
@@ -198,7 +198,7 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
        }
        a, ok := addr.(*UnixAddr)
        if !ok {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EINVAL}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
        }
        return c.WriteToUnix(b, a)
 }
@@ -211,18 +211,18 @@ func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err
                return 0, 0, syscall.EINVAL
        }
        if c.fd.sotype == syscall.SOCK_DGRAM && c.fd.isConnected {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
        }
        var sa syscall.Sockaddr
        if addr != nil {
                if addr.Net != sotypeToNet(c.fd.sotype) {
-                       return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: syscall.EAFNOSUPPORT}
+                       return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EAFNOSUPPORT}
                }
                sa = &syscall.SockaddrUnix{Name: addr.Name}
        }
        n, oobn, err = c.fd.writeMsg(b, oob, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
        }
        return
 }
@@ -235,7 +235,7 @@ func (c *UnixConn) CloseRead() error {
        }
        err := c.fd.closeRead()
        if err != nil {
-               err = &OpError{Op: "close", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return err
 }
@@ -248,7 +248,7 @@ func (c *UnixConn) CloseWrite() error {
        }
        err := c.fd.closeWrite()
        if err != nil {
-               err = &OpError{Op: "close", Net: c.fd.net, Addr: c.fd.raddr, Err: err}
+               err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
        return err
 }
@@ -260,7 +260,7 @@ func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
        switch net {
        case "unix", "unixgram", "unixpacket":
        default:
-               return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
        }
        return dialUnix(net, laddr, raddr, noDeadline)
 }
@@ -268,7 +268,7 @@ func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
 func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
        fd, err := unixSocket(net, laddr, raddr, "dial", deadline)
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: err}
        }
        return newUnixConn(fd), nil
 }
@@ -287,16 +287,16 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
        switch net {
        case "unix", "unixpacket":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
-               return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: errMissingAddress}
        }
        fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
        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 &UnixListener{fd, fd.laddr.String()}, nil
+       return &UnixListener{fd: fd, path: fd.laddr.String()}, nil
 }
 
 // AcceptUnix accepts the next incoming call and returns the new
@@ -307,7 +307,7 @@ func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
        }
        fd, err := l.fd.accept()
        if err != nil {
-               return nil, &OpError{Op: "accept", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return newUnixConn(fd), nil
 }
@@ -344,7 +344,7 @@ func (l *UnixListener) Close() error {
        }
        err := l.fd.Close()
        if err != nil {
-               err = &OpError{Op: "close", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               err = &OpError{Op: "close", Net: l.fd.net, Source: l.fd.laddr, Addr: l.fd.raddr, Err: err}
        }
        return err
 }
@@ -361,7 +361,7 @@ func (l *UnixListener) SetDeadline(t time.Time) error {
                return syscall.EINVAL
        }
        if err := l.fd.setDeadline(t); err != nil {
-               return &OpError{Op: "set", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return nil
 }
@@ -376,7 +376,7 @@ func (l *UnixListener) SetDeadline(t time.Time) error {
 func (l *UnixListener) File() (f *os.File, err error) {
        f, err = l.fd.dup()
        if err != nil {
-               err = &OpError{Op: "file", Net: l.fd.net, Addr: l.fd.laddr, Err: err}
+               err = &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
        }
        return
 }
@@ -389,14 +389,14 @@ func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
        switch net {
        case "unixgram":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
-               return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: errMissingAddress}
        }
        fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
        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 newUnixConn(fd), nil
 }