1 use super::*; 2 3 const RLE_REPORT_BLOCK_MIN_LENGTH: u16 = 8; 4 5 /// ChunkType enumerates the three kinds of chunks described in RFC 3611 section 4.1. 6 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 7 pub enum ChunkType { 8 RunLength = 0, 9 BitVector = 1, 10 TerminatingNull = 2, 11 } 12 13 /// Chunk as defined in RFC 3611, section 4.1. These represent information 14 /// about packet losses and packet duplication. They have three representations: 15 /// 16 /// Run Length Chunk: 17 /// 18 /// 0 1 19 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 20 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 21 /// |C|R| run length | 22 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 23 /// 24 /// Bit Vector Chunk: 25 /// 26 /// 0 1 27 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 28 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 29 /// |C| bit vector | 30 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 31 /// 32 /// Terminating Null Chunk: 33 /// 34 /// 0 1 35 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 36 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 37 /// |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| 38 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 39 #[derive(Debug, Default, PartialEq, Eq, Clone)] 40 pub struct Chunk(pub u16); 41 42 impl fmt::Display for Chunk { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 44 match self.chunk_type() { 45 ChunkType::RunLength => { 46 let run_type = self.run_type().unwrap_or(0); 47 write!(f, "[RunLength type={}, length={}]", run_type, self.value()) 48 } 49 ChunkType::BitVector => write!(f, "[BitVector {:#b}", self.value()), 50 ChunkType::TerminatingNull => write!(f, "[TerminatingNull]"), 51 } 52 } 53 } 54 impl Chunk { 55 /// chunk_type returns the ChunkType that this Chunk represents chunk_type(&self) -> ChunkType56 pub fn chunk_type(&self) -> ChunkType { 57 if self.0 == 0 { 58 ChunkType::TerminatingNull 59 } else if (self.0 >> 15) == 0 { 60 ChunkType::RunLength 61 } else { 62 ChunkType::BitVector 63 } 64 } 65 66 /// run_type returns the run_type that this Chunk represents. It is 67 /// only valid if ChunkType is RunLengthChunkType. run_type(&self) -> error::Result<u8>68 pub fn run_type(&self) -> error::Result<u8> { 69 if self.chunk_type() != ChunkType::RunLength { 70 Err(error::Error::WrongChunkType) 71 } else { 72 Ok((self.0 >> 14) as u8 & 0x01) 73 } 74 } 75 76 /// value returns the value represented in this Chunk value(&self) -> u1677 pub fn value(&self) -> u16 { 78 match self.chunk_type() { 79 ChunkType::RunLength => self.0 & 0x3FFF, 80 ChunkType::BitVector => self.0 & 0x7FFF, 81 ChunkType::TerminatingNull => 0, 82 } 83 } 84 } 85 86 /// RleReportBlock defines the common structure used by both 87 /// Loss RLE report blocks (RFC 3611 §4.1) and Duplicate RLE 88 /// report blocks (RFC 3611 §4.2). 89 /// 90 /// 0 1 2 3 91 /// 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 92 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 93 /// | BT = 1 or 2 | rsvd. | t | block length | 94 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 95 /// | ssrc of source | 96 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 97 /// | begin_seq | end_seq | 98 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 99 /// | chunk 1 | chunk 2 | 100 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 101 /// : ... : 102 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 103 /// | chunk n-1 | chunk n | 104 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 105 #[derive(Debug, Default, PartialEq, Eq, Clone)] 106 pub struct RLEReportBlock { 107 //not included in marshal/unmarshal 108 pub is_loss_rle: bool, 109 pub t: u8, 110 111 //marshal/unmarshal 112 pub ssrc: u32, 113 pub begin_seq: u16, 114 pub end_seq: u16, 115 pub chunks: Vec<Chunk>, 116 } 117 118 /// LossRLEReportBlock is used to report information about packet 119 /// losses, as described in RFC 3611, section 4.1 120 /// make sure to set is_loss_rle = true 121 pub type LossRLEReportBlock = RLEReportBlock; 122 123 /// DuplicateRLEReportBlock is used to report information about packet 124 /// duplication, as described in RFC 3611, section 4.1 125 /// make sure to set is_loss_rle = false 126 pub type DuplicateRLEReportBlock = RLEReportBlock; 127 128 impl RLEReportBlock { xr_header(&self) -> XRHeader129 pub fn xr_header(&self) -> XRHeader { 130 XRHeader { 131 block_type: if self.is_loss_rle { 132 BlockType::LossRLE 133 } else { 134 BlockType::DuplicateRLE 135 }, 136 type_specific: self.t & 0x0F, 137 block_length: (self.raw_size() / 4 - 1) as u16, 138 } 139 } 140 } 141 142 impl fmt::Display for RLEReportBlock { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 144 write!(f, "{self:?}") 145 } 146 } 147 148 impl Packet for RLEReportBlock { header(&self) -> Header149 fn header(&self) -> Header { 150 Header::default() 151 } 152 153 /// destination_ssrc returns an array of ssrc values that this report block refers to. destination_ssrc(&self) -> Vec<u32>154 fn destination_ssrc(&self) -> Vec<u32> { 155 vec![self.ssrc] 156 } 157 raw_size(&self) -> usize158 fn raw_size(&self) -> usize { 159 XR_HEADER_LENGTH + RLE_REPORT_BLOCK_MIN_LENGTH as usize + self.chunks.len() * 2 160 } 161 as_any(&self) -> &(dyn Any + Send + Sync)162 fn as_any(&self) -> &(dyn Any + Send + Sync) { 163 self 164 } equal(&self, other: &(dyn Packet + Send + Sync)) -> bool165 fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool { 166 other 167 .as_any() 168 .downcast_ref::<RLEReportBlock>() 169 .map_or(false, |a| self == a) 170 } cloned(&self) -> Box<dyn Packet + Send + Sync>171 fn cloned(&self) -> Box<dyn Packet + Send + Sync> { 172 Box::new(self.clone()) 173 } 174 } 175 176 impl MarshalSize for RLEReportBlock { marshal_size(&self) -> usize177 fn marshal_size(&self) -> usize { 178 self.raw_size() 179 } 180 } 181 182 impl Marshal for RLEReportBlock { 183 /// marshal_to encodes the RLEReportBlock in binary marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>184 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> { 185 if buf.remaining_mut() < self.marshal_size() { 186 return Err(error::Error::BufferTooShort.into()); 187 } 188 189 let h = self.xr_header(); 190 let n = h.marshal_to(buf)?; 191 buf = &mut buf[n..]; 192 193 buf.put_u32(self.ssrc); 194 buf.put_u16(self.begin_seq); 195 buf.put_u16(self.end_seq); 196 for chunk in &self.chunks { 197 buf.put_u16(chunk.0); 198 } 199 200 Ok(self.marshal_size()) 201 } 202 } 203 204 impl Unmarshal for RLEReportBlock { 205 /// Unmarshal decodes the RLEReportBlock from binary unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,206 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self> 207 where 208 Self: Sized, 209 B: Buf, 210 { 211 if raw_packet.remaining() < XR_HEADER_LENGTH { 212 return Err(error::Error::PacketTooShort.into()); 213 } 214 215 let xr_header = XRHeader::unmarshal(raw_packet)?; 216 let block_length = xr_header.block_length * 4; 217 if block_length < RLE_REPORT_BLOCK_MIN_LENGTH 218 || (block_length - RLE_REPORT_BLOCK_MIN_LENGTH) % 2 != 0 219 || raw_packet.remaining() < block_length as usize 220 { 221 return Err(error::Error::PacketTooShort.into()); 222 } 223 224 let is_loss_rle = xr_header.block_type == BlockType::LossRLE; 225 let t = xr_header.type_specific & 0x0F; 226 227 let ssrc = raw_packet.get_u32(); 228 let begin_seq = raw_packet.get_u16(); 229 let end_seq = raw_packet.get_u16(); 230 231 let remaining = block_length - RLE_REPORT_BLOCK_MIN_LENGTH; 232 let mut chunks = vec![]; 233 for _ in 0..remaining / 2 { 234 chunks.push(Chunk(raw_packet.get_u16())); 235 } 236 237 Ok(RLEReportBlock { 238 is_loss_rle, 239 t, 240 ssrc, 241 begin_seq, 242 end_seq, 243 chunks, 244 }) 245 } 246 } 247