rtcp/
raw_packet.rs

1use std::any::Any;
2use std::fmt;
3
4use bytes::{Buf, BufMut, Bytes, BytesMut};
5use util::marshal::{Marshal, MarshalSize, Unmarshal};
6
7use crate::error::Error;
8use crate::header::*;
9use crate::packet::Packet;
10use crate::util::*;
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 + Send + Sync) {
39        self
40    }
41
42    fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
43        other.as_any().downcast_ref::<RawPacket>() == Some(self)
44    }
45
46    fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
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, util::Error> {
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, util::Error>
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.into());
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        let mut raw = BytesMut::new();
88        raw.extend(raw_hdr);
89        raw.extend(raw_body);
90
91        Ok(RawPacket(raw.freeze()))
92    }
93}
94
95#[cfg(test)]
96mod test {
97    use super::*;
98
99    #[test]
100    fn test_raw_packet_roundtrip() -> Result<(), Error> {
101        let tests: Vec<(&str, RawPacket, Option<Error>)> = vec![
102            (
103                "valid",
104                RawPacket(Bytes::from_static(&[
105                    0x81, 0xcb, 0x00, 0x0c, // v=2, p=0, count=1, BYE, len=12
106                    0x90, 0x2f, 0x9e, 0x2e, // ssrc=0x902f9e2e
107                    0x03, 0x46, 0x4f, 0x4f, // len=3, text=FOO
108                ])),
109                None,
110            ),
111            (
112                "short header",
113                RawPacket(Bytes::from_static(&[0x80])),
114                Some(Error::PacketTooShort),
115            ),
116            (
117                "invalid header",
118                RawPacket(
119                    // v=0, p=0, count=0, RR, len=4
120                    Bytes::from_static(&[0x00, 0xc9, 0x00, 0x04]),
121                ),
122                Some(Error::BadVersion),
123            ),
124        ];
125
126        for (name, pkt, unmarshal_error) in tests {
127            let result = pkt.marshal();
128            assert_eq!(
129                result.is_err(),
130                unmarshal_error.is_some(),
131                "Unmarshal {name}: err = {result:?}, want {unmarshal_error:?}"
132            );
133
134            if result.is_err() {
135                continue;
136            }
137
138            let mut data = result.unwrap();
139
140            let result = RawPacket::unmarshal(&mut data);
141
142            assert_eq!(
143                result.is_err(),
144                unmarshal_error.is_some(),
145                "Unmarshal {name}: err = {result:?}, want {unmarshal_error:?}"
146            );
147
148            if result.is_err() {
149                continue;
150            }
151
152            let decoded = result.unwrap();
153
154            assert_eq!(
155                decoded, pkt,
156                "{name} raw round trip: got {decoded:?}, want {pkt:?}"
157            )
158        }
159
160        Ok(())
161    }
162}