1 #[cfg(test)] 2 mod sender_report_test; 3 4 use crate::{error::Error, header::*, packet::*, reception_report::*, util::*}; 5 use util::marshal::{Marshal, MarshalSize, Unmarshal}; 6 7 use bytes::{Buf, BufMut, Bytes}; 8 use std::any::Any; 9 use std::fmt; 10 11 type Result<T> = std::result::Result<T, util::Error>; 12 13 pub(crate) const SR_HEADER_LENGTH: usize = 24; 14 pub(crate) const SR_SSRC_OFFSET: usize = HEADER_LENGTH; 15 pub(crate) const SR_REPORT_OFFSET: usize = SR_SSRC_OFFSET + SR_HEADER_LENGTH; 16 17 pub(crate) const SR_NTP_OFFSET: usize = SR_SSRC_OFFSET + SSRC_LENGTH; 18 pub(crate) const NTP_TIME_LENGTH: usize = 8; 19 pub(crate) const SR_RTP_OFFSET: usize = SR_NTP_OFFSET + NTP_TIME_LENGTH; 20 pub(crate) const RTP_TIME_LENGTH: usize = 4; 21 pub(crate) const SR_PACKET_COUNT_OFFSET: usize = SR_RTP_OFFSET + RTP_TIME_LENGTH; 22 pub(crate) const SR_PACKET_COUNT_LENGTH: usize = 4; 23 pub(crate) const SR_OCTET_COUNT_OFFSET: usize = SR_PACKET_COUNT_OFFSET + SR_PACKET_COUNT_LENGTH; 24 pub(crate) const SR_OCTET_COUNT_LENGTH: usize = 4; 25 26 /// A SenderReport (SR) packet provides reception quality feedback for an RTP stream 27 #[derive(Debug, PartialEq, Eq, Default, Clone)] 28 pub struct SenderReport { 29 /// The synchronization source identifier for the originator of this SR packet. 30 pub ssrc: u32, 31 /// The wallclock time when this report was sent so that it may be used in 32 /// combination with timestamps returned in reception reports from other 33 /// receivers to measure round-trip propagation to those receivers. 34 pub ntp_time: u64, 35 /// Corresponds to the same time as the NTP timestamp (above), but in 36 /// the same units and with the same random offset as the RTP 37 /// timestamps in data packets. This correspondence may be used for 38 /// intra- and inter-media synchronization for sources whose NTP 39 /// timestamps are synchronized, and may be used by media-independent 40 /// receivers to estimate the nominal RTP clock frequency. 41 pub rtp_time: u32, 42 /// The total number of RTP data packets transmitted by the sender 43 /// since starting transmission up until the time this SR packet was 44 /// generated. 45 pub packet_count: u32, 46 /// The total number of payload octets (i.e., not including header or 47 /// padding) transmitted in RTP data packets by the sender since 48 /// starting transmission up until the time this SR packet was 49 /// generated. 50 pub octet_count: u32, 51 /// Zero or more reception report blocks depending on the number of other 52 /// sources heard by this sender since the last report. Each reception report 53 /// block conveys statistics on the reception of RTP packets from a 54 /// single synchronization source. 55 pub reports: Vec<ReceptionReport>, 56 57 /// ProfileExtensions contains additional, payload-specific information that needs to 58 /// be reported regularly about the sender. 59 pub profile_extensions: Bytes, 60 } 61 62 impl fmt::Display for SenderReport { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 64 let mut out = format!("SenderReport from {}\n", self.ssrc); 65 out += format!("\tNTPTime:\t{}\n", self.ntp_time).as_str(); 66 out += format!("\tRTPTIme:\t{}\n", self.rtp_time).as_str(); 67 out += format!("\tPacketCount:\t{}\n", self.packet_count).as_str(); 68 out += format!("\tOctetCount:\t{}\n", self.octet_count).as_str(); 69 out += "\tSSRC \tLost\tLastSequence\n"; 70 for rep in &self.reports { 71 out += format!( 72 "\t{:x}\t{}/{}\t{}\n", 73 rep.ssrc, rep.fraction_lost, rep.total_lost, rep.last_sequence_number 74 ) 75 .as_str(); 76 } 77 out += format!("\tProfile Extension Data: {:?}\n", self.profile_extensions).as_str(); 78 79 write!(f, "{out}") 80 } 81 } 82 83 impl Packet for SenderReport { 84 /// Header returns the Header associated with this packet. header(&self) -> Header85 fn header(&self) -> Header { 86 Header { 87 padding: get_padding_size(self.raw_size()) != 0, 88 count: self.reports.len() as u8, 89 packet_type: PacketType::SenderReport, 90 length: ((self.marshal_size() / 4) - 1) as u16, 91 } 92 } 93 94 /// destination_ssrc returns an array of SSRC values that this packet refers to. destination_ssrc(&self) -> Vec<u32>95 fn destination_ssrc(&self) -> Vec<u32> { 96 let mut out: Vec<u32> = self.reports.iter().map(|x| x.ssrc).collect(); 97 out.push(self.ssrc); 98 out 99 } 100 raw_size(&self) -> usize101 fn raw_size(&self) -> usize { 102 let mut reps_length = 0; 103 for rep in &self.reports { 104 reps_length += rep.marshal_size(); 105 } 106 107 HEADER_LENGTH + SR_HEADER_LENGTH + reps_length + self.profile_extensions.len() 108 } 109 as_any(&self) -> &(dyn Any + Send + Sync)110 fn as_any(&self) -> &(dyn Any + Send + Sync) { 111 self 112 } 113 equal(&self, other: &(dyn Packet + Send + Sync)) -> bool114 fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool { 115 other 116 .as_any() 117 .downcast_ref::<SenderReport>() 118 .map_or(false, |a| self == a) 119 } 120 cloned(&self) -> Box<dyn Packet + Send + Sync>121 fn cloned(&self) -> Box<dyn Packet + Send + Sync> { 122 Box::new(self.clone()) 123 } 124 } 125 126 impl MarshalSize for SenderReport { marshal_size(&self) -> usize127 fn marshal_size(&self) -> usize { 128 let l = self.raw_size(); 129 // align to 32-bit boundary 130 l + get_padding_size(l) 131 } 132 } 133 134 impl Marshal for SenderReport { 135 /// Marshal encodes the packet in binary. marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>136 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> { 137 if self.reports.len() > COUNT_MAX { 138 return Err(Error::TooManyReports.into()); 139 } 140 141 if buf.remaining_mut() < self.marshal_size() { 142 return Err(Error::BufferTooShort.into()); 143 } 144 145 /* 146 * 0 1 2 3 147 * 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 148 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 149 * header |V=2|P| RC | PT=SR=200 | length | 150 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 151 * | SSRC of sender | 152 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 153 * sender | NTP timestamp, most significant word | 154 * info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 155 * | NTP timestamp, least significant word | 156 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 157 * | RTP timestamp | 158 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 159 * | sender's packet count | 160 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 161 * | sender's octet count | 162 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 163 * report | SSRC_1 (SSRC of first source) | 164 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 165 * 1 | fraction lost | cumulative number of packets lost | 166 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 167 * | extended highest sequence number received | 168 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 169 * | interarrival jitter | 170 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 171 * | last SR (LSR) | 172 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 173 * | delay since last SR (DLSR) | 174 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 175 * report | SSRC_2 (SSRC of second source) | 176 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 177 * 2 : ... : 178 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 179 * | profile-specific extensions | 180 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 181 */ 182 let h = self.header(); 183 let n = h.marshal_to(buf)?; 184 buf = &mut buf[n..]; 185 186 buf.put_u32(self.ssrc); 187 buf.put_u64(self.ntp_time); 188 buf.put_u32(self.rtp_time); 189 buf.put_u32(self.packet_count); 190 buf.put_u32(self.octet_count); 191 192 for report in &self.reports { 193 let n = report.marshal_to(buf)?; 194 buf = &mut buf[n..]; 195 } 196 197 buf.put(self.profile_extensions.clone()); 198 199 if h.padding { 200 put_padding(buf, self.raw_size()); 201 } 202 203 Ok(self.marshal_size()) 204 } 205 } 206 207 impl Unmarshal for SenderReport { 208 /// Unmarshal decodes the SenderReport from binary unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,209 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self> 210 where 211 Self: Sized, 212 B: Buf, 213 { 214 /* 215 * 0 1 2 3 216 * 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 217 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 218 * header |V=2|P| RC | PT=SR=200 | length | 219 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 220 * | SSRC of sender | 221 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 222 * sender | NTP timestamp, most significant word | 223 * info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 224 * | NTP timestamp, least significant word | 225 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 226 * | RTP timestamp | 227 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 228 * | sender's packet count | 229 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 230 * | sender's octet count | 231 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 232 * report | SSRC_1 (SSRC of first source) | 233 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 234 * 1 | fraction lost | cumulative number of packets lost | 235 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 236 * | extended highest sequence number received | 237 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 238 * | interarrival jitter | 239 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 240 * | last SR (LSR) | 241 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 242 * | delay since last SR (DLSR) | 243 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 244 * report | SSRC_2 (SSRC of second source) | 245 * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 246 * 2 : ... : 247 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 248 * | profile-specific extensions | 249 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 250 */ 251 let raw_packet_len = raw_packet.remaining(); 252 if raw_packet_len < (HEADER_LENGTH + SR_HEADER_LENGTH) { 253 return Err(Error::PacketTooShort.into()); 254 } 255 256 let header = Header::unmarshal(raw_packet)?; 257 if header.packet_type != PacketType::SenderReport { 258 return Err(Error::WrongType.into()); 259 } 260 261 let ssrc = raw_packet.get_u32(); 262 let ntp_time = raw_packet.get_u64(); 263 let rtp_time = raw_packet.get_u32(); 264 let packet_count = raw_packet.get_u32(); 265 let octet_count = raw_packet.get_u32(); 266 267 let mut offset = SR_REPORT_OFFSET; 268 let mut reports = Vec::with_capacity(header.count as usize); 269 for _ in 0..header.count { 270 if offset + RECEPTION_REPORT_LENGTH > raw_packet_len { 271 return Err(Error::PacketTooShort.into()); 272 } 273 let reception_report = ReceptionReport::unmarshal(raw_packet)?; 274 reports.push(reception_report); 275 offset += RECEPTION_REPORT_LENGTH; 276 } 277 let profile_extensions = raw_packet.copy_to_bytes(raw_packet.remaining()); 278 /* 279 if header.padding && raw_packet.has_remaining() { 280 raw_packet.advance(raw_packet.remaining()); 281 } 282 */ 283 284 Ok(SenderReport { 285 ssrc, 286 ntp_time, 287 rtp_time, 288 packet_count, 289 octet_count, 290 reports, 291 profile_extensions, 292 }) 293 } 294 } 295