use crate::network::SocketAddrUse;
use crate::{
bindings::{
io::streams::{InputStream, OutputStream},
sockets::network::{IpAddressFamily, IpSocketAddress, Network},
sockets::tcp::{self, ShutdownType},
},
network::SocketAddressFamily,
};
use crate::{Pollable, SocketResult, WasiView};
use std::net::SocketAddr;
use std::time::Duration;
use wasmtime::component::Resource;
impl<T: WasiView> tcp::Host for T {}
impl<T: WasiView> crate::host::tcp::tcp::HostTcpSocket for T {
fn start_bind(
&mut self,
this: Resource<tcp::TcpSocket>,
network: Resource<Network>,
local_address: IpSocketAddress,
) -> SocketResult<()> {
self.ctx().allowed_network_uses.check_allowed_tcp()?;
let table = self.table();
let network = table.get(&network)?;
let local_address: SocketAddr = local_address.into();
network.check_socket_addr(&local_address, SocketAddrUse::TcpBind)?;
table.get_mut(&this)?.start_bind(local_address)?;
Ok(())
}
fn finish_bind(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<()> {
let table = self.table();
let socket = table.get_mut(&this)?;
socket.finish_bind()
}
fn start_connect(
&mut self,
this: Resource<tcp::TcpSocket>,
network: Resource<Network>,
remote_address: IpSocketAddress,
) -> SocketResult<()> {
self.ctx().allowed_network_uses.check_allowed_tcp()?;
let table = self.table();
let network = table.get(&network)?;
let remote_address: SocketAddr = remote_address.into();
network.check_socket_addr(&remote_address, SocketAddrUse::TcpConnect)?;
table.get_mut(&this)?.start_connect(remote_address)?;
Ok(())
}
fn finish_connect(
&mut self,
this: Resource<tcp::TcpSocket>,
) -> SocketResult<(Resource<InputStream>, Resource<OutputStream>)> {
let table = self.table();
let socket = table.get_mut(&this)?;
let (input, output) = socket.finish_connect()?;
let input_stream = self.table().push_child(input, &this)?;
let output_stream = self.table().push_child(output, &this)?;
Ok((input_stream, output_stream))
}
fn start_listen(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<()> {
self.ctx().allowed_network_uses.check_allowed_tcp()?;
let table = self.table();
let socket = table.get_mut(&this)?;
socket.start_listen()
}
fn finish_listen(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<()> {
let table = self.table();
let socket = table.get_mut(&this)?;
socket.finish_listen()
}
fn accept(
&mut self,
this: Resource<tcp::TcpSocket>,
) -> SocketResult<(
Resource<tcp::TcpSocket>,
Resource<InputStream>,
Resource<OutputStream>,
)> {
self.ctx().allowed_network_uses.check_allowed_tcp()?;
let table = self.table();
let socket = table.get_mut(&this)?;
let (tcp_socket, input, output) = socket.accept()?;
let tcp_socket = self.table().push(tcp_socket)?;
let input_stream = self.table().push_child(input, &tcp_socket)?;
let output_stream = self.table().push_child(output, &tcp_socket)?;
Ok((tcp_socket, input_stream, output_stream))
}
fn local_address(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<IpSocketAddress> {
let table = self.table();
let socket = table.get(&this)?;
socket.local_address().map(Into::into)
}
fn remote_address(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<IpSocketAddress> {
let table = self.table();
let socket = table.get(&this)?;
socket.remote_address().map(Into::into)
}
fn is_listening(&mut self, this: Resource<tcp::TcpSocket>) -> Result<bool, anyhow::Error> {
let table = self.table();
let socket = table.get(&this)?;
Ok(socket.is_listening())
}
fn address_family(
&mut self,
this: Resource<tcp::TcpSocket>,
) -> Result<IpAddressFamily, anyhow::Error> {
let table = self.table();
let socket = table.get(&this)?;
match socket.address_family() {
SocketAddressFamily::Ipv4 => Ok(IpAddressFamily::Ipv4),
SocketAddressFamily::Ipv6 => Ok(IpAddressFamily::Ipv6),
}
}
fn set_listen_backlog_size(
&mut self,
this: Resource<tcp::TcpSocket>,
value: u64,
) -> SocketResult<()> {
let table = self.table();
let socket = table.get_mut(&this)?;
let value = value.try_into().unwrap_or(u32::MAX);
socket.set_listen_backlog_size(value)
}
fn keep_alive_enabled(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<bool> {
let table = self.table();
let socket = table.get(&this)?;
socket.keep_alive_enabled()
}
fn set_keep_alive_enabled(
&mut self,
this: Resource<tcp::TcpSocket>,
value: bool,
) -> SocketResult<()> {
let table = self.table();
let socket = table.get(&this)?;
socket.set_keep_alive_enabled(value)
}
fn keep_alive_idle_time(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<u64> {
let table = self.table();
let socket = table.get(&this)?;
Ok(socket.keep_alive_idle_time()?.as_nanos() as u64)
}
fn set_keep_alive_idle_time(
&mut self,
this: Resource<tcp::TcpSocket>,
value: u64,
) -> SocketResult<()> {
let table = self.table();
let socket = table.get_mut(&this)?;
let duration = Duration::from_nanos(value);
socket.set_keep_alive_idle_time(duration)
}
fn keep_alive_interval(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<u64> {
let table = self.table();
let socket = table.get(&this)?;
Ok(socket.keep_alive_interval()?.as_nanos() as u64)
}
fn set_keep_alive_interval(
&mut self,
this: Resource<tcp::TcpSocket>,
value: u64,
) -> SocketResult<()> {
let table = self.table();
let socket = table.get(&this)?;
socket.set_keep_alive_interval(Duration::from_nanos(value))
}
fn keep_alive_count(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<u32> {
let table = self.table();
let socket = table.get(&this)?;
socket.keep_alive_count()
}
fn set_keep_alive_count(
&mut self,
this: Resource<tcp::TcpSocket>,
value: u32,
) -> SocketResult<()> {
let table = self.table();
let socket = table.get(&this)?;
socket.set_keep_alive_count(value)
}
fn hop_limit(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<u8> {
let table = self.table();
let socket = table.get(&this)?;
socket.hop_limit()
}
fn set_hop_limit(&mut self, this: Resource<tcp::TcpSocket>, value: u8) -> SocketResult<()> {
let table = self.table();
let socket = table.get_mut(&this)?;
socket.set_hop_limit(value)
}
fn receive_buffer_size(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<u64> {
let table = self.table();
let socket = table.get(&this)?;
Ok(socket.receive_buffer_size()? as u64)
}
fn set_receive_buffer_size(
&mut self,
this: Resource<tcp::TcpSocket>,
value: u64,
) -> SocketResult<()> {
let table = self.table();
let socket = table.get_mut(&this)?;
let value = value.try_into().unwrap_or(usize::MAX);
socket.set_receive_buffer_size(value)
}
fn send_buffer_size(&mut self, this: Resource<tcp::TcpSocket>) -> SocketResult<u64> {
let table = self.table();
let socket = table.get(&this)?;
Ok(socket.send_buffer_size()? as u64)
}
fn set_send_buffer_size(
&mut self,
this: Resource<tcp::TcpSocket>,
value: u64,
) -> SocketResult<()> {
let table = self.table();
let socket = table.get_mut(&this)?;
let value = value.try_into().unwrap_or(usize::MAX);
socket.set_send_buffer_size(value)
}
fn subscribe(&mut self, this: Resource<tcp::TcpSocket>) -> anyhow::Result<Resource<Pollable>> {
crate::poll::subscribe(self.table(), this)
}
fn shutdown(
&mut self,
this: Resource<tcp::TcpSocket>,
shutdown_type: ShutdownType,
) -> SocketResult<()> {
let table = self.table();
let socket = table.get(&this)?;
let how = match shutdown_type {
ShutdownType::Receive => std::net::Shutdown::Read,
ShutdownType::Send => std::net::Shutdown::Write,
ShutdownType::Both => std::net::Shutdown::Both,
};
Ok(socket.shutdown(how)?)
}
fn drop(&mut self, this: Resource<tcp::TcpSocket>) -> Result<(), anyhow::Error> {
let table = self.table();
let dropped = table.delete(this)?;
drop(dropped);
Ok(())
}
}