1 extern crate rustls;
2 extern crate webpki_roots;
3 
4 use std::net::SocketAddr;
5 use std::pin::Pin;
6 
7 use crate::tls::CLIENT_CONFIG;
8 
9 use futures::Future;
10 
11 use proto::error::ProtoError;
12 use proto::xfer::{BufDnsRequestStreamHandle, DnsExchange};
13 use trust_dns_https::{HttpsClientResponse, HttpsClientStream, HttpsClientStreamBuilder};
14 
15 use crate::config::TlsClientConfig;
16 
17 #[allow(clippy::type_complexity)]
new_https_stream( socket_addr: SocketAddr, dns_name: String, client_config: Option<TlsClientConfig>, ) -> ( Pin< Box< dyn Future< Output = Result< DnsExchange<HttpsClientStream, HttpsClientResponse>, ProtoError, >, > + Send, >, >, BufDnsRequestStreamHandle<HttpsClientResponse>, )18 pub(crate) fn new_https_stream(
19     socket_addr: SocketAddr,
20     dns_name: String,
21     client_config: Option<TlsClientConfig>,
22 ) -> (
23     Pin<
24         Box<
25             dyn Future<
26                     Output = Result<
27                         DnsExchange<HttpsClientStream, HttpsClientResponse>,
28                         ProtoError,
29                     >,
30                 > + Send,
31         >,
32     >,
33     BufDnsRequestStreamHandle<HttpsClientResponse>,
34 ) {
35     let client_config = client_config.map_or_else(
36         || CLIENT_CONFIG.clone(),
37         |TlsClientConfig(client_config)| client_config,
38     );
39 
40     let https_builder = HttpsClientStreamBuilder::with_client_config(client_config);
41     let (stream, handle) = DnsExchange::connect(https_builder.build(socket_addr, dns_name));
42     let handle = BufDnsRequestStreamHandle::new(handle);
43 
44     (Box::pin(stream), handle)
45 }
46 
47 #[cfg(test)]
48 mod tests {
49     extern crate env_logger;
50     use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
51 
52     use tokio::runtime::Runtime;
53 
54     use crate::config::{ResolverConfig, ResolverOpts};
55     use crate::AsyncResolver;
56 
https_test(config: ResolverConfig)57     fn https_test(config: ResolverConfig) {
58         //env_logger::try_init().ok();
59         let mut io_loop = Runtime::new().unwrap();
60 
61         let (resolver, bg) = AsyncResolver::new(config, ResolverOpts::default());
62         io_loop.spawn(bg);
63 
64         let response = io_loop
65             .block_on(resolver.lookup_ip("www.example.com."))
66             .expect("failed to run lookup");
67 
68         assert_eq!(response.iter().count(), 1);
69         for address in response.iter() {
70             if address.is_ipv4() {
71                 assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
72             } else {
73                 assert_eq!(
74                     address,
75                     IpAddr::V6(Ipv6Addr::new(
76                         0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
77                     ))
78                 );
79             }
80         }
81     }
82 
83     #[test]
test_cloudflare_https()84     fn test_cloudflare_https() {
85         https_test(ResolverConfig::cloudflare_https())
86     }
87 }
88