Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| db6fc65ee1 | |||
| 1002a6be68 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nanometrics-agent"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
+47
-3
@@ -10,22 +10,66 @@ extern "C" fn handle_signal(_: libc::c_int) {
|
||||
RUNNING.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn physical_ipv4_addrs() -> Vec<String> {
|
||||
let mut result = Vec::new();
|
||||
unsafe {
|
||||
let mut ifap = std::ptr::null_mut::<libc::ifaddrs>();
|
||||
if libc::getifaddrs(&mut ifap) != 0 { return result; }
|
||||
let mut ifa = ifap;
|
||||
while !ifa.is_null() {
|
||||
let flags = (*ifa).ifa_flags as i32;
|
||||
let up = flags & libc::IFF_UP as i32 != 0;
|
||||
let loopback = flags & libc::IFF_LOOPBACK as i32 != 0;
|
||||
let pointop = flags & libc::IFF_POINTOPOINT as i32 != 0;
|
||||
if !up || loopback || pointop { ifa = (*ifa).ifa_next; continue; }
|
||||
|
||||
let name = std::ffi::CStr::from_ptr((*ifa).ifa_name)
|
||||
.to_string_lossy().into_owned();
|
||||
|
||||
// Type 1 = ARPHRD_ETHER (Ethernet + WiFi), exclut WireGuard (65534), tunnels, etc.
|
||||
let itype: u32 = std::fs::read_to_string(
|
||||
format!("/sys/class/net/{}/type", name))
|
||||
.ok().and_then(|s| s.trim().parse().ok()).unwrap_or(0);
|
||||
if itype != 1 { ifa = (*ifa).ifa_next; continue; }
|
||||
|
||||
// Exclut bridges et interfaces Docker par nom
|
||||
let is_virtual = name.starts_with("br-") || name.starts_with("docker")
|
||||
|| name.starts_with("virbr") || name.starts_with("veth");
|
||||
if is_virtual { ifa = (*ifa).ifa_next; continue; }
|
||||
|
||||
if let Some(addr) = (*ifa).ifa_addr.as_ref() {
|
||||
if addr.sa_family as i32 == libc::AF_INET {
|
||||
let sin = addr as *const _ as *const libc::sockaddr_in;
|
||||
let b = (*sin).sin_addr.s_addr.to_ne_bytes();
|
||||
result.push(format!("{}.{}.{}.{}", b[0], b[1], b[2], b[3]));
|
||||
}
|
||||
}
|
||||
ifa = (*ifa).ifa_next;
|
||||
}
|
||||
libc::freeifaddrs(ifap);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn get_local_ip(server_ip: &str) -> String {
|
||||
let physical = physical_ipv4_addrs();
|
||||
|
||||
use std::net::UdpSocket;
|
||||
// Try server IP first (always reachable), then internet fallback
|
||||
for target in &[format!("{}:80", server_ip), "8.8.8.8:80".to_string()] {
|
||||
if let Ok(s) = UdpSocket::bind("0.0.0.0:0") {
|
||||
if s.connect(target.as_str()).is_ok() {
|
||||
if let Ok(addr) = s.local_addr() {
|
||||
let ip = addr.ip().to_string();
|
||||
if ip != "0.0.0.0" {
|
||||
// N'accepte que si c'est une vraie interface physique
|
||||
if ip != "0.0.0.0" && physical.contains(&ip) {
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"0.0.0.0".to_string()
|
||||
// Fallback : première IP physique disponible
|
||||
physical.into_iter().next().unwrap_or_else(|| "0.0.0.0".to_string())
|
||||
}
|
||||
|
||||
fn apply_config_update(cfg: &mut config::Config, data: &[u8]) {
|
||||
|
||||
@@ -26,11 +26,13 @@ pub fn current_yday() -> u32 {
|
||||
}
|
||||
|
||||
fn is_physical(name: &str) -> bool {
|
||||
if name == "lo" { return false; }
|
||||
for prefix in &["veth", "docker", "br-", "virbr", "vir", "tun", "tap", "dummy", "bond"] {
|
||||
if name.starts_with(prefix) { return false; }
|
||||
}
|
||||
true
|
||||
// Type 1 = ARPHRD_ETHER (Ethernet + WiFi). WireGuard = 65534, tunnels = autres.
|
||||
let itype: u32 = std::fs::read_to_string(format!("/sys/class/net/{}/type", name))
|
||||
.ok().and_then(|s| s.trim().parse().ok()).unwrap_or(0);
|
||||
if itype != 1 { return false; }
|
||||
// Exclut bridges et interfaces Docker par nom (type 1 aussi)
|
||||
!name.starts_with("br-") && !name.starts_with("docker")
|
||||
&& !name.starts_with("virbr") && !name.starts_with("veth")
|
||||
}
|
||||
|
||||
fn read_sysfs(iface: &str, file: &str) -> Option<String> {
|
||||
|
||||
@@ -15,7 +15,13 @@
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('../fonts/jetbrains-mono.woff2') format('woff2');
|
||||
font-weight: 400 700;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('../fonts/jetbrains-mono-bold.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,6 +2,7 @@ const Popups = (() => {
|
||||
let _currentAgentId = null;
|
||||
let _agentCfgData = null;
|
||||
let _resizeObs = null;
|
||||
let _resizeTimer = null;
|
||||
|
||||
// ══ POPUP DÉTAIL ══
|
||||
async function showDetail(agentId) {
|
||||
@@ -214,11 +215,14 @@ const Popups = (() => {
|
||||
if (_resizeObs) _resizeObs.disconnect();
|
||||
const pd = document.getElementById('popup-detail');
|
||||
_resizeObs = new ResizeObserver(() => {
|
||||
API.putServerConfig({
|
||||
...App.serverConfig,
|
||||
popup_detail_w: pd.offsetWidth,
|
||||
popup_detail_h: pd.offsetHeight,
|
||||
}).catch(() => {});
|
||||
clearTimeout(_resizeTimer);
|
||||
_resizeTimer = setTimeout(() => {
|
||||
API.putServerConfig({
|
||||
...App.serverConfig,
|
||||
popup_detail_w: pd.offsetWidth,
|
||||
popup_detail_h: pd.offsetHeight,
|
||||
}).catch(() => {});
|
||||
}, 600);
|
||||
});
|
||||
_resizeObs.observe(pd);
|
||||
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Reference in New Issue
Block a user