use std::io;
#[cfg(not(target_os = "windows"))]
use std::net::IpAddr;
#[cfg(not(target_os = "windows"))]
use crate::{AddAddress, AddressInfo};
use crate::{DeviceState, Interface, Tap};
#[cfg(not(target_os = "windows"))]
use async_io::Async;
#[cfg(target_os = "windows")]
struct TapWrapper(Tap);
#[cfg(target_os = "windows")]
impl TapWrapper {
#[inline]
pub fn get_ref(&self) -> &Tap {
&self.0
}
#[inline]
pub fn get_mut(&mut self) -> &mut Tap {
&mut self.0
}
}
pub struct AsyncTap {
#[cfg(not(target_os = "windows"))]
tap: Async<Tap>,
#[cfg(target_os = "windows")]
tap: TapWrapper,
}
impl AsyncTap {
#[inline]
pub fn new() -> io::Result<Self> {
Self::new_impl()
}
#[cfg(not(target_os = "windows"))]
fn new_impl() -> io::Result<Self> {
let mut tap = Tap::new()?;
tap.set_nonblocking(true)?;
Ok(Self {
tap: Async::new(tap)?,
})
}
#[cfg(target_os = "windows")]
fn new_impl() -> io::Result<Self> {
let mut tap = Tap::new()?;
Ok(Self {
tap: TapWrapper(tap),
})
}
#[inline]
pub fn new_named(if_name: Interface) -> io::Result<Self> {
Self::new_named_impl(if_name)
}
#[cfg(not(target_os = "windows"))]
pub fn new_named_impl(if_name: Interface) -> io::Result<Self> {
let mut tap = Tap::new_named(if_name)?;
tap.set_nonblocking(true)?;
Ok(Self {
tap: Async::new(tap)?,
})
}
#[cfg(target_os = "windows")]
pub fn new_named_impl(if_name: Interface) -> io::Result<Self> {
let mut tap = Tap::new_named(if_name)?;
Ok(Self {
tap: TapWrapper(tap),
})
}
#[inline]
pub fn name(&self) -> io::Result<Interface> {
self.tap.get_ref().name()
}
#[inline]
pub fn set_state(&mut self, state: DeviceState) -> io::Result<()> {
unsafe { self.tap.get_mut().set_state(state) }
}
#[inline]
pub fn set_up(&mut self) -> io::Result<()> {
unsafe { self.tap.get_mut().set_state(DeviceState::Up) }
}
#[inline]
pub fn set_down(&mut self) -> io::Result<()> {
unsafe { self.tap.get_mut().set_state(DeviceState::Down) }
}
#[inline]
pub fn mtu(&self) -> io::Result<usize> {
self.tap.get_ref().mtu()
}
#[cfg(not(target_os = "windows"))]
#[inline]
pub fn addrs(&self) -> io::Result<Vec<AddressInfo>> {
self.tap.get_ref().addrs()
}
#[cfg(not(target_os = "windows"))]
#[inline]
pub fn add_addr<A: Into<AddAddress>>(&self, req: A) -> io::Result<()> {
self.tap.get_ref().add_addr(req)
}
#[cfg(not(target_os = "windows"))]
#[inline]
pub fn remove_addr(&self, addr: IpAddr) -> io::Result<()> {
self.tap.get_ref().remove_addr(addr)
}
#[inline]
pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
self.send_impl(buf).await
}
#[cfg(not(target_os = "windows"))]
#[inline]
async fn send_impl(&self, buf: &[u8]) -> io::Result<usize> {
self.tap.write_with(|inner| inner.send(buf)).await
}
#[cfg(target_os = "windows")]
#[inline]
async fn send_impl(&self, buf: &[u8]) -> io::Result<usize> {
async_std::task::spawn_blocking(|| self.tap.get_ref().send(buf)).await
}
#[inline]
pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
self.recv_impl(buf).await
}
#[cfg(not(target_os = "windows"))]
pub async fn recv_impl(&self, buf: &mut [u8]) -> io::Result<usize> {
self.tap.read_with(|inner| inner.recv(buf)).await
}
#[cfg(target_os = "windows")]
pub async fn recv_impl(&self, buf: &mut [u8]) -> io::Result<usize> {
async_std::task::spawn_blocking(|| self.tap.get_ref().recv(buf)).await
}
}