turn_server/stun/
attribute.rs

1use super::StunError;
2
3use std::{
4    fmt::Debug,
5    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
6};
7
8use bytes::{Buf, BufMut, BytesMut};
9use num_enum::TryFromPrimitive;
10
11#[repr(u32)]
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
13pub enum Transport {
14    TCP = 0x06000000,
15    UDP = 0x11000000,
16}
17
18#[repr(u8)]
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub enum IpFamily {
21    V4 = 0x01,
22    V6 = 0x02,
23}
24
25impl TryFrom<u8> for IpFamily {
26    type Error = StunError;
27
28    fn try_from(value: u8) -> Result<Self, Self::Error> {
29        Ok(match value {
30            0x01 => Self::V4,
31            0x02 => Self::V6,
32            _ => return Err(StunError::InvalidInput),
33        })
34    }
35}
36
37/// [RFC3489]: https://datatracker.ietf.org/doc/html/rfc3489
38///
39/// The Address attribute indicates a reflexive transport address
40/// of the client.  It consists of an 8-bit address family and a 16-bit
41/// port, followed by a fixed-length value representing the IP address.
42/// If the address family is IPv4, the address MUST be 32 bits.  If the
43/// address family is IPv6, the address MUST be 128 bits.  All fields
44/// must be in network byte order.
45///
46/// The format of the MAPPED-ADDRESS attribute is:
47///
48/// ```text
49/// 0                   1                   2                   3
50/// 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
51/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52/// |0 0 0 0 0 0 0 0|    Family     |           Port                |
53/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54/// |                                                               |
55/// |                 Address (32 bits or 128 bits)                 |
56/// |                                                               |
57/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58/// ```
59///
60/// Figure 5: Format of MAPPED-ADDRESS Attribute
61///
62/// The address family can take on the following values:
63///
64/// * 0x01:IPv4
65/// * 0x02:IPv6
66///
67/// The first 8 bits of the MAPPED-ADDRESS MUST be set to 0 and MUST be
68/// ignored by receivers.  These bits are present for aligning parameters
69/// on natural 32-bit boundaries.
70///
71/// This attribute is used only by servers for achieving backwards
72/// compatibility with [RFC3489] clients.
73///
74/// The XOR-MAPPED-ADDRESS attribute is identical to the MAPPED-ADDRESS
75/// attribute, except that the reflexive transport address is obfuscated
76/// through the XOR function.
77///
78/// The format of the XOR-MAPPED-ADDRESS is:
79///
80/// ```text
81/// 0                   1                   2                   3
82/// 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
83/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84/// |0 0 0 0 0 0 0 0|    Family     |         X-Port                |
85/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86/// |                X-Address (Variable)
87/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88///
89///          Figure 6: Format of XOR-MAPPED-ADDRESS Attribute
90/// ```
91///
92/// The Family field represents the IP address family and is encoded
93/// identically to the Family field in MAPPED-ADDRESS.
94///
95/// X-Port is computed by XOR'ing the mapped port with the most
96/// significant 16 bits of the magic cookie.  If the IP address family is
97/// IPv4, X-Address is computed by XOR'ing the mapped IP address with the
98/// magic cookie.  If the IP address family is IPv6, X-Address is
99/// computed by XOR'ing the mapped IP address with the concatenation of
100/// the magic cookie and the 96-bit transaction ID.  In all cases, the
101/// XOR operation works on its inputs in network byte order (that is, the
102/// order they will be encoded in the message).
103///
104/// The rules for encoding and processing the first 8 bits of the
105/// attribute's value, the rules for handling multiple occurrences of the
106/// attribute, and the rules for processing address families are the same
107/// as for MAPPED-ADDRESS.
108///
109/// Note: XOR-MAPPED-ADDRESS and MAPPED-ADDRESS differ only in their
110/// encoding of the transport address.  The former encodes the transport
111/// address by XOR'ing it with the magic cookie.  The latter encodes it
112/// directly in binary.  [RFC3489] originally specified only MAPPED-
113/// ADDRESS.  However, deployment experience found that some NATs rewrite
114/// the 32-bit binary payloads containing the NAT's public IP address,
115/// such as STUN's MAPPED-ADDRESS attribute, in the well-meaning but
116/// misguided attempt to provide a generic Application Layer Gateway
117/// (ALG) function.  Such behavior interferes with the operation of STUN
118/// and also causes failure of STUN's message-integrity checking.
119pub struct Addr;
120
121impl Addr {
122    /// encoder SocketAddr as Bytes.
123    ///
124    /// # Test
125    ///
126    /// ```
127    /// use bytes::BytesMut;
128    /// use turn_server::stun::attribute::*;
129    ///
130    /// let xor_addr_bytes: [u8; 8] =
131    ///     [0x00, 0x01, 0xfc, 0xbe, 0xe1, 0xba, 0xa4, 0x29];
132    ///
133    /// let addr_bytes: [u8; 8] = [0x00, 0x01, 0xdd, 0xac, 0xc0, 0xa8, 0x00, 0x6b];
134    ///
135    /// let token: [u8; 12] = [
136    ///     0x6c, 0x46, 0x62, 0x54, 0x75, 0x4b, 0x44, 0x51, 0x46, 0x48, 0x4c, 0x71,
137    /// ];
138    ///
139    /// let source = "192.168.0.107:56748".parse().unwrap();
140    ///
141    /// let mut buffer = BytesMut::with_capacity(1280);
142    /// Addr::encode(&source, &token, &mut buffer, true);
143    /// assert_eq!(&xor_addr_bytes, &buffer[..]);
144    ///
145    /// let mut buffer = BytesMut::with_capacity(1280);
146    /// Addr::encode(&source, &token, &mut buffer, false);
147    /// assert_eq!(&addr_bytes, &buffer[..]);
148    /// ```
149    pub fn encode(addr: &SocketAddr, token: &[u8], bytes: &mut BytesMut, is_xor: bool) {
150        bytes.put_u8(0);
151        let xor_addr = if is_xor { xor(addr, token) } else { *addr };
152
153        bytes.put_u8(if xor_addr.is_ipv4() { IpFamily::V4 } else { IpFamily::V6 } as u8);
154
155        bytes.put_u16(xor_addr.port());
156        if let IpAddr::V4(ip) = xor_addr.ip() {
157            bytes.put(&ip.octets()[..]);
158        }
159
160        if let IpAddr::V6(ip) = xor_addr.ip() {
161            bytes.put(&ip.octets()[..]);
162        }
163    }
164
165    /// decoder Bytes as SocketAddr.
166    ///
167    /// # Test
168    ///
169    /// ```
170    /// use turn_server::stun::attribute::*;
171    ///
172    /// let xor_addr_bytes: [u8; 8] =
173    ///     [0x00, 0x01, 0xfc, 0xbe, 0xe1, 0xba, 0xa4, 0x29];
174    ///
175    /// let addr_bytes: [u8; 8] = [0x00, 0x01, 0xdd, 0xac, 0xc0, 0xa8, 0x00, 0x6b];
176    ///
177    /// let token: [u8; 12] = [
178    ///     0x6c, 0x46, 0x62, 0x54, 0x75, 0x4b, 0x44, 0x51, 0x46, 0x48, 0x4c, 0x71,
179    /// ];
180    ///
181    /// let source = "192.168.0.107:56748".parse().unwrap();
182    ///
183    /// let addr = Addr::decode(&xor_addr_bytes, &token, true).unwrap();
184    /// assert_eq!(addr, source);
185    ///
186    /// let addr = Addr::decode(&addr_bytes, &token, false).unwrap();
187    /// assert_eq!(addr, source);
188    /// ```
189    pub fn decode(packet: &[u8], token: &[u8], is_xor: bool) -> Result<SocketAddr, StunError> {
190        if packet.len() < 4 {
191            return Err(StunError::InvalidInput);
192        }
193
194        let port = u16::from_be_bytes([packet[2], packet[3]]);
195        let ip_addr = match IpFamily::try_from(packet[1])? {
196            IpFamily::V4 => from_bytes_v4(packet)?,
197            IpFamily::V6 => from_bytes_v6(packet)?,
198        };
199
200        let dyn_addr = SocketAddr::new(ip_addr, port);
201        Ok(if is_xor { xor(&dyn_addr, token) } else { dyn_addr })
202    }
203}
204
205/// # Test
206///
207/// ```
208/// use std::net::IpAddr;
209/// use turn_server::stun::attribute::*;
210///
211/// let bytes: [u8; 8] = [0x00, 0x01, 0xdd, 0xac, 0xc0, 0xa8, 0x00, 0x6b];
212///
213/// let source: IpAddr = "192.168.0.107".parse().unwrap();
214///
215/// let addr = from_bytes_v4(&bytes).unwrap();
216/// assert_eq!(addr, source);
217/// ```
218pub fn from_bytes_v4(packet: &[u8]) -> Result<IpAddr, StunError> {
219    if packet.len() != 8 {
220        return Err(StunError::InvalidInput);
221    }
222
223    let bytes: [u8; 4] = packet[4..8].try_into()?;
224    Ok(IpAddr::V4(bytes.into()))
225}
226
227/// # Test
228///
229/// ```
230/// use std::net::IpAddr;
231/// use turn_server::stun::attribute::*;
232///
233/// let bytes: [u8; 20] = [
234///     0x00, 0x01, 0xdd, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235///     0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x0A, 0x2F, 0x0F,
236/// ];
237///
238/// let source: IpAddr = "::ffff:192.10.47.15".parse().unwrap();
239///
240/// let addr = from_bytes_v6(&bytes).unwrap();
241/// assert_eq!(addr, source);
242/// ```
243pub fn from_bytes_v6(packet: &[u8]) -> Result<IpAddr, StunError> {
244    if packet.len() != 20 {
245        return Err(StunError::InvalidInput);
246    }
247
248    let bytes: [u8; 16] = packet[4..20].try_into()?;
249    Ok(IpAddr::V6(bytes.into()))
250}
251
252/// # Test
253///
254/// ```
255/// use std::net::SocketAddr;
256/// use turn_server::stun::attribute::*;
257///
258/// let source: SocketAddr = "192.168.0.107:1".parse().unwrap();
259///
260/// let res: SocketAddr = "225.186.164.41:8467".parse().unwrap();
261///
262/// let token: [u8; 12] = [
263///     0x6c, 0x46, 0x62, 0x54, 0x75, 0x4b, 0x44, 0x51, 0x46, 0x48, 0x4c, 0x71,
264/// ];
265///
266/// let addr = xor(&source, &token);
267/// assert_eq!(addr, res);
268/// ```
269pub fn xor(addr: &SocketAddr, token: &[u8]) -> SocketAddr {
270    let port = addr.port() ^ (0x2112A442 >> 16) as u16;
271    let ip_addr = match addr.ip() {
272        IpAddr::V4(x) => xor_v4(x),
273        IpAddr::V6(x) => xor_v6(x, token),
274    };
275
276    SocketAddr::new(ip_addr, port)
277}
278
279/// # Test
280///
281/// ```
282/// use std::net::{IpAddr, Ipv4Addr};
283/// use turn_server::stun::attribute::*;
284///
285/// let source: Ipv4Addr = "192.168.0.107".parse().unwrap();
286///
287/// let xor: IpAddr = "225.186.164.41".parse().unwrap();
288///
289/// let addr = xor_v4(source);
290/// assert_eq!(addr, xor);
291/// ```
292pub fn xor_v4(addr: Ipv4Addr) -> IpAddr {
293    let mut octets = addr.octets();
294    for (i, b) in octets.iter_mut().enumerate() {
295        *b ^= (0x2112A442 >> (24 - i * 8)) as u8;
296    }
297
298    IpAddr::V4(From::from(octets))
299}
300
301/// # Test
302///
303/// ```
304/// use std::net::{IpAddr, Ipv6Addr};
305/// use turn_server::stun::attribute::*;
306///
307/// let source: Ipv6Addr = "::ffff:192.10.47.15".parse().unwrap();
308///
309/// let xor: IpAddr =
310///     "2112:a442:6c46:6254:754b:bbae:8642:637e".parse().unwrap();
311///
312/// let token: [u8; 12] = [
313///     0x6c, 0x46, 0x62, 0x54, 0x75, 0x4b, 0x44, 0x51, 0x46, 0x48, 0x4c, 0x71,
314/// ];
315///
316/// let addr = xor_v6(source, &token);
317/// assert_eq!(addr, xor);
318/// ```
319pub fn xor_v6(addr: Ipv6Addr, token: &[u8]) -> IpAddr {
320    let mut octets = addr.octets();
321    for (i, b) in octets.iter_mut().enumerate().take(4) {
322        *b ^= (0x2112A442 >> (24 - i * 8)) as u8;
323    }
324
325    for (i, b) in octets.iter_mut().enumerate().take(16).skip(4) {
326        *b ^= token[i - 4];
327    }
328
329    IpAddr::V6(From::from(octets))
330}
331
332/// STUN Attributes Registry
333///
334/// [RFC8126]: https://datatracker.ietf.org/doc/html/rfc8126
335/// [RFC5389]: https://datatracker.ietf.org/doc/html/rfc5389
336/// [RFC8489]: https://datatracker.ietf.org/doc/html/rfc8489
337///
338/// A STUN attribute type is a hex number in the range 0x0000-0xFFFF.
339/// STUN attribute types in the range 0x0000-0x7FFF are considered
340/// comprehension-required; STUN attribute types in the range
341/// 0x8000-0xFFFF are considered comprehension-optional.  A STUN agent
342/// handles unknown comprehension-required and comprehension-optional
343/// attributes differently.
344///
345/// STUN attribute types in the first half of the comprehension-required
346/// range (0x0000-0x3FFF) and in the first half of the comprehension-
347/// optional range (0x8000-0xBFFF) are assigned by IETF Review [RFC8126].
348/// STUN attribute types in the second half of the comprehension-required
349/// range (0x4000-0x7FFF) and in the second half of the comprehension-
350/// optional range (0xC000-0xFFFF) are assigned by Expert Review
351/// [RFC8126].  The responsibility of the expert is to verify that the
352/// selected codepoint(s) are not in use and that the request is not for
353/// an abnormally large number of codepoints.  Technical review of the
354/// extension itself is outside the scope of the designated expert
355/// responsibility.
356///
357/// IANA has updated the names for attributes 0x0002, 0x0004, 0x0005,
358/// 0x0007, and 0x000B as well as updated the reference from [RFC5389] to
359/// [RFC8489] for each the following STUN methods.
360///
361/// In addition, [RFC5389] introduced a mistake in the name of attribute
362/// 0x0003; [RFC5389] called it CHANGE-ADDRESS when it was actually
363/// previously called CHANGE-REQUEST.  Thus, IANA has updated the
364/// description for 0x0003 to read "Reserved; was CHANGE-REQUEST prior to
365/// [RFC5389]".
366///
367/// Comprehension-required range (0x0000-0x7FFF):
368/// 0x0000: Reserved
369/// 0x0001: MAPPED-ADDRESS
370/// 0x0002: Reserved; was RESPONSE-ADDRESS prior to [RFC5389]
371/// 0x0003: Reserved; was CHANGE-REQUEST prior to [RFC5389]
372/// 0x0004: Reserved; was SOURCE-ADDRESS prior to [RFC5389]
373/// 0x0005: Reserved; was CHANGED-ADDRESS prior to [RFC5389]
374/// 0x0006: USERNAME
375/// 0x0007: Reserved; was PASSWORD prior to [RFC5389]
376/// 0x0008: MESSAGE-INTEGRITY
377/// 0x0009: ERROR-CODE
378/// 0x000A: UNKNOWN-ATTRIBUTES
379/// 0x000B: Reserved; was REFLECTED-FROM prior to [RFC5389]
380/// 0x0014: REALM
381/// 0x0015: NONCE
382/// 0x0020: XOR-MAPPED-ADDRESS
383///
384/// Comprehension-optional range (0x8000-0xFFFF)
385/// 0x8022: SOFTWARE
386///  0x8023: ALTERNATE-SERVER
387/// 0x8028: FINGERPRINT
388///
389/// IANA has added the following attribute to the "STUN Attributes"
390/// registry:
391///
392/// Comprehension-required range (0x0000-0x7FFF):
393/// 0x001C: MESSAGE-INTEGRITY-SHA256
394/// 0x001D: PASSWORD-ALGORITHM
395///  0x001E: USERHASH
396///
397/// Comprehension-optional range (0x8000-0xFFFF)
398/// 0x8002: PASSWORD-ALGORITHMS
399/// 0x8003: ALTERNATE-DOMAIN
400#[repr(u16)]
401#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Debug, TryFromPrimitive)]
402pub enum AttrKind {
403    #[default]
404    Unknown = 0x0000,
405    MappedAddress = 0x0001,
406    UserName = 0x0006,
407    MessageIntegrity = 0x0008,
408    ErrorCode = 0x0009,
409    ChannelNumber = 0x000C,
410    Lifetime = 0x000D,
411    XorPeerAddress = 0x0012,
412    Data = 0x0013,
413    Realm = 0x0014,
414    Nonce = 0x0015,
415    XorRelayedAddress = 0x0016,
416    RequestedAddressFamily = 0x0017,
417    EvenPort = 0x0018,
418    ReqeestedTransport = 0x0019,
419    DontFragment = 0x001A,
420    AccessToken = 0x001B,
421    MessageIntegritySha256 = 0x001C,
422    PasswordAlgorithm = 0x001D,
423    UserHash = 0x001E,
424    XorMappedAddress = 0x0020,
425    ReservationToken = 0x0022,
426    Priority = 0x0024,
427    UseCandidate = 0x0025,
428    Padding = 0x0026,
429    ResponsePort = 0x0027,
430    ConnectionId = 0x002A,
431    AdditionalAddressFamily = 0x8000,
432    AddressErrorCode = 0x8001,
433    PasswordAlgorithms = 0x8002,
434    AlternateDomain = 0x8003,
435    Icmp = 0x8004,
436    Software = 0x8022,
437    AlternateServer = 0x8023,
438    TransactionTransmitCounter = 0x8025,
439    CacheTimeout = 0x8027,
440    Fingerprint = 0x8028,
441    IceControlled = 0x8029,
442    IceControlling = 0x802A,
443    ResponseOrigin = 0x802B,
444    OtherAddress = 0x802C,
445    EcnCheck = 0x802D,
446    ThirdPartyAuathorization = 0x802E,
447    MobilityTicket = 0x8030,
448}
449
450/// dyn stun/turn message attribute.
451pub trait Attribute<'a> {
452    type Error: Debug;
453
454    /// current attribute inner type.
455    type Item;
456
457    /// current attribute type.
458    const KIND: AttrKind;
459
460    /// write the current attribute to the bytesfer.
461    #[allow(unused_variables)]
462    fn encode(value: Self::Item, bytes: &mut BytesMut, token: &'a [u8]) {}
463
464    /// convert bytesfer to current attribute.
465    fn decode(bytes: &'a [u8], token: &'a [u8]) -> Result<Self::Item, Self::Error>;
466}
467
468/// [RFC8265]: https://datatracker.ietf.org/doc/html/rfc8265
469/// [RFC5389]: https://datatracker.ietf.org/doc/html/rfc5389
470/// [RFC3629]: https://datatracker.ietf.org/doc/html/rfc3629
471///
472/// The USERNAME attribute is used for message integrity.  It identifies
473/// the username and password combination used in the message-integrity
474/// check.
475///
476/// The value of USERNAME is a variable-length value containing the
477/// authentication username.  It MUST contain a UTF-8-encoded [RFC3629]
478/// sequence of fewer than 509 bytes and MUST have been processed using
479/// the OpaqueString profile [RFC8265].  A compliant implementation MUST
480/// be able to parse a UTF-8-encoded sequence of 763 or fewer octets to
481/// be compatible with [RFC5389].
482pub struct UserName;
483
484impl<'a> Attribute<'a> for UserName {
485    type Error = StunError;
486    type Item = &'a str;
487
488    const KIND: AttrKind = AttrKind::UserName;
489
490    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
491        bytes.put(value.as_bytes());
492    }
493
494    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
495        Ok(std::str::from_utf8(bytes)?)
496    }
497}
498
499/// The DATA attribute is present in all Send and Data indications.  The
500/// value portion of this attribute is variable length and consists of
501/// the application data (that is, the data that would immediately follow
502/// the UDP header if the data was been sent directly between the client
503/// and the peer).  If the length of this attribute is not a multiple of
504/// 4, then padding must be added after this attribute.
505pub struct Data;
506
507impl<'a> Attribute<'a> for Data {
508    type Error = StunError;
509    type Item = &'a [u8];
510
511    const KIND: AttrKind = AttrKind::Data;
512
513    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
514        bytes.put(value);
515    }
516
517    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
518        Ok(bytes)
519    }
520}
521
522/// [RFC3629]: https://datatracker.ietf.org/doc/html/rfc3629
523/// [RFC3261]: https://datatracker.ietf.org/doc/html/rfc3261
524/// [RFC8265]: https://datatracker.ietf.org/doc/html/rfc8265
525///
526/// The REALM attribute may be present in requests and responses.  It
527/// contains text that meets the grammar for "realm-value" as described
528/// in [RFC3261] but without the double quotes and their surrounding
529/// whitespace.  That is, it is an unquoted realm-value (and is therefore
530/// a sequence of qdtext or quoted-pair).  It MUST be a UTF-8-encoded
531/// [RFC3629] sequence of fewer than 128 characters (which can be as long
532/// as 509 bytes when encoding them and as long as 763 bytes when
533/// decoding them) and MUST have been processed using the OpaqueString
534/// profile [RFC8265].
535///
536/// Presence of the REALM attribute in a request indicates that long-term
537/// credentials are being used for authentication.  Presence in certain
538/// error responses indicates that the server wishes the client to use a
539/// long-term credential in that realm for authentication.
540pub struct Realm;
541
542impl<'a> Attribute<'a> for Realm {
543    type Error = StunError;
544    type Item = &'a str;
545
546    const KIND: AttrKind = AttrKind::Realm;
547
548    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
549        bytes.put(value.as_bytes());
550    }
551
552    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
553        Ok(std::str::from_utf8(bytes)?)
554    }
555}
556
557/// [RFC3261]: https://datatracker.ietf.org/doc/html/rfc3261
558/// [RFC7616]: https://datatracker.ietf.org/doc/html/rfc7616
559///
560/// The NONCE attribute may be present in requests and responses.  It
561/// contains a sequence of qdtext or quoted-pair, which are defined in
562/// [RFC3261].  Note that this means that the NONCE attribute will not
563/// contain the actual surrounding quote characters.  The NONCE attribute
564/// MUST be fewer than 128 characters (which can be as long as 509 bytes
565/// when encoding them and a long as 763 bytes when decoding them).  See
566/// Section 5.4 of [RFC7616] for guidance on selection of nonce values in
567/// a server.
568pub struct Nonce;
569
570impl<'a> Attribute<'a> for Nonce {
571    type Error = StunError;
572    type Item = &'a str;
573
574    const KIND: AttrKind = AttrKind::Nonce;
575
576    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
577        bytes.put(value.as_bytes());
578    }
579
580    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
581        Ok(std::str::from_utf8(bytes)?)
582    }
583}
584
585/// [RFC3629]: https://datatracker.ietf.org/doc/html/rfc3629
586///
587/// The SOFTWARE attribute contains a textual description of the software
588/// being used by the agent sending the message.  It is used by clients
589/// and servers.  Its value SHOULD include manufacturer and version
590/// number.  The attribute has no impact on operation of the protocol and
591/// serves only as a tool for diagnostic and debugging purposes.  The
592/// value of SOFTWARE is variable length.  It MUST be a UTF-8-encoded
593/// [RFC3629] sequence of fewer than 128 characters (which can be as long
594/// as 509 when encoding them and as long as 763 bytes when decoding
595/// them).
596pub struct Software;
597
598impl<'a> Attribute<'a> for Software {
599    type Error = StunError;
600    type Item = &'a str;
601
602    const KIND: AttrKind = AttrKind::Software;
603
604    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
605        bytes.put(value.as_bytes());
606    }
607
608    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
609        Ok(std::str::from_utf8(bytes)?)
610    }
611}
612
613/// [RFC2104]: https://datatracker.ietf.org/doc/html/rfc2104
614/// [RFC5769]: https://datatracker.ietf.org/doc/html/rfc5769
615///
616/// The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of
617/// the STUN message.  The MESSAGE-INTEGRITY attribute can be present in
618/// any STUN message type.  Since it uses the SHA-1 hash, the HMAC will
619/// be 20 bytes.
620///
621/// The key for the HMAC depends on which credential mechanism is in use.
622/// Section 9.1.1 defines the key for the short-term credential
623/// mechanism, and Section 9.2.2 defines the key for the long-term
624/// credential mechanism.  Other credential mechanisms MUST define the
625/// key that is used for the HMAC.
626///
627/// The text used as input to HMAC is the STUN message, up to and
628/// including the attribute preceding the MESSAGE-INTEGRITY attribute.
629/// The Length field of the STUN message header is adjusted to point to
630/// the end of the MESSAGE-INTEGRITY attribute.  The value of the
631/// MESSAGE-INTEGRITY attribute is set to a dummy value.
632///
633/// Once the computation is performed, the value of the MESSAGE-INTEGRITY
634/// attribute is filled in, and the value of the length in the STUN
635/// header is set to its correct value -- the length of the entire
636/// message.  Similarly, when validating the MESSAGE-INTEGRITY, the
637/// Length field in the STUN header must be adjusted to point to the end
638/// of the MESSAGE-INTEGRITY attribute prior to calculating the HMAC over
639/// the STUN message, up to and including the attribute preceding the
640/// MESSAGE-INTEGRITY attribute.  Such adjustment is necessary when
641/// attributes, such as FINGERPRINT and MESSAGE-INTEGRITY-SHA256, appear
642/// after MESSAGE-INTEGRITY.  See also [RFC5769] for examples of such
643/// calculations.
644pub struct MessageIntegrity;
645
646impl<'a> Attribute<'a> for MessageIntegrity {
647    type Error = StunError;
648    type Item = &'a [u8];
649
650    const KIND: AttrKind = AttrKind::MessageIntegrity;
651
652    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
653        bytes.put(value);
654    }
655
656    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
657        Ok(bytes)
658    }
659}
660
661/// [RFC5389]: https://datatracker.ietf.org/doc/html/rfc5389
662///
663/// The XOR-PEER-ADDRESS specifies the address and port of the peer as
664/// seen from the TURN server.  (For example, the peer's server-reflexive
665/// transport address if the peer is behind a NAT.)  It is encoded in the
666/// same way as XOR-MAPPED-ADDRESS [RFC5389].
667pub struct XorPeerAddress;
668
669impl<'a> Attribute<'a> for XorPeerAddress {
670    type Error = StunError;
671    type Item = SocketAddr;
672
673    const KIND: AttrKind = AttrKind::XorPeerAddress;
674
675    fn encode(value: Self::Item, bytes: &mut BytesMut, token: &'a [u8]) {
676        Addr::encode(&value, token, bytes, true)
677    }
678
679    fn decode(bytes: &'a [u8], token: &'a [u8]) -> Result<Self::Item, Self::Error> {
680        Addr::decode(bytes, token, true)
681    }
682}
683
684/// [RFC5389]: https://datatracker.ietf.org/doc/html/rfc5389
685///
686/// The XOR-RELAYED-ADDRESS is present in Allocate responses.  It
687/// specifies the address and port that the server allocated to the
688/// client.  It is encoded in the same way as XOR-MAPPED-ADDRESS
689/// [RFC5389].
690pub struct XorRelayedAddress;
691
692impl<'a> Attribute<'a> for XorRelayedAddress {
693    type Error = StunError;
694    type Item = SocketAddr;
695
696    const KIND: AttrKind = AttrKind::XorRelayedAddress;
697
698    fn encode(value: Self::Item, bytes: &mut BytesMut, token: &'a [u8]) {
699        Addr::encode(&value, token, bytes, true)
700    }
701
702    fn decode(bytes: &'a [u8], token: &'a [u8]) -> Result<Self::Item, Self::Error> {
703        Addr::decode(bytes, token, true)
704    }
705}
706
707/// [RFC3489]: https://datatracker.ietf.org/doc/html/rfc3489
708///
709/// The XOR-MAPPED-ADDRESS attribute is identical to the MAPPED-ADDRESS
710/// attribute, except that the reflexive transport address is obfuscated
711/// through the XOR function.
712///
713/// The Family field represents the IP address family and is encoded
714/// identically to the Family field in MAPPED-ADDRESS.
715///
716/// X-Port is computed by XOR'ing the mapped port with the most
717/// significant 16 bits of the magic cookie.  If the IP address family is
718/// IPv4, X-Address is computed by XOR'ing the mapped IP address with the
719/// magic cookie.  If the IP address family is IPv6, X-Address is
720/// computed by XOR'ing the mapped IP address with the concatenation of
721/// the magic cookie and the 96-bit transaction ID.  In all cases, the
722/// XOR operation works on its inputs in network byte order (that is, the
723/// order they will be encoded in the message).
724///
725/// The rules for encoding and processing the first 8 bits of the
726/// attribute's value, the rules for handling multiple occurrences of the
727/// attribute, and the rules for processing address families are the same
728/// as for MAPPED-ADDRESS.
729///
730/// Note: XOR-MAPPED-ADDRESS and MAPPED-ADDRESS differ only in their
731/// encoding of the transport address.  The former encodes the transport
732/// address by XOR'ing it with the magic cookie.  The latter encodes it
733/// directly in binary.  [RFC3489] originally specified only MAPPED-
734/// ADDRESS.  However, deployment experience found that some NATs rewrite
735/// the 32-bit binary payloads containing the NAT's public IP address,
736/// such as STUN's MAPPED-ADDRESS attribute, in the well-meaning but
737/// misguided attempt to provide a generic Application Layer Gateway
738/// (ALG) function.  Such behavior interferes with the operation of STUN
739/// and also causes failure of STUN's message-integrity checking.
740pub struct XorMappedAddress;
741
742impl<'a> Attribute<'a> for XorMappedAddress {
743    type Error = StunError;
744    type Item = SocketAddr;
745
746    const KIND: AttrKind = AttrKind::XorMappedAddress;
747
748    fn encode(value: Self::Item, bytes: &mut BytesMut, token: &'a [u8]) {
749        Addr::encode(&value, token, bytes, true)
750    }
751
752    fn decode(bytes: &'a [u8], token: &'a [u8]) -> Result<Self::Item, Self::Error> {
753        Addr::decode(bytes, token, true)
754    }
755}
756
757/// [RFC3489]: https://datatracker.ietf.org/doc/html/rfc3489
758///
759/// The MAPPED-ADDRESS attribute indicates a reflexive transport address
760/// of the client.  It consists of an 8-bit address family and a 16-bit
761/// port, followed by a fixed-length value representing the IP address.
762/// If the address family is IPv4, the address MUST be 32 bits.  If the
763/// address family is IPv6, the address MUST be 128 bits.  All fields
764/// must be in network byte order.
765///
766/// The address family can take on the following values:
767///
768/// 0x01:IPv4
769/// 0x02:IPv6
770///
771/// The first 8 bits of the MAPPED-ADDRESS MUST be set to 0 and MUST be
772/// ignored by receivers.  These bits are present for aligning parameters
773/// on natural 32-bit boundaries.
774///
775/// This attribute is used only by servers for achieving backwards
776/// compatibility with [RFC3489] clients.
777pub struct MappedAddress;
778
779impl<'a> Attribute<'a> for MappedAddress {
780    type Error = StunError;
781    type Item = SocketAddr;
782
783    const KIND: AttrKind = AttrKind::MappedAddress;
784
785    fn encode(value: Self::Item, bytes: &mut BytesMut, token: &'a [u8]) {
786        Addr::encode(&value, token, bytes, false)
787    }
788
789    fn decode(bytes: &'a [u8], token: &'a [u8]) -> Result<Self::Item, Self::Error> {
790        Addr::decode(bytes, token, false)
791    }
792}
793
794/// The RESPONSE-ORIGIN attribute is inserted by the server and indicates
795/// the source IP address and port the response was sent from.  It is
796/// useful for detecting double NAT configurations.  It is only present
797/// in Binding Responses.
798pub struct ResponseOrigin;
799
800impl<'a> Attribute<'a> for ResponseOrigin {
801    type Error = StunError;
802    type Item = SocketAddr;
803
804    const KIND: AttrKind = AttrKind::ResponseOrigin;
805
806    fn encode(value: Self::Item, bytes: &mut BytesMut, token: &'a [u8]) {
807        Addr::encode(&value, token, bytes, false)
808    }
809
810    fn decode(bytes: &'a [u8], token: &'a [u8]) -> Result<Self::Item, Self::Error> {
811        Addr::decode(bytes, token, false)
812    }
813}
814
815/// The following error codes, along with their recommended reason
816/// phrases, are defined:
817///
818/// 300  Try Alternate: The client should contact an alternate server for
819///      this request.  This error response MUST only be sent if the
820///      request included either a USERNAME or USERHASH attribute and a
821///      valid MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute;
822///      otherwise, it MUST NOT be sent and error code 400 (Bad Request)
823///      is suggested.  This error response MUST be protected with the
824///      MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute, and
825///      receivers MUST validate the MESSAGE-INTEGRITY or MESSAGE-
826///      INTEGRITY-SHA256 of this response before redirecting themselves
827///      to an alternate server.
828///      Note: Failure to generate and validate message integrity for a
829///      300 response allows an on-path attacker to falsify a 300
830///      response thus causing subsequent STUN messages to be sent to a
831///      victim.
832///      
833/// 400  Bad Request: The request was malformed.  The client SHOULD NOT
834///      retry the request without modification from the previous
835///      attempt.  The server may not be able to generate a valid
836///      MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 for this error, so
837///      the client MUST NOT expect a valid MESSAGE-INTEGRITY or MESSAGE-
838///      INTEGRITY-SHA256 attribute on this response.
839///      
840/// 401  Unauthenticated: The request did not contain the correct
841///      credentials to proceed.  The client should retry the request
842///      with proper credentials.
843///      
844/// 420  Unknown Attribute: The server received a STUN packet containing
845///      a comprehension-required attribute that it did not understand.
846///      The server MUST put this unknown attribute in the UNKNOWN-
847///      ATTRIBUTE attribute of its error response.
848///      
849/// 438  Stale Nonce: The NONCE used by the client was no longer valid.
850///      The client should retry, using the NONCE provided in the
851///      response.
852///      
853/// 500  Server Error: The server has suffered a temporary error.  The
854///      client should try again.
855const fn errno(code: u16) -> u16 {
856    ((code / 100) << 8) | (code % 100)
857}
858
859#[repr(u16)]
860#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, TryFromPrimitive)]
861pub enum ErrorKind {
862    TryAlternate = errno(300),
863    BadRequest = errno(400),
864    Unauthorized = errno(401),
865    Forbidden = errno(403),
866    UnknownAttribute = errno(420),
867    AllocationMismatch = errno(437),
868    StaleNonce = errno(438),
869    AddressFamilyNotSupported = errno(440),
870    WrongCredentials = errno(441),
871    UnsupportedTransportAddress = errno(442),
872    PeerAddressFamilyMismatch = errno(443),
873    AllocationQuotaReached = errno(486),
874    ServerError = errno(500),
875    InsufficientCapacity = errno(508),
876}
877
878/// [RFC3629]: https://datatracker.ietf.org/doc/html/rfc3629
879/// [RFC7231]: https://datatracker.ietf.org/doc/html/rfc7231
880/// [RFC3261]: https://datatracker.ietf.org/doc/html/rfc3261
881/// [RFC3629]: https://datatracker.ietf.org/doc/html/rfc3629
882///
883/// The ERROR-CODE attribute is used in error response messages.  It
884/// contains a numeric error code value in the range of 300 to 699 plus a
885/// textual reason phrase encoded in UTF-8 [RFC3629]; it is also
886/// consistent in its code assignments and semantics with SIP [RFC3261]
887/// and HTTP [RFC7231].  The reason phrase is meant for diagnostic
888/// purposes and can be anything appropriate for the error code.
889/// Recommended reason phrases for the defined error codes are included
890/// in the IANA registry for error codes.  The reason phrase MUST be a
891/// UTF-8-encoded [RFC3629] sequence of fewer than 128 characters (which
892/// can be as long as 509 bytes when encoding them or 763 bytes when
893/// decoding them).
894///
895/// ```text
896/// 0                   1                   2                   3
897/// 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
898/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
899/// |           Reserved, should be 0         |Class|     Number    |
900/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
901/// |      Reason Phrase (variable)                                ..
902/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
903///
904///              Figure 7: Format of ERROR-CODE Attribute
905/// ```
906///
907/// To facilitate processing, the class of the error code (the hundreds
908/// digit) is encoded separately from the rest of the code, as shown in
909/// Figure 7.
910///
911/// The Reserved bits SHOULD be 0 and are for alignment on 32-bit
912/// boundaries.  Receivers MUST ignore these bits.  The Class represents
913/// the hundreds digit of the error code.  The value MUST be between 3
914/// and 6.  The Number represents the binary encoding of the error code
915/// modulo 100, and its value MUST be between 0 and 99.
916#[derive(Clone, Debug)]
917pub struct Error<'a> {
918    pub code: u16,
919    pub message: &'a str,
920}
921
922impl From<ErrorKind> for Error<'_> {
923    /// create error from error type.
924    ///
925    /// # Example
926    ///
927    /// ```no_run
928    /// use turn_server::stun::attribute::*;
929    ///
930    /// Error::from(ErrorKind::TryAlternate);
931    /// ```
932    fn from(value: ErrorKind) -> Self {
933        Self {
934            code: value as u16,
935            message: value.into(),
936        }
937    }
938}
939
940impl Error<'_> {
941    /// encode the error type as bytes.
942    ///
943    /// # Test
944    ///
945    /// ```
946    /// use bytes::BytesMut;
947    /// use turn_server::stun::attribute::*;
948    ///
949    /// let buffer = [
950    ///     0x00u8, 0x00, 0x03, 0x00, 0x54, 0x72, 0x79, 0x20, 0x41, 0x6c, 0x74,
951    ///     0x65, 0x72, 0x6e, 0x61, 0x74, 0x65,
952    /// ];
953    ///
954    /// let mut buf = BytesMut::with_capacity(1280);
955    /// let error = Error::from(ErrorKind::TryAlternate);
956    /// error.encode(&mut buf);
957    /// assert_eq!(&buf[..], &buffer);
958    /// ```
959    pub fn encode(self, bytes: &mut BytesMut) {
960        bytes.put_u16(0x0000);
961        bytes.put_u16(self.code);
962        bytes.put(self.message.as_bytes());
963    }
964}
965
966impl<'a> TryFrom<&'a [u8]> for Error<'a> {
967    type Error = StunError;
968
969    /// # Test
970    ///
971    /// ```
972    /// use std::convert::TryFrom;
973    /// use turn_server::stun::attribute::*;
974    ///
975    /// let buffer = [
976    ///     0x00u8, 0x00, 0x03, 0x00, 0x54, 0x72, 0x79, 0x20, 0x41, 0x6c, 0x74,
977    ///     0x65, 0x72, 0x6e, 0x61, 0x74, 0x65,
978    /// ];
979    ///
980    /// let error = Error::try_from(&buffer[..]).unwrap();
981    /// assert_eq!(error.code, ErrorKind::TryAlternate as u16);
982    /// assert_eq!(error.message, "Try Alternate");
983    /// ```
984    fn try_from(packet: &'a [u8]) -> Result<Self, Self::Error> {
985        if packet.len() < 4 {
986            return Err(StunError::InvalidInput);
987        }
988
989        if u16::from_be_bytes(packet[..2].try_into()?) != 0x0000 {
990            return Err(StunError::InvalidInput);
991        }
992
993        Ok(Self {
994            code: u16::from_be_bytes(packet[2..4].try_into()?),
995            message: std::str::from_utf8(&packet[4..])?,
996        })
997    }
998}
999
1000impl From<ErrorKind> for &'static str {
1001    /// # Test
1002    ///
1003    /// ```
1004    /// use std::convert::Into;
1005    /// use turn_server::stun::attribute::*;
1006    ///
1007    /// let err: &'static str = ErrorKind::TryAlternate.into();
1008    /// assert_eq!(err, "Try Alternate");
1009    /// ```
1010    #[rustfmt::skip]
1011    fn from(val: ErrorKind) -> Self {
1012        match val {
1013            ErrorKind::TryAlternate => "Try Alternate",
1014            ErrorKind::BadRequest => "Bad Request",
1015            ErrorKind::Unauthorized => "Unauthorized",
1016            ErrorKind::Forbidden => "Forbidden",
1017            ErrorKind::UnknownAttribute => "Unknown Attribute",
1018            ErrorKind::AllocationMismatch => "Allocation Mismatch",
1019            ErrorKind::StaleNonce => "Stale Nonce",
1020            ErrorKind::AddressFamilyNotSupported => "Address Family not Supported",
1021            ErrorKind::WrongCredentials => "Wrong Credentials",
1022            ErrorKind::UnsupportedTransportAddress => "Unsupported Transport Address",
1023            ErrorKind::AllocationQuotaReached => "Allocation Quota Reached",
1024            ErrorKind::ServerError => "Server Error",
1025            ErrorKind::InsufficientCapacity => "Insufficient Capacity",
1026            ErrorKind::PeerAddressFamilyMismatch => "Peer Address Family Mismatch",
1027        }
1028    }
1029}
1030
1031impl Eq for Error<'_> {}
1032impl PartialEq for Error<'_> {
1033    fn eq(&self, other: &Self) -> bool {
1034        self.code == other.code
1035    }
1036}
1037
1038/// [RFC7231]: https://datatracker.ietf.org/doc/html/rfc7231
1039/// [RFC3261]: https://datatracker.ietf.org/doc/html/rfc3261
1040/// [RFC3629]: https://datatracker.ietf.org/doc/html/rfc3629
1041///
1042/// The ERROR-CODE attribute is used in error response messages.  It
1043/// contains a numeric error code value in the range of 300 to 699 plus a
1044/// textual reason phrase encoded in UTF-8 [RFC3629]; it is also
1045/// consistent in its code assignments and semantics with SIP [RFC3261]
1046/// and HTTP [RFC7231].  The reason phrase is meant for diagnostic
1047/// purposes and can be anything appropriate for the error code.
1048/// Recommended reason phrases for the defined error codes are included
1049/// in the IANA registry for error codes.  The reason phrase MUST be a
1050/// UTF-8-encoded [RFC3629] sequence of fewer than 128 characters (which
1051/// can be as long as 509 bytes when encoding them or 763 bytes when
1052/// decoding them).
1053pub struct ErrorCode;
1054
1055impl<'a> Attribute<'a> for ErrorCode {
1056    type Error = StunError;
1057    type Item = Error<'a>;
1058
1059    const KIND: AttrKind = AttrKind::ErrorCode;
1060
1061    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1062        value.encode(bytes)
1063    }
1064
1065    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1066        Error::try_from(bytes)
1067    }
1068}
1069
1070/// The LIFETIME attribute represents the duration for which the server
1071/// will maintain an allocation in the absence of a refresh.  The value
1072/// portion of this attribute is 4-bytes long and consists of a 32-bit
1073/// unsigned integral value representing the number of seconds remaining
1074/// until expiration.
1075pub struct Lifetime;
1076
1077impl<'a> Attribute<'a> for Lifetime {
1078    type Error = StunError;
1079    type Item = u32;
1080
1081    const KIND: AttrKind = AttrKind::Lifetime;
1082
1083    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1084        bytes.put_u32(value)
1085    }
1086
1087    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1088        Ok(u32::from_be_bytes(bytes.try_into()?))
1089    }
1090}
1091
1092/// This attribute is used by the client to request a specific transport
1093/// protocol for the allocated transport address.
1094///
1095/// The Protocol field specifies the desired protocol.  The codepoints
1096/// used in this field are taken from those allowed in the Protocol field
1097/// in the IPv4 header and the NextHeader field in the IPv6 header
1098/// [Protocol-Numbers].  This specification only allows the use of
1099/// codepoint 17 (User Datagram Protocol).
1100///
1101/// The RFFU field MUST be set to zero on transmission and MUST be
1102/// ignored on reception.  It is reserved for future uses.
1103pub struct ReqeestedTransport;
1104
1105impl<'a> Attribute<'a> for ReqeestedTransport {
1106    type Error = StunError;
1107    type Item = Transport;
1108
1109    const KIND: AttrKind = AttrKind::ReqeestedTransport;
1110
1111    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1112        bytes.put_u32(value as u32)
1113    }
1114
1115    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1116        let value = u32::from_be_bytes(bytes.try_into()?);
1117        Transport::try_from(value).map_err(|_| StunError::InvalidInput)
1118    }
1119}
1120
1121/// [RFC1952]: https://datatracker.ietf.org/doc/html/rfc1952
1122///
1123/// The FINGERPRINT attribute MAY be present in all STUN messages.
1124///
1125/// The value of the attribute is computed as the CRC-32 of the STUN
1126/// message up to (but excluding) the FINGERPRINT attribute itself,
1127/// XOR'ed with the 32-bit value 0x5354554e.  (The XOR operation ensures
1128/// that the FINGERPRINT test will not report a false positive on a
1129/// packet containing a CRC-32 generated by an application protocol.)
1130///
1131/// The 32-bit CRC is the one defined in ITU V.42, which has a generator
1132/// polynomial of x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 +
1133/// x^7 + x^5 + x^4 + x^2 + x + 1.  See the sample code for the CRC-32 in
1134/// Section 8 of [RFC1952].
1135///
1136/// When present, the FINGERPRINT attribute MUST be the last attribute in
1137/// the message and thus will appear after MESSAGE-INTEGRITY and MESSAGE-
1138/// INTEGRITY-SHA256.
1139///
1140/// The FINGERPRINT attribute can aid in distinguishing STUN packets from
1141/// packets of other protocols.  See Section 7.
1142///
1143/// As with MESSAGE-INTEGRITY and MESSAGE-INTEGRITY-SHA256, the CRC used
1144/// in the FINGERPRINT attribute covers the Length field from the STUN
1145/// message header.  Therefore, prior to computation of the CRC, this
1146/// value must be correct and include the CRC attribute as part of the
1147/// message length.  When using the FINGERPRINT attribute in a message,
1148/// the attribute is first placed into the message with a dummy value;
1149/// then, the CRC is computed, and the value of the attribute is updated.
1150/// If the MESSAGE-INTEGRITY or MESSAGE-INTEGRITY-SHA256 attribute is
1151/// also present, then it must be present with the correct message-
1152/// integrity value before the CRC is computed, since the CRC is done
1153/// over the value of the MESSAGE-INTEGRITY and MESSAGE-INTEGRITY-SHA256
1154/// attributes as well.
1155pub struct Fingerprint;
1156
1157impl<'a> Attribute<'a> for Fingerprint {
1158    type Error = StunError;
1159    type Item = u32;
1160
1161    const KIND: AttrKind = AttrKind::Fingerprint;
1162
1163    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1164        bytes.put_u32(value)
1165    }
1166
1167    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1168        Ok(u32::from_be_bytes(bytes.try_into()?))
1169    }
1170}
1171
1172/// The CHANNEL-NUMBER attribute contains the number of the channel.  The
1173/// value portion of this attribute is 4 bytes long and consists of a
1174/// 16-bit unsigned integer followed by a two-octet RFFU (Reserved For
1175/// Future Use) field, which MUST be set to 0 on transmission and MUST be
1176/// ignored on reception.
1177pub struct ChannelNumber;
1178
1179impl<'a> Attribute<'a> for ChannelNumber {
1180    type Error = StunError;
1181    type Item = u16;
1182
1183    const KIND: AttrKind = AttrKind::ChannelNumber;
1184
1185    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1186        bytes.put_u16(value)
1187    }
1188
1189    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1190        Ok(u16::from_be_bytes(bytes[..2].try_into()?))
1191    }
1192}
1193
1194/// The ICE-CONTROLLING attribute is present in a Binding request.  The
1195/// attribute indicates that the client believes it is currently in the
1196/// controlling role.  The content of the attribute is a 64-bit unsigned
1197/// integer in network byte order, which contains a random number.  As
1198/// for the ICE-CONTROLLED attribute, the number is used for solving role
1199/// conflicts.  An agent MUST use the same number for all Binding
1200/// requests, for all streams, within an ICE session, unless it has
1201/// received a 487 response, in which case it MUST change the number.  
1202/// The agent MAY change the number when an ICE restart occurs.
1203pub struct IceControlling;
1204
1205impl<'a> Attribute<'a> for IceControlling {
1206    type Error = StunError;
1207    type Item = u64;
1208
1209    const KIND: AttrKind = AttrKind::IceControlling;
1210
1211    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1212        bytes.put_u64(value)
1213    }
1214
1215    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1216        Ok(u64::from_be_bytes(bytes.try_into()?))
1217    }
1218}
1219
1220/// The USE-CANDIDATE attribute indicates that the candidate pair
1221/// resulting from this check will be used for transmission of data.  The
1222/// attribute has no content (the Length field of the attribute is zero);
1223/// it serves as a flag.  It has an attribute value of 0x0025..
1224pub struct UseCandidate;
1225
1226impl<'a> Attribute<'a> for UseCandidate {
1227    type Error = StunError;
1228    type Item = ();
1229
1230    const KIND: AttrKind = AttrKind::UseCandidate;
1231
1232    fn encode(_: Self::Item, _: &mut BytesMut, _: &'a [u8]) {}
1233
1234    fn decode(_: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1235        Ok(())
1236    }
1237}
1238
1239/// The ICE-CONTROLLED attribute is present in a Binding request.  The
1240/// attribute indicates that the client believes it is currently in the
1241/// controlled role.  The content of the attribute is a 64-bit unsigned
1242/// integer in network byte order, which contains a random number.  The
1243/// number is used for solving role conflicts, when it is referred to as
1244/// the "tiebreaker value".  An ICE agent MUST use the same number for
1245/// all Binding requests, for all streams, within an ICE session, unless
1246/// it has received a 487 response, in which case it MUST change the
1247/// number. The agent MAY change the number when an ICE restart occurs.
1248pub struct IceControlled;
1249
1250impl<'a> Attribute<'a> for IceControlled {
1251    type Error = StunError;
1252    type Item = u64;
1253
1254    const KIND: AttrKind = AttrKind::IceControlled;
1255
1256    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1257        bytes.put_u64(value)
1258    }
1259
1260    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1261        Ok(u64::from_be_bytes(bytes.try_into()?))
1262    }
1263}
1264
1265/// The PRIORITY attribute indicates the priority that is to be
1266/// associated with a peer-reflexive candidate, if one will be discovered
1267/// by this check.  It is a 32-bit unsigned integer and has an attribute
1268/// value of 0x0024.
1269pub struct Priority;
1270
1271impl<'a> Attribute<'a> for Priority {
1272    type Error = StunError;
1273    type Item = u32;
1274
1275    const KIND: AttrKind = AttrKind::Priority;
1276
1277    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1278        bytes.put_u32(value)
1279    }
1280
1281    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1282        Ok(u32::from_be_bytes(bytes.try_into()?))
1283    }
1284}
1285
1286/// The RESERVATION-TOKEN attribute contains a token that uniquely identifies a
1287/// relayed transport address being held in reserve by the server. The server
1288/// includes this attribute in a success response to tell the client about the
1289/// token, and the client includes this attribute in a subsequent Allocate
1290/// request to request the server use that relayed transport address for the
1291/// allocation.
1292///
1293/// The attribute value is 8 bytes and contains the token value.
1294pub struct ReservationToken;
1295
1296impl<'a> Attribute<'a> for ReservationToken {
1297    type Error = StunError;
1298    type Item = u64;
1299
1300    const KIND: AttrKind = AttrKind::ReservationToken;
1301
1302    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1303        bytes.put_u64(value)
1304    }
1305
1306    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1307        Ok(u64::from_be_bytes(bytes.try_into()?))
1308    }
1309}
1310
1311/// This attribute allows the client to request that the port in the relayed
1312/// transport address be even, and (optionally) that the server reserve the
1313/// next-higher port number.  The value portion of this attribute is 1 byte
1314/// long.
1315pub struct EvenPort;
1316
1317impl<'a> Attribute<'a> for EvenPort {
1318    type Error = StunError;
1319    type Item = bool;
1320
1321    const KIND: AttrKind = AttrKind::EvenPort;
1322
1323    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1324        bytes.put_u8(if value { 0b10000000 } else { 0b00000000 })
1325    }
1326
1327    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1328        Ok(bytes[0] == 0b10000000)
1329    }
1330}
1331
1332/// The REQUESTED-ADDRESS-FAMILY attribute is used by clients to request the
1333/// allocation of a specific address type from a server.  The following is the
1334/// format of the REQUESTED-ADDRESS-FAMILY attribute. Note that TURN attributes
1335/// are TLV (Type-Length-Value) encoded, with a 16-bit type, a 16-bit length,
1336/// and a variable-length value.
1337pub struct RequestedAddressFamily;
1338
1339impl<'a> Attribute<'a> for RequestedAddressFamily {
1340    type Error = StunError;
1341    type Item = IpFamily;
1342
1343    const KIND: AttrKind = AttrKind::RequestedAddressFamily;
1344
1345    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1346        bytes.put_u8(value as u8)
1347    }
1348
1349    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1350        IpFamily::try_from(bytes[0])
1351    }
1352}
1353
1354/// This attribute is used by clients to request the allocation of an IPv4 and
1355/// IPv6 address type from a server. It is encoded in the same way as the
1356/// REQUESTED-ADDRESS-FAMILY attribute; The ADDITIONAL-ADDRESS-FAMILY attribute
1357/// MAY be present in the Allocate request. The attribute value of 0x02 (IPv6
1358/// address) is the only valid value in Allocate request.
1359pub struct AdditionalAddressFamily;
1360
1361impl<'a> Attribute<'a> for AdditionalAddressFamily {
1362    type Error = StunError;
1363    type Item = IpFamily;
1364
1365    const KIND: AttrKind = AttrKind::AdditionalAddressFamily;
1366
1367    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1368        bytes.put_u8(value as u8)
1369    }
1370
1371    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1372        IpFamily::try_from(bytes[0])
1373    }
1374}
1375
1376/// This attribute is used by the client to request that the server set the DF
1377/// (Don't Fragment) bit in the IP header when relaying the application data
1378/// onward to the peer and for determining the server capability in Allocate
1379/// requests. This attribute has no value part, and thus, the attribute length
1380/// field is 0.
1381pub struct DontFragment;
1382
1383impl<'a> Attribute<'a> for DontFragment {
1384    type Error = StunError;
1385    type Item = ();
1386
1387    const KIND: AttrKind = AttrKind::DontFragment;
1388
1389    fn decode(_: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1390        Ok(())
1391    }
1392}
1393
1394/// The access token is issued by the authorization server.  OAuth 2.0 does not
1395/// impose any limitation on the length of the access token but if path MTU is
1396/// unknown, then STUN messages over IPv4 would need to be less than 548 bytes
1397/// (Section 7.1 of [RFC5389]).  The access token length needs to be restricted
1398/// to fit within the maximum STUN message size.  Note that the self-contained
1399/// token is opaque to the client, and the client MUST NOT examine the token.
1400/// The ACCESS-TOKEN attribute is a comprehension-required attribute (see
1401/// Section 15 from [RFC5389]).
1402pub struct AccessToken<'a> {
1403    pub nonce: &'a str,
1404    pub mac_key: &'a str,
1405    pub timestamp: u64,
1406    pub lifetime: u32,
1407}
1408
1409impl<'a> Attribute<'a> for AccessToken<'a> {
1410    type Error = StunError;
1411    type Item = AccessToken<'a>;
1412
1413    const KIND: AttrKind = AttrKind::AccessToken;
1414
1415    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1416        bytes.put_u16(value.nonce.len() as u16);
1417        bytes.extend_from_slice(value.nonce.as_bytes());
1418        bytes.put_u16(value.mac_key.len() as u16);
1419        bytes.extend_from_slice(value.mac_key.as_bytes());
1420        bytes.put_u64(value.timestamp);
1421        bytes.put_u32(value.lifetime);
1422    }
1423
1424    fn decode(mut bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1425        // nonce_length:  Length of the nonce field.  The length of nonce for AEAD
1426        // algorithms is explained in [RFC5116].
1427        let nonce_length = bytes.get_u16() as usize;
1428        if nonce_length >= bytes.len() {
1429            return Err(StunError::InvalidInput);
1430        }
1431
1432        // Nonce: Nonce (N) formation is explained in Section 3.2 of [RFC5116].
1433        let nonce = std::str::from_utf8(&bytes[..nonce_length])?;
1434
1435        // key_length:  Length of the session key in octets.  The key length of 160 bits
1436        // MUST be supported (i.e., only the 160-bit key is used by HMAC-SHA-1 for
1437        // message integrity of STUN messages).  The key length facilitates the hash
1438        // agility plan discussed in Section 16.3 of [RFC5389].
1439        let key_length = bytes.get_u16() as usize;
1440        if key_length >= bytes.len() {
1441            return Err(StunError::InvalidInput);
1442        }
1443
1444        // mac_key:  The session key generated by the authorization server.
1445        let mac_key = std::str::from_utf8(&bytes[..key_length])?;
1446        if bytes.len() < 12 {
1447            return Err(StunError::InvalidInput);
1448        }
1449
1450        Ok(Self {
1451            // timestamp:  64-bit unsigned integer field containing a timestamp. The value indicates the time since
1452            // January 1, 1970, 00:00 UTC, by using a fixed-point format.  In this format, the integer number of seconds
1453            // is contained in the first 48 bits of the field, and the remaining 16 bits indicate the number of 1/64000
1454            // fractions of a second (Native format - Unix).
1455            timestamp: bytes.get_u64(),
1456            // lifetime:  The lifetime of the access token, in seconds.  For example, the value 3600 indicates one hour.
1457            // The lifetime value MUST be greater than or equal to the 'expires_in' parameter defined in Section 4.2.2
1458            // of [RFC6749], otherwise the resource server could revoke the token, but the client would assume that the
1459            // token has not expired and would not refresh the token.
1460            lifetime: bytes.get_u32(),
1461            mac_key,
1462            nonce,
1463        })
1464    }
1465}
1466
1467/// This attribute is used by the STUN server to inform the client that
1468/// it supports third-party authorization.  This attribute value contains
1469/// the STUN server name.  The authorization server may have tie ups with
1470/// multiple STUN servers and vice versa, so the client MUST provide the
1471/// STUN server name to the authorization server so that it can select
1472/// the appropriate keying material to generate the self-contained token.
1473/// If the authorization server does not have tie up with the STUN
1474/// server, then it returns an error to the client.  If the client does
1475/// not support or is not capable of doing third-party authorization,
1476/// then it defaults to first-party authentication.  The
1477/// THIRD-PARTY-AUTHORIZATION attribute is a comprehension-optional
1478/// attribute (see Section 15 from [RFC5389]).  If the client is able to
1479/// comprehend THIRD-PARTY-AUTHORIZATION, it MUST ensure that third-party
1480/// authorization takes precedence over first-party authentication (as
1481/// explained in Section 10 of [RFC5389]).
1482pub struct ThirdPartyAuathorization;
1483
1484impl<'a> Attribute<'a> for ThirdPartyAuathorization {
1485    type Error = StunError;
1486    type Item = &'a str;
1487
1488    const KIND: AttrKind = AttrKind::ThirdPartyAuathorization;
1489
1490    fn encode(value: Self::Item, bytes: &mut BytesMut, _: &'a [u8]) {
1491        bytes.put(value.as_bytes());
1492    }
1493
1494    fn decode(bytes: &'a [u8], _: &'a [u8]) -> Result<Self::Item, Self::Error> {
1495        Ok(std::str::from_utf8(bytes)?)
1496    }
1497}