#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
use std::fmt;
use std::mem::MaybeUninit;
use std::net::IpAddr;
use std::net::Ipv4Addr;
use std::net::Ipv6Addr;
use std::net::Shutdown;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;
use thiserror::Error;
pub use bytes::Bytes;
pub use bytes::BytesMut;
pub use virtual_mio::{handler_into_waker, InterestHandler};
#[cfg(feature = "host-net")]
pub use virtual_mio::{InterestGuard, InterestHandlerWaker, InterestType};
pub type Result<T> = std::result::Result<T, NetworkError>;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct IpCidr {
pub ip: IpAddr,
pub prefix: u8,
}
#[derive(Clone, Debug)]
pub struct IpRoute {
pub cidr: IpCidr,
pub via_router: IpAddr,
pub preferred_until: Option<Duration>,
pub expires_at: Option<Duration>,
}
pub trait VirtualIoSource: fmt::Debug + Send + Sync + 'static {
fn remove_handler(&mut self);
}
#[async_trait::async_trait]
#[allow(unused_variables)]
pub trait VirtualNetworking: fmt::Debug + Send + Sync + 'static {
async fn bridge(
&self,
network: &str,
access_token: &str,
security: StreamSecurity,
) -> Result<()> {
Err(NetworkError::Unsupported)
}
async fn unbridge(&self) -> Result<()> {
Err(NetworkError::Unsupported)
}
async fn dhcp_acquire(&self) -> Result<Vec<IpAddr>> {
Err(NetworkError::Unsupported)
}
fn ip_add(&self, ip: IpAddr, prefix: u8) -> Result<()> {
Err(NetworkError::Unsupported)
}
fn ip_remove(&self, ip: IpAddr) -> Result<()> {
Err(NetworkError::Unsupported)
}
fn ip_clear(&self) -> Result<()> {
Err(NetworkError::Unsupported)
}
fn ip_list(&self) -> Result<Vec<IpCidr>> {
Err(NetworkError::Unsupported)
}
fn mac(&self) -> Result<[u8; 6]> {
Err(NetworkError::Unsupported)
}
fn gateway_set(&self, ip: IpAddr) -> Result<()> {
Err(NetworkError::Unsupported)
}
fn route_add(
&self,
cidr: IpCidr,
via_router: IpAddr,
preferred_until: Option<Duration>,
expires_at: Option<Duration>,
) -> Result<()> {
Err(NetworkError::Unsupported)
}
fn route_remove(&self, cidr: IpAddr) -> Result<()> {
Err(NetworkError::Unsupported)
}
fn route_clear(&self) -> Result<()> {
Err(NetworkError::Unsupported)
}
fn route_list(&self) -> Result<Vec<IpRoute>> {
Err(NetworkError::Unsupported)
}
async fn bind_raw(&self) -> Result<Box<dyn VirtualRawSocket + Sync>> {
Err(NetworkError::Unsupported)
}
async fn listen_tcp(
&self,
addr: SocketAddr,
only_v6: bool,
reuse_port: bool,
reuse_addr: bool,
) -> Result<Box<dyn VirtualTcpListener + Sync>> {
Err(NetworkError::Unsupported)
}
async fn bind_udp(
&self,
addr: SocketAddr,
reuse_port: bool,
reuse_addr: bool,
) -> Result<Box<dyn VirtualUdpSocket + Sync>> {
Err(NetworkError::Unsupported)
}
async fn bind_icmp(&self, addr: IpAddr) -> Result<Box<dyn VirtualIcmpSocket + Sync>> {
Err(NetworkError::Unsupported)
}
async fn connect_tcp(
&self,
addr: SocketAddr,
peer: SocketAddr,
) -> Result<Box<dyn VirtualTcpSocket + Sync>> {
Err(NetworkError::Unsupported)
}
async fn resolve(
&self,
host: &str,
port: Option<u16>,
dns_server: Option<IpAddr>,
) -> Result<Vec<IpAddr>> {
Err(NetworkError::Unsupported)
}
}
pub type DynVirtualNetworking = Arc<dyn VirtualNetworking>;
pub trait VirtualTcpListener: VirtualIoSource + fmt::Debug + Send + Sync + 'static {
fn try_accept(&mut self) -> Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr)>;
fn set_handler(&mut self, handler: Box<dyn InterestHandler + Send + Sync>) -> Result<()>;
fn addr_local(&self) -> Result<SocketAddr>;
fn set_ttl(&mut self, ttl: u8) -> Result<()>;
fn ttl(&self) -> Result<u8>;
}
pub trait VirtualSocket: VirtualIoSource + fmt::Debug + Send + Sync + 'static {
fn set_ttl(&mut self, ttl: u32) -> Result<()>;
fn ttl(&self) -> Result<u32>;
fn addr_local(&self) -> Result<SocketAddr>;
fn status(&self) -> Result<SocketStatus>;
fn set_handler(&mut self, handler: Box<dyn InterestHandler + Send + Sync>) -> Result<()>;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SocketStatus {
Opening,
Opened,
Closed,
Failed,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum StreamSecurity {
Unencrypted,
AnyEncyption,
ClassicEncryption,
DoubleEncryption,
}
pub trait VirtualConnectedSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
fn set_linger(&mut self, linger: Option<Duration>) -> Result<()>;
fn linger(&self) -> Result<Option<Duration>>;
fn try_send(&mut self, data: &[u8]) -> Result<usize>;
fn try_flush(&mut self) -> Result<()>;
fn close(&mut self) -> Result<()>;
fn try_recv(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize>;
}
pub trait VirtualConnectionlessSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
fn try_send_to(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize>;
fn try_recv_from(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<(usize, SocketAddr)>;
}
pub trait VirtualIcmpSocket:
VirtualConnectionlessSocket + fmt::Debug + Send + Sync + 'static
{
}
pub trait VirtualRawSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
fn try_send(&mut self, data: &[u8]) -> Result<usize>;
fn try_flush(&mut self) -> Result<()>;
fn try_recv(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize>;
fn set_promiscuous(&mut self, promiscuous: bool) -> Result<()>;
fn promiscuous(&self) -> Result<bool>;
}
pub trait VirtualTcpSocket: VirtualConnectedSocket + fmt::Debug + Send + Sync + 'static {
fn set_recv_buf_size(&mut self, size: usize) -> Result<()>;
fn recv_buf_size(&self) -> Result<usize>;
fn set_send_buf_size(&mut self, size: usize) -> Result<()>;
fn send_buf_size(&self) -> Result<usize>;
fn set_nodelay(&mut self, reuse: bool) -> Result<()>;
fn nodelay(&self) -> Result<bool>;
fn addr_peer(&self) -> Result<SocketAddr>;
fn shutdown(&mut self, how: Shutdown) -> Result<()>;
fn is_closed(&self) -> bool;
}
pub trait VirtualUdpSocket:
VirtualConnectionlessSocket + fmt::Debug + Send + Sync + 'static
{
fn set_broadcast(&mut self, broadcast: bool) -> Result<()>;
fn broadcast(&self) -> Result<bool>;
fn set_multicast_loop_v4(&mut self, val: bool) -> Result<()>;
fn multicast_loop_v4(&self) -> Result<bool>;
fn set_multicast_loop_v6(&mut self, val: bool) -> Result<()>;
fn multicast_loop_v6(&self) -> Result<bool>;
fn set_multicast_ttl_v4(&mut self, ttl: u32) -> Result<()>;
fn multicast_ttl_v4(&self) -> Result<u32>;
fn join_multicast_v4(&mut self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<()>;
fn leave_multicast_v4(&mut self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<()>;
fn join_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<()>;
fn leave_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<()>;
fn addr_peer(&self) -> Result<Option<SocketAddr>>;
}
#[derive(Debug, Default)]
pub struct UnsupportedVirtualNetworking {}
#[async_trait::async_trait]
impl VirtualNetworking for UnsupportedVirtualNetworking {}
#[derive(Error, Copy, Clone, Debug, PartialEq, Eq)]
pub enum NetworkError {
#[error("invalid fd")]
InvalidFd,
#[error("file exists")]
AlreadyExists,
#[error("lock error")]
Lock,
#[error("io error")]
IOError,
#[error("address is in use")]
AddressInUse,
#[error("address could not be found")]
AddressNotAvailable,
#[error("broken pipe (was closed)")]
BrokenPipe,
#[error("Insufficient memory")]
InsufficientMemory,
#[error("connection aborted")]
ConnectionAborted,
#[error("connection refused")]
ConnectionRefused,
#[error("connection reset")]
ConnectionReset,
#[error("operation interrupted")]
Interrupted,
#[error("invalid internal data")]
InvalidData,
#[error("invalid input")]
InvalidInput,
#[error("connection is not open")]
NotConnected,
#[error("can't access device")]
NoDevice,
#[error("permission denied")]
PermissionDenied,
#[error("time out")]
TimedOut,
#[error("unexpected eof")]
UnexpectedEof,
#[error("blocking operation. try again")]
WouldBlock,
#[error("write returned 0")]
WriteZero,
#[error("too many open files")]
TooManyOpenFiles,
#[error("unsupported")]
Unsupported,
#[error("unknown error found")]
UnknownError,
}
#[cfg(feature = "host-net")]
pub mod host;