turn_types/attribute/
address.rs1use std::net::SocketAddr;
10
11use stun_types::{
12 attribute::*,
13 message::{StunParseError, TransactionId},
14};
15
16#[derive(Debug, Clone)]
18pub struct XorPeerAddress {
19 addr: XorSocketAddr,
21}
22
23impl AttributeStaticType for XorPeerAddress {
24 const TYPE: AttributeType = AttributeType::new(0x0012);
25}
26
27impl Attribute for XorPeerAddress {
28 fn get_type(&self) -> AttributeType {
29 Self::TYPE
30 }
31
32 fn length(&self) -> u16 {
33 self.addr.length()
34 }
35}
36
37impl AttributeWrite for XorPeerAddress {
38 fn to_raw(&self) -> RawAttribute {
39 self.addr.to_raw(self.get_type())
40 }
41 fn write_into_unchecked(&self, dest: &mut [u8]) {
42 self.write_header_unchecked(dest);
43 self.addr.write_into_unchecked(&mut dest[4..]);
44 }
45}
46
47impl AttributeFromRaw<'_> for XorPeerAddress {
48 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
49 where
50 Self: Sized,
51 {
52 Self::try_from(raw)
53 }
54}
55
56impl TryFrom<&RawAttribute<'_>> for XorPeerAddress {
57 type Error = StunParseError;
58 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
59 raw.check_type_and_len(Self::TYPE, 4..=20)?;
60 Ok(Self {
61 addr: XorSocketAddr::from_raw(raw)?,
62 })
63 }
64}
65
66impl XorPeerAddress {
67 pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
79 Self {
80 addr: XorSocketAddr::new(addr, transaction),
81 }
82 }
83
84 pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
96 self.addr.addr(transaction)
97 }
98}
99
100impl std::fmt::Display for XorPeerAddress {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 write!(f, "{}: {}", self.get_type(), self.addr)
103 }
104}
105
106#[derive(Debug, Clone)]
108pub struct XorRelayedAddress {
109 addr: XorSocketAddr,
110}
111
112impl AttributeStaticType for XorRelayedAddress {
113 const TYPE: AttributeType = AttributeType::new(0x0016);
114}
115
116impl Attribute for XorRelayedAddress {
117 fn get_type(&self) -> AttributeType {
118 Self::TYPE
119 }
120
121 fn length(&self) -> u16 {
122 self.addr.length()
123 }
124}
125
126impl AttributeWrite for XorRelayedAddress {
127 fn to_raw(&self) -> RawAttribute {
128 self.addr.to_raw(self.get_type())
129 }
130 fn write_into_unchecked(&self, dest: &mut [u8]) {
131 self.write_header_unchecked(dest);
132 self.addr.write_into_unchecked(&mut dest[4..]);
133 }
134}
135
136impl AttributeFromRaw<'_> for XorRelayedAddress {
137 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
138 where
139 Self: Sized,
140 {
141 Self::try_from(raw)
142 }
143}
144
145impl TryFrom<&RawAttribute<'_>> for XorRelayedAddress {
146 type Error = StunParseError;
147 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
148 if raw.get_type() != Self::TYPE {
149 return Err(StunParseError::WrongAttributeImplementation);
150 }
151 Ok(Self {
152 addr: XorSocketAddr::from_raw(raw)?,
153 })
154 }
155}
156
157impl XorRelayedAddress {
158 pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
170 Self {
171 addr: XorSocketAddr::new(addr, transaction),
172 }
173 }
174
175 pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
187 self.addr.addr(transaction)
188 }
189}
190
191impl std::fmt::Display for XorRelayedAddress {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 write!(f, "{}: {}", self.get_type(), self.addr)
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200 use byteorder::{BigEndian, ByteOrder};
201
202 #[test]
203 fn xor_peer_address() {
204 let _log = crate::tests::test_init_log();
205 let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
206 let addrs = &[
207 "192.168.0.1:40000".parse().unwrap(),
208 "[fd12:3456:789a:1::1]:41000".parse().unwrap(),
209 ];
210 for addr in addrs {
211 let mapped = XorPeerAddress::new(*addr, transaction_id);
212 assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
213 assert_eq!(mapped.addr(transaction_id), *addr);
214 let raw: RawAttribute = mapped.to_raw();
215 println!("{}", raw);
216 assert_eq!(raw.get_type(), XorPeerAddress::TYPE);
217 let mapped2 = XorPeerAddress::try_from(&raw).unwrap();
218 assert_eq!(mapped2.get_type(), XorPeerAddress::TYPE);
219 assert_eq!(mapped2.addr(transaction_id), *addr);
220 let mut data: Vec<_> = raw.clone().into();
222 let len = data.len();
223 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
224 assert!(matches!(
225 XorPeerAddress::try_from(
226 &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
227 ),
228 Err(StunParseError::Truncated {
229 expected: _,
230 actual: _,
231 })
232 ));
233 let mut data: Vec<_> = raw.into();
235 BigEndian::write_u16(&mut data[0..2], 0);
236 assert!(matches!(
237 XorPeerAddress::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
238 Err(StunParseError::WrongAttributeImplementation)
239 ));
240 }
241 }
242
243 #[test]
244 fn xor_relayed_address() {
245 let _log = crate::tests::test_init_log();
246 let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
247 let addrs = &[
248 "192.168.0.1:40000".parse().unwrap(),
249 "[fd12:3456:789a:1::1]:41000".parse().unwrap(),
250 ];
251 for addr in addrs {
252 let mapped = XorRelayedAddress::new(*addr, transaction_id);
253 assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
254 assert_eq!(mapped.addr(transaction_id), *addr);
255 let raw: RawAttribute = mapped.to_raw();
256 println!("{}", raw);
257 assert_eq!(raw.get_type(), XorRelayedAddress::TYPE);
258 let mapped2 = XorRelayedAddress::try_from(&raw).unwrap();
259 assert_eq!(mapped2.get_type(), XorRelayedAddress::TYPE);
260 assert_eq!(mapped2.addr(transaction_id), *addr);
261 let mut data: Vec<_> = raw.clone().into();
263 let len = data.len();
264 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
265 assert!(matches!(
266 XorRelayedAddress::try_from(
267 &RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
268 ),
269 Err(StunParseError::Truncated {
270 expected: _,
271 actual: _,
272 })
273 ));
274 let mut data: Vec<_> = raw.into();
276 BigEndian::write_u16(&mut data[0..2], 0);
277 assert!(matches!(
278 XorRelayedAddress::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
279 Err(StunParseError::WrongAttributeImplementation)
280 ));
281 }
282 }
283}