single tool
This commit is contained in:
+92
@@ -0,0 +1,92 @@
|
||||
use std::net::UdpSocket;
|
||||
|
||||
use crate::{
|
||||
config::Config, daemon, error::{WError, WResult}, ifaddrs::{self},
|
||||
};
|
||||
|
||||
pub struct Wolz {
|
||||
config: Config,
|
||||
}
|
||||
|
||||
pub struct WCommand {
|
||||
name: String,
|
||||
arg: String,
|
||||
}
|
||||
|
||||
impl WCommand {
|
||||
pub fn create(name: String, arg: String) -> Self {
|
||||
Self { name, arg }
|
||||
}
|
||||
}
|
||||
|
||||
impl Wolz {
|
||||
pub fn create() -> WResult<Self> {
|
||||
let config = Config::create()?;
|
||||
Ok(Self { config })
|
||||
}
|
||||
|
||||
pub fn execute(&self, command: &WCommand) -> WResult<()> {
|
||||
match command.name.as_str() {
|
||||
"up" => self.wake_up(&command.arg),
|
||||
"down" => self.shut_down(&command.arg),
|
||||
_ => Err(WError::InvalidCommandString(command.name.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn wake_up(&self, mac_or_nick: &str) -> WResult<()> {
|
||||
let mac = self.config.get_mac(mac_or_nick)?;
|
||||
let mut magic_bytes = [0u8; 102];
|
||||
mac.copy_magic_bytes(&mut magic_bytes);
|
||||
|
||||
let interfaces = ifaddrs::get_network_interfaces();
|
||||
let mut sent_addresses = Vec::new();
|
||||
for i in &interfaces {
|
||||
if sent_addresses.contains(&i.broadcast) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// man systemd.net-naming-scheme
|
||||
// Only broadcast to local network
|
||||
let iname = &i.name;
|
||||
if iname.starts_with("en") || iname.starts_with("wl") || iname.starts_with("eth") {
|
||||
let send_addr = format!("{}:0", i.ip);
|
||||
let broadcast_addr = format!("{}:9", i.broadcast);
|
||||
match try_send_magic_bytes(&magic_bytes, &send_addr, &broadcast_addr) {
|
||||
Ok(()) => {
|
||||
println!("Sent magic pkt {} -> {} for Mac {}", send_addr, broadcast_addr, mac);
|
||||
sent_addresses.push(i.broadcast);
|
||||
}
|
||||
Err(e) => {
|
||||
println!(
|
||||
"Unable to send magic pkt {} -> {} for Mac {}, because {}",
|
||||
send_addr, broadcast_addr, mac, e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if sent_addresses.len() == 0 {
|
||||
println!("Did not send to any address, are you connected to local network?");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn shut_down(&self, mac_or_nick: &str) -> WResult<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn try_send_magic_bytes(magic_bytes: &[u8; 102], send_addr: &str, broadcast_addr: &str) -> WResult<()> {
|
||||
let socket = UdpSocket::bind(&send_addr)
|
||||
.map_err(|e| WError::UdpSocketBindError(format!("couldn't bind to socket because {}", e)))?;
|
||||
socket
|
||||
.set_broadcast(true)
|
||||
.map_err(|e| WError::UdpSocketBindError(format!("couldn't set broadcast because {}", e)))?;
|
||||
socket
|
||||
.send_to(magic_bytes, &broadcast_addr)
|
||||
.map_err(|e| WError::UdpSocketBindError(format!("couldn't send data because {}", e)))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user