Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for UnixStream and UnixListener on Windows #1610

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7f69b97
add first pass implementation of windows uds
sullivan-sean Aug 15, 2022
bec570b
modify src/net for windows compatibility
sullivan-sean Aug 15, 2022
63e50c3
fix tests
sullivan-sean Aug 16, 2022
3591238
add docs back in
sullivan-sean Aug 16, 2022
9015ca2
cleanup
sullivan-sean Aug 16, 2022
7265833
remove log statements
sullivan-sean Aug 16, 2022
3884bb5
clean up selector
sullivan-sean Aug 16, 2022
5ca8952
clean up stream and listener sys logic
sullivan-sean Aug 18, 2022
985a145
fix re-registration
sullivan-sean Aug 18, 2022
f5ec8ce
add test for serial calls to listener.accept
sullivan-sean Aug 18, 2022
cee5c6b
fix serial calls to accept
sullivan-sean Aug 18, 2022
488254d
remove tempfile dependency and fix doc tests
sullivan-sean Aug 18, 2022
b6bae73
revert change in draining behavior
sullivan-sean Aug 20, 2022
2113b9f
re-organize stdnet files to mirror std::os::unix::net
sullivan-sean Aug 21, 2022
86c4c9a
use single syscall vectored approach from rust-lang/socket2
sullivan-sean Aug 21, 2022
9f26286
lint
sullivan-sean Aug 21, 2022
09a9b79
improve support across feature matrix
sullivan-sean Aug 21, 2022
bb914db
fix doc tests
sullivan-sean Aug 22, 2022
648855d
use bcrypt instead of rand
sullivan-sean Aug 22, 2022
3dd3c0f
add -_ to random char set to avoid rejection sampling
sullivan-sean Aug 22, 2022
2283d39
optimize rng syscall logic
sullivan-sean Aug 22, 2022
569de72
fix lint and fmt
sullivan-sean Aug 22, 2022
bdc6933
remove unused functions
sullivan-sean Aug 22, 2022
b07b4f1
fmt
sullivan-sean Aug 26, 2022
a2831ea
simplify windows mod
sullivan-sean Aug 26, 2022
73d5fae
clean up tests
sullivan-sean Aug 26, 2022
0baf112
fix indentation, imports, address other comments
sullivan-sean Aug 26, 2022
d9d4bb3
fmt
sullivan-sean Aug 26, 2022
82b17e8
remove unrelated code changes
sullivan-sean Sep 12, 2022
96e0735
fix lint
sullivan-sean Sep 12, 2022
0e1b6df
remove explicit SetHandleInformation calls
sullivan-sean Sep 13, 2022
77155cc
abstract socketaddr behind common API in net
sullivan-sean Sep 13, 2022
26a060b
fix lint
sullivan-sean Sep 13, 2022
fd8ddc1
add comment clarifying inheritance during calls to accept
sullivan-sean Oct 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ log = "0.4.8"
[target.'cfg(unix)'.dependencies]
libc = "0.2.121"

[target.'cfg(windows)'.dependencies]
rand = "0.8"
sullivan-sean marked this conversation as resolved.
Show resolved Hide resolved

[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.36"
features = [
"Win32_Storage_FileSystem", # Enables NtCreateFile
"Win32_Foundation", # Basic types eg HANDLE
"Win32_Networking_WinSock", # winsock2 types/functions
"Win32_System_IO", # IO types like OVERLAPPED etc
"Win32_System_Threading", # Process utilities
"Win32_System_WindowsProgramming", # General future used for various types/funcs
]

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ pub mod windows {
//! Windows only extensions.

pub use crate::sys::named_pipe::NamedPipe;

pub use crate::sys::windows::std;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must be removed. It currently contains the following types:

  • Incoming: not used.
  • SocketAddr: merge this with mio::net::SockAddr.
  • UnixListener and UnixStream: same as above.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The std::net types are used in tests/unix_listener.rs and test/unix_stream.rs for unix, and also accepted as an argument in from_std on mio::net::{UnixStream, UnixListener}. To remove this, I can swap to using mio::net for windows tests and make from_std pub(crate) on windows. Does this sound okay?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm this doesn't quite work as nicely as I'd hoped since the std::net types are blocking and the tests rely on this

}

pub mod features {
Expand Down
8 changes: 5 additions & 3 deletions src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ pub use self::tcp::{TcpListener, TcpStream};
mod udp;
#[cfg(not(target_os = "wasi"))]
pub use self::udp::UdpSocket;

#[cfg(unix)]
#[cfg(not(target_os = "wasi"))]
mod uds;
#[cfg(not(target_os = "wasi"))]
pub use self::uds::{SocketAddr, UnixListener, UnixStream};

#[cfg(unix)]
pub use self::uds::{SocketAddr, UnixDatagram, UnixListener, UnixStream};
pub use self::uds::UnixDatagram;
33 changes: 32 additions & 1 deletion src/net/uds/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ use crate::io_source::IoSource;
use crate::net::{SocketAddr, UnixStream};
use crate::{event, sys, Interest, Registry, Token};

#[cfg(windows)]
use crate::sys::windows::std::net;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(unix)]
use std::os::unix::net;
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::path::Path;
use std::{fmt, io};

Expand Down Expand Up @@ -35,7 +41,8 @@ impl UnixListener {
/// The call is responsible for ensuring that the listening socket is in
/// non-blocking mode.
pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
sys::uds::listener::accept(&self.inner)
self.inner
.do_io(|inner| sys::uds::listener::accept(&*inner))
}

/// Returns the local socket address of this listener.
Expand Down Expand Up @@ -79,18 +86,21 @@ impl fmt::Debug for UnixListener {
}
}

#[cfg(unix)]
sullivan-sean marked this conversation as resolved.
Show resolved Hide resolved
impl IntoRawFd for UnixListener {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}

#[cfg(unix)]
impl AsRawFd for UnixListener {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

#[cfg(unix)]
impl FromRawFd for UnixListener {
/// Converts a `RawFd` to a `UnixListener`.
///
Expand All @@ -102,3 +112,24 @@ impl FromRawFd for UnixListener {
UnixListener::from_std(FromRawFd::from_raw_fd(fd))
}
}

#[cfg(windows)]
impl IntoRawSocket for UnixListener {
fn into_raw_socket(self) -> RawSocket {
self.inner.into_inner().into_raw_socket()
}
}

#[cfg(windows)]
impl AsRawSocket for UnixListener {
fn as_raw_socket(&self) -> RawSocket {
self.inner.as_raw_socket()
}
}

#[cfg(windows)]
impl FromRawSocket for UnixListener {
unsafe fn from_raw_socket(sock: RawSocket) -> Self {
UnixListener::from_std(FromRawSocket::from_raw_socket(sock))
}
}
2 changes: 2 additions & 0 deletions src/net/uds/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#[cfg(unix)]
mod datagram;
#[cfg(unix)]
sullivan-sean marked this conversation as resolved.
Show resolved Hide resolved
pub use self::datagram::UnixDatagram;

mod listener;
Expand Down
100 changes: 99 additions & 1 deletion src/net/uds/stream.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use crate::io_source::IoSource;
use crate::{event, sys, Interest, Registry, Token};

#[cfg(windows)]
use crate::sys::windows::std::net;
use std::fmt;
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
use std::net::Shutdown;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(unix)]
use std::os::unix::net;
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::path::Path;

/// A non-blocking Unix stream socket.
Expand Down Expand Up @@ -86,7 +92,8 @@ impl UnixStream {
///
/// # Examples
///
/// ```
#[cfg_attr(unix, doc = "```")]
#[cfg_attr(windows, doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
Expand Down Expand Up @@ -134,6 +141,73 @@ impl UnixStream {
/// # Ok(())
/// # }
/// ```
///
#[cfg_attr(windows, doc = "```")]
#[cfg_attr(unix, doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use std::io;
/// use std::os::windows::io::AsRawSocket;
/// use std::os::raw::c_int;
/// use mio::net::UnixStream;
/// use windows_sys::Win32::Networking::WinSock;
/// use std::convert::TryInto;
///
/// let (stream1, stream2) = UnixStream::pair()?;
///
/// // Wait until the stream is writable...
///
/// // Write to the stream using a direct WinSock call, of course the
/// // `io::Write` implementation would be easier to use.
/// let buf = b"hello";
/// let n = stream1.try_io(|| {
/// let res = unsafe {
/// WinSock::send(
/// stream1.as_raw_socket().try_into().unwrap(),
/// &buf as *const _ as *const _,
/// buf.len() as c_int,
/// 0
/// )
/// };
/// if res != WinSock::SOCKET_ERROR {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by WinSock::send, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::from_raw_os_error(unsafe {
/// WinSock::WSAGetLastError()
/// }))
/// }
/// })?;
/// eprintln!("write {} bytes", n);
///
/// // Wait until the stream is readable...
///
/// // Read from the stream using a direct WinSock call, of course the
/// // `io::Read` implementation would be easier to use.
/// let mut buf = [0; 512];
/// let n = stream2.try_io(|| {
/// let res = unsafe {
/// WinSock::recv(
/// stream2.as_raw_socket().try_into().unwrap(),
/// &mut buf as *mut _ as *mut _,
/// buf.len() as c_int,
/// 0
/// )
/// };
/// if res != WinSock::SOCKET_ERROR {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by WinSock::recv, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("read {} bytes", n);
/// # Ok(())
/// # }
/// ```
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
where
F: FnOnce() -> io::Result<T>,
Expand Down Expand Up @@ -220,18 +294,21 @@ impl fmt::Debug for UnixStream {
}
}

#[cfg(unix)]
sullivan-sean marked this conversation as resolved.
Show resolved Hide resolved
impl IntoRawFd for UnixStream {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}

#[cfg(unix)]
impl AsRawFd for UnixStream {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

#[cfg(unix)]
impl FromRawFd for UnixStream {
/// Converts a `RawFd` to a `UnixStream`.
///
Expand All @@ -243,3 +320,24 @@ impl FromRawFd for UnixStream {
UnixStream::from_std(FromRawFd::from_raw_fd(fd))
}
}

#[cfg(windows)]
impl IntoRawSocket for UnixStream {
fn into_raw_socket(self) -> RawSocket {
self.inner.into_inner().into_raw_socket()
}
}

#[cfg(windows)]
impl AsRawSocket for UnixStream {
fn as_raw_socket(&self) -> RawSocket {
self.inner.as_raw_socket()
}
}

#[cfg(windows)]
impl FromRawSocket for UnixStream {
unsafe fn from_raw_socket(sock: RawSocket) -> Self {
UnixStream::from_std(FromRawSocket::from_raw_socket(sock))
}
}
12 changes: 11 additions & 1 deletion src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ cfg_os_poll! {

#[cfg(windows)]
cfg_os_poll! {
mod windows;
pub(crate) mod windows;
pub use self::windows::*;
}

Expand All @@ -83,4 +83,14 @@ cfg_not_os_poll! {
cfg_net! {
pub use self::unix::SocketAddr;
}

#[cfg(windows)]
cfg_any_os_ext! {
pub(crate) mod windows;
}

#[cfg(windows)]
cfg_net! {
pub use self::windows::SocketAddr;
}
}
1 change: 0 additions & 1 deletion src/sys/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub(crate) use self::waker::Waker;
cfg_net! {
pub(crate) mod tcp;
pub(crate) mod udp;
#[cfg(unix)]
pub(crate) mod uds;
}

Expand Down
7 changes: 7 additions & 0 deletions src/sys/shell/uds.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(unix)]
pub(crate) mod datagram {
use crate::net::SocketAddr;
use std::io;
Expand Down Expand Up @@ -34,7 +35,10 @@ pub(crate) mod datagram {

pub(crate) mod listener {
use crate::net::{SocketAddr, UnixStream};
#[cfg(windows)]
use crate::sys::windows::std::net;
use std::io;
#[cfg(unix)]
use std::os::unix::net;
use std::path::Path;

Expand All @@ -53,7 +57,10 @@ pub(crate) mod listener {

pub(crate) mod stream {
use crate::net::SocketAddr;
#[cfg(windows)]
use crate::sys::windows::std::net;
use std::io;
#[cfg(unix)]
use std::os::unix::net;
use std::path::Path;

Expand Down
Loading