Skip to content
File

Blob: firmware/vendor/str0m/src/rtp/header.rs

rust927 lines
1#![allow(clippy::unusual_byte_groupings)]
2 
3use super::ext::{ExtensionMap, ExtensionValues, ExtensionsForm};
4use super::{MAX_BLANK_PADDING_PAYLOAD_SIZE, Pt, SeqNo, Ssrc};
5 
6/// Parsed header from an RTP packet.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct RtpHeader {
9 /// Always 2
10 pub version: u8,
11 /// Whether the RTP packet has padding to be an equal of 4 bytes.
12 pub has_padding: bool,
13 /// RTP packet has "RTP header extensions".
14 pub has_extension: bool,
15 /// Number of contributing source identifiers.
16 pub csrc_count: usize,
17 /// For video, this marker signifies the end of a series of packets that
18 /// together form a single video frame.
19 /// For audio, it marks the beginning of a talkspurt, which is a burst of
20 /// audio packets.
21 pub marker: bool,
22 /// Type of payload being carried. What this correlates to is sent in the SDP.
23 pub payload_type: Pt,
24 /// Sequence number increasing by 1 for each RTP packet.
25 pub sequence_number: u16,
26 /// Timestamp in media time for the RTP packet. What the media time base is depends
27 /// on the codec.
28 pub timestamp: u32,
29 /// Sender source identifier.
30 pub ssrc: Ssrc,
31 /// Contributing source identifiers (CSRC). Up to 15 values per RFC 3550.
32 pub csrc: [u32; 15],
33 /// The extension values parsed using the mapping via SDP.
34 pub ext_vals: ExtensionValues,
35 /// Length of header.
36 pub header_len: usize,
37}
38 
39impl RtpHeader {
40 pub(crate) fn write_to(&self, buf: &mut [u8], exts: &ExtensionMap) -> usize {
41 assert!(self.csrc_count <= 15, "CSRC count must be <= 15");
42 buf[0] = 0b10_0_0_0000
43 | if self.has_padding { 1 << 5 } else { 0 }
44 | if self.has_extension { 1 << 4 } else { 0 }
45 | (self.csrc_count as u8);
46 
47 assert!(*self.payload_type <= 127);
48 buf[1] = *self.payload_type & 0b0111_1111 | if self.marker { 1 << 7 } else { 0 };
49 
50 buf[2..4].copy_from_slice(&self.sequence_number.to_be_bytes());
51 buf[4..8].copy_from_slice(&self.timestamp.to_be_bytes());
52 buf[8..12].copy_from_slice(&self.ssrc.to_be_bytes());
53 
54 let csrc_len = self.csrc_count * 4;
55 for i in 0..self.csrc_count {
56 let offset = 12 + i * 4;
57 buf[offset..offset + 4].copy_from_slice(&self.csrc[i].to_be_bytes());
58 }
59 
60 let ext_start = 12 + csrc_len;
61 let exts_form = exts.form(&self.ext_vals);
62 buf[ext_start..ext_start + 2].copy_from_slice(&exts_form.serialize());
63 
64 let ext_buf = &mut buf[ext_start + 4..];
65 let mut ext_len = exts.write_to(ext_buf, &self.ext_vals, exts_form);
66 
67 let pad = 4 - ext_len % 4;
68 if pad < 4 {
69 ext_len += pad;
70 for i in 0..pad {
71 ext_buf[ext_len - i - 1] = 0;
72 }
73 }
74 
75 let bede_len = (ext_len / 4) as u16;
76 buf[ext_start + 2..ext_start + 4].copy_from_slice(&bede_len.to_be_bytes());
77 
78 ext_start + 4 + ext_len
79 }
80 
81 fn do_pad(buf: &mut [u8], from: usize, pad: usize) {
82 assert!(pad <= 255);
83 
84 // set the padding bit
85 buf[0] |= 0b00_1_0_0000;
86 
87 for i in 0..pad {
88 buf[from + i] = 0;
89 }
90 
91 buf[from + pad - 1] = pad as u8;
92 }
93 
94 /// Write a packet consisting entirely of padding and write.
95 pub fn create_padding_packet(
96 buf: &mut [u8],
97 header_len: usize,
98 pad_len: u8,
99 block_size: usize,
100 ) -> usize {
101 if pad_len == 0 {
102 warn!("Not generating padding packet with zero length");
103 return 0;
104 }
105 
106 let rounded_len = if pad_len as usize % block_size == 0 {
107 pad_len as usize
108 } else {
109 ((pad_len as usize / block_size) + 1) * block_size
110 }
111 .min(MAX_BLANK_PADDING_PAYLOAD_SIZE);
112 
113 Self::do_pad(buf, header_len, rounded_len);
114 
115 rounded_len
116 }
117 
118 /// Returns `buf` with any trailing SRTP padding removed, or `None` if the
119 /// trailing padding length is invalid.
120 pub(crate) fn unpad_payload(buf: &[u8]) -> Option<&[u8]> {
121 if buf.is_empty() {
122 return Some(buf);
123 }
124 let pad_len = buf[buf.len() - 1] as usize;
125 let unpadded_len = buf.len().checked_sub(pad_len)?;
126 Some(&buf[..unpadded_len])
127 }
128 
129 pub(crate) fn parse(buf: &[u8], exts: &ExtensionMap) -> Option<RtpHeader> {
130 let orig_len = buf.len();
131 if buf.len() < 12 {
132 trace!("RTP header too short < 12: {}", buf.len());
133 return None;
134 }
135 
136 let version = (buf[0] & 0b1100_0000) >> 6;
137 if version != 2 {
138 trace!("RTP version is not 2");
139 return None;
140 }
141 let has_padding = buf[0] & 0b0010_0000 > 0;
142 let has_extension = buf[0] & 0b0001_0000 > 0;
143 let csrc_count = (buf[0] & 0b0000_1111) as usize;
144 let marker = buf[1] & 0b1000_0000 > 0;
145 let payload_type = (buf[1] & 0b0111_1111).into();
146 let sequence_number = u16::from_be_bytes([buf[2], buf[3]]);
147 
148 let timestamp = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
149 
150 let ssrc = u32::from_be_bytes([buf[8], buf[9], buf[10], buf[11]]);
151 
152 let buf: &[u8] = &buf[12..];
153 
154 let csrc_len = 4 * csrc_count;
155 if buf.len() < csrc_len {
156 trace!("RTP header invalid, not enough csrc");
157 return None;
158 }
159 
160 let mut csrc = [0_u32; 15];
161 for (i, item) in csrc.iter_mut().enumerate().take(csrc_count) {
162 let offset = i * 4;
163 *item = u32::from_be_bytes([
164 buf[offset],
165 buf[offset + 1],
166 buf[offset + 2],
167 buf[offset + 3],
168 ]);
169 }
170 
171 let buf: &[u8] = &buf[csrc_len..];
172 
173 let mut ext = ExtensionValues {
174 ..Default::default()
175 };
176 
177 let rest = if !has_extension {
178 buf
179 } else {
180 if buf.len() < 4 {
181 trace!("RTP bad header extension");
182 return None;
183 }
184 
185 let Some(exts_form) = ExtensionsForm::parse([buf[0], buf[1]]) else {
186 trace!(
187 "Ignoring unknown RTP header extensions form: {:?}",
188 u16::from_be_bytes([buf[0], buf[1]])
189 );
190 return None;
191 };
192 let ext_words = u16::from_be_bytes([buf[2], buf[3]]);
193 let ext_len = ext_words as usize * 4;
194 
195 let buf: &[u8] = &buf[4..];
196 
197 if buf.len() < ext_len {
198 trace!("RTP ext len larger than header {} > {}", buf.len(), ext_len);
199 return None;
200 }
201 
202 exts.parse(&buf[..ext_len], exts_form, &mut ext);
203 &buf[ext_len..]
204 };
205 
206 let header_len = orig_len - rest.len();
207 
208 let ret = RtpHeader {
209 version,
210 has_padding,
211 has_extension,
212 csrc_count,
213 marker,
214 payload_type,
215 sequence_number,
216 timestamp,
217 ssrc: ssrc.into(),
218 csrc,
219 ext_vals: ext,
220 header_len,
221 };
222 
223 Some(ret)
224 }
225 
226 /// For RTX the original sequence number is inserted before the RTP payload.
227 pub fn read_original_sequence_number(buf: &[u8], seq_no: &mut u16) -> usize {
228 if buf.len() < 2 {
229 // This is not an RTX packet, probably a padding packet
230 return 0;
231 }
232 *seq_no = u16::from_be_bytes([buf[0], buf[1]]);
233 2
234 }
235 
236 /// For RTX the original sequence number is inserted before the RTP payload.
237 pub fn write_original_sequence_number(buf: &mut [u8], seq_no: SeqNo) -> usize {
238 let seq_u16 = (*seq_no) as u16;
239 buf[0..2].copy_from_slice(&seq_u16.to_be_bytes());
240 2
241 }
242 
243 /// Sequencer number of this RTP header given the previous number.
244 ///
245 /// The logic detects wrap-arounds of the 16-bit RTP sequence number.
246 pub fn sequence_number(&self, previous: Option<SeqNo>) -> SeqNo {
247 let e_seq = extend_u16(previous.map(|v| *v), self.sequence_number);
248 e_seq.into()
249 }
250}
251 
252macro_rules! mk_extend {
253 ($id:ident, $t:ty, $bits:expr) => {
254 /// "extend" a less than 64 bit sequence number into a 64 bit by
255 /// using the knowledge of the previous such sequence number.
256 pub fn $id(prev_ext_seq: Option<u64>, seq: $t) -> u64 {
257 const MAX: u64 = 2_u64.pow($bits); // u16: 65_536;
258 const HALF: u64 = MAX / 2; // u16: 32_768
259 const BITS: usize = $bits;
260 const VAL_MASK: u64 = ((1 << BITS) - 1);
261 const ROC_MASK: i64 = (u64::MAX >> BITS) as i64;
262 
263 // We define the index of the SRTP packet corresponding to a given
264 // ROC and RTP sequence number to be the 48-bit quantity
265 // i = 2^16 * ROC + SEQ.
266 //
267 // https://tools.ietf.org/html/rfc3711#appendix-A
268 //
269 
270 // Mask seq to the N bits we are considering.
271 // As an example, this allows us to handle the wrap-around of 7 bit
272 // values while storing them in u8
273 let seq = seq as u64 & VAL_MASK;
274 
275 if prev_ext_seq.is_none() {
276 // No wrap-around so far.
277 return seq;
278 }
279 
280 let prev_index = prev_ext_seq.unwrap();
281 let roc = (prev_index >> BITS) as i64; // how many wrap-arounds.
282 let prev_seq = prev_index & (MAX - 1); // u16: 0xffff
283 
284 let v = if prev_seq < HALF {
285 if seq > HALF + prev_seq {
286 (roc - 1) & ROC_MASK
287 } else {
288 roc
289 }
290 } else if prev_seq > seq + HALF {
291 (roc + 1) & ROC_MASK
292 } else {
293 roc
294 };
295 
296 if v < 0 {
297 return 0;
298 }
299 
300 (v as u64) * MAX + seq
301 }
302 };
303}
304 
305mk_extend!(extend_u8, u8, 8);
306mk_extend!(extend_u16, u16, 16);
307mk_extend!(extend_u32, u32, 32);
308 
309// we 'host' 7 bits in u8 but we ignore the most significant one
310mk_extend!(extend_u7, u8, 7);
311mk_extend!(extend_u15, u16, 15);
312 
313impl Default for RtpHeader {
314 fn default() -> Self {
315 Self {
316 version: 2,
317 has_padding: false,
318 has_extension: true,
319 csrc_count: 0,
320 marker: false,
321 payload_type: 1.into(),
322 sequence_number: 0,
323 timestamp: 0,
324 ssrc: 0.into(),
325 csrc: [0; 15],
326 ext_vals: ExtensionValues::default(),
327 header_len: 16,
328 }
329 }
330}
331 
332#[cfg(test)]
333mod test {
334 use crate::util::already_happened;
335 use crate::{io::DATAGRAM_MAX_PACKET_SIZE, rtp_::Extension};
336 use std::time::Duration;
337 
338 use super::*;
339 
340 #[test]
341 fn extend_u16_wrap_around() {
342 assert_eq!(extend_u16(None, 0), 0);
343 assert_eq!(extend_u16(Some(0), 1), 1);
344 assert_eq!(extend_u16(Some(65_535), 0), 65_536);
345 assert_eq!(extend_u16(Some(65_500), 2), 65_538);
346 assert_eq!(extend_u16(Some(2), 1), 1);
347 assert_eq!(extend_u16(Some(65_538), 1), 65_537);
348 assert_eq!(extend_u16(Some(3), 3), 3);
349 assert_eq!(extend_u16(Some(65_500), 65_500), 65_500);
350 }
351 
352 #[test]
353 fn extend_u16_with_0_prev() {
354 // This tests going backwards from previous 0. This should wrap
355 // around "backwards" making a ridiculous number.
356 let seq = u16::MAX / 2 + 2;
357 let expected = u64::MAX - (u16::MAX - seq) as u64;
358 assert_eq!(extend_u16(Some(0), seq), expected);
359 }
360 
361 #[test]
362 fn extend_u32_wrap_around() {
363 const U32MAX: u64 = u32::MAX as u64 + 1;
364 assert_eq!(extend_u32(None, 0), 0);
365 assert_eq!(extend_u32(Some(0), 1), 1);
366 assert_eq!(extend_u32(Some(U32MAX - 1), 0), U32MAX);
367 assert_eq!(extend_u32(Some(U32MAX - 32), 2), U32MAX + 2);
368 assert_eq!(extend_u32(Some(2), 1), 1);
369 assert_eq!(extend_u32(Some(U32MAX + 2), 1), U32MAX + 1);
370 assert_eq!(extend_u32(Some(3), 3), 3);
371 assert_eq!(
372 extend_u32(Some(U32MAX - 32), (U32MAX - 32) as u32),
373 U32MAX - 32
374 );
375 }
376 
377 #[test]
378 fn extend_u32_with_0_prev() {
379 // This tests going backwards from previous 0. This should wrap
380 // around "backwards" making a ridiculous number.
381 let seq = u32::MAX / 2 + 2;
382 let expected = u64::MAX - (u32::MAX - seq) as u64;
383 assert_eq!(extend_u32(Some(0), seq), expected);
384 }
385 
386 #[test]
387 fn extend_u7_wrap_around() {
388 let max = 2_u64.pow(7) - 1;
389 let half = max / 2;
390 assert_eq!(extend_u7(None, 0), 0);
391 assert_eq!(extend_u7(None, 1), 1);
392 
393 // most significant bit gets ignored
394 assert_eq!(extend_u7(None, max as u8), max);
395 assert_eq!(extend_u7(None, (max + 1) as u8), 0);
396 
397 assert_eq!(extend_u7(Some(0), half as u8), half);
398 assert_eq!(extend_u7(Some(0), (half + 1) as u8), half + 1);
399 
400 let seq = max / 2 + 2;
401 let expected = u64::MAX - (max - seq);
402 assert_eq!(extend_u7(Some(0), seq as u8), expected);
403 }
404 
405 #[test]
406 fn extend_u15_wrap_around() {
407 let max = 2_u64.pow(15) - 1;
408 let half = max / 2;
409 assert_eq!(extend_u15(None, 0), 0);
410 assert_eq!(extend_u15(None, 1), 1);
411 
412 assert_eq!(extend_u15(None, max as u16), max);
413 assert_eq!(extend_u15(None, (max + 1) as u16), 0);
414 
415 assert_eq!(extend_u15(Some(0), half as u16), half);
416 assert_eq!(extend_u15(Some(0), (half + 1) as u16), half + 1);
417 
418 let seq = max / 2 + 2;
419 let expected = u64::MAX - (max - seq);
420 assert_eq!(extend_u15(Some(0), seq as u16), expected);
421 }
422 
423 #[test]
424 fn test_generate_one_length_padding_packet() {
425 let mut buf = vec![6; 255];
426 RtpHeader::create_padding_packet(&mut buf, 10, 1, 16);
427 
428 let mut expected = vec![0; 16];
429 expected[15] = 16;
430 assert_eq!(&buf[10..26], &expected);
431 }
432 
433 // version: 2,
434 // has_padding: false,
435 // has_extension: true,
436 // marker: false,
437 // payload_type: 1.into(),
438 // sequence_number: 0,
439 // timestamp: 0,
440 // ssrc: 0.into(),
441 // ext_vals: ExtensionValues::default(),
442 // header_len: 16,
443 
444 #[test]
445 fn test_write_rtp_headers() {
446 fn mk_header(seq: u16, ts: u32, level: i8, marker: bool, exts: &ExtensionMap) -> Vec<u8> {
447 let header = RtpHeader {
448 payload_type: 33.into(),
449 sequence_number: seq,
450 timestamp: ts,
451 ssrc: 44.into(),
452 marker,
453 ext_vals: ExtensionValues {
454 audio_level: Some(level),
455 voice_activity: Some(false),
456 ..Default::default()
457 },
458 ..Default::default()
459 };
460 let mut buf = vec![0; DATAGRAM_MAX_PACKET_SIZE];
461 let n = header.write_to(&mut buf[..], exts);
462 buf.truncate(n);
463 
464 buf
465 }
466 
467 let mut exts = ExtensionMap::empty();
468 exts.set(3, Extension::AudioLevel);
469 
470 let buf1 = mk_header(47_000, 10_000, -42, false, &exts);
471 let buf2 = mk_header(47_001, 12_000, -43, true, &exts);
472 let buf3 = mk_header(47_002, 14_000, -44, false, &exts);
473 
474 let p1 = &[
475 144, 33, 183, 152, 0, 0, 39, 16, 0, 0, 0, 44, 0xBE, 0xDE, 0, 1, 48, 170, 0, 0,
476 ];
477 let p2 = &[
478 144, 161, 183, 153, 0, 0, 46, 224, 0, 0, 0, 44, 0xBE, 0xDE, 0, 1, 48, 171, 0, 0,
479 ];
480 let p3 = &[
481 144, 33, 183, 154, 0, 0, 54, 176, 0, 0, 0, 44, 0xBE, 0xDE, 0, 1, 48, 172, 0, 0,
482 ];
483 
484 assert_eq!(&buf1, p1);
485 assert_eq!(&buf2, p2);
486 assert_eq!(&buf3, p3);
487 }
488 
489 #[test]
490 fn test_write_rtp_headers_two_byte_form() {
491 fn mk_header(seq: u16, ts: u32, level: i8, marker: bool, exts: &ExtensionMap) -> Vec<u8> {
492 let header = RtpHeader {
493 payload_type: 33.into(),
494 sequence_number: seq,
495 timestamp: ts,
496 ssrc: 44.into(),
497 marker,
498 ext_vals: ExtensionValues {
499 audio_level: Some(level),
500 voice_activity: Some(false),
501 ..Default::default()
502 },
503 ..Default::default()
504 };
505 let mut buf = vec![0; DATAGRAM_MAX_PACKET_SIZE];
506 let n = header.write_to(&mut buf[..], exts);
507 buf.truncate(n);
508 
509 buf
510 }
511 
512 let mut exts = ExtensionMap::empty();
513 // An ID larger than 14 forces the 2-byte header extension form
514 exts.set(15, Extension::AudioLevel);
515 
516 let buf1 = mk_header(47_000, 10_000, -42, false, &exts);
517 let buf2 = mk_header(47_001, 12_000, -43, true, &exts);
518 let buf3 = mk_header(47_002, 14_000, -44, false, &exts);
519 
520 let p1 = &[
521 144, 33, 183, 152, 0, 0, 39, 16, 0, 0, 0, 44, 0x10, 0x00, 0, 1, 15, 1, 170, 0,
522 ];
523 let p2 = &[
524 144, 161, 183, 153, 0, 0, 46, 224, 0, 0, 0, 44, 0x10, 0x00, 0, 1, 15, 1, 171, 0,
525 ];
526 let p3 = &[
527 144, 33, 183, 154, 0, 0, 54, 176, 0, 0, 0, 44, 0x10, 0x00, 0, 1, 15, 1, 172, 0,
528 ];
529 
530 assert_eq!(&buf1, p1);
531 assert_eq!(&buf2, p2);
532 assert_eq!(&buf3, p3);
533 }
534 
535 #[test]
536 fn test_parse_rtp_headers() {
537 let exts = ExtensionMap::standard();
538 
539 let hb1 = [
540 176, 111, 183, 152, 0, 0, 39, 16, 46, 87, 21, 249, 0xBE, 0xDE, 0, 4, 16, 170, 34, 254,
541 32, 106, 49, 0, 0, 66, 120, 89, 106, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
542 0, 12,
543 ];
544 
545 let hb2 = [
546 176, 111, 183, 153, 0, 0, 46, 224, 46, 87, 21, 249, 0xBE, 0xDE, 0, 4, 16, 171, 34, 254,
547 134, 208, 49, 0, 2, 66, 120, 89, 106, 0, 0, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
548 0, 0, 12,
549 ];
550 let hb3 = [
551 176, 111, 183, 154, 0, 0, 54, 176, 46, 87, 21, 249, 0xBE, 0xDE, 0, 4, 16, 172, 34, 254,
552 32, 106, 49, 0, 1, 66, 120, 89, 106, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0,
553 0, 0, 12,
554 ];
555 
556 let h1 = RtpHeader::parse(&hb1, &exts).unwrap();
557 let abs1 = already_happened() + Duration::from_micros(63531654);
558 
559 assert_eq!(
560 h1,
561 RtpHeader {
562 version: 2,
563 has_padding: true,
564 has_extension: true,
565 csrc_count: 0,
566 marker: false,
567 payload_type: 111.into(),
568 sequence_number: 47000,
569 timestamp: 10000,
570 ssrc: 777459193.into(),
571 csrc: [0; 15],
572 ext_vals: ExtensionValues {
573 mid: Some("xYj".into()),
574 abs_send_time: Some(abs1),
575 voice_activity: Some(true),
576 audio_level: Some(-42),
577 transport_cc: Some(0),
578 ..Default::default()
579 },
580 header_len: 32
581 }
582 );
583 
584 let h2 = RtpHeader::parse(&hb2, &exts).unwrap();
585 let abs2 = already_happened() + Duration::from_micros(63631652);
586 
587 assert_eq!(
588 h2,
589 RtpHeader {
590 version: 2,
591 has_padding: true,
592 has_extension: true,
593 csrc_count: 0,
594 marker: false,
595 payload_type: 111.into(),
596 sequence_number: 47001,
597 timestamp: 12000,
598 ssrc: 777459193.into(),
599 csrc: [0; 15],
600 ext_vals: ExtensionValues {
601 mid: Some("xYj".into()),
602 abs_send_time: Some(abs2),
603 voice_activity: Some(true),
604 audio_level: Some(-43),
605 transport_cc: Some(2),
606 ..Default::default()
607 },
608 header_len: 32
609 }
610 );
611 
612 let h3 = RtpHeader::parse(&hb3, &exts).unwrap();
613 let abs3 = already_happened() + Duration::from_micros(63531654);
614 
615 assert_eq!(
616 h3,
617 RtpHeader {
618 version: 2,
619 has_padding: true,
620 has_extension: true,
621 csrc_count: 0,
622 marker: false,
623 payload_type: 111.into(),
624 sequence_number: 47002,
625 timestamp: 14000,
626 ssrc: 777459193.into(),
627 csrc: [0; 15],
628 ext_vals: ExtensionValues {
629 mid: Some("xYj".into()),
630 abs_send_time: Some(abs3),
631 voice_activity: Some(true),
632 audio_level: Some(-44),
633 transport_cc: Some(1),
634 ..Default::default()
635 },
636 header_len: 32
637 }
638 );
639 }
640 
641 #[test]
642 fn test_parse_rtp_headers_two_byte_form() {
643 let exts = ExtensionMap::standard();
644 
645 let hb1 = [
646 176, 111, 183, 152, 0, 0, 39, 16, 46, 87, 21, 249, 0x10, 0x01, 0, 5, 1, 1, 170, 2, 3,
647 254, 32, 106, 3, 2, 0, 0, 4, 3, 120, 89, 106, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0,
648 0, 0, 0, 0, 12,
649 ];
650 
651 let hb2 = [
652 176, 111, 183, 153, 0, 0, 46, 224, 46, 87, 21, 249, 0x10, 0x02, 0, 5, 1, 1, 171, 2, 3,
653 254, 134, 208, 3, 2, 0, 2, 4, 3, 120, 89, 106, 0, 0, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0,
654 0, 0, 0, 0, 0, 12,
655 ];
656 let hb3 = [
657 176, 111, 183, 154, 0, 0, 54, 176, 46, 87, 21, 249, 0x10, 0x03, 0, 5, 1, 1, 172, 2, 3,
658 254, 32, 106, 3, 2, 0, 1, 4, 3, 120, 89, 106, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0,
659 0, 0, 0, 0, 0, 12,
660 ];
661 
662 let h1 = RtpHeader::parse(&hb1, &exts).unwrap();
663 let abs1 = already_happened() + Duration::from_micros(63531654);
664 
665 assert_eq!(
666 h1,
667 RtpHeader {
668 version: 2,
669 has_padding: true,
670 has_extension: true,
671 csrc_count: 0,
672 marker: false,
673 payload_type: 111.into(),
674 sequence_number: 47000,
675 timestamp: 10000,
676 ssrc: 777459193.into(),
677 csrc: [0; 15],
678 ext_vals: ExtensionValues {
679 mid: Some("xYj".into()),
680 abs_send_time: Some(abs1),
681 voice_activity: Some(true),
682 audio_level: Some(-42),
683 transport_cc: Some(0),
684 ..Default::default()
685 },
686 header_len: 36
687 }
688 );
689 
690 let h2 = RtpHeader::parse(&hb2, &exts).unwrap();
691 let abs2 = already_happened() + Duration::from_micros(63631652);
692 
693 assert_eq!(
694 h2,
695 RtpHeader {
696 version: 2,
697 has_padding: true,
698 has_extension: true,
699 csrc_count: 0,
700 marker: false,
701 payload_type: 111.into(),
702 sequence_number: 47001,
703 timestamp: 12000,
704 ssrc: 777459193.into(),
705 csrc: [0; 15],
706 ext_vals: ExtensionValues {
707 mid: Some("xYj".into()),
708 abs_send_time: Some(abs2),
709 voice_activity: Some(true),
710 audio_level: Some(-43),
711 transport_cc: Some(2),
712 ..Default::default()
713 },
714 header_len: 36
715 }
716 );
717 
718 let h3 = RtpHeader::parse(&hb3, &exts).unwrap();
719 let abs3 = already_happened() + Duration::from_micros(63531654);
720 
721 assert_eq!(
722 h3,
723 RtpHeader {
724 version: 2,
725 has_padding: true,
726 has_extension: true,
727 csrc_count: 0,
728 marker: false,
729 payload_type: 111.into(),
730 sequence_number: 47002,
731 timestamp: 14000,
732 ssrc: 777459193.into(),
733 csrc: [0; 15],
734 ext_vals: ExtensionValues {
735 mid: Some("xYj".into()),
736 abs_send_time: Some(abs3),
737 voice_activity: Some(true),
738 audio_level: Some(-44),
739 transport_cc: Some(1),
740 ..Default::default()
741 },
742 header_len: 36
743 }
744 );
745 }
746 
747 #[test]
748 fn test_write_rtp_headers_with_csrc() {
749 fn mk_header(csrc_count: usize, csrc: [u32; 15], exts: &ExtensionMap) -> Vec<u8> {
750 let header = RtpHeader {
751 csrc_count,
752 payload_type: 33.into(),
753 sequence_number: 47_000,
754 timestamp: 10_000,
755 ssrc: 44.into(),
756 csrc,
757 ext_vals: ExtensionValues {
758 audio_level: Some(-42),
759 voice_activity: Some(true),
760 ..Default::default()
761 },
762 ..Default::default()
763 };
764 let mut buf = vec![0; DATAGRAM_MAX_PACKET_SIZE];
765 let n = header.write_to(&mut buf[..], exts);
766 buf.truncate(n);
767 buf
768 }
769 
770 let mut exts = ExtensionMap::empty();
771 exts.set(3, Extension::AudioLevel);
772 
773 // 3 CSRC entries, one-byte extension form
774 let buf1 = mk_header(
775 3,
776 [
777 100,
778 0x12_34_56_78,
779 0xFFFF_FFFF,
780 0,
781 0,
782 0,
783 0,
784 0,
785 0,
786 0,
787 0,
788 0,
789 0,
790 0,
791 0,
792 ],
793 &exts,
794 );
795 let p1 = &[
796 147, 33, 183, 152, 0, 0, 39, 16, 0, 0, 0, 44, // fixed header (CC=3)
797 0, 0, 0, 100, 0x12, 0x34, 0x56, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, // CSRC values
798 0xBE, 0xDE, 0, 1, 48, 170, 0, 0, // extension
799 ];
800 assert_eq!(&buf1, p1);
801 
802 // 15 CSRC entries (maximum)
803 let buf2 = mk_header(
804 15,
805 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
806 &exts,
807 );
808 let p2 = &[
809 159, 33, 183, 152, 0, 0, 39, 16, 0, 0, 0, 44, // fixed header (CC=15)
810 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, // CSRC 1-4
811 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, // CSRC 5-8
812 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 12, // CSRC 9-12
813 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 15, // CSRC 13-15
814 0xBE, 0xDE, 0, 1, 48, 170, 0, 0, // extension
815 ];
816 assert_eq!(&buf2, p2);
817 }
818 
819 #[test]
820 fn test_parse_rtp_headers_with_csrc() {
821 let mut exts = ExtensionMap::empty();
822 exts.set(3, Extension::AudioLevel);
823 
824 // 3 CSRC entries with one-byte extension form (produced by test_write_rtp_headers_with_csrc)
825 let buf1 = [
826 147, 33, 183, 152, 0, 0, 39, 16, 0, 0, 0, 44, 0, 0, 0, 100, 0x12, 0x34, 0x56, 0x78,
827 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xDE, 0, 1, 48, 170, 0, 0,
828 ];
829 
830 let h1 = RtpHeader::parse(&buf1, &exts).unwrap();
831 
832 assert_eq!(
833 h1,
834 RtpHeader {
835 version: 2,
836 has_padding: false,
837 has_extension: true,
838 csrc_count: 3,
839 marker: false,
840 payload_type: 33.into(),
841 sequence_number: 47_000,
842 timestamp: 10_000,
843 ssrc: 44.into(),
844 csrc: [
845 100,
846 0x12_34_56_78,
847 0xFFFF_FFFF,
848 0,
849 0,
850 0,
851 0,
852 0,
853 0,
854 0,
855 0,
856 0,
857 0,
858 0,
859 0
860 ],
861 ext_vals: ExtensionValues {
862 audio_level: Some(-42),
863 voice_activity: Some(true),
864 ..Default::default()
865 },
866 header_len: 32,
867 }
868 );
869 
870 // 15 CSRC entries (maximum)
871 let buf2 = [
872 159, 33, 183, 152, 0, 0, 39, 16, 0, 0, 0, 44, // fixed header (CC=15)
873 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, // CSRC 1-4
874 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, // CSRC 5-8
875 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 12, // CSRC 9-12
876 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 15, // CSRC 13-15
877 0xBE, 0xDE, 0, 1, 48, 170, 0, 0, // extension
878 ];
879 
880 let h2 = RtpHeader::parse(&buf2, &exts).unwrap();
881 
882 assert_eq!(
883 h2,
884 RtpHeader {
885 version: 2,
886 has_padding: false,
887 has_extension: true,
888 csrc_count: 15,
889 marker: false,
890 payload_type: 33.into(),
891 sequence_number: 47_000,
892 timestamp: 10_000,
893 ssrc: 44.into(),
894 csrc: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
895 ext_vals: ExtensionValues {
896 audio_level: Some(-42),
897 voice_activity: Some(true),
898 ..Default::default()
899 },
900 header_len: 80,
901 }
902 );
903 }
904 
905 #[test]
906 fn truncate_off_srtp_padding() {
907 let truncate = |payload: Vec<u8>| -> Result<Vec<u8>, ()> {
908 match RtpHeader::unpad_payload(&payload) {
909 Some(unpadded) => Ok(unpadded.to_vec()),
910 None => Err(()),
911 }
912 };
913 
914 assert_eq!(Ok(vec![1, 2, 3, 4, 0]), truncate(vec![1, 2, 3, 4, 0]));
915 assert_eq!(Ok(vec![1, 2, 3, 4]), truncate(vec![1, 2, 3, 4, 1]));
916 assert_eq!(Ok(vec![1, 2, 3]), truncate(vec![1, 2, 3, 4, 2]));
917 assert_eq!(Ok(vec![1, 2]), truncate(vec![1, 2, 3, 4, 3]));
918 assert_eq!(Ok(vec![1]), truncate(vec![1, 2, 3, 4, 4]));
919 assert_eq!(Ok(vec![]), truncate(vec![1, 2, 3, 4, 5]));
920 assert_eq!(Err(()), truncate(vec![1, 2, 3, 4, 6]));
921 assert_eq!(Err(()), truncate(vec![1, 2, 3, 4, 255]));
922 assert_eq!(Ok(vec![0]), truncate(vec![0]));
923 assert_eq!(Ok(vec![]), truncate(vec![1]));
924 assert_eq!(Ok(vec![]), truncate(vec![]));
925 }
926}