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