Skip to main content

wasmtime_wasi/p3/sockets/
conv.rs

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