diff --git a/Cargo.lock b/Cargo.lock index 894382389..aa4c87dd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -570,13 +570,28 @@ checksum = "ab8b79fe3946ceb4a0b1c080b4018992b8d27e9ff363644c1c9b6387c854614d" dependencies = [ "atty", "bitflags", + "clap_derive", "clap_lex", "indexmap", + "once_cell", "strsim 0.10.0", "termcolor", "textwrap 0.15.0", ] +[[package]] +name = "clap_derive" +version = "3.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6db9e867166a43a53f7199b5e4d1f522a1e5bd626654be263c999ce59df39a" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -4146,6 +4161,7 @@ dependencies = [ "winit", "winreg 0.10.1", "winres", + "wol-rs", ] [[package]] @@ -5713,6 +5729,15 @@ dependencies = [ "toml", ] +[[package]] +name = "wol-rs" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f97e69b28b256ccfb02472c25057132e234aa8368fea3bb0268def564ce1f2" +dependencies = [ + "clap 3.2.6", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index 14cae5f9d..c008f7828 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ base64 = "0.13" sysinfo = "0.23" num_cpus = "1.13" default-net = "0.11.0" +wol-rs = "0.9.1" [target.'cfg(not(target_os = "linux"))'.dependencies] reqwest = { version = "0.11", features = ["json", "rustls-tls"], default-features=false } diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index ee8433770..8d2437c30 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -860,7 +860,7 @@ impl LocalConfig { pub struct DiscoveryPeer { pub id: String, #[serde(with = "serde_with::rust::map_as_tuple_list")] - pub mac_ips: HashMap, + pub ip_mac: HashMap, pub username: String, pub hostname: String, pub platform: String, diff --git a/src/rendezvous_mediator.rs b/src/rendezvous_mediator.rs index d87357366..f4f4fb15c 100644 --- a/src/rendezvous_mediator.rs +++ b/src/rendezvous_mediator.rs @@ -700,10 +700,9 @@ fn wait_response( if mac != p.mac { allow_err!(tx.send(config::DiscoveryPeer { id: p.id.clone(), - mac_ips: HashMap::from([( - p.mac.clone(), - addr.ip().to_string() - )]), + ip_mac: HashMap::from([ + (addr.ip().to_string(), p.mac.clone(),) + ]), username: p.username.clone(), hostname: p.hostname.clone(), platform: p.platform.clone(), @@ -744,7 +743,6 @@ async fn handle_received_peers(mut rx: UnboundedReceiver) peer.online = false; }); - // handle received peers let mut response_set = HashSet::new(); let mut last_write_time = Instant::now() - std::time::Duration::from_secs(4); loop { @@ -753,20 +751,24 @@ async fn handle_received_peers(mut rx: UnboundedReceiver) Some(peer) => { let in_response_set = !response_set.insert(peer.id.clone()); let mut pre_found = false; + // Try find and update peer for peer1 in &mut peers { if peer1.is_same_peer(&peer) { if in_response_set { - peer1.mac_ips.extend(peer.mac_ips.clone()); + // Merge ip_mac and update other infos + peer1.ip_mac.extend(peer.ip_mac.clone()); peer1.hostname = peer.hostname.clone(); peer1.platform = peer.platform.clone(); peer1.online = true; } else { + // Update all peer infos *peer1 = peer.clone(); } pre_found = true; break } } + // Push if not found if !pre_found { peers.push(peer); } @@ -796,3 +798,31 @@ pub async fn discover() -> ResultType<()> { log::info!("discover ping done"); Ok(()) } + +pub fn send_wol(id: String) { + let interfaces = default_net::get_interfaces(); + for peer in &config::LanPeers::load().peers { + if peer.id == id { + for (ip, mac) in peer.ip_mac.iter() { + if let Ok(mac_addr) = mac.parse() { + if let Ok(IpAddr::V4(ip)) = ip.parse() { + for interface in &interfaces { + for ipv4 in &interface.ipv4 { + if (u32::from(ipv4.addr) & u32::from(ipv4.netmask)) + == (u32::from(ip) & u32::from(ipv4.netmask)) + { + allow_err!(wol::send_wol( + mac_addr, + None, + Some(IpAddr::V4(ipv4.addr)) + )); + } + } + } + } + } + } + break; + } + } +} diff --git a/src/ui.rs b/src/ui.rs index 4bf201c0e..084422f6b 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -547,6 +547,10 @@ impl UI { config::LanPeers::store(&peers); } + fn send_wol(&mut self, id: String) { + crate::rendezvous_mediator::send_wol(id) + } + fn new_remote(&mut self, id: String, remote_type: String) { let mut lock = self.0.lock().unwrap(); let args = vec![format!("--{}", remote_type), id.clone()]; @@ -786,6 +790,7 @@ impl sciter::EventHandler for UI { fn closing(i32, i32, i32, i32); fn get_size(); fn new_remote(String, bool); + fn send_wol(String); fn remove_peer(String); fn remove_discovered(String); fn get_connect_status(); diff --git a/src/ui/ab.tis b/src/ui/ab.tis index 2fda2a5e1..5b822ed22 100644 --- a/src/ui/ab.tis +++ b/src/ui/ab.tis @@ -318,10 +318,11 @@ class SessionList: Reactor.Component {
  • {translate('TCP Tunneling')}
  • {false && !handler.using_public_server() &&
  • {svg_checkmark}{translate('Always connect via relay')}
  • }
  • RDP
  • +
  • {translate('WOL')}
  • {this.type != "lan" &&
  • {translate('Rename')}
  • } {this.type != "fav" &&
  • {translate('Remove')}
  • } - {is_win && this.type != "lan" &&
  • {translate('Create Desktop Shortcut')}
  • } + {is_win &&
  • {translate('Create Desktop Shortcut')}
  • }
  • {translate('Unremember Password')}
  • {(!this.type || this.type == "fav") &&
  • {translate('Add to Favorites')}
  • } {(!this.type || this.type == "fav") &&
  • {translate('Remove from Favorites')}
  • } @@ -419,6 +420,8 @@ class SessionList: Reactor.Component { createNewConnect(id, "connect"); } else if (action == "transfer") { createNewConnect(id, "file-transfer"); + } else if (action == "wol") { + handler.send_wol(id); } else if (action == "remove") { if (this.type == "ab") { for (var i = 0; i < ab.peers.length; ++i) {