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;
14
15pub trait QuicTransportReceive: AsyncRead {
17 fn stop(&mut self, code: u64);
19}
20
21pub trait QuicTransportSend: AsyncWrite {
23 fn reset(&mut self, code: u64);
25
26 fn set_priority(&mut self, _priority: i32) {}
31}
32
33pub trait QuicTransportBidi: QuicTransportReceive + QuicTransportSend + Transport {}
35
36pub trait QuicConnectionTrait: Clone + Send + Sync + 'static {
45 type BidiStream: QuicTransportBidi + Unpin + Send + Sync + 'static;
47
48 type RecvStream: QuicTransportReceive + Unpin + Send + Sync + 'static;
50
51 type SendStream: QuicTransportSend + Unpin + Send + Sync + 'static;
53
54 fn accept_bidi(&self) -> impl Future<Output = io::Result<(u64, Self::BidiStream)>> + Send;
58
59 fn accept_uni(&self) -> impl Future<Output = io::Result<(u64, Self::RecvStream)>> + Send;
63
64 fn open_uni(&self) -> impl Future<Output = io::Result<(u64, Self::SendStream)>> + Send;
68
69 fn open_bidi(&self) -> impl Future<Output = io::Result<(u64, Self::BidiStream)>> + Send;
73
74 fn remote_address(&self) -> SocketAddr;
76
77 fn close(&self, error_code: u64, reason: &[u8]);
79
80 fn send_datagram(&self, data: &[u8]) -> io::Result<()>;
86
87 fn recv_datagram<F: FnOnce(&[u8]) + Send>(
89 &self,
90 callback: F,
91 ) -> impl Future<Output = io::Result<()>> + Send;
92
93 fn max_datagram_size(&self) -> Option<usize>;
97}
98
99pub trait QuicConfig<S: Server>: Send + 'static {
109 type Endpoint: QuicEndpoint;
111
112 fn bind(
120 self,
121 addr: SocketAddr,
122 runtime: S::Runtime,
123 info: &mut Info,
124 ) -> Option<io::Result<Self::Endpoint>>;
125
126 fn is_configured(&self) -> bool {
132 true
133 }
134
135 fn bind_with_socket(
144 self,
145 socket: std::net::UdpSocket,
146 runtime: S::Runtime,
147 info: &mut Info,
148 ) -> io::Result<Self::Endpoint>
149 where
150 Self: Sized,
151 {
152 let addr = socket.local_addr()?;
153 drop(socket);
154 self.bind(addr, runtime, info).unwrap_or_else(|| {
155 Err(io::Error::new(
156 io::ErrorKind::Unsupported,
157 "QuicConfig::bind returned None; this QuicConfig is a no-op and cannot be bound \
158 with bind_with_socket",
159 ))
160 })
161 }
162}
163
164impl<S: Server> QuicConfig<S> for () {
165 type Endpoint = ();
166
167 fn bind(self, _: SocketAddr, _: S::Runtime, _: &mut Info) -> Option<io::Result<()>> {
168 None
169 }
170
171 fn is_configured(&self) -> bool {
172 false
173 }
174}
175
176pub trait QuicEndpoint: Send + Sync + 'static {
185 type Connection: QuicConnectionTrait;
187
188 fn accept(&self) -> impl Future<Output = Option<Self::Connection>> + Send;
190
191 fn connect(
195 &self,
196 addr: SocketAddr,
197 server_name: &str,
198 ) -> impl Future<Output = io::Result<Self::Connection>> + Send;
199
200 fn connect_with_alpn(
208 &self,
209 addr: SocketAddr,
210 server_name: &str,
211 alpn: &[Cow<'static, [u8]>],
212 ) -> impl Future<Output = io::Result<Self::Connection>> + Send {
213 let _ = alpn;
214 self.connect(addr, server_name)
215 }
216
217 fn local_addr(&self) -> io::Result<SocketAddr> {
220 Err(io::Error::new(
221 io::ErrorKind::Unsupported,
222 "QuicEndpoint::local_addr not implemented for this adapter",
223 ))
224 }
225}
226
227#[derive(Debug, Clone, Copy)]
232pub enum NoQuic {}
233
234impl QuicTransportSend for NoQuic {
235 fn reset(&mut self, _code: u64) {
236 match *self {}
237 }
238}
239
240impl QuicTransportReceive for NoQuic {
241 fn stop(&mut self, _code: u64) {
242 match *self {}
243 }
244}
245
246impl QuicTransportBidi for NoQuic {}
247
248impl QuicConnectionTrait for NoQuic {
249 type BidiStream = NoQuic;
250 type RecvStream = NoQuic;
251 type SendStream = NoQuic;
252
253 async fn accept_bidi(&self) -> io::Result<(u64, Self::BidiStream)> {
254 match *self {}
255 }
256
257 async fn accept_uni(&self) -> io::Result<(u64, Self::RecvStream)> {
258 match *self {}
259 }
260
261 async fn open_uni(&self) -> io::Result<(u64, Self::SendStream)> {
262 match *self {}
263 }
264
265 async fn open_bidi(&self) -> io::Result<(u64, Self::BidiStream)> {
266 match *self {}
267 }
268
269 fn remote_address(&self) -> SocketAddr {
270 match *self {}
271 }
272
273 fn close(&self, _: u64, _: &[u8]) {
274 match *self {}
275 }
276
277 fn send_datagram(&self, _: &[u8]) -> io::Result<()> {
278 match *self {}
279 }
280
281 async fn recv_datagram<F: FnOnce(&[u8]) + Send>(&self, _: F) -> io::Result<()> {
282 match *self {}
283 }
284
285 fn max_datagram_size(&self) -> Option<usize> {
286 match *self {}
287 }
288}
289
290impl Transport for NoQuic {}
291
292impl AsyncRead for NoQuic {
293 fn poll_read(
294 self: Pin<&mut Self>,
295 _: &mut Context<'_>,
296 _: &mut [u8],
297 ) -> Poll<io::Result<usize>> {
298 match *self.get_mut() {}
299 }
300}
301
302impl AsyncWrite for NoQuic {
303 fn poll_write(self: Pin<&mut Self>, _: &mut Context<'_>, _: &[u8]) -> Poll<io::Result<usize>> {
304 match *self.get_mut() {}
305 }
306
307 fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
308 match *self.get_mut() {}
309 }
310
311 fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
312 match *self.get_mut() {}
313 }
314}
315
316impl QuicEndpoint for () {
317 type Connection = NoQuic;
318
319 async fn accept(&self) -> Option<NoQuic> {
320 None
321 }
322
323 async fn connect(&self, _: SocketAddr, _: &str) -> io::Result<NoQuic> {
324 Err(io::Error::new(
325 io::ErrorKind::Unsupported,
326 "QUIC not configured",
327 ))
328 }
329}
330
331type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
334
335pub type BoxedRecvStream = Box<dyn QuicTransportReceive + Unpin + Send + Sync>;
338
339pub type BoxedSendStream = Box<dyn QuicTransportSend + Unpin + Send + Sync>;
341
342pub type BoxedBidiStream = Box<dyn QuicTransportBidi + Unpin + Send + Sync>;
344
345impl QuicTransportReceive for BoxedRecvStream {
346 fn stop(&mut self, code: u64) {
347 (**self).stop(code);
348 }
349}
350
351impl QuicTransportSend for BoxedSendStream {
352 fn reset(&mut self, code: u64) {
353 (**self).reset(code);
354 }
355
356 fn set_priority(&mut self, priority: i32) {
357 (**self).set_priority(priority);
358 }
359}
360
361impl QuicTransportReceive for BoxedBidiStream {
362 fn stop(&mut self, code: u64) {
363 (**self).stop(code);
364 }
365}
366
367impl QuicTransportSend for BoxedBidiStream {
368 fn reset(&mut self, code: u64) {
369 (**self).reset(code);
370 }
371
372 fn set_priority(&mut self, priority: i32) {
373 (**self).set_priority(priority);
374 }
375}
376
377impl QuicTransportBidi for BoxedBidiStream {}
378
379impl Transport for BoxedBidiStream {
380 fn set_linger(&mut self, linger: Option<std::time::Duration>) -> io::Result<()> {
381 (**self).set_linger(linger)
382 }
383
384 fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
385 (**self).set_nodelay(nodelay)
386 }
387
388 fn set_ip_ttl(&mut self, ttl: u32) -> io::Result<()> {
389 (**self).set_ip_ttl(ttl)
390 }
391
392 fn peer_addr(&self) -> io::Result<Option<SocketAddr>> {
393 (**self).peer_addr()
394 }
395
396 fn negotiated_alpn(&self) -> Option<Cow<'_, [u8]>> {
397 (**self).negotiated_alpn()
398 }
399}
400
401type ReceiveDatagramCallback<'a> = Box<dyn FnOnce(&[u8]) + Send + 'a>;
402
403trait ObjectSafeQuicConnection: Send + Sync {
404 fn accept_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>>;
405 fn accept_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedRecvStream)>>;
406 fn open_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedSendStream)>>;
407 fn open_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>>;
408 fn remote_address(&self) -> SocketAddr;
409 fn close(&self, error_code: u64, reason: &[u8]);
410 fn send_datagram(&self, data: &[u8]) -> io::Result<()>;
411 fn recv_datagram<'a>(
412 &'a self,
413 callback: ReceiveDatagramCallback<'a>,
414 ) -> BoxedFuture<'a, io::Result<()>>;
415 fn max_datagram_size(&self) -> Option<usize>;
416}
417
418impl<T: QuicConnectionTrait> ObjectSafeQuicConnection for T {
419 fn accept_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>> {
420 Box::pin(async {
421 let (id, stream) = QuicConnectionTrait::accept_bidi(self).await?;
422 Ok((id, Box::new(stream) as BoxedBidiStream))
423 })
424 }
425
426 fn accept_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedRecvStream)>> {
427 Box::pin(async {
428 let (id, stream) = QuicConnectionTrait::accept_uni(self).await?;
429 Ok((id, Box::new(stream) as BoxedRecvStream))
430 })
431 }
432
433 fn open_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedSendStream)>> {
434 Box::pin(async {
435 let (id, stream) = QuicConnectionTrait::open_uni(self).await?;
436 Ok((id, Box::new(stream) as BoxedSendStream))
437 })
438 }
439
440 fn open_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>> {
441 Box::pin(async {
442 let (id, stream) = QuicConnectionTrait::open_bidi(self).await?;
443 Ok((id, Box::new(stream) as BoxedBidiStream))
444 })
445 }
446
447 fn remote_address(&self) -> SocketAddr {
448 QuicConnectionTrait::remote_address(self)
449 }
450
451 fn close(&self, error_code: u64, reason: &[u8]) {
452 QuicConnectionTrait::close(self, error_code, reason)
453 }
454
455 fn send_datagram(&self, data: &[u8]) -> io::Result<()> {
456 QuicConnectionTrait::send_datagram(self, data)
457 }
458
459 fn recv_datagram<'a>(
460 &'a self,
461 callback: Box<dyn FnOnce(&[u8]) + Send + 'a>,
462 ) -> BoxedFuture<'a, io::Result<()>> {
463 Box::pin(QuicConnectionTrait::recv_datagram(self, callback))
464 }
465
466 fn max_datagram_size(&self) -> Option<usize> {
467 QuicConnectionTrait::max_datagram_size(self)
468 }
469}
470
471#[derive(Clone)]
477pub struct QuicConnection(Arc<dyn ObjectSafeQuicConnection>);
478
479impl Debug for QuicConnection {
480 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
481 f.debug_struct("QuicConnection")
482 .field("peer", &self.remote_address())
483 .finish_non_exhaustive()
484 }
485}
486
487impl<T: QuicConnectionTrait> From<T> for QuicConnection {
488 fn from(connection: T) -> Self {
489 Self(Arc::new(connection))
490 }
491}
492
493impl QuicConnection {
494 pub async fn accept_bidi(&self) -> io::Result<(u64, BoxedBidiStream)> {
496 self.0.accept_bidi().await
497 }
498
499 pub async fn accept_uni(&self) -> io::Result<(u64, BoxedRecvStream)> {
501 self.0.accept_uni().await
502 }
503
504 pub async fn open_uni(&self) -> io::Result<(u64, BoxedSendStream)> {
506 self.0.open_uni().await
507 }
508
509 pub async fn open_bidi(&self) -> io::Result<(u64, BoxedBidiStream)> {
511 self.0.open_bidi().await
512 }
513
514 pub fn remote_address(&self) -> SocketAddr {
516 self.0.remote_address()
517 }
518
519 pub fn close(&self, error_code: u64, reason: &[u8]) {
521 self.0.close(error_code, reason)
522 }
523
524 pub fn send_datagram(&self, data: &[u8]) -> io::Result<()> {
526 self.0.send_datagram(data)
527 }
528
529 pub async fn recv_datagram<'a, F: FnOnce(&[u8]) + Send + 'a>(
531 &'a self,
532 callback: F,
533 ) -> io::Result<()> {
534 self.0.recv_datagram(Box::new(callback)).await
535 }
536
537 pub fn max_datagram_size(&self) -> Option<usize> {
539 self.0.max_datagram_size()
540 }
541}
542
543trait ObjectSafeQuicEndpoint: Send + Sync {
546 fn accept(&self) -> BoxedFuture<'_, Option<QuicConnection>>;
547 fn connect<'a>(
548 &'a self,
549 addr: SocketAddr,
550 server_name: &'a str,
551 ) -> BoxedFuture<'a, io::Result<QuicConnection>>;
552 fn connect_with_alpn<'a>(
553 &'a self,
554 addr: SocketAddr,
555 server_name: &'a str,
556 alpn: &'a [Cow<'static, [u8]>],
557 ) -> BoxedFuture<'a, io::Result<QuicConnection>>;
558 fn local_addr(&self) -> io::Result<SocketAddr>;
559}
560
561impl<T: QuicEndpoint> ObjectSafeQuicEndpoint for T {
562 fn accept(&self) -> BoxedFuture<'_, Option<QuicConnection>> {
563 Box::pin(async { QuicEndpoint::accept(self).await.map(QuicConnection::from) })
564 }
565
566 fn connect<'a>(
567 &'a self,
568 addr: SocketAddr,
569 server_name: &'a str,
570 ) -> BoxedFuture<'a, io::Result<QuicConnection>> {
571 Box::pin(async move {
572 QuicEndpoint::connect(self, addr, server_name)
573 .await
574 .map(QuicConnection::from)
575 })
576 }
577
578 fn connect_with_alpn<'a>(
579 &'a self,
580 addr: SocketAddr,
581 server_name: &'a str,
582 alpn: &'a [Cow<'static, [u8]>],
583 ) -> BoxedFuture<'a, io::Result<QuicConnection>> {
584 Box::pin(async move {
585 QuicEndpoint::connect_with_alpn(self, addr, server_name, alpn)
586 .await
587 .map(QuicConnection::from)
588 })
589 }
590
591 fn local_addr(&self) -> io::Result<SocketAddr> {
592 QuicEndpoint::local_addr(self)
593 }
594}
595
596#[derive(Clone)]
599pub struct ArcedQuicEndpoint(Arc<dyn ObjectSafeQuicEndpoint>);
600
601impl Debug for ArcedQuicEndpoint {
602 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
603 f.debug_tuple("ArcedQuicEndpoint").finish()
604 }
605}
606
607impl<T: QuicEndpoint> From<T> for ArcedQuicEndpoint {
608 fn from(endpoint: T) -> Self {
609 Self(Arc::new(endpoint))
610 }
611}
612
613impl ArcedQuicEndpoint {
614 pub async fn accept(&self) -> Option<QuicConnection> {
616 self.0.accept().await
617 }
618
619 pub async fn connect(&self, addr: SocketAddr, server_name: &str) -> io::Result<QuicConnection> {
621 self.0.connect(addr, server_name).await
622 }
623
624 pub async fn connect_with_alpn(
627 &self,
628 addr: SocketAddr,
629 server_name: &str,
630 alpn: &[Cow<'static, [u8]>],
631 ) -> io::Result<QuicConnection> {
632 self.0.connect_with_alpn(addr, server_name, alpn).await
633 }
634
635 pub fn local_addr(&self) -> io::Result<SocketAddr> {
637 self.0.local_addr()
638 }
639}