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