123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- // Copyright 2017 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package ipv4
- import (
- "net"
- "runtime"
- "golang.org/x/net/internal/socket"
- )
- // BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
- // PacketConn are not implemented.
- // BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of
- // RawConn are not implemented.
- // A Message represents an IO message.
- //
- // type Message struct {
- // Buffers [][]byte
- // OOB []byte
- // Addr net.Addr
- // N int
- // NN int
- // Flags int
- // }
- //
- // The Buffers fields represents a list of contiguous buffers, which
- // can be used for vectored IO, for example, putting a header and a
- // payload in each slice.
- // When writing, the Buffers field must contain at least one byte to
- // write.
- // When reading, the Buffers field will always contain a byte to read.
- //
- // The OOB field contains protocol-specific control or miscellaneous
- // ancillary data known as out-of-band data.
- // It can be nil when not required.
- //
- // The Addr field specifies a destination address when writing.
- // It can be nil when the underlying protocol of the endpoint uses
- // connection-oriented communication.
- // After a successful read, it may contain the source address on the
- // received packet.
- //
- // The N field indicates the number of bytes read or written from/to
- // Buffers.
- //
- // The NN field indicates the number of bytes read or written from/to
- // OOB.
- //
- // The Flags field contains protocol-specific information on the
- // received message.
- type Message = socket.Message
- // ReadBatch reads a batch of messages.
- //
- // The provided flags is a set of platform-dependent flags, such as
- // syscall.MSG_PEEK.
- //
- // On a successful read it returns the number of messages received, up
- // to len(ms).
- //
- // On Linux, a batch read will be optimized.
- // On other platforms, this method will read only a single message.
- //
- // Unlike the ReadFrom method, it doesn't strip the IPv4 header
- // followed by option headers from the received IPv4 datagram when the
- // underlying transport is net.IPConn. Each Buffers field of Message
- // must be large enough to accommodate an IPv4 header and option
- // headers.
- func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) {
- if !c.ok() {
- return 0, errInvalidConn
- }
- switch runtime.GOOS {
- case "linux":
- n, err := c.RecvMsgs([]socket.Message(ms), flags)
- if err != nil {
- err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
- }
- return n, err
- default:
- n := 1
- err := c.RecvMsg(&ms[0], flags)
- if err != nil {
- n = 0
- err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
- }
- if compatFreeBSD32 && ms[0].NN > 0 {
- adjustFreeBSD32(&ms[0])
- }
- return n, err
- }
- }
- // WriteBatch writes a batch of messages.
- //
- // The provided flags is a set of platform-dependent flags, such as
- // syscall.MSG_DONTROUTE.
- //
- // It returns the number of messages written on a successful write.
- //
- // On Linux, a batch write will be optimized.
- // On other platforms, this method will write only a single message.
- func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) {
- if !c.ok() {
- return 0, errInvalidConn
- }
- switch runtime.GOOS {
- case "linux":
- n, err := c.SendMsgs([]socket.Message(ms), flags)
- if err != nil {
- err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
- }
- return n, err
- default:
- n := 1
- err := c.SendMsg(&ms[0], flags)
- if err != nil {
- n = 0
- err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
- }
- return n, err
- }
- }
- // ReadBatch reads a batch of messages.
- //
- // The provided flags is a set of platform-dependent flags, such as
- // syscall.MSG_PEEK.
- //
- // On a successful read it returns the number of messages received, up
- // to len(ms).
- //
- // On Linux, a batch read will be optimized.
- // On other platforms, this method will read only a single message.
- func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) {
- if !c.ok() {
- return 0, errInvalidConn
- }
- switch runtime.GOOS {
- case "linux":
- n, err := c.RecvMsgs([]socket.Message(ms), flags)
- if err != nil {
- err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
- }
- return n, err
- default:
- n := 1
- err := c.RecvMsg(&ms[0], flags)
- if err != nil {
- n = 0
- err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
- }
- if compatFreeBSD32 && ms[0].NN > 0 {
- adjustFreeBSD32(&ms[0])
- }
- return n, err
- }
- }
- // WriteBatch writes a batch of messages.
- //
- // The provided flags is a set of platform-dependent flags, such as
- // syscall.MSG_DONTROUTE.
- //
- // It returns the number of messages written on a successful write.
- //
- // On Linux, a batch write will be optimized.
- // On other platforms, this method will write only a single message.
- func (c *packetHandler) WriteBatch(ms []Message, flags int) (int, error) {
- if !c.ok() {
- return 0, errInvalidConn
- }
- switch runtime.GOOS {
- case "linux":
- n, err := c.SendMsgs([]socket.Message(ms), flags)
- if err != nil {
- err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
- }
- return n, err
- default:
- n := 1
- err := c.SendMsg(&ms[0], flags)
- if err != nil {
- n = 0
- err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
- }
- return n, err
- }
- }
|