github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/ipv4/payload_cmsg.go (about)

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
     6  // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
     7  
     8  package ipv4
     9  
    10  import (
    11  	"net"
    12  
    13  	"github.com/hxx258456/ccgo/net/internal/socket"
    14  )
    15  
    16  // ReadFrom reads a payload of the received IPv4 datagram, from the
    17  // endpoint c, copying the payload into b. It returns the number of
    18  // bytes copied into b, the control message cm and the source address
    19  // src of the received datagram.
    20  func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
    21  	if !c.ok() {
    22  		return 0, nil, nil, errInvalidConn
    23  	}
    24  	c.rawOpt.RLock()
    25  	m := socket.Message{
    26  		OOB: NewControlMessage(c.rawOpt.cflags),
    27  	}
    28  	c.rawOpt.RUnlock()
    29  	switch c.PacketConn.(type) {
    30  	case *net.UDPConn:
    31  		m.Buffers = [][]byte{b}
    32  		if err := c.RecvMsg(&m, 0); err != nil {
    33  			return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
    34  		}
    35  	case *net.IPConn:
    36  		h := make([]byte, HeaderLen)
    37  		m.Buffers = [][]byte{h, b}
    38  		if err := c.RecvMsg(&m, 0); err != nil {
    39  			return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
    40  		}
    41  		hdrlen := int(h[0]&0x0f) << 2
    42  		if hdrlen > len(h) {
    43  			d := hdrlen - len(h)
    44  			copy(b, b[d:])
    45  			m.N -= d
    46  		} else {
    47  			m.N -= hdrlen
    48  		}
    49  	default:
    50  		return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: errInvalidConnType}
    51  	}
    52  	if m.NN > 0 {
    53  		if compatFreeBSD32 {
    54  			adjustFreeBSD32(&m)
    55  		}
    56  		cm = new(ControlMessage)
    57  		if err := cm.Parse(m.OOB[:m.NN]); err != nil {
    58  			return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
    59  		}
    60  		cm.Src = netAddrToIP4(m.Addr)
    61  	}
    62  	return m.N, cm, m.Addr, nil
    63  }
    64  
    65  // WriteTo writes a payload of the IPv4 datagram, to the destination
    66  // address dst through the endpoint c, copying the payload from b. It
    67  // returns the number of bytes written. The control message cm allows
    68  // the datagram path and the outgoing interface to be specified.
    69  // Currently only Darwin and Linux support this. The cm may be nil if
    70  // control of the outgoing datagram is not required.
    71  func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
    72  	if !c.ok() {
    73  		return 0, errInvalidConn
    74  	}
    75  	m := socket.Message{
    76  		Buffers: [][]byte{b},
    77  		OOB:     cm.Marshal(),
    78  		Addr:    dst,
    79  	}
    80  	err = c.SendMsg(&m, 0)
    81  	if err != nil {
    82  		err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Addr: opAddr(dst), Err: err}
    83  	}
    84  	return m.N, err
    85  }