feat(lib): update to std::future::Future
				
					
				
			BREAKING CHANGE: All usage of async traits (`Future`, `Stream`, `AsyncRead`, `AsyncWrite`, etc) are updated to newer versions.
This commit is contained in:
		
							
								
								
									
										34
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,32 +1,34 @@ | ||||
| language: rust | ||||
| sudo: true # Required for functional IPv6 (forces VM instead of Docker). | ||||
| #sudo: true # Required for functional IPv6 (forces VM instead of Docker). | ||||
| dist: trusty | ||||
| matrix: | ||||
|     fast_finish: true | ||||
|     include: | ||||
|         - rust: nightly | ||||
|           env: FEATURES="--no-default-features --features runtime,nightly" | ||||
|         - rust: beta | ||||
|           env: FEATURES="--no-default-features --features runtime,__internal_happy_eyeballs_tests" | ||||
|         - rust: stable | ||||
|           env: FEATURES="--no-default-features --features runtime,__internal_happy_eyeballs_tests" | ||||
|         - rust: stable | ||||
|           env: FEATURES="--no-default-features" | ||||
|         # Dependencies may be using the unstable `async_await` feature for now... | ||||
|         #- rust: beta | ||||
|         #  env: FEATURES="--no-default-features --features runtime,__internal_happy_eyeballs_tests" | ||||
|         #- rust: stable | ||||
|         #  env: FEATURES="--no-default-features --features runtime,__internal_happy_eyeballs_tests" | ||||
|         #- rust: stable | ||||
|         #  env: FEATURES="--no-default-features" | ||||
|         # Minimum Supported Rust Version | ||||
|         - rust: 1.31.0 | ||||
|           env: FEATURES="--no-default-features --features runtime" BUILD_ONLY="1" | ||||
|         #- rust: 1.36.0 | ||||
|         #  env: FEATURES="--no-default-features --features runtime" BUILD_ONLY="1" | ||||
|  | ||||
| before_script: | ||||
| #before_script: | ||||
|   # Add an IPv6 config - see the corresponding Travis issue | ||||
|   # https://github.com/travis-ci/travis-ci/issues/8361 | ||||
|   - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then | ||||
|       sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'; | ||||
|     fi | ||||
|   # https://github.com/travis-ci/travis-ci/issues/83 | ||||
|   #- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then | ||||
|   #    sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'; | ||||
|   #  fi | ||||
|  | ||||
| script: | ||||
|   - cargo build $FEATURES | ||||
|   - 'if [ "$BUILD_ONLY" != "1" ]; then cargo test $FEATURES -- --test-threads=1; fi' | ||||
|   - 'if [ $TRAVIS_RUST_VERSION = nightly ]; then for f in ./benches/*.rs; do cargo test --bench $(basename $f .rs) $FEATURES; done; fi' | ||||
|   # Disable tests temporarily | ||||
|   # - 'if [ "$BUILD_ONLY" != "1" ]; then cargo test $FEATURES -- --test-threads=1; fi' | ||||
|   # - 'if [ $TRAVIS_RUST_VERSION = nightly ]; then for f in ./benches/*.rs; do cargo test --bench $(basename $f .rs) $FEATURES; done; fi' | ||||
|  | ||||
| env: | ||||
|     global: | ||||
|   | ||||
							
								
								
									
										30
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								Cargo.toml
									
									
									
									
									
								
							| @@ -23,8 +23,9 @@ include = [ | ||||
|  | ||||
| [dependencies] | ||||
| bytes = "0.4.4" | ||||
| futures = "0.1.21" | ||||
| futures-cpupool = { version = "0.1.6", optional = true } | ||||
| futures-core-preview = { version = "0.3.0-alpha.16" } | ||||
| futures-channel-preview = { version = "0.3.0-alpha.16" } | ||||
| futures-util-preview = { version = "0.3.0-alpha.16" } | ||||
| http = "0.1.15" | ||||
| http-body = "0.1" | ||||
| httparse = "1.0" | ||||
| @@ -33,28 +34,30 @@ iovec = "0.1" | ||||
| itoa = "0.4.1" | ||||
| log = "0.4" | ||||
| net2 = { version = "0.2.32", optional = true } | ||||
| pin-utils = "0.1.0-alpha.4" | ||||
| time = "0.1" | ||||
| tokio = { version = "0.1.14", optional = true, default-features = false, features = ["rt-full"] } | ||||
| tokio = { git = "https://github.com/tokio-rs/tokio", optional = true, default-features = false, features = ["rt-full"] } | ||||
| tokio-buf = "0.1" | ||||
| 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 } | ||||
| want = "0.2" | ||||
| tokio-executor = { git = "https://github.com/tokio-rs/tokio", optional = true } | ||||
| tokio-io = { git = "https://github.com/tokio-rs/tokio" } | ||||
| tokio-reactor = { git = "https://github.com/tokio-rs/tokio", optional = true } | ||||
| tokio-sync = { git = "https://github.com/tokio-rs/tokio" } | ||||
| tokio-tcp = { git = "https://github.com/tokio-rs/tokio", optional = true } | ||||
| tokio-threadpool = { git = "https://github.com/tokio-rs/tokio", optional = true } | ||||
| tokio-timer = { git = "https://github.com/tokio-rs/tokio", optional = true } | ||||
| want = { git = "https://github.com/seanmonstar/want", branch = "std-future" } | ||||
|  | ||||
| [build-dependencies] | ||||
| rustc_version = "0.2" | ||||
|  | ||||
| [dev-dependencies] | ||||
| futures-timer = "0.1" | ||||
| #futures-timer = "0.1" | ||||
| num_cpus = "1.0" | ||||
| pretty_env_logger = "0.3" | ||||
| spmc = "0.2" | ||||
| url = "1.0" | ||||
| tokio-fs = "0.1" | ||||
| tokio-mockstream = "1.1.0" | ||||
| #tokio-fs = "0.1" | ||||
| #tokio-mockstream = "1.1.0" | ||||
| serde = "1.0" | ||||
| serde_derive = "1.0" | ||||
| serde_json = "1.0" | ||||
| @@ -65,7 +68,6 @@ default = [ | ||||
|     "runtime", | ||||
| ] | ||||
| runtime = [ | ||||
|     "futures-cpupool", | ||||
|     "net2", | ||||
|     "tokio", | ||||
|     "tokio-executor", | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| #![feature(async_await)] | ||||
| #![deny(warnings)] | ||||
| extern crate hyper; | ||||
| extern crate pretty_env_logger; | ||||
| @@ -6,7 +7,7 @@ use std::env; | ||||
| use std::io::{self, Write}; | ||||
|  | ||||
| use hyper::Client; | ||||
| use hyper::rt::{self, Future, Stream}; | ||||
| use hyper::rt; | ||||
|  | ||||
| fn main() { | ||||
|     pretty_env_logger::init(); | ||||
| @@ -35,31 +36,34 @@ fn main() { | ||||
|     rt::run(fetch_url(url)); | ||||
| } | ||||
|  | ||||
| fn fetch_url(url: hyper::Uri) -> impl Future<Item=(), Error=()> { | ||||
| async fn fetch_url(url: hyper::Uri) { | ||||
|     let client = Client::new(); | ||||
|  | ||||
|     client | ||||
|         // Fetch the url... | ||||
|         .get(url) | ||||
|         // And then, if we get a response back... | ||||
|         .and_then(|res| { | ||||
|             println!("Response: {}", res.status()); | ||||
|             println!("Headers: {:#?}", res.headers()); | ||||
|     let res = match client.get(url).await { | ||||
|         Ok(res) => res, | ||||
|         Err(err) => { | ||||
|             eprintln!("Response Error: {}", err); | ||||
|             return; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|             // The body is a stream, and for_each returns a new Future | ||||
|             // when the stream is finished, and calls the closure on | ||||
|             // each chunk of the body... | ||||
|             res.into_body().for_each(|chunk| { | ||||
|     println!("Response: {}", res.status()); | ||||
|     println!("Headers: {:#?}\n", res.headers()); | ||||
|  | ||||
|     let mut body = res.into_body(); | ||||
|  | ||||
|     while let Some(next) = body.next().await { | ||||
|         match next { | ||||
|             Ok(chunk) => { | ||||
|                 io::stdout().write_all(&chunk) | ||||
|                     .map_err(|e| panic!("example expects stdout is open, error={}", e)) | ||||
|             }) | ||||
|         }) | ||||
|         // If all good, just tell the user... | ||||
|         .map(|_| { | ||||
|             println!("\n\nDone."); | ||||
|         }) | ||||
|         // If there was an error, let the user know... | ||||
|         .map_err(|err| { | ||||
|             eprintln!("Error {}", err); | ||||
|         }) | ||||
|                     .expect("example expects stdout is open"); | ||||
|             }, | ||||
|             Err(err) => { | ||||
|                 eprintln!("Body Error: {}", err); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     println!("\n\nDone!"); | ||||
| } | ||||
|   | ||||
| @@ -1,27 +1,38 @@ | ||||
| #![feature(async_await)] | ||||
| #![deny(warnings)] | ||||
| extern crate hyper; | ||||
| extern crate pretty_env_logger; | ||||
|  | ||||
| use hyper::{Body, Request, Response, Server}; | ||||
| use hyper::service::service_fn_ok; | ||||
| use hyper::rt::{self, Future}; | ||||
| use hyper::service::{make_service_fn, service_fn}; | ||||
| use hyper::rt; | ||||
|  | ||||
| fn main() { | ||||
|     pretty_env_logger::init(); | ||||
| async fn hello(_: Request<Body>) -> Result<Response<Body>, hyper::Error> { | ||||
|     Ok(Response::new(Body::from("Hello World!"))) | ||||
| } | ||||
|  | ||||
| async fn serve() { | ||||
|     let addr = ([127, 0, 0, 1], 3000).into(); | ||||
|  | ||||
|     let server = Server::bind(&addr) | ||||
|         .serve(|| { | ||||
|         .serve(make_service_fn(|_| { | ||||
|             // This is the `Service` that will handle the connection. | ||||
|             // `service_fn_ok` is a helper to convert a function that | ||||
|             // returns a Response into a `Service`. | ||||
|             service_fn_ok(move |_: Request<Body>| { | ||||
|                 Response::new(Body::from("Hello World!")) | ||||
|             }) | ||||
|         }) | ||||
|         .map_err(|e| eprintln!("server error: {}", e)); | ||||
|             async { | ||||
|                 Ok::<_, hyper::Error>(service_fn(hello)) | ||||
|             } | ||||
|         })); | ||||
|  | ||||
|     println!("Listening on http://{}", addr); | ||||
|  | ||||
|     rt::run(server); | ||||
|     if let Err(e) = server.await { | ||||
|         eprintln!("server error: {}", e); | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn main() { | ||||
|     pretty_env_logger::init(); | ||||
|  | ||||
|     rt::run(serve()); | ||||
| } | ||||
|   | ||||
							
								
								
									
										294
									
								
								src/body/body.rs
									
									
									
									
									
								
							
							
						
						
									
										294
									
								
								src/body/body.rs
									
									
									
									
									
								
							| @@ -3,13 +3,13 @@ use std::error::Error as StdError; | ||||
| use std::fmt; | ||||
|  | ||||
| use bytes::Bytes; | ||||
| use futures::sync::{mpsc, oneshot}; | ||||
| use futures::{Async, Future, Poll, Stream, Sink, AsyncSink, StartSend}; | ||||
| use futures_core::Stream; | ||||
| use futures_channel::{mpsc, oneshot}; | ||||
| use tokio_buf::SizeHint; | ||||
| use h2; | ||||
| use http::HeaderMap; | ||||
|  | ||||
| use crate::common::Never; | ||||
| use crate::common::{Future, Never, Pin, Poll, task}; | ||||
| use super::internal::{FullDataArg, FullDataRet}; | ||||
| use super::{Chunk, Payload}; | ||||
| use crate::upgrade::OnUpgrade; | ||||
| @@ -40,7 +40,7 @@ enum Kind { | ||||
|         content_length: Option<u64>, | ||||
|         recv: h2::RecvStream, | ||||
|     }, | ||||
|     Wrapped(Box<dyn Stream<Item = Chunk, Error = Box<dyn StdError + Send + Sync>> + Send>), | ||||
|     Wrapped(Pin<Box<dyn Stream<Item = Result<Chunk, Box<dyn StdError + Send + Sync>>> + Send>>), | ||||
| } | ||||
|  | ||||
| struct Extra { | ||||
| @@ -119,6 +119,7 @@ impl Body { | ||||
|         (tx, rx) | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     /// Wrap a futures `Stream` in a box inside `Body`. | ||||
|     /// | ||||
|     /// # Example | ||||
| @@ -148,6 +149,12 @@ impl Body { | ||||
|         let mapped = stream.map(Chunk::from).map_err(Into::into); | ||||
|         Body::new(Kind::Wrapped(Box::new(mapped))) | ||||
|     } | ||||
|     */ | ||||
|  | ||||
|     /// dox | ||||
|     pub async fn next(&mut self) -> Option<crate::Result<Chunk>> { | ||||
|         futures_util::future::poll_fn(|cx| self.poll_eof(cx)).await | ||||
|     } | ||||
|  | ||||
|     /// Converts this `Body` into a `Future` of a pending HTTP upgrade. | ||||
|     /// | ||||
| @@ -200,83 +207,91 @@ impl Body { | ||||
|             })) | ||||
|     } | ||||
|  | ||||
|     fn poll_eof(&mut self) -> Poll<Option<Chunk>, crate::Error> { | ||||
|     fn poll_eof(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<crate::Result<Chunk>>> { | ||||
|         match self.take_delayed_eof() { | ||||
|             Some(DelayEof::NotEof(mut delay)) => { | ||||
|                 match self.poll_inner() { | ||||
|                     ok @ Ok(Async::Ready(Some(..))) | | ||||
|                     ok @ Ok(Async::NotReady) => { | ||||
|                 match self.poll_inner(cx) { | ||||
|                     ok @ Poll::Ready(Some(Ok(..))) | | ||||
|                     ok @ Poll::Pending => { | ||||
|                         self.extra_mut().delayed_eof = Some(DelayEof::NotEof(delay)); | ||||
|                         ok | ||||
|                     }, | ||||
|                     Ok(Async::Ready(None)) => match delay.poll() { | ||||
|                         Ok(Async::Ready(never)) => match never {}, | ||||
|                         Ok(Async::NotReady) => { | ||||
|                     Poll::Ready(None) => match Pin::new(&mut delay).poll(cx) { | ||||
|                         Poll::Ready(Ok(never)) => match never {}, | ||||
|                         Poll::Pending => { | ||||
|                             self.extra_mut().delayed_eof = Some(DelayEof::Eof(delay)); | ||||
|                             Ok(Async::NotReady) | ||||
|                             Poll::Pending | ||||
|                         }, | ||||
|                         Err(_done) => { | ||||
|                             Ok(Async::Ready(None)) | ||||
|                         Poll::Ready(Err(_done)) => { | ||||
|                             Poll::Ready(None) | ||||
|                         }, | ||||
|                     }, | ||||
|                     Err(e) => Err(e), | ||||
|                     Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))), | ||||
|                 } | ||||
|             }, | ||||
|             Some(DelayEof::Eof(mut delay)) => { | ||||
|                 match delay.poll() { | ||||
|                     Ok(Async::Ready(never)) => match never {}, | ||||
|                     Ok(Async::NotReady) => { | ||||
|                 match Pin::new(&mut delay).poll(cx) { | ||||
|                     Poll::Ready(Ok(never)) => match never {}, | ||||
|                     Poll::Pending => { | ||||
|                         self.extra_mut().delayed_eof = Some(DelayEof::Eof(delay)); | ||||
|                         Ok(Async::NotReady) | ||||
|                         Poll::Pending | ||||
|                     }, | ||||
|                     Err(_done) => { | ||||
|                         Ok(Async::Ready(None)) | ||||
|                     Poll::Ready(Err(_done)) => { | ||||
|                         Poll::Ready(None) | ||||
|                     }, | ||||
|                 } | ||||
|             }, | ||||
|             None => self.poll_inner(), | ||||
|             None => self.poll_inner(cx), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn poll_inner(&mut self) -> Poll<Option<Chunk>, crate::Error> { | ||||
|     fn poll_inner(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<crate::Result<Chunk>>> { | ||||
|         match self.kind { | ||||
|             Kind::Once(ref mut val) => Ok(Async::Ready(val.take())), | ||||
|             Kind::Once(ref mut val) => Poll::Ready(val.take().map(Ok)), | ||||
|             Kind::Chan { | ||||
|                 content_length: ref mut len, | ||||
|                 ref mut rx, | ||||
|                 ref mut abort_rx, | ||||
|             } => { | ||||
|                 if let Ok(Async::Ready(())) = abort_rx.poll() { | ||||
|                     return Err(crate::Error::new_body_write("body write aborted")); | ||||
|                 if let Poll::Ready(Ok(())) = Pin::new(abort_rx).poll(cx) { | ||||
|                     return Poll::Ready(Some(Err(crate::Error::new_body_write("body write aborted")))); | ||||
|                 } | ||||
|  | ||||
|                 match rx.poll().expect("mpsc cannot error") { | ||||
|                     Async::Ready(Some(Ok(chunk))) => { | ||||
|                 match ready!(Pin::new(rx).poll_next(cx)?) { | ||||
|                     Some(chunk) => { | ||||
|                         if let Some(ref mut len) = *len { | ||||
|                             debug_assert!(*len >= chunk.len() as u64); | ||||
|                             *len = *len - chunk.len() as u64; | ||||
|                         } | ||||
|                         Ok(Async::Ready(Some(chunk))) | ||||
|                         Poll::Ready(Some(Ok(chunk))) | ||||
|                     } | ||||
|                     Async::Ready(Some(Err(err))) => Err(err), | ||||
|                     Async::Ready(None) => Ok(Async::Ready(None)), | ||||
|                     Async::NotReady => Ok(Async::NotReady), | ||||
|                     None => Poll::Ready(None), | ||||
|                 } | ||||
|             } | ||||
|             Kind::H2 { | ||||
|                 recv: ref mut h2, .. | ||||
|             } => h2 | ||||
|                 .poll() | ||||
|                 .map(|r#async| { | ||||
|                     r#async.map(|opt| { | ||||
|                         opt.map(|bytes| { | ||||
|                             let _ = h2.release_capacity().release_capacity(bytes.len()); | ||||
|                             Chunk::from(bytes) | ||||
|                 /*recv: ref mut h2,*/ .. | ||||
|             } => { | ||||
|                 unimplemented!("h2.poll_inner"); | ||||
|                 /* | ||||
|                 h2 | ||||
|                     .poll() | ||||
|                     .map(|r#async| { | ||||
|                         r#async.map(|opt| { | ||||
|                             opt.map(|bytes| { | ||||
|                                 let _ = h2.release_capacity().release_capacity(bytes.len()); | ||||
|                                 Chunk::from(bytes) | ||||
|                             }) | ||||
|                         }) | ||||
|                     }) | ||||
|                 }) | ||||
|                 .map_err(crate::Error::new_body), | ||||
|             Kind::Wrapped(ref mut s) => s.poll().map_err(crate::Error::new_body), | ||||
|                     .map_err(crate::Error::new_body) | ||||
|                     */ | ||||
|             } | ||||
|             Kind::Wrapped(ref mut s) => { | ||||
|                 match ready!(s.as_mut().poll_next(cx)) { | ||||
|                     Some(res) => Poll::Ready(Some(res.map_err(crate::Error::new_body))), | ||||
|                     None => Poll::Ready(None), | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -293,16 +308,17 @@ impl Payload for Body { | ||||
|     type Data = Chunk; | ||||
|     type Error = crate::Error; | ||||
|  | ||||
|     fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> { | ||||
|         self.poll_eof() | ||||
|     fn poll_data(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Result<Self::Data, Self::Error>>> { | ||||
|         self.poll_eof(cx) | ||||
|     } | ||||
|  | ||||
|     fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> { | ||||
|     fn poll_trailers(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Result<HeaderMap, Self::Error>>> { | ||||
|         match self.kind { | ||||
|             Kind::H2 { | ||||
|                 recv: ref mut h2, .. | ||||
|             } => h2.poll_trailers().map_err(crate::Error::new_h2), | ||||
|             _ => Ok(Async::Ready(None)), | ||||
|             Kind::H2 { /*recv: ref mut h2,*/ .. } => { | ||||
|                 unimplemented!("h2.poll_trailers"); | ||||
|                 //h2.poll_trailers().map_err(crate::Error::new_h2) | ||||
|             }, | ||||
|             _ => Poll::Ready(None), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -334,6 +350,27 @@ impl Payload for Body { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Debug for Body { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         #[derive(Debug)] | ||||
|         struct Streaming; | ||||
|         #[derive(Debug)] | ||||
|         struct Empty; | ||||
|         #[derive(Debug)] | ||||
|         struct Once<'a>(&'a Chunk); | ||||
|  | ||||
|         let mut builder = f.debug_tuple("Body"); | ||||
|         match self.kind { | ||||
|             Kind::Once(None) => builder.field(&Empty), | ||||
|             Kind::Once(Some(ref chunk)) => builder.field(&Once(chunk)), | ||||
|             _ => builder.field(&Streaming), | ||||
|         }; | ||||
|  | ||||
|         builder.finish() | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| impl ::http_body::Body for Body { | ||||
|     type Data = Chunk; | ||||
|     type Error = crate::Error; | ||||
| @@ -363,86 +400,28 @@ impl ::http_body::Body for Body { | ||||
|         hint | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
| impl Stream for Body { | ||||
|     type Item = Chunk; | ||||
|     type Error = crate::Error; | ||||
|     type Item = crate::Result<Chunk>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { | ||||
|         self.poll_data() | ||||
|     fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> { | ||||
|         self.poll_data(cx) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Debug for Body { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         #[derive(Debug)] | ||||
|         struct Streaming; | ||||
|         #[derive(Debug)] | ||||
|         struct Empty; | ||||
|         #[derive(Debug)] | ||||
|         struct Once<'a>(&'a Chunk); | ||||
|  | ||||
|         let mut builder = f.debug_tuple("Body"); | ||||
|         match self.kind { | ||||
|             Kind::Once(None) => builder.field(&Empty), | ||||
|             Kind::Once(Some(ref chunk)) => builder.field(&Once(chunk)), | ||||
|             _ => builder.field(&Streaming), | ||||
|         }; | ||||
|  | ||||
|         builder.finish() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Sender { | ||||
|     /// Check to see if this `Sender` can send more data. | ||||
|     pub fn poll_ready(&mut self) -> Poll<(), crate::Error> { | ||||
|         match self.abort_tx.poll_cancel() { | ||||
|             Ok(Async::Ready(())) | Err(_) => return Err(crate::Error::new_closed()), | ||||
|             Ok(Async::NotReady) => (), | ||||
|         } | ||||
|  | ||||
|         self.tx.poll_ready().map_err(|_| crate::Error::new_closed()) | ||||
|     } | ||||
|  | ||||
|     /// Sends data on this channel. | ||||
|     /// | ||||
|     /// This should be called after `poll_ready` indicated the channel | ||||
|     /// could accept another `Chunk`. | ||||
|     /// | ||||
|     /// Returns `Err(Chunk)` if the channel could not (currently) accept | ||||
|     /// another `Chunk`. | ||||
|     pub fn send_data(&mut self, chunk: Chunk) -> Result<(), Chunk> { | ||||
|         self.tx | ||||
|             .try_send(Ok(chunk)) | ||||
|             .map_err(|err| err.into_inner().expect("just sent Ok")) | ||||
|     } | ||||
|  | ||||
|     /// Aborts the body in an abnormal fashion. | ||||
|     pub fn abort(self) { | ||||
|         let _ = self.abort_tx.send(()); | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn send_error(&mut self, err: crate::Error) { | ||||
|         let _ = self.tx.try_send(Err(err)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Sink for Sender { | ||||
|     type SinkItem = Chunk; | ||||
|     type SinkError = crate::Error; | ||||
|  | ||||
|     fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { | ||||
|         Ok(Async::Ready(())) | ||||
|     } | ||||
|  | ||||
|     fn start_send(&mut self, msg: Chunk) -> StartSend<Self::SinkItem, Self::SinkError> { | ||||
|         match self.poll_ready()? { | ||||
|             Async::Ready(_) => { | ||||
|                 self.send_data(msg).map_err(|_| crate::Error::new_closed())?; | ||||
|                 Ok(AsyncSink::Ready) | ||||
|             } | ||||
|             Async::NotReady => Ok(AsyncSink::NotReady(msg)), | ||||
|         } | ||||
| impl | ||||
|     From<Box<dyn Stream<Item = Result<Chunk, Box<dyn StdError + Send + Sync>>> + Send>> | ||||
|     for Body | ||||
| { | ||||
|     #[inline] | ||||
|     fn from( | ||||
|         stream: Box< | ||||
|             dyn Stream<Item = Result<Chunk, Box<dyn StdError + Send + Sync>>> + Send, | ||||
|         >, | ||||
|     ) -> Body { | ||||
|         Body::new(Kind::Wrapped(stream.into())) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -457,20 +436,6 @@ impl From<Chunk> for Body { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl | ||||
|     From<Box<dyn Stream<Item = Chunk, Error = Box<dyn StdError + Send + Sync>> + Send + 'static>> | ||||
|     for Body | ||||
| { | ||||
|     #[inline] | ||||
|     fn from( | ||||
|         stream: Box< | ||||
|             dyn Stream<Item = Chunk, Error = Box<dyn StdError + Send + Sync>> + Send + 'static, | ||||
|         >, | ||||
|     ) -> Body { | ||||
|         Body::new(Kind::Wrapped(stream)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Bytes> for Body { | ||||
|     #[inline] | ||||
|     fn from(bytes: Bytes) -> Body { | ||||
| @@ -526,6 +491,61 @@ impl From<Cow<'static, str>> for Body { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Sender { | ||||
|     /// Check to see if this `Sender` can send more data. | ||||
|     pub fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         match self.abort_tx.poll_cancel(cx) { | ||||
|             Poll::Ready(()) => return Poll::Ready(Err(crate::Error::new_closed())), | ||||
|             Poll::Pending => (), // fallthrough | ||||
|         } | ||||
|  | ||||
|         self.tx.poll_ready(cx).map_err(|_| crate::Error::new_closed()) | ||||
|     } | ||||
|  | ||||
|     /// Sends data on this channel. | ||||
|     /// | ||||
|     /// This should be called after `poll_ready` indicated the channel | ||||
|     /// could accept another `Chunk`. | ||||
|     /// | ||||
|     /// Returns `Err(Chunk)` if the channel could not (currently) accept | ||||
|     /// another `Chunk`. | ||||
|     pub fn send_data(&mut self, chunk: Chunk) -> Result<(), Chunk> { | ||||
|         self.tx | ||||
|             .try_send(Ok(chunk)) | ||||
|             .map_err(|err| err.into_inner().expect("just sent Ok")) | ||||
|     } | ||||
|  | ||||
|     /// Aborts the body in an abnormal fashion. | ||||
|     pub fn abort(self) { | ||||
|         let _ = self.abort_tx.send(()); | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn send_error(&mut self, err: crate::Error) { | ||||
|         let _ = self.tx.try_send(Err(err)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| impl Sink for Sender { | ||||
|     type SinkItem = Chunk; | ||||
|     type SinkError = crate::Error; | ||||
|  | ||||
|     fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { | ||||
|         Poll::Ready(Ok(())) | ||||
|     } | ||||
|  | ||||
|     fn start_send(&mut self, msg: Chunk) -> StartSend<Self::SinkItem, Self::SinkError> { | ||||
|         match self.poll_ready()? { | ||||
|             Async::Ready(_) => { | ||||
|                 self.send_data(msg).map_err(|_| crate::Error::new_closed())?; | ||||
|                 Ok(AsyncSink::Ready) | ||||
|             } | ||||
|             Async::NotReady => Ok(AsyncSink::NotReady(msg)), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
| #[test] | ||||
| fn test_body_stream_concat() { | ||||
|     let body = Body::from("hello world"); | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| use std::error::Error as StdError; | ||||
|  | ||||
| use bytes::Buf; | ||||
| use futures::{Async, Poll}; | ||||
| use http::HeaderMap; | ||||
|  | ||||
| use crate::common::{Pin, Poll, task}; | ||||
| use super::internal::{FullDataArg, FullDataRet}; | ||||
|  | ||||
| /// This trait represents a streaming body of a `Request` or `Response`. | ||||
| @@ -21,15 +21,15 @@ pub trait Payload: Send + 'static { | ||||
|     /// | ||||
|     /// Similar to `Stream::poll_next`, this yields `Some(Data)` until | ||||
|     /// the body ends, when it yields `None`. | ||||
|     fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error>; | ||||
|     fn poll_data(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Result<Self::Data, Self::Error>>>; | ||||
|  | ||||
|     /// Poll for an optional **single** `HeaderMap` of trailers. | ||||
|     /// | ||||
|     /// This should **only** be called after `poll_data` has ended. | ||||
|     /// | ||||
|     /// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2. | ||||
|     fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> { | ||||
|         Ok(Async::Ready(None)) | ||||
|     fn poll_trailers(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Result<HeaderMap, Self::Error>>> { | ||||
|         Poll::Ready(None) | ||||
|     } | ||||
|  | ||||
|     /// A hint that the `Body` is complete, and doesn't need to be polled more. | ||||
| @@ -70,6 +70,7 @@ pub trait Payload: Send + 'static { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| impl<E: Payload> Payload for Box<E> { | ||||
|     type Data = E::Data; | ||||
|     type Error = E::Error; | ||||
| @@ -95,5 +96,6 @@ impl<E: Payload> Payload for Box<E> { | ||||
|         (**self).__hyper_full_data(arg) | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -13,13 +13,12 @@ use std::mem; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| use bytes::Bytes; | ||||
| use futures::{Async, Future, Poll}; | ||||
| use futures::future::{self, Either, Executor}; | ||||
| use futures_util::future::{self, Either, FutureExt as _}; | ||||
| use h2; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::body::Payload; | ||||
| use crate::common::Exec; | ||||
| use crate::common::{Exec, Future, Pin, Poll, task}; | ||||
| use crate::upgrade::Upgraded; | ||||
| use crate::proto; | ||||
| use super::dispatch; | ||||
| @@ -41,7 +40,7 @@ type ConnEither<T, B> = Either< | ||||
| /// This is a shortcut for `Builder::new().handshake(io)`. | ||||
| pub fn handshake<T>(io: T) -> Handshake<T, crate::Body> | ||||
| where | ||||
|     T: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     T: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
| { | ||||
|     Builder::new() | ||||
|         .handshake(io) | ||||
| @@ -88,7 +87,7 @@ pub struct Builder { | ||||
| pub struct Handshake<T, B> { | ||||
|     builder: Builder, | ||||
|     io: Option<T>, | ||||
|     _marker: PhantomData<B>, | ||||
|     _marker: PhantomData<fn(B)>, | ||||
| } | ||||
|  | ||||
| /// A future returned by `SendRequest::send_request`. | ||||
| @@ -96,9 +95,13 @@ pub struct Handshake<T, B> { | ||||
| /// Yields a `Response` if successful. | ||||
| #[must_use = "futures do nothing unless polled"] | ||||
| pub struct ResponseFuture { | ||||
|     // for now, a Box is used to hide away the internal `B` | ||||
|     // that can be returned if canceled | ||||
|     inner: Box<dyn Future<Item=Response<Body>, Error=crate::Error> + Send>, | ||||
|     inner: ResponseFutureState | ||||
| } | ||||
|  | ||||
| enum ResponseFutureState { | ||||
|     Waiting(dispatch::Promise<Response<Body>>), | ||||
|     // Option is to be able to `take()` it in `poll` | ||||
|     Error(Option<crate::Error>), | ||||
| } | ||||
|  | ||||
| /// Deconstructed parts of a `Connection`. | ||||
| @@ -123,14 +126,6 @@ pub struct Parts<T> { | ||||
|  | ||||
| // ========== internal client api | ||||
|  | ||||
| /// A `Future` for when `SendRequest::poll_ready()` is ready. | ||||
| // FIXME: allow() required due to `impl Trait` leaking types to this lint | ||||
| #[allow(missing_debug_implementations)] | ||||
| #[must_use = "futures do nothing unless polled"] | ||||
| pub(super) struct WhenReady<B> { | ||||
|     tx: Option<SendRequest<B>>, | ||||
| } | ||||
|  | ||||
| // A `SendRequest` that can be cloned to send HTTP2 requests. | ||||
| // private for now, probably not a great idea of a type... | ||||
| #[must_use = "futures do nothing unless polled"] | ||||
| @@ -145,14 +140,16 @@ impl<B> SendRequest<B> | ||||
|     /// Polls to determine whether this sender can be used yet for a request. | ||||
|     /// | ||||
|     /// If the associated connection is closed, this returns an Error. | ||||
|     pub fn poll_ready(&mut self) -> Poll<(), crate::Error> { | ||||
|         self.dispatch.poll_ready() | ||||
|     pub fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         self.dispatch.poll_ready(cx) | ||||
|     } | ||||
|  | ||||
|     pub(super) fn when_ready(self) -> WhenReady<B> { | ||||
|         WhenReady { | ||||
|             tx: Some(self), | ||||
|         } | ||||
|     pub(super) fn when_ready(self) -> impl Future<Output=crate::Result<Self>> { | ||||
|         let mut me = Some(self); | ||||
|         future::poll_fn(move |cx| { | ||||
|             ready!(me.as_mut().unwrap().poll_ready(cx))?; | ||||
|             Poll::Ready(Ok(me.take().unwrap())) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub(super) fn is_ready(&self) -> bool { | ||||
| @@ -224,37 +221,30 @@ where | ||||
|     pub fn send_request(&mut self, req: Request<B>) -> ResponseFuture { | ||||
|         let inner = match self.dispatch.send(req) { | ||||
|             Ok(rx) => { | ||||
|                 Either::A(rx.then(move |res| { | ||||
|                     match res { | ||||
|                         Ok(Ok(res)) => Ok(res), | ||||
|                         Ok(Err(err)) => Err(err), | ||||
|                         // this is definite bug if it happens, but it shouldn't happen! | ||||
|                         Err(_) => panic!("dispatch dropped without returning error"), | ||||
|                     } | ||||
|                 })) | ||||
|                 ResponseFutureState::Waiting(rx) | ||||
|             }, | ||||
|             Err(_req) => { | ||||
|                 debug!("connection was not ready"); | ||||
|                 let err = crate::Error::new_canceled().with("connection was not ready"); | ||||
|                 Either::B(future::err(err)) | ||||
|                 ResponseFutureState::Error(Some(err)) | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         ResponseFuture { | ||||
|             inner: Box::new(inner), | ||||
|             inner, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn send_request_retryable(&mut self, req: Request<B>) -> impl Future<Item = Response<Body>, Error = (crate::Error, Option<Request<B>>)> | ||||
|     pub(crate) fn send_request_retryable(&mut self, req: Request<B>) -> impl Future<Output = Result<Response<Body>, (crate::Error, Option<Request<B>>)>> + Unpin | ||||
|     where | ||||
|         B: Send, | ||||
|     { | ||||
|         match self.dispatch.try_send(req) { | ||||
|             Ok(rx) => { | ||||
|                 Either::A(rx.then(move |res| { | ||||
|                 Either::Left(rx.then(move |res| { | ||||
|                     match res { | ||||
|                         Ok(Ok(res)) => Ok(res), | ||||
|                         Ok(Err(err)) => Err(err), | ||||
|                         Ok(Ok(res)) => future::ok(res), | ||||
|                         Ok(Err(err)) => future::err(err), | ||||
|                         // this is definite bug if it happens, but it shouldn't happen! | ||||
|                         Err(_) => panic!("dispatch dropped without returning error"), | ||||
|                     } | ||||
| @@ -263,7 +253,7 @@ where | ||||
|             Err(req) => { | ||||
|                 debug!("connection was not ready"); | ||||
|                 let err = crate::Error::new_canceled().with("connection was not ready"); | ||||
|                 Either::B(future::err((err, Some(req)))) | ||||
|                 Either::Right(future::err((err, Some(req)))) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -305,16 +295,16 @@ impl<B> Http2SendRequest<B> | ||||
| where | ||||
|     B: Payload + 'static, | ||||
| { | ||||
|     pub(super) fn send_request_retryable(&mut self, req: Request<B>) -> impl Future<Item=Response<Body>, Error=(crate::Error, Option<Request<B>>)> | ||||
|     pub(super) fn send_request_retryable(&mut self, req: Request<B>) -> impl Future<Output=Result<Response<Body>, (crate::Error, Option<Request<B>>)>> | ||||
|     where | ||||
|         B: Send, | ||||
|     { | ||||
|         match self.dispatch.try_send(req) { | ||||
|             Ok(rx) => { | ||||
|                 Either::A(rx.then(move |res| { | ||||
|                 Either::Left(rx.then(move |res| { | ||||
|                     match res { | ||||
|                         Ok(Ok(res)) => Ok(res), | ||||
|                         Ok(Err(err)) => Err(err), | ||||
|                         Ok(Ok(res)) => future::ok(res), | ||||
|                         Ok(Err(err)) => future::err(err), | ||||
|                         // this is definite bug if it happens, but it shouldn't happen! | ||||
|                         Err(_) => panic!("dispatch dropped without returning error"), | ||||
|                     } | ||||
| @@ -323,7 +313,7 @@ where | ||||
|             Err(req) => { | ||||
|                 debug!("connection was not ready"); | ||||
|                 let err = crate::Error::new_canceled().with("connection was not ready"); | ||||
|                 Either::B(future::err((err, Some(req)))) | ||||
|                 Either::Right(future::err((err, Some(req)))) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -348,7 +338,7 @@ impl<B> Clone for Http2SendRequest<B> { | ||||
|  | ||||
| impl<T, B> Connection<T, B> | ||||
| where | ||||
|     T: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     T: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|     B: Payload + 'static, | ||||
| { | ||||
|     /// Return the inner IO object, and additional information. | ||||
| @@ -356,8 +346,8 @@ where | ||||
|     /// Only works for HTTP/1 connections. HTTP/2 connections will panic. | ||||
|     pub fn into_parts(self) -> Parts<T> { | ||||
|         let (io, read_buf, _) = match self.inner.expect("already upgraded") { | ||||
|             Either::A(h1) => h1.into_inner(), | ||||
|             Either::B(_h2) => { | ||||
|             Either::Left(h1) => h1.into_inner(), | ||||
|             Either::Right(_h2) => { | ||||
|                 panic!("http2 cannot into_inner"); | ||||
|             } | ||||
|         }; | ||||
| @@ -380,51 +370,58 @@ where | ||||
|     /// Use [`poll_fn`](https://docs.rs/futures/0.1.25/futures/future/fn.poll_fn.html) | ||||
|     /// and [`try_ready!`](https://docs.rs/futures/0.1.25/futures/macro.try_ready.html) | ||||
|     /// to work with this function; or use the `without_shutdown` wrapper. | ||||
|     pub fn poll_without_shutdown(&mut self) -> Poll<(), crate::Error> { | ||||
|     pub fn poll_without_shutdown(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> | ||||
|     where | ||||
|         B: Unpin, | ||||
|     { | ||||
|         match self.inner.as_mut().expect("already upgraded") { | ||||
|             &mut Either::A(ref mut h1) => { | ||||
|                 h1.poll_without_shutdown() | ||||
|             &mut Either::Left(ref mut h1) => { | ||||
|                 h1.poll_without_shutdown(cx) | ||||
|             }, | ||||
|             &mut Either::B(ref mut h2) => { | ||||
|             &mut Either::Right(ref mut h2) => { | ||||
|                 unimplemented!("h2 poll_without_shutdown"); | ||||
|                 /* | ||||
|                 h2.poll().map(|x| x.map(|_| ())) | ||||
|                 */ | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Prevent shutdown of the underlying IO object at the end of service the request, | ||||
|     /// instead run `into_parts`. This is a convenience wrapper over `poll_without_shutdown`. | ||||
|     pub fn without_shutdown(self) -> impl Future<Item=Parts<T>, Error=crate::Error> { | ||||
|     pub fn without_shutdown(self) -> impl Future<Output=crate::Result<Parts<T>>> | ||||
|     where | ||||
|         B: Unpin, | ||||
|     { | ||||
|         let mut conn = Some(self); | ||||
|         ::futures::future::poll_fn(move || -> crate::Result<_> { | ||||
|             try_ready!(conn.as_mut().unwrap().poll_without_shutdown()); | ||||
|             Ok(conn.take().unwrap().into_parts().into()) | ||||
|         future::poll_fn(move |cx| -> Poll<crate::Result<Parts<T>>> { | ||||
|             ready!(conn.as_mut().unwrap().poll_without_shutdown(cx))?; | ||||
|             Poll::Ready(Ok(conn.take().unwrap().into_parts())) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T, B> Future for Connection<T, B> | ||||
| where | ||||
|     T: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     B: Payload + 'static, | ||||
|     T: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|     B: Payload + Unpin + 'static, | ||||
| { | ||||
|     type Item = (); | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<()>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         match try_ready!(self.inner.poll()) { | ||||
|             Some(proto::Dispatched::Shutdown) | | ||||
|             None => { | ||||
|                 Ok(Async::Ready(())) | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match ready!(Pin::new(self.inner.as_mut().unwrap()).poll(cx))? { | ||||
|             proto::Dispatched::Shutdown => { | ||||
|                 Poll::Ready(Ok(())) | ||||
|             }, | ||||
|             Some(proto::Dispatched::Upgrade(pending)) => { | ||||
|             proto::Dispatched::Upgrade(pending) => { | ||||
|                 let h1 = match mem::replace(&mut self.inner, None) { | ||||
|                     Some(Either::A(h1)) => h1, | ||||
|                     Some(Either::Left(h1)) => h1, | ||||
|                     _ => unreachable!("Upgrade expects h1"), | ||||
|                 }; | ||||
|  | ||||
|                 let (io, buf, _) = h1.into_inner(); | ||||
|                 pending.fulfill(Upgraded::new(Box::new(io), buf)); | ||||
|                 Ok(Async::Ready(())) | ||||
|                 Poll::Ready(Ok(())) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -461,6 +458,7 @@ impl Builder { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     /// Provide an executor to execute background HTTP2 tasks. | ||||
|     pub fn executor<E>(&mut self, exec: E) -> &mut Builder | ||||
|     where | ||||
| @@ -469,6 +467,7 @@ impl Builder { | ||||
|         self.exec = Exec::Executor(Arc::new(exec)); | ||||
|         self | ||||
|     } | ||||
|     */ | ||||
|  | ||||
|     pub(super) fn h1_writev(&mut self, enabled: bool) -> &mut Builder { | ||||
|         self.h1_writev = enabled; | ||||
| @@ -532,7 +531,7 @@ impl Builder { | ||||
|     #[inline] | ||||
|     pub fn handshake<T, B>(&self, io: T) -> Handshake<T, B> | ||||
|     where | ||||
|         T: AsyncRead + AsyncWrite + Send + 'static, | ||||
|         T: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|         B: Payload + 'static, | ||||
|     { | ||||
|         trace!("client handshake HTTP/{}", if self.http2 { 2 } else { 1 }); | ||||
| @@ -548,13 +547,12 @@ impl Builder { | ||||
|  | ||||
| impl<T, B> Future for Handshake<T, B> | ||||
| where | ||||
|     T: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     T: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|     B: Payload + 'static, | ||||
| { | ||||
|     type Item = (SendRequest<B>, Connection<T, B>); | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<(SendRequest<B>, Connection<T, B>)>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         let io = self.io.take().expect("polled more than once"); | ||||
|         let (tx, rx) = dispatch::channel(); | ||||
|         let either = if !self.builder.http2 { | ||||
| @@ -573,13 +571,13 @@ where | ||||
|             } | ||||
|             let cd = proto::h1::dispatch::Client::new(rx); | ||||
|             let dispatch = proto::h1::Dispatcher::new(cd, conn); | ||||
|             Either::A(dispatch) | ||||
|             Either::Left(dispatch) | ||||
|         } else { | ||||
|             let h2 = proto::h2::Client::new(io, rx, &self.builder.h2_builder, self.builder.exec.clone()); | ||||
|             Either::B(h2) | ||||
|             Either::Right(h2) | ||||
|         }; | ||||
|  | ||||
|         Ok(Async::Ready(( | ||||
|         Poll::Ready(Ok(( | ||||
|             SendRequest { | ||||
|                 dispatch: tx, | ||||
|             }, | ||||
| @@ -600,12 +598,22 @@ impl<T, B> fmt::Debug for Handshake<T, B> { | ||||
| // ===== impl ResponseFuture | ||||
|  | ||||
| impl Future for ResponseFuture { | ||||
|     type Item = Response<Body>; | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<Response<Body>>; | ||||
|  | ||||
|     #[inline] | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         self.inner.poll() | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match self.inner { | ||||
|             ResponseFutureState::Waiting(ref mut rx) => { | ||||
|                 Pin::new(rx).poll(cx).map(|res| match res { | ||||
|                     Ok(Ok(resp)) => Ok(resp), | ||||
|                     Ok(Err(err)) => Err(err), | ||||
|                     // this is definite bug if it happens, but it shouldn't happen! | ||||
|                     Err(_canceled) => panic!("dispatch dropped without returning error"), | ||||
|                 }) | ||||
|             }, | ||||
|             ResponseFutureState::Error(ref mut err) => { | ||||
|                 Poll::Ready(Err(err.take().expect("polled after ready"))) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -616,24 +624,6 @@ impl fmt::Debug for ResponseFuture { | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ===== impl WhenReady | ||||
|  | ||||
| impl<B> Future for WhenReady<B> { | ||||
|     type Item = SendRequest<B>; | ||||
|     type Error = crate::Error; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         let mut tx = self.tx.take().expect("polled after complete"); | ||||
|         match tx.poll_ready()? { | ||||
|             Async::Ready(()) => Ok(Async::Ready(tx)), | ||||
|             Async::NotReady => { | ||||
|                 self.tx = Some(tx); | ||||
|                 Ok(Async::NotReady) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // assert trait markers | ||||
|  | ||||
| trait AssertSend: Send {} | ||||
|   | ||||
| @@ -16,20 +16,19 @@ use std::net::{ | ||||
| use std::str::FromStr; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| use futures::{Async, Future, Poll}; | ||||
| use futures::future::{Executor, ExecuteError}; | ||||
| use futures::sync::oneshot; | ||||
| use futures_cpupool::{Builder as CpuPoolBuilder}; | ||||
| use tokio_executor::TypedExecutor; | ||||
| use tokio_sync::oneshot; | ||||
| use tokio_threadpool; | ||||
|  | ||||
| use crate::common::{Future, Pin, Poll, Unpin, task}; | ||||
| use self::sealed::GaiTask; | ||||
|  | ||||
| /// Resolve a hostname to a set of IP addresses. | ||||
| pub trait Resolve { | ||||
| pub trait Resolve: Unpin { | ||||
|     /// The set of IP addresses to try to connect to. | ||||
|     type Addrs: Iterator<Item=IpAddr>; | ||||
|     /// A Future of the resolved set of addresses. | ||||
|     type Future: Future<Item=Self::Addrs, Error=io::Error>; | ||||
|     type Future: Future<Output=Result<Self::Addrs, io::Error>> + Unpin; | ||||
|     /// Resolve a hostname. | ||||
|     fn resolve(&self, name: Name) -> Self::Future; | ||||
| } | ||||
| @@ -53,7 +52,8 @@ pub struct GaiAddrs { | ||||
|  | ||||
| /// A future to resole a name returned by `GaiResolver`. | ||||
| pub struct GaiFuture { | ||||
|     rx: oneshot::SpawnHandle<IpAddrs, io::Error>, | ||||
|     //rx: oneshot::SpawnHandle<IpAddrs, io::Error>, | ||||
|     blocking: GaiBlocking, | ||||
| } | ||||
|  | ||||
| impl Name { | ||||
| @@ -112,24 +112,36 @@ impl GaiResolver { | ||||
|     /// | ||||
|     /// Takes number of DNS worker threads. | ||||
|     pub fn new(threads: usize) -> Self { | ||||
|         let pool = CpuPoolBuilder::new() | ||||
|             .name_prefix("hyper-dns") | ||||
|             .pool_size(threads) | ||||
|             .create(); | ||||
|         GaiResolver { | ||||
|             executor: GaiExecutor, | ||||
|         } | ||||
|         /* | ||||
|         use tokio_threadpool::Builder; | ||||
|  | ||||
|         let pool = Builder::new() | ||||
|             .name_prefix("hyper-dns-gai-resolver") | ||||
|             // not for CPU tasks, so only spawn workers | ||||
|             // in blocking mode | ||||
|             .pool_size(1) | ||||
|             .max_blocking(threads) | ||||
|             .build(); | ||||
|         GaiResolver::new_with_executor(pool) | ||||
|         */ | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     /// Construct a new `GaiResolver` with a shared thread pool executor. | ||||
|     /// | ||||
|     /// Takes an executor to run blocking `getaddrinfo` tasks on. | ||||
|     pub fn new_with_executor<E: 'static>(executor: E) -> Self | ||||
|     /*pub */fn new_with_executor<E: 'static>(executor: E) -> Self | ||||
|     where | ||||
|         E: Executor<GaiTask> + Send + Sync, | ||||
|         E: TypedExecutor<GaiTask> + Send + Sync, | ||||
|     { | ||||
|         GaiResolver { | ||||
|             executor: GaiExecutor(Arc::new(executor)), | ||||
|         } | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  | ||||
| impl Resolve for GaiResolver { | ||||
| @@ -138,9 +150,10 @@ impl Resolve for GaiResolver { | ||||
|  | ||||
|     fn resolve(&self, name: Name) -> Self::Future { | ||||
|         let blocking = GaiBlocking::new(name.host); | ||||
|         let rx = oneshot::spawn(blocking, &self.executor); | ||||
|         //let rx = oneshot::spawn(blocking, &self.executor); | ||||
|         GaiFuture { | ||||
|             rx, | ||||
|             //rx, | ||||
|             blocking, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -152,14 +165,16 @@ impl fmt::Debug for GaiResolver { | ||||
| } | ||||
|  | ||||
| impl Future for GaiFuture { | ||||
|     type Item = GaiAddrs; | ||||
|     type Error = io::Error; | ||||
|     type Output = Result<GaiAddrs, io::Error>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         /* | ||||
|         let addrs = try_ready!(self.rx.poll()); | ||||
|         Ok(Async::Ready(GaiAddrs { | ||||
|             inner: addrs, | ||||
|         })) | ||||
|         */ | ||||
|         Poll::Ready(self.blocking.block().map(|addrs| GaiAddrs { inner: addrs })) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -184,14 +199,16 @@ impl fmt::Debug for GaiAddrs { | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| struct GaiExecutor(Arc<dyn Executor<GaiTask> + Send + Sync>); | ||||
| struct GaiExecutor/*(Arc<dyn Executor<GaiTask> + Send + Sync>)*/; | ||||
|  | ||||
| /* | ||||
| impl Executor<oneshot::Execute<GaiBlocking>> for GaiExecutor { | ||||
|     fn execute(&self, future: oneshot::Execute<GaiBlocking>) -> Result<(), ExecuteError<oneshot::Execute<GaiBlocking>>> { | ||||
|         self.0.execute(GaiTask { work: future }) | ||||
|             .map_err(|err| ExecuteError::new(err.kind(), err.into_future().work)) | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
| pub(super) struct GaiBlocking { | ||||
|     host: String, | ||||
| @@ -201,8 +218,16 @@ impl GaiBlocking { | ||||
|     pub(super) fn new(host: String) -> GaiBlocking { | ||||
|         GaiBlocking { host } | ||||
|     } | ||||
|  | ||||
|     fn block(&self) -> io::Result<IpAddrs> { | ||||
|         debug!("resolving host={:?}", self.host); | ||||
|         (&*self.host, 0).to_socket_addrs() | ||||
|             .map(|i| IpAddrs { iter: i }) | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| impl Future for GaiBlocking { | ||||
|     type Item = IpAddrs; | ||||
|     type Error = io::Error; | ||||
| @@ -213,6 +238,7 @@ impl Future for GaiBlocking { | ||||
|             .map(|i| Async::Ready(IpAddrs { iter: i })) | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
| pub(super) struct IpAddrs { | ||||
|     iter: vec::IntoIter<SocketAddr>, | ||||
| @@ -276,7 +302,7 @@ pub(super) mod sealed { | ||||
|     use super::*; | ||||
|     // Blocking task to be executed on a thread pool. | ||||
|     pub struct GaiTask { | ||||
|         pub(super) work: oneshot::Execute<GaiBlocking> | ||||
|         //pub(super) work: oneshot::Execute<GaiBlocking> | ||||
|     } | ||||
|  | ||||
|     impl fmt::Debug for GaiTask { | ||||
| @@ -285,6 +311,7 @@ pub(super) mod sealed { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     impl Future for GaiTask { | ||||
|         type Item = (); | ||||
|         type Error = (); | ||||
| @@ -293,6 +320,7 @@ pub(super) mod sealed { | ||||
|             self.work.poll() | ||||
|         } | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -329,15 +357,14 @@ impl Resolve for TokioThreadpoolGaiResolver { | ||||
| } | ||||
|  | ||||
| impl Future for TokioThreadpoolGaiFuture { | ||||
|     type Item = GaiAddrs; | ||||
|     type Error = io::Error; | ||||
|     type Output = Result<GaiAddrs, io::Error>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<GaiAddrs, io::Error> { | ||||
|         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: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match ready!(tokio_threadpool::blocking(|| (self.name.as_str(), 0).to_socket_addrs())) { | ||||
|             Ok(Ok(iter)) => Poll::Ready(Ok(GaiAddrs { inner: IpAddrs { iter } })), | ||||
|             Ok(Err(e)) => Poll::Ready(Err(e)), | ||||
|             // a BlockingError, meaning not on a tokio_threadpool :( | ||||
|             Err(e) => Poll::Ready(Err(io::Error::new(io::ErrorKind::Other, e))), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,17 +6,19 @@ use std::mem; | ||||
| use std::net::{IpAddr, SocketAddr}; | ||||
| use std::time::{Duration, Instant}; | ||||
|  | ||||
| use futures::{Async, Future, Poll}; | ||||
| use futures::future::{Executor}; | ||||
| use http::uri::Scheme; | ||||
| use net2::TcpBuilder; | ||||
| use tokio_reactor::Handle; | ||||
| use tokio_tcp::{TcpStream, ConnectFuture}; | ||||
| use tokio_tcp::{TcpStream/*, ConnectFuture*/}; | ||||
| use tokio_timer::Delay; | ||||
|  | ||||
| use crate::common::{Future, Pin, Poll, task}; | ||||
| use super::{Connect, Connected, Destination}; | ||||
| use super::dns::{self, GaiResolver, Resolve, TokioThreadpoolGaiResolver}; | ||||
|  | ||||
| // TODO: unbox me? | ||||
| type ConnectFuture = Pin<Box<dyn Future<Output = io::Result<TcpStream>> + Send>>; | ||||
|  | ||||
| /// A connector for the `http` scheme. | ||||
| /// | ||||
| /// Performs DNS resolution in a thread pool, and then connects over TCP. | ||||
| @@ -89,6 +91,7 @@ impl HttpConnector { | ||||
|         http | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     /// Construct a new HttpConnector. | ||||
|     /// | ||||
|     /// Takes an executor to run blocking `getaddrinfo` tasks on. | ||||
| @@ -100,6 +103,7 @@ impl HttpConnector { | ||||
|         http.set_reactor(handle); | ||||
|         http | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  | ||||
| impl HttpConnector<TokioThreadpoolGaiResolver> { | ||||
| @@ -335,55 +339,54 @@ enum State<R: Resolve> { | ||||
|     Error(Option<io::Error>), | ||||
| } | ||||
|  | ||||
| impl<R: Resolve> Future for HttpConnecting<R> { | ||||
|     type Item = (TcpStream, Connected); | ||||
|     type Error = io::Error; | ||||
| impl<R: Resolve> Future for HttpConnecting<R> | ||||
| where | ||||
|     R::Future: Unpin, | ||||
| { | ||||
|     type Output = Result<(TcpStream, Connected), io::Error>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         let me = &mut *self; | ||||
|         loop { | ||||
|             let state; | ||||
|             match self.state { | ||||
|             match me.state { | ||||
|                 State::Lazy(ref resolver, ref mut host, local_addr) => { | ||||
|                     // If the host is already an IP addr (v4 or v6), | ||||
|                     // skip resolving the dns and start connecting right away. | ||||
|                     if let Some(addrs) = dns::IpAddrs::try_parse(host, self.port) { | ||||
|                     if let Some(addrs) = dns::IpAddrs::try_parse(host, me.port) { | ||||
|                         state = State::Connecting(ConnectingTcp::new( | ||||
|                             local_addr, addrs, self.happy_eyeballs_timeout, self.reuse_address)); | ||||
|                             local_addr, addrs, me.happy_eyeballs_timeout, me.reuse_address)); | ||||
|                     } else { | ||||
|                         let name = dns::Name::new(mem::replace(host, String::new())); | ||||
|                         state = State::Resolving(resolver.resolve(name), local_addr); | ||||
|                     } | ||||
|                 }, | ||||
|                 State::Resolving(ref mut future, local_addr) => { | ||||
|                     match future.poll()? { | ||||
|                         Async::NotReady => return Ok(Async::NotReady), | ||||
|                         Async::Ready(addrs) => { | ||||
|                             let port = self.port; | ||||
|                             let addrs = addrs | ||||
|                                 .map(|addr| SocketAddr::new(addr, port)) | ||||
|                                 .collect(); | ||||
|                             let addrs = dns::IpAddrs::new(addrs); | ||||
|                             state = State::Connecting(ConnectingTcp::new( | ||||
|                                 local_addr, addrs, self.happy_eyeballs_timeout, self.reuse_address)); | ||||
|                         } | ||||
|                     }; | ||||
|                     let addrs =  ready!(Pin::new(future).poll(cx))?; | ||||
|                     let port = me.port; | ||||
|                     let addrs = addrs | ||||
|                         .map(|addr| SocketAddr::new(addr, port)) | ||||
|                         .collect(); | ||||
|                     let addrs = dns::IpAddrs::new(addrs); | ||||
|                     state = State::Connecting(ConnectingTcp::new( | ||||
|                         local_addr, addrs, me.happy_eyeballs_timeout, me.reuse_address)); | ||||
|                 }, | ||||
|                 State::Connecting(ref mut c) => { | ||||
|                     let sock = try_ready!(c.poll(&self.handle)); | ||||
|                     let sock = ready!(c.poll(cx, &me.handle))?; | ||||
|  | ||||
|                     if let Some(dur) = self.keep_alive_timeout { | ||||
|                     if let Some(dur) = me.keep_alive_timeout { | ||||
|                         sock.set_keepalive(Some(dur))?; | ||||
|                     } | ||||
|  | ||||
|                     if let Some(size) = self.send_buffer_size { | ||||
|                     if let Some(size) = me.send_buffer_size { | ||||
|                         sock.set_send_buffer_size(size)?; | ||||
|                     } | ||||
|  | ||||
|                     if let Some(size) = self.recv_buffer_size { | ||||
|                     if let Some(size) = me.recv_buffer_size { | ||||
|                         sock.set_recv_buffer_size(size)?; | ||||
|                     } | ||||
|  | ||||
|                     sock.set_nodelay(self.nodelay)?; | ||||
|                     sock.set_nodelay(me.nodelay)?; | ||||
|  | ||||
|                     let extra = HttpInfo { | ||||
|                         remote_addr: sock.peer_addr()?, | ||||
| @@ -391,11 +394,11 @@ impl<R: Resolve> Future for HttpConnecting<R> { | ||||
|                     let connected = Connected::new() | ||||
|                         .extra(extra); | ||||
|  | ||||
|                     return Ok(Async::Ready((sock, connected))); | ||||
|                     return Poll::Ready(Ok((sock, connected))); | ||||
|                 }, | ||||
|                 State::Error(ref mut e) => return Err(e.take().expect("polled more than once")), | ||||
|                 State::Error(ref mut e) => return Poll::Ready(Err(e.take().expect("polled more than once"))), | ||||
|             } | ||||
|             self.state = state; | ||||
|             me.state = state; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -474,20 +477,21 @@ 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<TcpStream, io::Error> { | ||||
|     ) -> Poll<io::Result<TcpStream>> { | ||||
|         let mut err = None; | ||||
|         loop { | ||||
|             if let Some(ref mut current) = self.current { | ||||
|                 match current.poll() { | ||||
|                     Ok(Async::Ready(tcp)) => { | ||||
|                 match current.as_mut().poll(cx) { | ||||
|                     Poll::Ready(Ok(tcp)) => { | ||||
|                         debug!("connected to {:?}", tcp.peer_addr().ok()); | ||||
|                         return Ok(Async::Ready(tcp)); | ||||
|                         return Poll::Ready(Ok(tcp)); | ||||
|                     }, | ||||
|                     Ok(Async::NotReady) => return Ok(Async::NotReady), | ||||
|                     Err(e) => { | ||||
|                     Poll::Pending => return Poll::Pending, | ||||
|                     Poll::Ready(Err(e)) => { | ||||
|                         trace!("connect error {:?}", e); | ||||
|                         err = Some(e); | ||||
|                         if let Some(addr) = self.addrs.next() { | ||||
| @@ -503,7 +507,7 @@ impl ConnectingTcpRemote { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             return Err(err.take().expect("missing connect error")); | ||||
|             return Poll::Ready(Err(err.take().expect("missing connect error"))); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -540,51 +544,46 @@ fn connect(addr: &SocketAddr, local_addr: &Option<IpAddr>, handle: &Option<Handl | ||||
|         None => Cow::Owned(Handle::default()), | ||||
|     }; | ||||
|  | ||||
|     Ok(TcpStream::connect_std(builder.to_tcp_stream()?, addr, &handle)) | ||||
|     Ok(Box::pin(TcpStream::connect_std(builder.to_tcp_stream()?, addr, &handle))) | ||||
| } | ||||
|  | ||||
| impl ConnectingTcp { | ||||
|     // not a Future, since passing a &Handle to poll | ||||
|     fn poll(&mut self, handle: &Option<Handle>) -> Poll<TcpStream, io::Error> { | ||||
|     fn poll(&mut self, cx: &mut task::Context<'_>, handle: &Option<Handle>) -> Poll<io::Result<TcpStream>> { | ||||
|         match self.fallback.take() { | ||||
|             None => self.preferred.poll(&self.local_addr, handle, self.reuse_address), | ||||
|             Some(mut fallback) => match self.preferred.poll(&self.local_addr, handle, self.reuse_address) { | ||||
|                 Ok(Async::Ready(stream)) => { | ||||
|             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) { | ||||
|                 Poll::Ready(Ok(stream)) => { | ||||
|                     // Preferred successful - drop fallback. | ||||
|                     Ok(Async::Ready(stream)) | ||||
|                     Poll::Ready(Ok(stream)) | ||||
|                 } | ||||
|                 Ok(Async::NotReady) => match fallback.delay.poll() { | ||||
|                     Ok(Async::Ready(_)) => match fallback.remote.poll(&self.local_addr, handle, self.reuse_address) { | ||||
|                         Ok(Async::Ready(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(Ok(stream)) => { | ||||
|                             // Fallback successful - drop current preferred, | ||||
|                             // but keep fallback as new preferred. | ||||
|                             self.preferred = fallback.remote; | ||||
|                             Ok(Async::Ready(stream)) | ||||
|                             Poll::Ready(Ok(stream)) | ||||
|                         } | ||||
|                         Ok(Async::NotReady) => { | ||||
|                         Poll::Pending => { | ||||
|                             // Neither preferred nor fallback are ready. | ||||
|                             self.fallback = Some(fallback); | ||||
|                             Ok(Async::NotReady) | ||||
|                             Poll::Pending | ||||
|                         } | ||||
|                         Err(_) => { | ||||
|                         Poll::Ready(Err(_)) => { | ||||
|                             // Fallback failed - resume with preferred only. | ||||
|                             Ok(Async::NotReady) | ||||
|                             Poll::Pending | ||||
|                         } | ||||
|                     }, | ||||
|                     Ok(Async::NotReady) => { | ||||
|                     Poll::Pending => { | ||||
|                         // Too early to attempt fallback. | ||||
|                         self.fallback = Some(fallback); | ||||
|                         Ok(Async::NotReady) | ||||
|                     } | ||||
|                     Err(_) => { | ||||
|                         // Fallback delay failed - resume with preferred only. | ||||
|                         Ok(Async::NotReady) | ||||
|                         Poll::Pending | ||||
|                     } | ||||
|                 } | ||||
|                 Err(_) => { | ||||
|                 Poll::Ready(Err(_)) => { | ||||
|                     // Preferred failed - use fallback as new preferred. | ||||
|                     self.preferred = fallback.remote; | ||||
|                     self.preferred.poll(&self.local_addr, handle, self.reuse_address) | ||||
|                     self.preferred.poll(cx, &self.local_addr, handle, self.reuse_address) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -734,10 +733,10 @@ mod tests { | ||||
|  | ||||
|             fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|                 match self.0.poll(&Some(Handle::default())) { | ||||
|                     Ok(Async::Ready(stream)) => Ok(Async::Ready( | ||||
|                     Poll::Ready(Ok(stream)) => Poll::Ready(Ok( | ||||
|                         if stream.peer_addr().unwrap().is_ipv4() { 4 } else { 6 } | ||||
|                     )), | ||||
|                     Ok(Async::NotReady) => Ok(Async::NotReady), | ||||
|                     Poll::Pending => Poll::Pending, | ||||
|                     Err(err) => Err(err), | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -10,10 +10,11 @@ use std::{fmt, mem}; | ||||
| #[cfg(try_from)] use std::convert::TryFrom; | ||||
|  | ||||
| use bytes::{BufMut, Bytes, BytesMut}; | ||||
| use futures::Future; | ||||
| use ::http::{uri, Response, Uri}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::common::{Future, Unpin}; | ||||
|  | ||||
| #[cfg(feature = "runtime")] pub mod dns; | ||||
| #[cfg(feature = "runtime")] mod http; | ||||
| #[cfg(feature = "runtime")] pub use self::http::{HttpConnector, HttpInfo}; | ||||
| @@ -25,11 +26,11 @@ use tokio_io::{AsyncRead, AsyncWrite}; | ||||
| /// ready connection. | ||||
| pub trait Connect: Send + Sync { | ||||
|     /// The connected IO Stream. | ||||
|     type Transport: AsyncRead + AsyncWrite + Send + 'static; | ||||
|     type Transport: AsyncRead + AsyncWrite + Unpin + Send + 'static; | ||||
|     /// An error occured when trying to connect. | ||||
|     type Error: Into<Box<dyn StdError + Send + Sync>>; | ||||
|     /// A Future that will resolve to the connected Transport. | ||||
|     type Future: Future<Item=(Self::Transport, Connected), Error=Self::Error> + Send; | ||||
|     type Future: Future<Output=Result<(Self::Transport, Connected), Self::Error>> + Unpin + Send; | ||||
|     /// Connect to a destination. | ||||
|     fn connect(&self, dst: Destination) -> Self::Future; | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| use futures::{future, Async, Future, Poll, Stream}; | ||||
| use futures::sync::{mpsc, oneshot}; | ||||
| use futures_core::Stream; | ||||
| use futures_channel::{mpsc, oneshot}; | ||||
| use futures_util::future; | ||||
| use want; | ||||
|  | ||||
| use crate::common::Never; | ||||
| use crate::common::{Future, Never, Pin, Poll, task}; | ||||
|  | ||||
| pub type RetryPromise<T, U> = oneshot::Receiver<Result<U, (crate::Error, Option<T>)>>; | ||||
| pub type Promise<T> = oneshot::Receiver<Result<T, crate::Error>>; | ||||
| @@ -51,8 +52,8 @@ pub struct UnboundedSender<T, U> { | ||||
| } | ||||
|  | ||||
| impl<T, U> Sender<T, U> { | ||||
|     pub fn poll_ready(&mut self) -> Poll<(), crate::Error> { | ||||
|         self.giver.poll_want() | ||||
|     pub fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         self.giver.poll_want(cx) | ||||
|             .map_err(|_| crate::Error::new_closed()) | ||||
|     } | ||||
|  | ||||
| @@ -136,20 +137,32 @@ pub struct Receiver<T, U> { | ||||
|     taker: want::Taker, | ||||
| } | ||||
|  | ||||
| impl<T, U> Stream for Receiver<T, U> { | ||||
|     type Item = (T, Callback<T, U>); | ||||
|     type Error = Never; | ||||
| //impl<T, U> Stream for Receiver<T, U> { | ||||
| //    type Item = (T, Callback<T, U>); | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { | ||||
|         match self.inner.poll() { | ||||
|             Ok(Async::Ready(item)) => Ok(Async::Ready(item.map(|mut env| { | ||||
| impl<T, U> Receiver<T, U> { | ||||
|     pub(crate) fn poll_next(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<(T, Callback<T, U>)>> { | ||||
|         match Pin::new(&mut self.inner).poll_next(cx) { | ||||
|             Poll::Ready(item) => Poll::Ready(item.map(|mut env| { | ||||
|                 env.0.take().expect("envelope not dropped") | ||||
|             }))), | ||||
|             Ok(Async::NotReady) => { | ||||
|             })), | ||||
|             Poll::Pending => { | ||||
|                 self.taker.want(); | ||||
|                 Ok(Async::NotReady) | ||||
|             } | ||||
|             Err(()) => unreachable!("mpsc never errors"), | ||||
|                 Poll::Pending | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn close(&mut self) { | ||||
|         self.taker.cancel(); | ||||
|         self.inner.close(); | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn try_recv(&mut self) -> Option<(T, Callback<T, U>)> { | ||||
|         match self.inner.try_next() { | ||||
|             Ok(Some(mut env)) => env.0.take(), | ||||
|             Ok(None) => None, | ||||
|             Err(_) => None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -185,10 +198,10 @@ impl<T, U> Callback<T, U> { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn poll_cancel(&mut self) -> Poll<(), ()> { | ||||
|     pub(crate) fn poll_cancel(&mut self, cx: &mut task::Context<'_>) -> Poll<()> { | ||||
|         match *self { | ||||
|             Callback::Retry(ref mut tx) => tx.poll_cancel(), | ||||
|             Callback::NoRetry(ref mut tx) => tx.poll_cancel(), | ||||
|             Callback::Retry(ref mut tx) => tx.poll_cancel(cx), | ||||
|             Callback::NoRetry(ref mut tx) => tx.poll_cancel(cx), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -205,30 +218,30 @@ impl<T, U> Callback<T, U> { | ||||
|  | ||||
|     pub(crate) fn send_when( | ||||
|         self, | ||||
|         mut when: impl Future<Item=U, Error=(crate::Error, Option<T>)>, | ||||
|     ) -> impl Future<Item=(), Error=()> { | ||||
|         mut when: impl Future<Output=Result<U, (crate::Error, Option<T>)>> + Unpin, | ||||
|     ) -> impl Future<Output=()> { | ||||
|         let mut cb = Some(self); | ||||
|  | ||||
|         // "select" on this callback being canceled, and the future completing | ||||
|         future::poll_fn(move || { | ||||
|             match when.poll() { | ||||
|                 Ok(Async::Ready(res)) => { | ||||
|         future::poll_fn(move |cx| { | ||||
|             match Pin::new(&mut when).poll(cx) { | ||||
|                 Poll::Ready(Ok(res)) => { | ||||
|                     cb.take() | ||||
|                         .expect("polled after complete") | ||||
|                         .send(Ok(res)); | ||||
|                     Ok(().into()) | ||||
|                     Poll::Ready(()) | ||||
|                 }, | ||||
|                 Ok(Async::NotReady) => { | ||||
|                 Poll::Pending => { | ||||
|                     // check if the callback is canceled | ||||
|                     try_ready!(cb.as_mut().unwrap().poll_cancel()); | ||||
|                     ready!(cb.as_mut().unwrap().poll_cancel(cx)); | ||||
|                     trace!("send_when canceled"); | ||||
|                     Ok(().into()) | ||||
|                     Poll::Ready(()) | ||||
|                 }, | ||||
|                 Err(err) => { | ||||
|                 Poll::Ready(Err(err)) => { | ||||
|                     cb.take() | ||||
|                         .expect("polled after complete") | ||||
|                         .send(Err(err)); | ||||
|                     Ok(().into()) | ||||
|                     Poll::Ready(()) | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|   | ||||
| @@ -82,15 +82,15 @@ use std::mem; | ||||
| use std::sync::Arc; | ||||
| use std::time::Duration; | ||||
|  | ||||
| use futures::{Async, Future, Poll}; | ||||
| use futures::future::{self, Either, Executor}; | ||||
| use futures::sync::oneshot; | ||||
| use futures_channel::oneshot; | ||||
| use futures_util::future::{self, FutureExt as _, Either}; | ||||
| use futures_util::try_future::TryFutureExt as _; | ||||
| use http::{Method, Request, Response, Uri, Version}; | ||||
| use http::header::{HeaderValue, HOST}; | ||||
| use http::uri::Scheme; | ||||
|  | ||||
| use crate::body::{Body, Payload}; | ||||
| use crate::common::{lazy as hyper_lazy, Lazy}; | ||||
| use crate::common::{lazy as hyper_lazy, Lazy, Future, Pin, Poll, task}; | ||||
| use self::connect::{Alpn, Connect, Connected, Destination}; | ||||
| use self::pool::{Key as PoolKey, Pool, Poolable, Pooled, Reservation}; | ||||
|  | ||||
| @@ -118,6 +118,16 @@ struct Config { | ||||
|     ver: Ver, | ||||
| } | ||||
|  | ||||
| /// A `Future` that will resolve to an HTTP Response. | ||||
| /// | ||||
| /// This is returned by `Client::request` (and `Client::get`). | ||||
| #[must_use = "futures do nothing unless polled"] | ||||
| pub struct ResponseFuture { | ||||
|     inner: Pin<Box<dyn Future<Output=crate::Result<Response<Body>>> + Send>>, | ||||
| } | ||||
|  | ||||
| // ===== impl Client ===== | ||||
|  | ||||
| #[cfg(feature = "runtime")] | ||||
| impl Client<HttpConnector, Body> { | ||||
|     /// Create a new Client with the default [config](Builder). | ||||
| @@ -170,7 +180,7 @@ impl<C, B> Client<C, B> | ||||
| where C: Connect + Sync + 'static, | ||||
|       C::Transport: 'static, | ||||
|       C::Future: 'static, | ||||
|       B: Payload + Send + 'static, | ||||
|       B: Payload + Unpin + Send + 'static, | ||||
|       B::Data: Send, | ||||
| { | ||||
|     /// Send a `GET` request to the supplied `Uri`. | ||||
| @@ -257,16 +267,15 @@ where C: Connect + Sync + 'static, | ||||
|         ResponseFuture::new(Box::new(self.retryably_send_request(req, pool_key))) | ||||
|     } | ||||
|  | ||||
|     fn retryably_send_request(&self, req: Request<B>, pool_key: PoolKey) -> impl Future<Item=Response<Body>, Error=crate::Error> { | ||||
|     fn retryably_send_request(&self, req: Request<B>, pool_key: PoolKey) -> impl Future<Output=crate::Result<Response<Body>>> { | ||||
|         let client = self.clone(); | ||||
|         let uri = req.uri().clone(); | ||||
|  | ||||
|         let mut send_fut = client.send_request(req, pool_key.clone()); | ||||
|         future::poll_fn(move || loop { | ||||
|             match send_fut.poll() { | ||||
|                 Ok(Async::Ready(resp)) => return Ok(Async::Ready(resp)), | ||||
|                 Ok(Async::NotReady) => return Ok(Async::NotReady), | ||||
|                 Err(ClientError::Normal(err)) => return Err(err), | ||||
|         future::poll_fn(move |cx| loop { | ||||
|             match ready!(Pin::new(&mut send_fut).poll(cx)) { | ||||
|                 Ok(resp) => return Poll::Ready(Ok(resp)), | ||||
|                 Err(ClientError::Normal(err)) => return Poll::Ready(Err(err)), | ||||
|                 Err(ClientError::Canceled { | ||||
|                     connection_reused, | ||||
|                     mut req, | ||||
| @@ -275,7 +284,7 @@ where C: Connect + Sync + 'static, | ||||
|                     if !client.config.retry_canceled_requests || !connection_reused { | ||||
|                         // if client disabled, don't retry | ||||
|                         // a fresh connection means we definitely can't retry | ||||
|                         return Err(reason); | ||||
|                         return Poll::Ready(Err(reason)); | ||||
|                     } | ||||
|  | ||||
|                     trace!("unstarted request canceled, trying again (reason={:?})", reason); | ||||
| @@ -286,7 +295,7 @@ where C: Connect + Sync + 'static, | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn send_request(&self, mut req: Request<B>, pool_key: PoolKey) -> impl Future<Item=Response<Body>, Error=ClientError<B>> { | ||||
|     fn send_request(&self, mut req: Request<B>, pool_key: PoolKey) -> impl Future<Output=Result<Response<Body>, ClientError<B>>> + Unpin { | ||||
|         let conn = self.connection_for(req.uri().clone(), pool_key); | ||||
|  | ||||
|         let set_host = self.config.set_host; | ||||
| @@ -320,7 +329,7 @@ where C: Connect + Sync + 'static, | ||||
|                 }; | ||||
|             } else if req.method() == &Method::CONNECT { | ||||
|                 debug!("client does not support CONNECT requests over HTTP2"); | ||||
|                 return Either::A(future::err(ClientError::Normal(crate::Error::new_user_unsupported_request_method()))); | ||||
|                 return Either::Left(future::err(ClientError::Normal(crate::Error::new_user_unsupported_request_method()))); | ||||
|             } | ||||
|  | ||||
|             let fut = pooled.send_request_retryable(req) | ||||
| @@ -328,7 +337,7 @@ where C: Connect + Sync + 'static, | ||||
|  | ||||
|             // If the Connector included 'extra' info, add to Response... | ||||
|             let extra_info = pooled.conn_info.extra.clone(); | ||||
|             let fut = fut.map(move |mut res| { | ||||
|             let fut = fut.map_ok(move |mut res| { | ||||
|                 if let Some(extra) = extra_info { | ||||
|                     extra.set(&mut res); | ||||
|                 } | ||||
| @@ -343,11 +352,11 @@ where C: Connect + Sync + 'static, | ||||
|             // To counteract this, we must check if our senders 'want' channel | ||||
|             // has been closed after having tried to send. If so, error out... | ||||
|             if pooled.is_closed() { | ||||
|                 return Either::B(Either::A(fut)); | ||||
|                 return Either::Right(Either::Left(fut)); | ||||
|             } | ||||
|  | ||||
|             Either::B(Either::B(fut | ||||
|                 .and_then(move |mut res| { | ||||
|             Either::Right(Either::Right(fut | ||||
|                 .map_ok(move |mut res| { | ||||
|                     // If pooled is HTTP/2, we can toss this reference immediately. | ||||
|                     // | ||||
|                     // when pooled is dropped, it will try to insert back into the | ||||
| @@ -363,14 +372,13 @@ where C: Connect + Sync + 'static, | ||||
|                     } else if !res.body().is_end_stream() { | ||||
|                         let (delayed_tx, delayed_rx) = oneshot::channel(); | ||||
|                         res.body_mut().delayed_eof(delayed_rx); | ||||
|                         let on_idle = future::poll_fn(move || { | ||||
|                             pooled.poll_ready() | ||||
|                         let on_idle = future::poll_fn(move |cx| { | ||||
|                             pooled.poll_ready(cx) | ||||
|                         }) | ||||
|                             .then(move |_| { | ||||
|                             .map(move |_| { | ||||
|                                 // At this point, `pooled` is dropped, and had a chance | ||||
|                                 // to insert into the pool (if conn was idle) | ||||
|                                 drop(delayed_tx); | ||||
|                                 Ok(()) | ||||
|                             }); | ||||
|  | ||||
|                         if let Err(err) = executor.execute(on_idle) { | ||||
| @@ -380,23 +388,23 @@ where C: Connect + Sync + 'static, | ||||
|                     } else { | ||||
|                         // There's no body to delay, but the connection isn't | ||||
|                         // ready yet. Only re-insert when it's ready | ||||
|                         let on_idle = future::poll_fn(move || { | ||||
|                             pooled.poll_ready() | ||||
|                         let on_idle = future::poll_fn(move |cx| { | ||||
|                             pooled.poll_ready(cx) | ||||
|                         }) | ||||
|                             .then(|_| Ok(())); | ||||
|                             .map(|_| ()); | ||||
|  | ||||
|                         if let Err(err) = executor.execute(on_idle) { | ||||
|                             // This task isn't critical, so just log and ignore. | ||||
|                             warn!("error spawning task to insert idle connection: {}", err); | ||||
|                         } | ||||
|                     } | ||||
|                     Ok(res) | ||||
|                     res | ||||
|                 }))) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn connection_for(&self, uri: Uri, pool_key: PoolKey) | ||||
|         -> impl Future<Item=Pooled<PoolClient<B>>, Error=ClientError<B>> | ||||
|         -> impl Future<Output=Result<Pooled<PoolClient<B>>, ClientError<B>>> | ||||
|     { | ||||
|         // This actually races 2 different futures to try to get a ready | ||||
|         // connection the fastest, and to reduce connection churn. | ||||
| @@ -415,15 +423,14 @@ where C: Connect + Sync + 'static, | ||||
|         let connect = self.connect_to(uri, pool_key); | ||||
|  | ||||
|         let executor = self.conn_builder.exec.clone(); | ||||
|         checkout | ||||
|             // The order of the `select` is depended on below... | ||||
|             .select2(connect) | ||||
|             .map(move |either| match either { | ||||
|         // The order of the `select` is depended on below... | ||||
|         future::select(checkout, connect) | ||||
|             .then(move |either| match either { | ||||
|                 // Checkout won, connect future may have been started or not. | ||||
|                 // | ||||
|                 // If it has, let it finish and insert back into the pool, | ||||
|                 // so as to not waste the socket... | ||||
|                 Either::A((checked_out, connecting)) => { | ||||
|                 Either::Left((Ok(checked_out), connecting)) => { | ||||
|                     // This depends on the `select` above having the correct | ||||
|                     // order, such that if the checkout future were ready | ||||
|                     // immediately, the connect future will never have been | ||||
| @@ -433,25 +440,23 @@ where C: Connect + Sync + 'static, | ||||
|                     // have been started... | ||||
|                     if connecting.started() { | ||||
|                         let bg = connecting | ||||
|                             .map_err(|err| { | ||||
|                                 trace!("background connect error: {}", err); | ||||
|                             }) | ||||
|                             .map(|_pooled| { | ||||
|                                 // dropping here should just place it in | ||||
|                                 // the Pool for us... | ||||
|                             }) | ||||
|                             .map_err(|err| { | ||||
|                                 trace!("background connect error: {}", err); | ||||
|                             }); | ||||
|                         // An execute error here isn't important, we're just trying | ||||
|                         // to prevent a waste of a socket... | ||||
|                         let _ = executor.execute(bg); | ||||
|                     } | ||||
|                     checked_out | ||||
|                     Either::Left(future::ok(checked_out)) | ||||
|                 }, | ||||
|                 // Connect won, checkout can just be dropped. | ||||
|                 Either::B((connected, _checkout)) => { | ||||
|                     connected | ||||
|                 Either::Right((Ok(connected), _checkout)) => { | ||||
|                     Either::Left(future::ok(connected)) | ||||
|                 }, | ||||
|             }) | ||||
|             .or_else(|either| match either { | ||||
|                 // Either checkout or connect could get canceled: | ||||
|                 // | ||||
|                 // 1. Connect is canceled if this is HTTP/2 and there is | ||||
| @@ -460,25 +465,25 @@ where C: Connect + Sync + 'static, | ||||
|                 //    idle connection reliably. | ||||
|                 // | ||||
|                 // In both cases, we should just wait for the other future. | ||||
|                 Either::A((err, connecting)) => { | ||||
|                 Either::Left((Err(err), connecting)) => Either::Right(Either::Left({ | ||||
|                     if err.is_canceled() { | ||||
|                         Either::A(Either::A(connecting.map_err(ClientError::Normal))) | ||||
|                         Either::Left(connecting.map_err(ClientError::Normal)) | ||||
|                     } else { | ||||
|                         Either::B(future::err(ClientError::Normal(err))) | ||||
|                         Either::Right(future::err(ClientError::Normal(err))) | ||||
|                     } | ||||
|                 }, | ||||
|                 Either::B((err, checkout)) => { | ||||
|                 })), | ||||
|                 Either::Right((Err(err), checkout)) => Either::Right(Either::Right({ | ||||
|                     if err.is_canceled() { | ||||
|                         Either::A(Either::B(checkout.map_err(ClientError::Normal))) | ||||
|                         Either::Left(checkout.map_err(ClientError::Normal)) | ||||
|                     } else { | ||||
|                         Either::B(future::err(ClientError::Normal(err))) | ||||
|                         Either::Right(future::err(ClientError::Normal(err))) | ||||
|                     } | ||||
|                 } | ||||
|                 })), | ||||
|             }) | ||||
|     } | ||||
|  | ||||
|     fn connect_to(&self, uri: Uri, pool_key: PoolKey) | ||||
|         -> impl Lazy<Item=Pooled<PoolClient<B>>, Error=crate::Error> | ||||
|         -> impl Lazy<Output=crate::Result<Pooled<PoolClient<B>>>> + Unpin | ||||
|     { | ||||
|         let executor = self.conn_builder.exec.clone(); | ||||
|         let pool = self.pool.clone(); | ||||
| @@ -499,10 +504,10 @@ where C: Connect + Sync + 'static, | ||||
|                 Some(lock) => lock, | ||||
|                 None => { | ||||
|                     let canceled = crate::Error::new_canceled().with("HTTP/2 connection in progress"); | ||||
|                     return Either::B(future::err(canceled)); | ||||
|                     return Either::Right(future::err(canceled)); | ||||
|                 } | ||||
|             }; | ||||
|             Either::A(connector.connect(dst) | ||||
|             Either::Left(connector.connect(dst) | ||||
|                 .map_err(crate::Error::new_connect) | ||||
|                 .and_then(move |(io, connected)| { | ||||
|                     // If ALPN is h2 and we aren't http2_only already, | ||||
| @@ -518,34 +523,34 @@ where C: Connect + Sync + 'static, | ||||
|                                 // Another connection has already upgraded, | ||||
|                                 // the pool checkout should finish up for us. | ||||
|                                 let canceled = crate::Error::new_canceled().with("ALPN upgraded to HTTP/2"); | ||||
|                                 return Either::B(future::err(canceled)); | ||||
|                                 return Either::Right(future::err(canceled)); | ||||
|                             } | ||||
|                         } | ||||
|                     } else { | ||||
|                         connecting | ||||
|                     }; | ||||
|                     let is_h2 = is_ver_h2 || connected.alpn == Alpn::H2; | ||||
|                     Either::A(conn_builder | ||||
|                     Either::Left(conn_builder | ||||
|                         .http2_only(is_h2) | ||||
|                         .handshake(io) | ||||
|                         .and_then(move |(tx, conn)| { | ||||
|                             trace!("handshake complete, spawning background dispatcher task"); | ||||
|                             let bg = executor.execute(conn.map_err(|e| { | ||||
|                                 debug!("client connection error: {}", e) | ||||
|                             })); | ||||
|                             }).map(|_| ())); | ||||
|  | ||||
|                             // This task is critical, so an execute error | ||||
|                             // should be returned. | ||||
|                             if let Err(err) = bg { | ||||
|                                 warn!("error spawning critical client task: {}", err); | ||||
|                                 return Either::A(future::err(err)); | ||||
|                                 return Either::Left(future::err(err)); | ||||
|                             } | ||||
|  | ||||
|                             // Wait for 'conn' to ready up before we | ||||
|                             // declare this tx as usable | ||||
|                             Either::B(tx.when_ready()) | ||||
|                             Either::Right(tx.when_ready()) | ||||
|                         }) | ||||
|                         .map(move |tx| { | ||||
|                         .map_ok(move |tx| { | ||||
|                             pool.pooled(connecting, PoolClient { | ||||
|                                 conn_info: connected, | ||||
|                                 tx: if is_h2 { | ||||
| @@ -578,18 +583,12 @@ impl<C, B> fmt::Debug for Client<C, B> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// A `Future` that will resolve to an HTTP Response. | ||||
| /// | ||||
| /// This is returned by `Client::request` (and `Client::get`). | ||||
| #[must_use = "futures do nothing unless polled"] | ||||
| pub struct ResponseFuture { | ||||
|     inner: Box<dyn Future<Item=Response<Body>, Error=crate::Error> + Send>, | ||||
| } | ||||
| // ===== impl ResponseFuture ===== | ||||
|  | ||||
| impl ResponseFuture { | ||||
|     fn new(fut: Box<dyn Future<Item=Response<Body>, Error=crate::Error> + Send>) -> Self { | ||||
|     fn new(fut: Box<dyn Future<Output=crate::Result<Response<Body>>> + Send>) -> Self { | ||||
|         Self { | ||||
|             inner: fut, | ||||
|             inner: fut.into(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -606,14 +605,15 @@ impl fmt::Debug for ResponseFuture { | ||||
| } | ||||
|  | ||||
| impl Future for ResponseFuture { | ||||
|     type Item = Response<Body>; | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<Response<Body>>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         self.inner.poll() | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         Pin::new(&mut self.inner).poll(cx) | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ===== impl PoolClient ===== | ||||
|  | ||||
| // FIXME: allow() required due to `impl Trait` leaking types to this lint | ||||
| #[allow(missing_debug_implementations)] | ||||
| struct PoolClient<B> { | ||||
| @@ -627,10 +627,10 @@ enum PoolTx<B> { | ||||
| } | ||||
|  | ||||
| impl<B> PoolClient<B> { | ||||
|     fn poll_ready(&mut self) -> Poll<(), crate::Error> { | ||||
|     fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         match self.tx { | ||||
|             PoolTx::Http1(ref mut tx) => tx.poll_ready(), | ||||
|             PoolTx::Http2(_) => Ok(Async::Ready(())), | ||||
|             PoolTx::Http1(ref mut tx) => tx.poll_ready(cx), | ||||
|             PoolTx::Http2(_) => Poll::Ready(Ok(())), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -661,13 +661,13 @@ impl<B> PoolClient<B> { | ||||
| } | ||||
|  | ||||
| impl<B: Payload + 'static> PoolClient<B> { | ||||
|     fn send_request_retryable(&mut self, req: Request<B>) -> impl Future<Item = Response<Body>, Error = (crate::Error, Option<Request<B>>)> | ||||
|     fn send_request_retryable(&mut self, req: Request<B>) -> impl Future<Output = Result<Response<Body>, (crate::Error, Option<Request<B>>)>> | ||||
|     where | ||||
|         B: Send, | ||||
|     { | ||||
|         match self.tx { | ||||
|             PoolTx::Http1(ref mut tx) => Either::A(tx.send_request_retryable(req)), | ||||
|             PoolTx::Http2(ref mut tx) => Either::B(tx.send_request_retryable(req)), | ||||
|             PoolTx::Http1(ref mut tx) => Either::Left(tx.send_request_retryable(req)), | ||||
|             PoolTx::Http2(ref mut tx) => Either::Right(tx.send_request_retryable(req)), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -710,6 +710,8 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ===== impl ClientError ===== | ||||
|  | ||||
| // FIXME: allow() required due to `impl Trait` leaking types to this lint | ||||
| #[allow(missing_debug_implementations)] | ||||
| enum ClientError<B> { | ||||
| @@ -1027,6 +1029,7 @@ impl Builder { | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     /// Provide an executor to execute background `Connection` tasks. | ||||
|     pub fn executor<E>(&mut self, exec: E) -> &mut Self | ||||
|     where | ||||
| @@ -1035,6 +1038,7 @@ impl Builder { | ||||
|         self.conn_builder.executor(exec); | ||||
|         self | ||||
|     } | ||||
|     */ | ||||
|  | ||||
|     /// Builder a client with this configuration and the default `HttpConnector`. | ||||
|     #[cfg(feature = "runtime")] | ||||
|   | ||||
| @@ -4,12 +4,11 @@ use std::ops::{Deref, DerefMut}; | ||||
| use std::sync::{Arc, Mutex, Weak}; | ||||
| use std::time::{Duration, Instant}; | ||||
|  | ||||
| use futures::{Future, Async, Poll}; | ||||
| use futures::sync::oneshot; | ||||
| use futures_channel::oneshot; | ||||
| #[cfg(feature = "runtime")] | ||||
| use tokio_timer::Interval; | ||||
|  | ||||
| use crate::common::Exec; | ||||
| use crate::common::{Exec, Future, Pin, Poll, Unpin, task}; | ||||
| use super::Ver; | ||||
|  | ||||
| // FIXME: allow() required due to `impl Trait` leaking types to this lint | ||||
| @@ -24,7 +23,7 @@ pub(super) struct Pool<T> { | ||||
| // This is a trait to allow the `client::pool::tests` to work for `i32`. | ||||
| // | ||||
| // See https://github.com/hyperium/hyper/issues/1429 | ||||
| pub(super) trait Poolable: Send + Sized + 'static { | ||||
| pub(super) trait Poolable: Unpin + Send + Sized + 'static { | ||||
|     fn is_open(&self) -> bool; | ||||
|     /// Reserve this connection. | ||||
|     /// | ||||
| @@ -415,7 +414,7 @@ impl<T: Poolable> PoolInner<T> { | ||||
|  | ||||
|         let start = Instant::now() + dur; | ||||
|  | ||||
|         let interval = IdleInterval { | ||||
|         let interval = IdleTask { | ||||
|             interval: Interval::new(start, dur), | ||||
|             pool: WeakOpt::downgrade(pool_ref), | ||||
|             pool_drop_notifier: rx, | ||||
| @@ -449,7 +448,7 @@ impl<T> PoolInner<T> { | ||||
|  | ||||
| #[cfg(feature = "runtime")] | ||||
| impl<T: Poolable> PoolInner<T> { | ||||
|     /// This should *only* be called by the IdleInterval. | ||||
|     /// This should *only* be called by the IdleTask | ||||
|     fn clear_expired(&mut self) { | ||||
|         let dur = self.timeout.expect("interval assumes timeout"); | ||||
|  | ||||
| @@ -569,25 +568,25 @@ pub(super) struct Checkout<T> { | ||||
| } | ||||
|  | ||||
| impl<T: Poolable> Checkout<T> { | ||||
|     fn poll_waiter(&mut self) -> Poll<Option<Pooled<T>>, crate::Error> { | ||||
|     fn poll_waiter(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<crate::Result<Pooled<T>>>> { | ||||
|         static CANCELED: &str = "pool checkout failed"; | ||||
|         if let Some(mut rx) = self.waiter.take() { | ||||
|             match rx.poll() { | ||||
|                 Ok(Async::Ready(value)) => { | ||||
|             match Pin::new(&mut rx).poll(cx) { | ||||
|                 Poll::Ready(Ok(value)) => { | ||||
|                     if value.is_open() { | ||||
|                         Ok(Async::Ready(Some(self.pool.reuse(&self.key, value)))) | ||||
|                         Poll::Ready(Some(Ok(self.pool.reuse(&self.key, value)))) | ||||
|                     } else { | ||||
|                         Err(crate::Error::new_canceled().with(CANCELED)) | ||||
|                         Poll::Ready(Some(Err(crate::Error::new_canceled().with(CANCELED)))) | ||||
|                     } | ||||
|                 }, | ||||
|                 Ok(Async::NotReady) => { | ||||
|                 Poll::Pending => { | ||||
|                     self.waiter = Some(rx); | ||||
|                     Ok(Async::NotReady) | ||||
|                     Poll::Pending | ||||
|                 }, | ||||
|                 Err(_canceled) => Err(crate::Error::new_canceled().with(CANCELED)), | ||||
|                 Poll::Ready(Err(_canceled)) => Poll::Ready(Some(Err(crate::Error::new_canceled().with(CANCELED)))), | ||||
|             } | ||||
|         } else { | ||||
|             Ok(Async::Ready(None)) | ||||
|             Poll::Ready(None) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -622,9 +621,7 @@ impl<T: Poolable> Checkout<T> { | ||||
|             } | ||||
|  | ||||
|             if entry.is_none() && self.waiter.is_none() { | ||||
|                 let (tx, mut rx) = oneshot::channel(); | ||||
|                 let _ = rx.poll(); // park this task | ||||
|  | ||||
|                 let (tx, rx) = oneshot::channel(); | ||||
|                 trace!("checkout waiting for idle connection: {:?}", self.key); | ||||
|                 inner | ||||
|                     .waiters | ||||
| @@ -643,20 +640,21 @@ impl<T: Poolable> Checkout<T> { | ||||
| } | ||||
|  | ||||
| impl<T: Poolable> Future for Checkout<T> { | ||||
|     type Item = Pooled<T>; | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<Pooled<T>>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         if let Some(pooled) = try_ready!(self.poll_waiter()) { | ||||
|             return Ok(Async::Ready(pooled)); | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         if let Some(pooled) = ready!(self.poll_waiter(cx)?) { | ||||
|             return Poll::Ready(Ok(pooled)); | ||||
|         } | ||||
|  | ||||
|         if let Some(pooled) = self.checkout() { | ||||
|             Ok(Async::Ready(pooled)) | ||||
|             Poll::Ready(Ok(pooled)) | ||||
|         } else if !self.pool.is_enabled() { | ||||
|             Err(crate::Error::new_canceled().with("pool is disabled")) | ||||
|             Poll::Ready(Err(crate::Error::new_canceled().with("pool is disabled"))) | ||||
|         } else { | ||||
|             Ok(Async::NotReady) | ||||
|             // There's a new waiter, but there's no way it should be ready yet. | ||||
|             // We just need to register the waker. | ||||
|             self.poll_waiter(cx).map(|_| unreachable!()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -717,37 +715,34 @@ impl Expiration { | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "runtime")] | ||||
| struct IdleInterval<T> { | ||||
| struct IdleTask<T> { | ||||
|     interval: Interval, | ||||
|     pool: WeakOpt<Mutex<PoolInner<T>>>, | ||||
|     // This allows the IdleInterval to be notified as soon as the entire | ||||
|     // This allows the IdleTask to be notified as soon as the entire | ||||
|     // Pool is fully dropped, and shutdown. This channel is never sent on, | ||||
|     // but Err(Canceled) will be received when the Pool is dropped. | ||||
|     pool_drop_notifier: oneshot::Receiver<crate::common::Never>, | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "runtime")] | ||||
| impl<T: Poolable + 'static> Future for IdleInterval<T> { | ||||
|     type Item = (); | ||||
|     type Error = (); | ||||
| impl<T: Poolable + 'static> Future for IdleTask<T> { | ||||
|     type Output = (); | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         // Interval is a Stream | ||||
|         use futures::Stream; | ||||
|         use futures_core::Stream; | ||||
|  | ||||
|         loop { | ||||
|             match self.pool_drop_notifier.poll() { | ||||
|                 Ok(Async::Ready(n)) => match n {}, | ||||
|                 Ok(Async::NotReady) => (), | ||||
|                 Err(_canceled) => { | ||||
|             match Pin::new(&mut self.pool_drop_notifier).poll(cx) { | ||||
|                 Poll::Ready(Ok(n)) => match n {}, | ||||
|                 Poll::Pending => (), | ||||
|                 Poll::Ready(Err(_canceled)) => { | ||||
|                     trace!("pool closed, canceling idle interval"); | ||||
|                     return Ok(Async::Ready(())); | ||||
|                     return Poll::Ready(()); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             try_ready!(self.interval.poll().map_err(|err| { | ||||
|                 error!("idle interval timer error: {}", err); | ||||
|             })); | ||||
|             ready!(Pin::new(&mut self.interval).poll_next(cx)); | ||||
|  | ||||
|             if let Some(inner) = self.pool.upgrade() { | ||||
|                 if let Ok(mut inner) = inner.lock() { | ||||
| @@ -756,7 +751,7 @@ impl<T: Poolable + 'static> Future for IdleInterval<T> { | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|             return Ok(Async::Ready(())); | ||||
|             return Poll::Ready(()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,14 +1,19 @@ | ||||
| use std::mem; | ||||
|  | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use futures::future::Shared; | ||||
| use futures::sync::{mpsc, oneshot}; | ||||
| use tokio_sync::{mpsc, watch}; | ||||
|  | ||||
| use super::Never; | ||||
| use super::{Future, Never, Poll, Pin, task}; | ||||
|  | ||||
| // Sentinel value signaling that the watch is still open | ||||
| enum Action { | ||||
|     Open, | ||||
|     // Closed isn't sent via the `Action` type, but rather once | ||||
|     // the watch::Sender is dropped. | ||||
| } | ||||
|  | ||||
| pub fn channel() -> (Signal, Watch) { | ||||
|     let (tx, rx) = oneshot::channel(); | ||||
|     let (drained_tx, drained_rx) = mpsc::channel(0); | ||||
|     let (tx, rx) = watch::channel(Action::Open); | ||||
|     let (drained_tx, drained_rx) = mpsc::channel(1); | ||||
|     ( | ||||
|         Signal { | ||||
|             drained_rx, | ||||
| @@ -16,14 +21,14 @@ pub fn channel() -> (Signal, Watch) { | ||||
|         }, | ||||
|         Watch { | ||||
|             drained_tx, | ||||
|             rx: rx.shared(), | ||||
|             rx, | ||||
|         }, | ||||
|     ) | ||||
| } | ||||
|  | ||||
| pub struct Signal { | ||||
|     drained_rx: mpsc::Receiver<Never>, | ||||
|     tx: oneshot::Sender<()>, | ||||
|     tx: watch::Sender<Action>, | ||||
| } | ||||
|  | ||||
| pub struct Draining { | ||||
| @@ -33,7 +38,7 @@ pub struct Draining { | ||||
| #[derive(Clone)] | ||||
| pub struct Watch { | ||||
|     drained_tx: mpsc::Sender<Never>, | ||||
|     rx: Shared<oneshot::Receiver<()>>, | ||||
|     rx: watch::Receiver<Action>, | ||||
| } | ||||
|  | ||||
| #[allow(missing_debug_implementations)] | ||||
| @@ -50,7 +55,7 @@ enum State<F> { | ||||
|  | ||||
| impl Signal { | ||||
|     pub fn drain(self) -> Draining { | ||||
|         let _ = self.tx.send(()); | ||||
|         // Simply dropping `self.tx` will signal the watchers | ||||
|         Draining { | ||||
|             drained_rx: self.drained_rx, | ||||
|         } | ||||
| @@ -58,13 +63,12 @@ impl Signal { | ||||
| } | ||||
|  | ||||
| impl Future for Draining { | ||||
|     type Item = (); | ||||
|     type Error = (); | ||||
|     type Output = (); | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         match try_ready!(self.drained_rx.poll()) { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match ready!(self.drained_rx.poll_recv(cx)) { | ||||
|             Some(never) => match never {}, | ||||
|             None => Ok(Async::Ready(())), | ||||
|             None => Poll::Ready(()), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -73,7 +77,7 @@ impl Watch { | ||||
|     pub fn watch<F, FN>(self, future: F, on_drain: FN) -> Watching<F, FN> | ||||
|     where | ||||
|         F: Future, | ||||
|         FN: FnOnce(&mut F), | ||||
|         FN: FnOnce(Pin<&mut F>), | ||||
|     { | ||||
|         Watching { | ||||
|             future, | ||||
| @@ -86,28 +90,29 @@ impl Watch { | ||||
| impl<F, FN> Future for Watching<F, FN> | ||||
| where | ||||
|     F: Future, | ||||
|     FN: FnOnce(&mut F), | ||||
|     FN: FnOnce(Pin<&mut F>), | ||||
| { | ||||
|     type Item = F::Item; | ||||
|     type Error = F::Error; | ||||
|     type Output = F::Output; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         let me = unsafe { self.get_unchecked_mut() }; | ||||
|         loop { | ||||
|             match mem::replace(&mut self.state, State::Draining) { | ||||
|             match mem::replace(&mut me.state, State::Draining) { | ||||
|                 State::Watch(on_drain) => { | ||||
|                     match self.watch.rx.poll() { | ||||
|                         Ok(Async::Ready(_)) | Err(_) => { | ||||
|                     match me.watch.rx.poll_ref(cx) { | ||||
|                         Poll::Ready(None) => { | ||||
|                             // Drain has been triggered! | ||||
|                             on_drain(&mut self.future); | ||||
|                             on_drain(unsafe { Pin::new_unchecked(&mut me.future) }); | ||||
|                         }, | ||||
|                         Ok(Async::NotReady) => { | ||||
|                             self.state = State::Watch(on_drain); | ||||
|                             return self.future.poll(); | ||||
|                         Poll::Ready(Some(_/*State::Open*/)) | | ||||
|                         Poll::Pending => { | ||||
|                             me.state = State::Watch(on_drain); | ||||
|                             return unsafe { Pin::new_unchecked(&mut me.future) }.poll(cx); | ||||
|                         }, | ||||
|                     } | ||||
|                 }, | ||||
|                 State::Draining => { | ||||
|                     return self.future.poll(); | ||||
|                     return unsafe { Pin::new_unchecked(&mut me.future) }.poll(cx); | ||||
|                 }, | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| use std::fmt; | ||||
| use std::future::Future; | ||||
| use std::pin::Pin; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| use futures::future::{Executor, Future}; | ||||
| use tokio_executor::TypedExecutor; | ||||
|  | ||||
| use crate::body::Payload; | ||||
| use crate::proto::h2::server::H2Stream; | ||||
| @@ -9,11 +11,11 @@ use crate::server::conn::spawn_all::{NewSvcTask, Watcher}; | ||||
| use crate::service::Service; | ||||
|  | ||||
| pub trait H2Exec<F, B: Payload>: Clone { | ||||
|     fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()>; | ||||
|     fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()>; | ||||
| } | ||||
|  | ||||
| pub trait NewSvcExec<I, N, S: Service, E, W: Watcher<I, S, E>>: Clone { | ||||
|     fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()>; | ||||
|     fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()>; | ||||
| } | ||||
|  | ||||
| // Either the user provides an executor for background tasks, or we use | ||||
| @@ -21,7 +23,7 @@ pub trait NewSvcExec<I, N, S: Service, E, W: Watcher<I, S, E>>: Clone { | ||||
| #[derive(Clone)] | ||||
| pub enum Exec { | ||||
|     Default, | ||||
|     Executor(Arc<dyn Executor<Box<dyn Future<Item=(), Error=()> + Send>> + Send + Sync>), | ||||
|     Executor(Arc<dyn TypedExecutor<Pin<Box<dyn Future<Output=()> + Send>>> + Send + Sync>), | ||||
| } | ||||
|  | ||||
| // ===== impl Exec ===== | ||||
| @@ -29,14 +31,13 @@ pub enum Exec { | ||||
| impl Exec { | ||||
|     pub(crate) fn execute<F>(&self, fut: F) -> crate::Result<()> | ||||
|     where | ||||
|         F: Future<Item=(), Error=()> + Send + 'static, | ||||
|         F: Future<Output=()> + Send + 'static, | ||||
|     { | ||||
|         match *self { | ||||
|             Exec::Default => { | ||||
|                 #[cfg(feature = "runtime")] | ||||
|                 { | ||||
|                     use std::error::Error as StdError; | ||||
|                     use ::tokio_executor::Executor; | ||||
|  | ||||
|                     struct TokioSpawnError; | ||||
|  | ||||
| @@ -59,7 +60,7 @@ impl Exec { | ||||
|                     } | ||||
|  | ||||
|                     ::tokio_executor::DefaultExecutor::current() | ||||
|                         .spawn(Box::new(fut)) | ||||
|                         .spawn(Box::pin(fut)) | ||||
|                         .map_err(|err| { | ||||
|                             warn!("executor error: {:?}", err); | ||||
|                             crate::Error::new_execute(TokioSpawnError) | ||||
| @@ -72,11 +73,14 @@ impl Exec { | ||||
|                 } | ||||
|             }, | ||||
|             Exec::Executor(ref e) => { | ||||
|                 e.execute(Box::new(fut)) | ||||
|                 unimplemented!("custom executor exec"); | ||||
|                 /* XXX: needs mut | ||||
|                 e.spawn(Box::pin(fut)) | ||||
|                     .map_err(|err| { | ||||
|                         warn!("executor error: {:?}", err.kind()); | ||||
|                         warn!("executor error: {:?}", err); | ||||
|                         crate::Error::new_execute("custom executor failed") | ||||
|                     }) | ||||
|                     */ | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| @@ -92,21 +96,21 @@ impl fmt::Debug for Exec { | ||||
|  | ||||
| impl<F, B> H2Exec<F, B> for Exec | ||||
| where | ||||
|     H2Stream<F, B>: Future<Item=(), Error=()> + Send + 'static, | ||||
|     H2Stream<F, B>: Future<Output = ()> + Send + 'static, | ||||
|     B: Payload, | ||||
| { | ||||
|     fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()> { | ||||
|     fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()> { | ||||
|         self.execute(fut) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for Exec | ||||
| where | ||||
|     NewSvcTask<I, N, S, E, W>: Future<Item=(), Error=()> + Send + 'static, | ||||
|     NewSvcTask<I, N, S, E, W>: Future<Output=()> + Send + 'static, | ||||
|     S: Service, | ||||
|     W: Watcher<I, S, E>, | ||||
| { | ||||
|     fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> { | ||||
|     fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> { | ||||
|         self.execute(fut) | ||||
|     } | ||||
| } | ||||
| @@ -115,14 +119,14 @@ where | ||||
|  | ||||
| impl<E, F, B> H2Exec<F, B> for E | ||||
| where | ||||
|     E: Executor<H2Stream<F, B>> + Clone, | ||||
|     H2Stream<F, B>: Future<Item=(), Error=()>, | ||||
|     E: TypedExecutor<H2Stream<F, B>> + Clone, | ||||
|     H2Stream<F, B>: Future<Output=()>, | ||||
|     B: Payload, | ||||
| { | ||||
|     fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()> { | ||||
|         self.execute(fut) | ||||
|     fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()> { | ||||
|         self.spawn(fut) | ||||
|             .map_err(|err| { | ||||
|                 warn!("executor error: {:?}", err.kind()); | ||||
|                 warn!("executor error: {:?}", err); | ||||
|                 crate::Error::new_execute("custom executor failed") | ||||
|             }) | ||||
|     } | ||||
| @@ -130,15 +134,15 @@ where | ||||
|  | ||||
| impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for E | ||||
| where | ||||
|     E: Executor<NewSvcTask<I, N, S, E, W>> + Clone, | ||||
|     NewSvcTask<I, N, S, E, W>: Future<Item=(), Error=()>, | ||||
|     E: TypedExecutor<NewSvcTask<I, N, S, E, W>> + Clone, | ||||
|     NewSvcTask<I, N, S, E, W>: Future<Output=()>, | ||||
|     S: Service, | ||||
|     W: Watcher<I, S, E>, | ||||
| { | ||||
|     fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> { | ||||
|         self.execute(fut) | ||||
|     fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> { | ||||
|         self.spawn(fut) | ||||
|             .map_err(|err| { | ||||
|                 warn!("executor error: {:?}", err.kind()); | ||||
|                 warn!("executor error: {:?}", err); | ||||
|                 crate::Error::new_execute("custom executor failed") | ||||
|             }) | ||||
|     } | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| use std::cmp; | ||||
| use std::io::{self, Read, Write}; | ||||
| use std::io::{self, Read}; | ||||
| use std::marker::Unpin; | ||||
|  | ||||
| use bytes::{Buf, BufMut, Bytes, IntoBuf}; | ||||
| use futures::{Async, Poll}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::common::{Pin, Poll, task}; | ||||
|  | ||||
| /// Combine a buffer with an IO, rewinding reads to use the buffer. | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct Rewind<T> { | ||||
| @@ -37,12 +38,16 @@ impl<T> Rewind<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> Read for Rewind<T> | ||||
| impl<T> AsyncRead for Rewind<T> | ||||
| where | ||||
|     T: Read, | ||||
|     T: AsyncRead + Unpin, | ||||
| { | ||||
|     #[inline] | ||||
|     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | ||||
|     unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { | ||||
|         self.inner.prepare_uninitialized_buffer(buf) | ||||
|     } | ||||
|  | ||||
|     fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> { | ||||
|         if let Some(pre_bs) = self.pre.take() { | ||||
|             // If there are no remaining bytes, let the bytes get dropped. | ||||
|             if pre_bs.len() > 0 { | ||||
| @@ -57,39 +62,17 @@ where | ||||
|                     self.pre = Some(new_pre); | ||||
|                 } | ||||
|  | ||||
|                 return Ok(read_cnt); | ||||
|                 return Poll::Ready(Ok(read_cnt)); | ||||
|             } | ||||
|         } | ||||
|         self.inner.read(buf) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> Write for Rewind<T> | ||||
| where | ||||
|     T: Write, | ||||
| { | ||||
|     #[inline] | ||||
|     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | ||||
|         self.inner.write(buf) | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn flush(&mut self) -> io::Result<()> { | ||||
|         self.inner.flush() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> AsyncRead for Rewind<T> | ||||
| where | ||||
|     T: AsyncRead, | ||||
| { | ||||
|     #[inline] | ||||
|     unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { | ||||
|         self.inner.prepare_uninitialized_buffer(buf) | ||||
|         Pin::new(&mut self.inner).poll_read(cx, buf) | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     #[inline] | ||||
|     fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||
|         use std::cmp; | ||||
|  | ||||
|         if let Some(bs) = self.pre.take() { | ||||
|             let pre_len = bs.len(); | ||||
|             // If there are no remaining bytes, let the bytes get dropped. | ||||
| @@ -112,21 +95,31 @@ where | ||||
|         } | ||||
|         self.inner.read_buf(buf) | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  | ||||
| impl<T> AsyncWrite for Rewind<T> | ||||
| where | ||||
|     T: AsyncWrite, | ||||
|     T: AsyncWrite + Unpin, | ||||
| { | ||||
|     #[inline] | ||||
|     fn shutdown(&mut self) -> Poll<(), io::Error> { | ||||
|         AsyncWrite::shutdown(&mut self.inner) | ||||
|     fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> { | ||||
|         Pin::new(&mut self.inner).poll_write(cx, buf) | ||||
|     } | ||||
|  | ||||
|     fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         Pin::new(&mut self.inner).poll_flush(cx) | ||||
|     } | ||||
|  | ||||
|     fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         Pin::new(&mut self.inner).poll_shutdown(cx) | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     #[inline] | ||||
|     fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||
|         self.inner.write_buf(buf) | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| use std::mem; | ||||
|  | ||||
| use futures::{Future, IntoFuture, Poll}; | ||||
| use super::{Future, Pin, Poll, task}; | ||||
|  | ||||
| pub(crate) trait Started: Future { | ||||
|     fn started(&self) -> bool; | ||||
| @@ -9,7 +9,7 @@ pub(crate) trait Started: Future { | ||||
| pub(crate) fn lazy<F, R>(func: F) -> Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
|     R: Future + Unpin, | ||||
| { | ||||
|     Lazy { | ||||
|         inner: Inner::Init(func), | ||||
| @@ -18,8 +18,8 @@ where | ||||
|  | ||||
| // FIXME: allow() required due to `impl Trait` leaking types to this lint | ||||
| #[allow(missing_debug_implementations)] | ||||
| pub(crate) struct Lazy<F, R: IntoFuture> { | ||||
|     inner: Inner<F, R::Future> | ||||
| pub(crate) struct Lazy<F, R> { | ||||
|     inner: Inner<F, R> | ||||
| } | ||||
|  | ||||
| enum Inner<F, R> { | ||||
| @@ -31,7 +31,7 @@ enum Inner<F, R> { | ||||
| impl<F, R> Started for Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
|     R: Future + Unpin, | ||||
| { | ||||
|     fn started(&self) -> bool { | ||||
|         match self.inner { | ||||
| @@ -45,21 +45,20 @@ where | ||||
| impl<F, R> Future for Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
|     R: Future + Unpin, | ||||
| { | ||||
|     type Item = R::Item; | ||||
|     type Error = R::Error; | ||||
|     type Output = R::Output; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match self.inner { | ||||
|             Inner::Fut(ref mut f) => return f.poll(), | ||||
|             Inner::Fut(ref mut f) => return Pin::new(f).poll(cx), | ||||
|             _ => (), | ||||
|         } | ||||
|  | ||||
|         match mem::replace(&mut self.inner, Inner::Empty) { | ||||
|             Inner::Init(func) => { | ||||
|                 let mut fut = func().into_future(); | ||||
|                 let ret = fut.poll(); | ||||
|                 let mut fut = func(); | ||||
|                 let ret = Pin::new(&mut fut).poll(cx); | ||||
|                 self.inner = Inner::Fut(fut); | ||||
|                 ret | ||||
|             }, | ||||
| @@ -68,3 +67,6 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| // The closure `F` is never pinned | ||||
| impl<F, R: Unpin> Unpin for Lazy<F, R> {} | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,12 @@ | ||||
| macro_rules! ready { | ||||
|     ($e:expr) => ( | ||||
|         match $e { | ||||
|             ::std::task::Poll::Ready(v) => v, | ||||
|             ::std::task::Poll::Pending => return ::std::task::Poll::Pending, | ||||
|         } | ||||
|     ) | ||||
| } | ||||
|  | ||||
| mod buf; | ||||
| pub(crate) mod drain; | ||||
| pub(crate) mod exec; | ||||
| @@ -10,4 +19,12 @@ pub(crate) use self::buf::StaticBuf; | ||||
| pub(crate) use self::exec::Exec; | ||||
| pub(crate) use self::lazy::{lazy, Started as Lazy}; | ||||
| pub use self::never::Never; | ||||
| pub(crate) use self::task::YieldNow; | ||||
| pub(crate) use self::task::Poll; | ||||
|  | ||||
| // group up types normally needed for `Future` | ||||
| pub(crate) use std::{ | ||||
|     future::Future, | ||||
|     marker::Unpin, | ||||
|     pin::Pin, | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,40 +1,10 @@ | ||||
| use futures::{Async, Poll, task::Task}; | ||||
|  | ||||
| pub(crate) use std::task::{Context, Poll}; | ||||
| use super::Never; | ||||
|  | ||||
| /// A type to help "yield" a future, such that it is re-scheduled immediately. | ||||
| /// A function to help "yield" a future, such that it is re-scheduled immediately. | ||||
| /// | ||||
| /// Useful for spin counts, so a future doesn't hog too much time. | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct YieldNow { | ||||
|     cached_task: Option<Task>, | ||||
| } | ||||
|  | ||||
| impl YieldNow { | ||||
|     pub(crate) fn new() -> YieldNow { | ||||
|         YieldNow { | ||||
|             cached_task: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Returns `Ok(Async::NotReady)` always, while also notifying the | ||||
|     /// current task so that it is rescheduled immediately. | ||||
|     /// | ||||
|     /// Since it never returns `Async::Ready` or `Err`, those types are | ||||
|     /// set to `Never`. | ||||
|     pub(crate) fn poll_yield(&mut self) -> Poll<Never, Never> { | ||||
|         // Check for a cached `Task` first... | ||||
|         if let Some(ref t) = self.cached_task { | ||||
|             if t.will_notify_current() { | ||||
|                 t.notify(); | ||||
|                 return Ok(Async::NotReady); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // No cached task, or not current, so get a new one... | ||||
|         let t = ::futures::task::current(); | ||||
|         t.notify(); | ||||
|         self.cached_task = Some(t); | ||||
|         Ok(Async::NotReady) | ||||
|     } | ||||
| pub(crate) fn yield_now(cx: &mut Context) -> Poll<Never> { | ||||
|     cx.waker().wake_by_ref(); | ||||
|     Poll::Pending | ||||
| } | ||||
|   | ||||
							
								
								
									
										24
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -1,7 +1,10 @@ | ||||
| #![doc(html_root_url = "https://docs.rs/hyper/0.12.32")] | ||||
| #![deny(missing_docs)] | ||||
| #![deny(missing_debug_implementations)] | ||||
| #![cfg_attr(test, deny(warnings))] | ||||
| // XXX NOOOOOOOO | ||||
| //#![cfg_attr(test, deny(warnings))] | ||||
| #![allow(warnings)] | ||||
| #![feature(async_await)] | ||||
| #![cfg_attr(all(test, feature = "nightly"), feature(test))] | ||||
|  | ||||
| //! # hyper | ||||
| @@ -17,27 +20,8 @@ | ||||
| //! If looking for just a convenient HTTP client, consider the | ||||
| //! [reqwest](https://crates.io/crates/reqwest) crate. | ||||
|  | ||||
| extern crate bytes; | ||||
| #[macro_use] extern crate futures; | ||||
| #[cfg(feature = "runtime")] extern crate futures_cpupool; | ||||
| extern crate h2; | ||||
| #[doc(hidden)] pub extern crate http; | ||||
| extern crate http_body; | ||||
| extern crate httparse; | ||||
| extern crate iovec; | ||||
| extern crate itoa; | ||||
| #[macro_use] extern crate log; | ||||
| #[cfg(feature = "runtime")] extern crate net2; | ||||
| extern crate time; | ||||
| #[cfg(feature = "runtime")] extern crate tokio; | ||||
| extern crate tokio_buf; | ||||
| #[cfg(feature = "runtime")] extern crate tokio_executor; | ||||
| #[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_threadpool; | ||||
| #[cfg(feature = "runtime")] extern crate tokio_timer; | ||||
| extern crate want; | ||||
|  | ||||
| #[cfg(all(test, feature = "nightly"))] | ||||
| extern crate test; | ||||
|   | ||||
| @@ -3,12 +3,12 @@ use std::io::{self}; | ||||
| use std::marker::PhantomData; | ||||
|  | ||||
| use bytes::{Buf, Bytes}; | ||||
| use futures::{Async, Poll}; | ||||
| use http::{HeaderMap, Method, Version}; | ||||
| use http::header::{HeaderValue, CONNECTION}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::Chunk; | ||||
| use crate::common::{Pin, Poll, Unpin, task}; | ||||
| use crate::proto::{BodyLength, DecodedLength, MessageHead}; | ||||
| use crate::headers::connection_keep_alive; | ||||
| use super::io::{Buffered}; | ||||
| @@ -26,11 +26,11 @@ const H2_PREFACE: &'static [u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; | ||||
| pub(crate) struct Conn<I, B, T> { | ||||
|     io: Buffered<I, EncodedBuf<B>>, | ||||
|     state: State, | ||||
|     _marker: PhantomData<T> | ||||
|     _marker: PhantomData<fn(T)> | ||||
| } | ||||
|  | ||||
| impl<I, B, T> Conn<I, B, T> | ||||
| where I: AsyncRead + AsyncWrite, | ||||
| where I: AsyncRead + AsyncWrite + Unpin, | ||||
|       B: Buf, | ||||
|       T: Http1Transaction, | ||||
| { | ||||
| @@ -129,16 +129,15 @@ where I: AsyncRead + AsyncWrite, | ||||
|         read_buf.len() >= 24 && read_buf[..24] == *H2_PREFACE | ||||
|     } | ||||
|  | ||||
|     pub fn read_head(&mut self) -> Poll<Option<(MessageHead<T::Incoming>, DecodedLength, bool)>, crate::Error> { | ||||
|     pub fn poll_read_head(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<crate::Result<(MessageHead<T::Incoming>, DecodedLength, bool)>>> { | ||||
|         debug_assert!(self.can_read_head()); | ||||
|         trace!("Conn::read_head"); | ||||
|  | ||||
|         let msg = match self.io.parse::<T>(ParseContext { | ||||
|         let msg = match ready!(self.io.parse::<T>(cx, ParseContext { | ||||
|             cached_headers: &mut self.state.cached_headers, | ||||
|             req_method: &mut self.state.method, | ||||
|         }) { | ||||
|             Ok(Async::Ready(msg)) => msg, | ||||
|             Ok(Async::NotReady) => return Ok(Async::NotReady), | ||||
|         })) { | ||||
|             Ok(msg) => msg, | ||||
|             Err(e) => return self.on_read_head_error(e), | ||||
|         }; | ||||
|  | ||||
| @@ -155,7 +154,7 @@ where I: AsyncRead + AsyncWrite, | ||||
|             debug_assert!(!msg.expect_continue, "expect-continue needs a body"); | ||||
|             self.state.reading = Reading::KeepAlive; | ||||
|             if !T::should_read_first() { | ||||
|                 self.try_keep_alive(); | ||||
|                 self.try_keep_alive(cx); | ||||
|             } | ||||
|         } else { | ||||
|             if msg.expect_continue { | ||||
| @@ -165,10 +164,10 @@ where I: AsyncRead + AsyncWrite, | ||||
|             self.state.reading = Reading::Body(Decoder::new(msg.decode)); | ||||
|         }; | ||||
|  | ||||
|         Ok(Async::Ready(Some((msg.head, msg.decode, msg.wants_upgrade)))) | ||||
|         Poll::Ready(Some(Ok((msg.head, msg.decode, msg.wants_upgrade)))) | ||||
|     } | ||||
|  | ||||
|     fn on_read_head_error<Z>(&mut self, e: crate::Error) -> Poll<Option<Z>, crate::Error> { | ||||
|     fn on_read_head_error<Z>(&mut self, e: crate::Error) -> Poll<Option<crate::Result<Z>>> { | ||||
|         // If we are currently waiting on a message, then an empty | ||||
|         // message should be reported as an error. If not, it is just | ||||
|         // the connection closing gracefully. | ||||
| @@ -179,25 +178,28 @@ where I: AsyncRead + AsyncWrite, | ||||
|         if was_mid_parse || must_error { | ||||
|             // We check if the buf contains the h2 Preface | ||||
|             debug!("parse error ({}) with {} bytes", e, self.io.read_buf().len()); | ||||
|             self.on_parse_error(e) | ||||
|                 .map(|()| Async::NotReady) | ||||
|             match self.on_parse_error(e) { | ||||
|                 Ok(()) => Poll::Pending, // XXX: wat? | ||||
|                 Err(e) => Poll::Ready(Some(Err(e))), | ||||
|  | ||||
|             } | ||||
|         } else { | ||||
|             debug!("read eof"); | ||||
|             Ok(Async::Ready(None)) | ||||
|             Poll::Ready(None) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn read_body(&mut self) -> Poll<Option<Chunk>, io::Error> { | ||||
|     pub fn poll_read_body(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<io::Result<Chunk>>> { | ||||
|         debug_assert!(self.can_read_body()); | ||||
|  | ||||
|         let (reading, ret) = match self.state.reading { | ||||
|             Reading::Body(ref mut decoder) => { | ||||
|                 match decoder.decode(&mut self.io) { | ||||
|                     Ok(Async::Ready(slice)) => { | ||||
|                 match decoder.decode(cx, &mut self.io) { | ||||
|                     Poll::Ready(Ok(slice)) => { | ||||
|                         let (reading, chunk) = if decoder.is_eof() { | ||||
|                             debug!("incoming body completed"); | ||||
|                             (Reading::KeepAlive, if !slice.is_empty() { | ||||
|                                 Some(Chunk::from(slice)) | ||||
|                                 Some(Ok(Chunk::from(slice))) | ||||
|                             } else { | ||||
|                                 None | ||||
|                             }) | ||||
| @@ -208,14 +210,14 @@ where I: AsyncRead + AsyncWrite, | ||||
|                             // an empty slice... | ||||
|                             (Reading::Closed, None) | ||||
|                         } else { | ||||
|                             return Ok(Async::Ready(Some(Chunk::from(slice)))); | ||||
|                             return Poll::Ready(Some(Ok(Chunk::from(slice)))); | ||||
|                         }; | ||||
|                         (reading, Ok(Async::Ready(chunk))) | ||||
|                         (reading, Poll::Ready(chunk)) | ||||
|                     }, | ||||
|                     Ok(Async::NotReady) => return Ok(Async::NotReady), | ||||
|                     Err(e) => { | ||||
|                     Poll::Pending => return Poll::Pending, | ||||
|                     Poll::Ready(Err(e)) => { | ||||
|                         debug!("decode stream error: {}", e); | ||||
|                         (Reading::Closed, Err(e)) | ||||
|                         (Reading::Closed, Poll::Ready(Some(Err(e)))) | ||||
|                     }, | ||||
|                 } | ||||
|             }, | ||||
| @@ -223,7 +225,7 @@ where I: AsyncRead + AsyncWrite, | ||||
|         }; | ||||
|  | ||||
|         self.state.reading = reading; | ||||
|         self.try_keep_alive(); | ||||
|         self.try_keep_alive(cx); | ||||
|         ret | ||||
|     } | ||||
|  | ||||
| @@ -233,13 +235,13 @@ where I: AsyncRead + AsyncWrite, | ||||
|         ret | ||||
|     } | ||||
|  | ||||
|     pub fn read_keep_alive(&mut self) -> Poll<(), crate::Error> { | ||||
|     pub fn poll_read_keep_alive(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         debug_assert!(!self.can_read_head() && !self.can_read_body()); | ||||
|  | ||||
|         if self.is_mid_message() { | ||||
|             self.mid_message_detect_eof() | ||||
|             self.mid_message_detect_eof(cx) | ||||
|         } else { | ||||
|             self.require_empty_read() | ||||
|             self.require_empty_read(cx) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -254,25 +256,25 @@ where I: AsyncRead + AsyncWrite, | ||||
|     // | ||||
|     // This should only be called for Clients wanting to enter the idle | ||||
|     // state. | ||||
|     fn require_empty_read(&mut self) -> Poll<(), crate::Error> { | ||||
|     fn require_empty_read(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         debug_assert!(!self.can_read_head() && !self.can_read_body()); | ||||
|         debug_assert!(!self.is_mid_message()); | ||||
|         debug_assert!(T::is_client()); | ||||
|  | ||||
|         if !self.io.read_buf().is_empty() { | ||||
|             debug!("received an unexpected {} bytes", self.io.read_buf().len()); | ||||
|             return Err(crate::Error::new_unexpected_message()); | ||||
|             return Poll::Ready(Err(crate::Error::new_unexpected_message())); | ||||
|         } | ||||
|  | ||||
|         let num_read = try_ready!(self.force_io_read().map_err(crate::Error::new_io)); | ||||
|         let num_read = ready!(self.force_io_read(cx)).map_err(crate::Error::new_io)?; | ||||
|  | ||||
|         if num_read == 0 { | ||||
|             let ret = if self.should_error_on_eof() { | ||||
|                 trace!("found unexpected EOF on busy connection: {:?}", self.state); | ||||
|                 Err(crate::Error::new_incomplete()) | ||||
|                 Poll::Ready(Err(crate::Error::new_incomplete())) | ||||
|             } else { | ||||
|                 trace!("found EOF on idle connection, closing"); | ||||
|                 Ok(Async::Ready(())) | ||||
|                 Poll::Ready(Ok(())) | ||||
|             }; | ||||
|  | ||||
|             // order is important: should_error needs state BEFORE close_read | ||||
| @@ -281,38 +283,39 @@ where I: AsyncRead + AsyncWrite, | ||||
|         } | ||||
|  | ||||
|         debug!("received unexpected {} bytes on an idle connection", num_read); | ||||
|         Err(crate::Error::new_unexpected_message()) | ||||
|         Poll::Ready(Err(crate::Error::new_unexpected_message())) | ||||
|     } | ||||
|  | ||||
|     fn mid_message_detect_eof(&mut self) -> Poll<(), crate::Error> { | ||||
|     fn mid_message_detect_eof(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         debug_assert!(!self.can_read_head() && !self.can_read_body()); | ||||
|         debug_assert!(self.is_mid_message()); | ||||
|  | ||||
|         if self.state.allow_half_close || !self.io.read_buf().is_empty() { | ||||
|             return Ok(Async::NotReady); | ||||
|             return Poll::Pending; | ||||
|         } | ||||
|  | ||||
|         let num_read = try_ready!(self.force_io_read().map_err(crate::Error::new_io)); | ||||
|         let num_read = ready!(self.force_io_read(cx)).map_err(crate::Error::new_io)?; | ||||
|  | ||||
|         if num_read == 0 { | ||||
|             trace!("found unexpected EOF on busy connection: {:?}", self.state); | ||||
|             self.state.close_read(); | ||||
|             Err(crate::Error::new_incomplete()) | ||||
|             Poll::Ready(Err(crate::Error::new_incomplete())) | ||||
|         } else { | ||||
|             Ok(Async::Ready(())) | ||||
|             Poll::Ready(Ok(())) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn force_io_read(&mut self) -> Poll<usize, io::Error> { | ||||
|          self.io.read_from_io().map_err(|e| { | ||||
|     fn force_io_read(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<usize>> { | ||||
|         let result = ready!(self.io.poll_read_from_io(cx)); | ||||
|         Poll::Ready(result.map_err(|e| { | ||||
|             trace!("force_io_read; io error = {:?}", e); | ||||
|             self.state.close(); | ||||
|             e | ||||
|          }) | ||||
|          })) | ||||
|     } | ||||
|  | ||||
|  | ||||
|     fn maybe_notify(&mut self) { | ||||
|     fn maybe_notify(&mut self, cx: &mut task::Context<'_>) { | ||||
|         // its possible that we returned NotReady from poll() without having | ||||
|         // exhausted the underlying Io. We would have done this when we | ||||
|         // determined we couldn't keep reading until we knew how writing | ||||
| @@ -336,13 +339,13 @@ where I: AsyncRead + AsyncWrite, | ||||
|  | ||||
|         if !self.io.is_read_blocked() { | ||||
|             if self.io.read_buf().is_empty() { | ||||
|                 match self.io.read_from_io() { | ||||
|                     Ok(Async::Ready(_)) => (), | ||||
|                     Ok(Async::NotReady) => { | ||||
|                 match self.io.poll_read_from_io(cx) { | ||||
|                     Poll::Ready(Ok(_)) => (), | ||||
|                     Poll::Pending => { | ||||
|                         trace!("maybe_notify; read_from_io blocked"); | ||||
|                         return | ||||
|                     }, | ||||
|                     Err(e) => { | ||||
|                     Poll::Ready(Err(e)) => { | ||||
|                         trace!("maybe_notify; read_from_io error: {}", e); | ||||
|                         self.state.close(); | ||||
|                     } | ||||
| @@ -352,9 +355,9 @@ where I: AsyncRead + AsyncWrite, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn try_keep_alive(&mut self) { | ||||
|     fn try_keep_alive(&mut self, cx: &mut task::Context<'_>) { | ||||
|         self.state.try_keep_alive::<T>(); | ||||
|         self.maybe_notify(); | ||||
|         self.maybe_notify(cx); | ||||
|     } | ||||
|  | ||||
|     pub fn can_write_head(&self) -> bool { | ||||
| @@ -586,23 +589,22 @@ where I: AsyncRead + AsyncWrite, | ||||
|         Err(err) | ||||
|     } | ||||
|  | ||||
|     pub fn flush(&mut self) -> Poll<(), io::Error> { | ||||
|         try_ready!(self.io.flush()); | ||||
|         self.try_keep_alive(); | ||||
|     pub fn poll_flush(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         ready!(Pin::new(&mut self.io).poll_flush(cx))?; | ||||
|         self.try_keep_alive(cx); | ||||
|         trace!("flushed({}): {:?}", T::LOG, self.state); | ||||
|         Ok(Async::Ready(())) | ||||
|         Poll::Ready(Ok(())) | ||||
|     } | ||||
|  | ||||
|     pub fn shutdown(&mut self) -> Poll<(), io::Error> { | ||||
|         match self.io.io_mut().shutdown() { | ||||
|             Ok(Async::NotReady) => Ok(Async::NotReady), | ||||
|             Ok(Async::Ready(())) => { | ||||
|     pub fn poll_shutdown(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         match ready!(Pin::new(self.io.io_mut()).poll_shutdown(cx)) { | ||||
|             Ok(()) => { | ||||
|                 trace!("shut down IO complete"); | ||||
|                 Ok(Async::Ready(())) | ||||
|             } | ||||
|                 Poll::Ready(Ok(())) | ||||
|             }, | ||||
|             Err(e) => { | ||||
|                 debug!("error shutting down IO: {}", e); | ||||
|                 Err(e) | ||||
|                 Poll::Ready(Err(e)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -652,6 +654,9 @@ impl<I, B: Buf, T> fmt::Debug for Conn<I, B, T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| // B and T are never pinned | ||||
| impl<I: Unpin, B, T> Unpin for Conn<I, B, T> {} | ||||
|  | ||||
| struct State { | ||||
|     allow_half_close: bool, | ||||
|     /// Re-usable HeaderMap to reduce allocating new ones. | ||||
|   | ||||
| @@ -3,9 +3,10 @@ use std::fmt; | ||||
| use std::usize; | ||||
| use std::io; | ||||
|  | ||||
| use futures::{Async, Poll}; | ||||
| use bytes::Bytes; | ||||
|  | ||||
| use crate::common::{Poll, task}; | ||||
|  | ||||
| use super::io::MemRead; | ||||
| use super::{DecodedLength}; | ||||
|  | ||||
| @@ -93,50 +94,51 @@ impl Decoder { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn decode<R: MemRead>(&mut self, body: &mut R) -> Poll<Bytes, io::Error> { | ||||
|     pub fn decode<R: MemRead>(&mut self, cx: &mut task::Context<'_>, body: &mut R) -> Poll<Result<Bytes, io::Error>> { | ||||
|         trace!("decode; state={:?}", self.kind); | ||||
|         match self.kind { | ||||
|             Length(ref mut remaining) => { | ||||
|                 if *remaining == 0 { | ||||
|                     Ok(Async::Ready(Bytes::new())) | ||||
|                     Poll::Ready(Ok(Bytes::new())) | ||||
|                 } else { | ||||
|                     let to_read = *remaining as usize; | ||||
|                     let buf = try_ready!(body.read_mem(to_read)); | ||||
|                     let buf = ready!(body.read_mem(cx, to_read))?; | ||||
|                     let num = buf.as_ref().len() as u64; | ||||
|                     if num > *remaining { | ||||
|                         *remaining = 0; | ||||
|                     } else if num == 0 { | ||||
|                         return Err(io::Error::new(io::ErrorKind::UnexpectedEof, IncompleteBody)); | ||||
|                         return Poll::Ready(Err(io::Error::new(io::ErrorKind::UnexpectedEof, IncompleteBody))); | ||||
|                     } else { | ||||
|                         *remaining -= num; | ||||
|                     } | ||||
|                     Ok(Async::Ready(buf)) | ||||
|                     Poll::Ready(Ok(buf)) | ||||
|                 } | ||||
|             } | ||||
|             Chunked(ref mut state, ref mut size) => { | ||||
|                 loop { | ||||
|                     let mut buf = None; | ||||
|                     // advances the chunked state | ||||
|                     *state = try_ready!(state.step(body, size, &mut buf)); | ||||
|                     *state = ready!(state.step(cx, body, size, &mut buf))?; | ||||
|                     if *state == ChunkedState::End { | ||||
|                         trace!("end of chunked"); | ||||
|                         return Ok(Async::Ready(Bytes::new())); | ||||
|                         return Poll::Ready(Ok(Bytes::new())); | ||||
|                     } | ||||
|                     if let Some(buf) = buf { | ||||
|                         return Ok(Async::Ready(buf)); | ||||
|                         return Poll::Ready(Ok(buf)); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             Eof(ref mut is_eof) => { | ||||
|                 if *is_eof { | ||||
|                     Ok(Async::Ready(Bytes::new())) | ||||
|                     Poll::Ready(Ok(Bytes::new())) | ||||
|                 } else { | ||||
|                     // 8192 chosen because its about 2 packets, there probably | ||||
|                     // won't be that much available, so don't have MemReaders | ||||
|                     // allocate buffers to big | ||||
|                     let slice = try_ready!(body.read_mem(8192)); | ||||
|                     *is_eof = slice.is_empty(); | ||||
|                     Ok(Async::Ready(slice)) | ||||
|                     body.read_mem(cx, 8192).map_ok(|slice| { | ||||
|                         *is_eof = slice.is_empty(); | ||||
|                         slice | ||||
|                     }) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -151,41 +153,42 @@ impl fmt::Debug for Decoder { | ||||
| } | ||||
|  | ||||
| macro_rules! byte ( | ||||
|     ($rdr:ident) => ({ | ||||
|         let buf = try_ready!($rdr.read_mem(1)); | ||||
|     ($rdr:ident, $cx:expr) => ({ | ||||
|         let buf = ready!($rdr.read_mem($cx, 1))?; | ||||
|         if !buf.is_empty() { | ||||
|             buf[0] | ||||
|         } else { | ||||
|             return Err(io::Error::new(io::ErrorKind::UnexpectedEof, | ||||
|                                       "Unexpected eof during chunk size line")); | ||||
|             return Poll::Ready(Err(io::Error::new(io::ErrorKind::UnexpectedEof, | ||||
|                                       "unexpected EOF during chunk size line"))); | ||||
|         } | ||||
|     }) | ||||
| ); | ||||
|  | ||||
| impl ChunkedState { | ||||
|     fn step<R: MemRead>(&self, | ||||
|                         cx: &mut task::Context<'_>, | ||||
|                         body: &mut R, | ||||
|                         size: &mut u64, | ||||
|                         buf: &mut Option<Bytes>) | ||||
|                         -> Poll<ChunkedState, io::Error> { | ||||
|                         -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         use self::ChunkedState::*; | ||||
|         match *self { | ||||
|             Size => ChunkedState::read_size(body, size), | ||||
|             SizeLws => ChunkedState::read_size_lws(body), | ||||
|             Extension => ChunkedState::read_extension(body), | ||||
|             SizeLf => ChunkedState::read_size_lf(body, *size), | ||||
|             Body => ChunkedState::read_body(body, size, buf), | ||||
|             BodyCr => ChunkedState::read_body_cr(body), | ||||
|             BodyLf => ChunkedState::read_body_lf(body), | ||||
|             EndCr => ChunkedState::read_end_cr(body), | ||||
|             EndLf => ChunkedState::read_end_lf(body), | ||||
|             End => Ok(Async::Ready(ChunkedState::End)), | ||||
|             Size => ChunkedState::read_size(cx, body, size), | ||||
|             SizeLws => ChunkedState::read_size_lws(cx, body), | ||||
|             Extension => ChunkedState::read_extension(cx, body), | ||||
|             SizeLf => ChunkedState::read_size_lf(cx, body, *size), | ||||
|             Body => ChunkedState::read_body(cx, body, size, buf), | ||||
|             BodyCr => ChunkedState::read_body_cr(cx, body), | ||||
|             BodyLf => ChunkedState::read_body_lf(cx, body), | ||||
|             EndCr => ChunkedState::read_end_cr(cx, body), | ||||
|             EndLf => ChunkedState::read_end_lf(cx, body), | ||||
|             End => Poll::Ready(Ok(ChunkedState::End)), | ||||
|         } | ||||
|     } | ||||
|     fn read_size<R: MemRead>(rdr: &mut R, size: &mut u64) -> Poll<ChunkedState, io::Error> { | ||||
|     fn read_size<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R, size: &mut u64) -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         trace!("Read chunk hex size"); | ||||
|         let radix = 16; | ||||
|         match byte!(rdr) { | ||||
|         match byte!(rdr, cx) { | ||||
|             b @ b'0'..=b'9' => { | ||||
|                 *size *= radix; | ||||
|                 *size += (b - b'0') as u64; | ||||
| @@ -198,55 +201,55 @@ impl ChunkedState { | ||||
|                 *size *= radix; | ||||
|                 *size += (b + 10 - b'A') as u64; | ||||
|             } | ||||
|             b'\t' | b' ' => return Ok(Async::Ready(ChunkedState::SizeLws)), | ||||
|             b';' => return Ok(Async::Ready(ChunkedState::Extension)), | ||||
|             b'\r' => return Ok(Async::Ready(ChunkedState::SizeLf)), | ||||
|             b'\t' | b' ' => return Poll::Ready(Ok(ChunkedState::SizeLws)), | ||||
|             b';' => return Poll::Ready(Ok(ChunkedState::Extension)), | ||||
|             b'\r' => return Poll::Ready(Ok(ChunkedState::SizeLf)), | ||||
|             _ => { | ||||
|                 return Err(io::Error::new(io::ErrorKind::InvalidInput, | ||||
|                                           "Invalid chunk size line: Invalid Size")); | ||||
|                 return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, | ||||
|                                           "Invalid chunk size line: Invalid Size"))); | ||||
|             } | ||||
|         } | ||||
|         Ok(Async::Ready(ChunkedState::Size)) | ||||
|         Poll::Ready(Ok(ChunkedState::Size)) | ||||
|     } | ||||
|     fn read_size_lws<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> { | ||||
|     fn read_size_lws<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         trace!("read_size_lws"); | ||||
|         match byte!(rdr) { | ||||
|         match byte!(rdr, cx) { | ||||
|             // LWS can follow the chunk size, but no more digits can come | ||||
|             b'\t' | b' ' => Ok(Async::Ready(ChunkedState::SizeLws)), | ||||
|             b';' => Ok(Async::Ready(ChunkedState::Extension)), | ||||
|             b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)), | ||||
|             b'\t' | b' ' => Poll::Ready(Ok(ChunkedState::SizeLws)), | ||||
|             b';' => Poll::Ready(Ok(ChunkedState::Extension)), | ||||
|             b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)), | ||||
|             _ => { | ||||
|                 Err(io::Error::new(io::ErrorKind::InvalidInput, | ||||
|                                    "Invalid chunk size linear white space")) | ||||
|                 Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, | ||||
|                                    "Invalid chunk size linear white space"))) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     fn read_extension<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> { | ||||
|     fn read_extension<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         trace!("read_extension"); | ||||
|         match byte!(rdr) { | ||||
|             b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)), | ||||
|             _ => Ok(Async::Ready(ChunkedState::Extension)), // no supported extensions | ||||
|         match byte!(rdr, cx) { | ||||
|             b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)), | ||||
|             _ => Poll::Ready(Ok(ChunkedState::Extension)), // no supported extensions | ||||
|         } | ||||
|     } | ||||
|     fn read_size_lf<R: MemRead>(rdr: &mut R, size: u64) -> Poll<ChunkedState, io::Error> { | ||||
|     fn read_size_lf<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R, size: u64) -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         trace!("Chunk size is {:?}", size); | ||||
|         match byte!(rdr) { | ||||
|         match byte!(rdr, cx) { | ||||
|             b'\n' => { | ||||
|                 if size == 0 { | ||||
|                     Ok(Async::Ready(ChunkedState::EndCr)) | ||||
|                     Poll::Ready(Ok(ChunkedState::EndCr)) | ||||
|                 } else { | ||||
|                     debug!("incoming chunked header: {0:#X} ({0} bytes)", size); | ||||
|                     Ok(Async::Ready(ChunkedState::Body)) | ||||
|                     Poll::Ready(Ok(ChunkedState::Body)) | ||||
|                 } | ||||
|             }, | ||||
|             _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk size LF")), | ||||
|             _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk size LF"))), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn read_body<R: MemRead>(rdr: &mut R, | ||||
|     fn read_body<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R, | ||||
|                           rem: &mut u64, | ||||
|                           buf: &mut Option<Bytes>) | ||||
|                           -> Poll<ChunkedState, io::Error> { | ||||
|                           -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         trace!("Chunked read, remaining={:?}", rem); | ||||
|  | ||||
|         // cap remaining bytes at the max capacity of usize | ||||
| @@ -256,45 +259,45 @@ impl ChunkedState { | ||||
|         }; | ||||
|  | ||||
|         let to_read = rem_cap; | ||||
|         let slice = try_ready!(rdr.read_mem(to_read)); | ||||
|         let slice = ready!(rdr.read_mem(cx, to_read))?; | ||||
|         let count = slice.len(); | ||||
|  | ||||
|         if count == 0 { | ||||
|             *rem = 0; | ||||
|             return Err(io::Error::new(io::ErrorKind::UnexpectedEof, IncompleteBody)); | ||||
|             return Poll::Ready(Err(io::Error::new(io::ErrorKind::UnexpectedEof, IncompleteBody))); | ||||
|         } | ||||
|         *buf = Some(slice); | ||||
|         *rem -= count as u64; | ||||
|  | ||||
|         if *rem > 0 { | ||||
|             Ok(Async::Ready(ChunkedState::Body)) | ||||
|             Poll::Ready(Ok(ChunkedState::Body)) | ||||
|         } else { | ||||
|             Ok(Async::Ready(ChunkedState::BodyCr)) | ||||
|             Poll::Ready(Ok(ChunkedState::BodyCr)) | ||||
|         } | ||||
|     } | ||||
|     fn read_body_cr<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> { | ||||
|         match byte!(rdr) { | ||||
|             b'\r' => Ok(Async::Ready(ChunkedState::BodyLf)), | ||||
|             _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body CR")), | ||||
|     fn read_body_cr<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         match byte!(rdr, cx) { | ||||
|             b'\r' => Poll::Ready(Ok(ChunkedState::BodyLf)), | ||||
|             _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body CR"))), | ||||
|         } | ||||
|     } | ||||
|     fn read_body_lf<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> { | ||||
|         match byte!(rdr) { | ||||
|             b'\n' => Ok(Async::Ready(ChunkedState::Size)), | ||||
|             _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body LF")), | ||||
|     fn read_body_lf<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         match byte!(rdr, cx) { | ||||
|             b'\n' => Poll::Ready(Ok(ChunkedState::Size)), | ||||
|             _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body LF"))), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn read_end_cr<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> { | ||||
|         match byte!(rdr) { | ||||
|             b'\r' => Ok(Async::Ready(ChunkedState::EndLf)), | ||||
|             _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end CR")), | ||||
|     fn read_end_cr<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         match byte!(rdr, cx) { | ||||
|             b'\r' => Poll::Ready(Ok(ChunkedState::EndLf)), | ||||
|             _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end CR"))), | ||||
|         } | ||||
|     } | ||||
|     fn read_end_lf<R: MemRead>(rdr: &mut R) -> Poll<ChunkedState, io::Error> { | ||||
|         match byte!(rdr) { | ||||
|             b'\n' => Ok(Async::Ready(ChunkedState::End)), | ||||
|             _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end LF")), | ||||
|     fn read_end_lf<R: MemRead>(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll<Result<ChunkedState, io::Error>> { | ||||
|         match byte!(rdr, cx) { | ||||
|             b'\n' => Poll::Ready(Ok(ChunkedState::End)), | ||||
|             _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end LF"))), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -326,15 +329,15 @@ mod tests { | ||||
|     use crate::mock::AsyncIo; | ||||
|  | ||||
|     impl<'a> MemRead for &'a [u8] { | ||||
|         fn read_mem(&mut self, len: usize) -> Poll<Bytes, io::Error> { | ||||
|         fn read_mem(&mut self, len: usize) -> Poll<Result<Bytes, io::Error>> { | ||||
|             let n = ::std::cmp::min(len, self.len()); | ||||
|             if n > 0 { | ||||
|                 let (a, b) = self.split_at(n); | ||||
|                 let mut buf = BytesMut::from(a); | ||||
|                 *self = b; | ||||
|                 Ok(Async::Ready(buf.split_to(n).freeze())) | ||||
|                 Poll::Ready(Ok(buf.split_to(n).freeze())) | ||||
|             } else { | ||||
|                 Ok(Async::Ready(Bytes::new())) | ||||
|                 Poll::Ready(Ok(Bytes::new())) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -1,13 +1,12 @@ | ||||
| use std::error::Error as StdError; | ||||
|  | ||||
| use bytes::{Buf, Bytes}; | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use http::{Request, Response, StatusCode}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::body::{Body, Payload}; | ||||
| use crate::body::internal::FullDataArg; | ||||
| use crate::common::{Never, YieldNow}; | ||||
| use crate::common::{Future, Never, Poll, Pin, Unpin, task}; | ||||
| use crate::proto::{BodyLength, DecodedLength, Conn, Dispatched, MessageHead, RequestHead, RequestLine, ResponseHead}; | ||||
| use super::Http1Transaction; | ||||
| use crate::service::Service; | ||||
| @@ -16,12 +15,8 @@ pub(crate) struct Dispatcher<D, Bs: Payload, I, T> { | ||||
|     conn: Conn<I, Bs::Data, T>, | ||||
|     dispatch: D, | ||||
|     body_tx: Option<crate::body::Sender>, | ||||
|     body_rx: Option<Bs>, | ||||
|     body_rx: Pin<Box<Option<Bs>>>, | ||||
|     is_closing: bool, | ||||
|     /// If the poll loop reaches its max spin count, it will yield by notifying | ||||
|     /// the task immediately. This will cache that `Task`, since it usually is | ||||
|     /// the same one. | ||||
|     yield_now: YieldNow, | ||||
| } | ||||
|  | ||||
| pub(crate) trait Dispatch { | ||||
| @@ -29,14 +24,14 @@ pub(crate) trait Dispatch { | ||||
|     type PollBody; | ||||
|     type PollError; | ||||
|     type RecvItem; | ||||
|     fn poll_msg(&mut self) -> Poll<Option<(Self::PollItem, Self::PollBody)>, Self::PollError>; | ||||
|     fn poll_msg(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Self::PollError>>>; | ||||
|     fn recv_msg(&mut self, msg: crate::Result<(Self::RecvItem, Body)>) -> crate::Result<()>; | ||||
|     fn poll_ready(&mut self) -> Poll<(), ()>; | ||||
|     fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), ()>>; | ||||
|     fn should_poll(&self) -> bool; | ||||
| } | ||||
|  | ||||
| pub struct Server<S: Service> { | ||||
|     in_flight: Option<S::Future>, | ||||
|     in_flight: Pin<Box<Option<S::Future>>>, | ||||
|     pub(crate) service: S, | ||||
| } | ||||
|  | ||||
| @@ -49,10 +44,10 @@ type ClientRx<B> = crate::client::dispatch::Receiver<Request<B>, Response<Body>> | ||||
|  | ||||
| impl<D, Bs, I, T> Dispatcher<D, Bs, I, T> | ||||
| where | ||||
|     D: Dispatch<PollItem=MessageHead<T::Outgoing>, PollBody=Bs, RecvItem=MessageHead<T::Incoming>>, | ||||
|     D: Dispatch<PollItem=MessageHead<T::Outgoing>, PollBody=Bs, RecvItem=MessageHead<T::Incoming>> + Unpin, | ||||
|     D::PollError: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I: AsyncRead + AsyncWrite, | ||||
|     T: Http1Transaction, | ||||
|     I: AsyncRead + AsyncWrite + Unpin, | ||||
|     T: Http1Transaction + Unpin, | ||||
|     Bs: Payload, | ||||
| { | ||||
|     pub fn new(dispatch: D, conn: Conn<I, Bs::Data, T>) -> Self { | ||||
| @@ -60,9 +55,8 @@ where | ||||
|             conn: conn, | ||||
|             dispatch: dispatch, | ||||
|             body_tx: None, | ||||
|             body_rx: None, | ||||
|             body_rx: Box::pin(None), | ||||
|             is_closing: false, | ||||
|             yield_now: YieldNow::new(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -80,55 +74,74 @@ where | ||||
|     /// | ||||
|     /// This is useful for old-style HTTP upgrades, but ignores | ||||
|     /// newer-style upgrade API. | ||||
|     pub fn poll_without_shutdown(&mut self) -> Poll<(), crate::Error> { | ||||
|         self.poll_catch(false) | ||||
|             .map(|x| { | ||||
|                 x.map(|ds| if let Dispatched::Upgrade(pending) = ds { | ||||
|                     pending.manual(); | ||||
|                 }) | ||||
|             }) | ||||
|     pub(crate) fn poll_without_shutdown(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> | ||||
|     where | ||||
|         Self: Unpin, | ||||
|     { | ||||
|         Pin::new(self).poll_catch(cx, false).map_ok(|ds| { | ||||
|             if let Dispatched::Upgrade(pending) = ds { | ||||
|                 pending.manual(); | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn poll_catch(&mut self, should_shutdown: bool) -> Poll<Dispatched, crate::Error> { | ||||
|         self.poll_inner(should_shutdown).or_else(|e| { | ||||
|     fn poll_catch(&mut self, cx: &mut task::Context<'_>, should_shutdown: bool) -> Poll<crate::Result<Dispatched>> { | ||||
|         Poll::Ready(ready!(self.poll_inner(cx, should_shutdown)).or_else(|e| { | ||||
|             // An error means we're shutting down either way. | ||||
|             // We just try to give the error to the user, | ||||
|             // and close the connection with an Ok. If we | ||||
|             // cannot give it to the user, then return the Err. | ||||
|             self.dispatch.recv_msg(Err(e))?; | ||||
|             Ok(Async::Ready(Dispatched::Shutdown)) | ||||
|         }) | ||||
|             Ok(Dispatched::Shutdown) | ||||
|         })) | ||||
|     } | ||||
|  | ||||
|     fn poll_inner(&mut self, should_shutdown: bool) -> Poll<Dispatched, crate::Error> { | ||||
|     fn poll_inner(&mut self, cx: &mut task::Context<'_>, should_shutdown: bool) -> Poll<crate::Result<Dispatched>> { | ||||
|         T::update_date(); | ||||
|  | ||||
|         try_ready!(self.poll_loop()); | ||||
|         ready!(self.poll_loop(cx))?; | ||||
|         loop { | ||||
|             self.poll_read(cx)?; | ||||
|             self.poll_write(cx)?; | ||||
|             self.poll_flush(cx)?; | ||||
|  | ||||
|             // This could happen if reading paused before blocking on IO, | ||||
|             // such as getting to the end of a framed message, but then | ||||
|             // writing/flushing set the state back to Init. In that case, | ||||
|             // if the read buffer still had bytes, we'd want to try poll_read | ||||
|             // again, or else we wouldn't ever be woken up again. | ||||
|             // | ||||
|             // Using this instead of task::current() and notify() inside | ||||
|             // the Conn is noticeably faster in pipelined benchmarks. | ||||
|             if !self.conn.wants_read_again() { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if self.is_done() { | ||||
|             if let Some(pending) = self.conn.pending_upgrade() { | ||||
|                 self.conn.take_error()?; | ||||
|                 return Ok(Async::Ready(Dispatched::Upgrade(pending))); | ||||
|                 return Poll::Ready(Ok(Dispatched::Upgrade(pending))); | ||||
|             } else if should_shutdown { | ||||
|                 try_ready!(self.conn.shutdown().map_err(crate::Error::new_shutdown)); | ||||
|                 ready!(self.conn.poll_shutdown(cx)).map_err(crate::Error::new_shutdown)?; | ||||
|             } | ||||
|             self.conn.take_error()?; | ||||
|             Ok(Async::Ready(Dispatched::Shutdown)) | ||||
|             Poll::Ready(Ok(Dispatched::Shutdown)) | ||||
|         } else { | ||||
|             Ok(Async::NotReady) | ||||
|             Poll::Pending | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn poll_loop(&mut self) -> Poll<(), crate::Error> { | ||||
|     fn poll_loop(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         // Limit the looping on this connection, in case it is ready far too | ||||
|         // often, so that other futures don't starve. | ||||
|         // | ||||
|         // 16 was chosen arbitrarily, as that is number of pipelined requests | ||||
|         // benchmarks often use. Perhaps it should be a config option instead. | ||||
|         for _ in 0..16 { | ||||
|             self.poll_read()?; | ||||
|             self.poll_write()?; | ||||
|             self.poll_flush()?; | ||||
|             self.poll_read(cx)?; | ||||
|             self.poll_write(cx)?; | ||||
|             self.poll_flush(cx)?; | ||||
|  | ||||
|             // This could happen if reading paused before blocking on IO, | ||||
|             // such as getting to the end of a framed message, but then | ||||
| @@ -140,45 +153,39 @@ where | ||||
|             // the Conn is noticeably faster in pipelined benchmarks. | ||||
|             if !self.conn.wants_read_again() { | ||||
|                 //break; | ||||
|                 return Ok(Async::Ready(())); | ||||
|                 return Poll::Ready(Ok(())); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         trace!("poll_loop yielding (self = {:p})", self); | ||||
|  | ||||
|         match self.yield_now.poll_yield() { | ||||
|             Ok(Async::NotReady) => Ok(Async::NotReady), | ||||
|             // maybe with `!` this can be cleaner... | ||||
|             // but for now, just doing this to eliminate branches | ||||
|             Ok(Async::Ready(never)) | | ||||
|             Err(never) => match never {} | ||||
|         } | ||||
|         task::yield_now(cx).map(|never| match never {}) | ||||
|     } | ||||
|  | ||||
|     fn poll_read(&mut self) -> Poll<(), crate::Error> { | ||||
|     fn poll_read(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         loop { | ||||
|             if self.is_closing { | ||||
|                 return Ok(Async::Ready(())); | ||||
|                 return Poll::Ready(Ok(())); | ||||
|             } else if self.conn.can_read_head() { | ||||
|                 try_ready!(self.poll_read_head()); | ||||
|                 ready!(self.poll_read_head(cx))?; | ||||
|             } else if let Some(mut body) = self.body_tx.take() { | ||||
|                 if self.conn.can_read_body() { | ||||
|                     match body.poll_ready() { | ||||
|                         Ok(Async::Ready(())) => (), | ||||
|                         Ok(Async::NotReady) => { | ||||
|                     match body.poll_ready(cx) { | ||||
|                         Poll::Ready(Ok(())) => (), | ||||
|                         Poll::Pending => { | ||||
|                             self.body_tx = Some(body); | ||||
|                             return Ok(Async::NotReady); | ||||
|                             return Poll::Pending; | ||||
|                         }, | ||||
|                         Err(_canceled) => { | ||||
|                         Poll::Ready(Err(_canceled)) => { | ||||
|                             // user doesn't care about the body | ||||
|                             // so we should stop reading | ||||
|                             trace!("body receiver dropped before eof, closing"); | ||||
|                             self.conn.close_read(); | ||||
|                             return Ok(Async::Ready(())); | ||||
|                             return Poll::Ready(Ok(())); | ||||
|                         } | ||||
|                     } | ||||
|                     match self.conn.read_body() { | ||||
|                         Ok(Async::Ready(Some(chunk))) => { | ||||
|                     match self.conn.poll_read_body(cx) { | ||||
|                         Poll::Ready(Some(Ok(chunk))) => { | ||||
|                             match body.send_data(chunk) { | ||||
|                                 Ok(()) => { | ||||
|                                     self.body_tx = Some(body); | ||||
| @@ -191,14 +198,14 @@ where | ||||
|                                 } | ||||
|                             } | ||||
|                         }, | ||||
|                         Ok(Async::Ready(None)) => { | ||||
|                         Poll::Ready(None) => { | ||||
|                             // just drop, the body will close automatically | ||||
|                         }, | ||||
|                         Ok(Async::NotReady) => { | ||||
|                         Poll::Pending => { | ||||
|                             self.body_tx = Some(body); | ||||
|                             return Ok(Async::NotReady); | ||||
|                             return Poll::Pending; | ||||
|                         } | ||||
|                         Err(e) => { | ||||
|                         Poll::Ready(Some(Err(e))) => { | ||||
|                             body.send_error(crate::Error::new_body(e)); | ||||
|                         } | ||||
|                     } | ||||
| @@ -206,25 +213,24 @@ where | ||||
|                     // just drop, the body will close automatically | ||||
|                 } | ||||
|             } else { | ||||
|                 return self.conn.read_keep_alive(); | ||||
|                 return self.conn.poll_read_keep_alive(cx); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn poll_read_head(&mut self) -> Poll<(), crate::Error> { | ||||
|     fn poll_read_head(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         // can dispatch receive, or does it still care about, an incoming message? | ||||
|         match self.dispatch.poll_ready() { | ||||
|             Ok(Async::Ready(())) => (), | ||||
|             Ok(Async::NotReady) => return Ok(Async::NotReady), // service might not be ready | ||||
|         match ready!(self.dispatch.poll_ready(cx)) { | ||||
|             Ok(()) => (), | ||||
|             Err(()) => { | ||||
|                 trace!("dispatch no longer receiving messages"); | ||||
|                 self.close(); | ||||
|                 return Ok(Async::Ready(())); | ||||
|                 return Poll::Ready(Ok(())); | ||||
|             } | ||||
|         } | ||||
|         // dispatch is ready for a message, try to read one | ||||
|         match self.conn.read_head() { | ||||
|             Ok(Async::Ready(Some((head, body_len, wants_upgrade)))) => { | ||||
|         match ready!(self.conn.poll_read_head(cx)) { | ||||
|             Some(Ok((head, body_len, wants_upgrade))) => { | ||||
|                 let mut body = match body_len { | ||||
|                     DecodedLength::ZERO => Body::empty(), | ||||
|                     other => { | ||||
| @@ -237,67 +243,78 @@ where | ||||
|                     body.set_on_upgrade(self.conn.on_upgrade()); | ||||
|                 } | ||||
|                 self.dispatch.recv_msg(Ok((head, body)))?; | ||||
|                 Ok(Async::Ready(())) | ||||
|             } | ||||
|             Ok(Async::Ready(None)) => { | ||||
|                 // read eof, conn will start to shutdown automatically | ||||
|                 Ok(Async::Ready(())) | ||||
|             } | ||||
|             Ok(Async::NotReady) => Ok(Async::NotReady), | ||||
|             Err(err) => { | ||||
|                 Poll::Ready(Ok(())) | ||||
|             }, | ||||
|             Some(Err(err)) => { | ||||
|                 debug!("read_head error: {}", err); | ||||
|                 self.dispatch.recv_msg(Err(err))?; | ||||
|                 // if here, the dispatcher gave the user the error | ||||
|                 // somewhere else. we still need to shutdown, but | ||||
|                 // not as a second error. | ||||
|                 Ok(Async::Ready(())) | ||||
|                 Poll::Ready(Ok(())) | ||||
|             }, | ||||
|             None => { | ||||
|                 // read eof, conn will start to shutdown automatically | ||||
|                 Poll::Ready(Ok(())) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn poll_write(&mut self) -> Poll<(), crate::Error> { | ||||
|     fn poll_write(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         loop { | ||||
|             if self.is_closing { | ||||
|                 return Ok(Async::Ready(())); | ||||
|                 return Poll::Ready(Ok(())); | ||||
|             } else if self.body_rx.is_none() && self.conn.can_write_head() && self.dispatch.should_poll() { | ||||
|                 if let Some((head, mut body)) = try_ready!(self.dispatch.poll_msg().map_err(crate::Error::new_user_service)) { | ||||
|                 if let Some(msg) = ready!(self.dispatch.poll_msg(cx)) { | ||||
|                     let (head, mut body) = msg.map_err(crate::Error::new_user_service)?; | ||||
|  | ||||
|                     // Check if the body knows its full data immediately. | ||||
|                     // | ||||
|                     // If so, we can skip a bit of bookkeeping that streaming | ||||
|                     // bodies need to do. | ||||
|                     if let Some(full) = body.__hyper_full_data(FullDataArg(())).0 { | ||||
|                         self.conn.write_full_msg(head, full); | ||||
|                         return Ok(Async::Ready(())); | ||||
|                         return Poll::Ready(Ok(())); | ||||
|                     } | ||||
|                     let body_type = if body.is_end_stream() { | ||||
|                         self.body_rx = None; | ||||
|                         self.body_rx.set(None); | ||||
|                         None | ||||
|                     } else { | ||||
|                         let btype = body.content_length() | ||||
|                             .map(BodyLength::Known) | ||||
|                             .or_else(|| Some(BodyLength::Unknown)); | ||||
|                         self.body_rx = Some(body); | ||||
|                         self.body_rx.set(Some(body)); | ||||
|                         btype | ||||
|                     }; | ||||
|                     self.conn.write_head(head, body_type); | ||||
|                 } else { | ||||
|                     self.close(); | ||||
|                     return Ok(Async::Ready(())); | ||||
|                     return Poll::Ready(Ok(())); | ||||
|                 } | ||||
|             } else if !self.conn.can_buffer_body() { | ||||
|                 try_ready!(self.poll_flush()); | ||||
|             } else if let Some(mut body) = self.body_rx.take() { | ||||
|                 if !self.conn.can_write_body() { | ||||
|                     trace!( | ||||
|                         "no more write body allowed, user body is_end_stream = {}", | ||||
|                         body.is_end_stream(), | ||||
|                     ); | ||||
|                     continue; | ||||
|                 } | ||||
|                 match body.poll_data().map_err(crate::Error::new_user_body)? { | ||||
|                     Async::Ready(Some(chunk)) => { | ||||
|                 ready!(self.poll_flush(cx))?; | ||||
|             } else { | ||||
|                 // A new scope is needed :( | ||||
|                 if let (Some(mut body), clear_body) = OptGuard::new(self.body_rx.as_mut()).guard_mut() { | ||||
|                     debug_assert!(!*clear_body, "opt guard defaults to keeping body"); | ||||
|                     if !self.conn.can_write_body() { | ||||
|                         trace!( | ||||
|                             "no more write body allowed, user body is_end_stream = {}", | ||||
|                             body.is_end_stream(), | ||||
|                         ); | ||||
|                         *clear_body = true; | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     let item = ready!(body.as_mut().poll_data(cx)); | ||||
|                     if let Some(item) = item { | ||||
|                         let chunk = item.map_err(|e| { | ||||
|                             *clear_body = true; | ||||
|                             crate::Error::new_user_body(e) | ||||
|                         })?; | ||||
|                         let eos = body.is_end_stream(); | ||||
|                         if eos { | ||||
|                             *clear_body = true; | ||||
|                             if chunk.remaining() == 0 { | ||||
|                                 trace!("discarding empty chunk"); | ||||
|                                 self.conn.end_body(); | ||||
| @@ -305,30 +322,25 @@ where | ||||
|                                 self.conn.write_body_and_end(chunk); | ||||
|                             } | ||||
|                         } else { | ||||
|                             self.body_rx = Some(body); | ||||
|                             if chunk.remaining() == 0 { | ||||
|                                 trace!("discarding empty chunk"); | ||||
|                                 continue; | ||||
|                             } | ||||
|                             self.conn.write_body(chunk); | ||||
|                         } | ||||
|                     }, | ||||
|                     Async::Ready(None) => { | ||||
|                     } else { | ||||
|                         *clear_body = true; | ||||
|                         self.conn.end_body(); | ||||
|                     }, | ||||
|                     Async::NotReady => { | ||||
|                         self.body_rx = Some(body); | ||||
|                         return Ok(Async::NotReady); | ||||
|                     } | ||||
|                 } else { | ||||
|                     return Poll::Pending; | ||||
|                 } | ||||
|             } else { | ||||
|                 return Ok(Async::NotReady); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn poll_flush(&mut self) -> Poll<(), crate::Error> { | ||||
|         self.conn.flush().map_err(|err| { | ||||
|     fn poll_flush(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         self.conn.poll_flush(cx).map_err(|err| { | ||||
|             debug!("error writing: {}", err); | ||||
|             crate::Error::new_body_write(err) | ||||
|         }) | ||||
| @@ -360,35 +372,65 @@ where | ||||
|  | ||||
| impl<D, Bs, I, T> Future for Dispatcher<D, Bs, I, T> | ||||
| where | ||||
|     D: Dispatch<PollItem=MessageHead<T::Outgoing>, PollBody=Bs, RecvItem=MessageHead<T::Incoming>>, | ||||
|     D: Dispatch<PollItem=MessageHead<T::Outgoing>, PollBody=Bs, RecvItem=MessageHead<T::Incoming>> + Unpin, | ||||
|     D::PollError: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I: AsyncRead + AsyncWrite, | ||||
|     T: Http1Transaction, | ||||
|     I: AsyncRead + AsyncWrite + Unpin, | ||||
|     T: Http1Transaction + Unpin, | ||||
|     Bs: Payload, | ||||
| { | ||||
|     type Item = Dispatched; | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<Dispatched>; | ||||
|  | ||||
|     #[inline] | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         self.poll_catch(true) | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         self.poll_catch(cx, true) | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ===== impl OptGuard ===== | ||||
|  | ||||
| /// A drop guard to allow a mutable borrow of an Option while being able to | ||||
| /// set whether the `Option` should be cleared on drop. | ||||
| struct OptGuard<'a, T>(Pin<&'a mut Option<T>>, bool); | ||||
|  | ||||
| impl<'a, T> OptGuard<'a, T> { | ||||
|     fn new(pin: Pin<&'a mut Option<T>>) -> Self { | ||||
|         OptGuard(pin, false) | ||||
|     } | ||||
|  | ||||
|     fn guard_mut(&mut self) -> (Option<Pin<&mut T>>, &mut bool) { | ||||
|         (self.0.as_mut().as_pin_mut(), &mut self.1) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'a, T> Drop for OptGuard<'a, T> { | ||||
|     fn drop(&mut self) { | ||||
|         if self.1 { | ||||
|             self.0.set(None); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ===== impl Server ===== | ||||
|  | ||||
| impl<S> Server<S> where S: Service { | ||||
| impl<S> Server<S> | ||||
| where | ||||
|     S: Service, | ||||
| { | ||||
|     pub fn new(service: S) -> Server<S> { | ||||
|         Server { | ||||
|             in_flight: None, | ||||
|             in_flight: Box::pin(None), | ||||
|             service: service, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn into_service(self) -> S { | ||||
|         self.service | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Service is never pinned | ||||
| impl<S: Service> Unpin for Server<S> {} | ||||
|  | ||||
| impl<S, Bs> Dispatch for Server<S> | ||||
| where | ||||
|     S: Service<ReqBody=Body, ResBody=Bs>, | ||||
| @@ -400,25 +442,23 @@ where | ||||
|     type PollError = S::Error; | ||||
|     type RecvItem = RequestHead; | ||||
|  | ||||
|     fn poll_msg(&mut self) -> Poll<Option<(Self::PollItem, Self::PollBody)>, Self::PollError> { | ||||
|         if let Some(mut fut) = self.in_flight.take() { | ||||
|             let resp = match fut.poll()? { | ||||
|                 Async::Ready(res) => res, | ||||
|                 Async::NotReady => { | ||||
|                     self.in_flight = Some(fut); | ||||
|                     return Ok(Async::NotReady); | ||||
|                 } | ||||
|             }; | ||||
|     fn poll_msg(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Self::PollError>>> { | ||||
|         let ret = if let Some(ref mut fut) = self.in_flight.as_mut().as_pin_mut() { | ||||
|             let resp = ready!(fut.as_mut().poll(cx)?); | ||||
|             let (parts, body) = resp.into_parts(); | ||||
|             let head = MessageHead { | ||||
|                 version: parts.version, | ||||
|                 subject: parts.status, | ||||
|                 headers: parts.headers, | ||||
|             }; | ||||
|             Ok(Async::Ready(Some((head, body)))) | ||||
|             Poll::Ready(Some(Ok((head, body)))) | ||||
|         } else { | ||||
|             unreachable!("poll_msg shouldn't be called if no inflight"); | ||||
|         } | ||||
|         }; | ||||
|  | ||||
|         // Since in_flight finished, remove it | ||||
|         self.in_flight.set(None); | ||||
|         ret | ||||
|     } | ||||
|  | ||||
|     fn recv_msg(&mut self, msg: crate::Result<(Self::RecvItem, Body)>) -> crate::Result<()> { | ||||
| @@ -428,15 +468,16 @@ where | ||||
|         *req.uri_mut() = msg.subject.1; | ||||
|         *req.headers_mut() = msg.headers; | ||||
|         *req.version_mut() = msg.version; | ||||
|         self.in_flight = Some(self.service.call(req)); | ||||
|         let fut = self.service.call(req); | ||||
|         self.in_flight.set(Some(fut)); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn poll_ready(&mut self) -> Poll<(), ()> { | ||||
|     fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), ()>> { | ||||
|         if self.in_flight.is_some() { | ||||
|             Ok(Async::NotReady) | ||||
|             Poll::Pending | ||||
|         } else { | ||||
|             self.service.poll_ready() | ||||
|             self.service.poll_ready(cx) | ||||
|                 .map_err(|_e| { | ||||
|                     // FIXME: return error value. | ||||
|                     trace!("service closed"); | ||||
| @@ -470,16 +511,16 @@ where | ||||
|     type PollError = Never; | ||||
|     type RecvItem = ResponseHead; | ||||
|  | ||||
|     fn poll_msg(&mut self) -> Poll<Option<(Self::PollItem, Self::PollBody)>, Never> { | ||||
|         match self.rx.poll() { | ||||
|             Ok(Async::Ready(Some((req, mut cb)))) => { | ||||
|     fn poll_msg(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Never>>> { | ||||
|         match self.rx.poll_next(cx) { | ||||
|             Poll::Ready(Some((req, mut cb))) => { | ||||
|                 // check that future hasn't been canceled already | ||||
|                 match cb.poll_cancel().expect("poll_cancel cannot error") { | ||||
|                     Async::Ready(()) => { | ||||
|                 match cb.poll_cancel(cx) { | ||||
|                     Poll::Ready(()) => { | ||||
|                         trace!("request canceled"); | ||||
|                         Ok(Async::Ready(None)) | ||||
|                         Poll::Ready(None) | ||||
|                     }, | ||||
|                     Async::NotReady => { | ||||
|                     Poll::Pending => { | ||||
|                         let (parts, body) = req.into_parts(); | ||||
|                         let head = RequestHead { | ||||
|                             version: parts.version, | ||||
| @@ -487,17 +528,16 @@ where | ||||
|                             headers: parts.headers, | ||||
|                         }; | ||||
|                         self.callback = Some(cb); | ||||
|                         Ok(Async::Ready(Some((head, body)))) | ||||
|                         Poll::Ready(Some(Ok((head, body)))) | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             Ok(Async::Ready(None)) => { | ||||
|             Poll::Ready(None) => { | ||||
|                 trace!("client tx closed"); | ||||
|                 // user has dropped sender handle | ||||
|                 Ok(Async::Ready(None)) | ||||
|                 Poll::Ready(None) | ||||
|             }, | ||||
|             Ok(Async::NotReady) => Ok(Async::NotReady), | ||||
|             Err(never) => match never {}, | ||||
|             Poll::Pending => Poll::Pending, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -522,30 +562,32 @@ where | ||||
|                 if let Some(cb) = self.callback.take() { | ||||
|                     let _ = cb.send(Err((err, None))); | ||||
|                     Ok(()) | ||||
|                 } else if let Ok(Async::Ready(Some((req, cb)))) = self.rx.poll() { | ||||
|                     trace!("canceling queued request with connection error: {}", err); | ||||
|                     // in this case, the message was never even started, so it's safe to tell | ||||
|                     // the user that the request was completely canceled | ||||
|                     let _ = cb.send(Err((crate::Error::new_canceled().with(err), Some(req)))); | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err(err) | ||||
|                     self.rx.close(); | ||||
|                     if let Some((req, cb)) = self.rx.try_recv() { | ||||
|                         trace!("canceling queued request with connection error: {}", err); | ||||
|                         // in this case, the message was never even started, so it's safe to tell | ||||
|                         // the user that the request was completely canceled | ||||
|                         let _ = cb.send(Err((crate::Error::new_canceled().with(err), Some(req)))); | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(err) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn poll_ready(&mut self) -> Poll<(), ()> { | ||||
|     fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), ()>> { | ||||
|         match self.callback { | ||||
|             Some(ref mut cb) => match cb.poll_cancel() { | ||||
|                 Ok(Async::Ready(())) => { | ||||
|             Some(ref mut cb) => match cb.poll_cancel(cx) { | ||||
|                 Poll::Ready(()) => { | ||||
|                     trace!("callback receiver has dropped"); | ||||
|                     Err(()) | ||||
|                     Poll::Ready(Err(())) | ||||
|                 }, | ||||
|                 Ok(Async::NotReady) => Ok(Async::Ready(())), | ||||
|                 Err(_) => unreachable!("oneshot poll_cancel cannot error"), | ||||
|                 Poll::Pending => Poll::Ready(Ok(())), | ||||
|             }, | ||||
|             None => Err(()), | ||||
|             None => Poll::Ready(Err(())), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -5,10 +5,10 @@ use std::fmt; | ||||
| use std::io; | ||||
|  | ||||
| use bytes::{Buf, BufMut, Bytes, BytesMut}; | ||||
| use futures::{Async, Poll}; | ||||
| use iovec::IoVec; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::common::{Pin, Poll, Unpin, task}; | ||||
| use super::{Http1Transaction, ParseContext, ParsedMessage}; | ||||
|  | ||||
| /// The initial buffer size allocated before trying to read from IO. | ||||
| @@ -52,7 +52,7 @@ where | ||||
|  | ||||
| impl<T, B> Buffered<T, B> | ||||
| where | ||||
|     T: AsyncRead + AsyncWrite, | ||||
|     T: AsyncRead + AsyncWrite + Unpin, | ||||
|     B: Buf, | ||||
| { | ||||
|     pub fn new(io: T) -> Buffered<T, B> { | ||||
| @@ -135,57 +135,56 @@ where | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub(super) fn parse<S>(&mut self, ctx: ParseContext) | ||||
|         -> Poll<ParsedMessage<S::Incoming>, crate::Error> | ||||
|     pub(super) fn parse<S>(&mut self, cx: &mut task::Context<'_>, parse_ctx: ParseContext) | ||||
|         -> Poll<crate::Result<ParsedMessage<S::Incoming>>> | ||||
|     where | ||||
|         S: Http1Transaction, | ||||
|     { | ||||
|         loop { | ||||
|             match S::parse(&mut self.read_buf, ParseContext { | ||||
|                 cached_headers: ctx.cached_headers, | ||||
|                 req_method: ctx.req_method, | ||||
|                 cached_headers: parse_ctx.cached_headers, | ||||
|                 req_method: parse_ctx.req_method, | ||||
|             })? { | ||||
|                 Some(msg) => { | ||||
|                     debug!("parsed {} headers", msg.head.headers.len()); | ||||
|                     return Ok(Async::Ready(msg)) | ||||
|                     return Poll::Ready(Ok(msg)); | ||||
|                 }, | ||||
|                 None => { | ||||
|                     let max = self.read_buf_strategy.max(); | ||||
|                     if self.read_buf.len() >= max { | ||||
|                         debug!("max_buf_size ({}) reached, closing", max); | ||||
|                         return Err(crate::Error::new_too_large()); | ||||
|                         return Poll::Ready(Err(crate::Error::new_too_large())); | ||||
|                     } | ||||
|                 }, | ||||
|             } | ||||
|             match try_ready!(self.read_from_io().map_err(crate::Error::new_io)) { | ||||
|             match ready!(self.poll_read_from_io(cx)).map_err(crate::Error::new_io)? { | ||||
|                 0 => { | ||||
|                     trace!("parse eof"); | ||||
|                     return Err(crate::Error::new_incomplete()); | ||||
|                     return Poll::Ready(Err(crate::Error::new_incomplete())); | ||||
|                 } | ||||
|                 _ => {}, | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn read_from_io(&mut self) -> Poll<usize, io::Error> { | ||||
|     pub fn poll_read_from_io(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<usize>> { | ||||
|         self.read_blocked = false; | ||||
|         let next = self.read_buf_strategy.next(); | ||||
|         if self.read_buf.remaining_mut() < next { | ||||
|             self.read_buf.reserve(next); | ||||
|         } | ||||
|         self.io.read_buf(&mut self.read_buf).map(|ok| { | ||||
|             match ok { | ||||
|                 Async::Ready(n) => { | ||||
|         match Pin::new(&mut self.io).poll_read_buf(cx, &mut self.read_buf) { | ||||
|             Poll::Ready(Ok(n)) => { | ||||
|                     debug!("read {} bytes", n); | ||||
|                     self.read_buf_strategy.record(n); | ||||
|                     Async::Ready(n) | ||||
|                     Poll::Ready(Ok(n)) | ||||
|                 }, | ||||
|                 Async::NotReady => { | ||||
|                     self.read_blocked = true; | ||||
|                     Async::NotReady | ||||
|                 } | ||||
|             Poll::Pending => { | ||||
|                 self.read_blocked = true; | ||||
|                 Poll::Pending | ||||
|             } | ||||
|         }) | ||||
|             Poll::Ready(Err(e)) => Poll::Ready(Err(e)), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn into_inner(self) -> (T, Bytes) { | ||||
| @@ -200,38 +199,37 @@ where | ||||
|         self.read_blocked | ||||
|     } | ||||
|  | ||||
|     pub fn flush(&mut self) -> Poll<(), io::Error> { | ||||
|     pub fn poll_flush(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         if self.flush_pipeline && !self.read_buf.is_empty() { | ||||
|             //Ok(()) | ||||
|             Poll::Ready(Ok(())) | ||||
|         } else if self.write_buf.remaining() == 0 { | ||||
|             try_nb!(self.io.flush()); | ||||
|             Pin::new(&mut self.io).poll_flush(cx) | ||||
|         } else { | ||||
|             match self.write_buf.strategy { | ||||
|                 WriteStrategy::Flatten => return self.flush_flattened(), | ||||
|                 WriteStrategy::Flatten => return self.poll_flush_flattened(cx), | ||||
|                 _ => (), | ||||
|             } | ||||
|             loop { | ||||
|                 let n = try_ready!(self.io.write_buf(&mut self.write_buf.auto())); | ||||
|                 let n = ready!(Pin::new(&mut self.io).poll_write_buf(cx, &mut self.write_buf.auto()))?; | ||||
|                 debug!("flushed {} bytes", n); | ||||
|                 if self.write_buf.remaining() == 0 { | ||||
|                     break; | ||||
|                 } else if n == 0 { | ||||
|                     trace!("write returned zero, but {} bytes remaining", self.write_buf.remaining()); | ||||
|                     return Err(io::ErrorKind::WriteZero.into()) | ||||
|                     return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); | ||||
|                 } | ||||
|             } | ||||
|             try_nb!(self.io.flush()) | ||||
|             Pin::new(&mut self.io).poll_flush(cx) | ||||
|         } | ||||
|         Ok(Async::Ready(())) | ||||
|     } | ||||
|  | ||||
|     /// Specialized version of `flush` when strategy is Flatten. | ||||
|     /// | ||||
|     /// Since all buffered bytes are flattened into the single headers buffer, | ||||
|     /// that skips some bookkeeping around using multiple buffers. | ||||
|     fn flush_flattened(&mut self) -> Poll<(), io::Error> { | ||||
|     fn poll_flush_flattened(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         loop { | ||||
|             let n = try_nb!(self.io.write(self.write_buf.headers.bytes())); | ||||
|             let n = ready!(Pin::new(&mut self.io).poll_write(cx, self.write_buf.headers.bytes()))?; | ||||
|             debug!("flushed {} bytes", n); | ||||
|             self.write_buf.headers.advance(n); | ||||
|             if self.write_buf.headers.remaining() == 0 { | ||||
| @@ -239,30 +237,33 @@ where | ||||
|                 break; | ||||
|             } else if n == 0 { | ||||
|                 trace!("write returned zero, but {} bytes remaining", self.write_buf.remaining()); | ||||
|                 return Err(io::ErrorKind::WriteZero.into()) | ||||
|                 return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); | ||||
|             } | ||||
|         } | ||||
|         try_nb!(self.io.flush()); | ||||
|         Ok(Async::Ready(())) | ||||
|         Pin::new(&mut self.io).poll_flush(cx) | ||||
|     } | ||||
| } | ||||
|  | ||||
| // The `B` is a `Buf`, we never project a pin to it | ||||
| impl<T: Unpin, B> Unpin for Buffered<T, B> {} | ||||
|  | ||||
| // TODO: This trait is old... at least rename to PollBytes or something... | ||||
| pub trait MemRead { | ||||
|     fn read_mem(&mut self, len: usize) -> Poll<Bytes, io::Error>; | ||||
|     fn read_mem(&mut self, cx: &mut task::Context<'_>, len: usize) -> Poll<io::Result<Bytes>>; | ||||
| } | ||||
|  | ||||
| impl<T, B> MemRead for Buffered<T, B>  | ||||
| where | ||||
|     T: AsyncRead + AsyncWrite, | ||||
|     T: AsyncRead + AsyncWrite + Unpin, | ||||
|     B: Buf, | ||||
| { | ||||
|     fn read_mem(&mut self, len: usize) -> Poll<Bytes, io::Error> { | ||||
|     fn read_mem(&mut self, cx: &mut task::Context<'_>, len: usize) -> Poll<io::Result<Bytes>> { | ||||
|         if !self.read_buf.is_empty() { | ||||
|             let n = ::std::cmp::min(len, self.read_buf.len()); | ||||
|             Ok(Async::Ready(self.read_buf.split_to(n).freeze())) | ||||
|             Poll::Ready(Ok(self.read_buf.split_to(n).freeze())) | ||||
|         } else { | ||||
|             let n = try_ready!(self.read_from_io()); | ||||
|             Ok(Async::Ready(self.read_buf.split_to(::std::cmp::min(len, n)).freeze())) | ||||
|             let n = ready!(self.poll_read_from_io(cx))?; | ||||
|             Poll::Ready(Ok(self.read_buf.split_to(::std::cmp::min(len, n)).freeze())) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,26 +1,26 @@ | ||||
| use bytes::IntoBuf; | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use futures::future::{self, Either}; | ||||
| use futures::sync::{mpsc, oneshot}; | ||||
| //use futures::{Async, Future, Poll, Stream}; | ||||
| //use futures::future::{self, Either}; | ||||
| //use futures::sync::{mpsc, oneshot}; | ||||
| use h2::client::{Builder, Handshake, SendRequest}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::headers::content_length_parse_all; | ||||
| use crate::body::Payload; | ||||
| use crate::common::{Exec, Never}; | ||||
| use crate::common::{Exec, Future, Never, Pin, Poll, task}; | ||||
| use crate::headers; | ||||
| use crate::proto::Dispatched; | ||||
| use super::{PipeToSendStream, SendBuf}; | ||||
| use crate::{Body, Request, Response}; | ||||
|  | ||||
| type ClientRx<B> = crate::client::dispatch::Receiver<Request<B>, Response<Body>>; | ||||
| /// An mpsc channel is used to help notify the `Connection` task when *all* | ||||
| /// other handles to it have been dropped, so that it can shutdown. | ||||
| type ConnDropRef = mpsc::Sender<Never>; | ||||
| ///// An mpsc channel is used to help notify the `Connection` task when *all* | ||||
| ///// other handles to it have been dropped, so that it can shutdown. | ||||
| //type ConnDropRef = mpsc::Sender<Never>; | ||||
|  | ||||
| /// A oneshot channel watches the `Connection` task, and when it completes, | ||||
| /// the "dispatch" task will be notified and can shutdown sooner. | ||||
| type ConnEof = oneshot::Receiver<Never>; | ||||
| ///// A oneshot channel watches the `Connection` task, and when it completes, | ||||
| ///// the "dispatch" task will be notified and can shutdown sooner. | ||||
| //type ConnEof = oneshot::Receiver<Never>; | ||||
|  | ||||
| pub(crate) struct Client<T, B> | ||||
| where | ||||
| @@ -33,7 +33,7 @@ where | ||||
|  | ||||
| enum State<T, B> where B: IntoBuf { | ||||
|     Handshaking(Handshake<T, B>), | ||||
|     Ready(SendRequest<B>, ConnDropRef, ConnEof), | ||||
|     //Ready(SendRequest<B>, ConnDropRef, ConnEof), | ||||
| } | ||||
|  | ||||
| impl<T, B> Client<T, B> | ||||
| @@ -42,6 +42,8 @@ where | ||||
|     B: Payload, | ||||
| { | ||||
|     pub(crate) fn new(io: T, rx: ClientRx<B>, builder: &Builder, exec: Exec) -> Client<T, B> { | ||||
|         unimplemented!("proto::h2::Client::new"); | ||||
|         /* | ||||
|         let handshake = builder.handshake(io); | ||||
|  | ||||
|         Client { | ||||
| @@ -49,6 +51,7 @@ where | ||||
|             rx: rx, | ||||
|             state: State::Handshaking(handshake), | ||||
|         } | ||||
|         */ | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -57,10 +60,11 @@ where | ||||
|     T: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     B: Payload + 'static, | ||||
| { | ||||
|     type Item = Dispatched; | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<Dispatched>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         unimplemented!("impl Future for proto::h2::Client"); | ||||
|         /* | ||||
|         loop { | ||||
|             let next = match self.state { | ||||
|                 State::Handshaking(ref mut h) => { | ||||
| @@ -196,5 +200,6 @@ where | ||||
|             }; | ||||
|             self.state = next; | ||||
|         } | ||||
|         */ | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| use bytes::Buf; | ||||
| use futures::{Async, Future, Poll}; | ||||
| //use futures::{Async, Future, Poll}; | ||||
| use h2::{SendStream}; | ||||
| use http::header::{ | ||||
|     HeaderName, CONNECTION, PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, TE, TRAILER, | ||||
| @@ -106,6 +106,7 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| impl<S> Future for PipeToSendStream<S> | ||||
| where | ||||
|     S: Payload, | ||||
| @@ -114,6 +115,8 @@ where | ||||
|     type Error = crate::Error; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         unimplemented!("impl Future for PipeToSendStream"); | ||||
|         /* | ||||
|         loop { | ||||
|             if !self.data_done { | ||||
|                 // we don't have the next chunk of data yet, so just reserve 1 byte to make | ||||
| @@ -189,8 +192,10 @@ where | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         */ | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
| struct SendBuf<B>(Option<B>); | ||||
|  | ||||
|   | ||||
| @@ -1,15 +1,15 @@ | ||||
| use std::error::Error as StdError; | ||||
|  | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use h2::Reason; | ||||
| use h2::server::{Builder, Connection, Handshake, SendResponse}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::headers::content_length_parse_all; | ||||
| use crate::body::Payload; | ||||
| use crate::body::internal::FullDataArg; | ||||
| use crate::common::exec::H2Exec; | ||||
| use crate::common::{Future, Pin, Poll, task}; | ||||
| use crate::headers; | ||||
| use crate::headers::content_length_parse_all; | ||||
| use crate::service::Service; | ||||
| use crate::proto::Dispatched; | ||||
| use super::{PipeToSendStream, SendBuf}; | ||||
| @@ -26,6 +26,9 @@ where | ||||
|     state: State<T, B>, | ||||
| } | ||||
|  | ||||
| // TODO: fix me | ||||
| impl<T, S: Service, B: Payload, E> Unpin for Server<T, S, B, E> {} | ||||
|  | ||||
| enum State<T, B> | ||||
| where | ||||
|     B: Payload, | ||||
| @@ -53,15 +56,20 @@ where | ||||
|     E: H2Exec<S::Future, B>, | ||||
| { | ||||
|     pub(crate) fn new(io: T, service: S, builder: &Builder, exec: E) -> Server<T, S, B, E> { | ||||
|         unimplemented!("proto::h2::Server::new") | ||||
|         /* | ||||
|         let handshake = builder.handshake(io); | ||||
|         Server { | ||||
|             exec, | ||||
|             state: State::Handshaking(handshake), | ||||
|             service, | ||||
|         } | ||||
|         */ | ||||
|     } | ||||
|  | ||||
|     pub fn graceful_shutdown(&mut self) { | ||||
|         unimplemented!("proto::h2::Server::graceful_shutdown") | ||||
|         /* | ||||
|         trace!("graceful_shutdown"); | ||||
|         match self.state { | ||||
|             State::Handshaking(..) => { | ||||
| @@ -78,6 +86,7 @@ where | ||||
|             } | ||||
|         } | ||||
|         self.state = State::Closed; | ||||
|         */ | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -89,10 +98,11 @@ where | ||||
|     B: Payload, | ||||
|     E: H2Exec<S::Future, B>, | ||||
| { | ||||
|     type Item = Dispatched; | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<Dispatched>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         unimplemented!("h2 server future") | ||||
|         /* | ||||
|         loop { | ||||
|             let next = match self.state { | ||||
|                 State::Handshaking(ref mut h) => { | ||||
| @@ -114,6 +124,7 @@ where | ||||
|             }; | ||||
|             self.state = next; | ||||
|         } | ||||
|         */ | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -122,7 +133,7 @@ where | ||||
|     T: AsyncRead + AsyncWrite, | ||||
|     B: Payload, | ||||
| { | ||||
|     fn poll_server<S, E>(&mut self, service: &mut S, exec: &E) -> Poll<(), crate::Error> | ||||
|     fn poll_server<S, E>(&mut self, service: &mut S, exec: &E) -> Poll<crate::Result<()>> | ||||
|     where | ||||
|         S: Service< | ||||
|             ReqBody=Body, | ||||
| @@ -131,6 +142,7 @@ where | ||||
|         S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         E: H2Exec<S::Future, B>, | ||||
|     { | ||||
|         /* | ||||
|         if self.closing.is_none() { | ||||
|             loop { | ||||
|                 // At first, polls the readiness of supplied service. | ||||
| @@ -182,6 +194,8 @@ where | ||||
|         try_ready!(self.conn.poll_close().map_err(crate::Error::new_h2)); | ||||
|  | ||||
|         Err(self.closing.take().expect("polled after error")) | ||||
|         */ | ||||
|         unimplemented!("h2 server poll_server") | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -204,8 +218,8 @@ where | ||||
|  | ||||
| impl<F, B> H2Stream<F, B> | ||||
| where | ||||
|     F: Future<Item=Response<B>>, | ||||
|     F::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     //F: Future<Item=Response<B>>, | ||||
|     //F::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     B: Payload, | ||||
| { | ||||
|     fn new(fut: F, respond: SendResponse<SendBuf<B::Data>>) -> H2Stream<F, B> { | ||||
| @@ -214,8 +228,19 @@ where | ||||
|             state: H2StreamState::Service(fut), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|     fn poll2(&mut self) -> Poll<(), crate::Error> { | ||||
| impl<F, B> Future for H2Stream<F, B> | ||||
| where | ||||
|     //F: Future<Item=Response<B>>, | ||||
|     //F::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     B: Payload, | ||||
| { | ||||
|     type Output = (); | ||||
|  | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         unimplemented!("impl Future for H2Stream"); | ||||
|         /* | ||||
|         loop { | ||||
|             let next = match self.state { | ||||
|                 H2StreamState::Service(ref mut h) => { | ||||
| @@ -292,9 +317,10 @@ where | ||||
|             }; | ||||
|             self.state = next; | ||||
|         } | ||||
|         */ | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| impl<F, B> Future for H2Stream<F, B> | ||||
| where | ||||
|     F: Future<Item=Response<B>>, | ||||
| @@ -309,4 +335,5 @@ where | ||||
|             .map_err(|e| debug!("stream error: {}", e)) | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
|   | ||||
| @@ -6,8 +6,9 @@ | ||||
| //! The inclusion of a default runtime can be disabled by turning off hyper's | ||||
| //! `runtime` Cargo feature. | ||||
|  | ||||
| pub use futures::{Future, Stream}; | ||||
| pub use futures::future::{lazy, poll_fn}; | ||||
| pub use std::future::Future; | ||||
| pub use futures_core::Stream; | ||||
|  | ||||
| use tokio; | ||||
|  | ||||
| use self::inner::Spawn; | ||||
| @@ -25,7 +26,7 @@ use self::inner::Spawn; | ||||
| /// ignored for now. | ||||
| pub fn spawn<F>(f: F) -> Spawn | ||||
| where | ||||
|     F: Future<Item=(), Error=()> + Send + 'static, | ||||
|     F: Future<Output = ()> + Send + 'static, | ||||
| { | ||||
|     tokio::spawn(f); | ||||
|     Spawn { | ||||
| @@ -40,7 +41,7 @@ where | ||||
| /// See the [server documentation](::server) for an example of its usage. | ||||
| pub fn run<F>(f: F) | ||||
| where | ||||
|     F: Future<Item=(), Error=()> + Send + 'static | ||||
|     F: Future<Output = ()> + Send + 'static | ||||
| { | ||||
|     tokio::run(f); | ||||
| } | ||||
|   | ||||
| @@ -16,15 +16,16 @@ use std::sync::Arc; | ||||
| #[cfg(feature = "runtime")] use std::time::Duration; | ||||
|  | ||||
| use bytes::Bytes; | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use futures::future::{Either, Executor}; | ||||
| use futures_core::Stream; | ||||
| use h2; | ||||
| use pin_utils::{unsafe_pinned, unsafe_unpinned}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
| #[cfg(feature = "runtime")] use tokio_reactor::Handle; | ||||
|  | ||||
| use crate::body::{Body, Payload}; | ||||
| use crate::common::exec::{Exec, H2Exec, NewSvcExec}; | ||||
| use crate::common::io::Rewind; | ||||
| use crate::common::{Future, Pin, Poll, Unpin, task}; | ||||
| use crate::error::{Kind, Parse}; | ||||
| use crate::proto; | ||||
| use crate::service::{MakeServiceRef, Service}; | ||||
| @@ -103,8 +104,7 @@ pub struct Connection<T, S, E = Exec> | ||||
| where | ||||
|     S: Service, | ||||
| { | ||||
|     pub(super) conn: Option< | ||||
|         Either< | ||||
|     pub(super) conn: Option<Either< | ||||
|         proto::h1::Dispatcher< | ||||
|             proto::h1::dispatch::Server<S>, | ||||
|             S::ResBody, | ||||
| @@ -121,6 +121,11 @@ where | ||||
|     fallback: Fallback<E>, | ||||
| } | ||||
|  | ||||
| pub(super) enum Either<A, B> { | ||||
|     A(A), | ||||
|     B(B), | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Debug)] | ||||
| enum Fallback<E> { | ||||
|     ToHttp2(h2::server::Builder, E), | ||||
| @@ -136,6 +141,8 @@ impl<E> Fallback<E> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<E> Unpin for Fallback<E> {} | ||||
|  | ||||
| /// Deconstructed parts of a `Connection`. | ||||
| /// | ||||
| /// This allows taking apart a `Connection` at a later time, in order to | ||||
| @@ -175,16 +182,6 @@ impl Http { | ||||
|             pipeline_flush: false, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[doc(hidden)] | ||||
|     #[deprecated(note = "use Http::with_executor instead")] | ||||
|     pub fn executor<E>(&mut self, exec: E) -> &mut Self | ||||
|     where | ||||
|         E: Executor<Box<dyn Future<Item=(), Error=()> + Send>> + Send + Sync + 'static | ||||
|     { | ||||
|         self.exec = Exec::Executor(Arc::new(exec)); | ||||
|         self | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<E> Http<E> { | ||||
| @@ -367,7 +364,7 @@ impl<E> Http<E> { | ||||
|         S: Service<ReqBody=Body, ResBody=Bd>, | ||||
|         S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         Bd: Payload, | ||||
|         I: AsyncRead + AsyncWrite, | ||||
|         I: AsyncRead + AsyncWrite + Unpin, | ||||
|         E: H2Exec<S::Future, Bd>, | ||||
|     { | ||||
|         let either = match self.mode { | ||||
| @@ -457,13 +454,13 @@ impl<E> Http<E> { | ||||
|     } | ||||
|  | ||||
|     /// Bind the provided stream of incoming IO objects with a `MakeService`. | ||||
|     pub fn serve_incoming<I, S, Bd>(&self, incoming: I, make_service: S) -> Serve<I, S, E> | ||||
|     pub fn serve_incoming<I, IO, IE, S, Bd>(&self, incoming: I, make_service: S) -> Serve<I, S, E> | ||||
|     where | ||||
|         I: Stream, | ||||
|         I::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         I::Item: AsyncRead + AsyncWrite, | ||||
|         I: Stream<Item = Result<IO, IE>>, | ||||
|         IE: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         IO: AsyncRead + AsyncWrite + Unpin, | ||||
|         S: MakeServiceRef< | ||||
|             I::Item, | ||||
|             IO, | ||||
|             ReqBody=Body, | ||||
|             ResBody=Bd, | ||||
|         >, | ||||
| @@ -486,7 +483,7 @@ impl<I, B, S, E> Connection<I, S, E> | ||||
| where | ||||
|     S: Service<ReqBody=Body, ResBody=B>, | ||||
|     S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I: AsyncRead + AsyncWrite, | ||||
|     I: AsyncRead + AsyncWrite + Unpin, | ||||
|     B: Payload + 'static, | ||||
|     E: H2Exec<S::Future, B>, | ||||
| { | ||||
| @@ -494,8 +491,10 @@ where | ||||
|     /// | ||||
|     /// This `Connection` should continue to be polled until shutdown | ||||
|     /// can finish. | ||||
|     pub fn graceful_shutdown(&mut self) { | ||||
|         match *self.conn.as_mut().unwrap() { | ||||
|     pub fn graceful_shutdown(self: Pin<&mut Self>) { | ||||
|         // Safety: neither h1 nor h2 poll any of the generic futures | ||||
|         // in these methods. | ||||
|         match unsafe { self.get_unchecked_mut() }.conn.as_mut().unwrap() { | ||||
|             Either::A(ref mut h1) => { | ||||
|                 h1.disable_keep_alive(); | ||||
|             }, | ||||
| @@ -547,21 +546,26 @@ where | ||||
|     /// Use [`poll_fn`](https://docs.rs/futures/0.1.25/futures/future/fn.poll_fn.html) | ||||
|     /// and [`try_ready!`](https://docs.rs/futures/0.1.25/futures/macro.try_ready.html) | ||||
|     /// to work with this function; or use the `without_shutdown` wrapper. | ||||
|     pub fn poll_without_shutdown(&mut self) -> Poll<(), crate::Error> { | ||||
|     pub fn poll_without_shutdown(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> | ||||
|     where | ||||
|         S: Unpin, | ||||
|         S::Future: Unpin, | ||||
|         B: Unpin, | ||||
|     { | ||||
|         loop { | ||||
|             let polled = match *self.conn.as_mut().unwrap() { | ||||
|                 Either::A(ref mut h1) => h1.poll_without_shutdown(), | ||||
|                 Either::B(ref mut h2) => return h2.poll().map(|x| x.map(|_| ())), | ||||
|                 Either::A(ref mut h1) => h1.poll_without_shutdown(cx), | ||||
|                 Either::B(ref mut h2) => unimplemented!("Connection::poll_without_shutdown h2"),//return h2.poll().map(|x| x.map(|_| ())), | ||||
|             }; | ||||
|             match polled { | ||||
|                 Ok(x) => return Ok(x), | ||||
|             match ready!(polled) { | ||||
|                 Ok(x) => return Poll::Ready(Ok(x)), | ||||
|                 Err(e) => { | ||||
|                     match *e.kind() { | ||||
|                         Kind::Parse(Parse::VersionH2) if self.fallback.to_h2() => { | ||||
|                             self.upgrade_h2(); | ||||
|                             continue; | ||||
|                         } | ||||
|                         _ => return Err(e), | ||||
|                         _ => return Poll::Ready(Err(e)), | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -570,11 +574,16 @@ where | ||||
|  | ||||
|     /// Prevent shutdown of the underlying IO object at the end of service the request, | ||||
|     /// instead run `into_parts`. This is a convenience wrapper over `poll_without_shutdown`. | ||||
|     pub fn without_shutdown(self) -> impl Future<Item=Parts<I,S>, Error=crate::Error> { | ||||
|     pub fn without_shutdown(self) -> impl Future<Output=crate::Result<Parts<I, S>>> | ||||
|     where | ||||
|         S: Unpin, | ||||
|         S::Future: Unpin, | ||||
|         B: Unpin, | ||||
|     { | ||||
|         let mut conn = Some(self); | ||||
|         ::futures::future::poll_fn(move || -> crate::Result<_> { | ||||
|             try_ready!(conn.as_mut().unwrap().poll_without_shutdown()); | ||||
|             Ok(conn.take().unwrap().into_parts().into()) | ||||
|         futures_util::future::poll_fn(move |cx| { | ||||
|             ready!(conn.as_mut().unwrap().poll_without_shutdown(cx))?; | ||||
|             Poll::Ready(Ok(conn.take().unwrap().into_parts())) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
| @@ -624,32 +633,32 @@ impl<I, B, S, E> Future for Connection<I, S, E> | ||||
| where | ||||
|     S: Service<ReqBody=Body, ResBody=B> + 'static, | ||||
|     S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I: AsyncRead + AsyncWrite + 'static, | ||||
|     I: AsyncRead + AsyncWrite + Unpin + 'static, | ||||
|     B: Payload + 'static, | ||||
|     E: H2Exec<S::Future, B>, | ||||
| { | ||||
|     type Item = (); | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<()>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         loop { | ||||
|             match self.conn.poll() { | ||||
|                 Ok(x) => return Ok(x.map(|opt| { | ||||
|                     if let Some(proto::Dispatched::Upgrade(pending)) = opt { | ||||
|             match ready!(Pin::new(self.conn.as_mut().unwrap()).poll(cx)) { | ||||
|                 Ok(done) => { | ||||
|                     if let proto::Dispatched::Upgrade(pending) = done { | ||||
|                         // With no `Send` bound on `I`, we can't try to do | ||||
|                         // upgrades here. In case a user was trying to use | ||||
|                         // `Body::on_upgrade` with this API, send a special | ||||
|                         // error letting them know about that. | ||||
|                         pending.manual(); | ||||
|                     } | ||||
|                 })), | ||||
|                     return Poll::Ready(Ok(())); | ||||
|                 }, | ||||
|                 Err(e) => { | ||||
|                     match *e.kind() { | ||||
|                         Kind::Parse(Parse::VersionH2) if self.fallback.to_h2() => { | ||||
|                             self.upgrade_h2(); | ||||
|                             continue; | ||||
|                         } | ||||
|                         _ => return Err(e), | ||||
|                         _ => return Poll::Ready(Err(e)), | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -669,6 +678,9 @@ where | ||||
| // ===== impl Serve ===== | ||||
|  | ||||
| impl<I, S, E> Serve<I, S, E> { | ||||
|     unsafe_pinned!(incoming: I); | ||||
|     unsafe_unpinned!(make_service: S); | ||||
|  | ||||
|     /// Spawn all incoming connections onto the executor in `Http`. | ||||
|     pub(super) fn spawn_all(self) -> SpawnAll<I, S, E> { | ||||
|         SpawnAll { | ||||
| @@ -689,60 +701,63 @@ impl<I, S, E> Serve<I, S, E> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<I, S, B, E> Stream for Serve<I, S, E> | ||||
| impl<I, IO, IE, S, B, E> Stream for Serve<I, S, E> | ||||
| where | ||||
|     I: Stream, | ||||
|     I::Item: AsyncRead + AsyncWrite, | ||||
|     I::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>, | ||||
|     I: Stream<Item = Result<IO, IE>>, | ||||
|     IO: AsyncRead + AsyncWrite + Unpin, | ||||
|     IE: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     S: MakeServiceRef<IO, ReqBody=Body, ResBody=B>, | ||||
|     //S::Error2: Into<Box<StdError + Send + Sync>>, | ||||
|     //SME: Into<Box<StdError + Send + Sync>>, | ||||
|     B: Payload, | ||||
|     E: H2Exec<<S::Service as Service>::Future, B>, | ||||
| { | ||||
|     type Item = Connecting<I::Item, S::Future, E>; | ||||
|     type Error = crate::Error; | ||||
|     type Item = crate::Result<Connecting<IO, S::Future, E>>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { | ||||
|         match self.make_service.poll_ready_ref() { | ||||
|             Ok(Async::Ready(())) => (), | ||||
|             Ok(Async::NotReady) => return Ok(Async::NotReady), | ||||
|     fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> { | ||||
|         match ready!(self.as_mut().make_service().poll_ready_ref(cx)) { | ||||
|             Ok(()) => (), | ||||
|             Err(e) => { | ||||
|                 trace!("make_service closed"); | ||||
|                 return Err(crate::Error::new_user_make_service(e)); | ||||
|                 return Poll::Ready(Some(Err(crate::Error::new_user_make_service(e)))); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if let Some(io) = try_ready!(self.incoming.poll().map_err(crate::Error::new_accept)) { | ||||
|             let new_fut = self.make_service.make_service_ref(&io); | ||||
|             Ok(Async::Ready(Some(Connecting { | ||||
|         if let Some(item) = ready!(self.as_mut().incoming().poll_next(cx)) { | ||||
|             let io = item.map_err(crate::Error::new_accept)?; | ||||
|             let new_fut = self.as_mut().make_service().make_service_ref(&io); | ||||
|             Poll::Ready(Some(Ok(Connecting { | ||||
|                 future: new_fut, | ||||
|                 io: Some(io), | ||||
|                 protocol: self.protocol.clone(), | ||||
|             }))) | ||||
|         } else { | ||||
|             Ok(Async::Ready(None)) | ||||
|             Poll::Ready(None) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ===== impl Connecting ===== | ||||
|  | ||||
| impl<I, F, E, S, B> Future for Connecting<I, F, E> | ||||
| impl<I, F, E> Connecting<I, F, E> { | ||||
|     unsafe_pinned!(future: F); | ||||
|     unsafe_unpinned!(io: Option<I>); | ||||
| } | ||||
|  | ||||
| impl<I, F, S, FE, E, B> Future for Connecting<I, F, E> | ||||
| where | ||||
|     I: AsyncRead + AsyncWrite, | ||||
|     F: Future<Item=S>, | ||||
|     I: AsyncRead + AsyncWrite + Unpin, | ||||
|     F: Future<Output=Result<S, FE>>, | ||||
|     S: Service<ReqBody=Body, ResBody=B>, | ||||
|     B: Payload, | ||||
|     E: H2Exec<S::Future, B>, | ||||
| { | ||||
|     type Item = Connection<I, S, E>; | ||||
|     type Error = F::Error; | ||||
|     type Output = Result<Connection<I, S, E>, FE>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         let service = try_ready!(self.future.poll()); | ||||
|         let io = self.io.take().expect("polled after complete"); | ||||
|         Ok(self.protocol.serve_connection(io, service).into()) | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         let service = ready!(self.as_mut().future().poll(cx))?; | ||||
|         let io = self.as_mut().io().take().expect("polled after complete"); | ||||
|         Poll::Ready(Ok(self.protocol.serve_connection(io, service))) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -761,30 +776,51 @@ impl<I, S, E> SpawnAll<I, S, E> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<I, S, B, E> SpawnAll<I, S, E> | ||||
| impl<I, IO, IE, S, B, E> SpawnAll<I, S, E> | ||||
| where | ||||
|     I: Stream, | ||||
|     I::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I::Item: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     I: Stream<Item=Result<IO, IE>>, | ||||
|     IE: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|     S: MakeServiceRef< | ||||
|         I::Item, | ||||
|         IO, | ||||
|         ReqBody=Body, | ||||
|         ResBody=B, | ||||
|     >, | ||||
|     B: Payload, | ||||
|     E: H2Exec<<S::Service as Service>::Future, B>, | ||||
| { | ||||
|     pub(super) fn poll_watch<W>(&mut self, watcher: &W) -> Poll<(), crate::Error> | ||||
|     pub(super) fn poll_watch<W>(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, watcher: &W) -> Poll<crate::Result<()>> | ||||
|     where | ||||
|         E: NewSvcExec<I::Item, S::Future, S::Service, E, W>, | ||||
|         W: Watcher<I::Item, S::Service, E>, | ||||
|         E: NewSvcExec<IO, S::Future, S::Service, E, W>, | ||||
|         W: Watcher<IO, S::Service, E>, | ||||
|     { | ||||
|         // Safety: futures are never moved... lolwtf | ||||
|         let me = unsafe { self.get_unchecked_mut() }; | ||||
|         loop { | ||||
|             if let Some(connecting) = try_ready!(self.serve.poll()) { | ||||
|             if let Some(connecting) = ready!(unsafe { Pin::new_unchecked(&mut me.serve) }.poll_next(cx)?) { | ||||
|                 let fut = NewSvcTask::new(connecting, watcher.clone()); | ||||
|                 self.serve.protocol.exec.execute_new_svc(fut)?; | ||||
|                 me.serve.protocol.exec.execute_new_svc(fut)?; | ||||
|             } else { | ||||
|                 return Ok(Async::Ready(())) | ||||
|                 return Poll::Ready(Ok(())); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| impl<A, B> Future for Either<A, B> | ||||
| where | ||||
|     A: Future, | ||||
|     B: Future<Output=A::Output>, | ||||
| { | ||||
|     type Output = A::Output; | ||||
|  | ||||
|     fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         // Just simple pin projection to the inner variants | ||||
|         unsafe { | ||||
|             match self.get_unchecked_mut() { | ||||
|                 Either::A(a) => Pin::new_unchecked(a).poll(cx), | ||||
|                 Either::B(b) => Pin::new_unchecked(b).poll(cx), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -792,11 +828,11 @@ where | ||||
|  | ||||
| pub(crate) mod spawn_all { | ||||
|     use std::error::Error as StdError; | ||||
|     use futures::{Future, Poll}; | ||||
|     use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
|     use crate::body::{Body, Payload}; | ||||
|     use crate::common::exec::H2Exec; | ||||
|     use crate::common::{Future, Pin, Poll, Unpin, task}; | ||||
|     use crate::service::Service; | ||||
|     use super::{Connecting, UpgradeableConnection}; | ||||
|  | ||||
| @@ -809,7 +845,7 @@ pub(crate) mod spawn_all { | ||||
|     // connections, and signal that they start to shutdown when prompted, so | ||||
|     // it has a `GracefulWatcher` implementation to do that. | ||||
|     pub trait Watcher<I, S: Service, E>: Clone { | ||||
|         type Future: Future<Item=(), Error=crate::Error>; | ||||
|         type Future: Future<Output = crate::Result<()>>; | ||||
|  | ||||
|         fn watch(&self, conn: UpgradeableConnection<I, S, E>) -> Self::Future; | ||||
|     } | ||||
| @@ -820,7 +856,7 @@ pub(crate) mod spawn_all { | ||||
|  | ||||
|     impl<I, S, E> Watcher<I, S, E> for NoopWatcher | ||||
|     where | ||||
|         I: AsyncRead + AsyncWrite + Send + 'static, | ||||
|         I: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|         S: Service<ReqBody=Body> + 'static, | ||||
|         E: H2Exec<S::Future, S::ResBody>, | ||||
|     { | ||||
| @@ -858,42 +894,51 @@ pub(crate) mod spawn_all { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     impl<I, N, S, B, E, W> Future for NewSvcTask<I, N, S, E, W> | ||||
|     impl<I, N, S, NE, B, E, W> Future for NewSvcTask<I, N, S, E, W> | ||||
|     where | ||||
|         I: AsyncRead + AsyncWrite + Send + 'static, | ||||
|         N: Future<Item=S>, | ||||
|         N::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         I: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|         N: Future<Output=Result<S, NE>>, | ||||
|         NE: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         S: Service<ReqBody=Body, ResBody=B>, | ||||
|         B: Payload, | ||||
|         E: H2Exec<S::Future, B>, | ||||
|         W: Watcher<I, S, E>, | ||||
|     { | ||||
|         type Item = (); | ||||
|         type Error = (); | ||||
|         type Output = (); | ||||
|  | ||||
|         fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|             // If it weren't for needing to name this type so the `Send` bounds | ||||
|             // could be projected to the `Serve` executor, this could just be | ||||
|             // an `async fn`, and much safer. Woe is me. | ||||
|  | ||||
|             let me = unsafe { self.get_unchecked_mut() }; | ||||
|             loop { | ||||
|                 let next = match self.state { | ||||
|                 let next = match me.state { | ||||
|                     State::Connecting(ref mut connecting, ref watcher) => { | ||||
|                         let conn = try_ready!(connecting | ||||
|                             .poll() | ||||
|                             .map_err(|err| { | ||||
|                         let res = ready!(unsafe { Pin::new_unchecked(connecting).poll(cx) }); | ||||
|                         let conn = match res { | ||||
|                             Ok(conn) => conn, | ||||
|                             Err(err) => { | ||||
|                                 let err = crate::Error::new_user_make_service(err); | ||||
|                                 debug!("connecting error: {}", err); | ||||
|                             })); | ||||
|                                 return Poll::Ready(()); | ||||
|                             } | ||||
|                         }; | ||||
|                         let connected = watcher.watch(conn.with_upgrades()); | ||||
|                         State::Connected(connected) | ||||
|                     }, | ||||
|                     State::Connected(ref mut future) => { | ||||
|                         return future | ||||
|                             .poll() | ||||
|                             .map_err(|err| { | ||||
|                                 debug!("connection error: {}", err); | ||||
|                         return unsafe { Pin::new_unchecked(future) } | ||||
|                             .poll(cx) | ||||
|                             .map(|res| { | ||||
|                                 if let Err(err) = res { | ||||
|                                     debug!("connection error: {}", err); | ||||
|                                 } | ||||
|                             }); | ||||
|                     } | ||||
|                 }; | ||||
|  | ||||
|                 self.state = next; | ||||
|                 me.state = next; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -919,7 +964,7 @@ mod upgrades { | ||||
|     where | ||||
|         S: Service<ReqBody=Body, ResBody=B>,// + 'static, | ||||
|         S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         I: AsyncRead + AsyncWrite, | ||||
|         I: AsyncRead + AsyncWrite + Unpin, | ||||
|         B: Payload + 'static, | ||||
|         E: H2Exec<S::Future, B>, | ||||
|     { | ||||
| @@ -927,8 +972,8 @@ mod upgrades { | ||||
|         /// | ||||
|         /// This `Connection` should continue to be polled until shutdown | ||||
|         /// can finish. | ||||
|         pub fn graceful_shutdown(&mut self) { | ||||
|             self.inner.graceful_shutdown() | ||||
|         pub fn graceful_shutdown(mut self: Pin<&mut Self>) { | ||||
|             Pin::new(&mut self.inner).graceful_shutdown() | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -936,22 +981,17 @@ mod upgrades { | ||||
|     where | ||||
|         S: Service<ReqBody=Body, ResBody=B> + 'static, | ||||
|         S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         I: AsyncRead + AsyncWrite + Send + 'static, | ||||
|         I: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|         B: Payload + 'static, | ||||
|         E: super::H2Exec<S::Future, B>, | ||||
|     { | ||||
|         type Item = (); | ||||
|         type Error = crate::Error; | ||||
|         type Output = crate::Result<()>; | ||||
|  | ||||
|         fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|             loop { | ||||
|                 match self.inner.conn.poll() { | ||||
|                     Ok(Async::NotReady) => return Ok(Async::NotReady), | ||||
|                     Ok(Async::Ready(Some(proto::Dispatched::Shutdown))) | | ||||
|                     Ok(Async::Ready(None)) => { | ||||
|                         return Ok(Async::Ready(())); | ||||
|                     }, | ||||
|                     Ok(Async::Ready(Some(proto::Dispatched::Upgrade(pending)))) => { | ||||
|                 match ready!(Pin::new(self.inner.conn.as_mut().unwrap()).poll(cx)) { | ||||
|                     Ok(proto::Dispatched::Shutdown) => return Poll::Ready(Ok(())), | ||||
|                     Ok(proto::Dispatched::Upgrade(pending)) => { | ||||
|                         let h1 = match mem::replace(&mut self.inner.conn, None) { | ||||
|                             Some(Either::A(h1)) => h1, | ||||
|                             _ => unreachable!("Upgrade expects h1"), | ||||
| @@ -959,7 +999,7 @@ mod upgrades { | ||||
|  | ||||
|                         let (io, buf, _) = h1.into_inner(); | ||||
|                         pending.fulfill(Upgraded::new(Box::new(io), buf)); | ||||
|                         return Ok(Async::Ready(())); | ||||
|                         return Poll::Ready(Ok(())); | ||||
|                     }, | ||||
|                     Err(e) => { | ||||
|                         match *e.kind() { | ||||
| @@ -967,7 +1007,7 @@ mod upgrades { | ||||
|                                 self.inner.upgrade_h2(); | ||||
|                                 continue; | ||||
|                             } | ||||
|                             _ => return Err(e), | ||||
|                             _ => return Poll::Ready(Err(e)), | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
| @@ -60,12 +60,14 @@ use std::fmt; | ||||
|  | ||||
| #[cfg(feature = "runtime")] use std::time::Duration; | ||||
|  | ||||
| use futures::{Future, Stream, Poll}; | ||||
| use futures_core::Stream; | ||||
| use pin_utils::unsafe_pinned; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
| #[cfg(feature = "runtime")] use tokio_reactor; | ||||
|  | ||||
| use crate::body::{Body, Payload}; | ||||
| use crate::common::exec::{Exec, H2Exec, NewSvcExec}; | ||||
| use crate::common::{Future, Pin, Poll, Unpin, task}; | ||||
| use crate::service::{MakeServiceRef, Service}; | ||||
| // Renamed `Http` as `Http_` for now so that people upgrading don't see an | ||||
| // error that `hyper::server::Http` is private... | ||||
| @@ -102,6 +104,11 @@ impl<I> Server<I, ()> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<I, S, E> Server<I, S, E> { | ||||
|     // Never moved, just projected | ||||
|     unsafe_pinned!(spawn_all: SpawnAll<I, S, E>); | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "runtime")] | ||||
| impl Server<AddrIncoming, ()> { | ||||
|     /// Binds to the provided address, and returns a [`Builder`](Builder). | ||||
| @@ -140,17 +147,17 @@ impl<S> Server<AddrIncoming, S> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<I, S, E, B> Server<I, S, E> | ||||
| impl<I, IO, IE, S, E, B> Server<I, S, E> | ||||
| where | ||||
|     I: Stream, | ||||
|     I::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I::Item: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>, | ||||
|     I: Stream<Item=Result<IO, IE>>, | ||||
|     IE: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|     S: MakeServiceRef<IO, ReqBody=Body, ResBody=B>, | ||||
|     S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     S::Service: 'static, | ||||
|     B: Payload, | ||||
|     E: H2Exec<<S::Service as Service>::Future, B>, | ||||
|     E: NewSvcExec<I::Item, S::Future, S::Service, E, GracefulWatcher>, | ||||
|     E: NewSvcExec<IO, S::Future, S::Service, E, GracefulWatcher>, | ||||
| { | ||||
|     /// Prepares a server to handle graceful shutdown when the provided future | ||||
|     /// completes. | ||||
| @@ -193,29 +200,28 @@ where | ||||
|     /// ``` | ||||
|     pub fn with_graceful_shutdown<F>(self, signal: F) -> Graceful<I, S, F, E> | ||||
|     where | ||||
|         F: Future<Item=()> | ||||
|         F: Future<Output=()> | ||||
|     { | ||||
|         Graceful::new(self.spawn_all, signal) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<I, S, B, E> Future for Server<I, S, E> | ||||
| impl<I, IO, IE, S, B, E> Future for Server<I, S, E> | ||||
| where | ||||
|     I: Stream, | ||||
|     I::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I::Item: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>, | ||||
|     I: Stream<Item=Result<IO, IE>>, | ||||
|     IE: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|     S: MakeServiceRef<IO, ReqBody=Body, ResBody=B>, | ||||
|     S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     S::Service: 'static, | ||||
|     B: Payload, | ||||
|     E: H2Exec<<S::Service as Service>::Future, B>, | ||||
|     E: NewSvcExec<I::Item, S::Future, S::Service, E, NoopWatcher>, | ||||
|     E: NewSvcExec<IO, S::Future, S::Service, E, NoopWatcher>, | ||||
| { | ||||
|     type Item = (); | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<()>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         self.spawn_all.poll_watch(&NoopWatcher) | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         self.spawn_all().poll_watch(cx, &NoopWatcher) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -396,16 +402,16 @@ impl<I, E> Builder<I, E> { | ||||
|     /// // Finally, spawn `server` onto an Executor... | ||||
|     /// # } | ||||
|     /// ``` | ||||
|     pub fn serve<S, B>(self, new_service: S) -> Server<I, S, E> | ||||
|     pub fn serve<S, B, IO, IE>(self, new_service: S) -> Server<I, S, E> | ||||
|     where | ||||
|         I: Stream, | ||||
|         I::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         I::Item: AsyncRead + AsyncWrite + Send + 'static, | ||||
|         S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>, | ||||
|         I: Stream<Item=Result<IO, IE>>, | ||||
|         IE: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|         S: MakeServiceRef<IO, ReqBody=Body, ResBody=B>, | ||||
|         S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|         S::Service: 'static, | ||||
|         B: Payload, | ||||
|         E: NewSvcExec<I::Item, S::Future, S::Service, E, NoopWatcher>, | ||||
|         E: NewSvcExec<IO, S::Future, S::Service, E, NoopWatcher>, | ||||
|         E: H2Exec<<S::Service as Service>::Future, B>, | ||||
|     { | ||||
|         let serve = self.protocol.serve_incoming(self.incoming, new_service); | ||||
|   | ||||
| @@ -1,11 +1,12 @@ | ||||
| use std::error::Error as StdError; | ||||
|  | ||||
| use futures::{Async, Future, Stream, Poll}; | ||||
| use futures_core::Stream; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::body::{Body, Payload}; | ||||
| use crate::common::drain::{self, Draining, Signal, Watch, Watching}; | ||||
| use crate::common::exec::{H2Exec, NewSvcExec}; | ||||
| use crate::common::{Future, Pin, Poll, Unpin, task}; | ||||
| use crate::service::{MakeServiceRef, Service}; | ||||
| use super::conn::{SpawnAll, UpgradeableConnection, Watcher}; | ||||
|  | ||||
| @@ -37,31 +38,32 @@ impl<I, S, F, E> Graceful<I, S, F, E> { | ||||
| } | ||||
|  | ||||
|  | ||||
| impl<I, S, B, F, E> Future for Graceful<I, S, F, E> | ||||
| impl<I, IO, IE, S, B, F, E> Future for Graceful<I, S, F, E> | ||||
| where | ||||
|     I: Stream, | ||||
|     I::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I::Item: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>, | ||||
|     I: Stream<Item=Result<IO, IE>>, | ||||
|     IE: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|     S: MakeServiceRef<IO, ReqBody=Body, ResBody=B>, | ||||
|     S::Service: 'static, | ||||
|     S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     B: Payload, | ||||
|     F: Future<Item=()>, | ||||
|     F: Future<Output=()>, | ||||
|     E: H2Exec<<S::Service as Service>::Future, B>, | ||||
|     E: NewSvcExec<I::Item, S::Future, S::Service, E, GracefulWatcher>, | ||||
|     E: NewSvcExec<IO, S::Future, S::Service, E, GracefulWatcher>, | ||||
| { | ||||
|     type Item = (); | ||||
|     type Error = crate::Error; | ||||
|     type Output = crate::Result<()>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         // Safety: the futures are NEVER moved, self.state is overwritten instead. | ||||
|         let me = unsafe { self.get_unchecked_mut() }; | ||||
|         loop { | ||||
|             let next = match self.state { | ||||
|             let next = match me.state { | ||||
|                 State::Running { | ||||
|                     ref mut drain, | ||||
|                     ref mut spawn_all, | ||||
|                     ref mut signal, | ||||
|                 } => match signal.poll() { | ||||
|                     Ok(Async::Ready(())) | Err(_) => { | ||||
|                 } => match unsafe { Pin::new_unchecked(signal) }.poll(cx) { | ||||
|                     Poll::Ready(()) => { | ||||
|                         debug!("signal received, starting graceful shutdown"); | ||||
|                         let sig = drain | ||||
|                             .take() | ||||
| @@ -69,21 +71,21 @@ where | ||||
|                             .0; | ||||
|                         State::Draining(sig.drain()) | ||||
|                     }, | ||||
|                     Ok(Async::NotReady) => { | ||||
|                     Poll::Pending => { | ||||
|                         let watch = drain | ||||
|                             .as_ref() | ||||
|                             .expect("drain channel") | ||||
|                             .1 | ||||
|                             .clone(); | ||||
|                         return spawn_all.poll_watch(&GracefulWatcher(watch)); | ||||
|                         return unsafe { Pin::new_unchecked(spawn_all) }.poll_watch(cx, &GracefulWatcher(watch)); | ||||
|                     }, | ||||
|                 }, | ||||
|                 State::Draining(ref mut draining) => { | ||||
|                     return draining.poll() | ||||
|                         .map_err(|()| unreachable!("drain mpsc rx never errors")); | ||||
|                     return Pin::new(draining).poll(cx).map(Ok); | ||||
|                 } | ||||
|             }; | ||||
|             self.state = next; | ||||
|             // It's important to just assign, not mem::replace or anything. | ||||
|             me.state = next; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -94,11 +96,11 @@ pub struct GracefulWatcher(Watch); | ||||
|  | ||||
| impl<I, S, E> Watcher<I, S, E> for GracefulWatcher | ||||
| where | ||||
|     I: AsyncRead + AsyncWrite + Send + 'static, | ||||
|     I: AsyncRead + AsyncWrite + Unpin + Send + 'static, | ||||
|     S: Service<ReqBody=Body> + 'static, | ||||
|     E: H2Exec<S::Future, S::ResBody>, | ||||
| { | ||||
|     type Future = Watching<UpgradeableConnection<I, S, E>, fn(&mut UpgradeableConnection<I, S, E>)>; | ||||
|     type Future = Watching<UpgradeableConnection<I, S, E>, fn(Pin<&mut UpgradeableConnection<I, S, E>>)>; | ||||
|  | ||||
|     fn watch(&self, conn: UpgradeableConnection<I, S, E>) -> Self::Future { | ||||
|         self | ||||
| @@ -108,11 +110,11 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn on_drain<I, S, E>(conn: &mut UpgradeableConnection<I, S, E>) | ||||
| fn on_drain<I, S, E>(conn: Pin<&mut UpgradeableConnection<I, S, E>>) | ||||
| where | ||||
|     S: Service<ReqBody=Body>, | ||||
|     S::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     I: AsyncRead + AsyncWrite, | ||||
|     I: AsyncRead + AsyncWrite + Unpin, | ||||
|     S::ResBody: Payload + 'static, | ||||
|     E: H2Exec<S::Future, S::ResBody>, | ||||
| { | ||||
|   | ||||
| @@ -3,11 +3,13 @@ use std::io; | ||||
| use std::net::{SocketAddr, TcpListener as StdTcpListener}; | ||||
| use std::time::{Duration, Instant}; | ||||
|  | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use futures_core::Stream; | ||||
| use tokio_reactor::Handle; | ||||
| use tokio_tcp::TcpListener; | ||||
| use tokio_timer::Delay; | ||||
|  | ||||
| use crate::common::{Future, Pin, Poll, task}; | ||||
|  | ||||
| pub use self::addr_stream::AddrStream; | ||||
|  | ||||
| /// A stream of connections from binding to an address. | ||||
| @@ -92,28 +94,20 @@ impl AddrIncoming { | ||||
|     pub fn set_sleep_on_errors(&mut self, val: bool) { | ||||
|         self.sleep_on_errors = val; | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Stream for AddrIncoming { | ||||
|     // currently unnameable... | ||||
|     type Item = AddrStream; | ||||
|     type Error = ::std::io::Error; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { | ||||
|     fn poll_next_(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<AddrStream>> { | ||||
|         // Check if a previous timeout is active that was set by IO errors. | ||||
|         if let Some(ref mut to) = self.timeout { | ||||
|             match to.poll() { | ||||
|                 Ok(Async::Ready(())) => {} | ||||
|                 Ok(Async::NotReady) => return Ok(Async::NotReady), | ||||
|                 Err(err) => { | ||||
|                     error!("sleep timer error: {}", err); | ||||
|                 } | ||||
|             match Pin::new(to).poll(cx) { | ||||
|                 Poll::Ready(()) => {} | ||||
|                 Poll::Pending => return Poll::Pending, | ||||
|             } | ||||
|         } | ||||
|         self.timeout = None; | ||||
|  | ||||
|         loop { | ||||
|             match self.listener.poll_accept() { | ||||
|                 Ok(Async::Ready((socket, addr))) => { | ||||
|             match Pin::new(&mut self.listener).poll_accept(cx) { | ||||
|                 Poll::Ready(Ok((socket, addr))) => { | ||||
|                     if let Some(dur) = self.tcp_keepalive_timeout { | ||||
|                         if let Err(e) = socket.set_keepalive(Some(dur)) { | ||||
|                             trace!("error trying to set TCP keepalive: {}", e); | ||||
| @@ -122,10 +116,10 @@ impl Stream for AddrIncoming { | ||||
|                     if let Err(e) = socket.set_nodelay(self.tcp_nodelay) { | ||||
|                         trace!("error trying to set TCP nodelay: {}", e); | ||||
|                     } | ||||
|                     return Ok(Async::Ready(Some(AddrStream::new(socket, addr)))); | ||||
|                     return Poll::Ready(Ok(AddrStream::new(socket, addr))); | ||||
|                 }, | ||||
|                 Ok(Async::NotReady) => return Ok(Async::NotReady), | ||||
|                 Err(e) => { | ||||
|                 Poll::Pending => return Poll::Pending, | ||||
|                 Poll::Ready(Err(e)) => { | ||||
|                     // Connection errors can be ignored directly, continue by | ||||
|                     // accepting the next request. | ||||
|                     if is_connection_error(&e) { | ||||
| @@ -134,28 +128,24 @@ impl Stream for AddrIncoming { | ||||
|                     } | ||||
|  | ||||
|                     if self.sleep_on_errors { | ||||
|                         error!("accept error: {}", e); | ||||
|  | ||||
|                         // Sleep 1s. | ||||
|                         let delay = Instant::now() + Duration::from_secs(1); | ||||
|                         let mut timeout = Delay::new(delay); | ||||
|  | ||||
|                         match timeout.poll() { | ||||
|                             Ok(Async::Ready(())) => { | ||||
|                         match Pin::new(&mut timeout).poll(cx) { | ||||
|                             Poll::Ready(()) => { | ||||
|                                 // Wow, it's been a second already? Ok then... | ||||
|                                 error!("accept error: {}", e); | ||||
|                                 continue | ||||
|                             }, | ||||
|                             Ok(Async::NotReady) => { | ||||
|                                 error!("accept error: {}", e); | ||||
|                             Poll::Pending => { | ||||
|                                 self.timeout = Some(timeout); | ||||
|                                 return Ok(Async::NotReady); | ||||
|                                 return Poll::Pending; | ||||
|                             }, | ||||
|                             Err(timer_err) => { | ||||
|                                 error!("couldn't sleep on error, timer error: {}", timer_err); | ||||
|                                 return Err(e); | ||||
|                             } | ||||
|                         } | ||||
|                     } else { | ||||
|                         return Err(e); | ||||
|                         return Poll::Ready(Err(e)); | ||||
|                     } | ||||
|                 }, | ||||
|             } | ||||
| @@ -163,6 +153,15 @@ impl Stream for AddrIncoming { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Stream for AddrIncoming { | ||||
|     type Item = io::Result<AddrStream>; | ||||
|  | ||||
|     fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> { | ||||
|         let result = ready!(self.poll_next_(cx)); | ||||
|         Poll::Ready(Some(result)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// This function defines errors that are per-connection. Which basically | ||||
| /// means that if we get this error from `accept()` system call it means | ||||
| /// next connection might be ready to be accepted. | ||||
| @@ -191,13 +190,14 @@ impl fmt::Debug for AddrIncoming { | ||||
| } | ||||
|  | ||||
| mod addr_stream { | ||||
|     use std::io::{self, Read, Write}; | ||||
|     use std::io; | ||||
|     use std::net::SocketAddr; | ||||
|     use bytes::{Buf, BufMut}; | ||||
|     use futures::Poll; | ||||
|     use tokio_tcp::TcpStream; | ||||
|     use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
|     use crate::common::{Pin, Poll, task}; | ||||
|  | ||||
|  | ||||
|     /// A transport returned yieled by `AddrIncoming`. | ||||
|     #[derive(Debug)] | ||||
| @@ -227,26 +227,6 @@ mod addr_stream { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     impl Read for AddrStream { | ||||
|         #[inline] | ||||
|         fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | ||||
|             self.inner.read(buf) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     impl Write for AddrStream { | ||||
|         #[inline] | ||||
|         fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | ||||
|             self.inner.write(buf) | ||||
|         } | ||||
|  | ||||
|         #[inline] | ||||
|         fn flush(&mut self) -> io::Result<()> { | ||||
|             // TcpStream::flush is a noop, so skip calling it... | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     impl AsyncRead for AddrStream { | ||||
|         #[inline] | ||||
|         unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { | ||||
| @@ -254,20 +234,36 @@ mod addr_stream { | ||||
|         } | ||||
|  | ||||
|         #[inline] | ||||
|         fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||
|             self.inner.read_buf(buf) | ||||
|         fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> { | ||||
|             Pin::new(&mut self.inner).poll_read(cx, buf) | ||||
|         } | ||||
|  | ||||
|         #[inline] | ||||
|         fn poll_read_buf<B: BufMut>(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut B) -> Poll<io::Result<usize>> { | ||||
|             Pin::new(&mut self.inner).poll_read_buf(cx, buf) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     impl AsyncWrite for AddrStream { | ||||
|         #[inline] | ||||
|         fn shutdown(&mut self) -> Poll<(), io::Error> { | ||||
|             AsyncWrite::shutdown(&mut self.inner) | ||||
|         fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> { | ||||
|             Pin::new(&mut self.inner).poll_write(cx, buf) | ||||
|         } | ||||
|  | ||||
|         #[inline] | ||||
|         fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||
|             self.inner.write_buf(buf) | ||||
|         fn poll_write_buf<B: Buf>(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut B) -> Poll<io::Result<usize>> { | ||||
|             Pin::new(&mut self.inner).poll_write_buf(cx, buf) | ||||
|         } | ||||
|  | ||||
|         #[inline] | ||||
|         fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|             // TCP flush is a noop | ||||
|             Poll::Ready(Ok(())) | ||||
|         } | ||||
|  | ||||
|         #[inline] | ||||
|         fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|             Pin::new(&mut self.inner).poll_shutdown(cx) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,12 @@ | ||||
| use std::error::Error as StdError; | ||||
| use std::fmt; | ||||
|  | ||||
| use futures::{Async, Future, IntoFuture, Poll}; | ||||
|  | ||||
| use crate::body::Payload; | ||||
| use crate::common::{Future, Poll, task}; | ||||
| use super::Service; | ||||
|  | ||||
| /// An asynchronous constructor of `Service`s. | ||||
| pub trait MakeService<Ctx> { | ||||
| pub trait MakeService<Target> { | ||||
|     /// The `Payload` body of the `http::Request`. | ||||
|     type ReqBody: Payload; | ||||
|  | ||||
| @@ -25,7 +24,7 @@ pub trait MakeService<Ctx> { | ||||
|     >; | ||||
|  | ||||
|     /// The future returned from `new_service` of a `Service`. | ||||
|     type Future: Future<Item=Self::Service, Error=Self::MakeError>; | ||||
|     type Future: Future<Output=Result<Self::Service, Self::MakeError>>; | ||||
|  | ||||
|     /// The error type that can be returned when creating a new `Service`. | ||||
|     type MakeError: Into<Box<dyn StdError + Send + Sync>>; | ||||
| @@ -35,18 +34,18 @@ pub trait MakeService<Ctx> { | ||||
|     /// The implementation of this method is allowed to return a `Ready` even if | ||||
|     /// the factory is not ready to create a new service. In this case, the future | ||||
|     /// returned from `make_service` will resolve to an error. | ||||
|     fn poll_ready(&mut self) -> Poll<(), Self::MakeError> { | ||||
|         Ok(Async::Ready(())) | ||||
|     fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::MakeError>> { | ||||
|         Poll::Ready(Ok(())) | ||||
|     } | ||||
|  | ||||
|     /// Create a new `Service`. | ||||
|     fn make_service(&mut self, ctx: Ctx) -> Self::Future; | ||||
|     fn make_service(&mut self, target: Target) -> Self::Future; | ||||
| } | ||||
|  | ||||
| // Just a sort-of "trait alias" of `MakeService`, not to be implemented | ||||
| // by anyone, only used as bounds. | ||||
| #[doc(hidden)] | ||||
| pub trait MakeServiceRef<Ctx>: self::sealed::Sealed<Ctx> { | ||||
| pub trait MakeServiceRef<Target>: self::sealed::Sealed<Target> { | ||||
|     type ReqBody: Payload; | ||||
|     type ResBody: Payload; | ||||
|     type Error: Into<Box<dyn StdError + Send + Sync>>; | ||||
| @@ -56,7 +55,7 @@ pub trait MakeServiceRef<Ctx>: self::sealed::Sealed<Ctx> { | ||||
|         Error=Self::Error, | ||||
|     >; | ||||
|     type MakeError: Into<Box<dyn StdError + Send + Sync>>; | ||||
|     type Future: Future<Item=Self::Service, Error=Self::MakeError>; | ||||
|     type Future: Future<Output=Result<Self::Service, Self::MakeError>>; | ||||
|  | ||||
|     // Acting like a #[non_exhaustive] for associated types of this trait. | ||||
|     // | ||||
| @@ -69,18 +68,18 @@ pub trait MakeServiceRef<Ctx>: self::sealed::Sealed<Ctx> { | ||||
|     // if necessary. | ||||
|     type __DontNameMe: self::sealed::CantImpl; | ||||
|  | ||||
|     fn poll_ready_ref(&mut self) -> Poll<(), Self::MakeError>; | ||||
|     fn poll_ready_ref(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::MakeError>>; | ||||
|  | ||||
|     fn make_service_ref(&mut self, ctx: &Ctx) -> Self::Future; | ||||
|     fn make_service_ref(&mut self, target: &Target) -> Self::Future; | ||||
| } | ||||
|  | ||||
| impl<T, Ctx, E, ME, S, F, IB, OB> MakeServiceRef<Ctx> for T | ||||
| impl<T, Target, E, ME, S, F, IB, OB> MakeServiceRef<Target> for T | ||||
| where | ||||
|     T: for<'a> MakeService<&'a Ctx, Error=E, MakeError=ME, Service=S, Future=F, ReqBody=IB, ResBody=OB>, | ||||
|     T: for<'a> MakeService<&'a Target, Error=E, MakeError=ME, Service=S, Future=F, ReqBody=IB, ResBody=OB>, | ||||
|     E: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     ME: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     S: Service<ReqBody=IB, ResBody=OB, Error=E>, | ||||
|     F: Future<Item=S, Error=ME>, | ||||
|     F: Future<Output=Result<S, ME>>, | ||||
|     IB: Payload, | ||||
|     OB: Payload, | ||||
| { | ||||
| @@ -93,22 +92,22 @@ where | ||||
|  | ||||
|     type __DontNameMe = self::sealed::CantName; | ||||
|  | ||||
|     fn poll_ready_ref(&mut self) -> Poll<(), Self::MakeError> { | ||||
|         self.poll_ready() | ||||
|     fn poll_ready_ref(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::MakeError>> { | ||||
|         self.poll_ready(cx) | ||||
|     } | ||||
|  | ||||
|     fn make_service_ref(&mut self, ctx: &Ctx) -> Self::Future { | ||||
|         self.make_service(ctx) | ||||
|     fn make_service_ref(&mut self, target: &Target) -> Self::Future { | ||||
|         self.make_service(target) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T, Ctx, E, ME, S, F, IB, OB> self::sealed::Sealed<Ctx> for T | ||||
| impl<T, Target, E, ME, S, F, IB, OB> self::sealed::Sealed<Target> for T | ||||
| where | ||||
|     T: for<'a> MakeService<&'a Ctx, Error=E, MakeError=ME, Service=S, Future=F, ReqBody=IB, ResBody=OB>, | ||||
|     T: for<'a> MakeService<&'a Target, Error=E, MakeError=ME, Service=S, Future=F, ReqBody=IB, ResBody=OB>, | ||||
|     E: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     ME: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     S: Service<ReqBody=IB, ResBody=OB, Error=E>, | ||||
|     F: Future<Item=S, Error=ME>, | ||||
|     F: Future<Output=Result<S, ME>>, | ||||
|     IB: Payload, | ||||
|     OB: Payload, | ||||
| {} | ||||
| @@ -146,10 +145,10 @@ where | ||||
| /// # } | ||||
| /// # #[cfg(not(feature = "runtime"))] fn main() {} | ||||
| /// ``` | ||||
| pub fn make_service_fn<F, Ctx, Ret>(f: F) -> MakeServiceFn<F> | ||||
| pub fn make_service_fn<F, Target, Ret>(f: F) -> MakeServiceFn<F> | ||||
| where | ||||
|     F: FnMut(&Ctx) -> Ret, | ||||
|     Ret: IntoFuture, | ||||
|     F: FnMut(&Target) -> Ret, | ||||
|     Ret: Future, | ||||
| { | ||||
|     MakeServiceFn { | ||||
|         f, | ||||
| @@ -161,24 +160,24 @@ pub struct MakeServiceFn<F> { | ||||
|     f: F, | ||||
| } | ||||
|  | ||||
| impl<'c, F, Ctx, Ret, ReqBody, ResBody> MakeService<&'c Ctx> for MakeServiceFn<F> | ||||
| impl<'t, F, Target, Ret, ReqBody, ResBody, Svc, MkErr> MakeService<&'t Target> for MakeServiceFn<F> | ||||
| where | ||||
|     F: FnMut(&Ctx) -> Ret, | ||||
|     Ret: IntoFuture, | ||||
|     Ret::Item: Service<ReqBody=ReqBody, ResBody=ResBody>, | ||||
|     Ret::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     F: FnMut(&Target) -> Ret, | ||||
|     Ret: Future<Output=Result<Svc, MkErr>>, | ||||
|     Svc: Service<ReqBody=ReqBody, ResBody=ResBody>, | ||||
|     MkErr: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     ReqBody: Payload, | ||||
|     ResBody: Payload, | ||||
| { | ||||
|     type ReqBody = ReqBody; | ||||
|     type ResBody = ResBody; | ||||
|     type Error = <Ret::Item as Service>::Error; | ||||
|     type Service = Ret::Item; | ||||
|     type Future = Ret::Future; | ||||
|     type MakeError = Ret::Error; | ||||
|     type Error = Svc::Error; | ||||
|     type Service = Svc; | ||||
|     type Future = Ret; | ||||
|     type MakeError = MkErr; | ||||
|  | ||||
|     fn make_service(&mut self, ctx: &'c Ctx) -> Self::Future { | ||||
|         (self.f)(ctx).into_future() | ||||
|     fn make_service(&mut self, target: &'t Target) -> Self::Future { | ||||
|         (self.f)(target) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -31,11 +31,7 @@ | ||||
| //! is called. | ||||
|  | ||||
| mod make_service; | ||||
| mod new_service; | ||||
| mod service; | ||||
|  | ||||
| pub use self::make_service::{make_service_fn, MakeService, MakeServiceRef}; | ||||
| // NewService is soft-deprecated. | ||||
| #[doc(hidden)] | ||||
| pub use self::new_service::NewService; | ||||
| pub use self::service::{service_fn, service_fn_ok, Service}; | ||||
| pub use self::service::{service_fn, Service}; | ||||
|   | ||||
| @@ -1,79 +0,0 @@ | ||||
| use std::error::Error as StdError; | ||||
|  | ||||
| use futures::{Async, Future, IntoFuture, Poll}; | ||||
|  | ||||
| use crate::body::Payload; | ||||
| use super::{MakeService, Service}; | ||||
|  | ||||
| /// An asynchronous constructor of `Service`s. | ||||
| pub trait NewService { | ||||
|     /// The `Payload` body of the `http::Request`. | ||||
|     type ReqBody: Payload; | ||||
|  | ||||
|     /// The `Payload` body of the `http::Response`. | ||||
|     type ResBody: Payload; | ||||
|  | ||||
|     /// The error type that can be returned by `Service`s. | ||||
|     type Error: Into<Box<dyn StdError + Send + Sync>>; | ||||
|  | ||||
|     /// The resolved `Service` from `new_service()`. | ||||
|     type Service: Service< | ||||
|         ReqBody=Self::ReqBody, | ||||
|         ResBody=Self::ResBody, | ||||
|         Error=Self::Error, | ||||
|     >; | ||||
|  | ||||
|     /// The future returned from `new_service` of a `Service`. | ||||
|     type Future: Future<Item=Self::Service, Error=Self::InitError>; | ||||
|  | ||||
|     /// The error type that can be returned when creating a new `Service`. | ||||
|     type InitError: Into<Box<dyn StdError + Send + Sync>>; | ||||
|  | ||||
|     #[doc(hidden)] | ||||
|     fn poll_ready(&mut self) -> Poll<(), Self::InitError> { | ||||
|         Ok(Async::Ready(())) | ||||
|     } | ||||
|  | ||||
|     /// Create a new `Service`. | ||||
|     fn new_service(&self) -> Self::Future; | ||||
| } | ||||
|  | ||||
| impl<F, R, S> NewService for F | ||||
| where | ||||
|     F: Fn() -> R, | ||||
|     R: IntoFuture<Item=S>, | ||||
|     R::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     S: Service, | ||||
| { | ||||
|     type ReqBody = S::ReqBody; | ||||
|     type ResBody = S::ResBody; | ||||
|     type Error = S::Error; | ||||
|     type Service = S; | ||||
|     type Future = R::Future; | ||||
|     type InitError = R::Error; | ||||
|  | ||||
|     fn new_service(&self) -> Self::Future { | ||||
|         (*self)().into_future() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<N, Ctx> MakeService<Ctx> for N | ||||
| where | ||||
|     N: NewService, | ||||
| { | ||||
|     type ReqBody = N::ReqBody; | ||||
|     type ResBody = N::ResBody; | ||||
|     type Error = N::Error; | ||||
|     type Service = N::Service; | ||||
|     type Future = N::Future; | ||||
|     type MakeError = N::InitError; | ||||
|  | ||||
|     fn poll_ready(&mut self) -> Poll<(), Self::MakeError> { | ||||
|         NewService::poll_ready(self) | ||||
|     } | ||||
|  | ||||
|     fn make_service(&mut self, _: Ctx) -> Self::Future { | ||||
|         self.new_service() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -2,10 +2,8 @@ use std::error::Error as StdError; | ||||
| use std::fmt; | ||||
| use std::marker::PhantomData; | ||||
|  | ||||
| use futures::{future, Async, Future, IntoFuture, Poll}; | ||||
|  | ||||
| use crate::body::Payload; | ||||
| use crate::common::Never; | ||||
| use crate::common::{Future, Never, Poll, task}; | ||||
| use crate::{Request, Response}; | ||||
|  | ||||
| /// An asynchronous function from `Request` to `Response`. | ||||
| @@ -24,15 +22,15 @@ pub trait Service { | ||||
|     type Error: Into<Box<dyn StdError + Send + Sync>>; | ||||
|  | ||||
|     /// The `Future` returned by this `Service`. | ||||
|     type Future: Future<Item=Response<Self::ResBody>, Error=Self::Error>; | ||||
|     type Future: Future<Output=Result<Response<Self::ResBody>, Self::Error>>; | ||||
|  | ||||
|     /// Returns `Ready` when the service is able to process requests. | ||||
|     /// | ||||
|     /// The implementation of this method is allowed to return a `Ready` even if | ||||
|     /// the service is not ready to process. In this case, the future returned | ||||
|     /// from `call` will resolve to an error. | ||||
|     fn poll_ready(&mut self) -> Poll<(), Self::Error> { | ||||
|         Ok(Async::Ready(())) | ||||
|     fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> { | ||||
|         Poll::Ready(Ok(())) | ||||
|     } | ||||
|  | ||||
|     /// Calls this `Service` with a request, returning a `Future` of the response. | ||||
| @@ -61,7 +59,7 @@ pub trait Service { | ||||
| pub fn service_fn<F, R, S>(f: F) -> ServiceFn<F, R> | ||||
| where | ||||
|     F: FnMut(Request<R>) -> S, | ||||
|     S: IntoFuture, | ||||
|     S: Future, | ||||
| { | ||||
|     ServiceFn { | ||||
|         f, | ||||
| @@ -69,61 +67,27 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Create a `Service` from a function that never errors. | ||||
| /// | ||||
| /// # Example | ||||
| /// | ||||
| /// ```rust | ||||
| /// use hyper::{Body, Request, Response}; | ||||
| /// use hyper::service::service_fn_ok; | ||||
| /// | ||||
| /// let service = service_fn_ok(|req: Request<Body>| { | ||||
| ///     println!("request: {} {}", req.method(), req.uri()); | ||||
| ///     Response::new(Body::from("Hello World")) | ||||
| /// }); | ||||
| /// ``` | ||||
| pub fn service_fn_ok<F, R, S>(f: F) -> ServiceFnOk<F, R> | ||||
| where | ||||
|     F: FnMut(Request<R>) -> Response<S>, | ||||
|     S: Payload, | ||||
| { | ||||
|     ServiceFnOk { | ||||
|         f, | ||||
|         _req: PhantomData, | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Not exported from crate as this will likely be replaced with `impl Service`. | ||||
| pub struct ServiceFn<F, R> { | ||||
|     f: F, | ||||
|     _req: PhantomData<fn(R)>, | ||||
| } | ||||
|  | ||||
| impl<F, ReqBody, Ret, ResBody> Service for ServiceFn<F, ReqBody> | ||||
| impl<F, ReqBody, Ret, ResBody, E> Service for ServiceFn<F, ReqBody> | ||||
| where | ||||
|     F: FnMut(Request<ReqBody>) -> Ret, | ||||
|     ReqBody: Payload, | ||||
|     Ret: IntoFuture<Item=Response<ResBody>>, | ||||
|     Ret::Error: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     Ret: Future<Output=Result<Response<ResBody>, E>>, | ||||
|     E: Into<Box<dyn StdError + Send + Sync>>, | ||||
|     ResBody: Payload, | ||||
| { | ||||
|     type ReqBody = ReqBody; | ||||
|     type ResBody = ResBody; | ||||
|     type Error = Ret::Error; | ||||
|     type Future = Ret::Future; | ||||
|     type Error = E; | ||||
|     type Future = Ret; | ||||
|  | ||||
|     fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future { | ||||
|         (self.f)(req).into_future() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<F, R> IntoFuture for ServiceFn<F, R> { | ||||
|     type Future = future::FutureResult<Self::Item, Self::Error>; | ||||
|     type Item = Self; | ||||
|     type Error = Never; | ||||
|  | ||||
|     fn into_future(self) -> Self::Future { | ||||
|         future::ok(self) | ||||
|         (self.f)(req) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -133,63 +97,3 @@ impl<F, R> fmt::Debug for ServiceFn<F, R> { | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Not exported from crate as this will likely be replaced with `impl Service`. | ||||
| pub struct ServiceFnOk<F, R> { | ||||
|     f: F, | ||||
|     _req: PhantomData<fn(R)>, | ||||
| } | ||||
|  | ||||
| impl<F, ReqBody, ResBody> Service for ServiceFnOk<F, ReqBody> | ||||
| where | ||||
|     F: FnMut(Request<ReqBody>) -> Response<ResBody>, | ||||
|     ReqBody: Payload, | ||||
|     ResBody: Payload, | ||||
| { | ||||
|     type ReqBody = ReqBody; | ||||
|     type ResBody = ResBody; | ||||
|     type Error = Never; | ||||
|     type Future = future::FutureResult<Response<ResBody>, Never>; | ||||
|  | ||||
|     fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future { | ||||
|         future::ok((self.f)(req)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<F, R> IntoFuture for ServiceFnOk<F, R> { | ||||
|     type Future = future::FutureResult<Self::Item, Self::Error>; | ||||
|     type Item = Self; | ||||
|     type Error = Never; | ||||
|  | ||||
|     fn into_future(self) -> Self::Future { | ||||
|         future::ok(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<F, R> fmt::Debug for ServiceFnOk<F, R> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         f.debug_struct("impl Service") | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
|  | ||||
| //#[cfg(test)] | ||||
| fn _assert_fn_mut() { | ||||
|     fn assert_service<T: Service>(_t: &T) {} | ||||
|  | ||||
|     let mut val = 0; | ||||
|  | ||||
|     let svc = service_fn(move |_req: Request<crate::Body>| { | ||||
|         val += 1; | ||||
|         future::ok::<_, Never>(Response::new(crate::Body::empty())) | ||||
|     }); | ||||
|  | ||||
|     assert_service(&svc); | ||||
|  | ||||
|     let svc = service_fn_ok(move |_req: Request<crate::Body>| { | ||||
|         val += 1; | ||||
|         Response::new(crate::Body::empty()) | ||||
|     }); | ||||
|  | ||||
|     assert_service(&svc); | ||||
| } | ||||
|   | ||||
| @@ -8,14 +8,15 @@ | ||||
| use std::any::TypeId; | ||||
| use std::error::Error as StdError; | ||||
| use std::fmt; | ||||
| use std::io::{self, Read, Write}; | ||||
| use std::io; | ||||
| use std::marker::Unpin; | ||||
|  | ||||
| use bytes::{Buf, BufMut, Bytes}; | ||||
| use futures::{Async, Future, Poll}; | ||||
| use futures::sync::oneshot; | ||||
| use bytes::{/*Buf, BufMut, */Bytes}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
| use tokio_sync::oneshot; | ||||
|  | ||||
| use crate::common::io::Rewind; | ||||
| use crate::common::{Future, Pin, Poll, task}; | ||||
|  | ||||
| /// An upgraded HTTP connection. | ||||
| /// | ||||
| @@ -79,7 +80,7 @@ pub(crate) fn pending() -> (Pending, OnUpgrade) { | ||||
|     ) | ||||
| } | ||||
|  | ||||
| pub(crate) trait Io: AsyncRead + AsyncWrite + 'static { | ||||
| pub(crate) trait Io: AsyncRead + AsyncWrite + Unpin + 'static { | ||||
|     fn __hyper_type_id(&self) -> TypeId { | ||||
|         TypeId::of::<Self>() | ||||
|     } | ||||
| @@ -104,7 +105,7 @@ impl dyn Io + Send { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: AsyncRead + AsyncWrite + 'static> Io for T {} | ||||
| impl<T: AsyncRead + AsyncWrite + Unpin + 'static> Io for T {} | ||||
|  | ||||
| // ===== impl Upgraded ===== | ||||
|  | ||||
| @@ -119,7 +120,7 @@ impl Upgraded { | ||||
|     /// | ||||
|     /// On success, returns the downcasted parts. On error, returns the | ||||
|     /// `Upgraded` back. | ||||
|     pub fn downcast<T: AsyncRead + AsyncWrite + 'static>(self) -> Result<Parts<T>, Self> { | ||||
|     pub fn downcast<T: AsyncRead + AsyncWrite + Unpin + 'static>(self) -> Result<Parts<T>, Self> { | ||||
|         let (io, buf) = self.io.into_inner(); | ||||
|         match io.__hyper_downcast() { | ||||
|             Ok(t) => Ok(Parts { | ||||
| @@ -134,46 +135,27 @@ impl Upgraded { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Read for Upgraded { | ||||
|     #[inline] | ||||
|     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | ||||
|         self.io.read(buf) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Write for Upgraded { | ||||
|     #[inline] | ||||
|     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | ||||
|         self.io.write(buf) | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn flush(&mut self) -> io::Result<()> { | ||||
|         self.io.flush() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl AsyncRead for Upgraded { | ||||
|     #[inline] | ||||
|     unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { | ||||
|         self.io.prepare_uninitialized_buffer(buf) | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||
|         self.io.read_buf(buf) | ||||
|     fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> { | ||||
|         Pin::new(&mut self.io).poll_read(cx, buf) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl AsyncWrite for Upgraded { | ||||
|     #[inline] | ||||
|     fn shutdown(&mut self) -> Poll<(), io::Error> { | ||||
|         AsyncWrite::shutdown(&mut self.io) | ||||
|     fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> { | ||||
|         Pin::new(&mut self.io).poll_write(cx, buf) | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||
|         self.io.write_buf(buf) | ||||
|     fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         Pin::new(&mut self.io).poll_flush(cx) | ||||
|     } | ||||
|  | ||||
|     fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         Pin::new(&mut self.io).poll_shutdown(cx) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -199,20 +181,18 @@ impl OnUpgrade { | ||||
| } | ||||
|  | ||||
| impl Future for OnUpgrade { | ||||
|     type Item = Upgraded; | ||||
|     type Error = crate::Error; | ||||
|     type Output = Result<Upgraded, crate::Error>; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match self.rx { | ||||
|             Some(ref mut rx) => match rx.poll() { | ||||
|                 Ok(Async::NotReady) => Ok(Async::NotReady), | ||||
|                 Ok(Async::Ready(Ok(upgraded))) => Ok(Async::Ready(upgraded)), | ||||
|                 Ok(Async::Ready(Err(err))) => Err(err), | ||||
|             Some(ref mut rx) => Pin::new(rx).poll(cx).map(|res| match res { | ||||
|                 Ok(Ok(upgraded)) => Ok(upgraded), | ||||
|                 Ok(Err(err)) => Err(err), | ||||
|                 Err(_oneshot_canceled) => Err( | ||||
|                     crate::Error::new_canceled().with(UpgradeExpected(())) | ||||
|                 ), | ||||
|             }, | ||||
|             None => Err(crate::Error::new_user_no_upgrade()), | ||||
|             }), | ||||
|             None => Poll::Ready(Err(crate::Error::new_user_no_upgrade())), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user