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