1mod 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#[derive(Clone)]
21pub struct CompoundRtcpPacket {
22 inner: Vec<RtcpPacket>,
23}
24
25impl CompoundRtcpPacket {
26 #[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 #[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 #[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 #[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#[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 #[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#[repr(C, packed)]
133struct RawRtcpHeader {
134 options: u8,
135 packet_type: u8,
136 length: u16,
137}
138
139#[derive(Copy, Clone)]
141pub struct RtcpHeader {
142 options: u8,
143 packet_type: RtcpPacketType,
144 length: u16,
145}
146
147impl RtcpHeader {
148 #[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 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
166 let raw = unsafe { ptr.read_unaligned() };
167
168 if (raw.options >> 6) != 2 {
169 return Err(InvalidInput);
170 }
171
172 let res = Self {
173 options: raw.options,
174 packet_type: raw.packet_type.into(),
175 length: u16::from_be(raw.length),
176 };
177
178 data.advance(std::mem::size_of::<RawRtcpHeader>());
179
180 Ok(res)
181 }
182
183 pub fn encode(&self, buf: &mut BytesMut) {
185 let raw = RawRtcpHeader {
186 options: self.options,
187 packet_type: self.packet_type.raw_id(),
188 length: self.length.to_be(),
189 };
190
191 let ptr = &raw as *const _ as *const u8;
192
193 let data = unsafe { std::slice::from_raw_parts(ptr, std::mem::size_of::<RawRtcpHeader>()) };
194
195 buf.extend_from_slice(data);
196 }
197
198 #[inline]
200 pub fn padding(&self) -> bool {
201 (self.options & 0x20) != 0
202 }
203
204 #[inline]
206 pub fn with_padding(mut self, padding: bool) -> Self {
207 self.options &= !0x20;
208 self.options |= (padding as u8) << 5;
209 self
210 }
211
212 #[inline]
214 pub fn packet_length(&self) -> usize {
215 ((self.length as usize) + 1) << 2
216 }
217
218 #[inline]
227 pub fn with_packet_length(mut self, length: usize) -> Self {
228 assert!((4..=262_144).contains(&length) && (length & 3) == 0);
229
230 self.length = ((length >> 2) - 1) as u16;
231 self
232 }
233
234 #[inline]
236 pub fn packet_type(&self) -> RtcpPacketType {
237 self.packet_type
238 }
239
240 #[inline]
242 pub fn with_packet_type(mut self, packet_type: RtcpPacketType) -> Self {
243 self.packet_type = packet_type;
244 self
245 }
246
247 #[inline]
251 pub fn item_count(&self) -> u8 {
252 self.options & 0x1f
253 }
254
255 #[inline]
260 pub fn with_item_count(mut self, count: u8) -> Self {
261 assert!(count < 32);
262
263 self.options &= !0x1f;
264 self.options |= count & 0x1f;
265 self
266 }
267
268 #[inline]
270 pub fn raw_size(&self) -> usize {
271 std::mem::size_of::<RawRtcpHeader>()
272 }
273}
274
275#[derive(Clone)]
277pub struct RtcpPacket {
278 header: RtcpHeader,
279 payload: Bytes,
280}
281
282impl RtcpPacket {
283 #[inline]
285 pub const fn new(packet_type: RtcpPacketType) -> Self {
286 Self {
287 header: RtcpHeader::new(packet_type),
288 payload: Bytes::new(),
289 }
290 }
291
292 pub fn from_parts(header: RtcpHeader, payload: Bytes) -> Result<Self, InvalidInput> {
294 if header.padding() {
295 let padding_len = payload.last().copied().ok_or(InvalidInput)? as usize;
296
297 if padding_len == 0 || payload.len() < padding_len {
298 return Err(InvalidInput);
299 }
300 }
301
302 let packet_len = header.packet_length();
303
304 if packet_len != (payload.len() + 4) {
305 return Err(InvalidInput);
306 }
307
308 let res = Self { header, payload };
309
310 Ok(res)
311 }
312
313 #[inline]
315 pub fn deconstruct(self) -> (RtcpHeader, Bytes) {
316 (self.header, self.payload)
317 }
318
319 pub fn decode(data: &mut Bytes) -> Result<Self, InvalidInput> {
321 let mut buffer = data.clone();
322
323 let header = RtcpHeader::decode(&mut buffer)?;
324
325 let payload_len = header.packet_length() - 4;
326
327 if buffer.len() < payload_len {
328 return Err(InvalidInput);
329 }
330
331 let res = Self::from_parts(header, buffer.split_to(payload_len))?;
332
333 *data = buffer;
334
335 Ok(res)
336 }
337
338 pub fn encode(&self, buf: &mut BytesMut) {
340 buf.reserve(self.header.packet_length());
341
342 self.header.encode(buf);
343
344 buf.extend_from_slice(&self.payload);
345 }
346
347 #[inline]
349 pub fn header(&self) -> &RtcpHeader {
350 &self.header
351 }
352
353 #[inline]
355 pub fn packet_type(&self) -> RtcpPacketType {
356 self.header.packet_type()
357 }
358
359 #[inline]
361 pub fn with_packet_type(mut self, packet_type: RtcpPacketType) -> Self {
362 self.header = self.header.with_packet_type(packet_type);
363 self
364 }
365
366 #[inline]
370 pub fn item_count(&self) -> u8 {
371 self.header.item_count()
372 }
373
374 #[inline]
379 pub fn with_item_count(mut self, count: u8) -> Self {
380 self.header = self.header.with_item_count(count);
381 self
382 }
383
384 #[inline]
386 pub fn length(&self) -> usize {
387 self.header.packet_length()
388 }
389
390 #[inline]
394 pub fn padding(&self) -> u8 {
395 if self.header.padding() {
396 *self.payload.last().unwrap()
397 } else {
398 0
399 }
400 }
401
402 #[inline]
404 pub fn payload(&self) -> &Bytes {
405 &self.payload
406 }
407
408 #[inline]
410 pub fn stripped_payload(&self) -> Bytes {
411 let payload_len = self.payload.len();
412 let padding_len = self.padding() as usize;
413
414 let len = payload_len - padding_len;
415
416 self.payload.slice(..len)
417 }
418
419 #[inline]
429 pub fn with_payload(mut self, mut payload: Bytes, padding: u8) -> Self {
430 if padding > 0 {
431 let len = payload.len() + (padding as usize);
432
433 let mut buffer = BytesMut::with_capacity(len);
434
435 buffer.extend_from_slice(&payload);
436 buffer.resize(len, 0);
437
438 buffer[len - 1] = padding;
439
440 payload = buffer.freeze();
441
442 self.header = self
443 .header
444 .with_padding(true)
445 .with_packet_length(4 + payload.len());
446 } else {
447 self.header = self
448 .header
449 .with_padding(false)
450 .with_packet_length(4 + payload.len());
451 }
452
453 self.payload = payload;
454
455 self
456 }
457
458 #[inline]
471 pub fn with_padded_payload(mut self, payload: Bytes) -> Self {
472 let padding_len = payload.last().copied().expect("empty payload") as usize;
473
474 assert!(padding_len > 0 && payload.len() >= padding_len);
475
476 self.header = self
477 .header
478 .with_padding(true)
479 .with_packet_length(payload.len());
480
481 self.payload = payload;
482 self
483 }
484
485 #[inline]
487 pub fn raw_size(&self) -> usize {
488 self.length()
489 }
490}