1use std::fmt;
2use crate::{Seq, RtpPacketBuilder};
3
4pub struct RtpReader<'a> {
6 buf: &'a [u8],
7}
8
9#[derive(Debug)]
11pub enum RtpReaderError {
12 BufferTooShort(usize),
14 UnsupportedVersion(u8),
16 HeadersTruncated {
18 header_len: usize,
21 buffer_len: usize,
24 },
25 PaddingLengthInvalid(u8),
29}
30
31impl<'a> RtpReader<'a> {
32 pub const MIN_HEADER_LEN: usize = 12;
34 const EXTENSION_HEADER_LEN: usize = 4;
35
36 pub fn new(b: &'a [u8]) -> Result<RtpReader<'_>, RtpReaderError> {
44 if b.len() < Self::MIN_HEADER_LEN {
45 return Err(RtpReaderError::BufferTooShort(b.len()));
46 }
47 let r = RtpReader { buf: b };
48 if r.version() != 2 {
49 return Err(RtpReaderError::UnsupportedVersion(r.version()));
50 }
51 if r.extension_flag() {
52 let extension_start = r.csrc_end() + Self::EXTENSION_HEADER_LEN;
53 if extension_start > b.len() {
54 return Err(RtpReaderError::HeadersTruncated {
55 header_len: extension_start,
56 buffer_len: b.len(),
57 });
58 }
59 let extension_end = extension_start + r.extension_len();
60 if extension_end > b.len() {
61 return Err(RtpReaderError::HeadersTruncated {
62 header_len: extension_end,
63 buffer_len: b.len(),
64 });
65 }
66 }
67 if r.payload_offset() > b.len() {
68 return Err(RtpReaderError::HeadersTruncated {
69 header_len: r.payload_offset(),
70 buffer_len: b.len(),
71 });
72 }
73 if r.padding_flag() {
74 let post_header_bytes = b.len() - r.payload_offset();
75 if post_header_bytes == 0 {
78 return Err(RtpReaderError::HeadersTruncated {
79 header_len: r.payload_offset(),
80 buffer_len: b.len() - 1,
81 });
82 }
83 let pad_len = r.padding_len()?;
84
85 if r.payload_offset() + pad_len as usize > b.len() {
86 return Err(RtpReaderError::PaddingLengthInvalid(pad_len));
87 }
88 }
89 Ok(r)
90 }
91
92 pub fn version(&self) -> u8 {
95 (self.buf[0] & 0b1100_0000) >> 6
96 }
97
98 fn padding_flag(&self) -> bool {
100 (self.buf[0] & 0b0010_0000) != 0
101 }
102 pub fn padding(&self) -> Option<u8> {
105 if self.padding_flag() {
106 Some(self.padding_len().unwrap())
107 } else {
108 None
109 }
110 }
111
112 fn extension_flag(&self) -> bool {
113 (self.buf[0] & 0b0001_0000) != 0
114 }
115 pub fn csrc_count(&self) -> u8 {
119 self.buf[0] & 0b0000_1111
120 }
121 pub fn mark(&self) -> bool {
123 (self.buf[1] & 0b1000_0000) != 0
124 }
125 pub fn payload_type(&self) -> u8 {
131 self.buf[1] & 0b0111_1111
132 }
133 pub fn sequence_number(&self) -> Seq {
143 Seq((self.buf[2] as u16) << 8 | (self.buf[3] as u16))
144 }
145 pub fn timestamp(&self) -> u32 {
154 (self.buf[4] as u32) << 24
155 | (self.buf[5] as u32) << 16
156 | (self.buf[6] as u32) << 8
157 | (self.buf[7] as u32)
158 }
159 pub fn ssrc(&self) -> u32 {
162 (self.buf[8] as u32) << 24
163 | (self.buf[9] as u32) << 16
164 | (self.buf[10] as u32) << 8
165 | (self.buf[11] as u32)
166 }
167 pub fn csrc(&self) -> impl Iterator<Item = u32> + '_ {
170 self.buf[Self::MIN_HEADER_LEN..]
171 .chunks(4)
172 .take(self.csrc_count() as usize)
173 .map(|b| (b[0] as u32) << 24 | (b[1] as u32) << 16 | (b[2] as u32) << 8 | (b[3] as u32))
174 }
175
176 pub fn payload_offset(&self) -> usize {
178 let offset = self.csrc_end();
179 if self.extension_flag() {
180 offset + Self::EXTENSION_HEADER_LEN + self.extension_len()
181 } else {
182 offset
183 }
184 }
185
186 fn csrc_end(&self) -> usize {
187 Self::MIN_HEADER_LEN + (4 * self.csrc_count()) as usize
188 }
189
190 pub fn payload(&self) -> &'a [u8] {
193 let pad = if self.padding_flag() {
194 self.padding_len().unwrap() as usize
197 } else {
198 0
199 };
200 &self.buf[self.payload_offset()..self.buf.len() - pad]
201 }
202
203 fn extension_len(&self) -> usize {
204 let offset = self.csrc_end();
205 4 * ((self.buf[offset + 2] as usize) << 8 | (self.buf[offset + 3] as usize))
208 }
209
210 fn padding_len(&self) -> Result<u8, RtpReaderError> {
212 match self.buf[self.buf.len() - 1] {
213 0 => Err(RtpReaderError::PaddingLengthInvalid(0)),
214 l => Ok(l),
215 }
216 }
217
218 pub fn extension(&self) -> Option<(u16, &'a [u8])> {
222 if self.extension_flag() {
223 let offset = self.csrc_end();
224 let id = (self.buf[offset] as u16) << 8 | (self.buf[offset + 1] as u16);
225 let start = offset + 4;
226 Some((id, &self.buf[start..start + self.extension_len()]))
227 } else {
228 None
229 }
230 }
231
232 pub fn create_builder(&self) -> RtpPacketBuilder<'a> {
248 let mut builder = RtpPacketBuilder::new()
249 .payload_type(self.payload_type())
250 .marked(self.mark())
251 .sequence(self.sequence_number())
252 .ssrc(self.ssrc())
253 .timestamp(self.timestamp())
254 .payload(self.payload());
255
256 if let Some(ext) = self.extension() {
257 builder = builder.extension(ext.0, ext.1);
258 }
259
260 for csrc in self.csrc() {
261 builder = builder.add_csrc(csrc);
262 }
263
264 builder
265 }
266}
267impl<'a> fmt::Debug for RtpReader<'a> {
268 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
269 f.debug_struct("RtpReader")
270 .field("version", &self.version())
271 .field("padding", &self.padding())
272 .field("extension", &self.extension().map(|(id, _)| id))
273 .field("csrc_count", &self.csrc_count())
274 .field("mark", &self.mark())
275 .field("payload_type", &self.payload_type())
276 .field("sequence_number", &self.sequence_number())
277 .field("timestamp", &self.timestamp())
278 .field("ssrc", &self.ssrc())
279 .field("payload_length", &self.payload().len())
280 .finish()
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use super::*;
287 use crate::IntoSeqIterator;
288
289
290 const TEST_RTP_PACKET: [u8; 391] = [
291 0x80u8, 0xe0u8, 0x27u8, 0x38u8, 0x64u8, 0xe4u8, 0x05u8, 0xa7u8, 0xa2u8, 0x42u8, 0xafu8,
292 0x01u8, 0x3cu8, 0x41u8, 0xa4u8, 0xa3u8, 0x5du8, 0x13u8, 0xf9u8, 0xcau8, 0x2cu8, 0x7eu8,
293 0xa9u8, 0x77u8, 0xaau8, 0xdeu8, 0xf7u8, 0xcau8, 0xa4u8, 0x28u8, 0xfeu8, 0xdfu8, 0xc8u8,
294 0x68u8, 0xf1u8, 0xd9u8, 0x4fu8, 0x69u8, 0x96u8, 0xa0u8, 0x57u8, 0xbau8, 0xfbu8, 0x07u8,
295 0xc4u8, 0xc4u8, 0xd4u8, 0xfeu8, 0xf8u8, 0xc7u8, 0xb2u8, 0x0du8, 0x01u8, 0x12u8, 0x14u8,
296 0x36u8, 0x69u8, 0x75u8, 0xf2u8, 0xb4u8, 0xb5u8, 0xf2u8, 0x54u8, 0x2eu8, 0xc2u8, 0x66u8,
297 0x51u8, 0xebu8, 0x41u8, 0x80u8, 0x96u8, 0xceu8, 0x8eu8, 0x60u8, 0xb2u8, 0x44u8, 0xaeu8,
298 0xe5u8, 0x43u8, 0xadu8, 0x7bu8, 0x48u8, 0x89u8, 0x44u8, 0xb0u8, 0x48u8, 0x67u8, 0x6au8,
299 0x84u8, 0x7au8, 0x0au8, 0x8fu8, 0x71u8, 0x50u8, 0x69u8, 0xe6u8, 0xb1u8, 0x05u8, 0x40u8,
300 0xb9u8, 0x8cu8, 0xafu8, 0x42u8, 0xcbu8, 0x58u8, 0x83u8, 0xcbu8, 0x32u8, 0x64u8, 0xd2u8,
301 0x2au8, 0x7du8, 0x4eu8, 0xf5u8, 0xbcu8, 0x33u8, 0xfeu8, 0xb7u8, 0x0cu8, 0xe4u8, 0x8eu8,
302 0x38u8, 0xbcu8, 0x3au8, 0x1eu8, 0xd2u8, 0x56u8, 0x13u8, 0x23u8, 0x47u8, 0xcfu8, 0x42u8,
303 0xa9u8, 0xbbu8, 0xcfu8, 0x48u8, 0xf3u8, 0x11u8, 0xc7u8, 0xfdu8, 0x73u8, 0x2du8, 0xe1u8,
304 0xeau8, 0x47u8, 0x5cu8, 0x5du8, 0x11u8, 0x96u8, 0x1eu8, 0xc4u8, 0x70u8, 0x32u8, 0x77u8,
305 0xabu8, 0x31u8, 0x7au8, 0xb1u8, 0x22u8, 0x14u8, 0x8du8, 0x2bu8, 0xecu8, 0x3du8, 0x67u8,
306 0x97u8, 0xa4u8, 0x40u8, 0x21u8, 0x1eu8, 0xceu8, 0xb0u8, 0x63u8, 0x01u8, 0x75u8, 0x77u8,
307 0x03u8, 0x15u8, 0xcdu8, 0x35u8, 0xa1u8, 0x2fu8, 0x4bu8, 0xa0u8, 0xacu8, 0x8du8, 0xd7u8,
308 0x78u8, 0x02u8, 0x23u8, 0xcbu8, 0xfdu8, 0x82u8, 0x4eu8, 0x0bu8, 0x79u8, 0x7fu8, 0x39u8,
309 0x70u8, 0x26u8, 0x66u8, 0x37u8, 0xe9u8, 0x93u8, 0x91u8, 0x7bu8, 0xc4u8, 0x80u8, 0xa9u8,
310 0x18u8, 0x23u8, 0xb3u8, 0xa1u8, 0x04u8, 0x72u8, 0x53u8, 0xa0u8, 0xb4u8, 0xffu8, 0x79u8,
311 0x1fu8, 0x07u8, 0xe2u8, 0x5du8, 0x01u8, 0x7du8, 0x63u8, 0xc1u8, 0x16u8, 0x89u8, 0x23u8,
312 0x4au8, 0x17u8, 0xbbu8, 0x6du8, 0x0du8, 0x81u8, 0x1au8, 0xbbu8, 0x94u8, 0x5bu8, 0xcbu8,
313 0x2du8, 0xdeu8, 0x98u8, 0x40u8, 0x22u8, 0x62u8, 0x41u8, 0xc2u8, 0x9bu8, 0x95u8, 0x85u8,
314 0x60u8, 0xf0u8, 0xdeu8, 0x6fu8, 0xeeu8, 0x93u8, 0xccu8, 0x15u8, 0x76u8, 0xfbu8, 0xf8u8,
315 0x8au8, 0x1du8, 0xe1u8, 0x83u8, 0x12u8, 0xabu8, 0x25u8, 0x6au8, 0x7bu8, 0x89u8, 0xedu8,
316 0x70u8, 0x4eu8, 0xcdu8, 0x1eu8, 0xa9u8, 0xfcu8, 0xa8u8, 0x22u8, 0x91u8, 0x5fu8, 0x50u8,
317 0x68u8, 0x6au8, 0x35u8, 0xf7u8, 0xc1u8, 0x1eu8, 0x15u8, 0x37u8, 0xb4u8, 0x30u8, 0x62u8,
318 0x56u8, 0x1eu8, 0x2eu8, 0xe0u8, 0x2du8, 0xa4u8, 0x1eu8, 0x75u8, 0x5bu8, 0xc7u8, 0xd0u8,
319 0x5bu8, 0x9du8, 0xd0u8, 0x25u8, 0x76u8, 0xdfu8, 0xa7u8, 0x19u8, 0x12u8, 0x93u8, 0xf4u8,
320 0xebu8, 0x02u8, 0xf2u8, 0x4au8, 0x13u8, 0xe9u8, 0x1cu8, 0x17u8, 0xccu8, 0x11u8, 0x87u8,
321 0x9cu8, 0xa6u8, 0x40u8, 0x27u8, 0xb7u8, 0x2bu8, 0x9bu8, 0x6fu8, 0x23u8, 0x06u8, 0x2cu8,
322 0xc6u8, 0x6eu8, 0xc1u8, 0x9au8, 0xbdu8, 0x59u8, 0x37u8, 0xe9u8, 0x9eu8, 0x76u8, 0xf6u8,
323 0xc1u8, 0xbcu8, 0x81u8, 0x18u8, 0x60u8, 0xc9u8, 0x64u8, 0x0au8, 0xb3u8, 0x6eu8, 0xf3u8,
324 0x6bu8, 0xb9u8, 0xd0u8, 0xf6u8, 0xe0u8, 0x9bu8, 0x91u8, 0xc1u8, 0x0fu8, 0x96u8, 0xefu8,
325 0xbcu8, 0x5fu8, 0x8eu8, 0x86u8, 0x56u8, 0x5au8, 0xfcu8, 0x7au8, 0x8bu8, 0xddu8, 0x9au8,
326 0x1cu8, 0xf6u8, 0xb4u8, 0x85u8, 0xf4u8, 0xb0u8,
327 ];
328
329 const TEST_RTP_PACKET_WITH_EXTENSION: [u8; 63] = [
330 144u8, 111u8, 79u8, 252u8, 224u8, 94u8, 104u8, 203u8, 30u8, 112u8, 208u8,
331 191u8, 190u8, 222u8, 0u8, 3u8, 34u8, 175u8, 185u8, 88u8, 49u8, 0u8, 171u8,
332 64u8, 48u8, 16u8, 219u8, 0u8, 104u8, 9u8, 136u8, 90u8, 174u8, 145u8, 68u8,
333 165u8, 227u8, 178u8, 187u8, 68u8, 166u8, 66u8, 235u8, 40u8, 171u8, 135u8,
334 30u8, 174u8, 130u8, 239u8, 205u8, 14u8, 211u8, 232u8, 65u8, 67u8, 153u8,
335 120u8, 63u8, 17u8, 101u8, 55u8, 17u8
336 ];
337
338 #[test]
339 fn version() {
340 let reader = RtpReader::new(&TEST_RTP_PACKET).unwrap();
341 assert_eq!(2, reader.version());
342 assert!(reader.padding().is_none());
343 assert!(reader.extension().is_none());
344 assert_eq!(0, reader.csrc_count());
345 assert!(reader.mark());
346 assert_eq!(96, reader.payload_type());
347 assert_eq!(Seq(10040), reader.sequence_number());
348 assert_eq!(1_692_665_255, reader.timestamp());
349 assert_eq!(0xa242_af01, reader.ssrc());
350 assert_eq!(379, reader.payload().len());
351 format!("{:?}", reader);
352 }
353
354 #[test]
355 fn padding() {
356 let reader = RtpReader::new(&TEST_RTP_PACKET_WITH_EXTENSION).unwrap();
357 assert_eq!(2, reader.version());
358 assert!(reader.padding().is_none());
359 assert!(reader.extension().is_some());
360 assert_eq!(0, reader.csrc_count());
361 assert_eq!(111, reader.payload_type());
362 }
363
364 #[test]
365 fn padding_too_large() {
366 let data = [
369 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0x90, 0x0, 0x0, 0x1, 0x0, 0xff, 0xa2, 0xa2, 0xa2, 0xa2,
370 0x90, 0x0, 0x0, 0x0, 0x0, 0xff,
371 ];
372 assert!(RtpReader::new(&data).is_err());
373 }
374
375 #[test]
376 fn builder_juggle() {
377 let reader = RtpReader::new(&TEST_RTP_PACKET).unwrap();
378 let buffer = reader.create_builder().build().unwrap();
379
380 assert_eq!(&buffer.as_slice()[..], &TEST_RTP_PACKET[..]);
381 }
382
383 #[test]
384 fn builder_juggle_extension() {
385 let reader = RtpReader::new(&TEST_RTP_PACKET_WITH_EXTENSION).unwrap();
386 let buffer = reader.create_builder().build().unwrap();
387 assert_eq!(&buffer.as_slice()[..], &TEST_RTP_PACKET_WITH_EXTENSION[..]);
388 }
389
390 #[test]
391 fn builder_juggle_clear_payload() {
392 let new_payload = vec![];
393 let reader = RtpReader::new(&TEST_RTP_PACKET_WITH_EXTENSION).unwrap();
394 let buffer = reader.create_builder()
395 .payload(&new_payload).build().unwrap();
396
397 let expected = &TEST_RTP_PACKET_WITH_EXTENSION[0..(3 + 4) * 4];
398 assert_eq!(&buffer.as_slice()[..], expected);
399 }
400
401 #[test]
402 fn seq() {
403 assert!(Seq(0).precedes(Seq(1)));
404 assert!(Seq(0xffff).precedes(Seq(0)));
405 assert!(Seq(0) < Seq(1));
406 assert!(Seq(0xffff) < Seq(0));
407 assert_eq!(-1, Seq(0) - Seq(1));
408 assert_eq!(1, Seq(1) - Seq(0));
409 assert_eq!(0, Seq(1) - Seq(1));
410 assert_eq!(1, Seq(0) - Seq(0xffff));
411 assert_eq!(-1, Seq(0xffff) - Seq(0));
412 let mut it = (Seq(0xfffe)..Seq(1)).seq_iter();
413 assert_eq!(Seq(0xfffe), it.next().unwrap());
414 assert_eq!(Seq(0xffff), it.next().unwrap());
415 assert_eq!(Seq(0x0000), it.next().unwrap());
416 assert_eq!(None, it.next());
417 }
418}