use std::io;
use std::mem::ManuallyDrop;
use std::net::IpAddr;
#[cfg(not(target_os = "windows"))]
use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd};
#[cfg(not(target_os = "windows"))]
use crate::Tap;
use crate::{AddAddress, AddressInfo};
use crate::{DeviceState, Interface};
use mio::event::Source;
use mio::net::UdpSocket;
use mio::{Interest, Registry, Token};
pub struct AsyncTap {
#[cfg(not(target_os = "windows"))]
tap: Tap,
io: ManuallyDrop<UdpSocket>,
}
impl AsyncTap {
#[inline]
pub fn new() -> io::Result<Self> {
let mut tap = Tap::new()?;
tap.set_nonblocking(true)?;
let io = unsafe { UdpSocket::from_raw_fd(tap.as_raw_fd()) };
Ok(Self {
tap,
io: ManuallyDrop::new(io),
})
}
#[inline]
pub fn new_named(if_name: Interface) -> io::Result<Self> {
let mut tap = Tap::new_named(if_name)?;
tap.set_nonblocking(true)?;
let io = unsafe { UdpSocket::from_raw_fd(tap.as_raw_fd()) };
Ok(Self {
tap,
io: ManuallyDrop::new(io),
})
}
#[inline]
pub fn name(&self) -> io::Result<Interface> {
self.tap.name()
}
#[inline]
pub fn set_state(&mut self, state: DeviceState) -> io::Result<()> {
self.tap.set_state(state)
}
#[inline]
pub fn set_up(&mut self) -> io::Result<()> {
self.tap.set_state(DeviceState::Up)
}
#[inline]
pub fn set_down(&mut self) -> io::Result<()> {
self.tap.set_state(DeviceState::Down)
}
#[inline]
pub fn mtu(&self) -> io::Result<usize> {
self.tap.mtu()
}
#[inline]
pub fn addrs(&self) -> io::Result<Vec<AddressInfo>> {
self.tap.addrs()
}
#[inline]
pub fn add_addr<A: Into<AddAddress>>(&self, req: A) -> io::Result<()> {
self.tap.add_addr(req)
}
#[inline]
pub fn remove_addr(&self, addr: IpAddr) -> io::Result<()> {
self.tap.remove_addr(addr)
}
#[inline]
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
self.tap.send(buf)
}
#[inline]
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
self.io.recv(buf)
}
}
impl Source for AsyncTap {
fn register(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
self.io.register(registry, token, interests)
}
fn reregister(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
self.io.reregister(registry, token, interests)
}
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
self.io.deregister(registry)
}
}
impl Drop for AsyncTap {
fn drop(&mut self) {
let io = unsafe { ManuallyDrop::take(&mut self.io) };
let _ = io.into_raw_fd();
}
}