batch.go (5729B)
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 }