extended_report.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. package rtcp
  2. import (
  3. "fmt"
  4. )
  5. // The ExtendedReport packet is an Implementation of RTCP Extended
  6. // Reports defined in RFC 3611. It is used to convey detailed
  7. // information about an RTP stream. Each packet contains one or
  8. // more report blocks, each of which conveys a different kind of
  9. // information.
  10. //
  11. // 0 1 2 3
  12. // 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
  13. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  14. // |V=2|P|reserved | PT=XR=207 | length |
  15. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  16. // | SSRC |
  17. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  18. // : report blocks :
  19. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  20. type ExtendedReport struct {
  21. SenderSSRC uint32 `fmt:"0x%X"`
  22. Reports []ReportBlock
  23. }
  24. // ReportBlock represents a single report within an ExtendedReport
  25. // packet
  26. type ReportBlock interface {
  27. DestinationSSRC() []uint32
  28. setupBlockHeader()
  29. unpackBlockHeader()
  30. }
  31. // TypeSpecificField as described in RFC 3611 section 4.5. In typical
  32. // cases, users of ExtendedReports shouldn't need to access this,
  33. // and should instead use the corresponding fields in the actual
  34. // report blocks themselves.
  35. type TypeSpecificField uint8
  36. // XRHeader defines the common fields that must appear at the start
  37. // of each report block. In typical cases, users of ExtendedReports
  38. // shouldn't need to access this. For locally-constructed report
  39. // blocks, these values will not be accurate until the corresponding
  40. // packet is marshaled.
  41. type XRHeader struct {
  42. BlockType BlockTypeType
  43. TypeSpecific TypeSpecificField `fmt:"0x%X"`
  44. BlockLength uint16
  45. }
  46. // BlockTypeType specifies the type of report in a report block
  47. type BlockTypeType uint8
  48. // Extended Report block types from RFC 3611.
  49. const (
  50. LossRLEReportBlockType = 1 // RFC 3611, section 4.1
  51. DuplicateRLEReportBlockType = 2 // RFC 3611, section 4.2
  52. PacketReceiptTimesReportBlockType = 3 // RFC 3611, section 4.3
  53. ReceiverReferenceTimeReportBlockType = 4 // RFC 3611, section 4.4
  54. DLRRReportBlockType = 5 // RFC 3611, section 4.5
  55. StatisticsSummaryReportBlockType = 6 // RFC 3611, section 4.6
  56. VoIPMetricsReportBlockType = 7 // RFC 3611, section 4.7
  57. )
  58. // String converts the Extended report block types into readable strings
  59. func (t BlockTypeType) String() string {
  60. switch t {
  61. case LossRLEReportBlockType:
  62. return "LossRLEReportBlockType"
  63. case DuplicateRLEReportBlockType:
  64. return "DuplicateRLEReportBlockType"
  65. case PacketReceiptTimesReportBlockType:
  66. return "PacketReceiptTimesReportBlockType"
  67. case ReceiverReferenceTimeReportBlockType:
  68. return "ReceiverReferenceTimeReportBlockType"
  69. case DLRRReportBlockType:
  70. return "DLRRReportBlockType"
  71. case StatisticsSummaryReportBlockType:
  72. return "StatisticsSummaryReportBlockType"
  73. case VoIPMetricsReportBlockType:
  74. return "VoIPMetricsReportBlockType"
  75. }
  76. return fmt.Sprintf("invalid value %d", t)
  77. }
  78. // rleReportBlock defines the common structure used by both
  79. // Loss RLE report blocks (RFC 3611 §4.1) and Duplicate RLE
  80. // report blocks (RFC 3611 §4.2).
  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. // | BT = 1 or 2 | rsvd. | T | block length |
  86. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  87. // | SSRC of source |
  88. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  89. // | begin_seq | end_seq |
  90. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  91. // | chunk 1 | chunk 2 |
  92. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  93. // : ... :
  94. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  95. // | chunk n-1 | chunk n |
  96. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  97. type rleReportBlock struct {
  98. XRHeader
  99. T uint8 `encoding:"omit"`
  100. SSRC uint32 `fmt:"0x%X"`
  101. BeginSeq uint16
  102. EndSeq uint16
  103. Chunks []Chunk
  104. }
  105. // Chunk as defined in RFC 3611, section 4.1. These represent information
  106. // about packet losses and packet duplication. They have three representations:
  107. //
  108. // Run Length Chunk:
  109. //
  110. // 0 1
  111. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  112. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  113. // |C|R| run length |
  114. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  115. //
  116. // Bit Vector Chunk:
  117. //
  118. // 0 1
  119. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  120. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  121. // |C| bit vector |
  122. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  123. //
  124. // Terminating Null Chunk:
  125. //
  126. // 0 1
  127. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  128. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  129. // |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|
  130. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  131. type Chunk uint16
  132. // LossRLEReportBlock is used to report information about packet
  133. // losses, as described in RFC 3611, section 4.1
  134. type LossRLEReportBlock rleReportBlock
  135. // DestinationSSRC returns an array of SSRC values that this report block refers to.
  136. func (b *LossRLEReportBlock) DestinationSSRC() []uint32 {
  137. return []uint32{b.SSRC}
  138. }
  139. func (b *LossRLEReportBlock) setupBlockHeader() {
  140. b.XRHeader.BlockType = LossRLEReportBlockType
  141. b.XRHeader.TypeSpecific = TypeSpecificField(b.T & 0x0F)
  142. b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1)
  143. }
  144. func (b *LossRLEReportBlock) unpackBlockHeader() {
  145. b.T = uint8(b.XRHeader.TypeSpecific) & 0x0F
  146. }
  147. // DuplicateRLEReportBlock is used to report information about packet
  148. // duplication, as described in RFC 3611, section 4.1
  149. type DuplicateRLEReportBlock rleReportBlock
  150. // DestinationSSRC returns an array of SSRC values that this report block refers to.
  151. func (b *DuplicateRLEReportBlock) DestinationSSRC() []uint32 {
  152. return []uint32{b.SSRC}
  153. }
  154. func (b *DuplicateRLEReportBlock) setupBlockHeader() {
  155. b.XRHeader.BlockType = DuplicateRLEReportBlockType
  156. b.XRHeader.TypeSpecific = TypeSpecificField(b.T & 0x0F)
  157. b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1)
  158. }
  159. func (b *DuplicateRLEReportBlock) unpackBlockHeader() {
  160. b.T = uint8(b.XRHeader.TypeSpecific) & 0x0F
  161. }
  162. // ChunkType enumerates the three kinds of chunks described in RFC 3611 section 4.1.
  163. type ChunkType uint8
  164. // These are the valid values that ChunkType can assume
  165. const (
  166. RunLengthChunkType = 0
  167. BitVectorChunkType = 1
  168. TerminatingNullChunkType = 2
  169. )
  170. func (c Chunk) String() string {
  171. switch c.Type() {
  172. case RunLengthChunkType:
  173. runType, _ := c.RunType()
  174. return fmt.Sprintf("[RunLength type=%d, length=%d]", runType, c.Value())
  175. case BitVectorChunkType:
  176. return fmt.Sprintf("[BitVector 0b%015b]", c.Value())
  177. case TerminatingNullChunkType:
  178. return "[TerminatingNull]"
  179. }
  180. return fmt.Sprintf("[0x%X]", uint16(c))
  181. }
  182. // Type returns the ChunkType that this Chunk represents
  183. func (c Chunk) Type() ChunkType {
  184. if c == 0 {
  185. return TerminatingNullChunkType
  186. }
  187. return ChunkType(c >> 15)
  188. }
  189. // RunType returns the RunType that this Chunk represents. It is
  190. // only valid if ChunkType is RunLengthChunkType.
  191. func (c Chunk) RunType() (uint, error) {
  192. if c.Type() != RunLengthChunkType {
  193. return 0, errWrongChunkType
  194. }
  195. return uint((c >> 14) & 0x01), nil
  196. }
  197. // Value returns the value represented in this Chunk
  198. func (c Chunk) Value() uint {
  199. switch c.Type() {
  200. case RunLengthChunkType:
  201. return uint(c & 0x3FFF)
  202. case BitVectorChunkType:
  203. return uint(c & 0x7FFF)
  204. case TerminatingNullChunkType:
  205. return 0
  206. }
  207. return uint(c)
  208. }
  209. // PacketReceiptTimesReportBlock represents a Packet Receipt Times
  210. // report block, as described in RFC 3611 section 4.3.
  211. //
  212. // 0 1 2 3
  213. // 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
  214. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  215. // | BT=3 | rsvd. | T | block length |
  216. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  217. // | SSRC of source |
  218. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  219. // | begin_seq | end_seq |
  220. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  221. // | Receipt time of packet begin_seq |
  222. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  223. // | Receipt time of packet (begin_seq + 1) mod 65536 |
  224. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  225. // : ... :
  226. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  227. // | Receipt time of packet (end_seq - 1) mod 65536 |
  228. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  229. type PacketReceiptTimesReportBlock struct {
  230. XRHeader
  231. T uint8 `encoding:"omit"`
  232. SSRC uint32 `fmt:"0x%X"`
  233. BeginSeq uint16
  234. EndSeq uint16
  235. ReceiptTime []uint32
  236. }
  237. // DestinationSSRC returns an array of SSRC values that this report block refers to.
  238. func (b *PacketReceiptTimesReportBlock) DestinationSSRC() []uint32 {
  239. return []uint32{b.SSRC}
  240. }
  241. func (b *PacketReceiptTimesReportBlock) setupBlockHeader() {
  242. b.XRHeader.BlockType = PacketReceiptTimesReportBlockType
  243. b.XRHeader.TypeSpecific = TypeSpecificField(b.T & 0x0F)
  244. b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1)
  245. }
  246. func (b *PacketReceiptTimesReportBlock) unpackBlockHeader() {
  247. b.T = uint8(b.XRHeader.TypeSpecific) & 0x0F
  248. }
  249. // ReceiverReferenceTimeReportBlock encodes a Receiver Reference Time
  250. // report block as described in RFC 3611 section 4.4.
  251. //
  252. // 0 1 2 3
  253. // 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
  254. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  255. // | BT=4 | reserved | block length = 2 |
  256. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  257. // | NTP timestamp, most significant word |
  258. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  259. // | NTP timestamp, least significant word |
  260. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  261. type ReceiverReferenceTimeReportBlock struct {
  262. XRHeader
  263. NTPTimestamp uint64
  264. }
  265. // DestinationSSRC returns an array of SSRC values that this report block refers to.
  266. func (b *ReceiverReferenceTimeReportBlock) DestinationSSRC() []uint32 {
  267. return []uint32{}
  268. }
  269. func (b *ReceiverReferenceTimeReportBlock) setupBlockHeader() {
  270. b.XRHeader.BlockType = ReceiverReferenceTimeReportBlockType
  271. b.XRHeader.TypeSpecific = 0
  272. b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1)
  273. }
  274. func (b *ReceiverReferenceTimeReportBlock) unpackBlockHeader() {
  275. }
  276. // DLRRReportBlock encodes a DLRR Report Block as described in
  277. // RFC 3611 section 4.5.
  278. //
  279. // 0 1 2 3
  280. // 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
  281. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  282. // | BT=5 | reserved | block length |
  283. // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  284. // | SSRC_1 (SSRC of first receiver) | sub-
  285. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
  286. // | last RR (LRR) | 1
  287. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  288. // | delay since last RR (DLRR) |
  289. // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  290. // | SSRC_2 (SSRC of second receiver) | sub-
  291. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
  292. // : ... : 2
  293. // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  294. type DLRRReportBlock struct {
  295. XRHeader
  296. Reports []DLRRReport
  297. }
  298. // DLRRReport encodes a single report inside a DLRRReportBlock.
  299. type DLRRReport struct {
  300. SSRC uint32 `fmt:"0x%X"`
  301. LastRR uint32
  302. DLRR uint32
  303. }
  304. // DestinationSSRC returns an array of SSRC values that this report block refers to.
  305. func (b *DLRRReportBlock) DestinationSSRC() []uint32 {
  306. ssrc := make([]uint32, len(b.Reports))
  307. for i, r := range b.Reports {
  308. ssrc[i] = r.SSRC
  309. }
  310. return ssrc
  311. }
  312. func (b *DLRRReportBlock) setupBlockHeader() {
  313. b.XRHeader.BlockType = DLRRReportBlockType
  314. b.XRHeader.TypeSpecific = 0
  315. b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1)
  316. }
  317. func (b *DLRRReportBlock) unpackBlockHeader() {
  318. }
  319. // StatisticsSummaryReportBlock encodes a Statistics Summary Report
  320. // Block as described in RFC 3611, section 4.6.
  321. //
  322. // 0 1 2 3
  323. // 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
  324. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  325. // | BT=6 |L|D|J|ToH|rsvd.| block length = 9 |
  326. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  327. // | SSRC of source |
  328. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  329. // | begin_seq | end_seq |
  330. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  331. // | lost_packets |
  332. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  333. // | dup_packets |
  334. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  335. // | min_jitter |
  336. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  337. // | max_jitter |
  338. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  339. // | mean_jitter |
  340. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  341. // | dev_jitter |
  342. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  343. // | min_ttl_or_hl | max_ttl_or_hl |mean_ttl_or_hl | dev_ttl_or_hl |
  344. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  345. type StatisticsSummaryReportBlock struct {
  346. XRHeader
  347. LossReports bool `encoding:"omit"`
  348. DuplicateReports bool `encoding:"omit"`
  349. JitterReports bool `encoding:"omit"`
  350. TTLorHopLimit TTLorHopLimitType `encoding:"omit"`
  351. SSRC uint32 `fmt:"0x%X"`
  352. BeginSeq uint16
  353. EndSeq uint16
  354. LostPackets uint32
  355. DupPackets uint32
  356. MinJitter uint32
  357. MaxJitter uint32
  358. MeanJitter uint32
  359. DevJitter uint32
  360. MinTTLOrHL uint8
  361. MaxTTLOrHL uint8
  362. MeanTTLOrHL uint8
  363. DevTTLOrHL uint8
  364. }
  365. // TTLorHopLimitType encodes values for the ToH field in
  366. // a StatisticsSummaryReportBlock
  367. type TTLorHopLimitType uint8
  368. // Values for TTLorHopLimitType
  369. const (
  370. ToHMissing = 0
  371. ToHIPv4 = 1
  372. ToHIPv6 = 2
  373. )
  374. func (t TTLorHopLimitType) String() string {
  375. switch t {
  376. case ToHMissing:
  377. return "[ToH Missing]"
  378. case ToHIPv4:
  379. return "[ToH = IPv4]"
  380. case ToHIPv6:
  381. return "[ToH = IPv6]"
  382. }
  383. return "[ToH Flag is Invalid]"
  384. }
  385. // DestinationSSRC returns an array of SSRC values that this report block refers to.
  386. func (b *StatisticsSummaryReportBlock) DestinationSSRC() []uint32 {
  387. return []uint32{b.SSRC}
  388. }
  389. func (b *StatisticsSummaryReportBlock) setupBlockHeader() {
  390. b.XRHeader.BlockType = StatisticsSummaryReportBlockType
  391. b.XRHeader.TypeSpecific = 0x00
  392. if b.LossReports {
  393. b.XRHeader.TypeSpecific |= 0x80
  394. }
  395. if b.DuplicateReports {
  396. b.XRHeader.TypeSpecific |= 0x40
  397. }
  398. if b.JitterReports {
  399. b.XRHeader.TypeSpecific |= 0x20
  400. }
  401. b.XRHeader.TypeSpecific |= TypeSpecificField((b.TTLorHopLimit & 0x03) << 3)
  402. b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1)
  403. }
  404. func (b *StatisticsSummaryReportBlock) unpackBlockHeader() {
  405. b.LossReports = b.XRHeader.TypeSpecific&0x80 != 0
  406. b.DuplicateReports = b.XRHeader.TypeSpecific&0x40 != 0
  407. b.JitterReports = b.XRHeader.TypeSpecific&0x20 != 0
  408. b.TTLorHopLimit = TTLorHopLimitType((b.XRHeader.TypeSpecific & 0x18) >> 3)
  409. }
  410. // VoIPMetricsReportBlock encodes a VoIP Metrics Report Block as described
  411. // in RFC 3611, section 4.7.
  412. //
  413. // 0 1 2 3
  414. // 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
  415. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  416. // | BT=7 | reserved | block length = 8 |
  417. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  418. // | SSRC of source |
  419. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  420. // | loss rate | discard rate | burst density | gap density |
  421. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  422. // | burst duration | gap duration |
  423. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  424. // | round trip delay | end system delay |
  425. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  426. // | signal level | noise level | RERL | Gmin |
  427. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  428. // | R factor | ext. R factor | MOS-LQ | MOS-CQ |
  429. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  430. // | RX config | reserved | JB nominal |
  431. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  432. // | JB maximum | JB abs max |
  433. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  434. type VoIPMetricsReportBlock struct {
  435. XRHeader
  436. SSRC uint32 `fmt:"0x%X"`
  437. LossRate uint8
  438. DiscardRate uint8
  439. BurstDensity uint8
  440. GapDensity uint8
  441. BurstDuration uint16
  442. GapDuration uint16
  443. RoundTripDelay uint16
  444. EndSystemDelay uint16
  445. SignalLevel uint8
  446. NoiseLevel uint8
  447. RERL uint8
  448. Gmin uint8
  449. RFactor uint8
  450. ExtRFactor uint8
  451. MOSLQ uint8
  452. MOSCQ uint8
  453. RXConfig uint8
  454. _ uint8
  455. JBNominal uint16
  456. JBMaximum uint16
  457. JBAbsMax uint16
  458. }
  459. // DestinationSSRC returns an array of SSRC values that this report block refers to.
  460. func (b *VoIPMetricsReportBlock) DestinationSSRC() []uint32 {
  461. return []uint32{b.SSRC}
  462. }
  463. func (b *VoIPMetricsReportBlock) setupBlockHeader() {
  464. b.XRHeader.BlockType = VoIPMetricsReportBlockType
  465. b.XRHeader.TypeSpecific = 0
  466. b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1)
  467. }
  468. func (b *VoIPMetricsReportBlock) unpackBlockHeader() {
  469. }
  470. // UnknownReportBlock is used to store bytes for any report block
  471. // that has an unknown Report Block Type.
  472. type UnknownReportBlock struct {
  473. XRHeader
  474. Bytes []byte
  475. }
  476. // DestinationSSRC returns an array of SSRC values that this report block refers to.
  477. func (b *UnknownReportBlock) DestinationSSRC() []uint32 {
  478. return []uint32{}
  479. }
  480. func (b *UnknownReportBlock) setupBlockHeader() {
  481. b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1)
  482. }
  483. func (b *UnknownReportBlock) unpackBlockHeader() {
  484. }
  485. // Marshal encodes the ExtendedReport in binary
  486. func (x ExtendedReport) Marshal() ([]byte, error) {
  487. for _, p := range x.Reports {
  488. p.setupBlockHeader()
  489. }
  490. length := wireSize(x)
  491. // RTCP Header
  492. header := Header{
  493. Type: TypeExtendedReport,
  494. Length: uint16(length / 4),
  495. }
  496. headerBuffer, err := header.Marshal()
  497. if err != nil {
  498. return []byte{}, err
  499. }
  500. length += len(headerBuffer)
  501. rawPacket := make([]byte, length)
  502. buffer := packetBuffer{bytes: rawPacket}
  503. err = buffer.write(headerBuffer)
  504. if err != nil {
  505. return []byte{}, err
  506. }
  507. err = buffer.write(x)
  508. if err != nil {
  509. return []byte{}, err
  510. }
  511. return rawPacket, nil
  512. }
  513. // Unmarshal decodes the ExtendedReport from binary
  514. func (x *ExtendedReport) Unmarshal(b []byte) error {
  515. var header Header
  516. if err := header.Unmarshal(b); err != nil {
  517. return err
  518. }
  519. if header.Type != TypeExtendedReport {
  520. return errWrongType
  521. }
  522. buffer := packetBuffer{bytes: b[headerLength:]}
  523. err := buffer.read(&x.SenderSSRC)
  524. if err != nil {
  525. return err
  526. }
  527. for len(buffer.bytes) > 0 {
  528. var block ReportBlock
  529. headerBuffer := buffer
  530. xrHeader := XRHeader{}
  531. err = headerBuffer.read(&xrHeader)
  532. if err != nil {
  533. return err
  534. }
  535. switch xrHeader.BlockType {
  536. case LossRLEReportBlockType:
  537. block = new(LossRLEReportBlock)
  538. case DuplicateRLEReportBlockType:
  539. block = new(DuplicateRLEReportBlock)
  540. case PacketReceiptTimesReportBlockType:
  541. block = new(PacketReceiptTimesReportBlock)
  542. case ReceiverReferenceTimeReportBlockType:
  543. block = new(ReceiverReferenceTimeReportBlock)
  544. case DLRRReportBlockType:
  545. block = new(DLRRReportBlock)
  546. case StatisticsSummaryReportBlockType:
  547. block = new(StatisticsSummaryReportBlock)
  548. case VoIPMetricsReportBlockType:
  549. block = new(VoIPMetricsReportBlock)
  550. default:
  551. block = new(UnknownReportBlock)
  552. }
  553. // We need to limit the amount of data available to
  554. // this block to the actual length of the block
  555. blockLength := (int(xrHeader.BlockLength) + 1) * 4
  556. blockBuffer := buffer.split(blockLength)
  557. err = blockBuffer.read(block)
  558. if err != nil {
  559. return err
  560. }
  561. block.unpackBlockHeader()
  562. x.Reports = append(x.Reports, block)
  563. }
  564. return nil
  565. }
  566. // DestinationSSRC returns an array of SSRC values that this packet refers to.
  567. func (x *ExtendedReport) DestinationSSRC() []uint32 {
  568. ssrc := make([]uint32, 0)
  569. for _, p := range x.Reports {
  570. ssrc = append(ssrc, p.DestinationSSRC()...)
  571. }
  572. return ssrc
  573. }
  574. func (x *ExtendedReport) String() string {
  575. return stringify(x)
  576. }