quinn/runtime/
async_io.rs1use 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")]
19pub use self::smol::SmolRuntime;
21
22#[cfg(feature = "runtime-smol")]
23mod smol {
24 use super::*;
25
26 #[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")]
49pub use self::async_std::AsyncStdRuntime;
51
52#[cfg(feature = "runtime-async-std")]
53mod async_std {
54 use super::*;
55
56 #[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}