faster_stun/
lib.rs

1//! ## Session Traversal Utilities for NAT (STUN)
2//!
3//! [RFC8445]: https://tools.ietf.org/html/rfc8445
4//! [RFC5626]: https://tools.ietf.org/html/rfc5626
5//! [Section 13]: https://tools.ietf.org/html/rfc8489#section-13
6//!
7//! ### STUN Message Structure
8//!
9//! ```text
10//! 0                   1                   2                   3
11//! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
12//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13//! |0 0|     STUN Message Type     |         Message Length        |
14//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15//! |                         Magic Cookie                          |
16//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17//! |                                                               |
18//! |                     Transaction ID (96 bits)                  |
19//! |                                                               |
20//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21//! ```
22//!
23//! ### STUN Attributes
24//!
25//! ```text
26//! 0                   1                   2                   3
27//! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
28//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29//! |         Type                  |            Length             |
30//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31//! |                         Value (variable)                ....
32//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33//! ```
34//!
35//! STUN is intended to be used in the context of one or more NAT
36//! traversal solutions.  These solutions are known as "STUN Usages".
37//! Each usage describes how STUN is utilized to achieve the NAT
38//! traversal solution.  Typically, a usage indicates when STUN messages
39//! get sent, which optional attributes to include, what server is used,
40//! and what authentication mechanism is to be used.  Interactive
41//! Connectivity Establishment (ICE) [RFC8445] is one usage of STUN.
42//! SIP Outbound [RFC5626] is another usage of STUN.  In some cases,
43//! a usage will require extensions to STUN. A STUN extension can be
44//! in the form of new methods, attributes, or error response codes.
45//! More information on STUN Usages can be found in [Section 13].
46
47pub mod attribute;
48pub mod channel;
49pub mod message;
50pub mod util;
51
52use std::{error, fmt};
53
54pub use channel::ChannelData;
55pub use message::*;
56
57#[derive(Debug)]
58pub enum StunError {
59    InvalidInput,
60    UnsupportedIpFamily,
61    ShaFailed,
62    NotIntegrity,
63    IntegrityFailed,
64    NotCookie,
65    UnknownMethod,
66    FatalError,
67    Utf8Error,
68}
69
70impl error::Error for StunError {}
71
72impl fmt::Display for StunError {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        write!(
75            f,
76            "{}",
77            match self {
78                Self::InvalidInput => "InvalidInput",
79                Self::UnsupportedIpFamily => "UnsupportedIpFamily",
80                Self::ShaFailed => "ShaFailed",
81                Self::NotIntegrity => "NotIntegrity",
82                Self::IntegrityFailed => "IntegrityFailed",
83                Self::NotCookie => "NotCookie",
84                Self::UnknownMethod => "UnknownMethod",
85                Self::FatalError => "FatalError",
86                Self::Utf8Error => "Utf8Error",
87            }
88        )
89    }
90}
91
92/// STUN Methods Registry
93///
94/// [RFC5389]: https://datatracker.ietf.org/doc/html/rfc5389
95/// [RFC8489]: https://datatracker.ietf.org/doc/html/rfc8489
96/// [RFC8126]: https://datatracker.ietf.org/doc/html/rfc8126
97/// [Section 5]: https://datatracker.ietf.org/doc/html/rfc8489#section-5
98///
99/// A STUN method is a hex number in the range 0x000-0x0FF.  The encoding
100/// of a STUN method into a STUN message is described in [Section 5].
101///
102/// STUN methods in the range 0x000-0x07F are assigned by IETF Review
103/// [RFC8126].  STUN methods in the range 0x080-0x0FF are assigned by
104/// Expert Review [RFC8126].  The responsibility of the expert is to
105/// verify that the selected codepoint(s) is not in use and that the
106/// request is not for an abnormally large number of codepoints.
107/// Technical review of the extension itself is outside the scope of the
108/// designated expert responsibility.
109///
110/// IANA has updated the name for method 0x002 as described below as well
111/// as updated the reference from [RFC5389] to [RFC8489] for the following
112/// STUN methods:
113///
114/// 0x000: Reserved
115/// 0x001: Binding
116/// 0x002: Reserved; was SharedSecret prior to [RFC5389]
117/// 0x003: Allocate
118/// 0x004: Refresh
119/// 0x006: Send
120/// 0x007: Data
121/// 0x008: CreatePermission
122/// 0x009: ChannelBind
123#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
124pub enum Kind {
125    Request,
126    Response,
127    Error,
128}
129
130#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
131pub enum Method {
132    Binding(Kind),
133    Allocate(Kind),
134    CreatePermission(Kind),
135    ChannelBind(Kind),
136    Refresh(Kind),
137    SendIndication,
138    DataIndication,
139}
140
141impl TryFrom<u16> for Method {
142    type Error = StunError;
143
144    /// # Unit Test
145    ///
146    /// ```
147    /// use faster_stun::*;
148    /// use std::convert::TryFrom;
149    ///
150    /// assert_eq!(
151    ///     Method::try_from(0x0001).unwrap(),
152    ///     Method::Binding(Kind::Request)
153    /// );
154    /// assert_eq!(
155    ///     Method::try_from(0x0101).unwrap(),
156    ///     Method::Binding(Kind::Response)
157    /// );
158    /// assert_eq!(
159    ///     Method::try_from(0x0111).unwrap(),
160    ///     Method::Binding(Kind::Error)
161    /// );
162    /// assert_eq!(
163    ///     Method::try_from(0x0003).unwrap(),
164    ///     Method::Allocate(Kind::Request)
165    /// );
166    /// assert_eq!(
167    ///     Method::try_from(0x0103).unwrap(),
168    ///     Method::Allocate(Kind::Response)
169    /// );
170    /// assert_eq!(
171    ///     Method::try_from(0x0113).unwrap(),
172    ///     Method::Allocate(Kind::Error)
173    /// );
174    /// assert_eq!(
175    ///     Method::try_from(0x0008).unwrap(),
176    ///     Method::CreatePermission(Kind::Request)
177    /// );
178    /// assert_eq!(
179    ///     Method::try_from(0x0108).unwrap(),
180    ///     Method::CreatePermission(Kind::Response)
181    /// );
182    /// assert_eq!(
183    ///     Method::try_from(0x0118).unwrap(),
184    ///     Method::CreatePermission(Kind::Error)
185    /// );
186    /// assert_eq!(
187    ///     Method::try_from(0x0009).unwrap(),
188    ///     Method::ChannelBind(Kind::Request)
189    /// );
190    /// assert_eq!(
191    ///     Method::try_from(0x0109).unwrap(),
192    ///     Method::ChannelBind(Kind::Response)
193    /// );
194    /// assert_eq!(
195    ///     Method::try_from(0x0119).unwrap(),
196    ///     Method::ChannelBind(Kind::Error)
197    /// );
198    /// assert_eq!(
199    ///     Method::try_from(0x0004).unwrap(),
200    ///     Method::Refresh(Kind::Request)
201    /// );
202    /// assert_eq!(
203    ///     Method::try_from(0x0104).unwrap(),
204    ///     Method::Refresh(Kind::Response)
205    /// );
206    /// assert_eq!(
207    ///     Method::try_from(0x0114).unwrap(),
208    ///     Method::Refresh(Kind::Error)
209    /// );
210    /// assert_eq!(Method::try_from(0x0016).unwrap(), Method::SendIndication);
211    /// assert_eq!(Method::try_from(0x0017).unwrap(), Method::DataIndication);
212    /// ```
213    fn try_from(value: u16) -> Result<Self, Self::Error> {
214        Ok(match value {
215            0x0001 => Self::Binding(Kind::Request),
216            0x0101 => Self::Binding(Kind::Response),
217            0x0111 => Self::Binding(Kind::Error),
218            0x0003 => Self::Allocate(Kind::Request),
219            0x0103 => Self::Allocate(Kind::Response),
220            0x0113 => Self::Allocate(Kind::Error),
221            0x0008 => Self::CreatePermission(Kind::Request),
222            0x0108 => Self::CreatePermission(Kind::Response),
223            0x0118 => Self::CreatePermission(Kind::Error),
224            0x0009 => Self::ChannelBind(Kind::Request),
225            0x0109 => Self::ChannelBind(Kind::Response),
226            0x0119 => Self::ChannelBind(Kind::Error),
227            0x0004 => Self::Refresh(Kind::Request),
228            0x0104 => Self::Refresh(Kind::Response),
229            0x0114 => Self::Refresh(Kind::Error),
230            0x0016 => Self::SendIndication,
231            0x0017 => Self::DataIndication,
232            _ => return Err(StunError::UnknownMethod),
233        })
234    }
235}
236
237impl From<Method> for u16 {
238    /// # Unit Test
239    ///
240    /// ```
241    /// use faster_stun::*;
242    /// use std::convert::Into;
243    ///
244    /// assert_eq!(0x0001u16, Method::Binding(Kind::Request).into());
245    /// assert_eq!(0x0101u16, Method::Binding(Kind::Response).into());
246    /// assert_eq!(0x0111u16, Method::Binding(Kind::Error).into());
247    /// assert_eq!(0x0003u16, Method::Allocate(Kind::Request).into());
248    /// assert_eq!(0x0103u16, Method::Allocate(Kind::Response).into());
249    /// assert_eq!(0x0113u16, Method::Allocate(Kind::Error).into());
250    /// assert_eq!(0x0008u16, Method::CreatePermission(Kind::Request).into());
251    /// assert_eq!(0x0108u16, Method::CreatePermission(Kind::Response).into());
252    /// assert_eq!(0x0118u16, Method::CreatePermission(Kind::Error).into());
253    /// assert_eq!(0x0009u16, Method::ChannelBind(Kind::Request).into());
254    /// assert_eq!(0x0109u16, Method::ChannelBind(Kind::Response).into());
255    /// assert_eq!(0x0119u16, Method::ChannelBind(Kind::Error).into());
256    /// assert_eq!(0x0004u16, Method::Refresh(Kind::Request).into());
257    /// assert_eq!(0x0104u16, Method::Refresh(Kind::Response).into());
258    /// assert_eq!(0x0114u16, Method::Refresh(Kind::Error).into());
259    /// assert_eq!(0x0016u16, Method::SendIndication.into());
260    /// assert_eq!(0x0017u16, Method::DataIndication.into());
261    /// ```
262    fn from(val: Method) -> Self {
263        match val {
264            Method::Binding(Kind::Request) => 0x0001,
265            Method::Binding(Kind::Response) => 0x0101,
266            Method::Binding(Kind::Error) => 0x0111,
267            Method::Allocate(Kind::Request) => 0x0003,
268            Method::Allocate(Kind::Response) => 0x0103,
269            Method::Allocate(Kind::Error) => 0x0113,
270            Method::CreatePermission(Kind::Request) => 0x0008,
271            Method::CreatePermission(Kind::Response) => 0x0108,
272            Method::CreatePermission(Kind::Error) => 0x0118,
273            Method::ChannelBind(Kind::Request) => 0x0009,
274            Method::ChannelBind(Kind::Response) => 0x0109,
275            Method::ChannelBind(Kind::Error) => 0x0119,
276            Method::Refresh(Kind::Request) => 0x0004,
277            Method::Refresh(Kind::Response) => 0x0104,
278            Method::Refresh(Kind::Error) => 0x0114,
279            Method::SendIndication => 0x0016,
280            Method::DataIndication => 0x0017,
281        }
282    }
283}
284
285#[derive(Debug)]
286pub enum Payload<'a, 'b> {
287    Message(MessageReader<'a, 'b>),
288    ChannelData(ChannelData<'a>),
289}
290
291pub struct Decoder {
292    attrs: Vec<(attribute::AttrKind, &'static [u8])>,
293}
294
295impl Decoder {
296    pub fn new() -> Self {
297        Self {
298            attrs: Vec::with_capacity(10),
299        }
300    }
301
302    /// # Unit Test
303    ///
304    /// ```
305    /// use faster_stun::attribute::*;
306    /// use faster_stun::*;
307    ///
308    /// let buffer = [
309    ///     0x00, 0x01, 0x00, 0x4c, 0x21, 0x12, 0xa4, 0x42, 0x71, 0x66, 0x46, 0x31,
310    ///     0x2b, 0x59, 0x79, 0x65, 0x56, 0x69, 0x32, 0x72, 0x00, 0x06, 0x00, 0x09,
311    ///     0x55, 0x43, 0x74, 0x39, 0x3a, 0x56, 0x2f, 0x2b, 0x2f, 0x00, 0x00, 0x00,
312    ///     0xc0, 0x57, 0x00, 0x04, 0x00, 0x00, 0x03, 0xe7, 0x80, 0x29, 0x00, 0x08,
313    ///     0x22, 0x49, 0xda, 0x28, 0x2c, 0x6f, 0x2e, 0xdb, 0x00, 0x24, 0x00, 0x04,
314    ///     0x6e, 0x00, 0x28, 0xff, 0x00, 0x08, 0x00, 0x14, 0x19, 0x58, 0xda, 0x38,
315    ///     0xed, 0x1e, 0xdd, 0xc8, 0x6b, 0x8e, 0x22, 0x63, 0x3a, 0x22, 0x63, 0x97,
316    ///     0xcf, 0xf5, 0xde, 0x82, 0x80, 0x28, 0x00, 0x04, 0x56, 0xf7, 0xa3, 0xed,
317    /// ];
318    ///
319    /// let mut decoder = Decoder::new();
320    /// let payload = decoder.decode(&buffer).unwrap();
321    /// if let Payload::Message(reader) = payload {
322    ///     assert!(reader.get::<UserName>().is_some())
323    /// }
324    /// ```
325    pub fn decode<'a>(&mut self, buf: &'a [u8]) -> Result<Payload<'a, '_>, StunError> {
326        assert!(buf.len() >= 4);
327        if !self.attrs.is_empty() {
328            self.attrs.clear();
329        }
330
331        let flag = buf[0] >> 6;
332        if flag > 3 {
333            return Err(StunError::InvalidInput);
334        }
335
336        Ok(if flag == 0 {
337            // attrs will not be used again after decode is used, so the
338            // reference is safe. Unsafe is used here to make the external life
339            // cycle declaration cleaner.
340            Payload::Message(MessageReader::decode(
341                unsafe { std::mem::transmute(buf) },
342                &mut self.attrs,
343            )?)
344        } else {
345            Payload::ChannelData(ChannelData::try_from(buf)?)
346        })
347    }
348
349    /// # Unit Test
350    ///
351    /// ```
352    /// use faster_stun::attribute::*;
353    /// use faster_stun::*;
354    ///
355    /// let buffer = [
356    ///     0x00, 0x01, 0x00, 0x4c, 0x21, 0x12, 0xa4, 0x42, 0x71, 0x66, 0x46, 0x31,
357    ///     0x2b, 0x59, 0x79, 0x65, 0x56, 0x69, 0x32, 0x72, 0x00, 0x06, 0x00, 0x09,
358    ///     0x55, 0x43, 0x74, 0x39, 0x3a, 0x56, 0x2f, 0x2b, 0x2f, 0x00, 0x00, 0x00,
359    ///     0xc0, 0x57, 0x00, 0x04, 0x00, 0x00, 0x03, 0xe7, 0x80, 0x29, 0x00, 0x08,
360    ///     0x22, 0x49, 0xda, 0x28, 0x2c, 0x6f, 0x2e, 0xdb, 0x00, 0x24, 0x00, 0x04,
361    ///     0x6e, 0x00, 0x28, 0xff, 0x00, 0x08, 0x00, 0x14, 0x19, 0x58, 0xda, 0x38,
362    ///     0xed, 0x1e, 0xdd, 0xc8, 0x6b, 0x8e, 0x22, 0x63, 0x3a, 0x22, 0x63, 0x97,
363    ///     0xcf, 0xf5, 0xde, 0x82, 0x80, 0x28, 0x00, 0x04, 0x56, 0xf7, 0xa3, 0xed,
364    /// ];
365    ///
366    /// let size = Decoder::message_size(&buffer, false).unwrap();
367    /// assert_eq!(size, 96);
368    /// ```
369    pub fn message_size(buf: &[u8], is_tcp: bool) -> Result<usize, StunError> {
370        let flag = buf[0] >> 6;
371        if flag > 3 {
372            return Err(StunError::InvalidInput);
373        }
374
375        Ok(if flag == 0 {
376            MessageReader::message_size(buf)?
377        } else {
378            ChannelData::message_size(buf, is_tcp)?
379        })
380    }
381}
382
383impl Default for Decoder {
384    fn default() -> Self {
385        Self::new()
386    }
387}