use crate::runtime::with_ambient_tokio_runtime;
use crate::sockets::util::udp_socket;
use crate::sockets::{SocketAddrCheck, SocketAddressFamily};
use async_trait::async_trait;
use cap_net_ext::AddressFamily;
use io_lifetimes::raw::{FromRawSocketlike, IntoRawSocketlike};
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
use wasmtime_wasi_io::poll::Pollable;
pub(crate) enum UdpState {
Default,
BindStarted,
Bound,
Connected,
}
pub struct UdpSocket {
pub(crate) inner: Arc<tokio::net::UdpSocket>,
pub(crate) udp_state: UdpState,
pub(crate) family: SocketAddressFamily,
pub(crate) socket_addr_check: Option<SocketAddrCheck>,
}
#[async_trait]
impl Pollable for UdpSocket {
async fn ready(&mut self) {
}
}
impl UdpSocket {
pub fn new(family: AddressFamily) -> io::Result<Self> {
let fd = udp_socket(family)?;
let socket_address_family = match family {
AddressFamily::Ipv4 => SocketAddressFamily::Ipv4,
AddressFamily::Ipv6 => {
rustix::net::sockopt::set_ipv6_v6only(&fd, true)?;
SocketAddressFamily::Ipv6
}
};
let socket = Self::setup_tokio_udp_socket(fd.into())?;
Ok(UdpSocket {
inner: Arc::new(socket),
udp_state: UdpState::Default,
family: socket_address_family,
socket_addr_check: None,
})
}
fn setup_tokio_udp_socket(fd: rustix::fd::OwnedFd) -> io::Result<tokio::net::UdpSocket> {
let std_socket =
unsafe { std::net::UdpSocket::from_raw_socketlike(fd.into_raw_socketlike()) };
with_ambient_tokio_runtime(|| tokio::net::UdpSocket::try_from(std_socket))
}
pub fn udp_socket(&self) -> &tokio::net::UdpSocket {
&self.inner
}
}
pub struct IncomingDatagramStream {
pub(crate) inner: Arc<tokio::net::UdpSocket>,
pub(crate) remote_address: Option<SocketAddr>,
}
pub struct OutgoingDatagramStream {
pub(crate) inner: Arc<tokio::net::UdpSocket>,
pub(crate) remote_address: Option<SocketAddr>,
pub(crate) family: SocketAddressFamily,
pub(crate) send_state: SendState,
pub(crate) socket_addr_check: Option<SocketAddrCheck>,
}
pub(crate) enum SendState {
Idle,
Permitted(usize),
Waiting,
}