]>
Commit | Line | Data |
---|---|---|
60c5eb7d | 1 | use crate::convert::TryInto; |
532ac7d7 XL |
2 | use crate::fmt; |
3 | use crate::hash; | |
4 | use crate::io; | |
60c5eb7d | 5 | use crate::iter; |
532ac7d7 | 6 | use crate::mem; |
dfeec247 | 7 | use crate::net::{htons, ntohs, IpAddr, Ipv4Addr, Ipv6Addr}; |
532ac7d7 | 8 | use crate::option; |
60c5eb7d | 9 | use crate::slice; |
532ac7d7 | 10 | use crate::sys::net::netc as c; |
532ac7d7 | 11 | use crate::sys_common::net::LookupHost; |
60c5eb7d | 12 | use crate::sys_common::{AsInner, FromInner, IntoInner}; |
532ac7d7 | 13 | use crate::vec; |
85aaf69f | 14 | |
cc61c64b | 15 | /// An internet socket address, either IPv4 or IPv6. |
85aaf69f | 16 | /// |
cc61c64b XL |
17 | /// Internet socket addresses consist of an [IP address], a 16-bit port number, as well |
18 | /// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and | |
19 | /// [`SocketAddrV6`]'s respective documentation for more details. | |
20 | /// | |
0531ce1d XL |
21 | /// The size of a `SocketAddr` instance may vary depending on the target operating |
22 | /// system. | |
23 | /// | |
cc61c64b XL |
24 | /// [IP address]: ../../std/net/enum.IpAddr.html |
25 | /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html | |
26 | /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html | |
27 | /// | |
28 | /// # Examples | |
29 | /// | |
30 | /// ``` | |
31 | /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | |
32 | /// | |
33 | /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); | |
34 | /// | |
35 | /// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); | |
36 | /// assert_eq!(socket.port(), 8080); | |
37 | /// assert_eq!(socket.is_ipv4(), true); | |
38 | /// ``` | |
c34b1796 AL |
39 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
40 | #[stable(feature = "rust1", since = "1.0.0")] | |
41 | pub enum SocketAddr { | |
cc61c64b | 42 | /// An IPv4 socket address. |
c34b1796 | 43 | #[stable(feature = "rust1", since = "1.0.0")] |
7453a54e | 44 | V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4), |
476ff2be | 45 | /// An IPv6 socket address. |
c34b1796 | 46 | #[stable(feature = "rust1", since = "1.0.0")] |
7453a54e | 47 | V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6), |
85aaf69f SL |
48 | } |
49 | ||
cc61c64b XL |
50 | /// An IPv4 socket address. |
51 | /// | |
52 | /// IPv4 socket addresses consist of an [IPv4 address] and a 16-bit port number, as | |
53 | /// stated in [IETF RFC 793]. | |
54 | /// | |
55 | /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. | |
56 | /// | |
0531ce1d XL |
57 | /// The size of a `SocketAddrV4` struct may vary depending on the target operating |
58 | /// system. | |
59 | /// | |
cc61c64b XL |
60 | /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 |
61 | /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html | |
62 | /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html | |
63 | /// | |
64 | /// # Examples | |
65 | /// | |
66 | /// ``` | |
67 | /// use std::net::{Ipv4Addr, SocketAddrV4}; | |
68 | /// | |
69 | /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); | |
70 | /// | |
71 | /// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); | |
72 | /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); | |
73 | /// assert_eq!(socket.port(), 8080); | |
74 | /// ``` | |
85aaf69f | 75 | #[derive(Copy)] |
c34b1796 | 76 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d XL |
77 | pub struct SocketAddrV4 { |
78 | inner: c::sockaddr_in, | |
79 | } | |
c34b1796 | 80 | |
bd371182 | 81 | /// An IPv6 socket address. |
cc61c64b XL |
82 | /// |
83 | /// IPv6 socket addresses consist of an [Ipv6 address], a 16-bit port number, as well | |
84 | /// as fields containing the traffic class, the flow label, and a scope identifier | |
85 | /// (see [IETF RFC 2553, Section 3.3] for more details). | |
86 | /// | |
87 | /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. | |
88 | /// | |
0531ce1d XL |
89 | /// The size of a `SocketAddrV6` struct may vary depending on the target operating |
90 | /// system. | |
91 | /// | |
cc61c64b XL |
92 | /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 |
93 | /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html | |
94 | /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html | |
95 | /// | |
96 | /// # Examples | |
97 | /// | |
98 | /// ``` | |
99 | /// use std::net::{Ipv6Addr, SocketAddrV6}; | |
100 | /// | |
101 | /// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); | |
102 | /// | |
103 | /// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket)); | |
104 | /// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); | |
105 | /// assert_eq!(socket.port(), 8080); | |
106 | /// ``` | |
c34b1796 AL |
107 | #[derive(Copy)] |
108 | #[stable(feature = "rust1", since = "1.0.0")] | |
60c5eb7d XL |
109 | pub struct SocketAddrV6 { |
110 | inner: c::sockaddr_in6, | |
111 | } | |
85aaf69f SL |
112 | |
113 | impl SocketAddr { | |
cc61c64b XL |
114 | /// Creates a new socket address from an [IP address] and a port number. |
115 | /// | |
116 | /// [IP address]: ../../std/net/enum.IpAddr.html | |
476ff2be SL |
117 | /// |
118 | /// # Examples | |
119 | /// | |
120 | /// ``` | |
121 | /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | |
122 | /// | |
123 | /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); | |
124 | /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); | |
125 | /// assert_eq!(socket.port(), 8080); | |
126 | /// ``` | |
9cc50fc6 | 127 | #[stable(feature = "ip_addr", since = "1.7.0")] |
85aaf69f | 128 | pub fn new(ip: IpAddr, port: u16) -> SocketAddr { |
c34b1796 AL |
129 | match ip { |
130 | IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), | |
131 | IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)), | |
132 | } | |
85aaf69f SL |
133 | } |
134 | ||
bd371182 | 135 | /// Returns the IP address associated with this socket address. |
476ff2be SL |
136 | /// |
137 | /// # Examples | |
138 | /// | |
139 | /// ``` | |
140 | /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | |
141 | /// | |
142 | /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); | |
143 | /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); | |
144 | /// ``` | |
9cc50fc6 | 145 | #[stable(feature = "ip_addr", since = "1.7.0")] |
85aaf69f | 146 | pub fn ip(&self) -> IpAddr { |
c34b1796 AL |
147 | match *self { |
148 | SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), | |
149 | SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), | |
85aaf69f SL |
150 | } |
151 | } | |
152 | ||
cc61c64b | 153 | /// Changes the IP address associated with this socket address. |
476ff2be SL |
154 | /// |
155 | /// # Examples | |
156 | /// | |
157 | /// ``` | |
158 | /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | |
159 | /// | |
160 | /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); | |
161 | /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); | |
162 | /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); | |
163 | /// ``` | |
54a0048b | 164 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
7453a54e SL |
165 | pub fn set_ip(&mut self, new_ip: IpAddr) { |
166 | // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. | |
167 | match (self, new_ip) { | |
168 | (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip), | |
169 | (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip), | |
170 | (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()), | |
171 | } | |
172 | } | |
173 | ||
bd371182 | 174 | /// Returns the port number associated with this socket address. |
476ff2be SL |
175 | /// |
176 | /// # Examples | |
177 | /// | |
178 | /// ``` | |
179 | /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | |
180 | /// | |
181 | /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); | |
182 | /// assert_eq!(socket.port(), 8080); | |
183 | /// ``` | |
c34b1796 | 184 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 185 | pub fn port(&self) -> u16 { |
c34b1796 AL |
186 | match *self { |
187 | SocketAddr::V4(ref a) => a.port(), | |
188 | SocketAddr::V6(ref a) => a.port(), | |
85aaf69f SL |
189 | } |
190 | } | |
7453a54e | 191 | |
cc61c64b | 192 | /// Changes the port number associated with this socket address. |
476ff2be SL |
193 | /// |
194 | /// # Examples | |
195 | /// | |
196 | /// ``` | |
197 | /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | |
198 | /// | |
199 | /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); | |
200 | /// socket.set_port(1025); | |
201 | /// assert_eq!(socket.port(), 1025); | |
202 | /// ``` | |
54a0048b | 203 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
7453a54e SL |
204 | pub fn set_port(&mut self, new_port: u16) { |
205 | match *self { | |
206 | SocketAddr::V4(ref mut a) => a.set_port(new_port), | |
207 | SocketAddr::V6(ref mut a) => a.set_port(new_port), | |
208 | } | |
209 | } | |
c30ab7b3 | 210 | |
cc61c64b XL |
211 | /// Returns [`true`] if the [IP address] in this `SocketAddr` is an |
212 | /// [IPv4 address], and [`false`] otherwise. | |
213 | /// | |
214 | /// [`true`]: ../../std/primitive.bool.html | |
215 | /// [`false`]: ../../std/primitive.bool.html | |
216 | /// [IP address]: ../../std/net/enum.IpAddr.html | |
217 | /// [IPv4 address]: ../../std/net/enum.IpAddr.html#variant.V4 | |
476ff2be SL |
218 | /// |
219 | /// # Examples | |
220 | /// | |
221 | /// ``` | |
476ff2be SL |
222 | /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; |
223 | /// | |
e74abb32 XL |
224 | /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); |
225 | /// assert_eq!(socket.is_ipv4(), true); | |
226 | /// assert_eq!(socket.is_ipv6(), false); | |
476ff2be | 227 | /// ``` |
32a655c1 | 228 | #[stable(feature = "sockaddr_checker", since = "1.16.0")] |
c30ab7b3 | 229 | pub fn is_ipv4(&self) -> bool { |
dfeec247 | 230 | matches!(*self, SocketAddr::V4(_)) |
c30ab7b3 SL |
231 | } |
232 | ||
cc61c64b XL |
233 | /// Returns [`true`] if the [IP address] in this `SocketAddr` is an |
234 | /// [IPv6 address], and [`false`] otherwise. | |
235 | /// | |
236 | /// [`true`]: ../../std/primitive.bool.html | |
237 | /// [`false`]: ../../std/primitive.bool.html | |
238 | /// [IP address]: ../../std/net/enum.IpAddr.html | |
239 | /// [IPv6 address]: ../../std/net/enum.IpAddr.html#variant.V6 | |
476ff2be SL |
240 | /// |
241 | /// # Examples | |
242 | /// | |
243 | /// ``` | |
476ff2be SL |
244 | /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; |
245 | /// | |
e74abb32 XL |
246 | /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); |
247 | /// assert_eq!(socket.is_ipv4(), false); | |
248 | /// assert_eq!(socket.is_ipv6(), true); | |
476ff2be | 249 | /// ``` |
32a655c1 | 250 | #[stable(feature = "sockaddr_checker", since = "1.16.0")] |
c30ab7b3 | 251 | pub fn is_ipv6(&self) -> bool { |
dfeec247 | 252 | matches!(*self, SocketAddr::V6(_)) |
c30ab7b3 | 253 | } |
c34b1796 | 254 | } |
85aaf69f | 255 | |
c34b1796 | 256 | impl SocketAddrV4 { |
cc61c64b XL |
257 | /// Creates a new socket address from an [IPv4 address] and a port number. |
258 | /// | |
259 | /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html | |
476ff2be SL |
260 | /// |
261 | /// # Examples | |
262 | /// | |
263 | /// ``` | |
264 | /// use std::net::{SocketAddrV4, Ipv4Addr}; | |
265 | /// | |
266 | /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); | |
267 | /// ``` | |
c34b1796 AL |
268 | #[stable(feature = "rust1", since = "1.0.0")] |
269 | pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { | |
270 | SocketAddrV4 { | |
92a42be0 SL |
271 | inner: c::sockaddr_in { |
272 | sin_family: c::AF_INET as c::sa_family_t, | |
dfeec247 | 273 | sin_port: htons(port), |
c34b1796 | 274 | sin_addr: *ip.as_inner(), |
60c5eb7d | 275 | ..unsafe { mem::zeroed() } |
c34b1796 | 276 | }, |
85aaf69f SL |
277 | } |
278 | } | |
c34b1796 | 279 | |
bd371182 | 280 | /// Returns the IP address associated with this socket address. |
476ff2be SL |
281 | /// |
282 | /// # Examples | |
283 | /// | |
284 | /// ``` | |
285 | /// use std::net::{SocketAddrV4, Ipv4Addr}; | |
286 | /// | |
287 | /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); | |
288 | /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); | |
289 | /// ``` | |
c34b1796 AL |
290 | #[stable(feature = "rust1", since = "1.0.0")] |
291 | pub fn ip(&self) -> &Ipv4Addr { | |
60c5eb7d | 292 | unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) } |
c34b1796 AL |
293 | } |
294 | ||
cc61c64b | 295 | /// Changes the IP address associated with this socket address. |
476ff2be SL |
296 | /// |
297 | /// # Examples | |
298 | /// | |
299 | /// ``` | |
300 | /// use std::net::{SocketAddrV4, Ipv4Addr}; | |
301 | /// | |
302 | /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); | |
303 | /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1)); | |
304 | /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1)); | |
305 | /// ``` | |
54a0048b SL |
306 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
307 | pub fn set_ip(&mut self, new_ip: Ipv4Addr) { | |
308 | self.inner.sin_addr = *new_ip.as_inner() | |
309 | } | |
7453a54e | 310 | |
bd371182 | 311 | /// Returns the port number associated with this socket address. |
476ff2be SL |
312 | /// |
313 | /// # Examples | |
314 | /// | |
315 | /// ``` | |
316 | /// use std::net::{SocketAddrV4, Ipv4Addr}; | |
317 | /// | |
318 | /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); | |
319 | /// assert_eq!(socket.port(), 8080); | |
320 | /// ``` | |
c34b1796 | 321 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b | 322 | pub fn port(&self) -> u16 { |
dfeec247 | 323 | ntohs(self.inner.sin_port) |
54a0048b | 324 | } |
7453a54e | 325 | |
cc61c64b | 326 | /// Changes the port number associated with this socket address. |
476ff2be SL |
327 | /// |
328 | /// # Examples | |
329 | /// | |
330 | /// ``` | |
331 | /// use std::net::{SocketAddrV4, Ipv4Addr}; | |
332 | /// | |
333 | /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); | |
334 | /// socket.set_port(4242); | |
335 | /// assert_eq!(socket.port(), 4242); | |
336 | /// ``` | |
54a0048b SL |
337 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
338 | pub fn set_port(&mut self, new_port: u16) { | |
dfeec247 | 339 | self.inner.sin_port = htons(new_port); |
54a0048b | 340 | } |
85aaf69f SL |
341 | } |
342 | ||
c34b1796 | 343 | impl SocketAddrV6 { |
cc61c64b XL |
344 | /// Creates a new socket address from an [IPv6 address], a 16-bit port number, |
345 | /// and the `flowinfo` and `scope_id` fields. | |
346 | /// | |
347 | /// For more information on the meaning and layout of the `flowinfo` and `scope_id` | |
348 | /// parameters, see [IETF RFC 2553, Section 3.3]. | |
349 | /// | |
350 | /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 | |
351 | /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html | |
476ff2be SL |
352 | /// |
353 | /// # Examples | |
354 | /// | |
355 | /// ``` | |
356 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
357 | /// | |
358 | /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); | |
359 | /// ``` | |
c34b1796 | 360 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d | 361 | pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { |
c34b1796 | 362 | SocketAddrV6 { |
92a42be0 SL |
363 | inner: c::sockaddr_in6 { |
364 | sin6_family: c::AF_INET6 as c::sa_family_t, | |
dfeec247 | 365 | sin6_port: htons(port), |
c34b1796 | 366 | sin6_addr: *ip.as_inner(), |
54a0048b SL |
367 | sin6_flowinfo: flowinfo, |
368 | sin6_scope_id: scope_id, | |
60c5eb7d | 369 | ..unsafe { mem::zeroed() } |
c34b1796 | 370 | }, |
85aaf69f SL |
371 | } |
372 | } | |
c34b1796 | 373 | |
bd371182 | 374 | /// Returns the IP address associated with this socket address. |
476ff2be SL |
375 | /// |
376 | /// # Examples | |
377 | /// | |
378 | /// ``` | |
379 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
380 | /// | |
381 | /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); | |
382 | /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); | |
383 | /// ``` | |
c34b1796 AL |
384 | #[stable(feature = "rust1", since = "1.0.0")] |
385 | pub fn ip(&self) -> &Ipv6Addr { | |
60c5eb7d | 386 | unsafe { &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) } |
c34b1796 AL |
387 | } |
388 | ||
cc61c64b | 389 | /// Changes the IP address associated with this socket address. |
476ff2be SL |
390 | /// |
391 | /// # Examples | |
392 | /// | |
393 | /// ``` | |
394 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
395 | /// | |
396 | /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); | |
397 | /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); | |
398 | /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); | |
399 | /// ``` | |
54a0048b SL |
400 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
401 | pub fn set_ip(&mut self, new_ip: Ipv6Addr) { | |
402 | self.inner.sin6_addr = *new_ip.as_inner() | |
403 | } | |
7453a54e | 404 | |
bd371182 | 405 | /// Returns the port number associated with this socket address. |
476ff2be SL |
406 | /// |
407 | /// # Examples | |
408 | /// | |
409 | /// ``` | |
410 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
411 | /// | |
412 | /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); | |
413 | /// assert_eq!(socket.port(), 8080); | |
414 | /// ``` | |
c34b1796 | 415 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b | 416 | pub fn port(&self) -> u16 { |
dfeec247 | 417 | ntohs(self.inner.sin6_port) |
54a0048b | 418 | } |
c34b1796 | 419 | |
cc61c64b | 420 | /// Changes the port number associated with this socket address. |
476ff2be SL |
421 | /// |
422 | /// # Examples | |
423 | /// | |
424 | /// ``` | |
425 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
426 | /// | |
427 | /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); | |
428 | /// socket.set_port(4242); | |
429 | /// assert_eq!(socket.port(), 4242); | |
430 | /// ``` | |
54a0048b SL |
431 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
432 | pub fn set_port(&mut self, new_port: u16) { | |
dfeec247 | 433 | self.inner.sin6_port = htons(new_port); |
54a0048b | 434 | } |
7453a54e | 435 | |
cc61c64b XL |
436 | /// Returns the flow information associated with this address. |
437 | /// | |
438 | /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`, | |
439 | /// as specified in [IETF RFC 2553, Section 3.3]. | |
440 | /// It combines information about the flow label and the traffic class as specified | |
441 | /// in [IETF RFC 2460], respectively [Section 6] and [Section 7]. | |
442 | /// | |
443 | /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 | |
444 | /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460 | |
445 | /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6 | |
446 | /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7 | |
476ff2be SL |
447 | /// |
448 | /// # Examples | |
449 | /// | |
450 | /// ``` | |
451 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
452 | /// | |
453 | /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); | |
454 | /// assert_eq!(socket.flowinfo(), 10); | |
455 | /// ``` | |
c34b1796 | 456 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b SL |
457 | pub fn flowinfo(&self) -> u32 { |
458 | self.inner.sin6_flowinfo | |
459 | } | |
c34b1796 | 460 | |
cc61c64b XL |
461 | /// Changes the flow information associated with this socket address. |
462 | /// | |
463 | /// See the [`flowinfo`] method's documentation for more details. | |
464 | /// | |
465 | /// [`flowinfo`]: #method.flowinfo | |
476ff2be SL |
466 | /// |
467 | /// # Examples | |
468 | /// | |
469 | /// ``` | |
470 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
471 | /// | |
472 | /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); | |
473 | /// socket.set_flowinfo(56); | |
474 | /// assert_eq!(socket.flowinfo(), 56); | |
475 | /// ``` | |
54a0048b | 476 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
7453a54e | 477 | pub fn set_flowinfo(&mut self, new_flowinfo: u32) { |
54a0048b | 478 | self.inner.sin6_flowinfo = new_flowinfo; |
7453a54e SL |
479 | } |
480 | ||
cc61c64b XL |
481 | /// Returns the scope ID associated with this address. |
482 | /// | |
483 | /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`, | |
484 | /// as specified in [IETF RFC 2553, Section 3.3]. | |
485 | /// | |
486 | /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 | |
476ff2be SL |
487 | /// |
488 | /// # Examples | |
489 | /// | |
490 | /// ``` | |
491 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
492 | /// | |
493 | /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); | |
494 | /// assert_eq!(socket.scope_id(), 78); | |
495 | /// ``` | |
c34b1796 | 496 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b SL |
497 | pub fn scope_id(&self) -> u32 { |
498 | self.inner.sin6_scope_id | |
499 | } | |
7453a54e | 500 | |
9fa01778 | 501 | /// Changes the scope ID associated with this socket address. |
476ff2be | 502 | /// |
cc61c64b XL |
503 | /// See the [`scope_id`] method's documentation for more details. |
504 | /// | |
505 | /// [`scope_id`]: #method.scope_id | |
506 | /// | |
476ff2be SL |
507 | /// # Examples |
508 | /// | |
509 | /// ``` | |
510 | /// use std::net::{SocketAddrV6, Ipv6Addr}; | |
511 | /// | |
512 | /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); | |
513 | /// socket.set_scope_id(42); | |
514 | /// assert_eq!(socket.scope_id(), 42); | |
515 | /// ``` | |
54a0048b | 516 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
7453a54e | 517 | pub fn set_scope_id(&mut self, new_scope_id: u32) { |
54a0048b | 518 | self.inner.sin6_scope_id = new_scope_id; |
7453a54e | 519 | } |
85aaf69f SL |
520 | } |
521 | ||
92a42be0 SL |
522 | impl FromInner<c::sockaddr_in> for SocketAddrV4 { |
523 | fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 { | |
c34b1796 | 524 | SocketAddrV4 { inner: addr } |
85aaf69f SL |
525 | } |
526 | } | |
527 | ||
92a42be0 SL |
528 | impl FromInner<c::sockaddr_in6> for SocketAddrV6 { |
529 | fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 { | |
c34b1796 | 530 | SocketAddrV6 { inner: addr } |
85aaf69f SL |
531 | } |
532 | } | |
533 | ||
32a655c1 SL |
534 | #[stable(feature = "ip_from_ip", since = "1.16.0")] |
535 | impl From<SocketAddrV4> for SocketAddr { | |
0bf4aa26 | 536 | /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`]. |
48663c56 XL |
537 | /// |
538 | /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html | |
539 | /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4 | |
32a655c1 SL |
540 | fn from(sock4: SocketAddrV4) -> SocketAddr { |
541 | SocketAddr::V4(sock4) | |
542 | } | |
543 | } | |
544 | ||
545 | #[stable(feature = "ip_from_ip", since = "1.16.0")] | |
546 | impl From<SocketAddrV6> for SocketAddr { | |
0bf4aa26 | 547 | /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`]. |
48663c56 XL |
548 | /// |
549 | /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html | |
550 | /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6 | |
32a655c1 SL |
551 | fn from(sock6: SocketAddrV6) -> SocketAddr { |
552 | SocketAddr::V6(sock6) | |
553 | } | |
554 | } | |
555 | ||
8bb4bdeb XL |
556 | #[stable(feature = "addr_from_into_ip", since = "1.17.0")] |
557 | impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr { | |
0bf4aa26 XL |
558 | /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`]. |
559 | /// | |
560 | /// This conversion creates a [`SocketAddr::V4`] for a [`IpAddr::V4`] | |
561 | /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`]. | |
562 | /// | |
563 | /// `u16` is treated as port of the newly created [`SocketAddr`]. | |
48663c56 XL |
564 | /// |
565 | /// [`IpAddr`]: ../../std/net/enum.IpAddr.html | |
566 | /// [`IpAddr::V4`]: ../../std/net/enum.IpAddr.html#variant.V4 | |
567 | /// [`IpAddr::V6`]: ../../std/net/enum.IpAddr.html#variant.V6 | |
568 | /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html | |
569 | /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4 | |
570 | /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6 | |
8bb4bdeb XL |
571 | fn from(pieces: (I, u16)) -> SocketAddr { |
572 | SocketAddr::new(pieces.0.into(), pieces.1) | |
573 | } | |
574 | } | |
575 | ||
92a42be0 SL |
576 | impl<'a> IntoInner<(*const c::sockaddr, c::socklen_t)> for &'a SocketAddr { |
577 | fn into_inner(self) -> (*const c::sockaddr, c::socklen_t) { | |
c34b1796 AL |
578 | match *self { |
579 | SocketAddr::V4(ref a) => { | |
92a42be0 | 580 | (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) |
85aaf69f | 581 | } |
c34b1796 | 582 | SocketAddr::V6(ref a) => { |
92a42be0 | 583 | (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) |
85aaf69f SL |
584 | } |
585 | } | |
586 | } | |
587 | } | |
588 | ||
c34b1796 AL |
589 | #[stable(feature = "rust1", since = "1.0.0")] |
590 | impl fmt::Display for SocketAddr { | |
532ac7d7 | 591 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
c34b1796 AL |
592 | match *self { |
593 | SocketAddr::V4(ref a) => a.fmt(f), | |
594 | SocketAddr::V6(ref a) => a.fmt(f), | |
595 | } | |
596 | } | |
597 | } | |
598 | ||
599 | #[stable(feature = "rust1", since = "1.0.0")] | |
600 | impl fmt::Display for SocketAddrV4 { | |
532ac7d7 | 601 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
c34b1796 AL |
602 | write!(f, "{}:{}", self.ip(), self.port()) |
603 | } | |
604 | } | |
605 | ||
606 | #[stable(feature = "rust1", since = "1.0.0")] | |
607 | impl fmt::Debug for SocketAddrV4 { | |
532ac7d7 | 608 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
609 | fmt::Display::fmt(self, fmt) |
610 | } | |
611 | } | |
612 | ||
c34b1796 AL |
613 | #[stable(feature = "rust1", since = "1.0.0")] |
614 | impl fmt::Display for SocketAddrV6 { | |
532ac7d7 | 615 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
c34b1796 AL |
616 | write!(f, "[{}]:{}", self.ip(), self.port()) |
617 | } | |
85aaf69f SL |
618 | } |
619 | ||
c34b1796 AL |
620 | #[stable(feature = "rust1", since = "1.0.0")] |
621 | impl fmt::Debug for SocketAddrV6 { | |
532ac7d7 | 622 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
c34b1796 | 623 | fmt::Display::fmt(self, fmt) |
85aaf69f SL |
624 | } |
625 | } | |
85aaf69f | 626 | |
c34b1796 AL |
627 | #[stable(feature = "rust1", since = "1.0.0")] |
628 | impl Clone for SocketAddrV4 { | |
60c5eb7d XL |
629 | fn clone(&self) -> SocketAddrV4 { |
630 | *self | |
631 | } | |
c34b1796 AL |
632 | } |
633 | #[stable(feature = "rust1", since = "1.0.0")] | |
634 | impl Clone for SocketAddrV6 { | |
60c5eb7d XL |
635 | fn clone(&self) -> SocketAddrV6 { |
636 | *self | |
637 | } | |
c34b1796 AL |
638 | } |
639 | ||
640 | #[stable(feature = "rust1", since = "1.0.0")] | |
641 | impl PartialEq for SocketAddrV4 { | |
642 | fn eq(&self, other: &SocketAddrV4) -> bool { | |
60c5eb7d XL |
643 | self.inner.sin_port == other.inner.sin_port |
644 | && self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr | |
c34b1796 AL |
645 | } |
646 | } | |
647 | #[stable(feature = "rust1", since = "1.0.0")] | |
648 | impl PartialEq for SocketAddrV6 { | |
649 | fn eq(&self, other: &SocketAddrV6) -> bool { | |
60c5eb7d XL |
650 | self.inner.sin6_port == other.inner.sin6_port |
651 | && self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr | |
652 | && self.inner.sin6_flowinfo == other.inner.sin6_flowinfo | |
653 | && self.inner.sin6_scope_id == other.inner.sin6_scope_id | |
85aaf69f SL |
654 | } |
655 | } | |
85aaf69f | 656 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 AL |
657 | impl Eq for SocketAddrV4 {} |
658 | #[stable(feature = "rust1", since = "1.0.0")] | |
659 | impl Eq for SocketAddrV6 {} | |
660 | ||
661 | #[stable(feature = "rust1", since = "1.0.0")] | |
662 | impl hash::Hash for SocketAddrV4 { | |
85aaf69f | 663 | fn hash<H: hash::Hasher>(&self, s: &mut H) { |
c34b1796 AL |
664 | (self.inner.sin_port, self.inner.sin_addr.s_addr).hash(s) |
665 | } | |
666 | } | |
667 | #[stable(feature = "rust1", since = "1.0.0")] | |
668 | impl hash::Hash for SocketAddrV6 { | |
669 | fn hash<H: hash::Hasher>(&self, s: &mut H) { | |
60c5eb7d XL |
670 | ( |
671 | self.inner.sin6_port, | |
672 | &self.inner.sin6_addr.s6_addr, | |
673 | self.inner.sin6_flowinfo, | |
674 | self.inner.sin6_scope_id, | |
675 | ) | |
676 | .hash(s) | |
85aaf69f SL |
677 | } |
678 | } | |
679 | ||
680 | /// A trait for objects which can be converted or resolved to one or more | |
cc61c64b | 681 | /// [`SocketAddr`] values. |
85aaf69f SL |
682 | /// |
683 | /// This trait is used for generic address resolution when constructing network | |
9fa01778 | 684 | /// objects. By default it is implemented for the following types: |
85aaf69f | 685 | /// |
cc61c64b | 686 | /// * [`SocketAddr`]: [`to_socket_addrs`] is the identity function. |
85aaf69f | 687 | /// |
cc61c64b XL |
688 | /// * [`SocketAddrV4`], [`SocketAddrV6`], `(`[`IpAddr`]`, `[`u16`]`)`, |
689 | /// `(`[`Ipv4Addr`]`, `[`u16`]`)`, `(`[`Ipv6Addr`]`, `[`u16`]`)`: | |
690 | /// [`to_socket_addrs`] constructs a [`SocketAddr`] trivially. | |
85aaf69f | 691 | /// |
cc61c64b XL |
692 | /// * `(`[`&str`]`, `[`u16`]`)`: the string should be either a string representation |
693 | /// of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host | |
85aaf69f SL |
694 | /// name. |
695 | /// | |
cc61c64b XL |
696 | /// * [`&str`]: the string should be either a string representation of a |
697 | /// [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like | |
698 | /// `<host_name>:<port>` pair where `<port>` is a [`u16`] value. | |
85aaf69f | 699 | /// |
cc61c64b XL |
700 | /// This trait allows constructing network objects like [`TcpStream`] or |
701 | /// [`UdpSocket`] easily with values of various types for the bind/connection | |
85aaf69f SL |
702 | /// address. It is needed because sometimes one type is more appropriate than |
703 | /// the other: for simple uses a string like `"localhost:12345"` is much nicer | |
cc61c64b XL |
704 | /// than manual construction of the corresponding [`SocketAddr`], but sometimes |
705 | /// [`SocketAddr`] value is *the* main source of the address, and converting it to | |
0731742a | 706 | /// some other type (e.g., a string) just for it to be converted back to |
cc61c64b | 707 | /// [`SocketAddr`] in constructor methods is pointless. |
85aaf69f | 708 | /// |
3157f602 XL |
709 | /// Addresses returned by the operating system that are not IP addresses are |
710 | /// silently ignored. | |
711 | /// | |
cc61c64b XL |
712 | /// [`FromStr`]: ../../std/str/trait.FromStr.html |
713 | /// [`IpAddr`]: ../../std/net/enum.IpAddr.html | |
714 | /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html | |
715 | /// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html | |
716 | /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html | |
717 | /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html | |
718 | /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html | |
719 | /// [`&str`]: ../../std/primitive.str.html | |
720 | /// [`TcpStream`]: ../../std/net/struct.TcpStream.html | |
721 | /// [`to_socket_addrs`]: #tymethod.to_socket_addrs | |
722 | /// [`UdpSocket`]: ../../std/net/struct.UdpSocket.html | |
723 | /// [`u16`]: ../../std/primitive.u16.html | |
724 | /// | |
725 | /// # Examples | |
85aaf69f | 726 | /// |
ea8adc8c XL |
727 | /// Creating a [`SocketAddr`] iterator that yields one item: |
728 | /// | |
729 | /// ``` | |
730 | /// use std::net::{ToSocketAddrs, SocketAddr}; | |
731 | /// | |
732 | /// let addr = SocketAddr::from(([127, 0, 0, 1], 443)); | |
733 | /// let mut addrs_iter = addr.to_socket_addrs().unwrap(); | |
734 | /// | |
735 | /// assert_eq!(Some(addr), addrs_iter.next()); | |
736 | /// assert!(addrs_iter.next().is_none()); | |
737 | /// ``` | |
738 | /// | |
739 | /// Creating a [`SocketAddr`] iterator from a hostname: | |
740 | /// | |
85aaf69f | 741 | /// ```no_run |
ea8adc8c XL |
742 | /// use std::net::{SocketAddr, ToSocketAddrs}; |
743 | /// | |
744 | /// // assuming 'localhost' resolves to 127.0.0.1 | |
745 | /// let mut addrs_iter = "localhost:443".to_socket_addrs().unwrap(); | |
746 | /// assert_eq!(addrs_iter.next(), Some(SocketAddr::from(([127, 0, 0, 1], 443)))); | |
747 | /// assert!(addrs_iter.next().is_none()); | |
748 | /// | |
749 | /// // assuming 'foo' does not resolve | |
750 | /// assert!("foo:443".to_socket_addrs().is_err()); | |
85aaf69f | 751 | /// ``` |
ea8adc8c XL |
752 | /// |
753 | /// Creating a [`SocketAddr`] iterator that yields multiple items: | |
754 | /// | |
755 | /// ``` | |
756 | /// use std::net::{SocketAddr, ToSocketAddrs}; | |
757 | /// | |
758 | /// let addr1 = SocketAddr::from(([0, 0, 0, 0], 80)); | |
759 | /// let addr2 = SocketAddr::from(([127, 0, 0, 1], 443)); | |
760 | /// let addrs = vec![addr1, addr2]; | |
761 | /// | |
762 | /// let mut addrs_iter = (&addrs[..]).to_socket_addrs().unwrap(); | |
763 | /// | |
764 | /// assert_eq!(Some(addr1), addrs_iter.next()); | |
765 | /// assert_eq!(Some(addr2), addrs_iter.next()); | |
766 | /// assert!(addrs_iter.next().is_none()); | |
767 | /// ``` | |
768 | /// | |
769 | /// Attempting to create a [`SocketAddr`] iterator from an improperly formatted | |
770 | /// socket address `&str` (missing the port): | |
771 | /// | |
772 | /// ``` | |
773 | /// use std::io; | |
774 | /// use std::net::ToSocketAddrs; | |
775 | /// | |
776 | /// let err = "127.0.0.1".to_socket_addrs().unwrap_err(); | |
777 | /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); | |
778 | /// ``` | |
779 | /// | |
780 | /// [`TcpStream::connect`] is an example of an function that utilizes | |
ff7c6d11 | 781 | /// `ToSocketAddrs` as a trait bound on its parameter in order to accept |
ea8adc8c XL |
782 | /// different types: |
783 | /// | |
784 | /// ```no_run | |
785 | /// use std::net::{TcpStream, Ipv4Addr}; | |
786 | /// | |
787 | /// let stream = TcpStream::connect(("127.0.0.1", 443)); | |
788 | /// // or | |
789 | /// let stream = TcpStream::connect("127.0.0.1:443"); | |
790 | /// // or | |
791 | /// let stream = TcpStream::connect((Ipv4Addr::new(127, 0, 0, 1), 443)); | |
792 | /// ``` | |
793 | /// | |
794 | /// [`TcpStream::connect`]: ../../std/net/struct.TcpStream.html#method.connect | |
c34b1796 | 795 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
796 | pub trait ToSocketAddrs { |
797 | /// Returned iterator over socket addresses which this type may correspond | |
798 | /// to. | |
c34b1796 | 799 | #[stable(feature = "rust1", since = "1.0.0")] |
60c5eb7d | 800 | type Iter: Iterator<Item = SocketAddr>; |
85aaf69f SL |
801 | |
802 | /// Converts this object to an iterator of resolved `SocketAddr`s. | |
803 | /// | |
804 | /// The returned iterator may not actually yield any values depending on the | |
805 | /// outcome of any resolution performed. | |
806 | /// | |
807 | /// Note that this function may block the current thread while resolution is | |
808 | /// performed. | |
c34b1796 | 809 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
810 | fn to_socket_addrs(&self) -> io::Result<Self::Iter>; |
811 | } | |
812 | ||
c34b1796 | 813 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
814 | impl ToSocketAddrs for SocketAddr { |
815 | type Iter = option::IntoIter<SocketAddr>; | |
816 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
817 | Ok(Some(*self).into_iter()) | |
818 | } | |
819 | } | |
820 | ||
c34b1796 AL |
821 | #[stable(feature = "rust1", since = "1.0.0")] |
822 | impl ToSocketAddrs for SocketAddrV4 { | |
823 | type Iter = option::IntoIter<SocketAddr>; | |
824 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
825 | SocketAddr::V4(*self).to_socket_addrs() | |
826 | } | |
827 | } | |
828 | ||
829 | #[stable(feature = "rust1", since = "1.0.0")] | |
830 | impl ToSocketAddrs for SocketAddrV6 { | |
831 | type Iter = option::IntoIter<SocketAddr>; | |
832 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
833 | SocketAddr::V6(*self).to_socket_addrs() | |
834 | } | |
835 | } | |
836 | ||
837 | #[stable(feature = "rust1", since = "1.0.0")] | |
85aaf69f SL |
838 | impl ToSocketAddrs for (IpAddr, u16) { |
839 | type Iter = option::IntoIter<SocketAddr>; | |
840 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
841 | let (ip, port) = *self; | |
c34b1796 AL |
842 | match ip { |
843 | IpAddr::V4(ref a) => (*a, port).to_socket_addrs(), | |
844 | IpAddr::V6(ref a) => (*a, port).to_socket_addrs(), | |
845 | } | |
846 | } | |
847 | } | |
848 | ||
849 | #[stable(feature = "rust1", since = "1.0.0")] | |
850 | impl ToSocketAddrs for (Ipv4Addr, u16) { | |
851 | type Iter = option::IntoIter<SocketAddr>; | |
852 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
853 | let (ip, port) = *self; | |
854 | SocketAddrV4::new(ip, port).to_socket_addrs() | |
855 | } | |
856 | } | |
857 | ||
858 | #[stable(feature = "rust1", since = "1.0.0")] | |
859 | impl ToSocketAddrs for (Ipv6Addr, u16) { | |
860 | type Iter = option::IntoIter<SocketAddr>; | |
861 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
862 | let (ip, port) = *self; | |
863 | SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs() | |
85aaf69f SL |
864 | } |
865 | } | |
866 | ||
0731742a XL |
867 | fn resolve_socket_addr(lh: LookupHost) -> io::Result<vec::IntoIter<SocketAddr>> { |
868 | let p = lh.port(); | |
60c5eb7d XL |
869 | let v: Vec<_> = lh |
870 | .map(|mut a| { | |
871 | a.set_port(p); | |
872 | a | |
873 | }) | |
874 | .collect(); | |
85aaf69f SL |
875 | Ok(v.into_iter()) |
876 | } | |
877 | ||
c34b1796 | 878 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 879 | impl ToSocketAddrs for (&str, u16) { |
85aaf69f SL |
880 | type Iter = vec::IntoIter<SocketAddr>; |
881 | fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { | |
882 | let (host, port) = *self; | |
883 | ||
c34b1796 AL |
884 | // try to parse the host as a regular IP address first |
885 | if let Ok(addr) = host.parse::<Ipv4Addr>() { | |
886 | let addr = SocketAddrV4::new(addr, port); | |
60c5eb7d | 887 | return Ok(vec![SocketAddr::V4(addr)].into_iter()); |
c34b1796 AL |
888 | } |
889 | if let Ok(addr) = host.parse::<Ipv6Addr>() { | |
890 | let addr = SocketAddrV6::new(addr, port, 0, 0); | |
60c5eb7d | 891 | return Ok(vec![SocketAddr::V6(addr)].into_iter()); |
85aaf69f SL |
892 | } |
893 | ||
0731742a | 894 | resolve_socket_addr((host, port).try_into()?) |
85aaf69f SL |
895 | } |
896 | } | |
897 | ||
898 | // accepts strings like 'localhost:12345' | |
c34b1796 | 899 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
900 | impl ToSocketAddrs for str { |
901 | type Iter = vec::IntoIter<SocketAddr>; | |
902 | fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { | |
903 | // try to parse as a regular SocketAddr first | |
74b04a01 | 904 | if let Ok(addr) = self.parse() { |
7453a54e | 905 | return Ok(vec![addr].into_iter()); |
85aaf69f SL |
906 | } |
907 | ||
0731742a | 908 | resolve_socket_addr(self.try_into()?) |
85aaf69f SL |
909 | } |
910 | } | |
911 | ||
7453a54e SL |
912 | #[stable(feature = "slice_to_socket_addrs", since = "1.8.0")] |
913 | impl<'a> ToSocketAddrs for &'a [SocketAddr] { | |
914 | type Iter = iter::Cloned<slice::Iter<'a, SocketAddr>>; | |
915 | ||
916 | fn to_socket_addrs(&self) -> io::Result<Self::Iter> { | |
917 | Ok(self.iter().cloned()) | |
918 | } | |
919 | } | |
920 | ||
92a42be0 | 921 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 922 | impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T { |
85aaf69f SL |
923 | type Iter = T::Iter; |
924 | fn to_socket_addrs(&self) -> io::Result<T::Iter> { | |
925 | (**self).to_socket_addrs() | |
926 | } | |
927 | } | |
928 | ||
32a655c1 SL |
929 | #[stable(feature = "string_to_socket_addrs", since = "1.16.0")] |
930 | impl ToSocketAddrs for String { | |
931 | type Iter = vec::IntoIter<SocketAddr>; | |
932 | fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { | |
933 | (&**self).to_socket_addrs() | |
934 | } | |
935 | } | |
936 | ||
c30ab7b3 | 937 | #[cfg(all(test, not(target_os = "emscripten")))] |
85aaf69f | 938 | mod tests { |
60c5eb7d | 939 | use crate::net::test::{sa4, sa6, tsa}; |
532ac7d7 | 940 | use crate::net::*; |
c34b1796 | 941 | |
85aaf69f SL |
942 | #[test] |
943 | fn to_socket_addr_ipaddr_u16() { | |
c34b1796 AL |
944 | let a = Ipv4Addr::new(77, 88, 21, 11); |
945 | let p = 12345; | |
946 | let e = SocketAddr::V4(SocketAddrV4::new(a, p)); | |
85aaf69f SL |
947 | assert_eq!(Ok(vec![e]), tsa((a, p))); |
948 | } | |
949 | ||
950 | #[test] | |
951 | fn to_socket_addr_str_u16() { | |
c34b1796 AL |
952 | let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); |
953 | assert_eq!(Ok(vec![a]), tsa(("77.88.21.11", 24352))); | |
85aaf69f | 954 | |
c34b1796 | 955 | let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); |
85aaf69f SL |
956 | assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53))); |
957 | ||
c34b1796 | 958 | let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); |
532ac7d7 | 959 | #[cfg(not(target_env = "sgx"))] |
c34b1796 | 960 | assert!(tsa(("localhost", 23924)).unwrap().contains(&a)); |
532ac7d7 XL |
961 | #[cfg(target_env = "sgx")] |
962 | let _ = a; | |
85aaf69f SL |
963 | } |
964 | ||
965 | #[test] | |
966 | fn to_socket_addr_str() { | |
c34b1796 | 967 | let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); |
85aaf69f SL |
968 | assert_eq!(Ok(vec![a]), tsa("77.88.21.11:24352")); |
969 | ||
c34b1796 | 970 | let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); |
85aaf69f SL |
971 | assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53")); |
972 | ||
c34b1796 | 973 | let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); |
532ac7d7 | 974 | #[cfg(not(target_env = "sgx"))] |
85aaf69f | 975 | assert!(tsa("localhost:23924").unwrap().contains(&a)); |
532ac7d7 XL |
976 | #[cfg(target_env = "sgx")] |
977 | let _ = a; | |
85aaf69f | 978 | } |
c34b1796 | 979 | |
32a655c1 SL |
980 | #[test] |
981 | fn to_socket_addr_string() { | |
982 | let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); | |
983 | assert_eq!(Ok(vec![a]), tsa(&*format!("{}:{}", "77.88.21.11", "24352"))); | |
984 | assert_eq!(Ok(vec![a]), tsa(&format!("{}:{}", "77.88.21.11", "24352"))); | |
985 | assert_eq!(Ok(vec![a]), tsa(format!("{}:{}", "77.88.21.11", "24352"))); | |
986 | ||
987 | let s = format!("{}:{}", "77.88.21.11", "24352"); | |
988 | assert_eq!(Ok(vec![a]), tsa(s)); | |
989 | // s has been moved into the tsa call | |
990 | } | |
991 | ||
c34b1796 | 992 | #[test] |
ba9703b0 XL |
993 | fn bind_udp_socket_bad() { |
994 | // rust-lang/rust#53957: This is a regression test for a parsing problem | |
995 | // discovered as part of issue rust-lang/rust#23076, where we were | |
996 | // incorrectly parsing invalid input and then that would result in a | |
997 | // successful `UdpSocket` binding when we would expect failure. | |
998 | // | |
999 | // At one time, this test was written as a call to `tsa` with | |
1000 | // INPUT_23076. However, that structure yields an unreliable test, | |
1001 | // because it ends up passing junk input to the DNS server, and some DNS | |
1002 | // servers will respond with `Ok` to such input, with the ip address of | |
1003 | // the DNS server itself. | |
1004 | // | |
1005 | // This form of the test is more robust: even when the DNS server | |
1006 | // returns its own address, it is still an error to bind a UDP socket to | |
1007 | // a non-local address, and so we still get an error here in that case. | |
1008 | ||
1009 | const INPUT_23076: &'static str = "1200::AB00:1234::2552:7777:1313:34300"; | |
1010 | ||
1011 | assert!(crate::net::UdpSocket::bind(INPUT_23076).is_err()) | |
c34b1796 | 1012 | } |
7453a54e SL |
1013 | |
1014 | #[test] | |
1015 | fn set_ip() { | |
60c5eb7d XL |
1016 | fn ip4(low: u8) -> Ipv4Addr { |
1017 | Ipv4Addr::new(77, 88, 21, low) | |
1018 | } | |
1019 | fn ip6(low: u16) -> Ipv6Addr { | |
1020 | Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low) | |
1021 | } | |
7453a54e SL |
1022 | |
1023 | let mut v4 = SocketAddrV4::new(ip4(11), 80); | |
1024 | assert_eq!(v4.ip(), &ip4(11)); | |
1025 | v4.set_ip(ip4(12)); | |
1026 | assert_eq!(v4.ip(), &ip4(12)); | |
1027 | ||
1028 | let mut addr = SocketAddr::V4(v4); | |
1029 | assert_eq!(addr.ip(), IpAddr::V4(ip4(12))); | |
1030 | addr.set_ip(IpAddr::V4(ip4(13))); | |
1031 | assert_eq!(addr.ip(), IpAddr::V4(ip4(13))); | |
1032 | addr.set_ip(IpAddr::V6(ip6(14))); | |
1033 | assert_eq!(addr.ip(), IpAddr::V6(ip6(14))); | |
1034 | ||
1035 | let mut v6 = SocketAddrV6::new(ip6(1), 80, 0, 0); | |
1036 | assert_eq!(v6.ip(), &ip6(1)); | |
1037 | v6.set_ip(ip6(2)); | |
1038 | assert_eq!(v6.ip(), &ip6(2)); | |
1039 | ||
1040 | let mut addr = SocketAddr::V6(v6); | |
1041 | assert_eq!(addr.ip(), IpAddr::V6(ip6(2))); | |
1042 | addr.set_ip(IpAddr::V6(ip6(3))); | |
1043 | assert_eq!(addr.ip(), IpAddr::V6(ip6(3))); | |
1044 | addr.set_ip(IpAddr::V4(ip4(4))); | |
1045 | assert_eq!(addr.ip(), IpAddr::V4(ip4(4))); | |
1046 | } | |
1047 | ||
1048 | #[test] | |
1049 | fn set_port() { | |
1050 | let mut v4 = SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80); | |
1051 | assert_eq!(v4.port(), 80); | |
1052 | v4.set_port(443); | |
1053 | assert_eq!(v4.port(), 443); | |
1054 | ||
1055 | let mut addr = SocketAddr::V4(v4); | |
1056 | assert_eq!(addr.port(), 443); | |
1057 | addr.set_port(8080); | |
1058 | assert_eq!(addr.port(), 8080); | |
1059 | ||
1060 | let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 0); | |
1061 | assert_eq!(v6.port(), 80); | |
1062 | v6.set_port(443); | |
1063 | assert_eq!(v6.port(), 443); | |
1064 | ||
1065 | let mut addr = SocketAddr::V6(v6); | |
1066 | assert_eq!(addr.port(), 443); | |
1067 | addr.set_port(8080); | |
1068 | assert_eq!(addr.port(), 8080); | |
1069 | } | |
1070 | ||
1071 | #[test] | |
1072 | fn set_flowinfo() { | |
1073 | let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0); | |
1074 | assert_eq!(v6.flowinfo(), 10); | |
1075 | v6.set_flowinfo(20); | |
1076 | assert_eq!(v6.flowinfo(), 20); | |
1077 | } | |
1078 | ||
1079 | #[test] | |
1080 | fn set_scope_id() { | |
1081 | let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 10); | |
1082 | assert_eq!(v6.scope_id(), 10); | |
1083 | v6.set_scope_id(20); | |
1084 | assert_eq!(v6.scope_id(), 20); | |
1085 | } | |
c30ab7b3 SL |
1086 | |
1087 | #[test] | |
1088 | fn is_v4() { | |
1089 | let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)); | |
1090 | assert!(v4.is_ipv4()); | |
1091 | assert!(!v4.is_ipv6()); | |
1092 | } | |
1093 | ||
1094 | #[test] | |
1095 | fn is_v6() { | |
1096 | let v6 = SocketAddr::V6(SocketAddrV6::new( | |
60c5eb7d XL |
1097 | Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), |
1098 | 80, | |
1099 | 10, | |
1100 | 0, | |
1101 | )); | |
c30ab7b3 SL |
1102 | assert!(!v6.is_ipv4()); |
1103 | assert!(v6.is_ipv6()); | |
1104 | } | |
85aaf69f | 1105 | } |