Line | Count | Source (jump to first uncovered line) |
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.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 `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 | | #![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_rules! proto_err { |
91 | | (conn: $($msg:tt)+) => { |
92 | | tracing::debug!("connection error PROTOCOL_ERROR -- {};", format_args!($($msg)+)) |
93 | | }; |
94 | | (stream: $($msg:tt)+) => { |
95 | | tracing::debug!("stream error PROTOCOL_ERROR -- {};", format_args!($($msg)+)) |
96 | | }; |
97 | | } |
98 | | |
99 | | macro_rules! ready { |
100 | | ($e:expr) => { |
101 | | match $e { |
102 | | ::std::task::Poll::Ready(r) => r, |
103 | | ::std::task::Poll::Pending => return ::std::task::Poll::Pending, |
104 | | } |
105 | | }; |
106 | | } |
107 | | |
108 | | #[cfg_attr(feature = "unstable", allow(missing_docs))] |
109 | | mod codec; |
110 | | mod error; |
111 | | mod hpack; |
112 | | |
113 | | #[cfg(not(feature = "unstable"))] |
114 | | mod proto; |
115 | | |
116 | | #[cfg(feature = "unstable")] |
117 | | #[allow(missing_docs)] |
118 | | pub mod proto; |
119 | | |
120 | | #[cfg(not(feature = "unstable"))] |
121 | | mod frame; |
122 | | |
123 | | #[cfg(feature = "unstable")] |
124 | | #[allow(missing_docs)] |
125 | | pub mod frame; |
126 | | |
127 | | pub mod client; |
128 | | pub mod ext; |
129 | | pub mod server; |
130 | | mod share; |
131 | | |
132 | | #[cfg(fuzzing)] |
133 | | #[cfg_attr(feature = "unstable", allow(missing_docs))] |
134 | | pub mod fuzz_bridge; |
135 | | |
136 | | pub use crate::error::{Error, Reason}; |
137 | | pub use crate::share::{FlowControl, Ping, PingPong, Pong, RecvStream, SendStream, StreamId}; |
138 | | |
139 | | #[cfg(feature = "unstable")] |
140 | | pub use codec::{Codec, SendError, UserError}; |
141 | | |
142 | | use std::future::Future; |
143 | | use std::pin::Pin; |
144 | | use std::task::{Context, Poll}; |
145 | | |
146 | | /// Creates a future from a function that returns `Poll`. |
147 | 0 | fn poll_fn<T, F: FnMut(&mut Context<'_>) -> T>(f: F) -> PollFn<F> { |
148 | 0 | PollFn(f) |
149 | 0 | } |
150 | | |
151 | | /// The future created by `poll_fn`. |
152 | | struct PollFn<F>(F); |
153 | | |
154 | | impl<F> Unpin for PollFn<F> {} |
155 | | |
156 | | impl<T, F: FnMut(&mut Context<'_>) -> Poll<T>> Future for PollFn<F> { |
157 | | type Output = T; |
158 | | |
159 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
160 | 0 | (self.0)(cx) |
161 | 0 | } |
162 | | } |