xref: /webrtc/rtp/src/header.rs (revision ffe74184)
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