1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
//! Networking related functions.

mod resolver;
mod tcp_listener;
mod tcp_stream;
mod tls_listener;
mod tls_stream;
mod udp;

use std::io::{Error, ErrorKind, Result};
use std::iter::Cloned;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::option::IntoIter;
use std::slice::Iter;

pub use resolver::{resolve, resolve_timeout, SocketAddrIterator};
pub use tcp_listener::TcpListener;
pub use tcp_stream::TcpStream;
pub use tls_listener::TlsListener;
pub use tls_stream::TlsStream;
pub use udp::UdpSocket;

/// A trait for objects which can be converted or resolved to one or more
/// [`SocketAddr`] values.
///
/// Currently, this trait is only used as an argument to lunatic functions
/// that need to reference a target socket address. To perform a `SocketAddr`
/// conversion directly, use [`resolve`]. By default, it is implemented
/// for the following types:
///
///  * [`SocketAddr`]: [`to_socket_addrs`] is the identity function.
///
///  * [`SocketAddrV4`], [`SocketAddrV6`], `(`[`IpAddr`]`, `[`u16`]`)`,
///    `(`[`Ipv4Addr`]`, `[`u16`]`)`, `(`[`Ipv6Addr`]`, `[`u16`]`)`:
///    [`to_socket_addrs`] constructs a [`SocketAddr`] trivially.
///
///  * [`&str`]: the string should be either a string representation of a
///    [`SocketAddr`] as expected by its [`FromStr`] implementation or a string
///    like `<host_name>:<port>` pair where `<port>` is a [`u16`] value.
///
/// This trait allows constructing network objects like [`TcpStream`] easily
/// with values of various types for the bind/connection address. It is needed
/// because sometimes one type is more appropriate than the other: for simple
/// uses a string like `"localhost:12345"` is much nicer than manual
/// construction of the corresponding [`SocketAddr`], but sometimes
/// [`SocketAddr`] value is *the* main source of the address, and converting it
/// to  some other type (e.g., a string) just for it to be converted back to
/// [`SocketAddr`] in constructor methods is pointless.
///
/// Addresses returned by the operating system that are not IP addresses are
/// silently ignored.
///
/// [`resolve`]: resolve
/// [`FromStr`]: std::str::FromStr
/// [`&str`]: str
/// [`TcpStream`]: crate::net::TcpStream
/// [`to_socket_addrs`]: ToSocketAddrs::to_socket_addrs
///
/// # Examples
///
/// Creating a [`SocketAddr`] iterator that yields one item:
///
/// ```
/// use lunatic::net::ToSocketAddrs;
/// use std::net::SocketAddr;
///
/// let addr = SocketAddr::from(([127, 0, 0, 1], 443));
/// let mut addrs_iter = addr.to_socket_addrs().unwrap();
///
/// assert_eq!(Some(addr), addrs_iter.next());
/// assert!(addrs_iter.next().is_none());
/// ```
///
/// Creating a [`SocketAddr`] iterator from a hostname:
///
/// ```no_run
/// use std::net::SocketAddr;
/// use lunatic::net::ToSocketAddrs;
///
/// // assuming 'localhost' resolves to 127.0.0.1
/// let mut addrs_iter = "localhost:443".to_socket_addrs().unwrap();
/// assert_eq!(addrs_iter.next(), Some(SocketAddr::from(([127, 0, 0, 1], 443))));
/// assert!(addrs_iter.next().is_none());
///
/// // assuming 'foo' does not resolve
/// assert!("foo:443".to_socket_addrs().is_err());
/// ```
///
/// Creating a [`SocketAddr`] iterator that yields multiple items:
///
/// ```
/// use std::net::SocketAddr;
/// use lunatic::net::ToSocketAddrs;
///
/// let addr1 = SocketAddr::from(([0, 0, 0, 0], 80));
/// let addr2 = SocketAddr::from(([127, 0, 0, 1], 443));
/// let addrs = vec![addr1, addr2];
///
/// let mut addrs_iter = (&addrs[..]).to_socket_addrs().unwrap();
///
/// assert_eq!(Some(addr1), addrs_iter.next());
/// assert_eq!(Some(addr2), addrs_iter.next());
/// assert!(addrs_iter.next().is_none());
/// ```
///
/// Attempting to create a [`SocketAddr`] iterator from an improperly formatted
/// socket address `&str` (missing the port):
///
/// ```
/// use std::io;
/// use lunatic::net::ToSocketAddrs;
///
/// let err = "127.0.0.1".to_socket_addrs().unwrap_err();
/// assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
/// ```
///
/// [`TcpStream::connect`] is an example of an function that utilizes
/// `ToSocketAddrs` as a trait bound on its parameter in order to accept
/// different types:
///
/// ```no_run
/// use lunatic::net::TcpStream;
/// use std::net::Ipv4Addr;
/// // or
/// let stream = TcpStream::connect("127.0.0.1:443");
/// // or
/// let stream = TcpStream::connect((Ipv4Addr::new(127, 0, 0, 1), 443));
/// ```
///
/// [`TcpStream::connect`]: TcpStream::connect
pub trait ToSocketAddrs {
    type Iter: Iterator<Item = std::net::SocketAddr>;
    fn to_socket_addrs(&self) -> Result<Self::Iter>;
}

impl ToSocketAddrs for &str {
    type Iter = SocketAddrIterator;

    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        match resolve(self) {
            Ok(iter) => Ok(iter),
            Err(err) => Err(Error::new(ErrorKind::Other, err)),
        }
    }
}

impl ToSocketAddrs for String {
    type Iter = SocketAddrIterator;

    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        match resolve(self) {
            Ok(iter) => Ok(iter),
            Err(err) => Err(Error::new(ErrorKind::Other, err)),
        }
    }
}

/* The rest is just forwarded to the standard library implementations */

impl ToSocketAddrs for SocketAddr {
    type Iter = IntoIter<SocketAddr>;
    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        <SocketAddr as std::net::ToSocketAddrs>::to_socket_addrs(self)
    }
}

impl ToSocketAddrs for (IpAddr, u16) {
    type Iter = IntoIter<SocketAddr>;
    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        <(IpAddr, u16) as std::net::ToSocketAddrs>::to_socket_addrs(self)
    }
}

impl ToSocketAddrs for (Ipv4Addr, u16) {
    type Iter = IntoIter<SocketAddr>;
    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        <(Ipv4Addr, u16) as std::net::ToSocketAddrs>::to_socket_addrs(self)
    }
}

impl ToSocketAddrs for (Ipv6Addr, u16) {
    type Iter = IntoIter<SocketAddr>;
    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        <(Ipv6Addr, u16) as std::net::ToSocketAddrs>::to_socket_addrs(self)
    }
}

impl ToSocketAddrs for SocketAddrV4 {
    type Iter = IntoIter<SocketAddr>;
    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        <SocketAddrV4 as std::net::ToSocketAddrs>::to_socket_addrs(self)
    }
}

impl ToSocketAddrs for SocketAddrV6 {
    type Iter = IntoIter<SocketAddr>;
    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        <SocketAddrV6 as std::net::ToSocketAddrs>::to_socket_addrs(self)
    }
}

impl<'a> ToSocketAddrs for &'a [SocketAddr] {
    type Iter = Cloned<Iter<'a, SocketAddr>>;
    fn to_socket_addrs(&self) -> Result<Self::Iter> {
        <&[SocketAddr] as std::net::ToSocketAddrs>::to_socket_addrs(self)
    }
}