Implement sock_accept

With the addition of `sock_accept()` in `wasi-0.11.0`, wasmtime can now
implement basic networking for pre-opened sockets.

For Windows `AsHandle` was replaced with `AsRawHandleOrSocket` to cope
with the duality of Handles and Sockets.

For Unix a `wasi_cap_std_sync::net::Socket` enum was created to handle
the {Tcp,Unix}{Listener,Stream} more efficiently in
`WasiCtxBuilder::preopened_socket()`.

The addition of that many `WasiFile` implementors was mainly necessary,
because of the difference in the `num_ready_bytes()` function.

A known issue is Windows now busy polling on sockets, because except
for `stdin`, nothing is querying the status of windows handles/sockets.

Another know issue on Windows, is that there is no crate providing
support for `fcntl(fd, F_GETFL, 0)` on a socket.

Signed-off-by: Harald Hoyer <harald@profian.com>
This commit is contained in:
Harald Hoyer
2022-01-21 14:42:43 +01:00
committed by Dan Gohman
parent 8ba3294881
commit 853a025613
18 changed files with 650 additions and 30 deletions

View File

@@ -1,8 +1,8 @@
use crate::block_on_dummy_executor;
#[cfg(windows)]
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
#[cfg(not(windows))]
use io_lifetimes::AsFd;
#[cfg(windows)]
use io_lifetimes::{AsHandle, BorrowedHandle};
use std::any::Any;
use std::io;
use wasi_common::{
@@ -21,6 +21,54 @@ impl File {
}
}
pub struct TcpListener(wasi_cap_std_sync::net::TcpListener);
impl TcpListener {
pub(crate) fn from_inner(listener: wasi_cap_std_sync::net::TcpListener) -> Self {
TcpListener(listener)
}
pub fn from_cap_std(listener: cap_std::net::TcpListener) -> Self {
Self::from_inner(wasi_cap_std_sync::net::TcpListener::from_cap_std(listener))
}
}
pub struct TcpStream(wasi_cap_std_sync::net::TcpStream);
impl TcpStream {
pub(crate) fn from_inner(stream: wasi_cap_std_sync::net::TcpStream) -> Self {
TcpStream(stream)
}
pub fn from_cap_std(stream: cap_std::net::TcpStream) -> Self {
Self::from_inner(wasi_cap_std_sync::net::TcpStream::from_cap_std(stream))
}
}
#[cfg(unix)]
pub struct UnixListener(wasi_cap_std_sync::net::UnixListener);
#[cfg(unix)]
impl UnixListener {
pub(crate) fn from_inner(listener: wasi_cap_std_sync::net::UnixListener) -> Self {
UnixListener(listener)
}
pub fn from_cap_std(listener: cap_std::os::unix::net::UnixListener) -> Self {
Self::from_inner(wasi_cap_std_sync::net::UnixListener::from_cap_std(listener))
}
}
#[cfg(unix)]
pub struct UnixStream(wasi_cap_std_sync::net::UnixStream);
#[cfg(unix)]
impl UnixStream {
fn from_inner(stream: wasi_cap_std_sync::net::UnixStream) -> Self {
UnixStream(stream)
}
pub fn from_cap_std(stream: cap_std::os::unix::net::UnixStream) -> Self {
Self::from_inner(wasi_cap_std_sync::net::UnixStream::from_cap_std(stream))
}
}
pub struct Stdin(wasi_cap_std_sync::stdio::Stdin);
pub fn stdin() -> Stdin {
@@ -175,17 +223,28 @@ macro_rules! wasi_file_impl {
use wasi_common::ErrorExt;
Err(Error::badf())
}
async fn sock_accept(&mut self, fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
block_on_dummy_executor(|| self.0.sock_accept(fdflags))
}
}
#[cfg(windows)]
impl AsHandle for $ty {
fn as_handle(&self) -> BorrowedHandle<'_> {
self.0.as_handle()
impl AsRawHandleOrSocket for $ty {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0.as_raw_handle_or_socket()
}
}
};
}
wasi_file_impl!(File);
wasi_file_impl!(TcpListener);
wasi_file_impl!(TcpStream);
#[cfg(unix)]
wasi_file_impl!(UnixListener);
#[cfg(unix)]
wasi_file_impl!(UnixStream);
wasi_file_impl!(Stdin);
wasi_file_impl!(Stdout);
wasi_file_impl!(Stderr);