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 fn is_configured(&self) -> bool {
125 true
126 }
127
128 fn bind_with_socket(
137 self,
138 socket: std::net::UdpSocket,
139 runtime: S::Runtime,
140 info: &mut Info,
141 ) -> io::Result<Self::Endpoint>
142 where
143 Self: Sized,
144 {
145 let addr = socket.local_addr()?;
146 drop(socket);
147 self.bind(addr, runtime, info).unwrap_or_else(|| {
148 Err(io::Error::new(
149 io::ErrorKind::Unsupported,
150 "QuicConfig::bind returned None; this QuicConfig is a no-op and cannot be bound \
151 with bind_with_socket",
152 ))
153 })
154 }
155}
156
157impl<S: Server> QuicConfig<S> for () {
158 type Endpoint = ();
159
160 fn bind(self, _: SocketAddr, _: S::Runtime, _: &mut Info) -> Option<io::Result<()>> {
161 None
162 }
163
164 fn is_configured(&self) -> bool {
165 false
166 }
167}
168
169pub trait QuicEndpoint: Send + Sync + 'static {
178 type Connection: QuicConnectionTrait;
180
181 fn accept(&self) -> impl Future<Output = Option<Self::Connection>> + Send;
183
184 fn connect(
188 &self,
189 addr: SocketAddr,
190 server_name: &str,
191 ) -> impl Future<Output = io::Result<Self::Connection>> + Send;
192
193 fn local_addr(&self) -> io::Result<SocketAddr> {
196 Err(io::Error::new(
197 io::ErrorKind::Unsupported,
198 "QuicEndpoint::local_addr not implemented for this adapter",
199 ))
200 }
201}
202
203#[derive(Debug, Clone, Copy)]
208pub enum NoQuic {}
209
210impl QuicTransportSend for NoQuic {
211 fn reset(&mut self, _code: u64) {
212 match *self {}
213 }
214}
215
216impl QuicTransportReceive for NoQuic {
217 fn stop(&mut self, _code: u64) {
218 match *self {}
219 }
220}
221
222impl QuicTransportBidi for NoQuic {}
223
224impl QuicConnectionTrait for NoQuic {
225 type BidiStream = NoQuic;
226 type RecvStream = NoQuic;
227 type SendStream = NoQuic;
228
229 async fn accept_bidi(&self) -> io::Result<(u64, Self::BidiStream)> {
230 match *self {}
231 }
232
233 async fn accept_uni(&self) -> io::Result<(u64, Self::RecvStream)> {
234 match *self {}
235 }
236
237 async fn open_uni(&self) -> io::Result<(u64, Self::SendStream)> {
238 match *self {}
239 }
240
241 async fn open_bidi(&self) -> io::Result<(u64, Self::BidiStream)> {
242 match *self {}
243 }
244
245 fn remote_address(&self) -> SocketAddr {
246 match *self {}
247 }
248
249 fn close(&self, _: u64, _: &[u8]) {
250 match *self {}
251 }
252
253 fn send_datagram(&self, _: &[u8]) -> io::Result<()> {
254 match *self {}
255 }
256
257 async fn recv_datagram<F: FnOnce(&[u8]) + Send>(&self, _: F) -> io::Result<()> {
258 match *self {}
259 }
260
261 fn max_datagram_size(&self) -> Option<usize> {
262 match *self {}
263 }
264}
265
266impl Transport for NoQuic {}
267
268impl AsyncRead for NoQuic {
269 fn poll_read(
270 self: Pin<&mut Self>,
271 _: &mut Context<'_>,
272 _: &mut [u8],
273 ) -> Poll<io::Result<usize>> {
274 match *self.get_mut() {}
275 }
276}
277
278impl AsyncWrite for NoQuic {
279 fn poll_write(self: Pin<&mut Self>, _: &mut Context<'_>, _: &[u8]) -> Poll<io::Result<usize>> {
280 match *self.get_mut() {}
281 }
282
283 fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
284 match *self.get_mut() {}
285 }
286
287 fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
288 match *self.get_mut() {}
289 }
290}
291
292impl QuicEndpoint for () {
293 type Connection = NoQuic;
294
295 async fn accept(&self) -> Option<NoQuic> {
296 None
297 }
298
299 async fn connect(&self, _: SocketAddr, _: &str) -> io::Result<NoQuic> {
300 Err(io::Error::new(
301 io::ErrorKind::Unsupported,
302 "QUIC not configured",
303 ))
304 }
305}
306
307type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
310
311pub type BoxedRecvStream = Box<dyn QuicTransportReceive + Unpin + Send + Sync>;
314
315pub type BoxedSendStream = Box<dyn QuicTransportSend + Unpin + Send + Sync>;
317
318pub type BoxedBidiStream = Box<dyn QuicTransportBidi + Unpin + Send + Sync>;
320
321impl QuicTransportReceive for BoxedRecvStream {
322 fn stop(&mut self, code: u64) {
323 (**self).stop(code);
324 }
325}
326
327impl QuicTransportSend for BoxedSendStream {
328 fn reset(&mut self, code: u64) {
329 (**self).reset(code);
330 }
331}
332
333impl QuicTransportReceive for BoxedBidiStream {
334 fn stop(&mut self, code: u64) {
335 (**self).stop(code);
336 }
337}
338
339impl QuicTransportSend for BoxedBidiStream {
340 fn reset(&mut self, code: u64) {
341 (**self).reset(code);
342 }
343}
344
345impl QuicTransportBidi for BoxedBidiStream {}
346
347impl Transport for BoxedBidiStream {
348 fn set_linger(&mut self, linger: Option<std::time::Duration>) -> io::Result<()> {
349 (**self).set_linger(linger)
350 }
351
352 fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
353 (**self).set_nodelay(nodelay)
354 }
355
356 fn set_ip_ttl(&mut self, ttl: u32) -> io::Result<()> {
357 (**self).set_ip_ttl(ttl)
358 }
359
360 fn peer_addr(&self) -> io::Result<Option<SocketAddr>> {
361 (**self).peer_addr()
362 }
363
364 fn negotiated_alpn(&self) -> Option<std::borrow::Cow<'_, [u8]>> {
365 (**self).negotiated_alpn()
366 }
367}
368
369type ReceiveDatagramCallback<'a> = Box<dyn FnOnce(&[u8]) + Send + 'a>;
370
371trait ObjectSafeQuicConnection: Send + Sync {
372 fn accept_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>>;
373 fn accept_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedRecvStream)>>;
374 fn open_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedSendStream)>>;
375 fn open_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>>;
376 fn remote_address(&self) -> SocketAddr;
377 fn close(&self, error_code: u64, reason: &[u8]);
378 fn send_datagram(&self, data: &[u8]) -> io::Result<()>;
379 fn recv_datagram<'a>(
380 &'a self,
381 callback: ReceiveDatagramCallback<'a>,
382 ) -> BoxedFuture<'a, io::Result<()>>;
383 fn max_datagram_size(&self) -> Option<usize>;
384}
385
386impl<T: QuicConnectionTrait> ObjectSafeQuicConnection for T {
387 fn accept_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>> {
388 Box::pin(async {
389 let (id, stream) = QuicConnectionTrait::accept_bidi(self).await?;
390 Ok((id, Box::new(stream) as BoxedBidiStream))
391 })
392 }
393
394 fn accept_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedRecvStream)>> {
395 Box::pin(async {
396 let (id, stream) = QuicConnectionTrait::accept_uni(self).await?;
397 Ok((id, Box::new(stream) as BoxedRecvStream))
398 })
399 }
400
401 fn open_uni(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedSendStream)>> {
402 Box::pin(async {
403 let (id, stream) = QuicConnectionTrait::open_uni(self).await?;
404 Ok((id, Box::new(stream) as BoxedSendStream))
405 })
406 }
407
408 fn open_bidi(&self) -> BoxedFuture<'_, io::Result<(u64, BoxedBidiStream)>> {
409 Box::pin(async {
410 let (id, stream) = QuicConnectionTrait::open_bidi(self).await?;
411 Ok((id, Box::new(stream) as BoxedBidiStream))
412 })
413 }
414
415 fn remote_address(&self) -> SocketAddr {
416 QuicConnectionTrait::remote_address(self)
417 }
418
419 fn close(&self, error_code: u64, reason: &[u8]) {
420 QuicConnectionTrait::close(self, error_code, reason)
421 }
422
423 fn send_datagram(&self, data: &[u8]) -> io::Result<()> {
424 QuicConnectionTrait::send_datagram(self, data)
425 }
426
427 fn recv_datagram<'a>(
428 &'a self,
429 callback: Box<dyn FnOnce(&[u8]) + Send + 'a>,
430 ) -> BoxedFuture<'a, io::Result<()>> {
431 Box::pin(QuicConnectionTrait::recv_datagram(self, callback))
432 }
433
434 fn max_datagram_size(&self) -> Option<usize> {
435 QuicConnectionTrait::max_datagram_size(self)
436 }
437}
438
439#[derive(Clone)]
445pub struct QuicConnection(Arc<dyn ObjectSafeQuicConnection>);
446
447impl Debug for QuicConnection {
448 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
449 f.debug_struct("QuicConnection")
450 .field("peer", &self.remote_address())
451 .finish_non_exhaustive()
452 }
453}
454
455impl<T: QuicConnectionTrait> From<T> for QuicConnection {
456 fn from(connection: T) -> Self {
457 Self(Arc::new(connection))
458 }
459}
460
461impl QuicConnection {
462 pub async fn accept_bidi(&self) -> io::Result<(u64, BoxedBidiStream)> {
464 self.0.accept_bidi().await
465 }
466
467 pub async fn accept_uni(&self) -> io::Result<(u64, BoxedRecvStream)> {
469 self.0.accept_uni().await
470 }
471
472 pub async fn open_uni(&self) -> io::Result<(u64, BoxedSendStream)> {
474 self.0.open_uni().await
475 }
476
477 pub async fn open_bidi(&self) -> io::Result<(u64, BoxedBidiStream)> {
479 self.0.open_bidi().await
480 }
481
482 pub fn remote_address(&self) -> SocketAddr {
484 self.0.remote_address()
485 }
486
487 pub fn close(&self, error_code: u64, reason: &[u8]) {
489 self.0.close(error_code, reason)
490 }
491
492 pub fn send_datagram(&self, data: &[u8]) -> io::Result<()> {
494 self.0.send_datagram(data)
495 }
496
497 pub async fn recv_datagram<'a, F: FnOnce(&[u8]) + Send + 'a>(
499 &'a self,
500 callback: F,
501 ) -> io::Result<()> {
502 self.0.recv_datagram(Box::new(callback)).await
503 }
504
505 pub fn max_datagram_size(&self) -> Option<usize> {
507 self.0.max_datagram_size()
508 }
509}
510
511trait ObjectSafeQuicEndpoint: Send + Sync {
514 fn accept(&self) -> BoxedFuture<'_, Option<QuicConnection>>;
515 fn connect<'a>(
516 &'a self,
517 addr: SocketAddr,
518 server_name: &'a str,
519 ) -> BoxedFuture<'a, io::Result<QuicConnection>>;
520 fn local_addr(&self) -> io::Result<SocketAddr>;
521}
522
523impl<T: QuicEndpoint> ObjectSafeQuicEndpoint for T {
524 fn accept(&self) -> BoxedFuture<'_, Option<QuicConnection>> {
525 Box::pin(async { QuicEndpoint::accept(self).await.map(QuicConnection::from) })
526 }
527
528 fn connect<'a>(
529 &'a self,
530 addr: SocketAddr,
531 server_name: &'a str,
532 ) -> BoxedFuture<'a, io::Result<QuicConnection>> {
533 Box::pin(async move {
534 QuicEndpoint::connect(self, addr, server_name)
535 .await
536 .map(QuicConnection::from)
537 })
538 }
539
540 fn local_addr(&self) -> io::Result<SocketAddr> {
541 QuicEndpoint::local_addr(self)
542 }
543}
544
545#[derive(Clone)]
548pub struct ArcedQuicEndpoint(Arc<dyn ObjectSafeQuicEndpoint>);
549
550impl Debug for ArcedQuicEndpoint {
551 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
552 f.debug_tuple("ArcedQuicEndpoint").finish()
553 }
554}
555
556impl<T: QuicEndpoint> From<T> for ArcedQuicEndpoint {
557 fn from(endpoint: T) -> Self {
558 Self(Arc::new(endpoint))
559 }
560}
561
562impl ArcedQuicEndpoint {
563 pub async fn accept(&self) -> Option<QuicConnection> {
565 self.0.accept().await
566 }
567
568 pub async fn connect(&self, addr: SocketAddr, server_name: &str) -> io::Result<QuicConnection> {
570 self.0.connect(addr, server_name).await
571 }
572
573 pub fn local_addr(&self) -> io::Result<SocketAddr> {
575 self.0.local_addr()
576 }
577}