Coverage Report

Created: 2025-08-28 07:05

/src/h2/src/lib.rs
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
}