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 5package ipv4 6 7import ( 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. 56type 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. 74func (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. 108func (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. 140func (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. 174func (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} 195