iroh_quinn/runtime/
smol.rs

1use std::{
2    future::Future,
3    num::NonZeroUsize,
4    pin::Pin,
5    task::{Context, Poll},
6    time::Instant,
7};
8use std::{io, sync::Arc, task::ready};
9
10use async_io::Async;
11use async_io::Timer;
12
13use super::AsyncTimer;
14use super::{AsyncUdpSocket, Runtime, UdpSender, UdpSenderHelper, UdpSenderHelperSocket};
15
16/// A Quinn runtime for smol
17#[derive(Debug)]
18pub struct SmolRuntime;
19
20impl Runtime for SmolRuntime {
21    fn new_timer(&self, t: Instant) -> Pin<Box<dyn AsyncTimer>> {
22        Box::pin(Timer::at(t))
23    }
24
25    fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send>>) {
26        ::smol::spawn(future).detach();
27    }
28
29    fn wrap_udp_socket(&self, sock: std::net::UdpSocket) -> io::Result<Box<dyn AsyncUdpSocket>> {
30        Ok(Box::new(UdpSocket::new(sock)?))
31    }
32}
33
34impl AsyncTimer for Timer {
35    fn reset(mut self: Pin<&mut Self>, t: Instant) {
36        self.set_at(t)
37    }
38
39    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
40        Future::poll(self, cx).map(|_| ())
41    }
42}
43
44#[derive(Debug, Clone)]
45struct UdpSocket {
46    io: Arc<Async<std::net::UdpSocket>>,
47    inner: Arc<udp::UdpSocketState>,
48}
49
50impl UdpSocket {
51    fn new(sock: std::net::UdpSocket) -> io::Result<Self> {
52        Ok(Self {
53            inner: Arc::new(udp::UdpSocketState::new((&sock).into())?),
54            io: Arc::new(Async::new_nonblocking(sock)?),
55        })
56    }
57}
58
59impl UdpSenderHelperSocket for UdpSocket {
60    fn max_transmit_segments(&self) -> NonZeroUsize {
61        self.inner.max_gso_segments()
62    }
63
64    fn try_send(&self, transmit: &udp::Transmit) -> io::Result<()> {
65        self.inner.send((&self.io).into(), transmit)
66    }
67}
68
69impl AsyncUdpSocket for UdpSocket {
70    fn create_sender(&self) -> Pin<Box<dyn UdpSender>> {
71        Box::pin(UdpSenderHelper::new(self.clone(), |socket: &Self| {
72            let socket = socket.clone();
73            async move { socket.io.writable().await }
74        }))
75    }
76
77    fn poll_recv(
78        &mut self,
79        cx: &mut Context,
80        bufs: &mut [io::IoSliceMut<'_>],
81        meta: &mut [udp::RecvMeta],
82    ) -> Poll<io::Result<usize>> {
83        loop {
84            ready!(self.io.poll_readable(cx))?;
85            if let Ok(res) = self.inner.recv((&self.io).into(), bufs, meta) {
86                return Poll::Ready(Ok(res));
87            }
88        }
89    }
90
91    fn local_addr(&self) -> io::Result<std::net::SocketAddr> {
92        self.io.as_ref().as_ref().local_addr()
93    }
94
95    fn may_fragment(&self) -> bool {
96        self.inner.may_fragment()
97    }
98
99    fn max_receive_segments(&self) -> NonZeroUsize {
100        self.inner.gro_segments()
101    }
102}