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