Skip to content

Commit

Permalink
feat(h2): implement the extended CONNECT protocol from RFC 8441
Browse files Browse the repository at this point in the history
  • Loading branch information
nox committed Nov 3, 2021
1 parent b5022f3 commit 22d4767
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 2 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Expand Up @@ -252,3 +252,6 @@ required-features = ["full"]
name = "server"
path = "tests/server.rs"
required-features = ["full"]

[patch.crates-io]
h2 = { git = "https://github.com/hyperium/h2.git", branch = "rfc8441" }
16 changes: 16 additions & 0 deletions src/client/conn.rs
Expand Up @@ -486,6 +486,22 @@ where
Poll::Ready(Ok(conn.take().unwrap().into_parts()))
})
}

/// Returns whether the [extended CONNECT protocol][1] is enabled or not.
///
/// This setting is configured by the server peer by sending the
/// [`SETTINGS_ENABLE_CONNECT_PROTOCOL` parameter][2] in a `SETTINGS` frame.
/// This method returns the currently acknowledged value recieved from the
/// remote.
///
/// [1]: https://datatracker.ietf.org/doc/html/rfc8441#section-4
/// [2]: https://datatracker.ietf.org/doc/html/rfc8441#section-3
pub fn http2_is_extended_connect_protocol_enabled(&self) -> bool {
match self.inner.as_ref().unwrap() {
ProtoClient::H1 { .. } => false,
ProtoClient::H2 { h2 } => h2.is_extended_connect_protocol_enabled(),
}
}
}

impl<T, B> Future for Connection<T, B>
Expand Down
5 changes: 4 additions & 1 deletion src/ext.rs
@@ -1,10 +1,13 @@
//! HTTP extensions
//! HTTP extensions.

use bytes::Bytes;
#[cfg(feature = "http1")]
use http::header::{HeaderName, IntoHeaderName, ValueIter};
use http::HeaderMap;

#[cfg(feature = "http2")]
pub use h2::ext::Protocol;

/// A map from header names to their original casing as received in an HTTP message.
///
/// If an HTTP/1 response `res` is parsed on a connection whose option
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -76,7 +76,7 @@ mod cfg;
mod common;
pub mod body;
mod error;
mod ext;
pub mod ext;
#[cfg(test)]
mod mock;
pub mod rt;
Expand Down
9 changes: 9 additions & 0 deletions src/proto/h2/client.rs
Expand Up @@ -200,6 +200,15 @@ where
req_rx: ClientRx<B>,
}

impl<B> ClientTask<B>
where
B: HttpBody + 'static,
{
pub(crate) fn is_extended_connect_protocol_enabled(&self) -> bool {
self.h2_tx.is_extended_connect_protocol_enabled()
}
}

impl<B> Future for ClientTask<B>
where
B: HttpBody + Send + 'static,
Expand Down
5 changes: 5 additions & 0 deletions src/proto/h2/server.rs
Expand Up @@ -40,6 +40,7 @@ pub(crate) struct Config {
pub(crate) initial_conn_window_size: u32,
pub(crate) initial_stream_window_size: u32,
pub(crate) max_frame_size: u32,
pub(crate) enable_connect_protocol: bool,
pub(crate) max_concurrent_streams: Option<u32>,
#[cfg(feature = "runtime")]
pub(crate) keep_alive_interval: Option<Duration>,
Expand All @@ -54,6 +55,7 @@ impl Default for Config {
initial_conn_window_size: DEFAULT_CONN_WINDOW,
initial_stream_window_size: DEFAULT_STREAM_WINDOW,
max_frame_size: DEFAULT_MAX_FRAME_SIZE,
enable_connect_protocol: false,
max_concurrent_streams: None,
#[cfg(feature = "runtime")]
keep_alive_interval: None,
Expand Down Expand Up @@ -113,6 +115,9 @@ where
if let Some(max) = config.max_concurrent_streams {
builder.max_concurrent_streams(max);
}
if config.enable_connect_protocol {
builder.enable_connect_protocol();
}
let handshake = builder.handshake(io);

let bdp = if config.adaptive_window {
Expand Down
9 changes: 9 additions & 0 deletions src/server/conn.rs
Expand Up @@ -500,6 +500,15 @@ impl<E> Http<E> {
self
}

/// Enables the [extended CONNECT protocol].
///
/// [extended CONNECT protocol]: https://datatracker.ietf.org/doc/html/rfc8441#section-4
#[cfg(feature = "http2")]
pub fn http2_enable_connect_protocol(&mut self) -> &mut Self {
self.h2_builder.enable_connect_protocol = true;
self
}

/// Set the maximum buffer size for the connection.
///
/// Default is ~400kb.
Expand Down
9 changes: 9 additions & 0 deletions src/server/server.rs
Expand Up @@ -403,6 +403,15 @@ impl<I, E> Builder<I, E> {
self
}

/// Enables the [extended CONNECT protocol].
///
/// [extended CONNECT protocol]: https://datatracker.ietf.org/doc/html/rfc8441#section-4
#[cfg(feature = "http2")]
pub fn http2_enable_connect_protocol(mut self) -> Self {
self.protocol.http2_enable_connect_protocol();
self
}

/// Sets the `Executor` to deal with connection tasks.
///
/// Default is `tokio::spawn`.
Expand Down

0 comments on commit 22d4767

Please sign in to comment.