1 use std::io::{Read, Write}; 2 3 use util::Error; 4 5 use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; 6 7 const HEADER_LENGTH: usize = 4; 8 const VERSION_SHIFT: u8 = 6; 9 const VERSION_MASK: u8 = 0x3; 10 const PADDING_SHIFT: u8 = 5; 11 const PADDING_MASK: u8 = 0x1; 12 const EXTENSION_SHIFT: u8 = 4; 13 const EXTENSION_MASK: u8 = 0x1; 14 const EXTENSION_PROFILE_ONE_BYTE: u16 = 0xBEDE; 15 const EXTENSION_PROFILE_TWO_BYTE: u16 = 0x1000; 16 const EXTENSION_ID_RESERVED: u8 = 0xF; 17 const CC_MASK: u8 = 0xF; 18 const MARKER_SHIFT: u8 = 7; 19 const MARKER_MASK: u8 = 0x1; 20 const PT_MASK: u8 = 0x7F; 21 const SEQ_NUM_OFFSET: usize = 2; 22 const SEQ_NUM_LENGTH: usize = 2; 23 const TIMESTAMP_OFFSET: usize = 4; 24 const TIMESTAMP_LENGTH: usize = 4; 25 const SSRC_OFFSET: usize = 8; 26 const SSRC_LENGTH: usize = 4; 27 const CSRC_OFFSET: usize = 12; 28 const CSRC_LENGTH: usize = 4; 29 30 #[derive(Debug, Eq, PartialEq, Default)] 31 pub struct Extension { 32 pub id: u8, 33 pub payload: Vec<u8>, 34 } 35 36 // Header represents an RTP packet header 37 // NOTE: PayloadOffset is populated by Marshal/Unmarshal and should not be modified 38 #[derive(Debug, Eq, PartialEq, Default)] 39 pub struct Header { 40 pub version: u8, 41 pub padding: bool, 42 pub extension: bool, 43 pub marker: bool, 44 pub payload_type: u8, 45 pub sequence_number: u16, 46 pub timestamp: u32, 47 pub ssrc: u32, 48 pub csrc: Vec<u32>, 49 pub extension_profile: u16, 50 pub extensions: Vec<Extension>, 51 52 pub payload_offset: usize, 53 } 54 55 impl Header { 56 // MarshalSize returns the size of the packet once marshaled. 57 pub fn size(&self) -> usize { 58 let mut head_size = 12 + (self.csrc.len() * CSRC_LENGTH); 59 if self.extension { 60 head_size += 4 + self.get_extension_payload_len(); 61 } 62 head_size 63 } 64 65 fn get_extension_payload_len(&self) -> usize { 66 let mut extension_length = 0; 67 match self.extension_profile { 68 EXTENSION_PROFILE_ONE_BYTE => { 69 for extension in &self.extensions { 70 extension_length += 1 + extension.payload.len(); 71 } 72 } 73 EXTENSION_PROFILE_TWO_BYTE => { 74 for extension in &self.extensions { 75 extension_length += 2 + extension.payload.len(); 76 } 77 } 78 _ => { 79 for extension in &self.extensions { 80 extension_length += extension.payload.len(); 81 } 82 } 83 }; 84 85 extension_length 86 } 87 88 // SetExtension sets an RTP header extension 89 pub fn set_extension(&mut self, id: u8, payload: &[u8]) -> Result<(), Error> { 90 if self.extension { 91 match self.extension_profile { 92 EXTENSION_PROFILE_ONE_BYTE => { 93 if id < 1 || id > 14 { 94 return Err(Error::new( 95 "header extension id must be between 1 and 14 for RFC 5285 extensions" 96 .to_owned(), 97 )); 98 } 99 if payload.len() > 16 { 100 return Err(Error::new("header extension payload must be 16bytes or less for RFC 5285 one byte extensions".to_owned())); 101 } 102 } 103 EXTENSION_PROFILE_TWO_BYTE => { 104 if id < 1 { 105 return Err(Error::new( 106 "header extension id must be between 1 and 255 for RFC 5285 extensions" 107 .to_owned(), 108 )); 109 } 110 if payload.len() > 255 { 111 return Err(Error::new("header extension payload must be 255bytes or less for RFC 5285 two byte extensions".to_owned())); 112 } 113 } 114 _ => { 115 if id != 0 { 116 return Err(Error::new( 117 "header extension id must be 0 for none RFC 5285 extensions".to_owned(), 118 )); 119 } 120 } 121 }; 122 123 // Update existing if it exists else add new extension 124 for extension in &mut self.extensions { 125 if extension.id == id { 126 extension.payload.clear(); 127 extension.payload.extend_from_slice(payload); 128 return Ok(()); 129 } 130 } 131 self.extensions.push(Extension { 132 id, 133 payload: payload.to_vec(), 134 }); 135 return Ok(()); 136 } 137 138 // No existing header extensions 139 self.extension = true; 140 141 let len = payload.len(); 142 if len <= 16 { 143 self.extension_profile = EXTENSION_PROFILE_ONE_BYTE 144 } else if len > 16 && len < 256 { 145 self.extension_profile = EXTENSION_PROFILE_TWO_BYTE 146 } 147 148 self.extensions.push(Extension { 149 id, 150 payload: payload.to_vec(), 151 }); 152 153 Ok(()) 154 } 155 156 // returns an RTP header extension 157 pub fn get_extension(&self, id: u8) -> Option<&[u8]> { 158 if !self.extension { 159 return None; 160 } 161 162 for extension in &self.extensions { 163 if extension.id == id { 164 return Some(&extension.payload); 165 } 166 } 167 None 168 } 169 170 // Removes an RTP Header extension 171 pub fn del_extension(&mut self, id: u8) -> Result<(), Error> { 172 if !self.extension { 173 return Err(Error::new("extension not enabled".to_owned())); 174 } 175 for index in 0..self.extensions.len() { 176 if self.extensions[index].id == id { 177 self.extensions.remove(index); 178 return Ok(()); 179 } 180 } 181 Err(Error::new("extension not found".to_owned())) 182 } 183 184 // Unmarshal parses the passed byte slice and stores the result in the Header this method is called upon 185 pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self, Error> { 186 /* 187 * 0 1 2 3 188 * 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 189 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 190 * |V=2|P|X| CC |M| PT | sequence number | 191 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 192 * | timestamp | 193 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 194 * | synchronization source (SSRC) identifier | 195 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 196 * | contributing source (CSRC) identifiers | 197 * | .... | 198 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 199 */ 200 201 let b0 = reader.read_u8()?; 202 let version = b0 >> VERSION_SHIFT & VERSION_MASK; 203 let padding = (b0 >> PADDING_SHIFT & PADDING_MASK) > 0; 204 let extension = (b0 >> EXTENSION_SHIFT & EXTENSION_MASK) > 0; 205 let cc = (b0 & CC_MASK) as usize; 206 207 let b1 = reader.read_u8()?; 208 let marker = (b1 >> MARKER_SHIFT & MARKER_MASK) > 0; 209 let payload_type = b1 & PT_MASK; 210 211 let sequence_number = reader.read_u16::<BigEndian>()?; 212 let timestamp = reader.read_u32::<BigEndian>()?; 213 let ssrc = reader.read_u32::<BigEndian>()?; 214 215 let mut payload_offset = CSRC_OFFSET + (cc * CSRC_LENGTH); 216 let mut csrc = vec![]; 217 for _i in 0..cc { 218 csrc.push(reader.read_u32::<BigEndian>()?); 219 } 220 221 let (extension_profile, extensions) = if extension { 222 let extension_profile = reader.read_u16::<BigEndian>()?; 223 payload_offset += 2; 224 let extension_length = reader.read_u16::<BigEndian>()? as usize * 4; 225 payload_offset += 2; 226 227 let mut payload = vec![0; extension_length]; 228 reader.read_exact(&mut payload)?; 229 payload_offset += payload.len(); 230 231 let mut extensions = vec![]; 232 match extension_profile { 233 // RFC 8285 RTP One Byte Header Extension 234 EXTENSION_PROFILE_ONE_BYTE => { 235 let mut curr_offset = 0; 236 while curr_offset < extension_length { 237 if payload[curr_offset] == 0x00 { 238 // padding 239 curr_offset += 1; 240 continue; 241 } 242 243 let extid = payload[curr_offset] >> 4; 244 let len = ((payload[curr_offset] & (0xFF ^ 0xF0)) + 1) as usize; 245 curr_offset += 1; 246 247 if extid == EXTENSION_ID_RESERVED { 248 break; 249 } 250 251 extensions.push(Extension { 252 id: extid, 253 payload: payload[curr_offset..curr_offset + len].to_vec(), 254 }); 255 curr_offset += len; 256 } 257 } 258 // RFC 8285 RTP Two Byte Header Extension 259 EXTENSION_PROFILE_TWO_BYTE => { 260 let mut curr_offset = 0; 261 while curr_offset < extension_length { 262 if payload[curr_offset] == 0x00 { 263 // padding 264 curr_offset += 1; 265 continue; 266 } 267 268 let extid = payload[curr_offset]; 269 curr_offset += 1; 270 271 let len = payload[curr_offset] as usize; 272 curr_offset += 1; 273 274 extensions.push(Extension { 275 id: extid, 276 payload: payload[curr_offset..curr_offset + len].to_vec(), 277 }); 278 curr_offset += len; 279 } 280 } 281 _ => { 282 extensions.push(Extension { id: 0, payload }); 283 } 284 }; 285 286 (extension_profile, extensions) 287 } else { 288 (0, vec![]) 289 }; 290 291 Ok(Header { 292 version, 293 padding, 294 extension, 295 marker, 296 payload_type, 297 sequence_number, 298 timestamp, 299 ssrc, 300 csrc, 301 extension_profile, 302 extensions, 303 payload_offset, 304 }) 305 } 306 307 // Marshal serializes the header and writes to the buffer. 308 pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<(), Error> { 309 /* 310 * 0 1 2 3 311 * 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 312 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 313 * |V=2|P|X| CC |M| PT | sequence number | 314 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 315 * | timestamp | 316 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 317 * | synchronization source (SSRC) identifier | 318 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 319 * | contributing source (CSRC) identifiers | 320 * | .... | 321 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 322 */ 323 // The first byte contains the version, padding bit, extension bit, and csrc size 324 let mut b0 = (self.version << VERSION_SHIFT) | self.csrc.len() as u8; 325 if self.padding { 326 b0 |= 1 << PADDING_SHIFT; 327 } 328 329 if self.extension { 330 b0 |= 1 << EXTENSION_SHIFT; 331 } 332 writer.write_u8(b0)?; 333 334 // The second byte contains the marker bit and payload type. 335 let mut b1 = self.payload_type; 336 if self.marker { 337 b1 |= 1 << MARKER_SHIFT; 338 } 339 writer.write_u8(b1)?; 340 341 writer.write_u16::<BigEndian>(self.sequence_number)?; 342 writer.write_u32::<BigEndian>(self.timestamp)?; 343 writer.write_u32::<BigEndian>(self.ssrc)?; 344 345 for csrc in &self.csrc { 346 writer.write_u32::<BigEndian>(*csrc)?; 347 } 348 349 if self.extension { 350 writer.write_u16::<BigEndian>(self.extension_profile)?; 351 352 let extension_payload_len = self.get_extension_payload_len(); 353 if self.extension_profile != EXTENSION_PROFILE_ONE_BYTE 354 && self.extension_profile != EXTENSION_PROFILE_TWO_BYTE 355 && extension_payload_len % 4 != 0 356 { 357 //the payload must be in 32-bit words. 358 return Err(Error::new( 359 "extension_payload must be in 32-bit words".to_string(), 360 )); 361 } 362 let extension_payload_size = (extension_payload_len as u16 + 3) / 4; 363 writer.write_u16::<BigEndian>(extension_payload_size)?; 364 365 match self.extension_profile { 366 EXTENSION_PROFILE_ONE_BYTE => { 367 for extension in &self.extensions { 368 writer 369 .write_u8((extension.id << 4) | (extension.payload.len() as u8 - 1))?; 370 writer.write_all(&extension.payload)?; 371 } 372 } 373 EXTENSION_PROFILE_TWO_BYTE => { 374 for extension in &self.extensions { 375 writer.write_u8(extension.id)?; 376 writer.write_u8(extension.payload.len() as u8)?; 377 writer.write_all(&extension.payload)?; 378 } 379 } 380 _ => { 381 for extension in &self.extensions { 382 writer.write_all(&extension.payload)?; 383 } 384 } 385 }; 386 387 for _ in extension_payload_len..extension_payload_size as usize * 4 { 388 writer.write_u8(0)?; 389 } 390 } 391 392 Ok(()) 393 } 394 } 395