use std::net::SocketAddr;
#[cfg(unix)]
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
#[cfg(target_os = "linux")]
use crate::{
buf::PooledBuf,
io::{AsyncReadManaged, AsyncReadMulti, Stream},
};
use crate::{
buf::{BufResult, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut},
driver::helpers::socket::Socket,
io::{AsyncRead, AsyncWrite, IntoOwnedSplit, ReuniteError, ReuniteOwned},
net::split::{OwnedReadHalf, OwnedWriteHalf, ReadHalf, WriteHalf, split},
};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, RawSocket};
pub struct TcpStream {
pub(super) inner: Socket,
}
impl TcpStream {
pub async fn connect(addr: SocketAddr) -> std::io::Result<TcpStream> {
let socket = Socket::new(addr, socket2::Type::STREAM)?;
#[cfg(windows)]
{
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
let bind_addr = if addr.is_ipv4() {
socket2::SockAddr::from(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0))
} else {
socket2::SockAddr::from(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0))
};
socket.handle.bind(&bind_addr)?;
}
socket.connect(socket2::SockAddr::from(addr)).await?;
let tcp_stream = TcpStream { inner: socket };
Ok(tcp_stream)
}
pub async fn close(self) -> std::io::Result<()> {
self.inner.close().await
}
pub fn shutdown(&self, how: std::net::Shutdown) -> std::io::Result<()> {
self.inner.shutdown(how)
}
pub fn set_nodelay(&self, nodelay: bool) -> std::io::Result<()> {
self.inner.set_nodelay(nodelay)
}
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 peer_addr(&self) -> std::io::Result<SocketAddr> {
self.inner
.handle
.peer_addr()?
.as_socket()
.ok_or_else(|| std::io::Error::other("Could not get peer IP address"))
}
pub fn split(&self) -> (ReadHalf<'_, Self>, WriteHalf<'_, Self>) {
split(self)
}
pub fn into_split(self) -> (OwnedReadHalf<Self>, OwnedWriteHalf<Self>) {
<Self as IntoOwnedSplit>::into_split(self)
}
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(target_os = "linux")))]
pub async fn recv_managed(&self, len: usize) -> std::io::Result<Option<PooledBuf>> {
self.inner.recv_managed(len).await
}
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(target_os = "linux")))]
pub fn recv_multi(&self) -> std::io::Result<impl Stream<Item = std::io::Result<PooledBuf>> + use<>> {
self.inner.recv_multi()
}
}
impl AsyncRead for &TcpStream {
async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
self.inner.recv(buf).await
}
async fn read_vectored<V: IoVectoredBufMut>(&mut self, bufs: V) -> BufResult<usize, V> {
let (result, bufs) = self.inner.recvmsg(bufs).await.into_parts();
BufResult(result.map(|(n, _)| n), bufs)
}
}
impl AsyncRead for TcpStream {
async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
self.inner.recv(buf).await
}
async fn read_vectored<V: IoVectoredBufMut>(&mut self, bufs: V) -> BufResult<usize, V> {
let (result, bufs) = self.inner.recvmsg(bufs).await.into_parts();
BufResult(result.map(|(n, _)| n), bufs)
}
}
#[cfg(target_os = "linux")]
impl AsyncReadManaged for TcpStream {
type Buffer = PooledBuf;
async fn read_managed(&mut self, len: usize) -> std::io::Result<Option<Self::Buffer>> {
self.recv_managed(len).await
}
}
#[cfg(target_os = "linux")]
impl AsyncReadManaged for &TcpStream {
type Buffer = PooledBuf;
async fn read_managed(&mut self, len: usize) -> std::io::Result<Option<Self::Buffer>> {
self.recv_managed(len).await
}
}
#[cfg(target_os = "linux")]
impl AsyncReadMulti for TcpStream {
fn read_multi(&mut self) -> std::io::Result<impl Stream<Item = std::io::Result<Self::Buffer>>> {
self.recv_multi()
}
}
#[cfg(target_os = "linux")]
impl AsyncReadMulti for &TcpStream {
fn read_multi(&mut self) -> std::io::Result<impl Stream<Item = std::io::Result<Self::Buffer>>> {
self.recv_multi()
}
}
impl AsyncWrite for &TcpStream {
async fn write<B: IoBuf>(&mut self, buf: B) -> BufResult<usize, B> {
self.inner.send(buf).await
}
async fn write_vectored<V: IoVectoredBuf>(&mut self, bufs: V) -> BufResult<usize, V> {
let (res, bufs) = self.inner.sendmsg(bufs, None, None::<Vec<u8>>).await.into_parts();
BufResult(res.map(|(n, _)| n), bufs)
}
async fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
async fn shutdown(&mut self) -> std::io::Result<()> {
self.inner.shutdown(std::net::Shutdown::Write)
}
}
impl AsyncWrite for TcpStream {
async fn write<B: IoBuf>(&mut self, buf: B) -> BufResult<usize, B> {
self.inner.send(buf).await
}
async fn write_vectored<V: IoVectoredBuf>(&mut self, bufs: V) -> BufResult<usize, V> {
let (res, bufs) = self.inner.sendmsg(bufs, None, None::<Vec<u8>>).await.into_parts();
BufResult(res.map(|(n, _)| n), bufs)
}
async fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
async fn shutdown(&mut self) -> std::io::Result<()> {
self.inner.shutdown(std::net::Shutdown::Write)
}
}
#[cfg(unix)]
impl FromRawFd for TcpStream {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
TcpStream::from(unsafe { Socket::from_raw_fd(fd) })
}
}
#[cfg(unix)]
impl AsRawFd for TcpStream {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
#[cfg(windows)]
impl FromRawSocket for TcpStream {
unsafe fn from_raw_socket(socket: RawSocket) -> Self {
TcpStream::from(unsafe { Socket::from_raw_socket(socket) })
}
}
#[cfg(windows)]
impl AsRawSocket for TcpStream {
fn as_raw_socket(&self) -> RawSocket {
self.inner.as_raw_socket()
}
}
impl From<Socket> for TcpStream {
fn from(inner: Socket) -> Self {
Self { inner }
}
}
impl IntoOwnedSplit for TcpStream {
type ReadHalf = OwnedReadHalf<Self>;
type WriteHalf = OwnedWriteHalf<Self>;
fn into_split(self) -> (Self::ReadHalf, Self::WriteHalf) {
let read = OwnedReadHalf {
inner: self.inner.clone(),
_stream: std::marker::PhantomData,
};
let write = OwnedWriteHalf {
inner: self.inner,
shutdown_on_drop: true,
_stream: std::marker::PhantomData,
};
(read, write)
}
}
impl ReuniteOwned for TcpStream {
fn reunite(
read: Self::ReadHalf,
write: Self::WriteHalf,
) -> Result<Self, ReuniteError<Self::ReadHalf, Self::WriteHalf>> {
read.reunite(write)
}
}
impl TcpStream {
pub fn from_std(socket: std::net::TcpStream) -> std::io::Result<Self> {
let inner = Socket::from_socket(socket2::Socket::from(socket))?;
Ok(Self { inner })
}
}