stun_rs/attributes/stun/
xor_mapped_address.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
const XOR_MAPPED_ADDRESS: u16 = 0x0020;

crate::common::xor_socket_addr_attribute!(
    /// The `XorMappedAddress` attribute is identical to the
    /// [`MappedAddress`](crate::attributes::stun::MappedAddress)
    /// attribute, except that the reflexive transport address is
    /// obfuscated through the XOR function.
    ///
    /// # Examples
    ///```rust
    /// # use std::net::{IpAddr, Ipv4Addr, SocketAddr};
    /// # use stun_rs::attributes::stun::XorMappedAddress;
    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
    /// let attr = XorMappedAddress::from(socket);
    ///
    /// let socket = attr.socket_address();
    /// assert_eq!(socket.port(), 8080);
    /// assert_eq!(socket.is_ipv4(), true);
    ///```
    XorMappedAddress,
    XOR_MAPPED_ADDRESS,
);

#[cfg(test)]
mod tests {
    use super::*;
    use crate::common::{xor_decode, xor_encode};
    use crate::types::TRANSACTION_ID_SIZE;
    use crate::StunAttribute;
    use std::net::{IpAddr, Ipv4Addr, SocketAddr};
    use std::str::FromStr;

    fn transaction_id() -> [u8; TRANSACTION_ID_SIZE] {
        [
            0xB7, 0xE7, 0xA7, 0x01, //  }
            0xBC, 0x34, 0xD6, 0x86, //  }  Transaction ID
            0xFA, 0x87, 0xDF, 0xAE, // }
        ]
    }

    #[test]
    fn decode_ipv4() {
        // XOR Mapped Address: 192.0.2.1:32853
        let xor_buffer = [
            0x00, 0x01, 0xA1, 0x47, // Address family (IPv6) and xor'd mapped port number
            0xE1, 0x12, 0xA6, 0x43, // }  Xor'd mapped IPv6 address
        ];
        let tr = transaction_id();
        let (addr, size) = xor_decode(&tr, &xor_buffer).expect("Can not decode XorMappedAddress");
        let attr = XorMappedAddress::from(addr);

        assert_eq!(size, 8);
        assert!(attr.socket_address().is_ipv4());
        assert_eq!(attr.socket_address().port(), 32853);
        assert_eq!(attr.socket_address().to_string(), "192.0.2.1:32853");
    }

    #[test]
    fn decode_ipv6() {
        // XOR Mapped Address: `2001:db8:1234:5678:11:2233:4455:6677` port 32853
        let xor_buffer = [
            0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port number
            0x01, 0x13, 0xa9, 0xfa, // }
            0xa5, 0xd3, 0xf1, 0x79, // }  Xor'd mapped IPv6 address
            0xbc, 0x25, 0xf4, 0xb5, // }
            0xbe, 0xd2, 0xb9, 0xd9, // }
        ];
        let tr = transaction_id();
        let (addr, size) = xor_decode(&tr, &xor_buffer).expect("Can not decode XorMappedAddress");
        let attr = XorMappedAddress::from(addr);

        assert_eq!(size, 20);
        assert!(attr.socket_address().is_ipv6());
        assert_eq!(attr.socket_address().port(), 32853);
        assert_eq!(
            attr.socket_address().to_string(),
            "[2001:db8:1234:5678:11:2233:4455:6677]:32853"
        );
    }

    #[test]
    fn encode_ipv4() {
        let tr = transaction_id();
        let addr = SocketAddr::from_str("192.0.2.1:32853").expect("Can not parse SocketAddress");

        let attr = XorMappedAddress::from(addr);

        let mut buffer: [u8; 8] = [0x00; 8];
        let result = xor_encode(&tr, &attr, &mut buffer);

        assert_eq!(result, Ok(8));

        let xor_buffer = [
            0x00, 0x01, 0xA1, 0x47, // Address family (IPv6) and xor'd mapped port number
            0xE1, 0x12, 0xA6, 0x43, // }  Xor'd mapped IPv6 address
        ];
        assert_eq!(&buffer[..], &xor_buffer[..]);
    }

    #[test]
    fn encode_ipv6() {
        let tr = transaction_id();
        let addr = SocketAddr::from_str("[2001:db8:1234:5678:11:2233:4455:6677]:32853")
            .expect("Can not parse SocketAddress");
        let attr = XorMappedAddress::from(addr);

        let mut buffer: [u8; 20] = [0x00; 20];
        let result = xor_encode(&tr, &attr, &mut buffer);

        assert_eq!(result, Ok(20));

        let xor_buffer = [
            0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port number
            0x01, 0x13, 0xa9, 0xfa, // }
            0xa5, 0xd3, 0xf1, 0x79, // }  Xor'd mapped IPv6 address
            0xbc, 0x25, 0xf4, 0xb5, // }
            0xbe, 0xd2, 0xb9, 0xd9, // }
        ];
        assert_eq!(&buffer[..], &xor_buffer[..]);
    }

    #[test]
    fn xor_mapped_address_stunt_attribute() {
        let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
        let attr = StunAttribute::XorMappedAddress(XorMappedAddress::from(socket));
        assert!(attr.is_xor_mapped_address());
        assert!(attr.as_xor_mapped_address().is_ok());
        assert!(attr.as_error_code().is_err());

        assert!(attr.attribute_type().is_comprehension_required());
        assert!(!attr.attribute_type().is_comprehension_optional());

        let dbg_fmt = format!("{:?}", attr);
        assert_eq!(
            "XorMappedAddress(XorMappedAddress(127.0.0.1:8080))",
            dbg_fmt
        );
    }
}