1macro_rules! bytewise_xor {
105 ($size:literal, $a:expr, $b:expr, $default:literal) => {{
106 let mut arr = [$default; $size];
107 for (i, item) in arr.iter_mut().enumerate() {
108 *item = $a[i] ^ $b[i];
109 }
110 arr
111 }};
112}
113
114mod address;
115pub use address::{AddressFamily, MappedSocketAddr, XorSocketAddr};
116mod alternate;
117pub use alternate::{AlternateDomain, AlternateServer};
118mod error;
119pub use error::{ErrorCode, UnknownAttributes};
120mod ice;
121pub use ice::{IceControlled, IceControlling, Priority, UseCandidate};
122mod integrity;
123pub use integrity::{MessageIntegrity, MessageIntegritySha256};
124mod fingerprint;
125pub use fingerprint::Fingerprint;
126mod nonce;
127pub use nonce::Nonce;
128mod password_algorithm;
129pub use password_algorithm::{PasswordAlgorithm, PasswordAlgorithmValue, PasswordAlgorithms};
130mod realm;
131pub use realm::Realm;
132mod user;
133pub use user::{Userhash, Username};
134mod software;
135pub use software::Software;
136mod xor_addr;
137pub use xor_addr::XorMappedAddress;
138
139use crate::data::Data;
140use crate::message::{StunParseError, StunWriteError};
141
142use byteorder::{BigEndian, ByteOrder};
143
144#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
146pub struct AttributeType(u16);
147
148impl std::fmt::Display for AttributeType {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150 write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
151 }
152}
153
154impl AttributeType {
155 pub const fn new(val: u16) -> Self {
165 Self(val)
166 }
167
168 pub fn value(&self) -> u16 {
178 self.0
179 }
180
181 pub fn name(self) -> &'static str {
189 match self {
190 AttributeType(0x0001) => "MAPPED-ADDRESS",
191 Username::TYPE => "USERNAME",
192 MessageIntegrity::TYPE => "MESSAGE-INTEGRITY",
193 ErrorCode::TYPE => "ERROR-CODE",
194 UnknownAttributes::TYPE => "UNKNOWN-ATTRIBUTES",
195 Realm::TYPE => "REALM",
196 Nonce::TYPE => "NONCE",
197 MessageIntegritySha256::TYPE => "MESSAGE-INTEGRITY-SHA256",
198 PasswordAlgorithm::TYPE => "PASSWORD-ALGORITHM",
199 Userhash::TYPE => "USERHASH",
200 XorMappedAddress::TYPE => "XOR-MAPPED-ADDRESS",
201 PasswordAlgorithms::TYPE => "PASSWORD_ALGORITHMS",
202 AlternateDomain::TYPE => "ALTERNATE-DOMAIN",
203 Software::TYPE => "SOFTWARE",
204 AlternateServer::TYPE => "ALTERNATE-SERVER",
205 Fingerprint::TYPE => "FINGERPRINT",
206 Priority::TYPE => "PRIORITY",
207 UseCandidate::TYPE => "USE-CANDIDATE",
208 IceControlled::TYPE => "ICE-CONTROLLED",
209 IceControlling::TYPE => "ICE-CONTROLLING",
210 _ => "unknown",
211 }
212 }
213
214 pub fn comprehension_required(self) -> bool {
225 self.0 < 0x8000
226 }
227}
228impl From<u16> for AttributeType {
229 fn from(f: u16) -> Self {
230 Self::new(f)
231 }
232}
233impl From<AttributeType> for u16 {
234 fn from(f: AttributeType) -> Self {
235 f.0
236 }
237}
238
239#[derive(Debug, Copy, Clone, PartialEq, Eq)]
241pub struct AttributeHeader {
242 atype: AttributeType,
243 length: u16,
244}
245
246impl AttributeHeader {
247 fn parse(data: &[u8]) -> Result<Self, StunParseError> {
248 if data.len() < 4 {
249 return Err(StunParseError::Truncated {
250 expected: 4,
251 actual: data.len(),
252 });
253 }
254 let ret = Self {
255 atype: BigEndian::read_u16(&data[0..2]).into(),
256 length: BigEndian::read_u16(&data[2..4]),
257 };
258 Ok(ret)
259 }
260
261 fn to_bytes(self) -> Vec<u8> {
262 let mut ret = vec![0; 4];
263 self.write_into(&mut ret);
264 ret
265 }
266
267 fn write_into(&self, ret: &mut [u8]) {
268 BigEndian::write_u16(&mut ret[0..2], self.atype.into());
269 BigEndian::write_u16(&mut ret[2..4], self.length);
270 }
271
272 pub fn get_type(&self) -> AttributeType {
274 self.atype
275 }
276
277 pub fn length(&self) -> u16 {
279 self.length
280 }
281}
282impl From<AttributeHeader> for Vec<u8> {
283 fn from(f: AttributeHeader) -> Self {
284 f.to_bytes()
285 }
286}
287impl TryFrom<&[u8]> for AttributeHeader {
288 type Error = StunParseError;
289
290 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
291 AttributeHeader::parse(value)
292 }
293}
294
295pub trait AttributeStaticType {
297 const TYPE: AttributeType;
299}
300
301pub trait Attribute: std::fmt::Debug + std::marker::Sync {
303 fn get_type(&self) -> AttributeType;
305
306 fn length(&self) -> u16;
309}
310
311pub trait AttributeFromRaw<'a>: Attribute {
313 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
315 where
316 Self: Sized;
317
318 fn from_raw(raw: RawAttribute<'a>) -> Result<Self, StunParseError>
320 where
321 Self: Sized,
322 {
323 Self::from_raw_ref(&raw)
324 }
325}
326
327fn padded_attr_len(len: usize) -> usize {
328 if len % 4 == 0 {
329 len
330 } else {
331 len + 4 - len % 4
332 }
333}
334
335pub trait AttributeExt {
337 fn padded_len(&self) -> usize;
340}
341
342impl<A: Attribute + ?Sized> AttributeExt for A {
343 fn padded_len(&self) -> usize {
344 4 + padded_attr_len(self.length() as usize)
345 }
346}
347
348pub trait AttributeWrite: Attribute {
350 fn write_into_unchecked(&self, dest: &mut [u8]);
354 fn to_raw(&self) -> RawAttribute;
356}
357
358pub trait AttributeWriteExt: AttributeWrite {
361 fn write_header_unchecked(&self, dest: &mut [u8]) -> usize;
366 fn write_header(&self, dest: &mut [u8]) -> Result<usize, StunWriteError>;
369 fn write_into(&self, dest: &mut [u8]) -> Result<usize, StunWriteError>;
372}
373
374impl<A: AttributeWrite + ?Sized> AttributeWriteExt for A {
375 fn write_header(&self, dest: &mut [u8]) -> Result<usize, StunWriteError> {
376 if dest.len() < 4 {
377 return Err(StunWriteError::TooSmall {
378 expected: 4,
379 actual: dest.len(),
380 });
381 }
382 self.write_header_unchecked(dest);
383 Ok(4)
384 }
385 fn write_header_unchecked(&self, dest: &mut [u8]) -> usize {
386 AttributeHeader {
387 atype: self.get_type(),
388 length: self.length(),
389 }
390 .write_into(dest);
391 4
392 }
393
394 fn write_into(&self, dest: &mut [u8]) -> Result<usize, StunWriteError> {
395 let len = self.padded_len();
396 if len > dest.len() {
397 return Err(StunWriteError::TooSmall {
398 expected: len,
399 actual: dest.len(),
400 });
401 }
402 self.write_into_unchecked(dest);
403 Ok(len)
404 }
405}
406
407#[derive(Debug, Clone, PartialEq, Eq)]
409pub struct RawAttribute<'a> {
410 pub header: AttributeHeader,
412 pub value: Data<'a>,
414}
415
416macro_rules! display_attr {
417 ($this:ident, $CamelType:ty, $default:ident) => {{
418 if let Ok(attr) = <$CamelType>::from_raw_ref($this) {
419 format!("{}", attr)
420 } else {
421 $default
422 }
423 }};
424}
425
426impl std::fmt::Display for RawAttribute<'_> {
427 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
428 let malformed_str = format!(
430 "{}(Malformed): len: {}, data: {:?})",
431 self.get_type(),
432 self.header.length(),
433 self.value
434 );
435 let display_str = match self.get_type() {
436 Username::TYPE => display_attr!(self, Username, malformed_str),
437 MessageIntegrity::TYPE => display_attr!(self, MessageIntegrity, malformed_str),
438 ErrorCode::TYPE => display_attr!(self, ErrorCode, malformed_str),
439 UnknownAttributes::TYPE => display_attr!(self, UnknownAttributes, malformed_str),
440 Realm::TYPE => display_attr!(self, Realm, malformed_str),
441 Nonce::TYPE => display_attr!(self, Nonce, malformed_str),
442 MessageIntegritySha256::TYPE => {
443 display_attr!(self, MessageIntegritySha256, malformed_str)
444 }
445 PasswordAlgorithm::TYPE => display_attr!(self, PasswordAlgorithm, malformed_str),
446 XorMappedAddress::TYPE => display_attr!(self, XorMappedAddress, malformed_str),
448 PasswordAlgorithms::TYPE => display_attr!(self, PasswordAlgorithms, malformed_str),
449 AlternateDomain::TYPE => display_attr!(self, AlternateDomain, malformed_str),
450 Software::TYPE => display_attr!(self, Software, malformed_str),
451 AlternateServer::TYPE => display_attr!(self, AlternateServer, malformed_str),
452 Fingerprint::TYPE => display_attr!(self, Fingerprint, malformed_str),
453 Priority::TYPE => display_attr!(self, Priority, malformed_str),
454 UseCandidate::TYPE => display_attr!(self, UseCandidate, malformed_str),
455 IceControlled::TYPE => display_attr!(self, IceControlled, malformed_str),
456 IceControlling::TYPE => display_attr!(self, IceControlling, malformed_str),
457 _ => format!(
458 "RawAttribute (type: {:?}, len: {}, data: {:?})",
459 self.header.get_type(),
460 self.header.length(),
461 &self.value
462 ),
463 };
464 write!(f, "{}", display_str)
465 }
466}
467
468impl<'a> RawAttribute<'a> {
469 pub fn new(atype: AttributeType, data: &'a [u8]) -> Self {
471 Self {
472 header: AttributeHeader {
473 atype,
474 length: data.len() as u16,
475 },
476 value: data.into(),
477 }
478 }
479
480 pub fn new_owned(atype: AttributeType, data: Box<[u8]>) -> Self {
482 Self {
483 header: AttributeHeader {
484 atype,
485 length: data.len() as u16,
486 },
487 value: data.into(),
488 }
489 }
490
491 pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
503 let header = AttributeHeader::parse(data)?;
504 if header.length() > (data.len() - 4) as u16 {
506 return Err(StunParseError::Truncated {
507 expected: header.length() as usize,
508 actual: data.len() - 4,
509 });
510 }
511 Ok(Self {
512 header,
513 value: Data::Borrowed(data[4..header.length() as usize + 4].into()),
514 })
515 }
516
517 pub fn to_bytes(&self) -> Vec<u8> {
527 let mut vec = Vec::with_capacity(self.padded_len());
528 let mut header_bytes = [0; 4];
529 self.header.write_into(&mut header_bytes);
530 vec.extend(&header_bytes);
531 vec.extend(&*self.value);
532 let len = vec.len();
533 if len % 4 != 0 {
534 vec.resize(len + 4 - (len % 4), 0);
536 }
537 vec
538 }
539
540 pub fn check_type_and_len(
542 &self,
543 atype: AttributeType,
544 allowed_range: impl std::ops::RangeBounds<usize>,
545 ) -> Result<(), StunParseError> {
546 if self.header.get_type() != atype {
547 return Err(StunParseError::WrongAttributeImplementation);
548 }
549 check_len(self.value.len(), allowed_range)
550 }
551
552 pub fn into_owned<'b>(self) -> RawAttribute<'b> {
554 RawAttribute {
555 header: self.header,
556 value: self.value.into_owned(),
557 }
558 }
559}
560
561impl Attribute for RawAttribute<'_> {
562 fn get_type(&self) -> AttributeType {
564 self.header.get_type()
565 }
566
567 fn length(&self) -> u16 {
569 self.value.len() as u16
570 }
571}
572
573impl<'a> AttributeWrite for RawAttribute<'a> {
574 fn write_into_unchecked(&self, dest: &mut [u8]) {
576 let len = self.padded_len();
577 self.header.write_into(dest);
578 let mut offset = 4;
579 dest[offset..offset + self.value.len()].copy_from_slice(&self.value);
580 offset += self.value.len();
581 if len - offset > 0 {
582 dest[offset..len].fill(0);
583 }
584 }
585
586 fn to_raw(&self) -> RawAttribute<'a> {
587 self.clone()
588 }
589}
590
591impl<'a, A: AttributeWrite> From<&'a A> for RawAttribute<'a> {
592 fn from(value: &'a A) -> Self {
593 value.to_raw()
594 }
595}
596
597fn check_len(
598 len: usize,
599 allowed_range: impl std::ops::RangeBounds<usize>,
600) -> Result<(), StunParseError> {
601 match allowed_range.start_bound() {
602 std::ops::Bound::Unbounded => (),
603 std::ops::Bound::Included(start) => {
604 if len < *start {
605 return Err(StunParseError::Truncated {
606 expected: *start,
607 actual: len,
608 });
609 }
610 }
611 std::ops::Bound::Excluded(start) => {
612 if len <= *start {
613 return Err(StunParseError::Truncated {
614 expected: start + 1,
615 actual: len,
616 });
617 }
618 }
619 }
620 match allowed_range.end_bound() {
621 std::ops::Bound::Unbounded => (),
622 std::ops::Bound::Included(end) => {
623 if len > *end {
624 return Err(StunParseError::TooLarge {
625 expected: *end,
626 actual: len,
627 });
628 }
629 }
630 std::ops::Bound::Excluded(end) => {
631 if len >= *end {
632 return Err(StunParseError::TooLarge {
633 expected: *end - 1,
634 actual: len,
635 });
636 }
637 }
638 }
639 Ok(())
640}
641
642impl From<RawAttribute<'_>> for Vec<u8> {
643 fn from(f: RawAttribute) -> Self {
644 f.to_bytes()
645 }
646}
647
648#[cfg(test)]
649mod tests {
650 use super::*;
651
652 #[test]
653 fn attribute_type() {
654 let _log = crate::tests::test_init_log();
655 let atype = ErrorCode::TYPE;
656 let anum: u16 = atype.into();
657 assert_eq!(atype, anum.into());
658 }
659
660 #[test]
661 fn short_attribute_header() {
662 let _log = crate::tests::test_init_log();
663 let data = [0; 1];
664 let res: Result<AttributeHeader, _> = data.as_ref().try_into();
666 assert!(res.is_err());
667 }
668
669 #[test]
670 fn raw_attribute_construct() {
671 let _log = crate::tests::test_init_log();
672 let a = RawAttribute::new(1.into(), &[80, 160]);
673 assert_eq!(a.get_type(), 1.into());
674 let bytes: Vec<_> = a.into();
675 assert_eq!(bytes, &[0, 1, 0, 2, 80, 160, 0, 0]);
676 let b = RawAttribute::from_bytes(bytes.as_ref()).unwrap();
677 assert_eq!(b.get_type(), 1.into());
678 }
679
680 #[test]
681 fn raw_attribute_encoding() {
682 let _log = crate::tests::test_init_log();
683 let orig = RawAttribute::new(1.into(), &[80, 160]);
684 assert_eq!(orig.get_type(), 1.into());
685 let mut data: Vec<_> = orig.into();
686 let len = data.len();
687 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 + 1);
689 assert!(matches!(
690 RawAttribute::from_bytes(data.as_ref()),
691 Err(StunParseError::Truncated {
692 expected: 5,
693 actual: 4
694 })
695 ));
696 }
697
698 #[test]
699 fn test_check_len() {
700 let _log = crate::tests::test_init_log();
701 assert!(check_len(4, ..).is_ok());
702 assert!(check_len(4, 0..).is_ok());
703 assert!(check_len(4, 0..8).is_ok());
704 assert!(check_len(4, 0..=8).is_ok());
705 assert!(check_len(4, ..=8).is_ok());
706 assert!(matches!(
707 check_len(4, ..4),
708 Err(StunParseError::TooLarge {
709 expected: 3,
710 actual: 4
711 })
712 ));
713 assert!(matches!(
714 check_len(4, 5..),
715 Err(StunParseError::Truncated {
716 expected: 5,
717 actual: 4
718 })
719 ));
720 assert!(matches!(
721 check_len(4, ..=3),
722 Err(StunParseError::TooLarge {
723 expected: 3,
724 actual: 4
725 })
726 ));
727 assert!(matches!(
728 check_len(
729 4,
730 (std::ops::Bound::Excluded(4), std::ops::Bound::Unbounded)
731 ),
732 Err(StunParseError::Truncated {
733 expected: 5,
734 actual: 4
735 })
736 ));
737 }
738}