rtp_parse/rtcp/
rtcp_packet.rs1use anyhow::{anyhow, bail, Context};
2use parsely_rs::*;
3
4use crate::rtcp::rtcp_bye::RtcpByePacket;
5
6use super::{
7 rtcp_fb_fir::RtcpFbFirPacket,
8 rtcp_fb_header::RtcpFbHeader,
9 rtcp_fb_nack::RtcpFbNackPacket,
10 rtcp_fb_packet::{RtcpFbPsPacket, RtcpFbTlPacket},
11 rtcp_fb_tcc::RtcpFbTccPacket,
12 rtcp_header::RtcpHeader,
13 rtcp_rr::RtcpRrPacket,
14 rtcp_sdes::RtcpSdesPacket,
15 rtcp_sr::RtcpSrPacket,
16};
17
18#[derive(Debug)]
19pub enum SomeRtcpPacket {
20 CompoundRtcpPacket(Vec<SomeRtcpPacket>),
21 RtcpByePacket(RtcpByePacket),
22 RtcpSrPacket(RtcpSrPacket),
23 RtcpRrPacket(RtcpRrPacket),
24 RtcpSdesPacket(RtcpSdesPacket),
25 RtcpFbNackPacket(RtcpFbNackPacket),
26 RtcpFbFirPacket(RtcpFbFirPacket),
27 RtcpFbTccPacket(RtcpFbTccPacket),
28 UnknownRtcpPacket {
30 header: RtcpHeader,
31 payload: Vec<u8>,
32 },
33}
34
35impl<B: BitBuf> ParselyRead<B> for SomeRtcpPacket {
36 type Ctx = ();
37 fn read<T: ByteOrder>(buf: &mut B, _ctx: Self::Ctx) -> ParselyResult<Self> {
38 let mut packets: Vec<SomeRtcpPacket> = Vec::new();
39
40 let mut sub_packet_num = 1;
41 while buf.remaining_bytes() >= RtcpHeader::SIZE_BYTES {
42 let packet = read_single_rtcp_packet::<T, B>(buf)
43 .with_context(|| format!("sub packet {sub_packet_num}"))?;
44 packets.push(packet);
45 sub_packet_num += 1;
46 }
47
48 match packets.len() {
49 0 => Err(anyhow!("No valid packets found")),
50 1 => Ok(packets.remove(0)),
51 _ => Ok(SomeRtcpPacket::CompoundRtcpPacket(packets)),
52 }
53 }
54}
55
56pub fn read_single_rtcp_packet<T: ByteOrder, B: BitBuf>(
57 buf: &mut B,
58) -> ParselyResult<SomeRtcpPacket> {
59 let header = RtcpHeader::read::<T>(buf, ()).context("header")?;
60 let payload_length = header
61 .payload_length_bytes()
62 .context("header length field")? as usize;
63 if payload_length > buf.remaining_bytes() {
64 bail!("Invalid RTCP packet, length {payload_length} bytes but buf has only {} bytes remaining", buf.remaining_bytes());
65 }
66
67 let mut payload_buffer = buf.take_bytes(payload_length);
68 let result: ParselyResult<SomeRtcpPacket> = match header.packet_type {
69 RtcpByePacket::PT => Ok(SomeRtcpPacket::RtcpByePacket(
70 RtcpByePacket::read::<T>(&mut payload_buffer, (header,)).context("rtcp bye")?,
71 )),
72 RtcpSdesPacket::PT => Ok(SomeRtcpPacket::RtcpSdesPacket(
73 RtcpSdesPacket::read::<T>(&mut payload_buffer, (header,)).context("rtcp sdes")?,
74 )),
75 RtcpRrPacket::PT => Ok(SomeRtcpPacket::RtcpRrPacket(
76 RtcpRrPacket::read::<T>(&mut payload_buffer, (header,)).context("rtcp rr")?,
77 )),
78 RtcpSrPacket::PT => Ok(SomeRtcpPacket::RtcpSrPacket(
79 RtcpSrPacket::read::<T>(&mut payload_buffer, (header,)).context("rtcp sr")?,
80 )),
81 RtcpFbPsPacket::PT | RtcpFbTlPacket::PT => {
82 let fb_header =
83 RtcpFbHeader::read::<T>(&mut payload_buffer, ()).context("rtcp fb header")?;
84 match (header.packet_type, header.report_count) {
85 (RtcpFbPsPacket::PT, RtcpFbFirPacket::FMT) => Ok(SomeRtcpPacket::RtcpFbFirPacket(
86 RtcpFbFirPacket::read::<T>(&mut payload_buffer, (header, fb_header))
87 .context("rtcp fb fir")?,
88 )),
89 (RtcpFbTlPacket::PT, RtcpFbNackPacket::FMT) => {
90 Ok(SomeRtcpPacket::RtcpFbNackPacket(
91 RtcpFbNackPacket::read::<T>(&mut payload_buffer, (header, fb_header))
92 .context("rtcp fb nack")?,
93 ))
94 }
95 (RtcpFbTlPacket::PT, RtcpFbTccPacket::FMT) => Ok(SomeRtcpPacket::RtcpFbTccPacket(
96 RtcpFbTccPacket::read::<T>(&mut payload_buffer, (header, fb_header))
97 .context("rtcp fb tcc")?,
98 )),
99
100 (pt, fmt) => bail!("Unsuppsorted RTCP FB packet, pt {pt} fmt {fmt}"),
101 }
102 }
103 pt => bail!("Unsupported packet type {pt}"),
104 };
105 if payload_buffer.remaining_bytes() > 0 {
106 bail!("Did not consume entire buffer when reading rtcp packet");
108 }
109 result
113}
114
115#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_read_rtcp() {
179 let mut rtcp_bye = RtcpByePacket::default()
180 .add_ssrc(42)
181 .add_ssrc(43)
182 .with_reason("ciao");
183 rtcp_bye.sync(()).expect("sync");
184
185 let packet_size = RtcpHeader::SIZE_BYTES + rtcp_bye.payload_length_bytes() as usize;
186 let mut buf_mut = BitsMut::new();
187 rtcp_bye
188 .write::<NetworkOrder>(&mut buf_mut, ())
189 .expect("successful write");
190
191 assert_eq!(packet_size, buf_mut.len_bytes());
192
193 let mut buf = buf_mut.freeze();
194
195 let result = SomeRtcpPacket::read::<NetworkOrder>(&mut buf, ()).expect("successful read");
196 dbg!(result);
197 }
198}