1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//! Abstractions over DNS resolvers.

use std::{future::Future, net::SocketAddr, pin::Pin};

use crate::Error;

/// Trait for a DNS resolver to resolve hostnames and ports to IP addresses.
pub trait Resolver: Send {
    /// Resolve a hostname and port to an IP address, asynchronously.
    fn resolve(
        &self,
        host: &str,
        port: u16,
    ) -> Pin<Box<dyn Future<Output = Result<SocketAddr, Error>> + Send>>;
}

/// A [`Resolver`] that uses the blocking `getaddrinfo` syscall in the tokio
/// threadpool.
pub struct Gai;

impl Resolver for Gai {
    fn resolve(
        &self,
        host: &str,
        port: u16,
    ) -> Pin<Box<dyn Future<Output = Result<SocketAddr, Error>> + Send>> {
        let host = host.to_owned();

        Box::pin(async move {
            tokio::net::lookup_host((host, port))
                .await
                .map_err(|_| Error::CannotResolveHost)?
                .next()
                .ok_or(Error::CannotResolveHost)
        })
    }
}