1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 //! `Resolver` trait and `DefaultDnsResolver` implementation. 15 16 use std::future::Future; 17 use std::io; 18 use std::io::Error; 19 use std::net::{SocketAddr, ToSocketAddrs}; 20 use std::pin::Pin; 21 use std::task::{Context, Poll}; 22 use std::vec::IntoIter; 23 24 use crate::runtime::JoinHandle; 25 26 /// `SocketAddr` resolved by `Resolver`. 27 pub type Addrs = Box<dyn Iterator<Item = SocketAddr> + Sync + Send>; 28 /// Possible errors that this resolver may generate when attempting to 29 /// resolve. 30 pub type StdError = Box<dyn std::error::Error + Send + Sync>; 31 /// Futures generated by this resolve when attempting to resolve an address. 32 pub type SocketFuture = Pin<Box<dyn Future<Output = Result<Addrs, StdError>> + Sync + Send>>; 33 34 /// `Resolver` trait used by `async_impl::connector::HttpConnector`. `Resolver` 35 /// provides asynchronous dns resolve interfaces. 36 pub trait Resolver: Send + Sync + 'static { 37 /// resolve domain to a `SocketAddr` `Future`. resolvenull38 fn resolve(&self, domain: &str) -> SocketFuture; 39 } 40 41 /// `SocketAddr` resolved by `DefaultDnsResolver`. 42 pub struct ResolvedAddrs { 43 iter: IntoIter<SocketAddr>, 44 } 45 46 impl ResolvedAddrs { 47 pub(super) fn new(iter: IntoIter<SocketAddr>) -> Self { 48 Self { iter } 49 } 50 51 // The first ip in the dns record is the preferred addrs type. 52 pub(super) fn split_preferred_addrs(self) -> (Vec<SocketAddr>, Vec<SocketAddr>) { 53 // get preferred address family type. 54 let is_ipv6 = self 55 .iter 56 .as_slice() 57 .first() 58 .map(SocketAddr::is_ipv6) 59 .unwrap_or(false); 60 self.iter 61 .partition::<Vec<_>, _>(|addr| addr.is_ipv6() == is_ipv6) 62 } 63 } 64 65 impl Iterator for ResolvedAddrs { 66 type Item = SocketAddr; 67 nextnull68 fn next(&mut self) -> Option<Self::Item> { 69 self.iter.next() 70 } 71 } 72 73 /// Futures generated by `DefaultDnsResolver`. 74 pub struct DefaultDnsFuture { 75 inner: JoinHandle<Result<ResolvedAddrs, Error>>, 76 } 77 78 impl Future for DefaultDnsFuture { 79 type Output = Result<Addrs, StdError>; 80 pollnull81 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 82 Pin::new(&mut self.inner).poll(cx).map(|res| match res { 83 Ok(Ok(addrs)) => Ok(Box::new(addrs) as Addrs), 84 Ok(Err(err)) => Err(Box::new(err) as StdError), 85 Err(err) => Err(Box::new(Error::new(io::ErrorKind::Interrupted, err)) as StdError), 86 }) 87 } 88 } 89 90 /// Default dns resolver used by the `Client`。 91 #[derive(Default)] 92 pub struct DefaultDnsResolver {} 93 94 impl Resolver for DefaultDnsResolver { resolvenull95 fn resolve(&self, domain: &str) -> SocketFuture { 96 let domain: Box<str> = domain.into(); 97 let blocking = crate::runtime::spawn_blocking(move || { 98 (*domain) 99 .to_socket_addrs() 100 .map(|iter| ResolvedAddrs { iter }) 101 }); 102 Box::pin(DefaultDnsFuture { inner: blocking }) 103 } 104 } 105 106 #[cfg(test)] 107 mod ut_dns_resolver { 108 use crate::async_impl::{DefaultDnsResolver, Resolver}; 109 110 /// UT test cases for `FrameDecoder::decode`. 111 /// 112 /// # Brief 113 /// 114 /// Test a simple complete DATA frame. 115 /// 1. Creates a `FrameDecoder`. 116 /// 2. Calls its `FrameDecoder::decode` method. 117 /// 3. Checks the results. 118 #[test] 119 #[cfg(feature = "ylong_base")] ut_resolver_std_dns_resolver_resolvenull120 fn ut_resolver_std_dns_resolver_resolve() { 121 ylong_runtime::block_on(async move { 122 let resolver = DefaultDnsResolver {}; 123 let sockets = resolver 124 .resolve("www.baidu.com:80") 125 .await 126 .expect("dns resolver resolve domain occurs err"); 127 let mut size = 0; 128 for _socket in sockets.into_iter() { 129 size += 1; 130 } 131 assert!(size > 0); 132 }); 133 } 134 135 /// UT test cases for `FrameDecoder::decode`. 136 /// 137 /// # Brief 138 /// 139 /// Test a simple complete DATA frame. 140 /// 1. Creates a `FrameDecoder`. 141 /// 2. Calls its `FrameDecoder::decode` method. 142 /// 3. Checks the results. 143 #[test] 144 #[cfg(feature = "tokio_base")] ut_resolver_std_dns_resolver_resolvenull145 fn ut_resolver_std_dns_resolver_resolve() { 146 let runtime = tokio::runtime::Builder::new_multi_thread() 147 .worker_threads(1) 148 .enable_all() 149 .build() 150 .expect("Build runtime failed."); 151 runtime.block_on(async move { 152 let resolver = DefaultDnsResolver {}; 153 let sockets = resolver 154 .resolve("www.baidu.com:80") 155 .await 156 .expect("dns resolver resolve domain occurs err"); 157 let mut size = 0; 158 for _socket in sockets.into_iter() { 159 size += 1; 160 } 161 assert!(size > 0); 162 }); 163 } 164 } 165