Skip to main content

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}