msf_rtp/rtcp/
mod.rs

1//! RTCP types.
2
3mod bye;
4mod handler;
5mod report;
6
7use std::ops::Deref;
8
9use bytes::{Buf, Bytes, BytesMut};
10
11use crate::InvalidInput;
12
13pub use self::{
14    bye::ByePacket,
15    handler::{MuxedRtcpHandler, RtcpHandler},
16    report::{ReceiverReport, ReportBlock, SenderReport},
17};
18
19/// Compound RTCP packet.
20#[derive(Clone)]
21pub struct CompoundRtcpPacket {
22    inner: Vec<RtcpPacket>,
23}
24
25impl CompoundRtcpPacket {
26    /// Create a new compound packet.
27    #[inline]
28    pub fn new<T>(packets: T) -> Self
29    where
30        T: Into<Vec<RtcpPacket>>,
31    {
32        Self {
33            inner: packets.into(),
34        }
35    }
36
37    /// Decode a compound RTCP packet.
38    #[inline]
39    pub fn decode(mut frame: Bytes) -> Result<Self, InvalidInput> {
40        let mut res = Vec::new();
41
42        while !frame.is_empty() {
43            res.push(RtcpPacket::decode(&mut frame)?);
44        }
45
46        Ok(res.into())
47    }
48
49    /// Encode the packet.
50    #[inline]
51    pub fn encode(&self, buf: &mut BytesMut) {
52        buf.reserve(self.raw_size());
53
54        for packet in &self.inner {
55            packet.encode(buf);
56        }
57    }
58
59    /// Get encoded size of the compound packet.
60    #[inline]
61    pub fn raw_size(&self) -> usize {
62        self.inner.iter().map(|packet| packet.length()).sum()
63    }
64}
65
66impl Deref for CompoundRtcpPacket {
67    type Target = [RtcpPacket];
68
69    #[inline]
70    fn deref(&self) -> &Self::Target {
71        &self.inner
72    }
73}
74
75impl From<RtcpPacket> for CompoundRtcpPacket {
76    #[inline]
77    fn from(packet: RtcpPacket) -> Self {
78        Self {
79            inner: vec![packet],
80        }
81    }
82}
83
84impl<T> From<T> for CompoundRtcpPacket
85where
86    T: Into<Vec<RtcpPacket>>,
87{
88    #[inline]
89    fn from(packets: T) -> Self {
90        Self::new(packets)
91    }
92}
93
94/// RTCP packet type.
95#[derive(Debug, Copy, Clone, Eq, PartialEq)]
96pub enum RtcpPacketType {
97    SR,
98    RR,
99    SDES,
100    BYE,
101    Other(u8),
102}
103
104impl RtcpPacketType {
105    /// Get type ID.
106    #[inline]
107    pub fn raw_id(self) -> u8 {
108        match self {
109            RtcpPacketType::SR => 200,
110            RtcpPacketType::RR => 201,
111            RtcpPacketType::SDES => 202,
112            RtcpPacketType::BYE => 203,
113            RtcpPacketType::Other(id) => id,
114        }
115    }
116}
117
118impl From<u8> for RtcpPacketType {
119    #[inline]
120    fn from(id: u8) -> RtcpPacketType {
121        match id {
122            200 => RtcpPacketType::SR,
123            201 => RtcpPacketType::RR,
124            202 => RtcpPacketType::SDES,
125            203 => RtcpPacketType::BYE,
126            id => RtcpPacketType::Other(id),
127        }
128    }
129}
130
131/// Helper struct.
132#[repr(C, packed)]
133struct RawRtcpHeader {
134    options: u8,
135    packet_type: u8,
136    length: u16,
137}
138
139/// RTCP header.
140#[derive(Copy, Clone)]
141pub struct RtcpHeader {
142    options: u8,
143    packet_type: RtcpPacketType,
144    length: u16,
145}
146
147impl RtcpHeader {
148    /// Create a new packet header.
149    #[inline]
150    pub const fn new(packet_type: RtcpPacketType) -> Self {
151        Self {
152            options: 2 << 6,
153            packet_type,
154            length: 0,
155        }
156    }
157
158    /// Decode an RTCP header.
159    pub fn decode(data: &mut Bytes) -> Result<Self, InvalidInput> {
160        if data.len() < std::mem::size_of::<RawRtcpHeader>() {
161            return Err(InvalidInput);
162        }
163
164        let ptr = data.as_ptr() as *const RawRtcpHeader;
165
166        let raw = unsafe { ptr.read_unaligned() };
167
168        if (raw.options >> 6) != 2 {
169            return Err(InvalidInput);
170        }
171
172        let res = Self {
173            options: raw.options,
174            packet_type: raw.packet_type.into(),
175            length: u16::from_be(raw.length),
176        };
177
178        data.advance(std::mem::size_of::<RawRtcpHeader>());
179
180        Ok(res)
181    }
182
183    /// Encode the header.
184    pub fn encode(&self, buf: &mut BytesMut) {
185        let raw = RawRtcpHeader {
186            options: self.options,
187            packet_type: self.packet_type.raw_id(),
188            length: self.length.to_be(),
189        };
190
191        let ptr = &raw as *const _ as *const u8;
192
193        let data = unsafe { std::slice::from_raw_parts(ptr, std::mem::size_of::<RawRtcpHeader>()) };
194
195        buf.extend_from_slice(data);
196    }
197
198    /// Check if the padding bit is set.
199    #[inline]
200    pub fn padding(&self) -> bool {
201        (self.options & 0x20) != 0
202    }
203
204    /// Set the padding bit.
205    #[inline]
206    pub fn with_padding(mut self, padding: bool) -> Self {
207        self.options &= !0x20;
208        self.options |= (padding as u8) << 5;
209        self
210    }
211
212    /// Get packet length in bytes.
213    #[inline]
214    pub fn packet_length(&self) -> usize {
215        ((self.length as usize) + 1) << 2
216    }
217
218    /// Set the packet length in bytes.
219    ///
220    /// Please note that the packet length must be a multiple of four and it
221    /// must be from the range `4..=262_144`.
222    ///
223    /// # Panics
224    /// The method panics if the constraints on the packet length mentioned
225    /// above are not met.
226    #[inline]
227    pub fn with_packet_length(mut self, length: usize) -> Self {
228        assert!((4..=262_144).contains(&length) && (length & 3) == 0);
229
230        self.length = ((length >> 2) - 1) as u16;
231        self
232    }
233
234    /// Get RTCP packet type.
235    #[inline]
236    pub fn packet_type(&self) -> RtcpPacketType {
237        self.packet_type
238    }
239
240    /// Set RTCP packet type.
241    #[inline]
242    pub fn with_packet_type(mut self, packet_type: RtcpPacketType) -> Self {
243        self.packet_type = packet_type;
244        self
245    }
246
247    /// Get number of items in the packet body.
248    ///
249    /// Note: Only the lower 5 bits are actually used.
250    #[inline]
251    pub fn item_count(&self) -> u8 {
252        self.options & 0x1f
253    }
254
255    /// Set the number of items in the packet body.
256    ///
257    /// # Panics
258    /// The method panics if the number of items is greater than 31.
259    #[inline]
260    pub fn with_item_count(mut self, count: u8) -> Self {
261        assert!(count < 32);
262
263        self.options &= !0x1f;
264        self.options |= count & 0x1f;
265        self
266    }
267
268    /// Get encoded size of the header.
269    #[inline]
270    pub fn raw_size(&self) -> usize {
271        std::mem::size_of::<RawRtcpHeader>()
272    }
273}
274
275/// RTCP packet.
276#[derive(Clone)]
277pub struct RtcpPacket {
278    header: RtcpHeader,
279    payload: Bytes,
280}
281
282impl RtcpPacket {
283    /// Create a new packet.
284    #[inline]
285    pub const fn new(packet_type: RtcpPacketType) -> Self {
286        Self {
287            header: RtcpHeader::new(packet_type),
288            payload: Bytes::new(),
289        }
290    }
291
292    /// Create a new RTCP packet from given parts.
293    pub fn from_parts(header: RtcpHeader, payload: Bytes) -> Result<Self, InvalidInput> {
294        if header.padding() {
295            let padding_len = payload.last().copied().ok_or(InvalidInput)? as usize;
296
297            if padding_len == 0 || payload.len() < padding_len {
298                return Err(InvalidInput);
299            }
300        }
301
302        let packet_len = header.packet_length();
303
304        if packet_len != (payload.len() + 4) {
305            return Err(InvalidInput);
306        }
307
308        let res = Self { header, payload };
309
310        Ok(res)
311    }
312
313    /// Deconstruct the packet into its header and payload.
314    #[inline]
315    pub fn deconstruct(self) -> (RtcpHeader, Bytes) {
316        (self.header, self.payload)
317    }
318
319    /// Decode an RTCP packet.
320    pub fn decode(data: &mut Bytes) -> Result<Self, InvalidInput> {
321        let mut buffer = data.clone();
322
323        let header = RtcpHeader::decode(&mut buffer)?;
324
325        let payload_len = header.packet_length() - 4;
326
327        if buffer.len() < payload_len {
328            return Err(InvalidInput);
329        }
330
331        let res = Self::from_parts(header, buffer.split_to(payload_len))?;
332
333        *data = buffer;
334
335        Ok(res)
336    }
337
338    /// Encode the packet.
339    pub fn encode(&self, buf: &mut BytesMut) {
340        buf.reserve(self.header.packet_length());
341
342        self.header.encode(buf);
343
344        buf.extend_from_slice(&self.payload);
345    }
346
347    /// Get the packet header.
348    #[inline]
349    pub fn header(&self) -> &RtcpHeader {
350        &self.header
351    }
352
353    /// Get the packet type.
354    #[inline]
355    pub fn packet_type(&self) -> RtcpPacketType {
356        self.header.packet_type()
357    }
358
359    /// Set the packet type.
360    #[inline]
361    pub fn with_packet_type(mut self, packet_type: RtcpPacketType) -> Self {
362        self.header = self.header.with_packet_type(packet_type);
363        self
364    }
365
366    /// Get number of items in the packet body.
367    ///
368    /// Note: Only the lower 5 bits are actually used.
369    #[inline]
370    pub fn item_count(&self) -> u8 {
371        self.header.item_count()
372    }
373
374    /// Set the number of items in the packet body.
375    ///
376    /// # Panics
377    /// The method panics if the number of items is greater than 31.
378    #[inline]
379    pub fn with_item_count(mut self, count: u8) -> Self {
380        self.header = self.header.with_item_count(count);
381        self
382    }
383
384    /// Get packet length in bytes.
385    #[inline]
386    pub fn length(&self) -> usize {
387        self.header.packet_length()
388    }
389
390    /// Get length of the optional padding.
391    ///
392    /// Zero means that the padding is not used at all.
393    #[inline]
394    pub fn padding(&self) -> u8 {
395        if self.header.padding() {
396            *self.payload.last().unwrap()
397        } else {
398            0
399        }
400    }
401
402    /// Get the packet payload including the optional padding.
403    #[inline]
404    pub fn payload(&self) -> &Bytes {
405        &self.payload
406    }
407
408    /// Get the packet payload without any padding.
409    #[inline]
410    pub fn stripped_payload(&self) -> Bytes {
411        let payload_len = self.payload.len();
412        let padding_len = self.padding() as usize;
413
414        let len = payload_len - padding_len;
415
416        self.payload.slice(..len)
417    }
418
419    /// Set the payload and add padding of a given length.
420    ///
421    /// If the padding is zero, no padding will be added and the padding bit in
422    /// the RTP header will be set to zero.
423    ///
424    /// # Panics
425    /// The method panics if the payload length including padding is not a
426    /// multiple of four or if the payload length including padding is greater
427    /// than 262_140.
428    #[inline]
429    pub fn with_payload(mut self, mut payload: Bytes, padding: u8) -> Self {
430        if padding > 0 {
431            let len = payload.len() + (padding as usize);
432
433            let mut buffer = BytesMut::with_capacity(len);
434
435            buffer.extend_from_slice(&payload);
436            buffer.resize(len, 0);
437
438            buffer[len - 1] = padding;
439
440            payload = buffer.freeze();
441
442            self.header = self
443                .header
444                .with_padding(true)
445                .with_packet_length(4 + payload.len());
446        } else {
447            self.header = self
448                .header
449                .with_padding(false)
450                .with_packet_length(4 + payload.len());
451        }
452
453        self.payload = payload;
454
455        self
456    }
457
458    /// Set the payload that already includes padding.
459    ///
460    /// # Panics
461    /// The method panics if the following conditions are not met:
462    /// * The payload must not be empty.
463    /// * The last byte of the payload (i.e. the length of the padding) must
464    ///   not be zero.
465    /// * The length of the padding must not be greater than the length of the
466    ///   payload itself.
467    /// * The payload length including padding must be a multiple of four.
468    /// * The payload length including padding must not be greater than
469    ///   262_140.
470    #[inline]
471    pub fn with_padded_payload(mut self, payload: Bytes) -> Self {
472        let padding_len = payload.last().copied().expect("empty payload") as usize;
473
474        assert!(padding_len > 0 && payload.len() >= padding_len);
475
476        self.header = self
477            .header
478            .with_padding(true)
479            .with_packet_length(payload.len());
480
481        self.payload = payload;
482        self
483    }
484
485    /// Get encoded size of the packet.
486    #[inline]
487    pub fn raw_size(&self) -> usize {
488        self.length()
489    }
490}