use std::net::SocketAddr;
use std::time::Duration;
use crate::driver::helpers::socket::Socket;
use crate::net::tcp::{TcpListener, TcpStream};
#[cfg(unix)]
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, RawSocket};
pub struct TcpSocket {
pub(super) inner: Socket,
}
impl TcpSocket {
pub async fn close(self) -> std::io::Result<()> {
self.inner.close().await
}
pub fn new_v4() -> std::io::Result<Self> {
let socket = socket2::Socket::new(
socket2::Domain::IPV4,
socket2::Type::STREAM,
Some(socket2::Protocol::TCP),
)?;
let inner = Socket::from_socket(socket)?;
inner.set_async_flags()?;
Ok(Self { inner })
}
pub fn new_v6() -> std::io::Result<Self> {
let socket = socket2::Socket::new(
socket2::Domain::IPV6,
socket2::Type::STREAM,
Some(socket2::Protocol::TCP),
)?;
let inner = Socket::from_socket(socket)?;
inner.set_async_flags()?;
Ok(Self { inner })
}
pub fn bind(self, addr: SocketAddr) -> std::io::Result<Self> {
self.inner.handle.bind(&addr.into())?;
Ok(self)
}
pub async fn connect(self, addr: SocketAddr) -> std::io::Result<TcpStream> {
self.inner.connect(socket2::SockAddr::from(addr)).await?;
Ok(TcpStream { inner: self.inner })
}
pub fn listen(self, backlog: u32) -> std::io::Result<TcpListener> {
self.inner.listen(backlog as i32)?;
Ok(TcpListener { inner: self.inner })
}
pub fn local_addr(&self) -> std::io::Result<SocketAddr> {
self.inner
.handle
.local_addr()?
.as_socket()
.ok_or_else(|| std::io::Error::other("Could not get socket IP address"))
}
pub fn set_nodelay(&self, nodelay: bool) -> std::io::Result<()> {
self.inner.handle.set_tcp_nodelay(nodelay)
}
pub fn nodelay(&self) -> std::io::Result<bool> {
self.inner.handle.tcp_nodelay()
}
pub fn set_reuseaddr(&self, reuseaddr: bool) -> std::io::Result<()> {
self.inner.handle.set_reuse_address(reuseaddr)
}
pub fn reuseaddr(&self) -> std::io::Result<bool> {
self.inner.handle.reuse_address()
}
#[cfg(unix)]
pub fn set_reuseport(&self, reuseport: bool) -> std::io::Result<()> {
self.inner.handle.set_reuse_port(reuseport)
}
#[cfg(unix)]
pub fn reuseport(&self) -> std::io::Result<bool> {
self.inner.handle.reuse_port()
}
pub fn set_keepalive(&self, keepalive: bool) -> std::io::Result<()> {
self.inner.handle.set_keepalive(keepalive)
}
pub fn keepalive(&self) -> std::io::Result<bool> {
self.inner.handle.keepalive()
}
pub fn set_linger(&self, dur: Option<Duration>) -> std::io::Result<()> {
self.inner.handle.set_linger(dur)
}
pub fn linger(&self) -> std::io::Result<Option<Duration>> {
self.inner.handle.linger()
}
pub fn set_recv_buffer_size(&self, size: u32) -> std::io::Result<()> {
self.inner.handle.set_recv_buffer_size(size as usize)
}
pub fn recv_buffer_size(&self) -> std::io::Result<u32> {
self.inner.handle.recv_buffer_size().map(|s| s as u32)
}
pub fn set_send_buffer_size(&self, size: u32) -> std::io::Result<()> {
self.inner.handle.set_send_buffer_size(size as usize)
}
pub fn send_buffer_size(&self) -> std::io::Result<u32> {
self.inner.handle.send_buffer_size().map(|s| s as u32)
}
pub fn set_ttl_v4(&self, ttl: u32) -> std::io::Result<()> {
self.inner.handle.set_ttl_v4(ttl)
}
pub fn ttl_v4(&self) -> std::io::Result<u32> {
self.inner.handle.ttl_v4()
}
pub fn set_unicast_hops_v6(&self, hops: u32) -> std::io::Result<()> {
self.inner.handle.set_unicast_hops_v6(hops)
}
pub fn unicast_hops_v6(&self) -> std::io::Result<u32> {
self.inner.handle.unicast_hops_v6()
}
}
#[cfg(unix)]
impl FromRawFd for TcpSocket {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
TcpSocket::from(unsafe { Socket::from_raw_fd(fd) })
}
}
#[cfg(unix)]
impl AsRawFd for TcpSocket {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
#[cfg(windows)]
impl FromRawSocket for TcpSocket {
unsafe fn from_raw_socket(socket: RawSocket) -> Self {
TcpSocket::from(unsafe { Socket::from_raw_socket(socket) })
}
}
#[cfg(windows)]
impl AsRawSocket for TcpSocket {
fn as_raw_socket(&self) -> RawSocket {
self.inner.as_raw_socket()
}
}
impl From<Socket> for TcpSocket {
fn from(inner: Socket) -> Self {
Self { inner }
}
}