1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
2
3use crate::error::Error;
4use crate::host::HostResults;
5use crate::nameinfo::NameInfoResult;
6use crate::resolver::{Options, Resolver};
7
8#[cfg(cares1_24)]
9use c_ares::AresString;
10
11#[cfg(cares1_29)]
12use c_ares::ServerStateFlags;
13
14use std::sync::mpsc;
15
16pub struct BlockingResolver {
18 inner: Resolver,
19}
20
21macro_rules! blockify {
24 ($resolver:expr, $query:ident, $question:expr) => {{
25 let (tx, rx) = mpsc::sync_channel(1);
26 $resolver.$query($question, move |result| tx.send(result).unwrap());
27 rx.recv().unwrap()
28 }};
29}
30
31impl BlockingResolver {
32 pub fn new() -> Result<Self, Error> {
34 let options = Options::default();
35 Self::with_options(options)
36 }
37
38 pub fn with_options(options: Options) -> Result<Self, Error> {
40 let inner = Resolver::with_options(options)?;
41 let resolver = Self { inner };
42 Ok(resolver)
43 }
44
45 #[cfg(cares1_22)]
47 pub fn reinit(&self) -> c_ares::Result<&Self> {
48 self.inner.reinit()?;
49 Ok(self)
50 }
51
52 pub fn set_servers(&self, servers: &[&str]) -> c_ares::Result<&Self> {
58 self.inner.set_servers(servers)?;
59 Ok(self)
60 }
61
62 #[cfg(cares1_24)]
64 pub fn get_servers(&self) -> AresString {
65 self.inner.get_servers()
66 }
67
68 pub fn set_local_ipv4(&self, ipv4: Ipv4Addr) -> &Self {
70 self.inner.set_local_ipv4(ipv4);
71 self
72 }
73
74 pub fn set_local_ipv6(&self, ipv6: &Ipv6Addr) -> &Self {
76 self.inner.set_local_ipv6(ipv6);
77 self
78 }
79
80 pub fn set_local_device(&self, device: &str) -> &Self {
82 self.inner.set_local_device(device);
83 self
84 }
85
86 pub fn set_sortlist(&self, sortlist: &[&str]) -> c_ares::Result<&Self> {
93 self.inner.set_sortlist(sortlist)?;
94 Ok(self)
95 }
96
97 #[cfg(cares1_29)]
105 pub fn set_server_state_callback<F>(&self, callback: F) -> &Self
106 where
107 F: FnMut(&str, bool, ServerStateFlags) + Send + 'static,
108 {
109 self.inner.set_server_state_callback(callback);
110 self
111 }
112
113 pub fn query_a(&self, name: &str) -> c_ares::Result<c_ares::AResults> {
115 blockify!(self.inner, query_a, name)
116 }
117
118 pub fn search_a(&self, name: &str) -> c_ares::Result<c_ares::AResults> {
120 blockify!(self.inner, search_a, name)
121 }
122
123 pub fn query_aaaa(&self, name: &str) -> c_ares::Result<c_ares::AAAAResults> {
125 blockify!(self.inner, query_aaaa, name)
126 }
127
128 pub fn search_aaaa(&self, name: &str) -> c_ares::Result<c_ares::AAAAResults> {
130 blockify!(self.inner, search_aaaa, name)
131 }
132
133 #[cfg(cares1_17)]
135 pub fn query_caa(&self, name: &str) -> c_ares::Result<c_ares::CAAResults> {
136 blockify!(self.inner, query_caa, name)
137 }
138
139 #[cfg(cares1_17)]
141 pub fn search_caa(&self, name: &str) -> c_ares::Result<c_ares::CAAResults> {
142 blockify!(self.inner, search_caa, name)
143 }
144
145 pub fn query_cname(&self, name: &str) -> c_ares::Result<c_ares::CNameResults> {
147 blockify!(self.inner, query_cname, name)
148 }
149
150 pub fn search_cname(&self, name: &str) -> c_ares::Result<c_ares::CNameResults> {
152 blockify!(self.inner, search_cname, name)
153 }
154
155 pub fn query_mx(&self, name: &str) -> c_ares::Result<c_ares::MXResults> {
157 blockify!(self.inner, query_mx, name)
158 }
159
160 pub fn search_mx(&self, name: &str) -> c_ares::Result<c_ares::MXResults> {
162 blockify!(self.inner, search_mx, name)
163 }
164
165 pub fn query_naptr(&self, name: &str) -> c_ares::Result<c_ares::NAPTRResults> {
167 blockify!(self.inner, query_naptr, name)
168 }
169
170 pub fn search_naptr(&self, name: &str) -> c_ares::Result<c_ares::NAPTRResults> {
172 blockify!(self.inner, search_naptr, name)
173 }
174
175 pub fn query_ns(&self, name: &str) -> c_ares::Result<c_ares::NSResults> {
177 blockify!(self.inner, query_ns, name)
178 }
179
180 pub fn search_ns(&self, name: &str) -> c_ares::Result<c_ares::NSResults> {
182 blockify!(self.inner, search_ns, name)
183 }
184
185 pub fn query_ptr(&self, name: &str) -> c_ares::Result<c_ares::PTRResults> {
187 blockify!(self.inner, query_ptr, name)
188 }
189
190 pub fn search_ptr(&self, name: &str) -> c_ares::Result<c_ares::PTRResults> {
192 blockify!(self.inner, search_ptr, name)
193 }
194
195 pub fn query_soa(&self, name: &str) -> c_ares::Result<c_ares::SOAResult> {
197 blockify!(self.inner, query_soa, name)
198 }
199
200 pub fn search_soa(&self, name: &str) -> c_ares::Result<c_ares::SOAResult> {
202 blockify!(self.inner, search_soa, name)
203 }
204
205 pub fn query_srv(&self, name: &str) -> c_ares::Result<c_ares::SRVResults> {
207 blockify!(self.inner, query_srv, name)
208 }
209
210 pub fn search_srv(&self, name: &str) -> c_ares::Result<c_ares::SRVResults> {
212 blockify!(self.inner, search_srv, name)
213 }
214
215 pub fn query_txt(&self, name: &str) -> c_ares::Result<c_ares::TXTResults> {
217 blockify!(self.inner, query_txt, name)
218 }
219
220 pub fn search_txt(&self, name: &str) -> c_ares::Result<c_ares::TXTResults> {
222 blockify!(self.inner, search_txt, name)
223 }
224
225 pub fn query_uri(&self, name: &str) -> c_ares::Result<c_ares::URIResults> {
227 blockify!(self.inner, query_uri, name)
228 }
229
230 pub fn search_uri(&self, name: &str) -> c_ares::Result<c_ares::URIResults> {
232 blockify!(self.inner, search_uri, name)
233 }
234
235 pub fn get_host_by_address(&self, address: &IpAddr) -> c_ares::Result<HostResults> {
241 let (tx, rx) = mpsc::sync_channel(1);
242 self.inner.get_host_by_address(address, move |result| {
243 tx.send(result.map(Into::into)).unwrap()
244 });
245 rx.recv().unwrap()
246 }
247
248 pub fn get_host_by_name(
254 &self,
255 name: &str,
256 family: c_ares::AddressFamily,
257 ) -> c_ares::Result<HostResults> {
258 let (tx, rx) = mpsc::sync_channel(1);
259 self.inner.get_host_by_name(name, family, move |result| {
260 tx.send(result.map(Into::into)).unwrap()
261 });
262 rx.recv().unwrap()
263 }
264
265 pub fn get_name_info<F>(
271 &self,
272 address: &SocketAddr,
273 flags: c_ares::NIFlags,
274 ) -> c_ares::Result<NameInfoResult> {
275 let (tx, rx) = mpsc::sync_channel(1);
276 self.inner.get_name_info(address, flags, move |result| {
277 tx.send(result.map(Into::into)).unwrap()
278 });
279 rx.recv().unwrap()
280 }
281
282 pub fn query(&self, name: &str, dns_class: u16, query_type: u16) -> c_ares::Result<Vec<u8>> {
293 let (tx, rx) = mpsc::sync_channel(1);
294 self.inner
295 .query(name, dns_class, query_type, move |result| {
296 tx.send(result.map(std::borrow::ToOwned::to_owned)).unwrap()
297 });
298 rx.recv().unwrap()
299 }
300
301 pub fn search(&self, name: &str, dns_class: u16, query_type: u16) -> c_ares::Result<Vec<u8>> {
312 let (tx, rx) = mpsc::sync_channel(1);
313 self.inner
314 .search(name, dns_class, query_type, move |result| {
315 tx.send(result.map(std::borrow::ToOwned::to_owned)).unwrap()
316 });
317 rx.recv().unwrap()
318 }
319}