payload.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // Copyright 2012 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. "syscall"
  8. )
  9. // A payloadHandler represents the IPv4 datagram payload handler.
  10. type payloadHandler struct {
  11. c net.PacketConn
  12. rawOpt
  13. }
  14. func (c *payloadHandler) ok() bool { return c != nil && c.c != nil }
  15. // ReadFrom reads a payload of the received IPv4 datagram, from the
  16. // endpoint c, copying the payload into b. It returns the number of
  17. // bytes copied into b, the control message cm and the source address
  18. // src of the received datagram.
  19. func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
  20. if !c.ok() {
  21. return 0, nil, nil, syscall.EINVAL
  22. }
  23. oob := newControlMessage(&c.rawOpt)
  24. var oobn int
  25. switch rd := c.c.(type) {
  26. case *net.UDPConn:
  27. if n, oobn, _, src, err = rd.ReadMsgUDP(b, oob); err != nil {
  28. return 0, nil, nil, err
  29. }
  30. case *net.IPConn:
  31. nb := make([]byte, len(b)+maxHeaderLen)
  32. if n, oobn, _, src, err = rd.ReadMsgIP(nb, oob); err != nil {
  33. return 0, nil, nil, err
  34. }
  35. hdrlen := (int(b[0]) & 0x0f) << 2
  36. copy(b, nb[hdrlen:])
  37. n -= hdrlen
  38. default:
  39. return 0, nil, nil, errInvalidConnType
  40. }
  41. if cm, err = parseControlMessage(oob[:oobn]); err != nil {
  42. return 0, nil, nil, err
  43. }
  44. if cm != nil {
  45. cm.Src = netAddrToIP4(src)
  46. }
  47. return
  48. }
  49. // WriteTo writes a payload of the IPv4 datagram, to the destination
  50. // address dst through the endpoint c, copying the payload from b. It
  51. // returns the number of bytes written. The control message cm allows
  52. // the datagram path and the outgoing interface to be specified.
  53. // Currently only Linux supports this. The cm may be nil if control
  54. // of the outgoing datagram is not required.
  55. func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
  56. if !c.ok() {
  57. return 0, syscall.EINVAL
  58. }
  59. oob := marshalControlMessage(cm)
  60. if dst == nil {
  61. return 0, errMissingAddress
  62. }
  63. switch wr := c.c.(type) {
  64. case *net.UDPConn:
  65. n, _, err = wr.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
  66. case *net.IPConn:
  67. n, _, err = wr.WriteMsgIP(b, oob, dst.(*net.IPAddr))
  68. default:
  69. return 0, errInvalidConnType
  70. }
  71. if err != nil {
  72. return 0, err
  73. }
  74. return
  75. }