use std::{
io,
mem::MaybeUninit,
net::{Shutdown, SocketAddr},
time::Duration,
};
pub use crate::addr::{lookup_host, ToAddrs};
mod sock;
mod udp;
#[cfg(unix)]
#[path = "../unix.rs"]
pub mod unix;
#[cfg(unix)]
use sock::raw;
use sock::{is_in_progress, socket_addr, Io};
use socket2::{Domain, Protocol, SockAddr, Socket, Type};
pub use udp::UdpSocket;
#[cfg(unix)]
pub use unix::{UnixDatagram, UnixListener, UnixStream};
use crate::buf::{BufResult, IoBuf, IoBufMut};
pub struct TcpListener {
io: Io,
}
impl TcpListener {
pub async fn bind(addr: impl crate::addr::ToAddrs) -> io::Result<Self> {
let mut last = None;
for sa in crate::addr::lookup_host(addr).await? {
match Self::bind_addr(sa) {
Ok(l) => return Ok(l),
Err(e) => last = Some(e),
}
}
Err(last.unwrap_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"could not resolve to any address",
)
}))
}
pub fn bind_addr(addr: SocketAddr) -> io::Result<Self> {
let sock = Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP))?;
#[cfg(unix)]
sock.set_reuse_address(true)?;
#[cfg(all(unix, not(any(target_os = "solaris", target_os = "illumos"))))]
sock.set_reuse_port(true)?;
sock.bind(&SockAddr::from(addr))?;
sock.listen(1024)?;
Ok(Self { io: Io::new(sock)? })
}
pub fn from_std(listener: std::net::TcpListener) -> io::Result<Self> {
Ok(Self {
io: Io::new(Socket::from(listener))?,
})
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
socket_addr(self.io.sock.local_addr()?)
}
pub async fn accept(&self) -> io::Result<TcpStream> {
Ok(self.accept_addr().await?.0)
}
pub async fn accept_addr(&self) -> io::Result<(TcpStream, SocketAddr)> {
loop {
match self.io.sock.accept() {
Ok((sock, peer)) => {
return Ok((TcpStream { io: Io::new(sock)? }, socket_addr(peer)?));
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => self.io.ready(false).await?,
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
}
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.io.sock.set_ttl(ttl)
}
pub fn ttl(&self) -> io::Result<u32> {
self.io.sock.ttl()
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.io.sock.take_error()
}
#[cfg(unix)]
pub fn as_raw_fd(&self) -> std::os::fd::RawFd {
raw(&self.io.sock)
}
}
pub struct TcpStream {
io: Io,
}
impl TcpStream {
pub async fn connect(addr: impl crate::addr::ToAddrs) -> io::Result<Self> {
let mut last = None;
for sa in crate::addr::lookup_host(addr).await? {
match Self::connect_addr(sa).await {
Ok(s) => return Ok(s),
Err(e) => last = Some(e),
}
}
Err(last.unwrap_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"could not resolve to any address",
)
}))
}
pub async fn connect_addr(addr: SocketAddr) -> io::Result<Self> {
let sock = Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP))?;
let io = Io::new(sock)?;
match io.sock.connect(&SockAddr::from(addr)) {
Ok(()) => {}
Err(e) if is_in_progress(&e) => loop {
io.ready(true).await?;
if let Some(e) = io.sock.take_error()? {
return Err(e);
}
match io.sock.peer_addr() {
Ok(_) => break,
Err(e) if e.kind() == io::ErrorKind::NotConnected => {}
Err(e) => return Err(e),
}
},
Err(e) => return Err(e),
}
Ok(Self { io })
}
pub fn from_std(stream: std::net::TcpStream) -> io::Result<Self> {
Ok(Self {
io: Io::new(Socket::from(stream))?,
})
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
socket_addr(self.io.sock.peer_addr()?)
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
socket_addr(self.io.sock.local_addr()?)
}
pub async fn read<B>(&self, mut buf: B) -> BufResult<usize, B>
where
B: IoBufMut + Send + 'static,
{
loop {
let total = buf.bytes_total();
let ptr = buf.stable_ptr_mut() as *mut MaybeUninit<u8>;
let spare = unsafe { std::slice::from_raw_parts_mut(ptr, total) };
match self.io.sock.recv(spare) {
Ok(n) => {
unsafe { buf.set_init(n) };
return (Ok(n), buf);
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
if let Err(e) = self.io.ready(false).await {
return (Err(e), buf);
}
}
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return (Err(e), buf),
}
}
}
pub async fn read_exact<B>(&self, mut buf: B) -> BufResult<(), B>
where
B: IoBufMut + Send + 'static,
{
let total = buf.bytes_total();
let mut got = 0usize;
while got < total {
let base = buf.stable_ptr_mut();
let ptr = unsafe { base.add(got) } as *mut MaybeUninit<u8>;
let spare = unsafe { std::slice::from_raw_parts_mut(ptr, total - got) };
match self.io.sock.recv(spare) {
Ok(0) => {
let e =
io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer");
return (Err(e), buf);
}
Ok(n) => got += n,
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
if let Err(e) = self.io.ready(false).await {
return (Err(e), buf);
}
}
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return (Err(e), buf),
}
}
unsafe { buf.set_init(total) };
(Ok(()), buf)
}
pub async fn write<B>(&self, buf: B) -> BufResult<usize, B>
where
B: IoBuf + Send + 'static,
{
loop {
let data = unsafe { std::slice::from_raw_parts(buf.stable_ptr(), buf.bytes_init()) };
match self.io.send_nosig(data) {
Ok(n) => return (Ok(n), buf),
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
if let Err(e) = self.io.ready(true).await {
return (Err(e), buf);
}
}
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return (Err(e), buf),
}
}
}
pub async fn write_all<B>(&self, buf: B) -> BufResult<(), B>
where
B: IoBuf + Send + 'static,
{
let total = buf.bytes_init();
let mut sent = 0usize;
while sent < total {
let data =
unsafe { std::slice::from_raw_parts(buf.stable_ptr().add(sent), total - sent) };
match self.io.send_nosig(data) {
Ok(0) => {
let e =
io::Error::new(io::ErrorKind::WriteZero, "failed to write whole buffer");
return (Err(e), buf);
}
Ok(n) => sent += n,
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
if let Err(e) = self.io.ready(true).await {
return (Err(e), buf);
}
}
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return (Err(e), buf),
}
}
(Ok(()), buf)
}
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.io.sock.shutdown(how)
}
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
self.io.sock.set_nodelay(nodelay)
}
pub fn nodelay(&self) -> io::Result<bool> {
self.io.sock.nodelay()
}
pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
self.io.sock.set_keepalive(keepalive)
}
pub fn keepalive(&self) -> io::Result<bool> {
self.io.sock.keepalive()
}
pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
self.io.sock.set_linger(dur)
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
self.io.sock.linger()
}
pub fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
self.io.sock.set_recv_buffer_size(size)
}
pub fn recv_buffer_size(&self) -> io::Result<usize> {
self.io.sock.recv_buffer_size()
}
pub fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
self.io.sock.set_send_buffer_size(size)
}
pub fn send_buffer_size(&self) -> io::Result<usize> {
self.io.sock.send_buffer_size()
}
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.io.sock.set_ttl(ttl)
}
pub fn ttl(&self) -> io::Result<u32> {
self.io.sock.ttl()
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.io.sock.take_error()
}
#[cfg(unix)]
pub fn as_raw_fd(&self) -> std::os::fd::RawFd {
raw(&self.io.sock)
}
}