mod null;
mod tls;
use null::Null;
use super::{Compiled, Connected, Loader};
use anyhow::{Context, Result};
use cap_std::net::{TcpListener, TcpStream};
use enarx_config::{File, Protocol};
use wasi_common::{file::FileCaps, WasiFile};
use wasmtime::AsContextMut;
use wasmtime_wasi::stdio::{stderr, stdin, stdout};
impl Loader<Compiled> {
pub fn next(mut self) -> Result<Loader<Connected>> {
let mut ctx = self.0.wstore.as_context_mut();
let ctx = ctx.data_mut();
for (k, v) in self.0.config.env.iter() {
ctx.push_env(k, v)?;
}
ctx.push_arg("main.wasm")
.context("failed to push argv[0]")?;
for arg in self.0.config.args.iter() {
ctx.push_arg(arg).context("failed to push argument")?;
}
let names: Vec<_> = self.0.config.files.iter().map(|f| f.name()).collect();
ctx.push_env("FD_COUNT", &names.len().to_string())?;
ctx.push_env("FD_NAMES", &names.join(":"))?;
for (fd, file) in self.0.config.files.iter().enumerate() {
let srv = self.0.srvcfg.clone();
let clt = self.0.cltcfg.clone();
let (mut file, mut caps): (Box<dyn WasiFile>, _) = match file {
File::Null { .. } => (Box::new(Null), FileCaps::all()),
File::Stdin { .. } => (Box::new(stdin()), FileCaps::all()),
File::Stdout { .. } => (Box::new(stdout()), FileCaps::all()),
File::Stderr { .. } => (Box::new(stderr()), FileCaps::all()),
File::Listen {
addr, port, prot, ..
} => {
let caps = FileCaps::FILESTAT_GET
| FileCaps::FDSTAT_SET_FLAGS
| FileCaps::POLL_READWRITE
| FileCaps::READ;
let tcp = std::net::TcpListener::bind((addr.as_str(), *port))?;
let tcp = TcpListener::from_std(tcp);
match prot {
Protocol::Tcp => (wasmtime_wasi::net::Socket::from(tcp).into(), caps),
Protocol::Tls => (tls::Listener::new(tcp, srv).into(), caps),
}
}
File::Connect {
host, port, prot, ..
} => {
let caps = FileCaps::FILESTAT_GET
| FileCaps::FDSTAT_SET_FLAGS
| FileCaps::POLL_READWRITE
| FileCaps::READ
| FileCaps::WRITE;
let tcp = std::net::TcpStream::connect((&**host, *port))?;
let tcp = TcpStream::from_std(tcp);
match prot {
Protocol::Tcp => (wasmtime_wasi::net::Socket::from(tcp).into(), caps),
Protocol::Tls => (tls::Stream::connect(tcp, host, clt)?.into(), caps),
}
}
};
if file.isatty() {
caps &= !(FileCaps::TELL | FileCaps::SEEK);
}
ctx.insert_file(fd.try_into().unwrap(), file, caps);
}
Ok(Loader(Connected {
wstore: self.0.wstore,
linker: self.0.linker,
}))
}
}