Start writing API docs (#187)
This focuses mostly on the server module.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//! HTTP2 client side.
|
||||
//! Client implementation of the HTTP/2.0 protocol.
|
||||
use {SendStream, RecvStream, ReleaseCapacity};
|
||||
use codec::{Codec, RecvError, SendError, UserError};
|
||||
use frame::{Headers, Pseudo, Reason, Settings, StreamId};
|
||||
|
||||
88
src/lib.rs
88
src/lib.rs
@@ -1,6 +1,90 @@
|
||||
#![deny(warnings, missing_debug_implementations, missing_docs)]
|
||||
//! An asynchronous, HTTP/2.0 server and client implementation.
|
||||
//!
|
||||
//! This library implements the [HTTP/2.0] specification. The implementation is
|
||||
//! asynchronous, using [futures] as the basis for the API. The implementation
|
||||
//! is also decoupled from TCP or TLS details. The user must handle ALPN and
|
||||
//! HTTP/1.1 upgrades themselves.
|
||||
//!
|
||||
//! # Getting started
|
||||
//!
|
||||
//! Add the following to your `Cargo.toml` file:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! h2 = { git = 'https://github.com/carllerche/h2' } # soon to be on crates.io!
|
||||
//! ```
|
||||
//!
|
||||
//! Next, add this to your crate:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! extern crate h2;
|
||||
//! ```
|
||||
//!
|
||||
//! # Layout
|
||||
//!
|
||||
//! The crate is split into [`client`] and [`server`] modules. Types that are
|
||||
//! common to both clients and servers are located at the root of the crate.
|
||||
//!
|
||||
//! See module level documentation for more details on how to use `h2`.
|
||||
//!
|
||||
//! # Handshake
|
||||
//!
|
||||
//! Both the client and the server require a connection to already be in a state
|
||||
//! ready to start the HTTP/2.0 handshake. This library does not provide
|
||||
//! facilities to do this.
|
||||
//!
|
||||
//! There are three ways to reach an appropriate state to start the HTTP/2.0
|
||||
//! handshake.
|
||||
//!
|
||||
//! * Opening an HTTP/1.1 connection and performing an [upgrade].
|
||||
//! * Opening a connection with TLS and use ALPN to negotiate the protocol.
|
||||
//! * Open a connection with prior knowledge, i.e. both the client and the
|
||||
//! server assume that the connection is immediately ready to start the
|
||||
//! HTTP/2.0 handshake once opened.
|
||||
//!
|
||||
//! Once the connection is ready to start the HTTP/2.0 handshake, it can be
|
||||
//! passed to [`Server::handshake`] or [`Client::handshake`]. At this point, the
|
||||
//! library will start the handshake process, which consists of:
|
||||
//!
|
||||
//! * The client sends the connection preface (a predefined sequence of 24
|
||||
//! octets).
|
||||
//! * Both the client and the server sending a SETTINGS frame.
|
||||
//!
|
||||
//! See the [Starting HTTP/2] in the specification for more details.
|
||||
//!
|
||||
//! # Flow control
|
||||
//!
|
||||
//! [Flow control] is a fundamental feature of HTTP/2.0. The `h2` library
|
||||
//! exposes flow control to the user.
|
||||
//!
|
||||
//! An HTTP/2.0 client or server may not send unlimited data to the peer. When a
|
||||
//! stream is initiated, both the client and the server are provided with an
|
||||
//! initial window size for that stream. A window size is the number of bytes
|
||||
//! the endpoint can send to the peer. At any point in time, the peer may
|
||||
//! increase this window size by sending a `WINDOW_UPDATE` frame. Once a client
|
||||
//! or server has sent data filling the window for a stream, no further data may
|
||||
//! be sent on that stream until the peer increases the window.
|
||||
//!
|
||||
//! There is also a **connection level** window governing data sent across all
|
||||
//! streams.
|
||||
//!
|
||||
//! Managing flow control for inbound data is done through [`ReleaseCapacity`].
|
||||
//! Managing flow control for outbound data is done through [`SendStream`]. See
|
||||
//! the struct level documentation for those two types for more details.
|
||||
//!
|
||||
//! [HTTP/2.0]: https://http2.github.io/
|
||||
//! [futures]: https://docs.rs/futures/
|
||||
//! [`client`]: client/index.html
|
||||
//! [`server`]: server/index.html
|
||||
//! [Flow control]: http://httpwg.org/specs/rfc7540.html#FlowControl
|
||||
//! [`ReleaseCapacity`]: struct.ReleaseCapacity.html
|
||||
//! [`SendStream`]: struct.SendStream.html
|
||||
//! [Starting HTTP/2]: http://httpwg.org/specs/rfc7540.html#starting
|
||||
//! [upgrade]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism
|
||||
//! [`Server::handshake`]: server/struct.Server.html#method.handshake
|
||||
//! [`Client::handshake`]: client/struct.Client.html#method.handshake
|
||||
|
||||
//! HTTP2
|
||||
#![deny(warnings, missing_debug_implementations, missing_docs)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate futures;
|
||||
|
||||
592
src/server.rs
592
src/server.rs
@@ -1,4 +1,128 @@
|
||||
//! HTTP2 server side.
|
||||
//! Server implementation of the HTTP/2.0 protocol.
|
||||
//!
|
||||
//! # Getting started
|
||||
//!
|
||||
//! Running an HTTP/2.0 requires the caller to manage accepting the connections
|
||||
//! as well as getting the connections to a state that is ready to begin the
|
||||
//! HTTP/2.0 handshake. See [here](../index.html#handshake) for more details.
|
||||
//!
|
||||
//! Once a connection is obtained and primed (ALPN negotiation, HTTP/1.1
|
||||
//! upgrade, etc...), the connection handle is passed to [`Server::handshake`],
|
||||
//! which will begin the [HTTP/2.0 handshake]. This returns a future that will
|
||||
//! complete once the handshake is complete and HTTP/2.0 streams may be
|
||||
//! received.
|
||||
//!
|
||||
//! [`Server::handshake`] will use a default configuration. There are a number
|
||||
//! of configuration values that can be set by using a [`Builder`] instead.
|
||||
//!
|
||||
//! # Inbound streams
|
||||
//!
|
||||
//! The [`Server`] instance is used to accept inbound HTTP/2.0 streams. It does
|
||||
//! this by implementing [`futures::Stream`]. When a new stream is received, a
|
||||
//! call to [`Server::poll`] will return `(request, response)`. The `request`
|
||||
//! handle (of type [`http::Request<RecvStream>`]) contains the HTTP request
|
||||
//! head as well as provides a way to receive the inbound data stream and the
|
||||
//! trailers. The `response` handle (of type [`SendStream`]) allows responding
|
||||
//! to the request, stream the response payload, send trailers, and send push
|
||||
//! promises.
|
||||
//!
|
||||
//! The send ([`SendStream`]) and receive ([`RecvStream`]) halves of the stream
|
||||
//! can be operated independently.
|
||||
//!
|
||||
//! # Managing the connection
|
||||
//!
|
||||
//! The [`Server`] instance is used to manage the connection state. The caller
|
||||
//! is required to call either [`Server::poll`] or [`Server::poll_close`] in
|
||||
//! order to advance the connection state. Simply operating on [`SendStream`] or
|
||||
//! [`RecvStream`] will have no effect unless the connection state is advanced.
|
||||
//!
|
||||
//! It is not required to call **both** [`Server::poll`] and
|
||||
//! [`Server::poll_close`]. If the caller is ready to accept a new stream, then
|
||||
//! only [`Server::poll`] should be called. When the caller **does not** want to
|
||||
//! accept a new stream, [`Server::poll_close`] should be called.
|
||||
//!
|
||||
//! The [`Server`] instance should only be dropped once [`Server::poll_close`]
|
||||
//! returns `Ready`. Once [`Server::poll`] returns `Ready(None)`, there will no
|
||||
//! longer be any more inbound streams. At this point, only
|
||||
//! [`Server::poll_close`] should be called.
|
||||
//!
|
||||
//! # Shutting down the server
|
||||
//!
|
||||
//! Graceful shutdown of the server is [not yet
|
||||
//! implemented](https://github.com/carllerche/h2/issues/69).
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! A basic HTTP/2.0 server example that runs over TCP and assumes [prior
|
||||
//! knowledge], i.e. both the client and the server assume that the TCP socket
|
||||
//! will use the HTTP/2.0 protocol without prior negotiation.
|
||||
//!
|
||||
//! ```rust
|
||||
//! extern crate futures;
|
||||
//! extern crate h2;
|
||||
//! extern crate http;
|
||||
//! extern crate tokio_core;
|
||||
//!
|
||||
//! use futures::{Future, Stream};
|
||||
//! # use futures::future::ok;
|
||||
//! use h2::server::Server;
|
||||
//! use http::{Response, StatusCode};
|
||||
//! use tokio_core::reactor;
|
||||
//! use tokio_core::net::TcpListener;
|
||||
//!
|
||||
//! pub fn main () {
|
||||
//! let mut core = reactor::Core::new().unwrap();
|
||||
//! let handle = core.handle();
|
||||
//!
|
||||
//! let addr = "127.0.0.1:5928".parse().unwrap();
|
||||
//! let listener = TcpListener::bind(&addr, &handle).unwrap();
|
||||
//!
|
||||
//! core.run({
|
||||
//! // Accept all incoming TCP connections.
|
||||
//! listener.incoming().for_each(move |(socket, _)| {
|
||||
//! // Spawn a new task to process each connection.
|
||||
//! handle.spawn({
|
||||
//! // Start the HTTP/2.0 connection handshake
|
||||
//! Server::handshake(socket)
|
||||
//! .and_then(|h2| {
|
||||
//! // Accept all inbound HTTP/2.0 streams sent over the
|
||||
//! // connection.
|
||||
//! h2.for_each(|(request, mut respond)| {
|
||||
//! println!("Received request: {:?}", request);
|
||||
//!
|
||||
//! // Build a response with no body
|
||||
//! let response = Response::builder()
|
||||
//! .status(StatusCode::OK)
|
||||
//! .body(())
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! // Send the response back to the client
|
||||
//! respond.send_response(response, true)
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! Ok(())
|
||||
//! })
|
||||
//! })
|
||||
//! .map_err(|e| panic!("unexpected error = {:?}", e))
|
||||
//! });
|
||||
//!
|
||||
//! Ok(())
|
||||
//! })
|
||||
//! # .select(ok(()))
|
||||
//! }).ok().expect("failed to run HTTP/2.0 server");
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! [prior knowledge]: (http://httpwg.org/specs/rfc7540.html#known-http)
|
||||
//! [`Server::handshake`]: struct.Server.html#method.handshake
|
||||
//! [HTTP/2.0 handshake]: http://httpwg.org/specs/rfc7540.html#ConnectionHeader
|
||||
//! [`Builder`]: struct.Builder.html
|
||||
//! [`Server`]: struct.Server.html
|
||||
//! [`Server::poll`]: struct.Server.html#method.poll
|
||||
//! [`Server::poll_close`]: struct.Server.html#method.poll_close
|
||||
//! [`futures::Stream`]: https://docs.rs/futures/0.1/futures/stream/trait.Stream.html
|
||||
//! [`http::Request<RecvStream>`]: ../struct.RecvStream.html
|
||||
//! [`SendStream`]: ../struct.SendStream.html
|
||||
|
||||
use {SendStream, RecvStream, ReleaseCapacity};
|
||||
use codec::{Codec, RecvError};
|
||||
@@ -12,7 +136,20 @@ use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use std::{convert, fmt, mem};
|
||||
use std::time::Duration;
|
||||
|
||||
/// In progress H2 connection binding
|
||||
/// In progress HTTP/2.0 connection handshake future.
|
||||
///
|
||||
/// This type implements `Future`, yielding a `Server` instance once the
|
||||
/// handshake has completed.
|
||||
///
|
||||
/// The handshake is completed once the connection preface is fully received
|
||||
/// from the client **and** the initial settings frame is sent to the client.
|
||||
///
|
||||
/// The handshake future does not wait for the initial settings frame from the
|
||||
/// client.
|
||||
///
|
||||
/// See [module] level docs for more details.
|
||||
///
|
||||
/// [module]: index.html
|
||||
#[must_use = "futures do nothing unless polled"]
|
||||
pub struct Handshake<T, B: IntoBuf = Bytes> {
|
||||
/// The config to pass to Connection::new after handshake succeeds.
|
||||
@@ -21,13 +158,91 @@ pub struct Handshake<T, B: IntoBuf = Bytes> {
|
||||
state: Handshaking<T, B>
|
||||
}
|
||||
|
||||
/// Marker type indicating a client peer
|
||||
/// Accepts inbound HTTP/2.0 streams on a connection.
|
||||
///
|
||||
/// A `Server` is backed by an I/O resource (usually a TCP socket) and
|
||||
/// implements the HTTP/2.0 server logic for that connection. It is responsible
|
||||
/// for receiving inbound streams initiated by the client as well as driving the
|
||||
/// internal state forward.
|
||||
///
|
||||
/// `Server` values are created by calling [`handshake`]. Once a `Server` value
|
||||
/// is obtained, the caller must call [`poll`] or [`poll_close`] in order to
|
||||
/// drive the internal connection state forward.
|
||||
///
|
||||
/// See [module level] documentation for more details
|
||||
///
|
||||
/// [module level]: index.html
|
||||
/// [`handshake`]: struct.Server.html#method.handshake
|
||||
/// [`poll`]: struct.Server.html#method.poll
|
||||
/// [`poll_close`]: struct.Server.html#method.poll_close
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate futures;
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use futures::{Future, Stream};
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T) {
|
||||
/// Server::handshake(my_io)
|
||||
/// .and_then(|server| {
|
||||
/// server.for_each(|(request, respond)| {
|
||||
/// // Process the request and send the response back to the client
|
||||
/// // using `respond`.
|
||||
/// # Ok(())
|
||||
/// })
|
||||
/// })
|
||||
/// # .wait().unwrap();
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
#[must_use = "streams do nothing unless polled"]
|
||||
pub struct Server<T, B: IntoBuf> {
|
||||
connection: Connection<T, Peer, B>,
|
||||
}
|
||||
|
||||
/// Build a Server
|
||||
/// Server factory, which can be used in order to configure the properties of
|
||||
/// the HTTP/2.0 server before it is created.
|
||||
///
|
||||
/// Methods can be changed on it in order to configure it.
|
||||
///
|
||||
/// The server is constructed by calling [`handshake`] and passing the I/O
|
||||
/// handle that will back the HTTP/2.0 server.
|
||||
///
|
||||
/// New instances of `Builder` are obtained via [`Server::builder`].
|
||||
///
|
||||
/// See function level documentation for details on the various server
|
||||
/// configuration settings.
|
||||
///
|
||||
/// [`Server::builder`]: struct.Server.html#method.builder
|
||||
/// [`handshake`]: struct.Builder.html#method.handshake
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let server_fut = Server::builder()
|
||||
/// .initial_window_size(1_000_000)
|
||||
/// .max_concurrent_streams(1000)
|
||||
/// .handshake(my_io);
|
||||
/// # server_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Builder {
|
||||
/// Time to keep locally reset streams around before reaping.
|
||||
@@ -40,10 +255,22 @@ pub struct Builder {
|
||||
settings: Settings,
|
||||
}
|
||||
|
||||
/// Respond to a request
|
||||
/// Respond to a client request.
|
||||
///
|
||||
/// A `Respond` instance is provided when receiving a request and is used to
|
||||
/// send the associated response back to the client. It is also used to
|
||||
/// explicitly reset the stream with a custom reason.
|
||||
///
|
||||
/// Instances of `Respond` are used to send a response or reserve push promises.
|
||||
/// It will also be used to initiate push promises linked with the associated
|
||||
/// stream. This is [not yet
|
||||
/// implemented](https://github.com/carllerche/h2/issues/185).
|
||||
///
|
||||
/// If the `Response` instance is dropped without sending a response, then the
|
||||
/// HTTP/2.0 stream will be reset.
|
||||
///
|
||||
/// See [module] level docs for more details.
|
||||
///
|
||||
/// [module]: index.html
|
||||
#[derive(Debug)]
|
||||
pub struct Respond<B: IntoBuf> {
|
||||
inner: proto::StreamRef<B::Buf>,
|
||||
@@ -81,17 +308,73 @@ impl<T> Server<T, Bytes>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
{
|
||||
/// Bind an H2 server connection.
|
||||
/// Create a new configured HTTP/2.0 server with default configuration
|
||||
/// values backed by `io`.
|
||||
///
|
||||
/// Returns a future which resolves to the connection value once the H2
|
||||
/// handshake has been completed.
|
||||
/// It is expected that `io` already be in an appropriate state to commence
|
||||
/// the [HTTP/2.0 handshake]. See [Handshake] for more details.
|
||||
///
|
||||
/// Returns a future which resolves to the [`Server`] instance once the
|
||||
/// HTTP/2.0 handshake has been completed. The returned [`Server`] instance
|
||||
/// will be using default configuration values. Use [`Builder`] to customize
|
||||
/// the configuration values used by a [`Server`] instance.
|
||||
///
|
||||
/// [HTTP/2.0 handshake]: http://httpwg.org/specs/rfc7540.html#ConnectionHeader
|
||||
/// [Handshake]: ../index.html#handshake
|
||||
/// [`Server`]: struct.Server.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let handshake_fut = Server::handshake(my_io);
|
||||
/// # handshake_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn handshake(io: T) -> Handshake<T, Bytes> {
|
||||
Server::builder().handshake(io)
|
||||
}
|
||||
}
|
||||
|
||||
impl Server<(), Bytes> {
|
||||
/// Create a Server Builder
|
||||
/// Return a new `Server` builder instance initialized with default
|
||||
/// configuration values.
|
||||
///
|
||||
/// Configuration methods can be chained on the return value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let server_fut = Server::builder()
|
||||
/// .initial_window_size(1_000_000)
|
||||
/// .max_concurrent_streams(1000)
|
||||
/// .handshake(my_io);
|
||||
/// # server_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn builder() -> Builder {
|
||||
Builder::default()
|
||||
}
|
||||
@@ -124,16 +407,40 @@ where
|
||||
|
||||
/// Sets the target window size for the whole connection.
|
||||
///
|
||||
/// Default in HTTP2 is 65_535.
|
||||
/// If `size` is greater than the current value, then a `WINDOW_UPDATE`
|
||||
/// frame will be immediately sent to the remote, increasing the connection
|
||||
/// level window by `size - current_value`.
|
||||
///
|
||||
/// If `size` is less than the current value, nothing will happen
|
||||
/// immediately. However, as window capacity is released by
|
||||
/// [`ReleaseCapacity`] instances, no `WINDOW_UPDATE` frames will be sent
|
||||
/// out until the number of "in flight" bytes drops below `size`.
|
||||
///
|
||||
/// The default value is 65,535.
|
||||
///
|
||||
/// See [`ReleaseCapacity`] documentation for more details.
|
||||
///
|
||||
/// [`ReleaseCapacity`]: ../struct.ReleaseCapacity.html
|
||||
/// [library level]: ../index.html#flow-control
|
||||
pub fn set_target_window_size(&mut self, size: u32) {
|
||||
assert!(size <= proto::MAX_WINDOW_SIZE);
|
||||
self.connection.set_target_window_size(size);
|
||||
}
|
||||
|
||||
/// Returns `Ready` when the underlying connection has closed.
|
||||
///
|
||||
/// If any new inbound streams are received during a call to `poll_close`,
|
||||
/// they will be queued and returned on the next call to [`poll`].
|
||||
///
|
||||
/// This function will advance the internal connection state, driving
|
||||
/// progress on all the other handles (e.g. `RecvStream` and `SendStream`).
|
||||
///
|
||||
/// See [here](index.html#managing-the-connection) for more details.
|
||||
///
|
||||
/// [`poll`]: struct.Server.html#method.poll
|
||||
pub fn poll_close(&mut self) -> Poll<(), ::Error> {
|
||||
self.connection.poll().map_err(Into::into)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, B> futures::Stream for Server<T, B>
|
||||
@@ -188,13 +495,77 @@ where
|
||||
// ===== impl Builder =====
|
||||
|
||||
impl Builder {
|
||||
/// Set the initial window size of the remote peer.
|
||||
/// Indicates the initial window size (in octets) for stream-level
|
||||
/// flow control for received data.
|
||||
///
|
||||
/// The initial window of a stream is used as part of flow control. For more
|
||||
/// details, see [`ReleaseCapacity`].
|
||||
///
|
||||
/// The default value is 65,535.
|
||||
///
|
||||
/// [`ReleaseCapacity`]: ../struct.ReleaseCapacity.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let server_fut = Server::builder()
|
||||
/// .initial_window_size(1_000_000)
|
||||
/// .handshake(my_io);
|
||||
/// # server_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn initial_window_size(&mut self, size: u32) -> &mut Self {
|
||||
self.settings.set_initial_window_size(Some(size));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the max frame size of received frames.
|
||||
/// Indicates the size (in octets) of the largest HTTP/2.0 frame payload that the
|
||||
/// configured server is able to accept.
|
||||
///
|
||||
/// The sender may send data frames that are **smaller** than this value,
|
||||
/// but any data larger than `max` will be broken up into multiple `DATA`
|
||||
/// frames.
|
||||
///
|
||||
/// The value **must** be between 16,384 and 16,777,215. The default value is 16,384.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let server_fut = Server::builder()
|
||||
/// .max_frame_size(1_000_000)
|
||||
/// .handshake(my_io);
|
||||
/// # server_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if `max` is not within the legal range specified
|
||||
/// above.
|
||||
pub fn max_frame_size(&mut self, max: u32) -> &mut Self {
|
||||
self.settings.set_max_frame_size(Some(max));
|
||||
self
|
||||
@@ -202,11 +573,49 @@ impl Builder {
|
||||
|
||||
/// Set the maximum number of concurrent streams.
|
||||
///
|
||||
/// Servers can only limit the maximum number of streams that that the
|
||||
/// client can initiate. See [Section 5.1.2] in the HTTP/2 spec for more
|
||||
/// details.
|
||||
/// The maximum concurrent streams setting only controls the maximum number
|
||||
/// of streams that can be initiated by the remote peer. In otherwords, when
|
||||
/// this setting is set to 100, this does not limit the number of concurrent
|
||||
/// streams that can be created by the caller.
|
||||
///
|
||||
/// It is recommended that this value be no smaller than 100, so as to not
|
||||
/// unnecessarily limit parallelism. However, any value is legal, including
|
||||
/// 0. If `max` is set to 0, then the remote will not be permitted to
|
||||
/// initiate streams.
|
||||
///
|
||||
/// Note that streams in the reserved state, i.e., push promises that have
|
||||
/// been reserved but the stream has not started, do not count against this
|
||||
/// setting.
|
||||
///
|
||||
/// Also note that if the remote *does* exceed the value set here, it is not
|
||||
/// a protocol level error. Instead, the `h2` library will immediately reset
|
||||
/// the stream.
|
||||
///
|
||||
/// See [Section 5.1.2] in the HTTP/2.0 spec for more details.
|
||||
///
|
||||
/// [Section 5.1.2]: https://http2.github.io/http2-spec/#rfc.section.5.1.2
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let server_fut = Server::builder()
|
||||
/// .max_concurrent_streams(1000)
|
||||
/// .handshake(my_io);
|
||||
/// # server_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn max_concurrent_streams(&mut self, max: u32) -> &mut Self {
|
||||
self.settings.set_max_concurrent_streams(Some(max));
|
||||
self
|
||||
@@ -214,10 +623,46 @@ impl Builder {
|
||||
|
||||
/// Set the maximum number of concurrent locally reset streams.
|
||||
///
|
||||
/// Locally reset streams are to "ignore frames from the peer for some
|
||||
/// time". While waiting for that time, locally reset streams "waste"
|
||||
/// space in order to be able to ignore those frames. This setting
|
||||
/// can limit how many extra streams are left waiting for "some time".
|
||||
/// When a stream is explicitly reset by either calling
|
||||
/// [`Respond::send_reset`] or by dropping a [`Respond`] instance before
|
||||
/// completing te stream, the HTTP/2.0 specification requires that any
|
||||
/// further frames received for that stream must be ignored for "some time".
|
||||
///
|
||||
/// In order to satisfy the specification, internal state must be maintained
|
||||
/// to implement the behavior. This state grows linearly with the number of
|
||||
/// streams that are locally reset.
|
||||
///
|
||||
/// The `max_concurrent_reset_streams` setting configures sets an upper
|
||||
/// bound on the amount of state that is maintained. When this max value is
|
||||
/// reached, the oldest reset stream is purged from memory.
|
||||
///
|
||||
/// Once the stream has been fully purged from memory, any additional frames
|
||||
/// received for that stream will result in a connection level protocol
|
||||
/// error, forcing the connection to terminate.
|
||||
///
|
||||
/// The default value is 10.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let server_fut = Server::builder()
|
||||
/// .max_concurrent_reset_streams(1000)
|
||||
/// .handshake(my_io);
|
||||
/// # server_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn max_concurrent_reset_streams(&mut self, max: usize) -> &mut Self {
|
||||
self.reset_stream_max = max;
|
||||
self
|
||||
@@ -225,17 +670,112 @@ impl Builder {
|
||||
|
||||
/// Set the maximum number of concurrent locally reset streams.
|
||||
///
|
||||
/// Locally reset streams are to "ignore frames from the peer for some
|
||||
/// time", but that time is unspecified. Set that time with this setting.
|
||||
/// When a stream is explicitly reset by either calling
|
||||
/// [`Respond::send_reset`] or by dropping a [`Respond`] instance before
|
||||
/// completing te stream, the HTTP/2.0 specification requires that any
|
||||
/// further frames received for that stream must be ignored for "some time".
|
||||
///
|
||||
/// In order to satisfy the specification, internal state must be maintained
|
||||
/// to implement the behavior. This state grows linearly with the number of
|
||||
/// streams that are locally reset.
|
||||
///
|
||||
/// The `reset_stream_duration` setting configures the max amount of time
|
||||
/// this state will be maintained in memory. Once the duration elapses, the
|
||||
/// stream state is purged from memory.
|
||||
///
|
||||
/// Once the stream has been fully purged from memory, any additional frames
|
||||
/// received for that stream will result in a connection level protocol
|
||||
/// error, forcing the connection to terminate.
|
||||
///
|
||||
/// The default value is 30 seconds.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// # use std::time::Duration;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let server_fut = Server::builder()
|
||||
/// .reset_stream_duration(Duration::from_secs(10))
|
||||
/// .handshake(my_io);
|
||||
/// # server_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn reset_stream_duration(&mut self, dur: Duration) -> &mut Self {
|
||||
self.reset_stream_duration = dur;
|
||||
self
|
||||
}
|
||||
|
||||
/// Bind an H2 server connection.
|
||||
/// Create a new configured HTTP/2.0 server backed by `io`.
|
||||
///
|
||||
/// Returns a future which resolves to the connection value once the H2
|
||||
/// handshake has been completed.
|
||||
/// It is expected that `io` already be in an appropriate state to commence
|
||||
/// the [HTTP/2.0 handshake]. See [Handshake] for more details.
|
||||
///
|
||||
/// Returns a future which resolves to the [`Server`] instance once the
|
||||
/// HTTP/2.0 handshake has been completed.
|
||||
///
|
||||
/// This function also allows the caller to configure the send payload data
|
||||
/// type. See [Outbound data type] for more details.
|
||||
///
|
||||
/// [HTTP/2.0 handshake]: http://httpwg.org/specs/rfc7540.html#ConnectionHeader
|
||||
/// [Handshake]: ../index.html#handshake
|
||||
/// [`Server`]: struct.Server.html
|
||||
/// [Outbound data type]: ../index.html#outbound-data-type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let handshake_fut = Server::builder()
|
||||
/// .handshake(my_io);
|
||||
/// # handshake_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// Customizing the outbound data type. In this case, the outbound data type
|
||||
/// will be `&'static [u8]`.
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate h2;
|
||||
/// # extern crate tokio_io;
|
||||
/// # use tokio_io::*;
|
||||
/// # use h2::server::*;
|
||||
/// #
|
||||
/// # fn doc<T: AsyncRead + AsyncWrite>(my_io: T)
|
||||
/// # -> Handshake<T, &'static [u8]>
|
||||
/// # {
|
||||
/// // `server_fut` is a future representing the completion of the HTTP/2.0
|
||||
/// // handshake.
|
||||
/// let server_fut: Handshake<_, &'static [u8]> = Server::builder()
|
||||
/// .handshake(my_io);
|
||||
/// # server_fut
|
||||
/// # }
|
||||
/// #
|
||||
/// # pub fn main() {}
|
||||
/// ```
|
||||
pub fn handshake<T, B>(&self, io: T) -> Handshake<T, B>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
|
||||
@@ -26,7 +26,7 @@ pub struct ReleaseCapacity {
|
||||
inner: proto::OpaqueStreamRef,
|
||||
}
|
||||
|
||||
// ===== impl Stream =====
|
||||
// ===== impl SendStream =====
|
||||
|
||||
impl<B: IntoBuf> SendStream<B> {
|
||||
pub(crate) fn new(inner: proto::StreamRef<B::Buf>) -> Self {
|
||||
@@ -68,7 +68,7 @@ impl<B: IntoBuf> SendStream<B> {
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Body =====
|
||||
// ===== impl RecvStream =====
|
||||
|
||||
impl RecvStream {
|
||||
pub(crate) fn new(inner: ReleaseCapacity) -> Self {
|
||||
|
||||
Reference in New Issue
Block a user