rtc_rtcp/extended_report/
mod.rs1#[cfg(test)]
2mod extended_report_test;
3
4pub mod dlrr;
6pub mod prt;
8pub mod rle;
10pub mod rrt;
12pub mod ssr;
14pub mod unknown;
16pub mod vm;
18
19pub use dlrr::{DLRRReport, DLRRReportBlock};
20pub use prt::PacketReceiptTimesReportBlock;
21pub use rle::{Chunk, ChunkType, DuplicateRLEReportBlock, LossRLEReportBlock, RLEReportBlock};
22pub use rrt::ReceiverReferenceTimeReportBlock;
23pub use ssr::{StatisticsSummaryReportBlock, TTLorHopLimitType};
24pub use unknown::UnknownReportBlock;
25pub use vm::VoIPMetricsReportBlock;
26
27use crate::Packet;
28use crate::header::{HEADER_LENGTH, Header, PacketType, SSRC_LENGTH};
29use crate::util::{get_padding_size, put_padding};
30use bytes::{Buf, BufMut, Bytes};
31use shared::{
32 error::{Error, Result},
33 marshal::{Marshal, MarshalSize, Unmarshal},
34};
35use std::any::Any;
36use std::fmt;
37
38const XR_HEADER_LENGTH: usize = 4;
39
40#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
43#[non_exhaustive]
44pub enum BlockType {
45 #[default]
46 Unknown = 0,
48 LossRLE = 1, DuplicateRLE = 2, PacketReceiptTimes = 3, ReceiverReferenceTime = 4, DLRR = 5, StatisticsSummary = 6, VoIPMetrics = 7, }
63
64impl From<u8> for BlockType {
65 fn from(v: u8) -> Self {
66 match v {
67 1 => BlockType::LossRLE,
68 2 => BlockType::DuplicateRLE,
69 3 => BlockType::PacketReceiptTimes,
70 4 => BlockType::ReceiverReferenceTime,
71 5 => BlockType::DLRR,
72 6 => BlockType::StatisticsSummary,
73 7 => BlockType::VoIPMetrics,
74 _ => BlockType::Unknown,
75 }
76 }
77}
78
79impl fmt::Display for BlockType {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 let s = match *self {
83 BlockType::LossRLE => "LossRLEReportBlockType",
84 BlockType::DuplicateRLE => "DuplicateRLEReportBlockType",
85 BlockType::PacketReceiptTimes => "PacketReceiptTimesReportBlockType",
86 BlockType::ReceiverReferenceTime => "ReceiverReferenceTimeReportBlockType",
87 BlockType::DLRR => "DLRRReportBlockType",
88 BlockType::StatisticsSummary => "StatisticsSummaryReportBlockType",
89 BlockType::VoIPMetrics => "VoIPMetricsReportBlockType",
90 _ => "UnknownReportBlockType",
91 };
92 write!(f, "{s}")
93 }
94}
95
96pub type TypeSpecificField = u8;
101
102#[derive(Debug, Default, PartialEq, Eq, Clone)]
108pub struct XRHeader {
109 pub block_type: BlockType,
111 pub type_specific: TypeSpecificField,
113 pub block_length: u16,
115}
116
117impl MarshalSize for XRHeader {
118 fn marshal_size(&self) -> usize {
119 XR_HEADER_LENGTH
120 }
121}
122
123impl Marshal for XRHeader {
124 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
126 if buf.remaining_mut() < XR_HEADER_LENGTH {
127 return Err(Error::BufferTooShort);
128 }
129
130 buf.put_u8(self.block_type as u8);
131 buf.put_u8(self.type_specific);
132 buf.put_u16(self.block_length);
133
134 Ok(XR_HEADER_LENGTH)
135 }
136}
137
138impl Unmarshal for XRHeader {
139 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
141 where
142 Self: Sized,
143 B: Buf,
144 {
145 if raw_packet.remaining() < XR_HEADER_LENGTH {
146 return Err(Error::PacketTooShort);
147 }
148
149 let block_type: BlockType = raw_packet.get_u8().into();
150 let type_specific = raw_packet.get_u8();
151 let block_length = raw_packet.get_u16();
152
153 Ok(XRHeader {
154 block_type,
155 type_specific,
156 block_length,
157 })
158 }
159}
160#[derive(Debug, PartialEq, Default, Clone)]
176pub struct ExtendedReport {
177 pub sender_ssrc: u32,
179 pub reports: Vec<Box<dyn Packet>>,
181}
182
183impl fmt::Display for ExtendedReport {
184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 write!(f, "{self:?}")
186 }
187}
188
189impl Packet for ExtendedReport {
190 fn header(&self) -> Header {
192 Header {
193 padding: get_padding_size(self.raw_size()) != 0,
194 count: 0,
195 packet_type: PacketType::ExtendedReport,
196 length: ((self.marshal_size() / 4) - 1) as u16,
197 }
198 }
199
200 fn destination_ssrc(&self) -> Vec<u32> {
202 let mut ssrc = vec![];
203 for p in &self.reports {
204 ssrc.extend(p.destination_ssrc());
205 }
206 ssrc
207 }
208
209 fn raw_size(&self) -> usize {
210 let mut reps_length = 0;
211 for rep in &self.reports {
212 reps_length += rep.marshal_size();
213 }
214 HEADER_LENGTH + SSRC_LENGTH + reps_length
215 }
216
217 fn as_any(&self) -> &dyn Any {
218 self
219 }
220
221 fn equal(&self, other: &dyn Packet) -> bool {
222 other.as_any().downcast_ref::<ExtendedReport>() == Some(self)
223 }
224
225 fn cloned(&self) -> Box<dyn Packet> {
226 Box::new(self.clone())
227 }
228}
229
230impl MarshalSize for ExtendedReport {
231 fn marshal_size(&self) -> usize {
232 let l = self.raw_size();
233 l + get_padding_size(l)
235 }
236}
237
238impl Marshal for ExtendedReport {
239 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
241 if buf.remaining_mut() < self.marshal_size() {
242 return Err(Error::BufferTooShort);
243 }
244
245 let h = self.header();
246 let n = h.marshal_to(buf)?;
247 buf = &mut buf[n..];
248
249 buf.put_u32(self.sender_ssrc);
250
251 for report in &self.reports {
252 let n = report.marshal_to(buf)?;
253 buf = &mut buf[n..];
254 }
255
256 if h.padding {
257 put_padding(buf, self.raw_size());
258 }
259
260 Ok(self.marshal_size())
261 }
262}
263
264impl Unmarshal for ExtendedReport {
265 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
267 where
268 Self: Sized,
269 B: Buf,
270 {
271 let raw_packet_len = raw_packet.remaining();
272 if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
273 return Err(Error::PacketTooShort);
274 }
275
276 let header = Header::unmarshal(raw_packet)?;
277 if header.packet_type != PacketType::ExtendedReport {
278 return Err(Error::WrongType);
279 }
280
281 let sender_ssrc = raw_packet.get_u32();
282
283 let mut offset = HEADER_LENGTH + SSRC_LENGTH;
284 let mut reports = vec![];
285 while raw_packet.remaining() > 0 {
286 if offset + XR_HEADER_LENGTH > raw_packet_len {
287 return Err(Error::PacketTooShort);
288 }
289
290 let block_type: BlockType = raw_packet.chunk()[0].into();
291 let report: Box<dyn Packet> = match block_type {
292 BlockType::LossRLE => Box::new(LossRLEReportBlock::unmarshal(raw_packet)?),
293 BlockType::DuplicateRLE => {
294 Box::new(DuplicateRLEReportBlock::unmarshal(raw_packet)?)
295 }
296 BlockType::PacketReceiptTimes => {
297 Box::new(PacketReceiptTimesReportBlock::unmarshal(raw_packet)?)
298 }
299 BlockType::ReceiverReferenceTime => {
300 Box::new(ReceiverReferenceTimeReportBlock::unmarshal(raw_packet)?)
301 }
302 BlockType::DLRR => Box::new(DLRRReportBlock::unmarshal(raw_packet)?),
303 BlockType::StatisticsSummary => {
304 Box::new(StatisticsSummaryReportBlock::unmarshal(raw_packet)?)
305 }
306 BlockType::VoIPMetrics => Box::new(VoIPMetricsReportBlock::unmarshal(raw_packet)?),
307 _ => Box::new(UnknownReportBlock::unmarshal(raw_packet)?),
308 };
309
310 offset += report.marshal_size();
311 reports.push(report);
312 }
313
314 Ok(ExtendedReport {
315 sender_ssrc,
316 reports,
317 })
318 }
319}