1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
//! Uses the `uds_windows` crate to simulate Unix sockets on Windows.
//!
//! Run with:
//!
//! ```
//! 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!("This example works only on Windows!");
}
|