xref: /webrtc/rtcp/src/raw_packet.rs (revision 5d8fe953)
1 use crate::{error::Error, header::*, packet::Packet, util::*};
2 
3 use util::marshal::{Marshal, MarshalSize, Unmarshal};
4 
5 use bytes::{Buf, BufMut, Bytes, BytesMut};
6 use std::any::Any;
7 use std::fmt;
8 
9 /// RawPacket represents an unparsed RTCP packet. It's returned by Unmarshal when
10 /// a packet with an unknown type is encountered.
11 #[derive(Debug, PartialEq, Eq, Default, Clone)]
12 pub struct RawPacket(pub Bytes);
13 
14 impl fmt::Display for RawPacket {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result15     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16         write!(f, "RawPacket: {self:?}")
17     }
18 }
19 
20 impl Packet for RawPacket {
21     /// Header returns the Header associated with this packet.
header(&self) -> Header22     fn header(&self) -> Header {
23         match Header::unmarshal(&mut self.0.clone()) {
24             Ok(h) => h,
25             Err(_) => Header::default(),
26         }
27     }
28 
29     /// destination_ssrc returns an array of SSRC values that this packet refers to.
destination_ssrc(&self) -> Vec<u32>30     fn destination_ssrc(&self) -> Vec<u32> {
31         vec![]
32     }
33 
raw_size(&self) -> usize34     fn raw_size(&self) -> usize {
35         self.0.len()
36     }
37 
as_any(&self) -> &(dyn Any + Send + Sync)38     fn as_any(&self) -> &(dyn Any + Send + Sync) {
39         self
40     }
41 
equal(&self, other: &(dyn Packet + Send + Sync)) -> bool42     fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
43         other
44             .as_any()
45             .downcast_ref::<RawPacket>()
46             .map_or(false, |a| self == a)
47     }
48 
cloned(&self) -> Box<dyn Packet + Send + Sync>49     fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
50         Box::new(self.clone())
51     }
52 }
53 
54 impl MarshalSize for RawPacket {
marshal_size(&self) -> usize55     fn marshal_size(&self) -> usize {
56         let l = self.raw_size();
57         // align to 32-bit boundary
58         l + get_padding_size(l)
59     }
60 }
61 
62 impl Marshal for RawPacket {
63     /// Marshal encodes the packet in binary.
marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error>64     fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error> {
65         let h = Header::unmarshal(&mut self.0.clone())?;
66         buf.put(self.0.clone());
67         if h.padding {
68             put_padding(buf, self.raw_size());
69         }
70         Ok(self.marshal_size())
71     }
72 }
73 
74 impl Unmarshal for RawPacket {
75     /// Unmarshal decodes the packet from binary.
unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error> where Self: Sized, B: Buf,76     fn unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error>
77     where
78         Self: Sized,
79         B: Buf,
80     {
81         let raw_packet_len = raw_packet.remaining();
82         if raw_packet_len < HEADER_LENGTH {
83             return Err(Error::PacketTooShort.into());
84         }
85 
86         let h = Header::unmarshal(raw_packet)?;
87 
88         let raw_hdr = h.marshal()?;
89         let raw_body = raw_packet.copy_to_bytes(raw_packet.remaining());
90         let mut raw = BytesMut::new();
91         raw.extend(raw_hdr);
92         raw.extend(raw_body);
93 
94         Ok(RawPacket(raw.freeze()))
95     }
96 }
97 
98 #[cfg(test)]
99 mod test {
100     use super::*;
101 
102     #[test]
test_raw_packet_roundtrip() -> Result<(), Error>103     fn test_raw_packet_roundtrip() -> Result<(), Error> {
104         let tests: Vec<(&str, RawPacket, Option<Error>)> = vec![
105             (
106                 "valid",
107                 RawPacket(Bytes::from_static(&[
108                     0x81, 0xcb, 0x00, 0x0c, // v=2, p=0, count=1, BYE, len=12
109                     0x90, 0x2f, 0x9e, 0x2e, // ssrc=0x902f9e2e
110                     0x03, 0x46, 0x4f, 0x4f, // len=3, text=FOO
111                 ])),
112                 None,
113             ),
114             (
115                 "short header",
116                 RawPacket(Bytes::from_static(&[0x80])),
117                 Some(Error::PacketTooShort),
118             ),
119             (
120                 "invalid header",
121                 RawPacket(
122                     // v=0, p=0, count=0, RR, len=4
123                     Bytes::from_static(&[0x00, 0xc9, 0x00, 0x04]),
124                 ),
125                 Some(Error::BadVersion),
126             ),
127         ];
128 
129         for (name, pkt, unmarshal_error) in tests {
130             let result = pkt.marshal();
131             assert_eq!(
132                 result.is_err(),
133                 unmarshal_error.is_some(),
134                 "Unmarshal {name}: err = {result:?}, want {unmarshal_error:?}"
135             );
136 
137             if result.is_err() {
138                 continue;
139             }
140 
141             let mut data = result.unwrap();
142 
143             let result = RawPacket::unmarshal(&mut data);
144 
145             assert_eq!(
146                 result.is_err(),
147                 unmarshal_error.is_some(),
148                 "Unmarshal {name}: err = {result:?}, want {unmarshal_error:?}"
149             );
150 
151             if result.is_err() {
152                 continue;
153             }
154 
155             let decoded = result.unwrap();
156 
157             assert_eq!(
158                 decoded, pkt,
159                 "{name} raw round trip: got {decoded:?}, want {pkt:?}"
160             )
161         }
162 
163         Ok(())
164     }
165 }
166