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