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)]
43pub enum BlockType {
44 #[default]
45 Unknown = 0,
47 LossRLE = 1, DuplicateRLE = 2, PacketReceiptTimes = 3, ReceiverReferenceTime = 4, DLRR = 5, StatisticsSummary = 6, VoIPMetrics = 7, }
62
63impl From<u8> for BlockType {
64 fn from(v: u8) -> Self {
65 match v {
66 1 => BlockType::LossRLE,
67 2 => BlockType::DuplicateRLE,
68 3 => BlockType::PacketReceiptTimes,
69 4 => BlockType::ReceiverReferenceTime,
70 5 => BlockType::DLRR,
71 6 => BlockType::StatisticsSummary,
72 7 => BlockType::VoIPMetrics,
73 _ => BlockType::Unknown,
74 }
75 }
76}
77
78impl fmt::Display for BlockType {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 let s = match *self {
82 BlockType::LossRLE => "LossRLEReportBlockType",
83 BlockType::DuplicateRLE => "DuplicateRLEReportBlockType",
84 BlockType::PacketReceiptTimes => "PacketReceiptTimesReportBlockType",
85 BlockType::ReceiverReferenceTime => "ReceiverReferenceTimeReportBlockType",
86 BlockType::DLRR => "DLRRReportBlockType",
87 BlockType::StatisticsSummary => "StatisticsSummaryReportBlockType",
88 BlockType::VoIPMetrics => "VoIPMetricsReportBlockType",
89 _ => "UnknownReportBlockType",
90 };
91 write!(f, "{s}")
92 }
93}
94
95pub type TypeSpecificField = u8;
100
101#[derive(Debug, Default, PartialEq, Eq, Clone)]
107pub struct XRHeader {
108 pub block_type: BlockType,
110 pub type_specific: TypeSpecificField,
112 pub block_length: u16,
114}
115
116impl MarshalSize for XRHeader {
117 fn marshal_size(&self) -> usize {
118 XR_HEADER_LENGTH
119 }
120}
121
122impl Marshal for XRHeader {
123 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
125 if buf.remaining_mut() < XR_HEADER_LENGTH {
126 return Err(Error::BufferTooShort);
127 }
128
129 buf.put_u8(self.block_type as u8);
130 buf.put_u8(self.type_specific);
131 buf.put_u16(self.block_length);
132
133 Ok(XR_HEADER_LENGTH)
134 }
135}
136
137impl Unmarshal for XRHeader {
138 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
140 where
141 Self: Sized,
142 B: Buf,
143 {
144 if raw_packet.remaining() < XR_HEADER_LENGTH {
145 return Err(Error::PacketTooShort);
146 }
147
148 let block_type: BlockType = raw_packet.get_u8().into();
149 let type_specific = raw_packet.get_u8();
150 let block_length = raw_packet.get_u16();
151
152 Ok(XRHeader {
153 block_type,
154 type_specific,
155 block_length,
156 })
157 }
158}
159#[derive(Debug, PartialEq, Default, Clone)]
175pub struct ExtendedReport {
176 pub sender_ssrc: u32,
178 pub reports: Vec<Box<dyn Packet>>,
180}
181
182impl fmt::Display for ExtendedReport {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 write!(f, "{self:?}")
185 }
186}
187
188impl Packet for ExtendedReport {
189 fn header(&self) -> Header {
191 Header {
192 padding: get_padding_size(self.raw_size()) != 0,
193 count: 0,
194 packet_type: PacketType::ExtendedReport,
195 length: ((self.marshal_size() / 4) - 1) as u16,
196 }
197 }
198
199 fn destination_ssrc(&self) -> Vec<u32> {
201 let mut ssrc = vec![];
202 for p in &self.reports {
203 ssrc.extend(p.destination_ssrc());
204 }
205 ssrc
206 }
207
208 fn raw_size(&self) -> usize {
209 let mut reps_length = 0;
210 for rep in &self.reports {
211 reps_length += rep.marshal_size();
212 }
213 HEADER_LENGTH + SSRC_LENGTH + reps_length
214 }
215
216 fn as_any(&self) -> &dyn Any {
217 self
218 }
219
220 fn equal(&self, other: &dyn Packet) -> bool {
221 other.as_any().downcast_ref::<ExtendedReport>() == Some(self)
222 }
223
224 fn cloned(&self) -> Box<dyn Packet> {
225 Box::new(self.clone())
226 }
227}
228
229impl MarshalSize for ExtendedReport {
230 fn marshal_size(&self) -> usize {
231 let l = self.raw_size();
232 l + get_padding_size(l)
234 }
235}
236
237impl Marshal for ExtendedReport {
238 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
240 if buf.remaining_mut() < self.marshal_size() {
241 return Err(Error::BufferTooShort);
242 }
243
244 let h = self.header();
245 let n = h.marshal_to(buf)?;
246 buf = &mut buf[n..];
247
248 buf.put_u32(self.sender_ssrc);
249
250 for report in &self.reports {
251 let n = report.marshal_to(buf)?;
252 buf = &mut buf[n..];
253 }
254
255 if h.padding {
256 put_padding(buf, self.raw_size());
257 }
258
259 Ok(self.marshal_size())
260 }
261}
262
263impl Unmarshal for ExtendedReport {
264 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
266 where
267 Self: Sized,
268 B: Buf,
269 {
270 let raw_packet_len = raw_packet.remaining();
271 if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
272 return Err(Error::PacketTooShort);
273 }
274
275 let header = Header::unmarshal(raw_packet)?;
276 if header.packet_type != PacketType::ExtendedReport {
277 return Err(Error::WrongType);
278 }
279
280 let sender_ssrc = raw_packet.get_u32();
281
282 let mut offset = HEADER_LENGTH + SSRC_LENGTH;
283 let mut reports = vec![];
284 while raw_packet.remaining() > 0 {
285 if offset + XR_HEADER_LENGTH > raw_packet_len {
286 return Err(Error::PacketTooShort);
287 }
288
289 let block_type: BlockType = raw_packet.chunk()[0].into();
290 let report: Box<dyn Packet> = match block_type {
291 BlockType::LossRLE => Box::new(LossRLEReportBlock::unmarshal(raw_packet)?),
292 BlockType::DuplicateRLE => {
293 Box::new(DuplicateRLEReportBlock::unmarshal(raw_packet)?)
294 }
295 BlockType::PacketReceiptTimes => {
296 Box::new(PacketReceiptTimesReportBlock::unmarshal(raw_packet)?)
297 }
298 BlockType::ReceiverReferenceTime => {
299 Box::new(ReceiverReferenceTimeReportBlock::unmarshal(raw_packet)?)
300 }
301 BlockType::DLRR => Box::new(DLRRReportBlock::unmarshal(raw_packet)?),
302 BlockType::StatisticsSummary => {
303 Box::new(StatisticsSummaryReportBlock::unmarshal(raw_packet)?)
304 }
305 BlockType::VoIPMetrics => Box::new(VoIPMetricsReportBlock::unmarshal(raw_packet)?),
306 _ => Box::new(UnknownReportBlock::unmarshal(raw_packet)?),
307 };
308
309 offset += report.marshal_size();
310 reports.push(report);
311 }
312
313 Ok(ExtendedReport {
314 sender_ssrc,
315 reports,
316 })
317 }
318}