From 7b84faa213a7bbd440c8d252e94f0a2f30236401 Mon Sep 17 00:00:00 2001 From: ruben Date: Sat, 17 Jun 2023 18:44:36 +0200 Subject: [PATCH 1/7] move datagram to separate crate --- Cargo.toml | 1 + examples/Cargo.toml | 1 + examples/webtransport_server.rs | 5 +- h3-datagram/Cargo.toml | 9 ++++ h3-datagram/readme.md | 8 +++ h3-datagram/src/datagram.rs | 69 ++++++++++++++++++++++++++ h3-datagram/src/datagram_traits.rs | 21 ++++++++ h3-datagram/src/lib.rs | 4 ++ h3-datagram/src/quic_traits.rs | 38 +++++++++++++++ h3-datagram/src/server.rs | 78 ++++++++++++++++++++++++++++++ h3-quinn/Cargo.toml | 1 + h3-quinn/src/lib.rs | 10 ++-- h3-webtransport/Cargo.toml | 1 + h3-webtransport/src/server.rs | 12 ++++- h3/src/error.rs | 4 +- h3/src/ext.rs | 76 ----------------------------- h3/src/proto/stream.rs | 3 +- h3/src/quic.rs | 28 ----------- h3/src/server.rs | 65 +------------------------ 19 files changed, 256 insertions(+), 178 deletions(-) create mode 100644 h3-datagram/Cargo.toml create mode 100644 h3-datagram/readme.md create mode 100644 h3-datagram/src/datagram.rs create mode 100644 h3-datagram/src/datagram_traits.rs create mode 100644 h3-datagram/src/lib.rs create mode 100644 h3-datagram/src/quic_traits.rs create mode 100644 h3-datagram/src/server.rs diff --git a/Cargo.toml b/Cargo.toml index 93763f5b..f59a50d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "h3", "h3-quinn", "h3-webtransport", + "h3-datagram", # Internal "examples", diff --git a/examples/Cargo.toml b/examples/Cargo.toml index e1900860..fdf6ede0 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -35,6 +35,7 @@ tracing-subscriber = { version = "0.3", default-features = false, features = [ octets = "0.2.0" tracing-tree = { version = "0.2" } +h3-datagram = { path = "../h3-datagram" } [features] tree = [] diff --git a/examples/webtransport_server.rs b/examples/webtransport_server.rs index 58d4ba43..9c32d090 100644 --- a/examples/webtransport_server.rs +++ b/examples/webtransport_server.rs @@ -3,9 +3,10 @@ use bytes::{BufMut, Bytes, BytesMut}; use h3::{ error::ErrorLevel, ext::Protocol, - quic::{self, RecvDatagramExt, SendDatagramExt, SendStreamUnframed}, + quic::{self, SendStreamUnframed}, server::Connection, }; +use h3_datagram::quic_traits::{RecvDatagramExt, SendDatagramExt}; use h3_quinn::quinn; use h3_webtransport::{ server::{self, WebTransportSession}, @@ -294,6 +295,8 @@ where stream::SendStream: AsyncWrite, C::BidiStream: SendStreamUnframed, C::SendStream: SendStreamUnframed, + ::Error: h3::quic::Error, + >::Error: h3::quic::Error, { let session_id = session.session_id(); diff --git a/h3-datagram/Cargo.toml b/h3-datagram/Cargo.toml new file mode 100644 index 00000000..60e0a987 --- /dev/null +++ b/h3-datagram/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "h3-datagram" +version = "0.0.1" +edition = "2021" + +[dependencies] +h3 = { path = "../h3" } +bytes = "1.4" +pin-project-lite = { version = "0.2", default_features = false } diff --git a/h3-datagram/readme.md b/h3-datagram/readme.md new file mode 100644 index 00000000..ae01ab82 --- /dev/null +++ b/h3-datagram/readme.md @@ -0,0 +1,8 @@ +# H3 Datagram + +this crate provides an implementation of the [h3-datagram](https://datatracker.ietf.org/doc/html/rfc9297) spec that works with the h3 crate. + +## Usage +As stated in the [rfc](https://datatracker.ietf.org/doc/html/rfc9297#abstract) this is intended to be used for protocol extensions like [Web-Transport](https://datatracker.ietf.org/doc/draft-ietf-webtrans-http3/) and not directly by applications. + +> HTTP Datagrams and the Capsule Protocol are intended for use by HTTP extensions, not applications. \ No newline at end of file diff --git a/h3-datagram/src/datagram.rs b/h3-datagram/src/datagram.rs new file mode 100644 index 00000000..f4b2823f --- /dev/null +++ b/h3-datagram/src/datagram.rs @@ -0,0 +1,69 @@ +use bytes::{Buf, Bytes}; +use h3::{error::Code, proto::varint::VarInt, quic::StreamId, Error}; + +/// HTTP datagram frames +/// See: +pub struct Datagram { + /// Stream id divided by 4 + stream_id: StreamId, + /// The data contained in the datagram + payload: B, +} + +impl Datagram +where + B: Buf, +{ + /// Creates a new datagram frame + pub fn new(stream_id: StreamId, payload: B) -> Self { + assert!( + stream_id.into_inner() % 4 == 0, + "StreamId is not divisible by 4" + ); + Self { stream_id, payload } + } + + /// Decodes a datagram frame from the QUIC datagram + pub fn decode(mut buf: B) -> Result { + let q_stream_id = VarInt::decode(&mut buf) + .map_err(|_| Code::H3_DATAGRAM_ERROR.with_cause("Malformed datagram frame"))?; + + //= https://www.rfc-editor.org/rfc/rfc9297#section-2.1 + // Quarter Stream ID: A variable-length integer that contains the value of the client-initiated bidirectional + // stream that this datagram is associated with divided by four (the division by four stems + // from the fact that HTTP requests are sent on client-initiated bidirectional streams, + // which have stream IDs that are divisible by four). The largest legal QUIC stream ID + // value is 262-1, so the largest legal value of the Quarter Stream ID field is 260-1. + // Receipt of an HTTP/3 Datagram that includes a larger value MUST be treated as an HTTP/3 + // connection error of type H3_DATAGRAM_ERROR (0x33). + let stream_id = StreamId::try_from(u64::from(q_stream_id) * 4) + .map_err(|_| Code::H3_DATAGRAM_ERROR.with_cause("Invalid stream id"))?; + + let payload = buf; + + Ok(Self { stream_id, payload }) + } + + #[inline] + /// Returns the associated stream id of the datagram + pub fn stream_id(&self) -> StreamId { + self.stream_id + } + + #[inline] + /// Returns the datagram payload + pub fn payload(&self) -> &B { + &self.payload + } + + /// Encode the datagram to wire format + pub fn encode(self, buf: &mut D) { + (VarInt::from(self.stream_id) / 4).encode(buf); + buf.put(self.payload); + } + + /// Returns the datagram payload + pub fn into_payload(self) -> B { + self.payload + } +} diff --git a/h3-datagram/src/datagram_traits.rs b/h3-datagram/src/datagram_traits.rs new file mode 100644 index 00000000..c9474ac2 --- /dev/null +++ b/h3-datagram/src/datagram_traits.rs @@ -0,0 +1,21 @@ +//! Traits which define the user API for datagrams. +//! These traits are implemented for the client and server types in the `h3` crate. + +use bytes::Buf; +use h3::{ + quic::{self, StreamId}, + Error, +}; + +use crate::server::ReadDatagram; + +pub trait HandleDatagrams +where + B: Buf, + C: quic::Connection, +{ + /// Sends a datagram + fn send_datagram(&mut self, stream_id: StreamId, data: B) -> Result<(), Error>; + /// Reads an incoming datagram + fn read_datagram(&mut self) -> ReadDatagram; +} diff --git a/h3-datagram/src/lib.rs b/h3-datagram/src/lib.rs new file mode 100644 index 00000000..9c0e1fca --- /dev/null +++ b/h3-datagram/src/lib.rs @@ -0,0 +1,4 @@ +pub mod datagram; +pub mod datagram_traits; +pub mod quic_traits; +pub mod server; diff --git a/h3-datagram/src/quic_traits.rs b/h3-datagram/src/quic_traits.rs new file mode 100644 index 00000000..a1f6ca9e --- /dev/null +++ b/h3-datagram/src/quic_traits.rs @@ -0,0 +1,38 @@ +//! QUIC Transport traits +//! +//! This module includes traits and types meant to allow being generic over any +//! QUIC implementation. + +use core::task; +use std::{error::Error, task::Poll}; + +use bytes::Buf; + +use crate::datagram::Datagram; + +/// Extends the `Connection` trait for sending datagrams +/// +/// See: +pub trait SendDatagramExt { + /// The error type that can occur when sending a datagram + type Error: Into>; + + /// Send a datagram + fn send_datagram(&mut self, data: Datagram) -> Result<(), Self::Error>; +} + +/// Extends the `Connection` trait for receiving datagrams +/// +/// See: +pub trait RecvDatagramExt { + /// The type of `Buf` for *raw* datagrams (without the stream_id decoded) + type Buf: Buf; + /// The error type that can occur when receiving a datagram + type Error: Into>; + + /// Poll the connection for incoming datagrams. + fn poll_accept_datagram( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll, Self::Error>>; +} diff --git a/h3-datagram/src/server.rs b/h3-datagram/src/server.rs new file mode 100644 index 00000000..cc7f0e04 --- /dev/null +++ b/h3-datagram/src/server.rs @@ -0,0 +1,78 @@ +//! server API + +use std::{ + future::Future, + marker::PhantomData, + task::{ready, Context, Poll}, +}; + +use bytes::Buf; +use h3::{ + quic::{self, StreamId}, + server::Connection, + Error, +}; +use pin_project_lite::pin_project; + +use crate::{ + datagram::Datagram, + datagram_traits::HandleDatagrams, + quic_traits::{self, RecvDatagramExt, SendDatagramExt}, +}; + +impl HandleDatagrams for Connection +where + B: Buf, + C: quic::Connection + SendDatagramExt + RecvDatagramExt, + ::Error: h3::quic::Error + 'static, + >::Error: h3::quic::Error + 'static, +{ + /// Sends a datagram + fn send_datagram(&mut self, stream_id: StreamId, data: B) -> Result<(), Error> { + self.inner + .conn + .send_datagram(Datagram::new(stream_id, data))?; + //Todo Import tracing + //tracing::info!("Sent datagram"); + + Ok(()) + } + + /// Reads an incoming datagram + fn read_datagram(&mut self) -> ReadDatagram { + ReadDatagram { + conn: self, + _marker: PhantomData, + } + } +} + +pin_project! { + /// Future for [`Connection::read_datagram`] + pub struct ReadDatagram<'a, C, B> + where + C: quic::Connection, + B: Buf, + { + conn: &'a mut Connection, + _marker: PhantomData, + } +} + +impl<'a, C, B> Future for ReadDatagram<'a, C, B> +where + C: quic::Connection + RecvDatagramExt, + ::Error: h3::quic::Error + 'static, + B: Buf, +{ + type Output = Result>, Error>; + + fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + //Todo Import tracing + // tracing::trace!("poll: read_datagram"); + match ready!(self.conn.inner.conn.poll_accept_datagram(cx))? { + Some(v) => Poll::Ready(Ok(Some(Datagram::decode(v)?))), + None => Poll::Ready(Ok(None)), + } + } +} diff --git a/h3-quinn/Cargo.toml b/h3-quinn/Cargo.toml index c0b2291f..cf85fc49 100644 --- a/h3-quinn/Cargo.toml +++ b/h3-quinn/Cargo.toml @@ -22,3 +22,4 @@ quinn-proto = { version = "0.10", default-features = false } tokio-util = { version = "0.7.7" } futures = { version = "0.3.27" } tokio = { version = "1.28", features = ["io-util"], default-features = false } +h3-datagram = { path = "../h3-datagram" } \ No newline at end of file diff --git a/h3-quinn/src/lib.rs b/h3-quinn/src/lib.rs index 54c39f04..1992edd5 100644 --- a/h3-quinn/src/lib.rs +++ b/h3-quinn/src/lib.rs @@ -19,15 +19,13 @@ use futures::{ stream::{self, BoxStream}, StreamExt, }; +use h3_datagram::{datagram::Datagram, quic_traits}; use quinn::ReadDatagram; pub use quinn::{ self, crypto::Session, AcceptBi, AcceptUni, Endpoint, OpenBi, OpenUni, VarInt, WriteError, }; -use h3::{ - ext::Datagram, - quic::{self, Error, StreamId, WriteBuf}, -}; +use h3::quic::{self, Error, StreamId, WriteBuf}; use tokio_util::sync::ReusableBoxFuture; /// A QUIC connection backed by Quinn @@ -233,7 +231,7 @@ where } } -impl quic::SendDatagramExt for Connection +impl quic_traits::SendDatagramExt for Connection where B: Buf, { @@ -249,7 +247,7 @@ where } } -impl quic::RecvDatagramExt for Connection { +impl quic_traits::RecvDatagramExt for Connection { type Buf = Bytes; type Error = ConnectionError; diff --git a/h3-webtransport/Cargo.toml b/h3-webtransport/Cargo.toml index c4901844..d5ee2c43 100644 --- a/h3-webtransport/Cargo.toml +++ b/h3-webtransport/Cargo.toml @@ -12,6 +12,7 @@ http = "0.2.9" pin-project-lite = { version = "0.2", default_features = false } tracing = "0.1.37" tokio = { version = "1.28", default_features = false } +h3-datagram = { path = "../h3-datagram" } [dependencies.h3] version = "0.0.2" diff --git a/h3-webtransport/src/server.rs b/h3-webtransport/src/server.rs index fd24ed4d..0d167d3c 100644 --- a/h3-webtransport/src/server.rs +++ b/h3-webtransport/src/server.rs @@ -12,10 +12,10 @@ use futures_util::{future::poll_fn, ready, Future}; use h3::{ connection::ConnectionState, error::{Code, ErrorLevel}, - ext::{Datagram, Protocol}, + ext::Protocol, frame::FrameStream, proto::frame::Frame, - quic::{self, OpenStreams, RecvDatagramExt, SendDatagramExt, WriteBuf}, + quic::{self, OpenStreams, WriteBuf}, server::{self, Connection, RequestStream}, Error, }; @@ -23,6 +23,11 @@ use h3::{ quic::SendStreamUnframed, stream::{BidiStreamHeader, BufRecvStream, UniStreamHeader}, }; +use h3_datagram::{ + datagram::Datagram, + datagram_traits::HandleDatagrams, + quic_traits::{RecvDatagramExt, SendDatagramExt}, +}; use http::{Method, Request, Response, StatusCode}; use h3::webtransport::SessionId; @@ -38,6 +43,7 @@ use crate::stream::{BidiStream, RecvStream, SendStream}; pub struct WebTransportSession where C: quic::Connection, + Connection: HandleDatagrams, B: Buf, { // See: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3/#section-2-3 @@ -50,6 +56,7 @@ where impl WebTransportSession where + Connection: HandleDatagrams, C: quic::Connection, B: Buf, { @@ -373,6 +380,7 @@ impl<'a, C, B> Future for ReadDatagram<'a, C, B> where C: quic::Connection + RecvDatagramExt, B: Buf, + ::Error: h3::quic::Error + 'static, { type Output = Result, Error>; diff --git a/h3/src/error.rs b/h3/src/error.rs index b622262c..9a10501c 100644 --- a/h3/src/error.rs +++ b/h3/src/error.rs @@ -200,7 +200,9 @@ impl Code { }) } - pub(crate) fn with_cause>(self, cause: E) -> Error { + // Todo: public? private? + #[doc(hidden)] + pub fn with_cause>(self, cause: E) -> Error { Error::from(self).with_cause(cause) } diff --git a/h3/src/ext.rs b/h3/src/ext.rs index 9c42f441..0ef10bce 100644 --- a/h3/src/ext.rs +++ b/h3/src/ext.rs @@ -1,16 +1,7 @@ //! Extensions for the HTTP/3 protocol. -use std::convert::TryFrom; use std::str::FromStr; -use bytes::{Buf, Bytes}; - -use crate::{ - error::Code, - proto::{stream::StreamId, varint::VarInt}, - Error, -}; - /// Describes the `:protocol` pseudo-header for extended connect /// /// See: @@ -40,70 +31,3 @@ impl FromStr for Protocol { } } } - -/// HTTP datagram frames -/// See: -pub struct Datagram { - /// Stream id divided by 4 - stream_id: StreamId, - /// The data contained in the datagram - payload: B, -} - -impl Datagram -where - B: Buf, -{ - /// Creates a new datagram frame - pub fn new(stream_id: StreamId, payload: B) -> Self { - assert!( - stream_id.into_inner() % 4 == 0, - "StreamId is not divisible by 4" - ); - Self { stream_id, payload } - } - - /// Decodes a datagram frame from the QUIC datagram - pub fn decode(mut buf: B) -> Result { - let q_stream_id = VarInt::decode(&mut buf) - .map_err(|_| Code::H3_DATAGRAM_ERROR.with_cause("Malformed datagram frame"))?; - - //= https://www.rfc-editor.org/rfc/rfc9297#section-2.1 - // Quarter Stream ID: A variable-length integer that contains the value of the client-initiated bidirectional - // stream that this datagram is associated with divided by four (the division by four stems - // from the fact that HTTP requests are sent on client-initiated bidirectional streams, - // which have stream IDs that are divisible by four). The largest legal QUIC stream ID - // value is 262-1, so the largest legal value of the Quarter Stream ID field is 260-1. - // Receipt of an HTTP/3 Datagram that includes a larger value MUST be treated as an HTTP/3 - // connection error of type H3_DATAGRAM_ERROR (0x33). - let stream_id = StreamId::try_from(u64::from(q_stream_id) * 4) - .map_err(|_| Code::H3_DATAGRAM_ERROR.with_cause("Invalid stream id"))?; - - let payload = buf; - - Ok(Self { stream_id, payload }) - } - - #[inline] - /// Returns the associated stream id of the datagram - pub fn stream_id(&self) -> StreamId { - self.stream_id - } - - #[inline] - /// Returns the datagram payload - pub fn payload(&self) -> &B { - &self.payload - } - - /// Encode the datagram to wire format - pub fn encode(self, buf: &mut D) { - (VarInt::from(self.stream_id) / 4).encode(buf); - buf.put(self.payload); - } - - /// Returns the datagram payload - pub fn into_payload(self) -> B { - self.payload - } -} diff --git a/h3/src/proto/stream.rs b/h3/src/proto/stream.rs index 2d525167..456f895a 100644 --- a/h3/src/proto/stream.rs +++ b/h3/src/proto/stream.rs @@ -134,7 +134,8 @@ impl StreamId { } } - pub(crate) fn into_inner(self) -> u64 { + // TODO: pub? better option? + pub fn into_inner(self) -> u64 { self.0 } } diff --git a/h3/src/quic.rs b/h3/src/quic.rs index bb382a33..e9550515 100644 --- a/h3/src/quic.rs +++ b/h3/src/quic.rs @@ -7,7 +7,6 @@ use std::task::{self, Poll}; use bytes::Buf; -use crate::ext::Datagram; pub use crate::proto::stream::{InvalidStreamId, StreamId}; pub use crate::stream::WriteBuf; @@ -83,33 +82,6 @@ pub trait Connection { fn close(&mut self, code: crate::error::Code, reason: &[u8]); } -/// Extends the `Connection` trait for sending datagrams -/// -/// See: -pub trait SendDatagramExt { - /// The error type that can occur when sending a datagram - type Error: Into>; - - /// Send a datagram - fn send_datagram(&mut self, data: Datagram) -> Result<(), Self::Error>; -} - -/// Extends the `Connection` trait for receiving datagrams -/// -/// See: -pub trait RecvDatagramExt { - /// The type of `Buf` for *raw* datagrams (without the stream_id decoded) - type Buf: Buf; - /// The error type that can occur when receiving a datagram - type Error: Into>; - - /// Poll the connection for incoming datagrams. - fn poll_accept_datagram( - &mut self, - cx: &mut task::Context<'_>, - ) -> Poll, Self::Error>>; -} - /// Trait for opening outgoing streams pub trait OpenStreams { /// The type produced by `poll_open_bidi()` diff --git a/h3/src/server.rs b/h3/src/server.rs index 3e220f1e..2725405d 100644 --- a/h3/src/server.rs +++ b/h3/src/server.rs @@ -52,7 +52,6 @@ use std::{ collections::HashSet, - marker::PhantomData, option::Option, result::Result, sync::Arc, @@ -61,11 +60,10 @@ use std::{ use bytes::{Buf, BytesMut}; use futures_util::{ - future::{self, Future}, + future::{self}, ready, }; use http::{response, HeaderMap, Request, Response}; -use pin_project_lite::pin_project; use quic::RecvStream; use quic::StreamId; use tokio::sync::mpsc; @@ -74,7 +72,6 @@ use crate::{ config::Config, connection::{self, ConnectionInner, ConnectionState, SharedStateRef}, error::{Code, Error, ErrorLevel}, - ext::Datagram, frame::{FrameStream, FrameStreamError}, proto::{ frame::{Frame, PayloadLen}, @@ -82,7 +79,7 @@ use crate::{ push::PushId, }, qpack, - quic::{self, RecvDatagramExt, SendDatagramExt, SendStream as _}, + quic::{self, SendStream as _}, request::ResolveRequest, stream::{self, BufRecvStream}, }; @@ -469,36 +466,6 @@ where } } -impl Connection -where - C: quic::Connection + SendDatagramExt, - B: Buf, -{ - /// Sends a datagram - pub fn send_datagram(&mut self, stream_id: StreamId, data: B) -> Result<(), Error> { - self.inner - .conn - .send_datagram(Datagram::new(stream_id, data))?; - tracing::info!("Sent datagram"); - - Ok(()) - } -} - -impl Connection -where - C: quic::Connection + RecvDatagramExt, - B: Buf, -{ - /// Reads an incoming datagram - pub fn read_datagram(&mut self) -> ReadDatagram { - ReadDatagram { - conn: self, - _marker: PhantomData, - } - } -} - impl Drop for Connection where C: quic::Connection, @@ -807,31 +774,3 @@ impl Drop for RequestEnd { } } } - -pin_project! { - /// Future for [`Connection::read_datagram`] - pub struct ReadDatagram<'a, C, B> - where - C: quic::Connection, - B: Buf, - { - conn: &'a mut Connection, - _marker: PhantomData, - } -} - -impl<'a, C, B> Future for ReadDatagram<'a, C, B> -where - C: quic::Connection + RecvDatagramExt, - B: Buf, -{ - type Output = Result>, Error>; - - fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - tracing::trace!("poll: read_datagram"); - match ready!(self.conn.inner.conn.poll_accept_datagram(cx))? { - Some(v) => Poll::Ready(Ok(Some(Datagram::decode(v)?))), - None => Poll::Ready(Ok(None)), - } - } -} From 2e67426735d418207ffd28e2b0d739477d178d13 Mon Sep 17 00:00:00 2001 From: ruben Date: Sat, 17 Jun 2023 19:05:51 +0200 Subject: [PATCH 2/7] add to dev-dependencies --- h3/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/h3/Cargo.toml b/h3/Cargo.toml index bf6a48e7..6dd22253 100644 --- a/h3/Cargo.toml +++ b/h3/Cargo.toml @@ -53,3 +53,4 @@ tracing-subscriber = { version = "0.3", default-features = false, features = [ ] } futures = { version = "0.3.27" } tokio-util = { version = "0.7.7" } +h3-datagram = {path = "../h3-datagram" } \ No newline at end of file From 419c86093c0b69fdef3e58ba1f25ff27c78d98fb Mon Sep 17 00:00:00 2001 From: ruben Date: Sat, 24 Aug 2024 15:38:27 +0200 Subject: [PATCH 3/7] fix merge --- h3-datagram/Cargo.toml | 9 +++++++-- h3/src/server/connection.rs | 7 ++++--- h3/src/server/mod.rs | 1 - h3/src/server/stream.rs | 7 +++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/h3-datagram/Cargo.toml b/h3-datagram/Cargo.toml index 60e0a987..dd09c9d0 100644 --- a/h3-datagram/Cargo.toml +++ b/h3-datagram/Cargo.toml @@ -4,6 +4,11 @@ version = "0.0.1" edition = "2021" [dependencies] -h3 = { path = "../h3" } +#h3 = { path = "../h3" } bytes = "1.4" -pin-project-lite = { version = "0.2", default_features = false } +pin-project-lite = { version = "0.2", default-features = false } + +[dependencies.h3] +version = "0.0.6" +path = "../h3" +features = ["i-implement-a-third-party-backend-and-opt-into-breaking-changes"] diff --git a/h3/src/server/connection.rs b/h3/src/server/connection.rs index c4e5687d..d048d16b 100644 --- a/h3/src/server/connection.rs +++ b/h3/src/server/connection.rs @@ -24,14 +24,13 @@ use tokio::sync::mpsc; use crate::{ connection::{self, ConnectionInner, ConnectionState, SharedStateRef}, error::{Code, Error, ErrorLevel}, - ext::Datagram, frame::{FrameStream, FrameStreamError}, proto::{ frame::{Frame, PayloadLen}, push::PushId, }, qpack, - quic::{self, RecvDatagramExt, SendDatagramExt, SendStream as _}, + quic::{self, SendStream as _}, stream::BufRecvStream, }; @@ -40,7 +39,7 @@ use crate::server::request::ResolveRequest; #[cfg(feature = "tracing")] use tracing::{instrument, trace, warn}; -use super::stream::{ReadDatagram, RequestStream}; +use super::stream::RequestStream; /// Server connection driver /// @@ -429,6 +428,7 @@ where } } +/* impl Connection where C: quic::Connection + SendDatagramExt, @@ -462,6 +462,7 @@ where } } } + */ impl Drop for Connection where diff --git a/h3/src/server/mod.rs b/h3/src/server/mod.rs index a4663d5b..925f3666 100644 --- a/h3/src/server/mod.rs +++ b/h3/src/server/mod.rs @@ -58,5 +58,4 @@ mod stream; pub use builder::builder; pub use builder::Builder; pub use connection::Connection; -pub use stream::ReadDatagram; pub use stream::RequestStream; diff --git a/h3/src/server/stream.rs b/h3/src/server/stream.rs index 975537ed..ddb1815c 100644 --- a/h3/src/server/stream.rs +++ b/h3/src/server/stream.rs @@ -4,8 +4,7 @@ use bytes::Buf; use crate::{ connection::{ConnectionState, SharedStateRef}, - ext::Datagram, - quic::{self, RecvDatagramExt}, + quic::{self}, Error, }; use pin_project_lite::pin_project; @@ -220,6 +219,8 @@ impl Drop for RequestEnd { } } +/* + pin_project! { /// Future for [`Connection::read_datagram`] pub struct ReadDatagram<'a, C, B> @@ -249,3 +250,5 @@ where } } } + + */ From 61aa6ca3cb0e859a2733a0d3bf982f0aedce7644 Mon Sep 17 00:00:00 2001 From: ruben Date: Mon, 26 Aug 2024 22:38:15 +0200 Subject: [PATCH 4/7] cleanup --- h3/src/server/connection.rs | 1 - h3/src/server/stream.rs | 40 ++----------------------------------- 2 files changed, 2 insertions(+), 39 deletions(-) diff --git a/h3/src/server/connection.rs b/h3/src/server/connection.rs index d048d16b..a8b6d921 100644 --- a/h3/src/server/connection.rs +++ b/h3/src/server/connection.rs @@ -4,7 +4,6 @@ use std::{ collections::HashSet, - marker::PhantomData, option::Option, result::Result, sync::Arc, diff --git a/h3/src/server/stream.rs b/h3/src/server/stream.rs index ddb1815c..015d839f 100644 --- a/h3/src/server/stream.rs +++ b/h3/src/server/stream.rs @@ -7,10 +7,9 @@ use crate::{ quic::{self}, Error, }; -use pin_project_lite::pin_project; -use super::connection::{Connection, RequestEnd}; -use std::{marker::PhantomData, sync::Arc}; +use super::connection::RequestEnd; +use std::sync::Arc; use std::{ option::Option, @@ -19,7 +18,6 @@ use std::{ }; use bytes::BytesMut; -use futures_util::{future::Future, ready}; use http::{response, HeaderMap, Response}; use quic::StreamId; @@ -218,37 +216,3 @@ impl Drop for RequestEnd { } } } - -/* - -pin_project! { - /// Future for [`Connection::read_datagram`] - pub struct ReadDatagram<'a, C, B> - where - C: quic::Connection, - B: Buf, - { - pub(super) conn: &'a mut Connection, - pub(super) _marker: PhantomData, - } -} - -impl<'a, C, B> Future for ReadDatagram<'a, C, B> -where - C: quic::Connection + RecvDatagramExt, - B: Buf, -{ - type Output = Result>, Error>; - - fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - #[cfg(feature = "tracing")] - tracing::trace!("poll: read_datagram"); - - match ready!(self.conn.inner.conn.poll_accept_datagram(cx))? { - Some(v) => Poll::Ready(Ok(Some(Datagram::decode(v)?))), - None => Poll::Ready(Ok(None)), - } - } -} - - */ From dc8e0c20de8969395132b31ec1fba063a3efe94b Mon Sep 17 00:00:00 2001 From: ruben Date: Mon, 26 Aug 2024 22:46:21 +0200 Subject: [PATCH 5/7] remove todo comment --- h3/src/error.rs | 1 - h3/src/proto/stream.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/h3/src/error.rs b/h3/src/error.rs index 1ff35cc7..38e018e3 100644 --- a/h3/src/error.rs +++ b/h3/src/error.rs @@ -200,7 +200,6 @@ impl Code { }) } - // Todo: public? private? #[doc(hidden)] pub fn with_cause>(self, cause: E) -> Error { Error::from(self).with_cause(cause) diff --git a/h3/src/proto/stream.rs b/h3/src/proto/stream.rs index 456f895a..bbea9378 100644 --- a/h3/src/proto/stream.rs +++ b/h3/src/proto/stream.rs @@ -134,7 +134,7 @@ impl StreamId { } } - // TODO: pub? better option? + #[allow(missing_docs)] pub fn into_inner(self) -> u64 { self.0 } From cbb7ae759df9eba30c4cef4f568fcf500eae7994 Mon Sep 17 00:00:00 2001 From: ruben Date: Mon, 26 Aug 2024 22:59:03 +0200 Subject: [PATCH 6/7] cleanup --- h3-datagram/src/datagram_traits.rs | 2 +- h3-datagram/src/server.rs | 9 ++------ h3-webtransport/src/server.rs | 6 ++--- h3/src/server/connection.rs | 36 ------------------------------ 4 files changed, 6 insertions(+), 47 deletions(-) diff --git a/h3-datagram/src/datagram_traits.rs b/h3-datagram/src/datagram_traits.rs index c9474ac2..ee0c33ac 100644 --- a/h3-datagram/src/datagram_traits.rs +++ b/h3-datagram/src/datagram_traits.rs @@ -9,7 +9,7 @@ use h3::{ use crate::server::ReadDatagram; -pub trait HandleDatagrams +pub trait HandleDatagramsExt where B: Buf, C: quic::Connection, diff --git a/h3-datagram/src/server.rs b/h3-datagram/src/server.rs index cc7f0e04..c35acff2 100644 --- a/h3-datagram/src/server.rs +++ b/h3-datagram/src/server.rs @@ -16,11 +16,11 @@ use pin_project_lite::pin_project; use crate::{ datagram::Datagram, - datagram_traits::HandleDatagrams, + datagram_traits::HandleDatagramsExt, quic_traits::{self, RecvDatagramExt, SendDatagramExt}, }; -impl HandleDatagrams for Connection +impl HandleDatagramsExt for Connection where B: Buf, C: quic::Connection + SendDatagramExt + RecvDatagramExt, @@ -32,9 +32,6 @@ where self.inner .conn .send_datagram(Datagram::new(stream_id, data))?; - //Todo Import tracing - //tracing::info!("Sent datagram"); - Ok(()) } @@ -68,8 +65,6 @@ where type Output = Result>, Error>; fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - //Todo Import tracing - // tracing::trace!("poll: read_datagram"); match ready!(self.conn.inner.conn.poll_accept_datagram(cx))? { Some(v) => Poll::Ready(Ok(Some(Datagram::decode(v)?))), None => Poll::Ready(Ok(None)), diff --git a/h3-webtransport/src/server.rs b/h3-webtransport/src/server.rs index fdd3f3af..d3093f6a 100644 --- a/h3-webtransport/src/server.rs +++ b/h3-webtransport/src/server.rs @@ -26,7 +26,7 @@ use h3::{ }; use h3_datagram::{ datagram::Datagram, - datagram_traits::HandleDatagrams, + datagram_traits::HandleDatagramsExt, quic_traits::{RecvDatagramExt, SendDatagramExt}, }; use http::{Method, Request, Response, StatusCode}; @@ -44,7 +44,7 @@ use crate::stream::{BidiStream, RecvStream, SendStream}; pub struct WebTransportSession where C: quic::Connection, - Connection: HandleDatagrams, + Connection: HandleDatagramsExt, B: Buf, { // See: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3/#section-2-3 @@ -57,7 +57,7 @@ where impl WebTransportSession where - Connection: HandleDatagrams, + Connection: HandleDatagramsExt, C: quic::Connection, B: Buf, { diff --git a/h3/src/server/connection.rs b/h3/src/server/connection.rs index a8b6d921..c16e4833 100644 --- a/h3/src/server/connection.rs +++ b/h3/src/server/connection.rs @@ -427,42 +427,6 @@ where } } -/* -impl Connection -where - C: quic::Connection + SendDatagramExt, - B: Buf, -{ - /// Sends a datagram - #[cfg_attr(feature = "tracing", instrument(skip_all, level = "trace"))] - pub fn send_datagram(&mut self, stream_id: StreamId, data: B) -> Result<(), Error> { - self.inner - .conn - .send_datagram(Datagram::new(stream_id, data))?; - - #[cfg(feature = "tracing")] - tracing::info!("Sent datagram"); - - Ok(()) - } -} - -impl Connection -where - C: quic::Connection + RecvDatagramExt, - B: Buf, -{ - /// Reads an incoming datagram - #[cfg_attr(feature = "tracing", instrument(skip_all, level = "trace"))] - pub fn read_datagram(&mut self) -> ReadDatagram { - ReadDatagram { - conn: self, - _marker: PhantomData, - } - } -} - */ - impl Drop for Connection where C: quic::Connection, From 21ba7d167cdd0df76d69342413d528e8334d66e4 Mon Sep 17 00:00:00 2001 From: ruben Date: Fri, 30 Aug 2024 21:31:28 +0200 Subject: [PATCH 7/7] make feature for datagram in h3-quinn --- examples/Cargo.toml | 2 +- h3-quinn/Cargo.toml | 3 ++- h3-quinn/src/lib.rs | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 3e82a9e0..ed99d7d2 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -11,7 +11,7 @@ anyhow = "1.0" bytes = "1" futures = "0.3" h3 = { path = "../h3", features = ["tracing"] } -h3-quinn = { path = "../h3-quinn", features = ["tracing"] } +h3-quinn = { path = "../h3-quinn", features = ["tracing", "datagram"] } h3-webtransport = { path = "../h3-webtransport" } http = "1" quinn = { version = "0.11", default-features = false, features = [ diff --git a/h3-quinn/Cargo.toml b/h3-quinn/Cargo.toml index 30ece87e..39fb08fe 100644 --- a/h3-quinn/Cargo.toml +++ b/h3-quinn/Cargo.toml @@ -21,8 +21,9 @@ quinn = { version = "0.11", default-features = false, features = [ tokio-util = { version = "0.7.9" } futures = { version = "0.3.28" } tokio = { version = "1", features = ["io-util"], default-features = false } -h3-datagram = { path = "../h3-datagram" } +h3-datagram = { path = "../h3-datagram", optional = true } tracing = { version = "0.1.40", optional = true } [features] tracing = ["dep:tracing"] +datagram = ["dep:h3-datagram"] \ No newline at end of file diff --git a/h3-quinn/src/lib.rs b/h3-quinn/src/lib.rs index a7cf2c79..4fd8e634 100644 --- a/h3-quinn/src/lib.rs +++ b/h3-quinn/src/lib.rs @@ -19,7 +19,10 @@ use futures::{ stream::{self}, Stream, StreamExt, }; + +#[cfg(feature = "datagram")] use h3_datagram::{datagram::Datagram, quic_traits}; + pub use quinn::{self, AcceptBi, AcceptUni, Endpoint, OpenBi, OpenUni, VarInt, WriteError}; use quinn::{ApplicationClose, ClosedStream, ReadDatagram}; @@ -246,6 +249,7 @@ where } } +#[cfg(feature = "datagram")] impl quic_traits::SendDatagramExt for Connection where B: Buf, @@ -263,6 +267,7 @@ where } } +#[cfg(feature = "datagram")] impl quic_traits::RecvDatagramExt for Connection { type Buf = Bytes;