1use crate::{Server, Transport};
2use futures_lite::{AsyncRead, AsyncWrite};
3use std::{
4 fmt::Debug,
5 future::Future,
6 io,
7 net::SocketAddr,
8 pin::Pin,
9 sync::Arc,
10 task::{Context, Poll},
11};
12use trillium::Info;
13
14pub trait QuicTransportReceive: AsyncRead {
16 fn stop(&mut self, code: u64);
18}
19
20pub trait QuicTransportSend: AsyncWrite {
22 fn reset(&mut self, code: u64);
24}
25
26pub trait QuicTransportBidi: QuicTransportReceive + QuicTransportSend + Transport {}
28
29pub trait QuicConnectionTrait: Clone + Send + Sync + 'static {
38 type BidiStream: QuicTransportBidi + Unpin + Send + Sync + 'static;
40
41 type RecvStream: QuicTransportReceive + Unpin + Send + Sync + 'static;
43
44 type SendStream: QuicTransportSend + Unpin + Send + Sync + 'static;
46
47 fn accept_bidi(&self) -> impl Future<Output = io::Result<(u64, Self::BidiStream)>> + Send;
51
52 fn accept_uni(&self) -> impl Future<Output = io::Result<(u64, Self::RecvStream)>> + Send;
56
57 fn open_uni(&self) -> impl Future<Output = io::Result<(u64, Self::SendStream)>> + Send;
61
62 fn open_bidi(&self) -> impl Future<Output = io::Result<(u64, Self::BidiStream)>> + Send;
66
67 fn remote_address(&self) -> SocketAddr;
69
70 fn close(&self, error_code: u64, reason: &[u8]);
72
73 fn send_datagram(&self, data: &[u8]) -> io::Result<()>;
79
80 fn recv_datagram<F: FnOnce(&[u8]) + Send>(
82 &self,
83 callback: F,
84 ) -> impl Future<Output = io::Result<()>> + Send;
85
86 fn max_datagram_size(&self) -> Option<usize>;
90}
91
92pub trait QuicConfig<S: Server>: Send + 'static {
102 type Endpoint: QuicEndpoint;
104
105 fn bind(
113 self,
114 addr: SocketAddr,
115 runtime: S::Runtime,
116 info: &mut Info,
117 ) -> Option<io::Result<Self::Endpoint>>;
118}
119
120impl<S: Server> QuicConfig<S> for () {
121 type Endpoint = ();
122
123 fn bind(self, _: SocketAddr, _: S::Runtime, _: &mut Info) -> Option<io::Result<()>> {
124 None
125 }
126}
127
128pub trait QuicEndpoint: Send + Sync + 'static {
137 type Connection: QuicConnectionTrait;
139
140 fn accept(&self) -> impl Future<Output = Option<Self::Connection>> + Send;
142
143 fn connect(
147 &self,
148 addr: SocketAddr,
149 server_name: &str,
150 ) -> impl Future<Output = io::Result<Self::Connection>> + Send;
151}
152
153#[derive(Debug, Clone, Copy)]
158pub enum NoQuic {}
159
160impl QuicTransportSend for NoQuic {
161 fn reset(&mut self, _code: u64) {
162 match *self {}
163 }
164}
165
166impl QuicTransportReceive for NoQuic {
167 fn stop(&mut self, _code: u64) {
168 match *self {}
169 }
170}
171
172impl QuicTransportBidi for NoQuic {}
173
174impl QuicConnectionTrait for NoQuic {
175 type BidiStream = NoQuic;
176 type RecvStream = NoQuic;
177 type SendStream = NoQuic;
178
179 async fn accept_bidi(&self) -> io::Result<(u64, Self::BidiStream)> {
180 match *self {}
181 }
182
183 async fn accept_uni(&self) -> io::Result<(u64, Self::RecvStream)> {
184 match *self {}
185 }
186
187 async fn open_uni(&self) -> io::Result<(u64, Self::SendStream)> {
188 match *self {}
189 }
190
191 async fn open_bidi(&self) -> io::Result<(u64, Self::BidiStream)> {
192 match *self {}
193 }
194
195 fn remote_address(&self) -> SocketAddr {
196 match *self {}
197 }
198
199 fn close(&self, _: u64, _: &[u8]) {
200 match *self {}
201 }
202
203 fn send_datagram(&self, _: &[u8]) -> io::Result<()> {
204 match *self {}
205 }
206
207 async fn recv_datagram<F: FnOnce(&[u8]) + Send>(&self, _: F) -> io::Result<()> {
208 match *self {}
209 }
210
211 fn max_datagram_size(&self) -> Option<usize> {
212 match *self {}
213 }
214}
215
216impl Transport for NoQuic {}
217
218impl AsyncRead for NoQuic {
219 fn poll_read(
220 self: Pin<&mut Self>,
221 _: &mut Context<'_>,
222 _: &mut [u8],
223 ) -> Poll<io::Result<usize>> {
224 match *self.get_mut() {}
225 }
226}
227
228impl AsyncWrite for NoQuic {
229 fn poll_write(self: Pin<&mut Self>, _: &mut Context<'_>, _: &[u8]) -> Poll<io::Result<usize>> {
230 match *self.get_mut() {}
231 }
232
233 fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
234 match *self.get_mut() {}
235 }
236
237 fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
238 match *self.get_mut() {}
239 }
240}
241
242impl QuicEndpoint for () {
243 type Connection = NoQuic;
244
245 async fn accept(&self) -> Option<NoQuic> {
246 None
247 }
248
249 async fn connect(&self, _: SocketAddr, _: &str) -> io::Result<NoQuic> {
250 Err(io::Error::new(
251 io::ErrorKind::Unsupported,
252 "QUIC not configured",
253 ))
254 }
255}
256
257type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
260pub(crate) type BoxedRecvStream = Box<dyn QuicTransportReceive + Unpin + Send + Sync>;
261pub(crate) type BoxedSendStream = Box<dyn QuicTransportSend + Unpin + Send + Sync>;
262pub(crate) type BoxedBidiStream = Box<dyn QuicTransportBidi + Unpin + Send + Sync>;
263
264type ReceiveDatagramCallback<'a> = Box<dyn FnOnce(&[u8]) + Send + 'a>;
265
266trait ObjectSafeQuicConnection: Send + Sync {
267 fn accept_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>>;
268 fn accept_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedRecvStream)>>;
269 fn open_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedSendStream)>>;
270 fn open_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>>;
271 fn remote_address(&self) -> SocketAddr;
272 fn close(&self, error_code: u64, reason: &[u8]);
273 fn send_datagram(&self, data: &[u8]) -> io::Result<()>;
274 fn recv_datagram<'a>(
275 &'a self,
276 callback: ReceiveDatagramCallback<'a>,
277 ) -> BoxedFuture<'a, io::Result<()>>;
278 fn max_datagram_size(&self) -> Option<usize>;
279}
280
281impl<T: QuicConnectionTrait> ObjectSafeQuicConnection for T {
282 fn accept_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>> {
283 Box::pin(async {
284 let (id, stream) = QuicConnectionTrait::accept_bidi(self).await?;
285 Ok((id, Box::new(stream) as BoxedBidiStream))
286 })
287 }
288
289 fn accept_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedRecvStream)>> {
290 Box::pin(async {
291 let (id, stream) = QuicConnectionTrait::accept_uni(self).await?;
292 Ok((id, Box::new(stream) as BoxedRecvStream))
293 })
294 }
295
296 fn open_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedSendStream)>> {
297 Box::pin(async {
298 let (id, stream) = QuicConnectionTrait::open_uni(self).await?;
299 Ok((id, Box::new(stream) as BoxedSendStream))
300 })
301 }
302
303 fn open_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>> {
304 Box::pin(async {
305 let (id, stream) = QuicConnectionTrait::open_bidi(self).await?;
306 Ok((id, Box::new(stream) as BoxedBidiStream))
307 })
308 }
309
310 fn remote_address(&self) -> SocketAddr {
311 QuicConnectionTrait::remote_address(self)
312 }
313
314 fn close(&self, error_code: u64, reason: &[u8]) {
315 QuicConnectionTrait::close(self, error_code, reason)
316 }
317
318 fn send_datagram(&self, data: &[u8]) -> io::Result<()> {
319 QuicConnectionTrait::send_datagram(self, data)
320 }
321
322 fn recv_datagram<'a>(
323 &'a self,
324 callback: Box<dyn FnOnce(&[u8]) + Send + 'a>,
325 ) -> BoxedFuture<'a, io::Result<()>> {
326 Box::pin(QuicConnectionTrait::recv_datagram(self, callback))
327 }
328
329 fn max_datagram_size(&self) -> Option<usize> {
330 QuicConnectionTrait::max_datagram_size(self)
331 }
332}
333
334#[derive(Clone)]
340pub struct QuicConnection(Arc<dyn ObjectSafeQuicConnection>);
341
342impl Debug for QuicConnection {
343 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
344 f.debug_struct("QuicConnection")
345 .field("peer", &self.remote_address())
346 .finish_non_exhaustive()
347 }
348}
349
350impl<T: QuicConnectionTrait> From<T> for QuicConnection {
351 fn from(connection: T) -> Self {
352 Self(Arc::new(connection))
353 }
354}
355
356impl QuicConnection {
357 pub async fn accept_bidi(&self) -> io::Result<(u64, BoxedBidiStream)> {
359 self.0.accept_bidi().await
360 }
361
362 pub async fn accept_uni(&self) -> io::Result<(u64, BoxedRecvStream)> {
364 self.0.accept_uni().await
365 }
366
367 pub async fn open_uni(&self) -> io::Result<(u64, BoxedSendStream)> {
369 self.0.open_uni().await
370 }
371
372 pub async fn open_bidi(&self) -> io::Result<(u64, BoxedBidiStream)> {
374 self.0.open_bidi().await
375 }
376
377 pub fn remote_address(&self) -> SocketAddr {
379 self.0.remote_address()
380 }
381
382 pub fn close(&self, error_code: u64, reason: &[u8]) {
384 self.0.close(error_code, reason)
385 }
386
387 pub fn send_datagram(&self, data: &[u8]) -> io::Result<()> {
389 self.0.send_datagram(data)
390 }
391
392 pub async fn recv_datagram<'a, F: FnOnce(&[u8]) + Send + 'a>(
394 &'a self,
395 callback: F,
396 ) -> io::Result<()> {
397 self.0.recv_datagram(Box::new(callback)).await
398 }
399
400 pub fn max_datagram_size(&self) -> Option<usize> {
402 self.0.max_datagram_size()
403 }
404}
405
406trait ObjectSafeQuicEndpoint: Send + Sync {
409 fn accept(&self) -> BoxedFuture<'_, Option<QuicConnection>>;
410 fn connect<'a>(
411 &'a self,
412 addr: SocketAddr,
413 server_name: &'a str,
414 ) -> BoxedFuture<'a, io::Result<QuicConnection>>;
415}
416
417impl<T: QuicEndpoint> ObjectSafeQuicEndpoint for T {
418 fn accept(&self) -> BoxedFuture<'_, Option<QuicConnection>> {
419 Box::pin(async { QuicEndpoint::accept(self).await.map(QuicConnection::from) })
420 }
421
422 fn connect<'a>(
423 &'a self,
424 addr: SocketAddr,
425 server_name: &'a str,
426 ) -> BoxedFuture<'a, io::Result<QuicConnection>> {
427 Box::pin(async move {
428 QuicEndpoint::connect(self, addr, server_name)
429 .await
430 .map(QuicConnection::from)
431 })
432 }
433}
434
435#[derive(Clone)]
438pub struct ArcedQuicEndpoint(Arc<dyn ObjectSafeQuicEndpoint>);
439
440impl Debug for ArcedQuicEndpoint {
441 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
442 f.debug_tuple("ArcedQuicEndpoint").finish()
443 }
444}
445
446impl<T: QuicEndpoint> From<T> for ArcedQuicEndpoint {
447 fn from(endpoint: T) -> Self {
448 Self(Arc::new(endpoint))
449 }
450}
451
452impl ArcedQuicEndpoint {
453 pub async fn accept(&self) -> Option<QuicConnection> {
455 self.0.accept().await
456 }
457
458 pub async fn connect(&self, addr: SocketAddr, server_name: &str) -> io::Result<QuicConnection> {
460 self.0.connect(addr, server_name).await
461 }
462}