mprober_lib/network/
mod.rs

1mod network_stat;
2
3use std::{
4    collections::HashSet,
5    hash::{Hash, Hasher},
6    io::ErrorKind,
7    thread::sleep,
8    time::Duration,
9};
10
11pub use network_stat::*;
12
13use crate::scanner_rust::{generic_array::typenum::U1024, ScannerAscii, ScannerError};
14
15#[derive(Default, Debug, Clone, Eq)]
16pub struct Network {
17    pub interface: String,
18    pub stat:      NetworkStat,
19}
20
21impl Hash for Network {
22    #[inline]
23    fn hash<H: Hasher>(&self, state: &mut H) {
24        self.interface.hash(state)
25    }
26}
27
28impl PartialEq for Network {
29    #[inline]
30    fn eq(&self, other: &Network) -> bool {
31        self.interface.eq(&other.interface)
32    }
33}
34
35/// Get network information by reading the `/proc/net/dev` file.
36///
37/// ```rust
38/// use mprober_lib::network;
39///
40/// let networks = network::get_networks().unwrap();
41///
42/// println!("{networks:#?}");
43/// ```
44pub fn get_networks() -> Result<Vec<Network>, ScannerError> {
45    let mut sc: ScannerAscii<_, U1024> = ScannerAscii::scan_path2("/proc/net/dev")?;
46
47    for _ in 0..2 {
48        sc.drop_next_line()?.ok_or(ErrorKind::UnexpectedEof)?;
49    }
50
51    let mut networks = Vec::with_capacity(1);
52
53    while let Some(interface) = sc.next_until_raw(":")? {
54        let interface = unsafe { String::from_utf8_unchecked(interface) };
55
56        let receive_bytes = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
57
58        for _ in 0..7 {
59            sc.drop_next()?.ok_or(ErrorKind::UnexpectedEof)?;
60        }
61
62        let transmit_bytes = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
63
64        let stat = NetworkStat {
65            receive_bytes,
66            transmit_bytes,
67        };
68
69        let network = Network {
70            interface,
71            stat,
72        };
73
74        networks.push(network);
75
76        sc.drop_next_line()?.ok_or(ErrorKind::UnexpectedEof)?;
77    }
78
79    Ok(networks)
80}
81
82/// Get network information by reading the `/proc/net/dev` file and measure the speed within a specific time interval.
83///
84/// ```rust
85/// use std::time::Duration;
86///
87/// use mprober_lib::network;
88///
89/// let networks_with_speed =
90///     network::get_networks_with_speed(Duration::from_millis(100)).unwrap();
91///
92/// for (network, network_speed) in networks_with_speed {
93///     println!("{}: ", network.interface);
94///     println!("    Receive: {:.1} B/s", network_speed.receive);
95///     println!("    Transmit: {:.1} B/s", network_speed.transmit);
96/// }
97/// ```
98pub fn get_networks_with_speed(
99    interval: Duration,
100) -> Result<Vec<(Network, NetworkSpeed)>, ScannerError> {
101    let pre_networks = get_networks()?;
102
103    let pre_networks_length = pre_networks.len();
104
105    let mut pre_networks_hashset = HashSet::with_capacity(pre_networks_length);
106
107    for pre_network in pre_networks {
108        pre_networks_hashset.insert(pre_network);
109    }
110
111    sleep(interval);
112
113    let networks = get_networks()?;
114
115    let mut networks_with_speed = Vec::with_capacity(networks.len().min(pre_networks_length));
116
117    for network in networks {
118        if let Some(pre_network) = pre_networks_hashset.get(&network) {
119            let network_speed = pre_network.stat.compute_speed(&network.stat, interval);
120
121            networks_with_speed.push((network, network_speed));
122        }
123    }
124
125    Ok(networks_with_speed)
126}