From 34d780acd0fd7fe6a41b3eca1641791c7a33b366 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Tue, 23 Oct 2018 12:31:11 -0700 Subject: [PATCH] feat(dns): export `client::connect::dns` module, and `TokioThreadpoolGaiResolver` type. --- Cargo.toml | 4 +- src/client/connect/dns.rs | 81 ++++++++++++++++++++++---------------- src/client/connect/http.rs | 11 +++++- src/client/connect/mod.rs | 3 +- src/lib.rs | 2 +- 5 files changed, 60 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 429b0a5a9e..1e511ecdbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,8 +34,8 @@ tokio-executor = { version = "0.1.0", optional = true } tokio-io = "0.1" tokio-reactor = { 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-threadpool = { version = "0.1", optional = true } want = "0.0.6" [dev-dependencies] @@ -62,8 +62,8 @@ runtime = [ "tokio-executor", "tokio-reactor", "tokio-tcp", - "tokio-timer", "tokio-threadpool", + "tokio-timer", ] nightly = [] __internal_flaky_tests = [] diff --git a/src/client/connect/dns.rs b/src/client/connect/dns.rs index 6ca2a5c1d1..17a0e43bbe 100644 --- a/src/client/connect/dns.rs +++ b/src/client/connect/dns.rs @@ -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::net::{ IpAddr, Ipv4Addr, Ipv6Addr, @@ -10,12 +18,10 @@ use futures::{Async, Future, Poll}; use futures::future::{Executor, ExecuteError}; use futures::sync::oneshot; use futures_cpupool::{Builder as CpuPoolBuilder}; +use tokio_threadpool; use self::sealed::GaiTask; -#[cfg(feature = "runtime")] -pub use self::blocking::{TokioThreadpoolGaiFuture, TokioThreadpoolGaiResolver}; - /// Resolve a hostname to a set of IP addresses. pub trait Resolve { /// The set of IP addresses to try to connect to. @@ -37,10 +43,12 @@ pub struct GaiResolver { executor: GaiExecutor, } +/// An iterator of IP addresses returned from `getaddrinfo`. pub struct GaiAddrs { inner: IpAddrs, } +/// A future to resole a name returned by `GaiResolver`. pub struct GaiFuture { rx: oneshot::SpawnHandle, } @@ -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. - /// - /// Unlike the `GaiResolver` this will not spawn dedicated threads, but only works when running on the - /// multi-threaded Tokio runtime. - #[derive(Clone)] - pub struct TokioThreadpoolGaiResolver(()); +/// The future returned by `TokioThreadpoolGaiResolver`. +#[derive(Debug)] +pub struct TokioThreadpoolGaiFuture { + name: Name, +} - pub struct TokioThreadpoolGaiFuture { - name: Name, +impl TokioThreadpoolGaiResolver { + /// 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 { - type Addrs = GaiAddrs; - type Future = TokioThreadpoolGaiFuture; +impl Resolve for TokioThreadpoolGaiResolver { + type Addrs = GaiAddrs; + type Future = TokioThreadpoolGaiFuture; - fn resolve(&self, name: Name) -> TokioThreadpoolGaiFuture { - TokioThreadpoolGaiFuture { name } - } + fn resolve(&self, name: Name) -> TokioThreadpoolGaiFuture { + TokioThreadpoolGaiFuture { name } } +} + +impl Future for TokioThreadpoolGaiFuture { + type Item = GaiAddrs; + type Error = io::Error; - impl Future for TokioThreadpoolGaiFuture { - type Item = GaiAddrs; - type Error = io::Error; - - fn poll(&mut self) -> Poll { - 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(Err(e))) => Err(e), - Ok(Async::NotReady) => Ok(Async::NotReady), - Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)), - } + fn poll(&mut self) -> Poll { + 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(Err(e))) => Err(e), + Ok(Async::NotReady) => Ok(Async::NotReady), + Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)), } } } diff --git a/src/client/connect/http.rs b/src/client/connect/http.rs index 3ad245a630..ed31beea60 100644 --- a/src/client/connect/http.rs +++ b/src/client/connect/http.rs @@ -15,7 +15,7 @@ use tokio_tcp::{TcpStream, ConnectFuture}; use tokio_timer::Delay; use super::{Connect, Connected, Destination}; -use super::dns::{self, GaiResolver, Resolve}; +use super::dns::{self, GaiResolver, Resolve, TokioThreadpoolGaiResolver}; /// A connector for the `http` scheme. /// @@ -99,6 +99,15 @@ impl HttpConnector { } } +impl HttpConnector { + /// 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 HttpConnector { /// Construct a new HttpConnector. diff --git a/src/client/connect/mod.rs b/src/client/connect/mod.rs index 31d5f4b904..4754f64c6c 100644 --- a/src/client/connect/mod.rs +++ b/src/client/connect/mod.rs @@ -13,9 +13,8 @@ use futures::Future; use http::{uri, Response, Uri}; use tokio_io::{AsyncRead, AsyncWrite}; -#[cfg(feature = "runtime")] mod dns; +#[cfg(feature = "runtime")] pub mod dns; #[cfg(feature = "runtime")] mod http; -#[cfg(feature = "runtime")] pub use self::dns::{GaiResolver, Name, Resolve}; #[cfg(feature = "runtime")] pub use self::http::{HttpConnector, HttpInfo}; /// Connect to a destination, returning an IO transport. diff --git a/src/lib.rs b/src/lib.rs index ad1f58f6a6..7077e83993 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,8 +30,8 @@ extern crate time; #[macro_use] extern crate tokio_io; #[cfg(feature = "runtime")] extern crate tokio_reactor; #[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_timer; extern crate want; #[cfg(all(test, feature = "nightly"))]