1use crate::{Server, Transport};
2use futures_lite::{AsyncRead, AsyncWrite};
3use std::{
4 borrow::Cow,
5 fmt::Debug,
6 future::Future,
7 io,
8 net::SocketAddr,
9 pin::Pin,
10 sync::Arc,
11 task::{Context, Poll},
12};
13use trillium::Info;
14use trillium_http::PeerGone;
15
16pub trait QuicTransportReceive: AsyncRead {
18 fn stop(&mut self, code: u64);
20}
21
22pub trait QuicTransportSend: AsyncWrite {
24 fn reset(&mut self, code: u64);
26
27 fn stopped(&self) -> Option<PeerGone> {
37 None
38 }
39
40 fn set_priority(&mut self, _priority: i32) {}
45}
46
47pub trait QuicTransportBidi: QuicTransportReceive + QuicTransportSend + Transport {}
49
50pub trait QuicConnectionTrait: Clone + Send + Sync + 'static {
59 type BidiStream: QuicTransportBidi + Unpin + Send + Sync + 'static;
61
62 type RecvStream: QuicTransportReceive + Unpin + Send + Sync + 'static;
64
65 type SendStream: QuicTransportSend + Unpin + Send + Sync + 'static;
67
68 fn accept_bidi(&self) -> impl Future<Output = io::Result<(u64, Self::BidiStream)>> + Send;
72
73 fn accept_uni(&self) -> impl Future<Output = io::Result<(u64, Self::RecvStream)>> + Send;
77
78 fn open_uni(&self) -> impl Future<Output = io::Result<(u64, Self::SendStream)>> + Send;
82
83 fn open_bidi(&self) -> impl Future<Output = io::Result<(u64, Self::BidiStream)>> + Send;
87
88 fn remote_address(&self) -> SocketAddr;
90
91 fn close(&self, error_code: u64, reason: &[u8]);
93
94 fn send_datagram(&self, data: &[u8]) -> io::Result<()>;
100
101 fn recv_datagram<F: FnOnce(&[u8]) + Send>(
103 &self,
104 callback: F,
105 ) -> impl Future<Output = io::Result<()>> + Send;
106
107 fn max_datagram_size(&self) -> Option<usize>;
111}
112
113pub trait QuicConfig<S: Server>: Send + 'static {
123 type Endpoint: QuicEndpoint;
125
126 fn bind(
134 self,
135 addr: SocketAddr,
136 runtime: S::Runtime,
137 info: &mut Info,
138 ) -> Option<io::Result<Self::Endpoint>>;
139
140 fn is_configured(&self) -> bool {
146 true
147 }
148
149 fn bind_with_socket(
158 self,
159 socket: std::net::UdpSocket,
160 runtime: S::Runtime,
161 info: &mut Info,
162 ) -> io::Result<Self::Endpoint>
163 where
164 Self: Sized,
165 {
166 let addr = socket.local_addr()?;
167 drop(socket);
168 self.bind(addr, runtime, info).unwrap_or_else(|| {
169 Err(io::Error::new(
170 io::ErrorKind::Unsupported,
171 "QuicConfig::bind returned None; this QuicConfig is a no-op and cannot be bound \
172 with bind_with_socket",
173 ))
174 })
175 }
176}
177
178impl<S: Server> QuicConfig<S> for () {
179 type Endpoint = ();
180
181 fn bind(self, _: SocketAddr, _: S::Runtime, _: &mut Info) -> Option<io::Result<()>> {
182 None
183 }
184
185 fn is_configured(&self) -> bool {
186 false
187 }
188}
189
190pub trait QuicEndpoint: Send + Sync + 'static {
199 type Connection: QuicConnectionTrait;
201
202 fn accept(&self) -> impl Future<Output = Option<Self::Connection>> + Send;
204
205 fn connect(
209 &self,
210 addr: SocketAddr,
211 server_name: &str,
212 ) -> impl Future<Output = io::Result<Self::Connection>> + Send;
213
214 fn connect_with_alpn(
222 &self,
223 addr: SocketAddr,
224 server_name: &str,
225 alpn: &[Cow<'static, [u8]>],
226 ) -> impl Future<Output = io::Result<Self::Connection>> + Send {
227 let _ = alpn;
228 self.connect(addr, server_name)
229 }
230
231 fn local_addr(&self) -> io::Result<SocketAddr> {
234 Err(io::Error::new(
235 io::ErrorKind::Unsupported,
236 "QuicEndpoint::local_addr not implemented for this adapter",
237 ))
238 }
239}
240
241#[derive(Debug, Clone, Copy)]
246pub enum NoQuic {}
247
248impl QuicTransportSend for NoQuic {
249 fn reset(&mut self, _code: u64) {
250 match *self {}
251 }
252}
253
254impl QuicTransportReceive for NoQuic {
255 fn stop(&mut self, _code: u64) {
256 match *self {}
257 }
258}
259
260impl QuicTransportBidi for NoQuic {}
261
262impl QuicConnectionTrait for NoQuic {
263 type BidiStream = NoQuic;
264 type RecvStream = NoQuic;
265 type SendStream = NoQuic;
266
267 async fn accept_bidi(&self) -> io::Result<(u64, Self::BidiStream)> {
268 match *self {}
269 }
270
271 async fn accept_uni(&self) -> io::Result<(u64, Self::RecvStream)> {
272 match *self {}
273 }
274
275 async fn open_uni(&self) -> io::Result<(u64, Self::SendStream)> {
276 match *self {}
277 }
278
279 async fn open_bidi(&self) -> io::Result<(u64, Self::BidiStream)> {
280 match *self {}
281 }
282
283 fn remote_address(&self) -> SocketAddr {
284 match *self {}
285 }
286
287 fn close(&self, _: u64, _: &[u8]) {
288 match *self {}
289 }
290
291 fn send_datagram(&self, _: &[u8]) -> io::Result<()> {
292 match *self {}
293 }
294
295 async fn recv_datagram<F: FnOnce(&[u8]) + Send>(&self, _: F) -> io::Result<()> {
296 match *self {}
297 }
298
299 fn max_datagram_size(&self) -> Option<usize> {
300 match *self {}
301 }
302}
303
304impl Transport for NoQuic {}
305
306impl AsyncRead for NoQuic {
307 fn poll_read(
308 self: Pin<&mut Self>,
309 _: &mut Context<'_>,
310 _: &mut [u8],
311 ) -> Poll<io::Result<usize>> {
312 match *self.get_mut() {}
313 }
314}
315
316impl AsyncWrite for NoQuic {
317 fn poll_write(self: Pin<&mut Self>, _: &mut Context<'_>, _: &[u8]) -> Poll<io::Result<usize>> {
318 match *self.get_mut() {}
319 }
320
321 fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
322 match *self.get_mut() {}
323 }
324
325 fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
326 match *self.get_mut() {}
327 }
328}
329
330impl QuicEndpoint for () {
331 type Connection = NoQuic;
332
333 async fn accept(&self) -> Option<NoQuic> {
334 None
335 }
336
337 async fn connect(&self, _: SocketAddr, _: &str) -> io::Result<NoQuic> {
338 Err(io::Error::new(
339 io::ErrorKind::Unsupported,
340 "QUIC not configured",
341 ))
342 }
343}
344
345type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
348
349pub type BoxedRecvStream = Box<dyn QuicTransportReceive + Unpin + Send + Sync>;
352
353pub type BoxedSendStream = Box<dyn QuicTransportSend + Unpin + Send + Sync>;
355
356pub type BoxedBidiStream = Box<dyn QuicTransportBidi + Unpin + Send + Sync>;
358
359impl QuicTransportReceive for BoxedRecvStream {
360 fn stop(&mut self, code: u64) {
361 (**self).stop(code);
362 }
363}
364
365impl QuicTransportSend for BoxedSendStream {
366 fn reset(&mut self, code: u64) {
367 (**self).reset(code);
368 }
369
370 fn stopped(&self) -> Option<PeerGone> {
371 (**self).stopped()
372 }
373
374 fn set_priority(&mut self, priority: i32) {
375 (**self).set_priority(priority);
376 }
377}
378
379impl QuicTransportReceive for BoxedBidiStream {
380 fn stop(&mut self, code: u64) {
381 (**self).stop(code);
382 }
383}
384
385impl QuicTransportSend for BoxedBidiStream {
386 fn reset(&mut self, code: u64) {
387 (**self).reset(code);
388 }
389
390 fn stopped(&self) -> Option<PeerGone> {
391 (**self).stopped()
392 }
393
394 fn set_priority(&mut self, priority: i32) {
395 (**self).set_priority(priority);
396 }
397}
398
399impl QuicTransportBidi for BoxedBidiStream {}
400
401impl Transport for BoxedBidiStream {
402 fn set_linger(&mut self, linger: Option<std::time::Duration>) -> io::Result<()> {
403 (**self).set_linger(linger)
404 }
405
406 fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
407 (**self).set_nodelay(nodelay)
408 }
409
410 fn set_ip_ttl(&mut self, ttl: u32) -> io::Result<()> {
411 (**self).set_ip_ttl(ttl)
412 }
413
414 fn peer_addr(&self) -> io::Result<Option<SocketAddr>> {
415 (**self).peer_addr()
416 }
417
418 fn negotiated_alpn(&self) -> Option<Cow<'_, [u8]>> {
419 (**self).negotiated_alpn()
420 }
421}
422
423type ReceiveDatagramCallback<'a> = Box<dyn FnOnce(&[u8]) + Send + 'a>;
424
425trait ObjectSafeQuicConnection: Send + Sync {
426 fn accept_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>>;
427 fn accept_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedRecvStream)>>;
428 fn open_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedSendStream)>>;
429 fn open_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>>;
430 fn remote_address(&self) -> SocketAddr;
431 fn close(&self, error_code: u64, reason: &[u8]);
432 fn send_datagram(&self, data: &[u8]) -> io::Result<()>;
433 fn recv_datagram<'a>(
434 &'a self,
435 callback: ReceiveDatagramCallback<'a>,
436 ) -> BoxedFuture<'a, io::Result<()>>;
437 fn max_datagram_size(&self) -> Option<usize>;
438}
439
440impl<T: QuicConnectionTrait> ObjectSafeQuicConnection for T {
441 fn accept_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>> {
442 Box::pin(async {
443 let (id, stream) = QuicConnectionTrait::accept_bidi(self).await?;
444 Ok((id, Box::new(stream) as BoxedBidiStream))
445 })
446 }
447
448 fn accept_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedRecvStream)>> {
449 Box::pin(async {
450 let (id, stream) = QuicConnectionTrait::accept_uni(self).await?;
451 Ok((id, Box::new(stream) as BoxedRecvStream))
452 })
453 }
454
455 fn open_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedSendStream)>> {
456 Box::pin(async {
457 let (id, stream) = QuicConnectionTrait::open_uni(self).await?;
458 Ok((id, Box::new(stream) as BoxedSendStream))
459 })
460 }
461
462 fn open_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>> {
463 Box::pin(async {
464 let (id, stream) = QuicConnectionTrait::open_bidi(self).await?;
465 Ok((id, Box::new(stream) as BoxedBidiStream))
466 })
467 }
468
469 fn remote_address(&self) -> SocketAddr {
470 QuicConnectionTrait::remote_address(self)
471 }
472
473 fn close(&self, error_code: u64, reason: &[u8]) {
474 QuicConnectionTrait::close(self, error_code, reason)
475 }
476
477 fn send_datagram(&self, data: &[u8]) -> io::Result<()> {
478 QuicConnectionTrait::send_datagram(self, data)
479 }
480
481 fn recv_datagram<'a>(
482 &'a self,
483 callback: Box<dyn FnOnce(&[u8]) + Send + 'a>,
484 ) -> BoxedFuture<'a, io::Result<()>> {
485 Box::pin(QuicConnectionTrait::recv_datagram(self, callback))
486 }
487
488 fn max_datagram_size(&self) -> Option<usize> {
489 QuicConnectionTrait::max_datagram_size(self)
490 }
491}
492
493#[derive(Clone)]
499pub struct QuicConnection(Arc<dyn ObjectSafeQuicConnection>);
500
501impl Debug for QuicConnection {
502 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
503 f.debug_struct("QuicConnection")
504 .field("peer", &self.remote_address())
505 .finish_non_exhaustive()
506 }
507}
508
509impl<T: QuicConnectionTrait> From<T> for QuicConnection {
510 fn from(connection: T) -> Self {
511 Self(Arc::new(connection))
512 }
513}
514
515impl QuicConnection {
516 pub async fn accept_bidi(&self) -> io::Result<(u64, BoxedBidiStream)> {
518 self.0.accept_bidi().await
519 }
520
521 pub async fn accept_uni(&self) -> io::Result<(u64, BoxedRecvStream)> {
523 self.0.accept_uni().await
524 }
525
526 pub async fn open_uni(&self) -> io::Result<(u64, BoxedSendStream)> {
528 self.0.open_uni().await
529 }
530
531 pub async fn open_bidi(&self) -> io::Result<(u64, BoxedBidiStream)> {
533 self.0.open_bidi().await
534 }
535
536 pub fn remote_address(&self) -> SocketAddr {
538 self.0.remote_address()
539 }
540
541 pub fn close(&self, error_code: u64, reason: &[u8]) {
543 self.0.close(error_code, reason)
544 }
545
546 pub fn send_datagram(&self, data: &[u8]) -> io::Result<()> {
548 self.0.send_datagram(data)
549 }
550
551 pub async fn recv_datagram<'a, F: FnOnce(&[u8]) + Send + 'a>(
553 &'a self,
554 callback: F,
555 ) -> io::Result<()> {
556 self.0.recv_datagram(Box::new(callback)).await
557 }
558
559 pub fn max_datagram_size(&self) -> Option<usize> {
561 self.0.max_datagram_size()
562 }
563}
564
565trait ObjectSafeQuicEndpoint: Send + Sync {
568 fn accept(&self) -> BoxedFuture<'_, Option<QuicConnection>>;
569 fn connect<'a>(
570 &'a self,
571 addr: SocketAddr,
572 server_name: &'a str,
573 ) -> BoxedFuture<'a, io::Result<QuicConnection>>;
574 fn connect_with_alpn<'a>(
575 &'a self,
576 addr: SocketAddr,
577 server_name: &'a str,
578 alpn: &'a [Cow<'static, [u8]>],
579 ) -> BoxedFuture<'a, io::Result<QuicConnection>>;
580 fn local_addr(&self) -> io::Result<SocketAddr>;
581}
582
583impl<T: QuicEndpoint> ObjectSafeQuicEndpoint for T {
584 fn accept(&self) -> BoxedFuture<'_, Option<QuicConnection>> {
585 Box::pin(async { QuicEndpoint::accept(self).await.map(QuicConnection::from) })
586 }
587
588 fn connect<'a>(
589 &'a self,
590 addr: SocketAddr,
591 server_name: &'a str,
592 ) -> BoxedFuture<'a, io::Result<QuicConnection>> {
593 Box::pin(async move {
594 QuicEndpoint::connect(self, addr, server_name)
595 .await
596 .map(QuicConnection::from)
597 })
598 }
599
600 fn connect_with_alpn<'a>(
601 &'a self,
602 addr: SocketAddr,
603 server_name: &'a str,
604 alpn: &'a [Cow<'static, [u8]>],
605 ) -> BoxedFuture<'a, io::Result<QuicConnection>> {
606 Box::pin(async move {
607 QuicEndpoint::connect_with_alpn(self, addr, server_name, alpn)
608 .await
609 .map(QuicConnection::from)
610 })
611 }
612
613 fn local_addr(&self) -> io::Result<SocketAddr> {
614 QuicEndpoint::local_addr(self)
615 }
616}
617
618#[derive(Clone)]
621pub struct ArcedQuicEndpoint(Arc<dyn ObjectSafeQuicEndpoint>);
622
623impl Debug for ArcedQuicEndpoint {
624 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
625 f.debug_tuple("ArcedQuicEndpoint").finish()
626 }
627}
628
629impl<T: QuicEndpoint> From<T> for ArcedQuicEndpoint {
630 fn from(endpoint: T) -> Self {
631 Self(Arc::new(endpoint))
632 }
633}
634
635impl ArcedQuicEndpoint {
636 pub async fn accept(&self) -> Option<QuicConnection> {
638 self.0.accept().await
639 }
640
641 pub async fn connect(&self, addr: SocketAddr, server_name: &str) -> io::Result<QuicConnection> {
643 self.0.connect(addr, server_name).await
644 }
645
646 pub async fn connect_with_alpn(
649 &self,
650 addr: SocketAddr,
651 server_name: &str,
652 alpn: &[Cow<'static, [u8]>],
653 ) -> io::Result<QuicConnection> {
654 self.0.connect_with_alpn(addr, server_name, alpn).await
655 }
656
657 pub fn local_addr(&self) -> io::Result<SocketAddr> {
659 self.0.local_addr()
660 }
661}