wasmtime_wasi/p3/sockets/host/
ip_name_lookup.rs

1use tokio::net::lookup_host;
2use wasmtime::component::Accessor;
3
4use crate::p3::bindings::sockets::ip_name_lookup::{ErrorCode, Host, HostWithStore};
5use crate::p3::bindings::sockets::types;
6use crate::p3::sockets::WasiSockets;
7use crate::sockets::WasiSocketsCtxView;
8use crate::sockets::util::{from_ipv4_addr, from_ipv6_addr, parse_host};
9
10impl HostWithStore for WasiSockets {
11    async fn resolve_addresses<U>(
12        store: &Accessor<U, Self>,
13        name: String,
14    ) -> wasmtime::Result<Result<Vec<types::IpAddress>, ErrorCode>> {
15        let Ok(host) = parse_host(&name) else {
16            return Ok(Err(ErrorCode::InvalidArgument));
17        };
18        if !store.with(|mut view| view.get().ctx.allowed_network_uses.ip_name_lookup) {
19            return Ok(Err(ErrorCode::PermanentResolverFailure));
20        }
21        match host {
22            url::Host::Ipv4(addr) => Ok(Ok(vec![types::IpAddress::Ipv4(from_ipv4_addr(addr))])),
23            url::Host::Ipv6(addr) => Ok(Ok(vec![types::IpAddress::Ipv6(from_ipv6_addr(addr))])),
24            url::Host::Domain(domain) => {
25                // This is only resolving names, not ports, so force the port to be 0.
26                if let Ok(addrs) = lookup_host((domain.as_str(), 0)).await {
27                    Ok(Ok(addrs
28                        .map(|addr| addr.ip().to_canonical().into())
29                        .collect()))
30                } else {
31                    // If/when we use `getaddrinfo` directly, map the error properly.
32                    Ok(Err(ErrorCode::NameUnresolvable))
33                }
34            }
35        }
36    }
37}
38
39impl Host for WasiSocketsCtxView<'_> {}