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(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 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 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 #[inline]
199 pub fn padding(&self) -> bool {
200 (self.options & 0x20) != 0
201 }
202
203 #[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 #[inline]
213 pub fn packet_length(&self) -> usize {
214 ((self.length as usize) + 1) << 2
215 }
216
217 #[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 #[inline]
235 pub fn packet_type(&self) -> RtcpPacketType {
236 self.packet_type
237 }
238
239 #[inline]
241 pub fn with_packet_type(mut self, packet_type: RtcpPacketType) -> Self {
242 self.packet_type = packet_type;
243 self
244 }
245
246 #[inline]
250 pub fn item_count(&self) -> u8 {
251 self.options & 0x1f
252 }
253
254 #[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 #[inline]
269 pub fn raw_size(&self) -> usize {
270 std::mem::size_of::<RawRtcpHeader>()
271 }
272}
273
274#[derive(Clone)]
276pub struct RtcpPacket {
277 header: RtcpHeader,
278 payload: Bytes,
279}
280
281impl RtcpPacket {
282 #[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 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 #[inline]
314 pub fn deconstruct(self) -> (RtcpHeader, Bytes) {
315 (self.header, self.payload)
316 }
317
318 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 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 #[inline]
348 pub fn header(&self) -> &RtcpHeader {
349 &self.header
350 }
351
352 #[inline]
354 pub fn packet_type(&self) -> RtcpPacketType {
355 self.header.packet_type()
356 }
357
358 #[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 #[inline]
369 pub fn item_count(&self) -> u8 {
370 self.header.item_count()
371 }
372
373 #[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 #[inline]
385 pub fn length(&self) -> usize {
386 self.header.packet_length()
387 }
388
389 #[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 #[inline]
403 pub fn payload(&self) -> &Bytes {
404 &self.payload
405 }
406
407 #[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 #[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 #[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 #[inline]
486 pub fn raw_size(&self) -> usize {
487 self.length()
488 }
489}