header.go 1.6 KB

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