]> Cypherpunks repositories - gostls13.git/commitdiff
net: deduplicate raw IP socket code
authorMikio Hara <mikioh.mikioh@gmail.com>
Wed, 2 Mar 2016 21:22:11 +0000 (06:22 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Wed, 16 Mar 2016 03:08:13 +0000 (03:08 +0000)
This change consolidates functions and methods related to IPAddr and
IPConn for maintenance purpose, especially for documentation.

The followup changes will update comments and examples.

Updates #10624.

Change-Id: Ia5146f234225704a3c0b6459e1903e56a7b68134
Reviewed-on: https://go-review.googlesource.com/20124
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/net/iprawsock.go
src/net/iprawsock_plan9.go
src/net/iprawsock_posix.go

index 19813d171f515eccb8d873d112e5fd5e84835537..41cfb2311add3adcc1a059351719693ed0277cf2 100644 (file)
@@ -4,6 +4,8 @@
 
 package net
 
+import "syscall"
+
 // IPAddr represents the address of an IP end point.
 type IPAddr struct {
        IP   IP
@@ -60,3 +62,130 @@ func ResolveIPAddr(net, addr string) (*IPAddr, error) {
        }
        return addrs.first(isIPv4).(*IPAddr), nil
 }
+
+// IPConn is the implementation of the Conn and PacketConn interfaces
+// for IP network connections.
+type IPConn struct {
+       conn
+}
+
+// ReadFromIP reads an IP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
+       if !c.ok() {
+               return 0, nil, syscall.EINVAL
+       }
+       n, addr, err := c.readFrom(b)
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
+       }
+       return n, addr, err
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
+       if !c.ok() {
+               return 0, nil, syscall.EINVAL
+       }
+       n, addr, err := c.readFrom(b)
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
+       }
+       if addr == nil {
+               return n, nil, err
+       }
+       return n, addr, err
+}
+
+// ReadMsgIP reads a packet from c, copying the payload into b and the
+// associated out-of-band data into oob. It returns the number of
+// 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) {
+       if !c.ok() {
+               return 0, 0, 0, nil, syscall.EINVAL
+       }
+       n, oobn, flags, addr, err = c.readMsg(b, oob)
+       if err != nil {
+               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
+       }
+       return
+}
+
+// WriteToIP writes an IP packet to addr via c, copying the payload
+// from b.
+//
+// WriteToIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline. On packet-oriented connections, write timeouts
+// are rare.
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
+       if !c.ok() {
+               return 0, syscall.EINVAL
+       }
+       n, err := c.writeTo(b, addr)
+       if err != nil {
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
+       }
+       return n, err
+}
+
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
+       if !c.ok() {
+               return 0, syscall.EINVAL
+       }
+       a, ok := addr.(*IPAddr)
+       if !ok {
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
+       }
+       n, err := c.writeTo(b, a)
+       if err != nil {
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
+       }
+       return n, err
+}
+
+// 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) {
+       if !c.ok() {
+               return 0, 0, syscall.EINVAL
+       }
+       n, oobn, err = c.writeMsg(b, oob, addr)
+       if err != nil {
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
+       }
+       return
+}
+
+func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
+
+// DialIP connects to the remote address raddr on the network protocol
+// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
+// and a protocol number or name.
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
+       c, err := dialIP(netProto, laddr, raddr, noDeadline)
+       if err != nil {
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
+       }
+       return c, nil
+}
+
+// ListenIP listens for incoming IP packets addressed to the local
+// address laddr. The returned connection's ReadFrom and WriteTo
+// methods can be used to receive and send IP packets with per-packet
+// addressing.
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
+       c, err := listenIP(netProto, laddr)
+       if err != nil {
+               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
+       }
+       return c, nil
+}
index 6fb3893529ce4315273ef78954d8b44837f6d89e..e08f271e9b4c905f3f766889dfc2e88d4f39d053 100644 (file)
@@ -9,74 +9,26 @@ import (
        "time"
 )
 
-// IPConn is the implementation of the Conn and PacketConn interfaces
-// for IP network connections.
-type IPConn struct {
-       conn
+func (c *IPConn) readFrom(b []byte) (int, *IPAddr, error) {
+       return 0, nil, syscall.EPLAN9
 }
 
-// ReadFromIP reads an IP packet from c, copying the payload into b.
-// It returns the number of bytes copied into b and the return address
-// that was on the packet.
-//
-// ReadFromIP can be made to time out and return an error with
-// 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.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
+func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
+       return 0, 0, 0, nil, 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.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
+func (c *IPConn) writeTo(b []byte, addr *IPAddr) (int, error) {
+       return 0, syscall.EPLAN9
 }
 
-// ReadMsgIP reads a packet from c, copying the payload into b and the
-// associated out-of-band data into oob. It returns the number of
-// 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.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
-}
-
-// WriteToIP writes an IP packet to addr via c, copying the payload
-// from b.
-//
-// WriteToIP can be made to time out and return an error with
-// Timeout() == true after a fixed time limit; see SetDeadline and
-// 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.dir, Source: c.fd.laddr, Addr: addr.opAddr(), 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.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.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
-}
-
-// DialIP connects to the remote address raddr on the network protocol
-// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
-// and a protocol number or name.
-func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
-       return dialIP(netProto, laddr, raddr, noDeadline)
+func (c *IPConn) writeMsg(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
+       return 0, 0, syscall.EPLAN9
 }
 
 func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
-       return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: syscall.EPLAN9}
+       return nil, syscall.EPLAN9
 }
 
-// ListenIP listens for incoming IP packets addressed to the local
-// address laddr. The returned connection's ReadFrom and WriteTo
-// methods can be used to receive and send IP packets with per-packet
-// addressing.
-func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
-       return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: syscall.EPLAN9}
+func listenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
+       return nil, syscall.EPLAN9
 }
index cbfb1b22cee463522814d515600291aa21da658b..b959afe6b4af11dd23f8772f94e5a6134e0c1fce 100644 (file)
@@ -50,25 +50,7 @@ func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
        return ipToSockaddr(family, a.IP, 0, a.Zone)
 }
 
-// IPConn is the implementation of the Conn and PacketConn interfaces
-// for IP network connections.
-type IPConn struct {
-       conn
-}
-
-func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
-
-// ReadFromIP reads an IP packet from c, copying the payload into b.
-// It returns the number of bytes copied into b and the return address
-// that was on the packet.
-//
-// ReadFromIP can be made to time out and return an error with
-// Timeout() == true after a fixed time limit; see SetDeadline and
-// SetReadDeadline.
-func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
-       if !c.ok() {
-               return 0, nil, syscall.EINVAL
-       }
+func (c *IPConn) readFrom(b []byte) (int, *IPAddr, error) {
        // TODO(cw,rsc): consider using readv if we know the family
        // type to avoid the header trim/copy
        var addr *IPAddr
@@ -80,9 +62,6 @@ func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
        case *syscall.SockaddrInet6:
                addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
        }
-       if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
-       }
        return n, addr, err
 }
 
@@ -101,26 +80,7 @@ func stripIPv4Header(n int, b []byte) int {
        return n - l
 }
 
-// ReadFrom implements the PacketConn ReadFrom method.
-func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
-       if !c.ok() {
-               return 0, nil, syscall.EINVAL
-       }
-       n, addr, err := c.ReadFromIP(b)
-       if addr == nil {
-               return n, nil, err
-       }
-       return n, addr, err
-}
-
-// ReadMsgIP reads a packet from c, copying the payload into b and the
-// associated out-of-band data into oob. It returns the number of
-// 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) {
-       if !c.ok() {
-               return 0, 0, 0, nil, syscall.EINVAL
-       }
+func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
        var sa syscall.Sockaddr
        n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
        switch sa := sa.(type) {
@@ -129,94 +89,43 @@ func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err
        case *syscall.SockaddrInet6:
                addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
        }
-       if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
-       }
        return
 }
 
-// WriteToIP writes an IP packet to addr via c, copying the payload
-// from b.
-//
-// WriteToIP can be made to time out and return an error with
-// Timeout() == true after a fixed time limit; see SetDeadline and
-// SetWriteDeadline. On packet-oriented connections, write timeouts
-// are rare.
-func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
-       if !c.ok() {
-               return 0, syscall.EINVAL
-       }
+func (c *IPConn) writeTo(b []byte, addr *IPAddr) (int, error) {
        if c.fd.isConnected {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: ErrWriteToConnected}
+               return 0, ErrWriteToConnected
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: nil, Err: errMissingAddress}
+               return 0, errMissingAddress
        }
        sa, err := addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
+               return 0, err
        }
-       n, err := c.fd.writeTo(b, sa)
-       if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
-       }
-       return n, err
-}
-
-// WriteTo implements the PacketConn WriteTo method.
-func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
-       if !c.ok() {
-               return 0, syscall.EINVAL
-       }
-       a, ok := addr.(*IPAddr)
-       if !ok {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
-       }
-       return c.WriteToIP(b, a)
+       return c.fd.writeTo(b, sa)
 }
 
-// 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) {
-       if !c.ok() {
-               return 0, 0, syscall.EINVAL
-       }
+func (c *IPConn) writeMsg(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
        if c.fd.isConnected {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: ErrWriteToConnected}
+               return 0, 0, ErrWriteToConnected
        }
        if addr == nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: nil, 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, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
+               return 0, 0, errMissingAddress
        }
-       n, oobn, err = c.fd.writeMsg(b, oob, sa)
-       if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
-       }
-       return
-}
-
-// DialIP connects to the remote address raddr on the network protocol
-// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
-// and a protocol number or name.
-func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
-       c, err := dialIP(netProto, laddr, raddr, noDeadline)
+       sa, err := addr.sockaddr(c.fd.family)
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
+               return 0, 0, err
        }
-       return c, nil
+       return c.fd.writeMsg(b, oob, sa)
 }
 
 func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
-       net, proto, err := parseNetwork(netProto)
+       network, proto, err := parseNetwork(netProto)
        if err != nil {
                return nil, err
        }
-       switch net {
+       switch network {
        case "ip", "ip4", "ip6":
        default:
                return nil, UnknownNetworkError(netProto)
@@ -224,30 +133,26 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
        if raddr == nil {
                return nil, errMissingAddress
        }
-       fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial", noCancel)
+       fd, err := internetSocket(network, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial", noCancel)
        if err != nil {
                return nil, err
        }
        return newIPConn(fd), nil
 }
 
-// ListenIP listens for incoming IP packets addressed to the local
-// address laddr. The returned connection's ReadFrom and WriteTo
-// methods can be used to receive and send IP packets with per-packet
-// addressing.
-func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
-       net, proto, err := parseNetwork(netProto)
+func listenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
+       network, proto, err := parseNetwork(netProto)
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
+               return nil, err
        }
-       switch net {
+       switch network {
        case "ip", "ip4", "ip6":
        default:
-               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(netProto)}
+               return nil, UnknownNetworkError(netProto)
        }
-       fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", noCancel)
+       fd, err := internetSocket(network, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", noCancel)
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
+               return nil, err
        }
        return newIPConn(fd), nil
 }