rtc_rtcp/extended_report/
dlrr.rs1use super::*;
2
3const DLRR_REPORT_LENGTH: u16 = 12;
4
5#[derive(Debug, Default, PartialEq, Eq, Clone)]
7pub struct DLRRReport {
8 pub ssrc: u32,
9 pub last_rr: u32,
10 pub dlrr: u32,
11}
12
13impl fmt::Display for DLRRReport {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 write!(f, "{self:?}")
16 }
17}
18
19#[derive(Debug, Default, PartialEq, Eq, Clone)]
38pub struct DLRRReportBlock {
39 pub reports: Vec<DLRRReport>,
40}
41
42impl fmt::Display for DLRRReportBlock {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 write!(f, "{self:?}")
45 }
46}
47
48impl DLRRReportBlock {
49 pub fn xr_header(&self) -> XRHeader {
50 XRHeader {
51 block_type: BlockType::DLRR,
52 type_specific: 0,
53 block_length: (self.raw_size() / 4 - 1) as u16,
54 }
55 }
56}
57
58impl Packet for DLRRReportBlock {
59 fn header(&self) -> Header {
60 Header::default()
61 }
62
63 fn destination_ssrc(&self) -> Vec<u32> {
65 let mut ssrc = Vec::with_capacity(self.reports.len());
66 for r in &self.reports {
67 ssrc.push(r.ssrc);
68 }
69 ssrc
70 }
71
72 fn raw_size(&self) -> usize {
73 XR_HEADER_LENGTH + self.reports.len() * 4 * 3
74 }
75
76 fn as_any(&self) -> &dyn Any {
77 self
78 }
79 fn equal(&self, other: &dyn Packet) -> bool {
80 other.as_any().downcast_ref::<DLRRReportBlock>() == Some(self)
81 }
82 fn cloned(&self) -> Box<dyn Packet> {
83 Box::new(self.clone())
84 }
85}
86
87impl MarshalSize for DLRRReportBlock {
88 fn marshal_size(&self) -> usize {
89 self.raw_size()
90 }
91}
92
93impl Marshal for DLRRReportBlock {
94 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
96 if buf.remaining_mut() < self.marshal_size() {
97 return Err(Error::BufferTooShort);
98 }
99
100 let h = self.xr_header();
101 let n = h.marshal_to(buf)?;
102 buf = &mut buf[n..];
103
104 for rep in &self.reports {
105 buf.put_u32(rep.ssrc);
106 buf.put_u32(rep.last_rr);
107 buf.put_u32(rep.dlrr);
108 }
109
110 Ok(self.marshal_size())
111 }
112}
113
114impl Unmarshal for DLRRReportBlock {
115 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
117 where
118 Self: Sized,
119 B: Buf,
120 {
121 if raw_packet.remaining() < XR_HEADER_LENGTH {
122 return Err(Error::PacketTooShort);
123 }
124
125 let xr_header = XRHeader::unmarshal(raw_packet)?;
126 let block_length = match xr_header.block_length.checked_mul(4) {
127 Some(length) => length,
128 None => return Err(Error::InvalidBlockSize),
129 };
130 if block_length % DLRR_REPORT_LENGTH != 0 || raw_packet.remaining() < block_length as usize
131 {
132 return Err(Error::PacketTooShort);
133 }
134
135 let mut offset = 0;
136 let mut reports = vec![];
137 while offset < block_length {
138 let ssrc = raw_packet.get_u32();
139 let last_rr = raw_packet.get_u32();
140 let dlrr = raw_packet.get_u32();
141 reports.push(DLRRReport {
142 ssrc,
143 last_rr,
144 dlrr,
145 });
146 offset += DLRR_REPORT_LENGTH;
147 }
148
149 Ok(DLRRReportBlock { reports })
150 }
151}