http2/lib.rs
1//! An asynchronous, HTTP/2 server and client implementation.
2//!
3//! This library implements the [HTTP/2] specification. The implementation is
4//! asynchronous, using [futures] as the basis for the API. The implementation
5//! is also decoupled from TCP or TLS details. The user must handle ALPN and
6//! HTTP/1.1 upgrades themselves.
7//!
8//! # Getting started
9//!
10//! Add the following to your `Cargo.toml` file:
11//!
12//! ```toml
13//! [dependencies]
14//! http2 = "0.4"
15//! ```
16//!
17//! # Layout
18//!
19//! The crate is split into [`client`] and [`server`] modules. Types that are
20//! common to both clients and servers are located at the root of the crate.
21//!
22//! See module level documentation for more details on how to use `http2`.
23//!
24//! # Handshake
25//!
26//! Both the client and the server require a connection to already be in a state
27//! ready to start the HTTP/2 handshake. This library does not provide
28//! facilities to do this.
29//!
30//! There are three ways to reach an appropriate state to start the HTTP/2
31//! handshake.
32//!
33//! * Opening an HTTP/1.1 connection and performing an [upgrade].
34//! * Opening a connection with TLS and use ALPN to negotiate the protocol.
35//! * Open a connection with prior knowledge, i.e. both the client and the
36//! server assume that the connection is immediately ready to start the
37//! HTTP/2 handshake once opened.
38//!
39//! Once the connection is ready to start the HTTP/2 handshake, it can be
40//! passed to [`server::handshake`] or [`client::handshake`]. At this point, the
41//! library will start the handshake process, which consists of:
42//!
43//! * The client sends the connection preface (a predefined sequence of 24
44//! octets).
45//! * Both the client and the server sending a SETTINGS frame.
46//!
47//! See the [Starting HTTP/2] in the specification for more details.
48//!
49//! # Flow control
50//!
51//! [Flow control] is a fundamental feature of HTTP/2. The `http2` library
52//! exposes flow control to the user.
53//!
54//! An HTTP/2 client or server may not send unlimited data to the peer. When a
55//! stream is initiated, both the client and the server are provided with an
56//! initial window size for that stream. A window size is the number of bytes
57//! the endpoint can send to the peer. At any point in time, the peer may
58//! increase this window size by sending a `WINDOW_UPDATE` frame. Once a client
59//! or server has sent data filling the window for a stream, no further data may
60//! be sent on that stream until the peer increases the window.
61//!
62//! There is also a **connection level** window governing data sent across all
63//! streams.
64//!
65//! Managing flow control for inbound data is done through [`FlowControl`].
66//! Managing flow control for outbound data is done through [`SendStream`]. See
67//! the struct level documentation for those two types for more details.
68//!
69//! [HTTP/2]: https://http2.github.io/
70//! [futures]: https://docs.rs/futures/
71//! [`client`]: client/index.html
72//! [`server`]: server/index.html
73//! [Flow control]: http://httpwg.org/specs/rfc7540.html#FlowControl
74//! [`FlowControl`]: struct.FlowControl.html
75//! [`SendStream`]: struct.SendStream.html
76//! [Starting HTTP/2]: http://httpwg.org/specs/rfc7540.html#starting
77//! [upgrade]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism
78//! [`server::handshake`]: server/fn.handshake.html
79//! [`client::handshake`]: client/fn.handshake.html
80
81#![deny(
82 missing_debug_implementations,
83 missing_docs,
84 clippy::missing_safety_doc,
85 clippy::undocumented_unsafe_blocks
86)]
87#![allow(clippy::type_complexity, clippy::manual_range_contains)]
88#![cfg_attr(test, deny(warnings))]
89
90#[macro_use]
91mod macros;
92
93mod tracing;
94
95macro_rules! proto_err {
96 (conn: $($msg:tt)+) => {
97 crate::tracing::debug!("connection error PROTOCOL_ERROR -- {};", format_args!($($msg)+))
98 };
99 (stream: $($msg:tt)+) => {
100 crate::tracing::debug!("stream error PROTOCOL_ERROR -- {};", format_args!($($msg)+))
101 };
102}
103
104macro_rules! ready {
105 ($e:expr) => {
106 match $e {
107 ::std::task::Poll::Ready(r) => r,
108 ::std::task::Poll::Pending => return ::std::task::Poll::Pending,
109 }
110 };
111}
112
113#[cfg_attr(feature = "unstable", allow(missing_docs))]
114mod codec;
115mod error;
116mod hpack;
117
118#[cfg(not(feature = "unstable"))]
119mod proto;
120
121#[cfg(feature = "unstable")]
122#[allow(missing_docs)]
123pub mod proto;
124
125#[cfg(not(feature = "unstable"))]
126mod frame;
127
128#[cfg(feature = "unstable")]
129#[allow(missing_docs)]
130pub mod frame;
131
132pub mod client;
133pub mod ext;
134pub mod server;
135mod share;
136
137#[cfg(fuzzing)]
138#[cfg_attr(feature = "unstable", allow(missing_docs))]
139pub mod fuzz_bridge;
140
141pub use crate::error::{Error, Reason};
142pub use crate::share::{FlowControl, Ping, PingPong, Pong, RecvStream, SendStream, StreamId};
143
144#[cfg(feature = "unstable")]
145pub use codec::{Codec, SendError, UserError};
146
147use std::future::Future;
148use std::pin::Pin;
149use std::task::{Context, Poll};
150
151/// Creates a future from a function that returns `Poll`.
152fn poll_fn<T, F: FnMut(&mut Context<'_>) -> T>(f: F) -> PollFn<F> {
153 PollFn(f)
154}
155
156/// The future created by `poll_fn`.
157struct PollFn<F>(F);
158
159impl<F> Unpin for PollFn<F> {}
160
161impl<T, F: FnMut(&mut Context<'_>) -> Poll<T>> Future for PollFn<F> {
162 type Output = T;
163
164 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
165 (self.0)(cx)
166 }
167}