xref: /webrtc/rtcp/src/packet.rs (revision 259fddd2)
1 use std::io::{BufReader, Read, Write};
2 
3 use util::Error;
4 
5 use super::compound_packet::*;
6 use super::errors::*;
7 use super::full_intra_request::*;
8 use super::goodbye::*;
9 use super::header::*;
10 use super::picture_loss_indication::*;
11 use super::rapid_resynchronization_request::*;
12 use super::raw_packet::*;
13 use super::receiver_estimated_maximum_bitrate::*;
14 use super::receiver_report::*;
15 use super::sender_report::*;
16 use super::slice_loss_indication::*;
17 use super::source_description::*;
18 use super::transport_layer_cc::*;
19 use super::transport_layer_nack::*;
20 
21 #[cfg(test)]
22 mod packet_test;
23 
24 // Packet represents an RTCP packet, a protocol used for out-of-band statistics and control information for an RTP session
25 #[derive(Debug, Clone)]
26 pub enum Packet {
27     SenderReport(SenderReport),
28     ReceiverReport(ReceiverReport),
29     SourceDescription(SourceDescription),
30     Goodbye(Goodbye),
31     RawPacket(RawPacket),
32 
33     TransportLayerNack(TransportLayerNack),
34     RapidResynchronizationRequest(RapidResynchronizationRequest),
35     TransportLayerCC(TransportLayerCC),
36 
37     PictureLossIndication(PictureLossIndication),
38     SliceLossIndication(SliceLossIndication),
39     ReceiverEstimatedMaximumBitrate(ReceiverEstimatedMaximumBitrate),
40     FullIntraRequest(FullIntraRequest),
41 
42     CompoundPacket(CompoundPacket),
43 }
44 
45 impl Packet {
46     pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
47         match self {
48             Packet::SenderReport(p) => p.marshal(writer)?,
49             Packet::ReceiverReport(p) => p.marshal(writer)?,
50             Packet::SourceDescription(p) => p.marshal(writer)?,
51             Packet::Goodbye(p) => p.marshal(writer)?,
52             Packet::RawPacket(p) => p.marshal(writer)?,
53 
54             Packet::TransportLayerNack(p) => p.marshal(writer)?,
55             Packet::RapidResynchronizationRequest(p) => p.marshal(writer)?,
56             Packet::TransportLayerCC(p) => p.marshal(writer)?,
57 
58             Packet::PictureLossIndication(p) => p.marshal(writer)?,
59             Packet::SliceLossIndication(p) => p.marshal(writer)?,
60             Packet::ReceiverEstimatedMaximumBitrate(p) => p.marshal(writer)?,
61             Packet::FullIntraRequest(p) => p.marshal(writer)?,
62 
63             Packet::CompoundPacket(p) => p.marshal(writer)?,
64         };
65         Ok(())
66     }
67 
68     pub fn destination_ssrc(&self) -> Vec<u32> {
69         match self {
70             Packet::SenderReport(p) => p.destination_ssrc(),
71             Packet::ReceiverReport(p) => p.destination_ssrc(),
72             Packet::SourceDescription(p) => p.destination_ssrc(),
73             Packet::Goodbye(p) => p.destination_ssrc(),
74             Packet::RawPacket(p) => p.destination_ssrc(),
75 
76             Packet::TransportLayerNack(p) => p.destination_ssrc(),
77             Packet::RapidResynchronizationRequest(p) => p.destination_ssrc(),
78             Packet::TransportLayerCC(p) => p.destination_ssrc(),
79 
80             Packet::PictureLossIndication(p) => p.destination_ssrc(),
81             Packet::SliceLossIndication(p) => p.destination_ssrc(),
82             Packet::ReceiverEstimatedMaximumBitrate(p) => p.destination_ssrc(),
83             Packet::FullIntraRequest(p) => p.destination_ssrc(),
84 
85             Packet::CompoundPacket(p) => p.destination_ssrc(),
86         }
87     }
88 }
89 
90 //Marshal takes an array of Packets and serializes them to a single buffer
91 pub fn marshal<W: Write>(packets: &[Packet], writer: &mut W) -> Result<(), Error> {
92     for packet in packets {
93         packet.marshal(writer)?;
94     }
95     Ok(())
96 }
97 
98 // Unmarshal takes an entire udp datagram (which may consist of multiple RTCP packets) and
99 // returns the unmarshaled packets it contains.
100 //
101 // If this is a reduced-size RTCP packet a feedback packet (Goodbye, SliceLossIndication, etc)
102 // will be returned. Otherwise, the underlying type of the returned packet will be
103 // CompoundPacket.
104 pub fn unmarshal(mut raw_data: &[u8]) -> Result<Packet, Error> {
105     let mut packets = vec![];
106     while !raw_data.is_empty() {
107         if raw_data.len() < HEADER_LENGTH {
108             return Err(ERR_PACKET_TOO_SHORT.clone());
109         }
110         let mut header_reader = BufReader::new(&raw_data[0..HEADER_LENGTH]);
111         let header = Header::unmarshal(&mut header_reader)?;
112 
113         let bytes_processed = (header.length + 1) as usize * 4;
114         if bytes_processed > raw_data.len() {
115             return Err(ERR_PACKET_TOO_SHORT.clone());
116         }
117         let mut reader = BufReader::new(&raw_data[0..bytes_processed]);
118         let packet = unmarshaler(&mut reader, &header)?;
119         packets.push(packet);
120         raw_data = &raw_data[bytes_processed..];
121     }
122 
123     match packets.len() {
124         // Empty packet
125         0 => Err(ERR_INVALID_HEADER.clone()),
126         1 => packets.pop().ok_or_else(|| ERR_BAD_FIRST_PACKET.clone()),
127         // Multiple Packets
128         _ => Ok(Packet::CompoundPacket(CompoundPacket(packets))),
129     }
130 }
131 
132 // unmarshaler is a factory which pulls the first RTCP packet from a bytestream,
133 // and returns it's parsed representation, and the amount of data that was processed.
134 fn unmarshaler<R: Read>(reader: &mut R, header: &Header) -> Result<Packet, Error> {
135     match header.packet_type {
136         PacketType::SenderReport => Ok(Packet::SenderReport(SenderReport::unmarshal(reader)?)),
137         PacketType::ReceiverReport => {
138             Ok(Packet::ReceiverReport(ReceiverReport::unmarshal(reader)?))
139         }
140         PacketType::SourceDescription => Ok(Packet::SourceDescription(
141             SourceDescription::unmarshal(reader)?,
142         )),
143         PacketType::Goodbye => Ok(Packet::Goodbye(Goodbye::unmarshal(reader)?)),
144         PacketType::TransportSpecificFeedback => match header.count {
145             FORMAT_TLN => Ok(Packet::TransportLayerNack(TransportLayerNack::unmarshal(
146                 reader,
147             )?)),
148             FORMAT_RRR => Ok(Packet::RapidResynchronizationRequest(
149                 RapidResynchronizationRequest::unmarshal(reader)?,
150             )),
151             FORMAT_TCC => Ok(Packet::TransportLayerCC(TransportLayerCC::unmarshal(
152                 reader,
153             )?)),
154             _ => Ok(Packet::RawPacket(RawPacket::unmarshal(reader)?)),
155         },
156         PacketType::PayloadSpecificFeedback => match header.count {
157             FORMAT_PLI => Ok(Packet::PictureLossIndication(
158                 PictureLossIndication::unmarshal(reader)?,
159             )),
160             FORMAT_SLI => Ok(Packet::SliceLossIndication(SliceLossIndication::unmarshal(
161                 reader,
162             )?)),
163             FORMAT_REMB => Ok(Packet::ReceiverEstimatedMaximumBitrate(
164                 ReceiverEstimatedMaximumBitrate::unmarshal(reader)?,
165             )),
166             FORMAT_FIR => Ok(Packet::FullIntraRequest(FullIntraRequest::unmarshal(
167                 reader,
168             )?)),
169             _ => Ok(Packet::RawPacket(RawPacket::unmarshal(reader)?)),
170         },
171         _ => Ok(Packet::RawPacket(RawPacket::unmarshal(reader)?)),
172     }
173 }
174