header.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package rtcp
  4. import (
  5. "encoding/binary"
  6. )
  7. // PacketType specifies the type of an RTCP packet
  8. type PacketType uint8
  9. // RTCP packet types registered with IANA. See: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4
  10. const (
  11. TypeSenderReport PacketType = 200 // RFC 3550, 6.4.1
  12. TypeReceiverReport PacketType = 201 // RFC 3550, 6.4.2
  13. TypeSourceDescription PacketType = 202 // RFC 3550, 6.5
  14. TypeGoodbye PacketType = 203 // RFC 3550, 6.6
  15. TypeApplicationDefined PacketType = 204 // RFC 3550, 6.7 (unimplemented)
  16. TypeTransportSpecificFeedback PacketType = 205 // RFC 4585, 6051
  17. TypePayloadSpecificFeedback PacketType = 206 // RFC 4585, 6.3
  18. TypeExtendedReport PacketType = 207 // RFC 3611
  19. )
  20. // Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here
  21. const (
  22. FormatSLI uint8 = 2
  23. FormatPLI uint8 = 1
  24. FormatFIR uint8 = 4
  25. FormatTLN uint8 = 1
  26. FormatRRR uint8 = 5
  27. FormatCCFB uint8 = 11
  28. FormatREMB uint8 = 15
  29. // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5
  30. FormatTCC uint8 = 15
  31. )
  32. func (p PacketType) String() string {
  33. switch p {
  34. case TypeSenderReport:
  35. return "SR"
  36. case TypeReceiverReport:
  37. return "RR"
  38. case TypeSourceDescription:
  39. return "SDES"
  40. case TypeGoodbye:
  41. return "BYE"
  42. case TypeApplicationDefined:
  43. return "APP"
  44. case TypeTransportSpecificFeedback:
  45. return "TSFB"
  46. case TypePayloadSpecificFeedback:
  47. return "PSFB"
  48. case TypeExtendedReport:
  49. return "XR"
  50. default:
  51. return string(p)
  52. }
  53. }
  54. const rtpVersion = 2
  55. // A Header is the common header shared by all RTCP packets
  56. type Header struct {
  57. // If the padding bit is set, this individual RTCP packet contains
  58. // some additional padding octets at the end which are not part of
  59. // the control information but are included in the length field.
  60. Padding bool
  61. // The number of reception reports, sources contained or FMT in this packet (depending on the Type)
  62. Count uint8
  63. // The RTCP packet type for this packet
  64. Type PacketType
  65. // The length of this RTCP packet in 32-bit words minus one,
  66. // including the header and any padding.
  67. Length uint16
  68. }
  69. const (
  70. headerLength = 4
  71. versionShift = 6
  72. versionMask = 0x3
  73. paddingShift = 5
  74. paddingMask = 0x1
  75. countShift = 0
  76. countMask = 0x1f
  77. countMax = (1 << 5) - 1
  78. )
  79. // Marshal encodes the Header in binary
  80. func (h Header) Marshal() ([]byte, error) {
  81. /*
  82. * 0 1 2 3
  83. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  84. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  85. * |V=2|P| RC | PT=SR=200 | length |
  86. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  87. */
  88. rawPacket := make([]byte, headerLength)
  89. rawPacket[0] |= rtpVersion << versionShift
  90. if h.Padding {
  91. rawPacket[0] |= 1 << paddingShift
  92. }
  93. if h.Count > 31 {
  94. return nil, errInvalidHeader
  95. }
  96. rawPacket[0] |= h.Count << countShift
  97. rawPacket[1] = uint8(h.Type)
  98. binary.BigEndian.PutUint16(rawPacket[2:], h.Length)
  99. return rawPacket, nil
  100. }
  101. // Unmarshal decodes the Header from binary
  102. func (h *Header) Unmarshal(rawPacket []byte) error {
  103. if len(rawPacket) < headerLength {
  104. return errPacketTooShort
  105. }
  106. /*
  107. * 0 1 2 3
  108. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  109. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  110. * |V=2|P| RC | PT | length |
  111. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  112. */
  113. version := rawPacket[0] >> versionShift & versionMask
  114. if version != rtpVersion {
  115. return errBadVersion
  116. }
  117. h.Padding = (rawPacket[0] >> paddingShift & paddingMask) > 0
  118. h.Count = rawPacket[0] >> countShift & countMask
  119. h.Type = PacketType(rawPacket[1])
  120. h.Length = binary.BigEndian.Uint16(rawPacket[2:])
  121. return nil
  122. }