rtc_rtcp/
packet.rs

1use crate::{
2    goodbye::*, header::*, payload_feedbacks::full_intra_request::*,
3    payload_feedbacks::picture_loss_indication::*,
4    payload_feedbacks::receiver_estimated_maximum_bitrate::*,
5    payload_feedbacks::slice_loss_indication::*, raw_packet::*, receiver_report::*,
6    sender_report::*, source_description::*,
7    transport_feedbacks::rapid_resynchronization_request::*,
8    transport_feedbacks::transport_layer_cc::*, transport_feedbacks::transport_layer_nack::*,
9};
10use shared::{
11    error::{Error, Result},
12    marshal::{Marshal, Unmarshal},
13};
14
15use crate::extended_report::ExtendedReport;
16use bytes::{Buf, BufMut, BytesMut};
17use std::any::Any;
18use std::fmt;
19
20/// Packet represents an RTCP packet, a protocol used for out-of-band statistics and
21/// control information for an RTP session
22pub trait Packet: Send + Sync + Marshal + Unmarshal + fmt::Display + fmt::Debug {
23    fn header(&self) -> Header;
24    fn destination_ssrc(&self) -> Vec<u32>;
25    fn raw_size(&self) -> usize;
26    fn as_any(&self) -> &dyn Any;
27    fn equal(&self, other: &dyn Packet) -> bool;
28    fn cloned(&self) -> Box<dyn Packet>;
29}
30
31impl PartialEq for dyn Packet {
32    fn eq(&self, other: &Self) -> bool {
33        self.equal(other)
34    }
35}
36
37impl Clone for Box<dyn Packet> {
38    fn clone(&self) -> Box<dyn Packet> {
39        self.cloned()
40    }
41}
42
43/// marshal takes an array of Packets and serializes them to a single buffer
44pub fn marshal(packets: &[Box<dyn Packet>]) -> Result<BytesMut> {
45    let mut out = BytesMut::new();
46    for p in packets {
47        let data = p.marshal()?;
48        out.put(data);
49    }
50    Ok(out)
51}
52
53/// Unmarshal takes an entire udp datagram (which may consist of multiple RTCP packets) and
54/// returns the unmarshaled packets it contains.
55///
56/// If this is a reduced-size RTCP packet a feedback packet (Goodbye, SliceLossIndication, etc)
57/// will be returned. Otherwise, the underlying type of the returned packet will be
58/// CompoundPacket.
59pub fn unmarshal<B>(raw_data: &mut B) -> Result<Vec<Box<dyn Packet>>>
60where
61    B: Buf,
62{
63    let mut packets = vec![];
64
65    while raw_data.has_remaining() {
66        let p = unmarshaller(raw_data)?;
67        packets.push(p);
68    }
69
70    match packets.len() {
71        // Empty Packet
72        0 => Err(Error::InvalidHeader),
73
74        // Multiple Packet
75        _ => Ok(packets),
76    }
77}
78
79/// unmarshaller is a factory which pulls the first RTCP packet from a bytestream,
80/// and returns it's parsed representation, and the amount of data that was processed.
81pub(crate) fn unmarshaller<B>(raw_data: &mut B) -> Result<Box<dyn Packet>>
82where
83    B: Buf,
84{
85    let h = Header::unmarshal(raw_data)?;
86
87    let length = (h.length as usize) * 4;
88    if length > raw_data.remaining() {
89        return Err(Error::PacketTooShort);
90    }
91
92    let mut in_packet = h.marshal()?.chain(raw_data.take(length));
93
94    let p: Box<dyn Packet> = match h.packet_type {
95        PacketType::SenderReport => Box::new(SenderReport::unmarshal(&mut in_packet)?),
96        PacketType::ReceiverReport => Box::new(ReceiverReport::unmarshal(&mut in_packet)?),
97        PacketType::SourceDescription => Box::new(SourceDescription::unmarshal(&mut in_packet)?),
98        PacketType::Goodbye => Box::new(Goodbye::unmarshal(&mut in_packet)?),
99
100        PacketType::TransportSpecificFeedback => match h.count {
101            FORMAT_TLN => Box::new(TransportLayerNack::unmarshal(&mut in_packet)?),
102            FORMAT_RRR => Box::new(RapidResynchronizationRequest::unmarshal(&mut in_packet)?),
103            FORMAT_TCC => Box::new(TransportLayerCc::unmarshal(&mut in_packet)?),
104            _ => Box::new(RawPacket::unmarshal(&mut in_packet)?),
105        },
106        PacketType::PayloadSpecificFeedback => match h.count {
107            FORMAT_PLI => Box::new(PictureLossIndication::unmarshal(&mut in_packet)?),
108            FORMAT_SLI => Box::new(SliceLossIndication::unmarshal(&mut in_packet)?),
109            FORMAT_REMB => Box::new(ReceiverEstimatedMaximumBitrate::unmarshal(&mut in_packet)?),
110            FORMAT_FIR => Box::new(FullIntraRequest::unmarshal(&mut in_packet)?),
111            _ => Box::new(RawPacket::unmarshal(&mut in_packet)?),
112        },
113        PacketType::ExtendedReport => Box::new(ExtendedReport::unmarshal(&mut in_packet)?),
114        _ => Box::new(RawPacket::unmarshal(&mut in_packet)?),
115    };
116
117    Ok(p)
118}
119
120#[cfg(test)]
121mod test {
122    use super::*;
123    use crate::reception_report::*;
124    use bytes::Bytes;
125
126    #[test]
127    fn test_packet_unmarshal() {
128        let mut data = Bytes::from_static(&[
129            // Receiver Report (offset=0)
130            0x81, 0xc9, 0x0, 0x7, // v=2, p=0, count=1, RR, len=7
131            0x90, 0x2f, 0x9e, 0x2e, // ssrc=0x902f9e2e
132            0xbc, 0x5e, 0x9a, 0x40, // ssrc=0xbc5e9a40
133            0x0, 0x0, 0x0, 0x0, // fracLost=0, totalLost=0
134            0x0, 0x0, 0x46, 0xe1, // lastSeq=0x46e1
135            0x0, 0x0, 0x1, 0x11, // jitter=273
136            0x9, 0xf3, 0x64, 0x32, // lsr=0x9f36432
137            0x0, 0x2, 0x4a, 0x79, // delay=150137
138            // Source Description (offset=32)
139            0x81, 0xca, 0x0, 0xc, // v=2, p=0, count=1, SDES, len=12
140            0x90, 0x2f, 0x9e, 0x2e, // ssrc=0x902f9e2e
141            0x1, 0x26, // CNAME, len=38
142            0x7b, 0x39, 0x63, 0x30, 0x30, 0x65, 0x62, 0x39, 0x32, 0x2d, 0x31, 0x61, 0x66, 0x62,
143            0x2d, 0x39, 0x64, 0x34, 0x39, 0x2d, 0x61, 0x34, 0x37, 0x64, 0x2d, 0x39, 0x31, 0x66,
144            0x36, 0x34, 0x65, 0x65, 0x65, 0x36, 0x39, 0x66, 0x35,
145            0x7d, // text="{9c00eb92-1afb-9d49-a47d-91f64eee69f5}"
146            0x0, 0x0, 0x0, 0x0, // END + padding
147            // Goodbye (offset=84)
148            0x81, 0xcb, 0x0, 0x1, // v=2, p=0, count=1, BYE, len=1
149            0x90, 0x2f, 0x9e, 0x2e, // source=0x902f9e2e
150            0x81, 0xce, 0x0, 0x2, // Picture Loss Indication (offset=92)
151            0x90, 0x2f, 0x9e, 0x2e, // sender=0x902f9e2e
152            0x90, 0x2f, 0x9e, 0x2e, // media=0x902f9e2e
153            0x85, 0xcd, 0x0, 0x2, // RapidResynchronizationRequest (offset=104)
154            0x90, 0x2f, 0x9e, 0x2e, // sender=0x902f9e2e
155            0x90, 0x2f, 0x9e, 0x2e, // media=0x902f9e2e
156        ]);
157
158        let packet = unmarshal(&mut data).expect("Error unmarshalling packets");
159
160        let a = ReceiverReport {
161            ssrc: 0x902f9e2e,
162            reports: vec![ReceptionReport {
163                ssrc: 0xbc5e9a40,
164                fraction_lost: 0,
165                total_lost: 0,
166                last_sequence_number: 0x46e1,
167                jitter: 273,
168                last_sender_report: 0x9f36432,
169                delay: 150137,
170            }],
171            ..Default::default()
172        };
173
174        let b = SourceDescription {
175            chunks: vec![SourceDescriptionChunk {
176                source: 0x902f9e2e,
177                items: vec![SourceDescriptionItem {
178                    sdes_type: SdesType::SdesCname,
179                    text: Bytes::from_static(b"{9c00eb92-1afb-9d49-a47d-91f64eee69f5}"),
180                }],
181            }],
182        };
183
184        let c = Goodbye {
185            sources: vec![0x902f9e2e],
186            ..Default::default()
187        };
188
189        let d = PictureLossIndication {
190            sender_ssrc: 0x902f9e2e,
191            media_ssrc: 0x902f9e2e,
192        };
193
194        let e = RapidResynchronizationRequest {
195            sender_ssrc: 0x902f9e2e,
196            media_ssrc: 0x902f9e2e,
197        };
198
199        let expected: Vec<Box<dyn Packet>> = vec![
200            Box::new(a),
201            Box::new(b),
202            Box::new(c),
203            Box::new(d),
204            Box::new(e),
205        ];
206
207        assert!(packet == expected, "Invalid packets");
208    }
209
210    #[test]
211    fn test_packet_unmarshal_empty() -> Result<()> {
212        let result = unmarshal(&mut Bytes::new());
213        if let Err(got) = result {
214            let want = Error::InvalidHeader;
215            assert_eq!(got, want, "Unmarshal(nil) err = {got}, want {want}");
216        } else {
217            panic!("want error");
218        }
219
220        Ok(())
221    }
222
223    #[test]
224    fn test_packet_invalid_header_length() -> Result<()> {
225        let mut data = Bytes::from_static(&[
226            // Goodbye (offset=84)
227            // v=2, p=0, count=1, BYE, len=100
228            0x81, 0xcb, 0x0, 0x64,
229        ]);
230
231        let result = unmarshal(&mut data);
232        if let Err(got) = result {
233            let want = Error::PacketTooShort;
234            assert_eq!(
235                got, want,
236                "Unmarshal(invalid_header_length) err = {got}, want {want}"
237            );
238        } else {
239            panic!("want error");
240        }
241
242        Ok(())
243    }
244    #[test]
245    fn test_packet_unmarshal_firefox() -> Result<()> {
246        // issue report from https://github.com/webrtc-rs/srtp/issues/7
247        let tests = vec![
248            Bytes::from_static(&[
249                143, 205, 0, 6, 65, 227, 184, 49, 118, 243, 78, 96, 42, 63, 0, 5, 12, 162, 166, 0,
250                32, 5, 200, 4, 0, 4, 0, 0,
251            ]),
252            Bytes::from_static(&[
253                143, 205, 0, 9, 65, 227, 184, 49, 118, 243, 78, 96, 42, 68, 0, 17, 12, 162, 167, 1,
254                32, 17, 88, 0, 4, 0, 4, 8, 108, 0, 4, 0, 4, 12, 0, 4, 0, 4, 4, 0,
255            ]),
256            Bytes::from_static(&[
257                143, 205, 0, 8, 65, 227, 184, 49, 118, 243, 78, 96, 42, 91, 0, 12, 12, 162, 168, 3,
258                32, 12, 220, 4, 0, 4, 0, 8, 128, 4, 0, 4, 0, 8, 0, 0,
259            ]),
260            Bytes::from_static(&[
261                143, 205, 0, 7, 65, 227, 184, 49, 118, 243, 78, 96, 42, 103, 0, 8, 12, 162, 169, 4,
262                32, 8, 232, 4, 0, 4, 0, 4, 4, 0, 0, 0,
263            ]),
264        ];
265
266        for mut test in tests {
267            unmarshal(&mut test)?;
268        }
269
270        Ok(())
271    }
272}