1macro_rules! bytewise_xor {
132 ($size:literal, $a:expr, $b:expr, $default:literal) => {{
133 let mut arr = [$default; $size];
134 for (i, item) in arr.iter_mut().enumerate() {
135 *item = $a[i] ^ $b[i];
136 }
137 arr
138 }};
139}
140
141mod address;
142pub use address::{MappedSocketAddr, XorSocketAddr};
143mod alternate;
144pub use alternate::{AlternateDomain, AlternateServer};
145mod error;
146pub use error::{ErrorCode, UnknownAttributes};
147mod integrity;
148pub use integrity::{MessageIntegrity, MessageIntegritySha256};
149mod fingerprint;
150pub use fingerprint::Fingerprint;
151mod nonce;
152pub use nonce::Nonce;
153mod password_algorithm;
154pub use password_algorithm::{PasswordAlgorithm, PasswordAlgorithmValue, PasswordAlgorithms};
155mod realm;
156pub use realm::Realm;
157mod user;
158pub use user::{Userhash, Username};
159mod software;
160pub use software::Software;
161mod xor_addr;
162pub use xor_addr::XorMappedAddress;
163
164use crate::data::Data;
165use crate::message::{StunParseError, StunWriteError};
166use alloc::boxed::Box;
167use alloc::vec::Vec;
168
169use byteorder::{BigEndian, ByteOrder};
170
171#[cfg(feature = "std")]
172use alloc::collections::BTreeMap;
173#[cfg(feature = "std")]
174use std::sync::{Mutex, OnceLock};
175
176pub type AttributeDisplay =
184 fn(&RawAttribute<'_>, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
185#[cfg(feature = "std")]
186static ATTRIBUTE_EXTERNAL_DISPLAY_IMPL: OnceLock<Mutex<BTreeMap<AttributeType, AttributeDisplay>>> =
187 OnceLock::new();
188
189#[cfg(feature = "std")]
192pub fn add_display_impl(atype: AttributeType, imp: AttributeDisplay) {
193 let mut display_impls = ATTRIBUTE_EXTERNAL_DISPLAY_IMPL
194 .get_or_init(Default::default)
195 .lock()
196 .unwrap();
197 display_impls.insert(atype, imp);
198}
199
200#[macro_export]
245macro_rules! attribute_display {
246 ($typ:ty) => {{
247 let imp = |attr: &$crate::attribute::RawAttribute<'_>,
248 f: &mut core::fmt::Formatter<'_>|
249 -> core::fmt::Result {
250 if let Ok(attr) = <$typ>::from_raw_ref(attr) {
251 write!(f, "{}", attr)
252 } else {
253 write!(
254 f,
255 "{}(Malformed): len: {}, data: {:?})",
256 attr.get_type(),
257 attr.header.length(),
258 attr.value
259 )
260 }
261 };
262
263 $crate::attribute::add_display_impl(<$typ>::TYPE, imp);
264 }};
265}
266
267#[cfg(feature = "std")]
268static ATTRIBUTE_TYPE_NAME_MAP: OnceLock<Mutex<BTreeMap<AttributeType, &'static str>>> =
269 OnceLock::new();
270
271#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
273pub struct AttributeType(u16);
274
275impl core::fmt::Display for AttributeType {
276 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
277 write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
278 }
279}
280
281impl AttributeType {
282 #[cfg(feature = "std")]
284 pub fn add_name(self, name: &'static str) {
285 let mut anames = ATTRIBUTE_TYPE_NAME_MAP
286 .get_or_init(Default::default)
287 .lock()
288 .unwrap();
289 anames.insert(self, name);
290 }
291
292 pub const fn new(val: u16) -> Self {
302 Self(val)
303 }
304
305 pub fn value(&self) -> u16 {
315 self.0
316 }
317
318 pub fn name(self) -> &'static str {
326 match self {
327 AttributeType(0x0001) => "MAPPED-ADDRESS",
328 Username::TYPE => "USERNAME",
329 MessageIntegrity::TYPE => "MESSAGE-INTEGRITY",
330 ErrorCode::TYPE => "ERROR-CODE",
331 UnknownAttributes::TYPE => "UNKNOWN-ATTRIBUTES",
332 Realm::TYPE => "REALM",
333 Nonce::TYPE => "NONCE",
334 MessageIntegritySha256::TYPE => "MESSAGE-INTEGRITY-SHA256",
335 PasswordAlgorithm::TYPE => "PASSWORD-ALGORITHM",
336 Userhash::TYPE => "USERHASH",
337 XorMappedAddress::TYPE => "XOR-MAPPED-ADDRESS",
338 PasswordAlgorithms::TYPE => "PASSWORD_ALGORITHMS",
339 AlternateDomain::TYPE => "ALTERNATE-DOMAIN",
340 Software::TYPE => "SOFTWARE",
341 AlternateServer::TYPE => "ALTERNATE-SERVER",
342 Fingerprint::TYPE => "FINGERPRINT",
343 _ => {
344 #[cfg(feature = "std")]
345 {
346 let anames = ATTRIBUTE_TYPE_NAME_MAP
347 .get_or_init(Default::default)
348 .lock()
349 .unwrap();
350 if let Some(name) = anames.get(&self) {
351 return name;
352 }
353 }
354 "unknown"
355 }
356 }
357 }
358
359 pub fn comprehension_required(self) -> bool {
370 self.0 < 0x8000
371 }
372}
373impl From<u16> for AttributeType {
374 fn from(f: u16) -> Self {
375 Self::new(f)
376 }
377}
378impl From<AttributeType> for u16 {
379 fn from(f: AttributeType) -> Self {
380 f.0
381 }
382}
383
384#[derive(Debug, Copy, Clone, PartialEq, Eq)]
386pub struct AttributeHeader {
387 atype: AttributeType,
388 length: u16,
389}
390
391impl AttributeHeader {
392 fn parse(data: &[u8]) -> Result<Self, StunParseError> {
393 if data.len() < 4 {
394 return Err(StunParseError::Truncated {
395 expected: 4,
396 actual: data.len(),
397 });
398 }
399 let ret = Self {
400 atype: BigEndian::read_u16(&data[0..2]).into(),
401 length: BigEndian::read_u16(&data[2..4]),
402 };
403 Ok(ret)
404 }
405
406 fn to_bytes(self) -> [u8; 4] {
407 let mut ret = [0; 4];
408 self.write_into(&mut ret);
409 ret
410 }
411
412 fn write_into(&self, ret: &mut [u8]) {
413 BigEndian::write_u16(&mut ret[0..2], self.atype.into());
414 BigEndian::write_u16(&mut ret[2..4], self.length);
415 }
416
417 pub fn get_type(&self) -> AttributeType {
419 self.atype
420 }
421
422 pub fn length(&self) -> u16 {
424 self.length
425 }
426}
427impl From<AttributeHeader> for [u8; 4] {
428 fn from(f: AttributeHeader) -> Self {
429 f.to_bytes()
430 }
431}
432impl TryFrom<&[u8]> for AttributeHeader {
433 type Error = StunParseError;
434
435 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
436 AttributeHeader::parse(value)
437 }
438}
439
440pub trait AttributeStaticType {
442 const TYPE: AttributeType;
444}
445
446pub trait Attribute: core::fmt::Debug + core::marker::Sync + core::marker::Send {
448 fn get_type(&self) -> AttributeType;
450
451 fn length(&self) -> u16;
454}
455
456pub trait AttributeFromRaw<'a>: Attribute {
458 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
460 where
461 Self: Sized;
462
463 fn from_raw(raw: RawAttribute<'a>) -> Result<Self, StunParseError>
465 where
466 Self: Sized,
467 {
468 Self::from_raw_ref(&raw)
469 }
470}
471
472pub fn pad_attribute_len(len: usize) -> usize {
474 if len % 4 == 0 {
475 len
476 } else {
477 len + 4 - len % 4
478 }
479}
480
481pub trait AttributeExt {
483 fn padded_len(&self) -> usize;
486}
487
488impl<A: Attribute + ?Sized> AttributeExt for A {
489 fn padded_len(&self) -> usize {
490 4 + pad_attribute_len(self.length() as usize)
491 }
492}
493
494pub trait AttributeWrite: Attribute {
496 fn write_into_unchecked(&self, dest: &mut [u8]);
500 fn to_raw(&self) -> RawAttribute<'_>;
502}
503
504pub trait AttributeWriteExt: AttributeWrite {
507 fn write_header_unchecked(&self, dest: &mut [u8]) -> usize;
512 fn write_header(&self, dest: &mut [u8]) -> Result<usize, StunWriteError>;
515 fn write_into(&self, dest: &mut [u8]) -> Result<usize, StunWriteError>;
518}
519
520impl<A: AttributeWrite + ?Sized> AttributeWriteExt for A {
521 fn write_header(&self, dest: &mut [u8]) -> Result<usize, StunWriteError> {
522 if dest.len() < 4 {
523 return Err(StunWriteError::TooSmall {
524 expected: 4,
525 actual: dest.len(),
526 });
527 }
528 self.write_header_unchecked(dest);
529 Ok(4)
530 }
531 fn write_header_unchecked(&self, dest: &mut [u8]) -> usize {
532 AttributeHeader {
533 atype: self.get_type(),
534 length: self.length(),
535 }
536 .write_into(dest);
537 4
538 }
539
540 fn write_into(&self, dest: &mut [u8]) -> Result<usize, StunWriteError> {
541 let len = self.padded_len();
542 if len > dest.len() {
543 return Err(StunWriteError::TooSmall {
544 expected: len,
545 actual: dest.len(),
546 });
547 }
548 self.write_into_unchecked(dest);
549 Ok(len)
550 }
551}
552
553#[derive(Debug, Clone, PartialEq, Eq)]
555pub struct RawAttribute<'a> {
556 pub header: AttributeHeader,
558 pub value: Data<'a>,
560}
561
562macro_rules! display_attr {
563 ($this:ident, $f:ident, $CamelType:ty) => {{
564 if let Ok(attr) = <$CamelType>::from_raw_ref($this) {
565 write!($f, "{}", attr)
566 } else {
567 write!(
568 $f,
569 "{}(Malformed): len: {}, data: {:?})",
570 $this.get_type(),
571 $this.header.length(),
572 $this.value
573 )
574 }
575 }};
576}
577
578impl core::fmt::Display for RawAttribute<'_> {
579 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
580 match self.get_type() {
582 Username::TYPE => display_attr!(self, f, Username),
583 MessageIntegrity::TYPE => display_attr!(self, f, MessageIntegrity),
584 ErrorCode::TYPE => display_attr!(self, f, ErrorCode),
585 UnknownAttributes::TYPE => display_attr!(self, f, UnknownAttributes),
586 Realm::TYPE => display_attr!(self, f, Realm),
587 Nonce::TYPE => display_attr!(self, f, Nonce),
588 MessageIntegritySha256::TYPE => {
589 display_attr!(self, f, MessageIntegritySha256)
590 }
591 PasswordAlgorithm::TYPE => display_attr!(self, f, PasswordAlgorithm),
592 Userhash::TYPE => display_attr!(self, f, Userhash),
593 XorMappedAddress::TYPE => display_attr!(self, f, XorMappedAddress),
594 PasswordAlgorithms::TYPE => display_attr!(self, f, PasswordAlgorithms),
595 AlternateDomain::TYPE => display_attr!(self, f, AlternateDomain),
596 Software::TYPE => display_attr!(self, f, Software),
597 AlternateServer::TYPE => display_attr!(self, f, AlternateServer),
598 Fingerprint::TYPE => display_attr!(self, f, Fingerprint),
599 _ => {
600 #[cfg(feature = "std")]
601 {
602 let mut display_impls = ATTRIBUTE_EXTERNAL_DISPLAY_IMPL
603 .get_or_init(|| Default::default())
604 .lock()
605 .unwrap();
606 if let Some(imp) = display_impls.get_mut(&self.get_type()) {
607 return imp(self, f);
608 }
609 }
610 write!(
611 f,
612 "RawAttribute (type: {:?}, len: {}, data: {:?})",
613 self.header.get_type(),
614 self.header.length(),
615 &self.value
616 )
617 }
618 }
619 }
620}
621
622impl<'a> RawAttribute<'a> {
623 pub fn new(atype: AttributeType, data: &'a [u8]) -> Self {
625 Self {
626 header: AttributeHeader {
627 atype,
628 length: data.len() as u16,
629 },
630 value: data.into(),
631 }
632 }
633
634 pub fn new_owned(atype: AttributeType, data: Box<[u8]>) -> Self {
636 Self {
637 header: AttributeHeader {
638 atype,
639 length: data.len() as u16,
640 },
641 value: data.into(),
642 }
643 }
644
645 pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
657 let header = AttributeHeader::parse(data)?;
658 if header.length() > (data.len() - 4) as u16 {
660 return Err(StunParseError::Truncated {
661 expected: header.length() as usize,
662 actual: data.len() - 4,
663 });
664 }
665 Ok(Self {
666 header,
667 value: Data::Borrowed(data[4..header.length() as usize + 4].into()),
668 })
669 }
670
671 pub fn to_bytes(&self) -> Vec<u8> {
681 let mut vec = Vec::with_capacity(self.padded_len());
682 let mut header_bytes = [0; 4];
683 self.header.write_into(&mut header_bytes);
684 vec.extend(&header_bytes);
685 vec.extend(&*self.value);
686 let len = vec.len();
687 if len % 4 != 0 {
688 vec.resize(len + 4 - (len % 4), 0);
690 }
691 vec
692 }
693
694 pub fn check_type_and_len(
697 &self,
698 atype: AttributeType,
699 allowed_range: impl core::ops::RangeBounds<usize>,
700 ) -> Result<(), StunParseError> {
701 if self.header.get_type() != atype {
702 return Err(StunParseError::WrongAttributeImplementation);
703 }
704 check_len(self.value.len(), allowed_range)
705 }
706
707 pub fn into_owned<'b>(self) -> RawAttribute<'b> {
709 RawAttribute {
710 header: self.header,
711 value: self.value.into_owned(),
712 }
713 }
714}
715
716impl Attribute for RawAttribute<'_> {
717 fn get_type(&self) -> AttributeType {
719 self.header.get_type()
720 }
721
722 fn length(&self) -> u16 {
724 self.value.len() as u16
725 }
726}
727
728impl AttributeWrite for RawAttribute<'_> {
729 fn write_into_unchecked(&self, dest: &mut [u8]) {
731 let len = self.padded_len();
732 self.header.write_into(dest);
733 let mut offset = 4;
734 dest[offset..offset + self.value.len()].copy_from_slice(&self.value);
735 offset += self.value.len();
736 if len - offset > 0 {
737 dest[offset..len].fill(0);
738 }
739 }
740
741 fn to_raw(&self) -> RawAttribute<'_> {
742 self.clone()
743 }
744}
745
746impl<'a, A: AttributeWrite> From<&'a A> for RawAttribute<'a> {
747 fn from(value: &'a A) -> Self {
748 value.to_raw()
749 }
750}
751
752fn check_len(
753 len: usize,
754 allowed_range: impl core::ops::RangeBounds<usize>,
755) -> Result<(), StunParseError> {
756 match allowed_range.start_bound() {
757 core::ops::Bound::Unbounded => (),
758 core::ops::Bound::Included(start) => {
759 if len < *start {
760 return Err(StunParseError::Truncated {
761 expected: *start,
762 actual: len,
763 });
764 }
765 }
766 core::ops::Bound::Excluded(start) => {
767 if len <= *start {
768 return Err(StunParseError::Truncated {
769 expected: start + 1,
770 actual: len,
771 });
772 }
773 }
774 }
775 match allowed_range.end_bound() {
776 core::ops::Bound::Unbounded => (),
777 core::ops::Bound::Included(end) => {
778 if len > *end {
779 return Err(StunParseError::TooLarge {
780 expected: *end,
781 actual: len,
782 });
783 }
784 }
785 core::ops::Bound::Excluded(end) => {
786 if len >= *end {
787 return Err(StunParseError::TooLarge {
788 expected: *end - 1,
789 actual: len,
790 });
791 }
792 }
793 }
794 Ok(())
795}
796
797impl From<RawAttribute<'_>> for Vec<u8> {
798 fn from(f: RawAttribute) -> Self {
799 f.to_bytes()
800 }
801}
802
803#[cfg(test)]
804mod tests {
805 use super::*;
806
807 #[test]
808 fn attribute_type() {
809 let _log = crate::tests::test_init_log();
810 let atype = ErrorCode::TYPE;
811 let anum: u16 = atype.into();
812 assert_eq!(atype, anum.into());
813 }
814
815 #[test]
816 fn short_attribute_header() {
817 let _log = crate::tests::test_init_log();
818 let data = [0; 1];
819 let res: Result<AttributeHeader, _> = data.as_ref().try_into();
821 assert!(res.is_err());
822 }
823
824 #[test]
825 fn raw_attribute_construct() {
826 let _log = crate::tests::test_init_log();
827 let a = RawAttribute::new(1.into(), &[80, 160]);
828 assert_eq!(a.get_type(), 1.into());
829 let bytes: Vec<_> = a.into();
830 assert_eq!(bytes, &[0, 1, 0, 2, 80, 160, 0, 0]);
831 let b = RawAttribute::from_bytes(bytes.as_ref()).unwrap();
832 assert_eq!(b.get_type(), 1.into());
833 }
834
835 #[test]
836 fn raw_attribute_encoding() {
837 let mut out = [0; 8];
838 let mut out2 = [0; 8];
839 let _log = crate::tests::test_init_log();
840 let orig = RawAttribute::new(1.into(), &[80, 160]);
841 assert_eq!(orig.get_type(), 1.into());
842 orig.write_into(&mut out).unwrap();
843 orig.write_into_unchecked(&mut out2);
844 assert_eq!(out, out2);
845 let mut data: Vec<_> = orig.into();
846 let len = data.len();
847 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 + 1);
849 assert!(matches!(
850 RawAttribute::from_bytes(data.as_ref()),
851 Err(StunParseError::Truncated {
852 expected: 5,
853 actual: 4
854 })
855 ));
856 }
857
858 #[test]
859 fn raw_attribute_header() {
860 let mut out = [0; 4];
861 let mut out2 = [0; 4];
862 let _log = crate::tests::test_init_log();
863 let orig = RawAttribute::new(1.into(), &[80, 160]);
864 assert!(matches!(orig.write_header(&mut out), Ok(4)));
865 assert_eq!(orig.write_header_unchecked(&mut out2), 4);
866 assert_eq!(out, out2);
867 assert_eq!(orig.header.to_bytes(), out);
868 assert_eq!(&orig.to_bytes()[..4], out);
869 let bytes: [_; 4] = orig.header.into();
870 assert_eq!(bytes, out);
871 }
872
873 #[test]
874 fn test_check_len() {
875 let _log = crate::tests::test_init_log();
876 assert!(check_len(4, ..).is_ok());
877 assert!(check_len(4, 0..).is_ok());
878 assert!(check_len(4, 0..8).is_ok());
879 assert!(check_len(4, 0..=8).is_ok());
880 assert!(check_len(4, ..=8).is_ok());
881 assert!(matches!(
882 check_len(4, ..4),
883 Err(StunParseError::TooLarge {
884 expected: 3,
885 actual: 4
886 })
887 ));
888 assert!(matches!(
889 check_len(4, 5..),
890 Err(StunParseError::Truncated {
891 expected: 5,
892 actual: 4
893 })
894 ));
895 assert!(matches!(
896 check_len(4, ..=3),
897 Err(StunParseError::TooLarge {
898 expected: 3,
899 actual: 4
900 })
901 ));
902 assert!(matches!(
903 check_len(
904 4,
905 (core::ops::Bound::Excluded(4), core::ops::Bound::Unbounded)
906 ),
907 Err(StunParseError::Truncated {
908 expected: 5,
909 actual: 4
910 })
911 ));
912 }
913
914 #[test]
915 #[cfg(feature = "std")]
916 fn test_external_display_impl() {
917 let _log = crate::tests::test_init_log();
918 let atype = AttributeType::new(0xFFFF);
919 let imp = |attr: &RawAttribute<'_>,
920 f: &mut core::fmt::Formatter<'_>|
921 -> core::fmt::Result { write!(f, "Custom {}", attr.value[0]) };
922 add_display_impl(atype, imp);
923 let data = [4, 0];
924 let attr = RawAttribute::new(atype, &data);
925 let display_str = alloc::format!("{}", attr);
926 assert_eq!(display_str, "Custom 4");
927
928 atype.add_name("SOME-NAME");
929 assert_eq!(atype.name(), "SOME-NAME");
930
931 attribute_display!(Fingerprint);
932 }
933}