Update lib to std-future
This commit is contained in:
committed by
Sean McArthur
parent
782f1f712c
commit
c8fefd49f1
463
src/client.rs
463
src/client.rs
@@ -64,72 +64,60 @@
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```rust, no_run
|
||||
//! #![feature(async_await)]
|
||||
//!
|
||||
//! use h2::client;
|
||||
//!
|
||||
//! use futures::*;
|
||||
//! use http::*;
|
||||
//!
|
||||
//! use http::{Request, Method};
|
||||
//! use std::error::Error;
|
||||
//! use tokio::net::TcpStream;
|
||||
//!
|
||||
//! pub fn main() {
|
||||
//! #[tokio::main]
|
||||
//! pub async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! let addr = "127.0.0.1:5928".parse().unwrap();
|
||||
//!
|
||||
//! // Establish TCP connection to the server.
|
||||
//! let tcp = TcpStream::connect(&addr).await?;
|
||||
//! let (h2, connection) = client::handshake(tcp).await?;
|
||||
//! tokio::spawn(async move {
|
||||
//! connection.await.unwrap();
|
||||
//! });
|
||||
//!
|
||||
//! tokio::run(
|
||||
//! // Establish TCP connection to the server.
|
||||
//! TcpStream::connect(&addr)
|
||||
//! .map_err(|_| {
|
||||
//! panic!("failed to establish TCP connection")
|
||||
//! })
|
||||
//! .and_then(|tcp| client::handshake(tcp))
|
||||
//! .and_then(|(h2, connection)| {
|
||||
//! let connection = connection
|
||||
//! .map_err(|_| panic!("HTTP/2.0 connection failed"));
|
||||
//!
|
||||
//! // Spawn a new task to drive the connection state
|
||||
//! tokio::spawn(connection);
|
||||
//!
|
||||
//! // Wait until the `SendRequest` handle has available
|
||||
//! // capacity.
|
||||
//! h2.ready()
|
||||
//! })
|
||||
//! .and_then(|mut h2| {
|
||||
//! // Prepare the HTTP request to send to the server.
|
||||
//! let request = Request::builder()
|
||||
//! let mut h2 = h2.ready().await?;
|
||||
//! // Prepare the HTTP request to send to the server.
|
||||
//! let request = Request::builder()
|
||||
//! .method(Method::GET)
|
||||
//! .uri("https://www.example.com/")
|
||||
//! .body(())
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! // Send the request. The second tuple item allows the caller
|
||||
//! // to stream a request body.
|
||||
//! let (response, _) = h2.send_request(request, true).unwrap();
|
||||
//! // Send the request. The second tuple item allows the caller
|
||||
//! // to stream a request body.
|
||||
//! let (response, _) = h2.send_request(request, true).unwrap();
|
||||
//!
|
||||
//! let (head, mut body) = response.await?.into_parts();
|
||||
//!
|
||||
//! response.and_then(|response| {
|
||||
//! let (head, mut body) = response.into_parts();
|
||||
//! println!("Received response: {:?}", head);
|
||||
//!
|
||||
//! println!("Received response: {:?}", head);
|
||||
//! // The `release_capacity` handle allows the caller to manage
|
||||
//! // flow control.
|
||||
//! //
|
||||
//! // Whenever data is received, the caller is responsible for
|
||||
//! // releasing capacity back to the server once it has freed
|
||||
//! // the data from memory.
|
||||
//! let mut release_capacity = body.release_capacity().clone();
|
||||
//!
|
||||
//! // The `release_capacity` handle allows the caller to manage
|
||||
//! // flow control.
|
||||
//! //
|
||||
//! // Whenever data is received, the caller is responsible for
|
||||
//! // releasing capacity back to the server once it has freed
|
||||
//! // the data from memory.
|
||||
//! let mut release_capacity = body.release_capacity().clone();
|
||||
//! while let Some(chunk) = body.next().await {
|
||||
//! let chunk = chunk?;
|
||||
//! println!("RX: {:?}", chunk);
|
||||
//!
|
||||
//! body.for_each(move |chunk| {
|
||||
//! println!("RX: {:?}", chunk);
|
||||
//! // Let the server send more data.
|
||||
//! let _ = release_capacity.release_capacity(chunk.len());
|
||||
//! }
|
||||
//!
|
||||
//! // Let the server send more data.
|
||||
//! let _ = release_capacity.release_capacity(chunk.len());
|
||||
//!
|
||||
//! Ok(())
|
||||
//! })
|
||||
//! })
|
||||
//! })
|
||||
//! .map_err(|e| panic!("failed to perform HTTP/2.0 request: {:?}", e))
|
||||
//! )
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
@@ -151,21 +139,23 @@
|
||||
//! [`Builder`]: struct.Builder.html
|
||||
//! [`Error`]: ../struct.Error.html
|
||||
|
||||
use crate::{SendStream, RecvStream, ReleaseCapacity, PingPong};
|
||||
use crate::codec::{Codec, RecvError, SendError, UserError};
|
||||
use crate::frame::{Headers, Pseudo, Reason, Settings, StreamId};
|
||||
use crate::proto;
|
||||
use crate::{PingPong, RecvStream, ReleaseCapacity, SendStream};
|
||||
|
||||
use bytes::{Bytes, IntoBuf};
|
||||
use futures::{Async, Future, Poll, Stream, try_ready};
|
||||
use http::{uri, HeaderMap, Request, Response, Method, Version};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use tokio_io::io::WriteAll;
|
||||
|
||||
use futures::{ready, FutureExt, Stream};
|
||||
use http::{uri, HeaderMap, Method, Request, Response, Version};
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::time::Duration;
|
||||
use std::usize;
|
||||
use tokio_io::{AsyncRead, AsyncWrite, AsyncWriteExt};
|
||||
|
||||
/// Performs the HTTP/2.0 connection handshake.
|
||||
///
|
||||
@@ -182,9 +172,9 @@ use std::usize;
|
||||
///
|
||||
/// [module]: index.html
|
||||
#[must_use = "futures do nothing unless polled"]
|
||||
pub struct Handshake<T, B = Bytes> {
|
||||
pub struct Handshake<'a, T, B = Bytes> {
|
||||
builder: Builder,
|
||||
inner: WriteAll<T, &'static [u8]>,
|
||||
inner: Pin<Box<dyn Future<Output = io::Result<T>> + 'a>>,
|
||||
_marker: PhantomData<fn(B)>,
|
||||
}
|
||||
|
||||
@@ -246,31 +236,20 @@ pub struct ReadySendRequest<B: IntoBuf> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use futures::{Future, Stream};
|
||||
/// # use futures::future::Executor;
|
||||
/// #![feature(async_await)]
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T, E>(my_io: T, my_executor: E)
|
||||
/// # where T: AsyncRead + AsyncWrite + 'static,
|
||||
/// # E: Executor<Box<Future<Item = (), Error = ()>>>,
|
||||
/// # async fn doc<T>(my_io: T)
|
||||
/// # where T: AsyncRead + AsyncWrite + Send + Unpin + 'static,
|
||||
/// # {
|
||||
/// client::handshake(my_io)
|
||||
/// .and_then(|(send_request, connection)| {
|
||||
/// // Submit the connection handle to an executor.
|
||||
/// my_executor.execute(
|
||||
/// # Box::new(
|
||||
/// connection.map_err(|_| panic!("connection failed"))
|
||||
/// # )
|
||||
/// ).unwrap();
|
||||
/// let (send_request, connection) = client::handshake(my_io).await.unwrap();
|
||||
/// // Submit the connection handle to an executor.
|
||||
/// tokio::spawn(async { connection.await.expect("connection failed"); });
|
||||
///
|
||||
/// // Now, use `send_request` to initialize HTTP/2.0 streams.
|
||||
/// // ...
|
||||
/// # drop(send_request);
|
||||
/// # Ok(())
|
||||
/// })
|
||||
/// # .wait().unwrap();
|
||||
/// // Now, use `send_request` to initialize HTTP/2.0 streams.
|
||||
/// // ...
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
@@ -338,8 +317,8 @@ pub struct PushPromises {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -384,23 +363,23 @@ pub(crate) struct Peer;
|
||||
|
||||
impl<B> SendRequest<B>
|
||||
where
|
||||
B: IntoBuf,
|
||||
B::Buf: 'static,
|
||||
B: IntoBuf + Unpin,
|
||||
B::Buf: Unpin + 'static,
|
||||
{
|
||||
/// Returns `Ready` when the connection can initialize a new HTTP/2.0
|
||||
/// stream.
|
||||
///
|
||||
/// This function must return `Ready` before `send_request` is called. When
|
||||
/// `NotReady` is returned, the task will be notified once the readiness
|
||||
/// `Poll::Pending` is returned, the task will be notified once the readiness
|
||||
/// state changes.
|
||||
///
|
||||
/// See [module] level docs for more details.
|
||||
///
|
||||
/// [module]: index.html
|
||||
pub fn poll_ready(&mut self) -> Poll<(), crate::Error> {
|
||||
try_ready!(self.inner.poll_pending_open(self.pending.as_ref()));
|
||||
pub fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), crate::Error>> {
|
||||
ready!(self.inner.poll_pending_open(cx, self.pending.as_ref()))?;
|
||||
self.pending = None;
|
||||
Ok(().into())
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
/// Consumes `self`, returning a future that returns `self` back once it is
|
||||
@@ -415,19 +394,15 @@ where
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use futures::*;
|
||||
/// #![feature(async_await)]
|
||||
/// # use h2::client::*;
|
||||
/// # use http::*;
|
||||
/// # fn doc(send_request: SendRequest<&'static [u8]>)
|
||||
/// # async fn doc(send_request: SendRequest<&'static [u8]>)
|
||||
/// # {
|
||||
/// // First, wait until the `send_request` handle is ready to send a new
|
||||
/// // request
|
||||
/// send_request.ready()
|
||||
/// .and_then(|mut send_request| {
|
||||
/// // Use `send_request` here.
|
||||
/// # Ok(())
|
||||
/// })
|
||||
/// # .wait().unwrap();
|
||||
/// let mut send_request = send_request.ready().await.unwrap();
|
||||
/// // Use `send_request` here.
|
||||
/// # }
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
@@ -479,32 +454,24 @@ where
|
||||
/// Sending a request with no body
|
||||
///
|
||||
/// ```rust
|
||||
/// # use futures::*;
|
||||
/// #![feature(async_await)]
|
||||
/// # use h2::client::*;
|
||||
/// # use http::*;
|
||||
/// # fn doc(send_request: SendRequest<&'static [u8]>)
|
||||
/// # async fn doc(send_request: SendRequest<&'static [u8]>)
|
||||
/// # {
|
||||
/// // First, wait until the `send_request` handle is ready to send a new
|
||||
/// // request
|
||||
/// send_request.ready()
|
||||
/// .and_then(|mut send_request| {
|
||||
/// // Prepare the HTTP request to send to the server.
|
||||
/// let request = Request::get("https://www.example.com/")
|
||||
/// .body(())
|
||||
/// .unwrap();
|
||||
/// let mut send_request = send_request.ready().await.unwrap();
|
||||
/// // Prepare the HTTP request to send to the server.
|
||||
/// let request = Request::get("https://www.example.com/")
|
||||
/// .body(())
|
||||
/// .unwrap();
|
||||
///
|
||||
/// // Send the request to the server. Since we are not sending a
|
||||
/// // body or trailers, we can drop the `SendStream` instance.
|
||||
/// let (response, _) = send_request
|
||||
/// .send_request(request, true).unwrap();
|
||||
///
|
||||
/// response
|
||||
/// })
|
||||
/// .and_then(|response| {
|
||||
/// // Process the response
|
||||
/// # Ok(())
|
||||
/// })
|
||||
/// # .wait().unwrap();
|
||||
/// // Send the request to the server. Since we are not sending a
|
||||
/// // body or trailers, we can drop the `SendStream` instance.
|
||||
/// let (response, _) = send_request.send_request(request, true).unwrap();
|
||||
/// let response = response.await.unwrap();
|
||||
/// // Process the response
|
||||
/// # }
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
@@ -512,48 +479,43 @@ where
|
||||
/// Sending a request with a body and trailers
|
||||
///
|
||||
/// ```rust
|
||||
/// # use futures::*;
|
||||
/// #![feature(async_await)]
|
||||
/// # use h2::client::*;
|
||||
/// # use http::*;
|
||||
/// # fn doc(send_request: SendRequest<&'static [u8]>)
|
||||
/// # async fn doc(send_request: SendRequest<&'static [u8]>)
|
||||
/// # {
|
||||
/// // First, wait until the `send_request` handle is ready to send a new
|
||||
/// // request
|
||||
/// send_request.ready()
|
||||
/// .and_then(|mut send_request| {
|
||||
/// // Prepare the HTTP request to send to the server.
|
||||
/// let request = Request::get("https://www.example.com/")
|
||||
/// .body(())
|
||||
/// .unwrap();
|
||||
/// let mut send_request = send_request.ready().await.unwrap();
|
||||
///
|
||||
/// // Send the request to the server. If we are not sending a
|
||||
/// // body or trailers, we can drop the `SendStream` instance.
|
||||
/// let (response, mut send_stream) = send_request
|
||||
/// .send_request(request, false).unwrap();
|
||||
/// // Prepare the HTTP request to send to the server.
|
||||
/// let request = Request::get("https://www.example.com/")
|
||||
/// .body(())
|
||||
/// .unwrap();
|
||||
///
|
||||
/// // At this point, one option would be to wait for send capacity.
|
||||
/// // Doing so would allow us to not hold data in memory that
|
||||
/// // cannot be sent. However, this is not a requirement, so this
|
||||
/// // example will skip that step. See `SendStream` documentation
|
||||
/// // for more details.
|
||||
/// send_stream.send_data(b"hello", false).unwrap();
|
||||
/// send_stream.send_data(b"world", false).unwrap();
|
||||
/// // Send the request to the server. If we are not sending a
|
||||
/// // body or trailers, we can drop the `SendStream` instance.
|
||||
/// let (response, mut send_stream) = send_request
|
||||
/// .send_request(request, false).unwrap();
|
||||
///
|
||||
/// // Send the trailers.
|
||||
/// let mut trailers = HeaderMap::new();
|
||||
/// trailers.insert(
|
||||
/// header::HeaderName::from_bytes(b"my-trailer").unwrap(),
|
||||
/// header::HeaderValue::from_bytes(b"hello").unwrap());
|
||||
/// // At this point, one option would be to wait for send capacity.
|
||||
/// // Doing so would allow us to not hold data in memory that
|
||||
/// // cannot be sent. However, this is not a requirement, so this
|
||||
/// // example will skip that step. See `SendStream` documentation
|
||||
/// // for more details.
|
||||
/// send_stream.send_data(b"hello", false).unwrap();
|
||||
/// send_stream.send_data(b"world", false).unwrap();
|
||||
///
|
||||
/// send_stream.send_trailers(trailers).unwrap();
|
||||
/// // Send the trailers.
|
||||
/// let mut trailers = HeaderMap::new();
|
||||
/// trailers.insert(
|
||||
/// header::HeaderName::from_bytes(b"my-trailer").unwrap(),
|
||||
/// header::HeaderValue::from_bytes(b"hello").unwrap());
|
||||
///
|
||||
/// response
|
||||
/// })
|
||||
/// .and_then(|response| {
|
||||
/// // Process the response
|
||||
/// # Ok(())
|
||||
/// })
|
||||
/// # .wait().unwrap();
|
||||
/// send_stream.send_trailers(trailers).unwrap();
|
||||
///
|
||||
/// let response = response.await.unwrap();
|
||||
/// // Process the response
|
||||
/// # }
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
@@ -634,21 +596,21 @@ where
|
||||
// ===== impl ReadySendRequest =====
|
||||
|
||||
impl<B> Future for ReadySendRequest<B>
|
||||
where B: IntoBuf,
|
||||
B::Buf: 'static,
|
||||
where
|
||||
B: IntoBuf + Unpin,
|
||||
B::Buf: Unpin + 'static,
|
||||
{
|
||||
type Item = SendRequest<B>;
|
||||
type Error = crate::Error;
|
||||
type Output = Result<SendRequest<B>, crate::Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
match self.inner {
|
||||
Some(ref mut send_request) => {
|
||||
let _ = try_ready!(send_request.poll_ready());
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match &mut self.inner {
|
||||
Some(send_request) => {
|
||||
let _ = ready!(send_request.poll_ready(cx))?;
|
||||
}
|
||||
None => panic!("called `poll` after future completed"),
|
||||
}
|
||||
|
||||
Ok(self.inner.take().unwrap().into())
|
||||
Poll::Ready(Ok(self.inner.take().unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -666,8 +628,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -707,8 +669,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -741,8 +703,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -774,8 +736,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -813,8 +775,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -861,8 +823,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -901,8 +863,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -945,8 +907,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -990,8 +952,8 @@ impl Builder {
|
||||
/// # use h2::client::*;
|
||||
/// # use std::time::Duration;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -1027,8 +989,8 @@ impl Builder {
|
||||
/// # use h2::client::*;
|
||||
/// # use std::time::Duration;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -1081,8 +1043,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -1101,8 +1063,8 @@ impl Builder {
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T, &'static [u8]>
|
||||
/// # fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # -> Handshake<'a, T, &'static [u8]>
|
||||
/// # {
|
||||
/// // `client_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
@@ -1113,11 +1075,11 @@ impl Builder {
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn handshake<T, B>(&self, io: T) -> Handshake<T, B>
|
||||
pub fn handshake<'a, T, B>(&self, io: T) -> Handshake<'a, T, B>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
B: IntoBuf,
|
||||
B::Buf: 'static,
|
||||
T: AsyncRead + AsyncWrite + Unpin + 'a,
|
||||
B: IntoBuf + Unpin,
|
||||
B::Buf: Unpin + 'static,
|
||||
{
|
||||
Connection::handshake2(io, self.clone())
|
||||
}
|
||||
@@ -1149,45 +1111,41 @@ impl Default for Builder {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use futures::*;
|
||||
/// #![feature(async_await)]
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::client;
|
||||
/// # use h2::client::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # async fn doc<'a, T: AsyncRead + AsyncWrite + Unpin + 'a>(my_io: T)
|
||||
/// # {
|
||||
/// client::handshake(my_io)
|
||||
/// .and_then(|(send_request, connection)| {
|
||||
/// // The HTTP/2.0 handshake has completed, now start polling
|
||||
/// // `connection` and use `send_request` to send requests to the
|
||||
/// // server.
|
||||
/// # Ok(())
|
||||
/// })
|
||||
/// # .wait().unwrap();
|
||||
/// let (send_request, connection) = client::handshake(my_io).await.unwrap();
|
||||
/// // The HTTP/2.0 handshake has completed, now start polling
|
||||
/// // `connection` and use `send_request` to send requests to the
|
||||
/// // server.
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn handshake<T>(io: T) -> Handshake<T, Bytes>
|
||||
where T: AsyncRead + AsyncWrite,
|
||||
pub fn handshake<'a, T>(io: T) -> Handshake<'a, T, Bytes>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin + 'a,
|
||||
{
|
||||
Builder::new().handshake(io)
|
||||
}
|
||||
|
||||
// ===== impl Connection =====
|
||||
|
||||
impl<T, B> Connection<T, B>
|
||||
impl<'a, T, B> Connection<T, B>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
B: IntoBuf,
|
||||
T: AsyncRead + AsyncWrite + Unpin + 'a,
|
||||
B: IntoBuf + Unpin,
|
||||
B::Buf: Unpin,
|
||||
{
|
||||
fn handshake2(io: T, builder: Builder) -> Handshake<T, B> {
|
||||
use tokio_io::io;
|
||||
|
||||
fn handshake2(mut io: T, builder: Builder) -> Handshake<'a, T, B> {
|
||||
log::debug!("binding client connection");
|
||||
|
||||
let msg: &'static [u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
|
||||
let handshake = io::write_all(io, msg);
|
||||
let handshake = Box::pin(async move { io.write_all(msg).await.map(|_| io) });
|
||||
|
||||
Handshake {
|
||||
builder,
|
||||
@@ -1224,23 +1182,21 @@ where
|
||||
///
|
||||
/// This may only be called once. Calling multiple times will return `None`.
|
||||
pub fn ping_pong(&mut self) -> Option<PingPong> {
|
||||
self.inner
|
||||
.take_user_pings()
|
||||
.map(PingPong::new)
|
||||
self.inner.take_user_pings().map(PingPong::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, B> Future for Connection<T, B>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
B: IntoBuf,
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
B: IntoBuf + Unpin,
|
||||
B::Buf: Unpin,
|
||||
{
|
||||
type Item = ();
|
||||
type Error = crate::Error;
|
||||
type Output = Result<(), crate::Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<(), crate::Error> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.inner.maybe_close_connection_if_no_streams();
|
||||
self.inner.poll().map_err(Into::into)
|
||||
self.inner.poll(cx).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1258,20 +1214,16 @@ where
|
||||
|
||||
// ===== impl Handshake =====
|
||||
|
||||
impl<T, B> Future for Handshake<T, B>
|
||||
impl<'a, T, B> Future for Handshake<'_, T, B>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
B: IntoBuf,
|
||||
B::Buf: 'static,
|
||||
T: AsyncRead + AsyncWrite + Unpin + 'a,
|
||||
B: IntoBuf + Unpin,
|
||||
B::Buf: Unpin + 'static,
|
||||
{
|
||||
type Item = (SendRequest<B>, Connection<T, B>);
|
||||
type Error = crate::Error;
|
||||
type Output = Result<(SendRequest<B>, Connection<T, B>), crate::Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
let res = self.inner.poll()
|
||||
.map_err(crate::Error::from);
|
||||
|
||||
let (io, _) = try_ready!(res);
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let io = ready!(self.inner.poll_unpin(cx))?;
|
||||
|
||||
log::debug!("client connection bound");
|
||||
|
||||
@@ -1291,13 +1243,16 @@ where
|
||||
.buffer(self.builder.settings.clone().into())
|
||||
.expect("invalid SETTINGS frame");
|
||||
|
||||
let inner = proto::Connection::new(codec, proto::Config {
|
||||
next_stream_id: self.builder.stream_id,
|
||||
initial_max_send_streams: self.builder.initial_max_send_streams,
|
||||
reset_stream_duration: self.builder.reset_stream_duration,
|
||||
reset_stream_max: self.builder.reset_stream_max,
|
||||
settings: self.builder.settings.clone(),
|
||||
});
|
||||
let inner = proto::Connection::new(
|
||||
codec,
|
||||
proto::Config {
|
||||
next_stream_id: self.builder.stream_id,
|
||||
initial_max_send_streams: self.builder.initial_max_send_streams,
|
||||
reset_stream_duration: self.builder.reset_stream_duration,
|
||||
reset_stream_max: self.builder.reset_stream_max,
|
||||
settings: self.builder.settings.clone(),
|
||||
},
|
||||
);
|
||||
let send_request = SendRequest {
|
||||
inner: inner.streams().clone(),
|
||||
pending: None,
|
||||
@@ -1308,11 +1263,11 @@ where
|
||||
connection.set_target_window_size(sz);
|
||||
}
|
||||
|
||||
Ok(Async::Ready((send_request, connection)))
|
||||
Poll::Ready(Ok((send_request, connection)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, B> fmt::Debug for Handshake<T, B>
|
||||
impl<T, B> fmt::Debug for Handshake<'_, T, B>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
T: fmt::Debug,
|
||||
@@ -1327,14 +1282,13 @@ where
|
||||
// ===== impl ResponseFuture =====
|
||||
|
||||
impl Future for ResponseFuture {
|
||||
type Item = Response<RecvStream>;
|
||||
type Error = crate::Error;
|
||||
type Output = Result<Response<RecvStream>, crate::Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
let (parts, _) = try_ready!(self.inner.poll_response()).into_parts();
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let (parts, _) = ready!(self.inner.poll_response(cx))?.into_parts();
|
||||
let body = RecvStream::new(ReleaseCapacity::new(self.inner.clone()));
|
||||
|
||||
Ok(Response::from_parts(parts, body).into())
|
||||
Poll::Ready(Ok(Response::from_parts(parts, body).into()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1358,27 +1312,31 @@ impl ResponseFuture {
|
||||
panic!("Reference to push promises stream taken!");
|
||||
}
|
||||
self.push_promise_consumed = true;
|
||||
PushPromises { inner: self.inner.clone() }
|
||||
PushPromises {
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl PushPromises =====
|
||||
|
||||
impl Stream for PushPromises {
|
||||
type Item = PushPromise;
|
||||
type Error = crate::Error;
|
||||
type Item = Result<PushPromise, crate::Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
match try_ready!(self.inner.poll_pushed()) {
|
||||
Some((request, response)) => {
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
match self.inner.poll_pushed(cx) {
|
||||
Poll::Ready(Some(Ok((request, response)))) => {
|
||||
let response = PushedResponseFuture {
|
||||
inner: ResponseFuture {
|
||||
inner: response, push_promise_consumed: false
|
||||
}
|
||||
inner: response,
|
||||
push_promise_consumed: false,
|
||||
},
|
||||
};
|
||||
Ok(Async::Ready(Some(PushPromise{request, response})))
|
||||
Poll::Ready(Some(Ok(PushPromise { request, response })))
|
||||
}
|
||||
None => Ok(Async::Ready(None)),
|
||||
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e.into()))),
|
||||
Poll::Ready(None) => Poll::Ready(None),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1406,11 +1364,10 @@ impl PushPromise {
|
||||
// ===== impl PushedResponseFuture =====
|
||||
|
||||
impl Future for PushedResponseFuture {
|
||||
type Item = Response<RecvStream>;
|
||||
type Error = crate::Error;
|
||||
type Output = Result<Response<RecvStream>, crate::Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
self.inner.poll()
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.inner.poll_unpin(cx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1431,8 +1388,8 @@ impl Peer {
|
||||
pub fn convert_send_message(
|
||||
id: StreamId,
|
||||
request: Request<()>,
|
||||
end_of_stream: bool) -> Result<Headers, SendError>
|
||||
{
|
||||
end_of_stream: bool,
|
||||
) -> Result<Headers, SendError> {
|
||||
use http::request::Parts;
|
||||
|
||||
let (
|
||||
@@ -1503,7 +1460,9 @@ impl proto::Peer for Peer {
|
||||
}
|
||||
|
||||
fn convert_poll_message(
|
||||
pseudo: Pseudo, fields: HeaderMap, stream_id: StreamId
|
||||
pseudo: Pseudo,
|
||||
fields: HeaderMap,
|
||||
stream_id: StreamId,
|
||||
) -> Result<Self::Poll, RecvError> {
|
||||
let mut b = Response::builder();
|
||||
|
||||
@@ -1522,7 +1481,7 @@ impl proto::Peer for Peer {
|
||||
id: stream_id,
|
||||
reason: Reason::PROTOCOL_ERROR,
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
*response.headers_mut() = fields;
|
||||
|
||||
Reference in New Issue
Block a user