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(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        let raw = unsafe { &*ptr };
166
167        if (raw.options >> 6) != 2 {
168            return Err(InvalidInput);
169        }
170
171        let res = Self {
172            options: raw.options,
173            packet_type: raw.packet_type.into(),
174            length: u16::from_be(raw.length),
175        };
176
177        data.advance(std::mem::size_of::<RawRtcpHeader>());
178
179        Ok(res)
180    }
181
182    /// Encode the header.
183    pub fn encode(&self, buf: &mut BytesMut) {
184        let raw = RawRtcpHeader {
185            options: self.options,
186            packet_type: self.packet_type.raw_id(),
187            length: self.length.to_be(),
188        };
189
190        let ptr = &raw as *const _ as *const u8;
191
192        let data = unsafe { std::slice::from_raw_parts(ptr, std::mem::size_of::<RawRtcpHeader>()) };
193
194        buf.extend_from_slice(data);
195    }
196
197    /// Check if the padding bit is set.
198    #[inline]
199    pub fn padding(&self) -> bool {
200        (self.options & 0x20) != 0
201    }
202
203    /// Set the padding bit.
204    #[inline]
205    pub fn with_padding(mut self, padding: bool) -> Self {
206        self.options &= !0x20;
207        self.options |= (padding as u8) << 5;
208        self
209    }
210
211    /// Get packet length in bytes.
212    #[inline]
213    pub fn packet_length(&self) -> usize {
214        ((self.length as usize) + 1) << 2
215    }
216
217    /// Set the packet length in bytes.
218    ///
219    /// Please note that the packet length must be a multiple of four and it
220    /// must be from the range `4..=262_144`.
221    ///
222    /// # Panics
223    /// The method panics if the constraints on the packet length mentioned
224    /// above are not met.
225    #[inline]
226    pub fn with_packet_length(mut self, length: usize) -> Self {
227        assert!((4..=262_144).contains(&length) && (length & 3) == 0);
228
229        self.length = ((length >> 2) - 1) as u16;
230        self
231    }
232
233    /// Get RTCP packet type.
234    #[inline]
235    pub fn packet_type(&self) -> RtcpPacketType {
236        self.packet_type
237    }
238
239    /// Set RTCP packet type.
240    #[inline]
241    pub fn with_packet_type(mut self, packet_type: RtcpPacketType) -> Self {
242        self.packet_type = packet_type;
243        self
244    }
245
246    /// Get number of items in the packet body.
247    ///
248    /// Note: Only the lower 5 bits are actually used.
249    #[inline]
250    pub fn item_count(&self) -> u8 {
251        self.options & 0x1f
252    }
253
254    /// Set the number of items in the packet body.
255    ///
256    /// # Panics
257    /// The method panics if the number of items is greater than 31.
258    #[inline]
259    pub fn with_item_count(mut self, count: u8) -> Self {
260        assert!(count < 32);
261
262        self.options &= !0x1f;
263        self.options |= count & 0x1f;
264        self
265    }
266
267    /// Get encoded size of the header.
268    #[inline]
269    pub fn raw_size(&self) -> usize {
270        std::mem::size_of::<RawRtcpHeader>()
271    }
272}
273
274/// RTCP packet.
275#[derive(Clone)]
276pub struct RtcpPacket {
277    header: RtcpHeader,
278    payload: Bytes,
279}
280
281impl RtcpPacket {
282    /// Create a new packet.
283    #[inline]
284    pub const fn new(packet_type: RtcpPacketType) -> Self {
285        Self {
286            header: RtcpHeader::new(packet_type),
287            payload: Bytes::new(),
288        }
289    }
290
291    /// Create a new RTCP packet from given parts.
292    pub fn from_parts(header: RtcpHeader, payload: Bytes) -> Result<Self, InvalidInput> {
293        if header.padding() {
294            let padding_len = payload.last().copied().ok_or(InvalidInput)? as usize;
295
296            if padding_len == 0 || payload.len() < padding_len {
297                return Err(InvalidInput);
298            }
299        }
300
301        let packet_len = header.packet_length();
302
303        if packet_len != (payload.len() + 4) {
304            return Err(InvalidInput);
305        }
306
307        let res = Self { header, payload };
308
309        Ok(res)
310    }
311
312    /// Deconstruct the packet into its header and payload.
313    #[inline]
314    pub fn deconstruct(self) -> (RtcpHeader, Bytes) {
315        (self.header, self.payload)
316    }
317
318    /// Decode an RTCP packet.
319    pub fn decode(data: &mut Bytes) -> Result<Self, InvalidInput> {
320        let mut buffer = data.clone();
321
322        let header = RtcpHeader::decode(&mut buffer)?;
323
324        let payload_len = header.packet_length() - 4;
325
326        if buffer.len() < payload_len {
327            return Err(InvalidInput);
328        }
329
330        let res = Self::from_parts(header, buffer.split_to(payload_len))?;
331
332        *data = buffer;
333
334        Ok(res)
335    }
336
337    /// Encode the packet.
338    pub fn encode(&self, buf: &mut BytesMut) {
339        buf.reserve(self.header.packet_length());
340
341        self.header.encode(buf);
342
343        buf.extend_from_slice(&self.payload);
344    }
345
346    /// Get the packet header.
347    #[inline]
348    pub fn header(&self) -> &RtcpHeader {
349        &self.header
350    }
351
352    /// Get the packet type.
353    #[inline]
354    pub fn packet_type(&self) -> RtcpPacketType {
355        self.header.packet_type()
356    }
357
358    /// Set the packet type.
359    #[inline]
360    pub fn with_packet_type(mut self, packet_type: RtcpPacketType) -> Self {
361        self.header = self.header.with_packet_type(packet_type);
362        self
363    }
364
365    /// Get number of items in the packet body.
366    ///
367    /// Note: Only the lower 5 bits are actually used.
368    #[inline]
369    pub fn item_count(&self) -> u8 {
370        self.header.item_count()
371    }
372
373    /// Set the number of items in the packet body.
374    ///
375    /// # Panics
376    /// The method panics if the number of items is greater than 31.
377    #[inline]
378    pub fn with_item_count(mut self, count: u8) -> Self {
379        self.header = self.header.with_item_count(count);
380        self
381    }
382
383    /// Get packet length in bytes.
384    #[inline]
385    pub fn length(&self) -> usize {
386        self.header.packet_length()
387    }
388
389    /// Get length of the optional padding.
390    ///
391    /// Zero means that the padding is not used at all.
392    #[inline]
393    pub fn padding(&self) -> u8 {
394        if self.header.padding() {
395            *self.payload.last().unwrap()
396        } else {
397            0
398        }
399    }
400
401    /// Get the packet payload including the optional padding.
402    #[inline]
403    pub fn payload(&self) -> &Bytes {
404        &self.payload
405    }
406
407    /// Get the packet payload without any padding.
408    #[inline]
409    pub fn stripped_payload(&self) -> Bytes {
410        let payload_len = self.payload.len();
411        let padding_len = self.padding() as usize;
412
413        let len = payload_len - padding_len;
414
415        self.payload.slice(..len)
416    }
417
418    /// Set the payload and add padding of a given length.
419    ///
420    /// If the padding is zero, no padding will be added and the padding bit in
421    /// the RTP header will be set to zero.
422    ///
423    /// # Panics
424    /// The method panics if the payload length including padding is not a
425    /// multiple of four or if the payload length including padding is greater
426    /// than 262_140.
427    #[inline]
428    pub fn with_payload(mut self, mut payload: Bytes, padding: u8) -> Self {
429        if padding > 0 {
430            let len = payload.len() + (padding as usize);
431
432            let mut buffer = BytesMut::with_capacity(len);
433
434            buffer.extend_from_slice(&payload);
435            buffer.resize(len, 0);
436
437            buffer[len - 1] = padding;
438
439            payload = buffer.freeze();
440
441            self.header = self
442                .header
443                .with_padding(true)
444                .with_packet_length(4 + payload.len());
445        } else {
446            self.header = self
447                .header
448                .with_padding(false)
449                .with_packet_length(4 + payload.len());
450        }
451
452        self.payload = payload;
453
454        self
455    }
456
457    /// Set the payload that already includes padding.
458    ///
459    /// # Panics
460    /// The method panics if the following conditions are not met:
461    /// * The payload must not be empty.
462    /// * The last byte of the payload (i.e. the length of the padding) must
463    ///   not be zero.
464    /// * The length of the padding must not be greater than the length of the
465    ///   payload itself.
466    /// * The payload length including padding must be a multiple of four.
467    /// * The payload length including padding must not be greater than
468    ///   262_140.
469    #[inline]
470    pub fn with_padded_payload(mut self, payload: Bytes) -> Self {
471        let padding_len = payload.last().copied().expect("empty payload") as usize;
472
473        assert!(padding_len > 0 && payload.len() >= padding_len);
474
475        self.header = self
476            .header
477            .with_padding(true)
478            .with_packet_length(payload.len());
479
480        self.payload = payload;
481        self
482    }
483
484    /// Get encoded size of the packet.
485    #[inline]
486    pub fn raw_size(&self) -> usize {
487        self.length()
488    }
489}