feat(dns): export client::connect::dns module, and

`TokioThreadpoolGaiResolver` type.
This commit is contained in:
Sean McArthur
2018-10-23 12:31:11 -07:00
parent 1e8d6439cf
commit 34d780acd0
5 changed files with 59 additions and 40 deletions

View File

@@ -34,8 +34,8 @@ tokio-executor = { version = "0.1.0", optional = true }
tokio-io = "0.1" tokio-io = "0.1"
tokio-reactor = { version = "0.1", optional = true } tokio-reactor = { version = "0.1", optional = true }
tokio-tcp = { version = "0.1", optional = true } tokio-tcp = { version = "0.1", optional = true }
tokio-threadpool = { version = "0.1.3", optional = true }
tokio-timer = { version = "0.2", optional = true } tokio-timer = { version = "0.2", optional = true }
tokio-threadpool = { version = "0.1", optional = true }
want = "0.0.6" want = "0.0.6"
[dev-dependencies] [dev-dependencies]
@@ -62,8 +62,8 @@ runtime = [
"tokio-executor", "tokio-executor",
"tokio-reactor", "tokio-reactor",
"tokio-tcp", "tokio-tcp",
"tokio-timer",
"tokio-threadpool", "tokio-threadpool",
"tokio-timer",
] ]
nightly = [] nightly = []
__internal_flaky_tests = [] __internal_flaky_tests = []

View File

@@ -1,3 +1,11 @@
//! The `Resolve` trait, support types, and some basic implementations.
//!
//! This module contains:
//!
//! - A [`GaiResolver`](GaiResolver) that is the default resolver for the
//! `HttpConnector`.
//! - The [`Resolve`](Resolve) trait and related types to build a custom
//! resolver for use with the `HttpConnector`.
use std::{fmt, io, vec}; use std::{fmt, io, vec};
use std::net::{ use std::net::{
IpAddr, Ipv4Addr, Ipv6Addr, IpAddr, Ipv4Addr, Ipv6Addr,
@@ -10,12 +18,10 @@ use futures::{Async, Future, Poll};
use futures::future::{Executor, ExecuteError}; use futures::future::{Executor, ExecuteError};
use futures::sync::oneshot; use futures::sync::oneshot;
use futures_cpupool::{Builder as CpuPoolBuilder}; use futures_cpupool::{Builder as CpuPoolBuilder};
use tokio_threadpool;
use self::sealed::GaiTask; use self::sealed::GaiTask;
#[cfg(feature = "runtime")]
pub use self::blocking::{TokioThreadpoolGaiFuture, TokioThreadpoolGaiResolver};
/// Resolve a hostname to a set of IP addresses. /// Resolve a hostname to a set of IP addresses.
pub trait Resolve { pub trait Resolve {
/// The set of IP addresses to try to connect to. /// The set of IP addresses to try to connect to.
@@ -37,10 +43,12 @@ pub struct GaiResolver {
executor: GaiExecutor, executor: GaiExecutor,
} }
/// An iterator of IP addresses returned from `getaddrinfo`.
pub struct GaiAddrs { pub struct GaiAddrs {
inner: IpAddrs, inner: IpAddrs,
} }
/// A future to resole a name returned by `GaiResolver`.
pub struct GaiFuture { pub struct GaiFuture {
rx: oneshot::SpawnHandle<IpAddrs, io::Error>, rx: oneshot::SpawnHandle<IpAddrs, io::Error>,
} }
@@ -242,46 +250,49 @@ pub(super) mod sealed {
} }
} }
#[cfg(feature = "runtime")]
mod blocking {
use futures::{Async, Future, Poll};
use std::io;
use std::net::ToSocketAddrs;
use tokio_threadpool;
use super::{Name, IpAddrs, GaiAddrs, Resolve}; /// A resolver using `getaddrinfo` calls via the `tokio_threadpool::blocking` API.
///
/// Unlike the `GaiResolver` this will not spawn dedicated threads, but only works when running on the
/// multi-threaded Tokio runtime.
#[derive(Clone, Debug)]
pub struct TokioThreadpoolGaiResolver(());
/// A resolver using `getaddrinfo` calls via the `tokio_threadpool::blocking` API. /// The future returned by `TokioThreadpoolGaiResolver`.
/// #[derive(Debug)]
/// Unlike the `GaiResolver` this will not spawn dedicated threads, but only works when running on the pub struct TokioThreadpoolGaiFuture {
/// multi-threaded Tokio runtime. name: Name,
#[derive(Clone)] }
pub struct TokioThreadpoolGaiResolver(());
pub struct TokioThreadpoolGaiFuture { impl TokioThreadpoolGaiResolver {
name: Name, /// Creates a new DNS resolver that will use tokio threadpool's blocking
/// feature.
///
/// **Requires** its futures to be run on the threadpool runtime.
pub fn new() -> Self {
TokioThreadpoolGaiResolver::new()
} }
}
impl Resolve for TokioThreadpoolGaiResolver { impl Resolve for TokioThreadpoolGaiResolver {
type Addrs = GaiAddrs; type Addrs = GaiAddrs;
type Future = TokioThreadpoolGaiFuture; type Future = TokioThreadpoolGaiFuture;
fn resolve(&self, name: Name) -> TokioThreadpoolGaiFuture { fn resolve(&self, name: Name) -> TokioThreadpoolGaiFuture {
TokioThreadpoolGaiFuture { name } TokioThreadpoolGaiFuture { name }
}
} }
}
impl Future for TokioThreadpoolGaiFuture { impl Future for TokioThreadpoolGaiFuture {
type Item = GaiAddrs; type Item = GaiAddrs;
type Error = io::Error; type Error = io::Error;
fn poll(&mut self) -> Poll<GaiAddrs, io::Error> { fn poll(&mut self) -> Poll<GaiAddrs, io::Error> {
match tokio_threadpool::blocking(|| (self.name.as_str(), 0).to_socket_addrs()) { match tokio_threadpool::blocking(|| (self.name.as_str(), 0).to_socket_addrs()) {
Ok(Async::Ready(Ok(iter))) => Ok(Async::Ready(GaiAddrs { inner: IpAddrs { iter } })), Ok(Async::Ready(Ok(iter))) => Ok(Async::Ready(GaiAddrs { inner: IpAddrs { iter } })),
Ok(Async::Ready(Err(e))) => Err(e), Ok(Async::Ready(Err(e))) => Err(e),
Ok(Async::NotReady) => Ok(Async::NotReady), Ok(Async::NotReady) => Ok(Async::NotReady),
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)), Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
}
} }
} }
} }

View File

@@ -15,7 +15,7 @@ use tokio_tcp::{TcpStream, ConnectFuture};
use tokio_timer::Delay; use tokio_timer::Delay;
use super::{Connect, Connected, Destination}; use super::{Connect, Connected, Destination};
use super::dns::{self, GaiResolver, Resolve}; use super::dns::{self, GaiResolver, Resolve, TokioThreadpoolGaiResolver};
/// A connector for the `http` scheme. /// A connector for the `http` scheme.
/// ///
@@ -99,6 +99,15 @@ impl HttpConnector {
} }
} }
impl HttpConnector<TokioThreadpoolGaiResolver> {
/// Construct a new HttpConnector using the `TokioThreadpoolGaiResolver`.
///
/// This resolver **requires** the threadpool runtime to be used.
pub fn new_with_tokio_threadpool_resolver() -> Self {
HttpConnector::new_with_resolver(TokioThreadpoolGaiResolver::new())
}
}
impl<R> HttpConnector<R> { impl<R> HttpConnector<R> {
/// Construct a new HttpConnector. /// Construct a new HttpConnector.

View File

@@ -13,9 +13,8 @@ use futures::Future;
use http::{uri, Response, Uri}; use http::{uri, Response, Uri};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
#[cfg(feature = "runtime")] mod dns; #[cfg(feature = "runtime")] pub mod dns;
#[cfg(feature = "runtime")] mod http; #[cfg(feature = "runtime")] mod http;
#[cfg(feature = "runtime")] pub use self::dns::{GaiResolver, Name, Resolve};
#[cfg(feature = "runtime")] pub use self::http::{HttpConnector, HttpInfo}; #[cfg(feature = "runtime")] pub use self::http::{HttpConnector, HttpInfo};
/// Connect to a destination, returning an IO transport. /// Connect to a destination, returning an IO transport.

View File

@@ -30,8 +30,8 @@ extern crate time;
#[macro_use] extern crate tokio_io; #[macro_use] extern crate tokio_io;
#[cfg(feature = "runtime")] extern crate tokio_reactor; #[cfg(feature = "runtime")] extern crate tokio_reactor;
#[cfg(feature = "runtime")] extern crate tokio_tcp; #[cfg(feature = "runtime")] extern crate tokio_tcp;
#[cfg(feature = "runtime")] extern crate tokio_timer;
#[cfg(feature = "runtime")] extern crate tokio_threadpool; #[cfg(feature = "runtime")] extern crate tokio_threadpool;
#[cfg(feature = "runtime")] extern crate tokio_timer;
extern crate want; extern crate want;
#[cfg(all(test, feature = "nightly"))] #[cfg(all(test, feature = "nightly"))]