1 #[cfg(test)] 2 mod extended_report_test; 3 4 pub mod dlrr; 5 pub mod prt; 6 pub mod rle; 7 pub mod rrt; 8 pub mod ssr; 9 pub mod unknown; 10 pub mod vm; 11 12 pub use dlrr::{DLRRReport, DLRRReportBlock}; 13 pub use prt::PacketReceiptTimesReportBlock; 14 pub use rle::{Chunk, ChunkType, DuplicateRLEReportBlock, LossRLEReportBlock, RLEReportBlock}; 15 pub use rrt::ReceiverReferenceTimeReportBlock; 16 pub use ssr::{StatisticsSummaryReportBlock, TTLorHopLimitType}; 17 pub use unknown::UnknownReportBlock; 18 pub use vm::VoIPMetricsReportBlock; 19 20 use crate::error; 21 use crate::header::{Header, PacketType, HEADER_LENGTH, SSRC_LENGTH}; 22 use crate::packet::Packet; 23 use crate::util::{get_padding_size, put_padding}; 24 use bytes::{Buf, BufMut, Bytes}; 25 use std::any::Any; 26 use std::fmt; 27 use util::marshal::{Marshal, MarshalSize, Unmarshal}; 28 29 type Result<T> = std::result::Result<T, util::Error>; 30 31 const XR_HEADER_LENGTH: usize = 4; 32 33 /// BlockType specifies the type of report in a report block 34 /// Extended Report block types from RFC 3611. 35 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 36 pub enum BlockType { 37 Unknown = 0, 38 LossRLE = 1, // RFC 3611, section 4.1 39 DuplicateRLE = 2, // RFC 3611, section 4.2 40 PacketReceiptTimes = 3, // RFC 3611, section 4.3 41 ReceiverReferenceTime = 4, // RFC 3611, section 4.4 42 DLRR = 5, // RFC 3611, section 4.5 43 StatisticsSummary = 6, // RFC 3611, section 4.6 44 VoIPMetrics = 7, // RFC 3611, section 4.7 45 } 46 47 impl Default for BlockType { 48 fn default() -> Self { 49 BlockType::Unknown 50 } 51 } 52 53 impl From<u8> for BlockType { 54 fn from(v: u8) -> Self { 55 match v { 56 1 => BlockType::LossRLE, 57 2 => BlockType::DuplicateRLE, 58 3 => BlockType::PacketReceiptTimes, 59 4 => BlockType::ReceiverReferenceTime, 60 5 => BlockType::DLRR, 61 6 => BlockType::StatisticsSummary, 62 7 => BlockType::VoIPMetrics, 63 _ => BlockType::Unknown, 64 } 65 } 66 } 67 68 /// converts the Extended report block types into readable strings 69 impl fmt::Display for BlockType { 70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 71 let s = match *self { 72 BlockType::LossRLE => "LossRLEReportBlockType", 73 BlockType::DuplicateRLE => "DuplicateRLEReportBlockType", 74 BlockType::PacketReceiptTimes => "PacketReceiptTimesReportBlockType", 75 BlockType::ReceiverReferenceTime => "ReceiverReferenceTimeReportBlockType", 76 BlockType::DLRR => "DLRRReportBlockType", 77 BlockType::StatisticsSummary => "StatisticsSummaryReportBlockType", 78 BlockType::VoIPMetrics => "VoIPMetricsReportBlockType", 79 _ => "UnknownReportBlockType", 80 }; 81 write!(f, "{}", s) 82 } 83 } 84 85 /// TypeSpecificField as described in RFC 3611 section 4.5. In typical 86 /// cases, users of ExtendedReports shouldn't need to access this, 87 /// and should instead use the corresponding fields in the actual 88 /// report blocks themselves. 89 pub type TypeSpecificField = u8; 90 91 /// XRHeader defines the common fields that must appear at the start 92 /// of each report block. In typical cases, users of ExtendedReports 93 /// shouldn't need to access this. For locally-constructed report 94 /// blocks, these values will not be accurate until the corresponding 95 /// packet is marshaled. 96 #[derive(Debug, Default, PartialEq, Eq, Clone)] 97 pub struct XRHeader { 98 pub block_type: BlockType, 99 pub type_specific: TypeSpecificField, 100 pub block_length: u16, 101 } 102 103 impl MarshalSize for XRHeader { 104 fn marshal_size(&self) -> usize { 105 XR_HEADER_LENGTH 106 } 107 } 108 109 impl Marshal for XRHeader { 110 /// marshal_to encodes the ExtendedReport in binary 111 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> { 112 if buf.remaining_mut() < XR_HEADER_LENGTH { 113 return Err(error::Error::BufferTooShort.into()); 114 } 115 116 buf.put_u8(self.block_type as u8); 117 buf.put_u8(self.type_specific); 118 buf.put_u16(self.block_length); 119 120 Ok(XR_HEADER_LENGTH) 121 } 122 } 123 124 impl Unmarshal for XRHeader { 125 /// Unmarshal decodes the ExtendedReport from binary 126 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self> 127 where 128 Self: Sized, 129 B: Buf, 130 { 131 if raw_packet.remaining() < XR_HEADER_LENGTH { 132 return Err(error::Error::PacketTooShort.into()); 133 } 134 135 let block_type: BlockType = raw_packet.get_u8().into(); 136 let type_specific = raw_packet.get_u8(); 137 let block_length = raw_packet.get_u16(); 138 139 Ok(XRHeader { 140 block_type, 141 type_specific, 142 block_length, 143 }) 144 } 145 } 146 /// The ExtendedReport packet is an Implementation of RTCP Extended 147 /// reports defined in RFC 3611. It is used to convey detailed 148 /// information about an RTP stream. Each packet contains one or 149 /// more report blocks, each of which conveys a different kind of 150 /// information. 151 /// 152 /// 0 1 2 3 153 /// 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 154 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 155 /// |V=2|P|reserved | PT=XR=207 | length | 156 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 157 /// | ssrc | 158 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 159 /// : report blocks : 160 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 161 #[derive(Debug, PartialEq, Default, Clone)] 162 pub struct ExtendedReport { 163 pub sender_ssrc: u32, 164 pub reports: Vec<Box<dyn Packet + Send + Sync>>, 165 } 166 167 impl fmt::Display for ExtendedReport { 168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 169 write!(f, "{:?}", self) 170 } 171 } 172 173 impl Packet for ExtendedReport { 174 /// Header returns the Header associated with this packet. 175 fn header(&self) -> Header { 176 Header { 177 padding: get_padding_size(self.raw_size()) != 0, 178 count: 0, 179 packet_type: PacketType::ExtendedReport, 180 length: ((self.marshal_size() / 4) - 1) as u16, 181 } 182 } 183 184 /// destination_ssrc returns an array of ssrc values that this packet refers to. 185 fn destination_ssrc(&self) -> Vec<u32> { 186 let mut ssrc = vec![]; 187 for p in &self.reports { 188 ssrc.extend(p.destination_ssrc()); 189 } 190 ssrc 191 } 192 193 fn raw_size(&self) -> usize { 194 let mut reps_length = 0; 195 for rep in &self.reports { 196 reps_length += rep.marshal_size(); 197 } 198 HEADER_LENGTH + SSRC_LENGTH + reps_length 199 } 200 201 fn as_any(&self) -> &(dyn Any + Send + Sync) { 202 self 203 } 204 205 fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool { 206 other 207 .as_any() 208 .downcast_ref::<ExtendedReport>() 209 .map_or(false, |a| self == a) 210 } 211 212 fn cloned(&self) -> Box<dyn Packet + Send + Sync> { 213 Box::new(self.clone()) 214 } 215 } 216 217 impl MarshalSize for ExtendedReport { 218 fn marshal_size(&self) -> usize { 219 let l = self.raw_size(); 220 // align to 32-bit boundary 221 l + get_padding_size(l) 222 } 223 } 224 225 impl Marshal for ExtendedReport { 226 /// marshal_to encodes the ExtendedReport in binary 227 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> { 228 if buf.remaining_mut() < self.marshal_size() { 229 return Err(error::Error::BufferTooShort.into()); 230 } 231 232 let h = self.header(); 233 let n = h.marshal_to(buf)?; 234 buf = &mut buf[n..]; 235 236 buf.put_u32(self.sender_ssrc); 237 238 for report in &self.reports { 239 let n = report.marshal_to(buf)?; 240 buf = &mut buf[n..]; 241 } 242 243 if h.padding { 244 put_padding(buf, self.raw_size()); 245 } 246 247 Ok(self.marshal_size()) 248 } 249 } 250 251 impl Unmarshal for ExtendedReport { 252 /// Unmarshal decodes the ExtendedReport from binary 253 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self> 254 where 255 Self: Sized, 256 B: Buf, 257 { 258 let raw_packet_len = raw_packet.remaining(); 259 if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) { 260 return Err(error::Error::PacketTooShort.into()); 261 } 262 263 let header = Header::unmarshal(raw_packet)?; 264 if header.packet_type != PacketType::ExtendedReport { 265 return Err(error::Error::WrongType.into()); 266 } 267 268 let sender_ssrc = raw_packet.get_u32(); 269 270 let mut offset = HEADER_LENGTH + SSRC_LENGTH; 271 let mut reports = vec![]; 272 while raw_packet.remaining() > 0 { 273 if offset + XR_HEADER_LENGTH > raw_packet_len { 274 return Err(error::Error::PacketTooShort.into()); 275 } 276 277 let block_type: BlockType = raw_packet.chunk()[0].into(); 278 let report: Box<dyn Packet + Send + Sync> = match block_type { 279 BlockType::LossRLE => Box::new(LossRLEReportBlock::unmarshal(raw_packet)?), 280 BlockType::DuplicateRLE => { 281 Box::new(DuplicateRLEReportBlock::unmarshal(raw_packet)?) 282 } 283 BlockType::PacketReceiptTimes => { 284 Box::new(PacketReceiptTimesReportBlock::unmarshal(raw_packet)?) 285 } 286 BlockType::ReceiverReferenceTime => { 287 Box::new(ReceiverReferenceTimeReportBlock::unmarshal(raw_packet)?) 288 } 289 BlockType::DLRR => Box::new(DLRRReportBlock::unmarshal(raw_packet)?), 290 BlockType::StatisticsSummary => { 291 Box::new(StatisticsSummaryReportBlock::unmarshal(raw_packet)?) 292 } 293 BlockType::VoIPMetrics => Box::new(VoIPMetricsReportBlock::unmarshal(raw_packet)?), 294 _ => Box::new(UnknownReportBlock::unmarshal(raw_packet)?), 295 }; 296 297 offset += report.marshal_size(); 298 reports.push(report); 299 } 300 301 Ok(ExtendedReport { 302 sender_ssrc, 303 reports, 304 }) 305 } 306 } 307