#[cfg(unix)]
pub(crate) mod unix;
#[cfg(all(
unix,
not(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))
))]
pub use self::unix::DeviceImpl;
#[cfg(unix)]
#[cfg(feature = "interruptible")]
pub use unix::InterruptEvent;
#[cfg(windows)]
#[cfg(feature = "interruptible")]
pub use windows::InterruptEvent;
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
pub(crate) mod linux;
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
pub use self::linux::*;
#[cfg(target_os = "freebsd")]
pub(crate) mod freebsd;
#[cfg(target_os = "freebsd")]
pub use self::freebsd::DeviceImpl;
#[cfg(target_os = "macos")]
pub(crate) mod macos;
#[cfg(target_os = "macos")]
pub use self::macos::DeviceImpl;
#[cfg(target_os = "openbsd")]
pub(crate) mod openbsd;
#[cfg(target_os = "openbsd")]
pub use self::openbsd::DeviceImpl;
#[cfg(target_os = "netbsd")]
pub(crate) mod netbsd;
#[cfg(target_os = "netbsd")]
pub use self::netbsd::DeviceImpl;
#[cfg(target_os = "windows")]
pub(crate) mod windows;
#[cfg(target_os = "windows")]
pub use self::windows::DeviceImpl;
#[cfg(target_vendor = "apple")]
pub mod apple;
use getifaddrs::Interface;
#[cfg(unix)]
use std::io::{IoSlice, IoSliceMut};
use std::ops::Deref;
#[cfg(unix)]
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
#[allow(dead_code)]
pub(crate) const ETHER_ADDR_LEN: u8 = 6;
#[allow(dead_code)]
pub(crate) fn get_if_addrs_by_name(if_name: String) -> std::io::Result<Vec<Interface>> {
let addrs = getifaddrs::getifaddrs()?;
let ifs = addrs.filter(|v| v.name == if_name).collect();
Ok(ifs)
}
#[repr(transparent)]
pub struct SyncDevice(pub(crate) DeviceImpl);
impl SyncDevice {
#[cfg(unix)]
pub unsafe fn from_fd(fd: RawFd) -> std::io::Result<Self> {
Ok(SyncDevice(DeviceImpl::from_fd(fd)?))
}
#[cfg(unix)]
pub(crate) unsafe fn borrow_raw(fd: RawFd) -> std::io::Result<Self> {
Ok(SyncDevice(DeviceImpl::borrow_raw(fd)?))
}
#[inline]
pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
self.0.recv(buf)
}
#[inline]
pub fn send(&self, buf: &[u8]) -> std::io::Result<usize> {
self.0.send(buf)
}
#[cfg(target_os = "windows")]
#[inline]
pub fn try_recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
self.0.try_recv(buf)
}
#[cfg(target_os = "windows")]
#[inline]
pub fn try_send(&self, buf: &[u8]) -> std::io::Result<usize> {
self.0.try_send(buf)
}
#[cfg(target_os = "windows")]
pub fn shutdown(&self) -> std::io::Result<()> {
self.0.shutdown()
}
#[cfg(all(unix, feature = "experimental"))]
pub fn shutdown(&self) -> std::io::Result<()> {
Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
}
#[cfg(feature = "interruptible")]
pub fn recv_intr(&self, buf: &mut [u8], event: &InterruptEvent) -> std::io::Result<usize> {
self.0.read_interruptible(buf, event, None)
}
#[cfg(feature = "interruptible")]
pub fn recv_intr_timeout(
&self,
buf: &mut [u8],
event: &InterruptEvent,
timeout: Option<std::time::Duration>,
) -> std::io::Result<usize> {
self.0.read_interruptible(buf, event, timeout)
}
#[cfg(all(unix, feature = "interruptible"))]
pub fn recv_vectored_intr(
&self,
bufs: &mut [IoSliceMut<'_>],
event: &InterruptEvent,
) -> std::io::Result<usize> {
self.0.readv_interruptible(bufs, event, None)
}
#[cfg(all(unix, feature = "interruptible"))]
pub fn recv_vectored_intr_timeout(
&self,
bufs: &mut [IoSliceMut<'_>],
event: &InterruptEvent,
timeout: Option<std::time::Duration>,
) -> std::io::Result<usize> {
self.0.readv_interruptible(bufs, event, timeout)
}
#[cfg(feature = "interruptible")]
pub fn wait_readable_intr(&self, event: &InterruptEvent) -> std::io::Result<()> {
self.0.wait_readable_interruptible(event, None)
}
#[cfg(feature = "interruptible")]
pub fn wait_readable_intr_timeout(
&self,
event: &InterruptEvent,
timeout: Option<std::time::Duration>,
) -> std::io::Result<()> {
self.0.wait_readable_interruptible(event, timeout)
}
#[cfg(feature = "interruptible")]
pub fn send_intr(&self, buf: &[u8], event: &InterruptEvent) -> std::io::Result<usize> {
self.0.write_interruptible(buf, event)
}
#[cfg(all(unix, feature = "interruptible"))]
pub fn send_vectored_intr(
&self,
bufs: &[IoSlice<'_>],
event: &InterruptEvent,
) -> std::io::Result<usize> {
self.0.writev_interruptible(bufs, event)
}
#[cfg(all(unix, feature = "interruptible"))]
#[inline]
pub fn wait_writable_intr(&self, event: &InterruptEvent) -> std::io::Result<()> {
self.0.wait_writable_interruptible(event)
}
#[cfg(unix)]
pub fn recv_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> std::io::Result<usize> {
self.0.recv_vectored(bufs)
}
#[cfg(unix)]
pub fn send_vectored(&self, bufs: &[IoSlice<'_>]) -> std::io::Result<usize> {
self.0.send_vectored(bufs)
}
#[cfg(unix)]
pub fn is_nonblocking(&self) -> std::io::Result<bool> {
self.0.is_nonblocking()
}
#[cfg(unix)]
pub fn set_nonblocking(&self, nonblocking: bool) -> std::io::Result<()> {
self.0.set_nonblocking(nonblocking)
}
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
pub fn try_clone(&self) -> std::io::Result<SyncDevice> {
let device_impl = self.0.try_clone()?;
Ok(SyncDevice(device_impl))
}
}
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
impl SyncDevice {
#[cfg(feature = "interruptible")]
pub fn send_multiple_intr<B: ExpandBuffer>(
&self,
gro_table: &mut GROTable,
bufs: &mut [B],
offset: usize,
event: &InterruptEvent,
) -> std::io::Result<usize> {
self.send_multiple0(gro_table, bufs, offset, |tun, buf| {
tun.write_interruptible(buf, event)
})
}
#[cfg(feature = "interruptible")]
pub fn recv_multiple_intr<B: AsRef<[u8]> + AsMut<[u8]>>(
&self,
original_buffer: &mut [u8],
bufs: &mut [B],
sizes: &mut [usize],
offset: usize,
event: &InterruptEvent,
) -> std::io::Result<usize> {
self.recv_multiple0(original_buffer, bufs, sizes, offset, |tun, buf| {
tun.read_interruptible(buf, event, None)
})
}
}
impl Deref for SyncDevice {
type Target = DeviceImpl;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(unix)]
impl FromRawFd for SyncDevice {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
SyncDevice::from_fd(fd).unwrap()
}
}
#[cfg(unix)]
impl AsRawFd for SyncDevice {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
#[cfg(unix)]
impl AsFd for SyncDevice {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
}
}
#[cfg(unix)]
impl IntoRawFd for SyncDevice {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw_fd()
}
}
#[cfg(unix)]
pub struct BorrowedSyncDevice<'dev> {
dev: SyncDevice,
_phantom: std::marker::PhantomData<&'dev SyncDevice>,
}
#[cfg(unix)]
impl Deref for BorrowedSyncDevice<'_> {
type Target = SyncDevice;
fn deref(&self) -> &Self::Target {
&self.dev
}
}
#[cfg(unix)]
impl BorrowedSyncDevice<'_> {
pub unsafe fn borrow_raw(fd: RawFd) -> std::io::Result<Self> {
#[allow(unused_unsafe)]
unsafe {
Ok(Self {
dev: SyncDevice::borrow_raw(fd)?,
_phantom: std::marker::PhantomData,
})
}
}
}