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