Skip to content

Commit d597788

Browse files
committed
feat(server): introduce http3 connections
1 parent 7b03467 commit d597788

File tree

9 files changed

+268
-3
lines changed

9 files changed

+268
-3
lines changed

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ futures-channel = { version = "0.3", optional = true }
3232
futures-core = { version = "0.3.31", optional = true }
3333
futures-util = { version = "0.3", default-features = false, features = ["alloc"], optional = true }
3434
h2 = { version = "0.4.2", optional = true }
35+
h3 = { version = "0.0.8", optional = true }
3536
http-body-util = { version = "0.1", optional = true }
3637
httparse = { version = "1.9", optional = true }
3738
httpdate = { version = "1.0", optional = true }
@@ -69,7 +70,7 @@ tokio-util = "0.7.10"
6970

7071
[features]
7172
# Nothing by default
72-
default = []
73+
default = ["http3", "server"]
7374

7475
# Easily turn it all on
7576
full = [
@@ -82,6 +83,7 @@ full = [
8283
# HTTP versions
8384
http1 = ["dep:atomic-waker", "dep:futures-channel", "dep:futures-core", "dep:httparse", "dep:itoa", "dep:pin-utils"]
8485
http2 = ["dep:futures-channel", "dep:futures-core", "dep:h2"]
86+
http3 = ["dep:h3"]
8587

8688
# Client/Server
8789
client = ["dep:want", "dep:pin-project-lite", "dep:smallvec"]

src/cfg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ macro_rules! cfg_proto {
1515
($($item:item)*) => {
1616
cfg_feature! {
1717
#![all(
18-
any(feature = "http1", feature = "http2"),
18+
any(feature = "http1", feature = "http2", feature = "http3"),
1919
any(feature = "client", feature = "server"),
2020
)]
2121
$($item)*

src/common/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub(crate) mod either;
77
#[cfg(any(
88
all(feature = "client", any(feature = "http1", feature = "http2")),
99
all(feature = "server", feature = "http1"),
10+
all(feature = "server", feature = "http3"),
1011
))]
1112
pub(crate) mod future;
1213
pub(crate) mod io;

src/proto/h3/glue.rs

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
use std::task::{Context, Poll};
2+
3+
use bytes::Buf;
4+
5+
pub(super) struct Conn<Q>(Q);
6+
7+
pub(super) struct BidiStream<S>(S);
8+
pub(super) struct SendStream<S>(S);
9+
pub(super) struct RecvStream<S>(S);
10+
11+
impl<Q, B> h3::quic::Connection<B> for Conn<Q>
12+
where
13+
Q: crate::rt::quic::Connection<B>,
14+
B: Buf,
15+
{
16+
type RecvStream = RecvStream<Q::RecvStream>;
17+
type OpenStreams = Self;
18+
19+
fn poll_accept_recv(&mut self, _cx: &mut Context<'_>)
20+
-> Poll<Result<Self::RecvStream, h3::quic::ConnectionErrorIncoming>>
21+
{
22+
todo!();
23+
}
24+
25+
fn poll_accept_bidi(&mut self, _cx: &mut Context<'_>)
26+
-> Poll<Result<Self::BidiStream, h3::quic::ConnectionErrorIncoming>>
27+
{
28+
todo!();
29+
}
30+
31+
fn opener(&self) -> Self::OpenStreams {
32+
todo!();
33+
}
34+
}
35+
36+
impl<Q, B> h3::quic::OpenStreams<B> for Conn<Q>
37+
where
38+
Q: crate::rt::quic::Connection<B>,
39+
B: Buf,
40+
{
41+
type BidiStream = BidiStream<Q::BidiStream>;
42+
type SendStream = SendStream<Q::SendStream>;
43+
44+
fn poll_open_send(&mut self, _cx: &mut Context<'_>)
45+
-> Poll<Result<Self::SendStream, h3::quic::StreamErrorIncoming>>
46+
{
47+
todo!();
48+
}
49+
50+
fn poll_open_bidi(&mut self, _cx: &mut Context<'_>)
51+
-> Poll<Result<Self::BidiStream, h3::quic::StreamErrorIncoming>>
52+
{
53+
todo!();
54+
}
55+
56+
fn close(&mut self, _: h3::error::Code, _: &[u8]) {
57+
58+
}
59+
}
60+
61+
impl<S, B> h3::quic::SendStream<B> for BidiStream<S>
62+
where
63+
S: crate::rt::quic::SendStream<B>,
64+
B: Buf,
65+
{
66+
// Required methods
67+
fn poll_ready(
68+
&mut self,
69+
cx: &mut Context<'_>,
70+
) -> Poll<Result<(), h3::quic::StreamErrorIncoming>> {
71+
todo!();
72+
}
73+
fn send_data<T: Into<h3::quic::WriteBuf<B>>>(
74+
&mut self,
75+
data: T,
76+
) -> Result<(), h3::quic::StreamErrorIncoming> {
77+
todo!();
78+
}
79+
fn poll_finish(
80+
&mut self,
81+
cx: &mut Context<'_>,
82+
) -> Poll<Result<(), h3::quic::StreamErrorIncoming>> {
83+
todo!();
84+
}
85+
fn reset(&mut self, reset_code: u64) {
86+
todo!();
87+
}
88+
fn send_id(&self) -> h3::quic::StreamId {
89+
todo!()
90+
}
91+
}
92+
93+
impl<S, B> h3::quic::SendStream<B> for SendStream<S>
94+
where
95+
S: crate::rt::quic::SendStream<B>,
96+
B: Buf,
97+
{
98+
// Required methods
99+
fn poll_ready(
100+
&mut self,
101+
cx: &mut Context<'_>,
102+
) -> Poll<Result<(), h3::quic::StreamErrorIncoming>> {
103+
todo!();
104+
}
105+
fn send_data<T: Into<h3::quic::WriteBuf<B>>>(
106+
&mut self,
107+
data: T,
108+
) -> Result<(), h3::quic::StreamErrorIncoming> {
109+
todo!();
110+
}
111+
fn poll_finish(
112+
&mut self,
113+
cx: &mut Context<'_>,
114+
) -> Poll<Result<(), h3::quic::StreamErrorIncoming>> {
115+
todo!();
116+
}
117+
fn reset(&mut self, reset_code: u64) {
118+
todo!();
119+
}
120+
fn send_id(&self) -> h3::quic::StreamId {
121+
todo!()
122+
}
123+
}
124+
125+
impl<S> h3::quic::RecvStream for BidiStream<S>
126+
where
127+
S: crate::rt::quic::RecvStream,
128+
{
129+
type Buf = S::Buf;
130+
131+
// Required methods
132+
fn poll_data(
133+
&mut self,
134+
cx: &mut Context<'_>,
135+
) -> Poll<Result<Option<Self::Buf>, h3::quic::StreamErrorIncoming>> {
136+
todo!();
137+
}
138+
fn stop_sending(&mut self, error_code: u64) {
139+
todo!();
140+
}
141+
fn recv_id(&self) -> h3::quic::StreamId {
142+
todo!();
143+
}
144+
}
145+
146+
impl<S> h3::quic::RecvStream for RecvStream<S>
147+
where
148+
S: crate::rt::quic::RecvStream,
149+
{
150+
type Buf = S::Buf;
151+
152+
// Required methods
153+
fn poll_data(
154+
&mut self,
155+
cx: &mut Context<'_>,
156+
) -> Poll<Result<Option<Self::Buf>, h3::quic::StreamErrorIncoming>> {
157+
todo!();
158+
}
159+
fn stop_sending(&mut self, error_code: u64) {
160+
todo!();
161+
}
162+
fn recv_id(&self) -> h3::quic::StreamId {
163+
todo!();
164+
}
165+
}

src/proto/h3/mod.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use std::future::Future;
2+
use std::pin::Pin;
3+
use std::task::{Context, Poll};
4+
5+
use bytes::Buf;
6+
use h3::server::Connection;
7+
8+
use pin_project_lite::pin_project;
9+
10+
mod glue;
11+
12+
pin_project! {
13+
pub(crate) struct Server<Q, S, B, E>
14+
where
15+
Q: crate::rt::quic::Connection<B>,
16+
B: Buf,
17+
{
18+
exec: E,
19+
q: Connection<glue::Conn<Q>, B>,
20+
s: S,
21+
}
22+
}
23+
24+
impl<Q, S, B, E> Future for Server<Q, S, B, E>
25+
where
26+
Q: crate::rt::quic::Connection<B>,
27+
B: Buf,
28+
{
29+
type Output = crate::Result<()>;
30+
31+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
32+
todo!()
33+
}
34+
}

src/proto/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ cfg_feature! {
1616
#[cfg(feature = "http2")]
1717
pub(crate) mod h2;
1818

19+
#[cfg(feature = "http3")]
20+
pub(crate) mod h3;
21+
1922
/// An Incoming Message head. Includes request/status line, and headers.
2023
#[cfg(feature = "http1")]
2124
#[derive(Debug, Default)]

src/rt/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub mod bounds;
1717
mod io;
1818
mod timer;
1919

20-
#[cfg(hyper_unstable_quic)]
20+
//#[cfg(hyper_unstable_quic)]
2121
#[cfg_attr(docsrs, doc(cfg(hyper_unstable_quic)))]
2222
pub mod quic;
2323

src/server/conn/http3.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//! HTTP/3 Server Connections
2+
3+
use std::error::Error as StdError;
4+
5+
use pin_project_lite::pin_project;
6+
7+
use crate::body::{Body, Incoming as IncomingBody};
8+
use crate::rt::quic;
9+
use crate::service::HttpService;
10+
11+
pin_project! {
12+
/// A Future representing an HTTP/3 connection.
13+
#[must_use = "futures do nothing unless polled"]
14+
pub struct Connection<Q, S, E> {
15+
_i: (Q, S, E),
16+
}
17+
}
18+
19+
/// A configuration builder for HTTP/3 server connections.
20+
///
21+
/// **Note**: The default values of options are *not considered stable*. They
22+
/// are subject to change at any time.
23+
#[derive(Clone, Debug)]
24+
pub struct Builder<E> {
25+
exec: E,
26+
}
27+
28+
// ===== impl Connection =====
29+
30+
// ===== impl Builder =====
31+
32+
impl<E> Builder<E> {
33+
/// Create a new connection builder.
34+
pub fn new(exec: E) -> Self {
35+
Self {
36+
exec,
37+
}
38+
}
39+
40+
/// Bind a connection together with a [`Service`](crate::service::Service).
41+
///
42+
/// This returns a Future that must be polled in order for HTTP to be
43+
/// driven on the connection.
44+
pub fn serve_connection<S, Q, Bd>(&self, quic: Q, service: S) -> Connection<Q, S, E>
45+
where
46+
S: HttpService<IncomingBody, ResBody = Bd>,
47+
S::Error: Into<Box<dyn StdError + Send + Sync>>,
48+
Bd: Body + 'static,
49+
Bd::Error: Into<Box<dyn StdError + Send + Sync>>,
50+
Q: quic::Connection<Bd>,
51+
//E: Http2ServerConnExec<S::Future, Bd>,
52+
E: Clone,
53+
{
54+
Connection {
55+
_i: (quic, service, self.exec.clone()),
56+
}
57+
}
58+
}

src/server/conn/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@
1818
pub mod http1;
1919
#[cfg(feature = "http2")]
2020
pub mod http2;
21+
//#[cfg(feature = "http3")]
22+
pub mod http3;

0 commit comments

Comments
 (0)