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