rtcp/receiver_report/mod.rs
1#[cfg(test)]
2mod receiver_report_test;
3
4use std::any::Any;
5use std::fmt;
6
7use bytes::{Buf, BufMut, Bytes};
8use util::marshal::{Marshal, MarshalSize, Unmarshal};
9
10use crate::error::Error;
11use crate::header::*;
12use crate::packet::*;
13use crate::reception_report::*;
14use crate::util::*;
15
16type Result<T> = std::result::Result<T, util::Error>;
17
18pub(super) const RR_SSRC_OFFSET: usize = HEADER_LENGTH;
19pub(super) const RR_REPORT_OFFSET: usize = RR_SSRC_OFFSET + SSRC_LENGTH;
20
21/// A ReceiverReport (RR) packet provides reception quality feedback for an RTP stream
22#[derive(Debug, PartialEq, Eq, Default, Clone)]
23pub struct ReceiverReport {
24 /// The synchronization source identifier for the originator of this RR packet.
25 pub ssrc: u32,
26 /// Zero or more reception report blocks depending on the number of other
27 /// sources heard by this sender since the last report. Each reception report
28 /// block conveys statistics on the reception of RTP packets from a
29 /// single synchronization source.
30 pub reports: Vec<ReceptionReport>,
31 /// Extension contains additional, payload-specific information that needs to
32 /// be reported regularly about the receiver.
33 pub profile_extensions: Bytes,
34}
35
36impl fmt::Display for ReceiverReport {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 let mut out = format!("ReceiverReport from {}\n", self.ssrc);
39 out += "\tSSRC \tLost\tLastSequence\n";
40 for rep in &self.reports {
41 out += format!(
42 "\t{:x}\t{}/{}\t{}\n",
43 rep.ssrc, rep.fraction_lost, rep.total_lost, rep.last_sequence_number
44 )
45 .as_str();
46 }
47 out += format!("\tProfile Extension Data: {:?}\n", self.profile_extensions).as_str();
48
49 write!(f, "{out}")
50 }
51}
52
53impl Packet for ReceiverReport {
54 /// Header returns the Header associated with this packet.
55 fn header(&self) -> Header {
56 Header {
57 padding: get_padding_size(self.raw_size()) != 0,
58 count: self.reports.len() as u8,
59 packet_type: PacketType::ReceiverReport,
60 length: ((self.marshal_size() / 4) - 1) as u16,
61 }
62 }
63
64 /// destination_ssrc returns an array of SSRC values that this packet refers to.
65 fn destination_ssrc(&self) -> Vec<u32> {
66 self.reports.iter().map(|x| x.ssrc).collect()
67 }
68
69 fn raw_size(&self) -> usize {
70 let mut reps_length = 0;
71 for rep in &self.reports {
72 reps_length += rep.marshal_size();
73 }
74
75 HEADER_LENGTH + SSRC_LENGTH + reps_length + self.profile_extensions.len()
76 }
77
78 fn as_any(&self) -> &(dyn Any + Send + Sync) {
79 self
80 }
81
82 fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
83 other.as_any().downcast_ref::<ReceiverReport>() == Some(self)
84 }
85
86 fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
87 Box::new(self.clone())
88 }
89}
90
91impl MarshalSize for ReceiverReport {
92 fn marshal_size(&self) -> usize {
93 let l = self.raw_size();
94 // align to 32-bit boundary
95 l + get_padding_size(l)
96 }
97}
98
99impl Marshal for ReceiverReport {
100 /// marshal_to encodes the packet in binary.
101 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
102 if self.reports.len() > COUNT_MAX {
103 return Err(Error::TooManyReports.into());
104 }
105
106 if buf.remaining_mut() < self.marshal_size() {
107 return Err(Error::BufferTooShort.into());
108 }
109
110 /*
111 * 0 1 2 3
112 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
113 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 * header |V=2|P| RC | PT=RR=201 | length |
115 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116 * | SSRC of packet sender |
117 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
118 * report | SSRC_1 (SSRC of first source) |
119 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120 * 1 | fraction lost | cumulative number of packets lost |
121 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 * | extended highest sequence number received |
123 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124 * | interarrival jitter |
125 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126 * | last SR (LSR) |
127 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 * | delay since last SR (DLSR) |
129 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
130 * report | SSRC_2 (SSRC of second source) |
131 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132 * 2 : ... :
133 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
134 * | profile-specific extensions |
135 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136 */
137 let h = self.header();
138 let n = h.marshal_to(buf)?;
139 buf = &mut buf[n..];
140
141 buf.put_u32(self.ssrc);
142
143 for report in &self.reports {
144 let n = report.marshal_to(buf)?;
145 buf = &mut buf[n..];
146 }
147
148 buf.put(self.profile_extensions.clone());
149
150 if h.padding {
151 put_padding(buf, self.raw_size());
152 }
153
154 Ok(self.marshal_size())
155 }
156}
157
158impl Unmarshal for ReceiverReport {
159 /// Unmarshal decodes the ReceiverReport from binary
160 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
161 where
162 Self: Sized,
163 B: Buf,
164 {
165 /*
166 * 0 1 2 3
167 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
168 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
169 * header |V=2|P| RC | PT=RR=201 | length |
170 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171 * | SSRC of packet sender |
172 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
173 * report | SSRC_1 (SSRC of first source) |
174 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175 * 1 | fraction lost | cumulative number of packets lost |
176 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177 * | extended highest sequence number received |
178 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179 * | interarrival jitter |
180 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
181 * | last SR (LSR) |
182 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
183 * | delay since last SR (DLSR) |
184 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
185 * report | SSRC_2 (SSRC of second source) |
186 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
187 * 2 : ... :
188 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
189 * | profile-specific extensions |
190 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
191 */
192 let raw_packet_len = raw_packet.remaining();
193 if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
194 return Err(Error::PacketTooShort.into());
195 }
196
197 let header = Header::unmarshal(raw_packet)?;
198 if header.packet_type != PacketType::ReceiverReport {
199 return Err(Error::WrongType.into());
200 }
201
202 let ssrc = raw_packet.get_u32();
203
204 let mut offset = RR_REPORT_OFFSET;
205 let mut reports = Vec::with_capacity(header.count as usize);
206 for _ in 0..header.count {
207 if offset + RECEPTION_REPORT_LENGTH > raw_packet_len {
208 return Err(Error::PacketTooShort.into());
209 }
210 let reception_report = ReceptionReport::unmarshal(raw_packet)?;
211 reports.push(reception_report);
212 offset += RECEPTION_REPORT_LENGTH;
213 }
214 let profile_extensions = raw_packet.copy_to_bytes(raw_packet.remaining());
215 /*
216 if header.padding && raw_packet.has_remaining() {
217 raw_packet.advance(raw_packet.remaining());
218 }
219 */
220
221 Ok(ReceiverReport {
222 ssrc,
223 reports,
224 profile_extensions,
225 })
226 }
227}