xref: /webrtc/rtcp/src/extended_report/rle.rs (revision 5d8fe953)
1 use super::*;
2 
3 const RLE_REPORT_BLOCK_MIN_LENGTH: u16 = 8;
4 
5 /// ChunkType enumerates the three kinds of chunks described in RFC 3611 section 4.1.
6 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
7 pub enum ChunkType {
8     RunLength = 0,
9     BitVector = 1,
10     TerminatingNull = 2,
11 }
12 
13 /// Chunk as defined in RFC 3611, section 4.1. These represent information
14 /// about packet losses and packet duplication. They have three representations:
15 ///
16 /// Run Length Chunk:
17 ///
18 ///   0                   1
19 ///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
20 ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21 ///  |C|R|        run length         |
22 ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23 ///
24 /// Bit Vector Chunk:
25 ///
26 ///   0                   1
27 ///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
28 ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 ///  |C|        bit vector           |
30 ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 ///
32 /// Terminating Null Chunk:
33 ///
34 ///   0                   1
35 ///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
36 ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 ///  |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|
38 ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 #[derive(Debug, Default, PartialEq, Eq, Clone)]
40 pub struct Chunk(pub u16);
41 
42 impl fmt::Display for Chunk {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result43     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44         match self.chunk_type() {
45             ChunkType::RunLength => {
46                 let run_type = self.run_type().unwrap_or(0);
47                 write!(f, "[RunLength type={}, length={}]", run_type, self.value())
48             }
49             ChunkType::BitVector => write!(f, "[BitVector {:#b}", self.value()),
50             ChunkType::TerminatingNull => write!(f, "[TerminatingNull]"),
51         }
52     }
53 }
54 impl Chunk {
55     /// chunk_type returns the ChunkType that this Chunk represents
chunk_type(&self) -> ChunkType56     pub fn chunk_type(&self) -> ChunkType {
57         if self.0 == 0 {
58             ChunkType::TerminatingNull
59         } else if (self.0 >> 15) == 0 {
60             ChunkType::RunLength
61         } else {
62             ChunkType::BitVector
63         }
64     }
65 
66     /// run_type returns the run_type that this Chunk represents. It is
67     /// only valid if ChunkType is RunLengthChunkType.
run_type(&self) -> error::Result<u8>68     pub fn run_type(&self) -> error::Result<u8> {
69         if self.chunk_type() != ChunkType::RunLength {
70             Err(error::Error::WrongChunkType)
71         } else {
72             Ok((self.0 >> 14) as u8 & 0x01)
73         }
74     }
75 
76     /// value returns the value represented in this Chunk
value(&self) -> u1677     pub fn value(&self) -> u16 {
78         match self.chunk_type() {
79             ChunkType::RunLength => self.0 & 0x3FFF,
80             ChunkType::BitVector => self.0 & 0x7FFF,
81             ChunkType::TerminatingNull => 0,
82         }
83     }
84 }
85 
86 /// RleReportBlock defines the common structure used by both
87 /// Loss RLE report blocks (RFC 3611 §4.1) and Duplicate RLE
88 /// report blocks (RFC 3611 §4.2).
89 ///
90 ///  0                   1                   2                   3
91 ///  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
92 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 /// |  BT = 1 or 2  | rsvd. |   t   |         block length          |
94 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 /// |                        ssrc of source                         |
96 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 /// |          begin_seq            |             end_seq           |
98 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 /// |          chunk 1              |             chunk 2           |
100 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101 /// :                              ...                              :
102 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 /// |          chunk n-1            |             chunk n           |
104 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105 #[derive(Debug, Default, PartialEq, Eq, Clone)]
106 pub struct RLEReportBlock {
107     //not included in marshal/unmarshal
108     pub is_loss_rle: bool,
109     pub t: u8,
110 
111     //marshal/unmarshal
112     pub ssrc: u32,
113     pub begin_seq: u16,
114     pub end_seq: u16,
115     pub chunks: Vec<Chunk>,
116 }
117 
118 /// LossRLEReportBlock is used to report information about packet
119 /// losses, as described in RFC 3611, section 4.1
120 /// make sure to set is_loss_rle = true
121 pub type LossRLEReportBlock = RLEReportBlock;
122 
123 /// DuplicateRLEReportBlock is used to report information about packet
124 /// duplication, as described in RFC 3611, section 4.1
125 /// make sure to set is_loss_rle = false
126 pub type DuplicateRLEReportBlock = RLEReportBlock;
127 
128 impl RLEReportBlock {
xr_header(&self) -> XRHeader129     pub fn xr_header(&self) -> XRHeader {
130         XRHeader {
131             block_type: if self.is_loss_rle {
132                 BlockType::LossRLE
133             } else {
134                 BlockType::DuplicateRLE
135             },
136             type_specific: self.t & 0x0F,
137             block_length: (self.raw_size() / 4 - 1) as u16,
138         }
139     }
140 }
141 
142 impl fmt::Display for RLEReportBlock {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result143     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144         write!(f, "{self:?}")
145     }
146 }
147 
148 impl Packet for RLEReportBlock {
header(&self) -> Header149     fn header(&self) -> Header {
150         Header::default()
151     }
152 
153     /// destination_ssrc returns an array of ssrc values that this report block refers to.
destination_ssrc(&self) -> Vec<u32>154     fn destination_ssrc(&self) -> Vec<u32> {
155         vec![self.ssrc]
156     }
157 
raw_size(&self) -> usize158     fn raw_size(&self) -> usize {
159         XR_HEADER_LENGTH + RLE_REPORT_BLOCK_MIN_LENGTH as usize + self.chunks.len() * 2
160     }
161 
as_any(&self) -> &(dyn Any + Send + Sync)162     fn as_any(&self) -> &(dyn Any + Send + Sync) {
163         self
164     }
equal(&self, other: &(dyn Packet + Send + Sync)) -> bool165     fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
166         other
167             .as_any()
168             .downcast_ref::<RLEReportBlock>()
169             .map_or(false, |a| self == a)
170     }
cloned(&self) -> Box<dyn Packet + Send + Sync>171     fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
172         Box::new(self.clone())
173     }
174 }
175 
176 impl MarshalSize for RLEReportBlock {
marshal_size(&self) -> usize177     fn marshal_size(&self) -> usize {
178         self.raw_size()
179     }
180 }
181 
182 impl Marshal for RLEReportBlock {
183     /// marshal_to encodes the RLEReportBlock in binary
marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>184     fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
185         if buf.remaining_mut() < self.marshal_size() {
186             return Err(error::Error::BufferTooShort.into());
187         }
188 
189         let h = self.xr_header();
190         let n = h.marshal_to(buf)?;
191         buf = &mut buf[n..];
192 
193         buf.put_u32(self.ssrc);
194         buf.put_u16(self.begin_seq);
195         buf.put_u16(self.end_seq);
196         for chunk in &self.chunks {
197             buf.put_u16(chunk.0);
198         }
199 
200         Ok(self.marshal_size())
201     }
202 }
203 
204 impl Unmarshal for RLEReportBlock {
205     /// Unmarshal decodes the RLEReportBlock from binary
unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,206     fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
207     where
208         Self: Sized,
209         B: Buf,
210     {
211         if raw_packet.remaining() < XR_HEADER_LENGTH {
212             return Err(error::Error::PacketTooShort.into());
213         }
214 
215         let xr_header = XRHeader::unmarshal(raw_packet)?;
216         let block_length = xr_header.block_length * 4;
217         if block_length < RLE_REPORT_BLOCK_MIN_LENGTH
218             || (block_length - RLE_REPORT_BLOCK_MIN_LENGTH) % 2 != 0
219             || raw_packet.remaining() < block_length as usize
220         {
221             return Err(error::Error::PacketTooShort.into());
222         }
223 
224         let is_loss_rle = xr_header.block_type == BlockType::LossRLE;
225         let t = xr_header.type_specific & 0x0F;
226 
227         let ssrc = raw_packet.get_u32();
228         let begin_seq = raw_packet.get_u16();
229         let end_seq = raw_packet.get_u16();
230 
231         let remaining = block_length - RLE_REPORT_BLOCK_MIN_LENGTH;
232         let mut chunks = vec![];
233         for _ in 0..remaining / 2 {
234             chunks.push(Chunk(raw_packet.get_u16()));
235         }
236 
237         Ok(RLEReportBlock {
238             is_loss_rle,
239             t,
240             ssrc,
241             begin_seq,
242             end_seq,
243             chunks,
244         })
245     }
246 }
247