#[cfg(target_os = "windows")]
use std::borrow::ToOwned;
use std::io;
#[cfg(target_os = "windows")]
use std::sync::Arc;
#[cfg(not(target_os = "windows"))]
use async_io::Async;
use crate::filter::PacketFilter;
use crate::{Interface, Sniffer};
#[cfg(target_os = "windows")]
#[derive(Clone)]
struct SnifferWrapper(Arc<Sniffer>);
#[cfg(target_os = "windows")]
impl SnifferWrapper {
fn get_ref(&self) -> &Sniffer {
self.0.as_ref()
}
unsafe fn get_mut(&mut self) -> &mut Sniffer {
Arc::<Sniffer>::get_mut(&mut self.0).unwrap()
}
}
pub struct AsyncSniffer {
#[cfg(not(target_os = "windows"))]
sniffer: Async<Sniffer>,
#[cfg(target_os = "windows")]
sniffer: SnifferWrapper,
}
impl AsyncSniffer {
#[inline]
pub fn new(iface: Interface) -> io::Result<Self> {
Self::new_impl(iface)
}
#[cfg(not(target_os = "windows"))]
fn new_impl(iface: Interface) -> io::Result<Self> {
let sniffer = Sniffer::new(iface)?;
sniffer.set_nonblocking(true)?;
Ok(Self {
sniffer: Async::new(sniffer)?,
})
}
#[cfg(target_os = "windows")]
fn new_impl(iface: Interface) -> io::Result<Self> {
let sniffer = Sniffer::new(iface)?;
Ok(Self {
sniffer: SnifferWrapper(Arc::new(sniffer)),
})
}
#[inline]
pub fn activate(&mut self, filter: Option<PacketFilter>) -> io::Result<()> {
unsafe { self.sniffer.get_mut().activate(filter) }
}
pub fn deactivate(&mut self) -> io::Result<()> {
unsafe { self.sniffer.get_mut().deactivate() }
}
#[inline]
pub fn nonblocking(&self) -> io::Result<bool> {
self.sniffer.get_ref().nonblocking()
}
#[inline]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.sniffer.get_ref().set_nonblocking(nonblocking)
}
#[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.sniffer.write_with(|inner| inner.send(buf)).await
}
#[cfg(target_os = "windows")]
#[inline]
async fn send_impl(&self, buf: &[u8]) -> io::Result<usize> {
let arc = self.sniffer.clone();
let buf = buf.to_owned();
async_std::task::spawn_blocking(move || arc.get_ref().send(buf.as_slice())).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.sniffer.read_with(|inner| inner.recv(buf)).await
}
#[cfg(target_os = "windows")]
pub async fn recv_impl(&self, buf: &mut [u8]) -> io::Result<usize> {
let arc = self.sniffer.clone();
let buflen = buf.len();
let (res, data) = async_std::task::spawn_blocking(move || {
let mut buf = vec![0; buflen];
let res = arc.get_ref().recv(buf.as_mut_slice());
(res, buf)
})
.await;
match res {
Ok(len) => {
buf[..len].copy_from_slice(&data[..len]);
Ok(len)
}
err => err,
}
}
}