1mod context;
2mod device;
3mod runner;
4mod stack;
5
6use core::future::poll_fn;
7
8use alloc::{vec, vec::Vec};
9pub use context::*;
10use file_system::{DirectCharacterDevice, Path};
11pub use runner::*;
12use smoltcp::{
13 phy::Device,
14 socket::{icmp, tcp, udp},
15};
16use synchronization::{
17 Arc, blocking_mutex::raw::CriticalSectionRawMutex, rwlock::RwLock, signal::Signal,
18};
19use task::{SpawnerIdentifier, TaskIdentifier};
20use virtual_file_system::VirtualFileSystem;
21
22use crate::{
23 DnsQueryKind, Error, IcmpSocket, IpAddress, Result, TcpSocket, UdpSocket,
24 manager::{
25 device::NetworkDevice,
26 stack::{Stack, StackInner},
27 },
28};
29
30pub fn get_smoltcp_time(time_manager: &time::Manager<'_>) -> smoltcp::time::Instant {
31 let current_time = time_manager
32 .get_current_time()
33 .expect("Failed to get current time");
34
35 smoltcp::time::Instant::from_millis(current_time.as_millis() as i64)
36}
37
38type StackList = Vec<Stack>;
39
40pub struct Manager {
41 task_manager: &'static task::Manager,
42 virtual_file_system: &'static VirtualFileSystem,
43 time_manager: &'static time::Manager<'static>,
44 pub(crate) random_device: &'static dyn DirectCharacterDevice,
45 pub(crate) stacks: RwLock<CriticalSectionRawMutex, StackList>,
46}
47
48#[cfg(test)]
49pub(crate) static TEST_MANAGER: synchronization::once_lock::OnceLock<Manager> =
50 synchronization::once_lock::OnceLock::new();
51
52#[cfg(test)]
53pub(crate) fn test_manager() -> &'static Manager {
54 TEST_MANAGER
55 .try_get()
56 .expect("Network test manager not initialized")
57}
58
59pub fn initialize(
60 task_manager: &'static task::Manager,
61 virtual_file_system: &'static VirtualFileSystem,
62 time_manager: &'static time::Manager<'static>,
63 random_device: &'static dyn DirectCharacterDevice,
64) -> Manager {
65 Manager::new(
66 task_manager,
67 virtual_file_system,
68 time_manager,
69 random_device,
70 )
71}
72
73impl Manager {
74 pub fn new(
75 task_manager: &'static task::Manager,
76 virtual_file_system: &'static VirtualFileSystem,
77 time_manager: &'static time::Manager<'static>,
78 random_device: &'static dyn DirectCharacterDevice,
79 ) -> Self {
80 Manager {
81 task_manager,
82 virtual_file_system,
83 time_manager,
84 random_device,
85 stacks: RwLock::new(Vec::new()),
86 }
87 }
88
89 fn generate_seed(&self) -> Result<u64> {
90 let mut buffer = [0u8; 8];
91 self.random_device
92 .read(&mut buffer, 0)
93 .map_err(Error::FailedToGenerateSeed)?;
94 Ok(u64::from_le_bytes(buffer))
95 }
96
97 pub(crate) async fn find_first_available_stack(stacks: &StackList) -> Option<Stack> {
98 for stack in stacks {
99 let available = stack.with(|s| s.is_available()).await;
100
101 if available {
102 return Some(stack.clone());
103 }
104 }
105
106 None
107 }
108
109 pub(crate) async fn find_stack(stacks: &StackList, name: &str) -> Option<Stack> {
110 for stack in stacks {
111 let stack_name = stack.with(|s| s.name.clone()).await;
112
113 if stack_name.as_str() == name {
114 return Some(stack.clone());
115 }
116 }
117
118 None
119 }
120
121 pub async fn mount_interface(
122 &self,
123 task: TaskIdentifier,
124 name: &str,
125 mut device: impl Device + 'static,
126 controller_device: impl DirectCharacterDevice + 'static,
127 spawner: Option<SpawnerIdentifier>,
128 ) -> Result<()> {
129 let mut stacks = self.stacks.write().await;
130
131 if Self::find_stack(&stacks, name).await.is_some() {
132 return Err(Error::DuplicateIdentifier);
133 }
134
135 let random_seed = self.generate_seed()?;
136 let now = get_smoltcp_time(self.time_manager);
137
138 let stack_inner = StackInner::new(
139 name,
140 &mut device,
141 controller_device,
142 random_seed,
143 now,
144 self.time_manager,
145 );
146
147 let wake_signal: WakeSignal = Arc::new(Signal::new());
149
150 let stack = Stack::new(stack_inner, wake_signal.clone());
151
152 let mut runner = StackRunner::new(stack.clone(), device, wake_signal);
153
154 self.task_manager
155 .spawn(
156 task,
157 "Network Interface Runner",
158 spawner,
159 move |_| async move {
160 runner.run().await;
161 },
162 )
163 .await
164 .map_err(Error::FailedToSpawnNetworkTask)?;
165
166 let path = Path::NETWORK_DEVICES
167 .join(Path::from_str(name))
168 .ok_or(Error::InvalidIdentifier)?;
169
170 let device = NetworkDevice::new(stack.clone());
171
172 match self
173 .virtual_file_system
174 .create_directory(task, &Path::NETWORK_DEVICES)
175 .await
176 {
177 Ok(_) => {}
178 Err(virtual_file_system::Error::AlreadyExists) => {}
179 Err(e) => return Err(Error::FailedToMountDevice(e)),
180 };
181
182 match self.virtual_file_system.remove(task, &path).await {
183 Ok(_) => {}
184 Err(virtual_file_system::Error::FileSystem(file_system::Error::NotFound)) => {}
185 Err(e) => return Err(Error::FailedToMountDevice(e)),
186 };
187
188 self.virtual_file_system
189 .mount_character_device(task, path, device)
190 .await
191 .map_err(Error::FailedToMountDevice)?;
192
193 stacks.push(stack);
194
195 Ok(())
196 }
197
198 pub async fn resolve(
199 &self,
200 host: &str,
201 kind: DnsQueryKind,
202 stop_on_first_match: bool,
203 interface_name: Option<&str>,
204 ) -> Result<Vec<IpAddress>> {
205 if let Ok(host) = IpAddress::try_from(host) {
206 return Ok(vec![host]);
207 }
208
209 let stacks = self.stacks.read().await;
210
211 let stack = if let Some(name) = interface_name {
212 Self::find_stack(&stacks, name)
213 .await
214 .ok_or(Error::NotFound)?
215 } else {
216 Self::find_first_available_stack(&stacks)
217 .await
218 .ok_or(Error::NotFound)?
219 };
220
221 let query_iterator = &[
222 DnsQueryKind::A,
223 DnsQueryKind::Aaaa,
224 DnsQueryKind::Cname,
225 DnsQueryKind::Soa,
226 DnsQueryKind::Ns,
227 ];
228
229 let mut resolved_addresses = vec![];
230
231 for query_kind in query_iterator {
232 if !kind.contains(*query_kind) {
233 continue;
234 }
235
236 let handle = stack
237 .with_mutable(|s| s.start_dns_query(host, kind))
238 .await?;
239
240 let result = poll_fn(|cx| {
241 stack
242 .poll_with_mutable(cx, |s, cx| s.get_dns_query_result(handle, Some(cx.waker())))
243 })
244 .await?;
245
246 resolved_addresses.extend(result);
247
248 if !resolved_addresses.is_empty() && stop_on_first_match {
249 break;
250 }
251 }
252
253 Ok(resolved_addresses)
254 }
255
256 pub async fn new_tcp_socket(
257 &self,
258 transmit_buffer_size: usize,
259 receive_buffer_size: usize,
260 interface_name: Option<&str>,
261 ) -> Result<TcpSocket> {
262 let stacks = self.stacks.read().await;
263
264 let stack = if let Some(name) = interface_name {
265 Self::find_stack(&stacks, name)
266 .await
267 .ok_or(Error::NotFound)?
268 } else {
269 Self::find_first_available_stack(&stacks)
270 .await
271 .ok_or(Error::NotFound)?
272 };
273
274 let send_buffer = tcp::SocketBuffer::new(vec![0u8; transmit_buffer_size]);
275 let receive_buffer = tcp::SocketBuffer::new(vec![0u8; receive_buffer_size]);
276
277 let socket = tcp::Socket::new(receive_buffer, send_buffer);
278 let handle = stack.with_mutable(|s| s.add_socket(socket)).await;
279
280 let context = SocketContext {
281 handle,
282 stack: stack.clone(),
283 closed: false,
284 };
285
286 Ok(TcpSocket::new(context))
287 }
288
289 pub async fn new_udp_socket(
290 &self,
291 transmit_buffer_size: usize,
292 receive_buffer_size: usize,
293 receive_meta_buffer_size: usize,
294 transmit_meta_buffer_size: usize,
295 interface_name: Option<&str>,
296 ) -> Result<UdpSocket> {
297 let stacks = self.stacks.read().await;
298
299 let stack = if let Some(name) = interface_name {
300 Self::find_stack(&stacks, name)
301 .await
302 .ok_or(Error::NotFound)?
303 } else {
304 Self::find_first_available_stack(&stacks)
305 .await
306 .ok_or(Error::NotFound)?
307 };
308
309 let receive_meta_buffer = udp::PacketBuffer::new(
310 vec![udp::PacketMetadata::EMPTY; receive_meta_buffer_size],
311 vec![0u8; receive_buffer_size],
312 );
313 let transmit_meta_buffer = udp::PacketBuffer::new(
314 vec![udp::PacketMetadata::EMPTY; transmit_meta_buffer_size],
315 vec![0u8; transmit_buffer_size],
316 );
317
318 let socket = udp::Socket::new(receive_meta_buffer, transmit_meta_buffer);
319 let handle = stack.with_mutable(|s| s.add_socket(socket)).await;
320
321 let context = SocketContext {
322 handle,
323 stack: stack.clone(),
324 closed: false,
325 };
326
327 Ok(UdpSocket::new(context))
328 }
329
330 pub async fn new_icmp_socket(
331 &self,
332 receive_buffer_size: usize,
333 transmit_buffer_size: usize,
334 receive_meta_buffer_size: usize,
335 transmit_meta_buffer_size: usize,
336 interface_name: Option<&str>,
337 ) -> Result<IcmpSocket> {
338 let stacks = self.stacks.read().await;
339
340 let stack = if let Some(name) = interface_name {
341 Self::find_stack(&stacks, name)
342 .await
343 .ok_or(Error::NotFound)?
344 } else {
345 Self::find_first_available_stack(&stacks)
346 .await
347 .ok_or(Error::NotFound)?
348 };
349
350 let receive_buffer = icmp::PacketBuffer::new(
351 vec![icmp::PacketMetadata::EMPTY; receive_meta_buffer_size],
352 vec![0u8; receive_buffer_size],
353 );
354 let transmit_buffer = icmp::PacketBuffer::new(
355 vec![icmp::PacketMetadata::EMPTY; transmit_meta_buffer_size],
356 vec![0u8; transmit_buffer_size],
357 );
358
359 let socket = icmp::Socket::new(receive_buffer, transmit_buffer);
360 let handle = stack.with_mutable(|s| s.add_socket(socket)).await;
361
362 let context = SocketContext {
363 handle,
364 stack: stack.clone(),
365 closed: false,
366 };
367
368 let socket = IcmpSocket::new(context);
369
370 Ok(socket)
371 }
372}