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 all 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
11 changes: 8 additions & 3 deletions src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ 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(not(target_os = "wasi"))]
pub(crate) use self::uds::AddressKind;

#[cfg(unix)]
pub use self::uds::{SocketAddr, UnixDatagram, UnixListener, UnixStream};
pub use self::uds::UnixDatagram;
97 changes: 97 additions & 0 deletions src/net/uds/addr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use crate::sys;
use std::path::Path;
use std::{ascii, fmt};

/// An address associated with a `mio` specific Unix socket.
///
/// This is implemented instead of imported from [`net::SocketAddr`] because
/// there is no way to create a [`net::SocketAddr`]. One must be returned by
/// [`accept`], so this is returned instead.
///
/// [`net::SocketAddr`]: std::os::unix::net::SocketAddr
/// [`accept`]: #method.accept
pub struct SocketAddr {
inner: sys::SocketAddr,
}

struct AsciiEscaped<'a>(&'a [u8]);

pub(crate) enum AddressKind<'a> {
Unnamed,
Pathname(&'a Path),
Abstract(&'a [u8]),
}

impl SocketAddr {
pub(crate) fn new(inner: sys::SocketAddr) -> Self {
SocketAddr { inner }
}

fn address(&self) -> AddressKind<'_> {
self.inner.address()
}
}

cfg_os_poll! {
impl SocketAddr {
/// Returns `true` if the address is unnamed.
///
/// Documentation reflected in [`SocketAddr`]
///
/// [`SocketAddr`]: std::os::unix::net::SocketAddr
pub fn is_unnamed(&self) -> bool {
matches!(self.address(), AddressKind::Unnamed)
}

/// Returns the contents of this address if it is a `pathname` address.
///
/// Documentation reflected in [`SocketAddr`]
///
/// [`SocketAddr`]: std::os::unix::net::SocketAddr
pub fn as_pathname(&self) -> Option<&Path> {
if let AddressKind::Pathname(path) = self.address() {
Some(path)
} else {
None
}
}

/// Returns the contents of this address if it is an abstract namespace
/// without the leading null byte.
// Link to std::os::unix::net::SocketAddr pending
// https://github.com/rust-lang/rust/issues/85410.
pub fn as_abstract_namespace(&self) -> Option<&[u8]> {
if let AddressKind::Abstract(path) = self.address() {
Some(path)
} else {
None
}
}
}
}

impl fmt::Debug for SocketAddr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "{:?}", self.address())
}
}

impl fmt::Debug for AddressKind<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AddressKind::Unnamed => write!(fmt, "(unnamed)"),
AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)),
AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path),
}
}
}

impl<'a> fmt::Display for AsciiEscaped<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "\"")?;
for byte in self.0.iter().cloned().flat_map(ascii::escape_default) {
write!(fmt, "{}", byte as char)?;
}
write!(fmt, "\"")
}
}
12 changes: 7 additions & 5 deletions src/net/uds/datagram.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::io_source::IoSource;
use crate::net::SocketAddr;
use crate::{event, sys, Interest, Registry, Token};

use std::net::Shutdown;
Expand Down Expand Up @@ -54,24 +55,25 @@ impl UnixDatagram {
}

/// Returns the address of this socket.
pub fn local_addr(&self) -> io::Result<sys::SocketAddr> {
sys::uds::datagram::local_addr(&self.inner)
pub fn local_addr(&self) -> io::Result<SocketAddr> {
sys::uds::datagram::local_addr(&self.inner).map(SocketAddr::new)
}

/// Returns the address of this socket's peer.
///
/// The `connect` method will connect the socket to a peer.
pub fn peer_addr(&self) -> io::Result<sys::SocketAddr> {
sys::uds::datagram::peer_addr(&self.inner)
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
sys::uds::datagram::peer_addr(&self.inner).map(SocketAddr::new)
}

/// Receives data from the socket.
///
/// On success, returns the number of bytes read and the address from
/// whence the data came.
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, sys::SocketAddr)> {
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.inner
.do_io(|inner| sys::uds::datagram::recv_from(inner, buf))
.map(|(nread, addr)| (nread, SocketAddr::new(addr)))
}

/// Receives data from the socket.
Expand Down
53 changes: 50 additions & 3 deletions 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::stdnet as 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 All @@ -24,23 +30,34 @@ impl UnixListener {
/// standard library in the Mio equivalent. The conversion assumes nothing
/// about the underlying listener; it is left up to the user to set it in
/// non-blocking mode.
#[cfg(unix)]
sullivan-sean marked this conversation as resolved.
Show resolved Hide resolved
#[cfg_attr(docsrs, doc(cfg(unix)))]
pub fn from_std(listener: net::UnixListener) -> UnixListener {
UnixListener {
inner: IoSource::new(listener),
}
}

#[cfg(windows)]
pub(crate) fn from_std(listener: net::UnixListener) -> UnixListener {
UnixListener {
inner: IoSource::new(listener),
}
}

/// Accepts a new incoming connection to this listener.
///
/// 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(sys::uds::listener::accept)
.map(|(stream, addr)| (stream, SocketAddr::new(addr)))
}

/// Returns the local socket address of this listener.
pub fn local_addr(&self) -> io::Result<sys::SocketAddr> {
sys::uds::listener::local_addr(&self.inner)
pub fn local_addr(&self) -> io::Result<SocketAddr> {
sys::uds::listener::local_addr(&self.inner).map(SocketAddr::new)
}

/// Returns the value of the `SO_ERROR` option.
Expand Down Expand Up @@ -79,18 +96,24 @@ impl fmt::Debug for UnixListener {
}
}

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

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

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

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

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

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

mod listener;
Expand All @@ -7,4 +10,6 @@ pub use self::listener::UnixListener;
mod stream;
pub use self::stream::UnixStream;

pub use crate::sys::SocketAddr;
mod addr;
pub(crate) use self::addr::AddressKind;
pub use self::addr::SocketAddr;
Loading