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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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] 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