Skip to main content

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