use net2::TcpBuilder;
use std::io;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
pub fn new_reusably_bound_tcp_socket(local_addr: &SocketAddr) -> io::Result<TcpBuilder> {
let socket = match local_addr.ip() {
IpAddr::V4(..) => TcpBuilder::new_v4()?,
IpAddr::V6(..) => TcpBuilder::new_v6()?,
};
let _ = socket.reuse_address(true)?;
enable_so_reuseport(&socket)?;
let _ = socket.bind(local_addr)?;
Ok(socket)
}
#[cfg(target_family = "unix")]
pub fn enable_so_reuseport(sock: &TcpBuilder) -> io::Result<()> {
use net2::unix::UnixTcpBuilderExt;
let _ = sock.reuse_port(true)?;
Ok(())
}
#[cfg(target_family = "windows")]
pub fn enable_so_reuseport(_sock: &TcpBuilder) -> io::Result<()> {
Ok(())
}
pub fn ip_addr_is_global(ip: &IpAddr) -> bool {
match *ip {
IpAddr::V4(addr_v4) => ipv4_addr_is_global(addr_v4),
IpAddr::V6(addr_v6) => ipv6_addr_is_global(addr_v6),
}
}
pub fn ipv4_addr_is_global(ipv4: Ipv4Addr) -> bool {
!(ipv4.is_loopback()
|| ipv4.is_private()
|| ipv4.is_link_local()
|| ipv4.is_multicast()
|| ipv4.is_broadcast()
|| ipv4.is_documentation()
|| ipv4.octets() == [0, 0, 0, 0])
}
pub fn ipv6_addr_is_global(ipv6: Ipv6Addr) -> bool {
!(ipv6.is_loopback() || ipv6.is_unspecified())
}