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}