encoding.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package discover
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. )
  7. type Packet struct {
  8. Magic uint32 // AnnouncementMagic or QueryMagic
  9. Port uint16 // unset if magic == QueryMagic
  10. ID string
  11. IP []byte // zero length in local announcements
  12. }
  13. var (
  14. errBadMagic = errors.New("bad magic")
  15. errFormat = errors.New("incorrect packet format")
  16. )
  17. func EncodePacket(pkt Packet) []byte {
  18. if l := len(pkt.IP); l != 0 && l != 4 && l != 16 {
  19. // bad ip format
  20. return nil
  21. }
  22. var idbs = []byte(pkt.ID)
  23. var l = 4 + 4 + len(idbs) + pad(len(idbs))
  24. if pkt.Magic == AnnouncementMagic {
  25. l += 4 + 4 + len(pkt.IP)
  26. }
  27. var buf = make([]byte, l)
  28. var offset = 0
  29. binary.BigEndian.PutUint32(buf[offset:], pkt.Magic)
  30. offset += 4
  31. if pkt.Magic == AnnouncementMagic {
  32. binary.BigEndian.PutUint16(buf[offset:], uint16(pkt.Port))
  33. offset += 4
  34. }
  35. binary.BigEndian.PutUint32(buf[offset:], uint32(len(idbs)))
  36. offset += 4
  37. copy(buf[offset:], idbs)
  38. offset += len(idbs) + pad(len(idbs))
  39. if pkt.Magic == AnnouncementMagic {
  40. binary.BigEndian.PutUint32(buf[offset:], uint32(len(pkt.IP)))
  41. offset += 4
  42. copy(buf[offset:], pkt.IP)
  43. offset += len(pkt.IP)
  44. }
  45. return buf
  46. }
  47. func DecodePacket(buf []byte) (*Packet, error) {
  48. var p Packet
  49. var offset int
  50. if len(buf) < 4 {
  51. // short packet
  52. return nil, errFormat
  53. }
  54. p.Magic = binary.BigEndian.Uint32(buf[offset:])
  55. offset += 4
  56. if p.Magic != AnnouncementMagic && p.Magic != QueryMagic {
  57. return nil, errBadMagic
  58. }
  59. if p.Magic == AnnouncementMagic {
  60. // Port Number
  61. if len(buf) < offset+4 {
  62. // short packet
  63. return nil, errFormat
  64. }
  65. p.Port = binary.BigEndian.Uint16(buf[offset:])
  66. offset += 2
  67. reserved := binary.BigEndian.Uint16(buf[offset:])
  68. if reserved != 0 {
  69. return nil, errFormat
  70. }
  71. offset += 2
  72. }
  73. // Node ID
  74. if len(buf) < offset+4 {
  75. // short packet
  76. return nil, errFormat
  77. }
  78. l := binary.BigEndian.Uint32(buf[offset:])
  79. offset += 4
  80. if len(buf) < offset+int(l)+pad(int(l)) {
  81. // short packet
  82. return nil, errFormat
  83. }
  84. idbs := buf[offset : offset+int(l)]
  85. p.ID = string(idbs)
  86. offset += int(l) + pad(int(l))
  87. if p.Magic == AnnouncementMagic {
  88. // IP
  89. if len(buf) < offset+4 {
  90. // short packet
  91. return nil, errFormat
  92. }
  93. l = binary.BigEndian.Uint32(buf[offset:])
  94. offset += 4
  95. if l != 0 && l != 4 && l != 16 {
  96. // weird ip length
  97. return nil, errFormat
  98. }
  99. if len(buf) < offset+int(l) {
  100. // short packet
  101. return nil, errFormat
  102. }
  103. if l > 0 {
  104. p.IP = buf[offset : offset+int(l)]
  105. offset += int(l)
  106. }
  107. }
  108. if len(buf[offset:]) > 0 {
  109. // extra data
  110. return nil, errFormat
  111. }
  112. return &p, nil
  113. }
  114. func pad(l int) int {
  115. d := l % 4
  116. if d == 0 {
  117. return 0
  118. }
  119. return 4 - d
  120. }
  121. func ipStr(ip []byte) string {
  122. switch len(ip) {
  123. case 4:
  124. return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
  125. case 16:
  126. return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
  127. ip[0], ip[1], ip[2], ip[3],
  128. ip[4], ip[5], ip[6], ip[7],
  129. ip[8], ip[9], ip[10], ip[11],
  130. ip[12], ip[13], ip[14], ip[15])
  131. default:
  132. return ""
  133. }
  134. }