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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user