ts_netstack_smoltcp/
lib.rs1#![doc = include_str!("../README.md")]
2#![no_std]
3
4extern crate alloc;
5
6#[cfg(any(test, feature = "std"))]
7extern crate std;
8
9use core::{borrow::Borrow, time::Duration};
10
11pub extern crate ts_netstack_smoltcp_core as netcore;
12pub extern crate ts_netstack_smoltcp_socket as netsock;
13
14use netcore::{Channel, smoltcp};
15pub use netcore::{HasChannel, Netstack as CoreStack};
16#[cfg(feature = "tokio")]
17pub use netsock::ping;
18pub use netsock::{CreateSocket, PingError};
19
20mod pipe;
21mod run;
22#[cfg(feature = "std")]
23mod std_clock;
24#[cfg(feature = "tun")]
25mod tun_rs_device;
26
27pub use pipe::{WakingPipe, WakingPipeDev, WakingPipeReceiver, WakingPipeSender};
28pub use run::{run, run_blocking};
29#[cfg(feature = "tun")]
30pub use tun_rs_device::{TunRsDevice, TunRsDeviceAsync};
31
32pub type Clock = &'static (dyn Fn() -> smoltcp::time::Instant + Send + Sync);
36
37pub struct Netstack<D> {
42 core: CoreStack,
43 dev: D,
44 clock: Clock,
45}
46
47#[cfg(feature = "std")]
52pub fn piped(config: netcore::Config) -> (Netstack<WakingPipeDev>, WakingPipe) {
53 let (pipe1, pipe2) = WakingPipe::unbounded();
54
55 let dev = WakingPipeDev {
56 pipe: pipe1,
57 mtu: config.mtu,
58 medium: smoltcp::phy::Medium::Ip,
59 };
60
61 (Netstack::<WakingPipeDev>::new(dev, config), pipe2)
62}
63
64#[cfg(feature = "std")]
67pub fn piped_pair(config: netcore::Config) -> (Netstack<WakingPipeDev>, Netstack<WakingPipeDev>) {
68 let (pipe1, pipe2) = WakingPipe::unbounded();
69
70 let dev1 = WakingPipeDev {
71 pipe: pipe1,
72 mtu: config.mtu,
73 medium: smoltcp::phy::Medium::Ip,
74 };
75
76 let dev2 = WakingPipeDev {
77 pipe: pipe2,
78 mtu: config.mtu,
79 medium: smoltcp::phy::Medium::Ip,
80 };
81
82 (
83 Netstack::<WakingPipeDev>::new(dev1, config.clone()),
84 Netstack::<WakingPipeDev>::new(dev2, config),
85 )
86}
87
88impl<D> Netstack<D> {
89 #[cfg(feature = "std")]
93 pub fn new(dev: D, config: netcore::Config) -> Self {
94 Self::with_clock(dev, config, &|| std_clock::CLOCK.now())
95 }
96
97 pub fn with_clock(dev: D, config: netcore::Config, clock: Clock) -> Self {
99 Self {
100 core: CoreStack::new(config, clock()),
101 dev,
102 clock,
103 }
104 }
105
106 pub fn run_blocking(&mut self, poll_delay: Duration)
114 where
115 D: smoltcp::phy::Device,
116 {
117 run_blocking(&mut self.core, &mut self.dev, self.clock, poll_delay)
118 }
119
120 #[cfg(feature = "std")]
122 pub fn spawn_threaded(mut self, poll_dur: Duration) -> std::thread::JoinHandle<()>
123 where
124 D: smoltcp::phy::Device + Send + 'static,
125 {
126 std::thread::spawn(move || self.run_blocking(poll_dur))
127 }
128
129 #[cfg(feature = "tokio")]
131 pub fn spawn_tokio(mut self) -> tokio::task::JoinHandle<()>
132 where
133 D: smoltcp::phy::Device + netcore::AsyncWakeDevice + Send + 'static + Unpin,
134 {
135 tokio::spawn(async move { self.run_tokio().await })
136 }
137
138 #[cfg(feature = "tokio")]
142 pub async fn run_tokio(&mut self)
143 where
144 D: smoltcp::phy::Device + netcore::AsyncWakeDevice + Unpin,
145 {
146 run(&mut self.core, &mut self.dev, self.clock, |dur| {
147 tokio::time::sleep(dur)
148 })
149 .await
150 }
151
152 pub async fn run_with_sleep(&mut self, sleep: impl AsyncFn(Duration) + Clone)
159 where
160 D: smoltcp::phy::Device + netcore::AsyncWakeDevice + Unpin,
161 {
162 run(&mut self.core, &mut self.dev, self.clock, sleep).await
163 }
164}
165
166impl<D> HasChannel for Netstack<D> {
167 fn borrow_channel(&self) -> impl Borrow<Channel> + Send {
168 self.core.borrow_channel()
169 }
170}