1 use crate::error::Error; 2 use util::marshal::{Marshal, MarshalSize, Unmarshal}; 3 4 use bytes::{Buf, BufMut}; 5 6 /// PacketType specifies the type of an RTCP packet 7 /// RTCP packet types registered with IANA. See: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4 8 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] 9 #[repr(u8)] 10 pub enum PacketType { 11 #[default] 12 Unsupported = 0, 13 SenderReport = 200, // RFC 3550, 6.4.1 14 ReceiverReport = 201, // RFC 3550, 6.4.2 15 SourceDescription = 202, // RFC 3550, 6.5 16 Goodbye = 203, // RFC 3550, 6.6 17 ApplicationDefined = 204, // RFC 3550, 6.7 (unimplemented) 18 TransportSpecificFeedback = 205, // RFC 4585, 6051 19 PayloadSpecificFeedback = 206, // RFC 4585, 6.3 20 ExtendedReport = 207, // RFC 3611 21 } 22 23 /// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here 24 pub const FORMAT_SLI: u8 = 2; 25 /// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here 26 pub const FORMAT_PLI: u8 = 1; 27 /// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here 28 pub const FORMAT_FIR: u8 = 4; 29 /// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here 30 pub const FORMAT_TLN: u8 = 1; 31 /// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here 32 pub const FORMAT_RRR: u8 = 5; 33 /// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here 34 pub const FORMAT_REMB: u8 = 15; 35 /// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here. 36 /// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5 37 pub const FORMAT_TCC: u8 = 15; 38 39 impl std::fmt::Display for PacketType { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 41 let s = match self { 42 PacketType::Unsupported => "Unsupported", 43 PacketType::SenderReport => "SR", 44 PacketType::ReceiverReport => "RR", 45 PacketType::SourceDescription => "SDES", 46 PacketType::Goodbye => "BYE", 47 PacketType::ApplicationDefined => "APP", 48 PacketType::TransportSpecificFeedback => "TSFB", 49 PacketType::PayloadSpecificFeedback => "PSFB", 50 PacketType::ExtendedReport => "XR", 51 }; 52 write!(f, "{s}") 53 } 54 } 55 56 impl From<u8> for PacketType { from(b: u8) -> Self57 fn from(b: u8) -> Self { 58 match b { 59 200 => PacketType::SenderReport, // RFC 3550, 6.4.1 60 201 => PacketType::ReceiverReport, // RFC 3550, 6.4.2 61 202 => PacketType::SourceDescription, // RFC 3550, 6.5 62 203 => PacketType::Goodbye, // RFC 3550, 6.6 63 204 => PacketType::ApplicationDefined, // RFC 3550, 6.7 (unimplemented) 64 205 => PacketType::TransportSpecificFeedback, // RFC 4585, 6051 65 206 => PacketType::PayloadSpecificFeedback, // RFC 4585, 6.3 66 207 => PacketType::ExtendedReport, // RFC 3611 67 _ => PacketType::Unsupported, 68 } 69 } 70 } 71 72 pub const RTP_VERSION: u8 = 2; 73 pub const VERSION_SHIFT: u8 = 6; 74 pub const VERSION_MASK: u8 = 0x3; 75 pub const PADDING_SHIFT: u8 = 5; 76 pub const PADDING_MASK: u8 = 0x1; 77 pub const COUNT_SHIFT: u8 = 0; 78 pub const COUNT_MASK: u8 = 0x1f; 79 80 pub const HEADER_LENGTH: usize = 4; 81 pub const COUNT_MAX: usize = (1 << 5) - 1; 82 pub const SSRC_LENGTH: usize = 4; 83 pub const SDES_MAX_OCTET_COUNT: usize = (1 << 8) - 1; 84 85 /// A Header is the common header shared by all RTCP packets 86 #[derive(Debug, PartialEq, Eq, Default, Clone)] 87 pub struct Header { 88 /// If the padding bit is set, this individual RTCP packet contains 89 /// some additional padding octets at the end which are not part of 90 /// the control information but are included in the length field. 91 pub padding: bool, 92 /// The number of reception reports, sources contained or FMT in this packet (depending on the Type) 93 pub count: u8, 94 /// The RTCP packet type for this packet 95 pub packet_type: PacketType, 96 /// The length of this RTCP packet in 32-bit words minus one, 97 /// including the header and any padding. 98 pub length: u16, 99 } 100 101 /// Marshal encodes the Header in binary 102 impl MarshalSize for Header { marshal_size(&self) -> usize103 fn marshal_size(&self) -> usize { 104 HEADER_LENGTH 105 } 106 } 107 108 impl Marshal for Header { marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error>109 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error> { 110 if self.count > 31 { 111 return Err(Error::InvalidHeader.into()); 112 } 113 if buf.remaining_mut() < HEADER_LENGTH { 114 return Err(Error::BufferTooShort.into()); 115 } 116 117 /* 118 * 0 1 2 3 119 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 120 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 121 * |V=2|P| RC | PT=SR=200 | length | 122 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 123 */ 124 let b0 = (RTP_VERSION << VERSION_SHIFT) 125 | ((self.padding as u8) << PADDING_SHIFT) 126 | (self.count << COUNT_SHIFT); 127 128 buf.put_u8(b0); 129 buf.put_u8(self.packet_type as u8); 130 buf.put_u16(self.length); 131 132 Ok(HEADER_LENGTH) 133 } 134 } 135 136 impl Unmarshal for Header { 137 /// Unmarshal decodes the Header from binary unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error> where Self: Sized, B: Buf,138 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error> 139 where 140 Self: Sized, 141 B: Buf, 142 { 143 if raw_packet.remaining() < HEADER_LENGTH { 144 return Err(Error::PacketTooShort.into()); 145 } 146 147 /* 148 * 0 1 2 3 149 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 150 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 151 * |V=2|P| RC | PT | length | 152 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 153 */ 154 let b0 = raw_packet.get_u8(); 155 let version = (b0 >> VERSION_SHIFT) & VERSION_MASK; 156 if version != RTP_VERSION { 157 return Err(Error::BadVersion.into()); 158 } 159 160 let padding = ((b0 >> PADDING_SHIFT) & PADDING_MASK) > 0; 161 let count = (b0 >> COUNT_SHIFT) & COUNT_MASK; 162 let packet_type = PacketType::from(raw_packet.get_u8()); 163 let length = raw_packet.get_u16(); 164 165 Ok(Header { 166 padding, 167 count, 168 packet_type, 169 length, 170 }) 171 } 172 } 173 174 #[cfg(test)] 175 mod test { 176 use super::*; 177 use bytes::Bytes; 178 179 #[test] test_header_unmarshal()180 fn test_header_unmarshal() { 181 let tests = vec![ 182 ( 183 "valid", 184 Bytes::from_static(&[ 185 // v=2, p=0, count=1, RR, len=7 186 0x81u8, 0xc9, 0x00, 0x07, 187 ]), 188 Header { 189 padding: false, 190 count: 1, 191 packet_type: PacketType::ReceiverReport, 192 length: 7, 193 }, 194 None, 195 ), 196 ( 197 "also valid", 198 Bytes::from_static(&[ 199 // v=2, p=1, count=1, BYE, len=7 200 0xa1, 0xcc, 0x00, 0x07, 201 ]), 202 Header { 203 padding: true, 204 count: 1, 205 packet_type: PacketType::ApplicationDefined, 206 length: 7, 207 }, 208 None, 209 ), 210 ( 211 "bad version", 212 Bytes::from_static(&[ 213 // v=0, p=0, count=0, RR, len=4 214 0x00, 0xc9, 0x00, 0x04, 215 ]), 216 Header { 217 padding: false, 218 count: 0, 219 packet_type: PacketType::Unsupported, 220 length: 0, 221 }, 222 Some(Error::BadVersion), 223 ), 224 ]; 225 226 for (name, data, want, want_error) in tests { 227 let buf = &mut data.clone(); 228 let got = Header::unmarshal(buf); 229 230 assert_eq!( 231 got.is_err(), 232 want_error.is_some(), 233 "Unmarshal {name}: err = {got:?}, want {want_error:?}" 234 ); 235 236 if let Some(want_error) = want_error { 237 let got_err = got.err().unwrap(); 238 assert_eq!( 239 want_error, got_err, 240 "Unmarshal {name}: err = {got_err:?}, want {want_error:?}", 241 ); 242 } else { 243 let actual = got.unwrap(); 244 assert_eq!( 245 actual, want, 246 "Unmarshal {name}: got {actual:?}, want {want:?}" 247 ); 248 } 249 } 250 } 251 252 #[test] test_header_roundtrip()253 fn test_header_roundtrip() { 254 let tests = vec![ 255 ( 256 "valid", 257 Header { 258 padding: true, 259 count: 31, 260 packet_type: PacketType::SenderReport, 261 length: 4, 262 }, 263 None, 264 ), 265 ( 266 "also valid", 267 Header { 268 padding: false, 269 count: 28, 270 packet_type: PacketType::ReceiverReport, 271 length: 65535, 272 }, 273 None, 274 ), 275 ( 276 "invalid count", 277 Header { 278 padding: false, 279 count: 40, 280 packet_type: PacketType::Unsupported, 281 length: 0, 282 }, 283 Some(Error::InvalidHeader), 284 ), 285 ]; 286 287 for (name, want, want_error) in tests { 288 let got = want.marshal(); 289 290 assert_eq!( 291 got.is_ok(), 292 want_error.is_none(), 293 "Marshal {name}: err = {got:?}, want {want_error:?}" 294 ); 295 296 if let Some(err) = want_error { 297 let got_err = got.err().unwrap(); 298 assert_eq!( 299 err, got_err, 300 "Unmarshal {name} rr: err = {got_err:?}, want {err:?}", 301 ); 302 } else { 303 let data = got.ok().unwrap(); 304 let buf = &mut data.clone(); 305 let actual = Header::unmarshal(buf).unwrap_or_else(|_| panic!("Unmarshal {name}")); 306 307 assert_eq!( 308 actual, want, 309 "{name} round trip: got {actual:?}, want {want:?}" 310 ) 311 } 312 } 313 } 314 } 315