]> Cypherpunks repositories - gostls13.git/commitdiff
net: add read, write message methods to IPConn, UDPConn
authorMikio Hara <mikioh.mikioh@gmail.com>
Mon, 24 Sep 2012 21:57:32 +0000 (06:57 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Mon, 24 Sep 2012 21:57:32 +0000 (06:57 +0900)
Both methods allow to access the IP ancillary data through
socket control messages.

This CL is required for CL 6482044; go.net/ipv4: new package.

R=rsc, r, dave
CC=golang-dev
https://golang.org/cl/6426047

src/pkg/net/iprawsock_posix.go
src/pkg/net/udpsock_posix.go

index c3e119cd35d828be118b1ecc7d91274b19648476..d0f0b567ac8e409bd7103434047d863e183e942a 100644 (file)
@@ -98,6 +98,25 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
        return n, uaddr.toAddr(), err
 }
 
+// ReadMsgIP reads a packet from c, copying the payload into b and the
+// associdated 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
+       }
+       var sa syscall.Sockaddr
+       n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
+       switch sa := sa.(type) {
+       case *syscall.SockaddrInet4:
+               addr = &IPAddr{sa.Addr[0:]}
+       case *syscall.SockaddrInet6:
+               addr = &IPAddr{sa.Addr[0:]}
+       }
+       return
+}
+
 // WriteToIP writes an IP packet to addr via c, copying the payload from b.
 //
 // WriteToIP can be made to time out and return
@@ -127,6 +146,20 @@ func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
        return c.WriteToIP(b, a)
 }
 
+// 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
+       }
+       sa, err := addr.sockaddr(c.fd.family)
+       if err != nil {
+               return 0, 0, &OpError{"write", c.fd.net, addr, err}
+       }
+       return c.fd.WriteMsg(b, oob, sa)
+}
+
 // 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) {
index 5f46d25a7d4b938d44aa098f4d93be92d474c93b..e075380c8e3e0b385069e1fa00a34a061ff25746 100644 (file)
@@ -87,6 +87,26 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
        return n, uaddr.toAddr(), err
 }
 
+// ReadMsgUDP reads a packet from c, copying the payload into b and
+// the associdated 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 *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
+       if !c.ok() {
+               return 0, 0, 0, nil, syscall.EINVAL
+       }
+       var sa syscall.Sockaddr
+       n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
+       switch sa := sa.(type) {
+       case *syscall.SockaddrInet4:
+               addr = &UDPAddr{sa.Addr[0:], sa.Port}
+       case *syscall.SockaddrInet6:
+               addr = &UDPAddr{sa.Addr[0:], sa.Port}
+       }
+       return
+}
+
 // WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
 //
 // WriteToUDP can be made to time out and return
@@ -119,6 +139,23 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
        return c.WriteToUDP(b, a)
 }
 
+// WriteMsgUDP 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 *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
+       if !c.ok() {
+               return 0, 0, syscall.EINVAL
+       }
+       if c.fd.isConnected {
+               return 0, 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
+       }
+       sa, err := addr.sockaddr(c.fd.family)
+       if err != nil {
+               return 0, 0, &OpError{"write", c.fd.net, addr, err}
+       }
+       return c.fd.WriteMsg(b, oob, sa)
+}
+
 // DialUDP connects to the remote address raddr on the network net,
 // which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is used
 // as the local address for the connection.