WIP
This commit is contained in:
19
Cargo.lock
generated
19
Cargo.lock
generated
@@ -85,6 +85,12 @@ version = "3.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.51"
|
||||
@@ -556,6 +562,7 @@ name = "roowho2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"clap",
|
||||
"nix",
|
||||
@@ -753,9 +760,21 @@ dependencies = [
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "type-map"
|
||||
version = "0.5.1"
|
||||
|
||||
@@ -15,10 +15,11 @@ autolib = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.100"
|
||||
bytes = "1.11.0"
|
||||
chrono = { version = "0.4.42", features = ["serde"] }
|
||||
clap = { version = "4.5.53", features = ["derive"] }
|
||||
nix = { version = "0.30.1", features = ["hostname", "net"] }
|
||||
tokio = { version = "1.49.0", features = ["net", "rt-multi-thread"] }
|
||||
tokio = { version = "1.49.0", features = ["macros", "net", "rt-multi-thread"] }
|
||||
# onc-rpc = "0.3.2"
|
||||
# sd-notify = "0.4.5"
|
||||
# serde = { version = "1.0.228", features = ["derive"] }
|
||||
|
||||
@@ -1,10 +1,29 @@
|
||||
fn main() {
|
||||
println!(
|
||||
"{:#?}",
|
||||
roowho2_lib::server::rwhod::generate_rwhod_status_update(),
|
||||
);
|
||||
println!(
|
||||
"{:#?}",
|
||||
roowho2_lib::server::rwhod::determine_relevant_interfaces(),
|
||||
use std::net::SocketAddrV4;
|
||||
|
||||
use roowho2_lib::proto::Whod;
|
||||
|
||||
const RWHOD_BROADCAST_PORT: u16 = 513;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let addr = SocketAddrV4::new(
|
||||
std::net::Ipv4Addr::UNSPECIFIED,
|
||||
RWHOD_BROADCAST_PORT,
|
||||
);
|
||||
let socket = tokio::net::UdpSocket::bind(addr).await?;
|
||||
socket.set_broadcast(true)?;
|
||||
|
||||
let mut buf = [0u8; Whod::SIZE];
|
||||
loop {
|
||||
let (len, src) = socket.recv_from(&mut buf).await?;
|
||||
if len == Whod::SIZE {
|
||||
if let Ok(whod) = Whod::from_bytes(&buf) {
|
||||
println!("Received whod packet from {}: {:?}", src, whod);
|
||||
} else {
|
||||
println!("Received malformed whod packet from {}", src);
|
||||
}
|
||||
} else {
|
||||
println!("Received unexpected packet size {} from {}", len, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,13 +56,88 @@ impl Whod {
|
||||
// NOTE: there was probably meant to be more packet types, but only status is defined.
|
||||
pub const WHODTYPE_STATUS: u8 = 1;
|
||||
|
||||
pub fn to_bytes(&self) -> [u8; std::mem::size_of::<Whod>()] {
|
||||
pub fn to_bytes(&self) -> [u8; Whod::SIZE] {
|
||||
unsafe { std::mem::transmute_copy(self) }
|
||||
}
|
||||
|
||||
// TODO: we should probably make a safer parser.
|
||||
pub fn from_bytes(bytes: &[u8; std::mem::size_of::<Whod>()]) -> Self {
|
||||
unsafe { std::mem::transmute_copy(bytes) }
|
||||
// TODO: use the bytes crate to make this simpler and safer
|
||||
pub fn from_bytes(bytes: &[u8; Whod::SIZE]) -> anyhow::Result<Self> {
|
||||
let mut i = 0;
|
||||
|
||||
let wd_vers = bytes[i];
|
||||
i += 1;
|
||||
|
||||
let wd_type = bytes[1];
|
||||
i += 1;
|
||||
|
||||
i += 2; // skip wd_pad
|
||||
|
||||
let wd_sendtime = i32::from_le_bytes(bytes[i..i + 4].try_into()?);
|
||||
i += 4;
|
||||
|
||||
let wd_recvtime = i32::from_le_bytes(bytes[i..i + 4].try_into()?);
|
||||
i += 4;
|
||||
|
||||
let mut wd_hostname = [0u8; Self::MAX_HOSTNAME_LEN];
|
||||
wd_hostname.copy_from_slice(&bytes[i..i + Self::MAX_HOSTNAME_LEN]);
|
||||
i += Self::MAX_HOSTNAME_LEN;
|
||||
|
||||
let wd_loadav = [
|
||||
i32::from_le_bytes(bytes[i..i + 4].try_into()?),
|
||||
i32::from_le_bytes(bytes[i + 4..i + 8].try_into()?),
|
||||
i32::from_le_bytes(bytes[i + 8..i + 12].try_into()?),
|
||||
];
|
||||
|
||||
i += 4 * 3;
|
||||
|
||||
let wd_boottime = i32::from_le_bytes(bytes[i..i + 4].try_into()?);
|
||||
i += 4;
|
||||
|
||||
let mut wd_we = array::from_fn(|_| Whoent {
|
||||
we_utmp: Outmp {
|
||||
out_line: [0u8; Outmp::MAX_TTY_NAME_LEN],
|
||||
out_name: [0u8; Outmp::MAX_USER_ID_LEN],
|
||||
out_time: 0,
|
||||
},
|
||||
we_idle: 0,
|
||||
});
|
||||
|
||||
for entry in wd_we.iter_mut() {
|
||||
let mut out_line = [0u8; Outmp::MAX_TTY_NAME_LEN];
|
||||
out_line.copy_from_slice(&bytes[i..i + Outmp::MAX_TTY_NAME_LEN]);
|
||||
i += Outmp::MAX_TTY_NAME_LEN;
|
||||
|
||||
let mut out_name = [0u8; Outmp::MAX_USER_ID_LEN];
|
||||
out_name.copy_from_slice(&bytes[i..i + Outmp::MAX_USER_ID_LEN]);
|
||||
i += Outmp::MAX_USER_ID_LEN;
|
||||
|
||||
let out_time = i32::from_le_bytes(bytes[i..i + 4].try_into()?);
|
||||
i += 4;
|
||||
|
||||
let we_idle = i32::from_le_bytes(bytes[i..i + 4].try_into()?);
|
||||
i += 4;
|
||||
|
||||
entry.we_utmp = Outmp {
|
||||
out_line,
|
||||
out_name,
|
||||
out_time,
|
||||
};
|
||||
entry.we_idle = we_idle;
|
||||
}
|
||||
|
||||
debug_assert!(i == Whod::SIZE);
|
||||
|
||||
Ok(Whod {
|
||||
wd_vers,
|
||||
wd_type,
|
||||
wd_pad: [0u8; 2],
|
||||
wd_sendtime,
|
||||
wd_recvtime,
|
||||
wd_hostname,
|
||||
wd_loadav,
|
||||
wd_boottime,
|
||||
wd_we,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user