sec_http3/
quic.rs

1//! QUIC Transport traits
2//!
3//! This module includes traits and types meant to allow being generic over any
4//! QUIC implementation.
5
6use std::task::{self, Poll};
7
8use bytes::Buf;
9
10use crate::ext::Datagram;
11pub use crate::proto::stream::{InvalidStreamId, StreamId};
12pub use crate::stream::WriteBuf;
13
14// Unresolved questions:
15//
16// - Should the `poll_` methods be `Pin<&mut Self>`?
17
18/// Trait that represent an error from the transport layer
19pub trait Error: std::error::Error + Send + Sync {
20    /// Check if the current error is a transport timeout
21    fn is_timeout(&self) -> bool;
22
23    /// Get the QUIC error code from connection close or stream stop
24    fn err_code(&self) -> Option<u64>;
25}
26
27impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
28    fn from(err: E) -> Box<dyn Error + 'a> {
29        Box::new(err)
30    }
31}
32
33/// Trait representing a QUIC connection.
34pub trait Connection<B: Buf> {
35    /// The type produced by `poll_accept_bidi()`
36    type BidiStream: SendStream<B> + RecvStream;
37    /// The type of the sending part of `BidiStream`
38    type SendStream: SendStream<B>;
39    /// The type produced by `poll_accept_recv()`
40    type RecvStream: RecvStream;
41    /// A producer of outgoing Unidirectional and Bidirectional streams.
42    type OpenStreams: OpenStreams<
43        B,
44        SendStream = Self::SendStream,
45        RecvStream = Self::RecvStream,
46        BidiStream = Self::BidiStream,
47    >;
48    /// Error type yielded by this trait methods
49    type Error: Into<Box<dyn Error>>;
50
51    /// Accept an incoming unidirectional stream
52    ///
53    /// Returning `None` implies the connection is closing or closed.
54    fn poll_accept_recv(
55        &mut self,
56        cx: &mut task::Context<'_>,
57    ) -> Poll<Result<Option<Self::RecvStream>, Self::Error>>;
58
59    /// Accept an incoming bidirectional stream
60    ///
61    /// Returning `None` implies the connection is closing or closed.
62    fn poll_accept_bidi(
63        &mut self,
64        cx: &mut task::Context<'_>,
65    ) -> Poll<Result<Option<Self::BidiStream>, Self::Error>>;
66
67    /// Poll the connection to create a new bidirectional stream.
68    fn poll_open_bidi(
69        &mut self,
70        cx: &mut task::Context<'_>,
71    ) -> Poll<Result<Self::BidiStream, Self::Error>>;
72
73    /// Poll the connection to create a new unidirectional stream.
74    fn poll_open_send(
75        &mut self,
76        cx: &mut task::Context<'_>,
77    ) -> Poll<Result<Self::SendStream, Self::Error>>;
78
79    /// Get an object to open outgoing streams.
80    fn opener(&self) -> Self::OpenStreams;
81
82    /// Close the connection immediately
83    fn close(&mut self, code: crate::error::Code, reason: &[u8]);
84}
85
86/// Extends the `Connection` trait for sending datagrams
87///
88/// See: <https://www.rfc-editor.org/rfc/rfc9297>
89pub trait SendDatagramExt<B: Buf> {
90    /// The error type that can occur when sending a datagram
91    type Error: Into<Box<dyn Error>>;
92
93    /// Send a datagram
94    fn send_datagram(&mut self, data: Datagram<B>) -> Result<(), Self::Error>;
95}
96
97/// Extends the `Connection` trait for receiving datagrams
98///
99/// See: <https://www.rfc-editor.org/rfc/rfc9297>
100pub trait RecvDatagramExt {
101    /// The type of `Buf` for *raw* datagrams (without the stream_id decoded)
102    type Buf: Buf;
103    /// The error type that can occur when receiving a datagram
104    type Error: Into<Box<dyn Error>>;
105
106    /// Poll the connection for incoming datagrams.
107    fn poll_accept_datagram(
108        &mut self,
109        cx: &mut task::Context<'_>,
110    ) -> Poll<Result<Option<Self::Buf>, Self::Error>>;
111}
112
113/// Trait for opening outgoing streams
114pub trait OpenStreams<B: Buf> {
115    /// The type produced by `poll_open_bidi()`
116    type BidiStream: SendStream<B> + RecvStream;
117    /// The type produced by `poll_open_send()`
118    type SendStream: SendStream<B>;
119    /// The type of the receiving part of `BidiStream`
120    type RecvStream: RecvStream;
121    /// Error type yielded by these trait methods
122    type Error: Into<Box<dyn Error>>;
123
124    /// Poll the connection to create a new bidirectional stream.
125    fn poll_open_bidi(
126        &mut self,
127        cx: &mut task::Context<'_>,
128    ) -> Poll<Result<Self::BidiStream, Self::Error>>;
129
130    /// Poll the connection to create a new unidirectional stream.
131    fn poll_open_send(
132        &mut self,
133        cx: &mut task::Context<'_>,
134    ) -> Poll<Result<Self::SendStream, Self::Error>>;
135
136    /// Close the connection immediately
137    fn close(&mut self, code: crate::error::Code, reason: &[u8]);
138}
139
140/// A trait describing the "send" actions of a QUIC stream.
141pub trait SendStream<B: Buf> {
142    /// The error type returned by fallible send methods.
143    type Error: Into<Box<dyn Error>>;
144
145    /// Polls if the stream can send more data.
146    fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
147
148    /// Send more data on the stream.
149    fn send_data<T: Into<WriteBuf<B>>>(&mut self, data: T) -> Result<(), Self::Error>;
150
151    /// Poll to finish the sending side of the stream.
152    fn poll_finish(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
153
154    /// Send a QUIC reset code.
155    fn reset(&mut self, reset_code: u64);
156
157    /// Get QUIC send stream id
158    fn send_id(&self) -> StreamId;
159}
160
161/// Allows sending unframed pure bytes to a stream. Similar to [`AsyncWrite`](https://docs.rs/tokio/latest/tokio/io/trait.AsyncWrite.html)
162pub trait SendStreamUnframed<B: Buf>: SendStream<B> {
163    /// Attempts write data into the stream.
164    ///
165    /// Returns the number of bytes written.
166    ///
167    /// `buf` is advanced by the number of bytes written.
168    fn poll_send<D: Buf>(
169        &mut self,
170        cx: &mut task::Context<'_>,
171        buf: &mut D,
172    ) -> Poll<Result<usize, Self::Error>>;
173}
174
175/// A trait describing the "receive" actions of a QUIC stream.
176pub trait RecvStream {
177    /// The type of `Buf` for data received on this stream.
178    type Buf: Buf;
179    /// The error type that can occur when receiving data.
180    type Error: Into<Box<dyn Error>>;
181
182    /// Poll the stream for more data.
183    ///
184    /// When the receive side will no longer receive more data (such as because
185    /// the peer closed their sending side), this should return `None`.
186    fn poll_data(
187        &mut self,
188        cx: &mut task::Context<'_>,
189    ) -> Poll<Result<Option<Self::Buf>, Self::Error>>;
190
191    /// Send a `STOP_SENDING` QUIC code.
192    fn stop_sending(&mut self, error_code: u64);
193
194    /// Get QUIC send stream id
195    fn recv_id(&self) -> StreamId;
196}
197
198/// Optional trait to allow "splitting" a bidirectional stream into two sides.
199pub trait BidiStream<B: Buf>: SendStream<B> + RecvStream {
200    /// The type for the send half.
201    type SendStream: SendStream<B>;
202    /// The type for the receive half.
203    type RecvStream: RecvStream;
204
205    /// Split this stream into two halves.
206    fn split(self) -> (Self::SendStream, Self::RecvStream);
207}