rtp_parser/
parser.rs

1use crate::rtp::*;
2use crate::rtp_header_extension::*;
3
4extern crate nom;
5use nom::bits::bits;
6use nom::bits::complete::take as bits_take;
7use nom::bytes::complete::take as bytes_take;
8use nom::combinator::rest;
9use nom::error::make_error;
10use nom::error::ErrorKind;
11use nom::multi::count;
12use nom::number::complete::{be_u16, be_u32};
13use nom::sequence::tuple;
14use nom::Err;
15use nom::IResult;
16
17/// Parse an RTP packet
18pub fn parse_rtp_packet(input: &[u8]) -> IResult<&[u8], RtpPacket> {
19    let (
20        input,
21        (
22            (version, padding, extension, csrc_count),
23            (marker, payload_type),
24            sequence_number,
25            timestamp,
26            ssrc,
27        ),
28    ) = tuple((parse_vpxcc, parse_mpt, be_u16, be_u32, be_u32))(input)?;
29
30    let (input, csrc) = parse_csrc(input, csrc_count as usize)?;
31    let (input, header_extension) = parse_header_extension(input, extension)?;
32    let (input, (payload, padding_bytes)) = parse_payload(input, padding)?;
33
34    Ok((
35        input,
36        RtpPacket {
37            version,
38            padding,
39            extension,
40            csrc_count,
41            marker,
42            payload_type,
43            sequence_number,
44            timestamp,
45            ssrc,
46            csrc,
47            header_extension,
48            payload,
49            padding_bytes,
50        },
51    ))
52}
53
54fn parse_vpxcc(input: &[u8]) -> IResult<&[u8], (u8, u8, u8, u8)> {
55    bits(tuple((
56        bits_take::<_, _, _, (_, _)>(2usize),
57        bits_take::<_, _, _, (_, _)>(1usize),
58        bits_take::<_, _, _, (_, _)>(1usize),
59        bits_take::<_, _, _, (_, _)>(4usize),
60    )))(input)
61}
62
63fn parse_mpt(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
64    bits(tuple((
65        bits_take::<_, _, _, (_, _)>(1usize),
66        bits_take::<_, _, _, (_, _)>(7usize),
67    )))(input)
68}
69
70fn parse_csrc(input: &[u8], csrc_count: usize) -> IResult<&[u8], Vec<u32>> {
71    count(be_u32, csrc_count)(input)
72}
73
74fn parse_header_extension(
75    input: &[u8],
76    extension: u8,
77) -> IResult<&[u8], Option<RtpPacketHeaderExtension>> {
78    if extension == 0 {
79        Ok((input, None))
80    } else {
81        let (input, (profile, length)) = tuple((be_u16, be_u16))(input)?;
82        let (input, data) = bytes_take(length * 4)(input)?;
83
84        Ok((
85            input,
86            Some(RtpPacketHeaderExtension {
87                profile,
88                length,
89                data,
90            }),
91        ))
92    }
93}
94
95fn parse_payload_no_padding(input: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
96    let (input, payload) = rest::<_, (_, _)>(input)?;
97    Ok((input, (payload, &[])))
98}
99
100fn parse_payload_padding(input: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
101    let num_padding_bytes = input.last().map(|i| *i as usize).unwrap_or(usize::MAX);
102
103    if num_padding_bytes <= input.len() {
104        tuple((
105            bytes_take(input.len() - num_padding_bytes),
106            bytes_take(num_padding_bytes),
107        ))(input)
108    } else {
109        Err(Err::Error(make_error(input, ErrorKind::Eof)))
110    }
111}
112
113fn parse_payload(input: &[u8], padding: u8) -> IResult<&[u8], (&[u8], &[u8])> {
114    if padding == 0x00 {
115        parse_payload_no_padding(input)
116    } else {
117        parse_payload_padding(input)
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124
125    // helper function to take a byte and feed it into vpxcc parsing
126    fn parse_vpxcc_helper(value: u8) -> (u8, u8, u8, u8) {
127        let input: [u8; 1] = [value];
128        let result = parse_vpxcc(&input);
129
130        // parsing should work
131        assert!(result.is_ok());
132
133        // should have consumed all the data
134        let data = result.ok().unwrap();
135        assert_eq!(data.0.len(), 0);
136        return data.1;
137    }
138
139    #[test]
140    fn parse_vpxcc_all_one() {
141        assert_eq!(parse_vpxcc_helper(0xFF), (0x03, 0x01, 0x01, 0x0F));
142    }
143
144    #[test]
145    fn parse_vpxcc_all_zero() {
146        assert_eq!(parse_vpxcc_helper(0x00), (0x00, 0x00, 0x00, 0x00));
147    }
148
149    #[test]
150    fn parse_vpxcc_mixed() {
151        assert_eq!(parse_vpxcc_helper(0xA5), (0x02, 0x01, 0x00, 0x05));
152    }
153
154    #[test]
155    fn parse_vpxcc_missing_data() {
156        let input: [u8; 0] = [];
157        let result = parse_vpxcc(&input);
158
159        assert!(result.is_err());
160    }
161
162    fn parse_mpt_helper(value: u8) -> (u8, u8) {
163        let input: [u8; 1] = [value];
164        let result = parse_mpt(&input);
165
166        // parsing should work
167        assert!(result.is_ok());
168
169        // should have consumed all the data
170        let data = result.ok().unwrap();
171        assert_eq!(data.0.len(), 0);
172        return data.1;
173    }
174
175    #[test]
176    fn parse_mpt_all_zero() {
177        assert_eq!(parse_mpt_helper(0x00), (0x00, 0x00));
178    }
179
180    #[test]
181    fn parse_mpt_all_one() {
182        assert_eq!(parse_mpt_helper(0xFF), (0x01, 0x7F));
183    }
184
185    #[test]
186    fn parse_mpt_mixed() {
187        assert_eq!(parse_mpt_helper(0xA5), (0x01, 0x25));
188    }
189
190    #[test]
191    fn parse_mpt_missing_data() {
192        let input: [u8; 0] = [];
193        let result = parse_mpt(&input);
194
195        assert!(result.is_err());
196    }
197
198    #[test]
199    fn parse_csrc_empty() {
200        let input: [u8; 0] = [];
201        let result = parse_csrc(&input, 0);
202
203        assert!(result.is_ok());
204        assert_eq!(result.ok().unwrap().1.len(), 0);
205    }
206
207    #[test]
208    fn parse_csrc_non_empty() {
209        let input: [u8; 9] = [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0xA5];
210
211        let result = parse_csrc(&input, 2);
212        assert!(result.is_ok());
213
214        let data = result.ok().unwrap();
215
216        // should not have consumed all the data
217        assert_eq!(data.0.len(), 1);
218
219        // should have two entries
220        assert_eq!(data.1, vec!(0x12345678, 0x90ABCDEF));
221    }
222
223    #[test]
224    fn parse_csrc_not_enough_data() {
225        let input: [u8; 0] = [];
226        let result = parse_csrc(&input, 2);
227        assert!(result.is_err());
228    }
229
230    #[test]
231    fn parse_header_extension_empty_valid() {
232        let input: [u8; 0] = [];
233        let result = parse_header_extension(&input, 0);
234        assert!(result.is_ok());
235
236        let data = result.ok().unwrap();
237        assert!(data.1.is_none());
238    }
239
240    #[test]
241    fn parse_header_extension_empty_invalid() {
242        let input: [u8; 0] = [];
243        let result = parse_header_extension(&input, 1);
244        assert!(result.is_err());
245    }
246
247    #[test]
248    fn parse_header_extension_non_empty() {
249        let input: [u8; 8] = [0x12, 0x34, 0x00, 0x01, 0x56, 0x78, 0x90, 0xAB];
250        let result = parse_header_extension(&input, 1);
251        assert!(result.is_ok());
252
253        let data = result.ok().unwrap();
254        assert_eq!(data.0.len(), 0);
255        assert!(data.1.is_some());
256
257        let header_extension = data.1.unwrap();
258        assert_eq!(header_extension.profile, 0x1234);
259        assert_eq!(header_extension.length, 0x0001);
260        assert_eq!(header_extension.data, [0x56, 0x78, 0x90, 0xAB]);
261    }
262
263    #[test]
264    fn parse_payload_no_padding() {
265        let input: [u8; 1] = [0x12];
266        let result = parse_payload(&input, 0);
267        assert!(result.is_ok());
268        let data = result.ok().unwrap();
269        assert_eq!(data.0.len(), 0);
270
271        let (payload, padding_bytes) = data.1;
272        assert_eq!(payload, [0x12]);
273        assert_eq!(padding_bytes, []);
274    }
275
276    #[test]
277    fn parse_payload_padding_valid() {
278        let input: [u8; 4] = [0x12, 0x00, 0x00, 0x03];
279        let result = parse_payload(&input, 1);
280        assert!(result.is_ok());
281        let data = result.ok().unwrap();
282        assert_eq!(data.0.len(), 0);
283
284        let (payload, padding_bytes) = data.1;
285        assert_eq!(payload, [0x12]);
286        assert_eq!(padding_bytes, [0x00, 0x00, 0x03]);
287    }
288
289    #[test]
290    fn parse_payload_padding_valid_no_payload() {
291        let input: [u8; 4] = [0x12, 0x00, 0x00, 0x04];
292        let result = parse_payload(&input, 1);
293        assert!(result.is_ok());
294        let data = result.ok().unwrap();
295        assert_eq!(data.0.len(), 0);
296
297        let (payload, padding_bytes) = data.1;
298        assert_eq!(payload, []);
299        assert_eq!(padding_bytes, [0x12, 0x00, 0x00, 0x04]);
300    }
301
302    #[test]
303    fn parse_payload_padding_invalid() {
304        // number of padding bytes (last value in array) is too large
305        let input: [u8; 4] = [0x12, 0x00, 0x00, 0x05];
306        let result = parse_payload(&input, 1);
307        assert!(result.is_err());
308    }
309
310    #[test]
311    fn parse_payload_padding_empty() {
312        let input: [u8; 0] = [];
313        let result = parse_payload(&input, 1);
314        assert!(result.is_err());
315    }
316
317    #[test]
318    fn parse_rtp_packet_no_csrc_no_header_extension() {
319        let data = vec![
320            0x80, 0x11, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x09,
321        ];
322        let result = parse_rtp_packet(&data);
323
324        assert!(result.is_ok());
325
326        let data = result.ok().unwrap();
327        assert_eq!(data.0.len(), 0);
328
329        let packet = data.1;
330        assert_eq!(packet.version, 0x02);
331        assert_eq!(packet.padding, 0x00);
332        assert_eq!(packet.extension, 0x00);
333        assert_eq!(packet.csrc_count, 0x00);
334        assert_eq!(packet.marker, 0x00);
335        assert_eq!(packet.payload_type, 0x11);
336        assert_eq!(packet.sequence_number, 0x1234);
337        assert_eq!(packet.timestamp, 0x567890AB);
338        assert_eq!(packet.ssrc, 0xCDEFFEDC);
339        assert_eq!(packet.csrc, vec![]);
340        assert!(packet.header_extension.is_none());
341        assert_eq!(packet.payload, [0xBA, 0x09]);
342        assert_eq!(packet.padding_bytes, []);
343    }
344
345    #[test]
346    fn parse_rtp_packet_csrc() {
347        let data = vec![
348            0x81, 0x11, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x09,
349            0x87, 0x65, 0x43,
350        ];
351        let result = parse_rtp_packet(&data);
352
353        assert!(result.is_ok());
354
355        let data = result.ok().unwrap();
356        assert_eq!(data.0.len(), 0);
357
358        let packet = data.1;
359        assert_eq!(packet.version, 0x02);
360        assert_eq!(packet.padding, 0x00);
361        assert_eq!(packet.extension, 0x00);
362        assert_eq!(packet.csrc_count, 0x01);
363        assert_eq!(packet.marker, 0x00);
364        assert_eq!(packet.payload_type, 0x11);
365        assert_eq!(packet.sequence_number, 0x1234);
366        assert_eq!(packet.timestamp, 0x567890AB);
367        assert_eq!(packet.ssrc, 0xCDEFFEDC);
368        assert_eq!(packet.csrc, vec![0xBA098765]);
369        assert!(packet.header_extension.is_none());
370        assert_eq!(packet.payload, [0x43]);
371        assert_eq!(packet.padding_bytes, []);
372    }
373
374    #[test]
375    fn parse_rtp_packet_header_ext() {
376        let data = vec![
377            0x90, 0x11, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x09,
378            0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x43,
379        ];
380        let result = parse_rtp_packet(&data);
381
382        assert!(result.is_ok());
383
384        let data = result.ok().unwrap();
385        assert_eq!(data.0.len(), 0);
386
387        let packet = data.1;
388        assert_eq!(packet.version, 0x02);
389        assert_eq!(packet.padding, 0x00);
390        assert_eq!(packet.extension, 0x01);
391        assert_eq!(packet.csrc_count, 0x00);
392        assert_eq!(packet.marker, 0x00);
393        assert_eq!(packet.payload_type, 0x11);
394        assert_eq!(packet.sequence_number, 0x1234);
395        assert_eq!(packet.timestamp, 0x567890AB);
396        assert_eq!(packet.ssrc, 0xCDEFFEDC);
397        assert_eq!(packet.csrc, vec![]);
398        assert!(packet.header_extension.is_some());
399
400        let header_extension = packet.header_extension.unwrap();
401        assert_eq!(header_extension.profile, 0xBA09);
402        assert_eq!(header_extension.length, 0x0002);
403        assert_eq!(
404            header_extension.data,
405            [0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11]
406        );
407
408        assert_eq!(packet.payload, [0x43]);
409        assert_eq!(packet.padding_bytes, []);
410    }
411
412    #[test]
413    fn parse_rtp_packet_csrc_header_ext() {
414        let data = vec![
415            0x91, 0x11, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x09,
416            0x87, 0x65, 0x43, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,
417            0x43,
418        ];
419        let result = parse_rtp_packet(&data);
420
421        assert!(result.is_ok());
422
423        let data = result.ok().unwrap();
424        assert_eq!(data.0.len(), 0);
425
426        let packet = data.1;
427        assert_eq!(packet.version, 0x02);
428        assert_eq!(packet.padding, 0x00);
429        assert_eq!(packet.extension, 0x01);
430        assert_eq!(packet.csrc_count, 0x01);
431        assert_eq!(packet.marker, 0x00);
432        assert_eq!(packet.payload_type, 0x11);
433        assert_eq!(packet.sequence_number, 0x1234);
434        assert_eq!(packet.timestamp, 0x567890AB);
435        assert_eq!(packet.ssrc, 0xCDEFFEDC);
436        assert_eq!(packet.csrc, vec![0xBA098765]);
437        assert!(packet.header_extension.is_some());
438
439        let header_extension = packet.header_extension.unwrap();
440        assert_eq!(header_extension.profile, 0x4321);
441        assert_eq!(header_extension.length, 0x0002);
442        assert_eq!(
443            header_extension.data,
444            [0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11]
445        );
446
447        assert_eq!(packet.payload, [0x43]);
448        assert_eq!(packet.padding_bytes, []);
449    }
450
451    #[test]
452    fn parse_rtp_packet_padding() {
453        let data = vec![
454            0xA0, 0x11, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x09,
455            0x03,
456        ];
457        let result = parse_rtp_packet(&data);
458
459        assert!(result.is_ok());
460
461        let data = result.ok().unwrap();
462        assert_eq!(data.0.len(), 0);
463
464        let packet = data.1;
465        assert_eq!(packet.version, 0x02);
466        assert_eq!(packet.padding, 0x01);
467        assert_eq!(packet.extension, 0x00);
468        assert_eq!(packet.csrc_count, 0x00);
469        assert_eq!(packet.marker, 0x00);
470        assert_eq!(packet.payload_type, 0x11);
471        assert_eq!(packet.sequence_number, 0x1234);
472        assert_eq!(packet.timestamp, 0x567890AB);
473        assert_eq!(packet.ssrc, 0xCDEFFEDC);
474        assert_eq!(packet.csrc, vec![]);
475        assert!(packet.header_extension.is_none());
476        assert_eq!(packet.payload, []);
477        assert_eq!(packet.padding_bytes, [0xBA, 0x09, 0x03]);
478    }
479}