1 use super::*; 2 3 const DLRR_REPORT_LENGTH: u16 = 12; 4 5 /// DLRRReport encodes a single report inside a DLRRReportBlock. 6 #[derive(Debug, Default, PartialEq, Eq, Clone)] 7 pub struct DLRRReport { 8 pub ssrc: u32, 9 pub last_rr: u32, 10 pub dlrr: u32, 11 } 12 13 impl fmt::Display for DLRRReport { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 15 write!(f, "{self:?}") 16 } 17 } 18 19 /// DLRRReportBlock encodes a DLRR Report Block as described in 20 /// RFC 3611 section 4.5. 21 /// 22 /// 0 1 2 3 23 /// 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 24 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25 /// | BT=5 | reserved | block length | 26 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 27 /// | SSRC_1 (ssrc of first receiver) | sub- 28 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block 29 /// | last RR (LRR) | 1 30 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 31 /// | delay since last RR (DLRR) | 32 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 33 /// | SSRC_2 (ssrc of second receiver) | sub- 34 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block 35 /// : ... : 2 36 /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 37 #[derive(Debug, Default, PartialEq, Eq, Clone)] 38 pub struct DLRRReportBlock { 39 pub reports: Vec<DLRRReport>, 40 } 41 42 impl fmt::Display for DLRRReportBlock { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 44 write!(f, "{self:?}") 45 } 46 } 47 48 impl DLRRReportBlock { xr_header(&self) -> XRHeader49 pub fn xr_header(&self) -> XRHeader { 50 XRHeader { 51 block_type: BlockType::DLRR, 52 type_specific: 0, 53 block_length: (self.raw_size() / 4 - 1) as u16, 54 } 55 } 56 } 57 58 impl Packet for DLRRReportBlock { header(&self) -> Header59 fn header(&self) -> Header { 60 Header::default() 61 } 62 63 /// destination_ssrc returns an array of ssrc values that this report block refers to. destination_ssrc(&self) -> Vec<u32>64 fn destination_ssrc(&self) -> Vec<u32> { 65 let mut ssrc = Vec::with_capacity(self.reports.len()); 66 for r in &self.reports { 67 ssrc.push(r.ssrc); 68 } 69 ssrc 70 } 71 raw_size(&self) -> usize72 fn raw_size(&self) -> usize { 73 XR_HEADER_LENGTH + self.reports.len() * 4 * 3 74 } 75 as_any(&self) -> &(dyn Any + Send + Sync)76 fn as_any(&self) -> &(dyn Any + Send + Sync) { 77 self 78 } equal(&self, other: &(dyn Packet + Send + Sync)) -> bool79 fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool { 80 other 81 .as_any() 82 .downcast_ref::<DLRRReportBlock>() 83 .map_or(false, |a| self == a) 84 } cloned(&self) -> Box<dyn Packet + Send + Sync>85 fn cloned(&self) -> Box<dyn Packet + Send + Sync> { 86 Box::new(self.clone()) 87 } 88 } 89 90 impl MarshalSize for DLRRReportBlock { marshal_size(&self) -> usize91 fn marshal_size(&self) -> usize { 92 self.raw_size() 93 } 94 } 95 96 impl Marshal for DLRRReportBlock { 97 /// marshal_to encodes the DLRRReportBlock in binary marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>98 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> { 99 if buf.remaining_mut() < self.marshal_size() { 100 return Err(error::Error::BufferTooShort.into()); 101 } 102 103 let h = self.xr_header(); 104 let n = h.marshal_to(buf)?; 105 buf = &mut buf[n..]; 106 107 for rep in &self.reports { 108 buf.put_u32(rep.ssrc); 109 buf.put_u32(rep.last_rr); 110 buf.put_u32(rep.dlrr); 111 } 112 113 Ok(self.marshal_size()) 114 } 115 } 116 117 impl Unmarshal for DLRRReportBlock { 118 /// Unmarshal decodes the DLRRReportBlock from binary unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,119 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self> 120 where 121 Self: Sized, 122 B: Buf, 123 { 124 if raw_packet.remaining() < XR_HEADER_LENGTH { 125 return Err(error::Error::PacketTooShort.into()); 126 } 127 128 let xr_header = XRHeader::unmarshal(raw_packet)?; 129 let block_length = xr_header.block_length * 4; 130 if block_length % DLRR_REPORT_LENGTH != 0 || raw_packet.remaining() < block_length as usize 131 { 132 return Err(error::Error::PacketTooShort.into()); 133 } 134 135 let mut offset = 0; 136 let mut reports = vec![]; 137 while offset < block_length { 138 let ssrc = raw_packet.get_u32(); 139 let last_rr = raw_packet.get_u32(); 140 let dlrr = raw_packet.get_u32(); 141 reports.push(DLRRReport { 142 ssrc, 143 last_rr, 144 dlrr, 145 }); 146 offset += DLRR_REPORT_LENGTH; 147 } 148 149 Ok(DLRRReportBlock { reports }) 150 } 151 } 152