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