rtc_rtcp/extended_report/
mod.rs1#[cfg(test)]
2mod extended_report_test;
3
4pub mod dlrr;
5pub mod prt;
6pub mod rle;
7pub mod rrt;
8pub mod ssr;
9pub mod unknown;
10pub mod vm;
11
12pub use dlrr::{DLRRReport, DLRRReportBlock};
13pub use prt::PacketReceiptTimesReportBlock;
14pub use rle::{Chunk, ChunkType, DuplicateRLEReportBlock, LossRLEReportBlock, RLEReportBlock};
15pub use rrt::ReceiverReferenceTimeReportBlock;
16pub use ssr::{StatisticsSummaryReportBlock, TTLorHopLimitType};
17pub use unknown::UnknownReportBlock;
18pub use vm::VoIPMetricsReportBlock;
19
20use crate::Packet;
21use crate::header::{HEADER_LENGTH, Header, PacketType, SSRC_LENGTH};
22use crate::util::{get_padding_size, put_padding};
23use bytes::{Buf, BufMut, Bytes};
24use shared::{
25 error::{Error, Result},
26 marshal::{Marshal, MarshalSize, Unmarshal},
27};
28use std::any::Any;
29use std::fmt;
30
31const XR_HEADER_LENGTH: usize = 4;
32
33#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
36pub enum BlockType {
37 #[default]
38 Unknown = 0,
39 LossRLE = 1, DuplicateRLE = 2, PacketReceiptTimes = 3, ReceiverReferenceTime = 4, DLRR = 5, StatisticsSummary = 6, VoIPMetrics = 7, }
47
48impl From<u8> for BlockType {
49 fn from(v: u8) -> Self {
50 match v {
51 1 => BlockType::LossRLE,
52 2 => BlockType::DuplicateRLE,
53 3 => BlockType::PacketReceiptTimes,
54 4 => BlockType::ReceiverReferenceTime,
55 5 => BlockType::DLRR,
56 6 => BlockType::StatisticsSummary,
57 7 => BlockType::VoIPMetrics,
58 _ => BlockType::Unknown,
59 }
60 }
61}
62
63impl fmt::Display for BlockType {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 let s = match *self {
67 BlockType::LossRLE => "LossRLEReportBlockType",
68 BlockType::DuplicateRLE => "DuplicateRLEReportBlockType",
69 BlockType::PacketReceiptTimes => "PacketReceiptTimesReportBlockType",
70 BlockType::ReceiverReferenceTime => "ReceiverReferenceTimeReportBlockType",
71 BlockType::DLRR => "DLRRReportBlockType",
72 BlockType::StatisticsSummary => "StatisticsSummaryReportBlockType",
73 BlockType::VoIPMetrics => "VoIPMetricsReportBlockType",
74 _ => "UnknownReportBlockType",
75 };
76 write!(f, "{s}")
77 }
78}
79
80pub type TypeSpecificField = u8;
85
86#[derive(Debug, Default, PartialEq, Eq, Clone)]
92pub struct XRHeader {
93 pub block_type: BlockType,
94 pub type_specific: TypeSpecificField,
95 pub block_length: u16,
96}
97
98impl MarshalSize for XRHeader {
99 fn marshal_size(&self) -> usize {
100 XR_HEADER_LENGTH
101 }
102}
103
104impl Marshal for XRHeader {
105 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
107 if buf.remaining_mut() < XR_HEADER_LENGTH {
108 return Err(Error::BufferTooShort);
109 }
110
111 buf.put_u8(self.block_type as u8);
112 buf.put_u8(self.type_specific);
113 buf.put_u16(self.block_length);
114
115 Ok(XR_HEADER_LENGTH)
116 }
117}
118
119impl Unmarshal for XRHeader {
120 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
122 where
123 Self: Sized,
124 B: Buf,
125 {
126 if raw_packet.remaining() < XR_HEADER_LENGTH {
127 return Err(Error::PacketTooShort);
128 }
129
130 let block_type: BlockType = raw_packet.get_u8().into();
131 let type_specific = raw_packet.get_u8();
132 let block_length = raw_packet.get_u16();
133
134 Ok(XRHeader {
135 block_type,
136 type_specific,
137 block_length,
138 })
139 }
140}
141#[derive(Debug, PartialEq, Default, Clone)]
157pub struct ExtendedReport {
158 pub sender_ssrc: u32,
159 pub reports: Vec<Box<dyn Packet>>,
160}
161
162impl fmt::Display for ExtendedReport {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 write!(f, "{self:?}")
165 }
166}
167
168impl Packet for ExtendedReport {
169 fn header(&self) -> Header {
171 Header {
172 padding: get_padding_size(self.raw_size()) != 0,
173 count: 0,
174 packet_type: PacketType::ExtendedReport,
175 length: ((self.marshal_size() / 4) - 1) as u16,
176 }
177 }
178
179 fn destination_ssrc(&self) -> Vec<u32> {
181 let mut ssrc = vec![];
182 for p in &self.reports {
183 ssrc.extend(p.destination_ssrc());
184 }
185 ssrc
186 }
187
188 fn raw_size(&self) -> usize {
189 let mut reps_length = 0;
190 for rep in &self.reports {
191 reps_length += rep.marshal_size();
192 }
193 HEADER_LENGTH + SSRC_LENGTH + reps_length
194 }
195
196 fn as_any(&self) -> &dyn Any {
197 self
198 }
199
200 fn equal(&self, other: &dyn Packet) -> bool {
201 other.as_any().downcast_ref::<ExtendedReport>() == Some(self)
202 }
203
204 fn cloned(&self) -> Box<dyn Packet> {
205 Box::new(self.clone())
206 }
207}
208
209impl MarshalSize for ExtendedReport {
210 fn marshal_size(&self) -> usize {
211 let l = self.raw_size();
212 l + get_padding_size(l)
214 }
215}
216
217impl Marshal for ExtendedReport {
218 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
220 if buf.remaining_mut() < self.marshal_size() {
221 return Err(Error::BufferTooShort);
222 }
223
224 let h = self.header();
225 let n = h.marshal_to(buf)?;
226 buf = &mut buf[n..];
227
228 buf.put_u32(self.sender_ssrc);
229
230 for report in &self.reports {
231 let n = report.marshal_to(buf)?;
232 buf = &mut buf[n..];
233 }
234
235 if h.padding {
236 put_padding(buf, self.raw_size());
237 }
238
239 Ok(self.marshal_size())
240 }
241}
242
243impl Unmarshal for ExtendedReport {
244 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
246 where
247 Self: Sized,
248 B: Buf,
249 {
250 let raw_packet_len = raw_packet.remaining();
251 if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
252 return Err(Error::PacketTooShort);
253 }
254
255 let header = Header::unmarshal(raw_packet)?;
256 if header.packet_type != PacketType::ExtendedReport {
257 return Err(Error::WrongType);
258 }
259
260 let sender_ssrc = raw_packet.get_u32();
261
262 let mut offset = HEADER_LENGTH + SSRC_LENGTH;
263 let mut reports = vec![];
264 while raw_packet.remaining() > 0 {
265 if offset + XR_HEADER_LENGTH > raw_packet_len {
266 return Err(Error::PacketTooShort);
267 }
268
269 let block_type: BlockType = raw_packet.chunk()[0].into();
270 let report: Box<dyn Packet> = match block_type {
271 BlockType::LossRLE => Box::new(LossRLEReportBlock::unmarshal(raw_packet)?),
272 BlockType::DuplicateRLE => {
273 Box::new(DuplicateRLEReportBlock::unmarshal(raw_packet)?)
274 }
275 BlockType::PacketReceiptTimes => {
276 Box::new(PacketReceiptTimesReportBlock::unmarshal(raw_packet)?)
277 }
278 BlockType::ReceiverReferenceTime => {
279 Box::new(ReceiverReferenceTimeReportBlock::unmarshal(raw_packet)?)
280 }
281 BlockType::DLRR => Box::new(DLRRReportBlock::unmarshal(raw_packet)?),
282 BlockType::StatisticsSummary => {
283 Box::new(StatisticsSummaryReportBlock::unmarshal(raw_packet)?)
284 }
285 BlockType::VoIPMetrics => Box::new(VoIPMetricsReportBlock::unmarshal(raw_packet)?),
286 _ => Box::new(UnknownReportBlock::unmarshal(raw_packet)?),
287 };
288
289 offset += report.marshal_size();
290 reports.push(report);
291 }
292
293 Ok(ExtendedReport {
294 sender_ssrc,
295 reports,
296 })
297 }
298}