]>
Commit | Line | Data |
---|---|---|
85aaf69f SL |
1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | use prelude::v1::*; | |
12 | ||
13 | use fmt; | |
14 | use hash; | |
15 | use io; | |
85aaf69f | 16 | use mem; |
9cc50fc6 | 17 | use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr}; |
85aaf69f | 18 | use option; |
92a42be0 | 19 | use sys::net::netc as c; |
85aaf69f SL |
20 | use sys_common::{FromInner, AsInner, IntoInner}; |
21 | use vec; | |
7453a54e SL |
22 | use iter; |
23 | use slice; | |
85aaf69f | 24 | |
c34b1796 | 25 | /// Representation of a socket address for networking applications. |
85aaf69f | 26 | /// |
c34b1796 AL |
27 | /// A socket address can either represent the IPv4 or IPv6 protocol and is |
28 | /// paired with at least a port number as well. Each protocol may have more | |
29 | /// specific information about the address available to it as well. | |
30 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | |
31 | #[stable(feature = "rust1", since = "1.0.0")] | |
32 | pub enum SocketAddr { | |
33 | /// An IPv4 socket address which is a (ip, port) combination. | |
34 | #[stable(feature = "rust1", since = "1.0.0")] | |
7453a54e | 35 | V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4), |
c34b1796 AL |
36 | /// An IPv6 socket address |
37 | #[stable(feature = "rust1", since = "1.0.0")] | |
7453a54e | 38 | V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6), |
85aaf69f SL |
39 | } |
40 | ||
c34b1796 | 41 | /// An IPv4 socket address which is a (ip, port) combination. |
85aaf69f | 42 | #[derive(Copy)] |
c34b1796 | 43 | #[stable(feature = "rust1", since = "1.0.0")] |
92a42be0 | 44 | pub struct SocketAddrV4 { inner: c::sockaddr_in } |
c34b1796 | 45 | |
bd371182 | 46 | /// An IPv6 socket address. |
c34b1796 AL |
47 | #[derive(Copy)] |
48 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 | 49 | pub struct SocketAddrV6 { inner: c::sockaddr_in6 } |
85aaf69f SL |
50 | |
51 | impl SocketAddr { | |
52 | /// Creates a new socket address from the (ip, port) pair. | |
9cc50fc6 | 53 | #[stable(feature = "ip_addr", since = "1.7.0")] |
85aaf69f | 54 | pub fn new(ip: IpAddr, port: u16) -> SocketAddr { |
c34b1796 AL |
55 | match ip { |
56 | IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), | |
57 | IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)), | |
58 | } | |
85aaf69f SL |
59 | } |
60 | ||
bd371182 | 61 | /// Returns the IP address associated with this socket address. |
9cc50fc6 | 62 | #[stable(feature = "ip_addr", since = "1.7.0")] |
85aaf69f | 63 | pub fn ip(&self) -> IpAddr { |
c34b1796 AL |
64 | match *self { |
65 | SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), | |
66 | SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), | |
85aaf69f SL |
67 | } |
68 | } | |
69 | ||
7453a54e | 70 | /// Change the IP address associated with this socket address. |
54a0048b | 71 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
7453a54e SL |
72 | pub fn set_ip(&mut self, new_ip: IpAddr) { |
73 | // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. | |
74 | match (self, new_ip) { | |
75 | (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip), | |
76 | (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip), | |
77 | (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()), | |
78 | } | |
79 | } | |
80 | ||
bd371182 | 81 | /// Returns the port number associated with this socket address. |
c34b1796 | 82 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 83 | pub fn port(&self) -> u16 { |
c34b1796 AL |
84 | match *self { |
85 | SocketAddr::V4(ref a) => a.port(), | |
86 | SocketAddr::V6(ref a) => a.port(), | |
85aaf69f SL |
87 | } |
88 | } | |
7453a54e SL |
89 | |
90 | /// Change the port number associated with this socket address. | |
54a0048b | 91 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
7453a54e SL |
92 | pub fn set_port(&mut self, new_port: u16) { |
93 | match *self { | |
94 | SocketAddr::V4(ref mut a) => a.set_port(new_port), | |
95 | SocketAddr::V6(ref mut a) => a.set_port(new_port), | |
96 | } | |
97 | } | |
c34b1796 | 98 | } |
85aaf69f | 99 | |
c34b1796 AL |
100 | impl SocketAddrV4 { |
101 | /// Creates a new socket address from the (ip, port) pair. | |
102 | #[stable(feature = "rust1", since = "1.0.0")] | |
103 | pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { | |
104 | SocketAddrV4 { | |
92a42be0 SL |
105 | inner: c::sockaddr_in { |
106 | sin_family: c::AF_INET as c::sa_family_t, | |
c34b1796 AL |
107 | sin_port: hton(port), |
108 | sin_addr: *ip.as_inner(), | |
109 | .. unsafe { mem::zeroed() } | |
110 | }, | |
85aaf69f SL |
111 | } |
112 | } | |
c34b1796 | 113 | |
bd371182 | 114 | /// Returns the IP address associated with this socket address. |
c34b1796 AL |
115 | #[stable(feature = "rust1", since = "1.0.0")] |
116 | pub fn ip(&self) -> &Ipv4Addr { | |
117 | unsafe { | |
92a42be0 | 118 | &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) |
c34b1796 AL |
119 | } |
120 | } | |
121 | ||
7453a54e | 122 | /// Change the IP address associated with this socket address. |
54a0048b SL |
123 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
124 | pub fn set_ip(&mut self, new_ip: Ipv4Addr) { | |
125 | self.inner.sin_addr = *new_ip.as_inner() | |
126 | } | |
7453a54e | 127 | |
bd371182 | 128 | /// Returns the port number associated with this socket address. |
c34b1796 | 129 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b SL |
130 | pub fn port(&self) -> u16 { |
131 | ntoh(self.inner.sin_port) | |
132 | } | |
7453a54e SL |
133 | |
134 | /// Change the port number associated with this socket address. | |
54a0048b SL |
135 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
136 | pub fn set_port(&mut self, new_port: u16) { | |
137 | self.inner.sin_port = hton(new_port); | |
138 | } | |
85aaf69f SL |
139 | } |
140 | ||
c34b1796 AL |
141 | impl SocketAddrV6 { |
142 | /// Creates a new socket address from the ip/port/flowinfo/scope_id | |
143 | /// components. | |
144 | #[stable(feature = "rust1", since = "1.0.0")] | |
145 | pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) | |
146 | -> SocketAddrV6 { | |
147 | SocketAddrV6 { | |
92a42be0 SL |
148 | inner: c::sockaddr_in6 { |
149 | sin6_family: c::AF_INET6 as c::sa_family_t, | |
c34b1796 AL |
150 | sin6_port: hton(port), |
151 | sin6_addr: *ip.as_inner(), | |
54a0048b SL |
152 | sin6_flowinfo: flowinfo, |
153 | sin6_scope_id: scope_id, | |
c34b1796 AL |
154 | .. unsafe { mem::zeroed() } |
155 | }, | |
85aaf69f SL |
156 | } |
157 | } | |
c34b1796 | 158 | |
bd371182 | 159 | /// Returns the IP address associated with this socket address. |
c34b1796 AL |
160 | #[stable(feature = "rust1", since = "1.0.0")] |
161 | pub fn ip(&self) -> &Ipv6Addr { | |
162 | unsafe { | |
92a42be0 | 163 | &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) |
c34b1796 AL |
164 | } |
165 | } | |
166 | ||
7453a54e | 167 | /// Change the IP address associated with this socket address. |
54a0048b SL |
168 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
169 | pub fn set_ip(&mut self, new_ip: Ipv6Addr) { | |
170 | self.inner.sin6_addr = *new_ip.as_inner() | |
171 | } | |
7453a54e | 172 | |
bd371182 | 173 | /// Returns the port number associated with this socket address. |
c34b1796 | 174 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b SL |
175 | pub fn port(&self) -> u16 { |
176 | ntoh(self.inner.sin6_port) | |
177 | } | |
c34b1796 | 178 | |
7453a54e | 179 | /// Change the port number associated with this socket address. |
54a0048b SL |
180 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
181 | pub fn set_port(&mut self, new_port: u16) { | |
182 | self.inner.sin6_port = hton(new_port); | |
183 | } | |
7453a54e | 184 | |
9cc50fc6 SL |
185 | /// Returns the flow information associated with this address, |
186 | /// corresponding to the `sin6_flowinfo` field in C. | |
c34b1796 | 187 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b SL |
188 | pub fn flowinfo(&self) -> u32 { |
189 | self.inner.sin6_flowinfo | |
190 | } | |
c34b1796 | 191 | |
7453a54e | 192 | /// Change the flow information associated with this socket address. |
54a0048b | 193 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
7453a54e | 194 | pub fn set_flowinfo(&mut self, new_flowinfo: u32) { |
54a0048b | 195 | self.inner.sin6_flowinfo = new_flowinfo; |
7453a54e SL |
196 | } |
197 | ||
9cc50fc6 SL |
198 | /// Returns the scope ID associated with this address, |
199 | /// corresponding to the `sin6_scope_id` field in C. | |
c34b1796 | 200 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b SL |
201 | pub fn scope_id(&self) -> u32 { |
202 | self.inner.sin6_scope_id | |
203 | } | |
7453a54e SL |
204 | |
205 | /// Change the scope ID associated with this socket address. | |
54a0048b | 206 | #[stable(feature = "sockaddr_setters", since = "1.9.0")] |
7453a54e | 207 | pub fn set_scope_id(&mut self, new_scope_id: u32) { |
54a0048b | 208 | self.inner.sin6_scope_id = new_scope_id; |
7453a54e | 209 | } |
85aaf69f SL |
210 | } |
211 | ||
92a42be0 SL |
212 | impl FromInner<c::sockaddr_in> for SocketAddrV4 { |
213 | fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 { | |
c34b1796 | 214 | SocketAddrV4 { inner: addr } |
85aaf69f SL |
215 | } |
216 | } | |
217 | ||
92a42be0 SL |
218 | impl FromInner<c::sockaddr_in6> for SocketAddrV6 { |
219 | fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 { | |
c34b1796 | 220 | SocketAddrV6 { inner: addr } |
85aaf69f SL |
221 | } |
222 | } | |
223 | ||
92a42be0 SL |
224 | impl<'a> IntoInner<(*const c::sockaddr, c::socklen_t)> for &'a SocketAddr { |
225 | fn into_inner(self) -> (*const c::sockaddr, c::socklen_t) { | |
c34b1796 AL |
226 | match *self { |
227 | SocketAddr::V4(ref a) => { | |
92a42be0 | 228 | (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) |
85aaf69f | 229 | } |
c34b1796 | 230 | SocketAddr::V6(ref a) => { |
92a42be0 | 231 | (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) |
85aaf69f SL |
232 | } |
233 | } | |
234 | } | |
235 | } | |
236 | ||
c34b1796 AL |
237 | #[stable(feature = "rust1", since = "1.0.0")] |
238 | impl fmt::Display for SocketAddr { | |
239 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
240 | match *self { | |
241 | SocketAddr::V4(ref a) => a.fmt(f), | |
242 | SocketAddr::V6(ref a) => a.fmt(f), | |
243 | } | |
244 | } | |
245 | } | |
246 | ||
247 | #[stable(feature = "rust1", since = "1.0.0")] | |
248 | impl fmt::Display for SocketAddrV4 { | |
249 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
250 | write!(f, "{}:{}", self.ip(), self.port()) | |
251 | } | |
252 | } | |
253 | ||
254 | #[stable(feature = "rust1", since = "1.0.0")] | |
255 | impl fmt::Debug for SocketAddrV4 { | |
85aaf69f SL |
256 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
257 | fmt::Display::fmt(self, fmt) | |
258 | } | |
259 | } | |
260 | ||
c34b1796 AL |
261 | #[stable(feature = "rust1", since = "1.0.0")] |
262 | impl fmt::Display for SocketAddrV6 { | |
263 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
264 | write!(f, "[{}]:{}", self.ip(), self.port()) | |
265 | } | |
85aaf69f SL |
266 | } |
267 | ||
c34b1796 AL |
268 | #[stable(feature = "rust1", since = "1.0.0")] |
269 | impl fmt::Debug for SocketAddrV6 { | |
270 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
271 | fmt::Display::fmt(self, fmt) | |
85aaf69f SL |
272 | } |
273 | } | |
85aaf69f | 274 | |
c34b1796 AL |
275 | #[stable(feature = "rust1", since = "1.0.0")] |
276 | impl Clone for SocketAddrV4 { | |
277 | fn clone(&self) -> SocketAddrV4 { *self } | |
278 | } | |
279 | #[stable(feature = "rust1", since = "1.0.0")] | |
280 | impl Clone for SocketAddrV6 { | |
281 | fn clone(&self) -> SocketAddrV6 { *self } | |
282 | } | |
283 | ||
284 | #[stable(feature = "rust1", since = "1.0.0")] | |
285 | impl PartialEq for SocketAddrV4 { | |
286 | fn eq(&self, other: &SocketAddrV4) -> bool { | |
287 | self.inner.sin_port == other.inner.sin_port && | |
288 | self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr | |
289 | } | |
290 | } | |
291 | #[stable(feature = "rust1", since = "1.0.0")] | |
292 | impl PartialEq for SocketAddrV6 { | |
293 | fn eq(&self, other: &SocketAddrV6) -> bool { | |
294 | self.inner.sin6_port == other.inner.sin6_port && | |
295 | self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr && | |
296 | self.inner.sin6_flowinfo == other.inner.sin6_flowinfo && | |
297 | self.inner.sin6_scope_id == other.inner.sin6_scope_id | |
85aaf69f SL |
298 | } |
299 | } | |
85aaf69f | 300 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 AL |
301 | impl Eq for SocketAddrV4 {} |
302 | #[stable(feature = "rust1", since = "1.0.0")] | |
303 | impl Eq for SocketAddrV6 {} | |
304 | ||
305 | #[stable(feature = "rust1", since = "1.0.0")] | |
306 | impl hash::Hash for SocketAddrV4 { | |
85aaf69f | 307 | fn hash<H: hash::Hasher>(&self, s: &mut H) { |
c34b1796 AL |
308 | (self.inner.sin_port, self.inner.sin_addr.s_addr).hash(s) |
309 | } | |
310 | } | |
311 | #[stable(feature = "rust1", since = "1.0.0")] | |
312 | impl hash::Hash for SocketAddrV6 { | |
313 | fn hash<H: hash::Hasher>(&self, s: &mut H) { | |
314 | (self.inner.sin6_port, &self.inner.sin6_addr.s6_addr, | |
315 | self.inner.sin6_flowinfo, self.inner.sin6_scope_id).hash(s) | |
85aaf69f SL |
316 | } |
317 | } | |
318 | ||
319 | /// A trait for objects which can be converted or resolved to one or more | |
320 | /// `SocketAddr` values. | |
321 | /// | |
322 | /// This trait is used for generic address resolution when constructing network | |
323 | /// objects. By default it is implemented for the following types: | |
324 | /// | |
c34b1796 AL |
325 | /// * `SocketAddr`, `SocketAddrV4`, `SocketAddrV6` - `to_socket_addrs` is |
326 | /// identity function. | |
85aaf69f | 327 | /// |
c34b1796 | 328 | /// * `(IpvNAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially. |
85aaf69f SL |
329 | /// |
330 | /// * `(&str, u16)` - the string should be either a string representation of an | |
c34b1796 | 331 | /// IP address expected by `FromStr` implementation for `IpvNAddr` or a host |
85aaf69f SL |
332 | /// name. |
333 | /// | |
334 | /// * `&str` - the string should be either a string representation of a | |
335 | /// `SocketAddr` as expected by its `FromStr` implementation or a string like | |
336 | /// `<host_name>:<port>` pair where `<port>` is a `u16` value. | |
337 | /// | |
338 | /// This trait allows constructing network objects like `TcpStream` or | |
339 | /// `UdpSocket` easily with values of various types for the bind/connection | |
340 | /// address. It is needed because sometimes one type is more appropriate than | |
341 | /// the other: for simple uses a string like `"localhost:12345"` is much nicer | |
342 | /// than manual construction of the corresponding `SocketAddr`, but sometimes | |
343 | /// `SocketAddr` value is *the* main source of the address, and converting it to | |
344 | /// some other type (e.g. a string) just for it to be converted back to | |
345 | /// `SocketAddr` in constructor methods is pointless. | |
346 | /// | |
347 | /// Some examples: | |
348 | /// | |
349 | /// ```no_run | |
c34b1796 | 350 | /// use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr}; |
85aaf69f SL |
351 | /// |
352 | /// fn main() { | |
c34b1796 | 353 | /// let ip = Ipv4Addr::new(127, 0, 0, 1); |
85aaf69f SL |
354 | /// let port = 12345; |
355 | /// | |
356 | /// // The following lines are equivalent modulo possible "localhost" name | |
357 | /// // resolution differences | |
c34b1796 AL |
358 | /// let tcp_s = TcpStream::connect(SocketAddrV4::new(ip, port)); |
359 | /// let tcp_s = TcpStream::connect((ip, port)); | |
360 | /// let tcp_s = TcpStream::connect(("127.0.0.1", port)); | |
361 | /// let tcp_s = TcpStream::connect(("localhost", port)); | |
85aaf69f SL |
362 | /// let tcp_s = TcpStream::connect("127.0.0.1:12345"); |
363 | /// let tcp_s = TcpStream::connect("localhost:12345"); | |
364 | /// | |
365 | /// // TcpListener::bind(), UdpSocket::bind() and UdpSocket::send_to() | |
366 | /// // behave similarly | |
367 | /// let tcp_l = TcpListener::bind("localhost:12345"); | |
368 | /// | |
c34b1796 | 369 | /// let mut udp_s = UdpSocket::bind(("127.0.0.1", port)).unwrap(); |
9346a6ac | 370 | /// udp_s.send_to(&[7], (ip, 23451)).unwrap(); |
85aaf69f SL |
371 | /// } |
372 | /// ``` | |
c34b1796 | 373 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
374 | pub trait ToSocketAddrs { |
375 | /// Returned iterator over socket addresses which this type may correspond | |
376 | /// to. | |
c34b1796 | 377 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
378 | type Iter: Iterator<Item=SocketAddr>; |
379 | ||
380 | /// Converts this object to an iterator of resolved `SocketAddr`s. | |
381 | /// | |
382 | /// The returned iterator may not actually yield any values depending on the | |
383 | /// outcome of any resolution performed. | |
384 | /// | |
385 | /// Note that this function may block the current thread while resolution is | |
386 | /// performed. | |
387 | /// | |
388 | /// # Errors | |
389 | /// | |
390 | /// Any errors encountered during resolution will be returned as an `Err`. | |
c34b1796 | 391 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
392 | fn to_socket_addrs(&self) -> io::Result<Self::Iter>; |
393 | } | |
394 | ||
c34b1796 | 395 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
396 | impl ToSocketAddrs for SocketAddr { |
397 | type Iter = option::IntoIter<SocketAddr>; | |
398 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
399 | Ok(Some(*self).into_iter()) | |
400 | } | |
401 | } | |
402 | ||
c34b1796 AL |
403 | #[stable(feature = "rust1", since = "1.0.0")] |
404 | impl ToSocketAddrs for SocketAddrV4 { | |
405 | type Iter = option::IntoIter<SocketAddr>; | |
406 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
407 | SocketAddr::V4(*self).to_socket_addrs() | |
408 | } | |
409 | } | |
410 | ||
411 | #[stable(feature = "rust1", since = "1.0.0")] | |
412 | impl ToSocketAddrs for SocketAddrV6 { | |
413 | type Iter = option::IntoIter<SocketAddr>; | |
414 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
415 | SocketAddr::V6(*self).to_socket_addrs() | |
416 | } | |
417 | } | |
418 | ||
419 | #[stable(feature = "rust1", since = "1.0.0")] | |
85aaf69f SL |
420 | impl ToSocketAddrs for (IpAddr, u16) { |
421 | type Iter = option::IntoIter<SocketAddr>; | |
422 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
423 | let (ip, port) = *self; | |
c34b1796 AL |
424 | match ip { |
425 | IpAddr::V4(ref a) => (*a, port).to_socket_addrs(), | |
426 | IpAddr::V6(ref a) => (*a, port).to_socket_addrs(), | |
427 | } | |
428 | } | |
429 | } | |
430 | ||
431 | #[stable(feature = "rust1", since = "1.0.0")] | |
432 | impl ToSocketAddrs for (Ipv4Addr, u16) { | |
433 | type Iter = option::IntoIter<SocketAddr>; | |
434 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
435 | let (ip, port) = *self; | |
436 | SocketAddrV4::new(ip, port).to_socket_addrs() | |
437 | } | |
438 | } | |
439 | ||
440 | #[stable(feature = "rust1", since = "1.0.0")] | |
441 | impl ToSocketAddrs for (Ipv6Addr, u16) { | |
442 | type Iter = option::IntoIter<SocketAddr>; | |
443 | fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { | |
444 | let (ip, port) = *self; | |
445 | SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs() | |
85aaf69f SL |
446 | } |
447 | } | |
448 | ||
449 | fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> { | |
54a0048b SL |
450 | let ips = lookup_host(s)?; |
451 | let v: Vec<_> = ips.map(|a| { | |
7453a54e SL |
452 | a.map(|mut a| { |
453 | a.set_port(p); | |
454 | a | |
c34b1796 | 455 | }) |
54a0048b | 456 | }).collect()?; |
85aaf69f SL |
457 | Ok(v.into_iter()) |
458 | } | |
459 | ||
c34b1796 | 460 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
461 | impl<'a> ToSocketAddrs for (&'a str, u16) { |
462 | type Iter = vec::IntoIter<SocketAddr>; | |
463 | fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { | |
464 | let (host, port) = *self; | |
465 | ||
c34b1796 AL |
466 | // try to parse the host as a regular IP address first |
467 | if let Ok(addr) = host.parse::<Ipv4Addr>() { | |
468 | let addr = SocketAddrV4::new(addr, port); | |
469 | return Ok(vec![SocketAddr::V4(addr)].into_iter()) | |
470 | } | |
471 | if let Ok(addr) = host.parse::<Ipv6Addr>() { | |
472 | let addr = SocketAddrV6::new(addr, port, 0, 0); | |
473 | return Ok(vec![SocketAddr::V6(addr)].into_iter()) | |
85aaf69f SL |
474 | } |
475 | ||
476 | resolve_socket_addr(host, port) | |
477 | } | |
478 | } | |
479 | ||
480 | // accepts strings like 'localhost:12345' | |
c34b1796 | 481 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
482 | impl ToSocketAddrs for str { |
483 | type Iter = vec::IntoIter<SocketAddr>; | |
484 | fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { | |
485 | // try to parse as a regular SocketAddr first | |
7453a54e SL |
486 | if let Some(addr) = self.parse().ok() { |
487 | return Ok(vec![addr].into_iter()); | |
85aaf69f SL |
488 | } |
489 | ||
490 | macro_rules! try_opt { | |
491 | ($e:expr, $msg:expr) => ( | |
492 | match $e { | |
493 | Some(r) => r, | |
494 | None => return Err(io::Error::new(io::ErrorKind::InvalidInput, | |
c34b1796 | 495 | $msg)), |
85aaf69f SL |
496 | } |
497 | ) | |
498 | } | |
499 | ||
500 | // split the string by ':' and convert the second part to u16 | |
501 | let mut parts_iter = self.rsplitn(2, ':'); | |
502 | let port_str = try_opt!(parts_iter.next(), "invalid socket address"); | |
503 | let host = try_opt!(parts_iter.next(), "invalid socket address"); | |
504 | let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value"); | |
505 | resolve_socket_addr(host, port) | |
506 | } | |
507 | } | |
508 | ||
7453a54e SL |
509 | #[stable(feature = "slice_to_socket_addrs", since = "1.8.0")] |
510 | impl<'a> ToSocketAddrs for &'a [SocketAddr] { | |
511 | type Iter = iter::Cloned<slice::Iter<'a, SocketAddr>>; | |
512 | ||
513 | fn to_socket_addrs(&self) -> io::Result<Self::Iter> { | |
514 | Ok(self.iter().cloned()) | |
515 | } | |
516 | } | |
517 | ||
92a42be0 | 518 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
519 | impl<'a, T: ToSocketAddrs + ?Sized> ToSocketAddrs for &'a T { |
520 | type Iter = T::Iter; | |
521 | fn to_socket_addrs(&self) -> io::Result<T::Iter> { | |
522 | (**self).to_socket_addrs() | |
523 | } | |
524 | } | |
525 | ||
526 | #[cfg(test)] | |
527 | mod tests { | |
528 | use prelude::v1::*; | |
85aaf69f | 529 | use net::*; |
9346a6ac | 530 | use net::test::{tsa, sa6, sa4}; |
c34b1796 | 531 | |
85aaf69f SL |
532 | #[test] |
533 | fn to_socket_addr_ipaddr_u16() { | |
c34b1796 AL |
534 | let a = Ipv4Addr::new(77, 88, 21, 11); |
535 | let p = 12345; | |
536 | let e = SocketAddr::V4(SocketAddrV4::new(a, p)); | |
85aaf69f SL |
537 | assert_eq!(Ok(vec![e]), tsa((a, p))); |
538 | } | |
539 | ||
540 | #[test] | |
541 | fn to_socket_addr_str_u16() { | |
c34b1796 AL |
542 | let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); |
543 | assert_eq!(Ok(vec![a]), tsa(("77.88.21.11", 24352))); | |
85aaf69f | 544 | |
c34b1796 | 545 | let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); |
85aaf69f SL |
546 | assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53))); |
547 | ||
c34b1796 AL |
548 | let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); |
549 | assert!(tsa(("localhost", 23924)).unwrap().contains(&a)); | |
85aaf69f SL |
550 | } |
551 | ||
552 | #[test] | |
553 | fn to_socket_addr_str() { | |
c34b1796 | 554 | let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); |
85aaf69f SL |
555 | assert_eq!(Ok(vec![a]), tsa("77.88.21.11:24352")); |
556 | ||
c34b1796 | 557 | let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); |
85aaf69f SL |
558 | assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53")); |
559 | ||
c34b1796 | 560 | let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); |
85aaf69f SL |
561 | assert!(tsa("localhost:23924").unwrap().contains(&a)); |
562 | } | |
c34b1796 | 563 | |
92a42be0 | 564 | // FIXME: figure out why this fails on openbsd and bitrig and fix it |
c34b1796 | 565 | #[test] |
92a42be0 | 566 | #[cfg(not(any(windows, target_os = "openbsd", target_os = "bitrig")))] |
c34b1796 AL |
567 | fn to_socket_addr_str_bad() { |
568 | assert!(tsa("1200::AB00:1234::2552:7777:1313:34300").is_err()); | |
569 | } | |
7453a54e SL |
570 | |
571 | #[test] | |
572 | fn set_ip() { | |
573 | fn ip4(low: u8) -> Ipv4Addr { Ipv4Addr::new(77, 88, 21, low) } | |
574 | fn ip6(low: u16) -> Ipv6Addr { Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low) } | |
575 | ||
576 | let mut v4 = SocketAddrV4::new(ip4(11), 80); | |
577 | assert_eq!(v4.ip(), &ip4(11)); | |
578 | v4.set_ip(ip4(12)); | |
579 | assert_eq!(v4.ip(), &ip4(12)); | |
580 | ||
581 | let mut addr = SocketAddr::V4(v4); | |
582 | assert_eq!(addr.ip(), IpAddr::V4(ip4(12))); | |
583 | addr.set_ip(IpAddr::V4(ip4(13))); | |
584 | assert_eq!(addr.ip(), IpAddr::V4(ip4(13))); | |
585 | addr.set_ip(IpAddr::V6(ip6(14))); | |
586 | assert_eq!(addr.ip(), IpAddr::V6(ip6(14))); | |
587 | ||
588 | let mut v6 = SocketAddrV6::new(ip6(1), 80, 0, 0); | |
589 | assert_eq!(v6.ip(), &ip6(1)); | |
590 | v6.set_ip(ip6(2)); | |
591 | assert_eq!(v6.ip(), &ip6(2)); | |
592 | ||
593 | let mut addr = SocketAddr::V6(v6); | |
594 | assert_eq!(addr.ip(), IpAddr::V6(ip6(2))); | |
595 | addr.set_ip(IpAddr::V6(ip6(3))); | |
596 | assert_eq!(addr.ip(), IpAddr::V6(ip6(3))); | |
597 | addr.set_ip(IpAddr::V4(ip4(4))); | |
598 | assert_eq!(addr.ip(), IpAddr::V4(ip4(4))); | |
599 | } | |
600 | ||
601 | #[test] | |
602 | fn set_port() { | |
603 | let mut v4 = SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80); | |
604 | assert_eq!(v4.port(), 80); | |
605 | v4.set_port(443); | |
606 | assert_eq!(v4.port(), 443); | |
607 | ||
608 | let mut addr = SocketAddr::V4(v4); | |
609 | assert_eq!(addr.port(), 443); | |
610 | addr.set_port(8080); | |
611 | assert_eq!(addr.port(), 8080); | |
612 | ||
613 | let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 0); | |
614 | assert_eq!(v6.port(), 80); | |
615 | v6.set_port(443); | |
616 | assert_eq!(v6.port(), 443); | |
617 | ||
618 | let mut addr = SocketAddr::V6(v6); | |
619 | assert_eq!(addr.port(), 443); | |
620 | addr.set_port(8080); | |
621 | assert_eq!(addr.port(), 8080); | |
622 | } | |
623 | ||
624 | #[test] | |
625 | fn set_flowinfo() { | |
626 | let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0); | |
627 | assert_eq!(v6.flowinfo(), 10); | |
628 | v6.set_flowinfo(20); | |
629 | assert_eq!(v6.flowinfo(), 20); | |
630 | } | |
631 | ||
632 | #[test] | |
633 | fn set_scope_id() { | |
634 | let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 10); | |
635 | assert_eq!(v6.scope_id(), 10); | |
636 | v6.set_scope_id(20); | |
637 | assert_eq!(v6.scope_id(), 20); | |
638 | } | |
85aaf69f | 639 | } |