use socket2::{Domain, Socket, TcpKeepalive, Type};
use std::net::{SocketAddr, TcpListener};
use std::time::Duration;
pub fn default_socket(socket_addr: impl Into<SocketAddr>) -> std::io::Result<Socket> {
let socket_addr: SocketAddr = socket_addr.into();
let domain = if socket_addr.is_ipv6() {
Domain::IPV6
} else {
Domain::IPV4
};
let socket = Socket::new(domain, Type::STREAM, None)?;
if domain == Domain::IPV6 {
socket.set_only_v6(false)?;
}
#[cfg(not(windows))]
socket.set_reuse_address(true)?;
socket.bind(&socket_addr.into())?;
let keepalive = TcpKeepalive::new()
.with_time(Duration::from_mins(5))
.with_retries(5)
.with_interval(Duration::from_secs(90));
socket.set_tcp_keepalive(&keepalive)?;
let backlog = if cfg!(target_os = "windows") {
128
} else {
-1 };
socket.listen(backlog)?;
tracing::debug!(?socket_addr, "tcp socket configured");
Ok(socket)
}
pub fn default_nonblocking_listener(
socket_addr: impl Into<SocketAddr>,
) -> std::io::Result<TcpListener> {
let listener: TcpListener = default_socket(socket_addr)?.into();
listener.set_nonblocking(true)?;
tracing::debug!(?listener, "tcp listener configured");
Ok(listener)
}