#![doc = include_str!("../README.md")]
#![no_std]
extern crate alloc;
#[cfg(any(test, feature = "std"))]
extern crate std;
use core::{borrow::Borrow, time::Duration};
pub extern crate ts_netstack_smoltcp_core as netcore;
pub extern crate ts_netstack_smoltcp_socket as netsock;
use netcore::{Channel, smoltcp};
pub use netcore::{HasChannel, Netstack as CoreStack};
pub use netsock::CreateSocket;
mod pipe;
mod run;
#[cfg(feature = "std")]
mod std_clock;
#[cfg(feature = "tun")]
mod tun_rs_device;
pub use pipe::{WakingPipe, WakingPipeDev, WakingPipeReceiver, WakingPipeSender};
pub use run::{run, run_blocking};
#[cfg(feature = "tun")]
pub use tun_rs_device::{TunRsDevice, TunRsDeviceAsync};
pub type Clock = &'static (dyn Fn() -> smoltcp::time::Instant + Send + Sync);
pub struct Netstack<D> {
core: CoreStack,
dev: D,
clock: Clock,
}
#[cfg(feature = "std")]
pub fn piped(config: netcore::Config) -> (Netstack<WakingPipeDev>, WakingPipe) {
let (pipe1, pipe2) = WakingPipe::unbounded();
let dev = WakingPipeDev {
pipe: pipe1,
mtu: config.mtu,
medium: smoltcp::phy::Medium::Ip,
};
(Netstack::<WakingPipeDev>::new(dev, config), pipe2)
}
#[cfg(feature = "std")]
pub fn piped_pair(config: netcore::Config) -> (Netstack<WakingPipeDev>, Netstack<WakingPipeDev>) {
let (pipe1, pipe2) = WakingPipe::unbounded();
let dev1 = WakingPipeDev {
pipe: pipe1,
mtu: config.mtu,
medium: smoltcp::phy::Medium::Ip,
};
let dev2 = WakingPipeDev {
pipe: pipe2,
mtu: config.mtu,
medium: smoltcp::phy::Medium::Ip,
};
(
Netstack::<WakingPipeDev>::new(dev1, config.clone()),
Netstack::<WakingPipeDev>::new(dev2, config),
)
}
impl<D> Netstack<D> {
#[cfg(feature = "std")]
pub fn new(dev: D, config: netcore::Config) -> Self {
Self::with_clock(dev, config, &|| std_clock::CLOCK.now())
}
pub fn with_clock(dev: D, config: netcore::Config, clock: Clock) -> Self {
Self {
core: CoreStack::new(config, clock()),
dev,
clock,
}
}
pub fn run_blocking(&mut self, poll_delay: Duration)
where
D: smoltcp::phy::Device,
{
run_blocking(&mut self.core, &mut self.dev, self.clock, poll_delay)
}
#[cfg(feature = "std")]
pub fn spawn_threaded(mut self, poll_dur: Duration) -> std::thread::JoinHandle<()>
where
D: smoltcp::phy::Device + Send + 'static,
{
std::thread::spawn(move || self.run_blocking(poll_dur))
}
#[cfg(feature = "tokio")]
pub fn spawn_tokio(mut self) -> tokio::task::JoinHandle<()>
where
D: smoltcp::phy::Device + netcore::AsyncWakeDevice + Send + 'static + Unpin,
{
tokio::spawn(async move { self.run_tokio().await })
}
#[cfg(feature = "tokio")]
pub async fn run_tokio(&mut self)
where
D: smoltcp::phy::Device + netcore::AsyncWakeDevice + Unpin,
{
run(&mut self.core, &mut self.dev, self.clock, |dur| {
tokio::time::sleep(dur)
})
.await
}
pub async fn run_with_sleep(&mut self, sleep: impl AsyncFn(Duration) + Clone)
where
D: smoltcp::phy::Device + netcore::AsyncWakeDevice + Unpin,
{
run(&mut self.core, &mut self.dev, self.clock, sleep).await
}
}
impl<D> HasChannel for Netstack<D> {
fn borrow_channel(&self) -> impl Borrow<Channel> + Send {
self.core.borrow_channel()
}
}