xref: /webrtc/rtcp/src/extended_report/dlrr.rs (revision 5d8fe953)
1 use super::*;
2 
3 const DLRR_REPORT_LENGTH: u16 = 12;
4 
5 /// DLRRReport encodes a single report inside a DLRRReportBlock.
6 #[derive(Debug, Default, PartialEq, Eq, Clone)]
7 pub struct DLRRReport {
8     pub ssrc: u32,
9     pub last_rr: u32,
10     pub dlrr: u32,
11 }
12 
13 impl fmt::Display for DLRRReport {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result14     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15         write!(f, "{self:?}")
16     }
17 }
18 
19 /// DLRRReportBlock encodes a DLRR Report Block as described in
20 /// RFC 3611 section 4.5.
21 ///
22 ///  0                   1                   2                   3
23 ///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
24 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25 /// |     BT=5      |   reserved    |         block length          |
26 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
27 /// |                 SSRC_1 (ssrc of first receiver)               | sub-
28 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
29 /// |                         last RR (LRR)                         |   1
30 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 /// |                   delay since last RR (DLRR)                  |
32 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
33 /// |                 SSRC_2 (ssrc of second receiver)              | sub-
34 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
35 /// :                               ...                             :   2
36 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
37 #[derive(Debug, Default, PartialEq, Eq, Clone)]
38 pub struct DLRRReportBlock {
39     pub reports: Vec<DLRRReport>,
40 }
41 
42 impl fmt::Display for DLRRReportBlock {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result43     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44         write!(f, "{self:?}")
45     }
46 }
47 
48 impl DLRRReportBlock {
xr_header(&self) -> XRHeader49     pub fn xr_header(&self) -> XRHeader {
50         XRHeader {
51             block_type: BlockType::DLRR,
52             type_specific: 0,
53             block_length: (self.raw_size() / 4 - 1) as u16,
54         }
55     }
56 }
57 
58 impl Packet for DLRRReportBlock {
header(&self) -> Header59     fn header(&self) -> Header {
60         Header::default()
61     }
62 
63     /// destination_ssrc returns an array of ssrc values that this report block refers to.
destination_ssrc(&self) -> Vec<u32>64     fn destination_ssrc(&self) -> Vec<u32> {
65         let mut ssrc = Vec::with_capacity(self.reports.len());
66         for r in &self.reports {
67             ssrc.push(r.ssrc);
68         }
69         ssrc
70     }
71 
raw_size(&self) -> usize72     fn raw_size(&self) -> usize {
73         XR_HEADER_LENGTH + self.reports.len() * 4 * 3
74     }
75 
as_any(&self) -> &(dyn Any + Send + Sync)76     fn as_any(&self) -> &(dyn Any + Send + Sync) {
77         self
78     }
equal(&self, other: &(dyn Packet + Send + Sync)) -> bool79     fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
80         other
81             .as_any()
82             .downcast_ref::<DLRRReportBlock>()
83             .map_or(false, |a| self == a)
84     }
cloned(&self) -> Box<dyn Packet + Send + Sync>85     fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
86         Box::new(self.clone())
87     }
88 }
89 
90 impl MarshalSize for DLRRReportBlock {
marshal_size(&self) -> usize91     fn marshal_size(&self) -> usize {
92         self.raw_size()
93     }
94 }
95 
96 impl Marshal for DLRRReportBlock {
97     /// marshal_to encodes the DLRRReportBlock in binary
marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>98     fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
99         if buf.remaining_mut() < self.marshal_size() {
100             return Err(error::Error::BufferTooShort.into());
101         }
102 
103         let h = self.xr_header();
104         let n = h.marshal_to(buf)?;
105         buf = &mut buf[n..];
106 
107         for rep in &self.reports {
108             buf.put_u32(rep.ssrc);
109             buf.put_u32(rep.last_rr);
110             buf.put_u32(rep.dlrr);
111         }
112 
113         Ok(self.marshal_size())
114     }
115 }
116 
117 impl Unmarshal for DLRRReportBlock {
118     /// Unmarshal decodes the DLRRReportBlock from binary
unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,119     fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
120     where
121         Self: Sized,
122         B: Buf,
123     {
124         if raw_packet.remaining() < XR_HEADER_LENGTH {
125             return Err(error::Error::PacketTooShort.into());
126         }
127 
128         let xr_header = XRHeader::unmarshal(raw_packet)?;
129         let block_length = xr_header.block_length * 4;
130         if block_length % DLRR_REPORT_LENGTH != 0 || raw_packet.remaining() < block_length as usize
131         {
132             return Err(error::Error::PacketTooShort.into());
133         }
134 
135         let mut offset = 0;
136         let mut reports = vec![];
137         while offset < block_length {
138             let ssrc = raw_packet.get_u32();
139             let last_rr = raw_packet.get_u32();
140             let dlrr = raw_packet.get_u32();
141             reports.push(DLRRReport {
142                 ssrc,
143                 last_rr,
144                 dlrr,
145             });
146             offset += DLRR_REPORT_LENGTH;
147         }
148 
149         Ok(DLRRReportBlock { reports })
150     }
151 }
152