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