batch.go 5.7 KB

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