saluki_io/net/dns/
host.rs1use std::net::IpAddr;
4
5use snafu::{ResultExt as _, Snafu};
6
7#[derive(Debug, Snafu)]
9#[snafu(context(suffix(false)))]
10pub enum ResolveHostError {
11 #[snafu(display("failed to look up host '{}': {}", host, source))]
13 LookupFailed {
14 host: String,
16
17 source: std::io::Error,
19 },
20
21 #[snafu(display("host '{}' resolved to zero IP addresses", host))]
23 NoAddresses {
24 host: String,
26 },
27}
28
29pub async fn resolve_host(host: &str) -> Result<IpAddr, ResolveHostError> {
39 let mut addrs = tokio::net::lookup_host((host, 0u16))
40 .await
41 .context(LookupFailed { host })?;
42 addrs
43 .next()
44 .map(|sa| sa.ip())
45 .ok_or_else(|| ResolveHostError::NoAddresses { host: host.to_string() })
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[tokio::test]
53 async fn resolves_ip_literals_without_lookup() {
54 assert_eq!(resolve_host("127.0.0.1").await.unwrap(), IpAddr::from([127, 0, 0, 1]));
55 assert_eq!(
56 resolve_host("192.168.1.50").await.unwrap(),
57 IpAddr::from([192, 168, 1, 50])
58 );
59 assert_eq!(
60 resolve_host("::1").await.unwrap(),
61 IpAddr::from(std::net::Ipv6Addr::LOCALHOST)
62 );
63 }
64}