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
84 .as_any()
85 .downcast_ref::<ReceiverReport>()
86 .map_or(false, |a| self == a)
87 }
88
89 fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
90 Box::new(self.clone())
91 }
92}
93
94impl MarshalSize for ReceiverReport {
95 fn marshal_size(&self) -> usize {
96 let l = self.raw_size();
97 // align to 32-bit boundary
98 l + get_padding_size(l)
99 }
100}
101
102impl Marshal for ReceiverReport {
103 /// marshal_to encodes the packet in binary.
104 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
105 if self.reports.len() > COUNT_MAX {
106 return Err(Error::TooManyReports.into());
107 }
108
109 if buf.remaining_mut() < self.marshal_size() {
110 return Err(Error::BufferTooShort.into());
111 }
112
113 /*
114 * 0 1 2 3
115 * 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
116 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117 * header |V=2|P| RC | PT=RR=201 | length |
118 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119 * | SSRC of packet sender |
120 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
121 * report | SSRC_1 (SSRC of first source) |
122 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 * 1 | fraction lost | cumulative number of packets lost |
124 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125 * | extended highest sequence number received |
126 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127 * | interarrival jitter |
128 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 * | last SR (LSR) |
130 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 * | delay since last SR (DLSR) |
132 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
133 * report | SSRC_2 (SSRC of second source) |
134 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135 * 2 : ... :
136 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
137 * | profile-specific extensions |
138 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139 */
140 let h = self.header();
141 let n = h.marshal_to(buf)?;
142 buf = &mut buf[n..];
143
144 buf.put_u32(self.ssrc);
145
146 for report in &self.reports {
147 let n = report.marshal_to(buf)?;
148 buf = &mut buf[n..];
149 }
150
151 buf.put(self.profile_extensions.clone());
152
153 if h.padding {
154 put_padding(buf, self.raw_size());
155 }
156
157 Ok(self.marshal_size())
158 }
159}
160
161impl Unmarshal for ReceiverReport {
162 /// Unmarshal decodes the ReceiverReport from binary
163 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
164 where
165 Self: Sized,
166 B: Buf,
167 {
168 /*
169 * 0 1 2 3
170 * 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
171 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
172 * header |V=2|P| RC | PT=RR=201 | length |
173 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
174 * | SSRC of packet sender |
175 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
176 * report | SSRC_1 (SSRC of first source) |
177 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178 * 1 | fraction lost | cumulative number of packets lost |
179 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180 * | extended highest sequence number received |
181 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
182 * | interarrival jitter |
183 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
184 * | last SR (LSR) |
185 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
186 * | delay since last SR (DLSR) |
187 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
188 * report | SSRC_2 (SSRC of second source) |
189 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
190 * 2 : ... :
191 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
192 * | profile-specific extensions |
193 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
194 */
195 let raw_packet_len = raw_packet.remaining();
196 if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
197 return Err(Error::PacketTooShort.into());
198 }
199
200 let header = Header::unmarshal(raw_packet)?;
201 if header.packet_type != PacketType::ReceiverReport {
202 return Err(Error::WrongType.into());
203 }
204
205 let ssrc = raw_packet.get_u32();
206
207 let mut offset = RR_REPORT_OFFSET;
208 let mut reports = Vec::with_capacity(header.count as usize);
209 for _ in 0..header.count {
210 if offset + RECEPTION_REPORT_LENGTH > raw_packet_len {
211 return Err(Error::PacketTooShort.into());
212 }
213 let reception_report = ReceptionReport::unmarshal(raw_packet)?;
214 reports.push(reception_report);
215 offset += RECEPTION_REPORT_LENGTH;
216 }
217 let profile_extensions = raw_packet.copy_to_bytes(raw_packet.remaining());
218 /*
219 if header.padding && raw_packet.has_remaining() {
220 raw_packet.advance(raw_packet.remaining());
221 }
222 */
223
224 Ok(ReceiverReport {
225 ssrc,
226 reports,
227 profile_extensions,
228 })
229 }
230}