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