xref: /webrtc/stun/src/message/message_test.rs (revision 5d8fe953)
1 use super::*;
2 use crate::xoraddr::*;
3 
4 use crate::fingerprint::FINGERPRINT;
5 use crate::integrity::MessageIntegrity;
6 use crate::textattrs::TextAttribute;
7 use std::io::{BufReader, BufWriter};
8 
9 #[test]
test_message_buffer() -> Result<()>10 fn test_message_buffer() -> Result<()> {
11     let mut m = Message::new();
12     m.typ = MessageType {
13         method: METHOD_BINDING,
14         class: CLASS_REQUEST,
15     };
16     m.transaction_id = TransactionId::new();
17     m.add(ATTR_ERROR_CODE, &[0xff, 0xfe, 0xfa]);
18     m.write_header();
19 
20     let mut m_decoded = Message::new();
21     let mut reader = BufReader::new(m.raw.as_slice());
22     m_decoded.read_from(&mut reader)?;
23 
24     assert_eq!(m_decoded, m, "{m_decoded} != {m}");
25 
26     Ok(())
27 }
28 
29 #[test]
test_message_type_value() -> Result<()>30 fn test_message_type_value() -> Result<()> {
31     let tests = vec![
32         (
33             MessageType {
34                 method: METHOD_BINDING,
35                 class: CLASS_REQUEST,
36             },
37             0x0001,
38         ),
39         (
40             MessageType {
41                 method: METHOD_BINDING,
42                 class: CLASS_SUCCESS_RESPONSE,
43             },
44             0x0101,
45         ),
46         (
47             MessageType {
48                 method: METHOD_BINDING,
49                 class: CLASS_ERROR_RESPONSE,
50             },
51             0x0111,
52         ),
53         (
54             MessageType {
55                 method: Method(0xb6d),
56                 class: MessageClass(0x3),
57             },
58             0x2ddd,
59         ),
60     ];
61 
62     for (input, output) in tests {
63         let b = input.value();
64         assert_eq!(b, output, "Value({input}) -> {b}, want {output}");
65     }
66 
67     Ok(())
68 }
69 
70 #[test]
test_message_type_read_value() -> Result<()>71 fn test_message_type_read_value() -> Result<()> {
72     let tests = vec![
73         (
74             0x0001,
75             MessageType {
76                 method: METHOD_BINDING,
77                 class: CLASS_REQUEST,
78             },
79         ),
80         (
81             0x0101,
82             MessageType {
83                 method: METHOD_BINDING,
84                 class: CLASS_SUCCESS_RESPONSE,
85             },
86         ),
87         (
88             0x0111,
89             MessageType {
90                 method: METHOD_BINDING,
91                 class: CLASS_ERROR_RESPONSE,
92             },
93         ),
94     ];
95 
96     for (input, output) in tests {
97         let mut m = MessageType::default();
98         m.read_value(input);
99         assert_eq!(m, output, "ReadValue({input}) -> {m}, want {output}");
100     }
101 
102     Ok(())
103 }
104 
105 #[test]
test_message_type_read_write_value() -> Result<()>106 fn test_message_type_read_write_value() -> Result<()> {
107     let tests = vec![
108         MessageType {
109             method: METHOD_BINDING,
110             class: CLASS_REQUEST,
111         },
112         MessageType {
113             method: METHOD_BINDING,
114             class: CLASS_SUCCESS_RESPONSE,
115         },
116         MessageType {
117             method: METHOD_BINDING,
118             class: CLASS_ERROR_RESPONSE,
119         },
120         MessageType {
121             method: Method(0x12),
122             class: CLASS_ERROR_RESPONSE,
123         },
124     ];
125 
126     for test in tests {
127         let mut m = MessageType::default();
128         let v = test.value();
129         m.read_value(v);
130         assert_eq!(m, test, "ReadValue({test} -> {v}) = {m}, should be {test}");
131     }
132 
133     Ok(())
134 }
135 
136 #[test]
test_message_write_to() -> Result<()>137 fn test_message_write_to() -> Result<()> {
138     let mut m = Message::new();
139     m.typ = MessageType {
140         method: METHOD_BINDING,
141         class: CLASS_REQUEST,
142     };
143     m.transaction_id = TransactionId::new();
144     m.add(ATTR_ERROR_CODE, &[0xff, 0xfe, 0xfa]);
145     m.write_header();
146     let mut buf = vec![];
147     {
148         let mut writer = BufWriter::<&mut Vec<u8>>::new(buf.as_mut());
149         m.write_to(&mut writer)?;
150     }
151 
152     let mut m_decoded = Message::new();
153     let mut reader = BufReader::new(buf.as_slice());
154     m_decoded.read_from(&mut reader)?;
155     assert_eq!(m_decoded, m, "{m_decoded} != {m}");
156 
157     Ok(())
158 }
159 
160 #[test]
test_message_cookie() -> Result<()>161 fn test_message_cookie() -> Result<()> {
162     let buf = vec![0; 20];
163     let mut m_decoded = Message::new();
164     let mut reader = BufReader::new(buf.as_slice());
165     let result = m_decoded.read_from(&mut reader);
166     assert!(result.is_err(), "should error");
167 
168     Ok(())
169 }
170 
171 #[test]
test_message_length_less_header_size() -> Result<()>172 fn test_message_length_less_header_size() -> Result<()> {
173     let buf = vec![0; 8];
174     let mut m_decoded = Message::new();
175     let mut reader = BufReader::new(buf.as_slice());
176     let result = m_decoded.read_from(&mut reader);
177     assert!(result.is_err(), "should error");
178 
179     Ok(())
180 }
181 
182 #[test]
test_message_bad_length() -> Result<()>183 fn test_message_bad_length() -> Result<()> {
184     let m_type = MessageType {
185         method: METHOD_BINDING,
186         class: CLASS_REQUEST,
187     };
188     let mut m = Message {
189         typ: m_type,
190         length: 4,
191         transaction_id: TransactionId([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
192         ..Default::default()
193     };
194     m.add(AttrType(0x1), &[1, 2]);
195     m.write_header();
196     m.raw[20 + 3] = 10; // set attr length = 10
197 
198     let mut m_decoded = Message::new();
199     let result = m_decoded.write(&m.raw);
200     assert!(result.is_err(), "should error");
201 
202     Ok(())
203 }
204 
205 #[test]
test_message_attr_length_less_than_header() -> Result<()>206 fn test_message_attr_length_less_than_header() -> Result<()> {
207     let m_type = MessageType {
208         method: METHOD_BINDING,
209         class: CLASS_REQUEST,
210     };
211     let message_attribute = RawAttribute {
212         length: 2,
213         value: vec![1, 2],
214         typ: AttrType(0x1),
215     };
216     let message_attributes = Attributes(vec![message_attribute]);
217     let mut m = Message {
218         typ: m_type,
219         transaction_id: TransactionId::new(),
220         attributes: message_attributes,
221         ..Default::default()
222     };
223     m.encode();
224 
225     let mut m_decoded = Message::new();
226     m.raw[3] = 2; // rewrite to bad length
227 
228     let mut reader = BufReader::new(&m.raw[..20 + 2]);
229     let result = m_decoded.read_from(&mut reader);
230     assert!(result.is_err(), "should be error");
231 
232     Ok(())
233 }
234 
235 #[test]
test_message_attr_size_less_than_length() -> Result<()>236 fn test_message_attr_size_less_than_length() -> Result<()> {
237     let m_type = MessageType {
238         method: METHOD_BINDING,
239         class: CLASS_REQUEST,
240     };
241     let message_attribute = RawAttribute {
242         length: 4,
243         value: vec![1, 2, 3, 4],
244         typ: AttrType(0x1),
245     };
246     let message_attributes = Attributes(vec![message_attribute]);
247     let mut m = Message {
248         typ: m_type,
249         transaction_id: TransactionId::new(),
250         attributes: message_attributes,
251         ..Default::default()
252     };
253     m.write_attributes();
254     m.write_header();
255     m.raw[3] = 5; // rewrite to bad length
256 
257     let mut m_decoded = Message::new();
258     let mut reader = BufReader::new(&m.raw[..20 + 5]);
259     let result = m_decoded.read_from(&mut reader);
260     assert!(result.is_err(), "should be error");
261 
262     Ok(())
263 }
264 
265 #[test]
test_message_read_from_error() -> Result<()>266 fn test_message_read_from_error() -> Result<()> {
267     let mut m_decoded = Message::new();
268     let buf = vec![];
269     let mut reader = BufReader::new(buf.as_slice());
270     let result = m_decoded.read_from(&mut reader);
271     assert!(result.is_err(), "should be error");
272 
273     Ok(())
274 }
275 
276 #[test]
test_message_class_string() -> Result<()>277 fn test_message_class_string() -> Result<()> {
278     let v = vec![
279         CLASS_REQUEST,
280         CLASS_ERROR_RESPONSE,
281         CLASS_SUCCESS_RESPONSE,
282         CLASS_INDICATION,
283     ];
284 
285     for k in v {
286         if k.to_string() == *"unknown message class" {
287             panic!("bad stringer {k}");
288         }
289     }
290 
291     // should panic
292     let p = MessageClass(0x05).to_string();
293     assert_eq!(p, "unknown message class", "should be error {p}");
294 
295     Ok(())
296 }
297 
298 #[test]
test_attr_type_string() -> Result<()>299 fn test_attr_type_string() -> Result<()> {
300     let v = vec![
301         ATTR_MAPPED_ADDRESS,
302         ATTR_USERNAME,
303         ATTR_ERROR_CODE,
304         ATTR_MESSAGE_INTEGRITY,
305         ATTR_UNKNOWN_ATTRIBUTES,
306         ATTR_REALM,
307         ATTR_NONCE,
308         ATTR_XORMAPPED_ADDRESS,
309         ATTR_SOFTWARE,
310         ATTR_ALTERNATE_SERVER,
311         ATTR_FINGERPRINT,
312     ];
313     for k in v {
314         assert!(!k.to_string().starts_with("0x"), "bad stringer");
315     }
316 
317     let v_non_standard = AttrType(0x512);
318     assert!(
319         v_non_standard.to_string().starts_with("0x512"),
320         "bad prefix"
321     );
322 
323     Ok(())
324 }
325 
326 #[test]
test_method_string() -> Result<()>327 fn test_method_string() -> Result<()> {
328     assert_eq!(
329         METHOD_BINDING.to_string(),
330         "Binding".to_owned(),
331         "binding is not binding!"
332     );
333     assert_eq!(
334         Method(0x616).to_string(),
335         "0x616".to_owned(),
336         "Bad stringer {}",
337         Method(0x616)
338     );
339 
340     Ok(())
341 }
342 
343 #[test]
test_attribute_equal() -> Result<()>344 fn test_attribute_equal() -> Result<()> {
345     let a = RawAttribute {
346         length: 2,
347         value: vec![0x1, 0x2],
348         ..Default::default()
349     };
350     let b = RawAttribute {
351         length: 2,
352         value: vec![0x1, 0x2],
353         ..Default::default()
354     };
355     assert_eq!(a, b, "should equal");
356 
357     assert_ne!(
358         a,
359         RawAttribute {
360             typ: AttrType(0x2),
361             ..Default::default()
362         },
363         "should not equal"
364     );
365     assert_ne!(
366         a,
367         RawAttribute {
368             length: 0x2,
369             ..Default::default()
370         },
371         "should not equal"
372     );
373     assert_ne!(
374         a,
375         RawAttribute {
376             length: 0x3,
377             ..Default::default()
378         },
379         "should not equal"
380     );
381     assert_ne!(
382         a,
383         RawAttribute {
384             length: 0x2,
385             value: vec![0x1, 0x3],
386             ..Default::default()
387         },
388         "should not equal"
389     );
390 
391     Ok(())
392 }
393 
394 #[test]
test_message_equal() -> Result<()>395 fn test_message_equal() -> Result<()> {
396     let attr = RawAttribute {
397         length: 2,
398         value: vec![0x1, 0x2],
399         typ: AttrType(0x1),
400     };
401     let attrs = Attributes(vec![attr]);
402     let a = Message {
403         attributes: attrs.clone(),
404         length: 4 + 2,
405         ..Default::default()
406     };
407     let b = Message {
408         attributes: attrs.clone(),
409         length: 4 + 2,
410         ..Default::default()
411     };
412     assert_eq!(a, b, "should equal");
413     assert_ne!(
414         a,
415         Message {
416             typ: MessageType {
417                 class: MessageClass(128),
418                 ..Default::default()
419             },
420             ..Default::default()
421         },
422         "should not equal"
423     );
424 
425     let t_id = TransactionId([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
426 
427     assert_ne!(
428         a,
429         Message {
430             transaction_id: t_id,
431             ..Default::default()
432         },
433         "should not equal"
434     );
435     assert_ne!(
436         a,
437         Message {
438             length: 3,
439             ..Default::default()
440         },
441         "should not equal"
442     );
443 
444     let t_attrs = Attributes(vec![RawAttribute {
445         length: 1,
446         value: vec![0x1],
447         typ: AttrType(0x1),
448     }]);
449     assert_ne!(
450         a,
451         Message {
452             attributes: t_attrs,
453             length: 4 + 2,
454             ..Default::default()
455         },
456         "should not equal"
457     );
458 
459     let t_attrs = Attributes(vec![RawAttribute {
460         length: 2,
461         value: vec![0x1, 0x1],
462         typ: AttrType(0x2),
463     }]);
464     assert_ne!(
465         a,
466         Message {
467             attributes: t_attrs,
468             length: 4 + 2,
469             ..Default::default()
470         },
471         "should not equal"
472     );
473 
474     //"Nil attributes"
475     {
476         let a = Message {
477             length: 4 + 2,
478             ..Default::default()
479         };
480         let mut b = Message {
481             attributes: attrs,
482             length: 4 + 2,
483             ..Default::default()
484         };
485 
486         assert_ne!(a, b, "should not equal");
487         assert_ne!(b, a, "should not equal");
488         b.attributes = Attributes::default();
489         assert_eq!(a, b, "should equal");
490     }
491 
492     //"Attributes length"
493     {
494         let attr = RawAttribute {
495             length: 2,
496             value: vec![0x1, 0x2],
497             typ: AttrType(0x1),
498         };
499         let attr1 = RawAttribute {
500             length: 2,
501             value: vec![0x1, 0x2],
502             typ: AttrType(0x1),
503         };
504         let a = Message {
505             attributes: Attributes(vec![attr.clone()]),
506             length: 4 + 2,
507             ..Default::default()
508         };
509         let b = Message {
510             attributes: Attributes(vec![attr, attr1]),
511             length: 4 + 2,
512             ..Default::default()
513         };
514         assert_ne!(a, b, "should not equal");
515     }
516 
517     //"Attributes values"
518     {
519         let attr = RawAttribute {
520             length: 2,
521             value: vec![0x1, 0x2],
522             typ: AttrType(0x1),
523         };
524         let attr1 = RawAttribute {
525             length: 2,
526             value: vec![0x1, 0x1],
527             typ: AttrType(0x1),
528         };
529         let a = Message {
530             attributes: Attributes(vec![attr.clone(), attr.clone()]),
531             length: 4 + 2,
532             ..Default::default()
533         };
534         let b = Message {
535             attributes: Attributes(vec![attr, attr1]),
536             length: 4 + 2,
537             ..Default::default()
538         };
539         assert_ne!(a, b, "should not equal");
540     }
541 
542     Ok(())
543 }
544 
545 #[test]
test_message_grow() -> Result<()>546 fn test_message_grow() -> Result<()> {
547     let mut m = Message::new();
548     m.grow(512, false);
549     assert_eq!(m.raw.len(), 512, "Bad length {}", m.raw.len());
550 
551     Ok(())
552 }
553 
554 #[test]
test_message_grow_smaller() -> Result<()>555 fn test_message_grow_smaller() -> Result<()> {
556     let mut m = Message::new();
557     m.grow(2, false);
558     assert!(m.raw.capacity() >= 20, "Bad capacity {}", m.raw.capacity());
559 
560     assert!(m.raw.len() >= 20, "Bad length {}", m.raw.len());
561 
562     Ok(())
563 }
564 
565 #[test]
test_message_string() -> Result<()>566 fn test_message_string() -> Result<()> {
567     let m = Message::new();
568     assert_ne!(m.to_string(), "", "bad string");
569 
570     Ok(())
571 }
572 
573 #[test]
test_is_message() -> Result<()>574 fn test_is_message() -> Result<()> {
575     let mut m = Message::new();
576     let a = TextAttribute {
577         attr: ATTR_SOFTWARE,
578         text: "software".to_owned(),
579     };
580     a.add_to(&mut m)?;
581     m.write_header();
582 
583     let tests = vec![
584         (vec![], false),                           // 0
585         (vec![1, 2, 3], false),                    // 1
586         (vec![1, 2, 4], false),                    // 2
587         (vec![1, 2, 4, 5, 6, 7, 8, 9, 20], false), // 3
588         (m.raw.to_vec(), true),                    // 5
589         (
590             vec![
591                 0, 0, 0, 0, 33, 18, 164, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
592             ],
593             true,
594         ), // 6
595     ];
596 
597     for (input, output) in tests {
598         let got = is_message(&input);
599         assert_eq!(got, output, "IsMessage({input:?}) {got} != {output}");
600     }
601 
602     Ok(())
603 }
604 
605 #[test]
test_message_contains() -> Result<()>606 fn test_message_contains() -> Result<()> {
607     let mut m = Message::new();
608     m.add(ATTR_SOFTWARE, "value".as_bytes());
609 
610     assert!(m.contains(ATTR_SOFTWARE), "message should contain software");
611     assert!(!m.contains(ATTR_NONCE), "message should not contain nonce");
612 
613     Ok(())
614 }
615 
616 #[test]
test_message_full_size() -> Result<()>617 fn test_message_full_size() -> Result<()> {
618     let mut m = Message::new();
619     m.build(&[
620         Box::new(BINDING_REQUEST),
621         Box::new(TransactionId([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 0])),
622         Box::new(TextAttribute::new(ATTR_SOFTWARE, "pion/stun".to_owned())),
623         Box::new(MessageIntegrity::new_long_term_integrity(
624             "username".to_owned(),
625             "realm".to_owned(),
626             "password".to_owned(),
627         )),
628         Box::new(FINGERPRINT),
629     ])?;
630     let l = m.raw.len();
631     m.raw = m.raw[..l - 10].to_vec();
632 
633     let mut decoder = Message::new();
634     let l = m.raw.len();
635     decoder.raw = m.raw[..l - 10].to_vec();
636     let result = decoder.decode();
637     assert!(result.is_err(), "decode on truncated buffer should error");
638 
639     Ok(())
640 }
641 
642 #[test]
test_message_clone_to() -> Result<()>643 fn test_message_clone_to() -> Result<()> {
644     let mut m = Message::new();
645     m.build(&[
646         Box::new(BINDING_REQUEST),
647         Box::new(TransactionId([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 0])),
648         Box::new(TextAttribute::new(ATTR_SOFTWARE, "pion/stun".to_owned())),
649         Box::new(MessageIntegrity::new_long_term_integrity(
650             "username".to_owned(),
651             "realm".to_owned(),
652             "password".to_owned(),
653         )),
654         Box::new(FINGERPRINT),
655     ])?;
656     m.encode();
657 
658     let mut b = Message::new();
659     m.clone_to(&mut b)?;
660     assert_eq!(b, m, "not equal");
661 
662     //TODO: Corrupting m and checking that b is not corrupted.
663     /*let (mut s, ok) = b.attributes.get(ATTR_SOFTWARE);
664     assert!(ok, "no software attribute");
665     s.value[0] = b'k';
666     s.add_to(&mut b)?;
667     assert_ne!(b, m, "should not be equal");*/
668 
669     Ok(())
670 }
671 
672 #[test]
test_message_add_to() -> Result<()>673 fn test_message_add_to() -> Result<()> {
674     let mut m = Message::new();
675     m.build(&[
676         Box::new(BINDING_REQUEST),
677         Box::new(TransactionId([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 0])),
678         Box::new(FINGERPRINT),
679     ])?;
680     m.encode();
681 
682     let mut b = Message::new();
683     m.clone_to(&mut b)?;
684 
685     m.transaction_id = TransactionId([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 0]);
686     assert_ne!(b, m, "should not be equal");
687 
688     m.add_to(&mut b)?;
689     assert_eq!(b, m, "should be equal");
690 
691     Ok(())
692 }
693 
694 #[test]
test_decode() -> Result<()>695 fn test_decode() -> Result<()> {
696     let mut m = Message::new();
697     m.typ = MessageType {
698         method: METHOD_BINDING,
699         class: CLASS_REQUEST,
700     };
701     m.transaction_id = TransactionId::new();
702     m.add(ATTR_ERROR_CODE, &[0xff, 0xfe, 0xfa]);
703     m.write_header();
704 
705     let mut m_decoded = Message::new();
706     m_decoded.raw.clear();
707     m_decoded.raw.extend_from_slice(&m.raw);
708     m_decoded.decode()?;
709     assert_eq!(
710         m_decoded, m,
711         "decoded result is not equal to encoded message"
712     );
713 
714     Ok(())
715 }
716 
717 #[test]
test_message_marshal_binary() -> Result<()>718 fn test_message_marshal_binary() -> Result<()> {
719     let mut m = Message::new();
720     m.build(&[
721         Box::new(TextAttribute::new(ATTR_SOFTWARE, "software".to_owned())),
722         Box::new(XorMappedAddress {
723             ip: "213.1.223.5".parse().unwrap(),
724             port: 0,
725         }),
726     ])?;
727 
728     let mut data = m.marshal_binary()?;
729     // Reset m.Raw to check retention.
730     for i in 0..m.raw.len() {
731         m.raw[i] = 0;
732     }
733     m.unmarshal_binary(&data)?;
734 
735     // Reset data to check retention.
736     #[allow(clippy::needless_range_loop)]
737     for i in 0..data.len() {
738         data[i] = 0;
739     }
740 
741     m.decode()?;
742 
743     Ok(())
744 }
745