File: windows-uds.rs

package info (click to toggle)
rust-async-io 2.3.3-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 388 kB
  • sloc: makefile: 2
file content (127 lines) | stat: -rw-r--r-- 3,489 bytes parent folder | download | duplicates (2)
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!");
}