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