xref: /webrtc/stun/src/addr.rs (revision 5d8fe953)
1 #[cfg(test)]
2 mod addr_test;
3 
4 use crate::attributes::*;
5 use crate::error::*;
6 use crate::message::*;
7 
8 use std::fmt;
9 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
10 
11 pub(crate) const FAMILY_IPV4: u16 = 0x01;
12 pub(crate) const FAMILY_IPV6: u16 = 0x02;
13 pub(crate) const IPV4LEN: usize = 4;
14 pub(crate) const IPV6LEN: usize = 16;
15 
16 /// MappedAddress represents MAPPED-ADDRESS attribute.
17 ///
18 /// This attribute is used only by servers for achieving backwards
19 /// compatibility with RFC 3489 clients.
20 ///
21 /// RFC 5389 Section 15.1
22 pub struct MappedAddress {
23     pub ip: IpAddr,
24     pub port: u16,
25 }
26 
27 impl fmt::Display for MappedAddress {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result28     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 
41 impl Default for MappedAddress {
default() -> Self42     fn default() -> Self {
43         MappedAddress {
44             ip: IpAddr::V4(Ipv4Addr::from(0)),
45             port: 0,
46         }
47     }
48 }
49 
50 impl Setter for MappedAddress {
51     /// add_to adds MAPPED-ADDRESS to message.
add_to(&self, m: &mut Message) -> Result<()>52     fn add_to(&self, m: &mut Message) -> Result<()> {
53         self.add_to_as(m, ATTR_MAPPED_ADDRESS)
54     }
55 }
56 
57 impl Getter for MappedAddress {
58     /// get_from decodes MAPPED-ADDRESS from message.
get_from(&mut self, m: &Message) -> Result<()>59     fn get_from(&mut self, m: &Message) -> Result<()> {
60         self.get_from_as(m, ATTR_MAPPED_ADDRESS)
61     }
62 }
63 
64 impl MappedAddress {
65     /// get_from_as decodes MAPPED-ADDRESS value in message m as an attribute of type t.
get_from_as(&mut self, m: &Message, t: AttrType) -> Result<()>66     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     /// add_to_as adds MAPPED-ADDRESS value to m as t attribute.
add_to_as(&self, m: &mut Message, t: AttrType) -> Result<()>94     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] = 0 // first 8 bits are zeroes
102         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 
115 /// AlternateServer represents ALTERNATE-SERVER attribute.
116 ///
117 /// RFC 5389 Section 15.11
118 pub type AlternateServer = MappedAddress;
119 
120 /// ResponseOrigin represents RESPONSE-ORIGIN attribute.
121 ///
122 /// RFC 5780 Section 7.3
123 pub type ResponseOrigin = MappedAddress;
124 
125 /// OtherAddress represents OTHER-ADDRESS attribute.
126 ///
127 /// RFC 5780 Section 7.4
128 pub type OtherAddress = MappedAddress;
129