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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#![allow(unused_imports)]
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
#[cfg(feature = "enable_full")]
use tokio::net::TcpStream as TokioTcpStream;
use tracing::{debug, error, info, instrument, span, trace, warn, Level};

use crate::conf::ConfAte;
use crate::engine::TaskEngine;

use {
    trust_dns_client::client::*, trust_dns_client::op::DnsResponse, trust_dns_client::tcp::*,
    trust_dns_proto::iocompat::AsyncIoTokioAsStd, trust_dns_proto::DnssecDnsHandle,
};

pub use {trust_dns_client::error::ClientError, trust_dns_client::rr::*};

pub enum DnsClient {
    Dns {
        cfg: ConfAte,
        client: MemoizeClientHandle<AsyncClient>,
    },
    DnsSec {
        cfg: ConfAte,
        client: DnssecDnsHandle<MemoizeClientHandle<AsyncClient>>,
    },
}

impl DnsClient {
    #[cfg(feature = "enable_full")]
    pub async fn connect(cfg: &ConfAte) -> DnsClient {
        debug!("using DNS server: {}", cfg.dns_server);
        let addr: SocketAddr = (cfg.dns_server.clone(), 53)
            .to_socket_addrs()
            .unwrap()
            .next()
            .unwrap();

        let (stream, sender) = TcpClientStream::<AsyncIoTokioAsStd<TokioTcpStream>>::new(addr);
        let client = AsyncClient::new(stream, sender, None);
        let (client, bg) = client.await.expect("client failed to connect");
        TaskEngine::spawn(bg);

        let client = MemoizeClientHandle::new(client);

        match cfg.dns_sec {
            false => {
                debug!("configured for DNSSec");
                DnsClient::Dns {
                    cfg: cfg.clone(),
                    client,
                }
            }
            true => {
                debug!("configured for plain DNS");
                DnsClient::DnsSec {
                    cfg: cfg.clone(),
                    client: DnssecDnsHandle::new(client.clone()),
                }
            }
        }
    }

    pub async fn reconnect(&mut self) {
        let cfg = match self {
            DnsClient::Dns { cfg, client: _ } => cfg.clone(),
            DnsClient::DnsSec { cfg, client: _ } => cfg.clone(),
        };

        *self = DnsClient::connect(&cfg).await;
    }

    pub async fn query(
        &mut self,
        name: Name,
        query_class: DNSClass,
        query_type: RecordType,
    ) -> Result<DnsResponse, ClientError> {
        let ret = {
            match self {
                DnsClient::Dns { cfg: _, client: c } => {
                    c.query(name.clone(), query_class, query_type).await
                }
                DnsClient::DnsSec { cfg: _, client: c } => {
                    c.query(name.clone(), query_class, query_type).await
                }
            }
        };

        match ret {
            Ok(a) => Ok(a),
            Err(_) => {
                self.reconnect().await;

                match self {
                    DnsClient::Dns { cfg: _, client: c } => {
                        c.query(name, query_class, query_type).await
                    }
                    DnsClient::DnsSec { cfg: _, client: c } => {
                        c.query(name, query_class, query_type).await
                    }
                }
            }
        }
    }
}