cut down on bloat? or scale up on bloat?
This commit is contained in:
@@ -12,3 +12,7 @@ macaddr = "1.0.1"
|
||||
strum = { version = "0.27.2", features = ["derive", "strum_macros"] }
|
||||
thiserror = "2.0.16"
|
||||
tokio = { version = "1.47.1", features = ["fs", "process", "rt-multi-thread"] }
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
strip = true
|
||||
@@ -148,3 +148,52 @@ impl IpNeighLine {
|
||||
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
@@ -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 {
|
||||
Ok(x) if x > 0 => "Packet sent!",
|
||||
_ => "Wake failed",
|
||||
Ok(x) if x > 0 => Ok("Packet sent!"),
|
||||
_ => Err("Wake failed".into()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn status() -> Html<String> {
|
||||
let formatted_ips = match get_ips(MACHINE_NAME).await {
|
||||
Ok(ips) => {
|
||||
let string: String = ips
|
||||
.iter()
|
||||
.map(|ip| format!("<tr><td>{ip}</td></tr>"))
|
||||
.collect();
|
||||
format!(
|
||||
r#"<p>the ips of {m} are:</p>
|
||||
<table>
|
||||
<tr><th>IP</th></tr>
|
||||
{string}
|
||||
</table>"#,
|
||||
m = MACHINE_NAME
|
||||
)
|
||||
}
|
||||
Err(e) => format!("<p>error getting ips: {e}</p>"),
|
||||
};
|
||||
// let formatted_ips = match get_ips(MACHINE_NAME).await {
|
||||
// Ok(ips) => {
|
||||
// let string: String = ips
|
||||
// .iter()
|
||||
// .map(|ip| format!("<tr><td>{ip}</td></tr>"))
|
||||
// .collect();
|
||||
// format!(
|
||||
// r#"<p>the ips of {m} are:</p>
|
||||
// <table>
|
||||
// <tr><th>IP</th></tr>
|
||||
// {string}
|
||||
// </table>"#,
|
||||
// m = MACHINE_NAME
|
||||
// )
|
||||
// }
|
||||
// Err(e) => format!("<p>error getting ips: {e}</p>"),
|
||||
// };
|
||||
let formatted_macs = match get_macs_2_1(MACHINE_NAME).await {
|
||||
Ok(table) => {
|
||||
let the: String = table
|
||||
.iter()
|
||||
.map(|(ip, mac)| {
|
||||
.map(|(ip, mac, state)| {
|
||||
let mac_str = // if let Some(mac) = mac {
|
||||
mac.to_string()
|
||||
// } else {
|
||||
// "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();
|
||||
format!(
|
||||
r#"<p>the macs here:</p>
|
||||
r#"<p>info of {MACHINE_NAME}:</p>
|
||||
<table>
|
||||
<tr><th>IP</th><th>MAC</th></tr>
|
||||
<tr><th>IP</th><th>MAC</th><th>State</th></tr>
|
||||
{the}
|
||||
</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!(
|
||||
r#"
|
||||
<html>
|
||||
<body>
|
||||
{formatted_ips}
|
||||
{formatted_macs}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+48
-36
@@ -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> {
|
||||
let suh = UdpSocket::bind("0.0.0.0:0").await?;
|
||||
suh.set_broadcast(true)?;
|
||||
let mut macs = get_macs_2_1(machine_name).await.unwrap_or_default();
|
||||
macs.extend(LDA_MACS_2.map(|m| ([192, 168, 100, 255].into(), m)));
|
||||
let len = macs.len() as u32;
|
||||
// count - count fail
|
||||
let mut count_fail = 0;
|
||||
for (ip, mac) in macs.into_iter() {
|
||||
// let Some(mac) = mac else {
|
||||
// continue;
|
||||
// };
|
||||
let mut macs = get_macs_2_mac(machine_name).await.unwrap_or_default();
|
||||
macs.extend(*LDA_MACS_2);
|
||||
let mut sent_ok = 0;
|
||||
for mac in macs {
|
||||
let mb = mac.as_bytes();
|
||||
let start = [0xff; 6];
|
||||
let pac: Vec<u8> = iter::once(start.as_slice())
|
||||
.chain(iter::repeat_n(mb, 16))
|
||||
// what happens here?
|
||||
.flatten()
|
||||
.copied()
|
||||
.collect();
|
||||
suh.send_to(&pac, (ip, 9))
|
||||
|
||||
let mut pac = [0; 6 + 6 * 16]; // 6x FF + 16x mac6
|
||||
pac[..6].fill(0xff);
|
||||
for i in 1..=16 {
|
||||
pac[i * 6..(i + 1) * 6].copy_from_slice(mb);
|
||||
}
|
||||
|
||||
match suh
|
||||
.send_to(&pac, (IpAddr::from([192, 168, 100, 255]), 9))
|
||||
.await
|
||||
.inspect_err(|e| {
|
||||
eprintln!("ping error: {e}");
|
||||
count_fail += 1;
|
||||
})
|
||||
.ok()
|
||||
.inspect(|f| {
|
||||
if *f < (6 + 16 * 6) {
|
||||
// rare ass code path
|
||||
eprintln!("not complete transmission");
|
||||
count_fail += 1;
|
||||
{
|
||||
Ok(n) if n == pac.len() => sent_ok += 1,
|
||||
Ok(n) => eprintln!("partial send ({n}/{})", pac.len()),
|
||||
Err(e) => eprintln!("send error: {e}"),
|
||||
}
|
||||
}); // 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};
|
||||
|
||||
@@ -55,7 +42,7 @@ use tokio::{
|
||||
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
|
||||
// this is so bad
|
||||
@@ -84,7 +71,7 @@ pub async fn get_macs(machine_name: &str) -> io::Result<Vec<(IpAddr, MacAddr)>>
|
||||
.map(|ip| {
|
||||
let ip = ip.to_canonical();
|
||||
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
|
||||
.ok()?;
|
||||
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 ip = ip.to_canonical();
|
||||
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() {
|
||||
return Err(io::Error::other(format!(
|
||||
"`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())
|
||||
}
|
||||
|
||||
pub async fn get_macs_2_1(machine_name: &str) -> io::Result<HashSet<(IpAddr, MacAddr)>> {
|
||||
Ok(get_macs_1(machine_name).await?.into_iter().filter_map(|IpNeighLine { ip, dev: _, mac, state: _ }| mac.map(|mac| (ip, mac))).collect())
|
||||
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, 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]> {
|
||||
|
||||
Reference in New Issue
Block a user