Skip to content

Commit

Permalink
add first pass implementation of windows uds
Browse files Browse the repository at this point in the history
modify src/net for windows compatibility

fix tests

add docs back in

cleanup

remove log statements

clean up selector

clean up stream and listener sys logic

fix re-registration

add test for serial calls to listener.accept

fix serial calls to accept

remove tempfile dependency and fix doc tests

revert change in draining behavior

re-organize stdnet files to mirror std::os::unix::net

use single syscall vectored approach from rust-lang/socket2

lint

improve support across feature matrix

fix doc tests

use bcrypt instead of rand

add -_ to random char set to avoid rejection sampling

optimize rng syscall logic

fix lint and fmt

remove unused functions

fmt

simplify windows mod

clean up tests

fix indentation, imports, address other comments

fmt

remove unrelated code changes

fix lint

remove explicit SetHandleInformation calls

abstract socketaddr behind common API in net

fix lint

add comment clarifying inheritance during calls to accept
  • Loading branch information
sullivan-sean authored and KolbyML committed May 3, 2023
1 parent 0757ec8 commit 457f753
Show file tree
Hide file tree
Showing 28 changed files with 1,249 additions and 299 deletions.
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;
20 changes: 10 additions & 10 deletions src/net/tcp/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,49 +269,49 @@ impl TcpStream {

impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.read(buf))
self.inner.do_io(|inner| (&*inner).read(buf))
}

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
}
}

impl<'a> Read for &'a TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.read(buf))
self.inner.do_io(|inner| (&*inner).read(buf))
}

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
}
}

impl Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.write(buf))
self.inner.do_io(|inner| (&*inner).write(buf))
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
}

fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|mut inner| inner.flush())
self.inner.do_io(|inner| (&*inner).flush())
}
}

impl<'a> Write for &'a TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.write(buf))
self.inner.do_io(|inner| (&*inner).write(buf))
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
}

fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|mut inner| inner.flush())
self.inner.do_io(|inner| (&*inner).flush())
}
}

Expand Down
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)]
#[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)]
#[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)]
#[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

0 comments on commit 457f753

Please sign in to comment.