use std::collections::HashMap;
pub struct SharedCache {
pub netstat: Option<NetstatCache>,
pub ipconfig: Option<IpconfigCache>,
pub sysinfo_networks: Option<sysinfo::Networks>,
pub gateway_ip: Option<String>,
}
pub struct NetstatCache {
pub lines: Vec<String>,
pub process_map: HashMap<u32, String>,
}
pub struct IpconfigCache {
pub raw: String,
}
impl SharedCache {
pub async fn build_for_tech_mode() -> Self {
let (netstat, ipconfig, networks, gateway) = tokio::join!(
fetch_netstat(),
fetch_ipconfig(),
fetch_sysinfo_networks(),
fetch_gateway(),
);
Self {
netstat,
ipconfig,
sysinfo_networks: networks,
gateway_ip: gateway,
}
}
}
#[cfg(windows)]
async fn fetch_netstat() -> Option<NetstatCache> {
use sysinfo::System;
let mut cmd = tokio::process::Command::new("netstat");
cmd.args(["-ano"]);
let output = super::util::run_with_timeout(cmd, super::util::QUICK).await?;
let text = String::from_utf8_lossy(&output.stdout);
let lines: Vec<String> = text.lines().map(|l| l.to_string()).collect();
let process_map = tokio::task::spawn_blocking(|| {
let mut sys = System::new();
sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
let mut map = HashMap::new();
for (pid, process) in sys.processes() {
map.insert(pid.as_u32(), process.name().to_string_lossy().to_string());
}
map
})
.await
.unwrap_or_default();
Some(NetstatCache { lines, process_map })
}
#[cfg(target_os = "macos")]
async fn fetch_netstat() -> Option<NetstatCache> {
let mut cmd = tokio::process::Command::new("netstat");
cmd.args(["-anp", "tcp"]);
let output = super::util::run_with_timeout(cmd, super::util::QUICK).await?;
let text = String::from_utf8_lossy(&output.stdout);
let lines: Vec<String> = text.lines().map(|l| l.to_string()).collect();
Some(NetstatCache {
lines,
process_map: HashMap::new(),
})
}
#[cfg(target_os = "linux")]
async fn fetch_netstat() -> Option<NetstatCache> {
let mut cmd = tokio::process::Command::new("netstat");
cmd.args(["-an"]);
let output = super::util::run_with_timeout(cmd, super::util::QUICK).await?;
let text = String::from_utf8_lossy(&output.stdout);
let lines: Vec<String> = text.lines().map(|l| l.to_string()).collect();
Some(NetstatCache {
lines,
process_map: HashMap::new(),
})
}
#[cfg(windows)]
async fn fetch_ipconfig() -> Option<IpconfigCache> {
let mut cmd = tokio::process::Command::new("ipconfig");
cmd.args(["/all"]);
let output = super::util::run_with_timeout(cmd, super::util::QUICK).await?;
let raw = String::from_utf8_lossy(&output.stdout).to_string();
Some(IpconfigCache { raw })
}
#[cfg(not(windows))]
async fn fetch_ipconfig() -> Option<IpconfigCache> {
None
}
async fn fetch_sysinfo_networks() -> Option<sysinfo::Networks> {
Some(sysinfo::Networks::new_with_refreshed_list())
}
async fn fetch_gateway() -> Option<String> {
default_net::get_default_gateway()
.ok()
.map(|gw| gw.ip_addr.to_string())
}