header.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. package header
  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. // The low 8 bits of Reserved carry the multiport lane index (0 is the base
  14. // tunnel, which is what every non-multiport sender emits). The high 8 bits
  15. // remain reserved and are always sent as zero.
  16. // | Remote index (uint32) | 64
  17. // |-----------------------------------------------------------------------|
  18. // | Message counter | 96
  19. // | (uint64) | 128
  20. // |-----------------------------------------------------------------------|
  21. // | payload... |
  22. type m = map[string]any
  23. const (
  24. Version uint8 = 1
  25. Len = 16
  26. )
  27. type MessageType uint8
  28. type MessageSubType uint8
  29. const (
  30. Handshake MessageType = 0
  31. Message MessageType = 1
  32. RecvError MessageType = 2
  33. LightHouse MessageType = 3
  34. Test MessageType = 4
  35. CloseTunnel MessageType = 5
  36. Control MessageType = 6
  37. )
  38. var typeMap = map[MessageType]string{
  39. Handshake: "handshake",
  40. Message: "message",
  41. RecvError: "recvError",
  42. LightHouse: "lightHouse",
  43. Test: "test",
  44. CloseTunnel: "closeTunnel",
  45. Control: "control",
  46. }
  47. const (
  48. MessageNone MessageSubType = 0
  49. MessageRelay MessageSubType = 1
  50. )
  51. const (
  52. TestRequest MessageSubType = 0
  53. TestReply MessageSubType = 1
  54. // LaneProbe is sent on a multiport lane to prove the lane's 5-tuple is
  55. // usable; LaneProbeAck answers it on the base tunnel.
  56. LaneProbe MessageSubType = 2
  57. LaneProbeAck MessageSubType = 3
  58. )
  59. // MaxLane is the largest lane index the header can carry.
  60. const MaxLane = 0xff
  61. // laneMask covers the bits of Reserved that hold the lane index.
  62. const laneMask uint16 = 0x00ff
  63. const (
  64. HandshakeIXPSK0 MessageSubType = 0
  65. HandshakeXXPSK0 MessageSubType = 1
  66. )
  67. var ErrHeaderTooShort = errors.New("header is too short")
  68. var subTypeTestMap = map[MessageSubType]string{
  69. TestRequest: "testRequest",
  70. TestReply: "testReply",
  71. LaneProbe: "laneProbe",
  72. LaneProbeAck: "laneProbeAck",
  73. }
  74. var subTypeNoneMap = map[MessageSubType]string{0: "none"}
  75. var subTypeMap = map[MessageType]*map[MessageSubType]string{
  76. Message: {
  77. MessageNone: "none",
  78. MessageRelay: "relay",
  79. },
  80. RecvError: &subTypeNoneMap,
  81. LightHouse: &subTypeNoneMap,
  82. Test: &subTypeTestMap,
  83. CloseTunnel: &subTypeNoneMap,
  84. Handshake: {
  85. HandshakeIXPSK0: "ix_psk0",
  86. },
  87. Control: &subTypeNoneMap,
  88. }
  89. type H struct {
  90. Version uint8
  91. Type MessageType
  92. Subtype MessageSubType
  93. Reserved uint16
  94. RemoteIndex uint32
  95. MessageCounter uint64
  96. }
  97. // Encode uses the provided byte array to encode the provided header values into.
  98. // Byte array must be capped higher than HeaderLen or this will panic
  99. func Encode(b []byte, v uint8, t MessageType, st MessageSubType, ri uint32, c uint64) []byte {
  100. return EncodeLane(b, v, t, st, ri, c, 0)
  101. }
  102. // EncodeLane is Encode with an explicit multiport lane index, which is carried
  103. // in the low 8 bits of Reserved.
  104. func EncodeLane(b []byte, v uint8, t MessageType, st MessageSubType, ri uint32, c uint64, lane uint8) []byte {
  105. b = b[:Len]
  106. b[0] = v<<4 | byte(t&0x0f)
  107. b[1] = byte(st)
  108. binary.BigEndian.PutUint16(b[2:4], uint16(lane))
  109. binary.BigEndian.PutUint32(b[4:8], ri)
  110. binary.BigEndian.PutUint64(b[8:16], c)
  111. return b
  112. }
  113. // String creates a readable string representation of a header
  114. func (h *H) String() string {
  115. if h == nil {
  116. return "<nil>"
  117. }
  118. return fmt.Sprintf("ver=%d type=%s subtype=%s reserved=%#x remoteindex=%v messagecounter=%v",
  119. h.Version, h.TypeName(), h.SubTypeName(), h.Reserved, h.RemoteIndex, h.MessageCounter)
  120. }
  121. // MarshalJSON creates a json string representation of a header
  122. func (h *H) MarshalJSON() ([]byte, error) {
  123. return json.Marshal(m{
  124. "version": h.Version,
  125. "type": h.TypeName(),
  126. "subType": h.SubTypeName(),
  127. "reserved": h.Reserved,
  128. "remoteIndex": h.RemoteIndex,
  129. "messageCounter": h.MessageCounter,
  130. })
  131. }
  132. // Encode turns header into bytes
  133. func (h *H) Encode(b []byte) ([]byte, error) {
  134. if h == nil {
  135. return nil, errors.New("nil header")
  136. }
  137. return EncodeLane(b, h.Version, h.Type, h.Subtype, h.RemoteIndex, h.MessageCounter, h.Lane()), nil
  138. }
  139. // Lane returns the multiport lane index carried in Reserved. Lane 0 is the base
  140. // tunnel, which is what any sender that does not know about lanes will report.
  141. func (h *H) Lane() uint8 {
  142. return uint8(h.Reserved & laneMask)
  143. }
  144. // Parse is a helper function to parses given bytes into new Header struct
  145. func (h *H) Parse(b []byte) error {
  146. if len(b) < Len {
  147. return ErrHeaderTooShort
  148. }
  149. // get upper 4 bytes
  150. h.Version = uint8((b[0] >> 4) & 0x0f)
  151. // get lower 4 bytes
  152. h.Type = MessageType(b[0] & 0x0f)
  153. h.Subtype = MessageSubType(b[1])
  154. h.Reserved = binary.BigEndian.Uint16(b[2:4])
  155. h.RemoteIndex = binary.BigEndian.Uint32(b[4:8])
  156. h.MessageCounter = binary.BigEndian.Uint64(b[8:16])
  157. return nil
  158. }
  159. // TypeName will transform the headers message type into a human string
  160. func (h *H) TypeName() string {
  161. return TypeName(h.Type)
  162. }
  163. // TypeName will transform a nebula message type into a human string
  164. func TypeName(t MessageType) string {
  165. if n, ok := typeMap[t]; ok {
  166. return n
  167. }
  168. return "unknown"
  169. }
  170. // SubTypeName will transform the headers message sub type into a human string
  171. func (h *H) SubTypeName() string {
  172. return SubTypeName(h.Type, h.Subtype)
  173. }
  174. func (h *H) IsValidSubType() bool {
  175. return IsValidSubType(h.Type, h.Subtype)
  176. }
  177. // SubTypeName will transform a nebula message sub type into a human string
  178. func SubTypeName(t MessageType, s MessageSubType) string {
  179. if n, ok := subTypeMap[t]; ok {
  180. if x, ok := (*n)[s]; ok {
  181. return x
  182. }
  183. }
  184. return "unknown"
  185. }
  186. func IsValidSubType(t MessageType, s MessageSubType) bool {
  187. switch t {
  188. case Message:
  189. return s == MessageNone || s == MessageRelay
  190. case Handshake:
  191. return s == HandshakeIXPSK0
  192. case Test:
  193. return s == TestReply || s == TestRequest || s == LaneProbe || s == LaneProbeAck
  194. case Control, CloseTunnel, RecvError, LightHouse:
  195. return s == 0
  196. default:
  197. return false
  198. }
  199. }
  200. // NewHeader turns bytes into a header
  201. func NewHeader(b []byte) (*H, error) {
  202. h := new(H)
  203. if err := h.Parse(b); err != nil {
  204. return nil, err
  205. }
  206. return h, nil
  207. }