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