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}