msf_rtp/rtcp/
mod.rs

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