Skip to content

Commit

Permalink
Implement sock_accept
Browse files Browse the repository at this point in the history
Signed-off-by: Harald Hoyer <harald@profian.com>
  • Loading branch information
haraldh committed Jan 26, 2022
1 parent 5fc01ba commit b36445b
Show file tree
Hide file tree
Showing 20 changed files with 491 additions and 24 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/wasi-common/cap-std-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ rustix = "0.31.0"
winapi = "0.3"
lazy_static = "1.4"
atty = "0.2.14"
io-extras = "0.12.0"

[dev-dependencies]
tempfile = "3.1.0"
14 changes: 14 additions & 0 deletions crates/wasi-common/cap-std-sync/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ impl WasiFile for File {
fn as_any(&self) -> &dyn Any {
self
}
async fn sock_accept(&mut self, _fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
Err(Error::badf())
}
async fn datasync(&self) -> Result<(), Error> {
self.0.sync_data()?;
Ok(())
Expand Down Expand Up @@ -171,8 +174,19 @@ impl AsHandle for File {
}
}

#[cfg(windows)]
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
#[cfg(windows)]
impl AsRawHandleOrSocket for File {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0.as_raw_handle_or_socket()
}
}

#[cfg(unix)]
use io_lifetimes::{AsFd, BorrowedFd};

#[cfg(unix)]
impl AsFd for File {
fn as_fd(&self) -> BorrowedFd<'_> {
Expand Down
2 changes: 2 additions & 0 deletions crates/wasi-common/cap-std-sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub mod dir;
pub mod file;
pub mod sched;
pub mod stdio;
pub mod tcplisten;
pub mod tcpstream;

pub use cap_std::ambient_authority;
pub use cap_std::fs::Dir;
Expand Down
12 changes: 12 additions & 0 deletions crates/wasi-common/cap-std-sync/src/sched/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ fn wasi_file_fd(f: &dyn WasiFile) -> Option<BorrowedFd<'_>> {
let a = f.as_any();
if a.is::<crate::file::File>() {
Some(a.downcast_ref::<crate::file::File>().unwrap().as_fd())
} else if a.is::<crate::tcpstream::TcpStream>() {
Some(
a.downcast_ref::<crate::tcpstream::TcpStream>()
.unwrap()
.as_fd(),
)
} else if a.is::<crate::tcplisten::TcpListener>() {
Some(
a.downcast_ref::<crate::tcplisten::TcpListener>()
.unwrap()
.as_fd(),
)
} else if a.is::<crate::stdio::Stdin>() {
Some(a.downcast_ref::<crate::stdio::Stdin>().unwrap().as_fd())
} else if a.is::<crate::stdio::Stdout>() {
Expand Down
31 changes: 19 additions & 12 deletions crates/wasi-common/cap-std-sync/src/sched/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
// taken the time to improve it. See bug #2880.

use anyhow::Context;
use io_lifetimes::AsHandle;
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
use std::ops::Deref;
use std::os::windows::io::{AsRawHandle, RawHandle};
use std::sync::mpsc::{self, Receiver, RecvTimeoutError, Sender, TryRecvError};
use std::sync::Mutex;
use std::thread;
Expand All @@ -33,7 +32,7 @@ pub async fn poll_oneoff<'a>(poll: &mut Poll<'a>) -> Result<(), Error> {
pub async fn poll_oneoff_<'a>(
poll: &mut Poll<'a>,
file_is_stdin: impl Fn(&dyn WasiFile) -> bool,
file_to_handle: impl Fn(&dyn WasiFile) -> Option<RawHandle>,
file_to_handle: impl Fn(&dyn WasiFile) -> Option<RawHandleOrSocket>,
) -> Result<(), Error> {
if poll.is_empty() {
return Ok(());
Expand Down Expand Up @@ -140,35 +139,43 @@ pub fn wasi_file_is_stdin(f: &dyn WasiFile) -> bool {
f.as_any().is::<crate::stdio::Stdin>()
}

pub fn wasi_file_raw_handle(f: &dyn WasiFile) -> Option<RawHandle> {
pub fn wasi_file_raw_handle(f: &dyn WasiFile) -> Option<RawHandleOrSocket> {
let a = f.as_any();
if a.is::<crate::file::File>() {
Some(
a.downcast_ref::<crate::file::File>()
.unwrap()
.as_handle()
.as_raw_handle(),
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::tcpstream::TcpStream>() {
Some(
a.downcast_ref::<crate::tcpstream::TcpStream>()
.unwrap()
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::tcplisten::TcpListener>() {
Some(
a.downcast_ref::<crate::tcplisten::TcpListener>()
.unwrap()
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::stdio::Stdin>() {
Some(
a.downcast_ref::<crate::stdio::Stdin>()
.unwrap()
.as_handle()
.as_raw_handle(),
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::stdio::Stdout>() {
Some(
a.downcast_ref::<crate::stdio::Stdout>()
.unwrap()
.as_handle()
.as_raw_handle(),
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::stdio::Stderr>() {
Some(
a.downcast_ref::<crate::stdio::Stderr>()
.unwrap()
.as_handle()
.as_raw_handle(),
.as_raw_handle_or_socket(),
)
} else {
None
Expand Down
23 changes: 23 additions & 0 deletions crates/wasi-common/cap-std-sync/src/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use std::io;
use std::io::{Read, Write};
use system_interface::io::ReadReady;

#[cfg(windows)]
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
#[cfg(unix)]
use io_lifetimes::{AsFd, BorrowedFd};
#[cfg(windows)]
Expand Down Expand Up @@ -124,13 +126,24 @@ impl WasiFile for Stdin {
async fn writable(&self) -> Result<(), Error> {
Err(Error::badf())
}

async fn sock_accept(&mut self, _fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
Err(Error::badf())
}
}
#[cfg(windows)]
impl AsHandle for Stdin {
fn as_handle(&self) -> BorrowedHandle<'_> {
self.0.as_handle()
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for Stdin {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0.as_raw_handle_or_socket()
}
}
#[cfg(unix)]
impl AsFd for Stdin {
fn as_fd(&self) -> BorrowedFd<'_> {
Expand Down Expand Up @@ -244,6 +257,9 @@ macro_rules! wasi_file_write_impl {
async fn writable(&self) -> Result<(), Error> {
Err(Error::badf())
}
async fn sock_accept(&mut self, _fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
Err(Error::badf())
}
}
#[cfg(windows)]
impl AsHandle for $ty {
Expand All @@ -257,6 +273,13 @@ macro_rules! wasi_file_write_impl {
self.0.as_fd()
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for $ty {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0.as_raw_handle_or_socket()
}
}
};
}

Expand Down
156 changes: 156 additions & 0 deletions crates/wasi-common/cap-std-sync/src/tcplisten.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
use super::tcpstream::TcpStream;
use std::any::Any;
use std::io;
use wasi_common::{
file::{Advice, FdFlags, FileType, Filestat, WasiFile},
Error, ErrorExt,
};

pub struct TcpListener(cap_std::net::TcpListener);

impl TcpListener {
pub fn from_cap_std(socket: cap_std::net::TcpListener) -> Self {
TcpListener(socket)
}
}

#[async_trait::async_trait]
impl WasiFile for TcpListener {
fn as_any(&self) -> &dyn Any {
self
}
async fn sock_accept(&mut self, fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
let (stream, _) = self.0.accept()?;
let mut stream = TcpStream::from_cap_std(stream);
stream.set_fdflags(fdflags).await?;
Ok(Box::new(stream))
}
async fn datasync(&self) -> Result<(), Error> {
Err(Error::badf())
}
async fn sync(&self) -> Result<(), Error> {
Err(Error::badf())
}
async fn get_filetype(&self) -> Result<FileType, Error> {
Ok(FileType::SocketStream)
}
async fn get_fdflags(&self) -> Result<FdFlags, Error> {
Err(Error::badf())
}
async fn set_fdflags(&mut self, fdflags: FdFlags) -> Result<(), Error> {
if fdflags == wasi_common::file::FdFlags::NONBLOCK {
self.0.set_nonblocking(true)?;
} else if fdflags.is_empty() {
self.0.set_nonblocking(false)?;
} else {
return Err(Error::invalid_argument().context("cannot set anything else than NONBLOCK"));
}
Ok(())
}
async fn get_filestat(&self) -> Result<Filestat, Error> {
Err(Error::badf())
}
async fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
Err(Error::badf())
}
async fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> {
Err(Error::badf())
}
async fn allocate(&self, _offset: u64, _len: u64) -> Result<(), Error> {
Err(Error::badf())
}
async fn set_times(
&self,
_atime: Option<wasi_common::SystemTimeSpec>,
_mtime: Option<wasi_common::SystemTimeSpec>,
) -> Result<(), Error> {
Err(Error::badf())
}
async fn read_vectored<'a>(&self, _bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> {
Err(Error::badf())
}
async fn read_vectored_at<'a>(
&self,
_bufs: &mut [io::IoSliceMut<'a>],
_offset: u64,
) -> Result<u64, Error> {
Err(Error::badf())
}
async fn write_vectored<'a>(&self, _bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
Err(Error::badf())
}
async fn write_vectored_at<'a>(
&self,
_bufs: &[io::IoSlice<'a>],
_offset: u64,
) -> Result<u64, Error> {
Err(Error::badf())
}
async fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> {
Err(Error::badf())
}
async fn peek(&self, _buf: &mut [u8]) -> Result<u64, Error> {
Err(Error::badf())
}
async fn num_ready_bytes(&self) -> Result<u64, Error> {
Ok(1)
}
fn isatty(&self) -> bool {
false
}
async fn readable(&self) -> Result<(), Error> {
Err(Error::badf())
}
async fn writable(&self) -> Result<(), Error> {
Err(Error::badf())
}
}

pub fn filetype_from(ft: &cap_std::fs::FileType) -> FileType {
use cap_fs_ext::FileTypeExt;
if ft.is_block_device() {
FileType::SocketDgram
} else {
FileType::SocketStream
}
}

#[cfg(windows)]
use io_lifetimes::{AsSocket, BorrowedSocket};

#[cfg(windows)]
impl AsSocket for TcpListener {
#[inline]
fn as_socket(&self) -> BorrowedSocket<'_> {
self.0.as_socket()
}
}

#[cfg(windows)]
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};

#[cfg(windows)]
impl AsRawHandleOrSocket for TcpListener {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0.as_raw_handle_or_socket()
}
}

#[cfg(unix)]
use io_lifetimes::{AsFd, BorrowedFd};

#[cfg(unix)]
impl AsFd for TcpListener {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}

pub fn from_sysif_fdflags(f: system_interface::fs::FdFlags) -> wasi_common::file::FdFlags {
let mut out = wasi_common::file::FdFlags::empty();
if f.contains(system_interface::fs::FdFlags::NONBLOCK) {
out |= wasi_common::file::FdFlags::NONBLOCK;
}
out
}
Loading

0 comments on commit b36445b

Please sign in to comment.