[WIP] A simple wake-on-lan service
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

remove dependency on wake-on-lan

+52 -36
-7
Cargo.lock
··· 641 641 checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" 642 642 643 643 [[package]] 644 - name = "wake-on-lan" 645 - version = "0.2.0" 646 - source = "registry+https://github.com/rust-lang/crates.io-index" 647 - checksum = "1ccf60b60ad7e5b1b37372c5134cbcab4db0706c231d212e0c643a077462bc8f" 648 - 649 - [[package]] 650 644 name = "wasi" 651 645 version = "0.11.1+wasi-snapshot-preview1" 652 646 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 756 750 "thiserror", 757 751 "tokio", 758 752 "toml", 759 - "wake-on-lan", 760 753 ] 761 754 762 755 [[package]]
-1
Cargo.toml
··· 9 9 tokio = { version = "1.49.0", features = ["full"] } 10 10 toml = "1.0.2" 11 11 axum = "0.8.8" 12 - wake-on-lan = "0.2.0"
+45 -19
src/mac.rs
··· 1 - use std::{collections::HashMap, fmt::Display, num::ParseIntError, str::FromStr}; 1 + use std::{collections::HashMap, fmt::Display, net::UdpSocket, num::ParseIntError, str::FromStr}; 2 2 3 3 use serde::{Deserialize, Deserializer, de::Error}; 4 4 use thiserror::Error; ··· 6 6 #[derive(Clone, Debug)] 7 7 pub struct MacAddress([u8; 6]); 8 8 9 + #[derive(Error, Debug)] 10 + pub enum MacAddressParseError { 11 + #[error("Integer error: {}", .0)] 12 + ParseInt(#[from] ParseIntError), 13 + #[error("Mac address to short")] 14 + TooShort, 15 + } 16 + 17 + impl MacAddress { 18 + pub fn packet(&self) -> [u8; 102] { 19 + let mut magic = [0xffu8; 17 * 6]; 20 + let mut head: *mut u8 = &mut magic[0]; 21 + let mac: *const u8 = &self.0[0]; 22 + unsafe { 23 + for _ in 0..16 { 24 + head = head.offset(6); 25 + head.copy_from_nonoverlapping(mac, 6); 26 + } 27 + }; 28 + 29 + magic 30 + } 31 + 32 + pub async fn wake(&self) -> Result<(), std::io::Error> { 33 + let packet = self.packet(); 34 + let socket = UdpSocket::bind("0.0.0.0:0")?; 35 + socket.set_broadcast(true)?; 36 + socket.send_to(&packet, "255.255.255.255:9")?; 37 + 38 + Ok(()) 39 + } 40 + } 41 + 9 42 impl Display for MacAddress { 10 43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 11 44 write!( ··· 22 55 } 23 56 } 24 57 25 - #[derive(Error, Debug)] 26 - pub enum MacAddressError { 27 - #[error("Integer error: {}", .0)] 28 - ParseInt(#[from] ParseIntError), 29 - #[error("Mac address to short")] 30 - TooShort, 31 - } 32 - 33 58 impl FromStr for MacAddress { 34 - type Err = MacAddressError; 59 + type Err = MacAddressParseError; 35 60 36 61 fn from_str(s: &str) -> Result<Self, Self::Err> { 37 62 let mut parts = s.split(":"); 38 63 let mut address: [u8; 6] = [0, 0, 0, 0, 0, 0]; 39 64 for i in 0..address.len() { 40 - address[i] = u8::from_str_radix(parts.next().ok_or(MacAddressError::TooShort)?, 16)?; 65 + address[i] = 66 + u8::from_str_radix(parts.next().ok_or(MacAddressParseError::TooShort)?, 16)?; 41 67 } 42 68 Ok(MacAddress(address)) 43 69 } 44 70 } 45 71 46 - pub fn deserialize_mac_hashmap<'de, D>(de: D) -> Result<HashMap<String, MacAddress>, D::Error> 72 + pub fn deserialize_mac<'de, D>(de: D) -> Result<MacAddress, D::Error> 47 73 where 48 74 D: Deserializer<'de>, 49 75 { 50 - HashMap::<String, String>::deserialize(de)? 51 - .into_iter() 52 - .map::<Result<_, MacAddressError>, _>(|(k, v)| Ok((k, MacAddress::from_str(&v)?))) 53 - .collect::<Result<_, _>>() 54 - .map_err(Error::custom) 76 + MacAddress::from_str(&String::deserialize(de)?).map_err(Error::custom) 55 77 } 56 78 57 - pub fn deserialize_mac<'de, D>(de: D) -> Result<MacAddress, D::Error> 79 + pub fn deserialize_mac_hashmap<'de, D>(de: D) -> Result<HashMap<String, MacAddress>, D::Error> 58 80 where 59 81 D: Deserializer<'de>, 60 82 { 61 - MacAddress::from_str(&String::deserialize(de)?).map_err(Error::custom) 83 + HashMap::<String, String>::deserialize(de)? 84 + .into_iter() 85 + .map::<Result<_, MacAddressParseError>, _>(|(k, v)| Ok((k, MacAddress::from_str(&v)?))) 86 + .collect::<Result<_, _>>() 87 + .map_err(Error::custom) 62 88 }
+7 -9
src/server/mod.rs
··· 34 34 35 35 pub async fn wake(Json(req): Json<WakeRequest>) -> Result<(), Response<String>> { 36 36 println!("Waking {}", req.mac); 37 - wake_on_lan::MagicPacket::new(&req.mac.into()) 38 - .send() 39 - .map_err(|err| { 40 - Response::builder() 41 - .status(500) 42 - .body(err.to_string()) 43 - // unwrap is safe since this will always be a valid respose 44 - .unwrap() 45 - }) 37 + req.mac.wake().await.map_err(|err| { 38 + Response::builder() 39 + .status(500) 40 + .body(err.to_string()) 41 + // unwrap is safe since this will always be a valid respose 42 + .unwrap() 43 + }) 46 44 } 47 45 48 46 pub fn router(map: HashMap<String, MacAddress>) -> Router {