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.
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.
16 use libc
::{self, socklen_t, sa_family_t}
;
18 use net
::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr}
;
20 use sys_common
::{FromInner, AsInner, IntoInner}
;
23 /// Representation of a socket address for networking applications.
25 /// A socket address can either represent the IPv4 or IPv6 protocol and is
26 /// paired with at least a port number as well. Each protocol may have more
27 /// specific information about the address available to it as well.
28 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
29 #[stable(feature = "rust1", since = "1.0.0")]
31 /// An IPv4 socket address which is a (ip, port) combination.
32 #[stable(feature = "rust1", since = "1.0.0")]
34 /// An IPv6 socket address
35 #[stable(feature = "rust1", since = "1.0.0")]
39 /// An IPv4 socket address which is a (ip, port) combination.
41 #[stable(feature = "rust1", since = "1.0.0")]
42 pub struct SocketAddrV4 { inner: libc::sockaddr_in }
44 /// An IPv6 socket address
46 #[stable(feature = "rust1", since = "1.0.0")]
47 pub struct SocketAddrV6 { inner: libc::sockaddr_in6 }
50 /// Creates a new socket address from the (ip, port) pair.
51 #[unstable(feature = "ip_addr", reason = "recent addition")]
52 pub fn new(ip
: IpAddr
, port
: u16) -> SocketAddr
{
54 IpAddr
::V4(a
) => SocketAddr
::V4(SocketAddrV4
::new(a
, port
)),
55 IpAddr
::V6(a
) => SocketAddr
::V6(SocketAddrV6
::new(a
, port
, 0, 0)),
59 /// Gets the IP address associated with this socket address.
60 #[unstable(feature = "ip_addr", reason = "recent addition")]
61 pub fn ip(&self) -> IpAddr
{
63 SocketAddr
::V4(ref a
) => IpAddr
::V4(*a
.ip()),
64 SocketAddr
::V6(ref a
) => IpAddr
::V6(*a
.ip()),
68 /// Gets the port number associated with this socket address
69 #[stable(feature = "rust1", since = "1.0.0")]
70 pub fn port(&self) -> u16 {
72 SocketAddr
::V4(ref a
) => a
.port(),
73 SocketAddr
::V6(ref a
) => a
.port(),
79 /// Creates a new socket address from the (ip, port) pair.
80 #[stable(feature = "rust1", since = "1.0.0")]
81 pub fn new(ip
: Ipv4Addr
, port
: u16) -> SocketAddrV4
{
83 inner
: libc
::sockaddr_in
{
84 sin_family
: libc
::AF_INET
as sa_family_t
,
86 sin_addr
: *ip
.as_inner(),
87 .. unsafe { mem::zeroed() }
92 /// Gets the IP address associated with this socket address.
93 #[stable(feature = "rust1", since = "1.0.0")]
94 pub fn ip(&self) -> &Ipv4Addr
{
96 &*(&self.inner
.sin_addr
as *const libc
::in_addr
as *const Ipv4Addr
)
100 /// Gets the port number associated with this socket address
101 #[stable(feature = "rust1", since = "1.0.0")]
102 pub fn port(&self) -> u16 { ntoh(self.inner.sin_port) }
106 /// Creates a new socket address from the ip/port/flowinfo/scope_id
108 #[stable(feature = "rust1", since = "1.0.0")]
109 pub fn new(ip
: Ipv6Addr
, port
: u16, flowinfo
: u32, scope_id
: u32)
112 inner
: libc
::sockaddr_in6
{
113 sin6_family
: libc
::AF_INET6
as sa_family_t
,
114 sin6_port
: hton(port
),
115 sin6_addr
: *ip
.as_inner(),
116 sin6_flowinfo
: hton(flowinfo
),
117 sin6_scope_id
: hton(scope_id
),
118 .. unsafe { mem::zeroed() }
123 /// Gets the IP address associated with this socket address.
124 #[stable(feature = "rust1", since = "1.0.0")]
125 pub fn ip(&self) -> &Ipv6Addr
{
127 &*(&self.inner
.sin6_addr
as *const libc
::in6_addr
as *const Ipv6Addr
)
131 /// Gets the port number associated with this socket address
132 #[stable(feature = "rust1", since = "1.0.0")]
133 pub fn port(&self) -> u16 { ntoh(self.inner.sin6_port) }
135 /// Gets scope ID associated with this address, corresponding to the
136 /// `sin6_flowinfo` field in C.
137 #[stable(feature = "rust1", since = "1.0.0")]
138 pub fn flowinfo(&self) -> u32 { ntoh(self.inner.sin6_flowinfo) }
140 /// Gets scope ID associated with this address, corresponding to the
141 /// `sin6_scope_id` field in C.
142 #[stable(feature = "rust1", since = "1.0.0")]
143 pub fn scope_id(&self) -> u32 { ntoh(self.inner.sin6_scope_id) }
146 impl FromInner
<libc
::sockaddr_in
> for SocketAddrV4
{
147 fn from_inner(addr
: libc
::sockaddr_in
) -> SocketAddrV4
{
148 SocketAddrV4 { inner: addr }
152 impl FromInner
<libc
::sockaddr_in6
> for SocketAddrV6
{
153 fn from_inner(addr
: libc
::sockaddr_in6
) -> SocketAddrV6
{
154 SocketAddrV6 { inner: addr }
158 impl<'a
> IntoInner
<(*const libc
::sockaddr
, socklen_t
)> for &'a SocketAddr
{
159 fn into_inner(self) -> (*const libc
::sockaddr
, socklen_t
) {
161 SocketAddr
::V4(ref a
) => {
162 (a
as *const _
as *const _
, mem
::size_of_val(a
) as socklen_t
)
164 SocketAddr
::V6(ref a
) => {
165 (a
as *const _
as *const _
, mem
::size_of_val(a
) as socklen_t
)
171 #[stable(feature = "rust1", since = "1.0.0")]
172 impl fmt
::Display
for SocketAddr
{
173 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
175 SocketAddr
::V4(ref a
) => a
.fmt(f
),
176 SocketAddr
::V6(ref a
) => a
.fmt(f
),
181 #[stable(feature = "rust1", since = "1.0.0")]
182 impl fmt
::Display
for SocketAddrV4
{
183 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
184 write
!(f
, "{}:{}", self.ip(), self.port())
188 #[stable(feature = "rust1", since = "1.0.0")]
189 impl fmt
::Debug
for SocketAddrV4
{
190 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
191 fmt
::Display
::fmt(self, fmt
)
195 #[stable(feature = "rust1", since = "1.0.0")]
196 impl fmt
::Display
for SocketAddrV6
{
197 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
198 write
!(f
, "[{}]:{}", self.ip(), self.port())
202 #[stable(feature = "rust1", since = "1.0.0")]
203 impl fmt
::Debug
for SocketAddrV6
{
204 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
205 fmt
::Display
::fmt(self, fmt
)
209 #[stable(feature = "rust1", since = "1.0.0")]
210 impl Clone
for SocketAddrV4
{
211 fn clone(&self) -> SocketAddrV4 { *self }
213 #[stable(feature = "rust1", since = "1.0.0")]
214 impl Clone
for SocketAddrV6
{
215 fn clone(&self) -> SocketAddrV6 { *self }
218 #[stable(feature = "rust1", since = "1.0.0")]
219 impl PartialEq
for SocketAddrV4
{
220 fn eq(&self, other
: &SocketAddrV4
) -> bool
{
221 self.inner
.sin_port
== other
.inner
.sin_port
&&
222 self.inner
.sin_addr
.s_addr
== other
.inner
.sin_addr
.s_addr
225 #[stable(feature = "rust1", since = "1.0.0")]
226 impl PartialEq
for SocketAddrV6
{
227 fn eq(&self, other
: &SocketAddrV6
) -> bool
{
228 self.inner
.sin6_port
== other
.inner
.sin6_port
&&
229 self.inner
.sin6_addr
.s6_addr
== other
.inner
.sin6_addr
.s6_addr
&&
230 self.inner
.sin6_flowinfo
== other
.inner
.sin6_flowinfo
&&
231 self.inner
.sin6_scope_id
== other
.inner
.sin6_scope_id
234 #[stable(feature = "rust1", since = "1.0.0")]
235 impl Eq
for SocketAddrV4 {}
236 #[stable(feature = "rust1", since = "1.0.0")]
237 impl Eq
for SocketAddrV6 {}
239 #[stable(feature = "rust1", since = "1.0.0")]
240 impl hash
::Hash
for SocketAddrV4
{
241 fn hash
<H
: hash
::Hasher
>(&self, s
: &mut H
) {
242 (self.inner
.sin_port
, self.inner
.sin_addr
.s_addr
).hash(s
)
245 #[stable(feature = "rust1", since = "1.0.0")]
246 impl hash
::Hash
for SocketAddrV6
{
247 fn hash
<H
: hash
::Hasher
>(&self, s
: &mut H
) {
248 (self.inner
.sin6_port
, &self.inner
.sin6_addr
.s6_addr
,
249 self.inner
.sin6_flowinfo
, self.inner
.sin6_scope_id
).hash(s
)
253 /// A trait for objects which can be converted or resolved to one or more
254 /// `SocketAddr` values.
256 /// This trait is used for generic address resolution when constructing network
257 /// objects. By default it is implemented for the following types:
259 /// * `SocketAddr`, `SocketAddrV4`, `SocketAddrV6` - `to_socket_addrs` is
260 /// identity function.
262 /// * `(IpvNAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially.
264 /// * `(&str, u16)` - the string should be either a string representation of an
265 /// IP address expected by `FromStr` implementation for `IpvNAddr` or a host
268 /// * `&str` - the string should be either a string representation of a
269 /// `SocketAddr` as expected by its `FromStr` implementation or a string like
270 /// `<host_name>:<port>` pair where `<port>` is a `u16` value.
272 /// This trait allows constructing network objects like `TcpStream` or
273 /// `UdpSocket` easily with values of various types for the bind/connection
274 /// address. It is needed because sometimes one type is more appropriate than
275 /// the other: for simple uses a string like `"localhost:12345"` is much nicer
276 /// than manual construction of the corresponding `SocketAddr`, but sometimes
277 /// `SocketAddr` value is *the* main source of the address, and converting it to
278 /// some other type (e.g. a string) just for it to be converted back to
279 /// `SocketAddr` in constructor methods is pointless.
284 /// # #![feature(net)]
285 /// use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr};
288 /// let ip = Ipv4Addr::new(127, 0, 0, 1);
289 /// let port = 12345;
291 /// // The following lines are equivalent modulo possible "localhost" name
292 /// // resolution differences
293 /// let tcp_s = TcpStream::connect(SocketAddrV4::new(ip, port));
294 /// let tcp_s = TcpStream::connect((ip, port));
295 /// let tcp_s = TcpStream::connect(("127.0.0.1", port));
296 /// let tcp_s = TcpStream::connect(("localhost", port));
297 /// let tcp_s = TcpStream::connect("127.0.0.1:12345");
298 /// let tcp_s = TcpStream::connect("localhost:12345");
300 /// // TcpListener::bind(), UdpSocket::bind() and UdpSocket::send_to()
301 /// // behave similarly
302 /// let tcp_l = TcpListener::bind("localhost:12345");
304 /// let mut udp_s = UdpSocket::bind(("127.0.0.1", port)).unwrap();
305 /// udp_s.send_to(&[7], (ip, 23451));
308 #[stable(feature = "rust1", since = "1.0.0")]
309 pub trait ToSocketAddrs
{
310 /// Returned iterator over socket addresses which this type may correspond
312 #[stable(feature = "rust1", since = "1.0.0")]
313 type Iter
: Iterator
<Item
=SocketAddr
>;
315 /// Converts this object to an iterator of resolved `SocketAddr`s.
317 /// The returned iterator may not actually yield any values depending on the
318 /// outcome of any resolution performed.
320 /// Note that this function may block the current thread while resolution is
325 /// Any errors encountered during resolution will be returned as an `Err`.
326 #[stable(feature = "rust1", since = "1.0.0")]
327 fn to_socket_addrs(&self) -> io
::Result
<Self::Iter
>;
330 #[stable(feature = "rust1", since = "1.0.0")]
331 impl ToSocketAddrs
for SocketAddr
{
332 type Iter
= option
::IntoIter
<SocketAddr
>;
333 fn to_socket_addrs(&self) -> io
::Result
<option
::IntoIter
<SocketAddr
>> {
334 Ok(Some(*self).into_iter())
338 #[stable(feature = "rust1", since = "1.0.0")]
339 impl ToSocketAddrs
for SocketAddrV4
{
340 type Iter
= option
::IntoIter
<SocketAddr
>;
341 fn to_socket_addrs(&self) -> io
::Result
<option
::IntoIter
<SocketAddr
>> {
342 SocketAddr
::V4(*self).to_socket_addrs()
346 #[stable(feature = "rust1", since = "1.0.0")]
347 impl ToSocketAddrs
for SocketAddrV6
{
348 type Iter
= option
::IntoIter
<SocketAddr
>;
349 fn to_socket_addrs(&self) -> io
::Result
<option
::IntoIter
<SocketAddr
>> {
350 SocketAddr
::V6(*self).to_socket_addrs()
354 #[stable(feature = "rust1", since = "1.0.0")]
355 impl ToSocketAddrs
for (IpAddr
, u16) {
356 type Iter
= option
::IntoIter
<SocketAddr
>;
357 fn to_socket_addrs(&self) -> io
::Result
<option
::IntoIter
<SocketAddr
>> {
358 let (ip
, port
) = *self;
360 IpAddr
::V4(ref a
) => (*a
, port
).to_socket_addrs(),
361 IpAddr
::V6(ref a
) => (*a
, port
).to_socket_addrs(),
366 #[stable(feature = "rust1", since = "1.0.0")]
367 impl ToSocketAddrs
for (Ipv4Addr
, u16) {
368 type Iter
= option
::IntoIter
<SocketAddr
>;
369 fn to_socket_addrs(&self) -> io
::Result
<option
::IntoIter
<SocketAddr
>> {
370 let (ip
, port
) = *self;
371 SocketAddrV4
::new(ip
, port
).to_socket_addrs()
375 #[stable(feature = "rust1", since = "1.0.0")]
376 impl ToSocketAddrs
for (Ipv6Addr
, u16) {
377 type Iter
= option
::IntoIter
<SocketAddr
>;
378 fn to_socket_addrs(&self) -> io
::Result
<option
::IntoIter
<SocketAddr
>> {
379 let (ip
, port
) = *self;
380 SocketAddrV6
::new(ip
, port
, 0, 0).to_socket_addrs()
384 fn resolve_socket_addr(s
: &str, p
: u16) -> io
::Result
<vec
::IntoIter
<SocketAddr
>> {
385 let ips
= try
!(lookup_host(s
));
386 let v
: Vec
<_
> = try
!(ips
.map(|a
| {
389 SocketAddr
::V4(ref a
) => {
390 SocketAddr
::V4(SocketAddrV4
::new(*a
.ip(), p
))
392 SocketAddr
::V6(ref a
) => {
393 SocketAddr
::V6(SocketAddrV6
::new(*a
.ip(), p
, a
.flowinfo(),
402 #[stable(feature = "rust1", since = "1.0.0")]
403 impl<'a
> ToSocketAddrs
for (&'a
str, u16) {
404 type Iter
= vec
::IntoIter
<SocketAddr
>;
405 fn to_socket_addrs(&self) -> io
::Result
<vec
::IntoIter
<SocketAddr
>> {
406 let (host
, port
) = *self;
408 // try to parse the host as a regular IP address first
409 if let Ok(addr
) = host
.parse
::<Ipv4Addr
>() {
410 let addr
= SocketAddrV4
::new(addr
, port
);
411 return Ok(vec
![SocketAddr
::V4(addr
)].into_iter())
413 if let Ok(addr
) = host
.parse
::<Ipv6Addr
>() {
414 let addr
= SocketAddrV6
::new(addr
, port
, 0, 0);
415 return Ok(vec
![SocketAddr
::V6(addr
)].into_iter())
418 resolve_socket_addr(host
, port
)
422 // accepts strings like 'localhost:12345'
423 #[stable(feature = "rust1", since = "1.0.0")]
424 impl ToSocketAddrs
for str {
425 type Iter
= vec
::IntoIter
<SocketAddr
>;
426 fn to_socket_addrs(&self) -> io
::Result
<vec
::IntoIter
<SocketAddr
>> {
427 // try to parse as a regular SocketAddr first
428 match self.parse().ok() {
429 Some(addr
) => return Ok(vec
![addr
].into_iter()),
433 macro_rules
! try_opt
{
434 ($e
:expr
, $msg
:expr
) => (
437 None
=> return Err(io
::Error
::new(io
::ErrorKind
::InvalidInput
,
443 // split the string by ':' and convert the second part to u16
444 let mut parts_iter
= self.rsplitn(2, '
:'
);
445 let port_str
= try_opt
!(parts_iter
.next(), "invalid socket address");
446 let host
= try_opt
!(parts_iter
.next(), "invalid socket address");
447 let port
: u16 = try_opt
!(port_str
.parse().ok(), "invalid port value");
448 resolve_socket_addr(host
, port
)
452 impl<'a
, T
: ToSocketAddrs
+ ?Sized
> ToSocketAddrs
for &'a T
{
454 fn to_socket_addrs(&self) -> io
::Result
<T
::Iter
> {
455 (**self).to_socket_addrs()
464 use net
::Ipv6MulticastScope
::*;
467 fn test_from_str_ipv4() {
468 assert_eq
!(Ok(Ipv4Addr
::new(127, 0, 0, 1)), "127.0.0.1".parse());
469 assert_eq
!(Ok(Ipv4Addr
::new(255, 255, 255, 255)), "255.255.255.255".parse());
470 assert_eq
!(Ok(Ipv4Addr
::new(0, 0, 0, 0)), "0.0.0.0".parse());
473 let none
: Option
<Ipv4Addr
> = "256.0.0.1".parse().ok();
474 assert_eq
!(None
, none
);
476 let none
: Option
<Ipv4Addr
> = "255.0.0".parse().ok();
477 assert_eq
!(None
, none
);
479 let none
: Option
<Ipv4Addr
> = "255.0.0.1.2".parse().ok();
480 assert_eq
!(None
, none
);
481 // no number between dots
482 let none
: Option
<Ipv4Addr
> = "255.0..1".parse().ok();
483 assert_eq
!(None
, none
);
487 fn test_from_str_ipv6() {
488 assert_eq
!(Ok(Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
489 assert_eq
!(Ok(Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
491 assert_eq
!(Ok(Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
492 assert_eq
!(Ok(Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
494 assert_eq
!(Ok(Ipv6Addr
::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
495 "2a02:6b8::11:11".parse());
498 let none
: Option
<Ipv6Addr
> = "::00000".parse().ok();
499 assert_eq
!(None
, none
);
501 let none
: Option
<Ipv6Addr
> = "1:2:3:4:5:6:7".parse().ok();
502 assert_eq
!(None
, none
);
504 let none
: Option
<Ipv6Addr
> = "1:2:3:4:5:6:7:8:9".parse().ok();
505 assert_eq
!(None
, none
);
507 let none
: Option
<Ipv6Addr
> = "1:2:::6:7:8".parse().ok();
508 assert_eq
!(None
, none
);
510 let none
: Option
<Ipv6Addr
> = "1:2::6::8".parse().ok();
511 assert_eq
!(None
, none
);
515 fn test_from_str_ipv4_in_ipv6() {
516 assert_eq
!(Ok(Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 49152, 545)),
517 "::192.0.2.33".parse());
518 assert_eq
!(Ok(Ipv6Addr
::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
519 "::FFFF:192.0.2.33".parse());
520 assert_eq
!(Ok(Ipv6Addr
::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
521 "64:ff9b::192.0.2.33".parse());
522 assert_eq
!(Ok(Ipv6Addr
::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
523 "2001:db8:122:c000:2:2100:192.0.2.33".parse());
526 let none
: Option
<Ipv4Addr
> = "::127.0.0.1:".parse().ok();
527 assert_eq
!(None
, none
);
529 let none
: Option
<Ipv6Addr
> = "1.2.3.4.5:127.0.0.1".parse().ok();
530 assert_eq
!(None
, none
);
532 let none
: Option
<Ipv6Addr
> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
533 assert_eq
!(None
, none
);
537 fn test_from_str_socket_addr() {
538 assert_eq
!(Ok(sa4(Ipv4Addr
::new(77, 88, 21, 11), 80)),
539 "77.88.21.11:80".parse());
540 assert_eq
!(Ok(sa6(Ipv6Addr
::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
541 "[2a02:6b8:0:1::1]:53".parse());
542 assert_eq
!(Ok(sa6(Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
543 "[::127.0.0.1]:22".parse());
546 let none
: Option
<SocketAddr
> = "127.0.0.1".parse().ok();
547 assert_eq
!(None
, none
);
549 let none
: Option
<SocketAddr
> = "127.0.0.1:".parse().ok();
550 assert_eq
!(None
, none
);
551 // wrong brackets around v4
552 let none
: Option
<SocketAddr
> = "[127.0.0.1]:22".parse().ok();
553 assert_eq
!(None
, none
);
555 let none
: Option
<SocketAddr
> = "127.0.0.1:123456".parse().ok();
556 assert_eq
!(None
, none
);
560 fn ipv6_addr_to_string() {
561 // ipv4-mapped address
562 let a1
= Ipv6Addr
::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
563 assert_eq
!(a1
.to_string(), "::ffff:192.0.2.128");
565 // ipv4-compatible address
566 let a1
= Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
567 assert_eq
!(a1
.to_string(), "::192.0.2.128");
569 // v6 address with no zero segments
570 assert_eq
!(Ipv6Addr
::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
573 // reduce a single run of zeros
574 assert_eq
!("ae::ffff:102:304",
575 Ipv6Addr
::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string());
577 // don't reduce just a single zero segment
578 assert_eq
!("1:2:3:4:5:6:0:8",
579 Ipv6Addr
::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
582 assert_eq
!("::", Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
585 assert_eq
!("::1", Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
588 assert_eq
!("1::", Ipv6Addr
::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
590 // two runs of zeros, second one is longer
591 assert_eq
!("1:0:0:4::8", Ipv6Addr
::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
593 // two runs of zeros, equal length
594 assert_eq
!("1::4:5:0:0:8", Ipv6Addr
::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
599 assert_eq
!(Ipv6Addr
::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
600 Ipv4Addr
::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped());
601 assert_eq
!(Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
602 Ipv4Addr
::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible());
607 assert_eq
!(Ipv6Addr
::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
608 Some(Ipv4Addr
::new(0x12, 0x34, 0x56, 0x78)));
609 assert_eq
!(Ipv6Addr
::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
610 Some(Ipv4Addr
::new(0x12, 0x34, 0x56, 0x78)));
611 assert_eq
!(Ipv6Addr
::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
616 fn ipv4_properties() {
617 fn check(octets
: &[u8; 4], unspec
: bool
, loopback
: bool
,
618 private
: bool
, link_local
: bool
, global
: bool
,
620 let ip
= Ipv4Addr
::new(octets
[0], octets
[1], octets
[2], octets
[3]);
621 assert_eq
!(octets
, &ip
.octets());
623 assert_eq
!(ip
.is_unspecified(), unspec
);
624 assert_eq
!(ip
.is_loopback(), loopback
);
625 assert_eq
!(ip
.is_private(), private
);
626 assert_eq
!(ip
.is_link_local(), link_local
);
627 assert_eq
!(ip
.is_global(), global
);
628 assert_eq
!(ip
.is_multicast(), multicast
);
631 // address unspec loopbk privt linloc global multicast
632 check(&[0, 0, 0, 0], true, false, false, false, true, false);
633 check(&[0, 0, 0, 1], false, false, false, false, true, false);
634 check(&[1, 0, 0, 0], false, false, false, false, true, false);
635 check(&[10, 9, 8, 7], false, false, true, false, false, false);
636 check(&[127, 1, 2, 3], false, true, false, false, false, false);
637 check(&[172, 31, 254, 253], false, false, true, false, false, false);
638 check(&[169, 254, 253, 242], false, false, false, true, false, false);
639 check(&[192, 168, 254, 253], false, false, true, false, false, false);
640 check(&[224, 0, 0, 0], false, false, false, false, true, true);
641 check(&[239, 255, 255, 255], false, false, false, false, true, true);
642 check(&[255, 255, 255, 255], false, false, false, false, true, false);
646 fn ipv6_properties() {
647 fn check(str_addr
: &str, unspec
: bool
, loopback
: bool
,
648 unique_local
: bool
, global
: bool
,
649 u_link_local
: bool
, u_site_local
: bool
, u_global
: bool
,
650 m_scope
: Option
<Ipv6MulticastScope
>) {
651 let ip
: Ipv6Addr
= str_addr
.parse().unwrap();
652 assert_eq
!(str_addr
, ip
.to_string());
654 assert_eq
!(ip
.is_unspecified(), unspec
);
655 assert_eq
!(ip
.is_loopback(), loopback
);
656 assert_eq
!(ip
.is_unique_local(), unique_local
);
657 assert_eq
!(ip
.is_global(), global
);
658 assert_eq
!(ip
.is_unicast_link_local(), u_link_local
);
659 assert_eq
!(ip
.is_unicast_site_local(), u_site_local
);
660 assert_eq
!(ip
.is_unicast_global(), u_global
);
661 assert_eq
!(ip
.multicast_scope(), m_scope
);
662 assert_eq
!(ip
.is_multicast(), m_scope
.is_some());
665 // unspec loopbk uniqlo global unill unisl uniglo mscope
667 true, false, false, true, false, false, true, None
);
669 false, true, false, false, false, false, false, None
);
671 false, false, false, true, false, false, true, None
);
673 false, false, false, true, false, false, true, None
);
675 false, false, true, false, false, false, false, None
);
677 false, false, true, false, false, false, false, None
);
679 false, false, false, false, true, false, false, None
);
681 false, false, false, false, true, false, false, None
);
683 false, false, false, false, false, true, false, None
);
685 false, false, false, false, false, false, false, Some(InterfaceLocal
));
687 false, false, false, false, false, false, false, Some(LinkLocal
));
689 false, false, false, false, false, false, false, Some(RealmLocal
));
691 false, false, false, false, false, false, false, Some(AdminLocal
));
693 false, false, false, false, false, false, false, Some(SiteLocal
));
695 false, false, false, false, false, false, false, Some(OrganizationLocal
));
697 false, false, false, true, false, false, false, Some(Global
));
700 fn tsa
<A
: ToSocketAddrs
>(a
: A
) -> Result
<Vec
<SocketAddr
>, String
> {
701 match a
.to_socket_addrs() {
702 Ok(a
) => Ok(a
.collect()),
703 Err(e
) => Err(e
.to_string()),
708 fn to_socket_addr_socketaddr() {
709 let a
= sa4(Ipv4Addr
::new(77, 88, 21, 11), 12345);
710 assert_eq
!(Ok(vec
![a
]), tsa(a
));
713 fn sa4(a
: Ipv4Addr
, p
: u16) -> SocketAddr
{
714 SocketAddr
::V4(SocketAddrV4
::new(a
, p
))
717 fn sa6(a
: Ipv6Addr
, p
: u16) -> SocketAddr
{
718 SocketAddr
::V6(SocketAddrV6
::new(a
, p
, 0, 0))
722 fn to_socket_addr_ipaddr_u16() {
723 let a
= Ipv4Addr
::new(77, 88, 21, 11);
725 let e
= SocketAddr
::V4(SocketAddrV4
::new(a
, p
));
726 assert_eq
!(Ok(vec
![e
]), tsa((a
, p
)));
730 fn to_socket_addr_str_u16() {
731 let a
= sa4(Ipv4Addr
::new(77, 88, 21, 11), 24352);
732 assert_eq
!(Ok(vec
![a
]), tsa(("77.88.21.11", 24352)));
734 let a
= sa6(Ipv6Addr
::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53);
735 assert_eq
!(Ok(vec
![a
]), tsa(("2a02:6b8:0:1::1", 53)));
737 let a
= sa4(Ipv4Addr
::new(127, 0, 0, 1), 23924);
738 assert
!(tsa(("localhost", 23924)).unwrap().contains(&a
));
742 fn to_socket_addr_str() {
743 let a
= sa4(Ipv4Addr
::new(77, 88, 21, 11), 24352);
744 assert_eq
!(Ok(vec
![a
]), tsa("77.88.21.11:24352"));
746 let a
= sa6(Ipv6Addr
::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53);
747 assert_eq
!(Ok(vec
![a
]), tsa("[2a02:6b8:0:1::1]:53"));
749 let a
= sa4(Ipv4Addr
::new(127, 0, 0, 1), 23924);
750 assert
!(tsa("localhost:23924").unwrap().contains(&a
));
755 fn to_socket_addr_str_bad() {
756 assert
!(tsa("1200::AB00:1234::2552:7777:1313:34300").is_err());