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