1 use super::*; 2 use crate::goodbye::Goodbye; 3 use crate::payload_feedbacks::picture_loss_indication::PictureLossIndication; 4 5 // An RTCP packet from a packet dump 6 const REAL_PACKET: [u8; 116] = [ 7 // Receiver Report (offset=0) 8 0x81, 0xc9, 0x0, 0x7, // v=2, p=0, count=1, RR, len=7 9 0x90, 0x2f, 0x9e, 0x2e, // ssrc=0x902f9e2e 10 0xbc, 0x5e, 0x9a, 0x40, // ssrc=0xbc5e9a40 11 0x0, 0x0, 0x0, 0x0, // fracLost=0, totalLost=0 12 0x0, 0x0, 0x46, 0xe1, // lastSeq=0x46e1 13 0x0, 0x0, 0x1, 0x11, // jitter=273 14 0x9, 0xf3, 0x64, 0x32, // lsr=0x9f36432 15 0x0, 0x2, 0x4a, 0x79, // delay=150137 16 // Source Description (offset=32) 17 0x81, 0xca, 0x0, 0xc, // v=2, p=0, count=1, SDES, len=12 18 0x90, 0x2f, 0x9e, 0x2e, // ssrc=0x902f9e2e 19 0x1, 0x26, // CNAME, len=38 20 0x7b, 0x39, 0x63, 0x30, 0x30, 0x65, 0x62, 0x39, 0x32, 0x2d, 0x31, 0x61, 0x66, 0x62, 0x2d, 0x39, 21 0x64, 0x34, 0x39, 0x2d, 0x61, 0x34, 0x37, 0x64, 0x2d, 0x39, 0x31, 0x66, 0x36, 0x34, 0x65, 0x65, 22 0x65, 0x36, 0x39, 0x66, 0x35, 0x7d, // text="{9c00eb92-1afb-9d49-a47d-91f64eee69f5}" 23 0x0, 0x0, 0x0, 0x0, // END + padding 24 // Goodbye (offset=84) 25 0x81, 0xcb, 0x0, 0x1, // v=2, p=0, count=1, BYE, len=1 26 0x90, 0x2f, 0x9e, 0x2e, // source=0x902f9e2e 27 0x81, 0xce, 0x0, 0x2, // Picture Loss Indication (offset=92) 28 0x90, 0x2f, 0x9e, 0x2e, // sender=0x902f9e2e 29 0x90, 0x2f, 0x9e, 0x2e, // media=0x902f9e2e 30 0x85, 0xcd, 0x0, 0x2, // RapidResynchronizationRequest (offset=104) 31 0x90, 0x2f, 0x9e, 0x2e, // sender=0x902f9e2e 32 0x90, 0x2f, 0x9e, 0x2e, // media=0x902f9e2e 33 ]; 34 35 #[test] 36 fn test_read_eof() { 37 let mut short_header = Bytes::from_static(&[ 38 0x81, 0xc9, // missing type & len 39 ]); 40 let result = unmarshal(&mut short_header); 41 assert!(result.is_err(), "missing type & len"); 42 } 43 44 #[test] 45 fn test_bad_compound() { 46 let mut bad_compound = Bytes::copy_from_slice(&REAL_PACKET[..34]); 47 let result = unmarshal(&mut bad_compound); 48 assert!(result.is_err(), "trailing data!"); 49 50 let mut bad_compound = Bytes::copy_from_slice(&REAL_PACKET[84..104]); 51 let p = unmarshal(&mut bad_compound).expect("Error unmarshalling packet"); 52 let compound = CompoundPacket(p); 53 54 // this should return an error, 55 // it violates the "must start with RR or SR" rule 56 match compound.validate() { 57 Ok(_) => panic!("validation should return an error"), 58 59 Err(err) => { 60 let a = Error::BadFirstPacket; 61 assert_eq!( 62 Error::BadFirstPacket, 63 err, 64 "Unmarshal(badcompound) err={:?}, want {:?}", 65 err, 66 a, 67 ); 68 } 69 }; 70 71 let compound_len = compound.0.len(); 72 assert_eq!( 73 compound_len, 2, 74 "Unmarshal(badcompound) len={}, want {}", 75 compound_len, 2 76 ); 77 78 if compound.0[0].as_any().downcast_ref::<Goodbye>().is_none() { 79 panic!("Unmarshal(badcompound), want Goodbye") 80 } 81 82 if compound.0[1] 83 .as_any() 84 .downcast_ref::<PictureLossIndication>() 85 .is_none() 86 { 87 panic!("Unmarshal(badcompound), want PictureLossIndication") 88 } 89 } 90 91 #[test] 92 fn test_valid_packet() { 93 let cname = SourceDescription { 94 chunks: vec![SourceDescriptionChunk { 95 source: 1234, 96 items: vec![SourceDescriptionItem { 97 sdes_type: SdesType::SdesCname, 98 text: Bytes::from_static(b"cname"), 99 }], 100 }], 101 }; 102 103 let tests: Vec<(&str, CompoundPacket, Option<Error>)> = vec![ 104 ( 105 "no cname", 106 CompoundPacket(vec![Box::new(SenderReport::default())]), 107 Some(Error::MissingCname), 108 ), 109 ( 110 "SDES / no cname", 111 CompoundPacket(vec![ 112 Box::new(SenderReport::default()), 113 Box::new(SourceDescription::default()), 114 ]), 115 Some(Error::MissingCname), 116 ), 117 ( 118 "just SR", 119 CompoundPacket(vec![ 120 Box::new(SenderReport::default()), 121 Box::new(cname.to_owned()), 122 ]), 123 None, 124 ), 125 ( 126 "multiple SRs", 127 CompoundPacket(vec![ 128 Box::new(SenderReport::default()), 129 Box::new(SenderReport::default()), 130 Box::new(cname.clone()), 131 ]), 132 Some(Error::PacketBeforeCname), 133 ), 134 ( 135 "just RR", 136 CompoundPacket(vec![ 137 Box::new(ReceiverReport::default()), 138 Box::new(cname.clone()), 139 ]), 140 None, 141 ), 142 ( 143 "multiple RRs", 144 CompoundPacket(vec![ 145 Box::new(ReceiverReport::default()), 146 Box::new(cname.clone()), 147 Box::new(ReceiverReport::default()), 148 ]), 149 None, 150 ), 151 ( 152 "goodbye", 153 CompoundPacket(vec![ 154 Box::new(ReceiverReport::default()), 155 Box::new(cname), 156 Box::new(Goodbye::default()), 157 ]), 158 None, 159 ), 160 ]; 161 162 for (name, packet, error) in tests { 163 let result = packet.validate(); 164 assert_eq!(result.is_ok(), error.is_none()); 165 if let (Some(err), Err(got)) = (error, result) { 166 assert_eq!(err, got, "Valid({}) = {:?}, want {:?}", name, got, err); 167 } 168 } 169 } 170 171 #[test] 172 fn test_cname() { 173 let cname = SourceDescription { 174 chunks: vec![SourceDescriptionChunk { 175 source: 1234, 176 items: vec![SourceDescriptionItem { 177 sdes_type: SdesType::SdesCname, 178 text: Bytes::from_static(b"cname"), 179 }], 180 }], 181 }; 182 183 let tests: Vec<(&str, CompoundPacket, Option<Error>, &str)> = vec![ 184 ( 185 "no cname", 186 CompoundPacket(vec![Box::new(SenderReport::default())]), 187 Some(Error::MissingCname), 188 "", 189 ), 190 ( 191 "SDES / no cname", 192 CompoundPacket(vec![ 193 Box::new(SenderReport::default()), 194 Box::new(SourceDescription::default()), 195 ]), 196 Some(Error::MissingCname), 197 "", 198 ), 199 ( 200 "just SR", 201 CompoundPacket(vec![ 202 Box::new(SenderReport::default()), 203 Box::new(cname.clone()), 204 ]), 205 None, 206 "cname", 207 ), 208 ( 209 "multiple SRs", 210 CompoundPacket(vec![ 211 Box::new(SenderReport::default()), 212 Box::new(SenderReport::default()), 213 Box::new(cname.clone()), 214 ]), 215 Some(Error::PacketBeforeCname), 216 "", 217 ), 218 ( 219 "just RR", 220 CompoundPacket(vec![ 221 Box::new(ReceiverReport::default()), 222 Box::new(cname.clone()), 223 ]), 224 None, 225 "cname", 226 ), 227 ( 228 "multiple RRs", 229 CompoundPacket(vec![ 230 Box::new(ReceiverReport::default()), 231 Box::new(ReceiverReport::default()), 232 Box::new(cname.clone()), 233 ]), 234 None, 235 "cname", 236 ), 237 ( 238 "goodbye", 239 CompoundPacket(vec![ 240 Box::new(ReceiverReport::default()), 241 Box::new(cname), 242 Box::new(Goodbye::default()), 243 ]), 244 None, 245 "cname", 246 ), 247 ]; 248 249 for (name, compound_packet, want_error, text) in tests { 250 let err = compound_packet.validate(); 251 assert_eq!(err.is_err(), want_error.is_some()); 252 if let (Some(want), Err(err)) = (&want_error, err) { 253 assert_eq!(*want, err, "Valid({}) = {:?}, want {:?}", name, err, want); 254 } 255 256 let name_result = compound_packet.cname(); 257 assert_eq!(name_result.is_err(), want_error.is_some()); 258 259 match name_result { 260 Ok(e) => { 261 assert_eq!(e, text, "CNAME({}) = {:?}, want {}", name, e, text,); 262 } 263 264 Err(err) => { 265 if let Some(want) = &want_error { 266 assert_eq!(*want, err, "CNAME({}) = {:?}, want {:?}", name, err, want); 267 } 268 } 269 } 270 } 271 } 272 273 #[test] 274 fn test_compound_packet_roundtrip() { 275 let cname = SourceDescription { 276 chunks: vec![SourceDescriptionChunk { 277 source: 1234, 278 items: vec![SourceDescriptionItem { 279 sdes_type: SdesType::SdesCname, 280 text: Bytes::from_static(b"cname"), 281 }], 282 }], 283 }; 284 285 let tests = vec![ 286 ( 287 "goodbye", 288 CompoundPacket(vec![ 289 Box::new(ReceiverReport::default()), 290 Box::new(cname), 291 Box::new(Goodbye { 292 sources: vec![1234], 293 ..Default::default() 294 }), 295 ]), 296 None, 297 ), 298 ( 299 "no cname", 300 CompoundPacket(vec![Box::new(ReceiverReport::default())]), 301 Some(Error::MissingCname), 302 ), 303 ]; 304 305 for (name, packet, marshal_error) in tests { 306 let result = packet.marshal(); 307 if let Some(err) = marshal_error { 308 if let Err(got) = result { 309 assert_eq!( 310 err, got, 311 "marshal {} header: err = {}, want {}", 312 name, got, err 313 ); 314 } else { 315 panic!("want error in test {}", name); 316 } 317 continue; 318 } else { 319 assert!(result.is_ok(), "must no error in test {}", name); 320 } 321 322 let data1 = result.unwrap(); 323 let c = CompoundPacket::unmarshal(&mut data1.clone()) 324 .unwrap_or_else(|_| panic!("unmarshal {} error", name)); 325 326 let data2 = c 327 .marshal() 328 .unwrap_or_else(|_| panic!("marshal {} error", name)); 329 330 assert_eq!( 331 data1, data2, 332 "Unmarshal(Marshal({:?})) = {:?}, want {:?}", 333 name, data1, data2 334 ) 335 } 336 } 337