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  }