rtcp_types/
lib.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3#![deny(missing_debug_implementations)]
4#![deny(missing_docs)]
5
6//! # rtcp-type
7//!
8//! A crate for parsing and writing RTCP packets as specified in [RFC 3550] and related extensions.
9//!
10//! [RFC 3550]: https://tools.ietf.org/html/rfc3550
11
12/// A Trait defining RTCP Packet structural data.
13pub trait RtcpPacket {
14    /// RTCP protocol version.  The default version of 2 is fine and should not need to be
15    /// overriden.
16    const VERSION: u8 = 2;
17    /// A maximum count that is commonly used across multiple RTCP packet types.  A value larger
18    /// than this will produce a parsing error.
19    const MAX_COUNT: u8 = 0x1f;
20    /// The minimum size of a particular RTCP packet.  A packet shorter than this value will
21    /// produce a parsing error.
22    const MIN_PACKET_LEN: usize;
23    /// The RTCP type of the particular RTCP packet.
24    const PACKET_TYPE: u8;
25}
26
27/// A Trait to ease the implementation of RTCP Packet parsers.
28///
29/// Implementers only need to return the 4 byte RTCP header
30/// from [`RtcpPacketParser::header_data`] to be able to use
31/// the getters for the common RTCP packet fields.
32pub trait RtcpPacketParser<'a>: RtcpPacket + Sized {
33    /// Parses the provided data.
34    ///
35    /// Returns an instance of `Self` if parsing succeeds,
36    /// an `RtcpParseError` otherwise.
37    fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError>;
38
39    /// Returns the common header for this RTCP packet.
40    fn header_data(&self) -> [u8; 4];
41}
42
43/// Extension trait providing helper functions for particular pieces of data in the 4 byte RTCP
44/// header provided by [`RtcpPacketParser`].
45pub trait RtcpPacketParserExt<'a>: RtcpPacketParser<'a> {
46    /// The RTCP protocol version.
47    fn version(&self) -> u8 {
48        utils::parser::parse_version(&self.header_data())
49    }
50
51    /// The RTCP payload type.
52    fn type_(&self) -> u8 {
53        utils::parser::parse_packet_type(&self.header_data())
54    }
55
56    /// The sub type of the RTCP packet.  (Same value as [`count`](Self::count)).
57    fn subtype(&self) -> u8 {
58        utils::parser::parse_count(&self.header_data())
59    }
60
61    /// The advertsied length (in bytes) of the RTCP packet.
62    fn length(&self) -> usize {
63        utils::parser::parse_length(&self.header_data())
64    }
65
66    /// The number of records in this RTCP packet.  (Same value as [`subtype`](Self::subtype)).
67    fn count(&self) -> u8 {
68        utils::parser::parse_count(&self.header_data())
69    }
70}
71
72impl<'a, T: RtcpPacketParser<'a>> RtcpPacketParserExt<'a> for T {}
73
74/// A Trait with base functions needed for RTCP Packet writers.
75///
76/// Note: this trait must remain [object-safe].
77///
78/// [object-safe]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
79pub trait RtcpPacketWriter: std::fmt::Debug + Send + Sync {
80    /// Calculates the size required to write this RTCP packet.
81    ///
82    /// Also performs validity checks.
83    fn calculate_size(&self) -> Result<usize, RtcpWriteError>;
84
85    /// Writes this RTCP packet into `buf` without any validity checks.
86    ///
87    /// Uses the length of the buffer for the length field.
88    ///
89    /// Returns the number of bytes written.
90    ///
91    /// # Panic
92    ///
93    /// Panics if the buf is not large enough.
94    fn write_into_unchecked(&self, buf: &mut [u8]) -> usize;
95
96    /// Gets the padding that was configured for this RTCP packet.
97    fn get_padding(&self) -> Option<u8>;
98}
99
100/// Extension providing helpders for writing a [`RtcpPacket`].
101pub trait RtcpPacketWriterExt: RtcpPacketWriter {
102    /// Writes the Custom packet into `buf`.
103    ///
104    /// The default implementation:
105    ///
106    /// * Calls [`RtcpPacketWriter::calculate_size`] for validity checks and size calculation.
107    /// * Checks that the provided buffer is large enough to store this RTCP packet.
108    /// * Writes to the provided buffer using [`RtcpPacketWriter::write_into_unchecked`].
109    fn write_into(&self, buf: &mut [u8]) -> Result<usize, RtcpWriteError> {
110        let req_size = self.calculate_size()?;
111        if buf.len() < req_size {
112            return Err(RtcpWriteError::OutputTooSmall(req_size));
113        }
114
115        Ok(self.write_into_unchecked(&mut buf[..req_size]))
116    }
117}
118
119impl<T: RtcpPacketWriter> RtcpPacketWriterExt for T {}
120
121/// Errors that can be produced when parsing a RTCP packet
122#[derive(thiserror::Error, Debug, PartialEq, Eq)]
123#[non_exhaustive]
124pub enum RtcpParseError {
125    /// Unsupported version.  This implementation only deals with version 2.
126    #[error("Unsupported version: {}.  This implementation only deals with version 2.", .0)]
127    UnsupportedVersion(u8),
128    /// The packet was too short to parse
129    #[error("The packet was too short to parse. Expected size: {expected}, actual size encountered: {actual}")]
130    Truncated {
131        /// The expected size
132        expected: usize,
133        /// The actual size encountered
134        actual: usize,
135    },
136    /// The packet was too large to parse
137    #[error("The packet was too large to parse. Expected size: {expected}, actual size encountered: {actual}")]
138    TooLarge {
139        /// The expected size
140        expected: usize,
141        /// The actual size encountered
142        actual: usize,
143    },
144    /// Invalid Padding length 0.
145    #[error("Invalid Padding length 0")]
146    InvalidPadding,
147
148    /// The SDES Value was too large
149    #[error("The SDES Value length {len} was too large (max {max})")]
150    SdesValueTooLarge {
151        /// The length
152        len: usize,
153        /// The maximum length allowed
154        max: u8,
155    },
156
157    /// The SDES PRIV content was too short
158    #[error("The SDES PRIC content length {len} was too short (min {min})")]
159    SdesPrivContentTruncated {
160        /// The length
161        len: usize,
162        /// The minimum length allowed
163        min: u8,
164    },
165
166    /// The SDES PRIV prefix was too large
167    #[error("The SDES PRIV prefix length {len} too large (available {available})")]
168    SdesPrivPrefixTooLarge {
169        /// The length
170        len: usize,
171        /// The maximum length available
172        available: u8,
173    },
174
175    /// This implementation does not handle this packet
176    #[error("This implementation does not handle this packet")]
177    WrongImplementation,
178
179    /// RTCP Packet type mismatch.
180    #[error("RTCP Packet type mismatch. Actual: {actual}, requested {requested}")]
181    PacketTypeMismatch {
182        /// The packet type encountered.
183        actual: u8,
184        /// The requested packet type.
185        requested: u8,
186    },
187}
188
189/// Errors produced when writing a packet
190#[derive(thiserror::Error, Debug, PartialEq, Eq)]
191#[non_exhaustive]
192pub enum RtcpWriteError {
193    /// Output buffer is not large enough to fit the resulting buffer.  The requested size is
194    /// returned.
195    #[error("Output buffer is not large enough to fit the resulting buffer. Requested size: {}", .0)]
196    OutputTooSmall(usize),
197
198    /// The provided padding is not a multiple of 4.
199    #[error("The provided padding {padding} is not a multiple of 4")]
200    InvalidPadding {
201        /// The padding value encountered.
202        padding: u8,
203    },
204
205    /// App Subtype was out of range.
206    #[error("App Subtype {subtype} was out of range (max: {max})")]
207    AppSubtypeOutOfRange {
208        /// The subtype value encountered.
209        subtype: u8,
210        /// The maximum allowable value.
211        max: u8,
212    },
213
214    /// APP Packet Name is invalid.  Expecting a sequence of four ASCII characters.
215    #[error("APP Packet Name is invalid.  Expecting a sequence of four ASCII characters.")]
216    InvalidName,
217
218    /// Data length must be a mutliple of 32bits.  The data length is returned.
219    #[error("Data length must be a mutliple of 32bits. Data len: {}", .0)]
220    DataLen32bitMultiple(usize),
221
222    /// Too many Sources specified.
223    #[error("Too many Sources specified. Number of Sources: {count}, max: {max}")]
224    TooManySources {
225        /// The count of sources encountered.
226        count: usize,
227        /// The maximum allowable value.
228        max: u8,
229    },
230
231    /// Reason length was too large.
232    #[error("Reason length {len} was too large (max {max})")]
233    ReasonLenTooLarge {
234        /// The length value encountered.
235        len: usize,
236        /// The maximum allowable value.
237        max: u8,
238    },
239
240    /// Cumulative Lost was too large.
241    #[error("Cumulative Lost {value} was too large (max {max})")]
242    CumulativeLostTooLarge {
243        /// The value encountered.
244        value: u32,
245        /// The maximum allowable value.
246        max: u32,
247    },
248
249    /// Too many Report Blocks specified (max 31).
250    #[error("Too many Report Blocks specified. Number of Report Blocks: {count} max: {max}")]
251    TooManyReportBlocks {
252        /// The number of report blocks encountered.
253        count: usize,
254        /// The maximum allowable value.
255        max: u8,
256    },
257
258    /// Too many SDES Chunks specified.
259    #[error("Too many SDES Chunks specified. Number of SDES Chunks: {count}, max: {max}")]
260    TooManySdesChunks {
261        /// The number of SDES chunks encountered.
262        count: usize,
263        /// The maximum allowable value.
264        max: u8,
265    },
266
267    /// SDES Value length was too large.
268    #[error("SDES Value length {len} was too large (max {max})")]
269    SdesValueTooLarge {
270        /// The length of the SDES value that was encountered.
271        len: usize,
272        /// The maximum allowable value.
273        max: u8,
274    },
275
276    /// The SDES PRIV prefix was too large.
277    #[error("The SDES PRIV prefix length {len} too large (max {max})")]
278    SdesPrivPrefixTooLarge {
279        /// The length of the SDES PRIV prefix that was encountered.
280        len: usize,
281        /// The maximum allowable value.
282        max: u8,
283    },
284
285    /// Unknown Count was out of range.
286    #[error("Unknown Count {count} was out of range (max: {max})")]
287    CountOutOfRange {
288        /// The count value that was encountered.
289        count: u8,
290        /// The maximum allowable value.
291        max: u8,
292    },
293
294    /// Non-last Compound packet padding defined.
295    #[error("Non-last Compound packet padding defined")]
296    NonLastCompoundPacketPadding,
297
298    /// Feedback packet does not have any FCI defined.
299    #[error("Feedback packet does not contain any FCI data")]
300    MissingFci,
301
302    /// Number of NACK's will not fit within a single RTCP packet.
303    #[error("The number of NACK entries will not fit inside a RTCP packet.")]
304    TooManyNack,
305
306    /// Feedback packet does not support this FCI data.
307    #[error("Wrong feedback packet type for the provided FCI data")]
308    FciWrongFeedbackPacketType,
309
310    /// Payload type value out of range.
311    #[error("The RTP payload value is not a valid value")]
312    PayloadTypeInvalid,
313
314    /// Payload type value out of range.
315    #[error("The amount of padding bits are greater than the size of the data")]
316    PaddingBitsTooLarge,
317
318    /// Number of FIR's will not fit within a single RTCP packet.
319    #[error("The number of FIR entries will not fit inside a RTCP packet.")]
320    TooManyFir,
321}
322
323impl From<RtcpParseError> for RtcpWriteError {
324    fn from(err: RtcpParseError) -> Self {
325        match err {
326            RtcpParseError::SdesValueTooLarge { len, max } => {
327                RtcpWriteError::SdesValueTooLarge { len, max }
328            }
329            RtcpParseError::SdesPrivPrefixTooLarge { len, available } => {
330                RtcpWriteError::SdesPrivPrefixTooLarge {
331                    len,
332                    max: available,
333                }
334            }
335            other => unreachable!("{other}"),
336        }
337    }
338}
339
340mod app;
341mod bye;
342mod compound;
343mod feedback;
344mod receiver;
345mod report_block;
346mod sdes;
347mod sender;
348pub mod utils;
349mod xr;
350
351pub use app::{App, AppBuilder};
352pub use bye::{Bye, ByeBuilder};
353pub use compound::{Compound, CompoundBuilder, Packet, PacketBuilder, Unknown, UnknownBuilder};
354pub use feedback::fir::{Fir, FirBuilder, FirEntry};
355pub use feedback::nack::{Nack, NackBuilder};
356pub use feedback::pli::{Pli, PliBuilder};
357pub use feedback::rpsi::{Rpsi, RpsiBuilder};
358pub use feedback::sli::{Sli, SliBuilder};
359pub use feedback::{
360    FciBuilder, FciParser, PayloadFeedback, PayloadFeedbackBuilder, TransportFeedback,
361    TransportFeedbackBuilder,
362};
363pub use receiver::{ReceiverReport, ReceiverReportBuilder};
364pub use report_block::{ReportBlock, ReportBlockBuilder};
365pub use sdes::{Sdes, SdesBuilder, SdesChunk, SdesChunkBuilder, SdesItem, SdesItemBuilder};
366pub use sender::{SenderReport, SenderReportBuilder};
367pub use xr::dlrr::{
368    DelaySinceLastReceiverReport, DelaySinceLastReceiverReportBlock,
369    DelaySinceLastReceiverReportBlockBuilder, DelaySinceLastReceiverReportBuilder,
370};
371pub use xr::duplicate_rle::{DuplicateRle, DuplicateRleBuilder};
372pub use xr::loss_rle::{LossRle, LossRleBuilder};
373pub use xr::packet_receipt_time::{PacketReceiptTimes, PacketReceiptTimesBuilder};
374pub use xr::receiver_reference_time::{ReceiverReferenceTime, ReceiverReferenceTimeBuilder};
375pub use xr::rle::RleChunk;
376pub use xr::{
377    Xr, XrBlock, XrBlockBuilder, XrBlockBuilderExt, XrBlockParser, XrBlockParserExt,
378    XrBlockStaticType, XrBuilder,
379};
380
381/// Prelude module for defined/implementable traits
382pub mod prelude {
383    pub use super::{
384        FciBuilder, FciParser, RtcpPacket, RtcpPacketParser, RtcpPacketParserExt, RtcpPacketWriter,
385        RtcpPacketWriterExt, XrBlockBuilder, XrBlockBuilderExt, XrBlockParser, XrBlockParserExt,
386        XrBlockStaticType,
387    };
388}