iroh_quinn/runtime/
smol.rs1use 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#[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}