golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/ipv4/batch.go (about)

     1  // Copyright 2017 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  package ipv4
     6  
     7  import (
     8  	"net"
     9  	"runtime"
    10  
    11  	"golang.org/x/net/internal/socket"
    12  )
    13  
    14  // BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
    15  // PacketConn are not implemented.
    16  
    17  // BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
    18  // RawConn are not implemented.
    19  
    20  // A Message represents an IO message.
    21  //
    22  //	type Message struct {
    23  //		Buffers [][]byte
    24  //		OOB     []byte
    25  //		Addr    net.Addr
    26  //		N       int
    27  //		NN      int
    28  //		Flags   int
    29  //	}
    30  //
    31  // The Buffers fields represents a list of contiguous buffers, which
    32  // can be used for vectored IO, for example, putting a header and a
    33  // payload in each slice.
    34  // When writing, the Buffers field must contain at least one byte to
    35  // write.
    36  // When reading, the Buffers field will always contain a byte to read.
    37  //
    38  // The OOB field contains protocol-specific control or miscellaneous
    39  // ancillary data known as out-of-band data.
    40  // It can be nil when not required.
    41  //
    42  // The Addr field specifies a destination address when writing.
    43  // It can be nil when the underlying protocol of the endpoint uses
    44  // connection-oriented communication.
    45  // After a successful read, it may contain the source address on the
    46  // received packet.
    47  //
    48  // The N field indicates the number of bytes read or written from/to
    49  // Buffers.
    50  //
    51  // The NN field indicates the number of bytes read or written from/to
    52  // OOB.
    53  //
    54  // The Flags field contains protocol-specific information on the
    55  // received message.
    56  type Message = socket.Message
    57  
    58  // ReadBatch reads a batch of messages.
    59  //
    60  // The provided flags is a set of platform-dependent flags, such as
    61  // syscall.MSG_PEEK.
    62  //
    63  // On a successful read it returns the number of messages received, up
    64  // to len(ms).
    65  //
    66  // On Linux, a batch read will be optimized.
    67  // On other platforms, this method will read only a single message.
    68  //
    69  // Unlike the ReadFrom method, it doesn't strip the IPv4 header
    70  // followed by option headers from the received IPv4 datagram when the
    71  // underlying transport is net.IPConn. Each Buffers field of Message
    72  // must be large enough to accommodate an IPv4 header and option
    73  // headers.
    74  func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) {
    75  	if !c.ok() {
    76  		return 0, errInvalidConn
    77  	}
    78  	switch runtime.GOOS {
    79  	case "linux":
    80  		n, err := c.RecvMsgs([]socket.Message(ms), flags)
    81  		if err != nil {
    82  			err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
    83  		}
    84  		return n, err
    85  	default:
    86  		n := 1
    87  		err := c.RecvMsg(&ms[0], flags)
    88  		if err != nil {
    89  			n = 0
    90  			err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
    91  		}
    92  		if compatFreeBSD32 && ms[0].NN > 0 {
    93  			adjustFreeBSD32(&ms[0])
    94  		}
    95  		return n, err
    96  	}
    97  }
    98  
    99  // WriteBatch writes a batch of messages.
   100  //
   101  // The provided flags is a set of platform-dependent flags, such as
   102  // syscall.MSG_DONTROUTE.
   103  //
   104  // It returns the number of messages written on a successful write.
   105  //
   106  // On Linux, a batch write will be optimized.
   107  // On other platforms, this method will write only a single message.
   108  func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) {
   109  	if !c.ok() {
   110  		return 0, errInvalidConn
   111  	}
   112  	switch runtime.GOOS {
   113  	case "linux":
   114  		n, err := c.SendMsgs([]socket.Message(ms), flags)
   115  		if err != nil {
   116  			err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
   117  		}
   118  		return n, err
   119  	default:
   120  		n := 1
   121  		err := c.SendMsg(&ms[0], flags)
   122  		if err != nil {
   123  			n = 0
   124  			err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
   125  		}
   126  		return n, err
   127  	}
   128  }
   129  
   130  // ReadBatch reads a batch of messages.
   131  //
   132  // The provided flags is a set of platform-dependent flags, such as
   133  // syscall.MSG_PEEK.
   134  //
   135  // On a successful read it returns the number of messages received, up
   136  // to len(ms).
   137  //
   138  // On Linux, a batch read will be optimized.
   139  // On other platforms, this method will read only a single message.
   140  func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) {
   141  	if !c.ok() {
   142  		return 0, errInvalidConn
   143  	}
   144  	switch runtime.GOOS {
   145  	case "linux":
   146  		n, err := c.RecvMsgs([]socket.Message(ms), flags)
   147  		if err != nil {
   148  			err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
   149  		}
   150  		return n, err
   151  	default:
   152  		n := 1
   153  		err := c.RecvMsg(&ms[0], flags)
   154  		if err != nil {
   155  			n = 0
   156  			err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
   157  		}
   158  		if compatFreeBSD32 && ms[0].NN > 0 {
   159  			adjustFreeBSD32(&ms[0])
   160  		}
   161  		return n, err
   162  	}
   163  }
   164  
   165  // WriteBatch writes a batch of messages.
   166  //
   167  // The provided flags is a set of platform-dependent flags, such as
   168  // syscall.MSG_DONTROUTE.
   169  //
   170  // It returns the number of messages written on a successful write.
   171  //
   172  // On Linux, a batch write will be optimized.
   173  // On other platforms, this method will write only a single message.
   174  func (c *packetHandler) WriteBatch(ms []Message, flags int) (int, error) {
   175  	if !c.ok() {
   176  		return 0, errInvalidConn
   177  	}
   178  	switch runtime.GOOS {
   179  	case "linux":
   180  		n, err := c.SendMsgs([]socket.Message(ms), flags)
   181  		if err != nil {
   182  			err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
   183  		}
   184  		return n, err
   185  	default:
   186  		n := 1
   187  		err := c.SendMsg(&ms[0], flags)
   188  		if err != nil {
   189  			n = 0
   190  			err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
   191  		}
   192  		return n, err
   193  	}
   194  }