lan_discovery_WOL: mid commit
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
d3fc6ccd9c
commit
7e0f7be95c
83
Cargo.lock
generated
83
Cargo.lock
generated
@ -1176,6 +1176,18 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "default-net"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05e70d471b0ba4e722c85651b3bb04b6880dfdb1224a43ade80c1295314db646"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"memalloc",
|
||||
"system-configuration",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "0.8.6"
|
||||
@ -2673,6 +2685,12 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
|
||||
[[package]]
|
||||
name = "memalloc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
@ -4080,6 +4098,7 @@ dependencies = [
|
||||
"cpal",
|
||||
"ctrlc",
|
||||
"dasp",
|
||||
"default-net",
|
||||
"dispatch",
|
||||
"enigo",
|
||||
"flexi_logger",
|
||||
@ -4680,6 +4699,27 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75182f12f490e953596550b65ee31bda7c8e043d9386174b353bda50838c3fd"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation 0.9.3",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.8.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "1.3.2"
|
||||
@ -5450,6 +5490,19 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.30.0",
|
||||
"windows_i686_gnu 0.30.0",
|
||||
"windows_i686_msvc 0.30.0",
|
||||
"windows_x86_64_gnu 0.30.0",
|
||||
"windows_x86_64_msvc 0.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-service"
|
||||
version = "0.4.0"
|
||||
@ -5494,6 +5547,12 @@ version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
@ -5506,6 +5565,12 @@ version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
@ -5518,6 +5583,12 @@ version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
@ -5530,6 +5601,12 @@ version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
@ -5542,6 +5619,12 @@ version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
|
@ -55,6 +55,7 @@ rpassword = "6.0"
|
||||
base64 = "0.13"
|
||||
sysinfo = "0.23"
|
||||
num_cpus = "1.13"
|
||||
default-net = "0.11.0"
|
||||
|
||||
[target.'cfg(not(target_os = "linux"))'.dependencies]
|
||||
reqwest = { version = "0.11", features = ["json", "rustls-tls"], default-features=false }
|
||||
|
@ -1,4 +1,7 @@
|
||||
use crate::server::{check_zombie, new as new_server, ServerPtr};
|
||||
use crate::{
|
||||
ipc::get_id,
|
||||
server::{check_zombie, new as new_server, ServerPtr},
|
||||
};
|
||||
use hbb_common::{
|
||||
allow_err,
|
||||
anyhow::bail,
|
||||
@ -15,8 +18,9 @@ use hbb_common::{
|
||||
udp::FramedSocket,
|
||||
AddrMangle, IntoTargetAddr, ResultType, TargetAddr,
|
||||
};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{
|
||||
net::SocketAddr,
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr, ToSocketAddrs, UdpSocket},
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, Mutex,
|
||||
@ -62,11 +66,9 @@ impl RendezvousMediator {
|
||||
direct_server(server_cloned).await;
|
||||
});
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
if crate::platform::is_installed() {
|
||||
std::thread::spawn(move || {
|
||||
allow_err!(lan_discovery());
|
||||
});
|
||||
}
|
||||
std::thread::spawn(move || {
|
||||
allow_err!(lan_discovery());
|
||||
});
|
||||
loop {
|
||||
Config::reset_online();
|
||||
if Config::get_option("stop-service").is_empty() {
|
||||
@ -546,9 +548,19 @@ pub fn get_broadcast_port() -> u16 {
|
||||
(RENDEZVOUS_PORT + 3) as _
|
||||
}
|
||||
|
||||
pub fn get_mac() -> String {
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
pub struct DiscoveryPeer {
|
||||
id: String,
|
||||
mac: String,
|
||||
ip: String,
|
||||
username: String,
|
||||
hostname: String,
|
||||
platform: String,
|
||||
}
|
||||
|
||||
pub fn get_mac(ip: &IpAddr) -> String {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
if let Ok(Some(mac)) = mac_address::get_mac_address() {
|
||||
if let Ok(mac) = get_mac_by_ip(ip) {
|
||||
mac.to_string()
|
||||
} else {
|
||||
"".to_owned()
|
||||
@ -557,6 +569,56 @@ pub fn get_mac() -> String {
|
||||
"".to_owned()
|
||||
}
|
||||
|
||||
fn get_all_ipv4s() -> ResultType<Vec<Ipv4Addr>> {
|
||||
let mut ipv4s = Vec::new();
|
||||
for interface in default_net::get_interfaces() {
|
||||
for ipv4 in &interface.ipv4 {
|
||||
ipv4s.push(ipv4.addr.clone());
|
||||
}
|
||||
}
|
||||
Ok(ipv4s)
|
||||
}
|
||||
|
||||
fn get_mac_by_ip(ip: &IpAddr) -> ResultType<String> {
|
||||
for interface in default_net::get_interfaces() {
|
||||
match ip {
|
||||
IpAddr::V4(local_ipv4) => {
|
||||
if interface.ipv4.iter().any(|x| x.addr == *local_ipv4) {
|
||||
if let Some(mac_addr) = interface.mac_addr {
|
||||
return Ok(mac_addr.address());
|
||||
}
|
||||
}
|
||||
}
|
||||
IpAddr::V6(local_ipv6) => {
|
||||
if interface.ipv6.iter().any(|x| x.addr == *local_ipv6) {
|
||||
if let Some(mac_addr) = interface.mac_addr {
|
||||
return Ok(mac_addr.address());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bail!("No interface found for ip: {:?}", ip);
|
||||
}
|
||||
|
||||
// Mainly from https://github.com/shellrow/default-net/blob/cf7ca24e7e6e8e566ed32346c9cfddab3f47e2d6/src/interface/shared.rs#L4
|
||||
pub fn get_ipaddr_by_peer<A: ToSocketAddrs>(peer: A) -> Option<IpAddr> {
|
||||
let socket = match UdpSocket::bind("0.0.0.0:0") {
|
||||
Ok(s) => s,
|
||||
Err(_) => return None,
|
||||
};
|
||||
|
||||
match socket.connect(peer) {
|
||||
Ok(()) => (),
|
||||
Err(_) => return None,
|
||||
};
|
||||
|
||||
match socket.local_addr() {
|
||||
Ok(addr) => return Some(addr.ip()),
|
||||
Err(_) => return None,
|
||||
};
|
||||
}
|
||||
|
||||
fn lan_discovery() -> ResultType<()> {
|
||||
let addr = SocketAddr::from(([0, 0, 0, 0], get_broadcast_port()));
|
||||
let socket = std::net::UdpSocket::bind(addr)?;
|
||||
@ -569,18 +631,20 @@ fn lan_discovery() -> ResultType<()> {
|
||||
match msg_in.union {
|
||||
Some(rendezvous_message::Union::PeerDiscovery(p)) => {
|
||||
if p.cmd == "ping" {
|
||||
let mut msg_out = Message::new();
|
||||
let peer = PeerDiscovery {
|
||||
cmd: "pong".to_owned(),
|
||||
mac: get_mac(),
|
||||
id: Config::get_id(),
|
||||
hostname: whoami::hostname(),
|
||||
username: crate::platform::get_active_username(),
|
||||
platform: whoami::platform().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
msg_out.set_peer_discovery(peer);
|
||||
socket.send_to(&msg_out.write_to_bytes()?, addr).ok();
|
||||
if let Some(self_addr) = get_ipaddr_by_peer(&addr) {
|
||||
let mut msg_out = Message::new();
|
||||
let peer = PeerDiscovery {
|
||||
cmd: "pong".to_owned(),
|
||||
mac: get_mac(&self_addr),
|
||||
id: Config::get_id(),
|
||||
hostname: whoami::hostname(),
|
||||
username: crate::platform::get_active_username(),
|
||||
platform: whoami::platform().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
msg_out.set_peer_discovery(peer);
|
||||
socket.send_to(&msg_out.write_to_bytes()?, addr).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -590,10 +654,25 @@ fn lan_discovery() -> ResultType<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn discover() -> ResultType<()> {
|
||||
let addr = SocketAddr::from(([0, 0, 0, 0], 0));
|
||||
let socket = std::net::UdpSocket::bind(addr)?;
|
||||
socket.set_broadcast(true)?;
|
||||
fn create_broadcast_sockets() -> ResultType<Vec<UdpSocket>> {
|
||||
let mut sockets = Vec::new();
|
||||
for v4_addr in get_all_ipv4s()? {
|
||||
if v4_addr.is_private() {
|
||||
let s = UdpSocket::bind(SocketAddr::from((v4_addr, 0)))?;
|
||||
s.set_broadcast(true)?;
|
||||
log::debug!("Bind socket to {}", &v4_addr);
|
||||
sockets.push(s)
|
||||
}
|
||||
}
|
||||
Ok(sockets)
|
||||
}
|
||||
|
||||
fn send_query() -> ResultType<Vec<UdpSocket>> {
|
||||
let sockets = create_broadcast_sockets()?;
|
||||
if sockets.is_empty() {
|
||||
bail!("Found no ipv4 addresses");
|
||||
}
|
||||
|
||||
let mut msg_out = Message::new();
|
||||
let peer = PeerDiscovery {
|
||||
cmd: "ping".to_owned(),
|
||||
@ -601,25 +680,49 @@ pub fn discover() -> ResultType<()> {
|
||||
};
|
||||
msg_out.set_peer_discovery(peer);
|
||||
let maddr = SocketAddr::from(([255, 255, 255, 255], get_broadcast_port()));
|
||||
socket.send_to(&msg_out.write_to_bytes()?, maddr)?;
|
||||
for socket in &sockets {
|
||||
socket.send_to(&msg_out.write_to_bytes()?, maddr)?;
|
||||
}
|
||||
log::info!("discover ping sent");
|
||||
Ok(sockets)
|
||||
}
|
||||
|
||||
fn wait_response(
|
||||
socket: UdpSocket,
|
||||
timeout: Option<std::time::Duration>,
|
||||
) -> ResultType<Vec<DiscoveryPeer>> {
|
||||
let mut last_recv_time = Instant::now();
|
||||
let mut last_write_time = Instant::now();
|
||||
let mut last_write_n = 0;
|
||||
// to-do: load saved peers, and update incrementally (then we can see offline)
|
||||
let mut peers = Vec::new();
|
||||
let mac = get_mac();
|
||||
socket.set_read_timeout(Some(std::time::Duration::from_millis(10)))?;
|
||||
|
||||
socket.set_read_timeout(timeout)?;
|
||||
loop {
|
||||
let mut buf = [0; 2048];
|
||||
if let Ok((len, _)) = socket.recv_from(&mut buf) {
|
||||
if let Ok((len, addr)) = socket.recv_from(&mut buf) {
|
||||
if let Ok(msg_in) = Message::parse_from_bytes(&buf[0..len]) {
|
||||
match msg_in.union {
|
||||
Some(rendezvous_message::Union::PeerDiscovery(p)) => {
|
||||
last_recv_time = Instant::now();
|
||||
if p.cmd == "pong" {
|
||||
if p.mac != mac {
|
||||
peers.push((p.id, p.username, p.hostname, p.platform));
|
||||
let mac = if let Some(self_addr) = get_ipaddr_by_peer(&addr) {
|
||||
get_mac(&self_addr)
|
||||
} else {
|
||||
"".to_owned()
|
||||
};
|
||||
|
||||
let is_self = if !mac.is_empty() {
|
||||
p.mac == mac
|
||||
} else {
|
||||
p.id == get_id()
|
||||
};
|
||||
if !is_self {
|
||||
peers.push(DiscoveryPeer {
|
||||
id: p.id.clone(),
|
||||
mac: p.mac.clone(),
|
||||
ip: addr.to_string(),
|
||||
username: p.username.clone(),
|
||||
hostname: p.hostname.clone(),
|
||||
platform: p.platform.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -627,15 +730,43 @@ pub fn discover() -> ResultType<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if last_write_time.elapsed().as_millis() > 300 && last_write_n != peers.len() {
|
||||
config::LanPeers::store(serde_json::to_string(&peers)?);
|
||||
last_write_time = Instant::now();
|
||||
last_write_n = peers.len();
|
||||
}
|
||||
if last_recv_time.elapsed().as_millis() > 3_000 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(peers)
|
||||
}
|
||||
|
||||
pub fn discover() -> ResultType<()> {
|
||||
let sockets = send_query()?;
|
||||
let mut join_handles = Vec::new();
|
||||
for socket in sockets {
|
||||
let handle = std::thread::spawn(move || {
|
||||
wait_response(socket, Some(std::time::Duration::from_millis(10)))
|
||||
});
|
||||
join_handles.push(handle);
|
||||
}
|
||||
|
||||
// to-do: load saved peers, and update incrementally (then we can see offline)
|
||||
let mut peers: Vec<DiscoveryPeer> = match serde_json::from_str(&config::LanPeers::load().peers)
|
||||
{
|
||||
Ok(p) => p,
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
for handle in join_handles {
|
||||
match handle.join() {
|
||||
Ok(Ok(mut tmp)) => {
|
||||
peers.append(&mut tmp);
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
log::error!("Failed lan discove {e}");
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed join lan discove thread {e:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
log::info!("discover ping done");
|
||||
config::LanPeers::store(serde_json::to_string(&peers)?);
|
||||
Ok(())
|
||||
|
@ -526,7 +526,7 @@ class MultipleSessions: Reactor.Component {
|
||||
<div style="width:*" .sessions-tab #sessions-type>
|
||||
<span class={!type ? 'active' : 'inactive'}>{translate('Recent Sessions')}</span>
|
||||
<span #fav class={type == "fav" ? 'active' : 'inactive'}>{translate('Favorites')}</span>
|
||||
{handler.is_installed() && <span #lan class={type == "lan" ? 'active' : 'inactive'}>{translate('Discovered')}</span>}
|
||||
{<span #lan class={type == "lan" ? 'active' : 'inactive'}>{translate('Discovered')}</span>}
|
||||
<span #ab class={type == "ab" ? 'active' : 'inactive'}>{translate('Address Book')}</span>
|
||||
</div>
|
||||
{!this.hidden && <SearchBar type={type} />}
|
||||
@ -534,7 +534,7 @@ class MultipleSessions: Reactor.Component {
|
||||
</div>
|
||||
{!this.hidden &&
|
||||
((type == "fav" && <Favorites />) ||
|
||||
(type == "lan" && handler.is_installed() && <LanPeers />) ||
|
||||
(type == "lan" && <LanPeers />) ||
|
||||
(type == "ab" && <AddressBook />) ||
|
||||
<SessionList sessions={handler.get_recent_sessions()} />)}
|
||||
</div>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user