1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use std::{
    collections::BTreeMap,
    sync::{Arc, Mutex},
};

use twizzler_async::Task;

use crate::{
    link::ethernet::{handle_incoming_ethernet_packets, EthernetAddr},
    link::nic::NetworkInterface,
};

mod loopback;

lazy_static::lazy_static! {
    static ref NIC_MANAGER: NicManager = NicManager::new();
}

struct NicManagerInner {
    nics: BTreeMap<EthernetAddr, Arc<dyn NetworkInterface + Sync + Send>>,
}

struct NicManager {
    inner: Mutex<NicManagerInner>,
}

impl NicManager {
    fn new() -> Self {
        Self {
            inner: Mutex::new(NicManagerInner {
                nics: BTreeMap::new(),
            }),
        }
    }
}

pub fn init() {
    let mut inner = NIC_MANAGER.inner.lock().unwrap();
    let lo = Arc::new(loopback::Loopback::new());
    inner.nics.insert(lo.get_ethernet_addr(), lo.clone());
    Task::spawn(async move {
        loop {
            let recv = lo.recv_ethernet().await;
            if let Ok(recv) = recv {
                handle_incoming_ethernet_packets(&recv).await;
            } else {
                eprintln!("loopback recv thread encountered an error: {:?}", recv);
                break;
            }
        }
    })
    .detach();
}

pub fn lookup_nic(addr: &EthernetAddr) -> Option<Arc<dyn NetworkInterface + Send + Sync>> {
    let inner = NIC_MANAGER.inner.lock().unwrap();
    inner.nics.get(addr).cloned()
}