batch.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 && ms[0].NN > 0 {
  86. adjustFreeBSD32(&ms[0])
  87. }
  88. return n, err
  89. }
  90. }
  91. // WriteBatch writes a batch of messages.
  92. //
  93. // The provided flags is a set of platform-dependent flags, such as
  94. // syscall.MSG_DONTROUTE.
  95. //
  96. // It returns the number of messages written on a successful write.
  97. //
  98. // On Linux, a batch write will be optimized.
  99. // On other platforms, this method will write only a single message.
  100. func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) {
  101. if !c.ok() {
  102. return 0, errInvalidConn
  103. }
  104. switch runtime.GOOS {
  105. case "linux":
  106. n, err := c.SendMsgs([]socket.Message(ms), flags)
  107. if err != nil {
  108. err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
  109. }
  110. return n, err
  111. default:
  112. n := 1
  113. err := c.SendMsg(&ms[0], flags)
  114. if err != nil {
  115. n = 0
  116. err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err}
  117. }
  118. return n, err
  119. }
  120. }
  121. // ReadBatch reads a batch of messages.
  122. //
  123. // The provided flags is a set of platform-dependent flags, such as
  124. // syscall.MSG_PEEK.
  125. //
  126. // On a successful read it returns the number of messages received, up
  127. // to len(ms).
  128. //
  129. // On Linux, a batch read will be optimized.
  130. // On other platforms, this method will read only a single message.
  131. func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) {
  132. if !c.ok() {
  133. return 0, errInvalidConn
  134. }
  135. switch runtime.GOOS {
  136. case "linux":
  137. n, err := c.RecvMsgs([]socket.Message(ms), flags)
  138. if err != nil {
  139. err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
  140. }
  141. return n, err
  142. default:
  143. n := 1
  144. err := c.RecvMsg(&ms[0], flags)
  145. if err != nil {
  146. n = 0
  147. err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
  148. }
  149. if compatFreeBSD32 && ms[0].NN > 0 {
  150. adjustFreeBSD32(&ms[0])
  151. }
  152. return n, err
  153. }
  154. }
  155. // WriteBatch writes a batch of messages.
  156. //
  157. // The provided flags is a set of platform-dependent flags, such as
  158. // syscall.MSG_DONTROUTE.
  159. //
  160. // It returns the number of messages written on a successful write.
  161. //
  162. // On Linux, a batch write will be optimized.
  163. // On other platforms, this method will write only a single message.
  164. func (c *packetHandler) WriteBatch(ms []Message, flags int) (int, error) {
  165. if !c.ok() {
  166. return 0, errInvalidConn
  167. }
  168. switch runtime.GOOS {
  169. case "linux":
  170. n, err := c.SendMsgs([]socket.Message(ms), flags)
  171. if err != nil {
  172. err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
  173. }
  174. return n, err
  175. default:
  176. n := 1
  177. err := c.SendMsg(&ms[0], flags)
  178. if err != nil {
  179. n = 0
  180. err = &net.OpError{Op: "write", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err}
  181. }
  182. return n, err
  183. }
  184. }