Browse Source

move existing wasi-common sockets proposal interfaces to wasmtime-wasi-sockets

pull/6391/head
Pat Hickey 2 years ago
parent
commit
493aa23d67
  1. 25
      wasi-common/src/network.rs
  2. 54
      wasi-common/src/preview2/ip_name_lookup.rs
  3. 87
      wasi-common/src/preview2/network.rs
  4. 322
      wasi-common/src/preview2/tcp.rs
  5. 160
      wasi-common/src/preview2/udp.rs
  6. 68
      wasi-common/src/tcp_socket.rs
  7. 51
      wasi-common/src/udp_socket.rs

25
wasi-common/src/network.rs

@ -1,25 +0,0 @@
//! IP Networks.
use crate::Error;
use std::any::Any;
/// An IP network.
#[async_trait::async_trait]
pub trait WasiNetwork: Send + Sync {
fn as_any(&self) -> &dyn Any;
fn pool(&self) -> &cap_std::net::Pool;
}
pub trait TableNetworkExt {
fn get_network(&self, fd: u32) -> Result<&dyn WasiNetwork, Error>;
fn get_network_mut(&mut self, fd: u32) -> Result<&mut Box<dyn WasiNetwork>, Error>;
}
impl TableNetworkExt for crate::table::Table {
fn get_network(&self, fd: u32) -> Result<&dyn WasiNetwork, Error> {
self.get::<Box<dyn WasiNetwork>>(fd).map(|f| f.as_ref())
}
fn get_network_mut(&mut self, fd: u32) -> Result<&mut Box<dyn WasiNetwork>, Error> {
self.get_mut::<Box<dyn WasiNetwork>>(fd)
}
}

54
wasi-common/src/preview2/ip_name_lookup.rs

@ -1,54 +0,0 @@
#![allow(unused_variables)]
use crate::{
wasi::ip_name_lookup::{self, ResolveAddressStream},
wasi::network::{Error, IpAddress, IpAddressFamily, Network},
wasi::poll::Pollable,
WasiCtx,
};
#[async_trait::async_trait]
impl ip_name_lookup::Host for WasiCtx {
async fn resolve_addresses(
&mut self,
network: Network,
name: String,
address_family: Option<IpAddressFamily>,
include_unavailable: bool,
) -> anyhow::Result<Result<ResolveAddressStream, Error>> {
todo!()
}
async fn resolve_next_address(
&mut self,
stream: ResolveAddressStream,
) -> anyhow::Result<Result<Option<IpAddress>, Error>> {
todo!()
}
async fn drop_resolve_address_stream(
&mut self,
stream: ResolveAddressStream,
) -> anyhow::Result<()> {
todo!()
}
async fn non_blocking(
&mut self,
stream: ResolveAddressStream,
) -> anyhow::Result<Result<bool, Error>> {
todo!()
}
async fn set_non_blocking(
&mut self,
stream: ResolveAddressStream,
value: bool,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn subscribe(&mut self, stream: ResolveAddressStream) -> anyhow::Result<Pollable> {
todo!()
}
}

87
wasi-common/src/preview2/network.rs

@ -1,87 +0,0 @@
use crate::{
wasi::instance_network,
wasi::network::{self, Network},
WasiCtx, WasiNetwork,
};
use cap_std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
pub(crate) fn convert(_error: crate::Error) -> anyhow::Error {
todo!("convert wasi-common Error to wasi_network::Error")
}
#[async_trait::async_trait]
impl network::Host for WasiCtx {
async fn drop_network(&mut self, this: Network) -> anyhow::Result<()> {
let table = self.table_mut();
if !table.delete::<Box<dyn WasiNetwork>>(this).is_ok() {
anyhow::bail!("{this} is not a network");
}
Ok(())
}
}
#[async_trait::async_trait]
impl instance_network::Host for WasiCtx {
async fn instance_network(&mut self) -> anyhow::Result<Network> {
let network = (self.network_creator)(self.pool.clone())?;
let table = self.table_mut();
let network = table.push(Box::new(network)).map_err(convert)?;
Ok(network)
}
}
impl From<SocketAddr> for network::IpSocketAddress {
fn from(addr: SocketAddr) -> Self {
match addr {
SocketAddr::V4(v4) => Self::Ipv4(v4.into()),
SocketAddr::V6(v6) => Self::Ipv6(v6.into()),
}
}
}
impl From<SocketAddrV4> for network::Ipv4SocketAddress {
fn from(addr: SocketAddrV4) -> Self {
Self {
address: MyIpv4Addr::from(addr.ip()).0,
port: addr.port(),
}
}
}
impl From<SocketAddrV6> for network::Ipv6SocketAddress {
fn from(addr: SocketAddrV6) -> Self {
Self {
address: MyIpv6Addr::from(addr.ip()).0,
port: addr.port(),
flow_info: addr.flowinfo(),
scope_id: addr.scope_id(),
}
}
}
// Newtypes to guide conversions.
struct MyIpv4Addr((u8, u8, u8, u8));
struct MyIpv6Addr((u16, u16, u16, u16, u16, u16, u16, u16));
impl From<&Ipv4Addr> for MyIpv4Addr {
fn from(addr: &Ipv4Addr) -> Self {
let octets = addr.octets();
Self((octets[0], octets[1], octets[2], octets[3]))
}
}
impl From<&Ipv6Addr> for MyIpv6Addr {
fn from(addr: &Ipv6Addr) -> Self {
let segments = addr.segments();
Self((
segments[0],
segments[1],
segments[2],
segments[3],
segments[4],
segments[5],
segments[6],
segments[7],
))
}
}

322
wasi-common/src/preview2/tcp.rs

@ -1,322 +0,0 @@
#![allow(unused_variables)]
use crate::{
network::TableNetworkExt,
preview2::network::convert,
preview2::poll::PollableEntry,
tcp_socket::TableTcpSocketExt,
wasi::network::{
Error, IpAddressFamily, Ipv4Address, Ipv4SocketAddress, Ipv6Address, Ipv6SocketAddress,
Network,
},
wasi::poll::Pollable,
wasi::streams::{InputStream, OutputStream},
wasi::tcp::{self, IpSocketAddress, ShutdownType, TcpSocket},
wasi::tcp_create_socket,
WasiCtx, WasiTcpSocket,
};
use cap_net_ext::AddressFamily;
use cap_std::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
#[async_trait::async_trait]
impl tcp::Host for WasiCtx {
async fn listen(
&mut self,
socket: TcpSocket,
network: Network,
) -> anyhow::Result<Result<(), Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(socket)?;
let network = table.get_network(network)?;
socket.listen(network).await?;
Ok(Ok(()))
}
async fn accept(
&mut self,
socket: TcpSocket,
) -> anyhow::Result<Result<(TcpSocket, InputStream, OutputStream), Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(socket)?;
let (connection, input_stream, output_stream, _addr) = socket.accept(false).await?;
let connection = table.push(Box::new(connection)).map_err(convert)?;
let input_stream = table.push(Box::new(input_stream)).map_err(convert)?;
let output_stream = table.push(Box::new(output_stream)).map_err(convert)?;
Ok(Ok((connection, input_stream, output_stream)))
}
async fn connect(
&mut self,
socket: TcpSocket,
network: Network,
remote_address: IpSocketAddress,
) -> anyhow::Result<Result<(InputStream, OutputStream), Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(socket)?;
let network = table.get_network(network)?;
let (input_stream, output_stream) = socket.connect(network, remote_address.into()).await?;
let input_stream = table.push(Box::new(input_stream)).map_err(convert)?;
let output_stream = table.push(Box::new(output_stream)).map_err(convert)?;
Ok(Ok((input_stream, output_stream)))
}
async fn receive_buffer_size(
&mut self,
socket: TcpSocket,
) -> anyhow::Result<Result<u64, Error>> {
todo!()
}
async fn set_receive_buffer_size(
&mut self,
socket: TcpSocket,
value: u64,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn send_buffer_size(&mut self, socket: TcpSocket) -> anyhow::Result<Result<u64, Error>> {
todo!()
}
async fn set_send_buffer_size(
&mut self,
socket: TcpSocket,
value: u64,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn bind(
&mut self,
this: TcpSocket,
network: Network,
local_address: IpSocketAddress,
) -> anyhow::Result<Result<(), Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(this)?;
let network = table.get_network(network)?;
socket.bind(network, local_address.into()).await?;
Ok(Ok(()))
}
async fn shutdown(
&mut self,
this: TcpSocket,
shutdown_type: ShutdownType,
) -> anyhow::Result<Result<(), Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(this)?;
let how = match shutdown_type {
ShutdownType::Receive => Shutdown::Read,
ShutdownType::Send => Shutdown::Write,
ShutdownType::Both => Shutdown::Both,
};
let addr = socket.shutdown(how).await?;
Ok(Ok(()))
}
async fn local_address(
&mut self,
this: TcpSocket,
) -> anyhow::Result<Result<IpSocketAddress, Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(this)?;
let addr = socket.local_address()?;
Ok(Ok(addr.into()))
}
async fn remote_address(
&mut self,
this: TcpSocket,
) -> anyhow::Result<Result<IpSocketAddress, Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(this)?;
let addr = socket.remote_address()?;
Ok(Ok(addr.into()))
}
async fn keep_alive(&mut self, this: TcpSocket) -> anyhow::Result<Result<bool, Error>> {
todo!()
}
async fn set_keep_alive(
&mut self,
this: TcpSocket,
value: bool,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn no_delay(&mut self, this: TcpSocket) -> anyhow::Result<Result<bool, Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(this)?;
let value = socket.nodelay()?;
Ok(Ok(value))
}
async fn set_no_delay(
&mut self,
this: TcpSocket,
value: bool,
) -> anyhow::Result<Result<(), Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(this)?;
socket.set_nodelay(value)?;
Ok(Ok(()))
}
async fn address_family(
&mut self,
this: TcpSocket,
) -> anyhow::Result<Result<IpAddressFamily, Error>> {
todo!()
}
async fn unicast_hop_limit(&mut self, this: TcpSocket) -> anyhow::Result<Result<u8, Error>> {
todo!()
}
async fn set_unicast_hop_limit(
&mut self,
this: TcpSocket,
value: u8,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn set_listen_backlog_size(
&mut self,
this: TcpSocket,
value: u64,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn ipv6_only(&mut self, this: TcpSocket) -> anyhow::Result<Result<bool, Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(this)?;
let value = socket.v6_only()?;
Ok(Ok(value))
}
async fn set_ipv6_only(
&mut self,
this: TcpSocket,
value: bool,
) -> anyhow::Result<Result<(), Error>> {
let table = self.table_mut();
let socket = table.get_tcp_socket(this)?;
socket.set_v6_only(value)?;
Ok(Ok(()))
}
async fn non_blocking(&mut self, this: TcpSocket) -> anyhow::Result<Result<bool, Error>> {
todo!()
}
async fn set_non_blocking(
&mut self,
this: TcpSocket,
value: bool,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn subscribe(&mut self, this: TcpSocket) -> anyhow::Result<Pollable> {
Ok(self
.table_mut()
.push(Box::new(PollableEntry::TcpSocket(this)))?)
}
async fn drop_tcp_socket(&mut self, this: TcpSocket) -> anyhow::Result<()> {
let table = self.table_mut();
if !table.delete::<Box<dyn WasiTcpSocket>>(this).is_ok() {
anyhow::bail!("{this} is not a socket");
}
Ok(())
}
}
#[async_trait::async_trait]
impl tcp_create_socket::Host for WasiCtx {
async fn create_tcp_socket(
&mut self,
address_family: IpAddressFamily,
) -> anyhow::Result<Result<TcpSocket, Error>> {
let socket = (self.tcp_socket_creator)(address_family.into())?;
let table = self.table_mut();
let socket = table.push(Box::new(socket)).map_err(convert)?;
Ok(Ok(socket))
}
}
impl From<IpSocketAddress> for SocketAddr {
fn from(addr: IpSocketAddress) -> Self {
match addr {
IpSocketAddress::Ipv4(v4) => SocketAddr::V4(v4.into()),
IpSocketAddress::Ipv6(v6) => SocketAddr::V6(v6.into()),
}
}
}
impl From<Ipv4SocketAddress> for SocketAddrV4 {
fn from(addr: Ipv4SocketAddress) -> Self {
SocketAddrV4::new(convert_ipv4_addr(addr.address), addr.port)
}
}
impl From<Ipv6SocketAddress> for SocketAddrV6 {
fn from(addr: Ipv6SocketAddress) -> Self {
SocketAddrV6::new(
convert_ipv6_addr(addr.address),
addr.port,
addr.flow_info,
addr.scope_id,
)
}
}
fn convert_ipv4_addr(addr: Ipv4Address) -> Ipv4Addr {
Ipv4Addr::new(addr.0, addr.1, addr.2, addr.3)
}
fn convert_ipv6_addr(addr: Ipv6Address) -> Ipv6Addr {
Ipv6Addr::new(
addr.0, addr.1, addr.2, addr.3, addr.4, addr.5, addr.6, addr.7,
)
}
impl From<IpAddressFamily> for AddressFamily {
fn from(family: IpAddressFamily) -> Self {
match family {
IpAddressFamily::Ipv4 => AddressFamily::Ipv4,
IpAddressFamily::Ipv6 => AddressFamily::Ipv6,
}
}
}

160
wasi-common/src/preview2/udp.rs

@ -1,160 +0,0 @@
#![allow(unused_variables)]
use crate::{
udp_socket::TableUdpSocketExt,
wasi::network::{Error, IpAddressFamily, Network},
wasi::poll::Pollable,
wasi::udp::{self, Datagram, IpSocketAddress, UdpSocket},
wasi::udp_create_socket,
WasiCtx,
};
#[async_trait::async_trait]
impl udp::Host for WasiCtx {
async fn connect(
&mut self,
udp_socket: UdpSocket,
network: Network,
remote_address: IpSocketAddress,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn send(
&mut self,
socket: UdpSocket,
datagram: Datagram,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn receive(&mut self, socket: UdpSocket) -> anyhow::Result<Result<Datagram, Error>> {
todo!()
}
async fn receive_buffer_size(
&mut self,
socket: UdpSocket,
) -> anyhow::Result<Result<u64, Error>> {
todo!()
}
async fn set_receive_buffer_size(
&mut self,
socket: UdpSocket,
value: u64,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn send_buffer_size(&mut self, socket: UdpSocket) -> anyhow::Result<Result<u64, Error>> {
todo!()
}
async fn set_send_buffer_size(
&mut self,
socket: UdpSocket,
value: u64,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn bind(
&mut self,
this: UdpSocket,
network: Network,
local_address: IpSocketAddress,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn local_address(
&mut self,
this: UdpSocket,
) -> anyhow::Result<Result<IpSocketAddress, Error>> {
todo!()
}
async fn remote_address(
&mut self,
this: UdpSocket,
) -> anyhow::Result<Result<IpSocketAddress, Error>> {
todo!()
}
async fn address_family(
&mut self,
this: UdpSocket,
) -> anyhow::Result<Result<IpAddressFamily, Error>> {
todo!()
}
async fn unicast_hop_limit(&mut self, this: UdpSocket) -> anyhow::Result<Result<u8, Error>> {
todo!()
}
async fn set_unicast_hop_limit(
&mut self,
this: UdpSocket,
value: u8,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn ipv6_only(&mut self, this: UdpSocket) -> anyhow::Result<Result<bool, Error>> {
todo!()
}
async fn set_ipv6_only(
&mut self,
this: UdpSocket,
value: bool,
) -> anyhow::Result<Result<(), Error>> {
todo!()
}
async fn non_blocking(&mut self, this: UdpSocket) -> anyhow::Result<Result<bool, Error>> {
todo!()
}
async fn set_non_blocking(
&mut self,
this: UdpSocket,
value: bool,
) -> anyhow::Result<Result<(), Error>> {
let this = self.table.get_udp_socket_mut(this)?;
this.set_nonblocking(value)?;
Ok(Ok(()))
}
async fn subscribe(&mut self, this: UdpSocket) -> anyhow::Result<Pollable> {
todo!()
}
/* TODO: Revisit after https://github.com/WebAssembly/wasi-sockets/issues/17
async fn bytes_readable(&mut self, socket: UdpSocket) -> anyhow::Result<Result<(u64, bool), Error>> {
drop(socket);
todo!()
}
async fn bytes_writable(&mut self, socket: UdpSocket) -> anyhow::Result<Result<(u64, bool), Error>> {
drop(socket);
todo!()
}
*/
async fn drop_udp_socket(&mut self, socket: UdpSocket) -> anyhow::Result<()> {
drop(socket);
todo!()
}
}
#[async_trait::async_trait]
impl udp_create_socket::Host for WasiCtx {
async fn create_udp_socket(
&mut self,
address_family: IpAddressFamily,
) -> anyhow::Result<Result<UdpSocket, Error>> {
todo!()
}
}

68
wasi-common/src/tcp_socket.rs

@ -1,68 +0,0 @@
//! TCP sockets.
use crate::Error;
use crate::{InputStream, OutputStream, WasiNetwork};
use cap_std::net::{Shutdown, SocketAddr};
use std::any::Any;
/// A TCP socket.
#[async_trait::async_trait]
pub trait WasiTcpSocket: Send + Sync {
fn as_any(&self) -> &dyn Any;
/// Return the host file descriptor so that it can be polled with a host poll.
fn pollable(&self) -> rustix::fd::BorrowedFd;
async fn listen(&self, network: &dyn WasiNetwork) -> Result<(), Error>;
async fn accept(
&self,
nonblocking: bool,
) -> Result<
(
Box<dyn WasiTcpSocket>,
Box<dyn InputStream>,
Box<dyn OutputStream>,
SocketAddr,
),
Error,
>;
async fn connect(
&self,
network: &dyn WasiNetwork,
remote_address: SocketAddr,
) -> Result<(Box<dyn InputStream>, Box<dyn OutputStream>), Error>;
async fn bind(&self, network: &dyn WasiNetwork, local_address: SocketAddr)
-> Result<(), Error>;
async fn shutdown(&self, how: Shutdown) -> Result<(), Error>;
fn local_address(&self) -> Result<SocketAddr, Error>;
fn remote_address(&self) -> Result<SocketAddr, Error>;
fn nodelay(&self) -> Result<bool, Error>;
fn set_nodelay(&self, value: bool) -> Result<(), Error>;
fn v6_only(&self) -> Result<bool, Error>;
fn set_v6_only(&self, value: bool) -> Result<(), Error>;
fn set_nonblocking(&mut self, flag: bool) -> Result<(), Error>;
async fn readable(&self) -> Result<(), Error>;
async fn writable(&self) -> Result<(), Error>;
}
pub trait TableTcpSocketExt {
fn get_tcp_socket(&self, fd: u32) -> Result<&dyn WasiTcpSocket, Error>;
fn get_tcp_socket_mut(&mut self, fd: u32) -> Result<&mut Box<dyn WasiTcpSocket>, Error>;
}
impl TableTcpSocketExt for crate::table::Table {
fn get_tcp_socket(&self, fd: u32) -> Result<&dyn WasiTcpSocket, Error> {
self.get::<Box<dyn WasiTcpSocket>>(fd).map(|f| f.as_ref())
}
fn get_tcp_socket_mut(&mut self, fd: u32) -> Result<&mut Box<dyn WasiTcpSocket>, Error> {
self.get_mut::<Box<dyn WasiTcpSocket>>(fd)
}
}

51
wasi-common/src/udp_socket.rs

@ -1,51 +0,0 @@
//! UDP sockets.
use crate::Error;
use bitflags::bitflags;
use std::any::Any;
/// A UDP socket.
#[async_trait::async_trait]
pub trait WasiUdpSocket: Send + Sync {
fn as_any(&self) -> &dyn Any;
async fn sock_recv<'a>(
&mut self,
ri_data: &mut [std::io::IoSliceMut<'a>],
ri_flags: RiFlags,
) -> Result<(u64, RoFlags), Error>;
async fn sock_send<'a>(&mut self, si_data: &[std::io::IoSlice<'a>]) -> Result<u64, Error>;
fn set_nonblocking(&mut self, flag: bool) -> Result<(), Error>;
async fn readable(&self) -> Result<(), Error>;
async fn writable(&self) -> Result<(), Error>;
}
bitflags! {
pub struct RoFlags: u32 {
const RECV_DATA_TRUNCATED = 0b1;
}
}
bitflags! {
pub struct RiFlags: u32 {
const RECV_PEEK = 0b1;
const RECV_WAITALL = 0b10;
}
}
pub trait TableUdpSocketExt {
fn get_udp_socket(&self, fd: u32) -> Result<&dyn WasiUdpSocket, Error>;
fn get_udp_socket_mut(&mut self, fd: u32) -> Result<&mut Box<dyn WasiUdpSocket>, Error>;
}
impl TableUdpSocketExt for crate::table::Table {
fn get_udp_socket(&self, fd: u32) -> Result<&dyn WasiUdpSocket, Error> {
self.get::<Box<dyn WasiUdpSocket>>(fd).map(|f| f.as_ref())
}
fn get_udp_socket_mut(&mut self, fd: u32) -> Result<&mut Box<dyn WasiUdpSocket>, Error> {
self.get_mut::<Box<dyn WasiUdpSocket>>(fd)
}
}
Loading…
Cancel
Save