1pub trait RtcpPacket {
5 const VERSION: u8 = 2;
6 const MAX_COUNT: u8 = 0x1f;
7 const MIN_PACKET_LEN: usize;
8 const PACKET_TYPE: u8;
9}
10
11pub trait RtcpPacketParser<'a>: RtcpPacket + Sized {
17 fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError>;
22
23 fn header_data(&self) -> [u8; 4];
25}
26
27pub trait RtcpPacketParserExt<'a>: RtcpPacketParser<'a> {
28 fn version(&self) -> u8 {
29 utils::parser::parse_version(&self.header_data())
30 }
31
32 fn type_(&self) -> u8 {
33 utils::parser::parse_packet_type(&self.header_data())
34 }
35
36 fn subtype(&self) -> u8 {
37 utils::parser::parse_count(&self.header_data())
38 }
39
40 fn length(&self) -> usize {
41 utils::parser::parse_length(&self.header_data())
42 }
43
44 fn count(&self) -> u8 {
45 utils::parser::parse_count(&self.header_data())
46 }
47}
48
49impl<'a, T: RtcpPacketParser<'a>> RtcpPacketParserExt<'a> for T {}
50
51pub trait RtcpPacketWriter: std::fmt::Debug {
57 fn calculate_size(&self) -> Result<usize, RtcpWriteError>;
61
62 fn write_into_unchecked(&self, buf: &mut [u8]) -> usize;
72
73 fn get_padding(&self) -> Option<u8>;
75}
76
77pub trait RtcpPacketWriterExt: RtcpPacketWriter {
78 fn write_into(&self, buf: &mut [u8]) -> Result<usize, RtcpWriteError> {
86 let req_size = self.calculate_size()?;
87 if buf.len() < req_size {
88 return Err(RtcpWriteError::OutputTooSmall(req_size));
89 }
90
91 Ok(self.write_into_unchecked(&mut buf[..req_size]))
92 }
93}
94
95impl<T: RtcpPacketWriter> RtcpPacketWriterExt for T {}
96
97#[derive(thiserror::Error, Debug, PartialEq, Eq)]
99pub enum RtcpParseError {
100 #[error("Unsupported version: {}. This implementation only deals with version 2.", .0)]
102 UnsupportedVersion(u8),
103 #[error("The packet was too short to parse. Expected size: {expected}, actual size encountered: {actual}")]
105 Truncated {
106 expected: usize,
108 actual: usize,
110 },
111 #[error("The packet was too large to parse. Expected size: {expected}, actual size encountered: {actual}")]
113 TooLarge {
114 expected: usize,
116 actual: usize,
118 },
119 #[error("Invalid Padding length 0")]
121 InvalidPadding,
122
123 #[error("The SDES Value length {len} was too large (max {max})")]
125 SdesValueTooLarge {
126 len: usize,
128 max: u8,
130 },
131
132 #[error("The SDES PRIC content length {len} was too short (min {min})")]
134 SdesPrivContentTruncated {
135 len: usize,
137 min: u8,
139 },
140
141 #[error("The SDES PRIV prefix length {len} too large (available {available})")]
143 SdesPrivPrefixTooLarge {
144 len: usize,
146 available: u8,
148 },
149
150 #[error("This implementation does not handle this packet")]
152 WrongImplementation,
153
154 #[error("RTCP Packet type mismatch. Actual: {actual}, requested {requested}")]
156 PacketTypeMismatch { actual: u8, requested: u8 },
157}
158
159#[derive(thiserror::Error, Debug, PartialEq, Eq)]
161pub enum RtcpWriteError {
162 #[error("Output buffer is not large enough to fit the resulting buffer. Requested size: {}", .0)]
165 OutputTooSmall(usize),
166
167 #[error("The provided padding {padding} is not a multiple of 4")]
169 InvalidPadding { padding: u8 },
170
171 #[error("App Subtype {subtype} was out of range (max: {max})")]
173 AppSubtypeOutOfRange { subtype: u8, max: u8 },
174
175 #[error("APP Packet Name is invalid. Expecting a sequence of four ASCII characters.")]
177 InvalidName,
178
179 #[error("Data length must be a mutliple of 32bits. Data len: {}", .0)]
181 DataLen32bitMultiple(usize),
182
183 #[error("Too many Sources specified. Number of Sources: {count}, max: {max}")]
185 TooManySources { count: usize, max: u8 },
186
187 #[error("Reason length {len} was too large (max {max})")]
189 ReasonLenTooLarge { len: usize, max: u8 },
190
191 #[error("Cumulative Lost {value} was too large (max {max})")]
193 CumulativeLostTooLarge { value: u32, max: u32 },
194
195 #[error("Too many Report Blocks specified. Number of Report Blocks: {count} max: {max}")]
197 TooManyReportBlocks { count: usize, max: u8 },
198
199 #[error("Too many SDES Chunks specified. Number of SDES Chunks: {count}, max: {max}")]
201 TooManySdesChunks { count: usize, max: u8 },
202
203 #[error("SDES Value length {len} was too large (max {max})")]
205 SdesValueTooLarge { len: usize, max: u8 },
206
207 #[error("The SDES PRIV prefix length {len} too large (max {max})")]
209 SdesPrivPrefixTooLarge { len: usize, max: u8 },
210
211 #[error("Unknown Count {count} was out of range (max: {max})")]
213 CountOutOfRange { count: u8, max: u8 },
214
215 #[error("Non-last Compound packet padding defined")]
217 NonLastCompoundPacketPadding,
218
219 #[error("Feedback packet does not contain any FCI data")]
221 MissingFci,
222
223 #[error("The number of NACK entries will not fit inside a RTCP packet.")]
225 TooManyNack,
226
227 #[error("Wrong feedback packet type for the provided FCI data")]
229 FciWrongFeedbackPacketType,
230
231 #[error("The RTP payload value is not a valid value")]
233 PayloadTypeInvalid,
234
235 #[error("The amount of padding bits are greater than the size of the data")]
237 PaddingBitsTooLarge,
238
239 #[error("The number of FIR entries will not fit inside a RTCP packet.")]
241 TooManyFir,
242}
243
244impl From<RtcpParseError> for RtcpWriteError {
245 fn from(err: RtcpParseError) -> Self {
246 match err {
247 RtcpParseError::SdesValueTooLarge { len, max } => {
248 RtcpWriteError::SdesValueTooLarge { len, max }
249 }
250 RtcpParseError::SdesPrivPrefixTooLarge { len, available } => {
251 RtcpWriteError::SdesPrivPrefixTooLarge {
252 len,
253 max: available,
254 }
255 }
256 other => unreachable!("{other}"),
257 }
258 }
259}
260
261mod app;
262mod bye;
263mod compound;
264mod feedback;
265mod receiver;
266mod report_block;
267mod sdes;
268mod sender;
269pub mod utils;
270
271pub use app::{App, AppBuilder};
272pub use bye::{Bye, ByeBuilder};
273pub use compound::{Compound, CompoundBuilder, Packet, PacketBuilder, Unknown, UnknownBuilder};
274pub use feedback::fir::{Fir, FirBuilder, FirEntry};
275pub use feedback::nack::{Nack, NackBuilder};
276pub use feedback::pli::{Pli, PliBuilder};
277pub use feedback::rpsi::{Rpsi, RpsiBuilder};
278pub use feedback::sli::{Sli, SliBuilder};
279pub use feedback::{
280 FciBuilder, FciParser, PayloadFeedback, PayloadFeedbackBuilder, TransportFeedback,
281 TransportFeedbackBuilder,
282};
283pub use receiver::{ReceiverReport, ReceiverReportBuilder};
284pub use report_block::{ReportBlock, ReportBlockBuilder};
285pub use sdes::{Sdes, SdesBuilder, SdesChunk, SdesChunkBuilder, SdesItem, SdesItemBuilder};
286pub use sender::{SenderReport, SenderReportBuilder};
287
288pub mod prelude {
289 pub use super::{
290 FciBuilder, FciParser, RtcpPacket, RtcpPacketParser, RtcpPacketParserExt, RtcpPacketWriter,
291 RtcpPacketWriterExt,
292 };
293}