Skip to main content

wasmtime_wasi/p2/host/
network.rs

1use crate::p2::SocketError;
2use crate::p2::bindings::sockets::network::{
3    self, ErrorCode, IpAddress, IpSocketAddress, Ipv4SocketAddress, Ipv6SocketAddress,
4};
5use crate::sockets::WasiSocketsCtxView;
6use crate::sockets::util::{from_ipv4_addr, from_ipv6_addr, to_ipv4_addr, to_ipv6_addr};
7use rustix::io::Errno;
8use std::io;
9use wasmtime::Error;
10use wasmtime::component::Resource;
11
12impl network::Host for WasiSocketsCtxView<'_> {
13    fn convert_error_code(&mut self, error: SocketError) -> wasmtime::Result<ErrorCode> {
14        error.downcast()
15    }
16
17    fn network_error_code(&mut self, err: Resource<Error>) -> wasmtime::Result<Option<ErrorCode>> {
18        let err = self.table.get(&err)?;
19
20        if let Some(err) = err.downcast_ref::<std::io::Error>() {
21            return Ok(Some(ErrorCode::from(err)));
22        }
23
24        Ok(None)
25    }
26}
27
28impl crate::p2::bindings::sockets::network::HostNetwork for WasiSocketsCtxView<'_> {
29    fn drop(&mut self, this: Resource<network::Network>) -> Result<(), wasmtime::Error> {
30        self.table.delete(this)?;
31
32        Ok(())
33    }
34}
35
36impl From<io::Error> for ErrorCode {
37    fn from(value: io::Error) -> Self {
38        (&value).into()
39    }
40}
41
42impl From<&io::Error> for ErrorCode {
43    fn from(value: &io::Error) -> Self {
44        // Attempt the more detailed native error code first:
45        if let Some(errno) = Errno::from_io_error(value) {
46            return errno.into();
47        }
48
49        match value.kind() {
50            std::io::ErrorKind::AddrInUse => ErrorCode::AddressInUse,
51            std::io::ErrorKind::AddrNotAvailable => ErrorCode::AddressNotBindable,
52            std::io::ErrorKind::ConnectionAborted => ErrorCode::ConnectionAborted,
53            std::io::ErrorKind::ConnectionRefused => ErrorCode::ConnectionRefused,
54            std::io::ErrorKind::ConnectionReset => ErrorCode::ConnectionReset,
55            std::io::ErrorKind::Interrupted => ErrorCode::WouldBlock,
56            std::io::ErrorKind::InvalidInput => ErrorCode::InvalidArgument,
57            std::io::ErrorKind::NotConnected => ErrorCode::InvalidState,
58            std::io::ErrorKind::OutOfMemory => ErrorCode::OutOfMemory,
59            std::io::ErrorKind::PermissionDenied => ErrorCode::AccessDenied,
60            std::io::ErrorKind::TimedOut => ErrorCode::Timeout,
61            std::io::ErrorKind::Unsupported => ErrorCode::NotSupported,
62            std::io::ErrorKind::WouldBlock => ErrorCode::WouldBlock,
63
64            _ => {
65                tracing::debug!("unknown I/O error: {value}");
66                ErrorCode::Unknown
67            }
68        }
69    }
70}
71
72impl From<Errno> for ErrorCode {
73    fn from(value: Errno) -> Self {
74        (&value).into()
75    }
76}
77
78impl From<&Errno> for ErrorCode {
79    fn from(value: &Errno) -> Self {
80        match *value {
81            Errno::WOULDBLOCK => ErrorCode::WouldBlock,
82            #[allow(
83                unreachable_patterns,
84                reason = "EWOULDBLOCK and EAGAIN can have the same value"
85            )]
86            Errno::AGAIN => ErrorCode::WouldBlock,
87            Errno::INTR => ErrorCode::WouldBlock,
88            #[cfg(not(windows))]
89            Errno::PERM => ErrorCode::AccessDenied,
90            Errno::ACCESS => ErrorCode::AccessDenied,
91            Errno::ADDRINUSE => ErrorCode::AddressInUse,
92            Errno::ADDRNOTAVAIL => ErrorCode::AddressNotBindable,
93            Errno::ALREADY => ErrorCode::ConcurrencyConflict,
94            Errno::TIMEDOUT => ErrorCode::Timeout,
95            Errno::CONNREFUSED => ErrorCode::ConnectionRefused,
96            Errno::CONNRESET => ErrorCode::ConnectionReset,
97            Errno::CONNABORTED => ErrorCode::ConnectionAborted,
98            Errno::INVAL => ErrorCode::InvalidArgument,
99            Errno::HOSTUNREACH => ErrorCode::RemoteUnreachable,
100            Errno::HOSTDOWN => ErrorCode::RemoteUnreachable,
101            Errno::NETDOWN => ErrorCode::RemoteUnreachable,
102            Errno::NETUNREACH => ErrorCode::RemoteUnreachable,
103            #[cfg(target_os = "linux")]
104            Errno::NONET => ErrorCode::RemoteUnreachable,
105            Errno::ISCONN => ErrorCode::InvalidState,
106            Errno::NOTCONN => ErrorCode::InvalidState,
107            Errno::DESTADDRREQ => ErrorCode::InvalidState,
108            #[cfg(not(windows))]
109            Errno::NFILE => ErrorCode::NewSocketLimit,
110            Errno::MFILE => ErrorCode::NewSocketLimit,
111            Errno::MSGSIZE => ErrorCode::DatagramTooLarge,
112            #[cfg(not(windows))]
113            Errno::NOMEM => ErrorCode::OutOfMemory,
114            Errno::NOBUFS => ErrorCode::OutOfMemory,
115            Errno::OPNOTSUPP => ErrorCode::NotSupported,
116            Errno::NOPROTOOPT => ErrorCode::NotSupported,
117            Errno::PFNOSUPPORT => ErrorCode::NotSupported,
118            Errno::PROTONOSUPPORT => ErrorCode::NotSupported,
119            Errno::PROTOTYPE => ErrorCode::NotSupported,
120            Errno::SOCKTNOSUPPORT => ErrorCode::NotSupported,
121            Errno::AFNOSUPPORT => ErrorCode::NotSupported,
122
123            // FYI, EINPROGRESS should have already been handled by connect.
124            _ => {
125                tracing::debug!("unknown I/O error: {value}");
126                ErrorCode::Unknown
127            }
128        }
129    }
130}
131
132impl From<std::net::IpAddr> for IpAddress {
133    fn from(addr: std::net::IpAddr) -> Self {
134        match addr {
135            std::net::IpAddr::V4(v4) => Self::Ipv4(from_ipv4_addr(v4)),
136            std::net::IpAddr::V6(v6) => Self::Ipv6(from_ipv6_addr(v6)),
137        }
138    }
139}
140
141impl From<IpSocketAddress> for std::net::SocketAddr {
142    fn from(addr: IpSocketAddress) -> Self {
143        match addr {
144            IpSocketAddress::Ipv4(ipv4) => Self::V4(ipv4.into()),
145            IpSocketAddress::Ipv6(ipv6) => Self::V6(ipv6.into()),
146        }
147    }
148}
149
150impl From<std::net::SocketAddr> for IpSocketAddress {
151    fn from(addr: std::net::SocketAddr) -> Self {
152        match addr {
153            std::net::SocketAddr::V4(v4) => Self::Ipv4(v4.into()),
154            std::net::SocketAddr::V6(v6) => Self::Ipv6(v6.into()),
155        }
156    }
157}
158
159impl From<Ipv4SocketAddress> for std::net::SocketAddrV4 {
160    fn from(addr: Ipv4SocketAddress) -> Self {
161        Self::new(to_ipv4_addr(addr.address), addr.port)
162    }
163}
164
165impl From<std::net::SocketAddrV4> for Ipv4SocketAddress {
166    fn from(addr: std::net::SocketAddrV4) -> Self {
167        Self {
168            address: from_ipv4_addr(*addr.ip()),
169            port: addr.port(),
170        }
171    }
172}
173
174impl From<Ipv6SocketAddress> for std::net::SocketAddrV6 {
175    fn from(addr: Ipv6SocketAddress) -> Self {
176        Self::new(
177            to_ipv6_addr(addr.address),
178            addr.port,
179            addr.flow_info,
180            addr.scope_id,
181        )
182    }
183}
184
185impl From<std::net::SocketAddrV6> for Ipv6SocketAddress {
186    fn from(addr: std::net::SocketAddrV6) -> Self {
187        Self {
188            address: from_ipv6_addr(*addr.ip()),
189            port: addr.port(),
190            flow_info: addr.flowinfo(),
191            scope_id: addr.scope_id(),
192        }
193    }
194}
195
196impl std::net::ToSocketAddrs for IpSocketAddress {
197    type Iter = <std::net::SocketAddr as std::net::ToSocketAddrs>::Iter;
198
199    fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
200        std::net::SocketAddr::from(*self).to_socket_addrs()
201    }
202}
203
204impl std::net::ToSocketAddrs for Ipv4SocketAddress {
205    type Iter = <std::net::SocketAddrV4 as std::net::ToSocketAddrs>::Iter;
206
207    fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
208        std::net::SocketAddrV4::from(*self).to_socket_addrs()
209    }
210}
211
212impl std::net::ToSocketAddrs for Ipv6SocketAddress {
213    type Iter = <std::net::SocketAddrV6 as std::net::ToSocketAddrs>::Iter;
214
215    fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
216        std::net::SocketAddrV6::from(*self).to_socket_addrs()
217    }
218}