use super::*;
use std::io;
use std::ops::{Index, IndexMut, RangeBounds};
use std::slice::{Iter, IterMut, SliceIndex};
use std::vec::{Drain, IntoIter};
use futures_util::future::select_all;
pub struct TokioTun {
queues: Vec<TokioQueue>,
name: String,
}
impl TokioTun {
pub fn new(name: &str, num_queues: usize) -> Result<Self> {
if num_queues < 1 {
return Err(Error::InvalidNumQueues);
}
let (queues, name) = new_queues(name, num_queues)?;
Ok(Self { queues, name })
}
#[inline]
pub fn name(&self) -> &str {
self.name.as_str()
}
#[inline]
pub fn get<I>(&self, index: I) -> Option<&I::Output>
where
I: SliceIndex<[TokioQueue]>,
{
self.queues.get(index)
}
#[inline]
pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
where
I: SliceIndex<[TokioQueue]>,
{
self.queues.get_mut(index)
}
pub fn close(&mut self) -> Result<()> {
for mut queue in self.drain(..) {
queue.close()?;
}
Ok(())
}
#[inline]
pub fn drain<R>(&mut self, range: R) -> Drain<TokioQueue>
where
R: RangeBounds<usize>,
{
self.queues.drain(range)
}
#[inline]
pub fn iter(&self) -> Iter<TokioQueue> {
self.queues.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<TokioQueue> {
self.queues.iter_mut()
}
pub async fn send(&self, datagram: &[u8]) -> io::Result<usize> {
loop {
let futures = self.iter().map(|queue| Box::pin(queue.writable()));
let (result, _, _) = select_all(futures).await;
let mut guard = match result {
Ok(guard) => guard,
Err(e) => return Err(e),
};
match guard.try_io(|queue| queue.get_ref().send(datagram)) {
Ok(res) => return res,
Err(_) => continue,
};
}
}
pub async fn send_via(&self, queue: usize, datagram: &[u8]) -> io::Result<usize> {
self.get(queue)
.ok_or_else(|| Error::InvalidQueue(queue).into_io())?
.send(datagram)
.await
}
pub async fn recv(&self, datagram: &mut [u8]) -> io::Result<usize> {
loop {
let futures = self.iter().map(|queue| Box::pin(queue.readable()));
let (result, _, _) = select_all(futures).await;
let mut guard = match result {
Ok(guard) => guard,
Err(e) => return Err(e),
};
match guard.try_io(|queue| queue.get_ref().recv(datagram)) {
Ok(res) => return res,
Err(_) => continue,
};
}
}
pub async fn recv_via(&self, queue: usize, datagram: &mut [u8]) -> io::Result<usize> {
self.get(queue)
.ok_or_else(|| Error::InvalidQueue(queue).into_io())?
.recv(datagram)
.await
}
}
impl IntoIterator for TokioTun {
type Item = TokioQueue;
type IntoIter = IntoIter<TokioQueue>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.queues.into_iter()
}
}
impl Index<usize> for TokioTun {
type Output = TokioQueue;
#[inline]
fn index(&self, index: usize) -> &TokioQueue {
self.queues.index(index)
}
}
impl IndexMut<usize> for TokioTun {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut TokioQueue {
self.queues.index_mut(index)
}
}