modulized everthing
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
use std::error::Error;
|
||||
use std::result::Result;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NetworkInfo {
|
||||
pub interfaces: Option<Vec<String>>,
|
||||
pub rx_bytes: Option<f64>,
|
||||
pub tx_bytes: Option<f64>,
|
||||
}
|
||||
|
||||
pub struct NetworkMonitor {
|
||||
prev_rx: u64,
|
||||
prev_tx: u64,
|
||||
last_update: Instant,
|
||||
}
|
||||
|
||||
impl NetworkMonitor {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
prev_rx: 0,
|
||||
prev_tx: 0,
|
||||
last_update: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_usage(&mut self) -> Result<(f64, f64), Box<dyn Error>> {
|
||||
let (current_rx, current_tx) = get_network_bytes()?;
|
||||
let elapsed = self.last_update.elapsed().as_secs_f64();
|
||||
self.last_update = Instant::now();
|
||||
|
||||
let rx_rate = if current_rx >= self.prev_rx {
|
||||
(current_rx - self.prev_rx) as f64 / elapsed
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
let tx_rate = if current_tx >= self.prev_tx {
|
||||
(current_tx - self.prev_tx) as f64 / elapsed
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
self.prev_rx = current_rx;
|
||||
self.prev_tx = current_tx;
|
||||
|
||||
Ok((rx_rate, tx_rate))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_network_info() -> Result<NetworkInfo, Box<dyn Error>> {
|
||||
let (rx, tx) = get_network_bytes()?;
|
||||
Ok(NetworkInfo {
|
||||
interfaces: Some(get_network_interfaces()),
|
||||
rx_bytes: Some(rx as f64),
|
||||
tx_bytes: Some(tx as f64),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_network_bytes() -> Result<(u64, u64), Box<dyn Error>> {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use std::ptr::null_mut;
|
||||
use winapi::shared::ifmib::MIB_IFTABLE;
|
||||
use winapi::um::iphlpapi::GetIfTable;
|
||||
|
||||
unsafe {
|
||||
// Erste Abfrage zur Bestimmung der benötigten Puffergröße
|
||||
let mut buffer_size = 0u32;
|
||||
if GetIfTable(null_mut(), &mut buffer_size, 0)
|
||||
!= winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER
|
||||
{
|
||||
return Err(
|
||||
anyhow::anyhow!("Failed to get buffer size for network interfaces").into(),
|
||||
);
|
||||
}
|
||||
|
||||
// Puffer allozieren
|
||||
let mut buffer = vec![0u8; buffer_size as usize];
|
||||
let if_table = buffer.as_mut_ptr() as *mut MIB_IFTABLE;
|
||||
|
||||
// Tatsächliche Daten abrufen
|
||||
if GetIfTable(if_table, &mut buffer_size, 0) != 0 {
|
||||
return Err(anyhow::anyhow!("Failed to get network interface table").into());
|
||||
}
|
||||
|
||||
// Daten auswerten
|
||||
let mut rx_total = 0u64;
|
||||
let mut tx_total = 0u64;
|
||||
|
||||
for i in 0..(*if_table).dwNumEntries {
|
||||
let row = &*((*if_table).table.as_ptr().offset(i as isize));
|
||||
rx_total += row.dwInOctets as u64;
|
||||
tx_total += row.dwOutOctets as u64;
|
||||
}
|
||||
|
||||
if rx_total == 0 && tx_total == 0 {
|
||||
return Err(anyhow::anyhow!("No network data available").into());
|
||||
} else {
|
||||
Ok((rx_total, tx_total))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use std::fs;
|
||||
|
||||
let mut rx_total = 0u64;
|
||||
let mut tx_total = 0u64;
|
||||
if let Ok(dir) = fs::read_dir("/sys/class/net") {
|
||||
for entry in dir.flatten() {
|
||||
let iface = entry.file_name();
|
||||
let iface_name = iface.to_string_lossy();
|
||||
|
||||
// Ignoriere virtuelle Interfaces
|
||||
if !iface_name.starts_with("lo") && !iface_name.starts_with("virbr") {
|
||||
if let (Ok(rx), Ok(tx)) = (
|
||||
fs::read_to_string(entry.path().join("statistics/rx_bytes")),
|
||||
fs::read_to_string(entry.path().join("statistics/tx_bytes")),
|
||||
) {
|
||||
rx_total += rx.trim().parse::<u64>().unwrap_or(0);
|
||||
tx_total += tx.trim().parse::<u64>().unwrap_or(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if rx_total == 0 && tx_total == 0 {
|
||||
return Err(anyhow::anyhow!("No network data available").into());
|
||||
} else {
|
||||
return Ok((rx_total, tx_total));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
|
||||
Err("No network data available for this OS".into())
|
||||
}
|
||||
|
||||
fn get_network_interfaces() -> Vec<String> {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use std::ffi::CStr;
|
||||
use std::ptr::null_mut;
|
||||
use winapi::shared::ifmib::MIB_IFTABLE;
|
||||
use winapi::um::iphlpapi::GetIfTable;
|
||||
|
||||
unsafe {
|
||||
let mut buffer_size = 0u32;
|
||||
if GetIfTable(null_mut(), &mut buffer_size, 0)
|
||||
!= winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER
|
||||
{
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let mut buffer = vec![0u8; buffer_size as usize];
|
||||
let if_table = buffer.as_mut_ptr() as *mut MIB_IFTABLE;
|
||||
|
||||
if GetIfTable(if_table, &mut buffer_size, 0) != 0 {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
(0..(*if_table).dwNumEntries)
|
||||
.map(|i| {
|
||||
let row = &*((*if_table).table.as_ptr().offset(i as isize));
|
||||
let descr = CStr::from_ptr(row.bDescr.as_ptr() as *const i8)
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
descr.trim().to_string()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use std::fs;
|
||||
|
||||
let mut interfaces = vec![];
|
||||
if let Ok(dir) = fs::read_dir("/sys/class/net") {
|
||||
for entry in dir.flatten() {
|
||||
let iface = entry.file_name();
|
||||
interfaces.push(iface.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
interfaces
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
|
||||
vec![]
|
||||
}
|
||||
|
Reference in New Issue
Block a user