1use crate::protocol::ProtocolError;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct SenderReport {
28 pub interval_start_counter: u64,
29 pub interval_end_counter: u64,
30 pub interval_start_timestamp: u32,
31 pub interval_end_timestamp: u32,
32 pub interval_bytes_sent: u32,
33 pub cumulative_packets_sent: u64,
34 pub cumulative_bytes_sent: u64,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct ReceiverReport {
61 pub highest_counter: u64,
62 pub cumulative_packets_recv: u64,
63 pub cumulative_bytes_recv: u64,
64 pub timestamp_echo: u32,
65 pub dwell_time: u16,
66 pub max_burst_loss: u16,
67 pub mean_burst_loss: u16,
68 pub jitter: u32,
69 pub ecn_ce_count: u32,
70 pub owd_trend: i32,
71 pub burst_loss_count: u32,
72 pub cumulative_reorder_count: u32,
73 pub interval_packets_recv: u32,
74 pub interval_bytes_recv: u32,
75}
76
77impl SenderReport {
80 pub fn encode(&self) -> Vec<u8> {
82 let mut buf = Vec::with_capacity(48);
83 buf.push(0x01); buf.extend_from_slice(&[0u8; 3]); buf.extend_from_slice(&self.interval_start_counter.to_le_bytes());
86 buf.extend_from_slice(&self.interval_end_counter.to_le_bytes());
87 buf.extend_from_slice(&self.interval_start_timestamp.to_le_bytes());
88 buf.extend_from_slice(&self.interval_end_timestamp.to_le_bytes());
89 buf.extend_from_slice(&self.interval_bytes_sent.to_le_bytes());
90 buf.extend_from_slice(&self.cumulative_packets_sent.to_le_bytes());
91 buf.extend_from_slice(&self.cumulative_bytes_sent.to_le_bytes());
92 buf
93 }
94
95 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
99 if payload.len() < 47 {
100 return Err(ProtocolError::MessageTooShort {
101 expected: 47,
102 got: payload.len(),
103 });
104 }
105 let p = &payload[3..];
107 Ok(Self {
108 interval_start_counter: u64::from_le_bytes(p[0..8].try_into().unwrap()),
109 interval_end_counter: u64::from_le_bytes(p[8..16].try_into().unwrap()),
110 interval_start_timestamp: u32::from_le_bytes(p[16..20].try_into().unwrap()),
111 interval_end_timestamp: u32::from_le_bytes(p[20..24].try_into().unwrap()),
112 interval_bytes_sent: u32::from_le_bytes(p[24..28].try_into().unwrap()),
113 cumulative_packets_sent: u64::from_le_bytes(p[28..36].try_into().unwrap()),
114 cumulative_bytes_sent: u64::from_le_bytes(p[36..44].try_into().unwrap()),
115 })
116 }
117}
118
119impl ReceiverReport {
120 pub fn encode(&self) -> Vec<u8> {
122 let mut buf = Vec::with_capacity(68);
123 buf.push(0x02); buf.extend_from_slice(&[0u8; 3]); buf.extend_from_slice(&self.highest_counter.to_le_bytes());
126 buf.extend_from_slice(&self.cumulative_packets_recv.to_le_bytes());
127 buf.extend_from_slice(&self.cumulative_bytes_recv.to_le_bytes());
128 buf.extend_from_slice(&self.timestamp_echo.to_le_bytes());
129 buf.extend_from_slice(&self.dwell_time.to_le_bytes());
130 buf.extend_from_slice(&self.max_burst_loss.to_le_bytes());
131 buf.extend_from_slice(&self.mean_burst_loss.to_le_bytes());
132 buf.extend_from_slice(&[0u8; 2]); buf.extend_from_slice(&self.jitter.to_le_bytes());
134 buf.extend_from_slice(&self.ecn_ce_count.to_le_bytes());
135 buf.extend_from_slice(&self.owd_trend.to_le_bytes());
136 buf.extend_from_slice(&self.burst_loss_count.to_le_bytes());
137 buf.extend_from_slice(&self.cumulative_reorder_count.to_le_bytes());
138 buf.extend_from_slice(&self.interval_packets_recv.to_le_bytes());
139 buf.extend_from_slice(&self.interval_bytes_recv.to_le_bytes());
140 buf
141 }
142
143 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
147 if payload.len() < 67 {
148 return Err(ProtocolError::MessageTooShort {
149 expected: 67,
150 got: payload.len(),
151 });
152 }
153 let p = &payload[3..];
155 Ok(Self {
156 highest_counter: u64::from_le_bytes(p[0..8].try_into().unwrap()),
157 cumulative_packets_recv: u64::from_le_bytes(p[8..16].try_into().unwrap()),
158 cumulative_bytes_recv: u64::from_le_bytes(p[16..24].try_into().unwrap()),
159 timestamp_echo: u32::from_le_bytes(p[24..28].try_into().unwrap()),
160 dwell_time: u16::from_le_bytes(p[28..30].try_into().unwrap()),
161 max_burst_loss: u16::from_le_bytes(p[30..32].try_into().unwrap()),
162 mean_burst_loss: u16::from_le_bytes(p[32..34].try_into().unwrap()),
163 jitter: u32::from_le_bytes(p[36..40].try_into().unwrap()),
165 ecn_ce_count: u32::from_le_bytes(p[40..44].try_into().unwrap()),
166 owd_trend: i32::from_le_bytes(p[44..48].try_into().unwrap()),
167 burst_loss_count: u32::from_le_bytes(p[48..52].try_into().unwrap()),
168 cumulative_reorder_count: u32::from_le_bytes(p[52..56].try_into().unwrap()),
169 interval_packets_recv: u32::from_le_bytes(p[56..60].try_into().unwrap()),
170 interval_bytes_recv: u32::from_le_bytes(p[60..64].try_into().unwrap()),
171 })
172 }
173}
174
175use crate::protocol::{SessionReceiverReport, SessionSenderReport};
180
181impl From<&SenderReport> for SessionSenderReport {
182 fn from(r: &SenderReport) -> Self {
183 Self {
184 interval_start_counter: r.interval_start_counter,
185 interval_end_counter: r.interval_end_counter,
186 interval_start_timestamp: r.interval_start_timestamp,
187 interval_end_timestamp: r.interval_end_timestamp,
188 interval_bytes_sent: r.interval_bytes_sent,
189 cumulative_packets_sent: r.cumulative_packets_sent,
190 cumulative_bytes_sent: r.cumulative_bytes_sent,
191 }
192 }
193}
194
195impl From<&SessionSenderReport> for SenderReport {
196 fn from(r: &SessionSenderReport) -> Self {
197 Self {
198 interval_start_counter: r.interval_start_counter,
199 interval_end_counter: r.interval_end_counter,
200 interval_start_timestamp: r.interval_start_timestamp,
201 interval_end_timestamp: r.interval_end_timestamp,
202 interval_bytes_sent: r.interval_bytes_sent,
203 cumulative_packets_sent: r.cumulative_packets_sent,
204 cumulative_bytes_sent: r.cumulative_bytes_sent,
205 }
206 }
207}
208
209impl From<&ReceiverReport> for SessionReceiverReport {
210 fn from(r: &ReceiverReport) -> Self {
211 Self {
212 highest_counter: r.highest_counter,
213 cumulative_packets_recv: r.cumulative_packets_recv,
214 cumulative_bytes_recv: r.cumulative_bytes_recv,
215 timestamp_echo: r.timestamp_echo,
216 dwell_time: r.dwell_time,
217 max_burst_loss: r.max_burst_loss,
218 mean_burst_loss: r.mean_burst_loss,
219 jitter: r.jitter,
220 ecn_ce_count: r.ecn_ce_count,
221 owd_trend: r.owd_trend,
222 burst_loss_count: r.burst_loss_count,
223 cumulative_reorder_count: r.cumulative_reorder_count,
224 interval_packets_recv: r.interval_packets_recv,
225 interval_bytes_recv: r.interval_bytes_recv,
226 }
227 }
228}
229
230impl From<&SessionReceiverReport> for ReceiverReport {
231 fn from(r: &SessionReceiverReport) -> Self {
232 Self {
233 highest_counter: r.highest_counter,
234 cumulative_packets_recv: r.cumulative_packets_recv,
235 cumulative_bytes_recv: r.cumulative_bytes_recv,
236 timestamp_echo: r.timestamp_echo,
237 dwell_time: r.dwell_time,
238 max_burst_loss: r.max_burst_loss,
239 mean_burst_loss: r.mean_burst_loss,
240 jitter: r.jitter,
241 ecn_ce_count: r.ecn_ce_count,
242 owd_trend: r.owd_trend,
243 burst_loss_count: r.burst_loss_count,
244 cumulative_reorder_count: r.cumulative_reorder_count,
245 interval_packets_recv: r.interval_packets_recv,
246 interval_bytes_recv: r.interval_bytes_recv,
247 }
248 }
249}
250
251#[cfg(test)]
256mod tests {
257 use super::*;
258
259 fn sample_sender_report() -> SenderReport {
260 SenderReport {
261 interval_start_counter: 100,
262 interval_end_counter: 200,
263 interval_start_timestamp: 5000,
264 interval_end_timestamp: 6000,
265 interval_bytes_sent: 50_000,
266 cumulative_packets_sent: 10_000,
267 cumulative_bytes_sent: 5_000_000,
268 }
269 }
270
271 fn sample_receiver_report() -> ReceiverReport {
272 ReceiverReport {
273 highest_counter: 195,
274 cumulative_packets_recv: 9_500,
275 cumulative_bytes_recv: 4_750_000,
276 timestamp_echo: 5900,
277 dwell_time: 5,
278 max_burst_loss: 3,
279 mean_burst_loss: 384, jitter: 1200,
281 ecn_ce_count: 0,
282 owd_trend: -50,
283 burst_loss_count: 2,
284 cumulative_reorder_count: 10,
285 interval_packets_recv: 95,
286 interval_bytes_recv: 47_500,
287 }
288 }
289
290 #[test]
291 fn test_sender_report_encode_size() {
292 let sr = sample_sender_report();
293 let encoded = sr.encode();
294 assert_eq!(encoded.len(), 48);
295 assert_eq!(encoded[0], 0x01); }
297
298 #[test]
299 fn test_sender_report_roundtrip() {
300 let sr = sample_sender_report();
301 let encoded = sr.encode();
302 let decoded = SenderReport::decode(&encoded[1..]).unwrap();
304 assert_eq!(sr, decoded);
305 }
306
307 #[test]
308 fn test_sender_report_too_short() {
309 let result = SenderReport::decode(&[0u8; 10]);
310 assert!(result.is_err());
311 }
312
313 #[test]
314 fn test_receiver_report_encode_size() {
315 let rr = sample_receiver_report();
316 let encoded = rr.encode();
317 assert_eq!(encoded.len(), 68);
318 assert_eq!(encoded[0], 0x02); }
320
321 #[test]
322 fn test_receiver_report_roundtrip() {
323 let rr = sample_receiver_report();
324 let encoded = rr.encode();
325 let decoded = ReceiverReport::decode(&encoded[1..]).unwrap();
327 assert_eq!(rr, decoded);
328 }
329
330 #[test]
331 fn test_receiver_report_too_short() {
332 let result = ReceiverReport::decode(&[0u8; 10]);
333 assert!(result.is_err());
334 }
335
336 #[test]
337 fn test_sender_report_zero_values() {
338 let sr = SenderReport {
339 interval_start_counter: 0,
340 interval_end_counter: 0,
341 interval_start_timestamp: 0,
342 interval_end_timestamp: 0,
343 interval_bytes_sent: 0,
344 cumulative_packets_sent: 0,
345 cumulative_bytes_sent: 0,
346 };
347 let encoded = sr.encode();
348 let decoded = SenderReport::decode(&encoded[1..]).unwrap();
349 assert_eq!(sr, decoded);
350 }
351
352 #[test]
353 fn test_receiver_report_max_values() {
354 let rr = ReceiverReport {
355 highest_counter: u64::MAX,
356 cumulative_packets_recv: u64::MAX,
357 cumulative_bytes_recv: u64::MAX,
358 timestamp_echo: u32::MAX,
359 dwell_time: u16::MAX,
360 max_burst_loss: u16::MAX,
361 mean_burst_loss: u16::MAX,
362 jitter: u32::MAX,
363 ecn_ce_count: u32::MAX,
364 owd_trend: i32::MAX,
365 burst_loss_count: u32::MAX,
366 cumulative_reorder_count: u32::MAX,
367 interval_packets_recv: u32::MAX,
368 interval_bytes_recv: u32::MAX,
369 };
370 let encoded = rr.encode();
371 let decoded = ReceiverReport::decode(&encoded[1..]).unwrap();
372 assert_eq!(rr, decoded);
373 }
374
375 #[test]
376 fn test_receiver_report_negative_owd_trend() {
377 let rr = ReceiverReport {
378 owd_trend: -12345,
379 ..sample_receiver_report()
380 };
381 let encoded = rr.encode();
382 let decoded = ReceiverReport::decode(&encoded[1..]).unwrap();
383 assert_eq!(decoded.owd_trend, -12345);
384 }
385}