| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | package headerimport (	"encoding/binary"	"encoding/json"	"errors"	"fmt")//Version 1 header:// 0                                                                       31// |-----------------------------------------------------------------------|// | Version (uint4) | Type (uint4) |  Subtype (uint8) | Reserved (uint16) | 32// |-----------------------------------------------------------------------|// |                        Remote index (uint32)                          | 64// |-----------------------------------------------------------------------|// |                           Message counter                             | 96// |                               (uint64)                                | 128// |-----------------------------------------------------------------------|// |                               payload...                              |type m = map[string]anyconst (	Version uint8 = 1	Len           = 16)type MessageType uint8type MessageSubType uint8const (	Handshake   MessageType = 0	Message     MessageType = 1	RecvError   MessageType = 2	LightHouse  MessageType = 3	Test        MessageType = 4	CloseTunnel MessageType = 5	Control     MessageType = 6)var typeMap = map[MessageType]string{	Handshake:   "handshake",	Message:     "message",	RecvError:   "recvError",	LightHouse:  "lightHouse",	Test:        "test",	CloseTunnel: "closeTunnel",	Control:     "control",}const (	MessageNone  MessageSubType = 0	MessageRelay MessageSubType = 1)const (	TestRequest MessageSubType = 0	TestReply   MessageSubType = 1)const (	HandshakeIXPSK0 MessageSubType = 0	HandshakeXXPSK0 MessageSubType = 1)var ErrHeaderTooShort = errors.New("header is too short")var subTypeTestMap = map[MessageSubType]string{	TestRequest: "testRequest",	TestReply:   "testReply",}var subTypeNoneMap = map[MessageSubType]string{0: "none"}var subTypeMap = map[MessageType]*map[MessageSubType]string{	Message: {		MessageNone:  "none",		MessageRelay: "relay",	},	RecvError:   &subTypeNoneMap,	LightHouse:  &subTypeNoneMap,	Test:        &subTypeTestMap,	CloseTunnel: &subTypeNoneMap,	Handshake: {		HandshakeIXPSK0: "ix_psk0",	},	Control: &subTypeNoneMap,}type H struct {	Version        uint8	Type           MessageType	Subtype        MessageSubType	Reserved       uint16	RemoteIndex    uint32	MessageCounter uint64}// Encode uses the provided byte array to encode the provided header values into.// Byte array must be capped higher than HeaderLen or this will panicfunc Encode(b []byte, v uint8, t MessageType, st MessageSubType, ri uint32, c uint64) []byte {	b = b[:Len]	b[0] = v<<4 | byte(t&0x0f)	b[1] = byte(st)	binary.BigEndian.PutUint16(b[2:4], 0)	binary.BigEndian.PutUint32(b[4:8], ri)	binary.BigEndian.PutUint64(b[8:16], c)	return b}// String creates a readable string representation of a headerfunc (h *H) String() string {	if h == nil {		return "<nil>"	}	return fmt.Sprintf("ver=%d type=%s subtype=%s reserved=%#x remoteindex=%v messagecounter=%v",		h.Version, h.TypeName(), h.SubTypeName(), h.Reserved, h.RemoteIndex, h.MessageCounter)}// MarshalJSON creates a json string representation of a headerfunc (h *H) MarshalJSON() ([]byte, error) {	return json.Marshal(m{		"version":        h.Version,		"type":           h.TypeName(),		"subType":        h.SubTypeName(),		"reserved":       h.Reserved,		"remoteIndex":    h.RemoteIndex,		"messageCounter": h.MessageCounter,	})}// Encode turns header into bytesfunc (h *H) Encode(b []byte) ([]byte, error) {	if h == nil {		return nil, errors.New("nil header")	}	return Encode(b, h.Version, h.Type, h.Subtype, h.RemoteIndex, h.MessageCounter), nil}// Parse is a helper function to parses given bytes into new Header structfunc (h *H) Parse(b []byte) error {	if len(b) < Len {		return ErrHeaderTooShort	}	// get upper 4 bytes	h.Version = uint8((b[0] >> 4) & 0x0f)	// get lower 4 bytes	h.Type = MessageType(b[0] & 0x0f)	h.Subtype = MessageSubType(b[1])	h.Reserved = binary.BigEndian.Uint16(b[2:4])	h.RemoteIndex = binary.BigEndian.Uint32(b[4:8])	h.MessageCounter = binary.BigEndian.Uint64(b[8:16])	return nil}// TypeName will transform the headers message type into a human stringfunc (h *H) TypeName() string {	return TypeName(h.Type)}// TypeName will transform a nebula message type into a human stringfunc TypeName(t MessageType) string {	if n, ok := typeMap[t]; ok {		return n	}	return "unknown"}// SubTypeName will transform the headers message sub type into a human stringfunc (h *H) SubTypeName() string {	return SubTypeName(h.Type, h.Subtype)}// SubTypeName will transform a nebula message sub type into a human stringfunc SubTypeName(t MessageType, s MessageSubType) string {	if n, ok := subTypeMap[t]; ok {		if x, ok := (*n)[s]; ok {			return x		}	}	return "unknown"}// NewHeader turns bytes into a headerfunc NewHeader(b []byte) (*H, error) {	h := new(H)	if err := h.Parse(b); err != nil {		return nil, err	}	return h, nil}
 |