quinn/runtime/
async_io.rs

1use std::{
2    future::Future,
3    pin::Pin,
4    task::{Context, Poll},
5    time::Instant,
6};
7#[cfg(any(feature = "runtime-smol", feature = "runtime-async-std"))]
8use std::{io, sync::Arc, task::ready};
9
10#[cfg(any(feature = "runtime-smol", feature = "runtime-async-std"))]
11use async_io::Async;
12use async_io::Timer;
13
14use super::AsyncTimer;
15#[cfg(any(feature = "runtime-smol", feature = "runtime-async-std"))]
16use super::{AsyncUdpSocket, Runtime, UdpPollHelper};
17
18#[cfg(feature = "runtime-smol")]
19// Due to MSRV, we must specify `self::` where there's crate/module ambiguity
20pub use self::smol::SmolRuntime;
21
22#[cfg(feature = "runtime-smol")]
23mod smol {
24    use super::*;
25
26    /// A Quinn runtime for smol
27    #[derive(Debug)]
28    pub struct SmolRuntime;
29
30    impl Runtime for SmolRuntime {
31        fn new_timer(&self, t: Instant) -> Pin<Box<dyn AsyncTimer>> {
32            Box::pin(Timer::at(t))
33        }
34
35        fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send>>) {
36            ::smol::spawn(future).detach();
37        }
38
39        fn wrap_udp_socket(
40            &self,
41            sock: std::net::UdpSocket,
42        ) -> io::Result<Arc<dyn AsyncUdpSocket>> {
43            Ok(Arc::new(UdpSocket::new(sock)?))
44        }
45    }
46}
47
48#[cfg(feature = "runtime-async-std")]
49// Due to MSRV, we must specify `self::` where there's crate/module ambiguity
50pub use self::async_std::AsyncStdRuntime;
51
52#[cfg(feature = "runtime-async-std")]
53mod async_std {
54    use super::*;
55
56    /// A Quinn runtime for async-std
57    #[derive(Debug)]
58    pub struct AsyncStdRuntime;
59
60    impl Runtime for AsyncStdRuntime {
61        fn new_timer(&self, t: Instant) -> Pin<Box<dyn AsyncTimer>> {
62            Box::pin(Timer::at(t))
63        }
64
65        fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send>>) {
66            ::async_std::task::spawn(future);
67        }
68
69        fn wrap_udp_socket(
70            &self,
71            sock: std::net::UdpSocket,
72        ) -> io::Result<Arc<dyn AsyncUdpSocket>> {
73            Ok(Arc::new(UdpSocket::new(sock)?))
74        }
75    }
76}
77
78impl AsyncTimer for Timer {
79    fn reset(mut self: Pin<&mut Self>, t: Instant) {
80        self.set_at(t)
81    }
82
83    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
84        Future::poll(self, cx).map(|_| ())
85    }
86}
87
88#[cfg(any(feature = "runtime-smol", feature = "runtime-async-std"))]
89#[derive(Debug)]
90struct UdpSocket {
91    io: Async<std::net::UdpSocket>,
92    inner: udp::UdpSocketState,
93}
94
95#[cfg(any(feature = "runtime-smol", feature = "runtime-async-std"))]
96impl UdpSocket {
97    fn new(sock: std::net::UdpSocket) -> io::Result<Self> {
98        Ok(Self {
99            inner: udp::UdpSocketState::new((&sock).into())?,
100            io: Async::new_nonblocking(sock)?,
101        })
102    }
103}
104
105#[cfg(any(feature = "runtime-smol", feature = "runtime-async-std"))]
106impl AsyncUdpSocket for UdpSocket {
107    fn create_io_poller(self: Arc<Self>) -> Pin<Box<dyn super::UdpPoller>> {
108        Box::pin(UdpPollHelper::new(move || {
109            let socket = self.clone();
110            async move { socket.io.writable().await }
111        }))
112    }
113
114    fn try_send(&self, transmit: &udp::Transmit) -> io::Result<()> {
115        self.inner.send((&self.io).into(), transmit)
116    }
117
118    fn poll_recv(
119        &self,
120        cx: &mut Context,
121        bufs: &mut [io::IoSliceMut<'_>],
122        meta: &mut [udp::RecvMeta],
123    ) -> Poll<io::Result<usize>> {
124        loop {
125            ready!(self.io.poll_readable(cx))?;
126            if let Ok(res) = self.inner.recv((&self.io).into(), bufs, meta) {
127                return Poll::Ready(Ok(res));
128            }
129        }
130    }
131
132    fn local_addr(&self) -> io::Result<std::net::SocketAddr> {
133        self.io.as_ref().local_addr()
134    }
135
136    fn may_fragment(&self) -> bool {
137        self.inner.may_fragment()
138    }
139
140    fn max_transmit_segments(&self) -> usize {
141        self.inner.max_gso_segments()
142    }
143
144    fn max_receive_segments(&self) -> usize {
145        self.inner.gro_segments()
146    }
147}