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}