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