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)
}
}