tun_rs/async_device/unix/tokio.rs
1use std::io;
2use std::task::{Context, Poll};
3
4use crate::platform::DeviceImpl;
5use ::tokio::io::unix::AsyncFd as TokioAsyncFd;
6use ::tokio::io::Interest;
7use bytes::buf::UninitSlice;
8
9/// An async Tun/Tap device wrapper around a Tun/Tap device.
10///
11/// This type does not provide a split method, because this functionality can be achieved by instead wrapping the socket in an Arc.
12///
13/// # Streams
14///
15/// If you need to produce a `Stream`, you can look at `DeviceFramed`.
16///
17/// **Note:** `DeviceFramed` is only available when the `async_framed` feature is enabled.
18///
19/// [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html
20///
21/// # Examples
22///
23/// ```no_run
24/// use tun_rs::{AsyncDevice, DeviceBuilder};
25///
26/// #[tokio::main]
27/// async fn main() -> std::io::Result<()> {
28/// // Create a TUN device with basic configuration
29/// let dev = DeviceBuilder::new()
30/// .name("tun0")
31/// .mtu(1500)
32/// .ipv4("10.0.0.1", "255.255.255.0", None)
33/// .build_async()?;
34///
35/// // Send a simple packet (Replace with real IP message)
36/// let packet = b"[IP Packet: 10.0.0.1 -> 10.0.0.2] Hello, Async TUN!";
37/// dev.send(packet).await?;
38///
39/// // Receive a packet
40/// let mut buf = [0u8; 1500];
41/// let n = dev.recv(&mut buf).await?;
42/// println!("Received {} bytes: {:?}", n, &buf[..n]);
43///
44/// Ok(())
45/// }
46/// ```
47pub struct AsyncDevice(pub(crate) TokioAsyncFd<DeviceImpl>);
48impl AsyncDevice {
49 /// Polls the I/O handle for readability.
50 ///
51 /// # Caveats
52 ///
53 /// Note that on multiple calls to a `poll_*` method in the `recv` direction, only the
54 /// `Waker` from the `Context` passed to the most recent call will be scheduled to
55 /// receive a wakeup.
56 ///
57 /// # Return value
58 ///
59 /// The function returns:
60 ///
61 /// * `Poll::Pending` if the device is not ready for reading.
62 /// * `Poll::Ready(Ok(()))` if the device is ready for reading.
63 /// * `Poll::Ready(Err(e))` if an error is encountered.
64 ///
65 /// # Errors
66 ///
67 /// This function may encounter any standard I/O error except `WouldBlock`.
68 pub fn poll_readable(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
69 self.0.poll_read_ready(cx).map_ok(|_| ())
70 }
71 /// Attempts to receive a single packet from the device
72 ///
73 /// # Caveats
74 ///
75 /// Note that on multiple calls to a `poll_*` method in the `recv` direction, only the
76 /// `Waker` from the `Context` passed to the most recent call will be scheduled to
77 /// receive a wakeup.
78 ///
79 /// # Return value
80 ///
81 /// The function returns:
82 ///
83 /// * `Poll::Pending` if the device is not ready to read
84 /// * `Poll::Ready(Ok(()))` reads data `buf` if the device is ready
85 /// * `Poll::Ready(Err(e))` if an error is encountered.
86 ///
87 /// # Errors
88 ///
89 /// This function may encounter any standard I/O error except `WouldBlock`.
90 pub fn poll_recv(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> {
91 loop {
92 return match self.0.poll_read_ready(cx) {
93 Poll::Ready(Ok(mut rs)) => {
94 let n = match rs.try_io(|dev| dev.get_ref().recv(buf)) {
95 Ok(rs) => rs?,
96 Err(_) => continue,
97 };
98 Poll::Ready(Ok(n))
99 }
100 Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
101 Poll::Pending => Poll::Pending,
102 };
103 }
104 }
105
106 #[allow(dead_code)]
107 pub(crate) fn poll_recv_uninit(
108 &self,
109 cx: &mut Context<'_>,
110 buf: &mut UninitSlice,
111 ) -> Poll<io::Result<usize>> {
112 loop {
113 return match self.0.poll_read_ready(cx) {
114 Poll::Ready(Ok(mut rs)) => {
115 let n = match rs.try_io(|dev| dev.get_ref().recv_uninit(buf)) {
116 Ok(rs) => rs?,
117 Err(_) => continue,
118 };
119 Poll::Ready(Ok(n))
120 }
121 Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
122 Poll::Pending => Poll::Pending,
123 };
124 }
125 }
126
127 /// Polls the I/O handle for writability.
128 ///
129 /// # Caveats
130 ///
131 /// Note that on multiple calls to a `poll_*` method in the send direction,
132 /// only the `Waker` from the `Context` passed to the most recent call will
133 /// be scheduled to receive a wakeup.
134 ///
135 /// # Return value
136 ///
137 /// The function returns:
138 ///
139 /// * `Poll::Pending` if the device is not ready for writing.
140 /// * `Poll::Ready(Ok(()))` if the device is ready for writing.
141 /// * `Poll::Ready(Err(e))` if an error is encountered.
142 ///
143 /// # Errors
144 ///
145 /// This function may encounter any standard I/O error except `WouldBlock`.
146 pub fn poll_writable(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
147 self.0.poll_write_ready(cx).map_ok(|_| ())
148 }
149 /// Attempts to send packet to the device
150 ///
151 /// # Caveats
152 ///
153 /// Note that on multiple calls to a `poll_*` method in the send direction,
154 /// only the `Waker` from the `Context` passed to the most recent call will
155 /// be scheduled to receive a wakeup.
156 ///
157 /// # Return value
158 ///
159 /// The function returns:
160 ///
161 /// * `Poll::Pending` if the device is not available to write
162 /// * `Poll::Ready(Ok(n))` `n` is the number of bytes sent
163 /// * `Poll::Ready(Err(e))` if an error is encountered.
164 ///
165 /// # Errors
166 ///
167 /// This function may encounter any standard I/O error except `WouldBlock`.
168 pub fn poll_send(&self, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
169 loop {
170 return match self.0.poll_write_ready(cx) {
171 Poll::Ready(Ok(mut rs)) => {
172 let n = match rs.try_io(|dev| dev.get_ref().send(buf)) {
173 Ok(rs) => rs?,
174 Err(_) => continue,
175 };
176 Poll::Ready(Ok(n))
177 }
178 Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
179 Poll::Pending => Poll::Pending,
180 };
181 }
182 }
183}
184
185impl AsyncDevice {
186 pub(crate) fn new_dev(device: DeviceImpl) -> io::Result<Self> {
187 device.set_nonblocking(true)?;
188 Ok(Self(TokioAsyncFd::new(device)?))
189 }
190 pub(crate) fn into_device(self) -> io::Result<DeviceImpl> {
191 Ok(self.0.into_inner())
192 }
193
194 pub(crate) async fn read_with<R>(
195 &self,
196 mut op: impl FnMut(&DeviceImpl) -> io::Result<R>,
197 ) -> io::Result<R> {
198 self.0
199 .async_io(Interest::READABLE, |device| op(device))
200 .await
201 }
202 pub(crate) async fn write_with<R>(
203 &self,
204 mut op: impl FnMut(&DeviceImpl) -> io::Result<R>,
205 ) -> io::Result<R> {
206 self.0
207 .async_io(Interest::WRITABLE, |device| op(device))
208 .await
209 }
210
211 pub(crate) fn try_read_io<R>(
212 &self,
213 f: impl FnOnce(&DeviceImpl) -> io::Result<R>,
214 ) -> io::Result<R> {
215 self.0.try_io(Interest::READABLE, |device| f(device))
216 }
217
218 pub(crate) fn try_write_io<R>(
219 &self,
220 f: impl FnOnce(&DeviceImpl) -> io::Result<R>,
221 ) -> io::Result<R> {
222 self.0.try_io(Interest::WRITABLE, |device| f(device))
223 }
224
225 pub(crate) fn get_ref(&self) -> &DeviceImpl {
226 self.0.get_ref()
227 }
228}