stun_types/
message.rs

1// Copyright (C) 2020 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! STUN Messages
10//!
11//! Provides types for generating, parsing, and manipulating STUN messages as specified in one of
12//! [RFC8489], [RFC5389], or [RFC3489].
13//!
14//! Message parsing is zerocopy by default through the [`RawAttribute`] struct. Converting to a
15//! concrete attribute implementation (e.g. [`Software`]) may incur a
16//! copy depending on the attribute implementation.
17//!
18//! The destination for a written Message is completely customizable through the [`MessageWrite`]
19//! trait. It is therefore possible to write directly into network provided buffers for increased
20//! performance and throughput.
21//!
22//! [RFC8489]: https://tools.ietf.org/html/rfc8489
23//! [RFC5389]: https://tools.ietf.org/html/rfc5389
24//! [RFC3489]: https://tools.ietf.org/html/rfc3489
25//!
26//! ## Examples
27//!
28//! ### Parse a STUN [`Message`]
29//!
30//! ```
31//! use stun_types::prelude::*;
32//! use stun_types::attribute::{RawAttribute, PasswordAlgorithm, PasswordAlgorithmValue};
33//! use stun_types::message::{Message, MessageType, MessageClass, BINDING};
34//!
35//! let msg_data = [
36//!     0x00, 0x01, 0x00, 0x08, // method, class and length
37//!     0x21, 0x12, 0xA4, 0x42, // Fixed STUN magic bytes
38//!     0x00, 0x00, 0x00, 0x00, // \
39//!     0x00, 0x00, 0x00, 0x00, // } transaction ID
40//!     0x00, 0x00, 0x73, 0x92, // /
41//!     0x00, 0x1D, 0x00, 0x04, // PasswordAlgorithm attribute header (type and length)
42//!     0x00, 0x02, 0x00, 0x00  // PasswordAlgorithm attribute value
43//! ];
44//! let msg = Message::from_bytes(&msg_data).unwrap();
45//!
46//! // the various parts of a message can be retreived
47//! assert_eq!(msg.get_type(), MessageType::from_class_method(MessageClass::Request, BINDING));
48//! assert_eq!(msg.transaction_id(), 0x7392.into());
49//!
50//! // Attributes can be retrieved as raw values.
51//! let msg_attr = msg.raw_attribute(0x1D.into()).unwrap();
52//! let attr = RawAttribute::new(0x1D.into(), &[0, 2, 0, 0]);
53//! assert_eq!(msg_attr, attr);
54//!
55//! // Or as typed values
56//! let attr = msg.attribute::<PasswordAlgorithm>().unwrap();
57//! assert_eq!(attr.algorithm(), PasswordAlgorithmValue::SHA256);
58//! ```
59//!
60//! ### Generating a [`Message`]
61//!
62//! ```
63//! use stun_types::prelude::*;
64//! use stun_types::attribute::Software;
65//! use stun_types::message::{Message, MessageWriteVec, BINDING};
66//!
67//! // Automatically generates a transaction ID.
68//! let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
69//!
70//! let software_name = "stun-types";
71//! let software = Software::new(software_name).unwrap();
72//! assert_eq!(software.software(), software_name);
73//! msg.add_attribute(&software).unwrap();
74//!
75//! let attribute_data = [
76//!     0x80, 0x22, 0x00, 0x0a, // attribute type (0x8022) and length (0x000a)
77//!     0x73, 0x74, 0x75, 0x6E, // s t u n
78//!     0x2D, 0x74, 0x79, 0x70, // - t y p
79//!     0x65, 0x73, 0x00, 0x00  // e s
80//! ];
81//!
82//! let msg_data = msg.finish();
83//! // ignores the randomly generated transaction id
84//! assert_eq!(msg_data[20..], attribute_data);
85//! ```
86
87#[cfg(feature = "std")]
88use alloc::collections::BTreeMap;
89use alloc::string::String;
90use alloc::sync::Arc;
91use alloc::vec;
92use alloc::vec::Vec;
93use core::convert::TryFrom;
94#[cfg(feature = "std")]
95use std::sync::{Mutex, OnceLock};
96
97use byteorder::{BigEndian, ByteOrder};
98
99use crate::attribute::*;
100
101use tracing::{error, trace, warn};
102
103use hmac::digest::core_api::CoreWrapper;
104use hmac::digest::CtOutput;
105use hmac::HmacCore;
106
107/// The value of the magic cookie (in network byte order) as specified in RFC5389, and RFC8489.
108pub const MAGIC_COOKIE: u32 = 0x2112A442;
109
110/// The method in a STUN [`Message`]
111#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
112pub struct Method(u16);
113
114impl core::fmt::Display for Method {
115    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
116        write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
117    }
118}
119
120#[cfg(feature = "std")]
121static METHOD_NAME_MAP: OnceLock<Mutex<BTreeMap<Method, &'static str>>> = OnceLock::new();
122
123impl Method {
124    /// Add the name for a particular [`Method`] for formatting purposes.
125    #[cfg(feature = "std")]
126    pub fn add_name(self, name: &'static str) {
127        let mut mnames = METHOD_NAME_MAP
128            .get_or_init(Default::default)
129            .lock()
130            .unwrap();
131        mnames.insert(self, name);
132    }
133
134    /// Create a new [`Method`] from an existing value
135    ///
136    /// Note: the value passed in is not encoded as in a stun message
137    ///
138    /// Panics if the value is out of range (>= 0xf000)
139    ///
140    /// # Examples
141    /// ```
142    /// # use stun_types::message::Method;
143    /// assert_eq!(Method::new(0x123).value(), 0x123);
144    /// ```
145    pub const fn new(val: u16) -> Self {
146        if val >= 0xf000 {
147            panic!("Method value is out of range!");
148        }
149        Self(val)
150    }
151
152    /// Return the integer value of this [`Method`]
153    ///
154    /// Note: the value returned is not encoded as in a stun message
155    ///
156    /// # Examples
157    /// ```
158    /// # use stun_types::message::Method;
159    /// assert_eq!(Method::new(0x123).value(), 0x123);
160    /// ```
161    pub fn value(&self) -> u16 {
162        self.0
163    }
164
165    /// Returns a human readable name of this `Method` or "unknown"
166    ///
167    /// # Examples
168    /// ```
169    /// # use stun_types::attribute::*;
170    /// assert_eq!(XorMappedAddress::TYPE.name(), "XOR-MAPPED-ADDRESS");
171    /// ```
172    pub fn name(self) -> &'static str {
173        match self {
174            BINDING => "BINDING",
175            _ => {
176                #[cfg(feature = "std")]
177                {
178                    let mnames = METHOD_NAME_MAP
179                        .get_or_init(Default::default)
180                        .lock()
181                        .unwrap();
182                    if let Some(name) = mnames.get(&self) {
183                        return name;
184                    }
185                }
186                "unknown"
187            }
188        }
189    }
190}
191
192/// The value of the binding message type.  Can be used in either a request or an indication
193/// message.
194pub const BINDING: Method = Method::new(0x0001);
195
196/// Possible errors when parsing a STUN message.
197#[derive(Debug, thiserror::Error)]
198#[non_exhaustive]
199pub enum StunParseError {
200    /// Not a STUN message.
201    #[error("The provided data is not a STUN message")]
202    NotStun,
203    /// The message has been truncated
204    #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
205    Truncated {
206        /// The expeced number of bytes
207        expected: usize,
208        /// The encountered number of bytes
209        actual: usize,
210    },
211    /// The message has been truncated
212    #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
213    TooLarge {
214        /// The expeced number of bytes
215        expected: usize,
216        /// The encountered number of bytes
217        actual: usize,
218    },
219    /// Integrity value does not match computed value
220    #[error("Integrity value does not match")]
221    IntegrityCheckFailed,
222    /// An attribute was not found in the message
223    #[error("Missing attribute {}", .0)]
224    MissingAttribute(AttributeType),
225    /// An attribute was found after the message integrity attribute
226    #[error("An attribute {} was encountered after a message integrity attribute", .0)]
227    AttributeAfterIntegrity(AttributeType),
228    /// An attribute was found after the message integrity attribute
229    #[error("An attribute {} was encountered after a fingerprint attribute", .0)]
230    AttributeAfterFingerprint(AttributeType),
231    /// Fingerprint does not match the data.
232    #[error("Fingerprint does not match")]
233    FingerprintMismatch,
234    /// The provided data does not match the message
235    #[error("The provided data does not match the message")]
236    DataMismatch,
237    /// The attribute contains invalid data
238    #[error("The attribute contains invalid data")]
239    InvalidAttributeData,
240    /// The attribute does not parse this data
241    #[error("Cannot parse with this attribute")]
242    WrongAttributeImplementation,
243}
244
245/// Errors produced when writing a STUN message
246#[derive(Debug, thiserror::Error)]
247#[non_exhaustive]
248pub enum StunWriteError {
249    /// The message already has this attribute
250    #[error("The attribute already exists in the message")]
251    AttributeExists(AttributeType),
252    /// The fingerprint attribute already exists. Cannot write any further attributes
253    #[error("The message already contains a fingerprint attribute")]
254    FingerprintExists,
255    /// A message integrity attribute already exists. Cannot write any further attributes
256    #[error("The message already contains a message intregrity attribute")]
257    MessageIntegrityExists,
258    /// The message has been truncated
259    #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
260    TooLarge {
261        /// The expeced number of bytes
262        expected: usize,
263        /// The encountered number of bytes
264        actual: usize,
265    },
266    /// The message has been truncated
267    #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
268    TooSmall {
269        /// The expected number of bytes
270        expected: usize,
271        /// The encountered number of bytes
272        actual: usize,
273    },
274    /// Failed to compute integrity
275    #[error("Failed to compute integrity")]
276    IntegrityFailed,
277    /// Out of range input provided
278    #[error("Out of range input provided")]
279    OutOfRange {
280        /// The value provided.
281        value: usize,
282        /// The minimum allowed value.
283        min: usize,
284        /// The maximum allowed value.
285        max: usize,
286    },
287}
288
289/// Structure for holding the required credentials for handling long-term STUN credentials
290#[derive(Debug, Clone, PartialEq, Eq)]
291#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
292pub struct LongTermCredentials {
293    username: String,
294    password: String,
295    realm: String,
296}
297
298impl LongTermCredentials {
299    /// Create a new set of [`LongTermCredentials`]
300    ///
301    /// # Examples
302    ///
303    /// ```
304    /// # use stun_types::message::LongTermCredentials;
305    /// let credentials = LongTermCredentials::new(
306    ///     "user".to_string(),
307    ///     "pass".to_string(),
308    ///     "realm".to_string(),
309    /// );
310    /// assert_eq!(credentials.username(), "user");
311    /// assert_eq!(credentials.password(), "pass");
312    /// assert_eq!(credentials.realm(), "realm");
313    /// ```
314    pub fn new(username: String, password: String, realm: String) -> Self {
315        Self {
316            username,
317            password,
318            realm,
319        }
320    }
321
322    /// The configured username
323    pub fn username(&self) -> &str {
324        &self.username
325    }
326
327    /// The configured password
328    pub fn password(&self) -> &str {
329        &self.password
330    }
331
332    /// The configured realm
333    pub fn realm(&self) -> &str {
334        &self.realm
335    }
336}
337
338/// Structure for holding the required credentials for handling short-term STUN credentials
339#[derive(Debug, Clone, PartialEq, Eq)]
340#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
341pub struct ShortTermCredentials {
342    password: String,
343}
344
345impl ShortTermCredentials {
346    /// Create a new set of [`ShortTermCredentials`]
347    ///
348    /// # Examples
349    ///
350    /// ```
351    /// # use stun_types::message::ShortTermCredentials;
352    /// let credentials = ShortTermCredentials::new("password".to_string());
353    /// assert_eq!(credentials.password(), "password");
354    /// ```
355    pub fn new(password: String) -> Self {
356        Self { password }
357    }
358
359    /// The configured password
360    pub fn password(&self) -> &str {
361        &self.password
362    }
363}
364
365/// Enum for holding the credentials used to sign or verify a [`Message`]
366///
367/// This can either be a set of [`ShortTermCredentials`] or [`LongTermCredentials`]`
368#[derive(Debug, Clone, PartialEq, Eq)]
369#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
370pub enum MessageIntegrityCredentials {
371    /// Short term integrity credentials.
372    ShortTerm(ShortTermCredentials),
373    /// Long term integrity credentials.
374    LongTerm(LongTermCredentials),
375}
376
377impl From<LongTermCredentials> for MessageIntegrityCredentials {
378    fn from(value: LongTermCredentials) -> Self {
379        MessageIntegrityCredentials::LongTerm(value)
380    }
381}
382
383impl From<ShortTermCredentials> for MessageIntegrityCredentials {
384    fn from(value: ShortTermCredentials) -> Self {
385        MessageIntegrityCredentials::ShortTerm(value)
386    }
387}
388
389impl MessageIntegrityCredentials {
390    /// Compute a key for caching purposes.
391    pub fn make_key(&self) -> IntegrityKey {
392        match self {
393            MessageIntegrityCredentials::ShortTerm(short) => {
394                IntegrityKey::new(short.password.as_bytes().to_vec())
395            }
396            MessageIntegrityCredentials::LongTerm(long) => {
397                use md5::{Digest, Md5};
398                let mut digest = Md5::new();
399                digest.update(long.username.as_bytes());
400                digest.update(":".as_bytes());
401                digest.update(long.realm.as_bytes());
402                digest.update(":".as_bytes());
403                digest.update(long.password.as_bytes());
404                IntegrityKey::new(digest.finalize().to_vec())
405            }
406        }
407    }
408}
409
410type HmacSha1 = hmac::Hmac<sha1::Sha1>;
411type HmacSha256 = hmac::Hmac<sha2::Sha256>;
412
413/// A cached key for a particular set of credentials.
414#[derive(Debug, Clone)]
415pub struct IntegrityKey {
416    bytes: Vec<u8>,
417    #[cfg(feature = "std")]
418    sha1: Arc<Mutex<Option<HmacSha1>>>,
419    #[cfg(feature = "std")]
420    sha256: Arc<Mutex<Option<HmacSha256>>>,
421}
422
423impl PartialEq<IntegrityKey> for IntegrityKey {
424    fn eq(&self, other: &Self) -> bool {
425        self.bytes == other.bytes
426    }
427}
428
429impl Eq for IntegrityKey {}
430
431impl IntegrityKey {
432    fn new(bytes: Vec<u8>) -> Self {
433        Self {
434            bytes,
435            #[cfg(feature = "std")]
436            sha1: Default::default(),
437            #[cfg(feature = "std")]
438            sha256: Default::default(),
439        }
440    }
441    pub(crate) fn as_bytes(&self) -> &[u8] {
442        &self.bytes
443    }
444
445    pub(crate) fn verify_sha1(&self, data: &[&[u8]], expected: &[u8]) -> bool {
446        use hmac::digest::Output;
447        let computed = self.compute_sha1(data);
448        computed == Output::<sha1::Sha1Core>::from_slice(expected).into()
449    }
450
451    pub(crate) fn compute_sha1(
452        &self,
453        data: &[&[u8]],
454    ) -> CtOutput<CoreWrapper<HmacCore<CoreWrapper<sha1::Sha1Core>>>> {
455        use hmac::Mac;
456        #[cfg(feature = "std")]
457        let mut sha1 = self.sha1.lock().unwrap();
458        #[cfg(feature = "std")]
459        let hmac = sha1.get_or_insert_with(|| HmacSha1::new_from_slice(self.as_bytes()).unwrap());
460        #[cfg(not(feature = "std"))]
461        let mut hmac = HmacSha1::new_from_slice(self.as_bytes()).unwrap();
462
463        for data in data {
464            hmac.update(data);
465        }
466        #[cfg(feature = "std")]
467        let ret = hmac.finalize_reset();
468        #[cfg(not(feature = "std"))]
469        let ret = hmac.finalize();
470        ret
471    }
472
473    pub(crate) fn verify_sha256(&self, data: &[&[u8]], expected: &[u8]) -> bool {
474        if expected.is_empty() {
475            return false;
476        }
477        let computed = self.compute_sha256(data);
478        if computed.len() < expected.len() {
479            return false;
480        }
481        // TODO: use constant time equality
482        &computed[..expected.len()] == expected
483    }
484
485    pub(crate) fn compute_sha256(&self, data: &[&[u8]]) -> [u8; 32] {
486        use hmac::Mac;
487        #[cfg(feature = "std")]
488        let mut sha256 = self.sha256.lock().unwrap();
489        #[cfg(feature = "std")]
490        let hmac =
491            sha256.get_or_insert_with(|| HmacSha256::new_from_slice(self.as_bytes()).unwrap());
492        #[cfg(not(feature = "std"))]
493        let mut hmac = HmacSha256::new_from_slice(self.as_bytes()).unwrap();
494
495        for data in data {
496            hmac.update(data);
497        }
498        #[cfg(feature = "std")]
499        let ret = hmac.finalize_reset();
500        #[cfg(not(feature = "std"))]
501        let ret = hmac.finalize();
502        ret.into_bytes().into()
503    }
504}
505
506/// The class of a [`Message`].
507///
508/// There are four classes of [`Message`]s within the STUN protocol:
509///
510///  - [Request][`MessageClass::Request`] indicates that a request is being made and a
511///    response is expected.
512///  - An [Indication][`MessageClass::Indication`] is a fire and forget [`Message`] where
513///    no response is required or expected.
514///  - [Success][`MessageClass::Success`] indicates that a [Request][`MessageClass::Request`]
515///    was successfully handled and the
516///  - [Error][`MessageClass::Error`] class indicates that an error was produced.
517#[derive(Copy, Clone, Debug, PartialEq, Eq)]
518pub enum MessageClass {
519    /// A request that is expecting a response of either Success, or Error.
520    Request,
521    /// A request that does not expect a response.
522    Indication,
523    /// A success response to a previous Request.
524    Success,
525    /// An error response to a previous Request.
526    Error,
527}
528
529impl MessageClass {
530    /// Returns whether this [`MessageClass`] is of a response type.  i.e. is either
531    /// [`MessageClass::Success`] or [`MessageClass::Error`].
532    pub fn is_response(self) -> bool {
533        matches!(self, MessageClass::Success | MessageClass::Error)
534    }
535
536    fn to_bits(self) -> u16 {
537        match self {
538            MessageClass::Request => 0x000,
539            MessageClass::Indication => 0x010,
540            MessageClass::Success => 0x100,
541            MessageClass::Error => 0x110,
542        }
543    }
544}
545
546/// The type of a [`Message`].  A combination of a [`MessageClass`] and a STUN method.
547#[derive(Copy, Clone, Debug, PartialEq, Eq)]
548pub struct MessageType(u16);
549
550impl core::fmt::Display for MessageType {
551    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
552        write!(
553            f,
554            "MessageType(class: {:?}, method: {}",
555            self.class(),
556            self.method(),
557        )
558    }
559}
560
561impl MessageType {
562    /// Create a new [`MessageType`] from the provided [`MessageClass`] and method
563    ///
564    /// # Examples
565    ///
566    /// ```
567    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
568    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
569    /// assert_eq!(mtype.has_class(MessageClass::Indication), true);
570    /// assert_eq!(mtype.has_method(BINDING), true);
571    /// ```
572    pub fn from_class_method(class: MessageClass, method: Method) -> Self {
573        let class_bits = MessageClass::to_bits(class);
574        let method = method.value();
575        let method_bits = method & 0xf | (method & 0x70) << 1 | (method & 0xf80) << 2;
576        // trace!("MessageType from class {:?} and method {:?} into {:?}", class, method,
577        //     class_bits | method_bits);
578        Self(class_bits | method_bits)
579    }
580
581    /// Retrieves the class of a [`MessageType`]
582    ///
583    /// # Examples
584    ///
585    /// ```
586    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
587    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
588    /// assert_eq!(mtype.class(), MessageClass::Indication);
589    /// ```
590    pub fn class(self) -> MessageClass {
591        let class = (self.0 & 0x10) >> 4 | (self.0 & 0x100) >> 7;
592        match class {
593            0x0 => MessageClass::Request,
594            0x1 => MessageClass::Indication,
595            0x2 => MessageClass::Success,
596            0x3 => MessageClass::Error,
597            _ => unreachable!(),
598        }
599    }
600
601    /// Returns whether class of a [`MessageType`] is equal to the provided [`MessageClass`]
602    ///
603    /// # Examples
604    ///
605    /// ```
606    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
607    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
608    /// assert!(mtype.has_class(MessageClass::Indication));
609    /// ```
610    pub fn has_class(self, cls: MessageClass) -> bool {
611        self.class() == cls
612    }
613
614    /// Returns whether the class of a [`MessageType`] indicates a response [`Message`]
615    ///
616    /// # Examples
617    ///
618    /// ```
619    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
620    /// assert_eq!(MessageType::from_class_method(MessageClass::Indication, BINDING)
621    ///     .is_response(), false);
622    /// assert_eq!(MessageType::from_class_method(MessageClass::Request, BINDING)
623    ///     .is_response(), false);
624    /// assert_eq!(MessageType::from_class_method(MessageClass::Success, BINDING)
625    ///     .is_response(), true);
626    /// assert_eq!(MessageType::from_class_method(MessageClass::Error, BINDING)
627    ///     .is_response(), true);
628    /// ```
629    pub fn is_response(self) -> bool {
630        self.class().is_response()
631    }
632
633    /// Returns the method of a [`MessageType`]
634    ///
635    /// # Examples
636    ///
637    /// ```
638    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
639    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
640    /// assert_eq!(mtype.method(), BINDING);
641    /// ```
642    pub fn method(self) -> Method {
643        Method::new(self.0 & 0xf | (self.0 & 0xe0) >> 1 | (self.0 & 0x3e00) >> 2)
644    }
645
646    /// Returns whether the method of a [`MessageType`] is equal to the provided value
647    ///
648    /// # Examples
649    ///
650    /// ```
651    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
652    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
653    /// assert_eq!(mtype.has_method(BINDING), true);
654    /// ```
655    pub fn has_method(self, method: Method) -> bool {
656        self.method() == method
657    }
658
659    /// Convert a [`MessageType`] to network bytes
660    pub fn write_into(&self, dest: &mut [u8]) {
661        BigEndian::write_u16(dest, self.0);
662    }
663
664    /// Convert a [`MessageType`] to network bytes
665    pub fn to_bytes(self) -> Vec<u8> {
666        let mut ret = vec![0; 2];
667        BigEndian::write_u16(&mut ret[0..2], self.0);
668        ret
669    }
670
671    /// Convert a set of network bytes into a [`MessageType`] or return an error
672    pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
673        let data = BigEndian::read_u16(data);
674        if data & 0xc000 != 0x0 {
675            /* not a stun packet */
676            return Err(StunParseError::NotStun);
677        }
678        Ok(Self(data))
679    }
680}
681impl TryFrom<&[u8]> for MessageType {
682    type Error = StunParseError;
683
684    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
685        MessageType::from_bytes(value)
686    }
687}
688
689/// A unique transaction identifier for each message and it's (possible) response.
690#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
691pub struct TransactionId {
692    id: u128,
693}
694
695impl TransactionId {
696    /// Generate a new STUN transaction identifier.
697    pub fn generate() -> TransactionId {
698        #[cfg(not(feature = "std"))]
699        {
700            use rand::TryRngCore;
701            let mut dest = [0; 16];
702            rand::rngs::OsRng
703                .try_fill_bytes(&mut dest)
704                .expect("Cannot generate random data");
705            u128::from_be_bytes(dest).into()
706        }
707        #[cfg(feature = "std")]
708        {
709            use rand::Rng;
710            let mut rng = rand::rng();
711            rng.random::<u128>().into()
712        }
713    }
714}
715
716impl From<u128> for TransactionId {
717    fn from(id: u128) -> Self {
718        Self {
719            id: id & 0xffff_ffff_ffff_ffff_ffff_ffff,
720        }
721    }
722}
723impl From<TransactionId> for u128 {
724    fn from(id: TransactionId) -> Self {
725        id.id
726    }
727}
728impl core::fmt::Display for TransactionId {
729    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
730        write!(f, "{:#x}", self.id)
731    }
732}
733
734/// The fixed length header of a STUN message.  Allows reading the message header for a quick
735/// check if this message is a valid STUN message.  Can also be used to expose the length of the
736/// complete message without needing to receive the entire message.
737#[derive(Debug)]
738pub struct MessageHeader {
739    mtype: MessageType,
740    transaction_id: TransactionId,
741    length: u16,
742}
743
744impl MessageHeader {
745    /// The length of the STUN message header.
746    pub const LENGTH: usize = 20;
747
748    /// Deserialize a `MessageHeader`
749    ///
750    /// # Examples
751    ///
752    /// ```
753    /// # use stun_types::message::{MessageHeader, MessageType, MessageClass, BINDING};
754    /// let msg_data = [0, 1, 0, 8, 33, 18, 164, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 232];
755    /// let message = MessageHeader::from_bytes(&msg_data).unwrap();
756    /// assert_eq!(message.get_type(), MessageType::from_class_method(MessageClass::Request, BINDING));
757    /// assert_eq!(message.transaction_id(), 1000.into());
758    /// assert_eq!(message.data_length(), 8);
759    /// ```
760    pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
761        if data.len() < 20 {
762            return Err(StunParseError::Truncated {
763                expected: 20,
764                actual: data.len(),
765            });
766        }
767        let mtype = MessageType::from_bytes(data)?;
768        let mlength = BigEndian::read_u16(&data[2..]);
769        let tid = BigEndian::read_u128(&data[4..]);
770        let cookie = (tid >> 96) as u32;
771        if cookie != MAGIC_COOKIE {
772            warn!(
773                "malformed cookie constant {:?} != stored data {:?}",
774                MAGIC_COOKIE, cookie
775            );
776            return Err(StunParseError::NotStun);
777        }
778
779        Ok(Self {
780            mtype,
781            transaction_id: tid.into(),
782            length: mlength,
783        })
784    }
785
786    /// The number of bytes of content in this [`MessageHeader`]. Adding both `data_length()`
787    /// and [`MessageHeader::LENGTH`] will result in the size of the complete STUN message.
788    pub fn data_length(&self) -> u16 {
789        self.length
790    }
791
792    /// The [`TransactionId`] of this [`MessageHeader`]
793    pub fn transaction_id(&self) -> TransactionId {
794        self.transaction_id
795    }
796
797    /// The [`MessageType`] of this [`MessageHeader`]
798    pub fn get_type(&self) -> MessageType {
799        self.mtype
800    }
801
802    fn new(mtype: MessageType, transaction_id: TransactionId, length: u16) -> Self {
803        Self {
804            mtype,
805            transaction_id,
806            length,
807        }
808    }
809
810    fn write_into(&self, dest: &mut [u8]) {
811        self.mtype.write_into(&mut dest[..2]);
812        let transaction: u128 = self.transaction_id.into();
813        let tid = (MAGIC_COOKIE as u128) << 96 | transaction & 0xffff_ffff_ffff_ffff_ffff_ffff;
814        BigEndian::write_u128(&mut dest[4..20], tid);
815        BigEndian::write_u16(&mut dest[2..4], self.length);
816    }
817}
818
819/// The structure that encapsulates the entirety of a STUN message
820///
821/// Contains the [`MessageType`], a transaction ID, and a list of STUN
822/// [`Attribute`]
823#[derive(Debug, Clone, Copy)]
824pub struct Message<'a> {
825    data: &'a [u8],
826}
827
828impl core::fmt::Display for Message<'_> {
829    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
830        write!(
831            f,
832            "Message(class: {:?}, method: {}, transaction: {}, attributes: ",
833            self.get_type().class(),
834            self.get_type().method(),
835            self.transaction_id()
836        )?;
837        let iter = self.iter_attributes();
838        write!(f, "[")?;
839        for (i, (_offset, a)) in iter.enumerate() {
840            if i > 0 {
841                write!(f, ", ")?;
842            }
843            write!(f, "{a}")?;
844        }
845        write!(f, "]")?;
846        write!(f, ")")
847    }
848}
849
850/// The supported hashing algorithms for ensuring integrity of a [`Message`]
851#[derive(Clone, Copy, Debug, PartialEq, Eq)]
852pub enum IntegrityAlgorithm {
853    /// SHA-1 algorithm
854    Sha1,
855    /// SHA-256 algorithm
856    Sha256,
857}
858
859impl<'a> Message<'a> {
860    /// Create a new [`Message`] with the provided [`MessageType`] and transaction ID
861    ///
862    /// Note you probably want to use one of the other helper constructors instead.
863    ///
864    /// # Examples
865    ///
866    /// ```
867    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
868    /// #     MessageWrite, BINDING};
869    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
870    /// let message = Message::builder(mtype, 0.into(), MessageWriteVec::new()).finish();
871    /// let message = Message::from_bytes(&message).unwrap();
872    /// assert!(message.has_class(MessageClass::Indication));
873    /// assert!(message.has_method(BINDING));
874    /// ```
875    pub fn builder<B: MessageWrite>(
876        mtype: MessageType,
877        transaction_id: TransactionId,
878        mut write: B,
879    ) -> B {
880        let mut data = [0; 20];
881        MessageHeader::new(mtype, transaction_id, 0).write_into(&mut data);
882        write.push_data(&data);
883        write
884    }
885
886    /// Create a new request [`Message`] of the provided method
887    ///
888    /// # Examples
889    ///
890    /// ```
891    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
892    /// #     MessageWrite, BINDING};
893    /// let message = Message::builder_request(BINDING, MessageWriteVec::new());
894    /// let data = message.finish();
895    /// let message = Message::from_bytes(&data).unwrap();
896    /// assert!(message.has_class(MessageClass::Request));
897    /// assert!(message.has_method(BINDING));
898    /// ```
899    pub fn builder_request<B: MessageWrite>(method: Method, write: B) -> B {
900        Message::builder(
901            MessageType::from_class_method(MessageClass::Request, method),
902            TransactionId::generate(),
903            write,
904        )
905    }
906
907    /// Create a new success [`Message`] response from the provided request
908    ///
909    /// # Panics
910    ///
911    /// When a non-request [`Message`] is passed as the original input [`Message`]
912    ///
913    /// # Examples
914    ///
915    /// ```
916    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
917    /// #      MessageWrite, BINDING};
918    /// let message = Message::builder_request(BINDING, MessageWriteVec::new());
919    /// let data = message.finish();
920    /// let message = Message::from_bytes(&data).unwrap();
921    /// let success = Message::builder_success(&message, MessageWriteVec::new()).finish();
922    /// let success = Message::from_bytes(&success).unwrap();
923    /// assert!(success.has_class(MessageClass::Success));
924    /// assert!(success.has_method(BINDING));
925    /// ```
926    pub fn builder_success<B: MessageWrite>(orig: &Message, write: B) -> B {
927        if !orig.has_class(MessageClass::Request) {
928            panic!(
929                "A success response message was attempted to be created from a non-request message"
930            );
931        }
932        Message::builder(
933            MessageType::from_class_method(MessageClass::Success, orig.method()),
934            orig.transaction_id(),
935            write,
936        )
937    }
938
939    /// Create a new error [`Message`] response from the provided request
940    ///
941    /// # Panics
942    ///
943    /// When a non-request [`Message`] is passed as the original input [`Message`]
944    ///
945    /// # Examples
946    ///
947    /// ```
948    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
949    /// #     MessageWrite, BINDING};
950    /// let message = Message::builder_request(BINDING, MessageWriteVec::new());
951    /// let data = message.finish();
952    /// let message = Message::from_bytes(&data).unwrap();
953    /// let error = Message::builder_error(&message, MessageWriteVec::new()).finish();
954    /// let error = Message::from_bytes(&error).unwrap();
955    /// assert!(error.has_class(MessageClass::Error));
956    /// assert!(error.has_method(BINDING));
957    /// ```
958    pub fn builder_error<B: MessageWrite>(orig: &Message, write: B) -> B {
959        if !orig.has_class(MessageClass::Request) {
960            panic!(
961                "An error response message was attempted to be created from a non-request message"
962            );
963        }
964        Message::builder(
965            MessageType::from_class_method(MessageClass::Error, orig.method()),
966            orig.transaction_id(),
967            write,
968        )
969    }
970
971    /// Create a new indication [`Message`] of the provided method.
972    ///
973    /// # Examples
974    ///
975    /// ```
976    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
977    /// #     MessageWrite, BINDING};
978    /// let message = Message::builder_indication(BINDING, MessageWriteVec::new());
979    /// let data = message.finish();
980    /// let message = Message::from_bytes(&data).unwrap();
981    /// assert!(message.has_class(MessageClass::Indication));
982    /// assert!(message.has_method(BINDING));
983    /// ```
984    pub fn builder_indication<B: MessageWrite>(method: Method, write: B) -> B {
985        Message::builder(
986            MessageType::from_class_method(MessageClass::Indication, method),
987            TransactionId::generate(),
988            write,
989        )
990    }
991
992    /// Retrieve the [`MessageType`] of a [`Message`]
993    ///
994    /// # Examples
995    ///
996    /// ```
997    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
998    /// #     MessageWrite, BINDING};
999    /// let message = Message::builder_request(BINDING, MessageWriteVec::new());
1000    /// let data = message.finish();
1001    /// let message = Message::from_bytes(&data).unwrap();
1002    /// assert!(message.get_type().has_class(MessageClass::Request));
1003    /// assert!(message.get_type().has_method(BINDING));
1004    /// ```
1005    pub fn get_type(&self) -> MessageType {
1006        MessageType::try_from(&self.data[..2]).unwrap()
1007    }
1008
1009    /// Retrieve the [`MessageClass`] of a [`Message`]
1010    ///
1011    /// # Examples
1012    ///
1013    /// ```
1014    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1015    /// #     MessageWrite, BINDING};
1016    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1017    /// let message = Message::from_bytes(&message).unwrap();
1018    /// assert_eq!(message.class(), MessageClass::Request);
1019    /// ```
1020    pub fn class(&self) -> MessageClass {
1021        self.get_type().class()
1022    }
1023
1024    /// Returns whether the [`Message`] is of the specified [`MessageClass`]
1025    ///
1026    /// # Examples
1027    ///
1028    /// ```
1029    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1030    /// #     MessageWrite, BINDING};
1031    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1032    /// let message = Message::from_bytes(&message).unwrap();
1033    /// assert!(message.has_class(MessageClass::Request));
1034    /// ```
1035    pub fn has_class(&self, cls: MessageClass) -> bool {
1036        self.class() == cls
1037    }
1038
1039    /// Returns whether the [`Message`] is a response
1040    ///
1041    /// This means that the [`Message`] has a class of either success or error
1042    ///
1043    /// # Examples
1044    ///
1045    /// ```
1046    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1047    /// #     MessageWrite, BINDING};
1048    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1049    /// let message = Message::from_bytes(&message).unwrap();
1050    /// assert_eq!(message.is_response(), false);
1051    ///
1052    /// let error = Message::builder_error(&message, MessageWriteVec::new()).finish();
1053    /// let error = Message::from_bytes(&error).unwrap();
1054    /// assert_eq!(error.is_response(), true);
1055    ///
1056    /// let success = Message::builder_success(&message, MessageWriteVec::new()).finish();
1057    /// let success = Message::from_bytes(&success).unwrap();
1058    /// assert_eq!(success.is_response(), true);
1059    /// ```
1060    pub fn is_response(&self) -> bool {
1061        self.class().is_response()
1062    }
1063
1064    /// Retrieves the method of the [`Message`]
1065    ///
1066    /// # Examples
1067    ///
1068    /// ```
1069    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1070    /// #     MessageWrite, BINDING};
1071    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1072    /// let message = Message::from_bytes(&message).unwrap();
1073    /// assert_eq!(message.method(), BINDING);
1074    /// ```
1075    pub fn method(&self) -> Method {
1076        self.get_type().method()
1077    }
1078
1079    /// Returns whether the [`Message`] is of the specified method
1080    ///
1081    /// # Examples
1082    ///
1083    /// ```
1084    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1085    /// #     Method, MessageWrite, BINDING};
1086    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1087    /// let message = Message::from_bytes(&message).unwrap();
1088    /// assert_eq!(message.has_method(BINDING), true);
1089    /// assert_eq!(message.has_method(Method::new(0)), false);
1090    /// ```
1091    pub fn has_method(&self, method: Method) -> bool {
1092        self.method() == method
1093    }
1094
1095    /// Retrieves the 96-bit transaction ID of the [`Message`]
1096    ///
1097    /// # Examples
1098    ///
1099    /// ```
1100    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1101    /// #     MessageWrite, BINDING, TransactionId};
1102    /// let mtype = MessageType::from_class_method(MessageClass::Request, BINDING);
1103    /// let transaction_id = TransactionId::generate();
1104    /// let message = Message::builder(mtype, transaction_id, MessageWriteVec::new()).finish();
1105    /// let message = Message::from_bytes(&message).unwrap();
1106    /// assert_eq!(message.transaction_id(), transaction_id);
1107    /// ```
1108    pub fn transaction_id(&self) -> TransactionId {
1109        BigEndian::read_u128(&self.data[4..]).into()
1110    }
1111
1112    /// Deserialize a `Message`
1113    ///
1114    /// # Examples
1115    ///
1116    /// ```
1117    /// # use stun_types::attribute::{RawAttribute, Attribute};
1118    /// # use stun_types::message::{Message, MessageType, MessageClass, BINDING};
1119    /// let msg_data = vec![0, 1, 0, 8, 33, 18, 164, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 232, 0, 1, 0, 1, 3, 0, 0, 0];
1120    /// let message = Message::from_bytes(&msg_data).unwrap();
1121    /// let attr = RawAttribute::new(1.into(), &[3]);
1122    /// let msg_attr = message.raw_attribute(1.into()).unwrap();
1123    /// assert_eq!(msg_attr, attr);
1124    /// assert_eq!(message.get_type(), MessageType::from_class_method(MessageClass::Request, BINDING));
1125    /// assert_eq!(message.transaction_id(), 1000.into());
1126    /// ```
1127    #[tracing::instrument(
1128        name = "message_from_bytes",
1129        level = "trace",
1130        skip(data),
1131        fields(
1132            data.len = data.len()
1133        )
1134    )]
1135    pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
1136        let orig_data = data;
1137
1138        let header = MessageHeader::from_bytes(data)?;
1139        let mlength = header.data_length() as usize;
1140        if mlength + MessageHeader::LENGTH > data.len() {
1141            // mlength + header
1142            warn!(
1143                "malformed advertised size {} and data size {} don't match",
1144                mlength + 20,
1145                data.len()
1146            );
1147            return Err(StunParseError::Truncated {
1148                expected: mlength + MessageHeader::LENGTH,
1149                actual: data.len(),
1150            });
1151        }
1152
1153        let ending_attributes = [
1154            MessageIntegrity::TYPE,
1155            MessageIntegritySha256::TYPE,
1156            Fingerprint::TYPE,
1157        ];
1158        // XXX: maybe use small/tinyvec?
1159        let mut seen_ending_attributes = [AttributeType::new(0); 3];
1160        let mut seen_ending_len = 0;
1161        let mut data_offset = MessageHeader::LENGTH;
1162        for attr in MessageRawAttributesIter::new(data) {
1163            let (_offset, attr) = attr.map_err(|e| {
1164                warn!("failed to parse message attribute at offset {data_offset}: {e}",);
1165                e
1166            })?;
1167
1168            // if we have seen any ending attributes, then there is only a fixed set of attributes
1169            // that are allowed.
1170            if seen_ending_len > 0 && !ending_attributes.contains(&attr.get_type()) {
1171                if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1172                    warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1173                    return Ok(Message { data: orig_data });
1174                } else {
1175                    // only attribute valid after MESSAGE_INTEGRITY is FINGERPRINT
1176                    warn!(
1177                        "unexpected attribute {} after MESSAGE_INTEGRITY",
1178                        attr.get_type()
1179                    );
1180                    return Ok(Message { data: orig_data });
1181                }
1182            }
1183
1184            if ending_attributes.contains(&attr.get_type()) {
1185                if seen_ending_attributes.contains(&attr.get_type()) {
1186                    if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1187                        warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1188                        return Ok(Message { data: orig_data });
1189                    } else {
1190                        // only attribute valid after MESSAGE_INTEGRITY is FINGERPRINT
1191                        warn!(
1192                            "unexpected attribute {} after MESSAGE_INTEGRITY",
1193                            attr.get_type()
1194                        );
1195                        return Ok(Message { data: orig_data });
1196                    }
1197                } else {
1198                    seen_ending_attributes[seen_ending_len] = attr.get_type();
1199                    seen_ending_len += 1;
1200                    // need credentials to validate the integrity of the message
1201                }
1202            }
1203            let padded_len = attr.padded_len();
1204            if attr.get_type() == Fingerprint::TYPE {
1205                let f = Fingerprint::from_raw_ref(&attr)?;
1206                let msg_fingerprint = f.fingerprint();
1207                let mut header = [0; 4];
1208                header[0] = orig_data[0];
1209                header[1] = orig_data[1];
1210                BigEndian::write_u16(
1211                    &mut header[2..4],
1212                    (data_offset + padded_len - MessageHeader::LENGTH) as u16,
1213                );
1214                let fingerprint_data = &orig_data[4..data_offset];
1215                let calculated_fingerprint = Fingerprint::compute(&[&header, fingerprint_data]);
1216                if &calculated_fingerprint != msg_fingerprint {
1217                    warn!(
1218                        "fingerprint mismatch {:?} != {:?}",
1219                        calculated_fingerprint, msg_fingerprint
1220                    );
1221                    return Err(StunParseError::FingerprintMismatch);
1222                }
1223            }
1224            data_offset += padded_len;
1225        }
1226        Ok(Message { data: orig_data })
1227    }
1228
1229    /// Validates the MESSAGE_INTEGRITY attribute with the provided credentials
1230    ///
1231    /// The Original data that was used to construct this [`Message`] must be provided in order
1232    /// to successfully validate the [`Message`]
1233    ///
1234    /// # Examples
1235    ///
1236    /// ```
1237    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1238    /// #     MessageWrite, MessageWriteExt, BINDING, MessageIntegrityCredentials,
1239    /// #     LongTermCredentials, IntegrityAlgorithm};
1240    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1241    /// let credentials = LongTermCredentials::new(
1242    ///     "user".to_owned(),
1243    ///     "pass".to_owned(),
1244    ///     "realm".to_owned()
1245    /// ).into();
1246    /// assert!(message.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256).is_ok());
1247    /// let data = message.finish();
1248    /// let message = Message::from_bytes(&data).unwrap();
1249    /// assert!(message.validate_integrity(&credentials).is_ok());
1250    /// ```
1251    pub fn validate_integrity(
1252        &self,
1253        credentials: &MessageIntegrityCredentials,
1254    ) -> Result<IntegrityAlgorithm, StunParseError> {
1255        let key = credentials.make_key();
1256        self.validate_integrity_with_key(&key)
1257    }
1258
1259    /// Validates the MESSAGE_INTEGRITY attribute with the provided credentials key.
1260    #[tracing::instrument(
1261        name = "message_validate_integrity_with_key",
1262        level = "trace",
1263        skip(self, key),
1264        fields(
1265            msg.transaction = %self.transaction_id(),
1266        )
1267    )]
1268    pub fn validate_integrity_with_key(
1269        &self,
1270        key: &IntegrityKey,
1271    ) -> Result<IntegrityAlgorithm, StunParseError> {
1272        let raw_sha1 = self.raw_attribute(MessageIntegrity::TYPE);
1273        let raw_sha256 = self.raw_attribute(MessageIntegritySha256::TYPE);
1274        let (algo, msg_hmac) = match (raw_sha1, raw_sha256) {
1275            (_, Some(sha256)) => {
1276                let integrity = MessageIntegritySha256::try_from(&sha256)?;
1277                (IntegrityAlgorithm::Sha256, integrity.hmac().to_vec())
1278            }
1279            (Some(sha1), None) => {
1280                let integrity = MessageIntegrity::try_from(&sha1)?;
1281                (IntegrityAlgorithm::Sha1, integrity.hmac().to_vec())
1282            }
1283            (None, None) => return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE)),
1284        };
1285
1286        // find the location of the original MessageIntegrity attribute: XXX: maybe encode this into
1287        // the attribute instead?
1288        let data = self.data;
1289        debug_assert!(data.len() >= MessageHeader::LENGTH);
1290        let mut data = &data[MessageHeader::LENGTH..];
1291        let mut data_offset = MessageHeader::LENGTH;
1292        while !data.is_empty() {
1293            let attr = RawAttribute::from_bytes(data)?;
1294            if algo == IntegrityAlgorithm::Sha1 && attr.get_type() == MessageIntegrity::TYPE {
1295                let msg = MessageIntegrity::try_from(&attr)?;
1296                debug_assert!(msg.hmac().as_slice() == msg_hmac);
1297
1298                // HMAC is computed using all the data up to (exclusive of) the MESSAGE_INTEGRITY
1299                // but with a length field including the MESSAGE_INTEGRITY attribute...
1300                let mut header = [0; 4];
1301                header[0] = self.data[0];
1302                header[1] = self.data[1];
1303                let hmac_data = &self.data[4..data_offset];
1304                BigEndian::write_u16(
1305                    &mut header[2..4],
1306                    data_offset as u16 + 24 - MessageHeader::LENGTH as u16,
1307                );
1308                MessageIntegrity::verify(
1309                    &[header.as_slice(), hmac_data],
1310                    key,
1311                    msg_hmac.as_slice().try_into().unwrap(),
1312                )?;
1313                return Ok(algo);
1314            } else if algo == IntegrityAlgorithm::Sha256
1315                && attr.get_type() == MessageIntegritySha256::TYPE
1316            {
1317                let msg = MessageIntegritySha256::try_from(&attr)?;
1318                debug_assert!(msg.hmac() == msg_hmac);
1319
1320                // HMAC is computed using all the data up to (exclusive of) the MESSAGE_INTEGRITY
1321                // but with a length field including the MESSAGE_INTEGRITY attribute...
1322                let mut header = [0; 4];
1323                header[0] = self.data[0];
1324                header[1] = self.data[1];
1325                let hmac_data = &self.data[4..data_offset];
1326                BigEndian::write_u16(
1327                    &mut header[2..4],
1328                    data_offset as u16 + attr.padded_len() as u16 - MessageHeader::LENGTH as u16,
1329                );
1330                MessageIntegritySha256::verify(&[&header, hmac_data], key, &msg_hmac)?;
1331                return Ok(algo);
1332            }
1333            let padded_len = attr.padded_len();
1334            // checked when initially parsing.
1335            debug_assert!(padded_len <= data.len());
1336            data = &data[padded_len..];
1337            data_offset += padded_len;
1338        }
1339
1340        // Either there is no integrity (checked earlier), or the integrity was found and checked
1341        // by the loop above.
1342        unreachable!();
1343    }
1344
1345    /// Retrieve the nth `RawAttribute` with a particular [`AttributeType`] from this `Message`.
1346    ///
1347    /// # Examples
1348    ///
1349    /// Retrieve a`RawAttribute`
1350    ///
1351    /// ```
1352    /// # use stun_types::attribute::{RawAttribute, Attribute};
1353    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1354    /// #     MessageWrite, MessageWriteExt, BINDING};
1355    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1356    /// let attr = RawAttribute::new(1.into(), &[3]);
1357    /// assert!(message.add_attribute(&attr).is_ok());
1358    /// assert!(message.add_attribute(&attr).is_ok());
1359    /// let message = message.finish();
1360    /// let message = Message::from_bytes(&message).unwrap();
1361    /// assert_eq!(message.nth_raw_attribute(1.into(), 1).unwrap(), attr);
1362    /// ```
1363    pub fn nth_raw_attribute(&self, atype: AttributeType, n: usize) -> Option<RawAttribute<'_>> {
1364        self.nth_raw_attribute_and_offset(atype, n)
1365            .map(|(_offset, attr)| attr)
1366    }
1367
1368    /// Retrieve the first `RawAttribute` of a particular `AttributeTye` from this `Message`.
1369    ///
1370    /// The is equivalent to `Message::nth_raw_attribute(0)`.
1371    pub fn raw_attribute(&self, atype: AttributeType) -> Option<RawAttribute<'_>> {
1372        self.nth_raw_attribute(atype, 0)
1373    }
1374
1375    /// Retrieve the nth `RawAttribute` of a particular `AttributeType` from this `Message` with
1376    /// it's byte offset.
1377    ///
1378    /// The offset is from the start of the 4 byte Attribute header.
1379    ///
1380    /// # Examples
1381    ///
1382    /// Retrieve a`RawAttribute`
1383    ///
1384    /// ```
1385    /// # use stun_types::attribute::{RawAttribute, Attribute};
1386    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1387    /// #     MessageWrite, MessageWriteExt, BINDING};
1388    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1389    /// let attr = RawAttribute::new(1.into(), &[3]);
1390    /// assert!(message.add_attribute(&attr).is_ok());
1391    /// assert!(message.add_attribute(&attr).is_ok());
1392    /// let message = message.finish();
1393    /// let message = Message::from_bytes(&message).unwrap();
1394    /// assert_eq!(message.nth_raw_attribute_and_offset(1.into(), 1).unwrap(), (28, attr));
1395    /// ```
1396    #[tracing::instrument(
1397        name = "message_nth_raw_attribute_and_offset",
1398        level = "trace",
1399        skip(self, atype),
1400        fields(
1401            msg.transaction = %self.transaction_id(),
1402            attribute_type = %atype,
1403        )
1404    )]
1405    pub fn nth_raw_attribute_and_offset(
1406        &self,
1407        atype: AttributeType,
1408        n: usize,
1409    ) -> Option<(usize, RawAttribute<'_>)> {
1410        if let Some((offset, attr)) = self
1411            .iter_attributes()
1412            .filter(|(_offset, attr)| attr.get_type() == atype)
1413            .nth(n)
1414        {
1415            trace!("found attribute at offset: {offset}");
1416            Some((offset, attr))
1417        } else {
1418            trace!("could not find attribute");
1419            None
1420        }
1421    }
1422
1423    /// Retrieve the first `RawAttribute` of a particular `AttributeType` from this `Message` with
1424    /// it's byte offset.
1425    ///
1426    /// This equivalent to calling `Message::nth_raw_attribute_and_offset(0)`.
1427    pub fn raw_attribute_and_offset(
1428        &self,
1429        atype: AttributeType,
1430    ) -> Option<(usize, RawAttribute<'_>)> {
1431        self.nth_raw_attribute_and_offset(atype, 0)
1432    }
1433
1434    /// Retrieve the nth `Attribute` of a particular `AttributeType` from this `Message`.
1435    ///
1436    /// This will error with [`StunParseError::MissingAttribute`] if the attribute does not exist.
1437    /// Otherwise, other parsing errors of the data may be returned specific to the attribute
1438    /// implementation provided.
1439    ///
1440    /// # Examples
1441    ///
1442    /// Retrieve an `Attribute`
1443    ///
1444    /// ```
1445    /// # use stun_types::attribute::{Software, Attribute};
1446    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1447    /// #     MessageWrite, MessageWriteExt, BINDING};
1448    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1449    /// let attr = Software::new("stun-types").unwrap();
1450    /// assert!(message.add_attribute(&attr).is_ok());
1451    /// let message = message.finish();
1452    /// let message = Message::from_bytes(&message).unwrap();
1453    /// assert_eq!(message.attribute::<Software>().unwrap(), attr);
1454    /// ```
1455    pub fn nth_attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1456        &'a self,
1457        n: usize,
1458    ) -> Result<A, StunParseError> {
1459        self.nth_attribute_and_offset(n).map(|(_offset, attr)| attr)
1460    }
1461
1462    /// Retrieve the first `Attribute` of a particular `AttributeType` from this `Message`.
1463    ///
1464    /// This equivalent to calling `Message::nth_attribute(0)`.
1465    pub fn attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1466        &'a self,
1467    ) -> Result<A, StunParseError> {
1468        self.nth_attribute(0)
1469    }
1470
1471    /// Retrieve the nth `Attribute` of a particular `AttributeType` from this `Message` and it's
1472    /// offset in the original data.
1473    ///
1474    /// This will error with [`StunParseError::MissingAttribute`] if the attribute does not exist.
1475    /// Otherwise, other parsing errors of the data may be returned specific to the attribute
1476    /// implementation provided.
1477    ///
1478    /// The offset is from the start of the 4 byte [`Attribute`] header.
1479    ///
1480    /// # Examples
1481    ///
1482    /// Retrieve an `Attribute`
1483    ///
1484    /// ```
1485    /// # use stun_types::attribute::{Software, Attribute};
1486    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1487    /// #     MessageWrite, MessageWriteExt, BINDING};
1488    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1489    /// let attr = Software::new("stun-types").unwrap();
1490    /// assert!(message.add_attribute(&attr).is_ok());
1491    /// assert!(message.add_attribute(&attr).is_ok());
1492    /// let message = message.finish();
1493    /// let message = Message::from_bytes(&message).unwrap();
1494    /// assert_eq!(message.nth_attribute_and_offset::<Software>(1).unwrap(), (36, attr));
1495    /// ```
1496    pub fn nth_attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1497        &'a self,
1498        n: usize,
1499    ) -> Result<(usize, A), StunParseError> {
1500        self.nth_raw_attribute_and_offset(A::TYPE, n)
1501            .ok_or(StunParseError::MissingAttribute(A::TYPE))
1502            .and_then(|(offset, raw)| A::from_raw(raw).map(|attr| (offset, attr)))
1503    }
1504
1505    /// Retrieve the first `Attribute` of a particular `AttributeType` from this `Message` and it's
1506    /// offset in the original data.
1507    ///
1508    /// This equivalent to calling `Message::nth_attribute_and_offset(0)`.
1509    pub fn attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1510        &'a self,
1511    ) -> Result<(usize, A), StunParseError> {
1512        self.nth_attribute_and_offset(0)
1513    }
1514
1515    /// Returns an iterator over the attributes (with their byte offset) in the [`Message`].
1516    pub fn iter_attributes(&self) -> impl Iterator<Item = (usize, RawAttribute<'_>)> {
1517        MessageAttributesIter::new(self.data)
1518    }
1519
1520    /// Check that a message [`Message`] only contains required attributes that are supported and
1521    /// have at least some set of required attributes.  Returns an appropriate error message on
1522    /// failure to meet these requirements.
1523    ///
1524    /// # Examples
1525    ///
1526    /// ```
1527    /// # use stun_types::attribute::*;
1528    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1529    /// #     MessageWrite, MessageWriteExt, BINDING};
1530    /// # use core::convert::TryInto;
1531    /// let mut builder = Message::builder_request(BINDING, MessageWriteVec::new());
1532    /// let message = builder.finish();
1533    /// let message = Message::from_bytes(&message).unwrap();
1534    /// // If nothing is required, no error response is returned
1535    /// assert!(matches!(Message::check_attribute_types(&message, &[], &[], MessageWriteVec::new()), None));
1536    ///
1537    /// // If an atttribute is required that is not in the message, then an error response message
1538    /// // is generated
1539    /// let error_msg = Message::check_attribute_types(
1540    ///     &message,
1541    ///     &[],
1542    ///     &[Software::TYPE],
1543    ///     MessageWriteVec::new(),
1544    /// ).unwrap();
1545    /// assert!(error_msg.has_attribute(ErrorCode::TYPE));
1546    /// let error_msg = error_msg.finish();
1547    /// let error_msg = Message::from_bytes(&error_msg).unwrap();
1548    /// let error_code = error_msg.attribute::<ErrorCode>().unwrap();
1549    /// assert_eq!(error_code.code(), 400);
1550    ///
1551    /// let mut builder = Message::builder_request(BINDING, MessageWriteVec::new());
1552    /// let username = Username::new("user").unwrap();
1553    /// builder.add_attribute(&username).unwrap();
1554    /// let message = builder.finish();
1555    /// let message = Message::from_bytes(&message).unwrap();
1556    /// // If a Username is in the message but is not advertised as supported then an
1557    /// // 'UNKNOWN-ATTRIBUTES' error response is returned
1558    /// let error_msg = Message::check_attribute_types(&message, &[], &[], MessageWriteVec::new()).unwrap();
1559    /// let error_msg = error_msg.finish();
1560    /// let error_msg = Message::from_bytes(&error_msg).unwrap();
1561    /// assert!(error_msg.is_response());
1562    /// assert!(error_msg.has_attribute(ErrorCode::TYPE));
1563    /// let error_code = error_msg.attribute::<ErrorCode>().unwrap();
1564    /// assert_eq!(error_code.code(), 420);
1565    /// assert!(error_msg.has_attribute(UnknownAttributes::TYPE));
1566    /// ```
1567    #[tracing::instrument(
1568        level = "trace",
1569        skip(msg, write),
1570        fields(
1571            msg.transaction = %msg.transaction_id(),
1572        )
1573    )]
1574    pub fn check_attribute_types<B: MessageWrite>(
1575        msg: &Message,
1576        supported: &[AttributeType],
1577        required_in_msg: &[AttributeType],
1578        write: B,
1579    ) -> Option<B> {
1580        // Attribute -> AttributeType
1581        let unsupported: Vec<AttributeType> = msg
1582            .iter_attributes()
1583            .map(|(_offset, a)| a.get_type())
1584            // attribute types that require comprehension but are not supported by the caller
1585            .filter(|at| at.comprehension_required() && !supported.contains(at))
1586            .collect();
1587        if !unsupported.is_empty() {
1588            warn!(
1589                "Message contains unknown comprehension required attributes {:?}, returning unknown attributes",
1590                unsupported
1591            );
1592            return Some(Message::unknown_attributes(msg, &unsupported, write));
1593        }
1594        let has_required_attribute_missing = required_in_msg
1595            .iter()
1596            // attribute types we need in the message -> failure -> Bad Request
1597            .any(|&at| {
1598                !msg.iter_attributes()
1599                    .map(|(_offset, a)| a.get_type())
1600                    .any(|a| a == at)
1601            });
1602        if has_required_attribute_missing {
1603            warn!("Message is missing required attributes, returning bad request");
1604            return Some(Message::bad_request(msg, write));
1605        }
1606        None
1607    }
1608
1609    /// Generate an error message with an [`ErrorCode`] attribute signalling 'Unknown Attribute'
1610    /// and an [`UnknownAttributes`] attribute containing the attributes that are unknown.
1611    ///
1612    /// # Examples
1613    ///
1614    /// ```
1615    /// # use stun_types::message::{Message, MessageWriteVec, MessageWrite, BINDING};
1616    /// # use stun_types::attribute::*;
1617    /// # use core::convert::TryInto;
1618    /// let msg = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1619    /// let msg = Message::from_bytes(&msg).unwrap();
1620    /// let error_msg = Message::unknown_attributes(&msg, &[Username::TYPE], MessageWriteVec::new()).finish();
1621    /// let error_msg = Message::from_bytes(&error_msg).unwrap();
1622    /// assert!(error_msg.is_response());
1623    /// assert!(error_msg.has_attribute(ErrorCode::TYPE));
1624    /// let error_code = error_msg.attribute::<ErrorCode>().unwrap();
1625    /// assert_eq!(error_code.code(), 420);
1626    /// let unknown = error_msg.attribute::<UnknownAttributes>().unwrap();
1627    /// assert!(unknown.has_attribute(Username::TYPE));
1628    /// ```
1629    pub fn unknown_attributes<B: MessageWrite>(
1630        src: &Message,
1631        attributes: &[AttributeType],
1632        write: B,
1633    ) -> B {
1634        let mut out = Message::builder_error(src, write);
1635        let software = Software::new("stun-types").unwrap();
1636        out.add_attribute(&software).unwrap();
1637        let error = ErrorCode::new(420, "Unknown Attributes").unwrap();
1638        out.add_attribute(&error).unwrap();
1639        let unknown = UnknownAttributes::new(attributes);
1640        if !attributes.is_empty() {
1641            out.add_attribute(&unknown).unwrap();
1642        }
1643        out
1644    }
1645
1646    /// Generate an error message with an [`ErrorCode`] attribute signalling a 'Bad Request'
1647    ///
1648    /// # Examples
1649    ///
1650    /// ```
1651    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1652    /// #     MessageWrite, BINDING};
1653    /// # use stun_types::attribute::*;
1654    /// # use core::convert::TryInto;
1655    /// let msg = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1656    /// let msg = Message::from_bytes(&msg).unwrap();
1657    /// let error_msg = Message::bad_request(&msg, MessageWriteVec::new()).finish();
1658    /// let error_msg = Message::from_bytes(&error_msg).unwrap();
1659    /// assert!(error_msg.has_attribute(ErrorCode::TYPE));
1660    /// let error_code =  error_msg.attribute::<ErrorCode>().unwrap();
1661    /// assert_eq!(error_code.code(), 400);
1662    /// ```
1663    pub fn bad_request<B: MessageWrite>(src: &Message, write: B) -> B {
1664        let mut out = Message::builder_error(src, write);
1665        let software = Software::new("stun-types").unwrap();
1666        out.add_attribute(&software).unwrap();
1667        let error = ErrorCode::new(400, "Bad Request").unwrap();
1668        out.add_attribute(&error).unwrap();
1669        out
1670    }
1671
1672    /// Whether this message contains an attribute of the specified type.
1673    ///
1674    /// # Examples
1675    ///
1676    /// ```
1677    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1678    /// #     MessageWrite, MessageWriteExt, BINDING};
1679    /// # use stun_types::attribute::{Software, Attribute, AttributeStaticType};
1680    /// let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
1681    /// let attr = Software::new("stun-types").unwrap();
1682    /// assert!(msg.add_attribute(&attr).is_ok());
1683    /// let msg = msg.finish();
1684    /// let msg = Message::from_bytes(&msg).unwrap();
1685    /// assert!(msg.has_attribute(Software::TYPE));
1686    /// ```
1687    pub fn has_attribute(&self, atype: AttributeType) -> bool {
1688        self.iter_attributes()
1689            .any(|(_offset, attr)| attr.get_type() == atype)
1690    }
1691
1692    /// Returns the underlying slice.
1693    pub fn as_bytes(&self) -> &[u8] {
1694        self.data
1695    }
1696}
1697impl<'a> TryFrom<&'a [u8]> for Message<'a> {
1698    type Error = StunParseError;
1699
1700    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
1701        Message::from_bytes(value)
1702    }
1703}
1704
1705#[derive(Debug)]
1706struct MessageRawAttributesIter<'a> {
1707    data: &'a [u8],
1708    data_i: usize,
1709}
1710
1711impl<'a> MessageRawAttributesIter<'a> {
1712    fn new(data: &'a [u8]) -> Self {
1713        Self {
1714            data,
1715            data_i: MessageHeader::LENGTH,
1716        }
1717    }
1718}
1719
1720impl<'a> Iterator for MessageRawAttributesIter<'a> {
1721    type Item = Result<(usize, RawAttribute<'a>), StunParseError>;
1722
1723    fn next(&mut self) -> Option<Self::Item> {
1724        if self.data_i >= self.data.len() {
1725            return None;
1726        }
1727
1728        match RawAttribute::from_bytes(&self.data[self.data_i..]) {
1729            Ok(attr) => {
1730                let padded_len = attr.padded_len();
1731                self.data_i += padded_len;
1732                if self.data_i > self.data.len() {
1733                    warn!(
1734                        "attribute {} extends past the end of the data",
1735                        attr.get_type()
1736                    );
1737                    return Some(Err(StunParseError::Truncated {
1738                        expected: self.data_i,
1739                        actual: self.data.len(),
1740                    }));
1741                }
1742                Some(Ok((self.data_i - padded_len, attr)))
1743            }
1744            Err(e) => {
1745                let offset = self.data_i;
1746                self.data_i = self.data.len();
1747                let e = match e {
1748                    StunParseError::Truncated { expected, actual } => StunParseError::Truncated {
1749                        expected: expected + 4 + offset,
1750                        actual: actual + 4 + offset,
1751                    },
1752                    StunParseError::TooLarge { expected, actual } => StunParseError::TooLarge {
1753                        expected: expected + 4 + offset,
1754                        actual: actual + 4 + offset,
1755                    },
1756                    e => e,
1757                };
1758                Some(Err(e))
1759            }
1760        }
1761    }
1762}
1763
1764#[doc(hidden)]
1765#[derive(Debug)]
1766pub struct MessageAttributesIter<'a> {
1767    header_parsed: bool,
1768    inner: MessageRawAttributesIter<'a>,
1769    last_attr_type: AttributeType,
1770    seen_message_integrity: bool,
1771}
1772
1773impl<'a> MessageAttributesIter<'a> {
1774    /// Construct an Iterator over the attributes of a [`Message`].
1775    ///
1776    /// The provided data is the entirety of the message data.
1777    pub fn new(data: &'a [u8]) -> Self {
1778        Self {
1779            header_parsed: false,
1780            inner: MessageRawAttributesIter::new(data),
1781            seen_message_integrity: false,
1782            last_attr_type: AttributeType::new(0),
1783        }
1784    }
1785}
1786
1787impl<'a> Iterator for MessageAttributesIter<'a> {
1788    type Item = (usize, RawAttribute<'a>);
1789
1790    fn next(&mut self) -> Option<Self::Item> {
1791        // nothing further to parse after Fingerprint
1792        if self.last_attr_type == Fingerprint::TYPE {
1793            return None;
1794        }
1795
1796        if !self.header_parsed {
1797            let Ok(hdr) = MessageHeader::from_bytes(self.inner.data) else {
1798                self.last_attr_type = Fingerprint::TYPE;
1799                return None;
1800            };
1801            if hdr.data_length() as usize + MessageHeader::LENGTH > self.inner.data.len() {
1802                self.last_attr_type = Fingerprint::TYPE;
1803                return None;
1804            }
1805            self.header_parsed = true;
1806        }
1807
1808        let (offset, attr) = self.inner.next()?.ok()?;
1809        let attr_type = attr.get_type();
1810        if self.seen_message_integrity {
1811            if self.last_attr_type != Fingerprint::TYPE && attr_type == Fingerprint::TYPE {
1812                self.last_attr_type = attr_type;
1813                return Some((offset, attr));
1814            }
1815            if self.last_attr_type == MessageIntegrity::TYPE
1816                && attr_type == MessageIntegritySha256::TYPE
1817            {
1818                self.last_attr_type = attr_type;
1819                return Some((offset, attr));
1820            }
1821            self.last_attr_type = Fingerprint::TYPE;
1822            return None;
1823        }
1824        if attr.get_type() == MessageIntegrity::TYPE
1825            || attr.get_type() == MessageIntegritySha256::TYPE
1826            || attr.get_type() == Fingerprint::TYPE
1827        {
1828            self.seen_message_integrity = true;
1829        }
1830        self.last_attr_type = attr.get_type();
1831
1832        Some((offset, attr))
1833    }
1834}
1835
1836#[allow(clippy::len_without_is_empty)]
1837/// Trait for implementing a writer for [`Message`]s.
1838pub trait MessageWrite {
1839    /// The output of this [`MessageWrite`]
1840    type Output;
1841    /// Return the maximum size of the output.  If the output data is not bound to a fixed size,
1842    /// `None` should be returned.
1843    fn max_size(&self) -> Option<usize> {
1844        None
1845    }
1846
1847    /// A mutable reference to the contained data.
1848    fn mut_data(&mut self) -> &mut [u8];
1849    /// A reference to the contained data.
1850    fn data(&self) -> &[u8];
1851    /// The length of the currently written data.
1852    fn len(&self) -> usize;
1853    /// Append the provided data to the end of the output.
1854    fn push_data(&mut self, data: &[u8]);
1855    /// Write an attribute to the end of the Message.
1856    fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite);
1857
1858    /// Return whether this [`MessageWrite`] contains a particular attribute.
1859    fn has_attribute(&self, atype: AttributeType) -> bool;
1860
1861    /// Return whether this [`MessageWrite`] contains any of the provided attributes and
1862    /// returns the attribute found.
1863    fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType>;
1864
1865    /// Finishes and returns the built Message.
1866    fn finish(self) -> Self::Output;
1867}
1868
1869/// Extension trait for [`MessageWrite`] providing helper functions.
1870pub trait MessageWriteExt: MessageWrite {
1871    /// Retrieve the [`MessageClass`] of a [`Message`]
1872    ///
1873    /// # Examples
1874    ///
1875    /// ```
1876    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1877    /// #     MessageWrite, BINDING};
1878    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1879    /// let message = Message::from_bytes(&message).unwrap();
1880    /// assert_eq!(message.class(), MessageClass::Request);
1881    /// ```
1882    fn get_type(&self) -> MessageType {
1883        MessageType::from_bytes(self.data()).unwrap()
1884    }
1885
1886    /// Retrieve the [`MessageClass`] of a [`Message`]
1887    ///
1888    /// # Examples
1889    ///
1890    /// ```
1891    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1892    /// #     MessageWrite, BINDING};
1893    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1894    /// let message = Message::from_bytes(&message).unwrap();
1895    /// assert_eq!(message.class(), MessageClass::Request);
1896    /// ```
1897    fn class(&self) -> MessageClass {
1898        self.get_type().class()
1899    }
1900
1901    /// Returns whether the [`Message`] is of the specified [`MessageClass`]
1902    ///
1903    /// # Examples
1904    ///
1905    /// ```
1906    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1907    /// #     MessageWrite, BINDING};
1908    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1909    /// let message = Message::from_bytes(&message).unwrap();
1910    /// assert!(message.has_class(MessageClass::Request));
1911    /// ```
1912    fn has_class(&self, cls: MessageClass) -> bool {
1913        self.class() == cls
1914    }
1915
1916    /// Returns whether the [`Message`] is a response
1917    ///
1918    /// This means that the [`Message`] has a class of either success or error
1919    ///
1920    /// # Examples
1921    ///
1922    /// ```
1923    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1924    /// #     MessageWrite, BINDING};
1925    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1926    /// let message = Message::from_bytes(&message).unwrap();
1927    /// assert_eq!(message.is_response(), false);
1928    ///
1929    /// let error = Message::builder_error(&message, MessageWriteVec::new()).finish();
1930    /// let error = Message::from_bytes(&error).unwrap();
1931    /// assert_eq!(error.is_response(), true);
1932    ///
1933    /// let success = Message::builder_success(&message, MessageWriteVec::new()).finish();
1934    /// let success = Message::from_bytes(&success).unwrap();
1935    /// assert_eq!(success.is_response(), true);
1936    /// ```
1937    fn is_response(&self) -> bool {
1938        self.class().is_response()
1939    }
1940
1941    /// Retrieves the method of the [`Message`]
1942    ///
1943    /// # Examples
1944    ///
1945    /// ```
1946    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1947    /// #     MessageWrite, BINDING};
1948    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1949    /// let message = Message::from_bytes(&message).unwrap();
1950    /// assert_eq!(message.method(), BINDING);
1951    /// ```
1952    fn method(&self) -> Method {
1953        self.get_type().method()
1954    }
1955
1956    /// Returns whether the [`Message`] is of the specified method
1957    ///
1958    /// # Examples
1959    ///
1960    /// ```
1961    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1962    /// #     Method, MessageWrite, BINDING};
1963    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1964    /// let message = Message::from_bytes(&message).unwrap();
1965    /// assert_eq!(message.has_method(BINDING), true);
1966    /// assert_eq!(message.has_method(Method::new(0)), false);
1967    /// ```
1968    fn has_method(&self, method: Method) -> bool {
1969        self.method() == method
1970    }
1971
1972    /// Retrieves the 96-bit transaction ID of the [`Message`]
1973    ///
1974    /// # Examples
1975    ///
1976    /// ```
1977    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1978    /// #     MessageWrite, BINDING, TransactionId};
1979    /// let mtype = MessageType::from_class_method(MessageClass::Request, BINDING);
1980    /// let transaction_id = TransactionId::generate();
1981    /// let message = Message::builder(mtype, transaction_id, MessageWriteVec::new()).finish();
1982    /// let message = Message::from_bytes(&message).unwrap();
1983    /// assert_eq!(message.transaction_id(), transaction_id);
1984    /// ```
1985    fn transaction_id(&self) -> TransactionId {
1986        BigEndian::read_u128(&self.data()[4..]).into()
1987    }
1988
1989    /// Adds MESSAGE_INTEGRITY attribute to a [`Message`] using the provided credentials
1990    ///
1991    /// # Errors
1992    ///
1993    /// - If a [`MessageIntegrity`] attribute is already present
1994    /// - If a [`MessageIntegritySha256`] attribute is already present
1995    /// - If a [`Fingerprint`] attribute is already present
1996    ///
1997    /// # Examples
1998    ///
1999    /// ```
2000    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2001    /// #     MessageWrite, MessageWriteExt, BINDING, MessageIntegrityCredentials,
2002    /// #     ShortTermCredentials, IntegrityAlgorithm, StunWriteError};
2003    /// # use stun_types::attribute::{Attribute, AttributeStaticType, MessageIntegrity,
2004    /// #     MessageIntegritySha256};
2005    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
2006    /// let credentials = ShortTermCredentials::new("pass".to_owned()).into();
2007    /// assert!(message.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1).is_ok());
2008    ///
2009    /// // duplicate MessageIntegrity is an error
2010    /// assert!(matches!(
2011    ///     message.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2012    ///     Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE)),
2013    /// ));
2014    ///
2015    /// // both MessageIntegrity, and MessageIntegritySha256 are allowed, however Sha256 must be
2016    /// // after Sha1
2017    /// assert!(message.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256).is_ok());
2018    ///
2019    /// let data = message.finish();
2020    /// let message = Message::from_bytes(&data).unwrap();
2021    /// assert!(message.validate_integrity(&credentials).is_ok());
2022    /// ```
2023    fn add_message_integrity(
2024        &mut self,
2025        credentials: &MessageIntegrityCredentials,
2026        algorithm: IntegrityAlgorithm,
2027    ) -> Result<(), StunWriteError> {
2028        let key = credentials.make_key();
2029        self.add_message_integrity_with_key(&key, algorithm)
2030    }
2031
2032    /// Adds MESSAGE_INTEGRITY attribute to a [`Message`] using the provided credential key.
2033    #[tracing::instrument(
2034        name = "message_add_integrity_with_key",
2035        level = "trace",
2036        err,
2037        skip(self),
2038        fields(
2039            msg.transaction = %self.transaction_id(),
2040        )
2041    )]
2042    fn add_message_integrity_with_key(
2043        &mut self,
2044        key: &IntegrityKey,
2045        algorithm: IntegrityAlgorithm,
2046    ) -> Result<(), StunWriteError> {
2047        let mut atypes = [AttributeType::new(0); 3];
2048        let mut i = 0;
2049        atypes[i] = match algorithm {
2050            IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
2051            IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
2052        };
2053        i += 1;
2054        if algorithm == IntegrityAlgorithm::Sha1 {
2055            atypes[i] = MessageIntegritySha256::TYPE;
2056            i += 1;
2057        }
2058        atypes[i] = Fingerprint::TYPE;
2059        i += 1;
2060
2061        match self.has_any_attribute(&atypes[..i]) {
2062            // can't validly add generic attributes after message integrity or fingerprint
2063            Some(MessageIntegrity::TYPE) => {
2064                return Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2065            }
2066            Some(MessageIntegritySha256::TYPE) => {
2067                return Err(StunWriteError::AttributeExists(
2068                    MessageIntegritySha256::TYPE,
2069                ));
2070            }
2071            Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2072            _ => (),
2073        }
2074        match algorithm {
2075            IntegrityAlgorithm::Sha1 => {
2076                check_attribute_can_fit(self, &MessageIntegrity::new([0; 20]))?
2077            }
2078            IntegrityAlgorithm::Sha256 => {
2079                check_attribute_can_fit(self, &MessageIntegritySha256::new(&[0; 32]).unwrap())?
2080            }
2081        };
2082
2083        add_message_integrity_unchecked(self, key, algorithm);
2084
2085        Ok(())
2086    }
2087
2088    /// Adds [`Fingerprint`] attribute to a [`Message`]
2089    ///
2090    /// # Errors
2091    ///
2092    /// - If a [`Fingerprint`] attribute is already present
2093    ///
2094    /// # Examples
2095    ///
2096    /// ```
2097    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2098    /// #     MessageWriteExt, BINDING};
2099    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
2100    /// assert!(message.add_fingerprint().is_ok());
2101    ///
2102    /// // duplicate FINGERPRINT is an error
2103    /// assert!(message.add_fingerprint().is_err());
2104    /// ```
2105    #[tracing::instrument(
2106        name = "message_add_fingerprint",
2107        level = "trace",
2108        skip(self),
2109        fields(
2110            msg.transaction = %self.transaction_id(),
2111        )
2112    )]
2113    fn add_fingerprint(&mut self) -> Result<(), StunWriteError> {
2114        if self.has_attribute(Fingerprint::TYPE) {
2115            return Err(StunWriteError::AttributeExists(Fingerprint::TYPE));
2116        }
2117
2118        check_attribute_can_fit(self, &Fingerprint::new([0; 4]))?;
2119        add_fingerprint_unchecked(self);
2120
2121        Ok(())
2122    }
2123
2124    /// Add a `Attribute` to this `Message`.  Only one `AttributeType` can be added for each
2125    /// `Attribute.  Attempting to add multiple `Atribute`s of the same `AttributeType` will fail.
2126    ///
2127    /// # Errors
2128    ///
2129    /// - If the attribute already exists within the message
2130    /// - If attempting to add attributes when [`MessageIntegrity`], [`MessageIntegritySha256`] or
2131    /// [`Fingerprint`] atributes already exist.
2132    ///
2133    /// # Panics
2134    ///
2135    /// - if a [`MessageIntegrity`] or [`MessageIntegritySha256`] attribute is attempted to be added.  Use
2136    /// `Message::add_message_integrity` instead.
2137    /// - if a [`Fingerprint`] attribute is attempted to be added. Use
2138    /// `Message::add_fingerprint` instead.
2139    ///
2140    /// # Examples
2141    ///
2142    /// Add an `Attribute`
2143    ///
2144    /// ```
2145    /// # use stun_types::attribute::RawAttribute;
2146    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2147    /// #     MessageWriteExt, BINDING};
2148    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
2149    /// let attr = RawAttribute::new(1.into(), &[3]);
2150    /// assert!(message.add_attribute(&attr).is_ok());
2151    /// // Duplicate attributes are allowed, however semantically, the protocol may not allow them.
2152    /// assert!(message.add_attribute(&attr).is_ok());
2153    /// ```
2154    #[tracing::instrument(
2155        name = "message_add_attribute",
2156        level = "trace",
2157        err,
2158        skip(self, attr),
2159        fields(
2160            msg.transaction = %self.transaction_id(),
2161        )
2162    )]
2163    fn add_attribute(&mut self, attr: &dyn AttributeWrite) -> Result<(), StunWriteError> {
2164        let ty = attr.get_type();
2165        match ty {
2166            MessageIntegrity::TYPE => {
2167                panic!("Cannot write MessageIntegrity with `add_attribute`.  Use add_message_integrity() instead");
2168            }
2169            MessageIntegritySha256::TYPE => {
2170                panic!("Cannot write MessageIntegritySha256 with `add_attribute`.  Use add_message_integrity() instead");
2171            }
2172            Fingerprint::TYPE => {
2173                panic!(
2174                    "Cannot write Fingerprint with `add_attribute`.  Use add_fingerprint() instead"
2175                );
2176            }
2177            _ => (),
2178        }
2179        match self.has_any_attribute(&[
2180            MessageIntegrity::TYPE,
2181            MessageIntegritySha256::TYPE,
2182            Fingerprint::TYPE,
2183        ]) {
2184            // can't validly add generic attributes after message integrity or fingerprint
2185            Some(MessageIntegrity::TYPE) => return Err(StunWriteError::MessageIntegrityExists),
2186            Some(MessageIntegritySha256::TYPE) => {
2187                return Err(StunWriteError::MessageIntegrityExists)
2188            }
2189            Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2190            _ => (),
2191        }
2192        check_attribute_can_fit(self, attr)?;
2193        self.push_attribute_unchecked(attr);
2194        Ok(())
2195    }
2196}
2197
2198impl<T: MessageWrite> MessageWriteExt for T {}
2199
2200/// A [`MessageWrite`] implementation that writes into a `Vec<u8>`.
2201#[derive(Debug, Default)]
2202pub struct MessageWriteVec {
2203    output: Vec<u8>,
2204    attributes: smallvec::SmallVec<[AttributeType; 16]>,
2205}
2206
2207impl MessageWriteVec {
2208    /// Construct a new [`MessageWriteVec`].
2209    pub fn new() -> Self {
2210        Self::default()
2211    }
2212
2213    /// Allocate a new [`MessageWriteVec`] with a preallocated capacity
2214    pub fn with_capacity(capacity: usize) -> Self {
2215        Self {
2216            output: Vec::with_capacity(capacity),
2217            attributes: Default::default(),
2218        }
2219    }
2220}
2221
2222impl core::ops::Deref for MessageWriteVec {
2223    type Target = Vec<u8>;
2224    fn deref(&self) -> &Self::Target {
2225        &self.output
2226    }
2227}
2228
2229impl core::ops::DerefMut for MessageWriteVec {
2230    fn deref_mut(&mut self) -> &mut Self::Target {
2231        &mut self.output
2232    }
2233}
2234
2235impl MessageWrite for MessageWriteVec {
2236    type Output = Vec<u8>;
2237
2238    fn mut_data(&mut self) -> &mut [u8] {
2239        &mut self.output
2240    }
2241
2242    fn data(&self) -> &[u8] {
2243        &self.output
2244    }
2245
2246    fn len(&self) -> usize {
2247        self.output.len()
2248    }
2249
2250    fn push_data(&mut self, data: &[u8]) {
2251        self.output.extend(data)
2252    }
2253
2254    fn finish(self) -> Self::Output {
2255        self.output
2256    }
2257
2258    fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2259        let offset = self.output.len();
2260        let padded_len = attr.padded_len();
2261        let expected = offset + padded_len;
2262        BigEndian::write_u16(
2263            &mut self.output[2..4],
2264            (expected - MessageHeader::LENGTH) as u16,
2265        );
2266        self.output.resize(expected, 0);
2267        attr.write_into_unchecked(&mut self.output[offset..]);
2268        self.attributes.push(attr.get_type());
2269    }
2270
2271    fn has_attribute(&self, atype: AttributeType) -> bool {
2272        self.attributes.contains(&atype)
2273    }
2274
2275    fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2276        self.attributes
2277            .iter()
2278            .find(|&typ| atypes.contains(typ))
2279            .cloned()
2280    }
2281}
2282
2283/// A [`MessageWrite`] implementation that writes into a mutable slice.
2284#[derive(Debug, Default)]
2285pub struct MessageWriteMutSlice<'a> {
2286    output: &'a mut [u8],
2287    offset: usize,
2288    attributes: smallvec::SmallVec<[AttributeType; 16]>,
2289}
2290
2291impl<'a> MessageWriteMutSlice<'a> {
2292    /// Construct a new [`MessageWriteMutSlice`] using the provided mutbale slice.
2293    pub fn new(data: &'a mut [u8]) -> Self {
2294        Self {
2295            output: data,
2296            offset: 0,
2297            attributes: Default::default(),
2298        }
2299    }
2300}
2301
2302impl core::ops::Deref for MessageWriteMutSlice<'_> {
2303    type Target = [u8];
2304    fn deref(&self) -> &Self::Target {
2305        self.output
2306    }
2307}
2308
2309impl core::ops::DerefMut for MessageWriteMutSlice<'_> {
2310    fn deref_mut(&mut self) -> &mut Self::Target {
2311        self.output
2312    }
2313}
2314
2315impl<'a> MessageWrite for MessageWriteMutSlice<'a> {
2316    type Output = usize;
2317
2318    fn max_size(&self) -> Option<usize> {
2319        Some(self.output.len())
2320    }
2321
2322    fn mut_data(&mut self) -> &mut [u8] {
2323        &mut self.output[..self.offset]
2324    }
2325
2326    fn data(&self) -> &[u8] {
2327        &self.output[..self.offset]
2328    }
2329
2330    fn len(&self) -> usize {
2331        self.offset
2332    }
2333
2334    fn push_data(&mut self, data: &[u8]) {
2335        let len = data.len();
2336        self.output[self.offset..self.offset + len].copy_from_slice(data);
2337        self.offset += len;
2338    }
2339
2340    fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2341        let padded_len = attr.padded_len();
2342        let expected = self.offset + padded_len;
2343        BigEndian::write_u16(
2344            &mut self.output[2..4],
2345            (expected - MessageHeader::LENGTH) as u16,
2346        );
2347        self.attributes.push(attr.get_type());
2348        attr.write_into(&mut self.output[self.offset..self.offset + padded_len])
2349            .unwrap();
2350        self.offset += padded_len;
2351    }
2352
2353    fn finish(self) -> Self::Output {
2354        self.offset
2355    }
2356
2357    fn has_attribute(&self, atype: AttributeType) -> bool {
2358        self.attributes.contains(&atype)
2359    }
2360
2361    fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2362        self.attributes
2363            .iter()
2364            .find(|&typ| atypes.contains(typ))
2365            .cloned()
2366    }
2367}
2368
2369fn check_attribute_can_fit<O, T: MessageWrite<Output = O> + ?Sized>(
2370    this: &mut T,
2371    attr: &dyn AttributeWrite,
2372) -> Result<usize, StunWriteError> {
2373    let len = attr.padded_len();
2374    let out_data = this.data();
2375    if out_data.len() < MessageHeader::LENGTH {
2376        return Err(StunWriteError::TooSmall {
2377            expected: 20,
2378            actual: out_data.len(),
2379        });
2380    }
2381    let expected = BigEndian::read_u16(&out_data[2..4]) as usize + MessageHeader::LENGTH + len;
2382    if let Some(max) = this.max_size() {
2383        if max < expected {
2384            return Err(StunWriteError::TooSmall {
2385                expected,
2386                actual: max,
2387            });
2388        }
2389    }
2390    Ok(expected)
2391}
2392
2393fn add_message_integrity_unchecked<O, T: MessageWrite<Output = O> + ?Sized>(
2394    this: &mut T,
2395    key: &IntegrityKey,
2396    algorithm: IntegrityAlgorithm,
2397) {
2398    // message-integrity is computed using all the data up to (exclusive of) the
2399    // MESSAGE-INTEGRITY but with a length field including the MESSAGE-INTEGRITY attribute...
2400    match algorithm {
2401        IntegrityAlgorithm::Sha1 => {
2402            this.push_attribute_unchecked(&MessageIntegrity::new([0; 20]));
2403            let len = this.len();
2404            let data = this.mut_data();
2405            let integrity = MessageIntegrity::compute(&[&data[..len - 24]], key).unwrap();
2406            data[len - 20..].copy_from_slice(&integrity);
2407        }
2408        IntegrityAlgorithm::Sha256 => {
2409            this.push_attribute_unchecked(&MessageIntegritySha256::new(&[0; 32]).unwrap());
2410            let len = this.len();
2411            let data = this.mut_data();
2412            let integrity = MessageIntegritySha256::compute(&[&data[..len - 36]], key).unwrap();
2413            data[len - 32..].copy_from_slice(&integrity);
2414        }
2415    }
2416}
2417
2418fn add_fingerprint_unchecked<O, T: MessageWrite<Output = O> + ?Sized>(this: &mut T) {
2419    // fingerprint is computed using all the data up to (exclusive of) the FINGERPRINT
2420    // but with a length field including the FINGERPRINT attribute...
2421    this.push_attribute_unchecked(&Fingerprint::new([0; 4]));
2422    let len = this.len();
2423    let data = this.mut_data();
2424    let fingerprint = Fingerprint::compute(&[&data[..len - 8]]);
2425    let fingerprint = Fingerprint::new(fingerprint);
2426    fingerprint.write_into(&mut data[len - 8..]).unwrap();
2427}
2428
2429#[cfg(test)]
2430mod tests {
2431    use alloc::borrow::ToOwned;
2432    use tracing::error;
2433
2434    use super::*;
2435
2436    #[test]
2437    #[should_panic(expected = "Method value is out of range")]
2438    fn method_value_out_of_range() {
2439        let _log = crate::tests::test_init_log();
2440        Method::new(0xf000);
2441    }
2442
2443    #[test]
2444    #[cfg(feature = "std")]
2445    fn method_name() {
2446        let _log = crate::tests::test_init_log();
2447        assert_eq!(BINDING.name(), "BINDING");
2448        let method = Method::new(0x111);
2449        method.add_name("SOME-NAME");
2450        assert_eq!(method.name(), "SOME-NAME");
2451        assert_eq!(Method::new(0x112).name(), "unknown");
2452    }
2453
2454    #[test]
2455    fn msg_type_roundtrip() {
2456        let _log = crate::tests::test_init_log();
2457        /* validate that all methods/classes survive a roundtrip */
2458        for m in 0..0xfff {
2459            let m = Method::new(m);
2460            let classes = vec![
2461                MessageClass::Request,
2462                MessageClass::Indication,
2463                MessageClass::Success,
2464                MessageClass::Error,
2465            ];
2466            for c in classes {
2467                let mtype = MessageType::from_class_method(c, m);
2468                trace!("{mtype}");
2469                assert_eq!(mtype.class(), c);
2470                assert_eq!(mtype.method(), m);
2471                let bytes = mtype.to_bytes();
2472                let ptype = MessageType::from_bytes(&bytes).unwrap();
2473                assert_eq!(mtype, ptype);
2474            }
2475        }
2476    }
2477
2478    #[test]
2479    fn msg_type_not_stun() {
2480        assert!(matches!(
2481            MessageType::from_bytes(&[0xc0, 0x00]),
2482            Err(StunParseError::NotStun)
2483        ));
2484    }
2485
2486    #[test]
2487    fn msg_roundtrip() {
2488        let _log = crate::tests::test_init_log();
2489        /* validate that all methods/classes survive a roundtrip */
2490        for m in (0x009..0x4ff).step_by(0x123) {
2491            let m = Method::new(m);
2492            let classes = vec![
2493                MessageClass::Request,
2494                MessageClass::Indication,
2495                MessageClass::Success,
2496                MessageClass::Error,
2497            ];
2498            for c in classes {
2499                let mtype = MessageType::from_class_method(c, m);
2500                for tid in (0x18..0xff_ffff_ffff_ffff_ffff).step_by(0xfedc_ba98_7654_3210) {
2501                    let mut msg = Message::builder(mtype, tid.into(), MessageWriteVec::default());
2502                    let attr = RawAttribute::new(1.into(), &[3]);
2503                    assert!(msg.add_attribute(&attr).is_ok());
2504                    let data = msg.finish();
2505
2506                    let msg = Message::from_bytes(&data).unwrap();
2507                    let msg_attr = msg.raw_attribute(1.into()).unwrap();
2508                    assert_eq!(msg_attr, attr);
2509                    assert_eq!(msg.get_type(), mtype);
2510                    assert_eq!(msg.transaction_id(), tid.into());
2511                }
2512            }
2513        }
2514    }
2515
2516    #[test]
2517    fn unknown_attributes() {
2518        let _log = crate::tests::test_init_log();
2519        let src = Message::builder_request(BINDING, MessageWriteVec::default()).finish();
2520        let src = Message::from_bytes(&src).unwrap();
2521        let msg =
2522            Message::unknown_attributes(&src, &[Software::TYPE], MessageWriteVec::new()).finish();
2523        let msg = Message::from_bytes(&msg).unwrap();
2524        assert_eq!(msg.transaction_id(), src.transaction_id());
2525        assert_eq!(msg.class(), MessageClass::Error);
2526        assert_eq!(msg.method(), src.method());
2527        let err = msg.attribute::<ErrorCode>().unwrap();
2528        assert_eq!(err.code(), 420);
2529        let unknown_attrs = msg.attribute::<UnknownAttributes>().unwrap();
2530        assert!(unknown_attrs.has_attribute(Software::TYPE));
2531    }
2532
2533    #[test]
2534    fn bad_request() {
2535        let _log = crate::tests::test_init_log();
2536        let src = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2537        let src = Message::from_bytes(&src).unwrap();
2538        let msg = Message::bad_request(&src, MessageWriteVec::new()).finish();
2539        let msg = Message::from_bytes(&msg).unwrap();
2540        assert_eq!(msg.transaction_id(), src.transaction_id());
2541        assert_eq!(msg.class(), MessageClass::Error);
2542        assert_eq!(msg.method(), src.method());
2543        let err = msg.attribute::<ErrorCode>().unwrap();
2544        assert_eq!(err.code(), 400);
2545    }
2546
2547    #[test]
2548    fn fingerprint() {
2549        let _log = crate::tests::test_init_log();
2550        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2551        let software = Software::new("s").unwrap();
2552        msg.add_attribute(&software).unwrap();
2553        msg.add_fingerprint().unwrap();
2554        let bytes = msg.finish();
2555        // validates the fingerprint of the data when available
2556        let new_msg = Message::from_bytes(&bytes).unwrap();
2557        let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2558        assert_eq!(software.software(), "s");
2559        assert_eq!(offset, 20);
2560        let (offset, _new_fingerprint) = new_msg.attribute_and_offset::<Fingerprint>().unwrap();
2561        assert_eq!(offset, 28);
2562    }
2563
2564    #[test]
2565    fn integrity() {
2566        let _log = crate::tests::test_init_log();
2567        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2568            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2569            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2570            let software = Software::new("s").unwrap();
2571            msg.add_attribute(&software).unwrap();
2572            msg.add_message_integrity(&credentials, algorithm).unwrap();
2573            let bytes = msg.finish();
2574            // validates the fingerprint of the data when available
2575            let new_msg = Message::from_bytes(&bytes).unwrap();
2576            new_msg.validate_integrity(&credentials).unwrap();
2577            let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2578            assert_eq!(software.software(), "s");
2579            assert_eq!(offset, 20);
2580        }
2581    }
2582
2583    #[test]
2584    fn write_into_short_destination() {
2585        let _log = crate::tests::test_init_log();
2586        const LEN: usize = MessageHeader::LENGTH + 8;
2587        let mut data = [0; LEN - 1];
2588        let mut msg = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
2589        let software = Software::new("s").unwrap();
2590        assert!(
2591            matches!(msg.add_attribute(&software), Err(StunWriteError::TooSmall { expected, actual }) if expected == LEN && actual == LEN - 1)
2592        );
2593    }
2594
2595    #[test]
2596    fn add_duplicate_integrity() {
2597        let _log = crate::tests::test_init_log();
2598        let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2599        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2600        msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
2601            .unwrap();
2602        assert!(matches!(
2603            msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2604            Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2605        ));
2606        msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2607            .unwrap();
2608        assert!(matches!(
2609            msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256),
2610            Err(StunWriteError::AttributeExists(
2611                MessageIntegritySha256::TYPE
2612            ))
2613        ));
2614        let software = Software::new("s").unwrap();
2615        assert!(matches!(
2616            msg.add_attribute(&software),
2617            Err(StunWriteError::MessageIntegrityExists)
2618        ));
2619    }
2620
2621    #[test]
2622    fn add_sha1_integrity_after_sha256() {
2623        let _log = crate::tests::test_init_log();
2624        let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2625        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2626        msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2627            .unwrap();
2628        assert!(matches!(
2629            msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2630            Err(StunWriteError::AttributeExists(
2631                MessageIntegritySha256::TYPE
2632            ))
2633        ));
2634    }
2635
2636    #[test]
2637    fn add_attribute_after_integrity() {
2638        let _log = crate::tests::test_init_log();
2639        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2640            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2641            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2642            msg.add_message_integrity(&credentials, algorithm).unwrap();
2643            let software = Software::new("s").unwrap();
2644            assert!(matches!(
2645                msg.add_attribute(&software),
2646                Err(StunWriteError::MessageIntegrityExists)
2647            ));
2648        }
2649    }
2650
2651    #[test]
2652    fn add_raw_attribute_after_integrity() {
2653        let _log = crate::tests::test_init_log();
2654        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2655            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2656            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2657            msg.add_message_integrity(&credentials, algorithm).unwrap();
2658            let software = Software::new("s").unwrap();
2659            let raw = software.to_raw();
2660            assert!(matches!(
2661                msg.add_attribute(&raw),
2662                Err(StunWriteError::MessageIntegrityExists)
2663            ));
2664        }
2665    }
2666
2667    #[test]
2668    fn add_integrity_after_fingerprint() {
2669        let _log = crate::tests::test_init_log();
2670        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2671            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2672            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2673            msg.add_fingerprint().unwrap();
2674            assert!(matches!(
2675                msg.add_message_integrity(&credentials, algorithm),
2676                Err(StunWriteError::FingerprintExists)
2677            ));
2678        }
2679    }
2680
2681    #[test]
2682    fn duplicate_fingerprint() {
2683        let _log = crate::tests::test_init_log();
2684        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2685        msg.add_fingerprint().unwrap();
2686        assert!(matches!(
2687            msg.add_fingerprint(),
2688            Err(StunWriteError::AttributeExists(Fingerprint::TYPE))
2689        ));
2690    }
2691
2692    #[test]
2693    fn parse_invalid_fingerprint() {
2694        let _log = crate::tests::test_init_log();
2695        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2696        msg.add_fingerprint().unwrap();
2697        let mut bytes = msg.finish();
2698        bytes[24] = 0x80;
2699        bytes[25] = 0x80;
2700        bytes[26] = 0x80;
2701        bytes[27] = 0x80;
2702        assert!(matches!(
2703            Message::from_bytes(&bytes),
2704            Err(StunParseError::FingerprintMismatch)
2705        ));
2706    }
2707
2708    #[test]
2709    fn parse_wrong_magic() {
2710        let _log = crate::tests::test_init_log();
2711        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2712        msg.add_fingerprint().unwrap();
2713        let mut bytes = msg.finish();
2714        bytes[4] = 0x80;
2715        assert!(matches!(
2716            Message::from_bytes(&bytes),
2717            Err(StunParseError::NotStun)
2718        ));
2719    }
2720
2721    #[test]
2722    fn parse_attribute_after_integrity() {
2723        let _log = crate::tests::test_init_log();
2724        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2725            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2726            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2727            msg.add_message_integrity(&credentials, algorithm).unwrap();
2728            let mut bytes = msg.finish();
2729            let software = Software::new("s").unwrap();
2730            let software_bytes = RawAttribute::from(&software).to_bytes();
2731            let software_len = software_bytes.len();
2732            bytes.extend(software_bytes);
2733            bytes[3] += software_len as u8;
2734            let msg = Message::from_bytes(&bytes).unwrap();
2735            assert!(msg.raw_attribute(Software::TYPE).is_none());
2736        }
2737    }
2738
2739    #[test]
2740    fn parse_duplicate_integrity_after_integrity() {
2741        let _log = crate::tests::test_init_log();
2742        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2743            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2744            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2745            msg.add_message_integrity(&credentials, algorithm).unwrap();
2746            // duplicate integrity attribute. Don't do this in real code!
2747            add_message_integrity_unchecked(&mut msg, &credentials.make_key(), algorithm);
2748            let bytes = msg.finish();
2749            let integrity_type = match algorithm {
2750                IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
2751                IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
2752            };
2753            let msg = Message::from_bytes(&bytes).unwrap();
2754            msg.nth_raw_attribute(integrity_type, 0).unwrap();
2755            assert!(msg.nth_raw_attribute(integrity_type, 1).is_none());
2756        }
2757    }
2758
2759    #[test]
2760    fn parse_attribute_after_fingerprint() {
2761        let _log = crate::tests::test_init_log();
2762        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2763        msg.add_fingerprint().unwrap();
2764        let mut bytes = msg.finish();
2765        let software = Software::new("s").unwrap();
2766        let software_bytes = RawAttribute::from(&software).to_bytes();
2767        let software_len = software_bytes.len();
2768        bytes.extend(software_bytes);
2769        bytes[3] += software_len as u8;
2770        let msg = Message::from_bytes(&bytes).unwrap();
2771        assert!(msg.raw_attribute(Fingerprint::TYPE).is_some());
2772        assert!(msg.raw_attribute(Software::TYPE).is_none());
2773    }
2774
2775    #[test]
2776    fn parse_duplicate_fingerprint_after_fingerprint() {
2777        let _log = crate::tests::test_init_log();
2778        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2779        msg.add_fingerprint().unwrap();
2780        add_fingerprint_unchecked(&mut msg);
2781        let bytes = msg.finish();
2782        let msg = Message::from_bytes(&bytes).unwrap();
2783        assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 0).is_some());
2784        assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 1).is_none());
2785    }
2786
2787    #[test]
2788    fn add_attribute_after_fingerprint() {
2789        let _log = crate::tests::test_init_log();
2790        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2791        msg.add_fingerprint().unwrap();
2792        let software = Software::new("s").unwrap();
2793        assert!(matches!(
2794            msg.add_attribute(&software),
2795            Err(StunWriteError::FingerprintExists)
2796        ));
2797    }
2798
2799    #[test]
2800    fn add_raw_attribute_after_fingerprint() {
2801        let _log = crate::tests::test_init_log();
2802        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2803        msg.add_fingerprint().unwrap();
2804        let software = Software::new("s").unwrap();
2805        let raw = software.to_raw();
2806        assert!(matches!(
2807            msg.add_attribute(&raw),
2808            Err(StunWriteError::FingerprintExists)
2809        ));
2810    }
2811
2812    #[test]
2813    fn parse_truncated_message_header() {
2814        let _log = crate::tests::test_init_log();
2815        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2816        msg.add_fingerprint().unwrap();
2817        let bytes = msg.finish();
2818        assert!(matches!(
2819            Message::from_bytes(&bytes[..8]),
2820            Err(StunParseError::Truncated {
2821                expected: 20,
2822                actual: 8
2823            })
2824        ));
2825    }
2826
2827    #[test]
2828    fn parse_truncated_message() {
2829        let _log = crate::tests::test_init_log();
2830        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2831        msg.add_fingerprint().unwrap();
2832        let bytes = msg.finish();
2833        assert!(matches!(
2834            Message::from_bytes(&bytes[..24]),
2835            Err(StunParseError::Truncated {
2836                expected: 28,
2837                actual: 24
2838            })
2839        ));
2840    }
2841
2842    #[test]
2843    fn parse_truncated_message_attribute() {
2844        let _log = crate::tests::test_init_log();
2845        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2846        msg.add_fingerprint().unwrap();
2847        let mut bytes = msg.finish();
2848        // rewrite message header to support the truncated length, but not the attribute.
2849        bytes[3] = 4;
2850        assert!(matches!(
2851            Message::from_bytes(&bytes[..24]),
2852            Err(StunParseError::Truncated {
2853                expected: 28,
2854                actual: 24
2855            })
2856        ));
2857    }
2858
2859    #[test]
2860    fn parse_attribute_extends_past_message_end() {
2861        let _log = crate::tests::test_init_log();
2862        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2863        msg.add_attribute(&Software::new("a").unwrap()).unwrap();
2864        msg[23] += 1;
2865        let mut bytes = msg.finish();
2866        bytes[3] -= 1;
2867        error!("{bytes:x?}");
2868        error!("{:?}", Message::from_bytes(&bytes[..27]));
2869        assert!(matches!(
2870            Message::from_bytes(&bytes[..27]),
2871            Err(StunParseError::Truncated {
2872                expected: 28,
2873                actual: 27
2874            })
2875        ));
2876    }
2877
2878    #[test]
2879    fn valid_attributes() {
2880        let _log = crate::tests::test_init_log();
2881        let mut src = Message::builder_request(BINDING, MessageWriteVec::new());
2882        let username = Username::new("123").unwrap();
2883        src.add_attribute(&username).unwrap();
2884        let nonce = Nonce::new("nonce").unwrap();
2885        src.add_attribute(&nonce).unwrap();
2886        let src = src.finish();
2887        let src = Message::from_bytes(&src).unwrap();
2888
2889        // success case
2890        let res = Message::check_attribute_types(
2891            &src,
2892            &[Username::TYPE, Nonce::TYPE],
2893            &[Username::TYPE],
2894            MessageWriteVec::new(),
2895        );
2896        assert!(res.is_none());
2897
2898        // fingerprint required but not present
2899        let res = Message::check_attribute_types(
2900            &src,
2901            &[Username::TYPE, Nonce::TYPE],
2902            &[Fingerprint::TYPE],
2903            MessageWriteVec::new(),
2904        );
2905        assert!(res.is_some());
2906        let res = res.unwrap();
2907        let res = res.finish();
2908        let res = Message::from_bytes(&res).unwrap();
2909        assert!(res.has_class(MessageClass::Error));
2910        assert!(res.has_method(src.method()));
2911        let err = res.attribute::<ErrorCode>().unwrap();
2912        assert_eq!(err.code(), 400);
2913
2914        // nonce unsupported
2915        let res =
2916            Message::check_attribute_types(&src, &[Username::TYPE], &[], MessageWriteVec::new());
2917        assert!(res.is_some());
2918        let res = res.unwrap();
2919        let data = res.finish();
2920        let res = Message::from_bytes(&data).unwrap();
2921        assert!(res.has_class(MessageClass::Error));
2922        assert!(res.has_method(src.method()));
2923        let err = res.attribute::<ErrorCode>().unwrap();
2924        assert_eq!(err.code(), 420);
2925        let unknown = res.attribute::<UnknownAttributes>().unwrap();
2926        assert!(unknown.has_attribute(Nonce::TYPE));
2927    }
2928
2929    #[test]
2930    fn attributes_iter_with_short_data() {
2931        let _log = crate::tests::test_init_log();
2932        assert_eq!(
2933            MessageAttributesIter::new(&[0x0, 0x1, 0x2, 0x3, 0x4]).next(),
2934            None
2935        );
2936        assert_eq!(
2937            MessageAttributesIter::new(&[
2938                0x0, 0x1, 0x2, 0x3, 0x21, 0x12, 0xa4, 0x42, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
2939                0x10, 0x11, 0x12, 0x13, 0x14,
2940            ])
2941            .next(),
2942            None
2943        );
2944    }
2945
2946    #[test]
2947    fn attributes_iter_software_after_fingerprint_ignored() {
2948        let _log = crate::tests::test_init_log();
2949        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2950        msg.add_fingerprint().unwrap();
2951        let mut bytes = msg.finish();
2952        let software = Software::new("s").unwrap();
2953        let software_bytes = RawAttribute::from(&software).to_bytes();
2954        let software_len = software_bytes.len();
2955        bytes.extend(software_bytes);
2956        bytes[3] += software_len as u8;
2957        let mut it = MessageAttributesIter::new(&bytes);
2958        let (_offset, fingerprint) = it.next().unwrap();
2959        assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
2960        assert_eq!(it.next(), None);
2961    }
2962
2963    #[test]
2964    fn attributes_iter_message_integrities_fingerprint() {
2965        let _log = crate::tests::test_init_log();
2966        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2967        let credentials = ShortTermCredentials::new("pass".to_owned());
2968        msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha1)
2969            .unwrap();
2970        msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha256)
2971            .unwrap();
2972        msg.add_fingerprint().unwrap();
2973        let mut bytes = msg.finish();
2974        let software = Software::new("s").unwrap();
2975        let software_bytes = RawAttribute::from(&software).to_bytes();
2976        let software_len = software_bytes.len();
2977        bytes.extend(software_bytes);
2978        bytes[3] += software_len as u8;
2979        let mut it = MessageAttributesIter::new(&bytes);
2980        assert_eq!(it.next().unwrap().1.get_type(), MessageIntegrity::TYPE);
2981        assert_eq!(
2982            it.next().unwrap().1.get_type(),
2983            MessageIntegritySha256::TYPE
2984        );
2985        assert_eq!(it.next().unwrap().1.get_type(), Fingerprint::TYPE);
2986        assert_eq!(it.next(), None);
2987    }
2988
2989    #[test]
2990    fn attributes_iter_fingerprint_after_fingerprint_ignored() {
2991        let _log = crate::tests::test_init_log();
2992        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2993        msg.add_fingerprint().unwrap();
2994        let mut bytes = msg.finish();
2995        let fingerprint = Fingerprint::new([bytes[bytes.len() - 1].wrapping_sub(1); 4]);
2996        let fingerprint_bytes = RawAttribute::from(&fingerprint).to_bytes();
2997        let fingerprint_len = fingerprint_bytes.len();
2998        bytes.extend(fingerprint_bytes);
2999        bytes[3] += fingerprint_len as u8;
3000        let mut it = MessageAttributesIter::new(&bytes);
3001        let (_offset, fingerprint) = it.next().unwrap();
3002        assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
3003        assert_eq!(it.next(), None);
3004    }
3005
3006    #[test]
3007    fn write_vec_state() {
3008        let _log = crate::tests::test_init_log();
3009        let mut src = Message::builder_request(BINDING, MessageWriteVec::with_capacity(0x10));
3010        assert_eq!(src.len(), 20);
3011        assert_eq!(src[4], 0x21);
3012        let username = Username::new("123").unwrap();
3013        src.add_attribute(&username).unwrap();
3014        let nonce = Nonce::new("nonce").unwrap();
3015        src.add_attribute(&nonce).unwrap();
3016
3017        assert!(src.has_attribute(Username::TYPE));
3018        assert!(src.has_attribute(Nonce::TYPE));
3019        assert_eq!(
3020            src.has_any_attribute(&[Username::TYPE, Nonce::TYPE]),
3021            Some(Username::TYPE)
3022        );
3023        assert_eq!(
3024            src.has_any_attribute(&[Nonce::TYPE, Username::TYPE]),
3025            Some(Username::TYPE)
3026        );
3027        assert!(src.has_class(MessageClass::Request));
3028        assert!(!src.is_response());
3029        assert!(src.has_method(BINDING));
3030        assert!(!src.has_method(Method::new(0x111)));
3031    }
3032
3033    #[test]
3034    fn write_mut_slice_success() {
3035        let _log = crate::tests::test_init_log();
3036        let mut data = [0; 64];
3037        let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
3038        assert_eq!(src.len(), 20);
3039        assert_eq!(src[4], 0x21);
3040        let username = Username::new("123").unwrap();
3041        src.add_attribute(&username).unwrap();
3042        let nonce = Nonce::new("nonce").unwrap();
3043        src.add_attribute(&nonce).unwrap();
3044        assert!(src.has_attribute(Username::TYPE));
3045        assert!(!src.has_attribute(Software::TYPE));
3046        assert_eq!(src.finish(), 40);
3047        let msg = Message::from_bytes(&data[..40]).unwrap();
3048        let u2 = msg.attribute::<Username>().unwrap();
3049        assert_eq!(u2.username(), "123");
3050        let n2 = msg.attribute::<Nonce>().unwrap();
3051        assert_eq!(n2.nonce(), "nonce");
3052    }
3053
3054    #[test]
3055    fn write_mut_slice_too_short() {
3056        let _log = crate::tests::test_init_log();
3057        let mut data = [0; 20];
3058        let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
3059        assert!(matches!(
3060            src.add_attribute(&Username::new("123").unwrap()),
3061            Err(StunWriteError::TooSmall {
3062                expected: 28,
3063                actual: 20
3064            })
3065        ));
3066    }
3067
3068    #[test]
3069    #[should_panic(expected = "created from a non-request message")]
3070    fn builder_success_panic() {
3071        let _log = crate::tests::test_init_log();
3072        let msg = Message::builder(
3073            MessageType::from_class_method(MessageClass::Indication, BINDING),
3074            TransactionId::generate(),
3075            MessageWriteVec::new(),
3076        )
3077        .finish();
3078        let msg = Message::from_bytes(&msg).unwrap();
3079        let _builder = Message::builder_success(&msg, MessageWriteVec::new());
3080    }
3081
3082    #[test]
3083    #[should_panic(expected = "created from a non-request message")]
3084    fn builder_error_panic() {
3085        let _log = crate::tests::test_init_log();
3086        let msg = Message::builder(
3087            MessageType::from_class_method(MessageClass::Indication, BINDING),
3088            TransactionId::generate(),
3089            MessageWriteVec::new(),
3090        )
3091        .finish();
3092        let msg = Message::from_bytes(&msg).unwrap();
3093        let _builder = Message::builder_error(&msg, MessageWriteVec::new());
3094    }
3095
3096    #[test]
3097    #[should_panic(expected = "Use add_message_integrity() instead")]
3098    fn builder_add_attribute_integrity_panic() {
3099        let _log = crate::tests::test_init_log();
3100        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3101        let hmac = [2; 20];
3102        let integrity = MessageIntegrity::new(hmac);
3103        msg.add_attribute(&integrity).unwrap();
3104    }
3105
3106    #[test]
3107    #[should_panic(expected = "Use add_message_integrity() instead")]
3108    fn builder_add_raw_attribute_integrity_panic() {
3109        let _log = crate::tests::test_init_log();
3110        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3111        let hmac = [2; 20];
3112        let integrity = MessageIntegrity::new(hmac);
3113        let raw = integrity.to_raw();
3114        msg.add_attribute(&raw).unwrap();
3115    }
3116
3117    #[test]
3118    #[should_panic(expected = "Use add_message_integrity() instead")]
3119    fn builder_add_attribute_integrity_sha256_panic() {
3120        let _log = crate::tests::test_init_log();
3121        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3122        let hmac = [2; 16];
3123        let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3124        msg.add_attribute(&integrity).unwrap();
3125    }
3126
3127    #[test]
3128    #[should_panic(expected = "Use add_message_integrity() instead")]
3129    fn builder_add_raw_attribute_integrity_sha256_panic() {
3130        let _log = crate::tests::test_init_log();
3131        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3132        let hmac = [2; 16];
3133        let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3134        let raw = integrity.to_raw();
3135        msg.add_attribute(&raw).unwrap();
3136    }
3137
3138    #[test]
3139    #[should_panic(expected = "Use add_fingerprint() instead")]
3140    fn builder_add_attribute_fingerprint_panic() {
3141        let _log = crate::tests::test_init_log();
3142        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3143        let fingerprint = [2; 4];
3144        let fingerprint = Fingerprint::new(fingerprint);
3145        msg.add_attribute(&fingerprint).unwrap();
3146    }
3147
3148    #[test]
3149    #[should_panic(expected = "Use add_fingerprint() instead")]
3150    fn builder_add_raw_attribute_fingerprint_panic() {
3151        let _log = crate::tests::test_init_log();
3152        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3153        let fingerprint = [2; 4];
3154        let fingerprint = Fingerprint::new(fingerprint);
3155        let raw = fingerprint.to_raw();
3156        msg.add_attribute(&raw).unwrap();
3157    }
3158
3159    #[test]
3160    fn rfc5769_vector1() {
3161        let _log = crate::tests::test_init_log();
3162        // https://tools.ietf.org/html/rfc5769#section-2.1
3163        let data = vec![
3164            0x00, 0x01, 0x00, 0x58, // Request type message length
3165            0x21, 0x12, 0xa4, 0x42, // Magic cookie
3166            0xb7, 0xe7, 0xa7, 0x01, // }
3167            0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
3168            0xfa, 0x87, 0xdf, 0xae, // }
3169            0x80, 0x22, 0x00, 0x10, // SOFTWARE header
3170            0x53, 0x54, 0x55, 0x4e, //   }
3171            0x20, 0x74, 0x65, 0x73, //   }  User-agent...
3172            0x74, 0x20, 0x63, 0x6c, //   }  ...name
3173            0x69, 0x65, 0x6e, 0x74, //   }
3174            0x00, 0x24, 0x00, 0x04, // PRIORITY header
3175            0x6e, 0x00, 0x01, 0xff, //   PRIORITY value
3176            0x80, 0x29, 0x00, 0x08, // ICE_CONTROLLED header
3177            0x93, 0x2f, 0xf9, 0xb1, //   Pseudo random number
3178            0x51, 0x26, 0x3b, 0x36, //   ... for tie breaker
3179            0x00, 0x06, 0x00, 0x09, // USERNAME header
3180            0x65, 0x76, 0x74, 0x6a, //   Username value
3181            0x3a, 0x68, 0x36, 0x76, //   (9 bytes)
3182            0x59, 0x20, 0x20, 0x20, //   (3 bytes padding)
3183            0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY header
3184            0x9a, 0xea, 0xa7, 0x0c, //   }
3185            0xbf, 0xd8, 0xcb, 0x56, //   }
3186            0x78, 0x1e, 0xf2, 0xb5, //   } HMAC-SHA1 fingerprint
3187            0xb2, 0xd3, 0xf2, 0x49, //   }
3188            0xc1, 0xb5, 0x71, 0xa2, //   }
3189            0x80, 0x28, 0x00, 0x04, // FINGERPRINT header
3190            0xe5, 0x7a, 0x3b, 0xcf, //   CRC32 fingerprint
3191        ];
3192        let msg = Message::from_bytes(&data).unwrap();
3193        assert!(msg.has_class(MessageClass::Request));
3194        assert!(msg.has_method(BINDING));
3195        assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3196
3197        let mut builder = Message::builder(
3198            MessageType::from_class_method(MessageClass::Request, BINDING),
3199            msg.transaction_id(),
3200            MessageWriteVec::new(),
3201        );
3202
3203        // SOFTWARE
3204        assert!(msg.has_attribute(Software::TYPE));
3205        let raw = msg.raw_attribute(Software::TYPE).unwrap();
3206        assert!(Software::try_from(&raw).is_ok());
3207        let software = Software::try_from(&raw).unwrap();
3208        assert_eq!(software.software(), "STUN test client");
3209        builder.add_attribute(&software).unwrap();
3210
3211        // PRIORITY handled elswhere
3212        builder
3213            .add_attribute(&RawAttribute::new(0x24.into(), &[0x6e, 0x00, 0x01, 0xff]))
3214            .unwrap();
3215
3216        // ICE-CONTROLLED handled elswhere
3217        builder
3218            .add_attribute(&RawAttribute::new(
3219                0x8029.into(),
3220                &[0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36],
3221            ))
3222            .unwrap();
3223
3224        // USERNAME
3225        assert!(msg.has_attribute(Username::TYPE));
3226        let raw = msg.raw_attribute(Username::TYPE).unwrap();
3227        assert!(Username::try_from(&raw).is_ok());
3228        let username = Username::try_from(&raw).unwrap();
3229        assert_eq!(username.username(), "evtj:h6vY");
3230        builder.add_attribute(&username).unwrap();
3231
3232        // MESSAGE_INTEGRITY
3233        let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3234            password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3235        });
3236        assert!(matches!(
3237            msg.validate_integrity(&credentials),
3238            Ok(IntegrityAlgorithm::Sha1)
3239        ));
3240        builder
3241            .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3242            .unwrap();
3243
3244        // FINGERPRINT is checked by Message::from_bytes() when present
3245        assert!(msg.has_attribute(Fingerprint::TYPE));
3246        builder.add_fingerprint().unwrap();
3247
3248        // assert that we produce the same output as we parsed in this case
3249        let mut msg_data = builder.finish();
3250        // match the padding bytes with the original
3251        msg_data[73] = 0x20;
3252        msg_data[74] = 0x20;
3253        msg_data[75] = 0x20;
3254        // as a result of the padding difference, the message integrity and fingerpinrt values will
3255        // be different
3256        assert_eq!(msg_data[..80], data[..80]);
3257    }
3258
3259    #[test]
3260    fn rfc5769_vector2() {
3261        let _log = crate::tests::test_init_log();
3262        // https://tools.ietf.org/html/rfc5769#section-2.2
3263        let data = vec![
3264            0x01, 0x01, 0x00, 0x3c, // Response type message length
3265            0x21, 0x12, 0xa4, 0x42, // Magic cookie
3266            0xb7, 0xe7, 0xa7, 0x01, // }
3267            0xbc, 0x34, 0xd6, 0x86, // }  Transaction ID
3268            0xfa, 0x87, 0xdf, 0xae, // }
3269            0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
3270            0x74, 0x65, 0x73, 0x74, //   }
3271            0x20, 0x76, 0x65, 0x63, //   }  UTF-8 server name
3272            0x74, 0x6f, 0x72, 0x20, //   }
3273            0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
3274            0x00, 0x01, 0xa1, 0x47, //   Address family (IPv4) and xor'd mapped port number
3275            0xe1, 0x12, 0xa6, 0x43, //   Xor'd mapped IPv4 address
3276            0x00, 0x08, 0x00, 0x14, //   MESSAGE-INTEGRITY attribute header
3277            0x2b, 0x91, 0xf5, 0x99, // }
3278            0xfd, 0x9e, 0x90, 0xc3, // }
3279            0x8c, 0x74, 0x89, 0xf9, // }  HMAC-SHA1 fingerprint
3280            0x2a, 0xf9, 0xba, 0x53, // }
3281            0xf0, 0x6b, 0xe7, 0xd7, // }
3282            0x80, 0x28, 0x00, 0x04, //  FINGERPRINT attribute header
3283            0xc0, 0x7d, 0x4c, 0x96, //  CRC32 fingerprint
3284        ];
3285
3286        let msg = Message::from_bytes(&data).unwrap();
3287        assert!(msg.has_class(MessageClass::Success));
3288        assert!(msg.has_method(BINDING));
3289        assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3290        let mut builder = Message::builder(
3291            MessageType::from_class_method(MessageClass::Success, BINDING),
3292            msg.transaction_id(),
3293            MessageWriteVec::new(),
3294        );
3295
3296        // SOFTWARE
3297        assert!(msg.has_attribute(Software::TYPE));
3298        let raw = msg.raw_attribute(Software::TYPE).unwrap();
3299        assert!(Software::try_from(&raw).is_ok());
3300        let software = Software::try_from(&raw).unwrap();
3301        assert_eq!(software.software(), "test vector");
3302        builder.add_attribute(&software).unwrap();
3303
3304        // XOR_MAPPED_ADDRESS
3305        assert!(msg.has_attribute(XorMappedAddress::TYPE));
3306        let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3307        assert!(XorMappedAddress::try_from(&raw).is_ok());
3308        let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3309        assert_eq!(
3310            xor_mapped_addres.addr(msg.transaction_id()),
3311            "192.0.2.1:32853".parse().unwrap()
3312        );
3313        builder.add_attribute(&xor_mapped_addres).unwrap();
3314
3315        // MESSAGE_INTEGRITY
3316        let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3317            password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3318        });
3319        let ret = msg.validate_integrity(&credentials);
3320        warn!("{:?}", ret);
3321        assert!(matches!(ret, Ok(IntegrityAlgorithm::Sha1)));
3322        builder
3323            .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3324            .unwrap();
3325
3326        // FINGERPRINT is checked by Message::from_bytes() when present
3327        assert!(msg.has_attribute(Fingerprint::TYPE));
3328        builder.add_fingerprint().unwrap();
3329
3330        // assert that we produce the same output as we parsed in this case
3331        let mut msg_data = builder.finish();
3332        // match the padding bytes with the original
3333        msg_data[35] = 0x20;
3334        assert_eq!(msg_data[..52], data[..52]);
3335    }
3336
3337    #[test]
3338    fn rfc5769_vector3() {
3339        let _log = crate::tests::test_init_log();
3340        // https://tools.ietf.org/html/rfc5769#section-2.3
3341        let data = vec![
3342            0x01, 0x01, 0x00, 0x48, // Response type and message length
3343            0x21, 0x12, 0xa4, 0x42, // Magic cookie
3344            0xb7, 0xe7, 0xa7, 0x01, // }
3345            0xbc, 0x34, 0xd6, 0x86, // }  Transaction ID
3346            0xfa, 0x87, 0xdf, 0xae, // }
3347            0x80, 0x22, 0x00, 0x0b, //    SOFTWARE attribute header
3348            0x74, 0x65, 0x73, 0x74, // }
3349            0x20, 0x76, 0x65, 0x63, // }  UTF-8 server name
3350            0x74, 0x6f, 0x72, 0x20, // }
3351            0x00, 0x20, 0x00, 0x14, //    XOR-MAPPED-ADDRESS attribute header
3352            0x00, 0x02, 0xa1, 0x47, //    Address family (IPv6) and xor'd mapped port number
3353            0x01, 0x13, 0xa9, 0xfa, // }
3354            0xa5, 0xd3, 0xf1, 0x79, // }  Xor'd mapped IPv6 address
3355            0xbc, 0x25, 0xf4, 0xb5, // }
3356            0xbe, 0xd2, 0xb9, 0xd9, // }
3357            0x00, 0x08, 0x00, 0x14, //    MESSAGE-INTEGRITY attribute header
3358            0xa3, 0x82, 0x95, 0x4e, // }
3359            0x4b, 0xe6, 0x7b, 0xf1, // }
3360            0x17, 0x84, 0xc9, 0x7c, // }  HMAC-SHA1 fingerprint
3361            0x82, 0x92, 0xc2, 0x75, // }
3362            0xbf, 0xe3, 0xed, 0x41, // }
3363            0x80, 0x28, 0x00, 0x04, //    FINGERPRINT attribute header
3364            0xc8, 0xfb, 0x0b, 0x4c, //    CRC32 fingerprint
3365        ];
3366
3367        let msg = Message::from_bytes(&data).unwrap();
3368        assert!(msg.has_class(MessageClass::Success));
3369        assert!(msg.has_method(BINDING));
3370        assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3371        let mut builder = Message::builder(
3372            MessageType::from_class_method(MessageClass::Success, BINDING),
3373            msg.transaction_id(),
3374            MessageWriteVec::new(),
3375        );
3376
3377        // SOFTWARE
3378        assert!(msg.has_attribute(Software::TYPE));
3379        let raw = msg.raw_attribute(Software::TYPE).unwrap();
3380        assert!(Software::try_from(&raw).is_ok());
3381        let software = Software::try_from(&raw).unwrap();
3382        assert_eq!(software.software(), "test vector");
3383        builder.add_attribute(&software).unwrap();
3384
3385        // XOR_MAPPED_ADDRESS
3386        assert!(msg.has_attribute(XorMappedAddress::TYPE));
3387        let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3388        assert!(XorMappedAddress::try_from(&raw).is_ok());
3389        let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3390        assert_eq!(
3391            xor_mapped_addres.addr(msg.transaction_id()),
3392            "[2001:db8:1234:5678:11:2233:4455:6677]:32853"
3393                .parse()
3394                .unwrap()
3395        );
3396        builder.add_attribute(&xor_mapped_addres).unwrap();
3397
3398        // MESSAGE_INTEGRITY
3399        let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3400            password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3401        });
3402        assert!(matches!(
3403            msg.validate_integrity(&credentials),
3404            Ok(IntegrityAlgorithm::Sha1)
3405        ));
3406        builder
3407            .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3408            .unwrap();
3409
3410        // FINGERPRINT is checked by Message::from_bytes() when present
3411        assert!(msg.has_attribute(Fingerprint::TYPE));
3412        builder.add_fingerprint().unwrap();
3413
3414        // assert that we produce the same output as we parsed in this case
3415        let mut msg_data = builder.finish();
3416        // match the padding bytes with the original
3417        msg_data[35] = 0x20;
3418        assert_eq!(msg_data[..64], data[..64]);
3419    }
3420
3421    #[test]
3422    fn rfc5769_vector4() {
3423        let _log = crate::tests::test_init_log();
3424        // https://tools.ietf.org/html/rfc5769#section-2.4
3425        let data = vec![
3426            0x00, 0x01, 0x00, 0x60, //    Request type and message length
3427            0x21, 0x12, 0xa4, 0x42, //    Magic cookie
3428            0x78, 0xad, 0x34, 0x33, // }
3429            0xc6, 0xad, 0x72, 0xc0, // }  Transaction ID
3430            0x29, 0xda, 0x41, 0x2e, // }
3431            0x00, 0x06, 0x00, 0x12, //    USERNAME attribute header
3432            0xe3, 0x83, 0x9e, 0xe3, // }
3433            0x83, 0x88, 0xe3, 0x83, // }
3434            0xaa, 0xe3, 0x83, 0x83, // }  Username value (18 bytes) and padding (2 bytes)
3435            0xe3, 0x82, 0xaf, 0xe3, // }
3436            0x82, 0xb9, 0x00, 0x00, // }
3437            0x00, 0x15, 0x00, 0x1c, //    NONCE attribute header
3438            0x66, 0x2f, 0x2f, 0x34, // }
3439            0x39, 0x39, 0x6b, 0x39, // }
3440            0x35, 0x34, 0x64, 0x36, // }
3441            0x4f, 0x4c, 0x33, 0x34, // }  Nonce value
3442            0x6f, 0x4c, 0x39, 0x46, // }
3443            0x53, 0x54, 0x76, 0x79, // }
3444            0x36, 0x34, 0x73, 0x41, // }
3445            0x00, 0x14, 0x00, 0x0b, //    REALM attribute header
3446            0x65, 0x78, 0x61, 0x6d, // }
3447            0x70, 0x6c, 0x65, 0x2e, // }  Realm value (11 bytes) and padding (1 byte)
3448            0x6f, 0x72, 0x67, 0x00, // }
3449            0x00, 0x08, 0x00, 0x14, //    MESSAGE-INTEGRITY attribute header
3450            0xf6, 0x70, 0x24, 0x65, // }
3451            0x6d, 0xd6, 0x4a, 0x3e, // }
3452            0x02, 0xb8, 0xe0, 0x71, // }  HMAC-SHA1 fingerprint
3453            0x2e, 0x85, 0xc9, 0xa2, // }
3454            0x8c, 0xa8, 0x96, 0x66, // }
3455        ];
3456
3457        let msg = Message::from_bytes(&data).unwrap();
3458        assert!(msg.has_class(MessageClass::Request));
3459        assert!(msg.has_method(BINDING));
3460        assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3461        let mut builder = Message::builder(
3462            MessageType::from_class_method(MessageClass::Request, BINDING),
3463            msg.transaction_id(),
3464            MessageWriteVec::new(),
3465        );
3466
3467        let long_term = LongTermCredentials {
3468            username: "\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}".to_owned(),
3469            password: "The\u{00AD}M\u{00AA}tr\u{2168}".to_owned(),
3470            realm: "example.org".to_owned(),
3471        };
3472        // USERNAME
3473        assert!(msg.has_attribute(Username::TYPE));
3474        let raw = msg.raw_attribute(Username::TYPE).unwrap();
3475        assert!(Username::try_from(&raw).is_ok());
3476        let username = Username::try_from(&raw).unwrap();
3477        assert_eq!(username.username(), &long_term.username);
3478        builder.add_attribute(&username).unwrap();
3479
3480        // NONCE
3481        let expected_nonce = "f//499k954d6OL34oL9FSTvy64sA";
3482        assert!(msg.has_attribute(Nonce::TYPE));
3483        let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3484        assert!(Nonce::try_from(&raw).is_ok());
3485        let nonce = Nonce::try_from(&raw).unwrap();
3486        assert_eq!(nonce.nonce(), expected_nonce);
3487        builder.add_attribute(&nonce).unwrap();
3488
3489        // REALM
3490        assert!(msg.has_attribute(Realm::TYPE));
3491        let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3492        assert!(Realm::try_from(&raw).is_ok());
3493        let realm = Realm::try_from(&raw).unwrap();
3494        assert_eq!(realm.realm(), long_term.realm());
3495        builder.add_attribute(&realm).unwrap();
3496
3497        // MESSAGE_INTEGRITY
3498        /* XXX: the password needs SASLPrep-ing to be useful here
3499        let credentials = MessageIntegrityCredentials::LongTerm(long_term);
3500        assert!(matches!(msg.validate_integrity(&data, &credentials), Ok(())));
3501        */
3502        //builder.add_attribute(msg.raw_attribute(MessageIntegrity::TYPE).unwrap()).unwrap();
3503
3504        assert_eq!(builder.finish()[4..], data[4..92]);
3505    }
3506
3507    #[test]
3508    fn rfc8489_vector1() {
3509        let _log = crate::tests::test_init_log();
3510        // https://www.rfc-editor.org/rfc/rfc8489#appendix-B.1
3511        // https://www.rfc-editor.org/errata/eid6268
3512        let data = vec![
3513            0x00, 0x01, 0x00, 0x90, //     Request type and message length
3514            0x21, 0x12, 0xa4, 0x42, //     Magic cookie
3515            0x78, 0xad, 0x34, 0x33, //  }
3516            0xc6, 0xad, 0x72, 0xc0, //  }  Transaction ID
3517            0x29, 0xda, 0x41, 0x2e, //  }
3518            0x00, 0x1e, 0x00, 0x20, //     USERHASH attribute header
3519            0x4a, 0x3c, 0xf3, 0x8f, //  }
3520            0xef, 0x69, 0x92, 0xbd, //  }
3521            0xa9, 0x52, 0xc6, 0x78, //  }
3522            0x04, 0x17, 0xda, 0x0f, //  }  Userhash value (32 bytes)
3523            0x24, 0x81, 0x94, 0x15, //  }
3524            0x56, 0x9e, 0x60, 0xb2, //  }
3525            0x05, 0xc4, 0x6e, 0x41, //  }
3526            0x40, 0x7f, 0x17, 0x04, //  }
3527            0x00, 0x15, 0x00, 0x29, //     NONCE attribute header
3528            0x6f, 0x62, 0x4d, 0x61, //  }
3529            0x74, 0x4a, 0x6f, 0x73, //  }
3530            0x32, 0x41, 0x41, 0x41, //  }
3531            0x43, 0x66, 0x2f, 0x2f, //  }
3532            0x34, 0x39, 0x39, 0x6b, //  }  Nonce value and padding (3 bytes)
3533            0x39, 0x35, 0x34, 0x64, //  }
3534            0x36, 0x4f, 0x4c, 0x33, //  }
3535            0x34, 0x6f, 0x4c, 0x39, //  }
3536            0x46, 0x53, 0x54, 0x76, //  }
3537            0x79, 0x36, 0x34, 0x73, //  }
3538            0x41, 0x00, 0x00, 0x00, //  }
3539            0x00, 0x14, 0x00, 0x0b, //     REALM attribute header
3540            0x65, 0x78, 0x61, 0x6d, //  }
3541            0x70, 0x6c, 0x65, 0x2e, //  }  Realm value (11 bytes) and padding (1 byte)
3542            0x6f, 0x72, 0x67, 0x00, //  }
3543            0x00, 0x1d, 0x00, 0x04, //    PASSWORD-ALGORITHM attribute header
3544            0x00, 0x02, 0x00, 0x00, //    PASSWORD-ALGORITHM value (4 bytes)
3545            0x00, 0x1c, 0x00, 0x20, //    MESSAGE-INTEGRITY-SHA256 attribute header
3546            0xb5, 0xc7, 0xbf, 0x00, // }
3547            0x5b, 0x6c, 0x52, 0xa2, // }
3548            0x1c, 0x51, 0xc5, 0xe8, // }
3549            0x92, 0xf8, 0x19, 0x24, // }  HMAC-SHA256 value
3550            0x13, 0x62, 0x96, 0xcb, // }
3551            0x92, 0x7c, 0x43, 0x14, // }
3552            0x93, 0x09, 0x27, 0x8c, // }
3553            0xc6, 0x51, 0x8e, 0x65, // }
3554        ];
3555
3556        let msg = Message::from_bytes(&data).unwrap();
3557        assert!(msg.has_class(MessageClass::Request));
3558        assert!(msg.has_method(BINDING));
3559        assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3560        let mut builder = Message::builder(
3561            MessageType::from_class_method(MessageClass::Success, BINDING),
3562            msg.transaction_id(),
3563            MessageWriteVec::new(),
3564        );
3565
3566        let long_term = LongTermCredentials {
3567            username: "\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}".to_owned(),
3568            password: "The\u{00AD}M\u{00AA}tr\u{2168}".to_owned(),
3569            realm: "example.org".to_owned(),
3570        };
3571        // USERHASH
3572        assert!(msg.has_attribute(Userhash::TYPE));
3573        let raw = msg.raw_attribute(Userhash::TYPE).unwrap();
3574        assert!(Userhash::try_from(&raw).is_ok());
3575        let userhash = Userhash::try_from(&raw).unwrap();
3576        builder.add_attribute(&userhash).unwrap();
3577
3578        // NONCE
3579        let expected_nonce = "obMatJos2AAACf//499k954d6OL34oL9FSTvy64sA";
3580        assert!(msg.has_attribute(Nonce::TYPE));
3581        let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3582        assert!(Nonce::try_from(&raw).is_ok());
3583        let nonce = Nonce::try_from(&raw).unwrap();
3584        assert_eq!(nonce.nonce(), expected_nonce);
3585        builder.add_attribute(&nonce).unwrap();
3586
3587        // REALM
3588        assert!(msg.has_attribute(Realm::TYPE));
3589        let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3590        assert!(Realm::try_from(&raw).is_ok());
3591        let realm = Realm::try_from(&raw).unwrap();
3592        assert_eq!(realm.realm(), long_term.realm);
3593        builder.add_attribute(&realm).unwrap();
3594
3595        // PASSWORD_ALGORITHM
3596        assert!(msg.has_attribute(PasswordAlgorithm::TYPE));
3597        let raw = msg.raw_attribute(PasswordAlgorithm::TYPE).unwrap();
3598        assert!(PasswordAlgorithm::try_from(&raw).is_ok());
3599        let algo = PasswordAlgorithm::try_from(&raw).unwrap();
3600        assert_eq!(algo.algorithm(), PasswordAlgorithmValue::SHA256);
3601        builder.add_attribute(&algo).unwrap();
3602
3603        // MESSAGE_INTEGRITY_SHA256
3604        /* XXX: the password needs SASLPrep-ing to be useful here
3605        let credentials = MessageIntegrityCredentials::LongTerm(long_term);
3606        assert!(matches!(msg.validate_integrity(&data, &credentials), Ok(())));
3607        */
3608        //builder.add_attribute(msg.raw_attribute(MessageIntegritySha256::TYPE).unwrap()).unwrap();
3609
3610        assert_eq!(builder.finish()[4..], data[4..128]);
3611    }
3612}