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<'_> { convert_error_code(&mut self, error: SocketError) -> wasmtime::Result<ErrorCode>14 fn convert_error_code(&mut self, error: SocketError) -> wasmtime::Result<ErrorCode> { 15 error.downcast() 16 } 17 network_error_code(&mut self, err: Resource<Error>) -> wasmtime::Result<Option<ErrorCode>>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<'_> { drop(&mut self, this: Resource<network::Network>) -> Result<(), wasmtime::Error>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 { from(value: io::Error) -> Self38 fn from(value: io::Error) -> Self { 39 (&value).into() 40 } 41 } 42 43 impl From<&io::Error> for ErrorCode { from(value: &io::Error) -> Self44 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 { from(value: Errno) -> Self74 fn from(value: Errno) -> Self { 75 (&value).into() 76 } 77 } 78 79 impl From<&Errno> for ErrorCode { from(value: &Errno) -> Self80 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 { from(addr: std::net::IpAddr) -> Self134 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 { from(addr: IpSocketAddress) -> Self143 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 { from(addr: std::net::SocketAddr) -> Self152 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 { from(addr: Ipv4SocketAddress) -> Self161 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 { from(addr: std::net::SocketAddrV4) -> Self167 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 { from(addr: Ipv6SocketAddress) -> Self176 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 { from(addr: std::net::SocketAddrV6) -> Self187 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 to_socket_addrs(&self) -> io::Result<Self::Iter>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 to_socket_addrs(&self) -> io::Result<Self::Iter>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 to_socket_addrs(&self) -> io::Result<Self::Iter>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 { from(family: IpAddressFamily) -> Self222 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 { from(family: cap_net_ext::AddressFamily) -> Self231 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