use std::{
io,
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
sync::{
atomic::{AtomicU16, Ordering},
Arc,
},
};
use device::BufferDevice;
use futures::Future;
use reactor::Reactor;
pub use smoltcp;
use smoltcp::{
iface::{Config, Interface, Routes},
time::{Duration, Instant},
wire::{HardwareAddress, IpAddress, IpCidr, IpProtocol, IpVersion},
};
pub use socket::{RawSocket, TcpListener, TcpStream, UdpSocket};
pub use socket_allocator::BufferSize;
use tokio::sync::Notify;
pub mod device;
mod reactor;
mod socket;
mod socket_allocator;
pub const FOREVER: Instant =
Instant::from_micros_const(i64::max_value() - Duration::from_millis(60_000).micros() as i64);
pub struct Neighbor {
pub protocol_addr: IpAddress,
pub hardware_addr: HardwareAddress,
pub timestamp: Instant,
}
#[non_exhaustive]
pub struct NetConfig {
pub interface_config: Config,
pub ip_addr: IpCidr,
pub gateway: Vec<IpAddress>,
pub buffer_size: BufferSize,
}
impl NetConfig {
pub fn new(interface_config: Config, ip_addr: IpCidr, gateway: Vec<IpAddress>) -> Self {
Self {
interface_config,
ip_addr,
gateway,
buffer_size: Default::default(),
}
}
}
pub struct Net {
reactor: Arc<Reactor>,
ip_addr: IpCidr,
from_port: AtomicU16,
stopper: Arc<Notify>,
}
impl Net {
pub fn new<D: device::AsyncDevice + 'static>(device: D, config: NetConfig) -> Net {
let (net, fut) = Self::new2(device, config);
tokio::spawn(fut);
net
}
fn new2<D: device::AsyncDevice + 'static>(
device: D,
config: NetConfig,
) -> (Net, impl Future<Output = io::Result<()>> + Send) {
let mut buffer_device = BufferDevice::new(device.capabilities().clone());
let mut iface = Interface::new(config.interface_config, &mut buffer_device, Instant::now());
let ip_addr = config.ip_addr;
iface.update_ip_addrs(|ip_addrs| {
ip_addrs.push(ip_addr).unwrap();
});
for gateway in config.gateway {
match gateway {
IpAddress::Ipv4(v4) => {
iface.routes_mut().add_default_ipv4_route(v4).unwrap();
}
IpAddress::Ipv6(v6) => {
iface.routes_mut().add_default_ipv6_route(v6).unwrap();
}
#[allow(unreachable_patterns)]
_ => panic!("Unsupported address"),
};
}
let stopper = Arc::new(Notify::new());
let (reactor, fut) = Reactor::new(
device,
iface,
buffer_device,
config.buffer_size,
stopper.clone(),
);
(
Net {
reactor: Arc::new(reactor),
ip_addr: config.ip_addr,
from_port: AtomicU16::new(10001),
stopper,
},
fut,
)
}
fn get_port(&self) -> u16 {
self.from_port
.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
Some(if x > 60000 { 10000 } else { x + 1 })
})
.unwrap()
}
pub async fn tcp_bind(&self, addr: SocketAddr) -> io::Result<TcpListener> {
let addr = self.set_address(addr);
TcpListener::new(self.reactor.clone(), addr.into()).await
}
pub async fn tcp_connect(&self, addr: SocketAddr) -> io::Result<TcpStream> {
TcpStream::connect(
self.reactor.clone(),
(self.ip_addr.address(), self.get_port()).into(),
addr.into(),
)
.await
}
pub async fn udp_bind(&self, addr: SocketAddr) -> io::Result<UdpSocket> {
let addr = self.set_address(addr);
UdpSocket::new(self.reactor.clone(), addr.into()).await
}
pub async fn raw_socket(
&self,
ip_version: IpVersion,
ip_protocol: IpProtocol,
) -> io::Result<RawSocket> {
RawSocket::new(self.reactor.clone(), ip_version, ip_protocol).await
}
fn set_address(&self, mut addr: SocketAddr) -> SocketAddr {
if addr.ip().is_unspecified() {
addr.set_ip(match self.ip_addr.address() {
IpAddress::Ipv4(ip) => Ipv4Addr::from(ip).into(),
IpAddress::Ipv6(ip) => Ipv6Addr::from(ip).into(),
#[allow(unreachable_patterns)]
_ => panic!("address must not be unspecified"),
});
}
if addr.port() == 0 {
addr.set_port(self.get_port());
}
addr
}
pub fn set_any_ip(&self, any_ip: bool) {
let iface = self.reactor.iface().clone();
let mut iface: parking_lot::lock_api::MutexGuard<'_, parking_lot::RawMutex, Interface> =
iface.lock();
iface.set_any_ip(any_ip);
}
pub fn any_ip(&self) -> bool {
let iface = self.reactor.iface().clone();
let iface = iface.lock();
iface.any_ip()
}
pub fn routes<F: FnOnce(&Routes)>(&self, f: F) {
let iface = self.reactor.iface().clone();
let iface = iface.lock();
let routes = iface.routes();
f(routes)
}
pub fn routes_mut<F: FnOnce(&mut Routes)>(&self, f: F) {
let iface = self.reactor.iface().clone();
let mut iface = iface.lock();
let routes = iface.routes_mut();
f(routes)
}
}
impl Drop for Net {
fn drop(&mut self) {
self.stopper.notify_waiters()
}
}