mycrl_stun/
attribute.rs

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