From 2e03ca19f6afe9bb705e041af3b97e2ddb398ba7 Mon Sep 17 00:00:00 2001 From: chenbaiyu Date: Wed, 12 Jan 2022 21:40:02 +0800 Subject: [PATCH] temp commit --- Cargo.lock | 77 +++++++++++++++++ Cargo.toml | 1 + libs/hbb_common/Cargo.toml | 3 + libs/hbb_common/src/config.rs | 154 +++++++++++++++++++++++----------- src/ipc.rs | 51 ++++++----- src/lib.rs | 2 +- src/main.rs | 86 ++++++++++--------- src/platform/macos.rs | 7 ++ src/server.rs | 98 +++++++++++++++++++--- 9 files changed, 358 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ea2e7c9b..9c3f27000 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1115,6 +1115,31 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + +[[package]] +name = "fsevent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +dependencies = [ + "bitflags", + "fsevent-sys", +] + +[[package]] +name = "fsevent-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" +dependencies = [ + "libc", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -1623,6 +1648,7 @@ dependencies = [ "dirs-next", "env_logger 0.9.0", "filetime", + "fs_extra", "futures", "futures-util", "lazy_static", @@ -1698,6 +1724,26 @@ dependencies = [ "tiff", ] +[[package]] +name = "inotify" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -2060,6 +2106,18 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio 0.6.23", + "slab", +] + [[package]] name = "mio-named-pipes" version = "0.1.7" @@ -2224,6 +2282,24 @@ dependencies = [ "version_check", ] +[[package]] +name = "notify" +version = "4.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" +dependencies = [ + "bitflags", + "filetime", + "fsevent", + "fsevent-sys", + "inotify", + "libc", + "mio 0.6.23", + "mio-extras", + "walkdir", + "winapi 0.3.9", +] + [[package]] name = "ntapi" version = "0.3.6" @@ -3153,6 +3229,7 @@ dependencies = [ "mac_address", "machine-uid", "magnum-opus", + "notify", "objc", "parity-tokio-ipc", "psutil", diff --git a/Cargo.toml b/Cargo.toml index 6a9325e25..9a13bedaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,7 @@ cocoa = "0.24" dispatch = "0.2" core-foundation = "0.9" core-graphics = "0.22" +notify = "4.0.17" [target.'cfg(target_os = "linux")'.dependencies] libpulse-simple-binding = "2.24" diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml index d1868f5b5..485e91ba0 100644 --- a/libs/hbb_common/Cargo.toml +++ b/libs/hbb_common/Cargo.toml @@ -43,6 +43,9 @@ protobuf-codegen-pure = "3.0.0-alpha.2" [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["winuser"] } +[target.'cfg(target_os = "macos")'.dependencies] +fs_extra = "1.2.0" + [dev-dependencies] toml = "0.5" serde_json = "1.0" diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index d248f0c28..e9df2f15c 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -11,6 +11,7 @@ use std::{ sync::{Arc, Mutex, RwLock}, time::SystemTime, }; +use std::borrow::Borrow; pub const APP_NAME: &str = "RustDesk"; pub const RENDEZVOUS_TIMEOUT: u64 = 12_000; @@ -69,7 +70,8 @@ pub struct Config { #[serde(default)] salt: String, #[serde(default)] - key_pair: (Vec, Vec), // sk, pk + key_pair: (Vec, Vec), + // sk, pk #[serde(default)] key_confirmed: bool, #[serde(default)] @@ -90,7 +92,8 @@ pub struct Socks5Server { #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct Config2 { #[serde(default)] - remote_id: String, // latest used one + remote_id: String, + // latest used one #[serde(default)] size: Size, #[serde(default)] @@ -119,7 +122,8 @@ pub struct PeerConfig { #[serde(default)] pub size_pf: Size, #[serde(default)] - pub view_style: String, // original (default), scale + pub view_style: String, + // original (default), scale #[serde(default)] pub image_quality: String, #[serde(default)] @@ -159,28 +163,28 @@ pub struct PeerInfoSerde { fn patch(path: PathBuf) -> PathBuf { if let Some(_tmp) = path.to_str() { #[cfg(windows)] - return _tmp + return _tmp .replace( "system32\\config\\systemprofile", "ServiceProfiles\\LocalService", ) .into(); #[cfg(target_os = "macos")] - return _tmp.replace("Application Support", "Preferences").into(); + return _tmp.replace("Application Support", "Preferences").into(); #[cfg(target_os = "linux")] - { - if _tmp == "/root" { - if let Ok(output) = std::process::Command::new("whoami").output() { - let user = String::from_utf8_lossy(&output.stdout) - .to_string() - .trim() - .to_owned(); - if user != "root" { - return format!("/home/{}", user).into(); + { + if _tmp == "/root" { + if let Ok(output) = std::process::Command::new("whoami").output() { + let user = String::from_utf8_lossy(&output.stdout) + .to_string() + .trim() + .to_owned(); + if user != "root" { + return format!("/home/{}", user).into(); + } } } } - } } path } @@ -190,6 +194,11 @@ impl Config2 { Config::load_::("2") } + fn reload(&mut self) { + let new_config = Config2::load(); + *self = new_config; + } + fn store(&self) { Config::store_(self, "2"); } @@ -229,6 +238,11 @@ impl Config { Config::store_(self, ""); } + fn reload(&mut self) { + let new_config = Config::load(); + *self = new_config; + } + pub fn file() -> PathBuf { Self::file_("") } @@ -262,7 +276,7 @@ impl Config { pub fn get_home() -> PathBuf { #[cfg(any(target_os = "android", target_os = "ios"))] - return Self::path(""); + return Self::path(""); if let Some(path) = dirs_next::home_dir() { patch(path) } else if let Ok(path) = std::env::current_dir() { @@ -272,17 +286,17 @@ impl Config { } } - fn path>(p: P) -> PathBuf { + pub fn path>(p: P) -> PathBuf { #[cfg(any(target_os = "android", target_os = "ios"))] - { - let mut path: PathBuf = APP_DIR.read().unwrap().clone().into(); - path.push(p); - return path; - } + { + let mut path: PathBuf = APP_DIR.read().unwrap().clone().into(); + path.push(p); + return path; + } #[cfg(not(target_os = "macos"))] - let org = ""; + let org = ""; #[cfg(target_os = "macos")] - let org = ORG; + let org = ORG; // /var/root for root if let Some(project) = ProjectDirs::from("", org, APP_NAME) { let mut path = patch(project.config_dir().to_path_buf()); @@ -295,19 +309,19 @@ impl Config { #[allow(unreachable_code)] pub fn log_path() -> PathBuf { #[cfg(target_os = "macos")] - { - if let Some(path) = dirs_next::home_dir().as_mut() { - path.push(format!("Library/Logs/{}", APP_NAME)); - return path.clone(); + { + if let Some(path) = dirs_next::home_dir().as_mut() { + path.push(format!("Library/Logs/{}", APP_NAME)); + return path.clone(); + } } - } #[cfg(target_os = "linux")] - { - let mut path = Self::get_home(); - path.push(format!(".local/share/logs/{}", APP_NAME)); - std::fs::create_dir_all(&path).ok(); - return path; - } + { + let mut path = Self::get_home(); + path.push(format!(".local/share/logs/{}", APP_NAME)); + std::fs::create_dir_all(&path).ok(); + return path; + } if let Some(path) = Self::path("").parent() { let mut path: PathBuf = path.into(); path.push("log"); @@ -318,21 +332,21 @@ impl Config { pub fn ipc_path(postfix: &str) -> String { #[cfg(windows)] - { - // \\ServerName\pipe\PipeName - // where ServerName is either the name of a remote computer or a period, to specify the local computer. - // https://docs.microsoft.com/en-us/windows/win32/ipc/pipe-names - format!("\\\\.\\pipe\\{}\\query{}", APP_NAME, postfix) - } + { + // \\ServerName\pipe\PipeName + // where ServerName is either the name of a remote computer or a period, to specify the local computer. + // https://docs.microsoft.com/en-us/windows/win32/ipc/pipe-names + format!("\\\\.\\pipe\\{}\\query{}", APP_NAME, postfix) + } #[cfg(not(windows))] - { - use std::os::unix::fs::PermissionsExt; - let mut path: PathBuf = format!("/tmp/{}", APP_NAME).into(); - fs::create_dir(&path).ok(); - fs::set_permissions(&path, fs::Permissions::from_mode(0o0777)).ok(); - path.push(format!("ipc{}", postfix)); - path.to_str().unwrap_or("").to_owned() - } + { + use std::os::unix::fs::PermissionsExt; + let mut path: PathBuf = format!("/tmp/{}", APP_NAME).into(); + fs::create_dir(&path).ok(); + fs::set_permissions(&path, fs::Permissions::from_mode(0o0777)).ok(); + path.push(format!("ipc{}", postfix)); + path.to_str().unwrap_or("").to_owned() + } } pub fn icon_path() -> PathBuf { @@ -446,7 +460,7 @@ impl Config { fn get_auto_id() -> Option { #[cfg(any(target_os = "android", target_os = "ios"))] - return None; + return None; let mut id = 0u32; #[cfg(not(any(target_os = "android", target_os = "ios")))] if let Ok(Some(ma)) = mac_address::get_mac_address() { @@ -659,6 +673,45 @@ impl Config { Some(_) => NetworkType::ProxySocks, } } + + pub fn copy_and_reload_config_dir>( + target_username: String, + from: P, + ) -> Result { + let to = Self::path(""); + let to_parent = to.parent().unwrap(); + + let mut options = fs_extra::dir::CopyOptions::new(); + options.overwrite = true; + options.copy_inside = true; + + let mut f = from.as_ref(); + + return match fs_extra::dir::copy(f, to_parent, &options) { + Ok(count) => { + if count > 0 { + log::info!("{}",target_username); + log::info!("{}",f.to_str().unwrap().to_string()); + log::info!("{}",to.to_str().unwrap().to_string()); + + std::process::Command::new("chown") + .arg("-R") + .arg(target_username) + .arg(to.to_str().unwrap().to_string()) + .spawn(); + + CONFIG.write().unwrap().reload(); + CONFIG2.write().unwrap().reload(); + } + + Ok(count > 0) + } + Err(e) => { + log::error!("config copy failed: {}", e); + Err(e) + } + }; + } } const PEERS: &str = "peers"; @@ -757,6 +810,7 @@ impl Fav { #[cfg(test)] mod tests { use super::*; + #[test] fn test_serialize() { let cfg: Config = Default::default(); diff --git a/src/ipc.rs b/src/ipc.rs index e197d804d..bbfc40a31 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -1,19 +1,10 @@ -use hbb_common::{ - allow_err, bail, bytes, - bytes_codec::BytesCodec, - config::{self, Config}, - futures::StreamExt as _, - futures_util::sink::SinkExt, - log, timeout, tokio, - tokio::io::{AsyncRead, AsyncWrite}, - tokio_util::codec::Framed, - ResultType, -}; +use hbb_common::{allow_err, bail, bytes, bytes_codec::BytesCodec, config::{self, Config}, futures::StreamExt as _, futures_util::sink::SinkExt, log, timeout, tokio, tokio::io::{AsyncRead, AsyncWrite}, tokio_util::codec::Framed, ResultType}; use parity_tokio_ipc::{ Connection as Conn, ConnectionClient as ConnClient, Endpoint, Incoming, SecurityAttributes, }; use serde_derive::{Deserialize, Serialize}; use std::collections::HashMap; +use std::path::PathBuf; #[cfg(not(windows))] use std::{fs::File, io::prelude::*}; @@ -92,6 +83,11 @@ pub enum Data { Socks(Option), FS(FS), Test, + ConfigCopyReq { + target_username: String, + dir_path: String, + }, + ConfigCopyResp(Option), } #[tokio::main(flavor = "current_thread")] @@ -129,7 +125,7 @@ pub async fn start(postfix: &str) -> ResultType<()> { pub async fn new_listener(postfix: &str) -> ResultType { let path = Config::ipc_path(postfix); #[cfg(not(windows))] - check_pid(postfix).await; + check_pid(postfix).await; let mut endpoint = Endpoint::new(path.clone()); match SecurityAttributes::allow_everyone_create() { Ok(attr) => endpoint.set_security_attributes(attr), @@ -139,11 +135,11 @@ pub async fn new_listener(postfix: &str) -> ResultType { Ok(incoming) => { log::info!("Started ipc{} server at path: {}", postfix, &path); #[cfg(not(windows))] - { - use std::os::unix::fs::PermissionsExt; - std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o0777)).ok(); - write_pid(postfix); - } + { + use std::os::unix::fs::PermissionsExt; + std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o0777)).ok(); + write_pid(postfix); + } Ok(incoming) } Err(err) => { @@ -252,6 +248,23 @@ async fn handle(data: Data, stream: &mut Connection) { let t = Config::get_nat_type(); allow_err!(stream.send(&Data::NatType(Some(t))).await); } + Data::ConfigCopyReq { target_username, dir_path } => { + let from = PathBuf::from(dir_path); + if !from.exists() { + allow_err!(stream.send(&Data::ConfigCopyResp(None)).await); + return; + } + + match Config::copy_and_reload_config_dir(target_username, from) { + Ok(result) => { + allow_err!(stream.send(&Data::ConfigCopyResp(Some(result))).await); + } + Err(e) => { + log::error!("copy_and_reload_config_dir failed: {:?}",e); + allow_err!(stream.send(&Data::ConfigCopyResp(Some(false))).await); + } + } + } _ => {} } } @@ -312,8 +325,8 @@ pub struct ConnectionTmpl { pub type Connection = ConnectionTmpl; impl ConnectionTmpl -where - T: AsyncRead + AsyncWrite + std::marker::Unpin, + where + T: AsyncRead + AsyncWrite + std::marker::Unpin, { pub fn new(conn: T) -> Self { Self { diff --git a/src/lib.rs b/src/lib.rs index 2df657ab0..7bac02eeb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,4 +27,4 @@ use common::*; pub mod cli; #[cfg(not(any(target_os = "android", target_os = "ios")))] mod port_forward; -mod lang; +mod lang; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e2d00d0c5..1af4c9f45 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ fn main() { common::test_rendezvous_server(); common::test_nat_type(); #[cfg(target_os = "android")] - crate::common::check_software_update(); + crate::common::check_software_update(); mobile::Session::start(""); } @@ -29,53 +29,53 @@ fn main() { return; } #[cfg(not(feature = "inline"))] - { - use hbb_common::env_logger::*; - init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); - } - #[cfg(feature = "inline")] - { - let mut path = hbb_common::config::Config::log_path(); - if args.len() > 0 && args[0].starts_with("--") { - let name = args[0].replace("--", ""); - if !name.is_empty() { - path.push(name); - } + { + use hbb_common::env_logger::*; + init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); + } + #[cfg(feature = "inline")] + { + let mut path = hbb_common::config::Config::log_path(); + if args.len() > 0 && args[0].starts_with("--") { + let name = args[0].replace("--", ""); + if !name.is_empty() { + path.push(name); + } + } + use flexi_logger::*; + Logger::try_with_env_or_str("debug") + .map(|x| { + x.log_to_file(FileSpec::default().directory(path)) + .format(opt_format) + .rotate( + Criterion::Age(Age::Day), + Naming::Timestamps, + Cleanup::KeepLogFiles(6), + ) + .start() + .ok(); + }) + .ok(); } - use flexi_logger::*; - Logger::try_with_env_or_str("debug") - .map(|x| { - x.log_to_file(FileSpec::default().directory(path)) - .format(opt_format) - .rotate( - Criterion::Age(Age::Day), - Naming::Timestamps, - Cleanup::KeepLogFiles(6), - ) - .start() - .ok(); - }) - .ok(); - } if args.is_empty() { std::thread::spawn(move || start_server(false, false)); } else { #[cfg(windows)] - { - if args[0] == "--uninstall" { - if let Err(err) = platform::uninstall_me() { - log::error!("Failed to uninstall: {}", err); + { + if args[0] == "--uninstall" { + if let Err(err) = platform::uninstall_me() { + log::error!("Failed to uninstall: {}", err); + } + return; + } else if args[0] == "--update" { + hbb_common::allow_err!(platform::update_me()); + return; + } else if args[0] == "--reinstall" { + hbb_common::allow_err!(platform::uninstall_me()); + hbb_common::allow_err!(platform::install_me("desktopicon startmenu",)); + return; } - return; - } else if args[0] == "--update" { - hbb_common::allow_err!(platform::update_me()); - return; - } else if args[0] == "--reinstall" { - hbb_common::allow_err!(platform::uninstall_me()); - hbb_common::allow_err!(platform::install_me("desktopicon startmenu",)); - return; } - } if args[0] == "--remove" { if args.len() == 2 { // sleep a while so that process of removed exe exit @@ -101,6 +101,10 @@ fn main() { ipc::set_password(args[1].to_owned()).unwrap(); } return; + } else if cfg!(target_os = "macos") && args[0] == "--daemon" { + log::info!("start --daemon"); + crate::platform::start_daemon(); + return; } } ui::start(&mut args[..]); diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 5834fd024..a79094172 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -333,3 +333,10 @@ pub fn block_input(_v: bool) { pub fn is_installed() -> bool { true } + +pub fn start_daemon(){ + if let Err(err) = crate::ipc::start("_daemon") { + log::error!("Failed to start ipc_daemon: {}", err); + std::process::exit(-1); + } +} diff --git a/src/server.rs b/src/server.rs index 451c18e1b..27cf0061a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,4 +1,4 @@ -use crate::ipc::Data; +use crate::ipc::{ConnectionTmpl, Data}; use connection::{ConnInner, Connection}; use hbb_common::{ allow_err, @@ -9,18 +9,24 @@ use hbb_common::{ message_proto::*, protobuf::{Message as _, ProtobufEnum}, rendezvous_proto::*, - sleep, + sleep, socket_client, sodiumoxide::crypto::{box_, secretbox, sign}, timeout, tokio, ResultType, Stream, - socket_client, }; use service::{GenericService, Service, ServiceTmpl, Subscriber}; +use std::sync::mpsc::RecvError; +use std::time::Duration; use std::{ collections::HashMap, net::SocketAddr, sync::{Arc, Mutex, RwLock, Weak}, }; +use hbb_common::log::info; +#[cfg(target_os = "macos")] +use notify::{watcher, RecursiveMode, Watcher}; +use parity_tokio_ipc::ConnectionClient; + mod audio_service; mod clipboard_service; mod connection; @@ -166,7 +172,7 @@ pub async fn create_relay_connection( secure: bool, ) { if let Err(err) = - create_relay_connection_(server, relay_server, uuid.clone(), peer_addr, secure).await + create_relay_connection_(server, relay_server, uuid.clone(), peer_addr, secure).await { log::error!( "Failed to create relay connection for {} with uuid {}: {}", @@ -189,7 +195,7 @@ async fn create_relay_connection_( Config::get_any_listen_addr(), CONNECT_TIMEOUT, ) - .await?; + .await?; let mut msg_out = RendezvousMessage::new(); msg_out.set_request_relay(RequestRelay { uuid, @@ -264,10 +270,13 @@ pub fn check_zombie() { #[tokio::main] pub async fn start_server(is_server: bool, _tray: bool) { #[cfg(target_os = "linux")] - { - log::info!("DISPLAY={:?}", std::env::var("DISPLAY")); - log::info!("XAUTHORITY={:?}", std::env::var("XAUTHORITY")); - } + { + log::info!("DISPLAY={:?}", std::env::var("DISPLAY")); + log::info!("XAUTHORITY={:?}", std::env::var("XAUTHORITY")); + } + + sync_and_watch_config_dir().await; + if is_server { std::thread::spawn(move || { if let Err(err) = crate::ipc::start("") { @@ -298,7 +307,7 @@ pub async fn start_server(is_server: bool, _tray: bool) { } else { allow_err!(conn.send(&Data::ConfirmedKey(None)).await); if let Ok(Some(Data::ConfirmedKey(Some(pair)))) = - conn.next_timeout(1000).await + conn.next_timeout(1000).await { Config::set_key_pair(pair); Config::set_key_confirmed(true); @@ -317,3 +326,72 @@ pub async fn start_server(is_server: bool, _tray: bool) { } } } + +async fn sync_and_watch_config_dir() -> ResultType<()> { + let mut conn = crate::ipc::connect(1000, "_daemon").await?; + + sync_config_dir(&mut conn, "/var/root/Library/Preferences/com.carriez.RustDesk/".to_string()).await?; + + tokio::spawn(async move { + log::info!( + "watching config dir: {}", + Config::path("").to_str().unwrap().to_string() + ); + + let (tx, rx) = std::sync::mpsc::channel(); + let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap(); + watcher + .watch(Config::path("").as_path(), RecursiveMode::Recursive) + .unwrap(); + + loop { + let ev = rx.recv(); + match ev { + Ok(event) => match event { + notify::DebouncedEvent::Write(path) => { + log::info!( + "config file changed, call ipc_daemon to sync: {}", + path.to_str().unwrap().to_string() + ); + sync_config_dir(&mut conn, Config::path("").to_str().unwrap().to_string()).await; + } + x => { + log::info!("another {:?}", x) + } + }, + Err(e) => println!("watch error: {:?}", e), + } + } + }); + + Ok(()) +} + +async fn sync_config_dir(conn: &mut ConnectionTmpl, path: String) -> ResultType<()> { + allow_err!( + conn.send(&Data::ConfigCopyReq { + target_username: crate::username(), + dir_path: path + }) + .await + ); + if let Ok(Some(data)) = conn.next_timeout(1000).await { + match data { + Data::ConfigCopyResp(result) => match result { + Some(success) => { + if success { + log::info!("copy and reload config dir success"); + } else { + log::info!("copy config dir failed. may be first running"); + } + } + None => {} + }, + x => { + log::info!("receive another {:?}",x) + } + }; + }; + + Ok(()) +}