use std::future::Future;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use crate::error::Error;
use crate::host::HostResults;
use crate::nameinfo::NameInfoResult;
use crate::resolver::{Options, Resolver};
pub struct CAresFuture<T> {
inner: futures::channel::oneshot::Receiver<c_ares::Result<T>>,
_resolver: Arc<Resolver>,
}
impl<T> CAresFuture<T> {
fn new(
promise: futures::channel::oneshot::Receiver<c_ares::Result<T>>,
resolver: Arc<Resolver>,
) -> Self {
CAresFuture {
inner: promise,
_resolver: resolver,
}
}
fn pin_get_inner(
self: Pin<&mut Self>,
) -> Pin<&mut futures::channel::oneshot::Receiver<c_ares::Result<T>>> {
unsafe { self.map_unchecked_mut(|s| &mut s.inner) }
}
}
impl<T> Future for CAresFuture<T> {
type Output = Result<T, c_ares::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
self.pin_get_inner()
.poll(cx)
.map(|result| result.unwrap_or(Err(c_ares::Error::ECANCELLED)))
}
}
pub struct FutureResolver {
inner: Arc<Resolver>,
}
macro_rules! futurize {
($resolver:expr, $query:ident, $question:expr) => {{
let (sender, receiver) = futures::channel::oneshot::channel();
$resolver.$query($question, move |result| {
let _ = sender.send(result);
});
let resolver = Arc::clone(&$resolver);
CAresFuture::new(receiver, resolver)
}};
}
impl FutureResolver {
pub fn new() -> Result<Self, Error> {
let options = Options::default();
Self::with_options(options)
}
pub fn with_options(options: Options) -> Result<FutureResolver, Error> {
let inner = Resolver::with_options(options)?;
let resolver = FutureResolver {
inner: Arc::new(inner),
};
Ok(resolver)
}
pub fn set_servers(&self, servers: &[&str]) -> Result<&Self, c_ares::Error> {
self.inner.set_servers(servers)?;
Ok(self)
}
pub fn set_local_ipv4(&self, ipv4: Ipv4Addr) -> &Self {
self.inner.set_local_ipv4(ipv4);
self
}
pub fn set_local_ipv6(&self, ipv6: &Ipv6Addr) -> &Self {
self.inner.set_local_ipv6(ipv6);
self
}
pub fn set_local_device(&self, device: &str) -> &Self {
self.inner.set_local_device(device);
self
}
pub fn query_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
futurize!(self.inner, query_a, name)
}
pub fn search_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
futurize!(self.inner, search_a, name)
}
pub fn query_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
futurize!(self.inner, query_aaaa, name)
}
pub fn search_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
futurize!(self.inner, search_aaaa, name)
}
pub fn query_cname(&self, name: &str) -> CAresFuture<c_ares::CNameResults> {
futurize!(self.inner, query_cname, name)
}
pub fn search_cname(&self, name: &str) -> CAresFuture<c_ares::CNameResults> {
futurize!(self.inner, search_cname, name)
}
pub fn query_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
futurize!(self.inner, query_mx, name)
}
pub fn search_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
futurize!(self.inner, search_mx, name)
}
pub fn query_naptr(&self, name: &str) -> CAresFuture<c_ares::NAPTRResults> {
futurize!(self.inner, query_naptr, name)
}
pub fn search_naptr(&self, name: &str) -> CAresFuture<c_ares::NAPTRResults> {
futurize!(self.inner, search_naptr, name)
}
pub fn query_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
futurize!(self.inner, query_ns, name)
}
pub fn search_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
futurize!(self.inner, search_ns, name)
}
pub fn query_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
futurize!(self.inner, query_ptr, name)
}
pub fn search_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
futurize!(self.inner, search_ptr, name)
}
pub fn query_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
futurize!(self.inner, query_soa, name)
}
pub fn search_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
futurize!(self.inner, search_soa, name)
}
pub fn query_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
futurize!(self.inner, query_srv, name)
}
pub fn search_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
futurize!(self.inner, search_srv, name)
}
pub fn query_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
futurize!(self.inner, query_txt, name)
}
pub fn search_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
futurize!(self.inner, search_txt, name)
}
pub fn get_host_by_address(&self, address: &IpAddr) -> CAresFuture<HostResults> {
let (sender, receiver) = futures::channel::oneshot::channel();
self.inner.get_host_by_address(address, move |result| {
let _ = sender.send(result.map(Into::into));
});
let resolver = Arc::clone(&self.inner);
CAresFuture::new(receiver, resolver)
}
pub fn get_host_by_name(
&self,
name: &str,
family: c_ares::AddressFamily,
) -> CAresFuture<HostResults> {
let (sender, receiver) = futures::channel::oneshot::channel();
self.inner.get_host_by_name(name, family, move |result| {
let _ = sender.send(result.map(Into::into));
});
let resolver = Arc::clone(&self.inner);
CAresFuture::new(receiver, resolver)
}
pub fn get_name_info<F>(
&self,
address: &SocketAddr,
flags: c_ares::NIFlags,
) -> CAresFuture<NameInfoResult> {
let (sender, receiver) = futures::channel::oneshot::channel();
self.inner.get_name_info(address, flags, move |result| {
let _ = sender.send(result.map(Into::into));
});
let resolver = Arc::clone(&self.inner);
CAresFuture::new(receiver, resolver)
}
pub fn query(&self, name: &str, dns_class: u16, query_type: u16) -> CAresFuture<Vec<u8>> {
let (sender, receiver) = futures::channel::oneshot::channel();
self.inner
.query(name, dns_class, query_type, move |result| {
let _ = sender.send(result.map(std::borrow::ToOwned::to_owned));
});
let resolver = Arc::clone(&self.inner);
CAresFuture::new(receiver, resolver)
}
pub fn search(&self, name: &str, dns_class: u16, query_type: u16) -> CAresFuture<Vec<u8>> {
let (sender, receiver) = futures::channel::oneshot::channel();
self.inner
.search(name, dns_class, query_type, move |result| {
let _ = sender.send(result.map(std::borrow::ToOwned::to_owned));
});
let resolver = Arc::clone(&self.inner);
CAresFuture::new(receiver, resolver)
}
pub fn cancel(&self) {
self.inner.cancel()
}
}