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 //! h2 = "0.3"
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 `h2`.
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 `h2` 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 #![doc(html_root_url = "https://docs.rs/h2/0.3.9")]
82 #![deny(missing_debug_implementations, missing_docs)]
83 #![cfg_attr(test, deny(warnings))]
84 
85 macro_rules! proto_err {
86     (conn: $($msg:tt)+) => {
87         tracing::debug!("connection error PROTOCOL_ERROR -- {};", format_args!($($msg)+))
88     };
89     (stream: $($msg:tt)+) => {
90         tracing::debug!("stream error PROTOCOL_ERROR -- {};", format_args!($($msg)+))
91     };
92 }
93 
94 macro_rules! ready {
95     ($e:expr) => {
96         match $e {
97             ::std::task::Poll::Ready(r) => r,
98             ::std::task::Poll::Pending => return ::std::task::Poll::Pending,
99         }
100     };
101 }
102 
103 #[cfg_attr(feature = "unstable", allow(missing_docs))]
104 mod codec;
105 mod error;
106 mod hpack;
107 
108 #[cfg(not(feature = "unstable"))]
109 mod proto;
110 
111 #[cfg(feature = "unstable")]
112 #[allow(missing_docs)]
113 pub mod proto;
114 
115 #[cfg(not(feature = "unstable"))]
116 mod frame;
117 
118 #[cfg(feature = "unstable")]
119 #[allow(missing_docs)]
120 pub mod frame;
121 
122 pub mod client;
123 pub mod ext;
124 pub mod server;
125 mod share;
126 
127 #[cfg(fuzzing)]
128 #[cfg_attr(feature = "unstable", allow(missing_docs))]
129 pub mod fuzz_bridge;
130 
131 pub use crate::error::{Error, Reason};
132 pub use crate::share::{FlowControl, Ping, PingPong, Pong, RecvStream, SendStream, StreamId};
133 
134 #[cfg(feature = "unstable")]
135 pub use codec::{Codec, SendError, UserError};
136 
137 use std::task::Poll;
138 
139 // TODO: Get rid of this trait once https://github.com/rust-lang/rust/pull/63512
140 // is stabilized.
141 trait PollExt<T, E> {
142     /// Changes the success value of this `Poll` with the closure provided.
map_ok_<U, F>(self, f: F) -> Poll<Option<Result<U, E>>> where F: FnOnce(T) -> U143     fn map_ok_<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
144     where
145         F: FnOnce(T) -> U;
146     /// Changes the error value of this `Poll` with the closure provided.
map_err_<U, F>(self, f: F) -> Poll<Option<Result<T, U>>> where F: FnOnce(E) -> U147     fn map_err_<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
148     where
149         F: FnOnce(E) -> U;
150 }
151 
152 impl<T, E> PollExt<T, E> for Poll<Option<Result<T, E>>> {
map_ok_<U, F>(self, f: F) -> Poll<Option<Result<U, E>>> where F: FnOnce(T) -> U,153     fn map_ok_<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
154     where
155         F: FnOnce(T) -> U,
156     {
157         match self {
158             Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
159             Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
160             Poll::Ready(None) => Poll::Ready(None),
161             Poll::Pending => Poll::Pending,
162         }
163     }
164 
map_err_<U, F>(self, f: F) -> Poll<Option<Result<T, U>>> where F: FnOnce(E) -> U,165     fn map_err_<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
166     where
167         F: FnOnce(E) -> U,
168     {
169         match self {
170             Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
171             Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
172             Poll::Ready(None) => Poll::Ready(None),
173             Poll::Pending => Poll::Pending,
174         }
175     }
176 }
177