rtp_parse/rtcp/
rtcp_header.rs1use std::fmt::Debug;
2
3use anyhow::{anyhow, Result};
4use parsely_rs::*;
5
6#[derive(Clone, Debug, PartialEq, Eq, ParselyRead, ParselyWrite)]
20#[parsely_write(sync_args("payload_length_bytes: u16", "report_count_value: u5"))]
21pub struct RtcpHeader {
22 #[parsely(assertion = "|v: &u2| *v == 2")]
23 pub version: u2,
24 pub has_padding: bool,
25 #[parsely_write(sync_expr = "report_count_value")]
26 pub report_count: u5,
27 pub packet_type: u8,
28 #[parsely_write(sync_expr = "payload_length_bytes / 4")]
29 pub length_field: u16,
30}
31
32impl Default for RtcpHeader {
33 fn default() -> Self {
34 Self {
35 version: u2::new(2),
36 has_padding: Default::default(),
37 report_count: Default::default(),
38 packet_type: Default::default(),
39 length_field: Default::default(),
40 }
41 }
42}
43
44pub fn get_sender_ssrc(buf: &[u8]) -> u32 {
49 u32::from_be_bytes(buf[4..8].try_into().unwrap())
50}
51
52impl RtcpHeader {
53 pub const SIZE_BYTES: usize = 4;
54
55 pub fn payload_length_bytes(&self) -> Result<u16> {
57 self.length_field
58 .checked_mul(4)
59 .ok_or(anyhow!("Invalid length field"))
60 }
61
62 pub fn report_count(mut self, report_count: u5) -> Self {
63 self.report_count = report_count;
64 self
65 }
66
67 pub fn packet_type(mut self, packet_type: u8) -> Self {
68 self.packet_type = packet_type;
69 self
70 }
71}
72
73#[cfg(test)]
74#[allow(clippy::unusual_byte_groupings, clippy::bool_assert_comparison)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_read_rtcp_header() {
80 let mut buf = Bits::from_static_bytes(&[0b10_0_00001, 202, 0, 42]);
81
82 let header = RtcpHeader::read::<NetworkOrder>(&mut buf, ())
83 .context("rtcp header")
84 .unwrap();
85 assert_eq!(header.version, u2::new(2));
86 assert_eq!(header.has_padding, false);
87 assert_eq!(header.report_count, u5::new(1));
88 assert_eq!(header.packet_type, 202);
89 assert_eq!(header.length_field, 42);
90 }
91
92 #[test]
93 fn test_write_rtcp_header() {
94 let header = RtcpHeader {
95 version: u2::new(2),
96 has_padding: false,
97 report_count: u5::new(1),
98 packet_type: 1,
99 length_field: 2,
100 };
101
102 let mut buf_mut = BitsMut::new();
103
104 header
105 .write::<NetworkOrder>(&mut buf_mut, ())
106 .expect("successful write");
107
108 let mut buf = buf_mut.freeze();
109 let read_header = RtcpHeader::read::<NetworkOrder>(&mut buf, ())
110 .context("rtcp header")
111 .unwrap();
112 assert_eq!(header, read_header);
113 }
114}