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