Skip to main content

rtc_rtcp/
raw_packet.rs

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