feat(lib): update Tokio, bytes, http, h2, and http-body
This commit is contained in:
@@ -30,6 +30,7 @@ use std::net::{
|
||||
};
|
||||
use std::str::FromStr;
|
||||
|
||||
use tokio::task::JoinHandle;
|
||||
use tower_service::Service;
|
||||
use crate::common::{Future, Pin, Poll, task};
|
||||
|
||||
@@ -54,7 +55,7 @@ pub struct GaiAddrs {
|
||||
|
||||
/// A future to resolve a name returned by `GaiResolver`.
|
||||
pub struct GaiFuture {
|
||||
inner: tokio_executor::blocking::Blocking<Result<IpAddrs, io::Error>>,
|
||||
inner: JoinHandle<Result<IpAddrs, io::Error>>,
|
||||
}
|
||||
|
||||
impl Name {
|
||||
@@ -123,7 +124,7 @@ impl Service<Name> for GaiResolver {
|
||||
}
|
||||
|
||||
fn call(&mut self, name: Name) -> Self::Future {
|
||||
let blocking = tokio_executor::blocking::run(move || {
|
||||
let blocking = tokio::task::spawn_blocking(move || {
|
||||
debug!("resolving host={:?}", name.host);
|
||||
(&*name.host, 0).to_socket_addrs()
|
||||
.map(|i| IpAddrs { iter: i })
|
||||
@@ -146,8 +147,9 @@ impl Future for GaiFuture {
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
||||
Pin::new(&mut self.inner).poll(cx).map(|res| match res {
|
||||
Ok(addrs) => Ok(GaiAddrs { inner: addrs }),
|
||||
Err(err) => Err(err),
|
||||
Ok(Ok(addrs)) => Ok(GaiAddrs { inner: addrs }),
|
||||
Ok(Err(err)) => Err(err),
|
||||
Err(join_err) => panic!("gai background task failed: {:?}", join_err),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -232,6 +234,7 @@ impl Iterator for IpAddrs {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/// A resolver using `getaddrinfo` calls via the `tokio_executor::threadpool::blocking` API.
|
||||
///
|
||||
/// Unlike the `GaiResolver` this will not spawn dedicated threads, but only works when running on the
|
||||
@@ -286,6 +289,7 @@ impl Future for TokioThreadpoolGaiFuture {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
mod sealed {
|
||||
use tower_service::Service;
|
||||
|
||||
@@ -7,17 +7,16 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use http::uri::{Scheme, Uri};
|
||||
use futures_util::{TryFutureExt, FutureExt};
|
||||
use futures_util::{TryFutureExt};
|
||||
use net2::TcpBuilder;
|
||||
use pin_project::{pin_project, project};
|
||||
use tokio_net::driver::Handle;
|
||||
use tokio_net::tcp::TcpStream;
|
||||
use tokio_timer::{Delay, Timeout};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::Delay;
|
||||
|
||||
use crate::common::{Future, Pin, Poll, task};
|
||||
use super::{Connected, Destination};
|
||||
use super::dns::{self, GaiResolver, Resolve};
|
||||
#[cfg(feature = "runtime")] use super::dns::TokioThreadpoolGaiResolver;
|
||||
//#[cfg(feature = "runtime")] use super::dns::TokioThreadpoolGaiResolver;
|
||||
|
||||
// TODO: unbox me?
|
||||
type ConnectFuture = Pin<Box<dyn Future<Output = io::Result<TcpStream>> + Send>>;
|
||||
@@ -73,7 +72,6 @@ pub struct HttpInfo {
|
||||
struct Config {
|
||||
connect_timeout: Option<Duration>,
|
||||
enforce_http: bool,
|
||||
handle: Option<Handle>,
|
||||
happy_eyeballs_timeout: Option<Duration>,
|
||||
keep_alive_timeout: Option<Duration>,
|
||||
local_address: Option<IpAddr>,
|
||||
@@ -92,6 +90,7 @@ impl HttpConnector {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(feature = "runtime")]
|
||||
impl HttpConnector<TokioThreadpoolGaiResolver> {
|
||||
/// Construct a new HttpConnector using the `TokioThreadpoolGaiResolver`.
|
||||
@@ -101,6 +100,7 @@ impl HttpConnector<TokioThreadpoolGaiResolver> {
|
||||
HttpConnector::new_with_resolver(TokioThreadpoolGaiResolver::new())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
impl<R> HttpConnector<R> {
|
||||
@@ -112,7 +112,6 @@ impl<R> HttpConnector<R> {
|
||||
config: Arc::new(Config {
|
||||
connect_timeout: None,
|
||||
enforce_http: true,
|
||||
handle: None,
|
||||
happy_eyeballs_timeout: Some(Duration::from_millis(300)),
|
||||
keep_alive_timeout: None,
|
||||
local_address: None,
|
||||
@@ -133,14 +132,6 @@ impl<R> HttpConnector<R> {
|
||||
self.config_mut().enforce_http = is_enforced;
|
||||
}
|
||||
|
||||
/// Set a handle to a `Reactor` to register connections to.
|
||||
///
|
||||
/// If `None`, the implicit default reactor will be used.
|
||||
#[inline]
|
||||
pub fn set_reactor(&mut self, handle: Option<Handle>) {
|
||||
self.config_mut().handle = handle;
|
||||
}
|
||||
|
||||
/// Set that all sockets have `SO_KEEPALIVE` set with the supplied duration.
|
||||
///
|
||||
/// If `None`, the option will not be set.
|
||||
@@ -276,10 +267,10 @@ where
|
||||
);
|
||||
|
||||
if self.config.enforce_http {
|
||||
if dst.uri.scheme_part() != Some(&Scheme::HTTP) {
|
||||
if dst.uri.scheme() != Some(&Scheme::HTTP) {
|
||||
return self.invalid_url(INVALID_NOT_HTTP);
|
||||
}
|
||||
} else if dst.uri.scheme_part().is_none() {
|
||||
} else if dst.uri.scheme().is_none() {
|
||||
return self.invalid_url(INVALID_MISSING_SCHEME);
|
||||
}
|
||||
|
||||
@@ -287,9 +278,9 @@ where
|
||||
Some(s) => s,
|
||||
None => return self.invalid_url(INVALID_MISSING_HOST),
|
||||
};
|
||||
let port = match dst.uri.port_part() {
|
||||
let port = match dst.uri.port() {
|
||||
Some(port) => port.as_u16(),
|
||||
None => if dst.uri.scheme_part() == Some(&Scheme::HTTPS) { 443 } else { 80 },
|
||||
None => if dst.uri.scheme() == Some(&Scheme::HTTPS) { 443 } else { 80 },
|
||||
};
|
||||
|
||||
HttpConnecting {
|
||||
@@ -314,10 +305,7 @@ where
|
||||
}
|
||||
|
||||
fn call(&mut self, uri: Uri) -> Self::Future {
|
||||
self
|
||||
.call(Destination { uri })
|
||||
.map_ok(|(s, _)| s)
|
||||
.boxed()
|
||||
Box::pin(self.call(Destination { uri }).map_ok(|(s, _)| s))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,7 +435,7 @@ impl<R: Resolve> Future for HttpConnecting<R> {
|
||||
config.local_address, addrs, config.connect_timeout, config.happy_eyeballs_timeout, config.reuse_address));
|
||||
},
|
||||
State::Connecting(ref mut c) => {
|
||||
let sock = ready!(c.poll(cx, &config.handle))
|
||||
let sock = ready!(c.poll(cx))
|
||||
.map_err(ConnectError::m("tcp connect error"))?;
|
||||
|
||||
if let Some(dur) = config.keep_alive_timeout {
|
||||
@@ -515,7 +503,7 @@ impl ConnectingTcp {
|
||||
local_addr,
|
||||
preferred: ConnectingTcpRemote::new(preferred_addrs, connect_timeout),
|
||||
fallback: Some(ConnectingTcpFallback {
|
||||
delay: tokio_timer::delay_for(fallback_timeout),
|
||||
delay: tokio::time::delay_for(fallback_timeout),
|
||||
remote: ConnectingTcpRemote::new(fallback_addrs, connect_timeout),
|
||||
}),
|
||||
reuse_address,
|
||||
@@ -555,12 +543,10 @@ impl ConnectingTcpRemote {
|
||||
}
|
||||
|
||||
impl ConnectingTcpRemote {
|
||||
// not a Future, since passing a &Handle to poll
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut task::Context<'_>,
|
||||
local_addr: &Option<IpAddr>,
|
||||
handle: &Option<Handle>,
|
||||
reuse_address: bool,
|
||||
) -> Poll<io::Result<TcpStream>> {
|
||||
let mut err = None;
|
||||
@@ -577,14 +563,14 @@ impl ConnectingTcpRemote {
|
||||
err = Some(e);
|
||||
if let Some(addr) = self.addrs.next() {
|
||||
debug!("connecting to {}", addr);
|
||||
*current = connect(&addr, local_addr, handle, reuse_address, self.connect_timeout)?;
|
||||
*current = connect(&addr, local_addr, reuse_address, self.connect_timeout)?;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(addr) = self.addrs.next() {
|
||||
debug!("connecting to {}", addr);
|
||||
self.current = Some(connect(&addr, local_addr, handle, reuse_address, self.connect_timeout)?);
|
||||
self.current = Some(connect(&addr, local_addr, reuse_address, self.connect_timeout)?);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -596,7 +582,6 @@ impl ConnectingTcpRemote {
|
||||
fn connect(
|
||||
addr: &SocketAddr,
|
||||
local_addr: &Option<IpAddr>,
|
||||
handle: &Option<Handle>,
|
||||
reuse_address: bool,
|
||||
connect_timeout: Option<Duration>,
|
||||
) -> io::Result<ConnectFuture> {
|
||||
@@ -625,18 +610,14 @@ fn connect(
|
||||
builder.bind(any)?;
|
||||
}
|
||||
|
||||
let handle = match *handle {
|
||||
Some(ref handle) => handle.clone(),
|
||||
None => Handle::default(),
|
||||
};
|
||||
let addr = *addr;
|
||||
|
||||
let std_tcp = builder.to_tcp_stream()?;
|
||||
|
||||
Ok(Box::pin(async move {
|
||||
let connect = TcpStream::connect_std(std_tcp, &addr, &handle);
|
||||
let connect = TcpStream::connect_std(std_tcp, &addr);
|
||||
match connect_timeout {
|
||||
Some(timeout) => match Timeout::new(connect, timeout).await {
|
||||
Some(dur) => match tokio::time::timeout(dur, connect).await {
|
||||
Ok(Ok(s)) => Ok(s),
|
||||
Ok(Err(e)) => Err(e),
|
||||
Err(e) => Err(io::Error::new(io::ErrorKind::TimedOut, e)),
|
||||
@@ -647,16 +628,16 @@ fn connect(
|
||||
}
|
||||
|
||||
impl ConnectingTcp {
|
||||
fn poll(&mut self, cx: &mut task::Context<'_>, handle: &Option<Handle>) -> Poll<io::Result<TcpStream>> {
|
||||
fn poll(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<TcpStream>> {
|
||||
match self.fallback.take() {
|
||||
None => self.preferred.poll(cx, &self.local_addr, handle, self.reuse_address),
|
||||
Some(mut fallback) => match self.preferred.poll(cx, &self.local_addr, handle, self.reuse_address) {
|
||||
None => self.preferred.poll(cx, &self.local_addr, self.reuse_address),
|
||||
Some(mut fallback) => match self.preferred.poll(cx, &self.local_addr, self.reuse_address) {
|
||||
Poll::Ready(Ok(stream)) => {
|
||||
// Preferred successful - drop fallback.
|
||||
Poll::Ready(Ok(stream))
|
||||
}
|
||||
Poll::Pending => match Pin::new(&mut fallback.delay).poll(cx) {
|
||||
Poll::Ready(()) => match fallback.remote.poll(cx, &self.local_addr, handle, self.reuse_address) {
|
||||
Poll::Ready(()) => match fallback.remote.poll(cx, &self.local_addr, self.reuse_address) {
|
||||
Poll::Ready(Ok(stream)) => {
|
||||
// Fallback successful - drop current preferred,
|
||||
// but keep fallback as new preferred.
|
||||
@@ -682,7 +663,7 @@ impl ConnectingTcp {
|
||||
Poll::Ready(Err(_)) => {
|
||||
// Preferred failed - use fallback as new preferred.
|
||||
self.preferred = fallback.remote;
|
||||
self.preferred.poll(cx, &self.local_addr, handle, self.reuse_address)
|
||||
self.preferred.poll(cx, &self.local_addr, self.reuse_address)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -693,8 +674,6 @@ impl ConnectingTcp {
|
||||
mod tests {
|
||||
use std::io;
|
||||
|
||||
use tokio_net::driver::Handle;
|
||||
|
||||
use super::{Connected, Destination, HttpConnector};
|
||||
use super::super::sealed::Connect;
|
||||
|
||||
@@ -738,8 +717,6 @@ mod tests {
|
||||
use std::task::Poll;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use tokio::runtime::current_thread::Runtime;
|
||||
|
||||
use crate::common::{Pin, task};
|
||||
use super::dns;
|
||||
use super::ConnectingTcp;
|
||||
@@ -748,7 +725,12 @@ mod tests {
|
||||
let server4 = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let addr = server4.local_addr().unwrap();
|
||||
let _server6 = TcpListener::bind(&format!("[::1]:{}", addr.port())).unwrap();
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
let mut rt = tokio::runtime::Builder::new()
|
||||
.enable_io()
|
||||
.enable_time()
|
||||
.basic_scheduler()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let local_timeout = Duration::default();
|
||||
let unreachable_v4_timeout = measure_connect(unreachable_ipv4_addr()).1;
|
||||
@@ -804,12 +786,13 @@ mod tests {
|
||||
}
|
||||
|
||||
let addrs = hosts.iter().map(|host| (host.clone(), addr.port()).into()).collect();
|
||||
let connecting_tcp = ConnectingTcp::new(None, dns::IpAddrs::new(addrs), None, Some(fallback_timeout), false);
|
||||
let fut = ConnectingTcpFuture(connecting_tcp);
|
||||
|
||||
let start = Instant::now();
|
||||
let res = rt.block_on(fut).unwrap();
|
||||
let duration = start.elapsed();
|
||||
let (res, duration) = rt.block_on(async move {
|
||||
let connecting_tcp = ConnectingTcp::new(None, dns::IpAddrs::new(addrs), None, Some(fallback_timeout), false);
|
||||
let fut = ConnectingTcpFuture(connecting_tcp);
|
||||
let start = Instant::now();
|
||||
let res = fut.await.unwrap();
|
||||
(res, start.elapsed())
|
||||
});
|
||||
|
||||
// Allow actual duration to be +/- 150ms off.
|
||||
let min_duration = if timeout >= Duration::from_millis(150) {
|
||||
@@ -830,7 +813,7 @@ mod tests {
|
||||
type Output = Result<u8, std::io::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
||||
match self.0.poll(cx,&Some(Handle::default())) {
|
||||
match self.0.poll(cx) {
|
||||
Poll::Ready(Ok(stream)) => Poll::Ready(Ok(
|
||||
if stream.peer_addr().unwrap().is_ipv4() { 4 } else { 6 }
|
||||
)),
|
||||
|
||||
@@ -50,8 +50,8 @@ impl Destination {
|
||||
/// Returns an error if the uri contains no authority or
|
||||
/// no scheme.
|
||||
pub fn try_from_uri(uri: Uri) -> crate::Result<Self> {
|
||||
uri.authority_part().ok_or(crate::error::Parse::Uri)?;
|
||||
uri.scheme_part().ok_or(crate::error::Parse::Uri)?;
|
||||
uri.authority().ok_or(crate::error::Parse::Uri)?;
|
||||
uri.scheme().ok_or(crate::error::Parse::Uri)?;
|
||||
Ok(Destination { uri })
|
||||
}
|
||||
|
||||
@@ -131,11 +131,11 @@ impl Destination {
|
||||
}
|
||||
let auth = if let Some(port) = self.port() {
|
||||
let bytes = Bytes::from(format!("{}:{}", host, port));
|
||||
uri::Authority::from_shared(bytes)
|
||||
uri::Authority::from_maybe_shared(bytes)
|
||||
.map_err(crate::error::Parse::from)?
|
||||
} else {
|
||||
let auth = host.parse::<uri::Authority>().map_err(crate::error::Parse::from)?;
|
||||
if auth.port_part().is_some() { // std::uri::Authority::Uri
|
||||
if auth.port().is_some() { // std::uri::Authority::Uri
|
||||
return Err(crate::error::Parse::Uri.into());
|
||||
}
|
||||
auth
|
||||
@@ -186,7 +186,7 @@ impl Destination {
|
||||
write!(buf, "{}", port)
|
||||
.expect("should have space for 5 digits");
|
||||
|
||||
uri::Authority::from_shared(buf.freeze())
|
||||
uri::Authority::from_maybe_shared(buf.freeze())
|
||||
.expect("valid host + :port should be valid authority")
|
||||
} else {
|
||||
self.host().parse()
|
||||
@@ -372,7 +372,7 @@ where
|
||||
pub(super) mod sealed {
|
||||
use std::error::Error as StdError;
|
||||
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use crate::common::{Future, Unpin};
|
||||
use super::{Connected, Destination};
|
||||
|
||||
Reference in New Issue
Block a user