Skip to main content

network/manager/
mod.rs

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        // Create a wake signal for runner/stack communication
123        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}