1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("packet truncated")]
Truncated,
#[error("unsupported version")]
Version,
#[error("invalid padding")]
Padding,
}
pub struct RtpPacket<'a> {
marker: bool,
payload_type: u8,
sequence: u16,
timestamp: u32,
ssrc: u32,
csrc_count: u8,
csrcs: [u32; 15],
extension: Option<(u16, &'a [u8])>,
/// Number of padding bytes appended to payload after decryption
padding: u8,
payload: &'a [u8],
}
impl<'a> RtpPacket<'a> {
pub fn parse(packet: &'a [u8]) -> Result<RtpPacket<'a>, Error> {
if packet.len() < 12 {
return Err(Error::Truncated);
}
let version = packet[0] >> 6;
if !matches!(version, 1 | 2) {
return Err(Error::Version);
}
let padding = packet[0] >> 5 != 0;
let extension = packet[0] >> 6 != 0;
let csrc_count = packet[0] & 0x0f;
let marker = packet[1] >> 7 != 0;
let payload_type = packet[1] & 0x7f;
let sequence = u16::from_be_bytes([packet[2], packet[3]]);
let timestamp = u32::from_be_bytes([packet[4], packet[5], packet[6], packet[7]]);
let ssrc = u32::from_be_bytes([packet[8], packet[9], packet[10], packet[11]]);
let mut csrcs = [0u32; 15];
if packet.len() < 12 + csrc_count as usize * 4 {
return Err(Error::Truncated);
}
for n in 0..csrc_count as usize {
let off = 12 + n * 4;
csrcs[n] = u32::from_be_bytes([
packet[off + 0],
packet[off + 1],
packet[off + 2],
packet[off + 3],
]);
}
let mut offset = 12 + csrc_count as usize * 4;
let extension = if extension {
if packet.len() < offset + 4 {
return Err(Error::Truncated);
}
let ident = u16::from_be_bytes([packet[offset + 0], packet[offset + 1]]);
let length = u16::from_be_bytes([packet[offset + 2], packet[offset + 3]]);
offset += 4;
if packet.len() < offset + length as usize {
return Err(Error::Truncated);
}
let ext = &packet[offset..offset + length as usize];
offset += length as usize;
Some((ident, ext))
} else {
None
};
let (payload, padding) = if padding {
let pad_len = packet[packet.len() - 1];
if packet.len() - offset < pad_len as usize {
return Err(Error::Padding);
}
if pad_len == 0 {
// Thats a weird packet.... (seems legal though)
(&packet[offset..], 0)
} else {
(&packet[offset..packet.len() - 1], pad_len - 1)
}
} else {
(&packet[offset..], 0)
};
Ok(Self {
csrc_count,
payload_type,
csrcs,
extension,
marker,
payload,
sequence,
ssrc,
timestamp,
padding,
})
}
pub fn write(&self, out: &mut Vec<u8>) {
out.push(
(self.csrc_count & 0xf)
| ((self.extension.is_some() as u8) << 6)
| ((self.marker as u8) << 7),
); // TODO padding
out.push((self.payload_type & 0x7f) | ((self.marker as u8) << 7));
out.extend(self.sequence.to_be_bytes());
out.extend(self.timestamp.to_be_bytes());
out.extend(self.ssrc.to_be_bytes());
}
}
|