github.com/pion/dtls/v2@v2.2.12/pkg/protocol/recordlayer/header.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package recordlayer 5 6 import ( 7 "encoding/binary" 8 9 "github.com/pion/dtls/v2/internal/util" 10 "github.com/pion/dtls/v2/pkg/protocol" 11 ) 12 13 // Header implements a TLS RecordLayer header 14 type Header struct { 15 ContentType protocol.ContentType 16 ContentLen uint16 17 Version protocol.Version 18 Epoch uint16 19 SequenceNumber uint64 // uint48 in spec 20 } 21 22 // RecordLayer enums 23 const ( 24 HeaderSize = 13 25 MaxSequenceNumber = 0x0000FFFFFFFFFFFF 26 ) 27 28 // Marshal encodes a TLS RecordLayer Header to binary 29 func (h *Header) Marshal() ([]byte, error) { 30 if h.SequenceNumber > MaxSequenceNumber { 31 return nil, errSequenceNumberOverflow 32 } 33 34 out := make([]byte, HeaderSize) 35 out[0] = byte(h.ContentType) 36 out[1] = h.Version.Major 37 out[2] = h.Version.Minor 38 binary.BigEndian.PutUint16(out[3:], h.Epoch) 39 util.PutBigEndianUint48(out[5:], h.SequenceNumber) 40 binary.BigEndian.PutUint16(out[HeaderSize-2:], h.ContentLen) 41 return out, nil 42 } 43 44 // Unmarshal populates a TLS RecordLayer Header from binary 45 func (h *Header) Unmarshal(data []byte) error { 46 if len(data) < HeaderSize { 47 return errBufferTooSmall 48 } 49 h.ContentType = protocol.ContentType(data[0]) 50 h.Version.Major = data[1] 51 h.Version.Minor = data[2] 52 h.Epoch = binary.BigEndian.Uint16(data[3:]) 53 54 // SequenceNumber is stored as uint48, make into uint64 55 seqCopy := make([]byte, 8) 56 copy(seqCopy[2:], data[5:11]) 57 h.SequenceNumber = binary.BigEndian.Uint64(seqCopy) 58 59 if !h.Version.Equal(protocol.Version1_0) && !h.Version.Equal(protocol.Version1_2) { 60 return errUnsupportedProtocolVersion 61 } 62 63 return nil 64 }