cut down on bloat? or scale up on bloat?

This commit is contained in:
lda
2025-08-23 06:15:28 +07:00 Unverified
parent 69f4662826
commit 0fb1acd61a
4 changed files with 130 additions and 63 deletions
+4
View File
@@ -12,3 +12,7 @@ macaddr = "1.0.1"
strum = { version = "0.27.2", features = ["derive", "strum_macros"] } strum = { version = "0.27.2", features = ["derive", "strum_macros"] }
thiserror = "2.0.16" thiserror = "2.0.16"
tokio = { version = "1.47.1", features = ["fs", "process", "rt-multi-thread"] } tokio = { version = "1.47.1", features = ["fs", "process", "rt-multi-thread"] }
[profile.release]
opt-level = "z"
strip = true
+49
View File
@@ -148,3 +148,52 @@ impl IpNeighLine {
self.ip = ip; self.ip = ip;
} }
} }
// ideas from copilot:
impl NUDState {
// higher is "better"/more online
pub const fn rank(self) -> u8 {
match self {
NUDState::Permanent | NUDState::Reachable => 5,
NUDState::Stale => 4,
NUDState::Delay | NUDState::Probe | NUDState::Incomplete => 3,
NUDState::Noarp => 2,
NUDState::None => 1,
NUDState::Failed => 0,
}
}
}
impl PartialOrd for NUDState {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for NUDState {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.rank().cmp(&other.rank())
}
}
impl IpNeighLine {
// score for “local and online”: state, has-mac, v4, iface preference
pub fn score(&self) -> (u8, u8, u8, u8) {
let iface = self
.dev
.as_deref()
.map(|d| {
if d.starts_with("br") || d.starts_with("lan") || d.starts_with("eth") { 2 }
else if d.starts_with("wlan") || d.starts_with("wl") { 1 }
else { 0 }
})
.unwrap_or(0);
(
self.state.rank(),
self.mac.is_some() as u8,
matches!(self.ip, IpAddr::V4(_)) as u8,
iface,
)
}
}
+28 -26
View File
@@ -30,61 +30,63 @@ async fn home() -> Html<String> {
)) ))
} }
async fn wake_handler() -> &'static str { async fn wake_handler() -> axum::response::Result< &'static str> {
match wake(MACHINE_NAME).await { match wake(MACHINE_NAME).await {
Ok(x) if x > 0 => "Packet sent!", Ok(x) if x > 0 => Ok("Packet sent!"),
_ => "Wake failed", _ => Err("Wake failed".into()),
} }
} }
async fn status() -> Html<String> { async fn status() -> Html<String> {
let formatted_ips = match get_ips(MACHINE_NAME).await { // let formatted_ips = match get_ips(MACHINE_NAME).await {
Ok(ips) => { // Ok(ips) => {
let string: String = ips // let string: String = ips
.iter() // .iter()
.map(|ip| format!("<tr><td>{ip}</td></tr>")) // .map(|ip| format!("<tr><td>{ip}</td></tr>"))
.collect(); // .collect();
format!( // format!(
r#"<p>the ips of {m} are:</p> // r#"<p>the ips of {m} are:</p>
<table> // <table>
<tr><th>IP</th></tr> // <tr><th>IP</th></tr>
{string} // {string}
</table>"#, // </table>"#,
m = MACHINE_NAME // m = MACHINE_NAME
) // )
} // }
Err(e) => format!("<p>error getting ips: {e}</p>"), // Err(e) => format!("<p>error getting ips: {e}</p>"),
}; // };
let formatted_macs = match get_macs_2_1(MACHINE_NAME).await { let formatted_macs = match get_macs_2_1(MACHINE_NAME).await {
Ok(table) => { Ok(table) => {
let the: String = table let the: String = table
.iter() .iter()
.map(|(ip, mac)| { .map(|(ip, mac, state)| {
let mac_str = // if let Some(mac) = mac { let mac_str = // if let Some(mac) = mac {
mac.to_string() mac.to_string()
// } else { // } else {
// "None".into() // "None".into()
// } // }
; ;
format!("<tr><td>{ip}</td><td>{mac_str}</td></tr>") format!(
"<tr><td>{ip}</td><td>{mac_str}</td><td>{state}</td></tr>",
state = state.dumber_state()
)
}) })
.collect(); .collect();
format!( format!(
r#"<p>the macs here:</p> r#"<p>info of {MACHINE_NAME}:</p>
<table> <table>
<tr><th>IP</th><th>MAC</th></tr> <tr><th>IP</th><th>MAC</th><th>State</th></tr>
{the} {the}
</table>"# </table>"#
) )
} }
Err(e) => format!("<p>cant get macs either: {e}</p>"), Err(e) => format!("<p>errors getting table for {MACHINE_NAME}: {e}</p>"),
}; };
Html(format!( Html(format!(
r#" r#"
<html> <html>
<body> <body>
{formatted_ips}
{formatted_macs} {formatted_macs}
</body> </body>
</html> </html>
+48 -36
View File
@@ -10,41 +10,28 @@ pub static LDA_MACS_2: LazyLock<[MacAddr; 2]> = LazyLock::new(|| LDA_MACS.map(Ma
pub async fn wake(machine_name: &str) -> io::Result<u32> { pub async fn wake(machine_name: &str) -> io::Result<u32> {
let suh = UdpSocket::bind("0.0.0.0:0").await?; let suh = UdpSocket::bind("0.0.0.0:0").await?;
suh.set_broadcast(true)?; suh.set_broadcast(true)?;
let mut macs = get_macs_2_1(machine_name).await.unwrap_or_default(); let mut macs = get_macs_2_mac(machine_name).await.unwrap_or_default();
macs.extend(LDA_MACS_2.map(|m| ([192, 168, 100, 255].into(), m))); macs.extend(*LDA_MACS_2);
let len = macs.len() as u32; let mut sent_ok = 0;
// count - count fail for mac in macs {
let mut count_fail = 0;
for (ip, mac) in macs.into_iter() {
// let Some(mac) = mac else {
// continue;
// };
let mb = mac.as_bytes(); let mb = mac.as_bytes();
let start = [0xff; 6];
let pac: Vec<u8> = iter::once(start.as_slice()) let mut pac = [0; 6 + 6 * 16]; // 6x FF + 16x mac6
.chain(iter::repeat_n(mb, 16)) pac[..6].fill(0xff);
// what happens here? for i in 1..=16 {
.flatten() pac[i * 6..(i + 1) * 6].copy_from_slice(mb);
.copied() }
.collect();
suh.send_to(&pac, (ip, 9)) match suh
.send_to(&pac, (IpAddr::from([192, 168, 100, 255]), 9))
.await .await
.inspect_err(|e| { {
eprintln!("ping error: {e}"); Ok(n) if n == pac.len() => sent_ok += 1,
count_fail += 1; Ok(n) => eprintln!("partial send ({n}/{})", pac.len()),
}) Err(e) => eprintln!("send error: {e}"),
.ok()
.inspect(|f| {
if *f < (6 + 16 * 6) {
// rare ass code path
eprintln!("not complete transmission");
count_fail += 1;
} }
}); // type shit
// suh.send_to(&pac, "192.168.100.255:9").await?; // type good
// suh.send_to(&pac, "255.255.255.255:9").await?; // type ass; this doesnt work somehow.
} }
Ok(len - count_fail) Ok(sent_ok)
} }
use std::{collections::HashSet, iter, net::IpAddr, str::FromStr, sync::LazyLock, time::Duration}; use std::{collections::HashSet, iter, net::IpAddr, str::FromStr, sync::LazyLock, time::Duration};
@@ -55,7 +42,7 @@ use tokio::{
time::timeout, time::timeout,
}; };
use crate::arpparse::{self, IpNeighLine}; use crate::arpparse::{self, IpNeighLine, NUDState};
/// generic so you can do "123.45.67.89:22" or "lda.lan:22" as an input /// generic so you can do "123.45.67.89:22" or "lda.lan:22" as an input
// this is so bad // this is so bad
@@ -84,7 +71,7 @@ pub async fn get_macs(machine_name: &str) -> io::Result<Vec<(IpAddr, MacAddr)>>
.map(|ip| { .map(|ip| {
let ip = ip.to_canonical(); let ip = ip.to_canonical();
async move { async move {
let o = exec_command("ip", ["neigh", "show", "to", &ip.to_string()]) let o = exec_command("ip", ["neigh", "show", "to", &ip.to_string(), "dev", "br-lan"])
.await .await
.ok()?; .ok()?;
o.status.success().then(|| { o.status.success().then(|| {
@@ -112,7 +99,7 @@ pub async fn get_macs_1(machine_name: &str) -> io::Result<Vec<arpparse::IpNeighL
let futures = ips.iter().map(|ip| { let futures = ips.iter().map(|ip| {
let ip = ip.to_canonical(); let ip = ip.to_canonical();
async move { async move {
let o = exec_command("ip", ["neigh", "show", "to", &ip.to_string()]).await?; let o = exec_command("ip", ["neigh", "show", "to", &ip.to_string(), "dev", "br-lan"]).await?;
if !o.status.success() { if !o.status.success() {
return Err(io::Error::other(format!( return Err(io::Error::other(format!(
"`ip neigh` failed for {ip} (status: {st}): {err}", "`ip neigh` failed for {ip} (status: {st}): {err}",
@@ -147,8 +134,33 @@ pub async fn get_macs_2(machine_name: &str) -> io::Result<HashSet<(IpAddr, MacAd
Ok(get_macs(machine_name).await?.into_iter().collect()) Ok(get_macs(machine_name).await?.into_iter().collect())
} }
pub async fn get_macs_2_1(machine_name: &str) -> io::Result<HashSet<(IpAddr, MacAddr)>> { pub async fn get_macs_2_1(machine_name: &str) -> io::Result<HashSet<(IpAddr, MacAddr, NUDState)>> {
Ok(get_macs_1(machine_name).await?.into_iter().filter_map(|IpNeighLine { ip, dev: _, mac, state: _ }| mac.map(|mac| (ip, mac))).collect()) Ok(get_macs_1(machine_name)
.await?
.into_iter()
.filter_map(
|IpNeighLine {
ip,
dev: _,
mac,
state,
}| mac.map(|mac| (ip, mac, state)),
)
.collect())
}
pub async fn get_macs_2_mac(machine_name: &str) -> io::Result<HashSet<MacAddr>> {
Ok(get_macs_1(machine_name)
.await?
.into_iter()
.filter_map(
|IpNeighLine {
ip: _,
dev: _,
mac,
state: _,
}| mac,
)
.collect())
} }
pub fn to_arr(macstr: &str) -> Option<[u8; 6]> { pub fn to_arr(macstr: &str) -> Option<[u8; 6]> {