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