pub use crate::fs::FsOutput;
use crate::{
BufLease, BufferPool, Config, Error, Handle, Integration, OpId, Open, ReadBuf, Result,
WriteBuf, WriteVectored,
};
use std::{net::SocketAddr, sync::Arc, time::Duration};
pub trait Wake: Send + Sync + 'static {
fn wake(&self) -> Result<()>;
fn syscall_count(&self) -> u64;
}
#[derive(Debug)]
pub struct Request {
pub op: OpId,
pub handle: Handle,
pub operation: Operation,
}
#[derive(Debug)]
pub enum Operation {
ProcessExit,
WatchSignal,
SendHandle(Handle),
RecvHandle,
Connect,
Accept {
multishot: bool,
},
Read {
buf: ReadBuf,
multishot: bool,
},
Write(WriteBuf),
Writev(WriteVectored),
SendTo {
buf: WriteBuf,
to: SocketAddr,
},
RecvFrom(ReadBuf),
Shutdown,
WatchFs,
}
#[derive(Debug)]
pub struct Event<D> {
pub op: OpId,
pub terminal: bool,
pub result: std::result::Result<Outcome<D>, Error>,
}
#[derive(Debug)]
pub enum Outcome<D> {
Resolved(Vec<SocketAddr>),
Exited(crate::ExitStatus),
Signal(crate::Signal),
PipeAccepted(D),
HandleReceived(D),
HandleSent,
Connected,
Accepted {
transport: D,
peer: SocketAddr,
},
Read {
n: usize,
lease: Option<BufLease>,
},
Eof,
Wrote(usize),
RecvFrom {
n: usize,
from: SocketAddr,
lease: Option<BufLease>,
},
Shutdown,
Watch {
events: BufLease,
overflow: bool,
},
Fs {
output: FsOutput,
lease: Option<BufLease>,
},
Cancelled,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Filesystem {
Pool,
Backend,
Unsupported,
}
#[derive(Clone, Copy, Debug, Default)]
pub struct PollInfo {
pub waits: u32,
pub discovery_polls: u32,
pub zero_event_waits: u32,
}
#[cfg(any(
turnloop_backend = "epoll",
turnloop_backend = "kqueue",
turnloop_backend = "iocp",
turnloop_backend = "wasi_p2",
all(turnloop_backend = "wasi_p3", feature = "wasi-p3-experimental")
))]
impl PollInfo {
pub(crate) fn native(timeout: Option<Duration>, empty: bool) -> Self {
let discovery = timeout == Some(Duration::ZERO);
Self {
waits: u32::from(!discovery),
discovery_polls: u32::from(discovery),
zero_event_waits: u32::from(empty),
}
}
}
pub unsafe trait Backend: Sized + 'static {
type Wake: Wake;
type Detached: Send + 'static;
const FILESYSTEM: Filesystem = if cfg!(target_arch = "wasm32") {
Filesystem::Unsupported
} else {
Filesystem::Pool
};
fn new(config: &Config, pool: BufferPool) -> Result<Self>;
fn fs(&mut self, _op: OpId, _handle: Option<Handle>, _request: crate::FsRequest) -> Result<()> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn fs_watch(
&mut self,
_handle: Handle,
_path: &crate::FsPath,
_options: crate::WatchOptions,
) -> Result<()> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn set_notifier(&mut self, _notifier: crate::Notifier) {}
fn spawn(
&mut self,
_handle: Handle,
_pipes: [Option<Handle>; 3],
_extra: &[Option<Handle>],
_spec: &crate::ProcessSpec,
) -> Result<u32> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn prepare_close(&mut self, _handle: Handle) -> Result<()> {
Ok(())
}
fn kill(&mut self, _handle: Handle, _signal: crate::Signal, _group: bool) -> Result<()> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn signal(&mut self, _handle: Handle, _signal: crate::Signal) -> Result<()> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn tty_set_mode(&mut self, _handle: Handle, _mode: crate::TtyMode) -> Result<()> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn set_option(&mut self, _handle: Handle, _option: crate::SocketOption) -> Result<()> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn get_option(
&self,
_handle: Handle,
_kind: crate::SocketOptionKind,
) -> Result<crate::SocketOption> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn raw_transport(&self, _handle: Handle) -> Result<crate::RawTransport> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn tty_window_size(&self, _handle: Handle) -> Result<crate::WindowSize> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn now(&self) -> crate::Instant;
fn validate_timeout(&self, _timeout: crate::Timeout) -> Result<()> {
Ok(())
}
fn deadline_changed(&mut self, _deadline: Option<crate::Instant>) {}
fn waker(&self) -> Arc<Self::Wake>;
fn open(&mut self, handle: Handle, spec: Open) -> Result<()>;
fn local_addr(&self, handle: Handle) -> Result<SocketAddr>;
fn submit(&mut self, request: Request) -> Result<()>;
fn resolve(&mut self, _op: OpId, _request: &crate::DnsRequest) -> Result<()> {
Err(Error::new(crate::ErrorKind::Unsupported))
}
fn cancel(&mut self, op: OpId) -> Result<()>;
fn has_work(&self) -> bool;
fn poll(
&mut self,
timeout: Option<Duration>,
events: &mut Vec<Event<Self::Detached>>,
) -> Result<PollInfo>;
fn release(&mut self, handle: Handle);
fn detach(&mut self, handle: Handle) -> Result<Self::Detached>;
fn attach(&mut self, handle: Handle, transport: Self::Detached) -> Result<()>;
fn integration(&mut self) -> Result<Integration>;
}
#[cfg(turnloop_backend = "epoll")]
mod epoll;
#[cfg(turnloop_backend = "kqueue")]
mod kqueue;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod poller;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod socket;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod sockopt;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
pub mod unix;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
pub use unix::Unix as Platform;
#[cfg(turnloop_backend = "iocp")]
pub mod iocp;
#[cfg(turnloop_backend = "iocp")]
pub use iocp::Iocp as Platform;
#[cfg(any(
turnloop_backend = "wasi_p2",
all(turnloop_backend = "wasi_p3", feature = "wasi-p3-experimental")
))]
mod wasi_fs;
#[cfg(turnloop_backend = "wasi_p2")]
pub mod wasi_p2;
#[cfg(turnloop_backend = "wasi_p2")]
pub use wasi_p2::WasiP2 as Platform;
#[cfg(turnloop_backend = "web")]
pub mod web;
#[cfg(turnloop_backend = "web")]
pub use web::Web as Platform;
#[cfg(all(turnloop_backend = "wasi_p3", feature = "wasi-p3-experimental"))]
pub mod wasi_p3;
#[cfg(all(turnloop_backend = "wasi_p3", feature = "wasi-p3-experimental"))]
pub use wasi_p3::WasiP3 as Platform;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod ipc;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod process;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod services;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod signals;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod files;
#[cfg(any(turnloop_backend = "kqueue", turnloop_backend = "epoll"))]
mod watch;