header.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package nebula
  2. import (
  3. "encoding/binary"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. )
  8. //Version 1 header:
  9. // 0 31
  10. // |-----------------------------------------------------------------------|
  11. // | Version (uint4) | Type (uint4) | Subtype (uint8) | Reserved (uint16) | 32
  12. // |-----------------------------------------------------------------------|
  13. // | Remote index (uint32) | 64
  14. // |-----------------------------------------------------------------------|
  15. // | Message counter | 96
  16. // | (uint64) | 128
  17. // |-----------------------------------------------------------------------|
  18. // | payload... |
  19. const (
  20. Version uint8 = 1
  21. HeaderLen = 16
  22. )
  23. type NebulaMessageType uint8
  24. type NebulaMessageSubType uint8
  25. const (
  26. handshake NebulaMessageType = 0
  27. message NebulaMessageType = 1
  28. recvError NebulaMessageType = 2
  29. lightHouse NebulaMessageType = 3
  30. test NebulaMessageType = 4
  31. closeTunnel NebulaMessageType = 5
  32. //TODO These are deprecated as of 06/12/2018 - NB
  33. testRemote NebulaMessageType = 6
  34. testRemoteReply NebulaMessageType = 7
  35. )
  36. var typeMap = map[NebulaMessageType]string{
  37. handshake: "handshake",
  38. message: "message",
  39. recvError: "recvError",
  40. lightHouse: "lightHouse",
  41. test: "test",
  42. closeTunnel: "closeTunnel",
  43. //TODO These are deprecated as of 06/12/2018 - NB
  44. testRemote: "testRemote",
  45. testRemoteReply: "testRemoteReply",
  46. }
  47. const (
  48. testRequest NebulaMessageSubType = 0
  49. testReply NebulaMessageSubType = 1
  50. )
  51. var eHeaderTooShort = errors.New("header is too short")
  52. var subTypeTestMap = map[NebulaMessageSubType]string{
  53. testRequest: "testRequest",
  54. testReply: "testReply",
  55. }
  56. var subTypeNoneMap = map[NebulaMessageSubType]string{0: "none"}
  57. var subTypeMap = map[NebulaMessageType]*map[NebulaMessageSubType]string{
  58. message: &subTypeNoneMap,
  59. recvError: &subTypeNoneMap,
  60. lightHouse: &subTypeNoneMap,
  61. test: &subTypeTestMap,
  62. closeTunnel: &subTypeNoneMap,
  63. handshake: {
  64. handshakeIXPSK0: "ix_psk0",
  65. },
  66. //TODO: these are deprecated
  67. testRemote: &subTypeNoneMap,
  68. testRemoteReply: &subTypeNoneMap,
  69. }
  70. type Header struct {
  71. Version uint8
  72. Type NebulaMessageType
  73. Subtype NebulaMessageSubType
  74. Reserved uint16
  75. RemoteIndex uint32
  76. MessageCounter uint64
  77. }
  78. // HeaderEncode uses the provided byte array to encode the provided header values into.
  79. // Byte array must be capped higher than HeaderLen or this will panic
  80. func HeaderEncode(b []byte, v uint8, t uint8, st uint8, ri uint32, c uint64) []byte {
  81. b = b[:HeaderLen]
  82. b[0] = byte(v<<4 | (t & 0x0f))
  83. b[1] = byte(st)
  84. binary.BigEndian.PutUint16(b[2:4], 0)
  85. binary.BigEndian.PutUint32(b[4:8], ri)
  86. binary.BigEndian.PutUint64(b[8:16], c)
  87. return b
  88. }
  89. // String creates a readable string representation of a header
  90. func (h *Header) String() string {
  91. if h == nil {
  92. return "<nil>"
  93. }
  94. return fmt.Sprintf("ver=%d type=%s subtype=%s reserved=%#x remoteindex=%v messagecounter=%v",
  95. h.Version, h.TypeName(), h.SubTypeName(), h.Reserved, h.RemoteIndex, h.MessageCounter)
  96. }
  97. // MarshalJSON creates a json string representation of a header
  98. func (h *Header) MarshalJSON() ([]byte, error) {
  99. return json.Marshal(m{
  100. "version": h.Version,
  101. "type": h.TypeName(),
  102. "subType": h.SubTypeName(),
  103. "reserved": h.Reserved,
  104. "remoteIndex": h.RemoteIndex,
  105. "messageCounter": h.MessageCounter,
  106. })
  107. }
  108. // Encode turns header into bytes
  109. func (h *Header) Encode(b []byte) ([]byte, error) {
  110. if h == nil {
  111. return nil, errors.New("nil header")
  112. }
  113. return HeaderEncode(b, h.Version, uint8(h.Type), uint8(h.Subtype), h.RemoteIndex, h.MessageCounter), nil
  114. }
  115. // Parse is a helper function to parses given bytes into new Header struct
  116. func (h *Header) Parse(b []byte) error {
  117. if len(b) < HeaderLen {
  118. return eHeaderTooShort
  119. }
  120. // get upper 4 bytes
  121. h.Version = uint8((b[0] >> 4) & 0x0f)
  122. // get lower 4 bytes
  123. h.Type = NebulaMessageType(b[0] & 0x0f)
  124. h.Subtype = NebulaMessageSubType(b[1])
  125. h.Reserved = binary.BigEndian.Uint16(b[2:4])
  126. h.RemoteIndex = binary.BigEndian.Uint32(b[4:8])
  127. h.MessageCounter = binary.BigEndian.Uint64(b[8:16])
  128. return nil
  129. }
  130. // TypeName will transform the headers message type into a human string
  131. func (h *Header) TypeName() string {
  132. return TypeName(h.Type)
  133. }
  134. // TypeName will transform a nebula message type into a human string
  135. func TypeName(t NebulaMessageType) string {
  136. if n, ok := typeMap[t]; ok {
  137. return n
  138. }
  139. return "unknown"
  140. }
  141. // SubTypeName will transform the headers message sub type into a human string
  142. func (h *Header) SubTypeName() string {
  143. return SubTypeName(h.Type, h.Subtype)
  144. }
  145. // SubTypeName will transform a nebula message sub type into a human string
  146. func SubTypeName(t NebulaMessageType, s NebulaMessageSubType) string {
  147. if n, ok := subTypeMap[t]; ok {
  148. if x, ok := (*n)[s]; ok {
  149. return x
  150. }
  151. }
  152. return "unknown"
  153. }
  154. // NewHeader turns bytes into a header
  155. func NewHeader(b []byte) (*Header, error) {
  156. h := new(Header)
  157. if err := h.Parse(b); err != nil {
  158. return nil, err
  159. }
  160. return h, nil
  161. }