1#[cfg(test)]
2mod addr_test;
3
4use crate::attributes::*;
5use crate::message::*;
6use shared::error::*;
7
8use std::fmt;
9use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
10
11pub(crate) const FAMILY_IPV4: u16 = 0x01;
12pub(crate) const FAMILY_IPV6: u16 = 0x02;
13pub(crate) const IPV4LEN: usize = 4;
14pub(crate) const IPV6LEN: usize = 16;
15
16pub struct MappedAddress {
23 pub ip: IpAddr,
24 pub port: u16,
25}
26
27impl fmt::Display for MappedAddress {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 let family = match self.ip {
30 IpAddr::V4(_) => FAMILY_IPV4,
31 IpAddr::V6(_) => FAMILY_IPV6,
32 };
33 if family == FAMILY_IPV4 {
34 write!(f, "{}:{}", self.ip, self.port)
35 } else {
36 write!(f, "[{}]:{}", self.ip, self.port)
37 }
38 }
39}
40
41impl Default for MappedAddress {
42 fn default() -> Self {
43 MappedAddress {
44 ip: IpAddr::V4(Ipv4Addr::from(0)),
45 port: 0,
46 }
47 }
48}
49
50impl Setter for MappedAddress {
51 fn add_to(&self, m: &mut Message) -> Result<()> {
53 self.add_to_as(m, ATTR_MAPPED_ADDRESS)
54 }
55}
56
57impl Getter for MappedAddress {
58 fn get_from(&mut self, m: &Message) -> Result<()> {
60 self.get_from_as(m, ATTR_MAPPED_ADDRESS)
61 }
62}
63
64impl MappedAddress {
65 pub fn get_from_as(&mut self, m: &Message, t: AttrType) -> Result<()> {
67 let v = m.get(t)?;
68 if v.len() <= 4 {
69 return Err(Error::ErrUnexpectedEof);
70 }
71
72 let family = u16::from_be_bytes([v[0], v[1]]);
73 if family != FAMILY_IPV6 && family != FAMILY_IPV4 {
74 return Err(Error::Other(format!("bad value {family}")));
75 }
76 self.port = u16::from_be_bytes([v[2], v[3]]);
77
78 if family == FAMILY_IPV6 {
79 let mut ip = [0; IPV6LEN];
80 let l = std::cmp::min(ip.len(), v[4..].len());
81 ip[..l].copy_from_slice(&v[4..4 + l]);
82 self.ip = IpAddr::V6(Ipv6Addr::from(ip));
83 } else {
84 let mut ip = [0; IPV4LEN];
85 let l = std::cmp::min(ip.len(), v[4..].len());
86 ip[..l].copy_from_slice(&v[4..4 + l]);
87 self.ip = IpAddr::V4(Ipv4Addr::from(ip));
88 };
89
90 Ok(())
91 }
92
93 pub fn add_to_as(&self, m: &mut Message, t: AttrType) -> Result<()> {
95 let family = match self.ip {
96 IpAddr::V4(_) => FAMILY_IPV4,
97 IpAddr::V6(_) => FAMILY_IPV6,
98 };
99
100 let mut value = vec![0u8; 4];
101 value[0..2].copy_from_slice(&family.to_be_bytes());
103 value[2..4].copy_from_slice(&self.port.to_be_bytes());
104
105 match self.ip {
106 IpAddr::V4(ipv4) => value.extend_from_slice(&ipv4.octets()),
107 IpAddr::V6(ipv6) => value.extend_from_slice(&ipv6.octets()),
108 };
109
110 m.add(t, &value);
111 Ok(())
112 }
113}
114
115pub type AlternateServer = MappedAddress;
119
120pub type ResponseOrigin = MappedAddress;
124
125pub type OtherAddress = MappedAddress;