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
9use alloc::boxed::Box;
10use core::net::SocketAddr;
11
12use crate::AddressFamily;
13use stun_types::{
14    attribute::*,
15    message::{StunParseError, TransactionId},
16};
17
18/// The [`XorPeerAddress`] [`Attribute`].
19///
20/// Typically used for signalling the address of the peer that a TURN server should send data
21/// towards, or has received data from.
22///
23/// Reference: [RFC5766 Section 14.3](https://datatracker.ietf.org/doc/html/rfc5766#section-14.3).
24#[derive(Debug, Clone)]
25pub struct XorPeerAddress {
26    // stored XOR-ed as we need the transaction id to get the original value
27    addr: XorSocketAddr,
28}
29
30impl AttributeStaticType for XorPeerAddress {
31    const TYPE: AttributeType = AttributeType::new(0x0012);
32}
33
34impl Attribute for XorPeerAddress {
35    fn get_type(&self) -> AttributeType {
36        Self::TYPE
37    }
38
39    fn length(&self) -> u16 {
40        self.addr.length()
41    }
42}
43
44impl AttributeWrite for XorPeerAddress {
45    fn to_raw(&self) -> RawAttribute<'_> {
46        self.addr.to_raw(self.get_type())
47    }
48    fn write_into_unchecked(&self, dest: &mut [u8]) {
49        self.write_header_unchecked(dest);
50        self.addr.write_into_unchecked(&mut dest[4..]);
51    }
52}
53
54impl AttributeFromRaw<'_> for XorPeerAddress {
55    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
56    where
57        Self: Sized,
58    {
59        Self::try_from(raw)
60    }
61}
62
63impl TryFrom<&RawAttribute<'_>> for XorPeerAddress {
64    type Error = StunParseError;
65    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
66        raw.check_type_and_len(Self::TYPE, 4..=20)?;
67        Ok(Self {
68            addr: XorSocketAddr::from_raw(raw)?,
69        })
70    }
71}
72
73impl XorPeerAddress {
74    /// Create a new [`XorPeerAddress`] [`Attribute`].
75    ///
76    /// # Examples
77    ///
78    /// ```
79    /// # use turn_types::attribute::*;
80    /// # use core::net::SocketAddr;
81    /// let addr = "127.0.0.1:1234".parse().unwrap();
82    /// let mapped_addr = XorPeerAddress::new(addr, 0x5678.into());
83    /// assert_eq!(mapped_addr.addr(0x5678.into()), addr);
84    /// ```
85    pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
86        Self {
87            addr: XorSocketAddr::new(addr, transaction),
88        }
89    }
90
91    /// Retrieve the address stored in a [`XorPeerAddress`].
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// # use turn_types::attribute::*;
97    /// # use core::net::SocketAddr;
98    /// let addr = "[::1]:1234".parse().unwrap();
99    /// let mapped_addr = XorPeerAddress::new(addr, 0x5678.into());
100    /// assert_eq!(mapped_addr.addr(0x5678.into()), addr);
101    /// ```
102    pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
103        self.addr.addr(transaction)
104    }
105}
106
107impl core::fmt::Display for XorPeerAddress {
108    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
109        write!(f, "{}: {}", self.get_type(), self.addr)
110    }
111}
112
113/// The [`XorRelayedAddress`] [`Attribute`].
114///
115/// Used to reference the address allocated on the TURN server on behalf of the client.
116///
117/// Reference: [RFC5766 Section 14.5](https://datatracker.ietf.org/doc/html/rfc5766#section-14.5).
118#[derive(Debug, Clone)]
119pub struct XorRelayedAddress {
120    addr: XorSocketAddr,
121}
122
123impl AttributeStaticType for XorRelayedAddress {
124    const TYPE: AttributeType = AttributeType::new(0x0016);
125}
126
127impl Attribute for XorRelayedAddress {
128    fn get_type(&self) -> AttributeType {
129        Self::TYPE
130    }
131
132    fn length(&self) -> u16 {
133        self.addr.length()
134    }
135}
136
137impl AttributeWrite for XorRelayedAddress {
138    fn to_raw(&self) -> RawAttribute<'_> {
139        self.addr.to_raw(self.get_type())
140    }
141    fn write_into_unchecked(&self, dest: &mut [u8]) {
142        self.write_header_unchecked(dest);
143        self.addr.write_into_unchecked(&mut dest[4..]);
144    }
145}
146
147impl AttributeFromRaw<'_> for XorRelayedAddress {
148    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
149    where
150        Self: Sized,
151    {
152        Self::try_from(raw)
153    }
154}
155
156impl TryFrom<&RawAttribute<'_>> for XorRelayedAddress {
157    type Error = StunParseError;
158    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
159        if raw.get_type() != Self::TYPE {
160            return Err(StunParseError::WrongAttributeImplementation);
161        }
162        Ok(Self {
163            addr: XorSocketAddr::from_raw(raw)?,
164        })
165    }
166}
167
168impl XorRelayedAddress {
169    /// Create a new [`XorRelayedAddress`] [`Attribute`].
170    ///
171    /// # Examples
172    ///
173    /// ```
174    /// # use turn_types::attribute::*;
175    /// # use core::net::SocketAddr;
176    /// let addr = "127.0.0.1:1234".parse().unwrap();
177    /// let mapped_addr = XorRelayedAddress::new(addr, 0x5678.into());
178    /// assert_eq!(mapped_addr.addr(0x5678.into()), addr);
179    /// ```
180    pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
181        Self {
182            addr: XorSocketAddr::new(addr, transaction),
183        }
184    }
185
186    /// Retrieve the address stored in a [`XorRelayedAddress`].
187    ///
188    /// # Examples
189    ///
190    /// ```
191    /// # use turn_types::attribute::*;
192    /// # use core::net::SocketAddr;
193    /// let addr = "[::1]:1234".parse().unwrap();
194    /// let mapped_addr = XorRelayedAddress::new(addr, 0x5678.into());
195    /// assert_eq!(mapped_addr.addr(0x5678.into()), addr);
196    /// ```
197    pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
198        self.addr.addr(transaction)
199    }
200}
201
202impl core::fmt::Display for XorRelayedAddress {
203    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
204        write!(f, "{}: {}", self.get_type(), self.addr)
205    }
206}
207
208/// The [`RequestedAddressFamily`] [`Attribute`].
209///
210/// Used to request an allocation with a specific address family.
211///
212/// Reference: [RFC6156 Section 4.1.1](https://datatracker.ietf.org/doc/html/rfc6156#section-4.1.1).
213#[derive(Debug, Clone)]
214pub struct RequestedAddressFamily {
215    family: AddressFamily,
216}
217
218impl AttributeStaticType for RequestedAddressFamily {
219    const TYPE: AttributeType = AttributeType::new(0x0017);
220}
221
222impl Attribute for RequestedAddressFamily {
223    fn get_type(&self) -> AttributeType {
224        Self::TYPE
225    }
226
227    fn length(&self) -> u16 {
228        4
229    }
230}
231
232impl AttributeWrite for RequestedAddressFamily {
233    fn to_raw(&self) -> RawAttribute<'_> {
234        let mut data = [0; 4];
235        data[0] = match self.family {
236            AddressFamily::IPV4 => 1,
237            AddressFamily::IPV6 => 2,
238        };
239        RawAttribute::new(self.get_type(), &data).into_owned()
240    }
241    fn write_into_unchecked(&self, dest: &mut [u8]) {
242        self.write_header_unchecked(dest);
243        dest[4] = match self.family {
244            AddressFamily::IPV4 => 1,
245            AddressFamily::IPV6 => 2,
246        };
247        dest[5] = 0;
248        dest[6] = 0;
249        dest[7] = 0;
250    }
251}
252
253impl AttributeFromRaw<'_> for RequestedAddressFamily {
254    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
255    where
256        Self: Sized,
257    {
258        Self::try_from(raw)
259    }
260}
261
262impl TryFrom<&RawAttribute<'_>> for RequestedAddressFamily {
263    type Error = StunParseError;
264    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
265        if raw.get_type() != Self::TYPE {
266            return Err(StunParseError::WrongAttributeImplementation);
267        }
268        raw.check_type_and_len(Self::TYPE, 4..=4)?;
269        let family = match raw.value[0] {
270            1 => AddressFamily::IPV4,
271            2 => AddressFamily::IPV6,
272            _ => return Err(StunParseError::InvalidAttributeData),
273        };
274        Ok(Self { family })
275    }
276}
277
278impl RequestedAddressFamily {
279    /// Create a new [`RequestedAddressFamily`] [`Attribute`].
280    ///
281    /// # Examples
282    ///
283    /// ```
284    /// # use turn_types::AddressFamily;
285    /// # use turn_types::attribute::*;
286    /// let requested = RequestedAddressFamily::new(AddressFamily::IPV4);
287    /// assert_eq!(requested.family(), AddressFamily::IPV4);
288    /// ```
289    pub fn new(family: AddressFamily) -> Self {
290        Self { family }
291    }
292
293    /// Retrieve the requested address family stored in a [`RequestedAddressFamily`].
294    ///
295    /// # Examples
296    ///
297    /// ```
298    /// # use turn_types::AddressFamily;
299    /// # use turn_types::attribute::*;
300    /// let requested = RequestedAddressFamily::new(AddressFamily::IPV6);
301    /// assert_eq!(requested.family(), AddressFamily::IPV6);
302    /// ```
303    pub fn family(&self) -> AddressFamily {
304        self.family
305    }
306}
307
308impl core::fmt::Display for RequestedAddressFamily {
309    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
310        write!(f, "{}: {}", self.get_type(), self.family)
311    }
312}
313
314/// The [`AdditionalAddressFamily`] [`Attribute`].
315///
316/// Used to request an allocation with an additional address family.
317///
318/// Reference: [RFC8656 Section 18.11](https://datatracker.ietf.org/doc/html/rfc8656#section-18.11).
319#[derive(Debug, Clone)]
320pub struct AdditionalAddressFamily {
321    family: AddressFamily,
322}
323
324impl AttributeStaticType for AdditionalAddressFamily {
325    const TYPE: AttributeType = AttributeType::new(0x8000);
326}
327
328impl Attribute for AdditionalAddressFamily {
329    fn get_type(&self) -> AttributeType {
330        Self::TYPE
331    }
332
333    fn length(&self) -> u16 {
334        4
335    }
336}
337
338impl AttributeWrite for AdditionalAddressFamily {
339    fn to_raw(&self) -> RawAttribute<'_> {
340        let mut data = [0; 4];
341        data[0] = match self.family {
342            AddressFamily::IPV4 => 1,
343            AddressFamily::IPV6 => 2,
344        };
345        RawAttribute::new(self.get_type(), &data).into_owned()
346    }
347    fn write_into_unchecked(&self, dest: &mut [u8]) {
348        self.write_header_unchecked(dest);
349        dest[4] = match self.family {
350            AddressFamily::IPV4 => 1,
351            AddressFamily::IPV6 => 2,
352        };
353        dest[5] = 0;
354        dest[6] = 0;
355        dest[7] = 0;
356    }
357}
358
359impl AttributeFromRaw<'_> for AdditionalAddressFamily {
360    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
361    where
362        Self: Sized,
363    {
364        Self::try_from(raw)
365    }
366}
367
368impl TryFrom<&RawAttribute<'_>> for AdditionalAddressFamily {
369    type Error = StunParseError;
370    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
371        if raw.get_type() != Self::TYPE {
372            return Err(StunParseError::WrongAttributeImplementation);
373        }
374        raw.check_type_and_len(Self::TYPE, 4..=4)?;
375        let family = match raw.value[0] {
376            // IPv4 is not supported for AdditionalAddressFamily.
377            2 => AddressFamily::IPV6,
378            _ => return Err(StunParseError::InvalidAttributeData),
379        };
380        Ok(Self { family })
381    }
382}
383
384impl AdditionalAddressFamily {
385    /// Create a new [`AdditionalAddressFamily`] [`Attribute`].
386    ///
387    /// Only IPV6 is supported.
388    ///
389    /// # Examples
390    ///
391    /// ```
392    /// # use turn_types::AddressFamily;
393    /// # use turn_types::attribute::*;
394    /// let additional = AdditionalAddressFamily::new(AddressFamily::IPV6);
395    /// assert_eq!(additional.family(), AddressFamily::IPV6);
396    /// ```
397    pub fn new(family: AddressFamily) -> Self {
398        if family == AddressFamily::IPV4 {
399            panic!("IPv4 is not supported in AdditionalAddressFamily");
400        }
401        Self { family }
402    }
403
404    /// Retrieve the requested address family stored in a [`RequestedAddressFamily`].
405    ///
406    /// # Examples
407    ///
408    /// ```
409    /// # use turn_types::AddressFamily;
410    /// # use turn_types::attribute::*;
411    /// let additional = AdditionalAddressFamily::new(AddressFamily::IPV6);
412    /// assert_eq!(additional.family(), AddressFamily::IPV6);
413    /// ```
414    pub fn family(&self) -> AddressFamily {
415        self.family
416    }
417}
418
419impl core::fmt::Display for AdditionalAddressFamily {
420    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
421        write!(f, "{}: {}", self.get_type(), self.family)
422    }
423}
424
425/// The [`AddressErrorCode`] [`Attribute`].
426///
427/// Used to notofy of errors with a particular address family.
428///
429/// Reference: [RFC8656 Section 18.12](https://datatracker.ietf.org/doc/html/rfc8656#section-18.12).
430#[derive(Debug, Clone)]
431pub struct AddressErrorCode {
432    family: AddressFamily,
433    error: ErrorCode,
434}
435
436impl AttributeStaticType for AddressErrorCode {
437    const TYPE: AttributeType = AttributeType::new(0x8001);
438}
439
440impl Attribute for AddressErrorCode {
441    fn get_type(&self) -> AttributeType {
442        Self::TYPE
443    }
444
445    fn length(&self) -> u16 {
446        self.error.length()
447    }
448}
449
450impl AttributeWrite for AddressErrorCode {
451    fn to_raw(&self) -> RawAttribute<'_> {
452        let raw = self.error.to_raw();
453        let mut data = raw.to_bytes();
454        data[4] = match self.family {
455            AddressFamily::IPV4 => 1,
456            AddressFamily::IPV6 => 2,
457        };
458        RawAttribute::new_owned(
459            self.get_type(),
460            Box::from(&data[4..4 + raw.length() as usize]),
461        )
462    }
463    fn write_into_unchecked(&self, dest: &mut [u8]) {
464        self.error.write_into_unchecked(dest);
465        self.write_header_unchecked(dest);
466        dest[4] = match self.family {
467            AddressFamily::IPV4 => 1,
468            AddressFamily::IPV6 => 2,
469        };
470    }
471}
472
473impl AttributeFromRaw<'_> for AddressErrorCode {
474    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
475    where
476        Self: Sized,
477    {
478        Self::try_from(raw)
479    }
480}
481
482impl TryFrom<&RawAttribute<'_>> for AddressErrorCode {
483    type Error = StunParseError;
484    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
485        if raw.get_type() != Self::TYPE {
486            return Err(StunParseError::WrongAttributeImplementation);
487        }
488        let tmp_raw = RawAttribute::new(ErrorCode::TYPE, &raw.value);
489        let error = ErrorCode::from_raw_ref(&tmp_raw)?;
490        let family = match raw.value[0] {
491            1 => AddressFamily::IPV4,
492            2 => AddressFamily::IPV6,
493            _ => return Err(StunParseError::InvalidAttributeData),
494        };
495        Ok(Self { family, error })
496    }
497}
498
499impl AddressErrorCode {
500    /// Create a new [`AddressErrorCode`] [`Attribute`].
501    ///
502    /// # Examples
503    ///
504    /// ```
505    /// # use turn_types::AddressFamily;
506    /// # use turn_types::attribute::*;
507    /// use stun_types::attribute::ErrorCode;
508    /// let error = ErrorCode::builder(440).build().unwrap();
509    /// let addr_error = AddressErrorCode::new(AddressFamily::IPV6, error);
510    /// assert_eq!(addr_error.family(), AddressFamily::IPV6);
511    /// ```
512    pub fn new(family: AddressFamily, error: ErrorCode) -> Self {
513        Self { family, error }
514    }
515
516    /// Retrieve the requested address family stored in an [`AddressErrorCode`].
517    ///
518    /// # Examples
519    ///
520    /// ```
521    /// # use turn_types::AddressFamily;
522    /// # use turn_types::attribute::*;
523    /// use stun_types::attribute::ErrorCode;
524    /// let error = ErrorCode::builder(440).build().unwrap();
525    /// let addr_error = AddressErrorCode::new(AddressFamily::IPV6, error);
526    /// assert_eq!(addr_error.family(), AddressFamily::IPV6);
527    /// ```
528    pub fn family(&self) -> AddressFamily {
529        self.family
530    }
531
532    /// Retrieve the error stored in an [`AddressErrorCode`].
533    ///
534    /// # Examples
535    ///
536    /// ```
537    /// # use turn_types::AddressFamily;
538    /// # use turn_types::attribute::*;
539    /// use stun_types::attribute::ErrorCode;
540    /// let error = ErrorCode::builder(440).build().unwrap();
541    /// let addr_error = AddressErrorCode::new(AddressFamily::IPV6, error.clone());
542    /// assert_eq!(addr_error.family(), AddressFamily::IPV6);
543    /// assert_eq!(addr_error.error(), &error);
544    /// ```
545    pub fn error(&self) -> &ErrorCode {
546        &self.error
547    }
548}
549
550impl core::fmt::Display for AddressErrorCode {
551    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
552        write!(f, "{}: {} {}", self.get_type(), self.family, self.error)
553    }
554}
555
556#[cfg(test)]
557mod tests {
558    use super::*;
559    use alloc::vec::Vec;
560    use byteorder::{BigEndian, ByteOrder};
561    use std::println;
562
563    #[test]
564    fn xor_peer_address() {
565        let _log = crate::tests::test_init_log();
566        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
567        let addrs = &[
568            "192.168.0.1:40000".parse().unwrap(),
569            "[fd12:3456:789a:1::1]:41000".parse().unwrap(),
570        ];
571        for addr in addrs {
572            let mapped = XorPeerAddress::new(*addr, transaction_id);
573            assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
574            assert_eq!(mapped.addr(transaction_id), *addr);
575            let raw: RawAttribute = mapped.to_raw();
576            println!("{}", raw);
577            assert_eq!(raw.get_type(), XorPeerAddress::TYPE);
578            let mapped2 = XorPeerAddress::try_from(&raw).unwrap();
579            assert_eq!(mapped2.get_type(), XorPeerAddress::TYPE);
580            assert_eq!(mapped2.addr(transaction_id), *addr);
581            // truncate by one byte
582            let mut data: Vec<_> = raw.clone().into();
583            let len = data.len();
584            BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
585            assert!(matches!(
586                XorPeerAddress::try_from(
587                    &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
588                ),
589                Err(StunParseError::Truncated {
590                    expected: _,
591                    actual: _,
592                })
593            ));
594            // provide incorrectly typed data
595            let mut data: Vec<_> = raw.into();
596            BigEndian::write_u16(&mut data[0..2], 0);
597            assert!(matches!(
598                XorPeerAddress::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
599                Err(StunParseError::WrongAttributeImplementation)
600            ));
601        }
602    }
603
604    #[test]
605    fn xor_relayed_address() {
606        let _log = crate::tests::test_init_log();
607        let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
608        let addrs = &[
609            "192.168.0.1:40000".parse().unwrap(),
610            "[fd12:3456:789a:1::1]:41000".parse().unwrap(),
611        ];
612        for addr in addrs {
613            let mapped = XorRelayedAddress::new(*addr, transaction_id);
614            assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
615            assert_eq!(mapped.addr(transaction_id), *addr);
616            let raw: RawAttribute = mapped.to_raw();
617            println!("{}", raw);
618            assert_eq!(raw.get_type(), XorRelayedAddress::TYPE);
619            let mapped2 = XorRelayedAddress::try_from(&raw).unwrap();
620            assert_eq!(mapped2.get_type(), XorRelayedAddress::TYPE);
621            assert_eq!(mapped2.addr(transaction_id), *addr);
622            // truncate by one byte
623            let mut data: Vec<_> = raw.clone().into();
624            let len = data.len();
625            BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
626            assert!(matches!(
627                XorRelayedAddress::try_from(
628                    &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
629                ),
630                Err(StunParseError::Truncated {
631                    expected: _,
632                    actual: _,
633                })
634            ));
635            // provide incorrectly typed data
636            let mut data: Vec<_> = raw.into();
637            BigEndian::write_u16(&mut data[0..2], 0);
638            assert!(matches!(
639                XorRelayedAddress::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
640                Err(StunParseError::WrongAttributeImplementation)
641            ));
642        }
643    }
644
645    #[test]
646    fn requested_address_family() {
647        let _log = crate::tests::test_init_log();
648        for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
649            let mapped = RequestedAddressFamily::new(family);
650            assert_eq!(mapped.get_type(), RequestedAddressFamily::TYPE);
651            assert_eq!(mapped.family(), family);
652            let raw: RawAttribute = mapped.to_raw();
653            println!("{}", raw);
654            assert_eq!(raw.get_type(), RequestedAddressFamily::TYPE);
655            let mapped2 = RequestedAddressFamily::try_from(&raw).unwrap();
656            assert_eq!(mapped2.get_type(), RequestedAddressFamily::TYPE);
657            assert_eq!(mapped2.family(), family);
658        }
659        let mapped = RequestedAddressFamily::new(AddressFamily::IPV4);
660        let raw: RawAttribute = mapped.to_raw();
661        // truncate by one byte
662        let mut data: Vec<_> = raw.clone().into();
663        let len = data.len();
664        BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
665        assert!(matches!(
666            RequestedAddressFamily::try_from(
667                &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
668            ),
669            Err(StunParseError::Truncated {
670                expected: _,
671                actual: _,
672            })
673        ));
674        // provide incorrectly typed data
675        let mut data: Vec<_> = raw.clone().into();
676        BigEndian::write_u16(&mut data[0..2], 0);
677        assert!(matches!(
678            RequestedAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
679            Err(StunParseError::WrongAttributeImplementation)
680        ));
681        // provide invalid address family
682        let mut data: Vec<_> = raw.clone().into();
683        data[4] = 3;
684        assert!(matches!(
685            RequestedAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
686            Err(StunParseError::InvalidAttributeData)
687        ));
688    }
689
690    #[test]
691    fn additional_address_family() {
692        let _log = crate::tests::test_init_log();
693        let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
694        assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
695        assert_eq!(mapped.family(), AddressFamily::IPV6);
696        let raw: RawAttribute = mapped.to_raw();
697        println!("{}", raw);
698        assert_eq!(raw.get_type(), AdditionalAddressFamily::TYPE);
699        let mapped2 = AdditionalAddressFamily::try_from(&raw).unwrap();
700        assert_eq!(mapped2.get_type(), AdditionalAddressFamily::TYPE);
701        assert_eq!(mapped2.family(), AddressFamily::IPV6);
702        // truncate by one byte
703        let mut data: Vec<_> = raw.clone().into();
704        let len = data.len();
705        BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
706        println!(
707            "{:?}",
708            AdditionalAddressFamily::try_from(
709                &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
710            )
711        );
712        assert!(matches!(
713            AdditionalAddressFamily::try_from(
714                &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
715            ),
716            Err(StunParseError::Truncated {
717                expected: _,
718                actual: _,
719            })
720        ));
721        // provide incorrectly typed data
722        let mut data: Vec<_> = raw.clone().into();
723        BigEndian::write_u16(&mut data[0..2], 0);
724        assert!(matches!(
725            AdditionalAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
726            Err(StunParseError::WrongAttributeImplementation)
727        ));
728        // provide invalid address family
729        let mut data: Vec<_> = raw.clone().into();
730        data[4] = 1;
731        assert!(matches!(
732            AdditionalAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
733            Err(StunParseError::InvalidAttributeData)
734        ));
735    }
736
737    #[test]
738    #[should_panic = "IPv4 is not supported"]
739    fn additional_address_family_ipv4_panic() {
740        let _log = crate::tests::test_init_log();
741        AdditionalAddressFamily::new(AddressFamily::IPV4);
742    }
743
744    #[test]
745    fn address_error_code() {
746        let _log = crate::tests::test_init_log();
747        let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
748            .build()
749            .unwrap();
750        for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
751            let mapped = AddressErrorCode::new(family, error.clone());
752            assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
753            assert_eq!(mapped.family(), family);
754            assert_eq!(mapped.error(), &error);
755            let raw: RawAttribute = mapped.to_raw();
756            println!("{}", raw);
757            assert_eq!(raw.get_type(), AddressErrorCode::TYPE);
758            let mapped2 = AddressErrorCode::try_from(&raw).unwrap();
759            assert_eq!(mapped2.get_type(), AddressErrorCode::TYPE);
760            assert_eq!(mapped2.family(), family);
761            assert_eq!(mapped2.error(), &error);
762        }
763        let mapped = AddressErrorCode::new(AddressFamily::IPV6, error);
764        let raw: RawAttribute = mapped.to_raw();
765        // provide incorrectly typed data
766        let mut data: Vec<_> = raw.clone().into();
767        BigEndian::write_u16(&mut data[0..2], 0);
768        assert!(matches!(
769            AddressErrorCode::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
770            Err(StunParseError::WrongAttributeImplementation)
771        ));
772        // provide invalid address family
773        let mut data: Vec<_> = raw.clone().into();
774        data[4] = 3;
775        assert!(matches!(
776            AddressErrorCode::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
777            Err(StunParseError::InvalidAttributeData)
778        ));
779    }
780}