mod listener_config;
pub mod tcp;
pub mod udp;
#[cfg(unix)]
pub mod unix;
pub use listener_config::ListenerOpts;
#[deprecated(since = "0.2.0", note = "use ListenerOpts")]
pub use listener_config::ListenerOpts as ListenerConfig;
pub use tcp::{TcpConnectOpts, TcpListener, TcpStream};
#[cfg(unix)]
pub use unix::{Pipe, UnixDatagram, UnixListener, UnixStream};
#[cfg(windows)]
use {
std::os::windows::prelude::RawSocket,
windows_sys::Win32::{
Foundation::NO_ERROR,
Networking::WinSock::{
closesocket, ioctlsocket, socket, WSACleanup, WSAStartup, ADDRESS_FAMILY, FIONBIO,
INVALID_SOCKET, WINSOCK_SOCKET_TYPE,
},
},
};
#[cfg(unix)]
pub(crate) fn new_socket(
domain: libc::c_int,
socket_type: libc::c_int,
) -> std::io::Result<libc::c_int> {
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd"
))]
let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
#[cfg(target_os = "linux")]
let socket_type = {
if crate::driver::op::is_legacy() {
socket_type | libc::SOCK_CLOEXEC | libc::SOCK_NONBLOCK
} else {
socket_type | libc::SOCK_CLOEXEC
}
};
#[allow(clippy::let_and_return)]
#[cfg(unix)]
let socket = crate::syscall!(socket(domain, socket_type, 0));
#[cfg(target_vendor = "apple")]
let socket = socket.and_then(|socket| {
crate::syscall!(setsockopt(
socket,
libc::SOL_SOCKET,
libc::SO_NOSIGPIPE,
&1 as *const libc::c_int as *const libc::c_void,
std::mem::size_of::<libc::c_int>() as libc::socklen_t
))
.map(|_| socket)
});
#[cfg(any(target_os = "ios", target_os = "macos"))]
let socket = socket.and_then(|socket| {
crate::syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))
.and_then(|_| {
crate::syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)).map(|_| socket)
})
.inspect_err(|_| {
let _ = crate::syscall!(close(socket));
})
});
socket
}
#[allow(non_snake_case, missing_docs)]
#[cfg(windows)]
#[inline]
pub fn MAKEWORD(a: u8, b: u8) -> u16 {
(a as u16) | ((b as u16) << 8)
}
#[cfg(windows)]
pub(crate) fn new_socket(
domain: ADDRESS_FAMILY,
socket_type: WINSOCK_SOCKET_TYPE,
) -> std::io::Result<RawSocket> {
let _: i32 = crate::syscall!(
WSAStartup(MAKEWORD(2, 2), std::ptr::null_mut()),
PartialEq::eq,
NO_ERROR as _
)?;
let socket = crate::syscall!(
socket(domain as _, socket_type, 0),
PartialEq::eq,
INVALID_SOCKET
)?;
crate::syscall!(
ioctlsocket(socket, FIONBIO, &mut 1),
PartialEq::ne,
NO_ERROR as _
)
.map(|_: i32| socket as RawSocket)
.inspect_err(|_| {
unsafe {
closesocket(socket);
WSACleanup();
}
})
}