1use crate::{
4 prelude::*,
5 utils::{parser::*, writer::*},
6 RtcpPacket, RtcpParseError, RtcpWriteError,
7};
8
9#[derive(Debug, PartialEq, Eq)]
12pub struct Unknown<'a> {
13 data: &'a [u8],
14}
15
16impl<'a> RtcpPacket for Unknown<'a> {
17 const MIN_PACKET_LEN: usize = 4;
18 const PACKET_TYPE: u8 = 255; }
20
21impl<'a> RtcpPacketParser<'a> for Unknown<'a> {
22 fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError> {
23 if data.len() < Self::MIN_PACKET_LEN {
24 return Err(RtcpParseError::Truncated {
25 expected: Self::MIN_PACKET_LEN,
26 actual: data.len(),
27 });
28 }
29
30 let version = parse_version(data);
31 if parse_version(data) != Self::VERSION {
32 return Err(RtcpParseError::UnsupportedVersion(version));
33 }
34
35 let length = parse_length(data);
36 if data.len() < length {
37 return Err(RtcpParseError::Truncated {
38 expected: length,
39 actual: data.len(),
40 });
41 }
42 if data.len() > length {
43 return Err(RtcpParseError::TooLarge {
44 expected: length,
45 actual: data.len(),
46 });
47 }
48
49 Ok(Self { data })
50 }
51
52 #[inline(always)]
53 fn header_data(&self) -> [u8; 4] {
54 self.data[..4].try_into().unwrap()
55 }
56}
57
58impl<'a> Unknown<'a> {
59 pub fn data(&self) -> &[u8] {
61 self.data
62 }
63
64 pub fn try_as<P>(&'a self) -> Result<P, RtcpParseError>
67 where
68 P: RtcpPacket,
69 P: TryFrom<&'a Self, Error = RtcpParseError>,
70 {
71 TryFrom::try_from(self)
72 }
73
74 pub fn builder(type_: u8, data: &'a [u8]) -> UnknownBuilder<'a> {
77 UnknownBuilder::new(type_, data)
78 }
79}
80
81#[derive(Debug)]
83#[must_use = "The builder must be built to be used"]
84pub struct UnknownBuilder<'a> {
85 padding: u8,
86 type_: u8,
87 count: u8,
88 data: &'a [u8],
89}
90
91impl<'a> UnknownBuilder<'a> {
92 pub fn new(type_: u8, data: &'a [u8]) -> UnknownBuilder<'a> {
95 UnknownBuilder {
96 padding: 0,
97 type_,
98 count: 0,
99 data,
100 }
101 }
102
103 pub fn padding(mut self, padding: u8) -> Self {
105 self.padding = padding;
106 self
107 }
108
109 pub fn count(mut self, count: u8) -> Self {
112 self.count = count;
113 self
114 }
115}
116
117impl<'a> RtcpPacketWriter for UnknownBuilder<'a> {
118 fn calculate_size(&self) -> Result<usize, RtcpWriteError> {
125 if self.count > Unknown::MAX_COUNT {
126 return Err(RtcpWriteError::CountOutOfRange {
127 count: self.count,
128 max: Unknown::MAX_COUNT,
129 });
130 }
131
132 check_padding(self.padding)?;
133
134 Ok(Unknown::MIN_PACKET_LEN + self.data.len())
135 }
136
137 #[inline]
145 fn write_into_unchecked(&self, buf: &mut [u8]) -> usize {
146 write_header_unchecked::<Unknown>(self.padding, self.count, buf);
147 buf[1] = self.type_;
148
149 let mut end = 4 + self.data.len();
150 buf[4..end].copy_from_slice(self.data);
151
152 end += write_padding_unchecked(self.padding, &mut buf[end..]);
153
154 end
155 }
156
157 fn get_padding(&self) -> Option<u8> {
158 if self.padding == 0 {
159 return None;
160 }
161
162 Some(self.padding)
163 }
164}
165
166#[derive(Debug)]
169pub enum Packet<'a> {
170 App(crate::App<'a>),
171 Bye(crate::Bye<'a>),
172 Rr(crate::ReceiverReport<'a>),
173 Sdes(crate::Sdes<'a>),
174 Sr(crate::SenderReport<'a>),
175 TransportFeedback(crate::TransportFeedback<'a>),
176 PayloadFeedback(crate::PayloadFeedback<'a>),
177 Unknown(Unknown<'a>),
178}
179
180impl<'a> Packet<'a> {
181 pub fn is_unknown(&self) -> bool {
182 matches!(self, Packet::Unknown(_))
183 }
184}
185
186impl<'a> RtcpPacket for Packet<'a> {
187 const MIN_PACKET_LEN: usize = 4;
188 const PACKET_TYPE: u8 = 255; }
190
191impl<'a> RtcpPacketParser<'a> for Packet<'a> {
192 fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError> {
193 if data.len() < Self::MIN_PACKET_LEN {
194 return Err(RtcpParseError::Truncated {
195 expected: Self::MIN_PACKET_LEN,
196 actual: data.len(),
197 });
198 }
199
200 match parse_packet_type(data) {
201 crate::App::PACKET_TYPE => crate::App::parse(data).map(Packet::App),
202 crate::Bye::PACKET_TYPE => crate::Bye::parse(data).map(Packet::Bye),
203 crate::ReceiverReport::PACKET_TYPE => {
204 crate::ReceiverReport::parse(data).map(Packet::Rr)
205 }
206 crate::Sdes::PACKET_TYPE => crate::Sdes::parse(data).map(Packet::Sdes),
207 crate::SenderReport::PACKET_TYPE => crate::SenderReport::parse(data).map(Packet::Sr),
208 crate::PayloadFeedback::PACKET_TYPE => {
209 crate::PayloadFeedback::parse(data).map(Packet::PayloadFeedback)
210 }
211 crate::TransportFeedback::PACKET_TYPE => {
212 crate::TransportFeedback::parse(data).map(Packet::TransportFeedback)
213 }
214 _ => Ok(Packet::Unknown(Unknown::parse(data)?)),
215 }
216 }
217
218 #[inline(always)]
219 fn header_data(&self) -> [u8; 4] {
220 use Packet::*;
221 match self {
222 App(this) => this.header_data(),
223 Bye(this) => this.header_data(),
224 Rr(this) => this.header_data(),
225 Sdes(this) => this.header_data(),
226 Sr(this) => this.header_data(),
227 TransportFeedback(this) => this.header_data(),
228 PayloadFeedback(this) => this.header_data(),
229 Unknown(this) => this.header_data(),
230 }
231 }
232}
233
234impl<'a> Packet<'a> {
235 pub fn try_as<P>(&'a self) -> Result<P, RtcpParseError>
237 where
238 P: RtcpPacket,
239 P: TryFrom<&'a Self, Error = RtcpParseError>,
240 {
241 TryFrom::try_from(self)
242 }
243}
244
245#[derive(Debug)]
247pub struct Compound<'a> {
248 data: &'a [u8],
249 offset: usize,
250 is_over: bool,
251}
252
253impl<'a> Compound<'a> {
254 pub fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError> {
258 let mut offset = 0;
259 let mut packet_length;
260
261 if data.is_empty() {
262 return Err(RtcpParseError::Truncated {
263 expected: 4,
264 actual: 0,
265 });
266 }
267
268 while offset < data.len() {
269 if data.len() < offset + Unknown::MIN_PACKET_LEN {
270 return Err(RtcpParseError::Truncated {
271 expected: offset + Unknown::MIN_PACKET_LEN,
272 actual: data.len(),
273 });
274 }
275
276 packet_length = parse_length(&data[offset..]);
277 if data.len() < offset + packet_length {
278 return Err(RtcpParseError::Truncated {
279 expected: offset + packet_length,
280 actual: data.len(),
281 });
282 }
283
284 offset += packet_length;
285 }
286
287 Ok(Self {
288 data,
289 offset: 0,
290 is_over: false,
291 })
292 }
293
294 pub fn builder() -> CompoundBuilder<'a> {
296 CompoundBuilder::default()
297 }
298}
299
300impl<'a> Iterator for Compound<'a> {
301 type Item = Result<Packet<'a>, RtcpParseError>;
302
303 fn next(&mut self) -> Option<Self::Item> {
304 if self.is_over {
305 return None;
306 }
307
308 let packet_length = parse_length(&self.data[self.offset..]);
311 let res = Packet::parse(&self.data[self.offset..self.offset + packet_length]);
312
313 self.is_over = res.is_err();
314
315 self.offset += packet_length;
316 if self.offset >= self.data.len() {
317 self.is_over = true;
318 }
319
320 Some(res)
321 }
322}
323
324#[derive(Debug)]
326#[must_use = "The builder must be built to be used"]
327pub enum PacketBuilder<'a> {
328 App(crate::app::AppBuilder<'a>),
329 Bye(crate::bye::ByeBuilder<'a>),
330 Rr(crate::receiver::ReceiverReportBuilder),
331 Sdes(crate::sdes::SdesBuilder<'a>),
332 Sr(crate::sender::SenderReportBuilder),
333 TransportFeedback(crate::feedback::TransportFeedbackBuilder<'a>),
334 PayloadFeedback(crate::feedback::PayloadFeedbackBuilder<'a>),
335 Unknown(UnknownBuilder<'a>),
336}
337
338impl<'a> RtcpPacketWriter for PacketBuilder<'a> {
339 fn get_padding(&self) -> Option<u8> {
340 use PacketBuilder::*;
341 match self {
342 App(this) => this.get_padding(),
343 Bye(this) => this.get_padding(),
344 Rr(this) => this.get_padding(),
345 Sdes(this) => this.get_padding(),
346 Sr(this) => this.get_padding(),
347 TransportFeedback(this) => this.get_padding(),
348 PayloadFeedback(this) => this.get_padding(),
349 Unknown(this) => this.get_padding(),
350 }
351 }
352
353 fn calculate_size(&self) -> Result<usize, RtcpWriteError> {
354 use PacketBuilder::*;
355 match self {
356 App(this) => this.calculate_size(),
357 Bye(this) => this.calculate_size(),
358 Rr(this) => this.calculate_size(),
359 Sdes(this) => this.calculate_size(),
360 Sr(this) => this.calculate_size(),
361 TransportFeedback(this) => this.calculate_size(),
362 PayloadFeedback(this) => this.calculate_size(),
363 Unknown(this) => this.calculate_size(),
364 }
365 }
366
367 fn write_into_unchecked(&self, buf: &mut [u8]) -> usize {
368 use PacketBuilder::*;
369 match self {
370 App(this) => this.write_into_unchecked(buf),
371 Bye(this) => this.write_into_unchecked(buf),
372 Rr(this) => this.write_into_unchecked(buf),
373 Sdes(this) => this.write_into_unchecked(buf),
374 Sr(this) => this.write_into_unchecked(buf),
375 TransportFeedback(this) => this.write_into_unchecked(buf),
376 PayloadFeedback(this) => this.write_into_unchecked(buf),
377 Unknown(this) => this.write_into_unchecked(buf),
378 }
379 }
380}
381
382#[derive(Default, Debug)]
384#[must_use = "The builder must be built to be used"]
385pub struct CompoundBuilder<'a> {
386 packets: Vec<Box<dyn RtcpPacketWriter + 'a>>,
387}
388
389impl<'a> CompoundBuilder<'a> {
390 pub fn add_packet(mut self, packet: impl RtcpPacketWriter + 'a) -> Self {
392 self.packets.push(Box::new(packet));
393 self
394 }
395}
396
397impl<'a> RtcpPacketWriter for CompoundBuilder<'a> {
398 fn calculate_size(&self) -> Result<usize, RtcpWriteError> {
406 let mut size = 0;
407 let last = self.packets.len().saturating_sub(1);
408 for (idx, packet) in self.packets.iter().enumerate() {
409 size += packet.calculate_size()?;
410
411 if packet.get_padding().unwrap_or(0) > 0 && idx != last {
412 return Err(RtcpWriteError::NonLastCompoundPacketPadding);
413 }
414 }
415
416 Ok(size)
417 }
418
419 fn write_into_unchecked(&self, buf: &mut [u8]) -> usize {
429 let mut offset = 0;
430 for packet in self.packets.iter() {
431 let req_size = packet.calculate_size().unwrap();
432 offset += packet.write_into_unchecked(&mut buf[offset..offset + req_size]);
433 }
434
435 offset
436 }
437
438 fn get_padding(&self) -> Option<u8> {
439 self.packets.last()?.get_padding()
440 }
441}
442
443macro_rules! impl_try_from {
444 ($parser:ty, $builder:ty, $variant:ident) => {
445 impl<'a> TryFrom<Unknown<'a>> for $parser {
446 type Error = RtcpParseError;
447
448 fn try_from(p: Unknown<'a>) -> Result<Self, Self::Error> {
449 <$parser>::parse(p.data)
450 }
451 }
452
453 impl<'a> TryFrom<&'a Unknown<'a>> for $parser {
454 type Error = RtcpParseError;
455
456 fn try_from(p: &'a Unknown<'a>) -> Result<Self, Self::Error> {
457 <$parser>::parse(p.data)
458 }
459 }
460
461 impl<'a> TryFrom<Packet<'a>> for $parser {
462 type Error = RtcpParseError;
463
464 fn try_from(p: Packet<'a>) -> Result<Self, Self::Error> {
465 match p {
466 Packet::$variant(this) => Ok(this),
467 Packet::Unknown(p) => Self::try_from(p),
468 _ => Err(RtcpParseError::PacketTypeMismatch {
469 actual: p.type_(),
470 requested: <$parser>::PACKET_TYPE,
471 }),
472 }
473 }
474 }
475
476 impl<'a> TryFrom<&'a Packet<'a>> for $parser {
477 type Error = RtcpParseError;
478
479 fn try_from(p: &'a Packet<'a>) -> Result<Self, Self::Error> {
480 match p {
481 Packet::$variant(this) => Ok(this.clone()),
482 Packet::Unknown(p) => Self::try_from(p),
483 _ => Err(RtcpParseError::PacketTypeMismatch {
484 actual: p.type_(),
485 requested: <$parser>::PACKET_TYPE,
486 }),
487 }
488 }
489 }
490
491 impl<'a> From<$parser> for Packet<'a> {
492 fn from(p: $parser) -> Self {
493 Packet::$variant(p)
494 }
495 }
496
497 impl<'a> From<$builder> for PacketBuilder<'a> {
498 fn from(pb: $builder) -> Self {
499 Self::$variant(pb)
500 }
501 }
502 };
503}
504
505impl_try_from!(crate::app::App<'a>, crate::app::AppBuilder<'a>, App);
506impl_try_from!(crate::bye::Bye<'a>, crate::bye::ByeBuilder<'a>, Bye);
507impl_try_from!(crate::sdes::Sdes<'a>, crate::sdes::SdesBuilder<'a>, Sdes);
508impl_try_from!(
509 crate::receiver::ReceiverReport<'a>,
510 crate::receiver::ReceiverReportBuilder,
511 Rr
512);
513impl_try_from!(
514 crate::sender::SenderReport<'a>,
515 crate::sender::SenderReportBuilder,
516 Sr
517);
518impl_try_from!(
519 crate::feedback::TransportFeedback<'a>,
520 crate::feedback::TransportFeedbackBuilder<'a>,
521 TransportFeedback
522);
523impl_try_from!(
524 crate::feedback::PayloadFeedback<'a>,
525 crate::feedback::PayloadFeedbackBuilder<'a>,
526 PayloadFeedback
527);
528
529impl<'a> From<Unknown<'a>> for Packet<'a> {
530 fn from(p: Unknown<'a>) -> Self {
531 Packet::Unknown(p)
532 }
533}
534
535impl<'a> From<UnknownBuilder<'a>> for PacketBuilder<'a> {
536 fn from(pb: UnknownBuilder<'a>) -> Self {
537 Self::Unknown(pb)
538 }
539}
540
541#[cfg(test)]
542mod tests {
543 use super::*;
544 use crate::{App, Bye, ReceiverReport, SenderReport};
545
546 #[test]
547 fn parse_rr_bye() {
548 let data = [
549 0x80, 0xc9, 0x00, 0x01, 0x91, 0x82, 0x73, 0x64, 0x80, 0xcb, 0x00, 0x00,
550 ];
551 let mut compound = Compound::parse(&data).unwrap();
552 let packet = compound.next().unwrap().unwrap();
553 matches!(packet, Packet::Rr(_));
554
555 let packet = compound.next().unwrap().unwrap();
556 matches!(packet, Packet::Bye(_));
557
558 assert!(compound.next().is_none());
559 }
560
561 #[test]
562 fn build_rr_bye() {
563 const REQ_LEN: usize = ReceiverReport::MIN_PACKET_LEN + Bye::MIN_PACKET_LEN;
564
565 let b = Compound::builder()
566 .add_packet(ReceiverReport::builder(0x1234567))
567 .add_packet(Bye::builder());
568
569 let mut data = [0; REQ_LEN];
570 let len = b.write_into(&mut data).unwrap();
571 assert_eq!(len, REQ_LEN);
572 assert_eq!(
573 data,
574 [0x80, 0xc9, 0x00, 0x01, 0x01, 0x23, 0x45, 0x67, 0x80, 0xcb, 0x00, 0x00]
575 );
576 }
577
578 #[test]
579 fn parse_sr_bye() {
580 let data = [
581 0x80, 0xc8, 0x00, 0x06, 0x91, 0x82, 0x73, 0x64, 0x89, 0xab, 0xcd, 0xef, 0x02, 0x24,
582 0x46, 0x68, 0x8a, 0xac, 0xce, 0xe0, 0xf1, 0xe2, 0xd3, 0xc4, 0xb5, 0xa6, 0x97, 0x88,
583 0x80, 0xcb, 0x00, 0x00,
584 ];
585 let mut compound = Compound::parse(&data).unwrap();
586 let packet = compound.next().unwrap().unwrap();
587 matches!(packet, Packet::Sr(_));
588
589 let packet = compound.next().unwrap().unwrap();
590 matches!(packet, Packet::Bye(_));
591
592 assert!(compound.next().is_none());
593 }
594
595 #[test]
596 fn build_sr_bye() {
597 const REQ_LEN: usize = SenderReport::MIN_PACKET_LEN + Bye::MIN_PACKET_LEN;
598
599 let b = Compound::builder()
600 .add_packet(SenderReport::builder(0x1234567))
601 .add_packet(Bye::builder());
602
603 let mut data = [0; REQ_LEN];
604 let len = b.write_into(&mut data).unwrap();
605 assert_eq!(len, REQ_LEN);
606 assert_eq!(
607 data,
608 [
609 0x80, 0xc8, 0x00, 0x06, 0x01, 0x23, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x80, 0xcb, 0x00, 0x00,
612 ]
613 );
614 }
615
616 #[test]
617 fn build_rr_bye_padding() {
618 const REQ_LEN: usize = ReceiverReport::MIN_PACKET_LEN + Bye::MIN_PACKET_LEN + 4;
619
620 let b = Compound::builder()
621 .add_packet(ReceiverReport::builder(0x1234567))
622 .add_packet(Bye::builder().padding(4));
623
624 let mut data = [0; REQ_LEN];
625 let len = b.write_into(&mut data).unwrap();
626 assert_eq!(len, REQ_LEN);
627 assert_eq!(
628 data,
629 [
630 0x80, 0xc9, 0x00, 0x01, 0x01, 0x23, 0x45, 0x67, 0xa0, 0xcb, 0x00, 0x01, 0x00, 0x00,
631 0x00, 0x04,
632 ]
633 );
634 }
635
636 #[test]
637 fn parse_unknown() {
638 let data = [
639 0x80, 0xf2, 0x00, 0x02, 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00,
640 ];
641 let p = Packet::parse(&data).unwrap();
642 assert!(p.is_unknown());
643 assert_eq!(p.type_(), 242);
644 }
645
646 #[test]
647 fn build_app_padding_bye() {
648 let b = Compound::builder()
649 .add_packet(App::builder(0x91827364, "name").padding(4))
650 .add_packet(Bye::builder());
651
652 let err = b.calculate_size().unwrap_err();
653 assert_eq!(err, RtcpWriteError::NonLastCompoundPacketPadding);
654 }
655
656 #[test]
657 fn parse_rr_bye_wrong_first_len() {
658 let data = [
659 0x80, 0xc9, 0x00, 0x03, 0x91, 0x82, 0x73, 0x64, 0x80, 0xcb, 0x00, 0x00,
660 ];
661 let err = Compound::parse(&data).unwrap_err();
662 assert_eq!(
663 err,
664 RtcpParseError::Truncated {
665 expected: 16,
666 actual: 12
667 }
668 );
669 }
670
671 #[test]
672 fn parse_rr_truncated_bye() {
673 let data = [
674 0x80, 0xc9, 0x00, 0x01, 0x91, 0x82, 0x73, 0x64, 0x80, 0xcb, 0x00,
675 ];
676 let err = Compound::parse(&data).unwrap_err();
677 assert_eq!(
678 err,
679 RtcpParseError::Truncated {
680 expected: 12,
681 actual: 11
682 }
683 );
684 }
685
686 #[test]
687 fn parsing_failure_rr_bye() {
688 let data = [
689 0x81, 0xc9, 0x00, 0x01, 0x91, 0x82, 0x73, 0x64, 0x80, 0xcb, 0x00, 0x00,
690 ];
691 let mut compound = Compound::parse(&data).unwrap();
692
693 let err = compound.next().unwrap().unwrap_err();
695 assert_eq!(
696 err,
697 RtcpParseError::Truncated {
698 expected: 32,
699 actual: 8
700 }
701 );
702
703 assert!(compound.next().is_none());
704 }
705
706 #[test]
707 fn parse_packet_try_as_app() {
708 let data = [
709 0x80, 0xcc, 0x00, 0x02, 0x91, 0x82, 0x73, 0x64, 0x6e, 0x61, 0x6d, 0x65,
710 ];
711 let packet = Packet::parse(&data).unwrap();
712
713 let app = packet.try_as::<crate::App>().unwrap();
714 assert_eq!(app.name(), "name".as_bytes());
715
716 matches!(packet, Packet::App(_));
717 }
718
719 #[test]
720 fn parse_unknown_try_as_bye() {
721 let data = [0x81, 0xcb, 0x00, 0x01, 0x12, 0x34, 0x56, 0x78];
722 let unknown = Unknown::parse(&data).unwrap();
723
724 let bye = unknown.try_as::<crate::Bye>().unwrap();
725 let mut ssrcs = bye.ssrcs();
726 let ssrc = ssrcs.next().unwrap();
727 assert_eq!(ssrc, 0x12345678);
728 }
729}