You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
5.5 KiB

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