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