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