From 87f50a6318a7c21ff2bf1875ce9f6a4d7b020913 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 18 Dec 2021 23:38:50 +0800 Subject: [PATCH 1/5] lan discovery in socket_cs Signed-off-by: fufesou --- Cargo.lock | 9 ++ Cargo.toml | 2 +- libs/hbb_common/build.rs | 2 +- libs/hbb_common/protos/base_proto.proto | 21 ++++ libs/hbb_common/protos/discovery.proto | 10 ++ libs/hbb_common/protos/message.proto | 23 +--- libs/hbb_common/src/lib.rs | 4 + libs/socket_cs/Cargo.toml | 14 +++ libs/socket_cs/examples/discovery.rs | 88 +++++++++++++ libs/socket_cs/src/discovery.rs | 120 ++++++++++++++++++ libs/socket_cs/src/lib.rs | 12 ++ libs/socket_cs/src/udp.rs | 160 ++++++++++++++++++++++++ src/client.rs | 1 + src/server.rs | 1 + src/ui/remote.rs | 1 + 15 files changed, 446 insertions(+), 22 deletions(-) create mode 100644 libs/hbb_common/protos/base_proto.proto create mode 100644 libs/hbb_common/protos/discovery.proto create mode 100644 libs/socket_cs/Cargo.toml create mode 100644 libs/socket_cs/examples/discovery.rs create mode 100644 libs/socket_cs/src/discovery.rs create mode 100644 libs/socket_cs/src/lib.rs create mode 100644 libs/socket_cs/src/udp.rs diff --git a/Cargo.lock b/Cargo.lock index 359e344bb..8707edb59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3187,6 +3187,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "socket_cs" +version = "0.1.0" +dependencies = [ + "async-trait", + "clap", + "hbb_common", +] + [[package]] name = "sodiumoxide" version = "0.2.7" diff --git a/Cargo.toml b/Cargo.toml index b4b8ad48c..bce47613f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ psutil = "3.2" android_logger = "0.9" [workspace] -members = ["libs/scrap", "libs/hbb_common", "libs/enigo"] +members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/socket_cs"] [package.metadata.winres] LegalCopyright = "Copyright © 2020" diff --git a/libs/hbb_common/build.rs b/libs/hbb_common/build.rs index 99dacb7ec..4f7778790 100644 --- a/libs/hbb_common/build.rs +++ b/libs/hbb_common/build.rs @@ -2,7 +2,7 @@ fn main() { std::fs::create_dir_all("src/protos").unwrap(); protobuf_codegen_pure::Codegen::new() .out_dir("src/protos") - .inputs(&["protos/rendezvous.proto", "protos/message.proto"]) + .inputs(&["protos/rendezvous.proto", "protos/base_proto.proto", "protos/message.proto", "protos/discovery.proto"]) .include("protos") .run() .expect("Codegen failed."); diff --git a/libs/hbb_common/protos/base_proto.proto b/libs/hbb_common/protos/base_proto.proto new file mode 100644 index 000000000..1d179db18 --- /dev/null +++ b/libs/hbb_common/protos/base_proto.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; +package base; + +message DisplayInfo { + sint32 x = 1; + sint32 y = 2; + int32 width = 3; + int32 height = 4; + string name = 5; + bool online = 6; +} + +message PeerInfo { + string username = 1; + string hostname = 2; + string platform = 3; + repeated DisplayInfo displays = 4; + int32 current_display = 5; + bool sas_enabled = 6; + string version = 7; +} \ No newline at end of file diff --git a/libs/hbb_common/protos/discovery.proto b/libs/hbb_common/protos/discovery.proto new file mode 100644 index 000000000..df13d967c --- /dev/null +++ b/libs/hbb_common/protos/discovery.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package discovery; + +import "base_proto.proto"; + +message Discovery { + base.PeerInfo peer = 1; + /// response port for current listening port(udp for now) + int32 port = 2; +} diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index a8e8d34b5..331078865 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -1,6 +1,8 @@ syntax = "proto3"; package hbb; +import "base_proto.proto"; + message VP9 { bytes data = 1; bool key = 2; @@ -25,15 +27,6 @@ message VideoFrame { } } -message DisplayInfo { - sint32 x = 1; - sint32 y = 2; - int32 width = 3; - int32 height = 4; - string name = 5; - bool online = 6; -} - message PortForward { string host = 1; int32 port = 2; @@ -58,20 +51,10 @@ message LoginRequest { message ChatMessage { string text = 1; } -message PeerInfo { - string username = 1; - string hostname = 2; - string platform = 3; - repeated DisplayInfo displays = 4; - int32 current_display = 5; - bool sas_enabled = 6; - string version = 7; -} - message LoginResponse { oneof union { string error = 1; - PeerInfo peer_info = 2; + base.PeerInfo peer_info = 2; } } diff --git a/libs/hbb_common/src/lib.rs b/libs/hbb_common/src/lib.rs index 91cc076d3..0e682219b 100644 --- a/libs/hbb_common/src/lib.rs +++ b/libs/hbb_common/src/lib.rs @@ -1,4 +1,8 @@ pub mod compress; +#[path = "./protos/base_proto.rs"] +pub mod base_proto; +#[path = "./protos/discovery.rs"] +pub mod discovery_proto; #[path = "./protos/message.rs"] pub mod message_proto; #[path = "./protos/rendezvous.rs"] diff --git a/libs/socket_cs/Cargo.toml b/libs/socket_cs/Cargo.toml new file mode 100644 index 000000000..cecb82257 --- /dev/null +++ b/libs/socket_cs/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "socket_cs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +hbb_common = { path = "../hbb_common" } +async-trait = "0.1" + + +[dev-dependencies] +clap = "2.33" diff --git a/libs/socket_cs/examples/discovery.rs b/libs/socket_cs/examples/discovery.rs new file mode 100644 index 000000000..c321cddfe --- /dev/null +++ b/libs/socket_cs/examples/discovery.rs @@ -0,0 +1,88 @@ +use hbb_common::{ + base_proto::PeerInfo, + discovery_proto::Discovery as DiscoveryProto, + env_logger::*, + log, protobuf, + tokio::{self, sync::Notify}, +}; +use socket_cs::{discovery::*, udp::*}; +use std::env; +use std::sync::Arc; + +async fn lan_discover(port: u16, port_back: u16) { + let peer = PeerInfo { + username: "client username".to_owned(), + hostname: "client hostname".to_owned(), + ..Default::default() + }; + let client = DiscoveryClient::create(DiscoveryProto { + peer: protobuf::MessageField::from_option(Some(peer)), + port: port_back as i32, + ..Default::default() + }) + .await + .unwrap(); + + client.lan_discover(port).await.unwrap(); +} + +async fn listen_discovery_back(port: u16) { + fn proc_peer(peer: PeerInfo) { + log::info!( + "peer recived, username: {}, hostname: {}", + peer.username, + peer.hostname + ); + } + + let exit_notify = Notify::new(); + let handlers = UdpHandlers::new().handle( + CMD_DISCOVERY_BACK.as_bytes().to_vec(), + Box::new(HandlerDiscoveryBack::new(proc_peer)), + ); + + let server = Server::new(port, Arc::new(exit_notify)); + server.start(handlers).await.unwrap(); + + loop { + std::thread::sleep(std::time::Duration::from_millis(1000)); + } +} + +async fn listen_discovery(port: u16) { + let peer = PeerInfo { + username: "server username".to_owned(), + hostname: "server hostname".to_owned(), + ..Default::default() + }; + + let exit_notify = Notify::new(); + let handlers = UdpHandlers::new().handle( + CMD_DISCOVERY.as_bytes().to_vec(), + Box::new(HandlerDiscovery::new(peer)), + ); + + let server = Server::new(port, Arc::new(exit_notify)); + server.start(handlers).await.unwrap(); + loop { + std::thread::sleep(std::time::Duration::from_millis(1000)); + } +} + +#[tokio::main] +async fn main() { + init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "trace")); + + let args: Vec = env::args().collect(); + + let port_back = 9801u16; + let server_port: u16 = 9802u16; + + if args.len() == 1 { + lan_discover(server_port, port_back).await; + } else if args.len() == 2 { + listen_discovery_back(port_back).await; + } else { + listen_discovery(server_port).await; + } +} diff --git a/libs/socket_cs/src/discovery.rs b/libs/socket_cs/src/discovery.rs new file mode 100644 index 000000000..3efcca6e2 --- /dev/null +++ b/libs/socket_cs/src/discovery.rs @@ -0,0 +1,120 @@ +use super::udp::UdpRequest; +use async_trait::async_trait; +use hbb_common::{ + base_proto::PeerInfo, discovery_proto::Discovery as DiscoveryProto, log, + protobuf::Message, tokio::net::UdpSocket, ResultType, +}; +use std::net::SocketAddr; + +pub const CMD_DISCOVERY: &str = "discovery"; +pub const CMD_DISCOVERY_BACK: &str = "discovery_back"; + +// TODO: make sure if UdpFramed is needed, or UdpSocket just works fine. +pub struct DiscoveryClient { + socket: UdpSocket, + send_data: Vec, +} + +fn make_send_data(cmd: &str, msg: &impl Message) -> ResultType> { + let info_bytes = msg.write_to_bytes()?; + let mut send_data = cmd.as_bytes().to_vec(); + send_data.push(crate::CMD_TOKEN); + send_data.extend(info_bytes); + Ok(send_data) +} + +impl DiscoveryClient { + pub async fn create(info: DiscoveryProto) -> ResultType { + let addr = "0.0.0.0:0"; + let socket = UdpSocket::bind(addr).await?; + log::trace!("succeeded to bind {} for discovery client", addr); + + socket.set_broadcast(true)?; + log::info!("Broadcast mode set to ON"); + + let send_data = make_send_data(CMD_DISCOVERY, &info)?; + Ok(Self { + socket, + send_data, + }) + } + + pub async fn lan_discover(&self, peer_port: u16) -> ResultType<()> { + let addr = SocketAddr::from(([255, 255, 255, 255], peer_port)); + self.socket.send_to(&self.send_data, addr).await?; + Ok(()) + } +} + +pub struct HandlerDiscovery { + send_data: Vec, +} + +impl HandlerDiscovery { + pub fn new(self_info: PeerInfo) -> Self { + let send_data = make_send_data(CMD_DISCOVERY_BACK, &self_info).unwrap(); + Self { send_data } + } +} + +#[async_trait] +impl crate::Handler for HandlerDiscovery { + async fn call(&self, request: UdpRequest) -> ResultType<()> { + log::trace!("received discover query from {}", request.addr); + + let discovery = DiscoveryProto::parse_from_bytes(&request.data)?; + let peer = discovery.peer.as_ref().take().unwrap(); + log::debug!( + "received discovery query from {} {}", + peer.username, + peer.hostname + ); + + let addr = "0.0.0.0:0"; + let socket = match UdpSocket::bind(addr).await { + Ok(s) => s, + Err(e) => { + log::error!("cannot bind socket? {}", e); + return Ok(()); + } + }; + + let mut peer_addr = request.addr; + peer_addr.set_port(discovery.port as u16); + + // let peer_addr = SocketAddr::from(([255, 255, 255, 255], discovery.port as u16)); + // socket.set_broadcast(true).unwrap(); + log::debug!("send self peer info to {}", peer_addr); + + let send_len = self.send_data.len(); + let mut cur_len = 0usize; + while cur_len < send_len { + let len = socket.send_to(&self.send_data[cur_len..], peer_addr).await?; + cur_len += len; + } + log::trace!("send self peer info to {} done", peer_addr); + + Ok(()) + } +} + +pub struct HandlerDiscoveryBack { + proc: fn(peer_info: PeerInfo), +} + +impl HandlerDiscoveryBack { + pub fn new(proc: fn(peer_info: PeerInfo)) -> Self { + Self { proc } + } +} + +#[async_trait] +impl crate::Handler for HandlerDiscoveryBack { + async fn call(&self, request: UdpRequest) -> ResultType<()> { + log::trace!("recved discover back from {}", request.addr); + + let peer = PeerInfo::parse_from_bytes(&request.data)?; + (self.proc)(peer); + Ok(()) + } +} diff --git a/libs/socket_cs/src/lib.rs b/libs/socket_cs/src/lib.rs new file mode 100644 index 000000000..a954b9243 --- /dev/null +++ b/libs/socket_cs/src/lib.rs @@ -0,0 +1,12 @@ +use async_trait::async_trait; +pub use hbb_common::ResultType; +pub mod discovery; +pub mod udp; + +const CMD_TOKEN: u8 = '\n' as u8; + +/// Use tower::Service may be better ? +#[async_trait] +pub trait Handler: Send + Sync { + async fn call(&self, request: Request) -> ResultType<()>; +} diff --git a/libs/socket_cs/src/udp.rs b/libs/socket_cs/src/udp.rs new file mode 100644 index 000000000..9c23a8e9b --- /dev/null +++ b/libs/socket_cs/src/udp.rs @@ -0,0 +1,160 @@ +use async_trait::async_trait; +use hbb_common::{ + log, + tokio::{self, sync::Notify}, + udp::FramedSocket, + ResultType, +}; +use std::collections::HashMap; +use std::future::Future; +use std::net::SocketAddr; +use std::sync::Arc; + +/// Simple udp server +pub struct Server { + port: u16, + exit_notify: Arc, +} + +pub struct UdpRequest { + pub data: Vec, + pub addr: SocketAddr, +} + +type UdpHandler = Box>; + +pub struct UdpFnHandler(F); + +/// Handlers of udp server. +/// After udp server received data. Command should be parsed. +/// Handler will then be used to process data. +pub struct UdpHandlers { + handlers: HashMap, UdpHandler>, +} + +impl Server { + pub fn new(port: u16, exit_notify: Arc) -> Self { + Self { port, exit_notify } + } + + /// Start server with the handlers. + pub async fn start(&self, handlers: UdpHandlers) -> ResultType<()> { + let exit_notify = self.exit_notify.clone(); + + let addr = SocketAddr::from(([0, 0, 0, 0], self.port)); + let mut server = FramedSocket::new(addr).await?; + log::trace!("succeeded to bind {} for discovery server", addr); + + tokio::spawn(async move { + let handlers = Arc::new(handlers.handlers); + loop { + tokio::select! { + _ = exit_notify.notified() => { + log::debug!("exit server graceful"); + break; + } + n = server.next() => { + log::info!("received message"); + let handlers = handlers.clone(); + match n { + Some(Ok((data, addr))) => { + match data.iter().position(|x| x == &crate::CMD_TOKEN) { + Some(p) => { + tokio::spawn(async move { + let cmd = data[0..p].to_vec(); + match handlers.get(&cmd) { + Some(h) => { + let request = UdpRequest {data: data[p+1..].to_vec(), addr}; + if let Err(e) = h.call(request).await { + log::error!("handle {:?} failed, {}", cmd, e); + } + } + None => { + log::warn!("no handler for {:?}", &cmd); + } + } + }); + } + None => { + log::error!("failed to parse command token"); + } + } + + } + Some(Err(e)) => { + log::error!("recv error: {}", e) + } + None => { + log::error!("should never reach here"); + } + } + } + } + } + }); + Ok(()) + } +} + +impl UdpHandlers { + pub fn new() -> Self { + Self { + handlers: HashMap::new(), + } + } + /// Insert pair. + /// + /// # Example + /// + /// ```rust + /// extern crate socket_cs; + /// use socket_cs::{ResultType, udp::{UdpHandlers, UdpRequest}}; + /// + /// struct SimpleHandler; + /// + /// #[async_trait] + /// impl crate::Handler for SimpleHandler { + /// async fn call(&self, _: UdpRequest) -> ResultType<()> { + /// Ok(()) + /// } + /// } + /// async fn simple_ignore(_: UdpRequest) -> ResultType<()> { + /// Ok(()) + /// } + /// let handlers = UdpHandlers::new(); + /// + /// handlers + /// .handle(b"cmd".to_vec(), Box::new(SimpleHandler)) + /// .handle(b"cmd2".to_vec(), simple_ignore.into()); + /// + /// ``` + /// + /// **Notice** Same cmd where override the previous one. + /// + pub fn handle(mut self, cmd: Vec, h: UdpHandler) -> Self { + self.handlers.insert(cmd, h); + self + } +} + +/// TODO: more generice Request. +#[async_trait] +impl crate::Handler for UdpFnHandler +where + Fut: Future> + Send, + F: Fn(UdpRequest) -> Fut + Send + Sync, +{ + async fn call(&self, request: UdpRequest) -> ResultType<()> { + self.0(request).await + } +} + +impl From for UdpHandler +where + Fut: Future> + Send, + F: Fn(UdpRequest) -> Fut + Send + Sync + 'static, +{ + fn from(f: F) -> Self { + Box::new(UdpFnHandler(f)) + } +} diff --git a/src/client.rs b/src/client.rs index b4116a945..e29c106e7 100644 --- a/src/client.rs +++ b/src/client.rs @@ -10,6 +10,7 @@ use hbb_common::{ bail, config::{Config, PeerConfig, PeerInfoSerde, CONNECT_TIMEOUT, RELAY_PORT, RENDEZVOUS_TIMEOUT}, log, + base_proto::*, message_proto::*, protobuf::Message as _, rendezvous_proto::*, diff --git a/src/server.rs b/src/server.rs index 541d88f29..02a27b885 100644 --- a/src/server.rs +++ b/src/server.rs @@ -7,6 +7,7 @@ use hbb_common::{ config::{Config, CONNECT_TIMEOUT, RELAY_PORT}, log, message_proto::*, + base_proto::*, protobuf::{Message as _, ProtobufEnum}, rendezvous_proto::*, sleep, diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 8c82ce4d5..55f31439e 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -7,6 +7,7 @@ use hbb_common::{ allow_err, config::{self, Config, PeerConfig}, fs, log, + base_proto::*, message_proto::*, protobuf::Message as _, rendezvous_proto::ConnType, From bcbe9ccbe519fba43a22c3eefead9782b722e191 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 19 Dec 2021 00:07:44 +0800 Subject: [PATCH 2/5] trivial changes Signed-off-by: fufesou --- libs/socket_cs/src/discovery.rs | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/libs/socket_cs/src/discovery.rs b/libs/socket_cs/src/discovery.rs index 3efcca6e2..d3adf4806 100644 --- a/libs/socket_cs/src/discovery.rs +++ b/libs/socket_cs/src/discovery.rs @@ -1,8 +1,8 @@ use super::udp::UdpRequest; use async_trait::async_trait; use hbb_common::{ - base_proto::PeerInfo, discovery_proto::Discovery as DiscoveryProto, log, - protobuf::Message, tokio::net::UdpSocket, ResultType, + base_proto::PeerInfo, discovery_proto::Discovery as DiscoveryProto, log, protobuf::Message, + tokio::net::UdpSocket, ResultType, }; use std::net::SocketAddr; @@ -33,10 +33,7 @@ impl DiscoveryClient { log::info!("Broadcast mode set to ON"); let send_data = make_send_data(CMD_DISCOVERY, &info)?; - Ok(Self { - socket, - send_data, - }) + Ok(Self { socket, send_data }) } pub async fn lan_discover(&self, peer_port: u16) -> ResultType<()> { @@ -71,25 +68,18 @@ impl crate::Handler for HandlerDiscovery { ); let addr = "0.0.0.0:0"; - let socket = match UdpSocket::bind(addr).await { - Ok(s) => s, - Err(e) => { - log::error!("cannot bind socket? {}", e); - return Ok(()); - } - }; + let socket = UdpSocket::bind(addr).await?; let mut peer_addr = request.addr; peer_addr.set_port(discovery.port as u16); - - // let peer_addr = SocketAddr::from(([255, 255, 255, 255], discovery.port as u16)); - // socket.set_broadcast(true).unwrap(); log::debug!("send self peer info to {}", peer_addr); let send_len = self.send_data.len(); let mut cur_len = 0usize; while cur_len < send_len { - let len = socket.send_to(&self.send_data[cur_len..], peer_addr).await?; + let len = socket + .send_to(&self.send_data[cur_len..], peer_addr) + .await?; cur_len += len; } log::trace!("send self peer info to {} done", peer_addr); From 5682b088dec07f7cd368904e1a5cd45f9d5915a7 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 19 Dec 2021 19:58:08 +0800 Subject: [PATCH 3/5] lan discovery will be done soon Signed-off-by: fufesou --- Cargo.lock | 1 + Cargo.toml | 1 + libs/hbb_common/protos/discovery.proto | 5 ++ libs/hbb_common/src/config.rs | 2 + libs/socket_cs/examples/discovery.rs | 33 ++++---- libs/socket_cs/src/discovery.rs | 35 ++++++--- libs/socket_cs/src/udp.rs | 42 ++++++++-- src/ipc.rs | 1 + src/server.rs | 9 +++ src/server/udp.rs | 105 +++++++++++++++++++++++++ src/ui.rs | 51 ++++++++++++ 11 files changed, 254 insertions(+), 31 deletions(-) create mode 100644 src/server/udp.rs diff --git a/Cargo.lock b/Cargo.lock index 8707edb59..a80486e50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2909,6 +2909,7 @@ dependencies = [ "serde_derive", "serde_json 1.0.66", "sha2", + "socket_cs", "uuid", "whoami", "winapi 0.3.9", diff --git a/Cargo.toml b/Cargo.toml index bce47613f..231e9952e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ default = ["use_dasp"] whoami = "1.1" scrap = { path = "libs/scrap" } hbb_common = { path = "libs/hbb_common" } +socket_cs = { path = "libs/socket_cs" } enigo = { path = "libs/enigo" } serde_derive = "1.0" serde = "1.0" diff --git a/libs/hbb_common/protos/discovery.proto b/libs/hbb_common/protos/discovery.proto index df13d967c..09474f53a 100644 --- a/libs/hbb_common/protos/discovery.proto +++ b/libs/hbb_common/protos/discovery.proto @@ -8,3 +8,8 @@ message Discovery { /// response port for current listening port(udp for now) int32 port = 2; } + +message DiscoveryBack { + string id = 1; + base.PeerInfo peer = 2; +} diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index bf4dfb7da..a9d3772b6 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -55,6 +55,8 @@ pub const RENDEZVOUS_SERVERS: &'static [&'static str] = &[ pub const RENDEZVOUS_PORT: i32 = 21116; pub const RELAY_PORT: i32 = 21117; +pub const SERVER_UDP_PORT: u16 = 21001; // udp + #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct Config { #[serde(default)] diff --git a/libs/socket_cs/examples/discovery.rs b/libs/socket_cs/examples/discovery.rs index c321cddfe..74f38a6e2 100644 --- a/libs/socket_cs/examples/discovery.rs +++ b/libs/socket_cs/examples/discovery.rs @@ -1,13 +1,11 @@ use hbb_common::{ base_proto::PeerInfo, - discovery_proto::Discovery as DiscoveryProto, + discovery_proto::{Discovery as DiscoveryProto, DiscoveryBack as DiscoveryBackProto}, env_logger::*, - log, protobuf, - tokio::{self, sync::Notify}, + log, protobuf, tokio, }; use socket_cs::{discovery::*, udp::*}; use std::env; -use std::sync::Arc; async fn lan_discover(port: u16, port_back: u16) { let peer = PeerInfo { @@ -27,21 +25,21 @@ async fn lan_discover(port: u16, port_back: u16) { } async fn listen_discovery_back(port: u16) { - fn proc_peer(peer: PeerInfo) { + fn proc_peer(info: DiscoveryBackProto) { log::info!( - "peer recived, username: {}, hostname: {}", - peer.username, - peer.hostname + "peer recived, id: {}, username: {}, hostname: {}", + info.id, + info.peer.as_ref().unwrap().username, + info.peer.as_ref().unwrap().hostname ); } - let exit_notify = Notify::new(); let handlers = UdpHandlers::new().handle( CMD_DISCOVERY_BACK.as_bytes().to_vec(), Box::new(HandlerDiscoveryBack::new(proc_peer)), ); - let server = Server::new(port, Arc::new(exit_notify)); + let mut server = Server::create(port).unwrap(); server.start(handlers).await.unwrap(); loop { @@ -50,19 +48,22 @@ async fn listen_discovery_back(port: u16) { } async fn listen_discovery(port: u16) { - let peer = PeerInfo { - username: "server username".to_owned(), - hostname: "server hostname".to_owned(), + let info = DiscoveryBackProto { + id: "server id".to_owned(), + peer: protobuf::MessageField::from_option(Some(PeerInfo { + username: "server username".to_owned(), + hostname: "server hostname".to_owned(), + ..Default::default() + })), ..Default::default() }; - let exit_notify = Notify::new(); let handlers = UdpHandlers::new().handle( CMD_DISCOVERY.as_bytes().to_vec(), - Box::new(HandlerDiscovery::new(peer)), + Box::new(HandlerDiscovery::new(Some(|| true), info)), ); - let server = Server::new(port, Arc::new(exit_notify)); + let mut server = Server::create(port).unwrap(); server.start(handlers).await.unwrap(); loop { std::thread::sleep(std::time::Duration::from_millis(1000)); diff --git a/libs/socket_cs/src/discovery.rs b/libs/socket_cs/src/discovery.rs index d3adf4806..c808acabf 100644 --- a/libs/socket_cs/src/discovery.rs +++ b/libs/socket_cs/src/discovery.rs @@ -1,15 +1,17 @@ use super::udp::UdpRequest; use async_trait::async_trait; use hbb_common::{ - base_proto::PeerInfo, discovery_proto::Discovery as DiscoveryProto, log, protobuf::Message, - tokio::net::UdpSocket, ResultType, + discovery_proto::{Discovery as DiscoveryProto, DiscoveryBack as DiscoveryBackProto}, + log, + protobuf::Message, + tokio::net::UdpSocket, + ResultType, }; use std::net::SocketAddr; pub const CMD_DISCOVERY: &str = "discovery"; pub const CMD_DISCOVERY_BACK: &str = "discovery_back"; -// TODO: make sure if UdpFramed is needed, or UdpSocket just works fine. pub struct DiscoveryClient { socket: UdpSocket, send_data: Vec, @@ -44,13 +46,17 @@ impl DiscoveryClient { } pub struct HandlerDiscovery { + get_allow: Option bool>, send_data: Vec, } impl HandlerDiscovery { - pub fn new(self_info: PeerInfo) -> Self { + pub fn new(get_allow: Option bool>, self_info: DiscoveryBackProto) -> Self { let send_data = make_send_data(CMD_DISCOVERY_BACK, &self_info).unwrap(); - Self { send_data } + Self { + get_allow, + send_data, + } } } @@ -67,6 +73,17 @@ impl crate::Handler for HandlerDiscovery { peer.hostname ); + let allowed = self.get_allow.map_or(false, |f| f()); + if !allowed { + log::info!( + "received discovery query from {} {} {}, but discovery is not allowed", + request.addr, + peer.hostname, + peer.username + ); + return Ok(()); + } + let addr = "0.0.0.0:0"; let socket = UdpSocket::bind(addr).await?; @@ -89,11 +106,11 @@ impl crate::Handler for HandlerDiscovery { } pub struct HandlerDiscoveryBack { - proc: fn(peer_info: PeerInfo), + proc: fn(info: DiscoveryBackProto), } impl HandlerDiscoveryBack { - pub fn new(proc: fn(peer_info: PeerInfo)) -> Self { + pub fn new(proc: fn(info: DiscoveryBackProto)) -> Self { Self { proc } } } @@ -103,8 +120,8 @@ impl crate::Handler for HandlerDiscoveryBack { async fn call(&self, request: UdpRequest) -> ResultType<()> { log::trace!("recved discover back from {}", request.addr); - let peer = PeerInfo::parse_from_bytes(&request.data)?; - (self.proc)(peer); + let info = DiscoveryBackProto::parse_from_bytes(&request.data)?; + (self.proc)(info); Ok(()) } } diff --git a/libs/socket_cs/src/udp.rs b/libs/socket_cs/src/udp.rs index 9c23a8e9b..fad6bc452 100644 --- a/libs/socket_cs/src/udp.rs +++ b/libs/socket_cs/src/udp.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use hbb_common::{ log, - tokio::{self, sync::Notify}, + tokio::{self, runtime::Runtime, sync::Notify, task::JoinHandle}, udp::FramedSocket, ResultType, }; @@ -14,6 +14,8 @@ use std::sync::Arc; pub struct Server { port: u16, exit_notify: Arc, + rt: Arc, + join_handler: Option>, } pub struct UdpRequest { @@ -33,19 +35,27 @@ pub struct UdpHandlers { } impl Server { - pub fn new(port: u16, exit_notify: Arc) -> Self { - Self { port, exit_notify } + pub fn create(port: u16) -> ResultType { + let rt = Arc::new(Runtime::new()?); + let exit_notify = Arc::new(Notify::new()); + Ok(Self { + port, + exit_notify, + rt, + join_handler: None, + }) } /// Start server with the handlers. - pub async fn start(&self, handlers: UdpHandlers) -> ResultType<()> { + pub async fn start(&mut self, handlers: UdpHandlers) -> ResultType<()> { let exit_notify = self.exit_notify.clone(); let addr = SocketAddr::from(([0, 0, 0, 0], self.port)); let mut server = FramedSocket::new(addr).await?; log::trace!("succeeded to bind {} for discovery server", addr); - tokio::spawn(async move { + let rt = self.rt.clone(); + let join_handler = rt.clone().spawn(async move { let handlers = Arc::new(handlers.handlers); loop { tokio::select! { @@ -56,11 +66,12 @@ impl Server { n = server.next() => { log::info!("received message"); let handlers = handlers.clone(); + let rt = rt.clone(); match n { Some(Ok((data, addr))) => { match data.iter().position(|x| x == &crate::CMD_TOKEN) { Some(p) => { - tokio::spawn(async move { + rt.spawn(async move { let cmd = data[0..p].to_vec(); match handlers.get(&cmd) { Some(h) => { @@ -92,8 +103,27 @@ impl Server { } } }); + + self.join_handler = Some(join_handler); Ok(()) } + + pub async fn shutdonw(&mut self) { + self.exit_notify.notify_one(); + if let Some(h) = self.join_handler.take() { + if let Err(e) = h.await { + log::error!("failed to join udp server, {}", e); + } + } + } +} + +impl Drop for Server { + fn drop(&mut self) { + self.rt.clone().block_on(async { + self.shutdonw().await; + }) + } } impl UdpHandlers { diff --git a/src/ipc.rs b/src/ipc.rs index 0474e457f..9727faa92 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -90,6 +90,7 @@ pub enum Data { ConfirmedKey(Option<(Vec, Vec)>), RawMessage(Vec), FS(FS), + SessionsUpdated, Test, } diff --git a/src/server.rs b/src/server.rs index 02a27b885..c2c43a930 100644 --- a/src/server.rs +++ b/src/server.rs @@ -28,6 +28,7 @@ mod connection; pub mod input_service; mod service; mod video_service; +mod udp; use hbb_common::tcp::new_listener; @@ -261,6 +262,7 @@ pub fn check_zombie() { #[tokio::main] pub async fn start_server(is_server: bool, _tray: bool) { + // TODO: Add a graceful shutdown handler, and attach all servers to that handler. #[cfg(target_os = "linux")] { log::info!("DISPLAY={:?}", std::env::var("DISPLAY")); @@ -273,6 +275,13 @@ pub async fn start_server(is_server: bool, _tray: bool) { std::process::exit(-1); } }); + let _server_guard = match udp::start_udp_server().await { + Ok(s) => Some(s), + Err(e) => { + log::warn!("Failed to start udp server {}", e); + None + } + }; input_service::fix_key_down_timeout_loop(); crate::RendezvousMediator::start_all().await; } else { diff --git a/src/server/udp.rs b/src/server/udp.rs new file mode 100644 index 000000000..c9f3621ae --- /dev/null +++ b/src/server/udp.rs @@ -0,0 +1,105 @@ +/// udp server +/// +/// eg. discovery +/// +use hbb_common::{base_proto::PeerInfo, config::SERVER_UDP_PORT, ResultType}; +use socket_cs::udp::{Server, UdpHandlers}; + +/// Simple copy from ../connections.rs#send_logon_response +/// Should be merged into one function. +fn get_peer_info() -> PeerInfo { + let username = crate::platform::get_active_username(); + #[allow(unused_mut)] + let mut sas_enabled = false; + #[cfg(windows)] + if crate::platform::is_root() { + sas_enabled = true; + } + PeerInfo { + hostname: whoami::hostname(), + username, + platform: whoami::platform().to_string(), + version: crate::VERSION.to_owned(), + sas_enabled, + ..Default::default() + } +} + +mod discovery { + use super::get_peer_info; + use crate::ipc; + use hbb_common::{ + base_proto::PeerInfo, + config::{PeerConfig, PeerInfoSerde}, + discovery_proto::{Discovery as DiscoveryProto, DiscoveryBack as DiscoveryBackProto}, + log, protobuf, + tokio::runtime::Runtime, + ResultType, + }; + use socket_cs::{discovery::*, udp::UdpHandlers}; + + fn get_discovery_back_info() -> DiscoveryBackProto { + let peer = get_peer_info(); + DiscoveryBackProto { + id: ipc::get_id(), + peer: protobuf::MessageField::from_option(Some(peer)), + ..Default::default() + } + } + + fn process_discovery_back(info: DiscoveryBackProto) { + let mut config = PeerConfig::load(info.id.as_str()); + + let peer = info.peer.as_ref().unwrap(); + let serde = PeerInfoSerde { + username: peer.username.clone(), + hostname: peer.hostname.clone(), + platform: peer.platform.clone(), + }; + config.info = serde; + config.store(info.id.as_str()); + + let rt = match Runtime::new() { + Ok(r) => r, + Err(e) => { + log::error!("Failed to notify index window, {}", e); + return; + } + }; + + async fn notify_index_window() -> ResultType<()> { + let ms_timeout = 1000; + let mut c = ipc::connect(ms_timeout, "_index").await?; + c.send(&ipc::Data::SessionsUpdated).await?; + Ok(()) + } + rt.block_on(async move { + if let Err(e) = notify_index_window().await { + log::error!("Failed to notify index window, {}", e); + } + }); + } + + // pub(crate) fn lan_discover(); + + pub(super) fn handle_discovery(handlers: UdpHandlers) -> UdpHandlers { + let info = get_discovery_back_info(); + handlers + .handle( + CMD_DISCOVERY.as_bytes().to_vec(), + Box::new(HandlerDiscovery::new(Some(|| true), info)), + ) + .handle( + CMD_DISCOVERY_BACK.as_bytes().to_vec(), + Box::new(HandlerDiscoveryBack::new(process_discovery_back)), + ) + } +} + +pub(super) async fn start_udp_server() -> ResultType { + let handlers = discovery::handle_discovery(UdpHandlers::new()); + + let mut server = Server::create(SERVER_UDP_PORT)?; + server.start(handlers).await?; + Ok(server) +} diff --git a/src/ui.rs b/src/ui.rs index 8d68c833e..0f0f4717c 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -86,6 +86,8 @@ pub fn start(args: &mut [String]) { let childs: Childs = Default::default(); let cloned = childs.clone(); std::thread::spawn(move || check_zombie(cloned)); + let cloned = childs.clone(); + tokio::spawn(async move {start_ipc(cloned)}); crate::common::check_software_update(); frame.event_handler(UI::new(childs)); frame.sciter_handler(UIHostHandler {}); @@ -644,6 +646,55 @@ pub fn check_zombie(childs: Childs) { } } +// TODO: Duplicated code. +// Need more generic and better shutdown handler +#[tokio::main(flavor = "current_thread")] +async fn start_ipc(childs: Childs) { + match ipc::new_listener("_index").await { + Ok(mut incoming) => { + while let Some(result) = incoming.next().await { + match result { + Ok(stream) => { + let mut stream = ipc::Connection::new(stream); + let childs = childs.clone(); + tokio::spawn(async move { + loop { + tokio::select! { + res = stream.next() => { + match res { + Err(err) => { + log::info!("cm ipc connection closed: {}", err); + break; + } + Ok(Some(data)) => { + match data { + ipc::Data::SessionsUpdated => { + childs.lock().unwrap().0 = true; + } + _ => { + } + } + } + _ => {} + } + } + } + } + }); + } + Err(err) => { + log::error!("Couldn't get index client: {:?}", err); + } + } + } + } + Err(err) => { + log::error!("Failed to start index ipc server: {}", err); + } + } + std::process::exit(-1); +} + // notice: avoiding create ipc connection repeatedly, // because windows named pipe has serious memory leak issue. #[tokio::main(flavor = "current_thread")] From d00352f4e4af0a1f452a075bba0ca379343ca365 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 21 Dec 2021 00:10:14 +0800 Subject: [PATCH 4/5] lan discovery almost done Signed-off-by: fufesou --- libs/hbb_common/protos/discovery.proto | 5 ++- libs/socket_cs/examples/discovery.rs | 1 + libs/socket_cs/src/discovery.rs | 26 ++++++----- libs/socket_cs/src/udp.rs | 16 +++---- src/ipc.rs | 16 +++++++ src/server.rs | 2 +- src/server/udp.rs | 62 ++++++++++++++++---------- src/ui.rs | 7 ++- src/ui/index.tis | 5 +++ 9 files changed, 93 insertions(+), 47 deletions(-) diff --git a/libs/hbb_common/protos/discovery.proto b/libs/hbb_common/protos/discovery.proto index 09474f53a..e24fe32bf 100644 --- a/libs/hbb_common/protos/discovery.proto +++ b/libs/hbb_common/protos/discovery.proto @@ -4,9 +4,10 @@ package discovery; import "base_proto.proto"; message Discovery { - base.PeerInfo peer = 1; + string id = 1; + base.PeerInfo peer = 2; /// response port for current listening port(udp for now) - int32 port = 2; + int32 port = 3; } message DiscoveryBack { diff --git a/libs/socket_cs/examples/discovery.rs b/libs/socket_cs/examples/discovery.rs index 74f38a6e2..a23d80878 100644 --- a/libs/socket_cs/examples/discovery.rs +++ b/libs/socket_cs/examples/discovery.rs @@ -14,6 +14,7 @@ async fn lan_discover(port: u16, port_back: u16) { ..Default::default() }; let client = DiscoveryClient::create(DiscoveryProto { + id: "client id".to_owned(), peer: protobuf::MessageField::from_option(Some(peer)), port: port_back as i32, ..Default::default() diff --git a/libs/socket_cs/src/discovery.rs b/libs/socket_cs/src/discovery.rs index c808acabf..c18334971 100644 --- a/libs/socket_cs/src/discovery.rs +++ b/libs/socket_cs/src/discovery.rs @@ -32,7 +32,7 @@ impl DiscoveryClient { log::trace!("succeeded to bind {} for discovery client", addr); socket.set_broadcast(true)?; - log::info!("Broadcast mode set to ON"); + log::trace!("Broadcast mode set to ON"); let send_data = make_send_data(CMD_DISCOVERY, &info)?; Ok(Self { socket, send_data }) @@ -47,6 +47,7 @@ impl DiscoveryClient { pub struct HandlerDiscovery { get_allow: Option bool>, + id: String, send_data: Vec, } @@ -55,6 +56,7 @@ impl HandlerDiscovery { let send_data = make_send_data(CMD_DISCOVERY_BACK, &self_info).unwrap(); Self { get_allow, + id: self_info.id, send_data, } } @@ -63,11 +65,13 @@ impl HandlerDiscovery { #[async_trait] impl crate::Handler for HandlerDiscovery { async fn call(&self, request: UdpRequest) -> ResultType<()> { - log::trace!("received discover query from {}", request.addr); - let discovery = DiscoveryProto::parse_from_bytes(&request.data)?; + if discovery.id == self.id { + return Ok(()); + } + let peer = discovery.peer.as_ref().take().unwrap(); - log::debug!( + log::trace!( "received discovery query from {} {}", peer.username, peer.hostname @@ -75,12 +79,12 @@ impl crate::Handler for HandlerDiscovery { let allowed = self.get_allow.map_or(false, |f| f()); if !allowed { - log::info!( - "received discovery query from {} {} {}, but discovery is not allowed", - request.addr, - peer.hostname, - peer.username - ); + // log::info!( + // "received discovery query from {} {} {}, but discovery is not allowed", + // request.addr, + // peer.hostname, + // peer.username + // ); return Ok(()); } @@ -89,7 +93,7 @@ impl crate::Handler for HandlerDiscovery { let mut peer_addr = request.addr; peer_addr.set_port(discovery.port as u16); - log::debug!("send self peer info to {}", peer_addr); + log::trace!("send self peer info to {}", peer_addr); let send_len = self.send_data.len(); let mut cur_len = 0usize; diff --git a/libs/socket_cs/src/udp.rs b/libs/socket_cs/src/udp.rs index fad6bc452..73bdb77e4 100644 --- a/libs/socket_cs/src/udp.rs +++ b/libs/socket_cs/src/udp.rs @@ -64,7 +64,6 @@ impl Server { break; } n = server.next() => { - log::info!("received message"); let handlers = handlers.clone(); let rt = rt.clone(); match n { @@ -76,24 +75,24 @@ impl Server { match handlers.get(&cmd) { Some(h) => { let request = UdpRequest {data: data[p+1..].to_vec(), addr}; - if let Err(e) = h.call(request).await { - log::error!("handle {:?} failed, {}", cmd, e); + if let Err(_e) = h.call(request).await { + // log::error!("handle {:?} failed, {}", cmd, e); } } None => { - log::warn!("no handler for {:?}", &cmd); + // log::warn!("no handler for {:?}", &cmd); } } }); } None => { - log::error!("failed to parse command token"); + // log::error!("failed to parse command token"); } } } - Some(Err(e)) => { - log::error!("recv error: {}", e) + Some(Err(_e)) => { + // log::error!("recv error: {}", e) } None => { log::error!("should never reach here"); @@ -139,11 +138,12 @@ impl UdpHandlers { /// ```rust /// extern crate socket_cs; /// use socket_cs::{ResultType, udp::{UdpHandlers, UdpRequest}}; + /// use async_trait::async_trait; /// /// struct SimpleHandler; /// /// #[async_trait] - /// impl crate::Handler for SimpleHandler { + /// impl socket_cs::Handler for SimpleHandler { /// async fn call(&self, _: UdpRequest) -> ResultType<()> { /// Ok(()) /// } diff --git a/src/ipc.rs b/src/ipc.rs index 9727faa92..7a8b855e2 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -389,6 +389,22 @@ pub fn get_id() -> String { } } +pub async fn get_id_async() -> String { + if let Ok(Some(v)) = get_config_async("id", 1_000).await { + // update salt also, so that next time reinstallation not causing first-time auto-login failure + if let Ok(Some(v2)) = get_config_async("salt", 1_000).await { + Config::set_salt(&v2); + } + if v != Config::get_id() { + Config::set_key_confirmed(false); + Config::set_id(&v); + } + v + } else { + Config::get_id() + } +} + pub fn get_password() -> String { if let Ok(Some(v)) = get_config("password") { Config::set_password(&v); diff --git a/src/server.rs b/src/server.rs index c2c43a930..fe1d36da4 100644 --- a/src/server.rs +++ b/src/server.rs @@ -28,7 +28,7 @@ mod connection; pub mod input_service; mod service; mod video_service; -mod udp; +pub mod udp; use hbb_common::tcp::new_listener; diff --git a/src/server/udp.rs b/src/server/udp.rs index c9f3621ae..7eeea6f26 100644 --- a/src/server/udp.rs +++ b/src/server/udp.rs @@ -25,23 +25,20 @@ fn get_peer_info() -> PeerInfo { } } -mod discovery { +pub mod discovery { use super::get_peer_info; use crate::ipc; use hbb_common::{ - base_proto::PeerInfo, - config::{PeerConfig, PeerInfoSerde}, + config::{Config, PeerConfig, PeerInfoSerde, SERVER_UDP_PORT}, discovery_proto::{Discovery as DiscoveryProto, DiscoveryBack as DiscoveryBackProto}, - log, protobuf, - tokio::runtime::Runtime, - ResultType, + log, protobuf, tokio, ResultType, }; use socket_cs::{discovery::*, udp::UdpHandlers}; - fn get_discovery_back_info() -> DiscoveryBackProto { + async fn get_discovery_back_info() -> DiscoveryBackProto { let peer = get_peer_info(); DiscoveryBackProto { - id: ipc::get_id(), + id: ipc::get_id_async().await, peer: protobuf::MessageField::from_option(Some(peer)), ..Default::default() } @@ -59,35 +56,52 @@ mod discovery { config.info = serde; config.store(info.id.as_str()); - let rt = match Runtime::new() { - Ok(r) => r, - Err(e) => { - log::error!("Failed to notify index window, {}", e); - return; - } - }; - + #[tokio::main(flavor = "current_thread")] async fn notify_index_window() -> ResultType<()> { - let ms_timeout = 1000; + let ms_timeout = 300; let mut c = ipc::connect(ms_timeout, "_index").await?; c.send(&ipc::Data::SessionsUpdated).await?; Ok(()) } - rt.block_on(async move { - if let Err(e) = notify_index_window().await { + std::thread::spawn(move || { + if let Err(e) = notify_index_window() { log::error!("Failed to notify index window, {}", e); } }); } - // pub(crate) fn lan_discover(); + pub fn launch_lan_discover() { + std::thread::spawn(move || { + if let Err(e) = lan_discover() { + log::error!("Failed to lauch lan discover, {}", e); + } + }); + } - pub(super) fn handle_discovery(handlers: UdpHandlers) -> UdpHandlers { - let info = get_discovery_back_info(); + #[tokio::main(flavor = "current_thread")] + pub async fn lan_discover() -> ResultType<()> { + let peer = get_peer_info(); + let client = DiscoveryClient::create(DiscoveryProto { + id: ipc::get_id_async().await, + peer: protobuf::MessageField::from_option(Some(peer)), + port: SERVER_UDP_PORT as i32, + ..Default::default() + }) + .await?; + + client.lan_discover(SERVER_UDP_PORT).await + } + + pub(super) async fn handle_discovery(handlers: UdpHandlers) -> UdpHandlers { + let info = get_discovery_back_info().await; handlers .handle( CMD_DISCOVERY.as_bytes().to_vec(), - Box::new(HandlerDiscovery::new(Some(|| true), info)), + Box::new(HandlerDiscovery::new( + // Some(|| Config::get_option("enable-be-discovered") == "Y".to_owned()), + Some(|| true), + info, + )), ) .handle( CMD_DISCOVERY_BACK.as_bytes().to_vec(), @@ -97,7 +111,7 @@ mod discovery { } pub(super) async fn start_udp_server() -> ResultType { - let handlers = discovery::handle_discovery(UdpHandlers::new()); + let handlers = discovery::handle_discovery(UdpHandlers::new()).await; let mut server = Server::create(SERVER_UDP_PORT)?; server.start(handlers).await?; diff --git a/src/ui.rs b/src/ui.rs index 0f0f4717c..cba285303 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -87,7 +87,7 @@ pub fn start(args: &mut [String]) { let cloned = childs.clone(); std::thread::spawn(move || check_zombie(cloned)); let cloned = childs.clone(); - tokio::spawn(async move {start_ipc(cloned)}); + std::thread::spawn(move || start_ipc(cloned)); crate::common::check_software_update(); frame.event_handler(UI::new(childs)); frame.sciter_handler(UIHostHandler {}); @@ -567,6 +567,10 @@ impl UI { fn is_xfce(&self) -> bool { crate::platform::is_xfce() } + + fn lan_discover(&self) { + crate::server::udp::discovery::launch_lan_discover(); + } } impl sciter::EventHandler for UI { @@ -615,6 +619,7 @@ impl sciter::EventHandler for UI { fn get_software_ext(); fn open_url(String); fn create_shortcut(String); + fn lan_discover(); } } diff --git a/src/ui/index.tis b/src/ui/index.tis index 55fcf6f7c..903a1a030 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -51,12 +51,17 @@ class RecentSessions: Reactor.Component { sessions = sessions.map(this.getSession); return
RECENT SESSIONS
+
{sessions}
; } + event click $(button#discover) { + handler.lan_discover(); + } + function getSession(s) { var id = s[0]; var username = s[1]; From 35462eecfe327d2ad89a63b0f931b7099d090927 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 21 Dec 2021 00:49:39 +0800 Subject: [PATCH 5/5] comment out discovery button Signed-off-by: fufesou --- libs/socket_cs/src/udp.rs | 5 +---- src/server/udp.rs | 8 +++++++- src/ui/index.tis | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libs/socket_cs/src/udp.rs b/libs/socket_cs/src/udp.rs index 73bdb77e4..aef64fd65 100644 --- a/libs/socket_cs/src/udp.rs +++ b/libs/socket_cs/src/udp.rs @@ -5,10 +5,7 @@ use hbb_common::{ udp::FramedSocket, ResultType, }; -use std::collections::HashMap; -use std::future::Future; -use std::net::SocketAddr; -use std::sync::Arc; +use std::{collections::HashMap, future::Future, net::SocketAddr, sync::Arc}; /// Simple udp server pub struct Server { diff --git a/src/server/udp.rs b/src/server/udp.rs index 7eeea6f26..7ff828485 100644 --- a/src/server/udp.rs +++ b/src/server/udp.rs @@ -29,7 +29,7 @@ pub mod discovery { use super::get_peer_info; use crate::ipc; use hbb_common::{ - config::{Config, PeerConfig, PeerInfoSerde, SERVER_UDP_PORT}, + config::{PeerConfig, PeerInfoSerde, SERVER_UDP_PORT}, discovery_proto::{Discovery as DiscoveryProto, DiscoveryBack as DiscoveryBackProto}, log, protobuf, tokio, ResultType, }; @@ -44,6 +44,9 @@ pub mod discovery { } } + /// process sicovery bakc(response) + /// 1. update current peers. + /// 2. notify index window to udpate recent sessions. fn process_discovery_back(info: DiscoveryBackProto) { let mut config = PeerConfig::load(info.id.as_str()); @@ -70,6 +73,7 @@ pub mod discovery { }); } + /// launch lan discover when user click "discover" button. pub fn launch_lan_discover() { std::thread::spawn(move || { if let Err(e) = lan_discover() { @@ -95,6 +99,7 @@ pub mod discovery { pub(super) async fn handle_discovery(handlers: UdpHandlers) -> UdpHandlers { let info = get_discovery_back_info().await; handlers + // handle discover request .handle( CMD_DISCOVERY.as_bytes().to_vec(), Box::new(HandlerDiscovery::new( @@ -103,6 +108,7 @@ pub mod discovery { info, )), ) + // handle discover back(response) .handle( CMD_DISCOVERY_BACK.as_bytes().to_vec(), Box::new(HandlerDiscoveryBack::new(process_discovery_back)), diff --git a/src/ui/index.tis b/src/ui/index.tis index 903a1a030..16c6786be 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -51,7 +51,7 @@ class RecentSessions: Reactor.Component { sessions = sessions.map(this.getSession); return
RECENT SESSIONS
- + { false && }
{sessions}