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