3
0

header.go 5.2 KB

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