proto_lab/
ether_simulator.rs

1use std::sync::{Arc, Mutex};
2
3use crate::{device::IODriverSimulator, WirelessModemFake};
4
5pub struct EtherSimulator {
6    name: String,
7    devices: Arc<Mutex<Vec<WirelessModemFake>>>,
8}
9
10impl EtherSimulator {
11    pub fn new(name: &str) -> Self {
12        Self {
13            name: String::from(name),
14            devices: Arc::new(Mutex::new(vec![])),
15        }
16    }
17
18    /// Gets the name of the ether
19    /// ```
20    /// use network_simulator::EtherSimulator;
21    /// let mut ether = EtherSimulator::new("my_ether");
22    /// assert_eq!(ether.get_name(), "my_ether");
23    /// ```
24    pub fn get_name(&self) -> &str {
25        &self.name
26    }
27
28    /// Registers a new device (driver / modem)
29    /// ```
30    /// use network_simulator::EtherSimulator;
31    /// use network_simulator::WirelessModemFake;
32    /// use network_simulator::IODriverSimulator;
33    ///
34    /// let mut ether = EtherSimulator::new("my_ether");
35    /// ether.register_driver(WirelessModemFake::new("my_modem"));
36    /// assert_eq!(ether.get_driver("my_modem").unwrap().get_name(), "my_modem");
37    /// ```
38    pub fn register_driver(&mut self, driver: WirelessModemFake) {
39        let mut devices = self.devices.lock().expect("Fail to get lock on devices");
40        devices.push(WirelessModemFake::clone(&driver));
41    }
42
43    /// Unregisters a device
44    /// ```
45    /// use network_simulator::EtherSimulator;
46    /// use network_simulator::WirelessModemFake;
47    /// use network_simulator::IODriverSimulator;
48    ///
49    /// let mut ether = EtherSimulator::new("my_ether");
50    /// ether.register_driver(WirelessModemFake::new("my_modem"));
51    /// ether.unregister_driver("my_modem");
52    /// assert!(ether.get_driver("my_modem").is_none());
53    /// ```
54    pub fn unregister_driver(&mut self, name: &str) {
55        let mut devices = self.devices.lock().expect("Fail to get lock on devices");
56
57        loop {
58            let mut index_to_remove: Option<_> = None;
59
60            for (i, device) in devices.iter_mut().enumerate() {
61                if device.get_name() == name {
62                    index_to_remove.replace(i);
63                }
64            }
65
66            match index_to_remove {
67                Some(i) => devices.remove(i),
68                None => break,
69            };
70        }
71    }
72
73    /// Gets a registered device
74    /// ```
75    /// use network_simulator::EtherSimulator;
76    /// use network_simulator::WirelessModemFake;
77    /// use network_simulator::IODriverSimulator;
78    ///
79    /// let mut ether = EtherSimulator::new("my_ether");
80    /// assert!(ether.get_driver("my_modem").is_none());
81    /// ether.register_driver(WirelessModemFake::new("my_modem"));
82    /// assert_eq!(ether.get_driver("my_modem").unwrap().get_name(), "my_modem");
83    /// ```
84    pub fn get_driver(&self, name: &str) -> Option<WirelessModemFake> {
85        let devices = self.devices.lock().expect("Fail to get lock on devices");
86
87        for device in devices.iter() {
88            if device.get_name() == name {
89                return Some(WirelessModemFake::clone(&device));
90            }
91        }
92        None
93    }
94
95    /// Gets the broadcasted byte from latest broadasting device.
96    /// That is the place where the data collision is possible.
97    fn get_current_byte(&self) -> Option<u8> {
98        let mut result: Option<u8> = None;
99        let devices = self.devices.lock().expect("Fail to get lock on devices");
100
101        for device in devices.iter() {
102            if let Some(byte) = device.get_from_device_network_side() {
103                result = Some(byte);
104            }
105        }
106
107        result
108    }
109
110    /// Prepares all the registered devices for starting of simulation during tick.
111    pub fn start_tick(&self) {
112        let devices = self.devices.lock().expect("Fail to get lock on devices");
113        for device in devices.iter() {
114            device.start_tick();
115        }
116    }
117
118    /// Prepares all the registered devices for ending of simulation during tick.
119    pub fn end_tick(&self) {
120        let devices = self.devices.lock().expect("Fail to get lock on devices");
121        for device in devices.iter() {
122            device.end_tick();
123        }
124    }
125
126    /// This operation shall be called only during tick is active.
127    pub fn simulate(&self) {
128        let current_byte = self.get_current_byte();
129
130        let devices = self.devices.lock().expect("Fail to get lock on devices");
131
132        if let Some(current_byte) = current_byte {
133            for device in devices.iter() {
134                device.put_to_device_network_side(current_byte);
135            }
136        }
137    }
138
139    /// Clones itself.
140    /// Also makes all internal data shared to be able to use from multiple threads.
141    /// ```
142    /// use network_simulator::EtherSimulator;
143    /// use network_simulator::WirelessModemFake;
144    /// use network_simulator::IODriverSimulator;
145    ///
146    /// let mut ether = EtherSimulator::new("my_ether");
147    /// let ether_clone = ether.clone();
148    ///
149    /// assert_eq!(ether.get_name(), ether_clone.get_name());
150    pub fn clone(&self) -> EtherSimulator {
151        EtherSimulator {
152            name: String::from(&self.name),
153            devices: Arc::clone(&self.devices),
154        }
155    }
156}