rtc_rtcp/extended_report/
ssr.rs1use super::*;
2
3const SSR_REPORT_BLOCK_LENGTH: u16 = 4 + 2 * 2 + 4 * 6 + 4;
4
5#[derive(Debug, Default, PartialEq, Eq, Clone)]
32pub struct StatisticsSummaryReportBlock {
33 pub loss_reports: bool,
36 pub duplicate_reports: bool,
38 pub jitter_reports: bool,
40 pub ttl_or_hop_limit: TTLorHopLimitType,
42
43 pub ssrc: u32,
46 pub begin_seq: u16,
48 pub end_seq: u16,
50 pub lost_packets: u32,
52 pub dup_packets: u32,
54 pub min_jitter: u32,
56 pub max_jitter: u32,
58 pub mean_jitter: u32,
60 pub dev_jitter: u32,
62 pub min_ttl_or_hl: u8,
64 pub max_ttl_or_hl: u8,
66 pub mean_ttl_or_hl: u8,
68 pub dev_ttl_or_hl: u8,
70}
71
72impl fmt::Display for StatisticsSummaryReportBlock {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 write!(f, "{self:?}")
75 }
76}
77
78#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
81pub enum TTLorHopLimitType {
82 #[default]
83 Missing = 0,
85 IPv4 = 1,
87 IPv6 = 2,
89}
90
91impl From<u8> for TTLorHopLimitType {
92 fn from(v: u8) -> Self {
93 match v {
94 1 => TTLorHopLimitType::IPv4,
95 2 => TTLorHopLimitType::IPv6,
96 _ => TTLorHopLimitType::Missing,
97 }
98 }
99}
100
101impl fmt::Display for TTLorHopLimitType {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 let s = match *self {
104 TTLorHopLimitType::Missing => "[ToH Missing]",
105 TTLorHopLimitType::IPv4 => "[ToH = IPv4]",
106 TTLorHopLimitType::IPv6 => "[ToH = IPv6]",
107 };
108 write!(f, "{s}")
109 }
110}
111
112impl StatisticsSummaryReportBlock {
113 pub fn xr_header(&self) -> XRHeader {
115 let mut type_specific = 0x00;
116 if self.loss_reports {
117 type_specific |= 0x80;
118 }
119 if self.duplicate_reports {
120 type_specific |= 0x40;
121 }
122 if self.jitter_reports {
123 type_specific |= 0x20;
124 }
125 type_specific |= (self.ttl_or_hop_limit as u8 & 0x03) << 3;
126
127 XRHeader {
128 block_type: BlockType::StatisticsSummary,
129 type_specific,
130 block_length: (self.raw_size() / 4 - 1) as u16,
131 }
132 }
133}
134
135impl Packet for StatisticsSummaryReportBlock {
136 fn header(&self) -> Header {
137 Header::default()
138 }
139
140 fn destination_ssrc(&self) -> Vec<u32> {
142 vec![self.ssrc]
143 }
144
145 fn raw_size(&self) -> usize {
146 XR_HEADER_LENGTH + SSR_REPORT_BLOCK_LENGTH as usize
147 }
148
149 fn as_any(&self) -> &dyn Any {
150 self
151 }
152 fn equal(&self, other: &dyn Packet) -> bool {
153 other
154 .as_any()
155 .downcast_ref::<StatisticsSummaryReportBlock>()
156 == Some(self)
157 }
158 fn cloned(&self) -> Box<dyn Packet> {
159 Box::new(self.clone())
160 }
161}
162
163impl MarshalSize for StatisticsSummaryReportBlock {
164 fn marshal_size(&self) -> usize {
165 self.raw_size()
166 }
167}
168
169impl Marshal for StatisticsSummaryReportBlock {
170 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
172 if buf.remaining_mut() < self.marshal_size() {
173 return Err(Error::BufferTooShort);
174 }
175
176 let h = self.xr_header();
177 let n = h.marshal_to(buf)?;
178 buf = &mut buf[n..];
179
180 buf.put_u32(self.ssrc);
181 buf.put_u16(self.begin_seq);
182 buf.put_u16(self.end_seq);
183 buf.put_u32(self.lost_packets);
184 buf.put_u32(self.dup_packets);
185 buf.put_u32(self.min_jitter);
186 buf.put_u32(self.max_jitter);
187 buf.put_u32(self.mean_jitter);
188 buf.put_u32(self.dev_jitter);
189 buf.put_u8(self.min_ttl_or_hl);
190 buf.put_u8(self.max_ttl_or_hl);
191 buf.put_u8(self.mean_ttl_or_hl);
192 buf.put_u8(self.dev_ttl_or_hl);
193
194 Ok(self.marshal_size())
195 }
196}
197
198impl Unmarshal for StatisticsSummaryReportBlock {
199 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
201 where
202 Self: Sized,
203 B: Buf,
204 {
205 if raw_packet.remaining() < XR_HEADER_LENGTH {
206 return Err(Error::PacketTooShort);
207 }
208
209 let xr_header = XRHeader::unmarshal(raw_packet)?;
210 let block_length = match xr_header.block_length.checked_mul(4) {
211 Some(length) => length,
212 None => return Err(Error::InvalidBlockSize),
213 };
214 if block_length != SSR_REPORT_BLOCK_LENGTH || raw_packet.remaining() < block_length as usize
215 {
216 return Err(Error::PacketTooShort);
217 }
218
219 let loss_reports = xr_header.type_specific & 0x80 != 0;
220 let duplicate_reports = xr_header.type_specific & 0x40 != 0;
221 let jitter_reports = xr_header.type_specific & 0x20 != 0;
222 let ttl_or_hop_limit: TTLorHopLimitType = ((xr_header.type_specific & 0x18) >> 3).into();
223
224 let ssrc = raw_packet.get_u32();
225 let begin_seq = raw_packet.get_u16();
226 let end_seq = raw_packet.get_u16();
227 let lost_packets = raw_packet.get_u32();
228 let dup_packets = raw_packet.get_u32();
229 let min_jitter = raw_packet.get_u32();
230 let max_jitter = raw_packet.get_u32();
231 let mean_jitter = raw_packet.get_u32();
232 let dev_jitter = raw_packet.get_u32();
233 let min_ttl_or_hl = raw_packet.get_u8();
234 let max_ttl_or_hl = raw_packet.get_u8();
235 let mean_ttl_or_hl = raw_packet.get_u8();
236 let dev_ttl_or_hl = raw_packet.get_u8();
237
238 Ok(StatisticsSummaryReportBlock {
239 loss_reports,
240 duplicate_reports,
241 jitter_reports,
242 ttl_or_hop_limit,
243
244 ssrc,
245 begin_seq,
246 end_seq,
247 lost_packets,
248 dup_packets,
249 min_jitter,
250 max_jitter,
251 mean_jitter,
252 dev_jitter,
253 min_ttl_or_hl,
254 max_ttl_or_hl,
255 mean_ttl_or_hl,
256 dev_ttl_or_hl,
257 })
258 }
259}