remove tokio dep from actix-tls. use static future for default dnslookup

This commit is contained in:
fakeshadow 2021-01-22 15:17:18 -08:00
parent 8e30a1d643
commit de2f8e0c62
2 changed files with 83 additions and 61 deletions

View File

@ -29,7 +29,7 @@ default = ["accept", "connect", "uri"]
accept = []
# enable connector services
connect = ["tokio/net"]
connect = []
# use openssl impls
openssl = ["tls-openssl", "tokio-openssl"]
@ -53,7 +53,6 @@ derive_more = "0.99.5"
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
http = { version = "0.2.3", optional = true }
log = "0.4"
tokio = { version = "1", optional = true }
# openssl
tls-openssl = { package = "openssl", version = "0.10", optional = true }

View File

@ -1,13 +1,16 @@
use std::{
future::Future,
io,
net::SocketAddr,
pin::Pin,
rc::Rc,
task::{Context, Poll},
vec::IntoIter,
};
use actix_rt::task::{spawn_blocking, JoinHandle};
use actix_service::{Service, ServiceFactory};
use futures_core::future::LocalBoxFuture;
use futures_core::{future::LocalBoxFuture, ready};
use log::trace;
use super::connect::{Address, Connect};
@ -115,12 +118,8 @@ impl Resolver {
Self::Custom(Rc::new(resolver))
}
async fn lookup<T: Address>(
&self,
req: &Connect<T>,
) -> Result<Vec<SocketAddr>, ConnectError> {
match self {
Self::Default => {
// look up with default resolver variant.
fn look_up<T: Address>(req: &Connect<T>) -> JoinHandle<io::Result<IntoIter<SocketAddr>>> {
let host = req.host();
// TODO: Connect should always return host with port if possible.
let host = if req
@ -136,25 +135,7 @@ impl Resolver {
format!("{}:{}", host, req.port())
};
let res = tokio::net::lookup_host(host)
.await
.map_err(|e| {
trace!(
"DNS resolver: failed to resolve host {:?} err: {}",
req.host(),
e
);
ConnectError::Resolver(Box::new(e))
})?
.collect();
Ok(res)
}
Self::Custom(resolver) => resolver
.lookup(req.host(), req.port())
.await
.map_err(ConnectError::Resolver),
}
spawn_blocking(move || std::net::ToSocketAddrs::to_socket_addrs(&host))
}
}
@ -175,18 +156,22 @@ impl<T: Address> Service<Connect<T>> for Resolver {
} else {
trace!("DNS resolver: resolving host {:?}", req.host());
let resolver = self.clone();
ResolverFuture::Lookup(Box::pin(async move {
let addrs = resolver.lookup(&req).await?;
match self {
Self::Default => {
let fut = Self::look_up(&req);
ResolverFuture::LookUp(fut, Some(req))
}
Self::Custom(resolver) => {
let resolver = Rc::clone(&resolver);
ResolverFuture::LookupCustom(Box::pin(async move {
let addrs = resolver
.lookup(req.host(), req.port())
.await
.map_err(ConnectError::Resolver)?;
let req = req.set_addrs(addrs);
trace!(
"DNS resolver: host {:?} resolved to {:?}",
req.host(),
req.addrs()
);
if req.addr.is_none() {
Err(ConnectError::NoRecords)
} else {
@ -196,10 +181,16 @@ impl<T: Address> Service<Connect<T>> for Resolver {
}
}
}
}
}
pub enum ResolverFuture<T: Address> {
Connected(Option<Connect<T>>),
Lookup(LocalBoxFuture<'static, Result<Connect<T>, ConnectError>>),
LookUp(
JoinHandle<io::Result<IntoIter<SocketAddr>>>,
Option<Connect<T>>,
),
LookupCustom(LocalBoxFuture<'static, Result<Connect<T>, ConnectError>>),
}
impl<T: Address> Future for ResolverFuture<T> {
@ -210,7 +201,39 @@ impl<T: Address> Future for ResolverFuture<T> {
Self::Connected(conn) => Poll::Ready(Ok(conn
.take()
.expect("ResolverFuture polled after finished"))),
Self::Lookup(fut) => fut.as_mut().poll(cx),
Self::LookUp(fut, req) => {
let res = match ready!(Pin::new(fut).poll(cx)) {
Ok(Ok(res)) => Ok(res),
Ok(Err(e)) => Err(ConnectError::Resolver(Box::new(e))),
Err(e) => Err(ConnectError::Io(e.into())),
};
let req = req.take().unwrap();
let addrs = res.map_err(|e| {
trace!(
"DNS resolver: failed to resolve host {:?} err: {:?}",
req.host(),
e
);
e
})?;
let req = req.set_addrs(addrs);
trace!(
"DNS resolver: host {:?} resolved to {:?}",
req.host(),
req.addrs()
);
if req.addr.is_none() {
Poll::Ready(Err(ConnectError::NoRecords))
} else {
Poll::Ready(Ok(req))
}
}
Self::LookupCustom(fut) => fut.as_mut().poll(cx),
}
}
}