package recordlayer import ( "encoding/binary" "github.com/pion/dtls/v2/internal/util" "github.com/pion/dtls/v2/pkg/protocol" ) // Header implements a TLS RecordLayer header type Header struct { ContentType protocol.ContentType ContentLen uint16 Version protocol.Version Epoch uint16 SequenceNumber uint64 // uint48 in spec } // RecordLayer enums const ( HeaderSize = 13 MaxSequenceNumber = 0x0000FFFFFFFFFFFF ) // Marshal encodes a TLS RecordLayer Header to binary func (h *Header) Marshal() ([]byte, error) { if h.SequenceNumber > MaxSequenceNumber { return nil, errSequenceNumberOverflow } out := make([]byte, HeaderSize) out[0] = byte(h.ContentType) out[1] = h.Version.Major out[2] = h.Version.Minor binary.BigEndian.PutUint16(out[3:], h.Epoch) util.PutBigEndianUint48(out[5:], h.SequenceNumber) binary.BigEndian.PutUint16(out[HeaderSize-2:], h.ContentLen) return out, nil } // Unmarshal populates a TLS RecordLayer Header from binary func (h *Header) Unmarshal(data []byte) error { if len(data) < HeaderSize { return errBufferTooSmall } h.ContentType = protocol.ContentType(data[0]) h.Version.Major = data[1] h.Version.Minor = data[2] h.Epoch = binary.BigEndian.Uint16(data[3:]) // SequenceNumber is stored as uint48, make into uint64 seqCopy := make([]byte, 8) copy(seqCopy[2:], data[5:11]) h.SequenceNumber = binary.BigEndian.Uint64(seqCopy) if !h.Version.Equal(protocol.Version1_0) && !h.Version.Equal(protocol.Version1_2) { return errUnsupportedProtocolVersion } return nil }