Skip to content

Commit

Permalink
Review comments
Browse files Browse the repository at this point in the history
Signed-off-by: John Nunley <[email protected]>
  • Loading branch information
notgull committed Sep 8, 2023
1 parent ea3a4bc commit dba9139
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 2 deletions.
118 changes: 117 additions & 1 deletion examples/windows-uds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<uds_windows::UnixListener> 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<uds_windows::UnixStream> 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<usize> {
io::Read::read(&mut self.0, buf)
}
}

impl io::Write for UnixStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
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!");
}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ impl<T> Drop for Async<T> {
/// 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
Expand Down Expand Up @@ -1205,6 +1205,7 @@ unsafe impl<T: IoSafe + Write> IoSafe for std::io::BufWriter<T> {}
unsafe impl<T: IoSafe + Write> IoSafe for std::io::LineWriter<T> {}
unsafe impl<T: IoSafe + ?Sized> IoSafe for &mut T {}
unsafe impl<T: IoSafe + ?Sized> IoSafe for Box<T> {}
unsafe impl<T: Clone + IoSafe + ?Sized> IoSafe for std::borrow::Cow<'_, T> {}

impl<T: IoSafe + Read> AsyncRead for Async<T> {
fn poll_read(
Expand Down

0 comments on commit dba9139

Please sign in to comment.