From dba91398f39874d8583125c551e4fb70f16fd108 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Fri, 8 Sep 2023 08:47:31 -0700 Subject: [PATCH] Review comments Signed-off-by: John Nunley --- examples/windows-uds.rs | 118 +++++++++++++++++++++++++++++++++++++++- src/lib.rs | 3 +- 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/examples/windows-uds.rs b/examples/windows-uds.rs index d538702..0f1bf04 100644 --- a/examples/windows-uds.rs +++ b/examples/windows-uds.rs @@ -6,6 +6,122 @@ //! cargo run --example windows-uds //! ``` +#[cfg(windows)] +fn main() -> std::io::Result<()> { + use std::ops::Deref; + use std::os::windows::io::{AsRawSocket, AsSocket, BorrowedSocket}; + use std::path::PathBuf; + + use async_io::Async; + use blocking::Unblock; + use futures_lite::{future, prelude::*}; + use std::io; + use tempfile::tempdir; + + // n.b.: notgull: uds_windows does not support I/O safety uet, hence the wrapper types + + struct UnixListener(uds_windows::UnixListener); + + impl From for UnixListener { + fn from(ul: uds_windows::UnixListener) -> Self { + Self(ul) + } + } + + impl Deref for UnixListener { + type Target = uds_windows::UnixListener; + + fn deref(&self) -> &uds_windows::UnixListener { + &self.0 + } + } + + impl AsSocket for UnixListener { + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } + } + } + + struct UnixStream(uds_windows::UnixStream); + + impl From for UnixStream { + fn from(ul: uds_windows::UnixStream) -> Self { + Self(ul) + } + } + + impl Deref for UnixStream { + type Target = uds_windows::UnixStream; + + fn deref(&self) -> &uds_windows::UnixStream { + &self.0 + } + } + + impl AsSocket for UnixStream { + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } + } + } + + impl io::Read for UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::Read::read(&mut self.0, buf) + } + } + + impl io::Write for UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + io::Write::write(&mut self.0, buf) + } + + fn flush(&mut self) -> io::Result<()> { + io::Write::flush(&mut self.0) + } + } + + unsafe impl async_io::IoSafe for UnixStream {} + + async fn client(addr: PathBuf) -> io::Result<()> { + // Connect to the address. + let stream = Async::new(UnixStream::from(uds_windows::UnixStream::connect(addr)?))?; + println!("Connected to {:?}", stream.get_ref().peer_addr()?); + + // Pipe the stream to stdout. + let mut stdout = Unblock::new(std::io::stdout()); + futures_lite::io::copy(stream, &mut stdout).await?; + Ok(()) + } + + let dir = tempdir()?; + let path = dir.path().join("socket"); + + future::block_on(async { + // Create a listener. + let listener = Async::new(UnixListener::from(uds_windows::UnixListener::bind(&path)?))?; + println!("Listening on {:?}", listener.get_ref().local_addr()?); + + future::try_zip( + async { + // Accept the client. + let (stream, _) = listener.read_with(|l| l.accept()).await?; + println!("Accepted a client"); + + // Send a message, drop the stream, and wait for the client. + Async::new(UnixStream::from(stream))? + .write_all(b"Hello!\n") + .await?; + Ok(()) + }, + client(path), + ) + .await?; + + Ok(()) + }) +} + +#[cfg(not(windows))] fn main() { - println!("TODO: Restore this example from git once uds_windows implements I/O safety"); + println!("This example works only on Windows!"); } diff --git a/src/lib.rs b/src/lib.rs index 55cfc35..91cdabf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1153,7 +1153,7 @@ impl Drop for Async { /// happen if the inner resource (the [`TcpStream`], [`UnixListener`] or other `T`) is moved out /// and dropped before the [`Async`]. Because of this, functions that grant mutable access to /// the inner type are unsafe, as there is no way to guarantee that the source won't be dropped -/// and a dangling pointer won't be left behind. +/// and a dangling handle won't be left behind. /// /// Unfortunately this extends to implementations of [`Read`] and [`Write`]. Since methods on those /// traits take `&mut`, there is no guarantee that the implementor of those traits won't move the @@ -1205,6 +1205,7 @@ unsafe impl IoSafe for std::io::BufWriter {} unsafe impl IoSafe for std::io::LineWriter {} unsafe impl IoSafe for &mut T {} unsafe impl IoSafe for Box {} +unsafe impl IoSafe for std::borrow::Cow<'_, T> {} impl AsyncRead for Async { fn poll_read(