1use crate::host::network::util;
2use crate::runtime::with_ambient_tokio_runtime;
3use async_trait::async_trait;
4use cap_net_ext::{AddressFamily, Blocking};
5use io_lifetimes::raw::{FromRawSocketlike, IntoRawSocketlike};
6use std::io;
7use std::net::SocketAddr;
8use std::sync::Arc;
9use wasmtime_wasi_io::poll::Pollable;
10
11use super::network::{SocketAddrCheck, SocketAddressFamily};
12
13pub(crate) enum UdpState {
18 Default,
20
21 BindStarted,
23
24 Bound,
27
28 Connected,
30}
31
32pub struct UdpSocket {
37 pub(crate) inner: Arc<tokio::net::UdpSocket>,
40
41 pub(crate) udp_state: UdpState,
43
44 pub(crate) family: SocketAddressFamily,
46
47 pub(crate) socket_addr_check: Option<SocketAddrCheck>,
49}
50
51#[async_trait]
52impl Pollable for UdpSocket {
53 async fn ready(&mut self) {
54 }
56}
57
58impl UdpSocket {
59 pub fn new(family: AddressFamily) -> io::Result<Self> {
61 let fd = util::udp_socket(family, Blocking::No)?;
64
65 let socket_address_family = match family {
66 AddressFamily::Ipv4 => SocketAddressFamily::Ipv4,
67 AddressFamily::Ipv6 => {
68 rustix::net::sockopt::set_ipv6_v6only(&fd, true)?;
69 SocketAddressFamily::Ipv6
70 }
71 };
72
73 let socket = Self::setup_tokio_udp_socket(fd)?;
74
75 Ok(UdpSocket {
76 inner: Arc::new(socket),
77 udp_state: UdpState::Default,
78 family: socket_address_family,
79 socket_addr_check: None,
80 })
81 }
82
83 fn setup_tokio_udp_socket(fd: rustix::fd::OwnedFd) -> io::Result<tokio::net::UdpSocket> {
84 let std_socket =
85 unsafe { std::net::UdpSocket::from_raw_socketlike(fd.into_raw_socketlike()) };
86 with_ambient_tokio_runtime(|| tokio::net::UdpSocket::try_from(std_socket))
87 }
88
89 pub fn udp_socket(&self) -> &tokio::net::UdpSocket {
90 &self.inner
91 }
92}
93
94pub struct IncomingDatagramStream {
95 pub(crate) inner: Arc<tokio::net::UdpSocket>,
96
97 pub(crate) remote_address: Option<SocketAddr>,
99}
100
101pub struct OutgoingDatagramStream {
102 pub(crate) inner: Arc<tokio::net::UdpSocket>,
103
104 pub(crate) remote_address: Option<SocketAddr>,
106
107 pub(crate) family: SocketAddressFamily,
109
110 pub(crate) send_state: SendState,
111
112 pub(crate) socket_addr_check: Option<SocketAddrCheck>,
114}
115
116pub(crate) enum SendState {
117 Idle,
119
120 Permitted(usize),
122
123 Waiting,
125}