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