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

@@ -30,6 +30,9 @@ pub use anyhow::{Context, Error};
/// the crate. Not all values are represented presently.
#[derive(Debug, thiserror::Error)]
pub enum ErrorKind {
/// Errno::WouldBlk: Would block
#[error("WouldBlk: Would block")]
WouldBlk,
/// Errno::Noent: No such file or directory
#[error("Noent: No such file or directory")]
Noent,

View File

@@ -5,6 +5,7 @@ use std::any::Any;
#[wiggle::async_trait]
pub trait WasiFile: Send + Sync {
fn as_any(&self) -> &dyn Any;
async fn sock_accept(&mut self, fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error>;
async fn datasync(&self) -> Result<(), Error>; // write op
async fn sync(&self) -> Result<(), Error>; // file op
async fn get_filetype(&self) -> Result<FileType, Error>; // file op

View File

@@ -189,6 +189,10 @@ impl<R: Read + Any + Send + Sync> WasiFile for ReadPipe<R> {
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())
}
}
/// A virtual pipe write end.
@@ -348,4 +352,8 @@ impl<W: Write + Any + Send + Sync> WasiFile for WritePipe<W> {
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())
}
}

View File

@@ -70,6 +70,7 @@ impl From<ErrorKind> for types::Errno {
fn from(e: ErrorKind) -> types::Errno {
use types::Errno;
match e {
ErrorKind::WouldBlk => Errno::Again,
ErrorKind::Noent => Errno::Noent,
ErrorKind::TooBig => Errno::TooBig,
ErrorKind::Badf => Errno::Badf,
@@ -114,6 +115,7 @@ impl TryFrom<std::io::Error> for types::Errno {
fn raw_error_code(err: &std::io::Error) -> Option<types::Errno> {
use rustix::io::Error;
match Error::from_io_error(err) {
Some(Error::AGAIN) => Some(types::Errno::Again),
Some(Error::PIPE) => Some(types::Errno::Pipe),
Some(Error::PERM) => Some(types::Errno::Perm),
Some(Error::NOENT) => Some(types::Errno::Noent),
@@ -147,6 +149,7 @@ impl TryFrom<std::io::Error> for types::Errno {
fn raw_error_code(err: &std::io::Error) -> Option<types::Errno> {
use winapi::shared::winerror;
match err.raw_os_error().map(|code| code as u32) {
Some(winerror::WSAEWOULDBLOCK) => Some(types::Errno::Again),
Some(winerror::ERROR_BAD_ENVIRONMENT) => Some(types::Errno::TooBig),
Some(winerror::ERROR_FILE_NOT_FOUND) => Some(types::Errno::Noent),
Some(winerror::ERROR_PATH_NOT_FOUND) => Some(types::Errno::Noent),
@@ -1148,6 +1151,27 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(())
}
async fn sock_accept(
&mut self,
fd: types::Fd,
flags: types::Fdflags,
) -> Result<types::Fd, Error> {
let table = self.table();
let f = table
.get_file_mut(u32::from(fd))?
.get_cap_mut(FileCaps::READ)?;
let file = f.sock_accept(FdFlags::from(flags)).await?;
let file_caps = FileCaps::READ
| FileCaps::WRITE
| FileCaps::FDSTAT_SET_FLAGS
| FileCaps::POLL_READWRITE
| FileCaps::FILESTAT_GET;
let fd = table.push(Box::new(FileEntry::new(file_caps, file)))?;
Ok(types::Fd::from(fd))
}
async fn sock_recv<'a>(
&mut self,
_fd: types::Fd,