Skip to main content

turn_types/attribute/
address.rs

1// Copyright (C) 2025 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8//
9// SPDX-License-Identifier: MIT OR Apache-2.0
10
11use alloc::boxed::Box;
12use core::net::SocketAddr;
13
14use crate::AddressFamily;
15use stun_types::{
16    attribute::*,
17    message::{StunParseError, TransactionId},
18};
19
20/// The [`XorPeerAddress`] [`Attribute`].
21///
22/// Typically used for signalling the address of the peer that a TURN server should send data
23/// towards, or has received data from.
24///
25/// Reference: [RFC5766 Section 14.3](https://datatracker.ietf.org/doc/html/rfc5766#section-14.3).
26#[derive(Debug, Clone)]
27pub struct XorPeerAddress {
28    // stored XOR-ed as we need the transaction id to get the original value
29    addr: XorSocketAddr,
30}
31
32impl AttributeStaticType for XorPeerAddress {
33    const TYPE: AttributeType = AttributeType::new(0x0012);
34}
35
36impl Attribute for XorPeerAddress {
37    fn get_type(&self) -> AttributeType {
38        Self::TYPE
39    }
40
41    fn length(&self) -> u16 {
42        self.addr.length()
43    }
44}
45
46impl AttributeWrite for XorPeerAddress {
47    fn to_raw(&self) -> RawAttribute<'_> {
48        self.addr.to_raw(self.get_type())
49    }
50    fn write_into_unchecked(&self, dest: &mut [u8]) {
51        self.write_header_unchecked(dest);
52        self.addr.write_into_unchecked(&mut dest[4..]);
53    }
54}
55
56impl AttributeFromRaw<'_> for XorPeerAddress {
57    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
58    where
59        Self: Sized,
60    {
61        Self::try_from(raw)
62    }
63}
64
65impl TryFrom<&RawAttribute<'_>> for XorPeerAddress {
66    type Error = StunParseError;
67    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
68        raw.check_type_and_len(Self::TYPE, 4..=20)?;
69        Ok(Self {
70            addr: XorSocketAddr::from_raw(raw)?,
71        })
72    }
73}
74
75impl XorPeerAddress {
76    /// Create a new [`XorPeerAddress`] [`Attribute`].
77    ///
78    /// # Examples
79    ///
80    /// ```
81    /// # use turn_types::attribute::*;
82    /// # use core::net::SocketAddr;
83    /// let addr = "127.0.0.1:1234".parse().unwrap();
84    /// let mapped_addr = XorPeerAddress::new(addr, 0x5678.into());
85    /// assert_eq!(mapped_addr.addr(0x5678.into()), addr);
86    /// ```
87    pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
88        Self {
89            addr: XorSocketAddr::new(addr, transaction),
90        }
91    }
92
93    /// Retrieve the address stored in a [`XorPeerAddress`].
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// # use turn_types::attribute::*;
99    /// # use core::net::SocketAddr;
100    /// let addr = "[::1]:1234".parse().unwrap();
101    /// let mapped_addr = XorPeerAddress::new(addr, 0x5678.into());
102    /// assert_eq!(mapped_addr.addr(0x5678.into()), addr);
103    /// ```
104    pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
105        self.addr.addr(transaction)
106    }
107}
108
109impl core::fmt::Display for XorPeerAddress {
110    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111        write!(f, "{}: {}", self.get_type(), self.addr)
112    }
113}
114
115/// The [`XorRelayedAddress`] [`Attribute`].
116///
117/// Used to reference the address allocated on the TURN server on behalf of the client.
118///
119/// Reference: [RFC5766 Section 14.5](https://datatracker.ietf.org/doc/html/rfc5766#section-14.5).
120#[derive(Debug, Clone)]
121pub struct XorRelayedAddress {
122    addr: XorSocketAddr,
123}
124
125impl AttributeStaticType for XorRelayedAddress {
126    const TYPE: AttributeType = AttributeType::new(0x0016);
127}
128
129impl Attribute for XorRelayedAddress {
130    fn get_type(&self) -> AttributeType {
131        Self::TYPE
132    }
133
134    fn length(&self) -> u16 {
135        self.addr.length()
136    }
137}
138
139impl AttributeWrite for XorRelayedAddress {
140    fn to_raw(&self) -> RawAttribute<'_> {
141        self.addr.to_raw(self.get_type())
142    }
143    fn write_into_unchecked(&self, dest: &mut [u8]) {
144        self.write_header_unchecked(dest);
145        self.addr.write_into_unchecked(&mut dest[4..]);
146    }
147}
148
149impl AttributeFromRaw<'_> for XorRelayedAddress {
150    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
151    where
152        Self: Sized,
153    {
154        Self::try_from(raw)
155    }
156}
157
158impl TryFrom<&RawAttribute<'_>> for XorRelayedAddress {
159    type Error = StunParseError;
160    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
161        if raw.get_type() != Self::TYPE {
162            return Err(StunParseError::WrongAttributeImplementation);
163        }
164        Ok(Self {
165            addr: XorSocketAddr::from_raw(raw)?,
166        })
167    }
168}
169
170impl XorRelayedAddress {
171    /// Create a new [`XorRelayedAddress`] [`Attribute`].
172    ///
173    /// # Examples
174    ///
175    /// ```
176    /// # use turn_types::attribute::*;
177    /// # use core::net::SocketAddr;
178    /// let addr = "127.0.0.1:1234".parse().unwrap();
179    /// let mapped_addr = XorRelayedAddress::new(addr, 0x5678.into());
180    /// assert_eq!(mapped_addr.addr(0x5678.into()), addr);
181    /// ```
182    pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
183        Self {
184            addr: XorSocketAddr::new(addr, transaction),
185        }
186    }
187
188    /// Retrieve the address stored in a [`XorRelayedAddress`].
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// # use turn_types::attribute::*;
194    /// # use core::net::SocketAddr;
195    /// let addr = "[::1]:1234".parse().unwrap();
196    /// let mapped_addr = XorRelayedAddress::new(addr, 0x5678.into());
197    /// assert_eq!(mapped_addr.addr(0x5678.into()), addr);
198    /// ```
199    pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
200        self.addr.addr(transaction)
201    }
202}
203
204impl core::fmt::Display for XorRelayedAddress {
205    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
206        write!(f, "{}: {}", self.get_type(), self.addr)
207    }
208}
209
210/// The [`RequestedAddressFamily`] [`Attribute`].
211///
212/// Used to request an allocation with a specific address family.
213///
214/// Reference: [RFC6156 Section 4.1.1](https://datatracker.ietf.org/doc/html/rfc6156#section-4.1.1).
215#[derive(Debug, Clone)]
216pub struct RequestedAddressFamily {
217    family: AddressFamily,
218}
219
220impl AttributeStaticType for RequestedAddressFamily {
221    const TYPE: AttributeType = AttributeType::new(0x0017);
222}
223
224impl Attribute for RequestedAddressFamily {
225    fn get_type(&self) -> AttributeType {
226        Self::TYPE
227    }
228
229    fn length(&self) -> u16 {
230        4
231    }
232}
233
234impl AttributeWrite for RequestedAddressFamily {
235    fn to_raw(&self) -> RawAttribute<'_> {
236        let mut data = [0; 4];
237        data[0] = match self.family {
238            AddressFamily::IPV4 => 1,
239            AddressFamily::IPV6 => 2,
240        };
241        RawAttribute::new(self.get_type(), &data).into_owned()
242    }
243    fn write_into_unchecked(&self, dest: &mut [u8]) {
244        self.write_header_unchecked(dest);
245        dest[4] = match self.family {
246            AddressFamily::IPV4 => 1,
247            AddressFamily::IPV6 => 2,
248        };
249        dest[5] = 0;
250        dest[6] = 0;
251        dest[7] = 0;
252    }
253}
254
255impl AttributeFromRaw<'_> for RequestedAddressFamily {
256    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
257    where
258        Self: Sized,
259    {
260        Self::try_from(raw)
261    }
262}
263
264impl TryFrom<&RawAttribute<'_>> for RequestedAddressFamily {
265    type Error = StunParseError;
266    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
267        if raw.get_type() != Self::TYPE {
268            return Err(StunParseError::WrongAttributeImplementation);
269        }
270        raw.check_type_and_len(Self::TYPE, 4..=4)?;
271        let family = match raw.value[0] {
272            1 => AddressFamily::IPV4,
273            2 => AddressFamily::IPV6,
274            _ => return Err(StunParseError::InvalidAttributeData),
275        };
276        Ok(Self { family })
277    }
278}
279
280impl RequestedAddressFamily {
281    /// Create a new [`RequestedAddressFamily`] [`Attribute`].
282    ///
283    /// # Examples
284    ///
285    /// ```
286    /// # use turn_types::AddressFamily;
287    /// # use turn_types::attribute::*;
288    /// let requested = RequestedAddressFamily::new(AddressFamily::IPV4);
289    /// assert_eq!(requested.family(), AddressFamily::IPV4);
290    /// ```
291    pub fn new(family: AddressFamily) -> Self {
292        Self { family }
293    }
294
295    /// Retrieve the requested address family stored in a [`RequestedAddressFamily`].
296    ///
297    /// # Examples
298    ///
299    /// ```
300    /// # use turn_types::AddressFamily;
301    /// # use turn_types::attribute::*;
302    /// let requested = RequestedAddressFamily::new(AddressFamily::IPV6);
303    /// assert_eq!(requested.family(), AddressFamily::IPV6);
304    /// ```
305    pub fn family(&self) -> AddressFamily {
306        self.family
307    }
308}
309
310impl core::fmt::Display for RequestedAddressFamily {
311    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
312        write!(f, "{}: {}", self.get_type(), self.family)
313    }
314}
315
316/// The [`AdditionalAddressFamily`] [`Attribute`].
317///
318/// Used to request an allocation with an additional address family.
319///
320/// Reference: [RFC8656 Section 18.11](https://datatracker.ietf.org/doc/html/rfc8656#section-18.11).
321#[derive(Debug, Clone)]
322pub struct AdditionalAddressFamily {
323    family: AddressFamily,
324}
325
326impl AttributeStaticType for AdditionalAddressFamily {
327    const TYPE: AttributeType = AttributeType::new(0x8000);
328}
329
330impl Attribute for AdditionalAddressFamily {
331    fn get_type(&self) -> AttributeType {
332        Self::TYPE
333    }
334
335    fn length(&self) -> u16 {
336        4
337    }
338}
339
340impl AttributeWrite for AdditionalAddressFamily {
341    fn to_raw(&self) -> RawAttribute<'_> {
342        let mut data = [0; 4];
343        data[0] = match self.family {
344            AddressFamily::IPV4 => 1,
345            AddressFamily::IPV6 => 2,
346        };
347        RawAttribute::new(self.get_type(), &data).into_owned()
348    }
349    fn write_into_unchecked(&self, dest: &mut [u8]) {
350        self.write_header_unchecked(dest);
351        dest[4] = match self.family {
352            AddressFamily::IPV4 => 1,
353            AddressFamily::IPV6 => 2,
354        };
355        dest[5] = 0;
356        dest[6] = 0;
357        dest[7] = 0;
358    }
359}
360
361impl AttributeFromRaw<'_> for AdditionalAddressFamily {
362    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
363    where
364        Self: Sized,
365    {
366        Self::try_from(raw)
367    }
368}
369
370impl TryFrom<&RawAttribute<'_>> for AdditionalAddressFamily {
371    type Error = StunParseError;
372    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
373        if raw.get_type() != Self::TYPE {
374            return Err(StunParseError::WrongAttributeImplementation);
375        }
376        raw.check_type_and_len(Self::TYPE, 4..=4)?;
377        let family = match raw.value[0] {
378            // IPv4 is not supported for AdditionalAddressFamily.
379            2 => AddressFamily::IPV6,
380            _ => return Err(StunParseError::InvalidAttributeData),
381        };
382        Ok(Self { family })
383    }
384}
385
386impl AdditionalAddressFamily {
387    /// Create a new [`AdditionalAddressFamily`] [`Attribute`].
388    ///
389    /// Only IPV6 is supported.
390    ///
391    /// # Examples
392    ///
393    /// ```
394    /// # use turn_types::AddressFamily;
395    /// # use turn_types::attribute::*;
396    /// let additional = AdditionalAddressFamily::new(AddressFamily::IPV6);
397    /// assert_eq!(additional.family(), AddressFamily::IPV6);
398    /// ```
399    pub fn new(family: AddressFamily) -> Self {
400        if family == AddressFamily::IPV4 {
401            panic!("IPv4 is not supported in AdditionalAddressFamily");
402        }
403        Self { family }
404    }
405
406    /// Retrieve the requested address family stored in a [`RequestedAddressFamily`].
407    ///
408    /// # Examples
409    ///
410    /// ```
411    /// # use turn_types::AddressFamily;
412    /// # use turn_types::attribute::*;
413    /// let additional = AdditionalAddressFamily::new(AddressFamily::IPV6);
414    /// assert_eq!(additional.family(), AddressFamily::IPV6);
415    /// ```
416    pub fn family(&self) -> AddressFamily {
417        self.family
418    }
419}
420
421impl core::fmt::Display for AdditionalAddressFamily {
422    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
423        write!(f, "{}: {}", self.get_type(), self.family)
424    }
425}
426
427/// The [`AddressErrorCode`] [`Attribute`].
428///
429/// Used to notofy of errors with a particular address family.
430///
431/// Reference: [RFC8656 Section 18.12](https://datatracker.ietf.org/doc/html/rfc8656#section-18.12).
432#[derive(Debug, Clone)]
433pub struct AddressErrorCode {
434    family: AddressFamily,
435    error: ErrorCode,
436}
437
438impl AttributeStaticType for AddressErrorCode {
439    const TYPE: AttributeType = AttributeType::new(0x8001);
440}
441
442impl Attribute for AddressErrorCode {
443    fn get_type(&self) -> AttributeType {
444        Self::TYPE
445    }
446
447    fn length(&self) -> u16 {
448        self.error.length()
449    }
450}
451
452impl AttributeWrite for AddressErrorCode {
453    fn to_raw(&self) -> RawAttribute<'_> {
454        let raw = self.error.to_raw();
455        let mut data = raw.to_bytes();
456        data[4] = match self.family {
457            AddressFamily::IPV4 => 1,
458            AddressFamily::IPV6 => 2,
459        };
460        RawAttribute::new_owned(
461            self.get_type(),
462            Box::from(&data[4..4 + raw.length() as usize]),
463        )
464    }
465    fn write_into_unchecked(&self, dest: &mut [u8]) {
466        self.error.write_into_unchecked(dest);
467        self.write_header_unchecked(dest);
468        dest[4] = match self.family {
469            AddressFamily::IPV4 => 1,
470            AddressFamily::IPV6 => 2,
471        };
472    }
473}
474
475impl AttributeFromRaw<'_> for AddressErrorCode {
476    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
477    where
478        Self: Sized,
479    {
480        Self::try_from(raw)
481    }
482}
483
484impl TryFrom<&RawAttribute<'_>> for AddressErrorCode {
485    type Error = StunParseError;
486    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
487        if raw.get_type() != Self::TYPE {
488            return Err(StunParseError::WrongAttributeImplementation);
489        }
490        let tmp_raw = RawAttribute::new(ErrorCode::TYPE, &raw.value);
491        let error = ErrorCode::from_raw_ref(&tmp_raw)?;
492        let family = match raw.value[0] {
493            1 => AddressFamily::IPV4,
494            2 => AddressFamily::IPV6,
495            _ => return Err(StunParseError::InvalidAttributeData),
496        };
497        Ok(Self { family, error })
498    }
499}
500
501impl AddressErrorCode {
502    /// Create a new [`AddressErrorCode`] [`Attribute`].
503    ///
504    /// # Examples
505    ///
506    /// ```
507    /// # use turn_types::AddressFamily;
508    /// # use turn_types::attribute::*;
509    /// use stun_types::attribute::ErrorCode;
510    /// let error = ErrorCode::builder(440).build().unwrap();
511    /// let addr_error = AddressErrorCode::new(AddressFamily::IPV6, error);
512    /// assert_eq!(addr_error.family(), AddressFamily::IPV6);
513    /// ```
514    pub fn new(family: AddressFamily, error: ErrorCode) -> Self {
515        Self { family, error }
516    }
517
518    /// Retrieve the requested address family stored in an [`AddressErrorCode`].
519    ///
520    /// # Examples
521    ///
522    /// ```
523    /// # use turn_types::AddressFamily;
524    /// # use turn_types::attribute::*;
525    /// use stun_types::attribute::ErrorCode;
526    /// let error = ErrorCode::builder(440).build().unwrap();
527    /// let addr_error = AddressErrorCode::new(AddressFamily::IPV6, error);
528    /// assert_eq!(addr_error.family(), AddressFamily::IPV6);
529    /// ```
530    pub fn family(&self) -> AddressFamily {
531        self.family
532    }
533
534    /// Retrieve the error stored in an [`AddressErrorCode`].
535    ///
536    /// # Examples
537    ///
538    /// ```
539    /// # use turn_types::AddressFamily;
540    /// # use turn_types::attribute::*;
541    /// use stun_types::attribute::ErrorCode;
542    /// let error = ErrorCode::builder(440).build().unwrap();
543    /// let addr_error = AddressErrorCode::new(AddressFamily::IPV6, error.clone());
544    /// assert_eq!(addr_error.family(), AddressFamily::IPV6);
545    /// assert_eq!(addr_error.error(), &error);
546    /// ```
547    pub fn error(&self) -> &ErrorCode {
548        &self.error
549    }
550}
551
552impl core::fmt::Display for AddressErrorCode {
553    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
554        write!(f, "{}: {} {}", self.get_type(), self.family, self.error)
555    }
556}
557
558#[cfg(test)]
559mod tests {
560    use super::*;
561    use alloc::{vec, vec::Vec};
562    use byteorder::{BigEndian, ByteOrder};
563    use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
564    use tracing::trace;
565
566    const ADDRS: [SocketAddr; 2] = [
567        SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)), 40000),
568        SocketAddr::new(
569            IpAddr::V6(Ipv6Addr::new(
570                0xfd12, 0x3456, 0x789a, 0x01, 0x0, 0x0, 0x0, 0x1,
571            )),
572            41000,
573        ),
574    ];
575
576    #[test]
577    fn xor_peer_address_raw() {
578        let _log = crate::tests::test_init_log();
579        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
580        for addr in ADDRS {
581            let mapped = XorPeerAddress::new(addr, transaction_id);
582            assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
583            assert_eq!(mapped.addr(transaction_id), addr);
584            let raw: RawAttribute = mapped.to_raw();
585            trace!("{}", raw);
586            assert_eq!(raw.get_type(), XorPeerAddress::TYPE);
587            let mapped2 = XorPeerAddress::try_from(&raw).unwrap();
588            assert_eq!(mapped2.get_type(), XorPeerAddress::TYPE);
589            assert_eq!(mapped2.addr(transaction_id), addr);
590        }
591    }
592
593    #[test]
594    fn xor_peer_address_raw_short() {
595        let _log = crate::tests::test_init_log();
596        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
597        for addr in ADDRS {
598            let mapped = XorPeerAddress::new(addr, transaction_id);
599            assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
600            assert_eq!(mapped.addr(transaction_id), addr);
601            let raw: RawAttribute = mapped.to_raw();
602            // truncate by one byte
603            let mut data: Vec<_> = raw.clone().into();
604            let len = data.len();
605            BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
606            assert!(matches!(
607                XorPeerAddress::try_from(
608                    &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
609                ),
610                Err(StunParseError::Truncated {
611                    expected: _,
612                    actual: _,
613                })
614            ));
615        }
616    }
617
618    #[test]
619    fn xor_peer_address_raw_wrong_type() {
620        let _log = crate::tests::test_init_log();
621        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
622        for addr in ADDRS {
623            let mapped = XorPeerAddress::new(addr, transaction_id);
624            assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
625            assert_eq!(mapped.addr(transaction_id), addr);
626            let raw: RawAttribute = mapped.to_raw();
627            // provide incorrectly typed data
628            let mut data: Vec<_> = raw.into();
629            BigEndian::write_u16(&mut data[0..2], 0);
630            assert!(matches!(
631                XorPeerAddress::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
632                Err(StunParseError::WrongAttributeImplementation)
633            ));
634        }
635    }
636
637    #[test]
638    fn xor_peer_address_write_into() {
639        let _log = crate::tests::test_init_log();
640        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
641        for addr in ADDRS {
642            let mapped = XorPeerAddress::new(addr, transaction_id);
643            assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
644            assert_eq!(mapped.addr(transaction_id), addr);
645            let raw: RawAttribute = mapped.to_raw();
646            let mut dest = vec![0; raw.padded_len()];
647            mapped.write_into(&mut dest).unwrap();
648            let raw = RawAttribute::from_bytes(&dest).unwrap();
649            let mapped2 = XorPeerAddress::try_from(&raw).unwrap();
650            assert_eq!(mapped2.addr(transaction_id), addr);
651        }
652    }
653
654    #[test]
655    #[should_panic = "out of range"]
656    fn xor_peer_address_write_into_unchecked() {
657        let _log = crate::tests::test_init_log();
658        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
659        let addr = ADDRS[0];
660        let mapped = XorPeerAddress::new(addr, transaction_id);
661        assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
662        assert_eq!(mapped.addr(transaction_id), addr);
663        let raw: RawAttribute = mapped.to_raw();
664        let mut dest = vec![0; raw.padded_len() - 1];
665        mapped.write_into_unchecked(&mut dest);
666    }
667
668    #[test]
669    fn xor_relayed_address_raw() {
670        let _log = crate::tests::test_init_log();
671        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
672        for addr in ADDRS {
673            let mapped = XorRelayedAddress::new(addr, transaction_id);
674            assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
675            assert_eq!(mapped.addr(transaction_id), addr);
676            let raw: RawAttribute = mapped.to_raw();
677            trace!("{}", raw);
678            assert_eq!(raw.get_type(), XorRelayedAddress::TYPE);
679            let mapped2 = XorRelayedAddress::try_from(&raw).unwrap();
680            assert_eq!(mapped2.get_type(), XorRelayedAddress::TYPE);
681            assert_eq!(mapped2.addr(transaction_id), addr);
682        }
683    }
684
685    #[test]
686    fn xor_relayed_address_raw_short() {
687        let _log = crate::tests::test_init_log();
688        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
689        for addr in ADDRS {
690            let mapped = XorRelayedAddress::new(addr, transaction_id);
691            assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
692            assert_eq!(mapped.addr(transaction_id), addr);
693            let raw: RawAttribute = mapped.to_raw();
694            // truncate by one byte
695            let mut data: Vec<_> = raw.clone().into();
696            let len = data.len();
697            BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
698            assert!(matches!(
699                XorRelayedAddress::try_from(
700                    &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
701                ),
702                Err(StunParseError::Truncated {
703                    expected: _,
704                    actual: _,
705                })
706            ));
707        }
708    }
709
710    #[test]
711    fn xor_relayed_address_raw_wrong_type() {
712        let _log = crate::tests::test_init_log();
713        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
714        for addr in ADDRS {
715            let mapped = XorRelayedAddress::new(addr, transaction_id);
716            assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
717            assert_eq!(mapped.addr(transaction_id), addr);
718            let raw: RawAttribute = mapped.to_raw();
719            // provide incorrectly typed data
720            let mut data: Vec<_> = raw.into();
721            BigEndian::write_u16(&mut data[0..2], 0);
722            assert!(matches!(
723                XorRelayedAddress::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
724                Err(StunParseError::WrongAttributeImplementation)
725            ));
726        }
727    }
728
729    #[test]
730    fn xor_relayed_address_write_into() {
731        let _log = crate::tests::test_init_log();
732        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
733        for addr in ADDRS {
734            let mapped = XorRelayedAddress::new(addr, transaction_id);
735            assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
736            assert_eq!(mapped.addr(transaction_id), addr);
737            let raw: RawAttribute = mapped.to_raw();
738            let mut dest = vec![0; raw.padded_len()];
739            mapped.write_into(&mut dest).unwrap();
740            let raw = RawAttribute::from_bytes(&dest).unwrap();
741            let mapped2 = XorRelayedAddress::try_from(&raw).unwrap();
742            assert_eq!(mapped2.addr(transaction_id), addr);
743        }
744    }
745
746    #[test]
747    #[should_panic = "out of range"]
748    fn xor_relayed_address_write_into_unchecked() {
749        let _log = crate::tests::test_init_log();
750        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
751        let addr = ADDRS[0];
752        let mapped = XorRelayedAddress::new(addr, transaction_id);
753        assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
754        assert_eq!(mapped.addr(transaction_id), addr);
755        let raw: RawAttribute = mapped.to_raw();
756        let mut dest = vec![0; raw.padded_len() - 1];
757        mapped.write_into_unchecked(&mut dest);
758    }
759
760    #[test]
761    fn requested_address_family_raw() {
762        let _log = crate::tests::test_init_log();
763        for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
764            let mapped = RequestedAddressFamily::new(family);
765            assert_eq!(mapped.get_type(), RequestedAddressFamily::TYPE);
766            assert_eq!(mapped.family(), family);
767            let raw: RawAttribute = mapped.to_raw();
768            trace!("{}", raw);
769            assert_eq!(raw.get_type(), RequestedAddressFamily::TYPE);
770            let mapped2 = RequestedAddressFamily::try_from(&raw).unwrap();
771            assert_eq!(mapped2.get_type(), RequestedAddressFamily::TYPE);
772            assert_eq!(mapped2.family(), family);
773        }
774    }
775
776    #[test]
777    fn requested_address_family_raw_short() {
778        let _log = crate::tests::test_init_log();
779        let mapped = RequestedAddressFamily::new(AddressFamily::IPV4);
780        let raw: RawAttribute = mapped.to_raw();
781        // truncate by one byte
782        let mut data: Vec<_> = raw.clone().into();
783        let len = data.len();
784        BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
785        assert!(matches!(
786            RequestedAddressFamily::try_from(
787                &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
788            ),
789            Err(StunParseError::Truncated {
790                expected: _,
791                actual: _,
792            })
793        ));
794    }
795
796    #[test]
797    fn requested_address_family_raw_wrong_type() {
798        let _log = crate::tests::test_init_log();
799        let mapped = RequestedAddressFamily::new(AddressFamily::IPV4);
800        let raw: RawAttribute = mapped.to_raw();
801        // provide incorrectly typed data
802        let mut data: Vec<_> = raw.clone().into();
803        BigEndian::write_u16(&mut data[0..2], 0);
804        assert!(matches!(
805            RequestedAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
806            Err(StunParseError::WrongAttributeImplementation)
807        ));
808    }
809
810    #[test]
811    fn requested_address_family_raw_wrong_family() {
812        let _log = crate::tests::test_init_log();
813        let mapped = RequestedAddressFamily::new(AddressFamily::IPV4);
814        let raw: RawAttribute = mapped.to_raw();
815        // provide invalid address family
816        let mut data: Vec<_> = raw.clone().into();
817        data[4] = 3;
818        assert!(matches!(
819            RequestedAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
820            Err(StunParseError::InvalidAttributeData)
821        ));
822    }
823
824    #[test]
825    fn requested_address_family_write_into() {
826        let _log = crate::tests::test_init_log();
827        for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
828            let mapped = RequestedAddressFamily::new(family);
829            assert_eq!(mapped.get_type(), RequestedAddressFamily::TYPE);
830            assert_eq!(mapped.family(), family);
831            let raw: RawAttribute = mapped.to_raw();
832            let mut dest = vec![0; raw.padded_len()];
833            mapped.write_into(&mut dest).unwrap();
834            let raw = RawAttribute::from_bytes(&dest).unwrap();
835            let mapped2 = RequestedAddressFamily::try_from(&raw).unwrap();
836            assert_eq!(mapped2.get_type(), RequestedAddressFamily::TYPE);
837            assert_eq!(mapped2.family(), family);
838        }
839    }
840
841    #[test]
842    #[should_panic = "out of bounds"]
843    fn requested_address_family_write_into_unchecked() {
844        let _log = crate::tests::test_init_log();
845        let mapped = RequestedAddressFamily::new(AddressFamily::IPV6);
846        let raw: RawAttribute = mapped.to_raw();
847        let mut dest = vec![0; raw.padded_len() - 1];
848        mapped.write_into_unchecked(&mut dest);
849    }
850
851    #[test]
852    fn additional_address_family_raw() {
853        let _log = crate::tests::test_init_log();
854        let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
855        assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
856        assert_eq!(mapped.family(), AddressFamily::IPV6);
857        let raw: RawAttribute = mapped.to_raw();
858        trace!("{}", raw);
859        assert_eq!(raw.get_type(), AdditionalAddressFamily::TYPE);
860        let mapped2 = AdditionalAddressFamily::try_from(&raw).unwrap();
861        assert_eq!(mapped2.get_type(), AdditionalAddressFamily::TYPE);
862        assert_eq!(mapped2.family(), AddressFamily::IPV6);
863    }
864
865    #[test]
866    fn additional_address_family_raw_short() {
867        let _log = crate::tests::test_init_log();
868        let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
869        assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
870        assert_eq!(mapped.family(), AddressFamily::IPV6);
871        let raw: RawAttribute = mapped.to_raw();
872        // truncate by one byte
873        let mut data: Vec<_> = raw.clone().into();
874        let len = data.len();
875        BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
876        assert!(matches!(
877            AdditionalAddressFamily::try_from(
878                &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
879            ),
880            Err(StunParseError::Truncated {
881                expected: _,
882                actual: _,
883            })
884        ));
885    }
886
887    #[test]
888    fn additional_address_family_raw_wrong_type() {
889        let _log = crate::tests::test_init_log();
890        let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
891        assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
892        assert_eq!(mapped.family(), AddressFamily::IPV6);
893        let raw: RawAttribute = mapped.to_raw();
894        // provide incorrectly typed data
895        let mut data: Vec<_> = raw.clone().into();
896        BigEndian::write_u16(&mut data[0..2], 0);
897        assert!(matches!(
898            AdditionalAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
899            Err(StunParseError::WrongAttributeImplementation)
900        ));
901    }
902
903    #[test]
904    fn additional_address_family_raw_wrong_family() {
905        let _log = crate::tests::test_init_log();
906        let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
907        assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
908        assert_eq!(mapped.family(), AddressFamily::IPV6);
909        let raw: RawAttribute = mapped.to_raw();
910        // provide invalid address family
911        let mut data: Vec<_> = raw.clone().into();
912        data[4] = 1;
913        assert!(matches!(
914            AdditionalAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
915            Err(StunParseError::InvalidAttributeData)
916        ));
917    }
918
919    #[test]
920    #[should_panic = "IPv4 is not supported"]
921    fn additional_address_family_ipv4_panic() {
922        let _log = crate::tests::test_init_log();
923        AdditionalAddressFamily::new(AddressFamily::IPV4);
924    }
925
926    #[test]
927    fn additional_address_family_write_into() {
928        let _log = crate::tests::test_init_log();
929        let family = AddressFamily::IPV6;
930        let mapped = AdditionalAddressFamily::new(family);
931        assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
932        assert_eq!(mapped.family(), family);
933        let raw: RawAttribute = mapped.to_raw();
934        let mut dest = vec![0; raw.padded_len()];
935        mapped.write_into(&mut dest).unwrap();
936        let raw = RawAttribute::from_bytes(&dest).unwrap();
937        let mapped2 = AdditionalAddressFamily::try_from(&raw).unwrap();
938        assert_eq!(mapped2.get_type(), AdditionalAddressFamily::TYPE);
939        assert_eq!(mapped2.family(), family);
940    }
941
942    #[test]
943    #[should_panic = "out of bounds"]
944    fn additional_address_fmaily_write_into_unchecked() {
945        let _log = crate::tests::test_init_log();
946        let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
947        let raw: RawAttribute = mapped.to_raw();
948        let mut dest = vec![0; raw.padded_len() - 1];
949        mapped.write_into_unchecked(&mut dest);
950    }
951
952    #[test]
953    fn address_error_code() {
954        let _log = crate::tests::test_init_log();
955        let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
956            .build()
957            .unwrap();
958        for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
959            let mapped = AddressErrorCode::new(family, error.clone());
960            assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
961            assert_eq!(mapped.family(), family);
962            assert_eq!(mapped.error(), &error);
963            let raw: RawAttribute = mapped.to_raw();
964            trace!("{}", raw);
965            assert_eq!(raw.get_type(), AddressErrorCode::TYPE);
966            let mapped2 = AddressErrorCode::try_from(&raw).unwrap();
967            assert_eq!(mapped2.get_type(), AddressErrorCode::TYPE);
968            assert_eq!(mapped2.family(), family);
969            assert_eq!(mapped2.error(), &error);
970        }
971    }
972
973    #[test]
974    fn address_error_code_raw_wrong_type() {
975        let _log = crate::tests::test_init_log();
976        let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
977            .build()
978            .unwrap();
979        for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
980            let mapped = AddressErrorCode::new(family, error.clone());
981            assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
982            assert_eq!(mapped.family(), family);
983            assert_eq!(mapped.error(), &error);
984            let raw: RawAttribute = mapped.to_raw();
985            // provide incorrectly typed data
986            let mut data: Vec<_> = raw.clone().into();
987            BigEndian::write_u16(&mut data[0..2], 0);
988            assert!(matches!(
989                AddressErrorCode::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
990                Err(StunParseError::WrongAttributeImplementation)
991            ));
992        }
993    }
994
995    #[test]
996    fn address_error_code_raw_wrong_family() {
997        let _log = crate::tests::test_init_log();
998        let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
999            .build()
1000            .unwrap();
1001        for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
1002            let mapped = AddressErrorCode::new(family, error.clone());
1003            assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
1004            assert_eq!(mapped.family(), family);
1005            assert_eq!(mapped.error(), &error);
1006            let raw: RawAttribute = mapped.to_raw();
1007            // provide invalid address family
1008            let mut data: Vec<_> = raw.clone().into();
1009            data[4] = 3;
1010            assert!(matches!(
1011                AddressErrorCode::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
1012                Err(StunParseError::InvalidAttributeData)
1013            ));
1014        }
1015    }
1016
1017    #[test]
1018    fn address_error_code_write_into() {
1019        let _log = crate::tests::test_init_log();
1020        let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
1021            .build()
1022            .unwrap();
1023        for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
1024            let mapped = AddressErrorCode::new(family, error.clone());
1025            assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
1026            assert_eq!(mapped.family(), family);
1027            assert_eq!(mapped.error(), &error);
1028            let raw: RawAttribute = mapped.to_raw();
1029            let mut dest = vec![0; raw.padded_len()];
1030            mapped.write_into(&mut dest).unwrap();
1031            let raw = RawAttribute::from_bytes(&dest).unwrap();
1032            let mapped2 = AddressErrorCode::try_from(&raw).unwrap();
1033            assert_eq!(mapped2.get_type(), AddressErrorCode::TYPE);
1034            assert_eq!(mapped2.family(), family);
1035            assert_eq!(mapped.error(), &error);
1036        }
1037    }
1038
1039    #[test]
1040    #[should_panic = "out of range"]
1041    fn address_error_code_write_into_unchecked() {
1042        let _log = crate::tests::test_init_log();
1043        let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
1044            .build()
1045            .unwrap();
1046        let mapped = AddressErrorCode::new(AddressFamily::IPV6, error.clone());
1047        let raw: RawAttribute = mapped.to_raw();
1048        let mut dest = vec![0; raw.padded_len() - 1];
1049        mapped.write_into_unchecked(&mut dest);
1050    }
1051}