From 88f0f67ee321429c94f3fc2419edd537382917de Mon Sep 17 00:00:00 2001 From: chenbaiyu Date: Thu, 13 Jan 2022 15:26:57 +0800 Subject: [PATCH] temp commit --- libs/hbb_common/src/config.rs | 203 +++++++++++++++++++++------------- src/ipc.rs | 83 +++++++++----- src/platform/macos.rs | 1 + src/server.rs | 143 ++++++++++++++---------- 4 files changed, 264 insertions(+), 166 deletions(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index e9df2f15c..cb52f8708 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -11,7 +11,6 @@ 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; @@ -163,28 +162,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 } @@ -276,7 +275,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() { @@ -288,15 +287,15 @@ impl Config { 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()); @@ -309,19 +308,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"); @@ -332,21 +331,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 { @@ -460,7 +459,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() { @@ -674,43 +673,91 @@ impl Config { } } - pub fn copy_and_reload_config_dir>( - target_username: String, - from: P, - ) -> Result { - let to = Self::path(""); - let to_parent = to.parent().unwrap(); + pub fn sync_config_to_user>(target_username: String, to_dir: P) -> bool { + let config1_root_file_path = Config::file_(""); + let config1_filename = config1_root_file_path.file_name(); - let mut options = fs_extra::dir::CopyOptions::new(); - options.overwrite = true; - options.copy_inside = true; + let config2_root_file_path = Config::file_("2"); + let config2_filename = config2_root_file_path.file_name(); - let mut f = from.as_ref(); + let config1_to_file_path = to_dir + .as_ref() + .join(PathBuf::from(&config1_filename.unwrap())); + let config2_to_file_path = to_dir + .as_ref() + .join(PathBuf::from(&config2_filename.unwrap())); - 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()); + log::info!( + "config1_root_path:{}", + &config1_root_file_path.as_path().to_str().unwrap() + ); + log::info!( + "config2_root_path:{}", + &config2_root_file_path.as_path().to_str().unwrap() + ); + log::info!( + "config1_to_path:{}", + &config1_to_file_path.as_path().to_str().unwrap() + ); + log::info!( + "config2_to_path:{}", + &config2_to_file_path.as_path().to_str().unwrap() + ); - std::process::Command::new("chown") - .arg("-R") - .arg(target_username) - .arg(to.to_str().unwrap().to_string()) - .spawn(); + match std::fs::copy(&config1_root_file_path, &config1_to_file_path) { + Err(e) => log::error!( + "copy config {} to user failed: {}", + config1_filename.unwrap().to_str().unwrap(), + e + ), + _ => {} + } - CONFIG.write().unwrap().reload(); - CONFIG2.write().unwrap().reload(); + match std::fs::copy(&config2_root_file_path, &config2_to_file_path) { + Err(e) => log::error!( + "copy config {} to user failed: {}", + config2_filename.unwrap().to_str().unwrap(), + e + ), + _ => {} + } + + let success = std::process::Command::new("chown") + .arg(&target_username.to_string()) + .arg(&config1_to_file_path.to_str().unwrap().to_string()) + .arg(&config2_to_file_path.to_str().unwrap().to_string()) + .spawn() + .is_ok(); + + if success { + CONFIG.write().unwrap().reload(); + CONFIG2.write().unwrap().reload(); + } + + return success; + } + + pub fn sync_config_to_root>(from_file_path: P) -> bool { + if let Some(filename) = from_file_path.as_ref().file_name() { + let to = Config::path(filename); + return match std::fs::copy(from_file_path, &to) { + Ok(count) => { + if count > 0 { + return std::process::Command::new("chown") + .arg("root") + .arg(&to.to_str().unwrap().to_string()) + .spawn() + .is_ok(); + } + false } - - Ok(count > 0) - } - Err(e) => { - log::error!("config copy failed: {}", e); - Err(e) - } - }; + Err(e) => { + log::error!("sync_config_to_root failed: {}", e); + false + } + }; + } + false } } diff --git a/src/ipc.rs b/src/ipc.rs index bbfc40a31..59e406430 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -1,10 +1,20 @@ -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::log::info; +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::*}; @@ -83,17 +93,22 @@ pub enum Data { Socks(Option), FS(FS), Test, - ConfigCopyReq { - target_username: String, - dir_path: String, + SyncConfigToRootReq { + from: String, }, - ConfigCopyResp(Option), + SyncConfigToRootResp(bool), + SyncConfigToUserReq { + username: String, + to: String, + }, + SyncConfigToUserResp(bool), } #[tokio::main(flavor = "current_thread")] pub async fn start(postfix: &str) -> ResultType<()> { let mut incoming = new_listener(postfix).await?; loop { + log::info!("begin loop"); if let Some(result) = incoming.next().await { match result { Ok(stream) => { @@ -101,13 +116,16 @@ pub async fn start(postfix: &str) -> ResultType<()> { let postfix = postfix.to_owned(); tokio::spawn(async move { loop { + log::info!("begin loop"); match stream.next().await { Err(err) => { log::trace!("ipc{} connection closed: {}", postfix, err); break; } Ok(Some(data)) => { + log::info!("begin handle"); handle(data, &mut stream).await; + log::info!("end handle"); } _ => {} } @@ -125,7 +143,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), @@ -135,11 +153,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) => { @@ -248,22 +266,27 @@ 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); - } - } + Data::SyncConfigToRootReq { from } => { + info!("begin SyncConfigToRootReq, {}", from); + allow_err!( + stream + .send(&Data::SyncConfigToRootResp(Config::sync_config_to_root( + from + ))) + .await + ); + info!("begin SyncConfigToRootReq end"); + } + Data::SyncConfigToUserReq { username, to } => { + info!("begin SyncConfigToUserReq,{},{}", username, to); + allow_err!( + stream + .send(&Data::SyncConfigToUserResp(Config::sync_config_to_user( + username, to + ))) + .await + ); + info!("begin SyncConfigToUserReq end"); } _ => {} } @@ -325,8 +348,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/platform/macos.rs b/src/platform/macos.rs index a79094172..f278fdf9c 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -335,6 +335,7 @@ pub fn is_installed() -> bool { } pub fn start_daemon(){ + log::info!("{}",crate::username()); 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 27cf0061a..38da11b5c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -14,7 +14,7 @@ use hbb_common::{ timeout, tokio, ResultType, Stream, }; use service::{GenericService, Service, ServiceTmpl, Subscriber}; -use std::sync::mpsc::RecvError; +use std::path::PathBuf; use std::time::Duration; use std::{ collections::HashMap, @@ -22,7 +22,6 @@ use std::{ sync::{Arc, Mutex, RwLock, Weak}, }; -use hbb_common::log::info; #[cfg(target_os = "macos")] use notify::{watcher, RecursiveMode, Watcher}; use parity_tokio_ipc::ConnectionClient; @@ -172,7 +171,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 {}: {}", @@ -195,7 +194,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, @@ -270,12 +269,14 @@ 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; + tokio::spawn(async { sync_and_watch_config_dir().await }); + + log::info!("enter server"); if is_server { std::thread::spawn(move || { @@ -307,7 +308,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); @@ -327,68 +328,94 @@ 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?; +async fn sync_and_watch_config_dir() { + if crate::username() == "root"{ + return; + } - sync_config_dir(&mut conn, "/var/root/Library/Preferences/com.carriez.RustDesk/".to_string()).await?; + match crate::ipc::connect(1000, "_daemon").await { + Ok(mut conn) => { + sync_config_to_user(&mut conn).await; - tokio::spawn(async move { - log::info!( - "watching config dir: {}", - Config::path("").to_str().unwrap().to_string() - ); + 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(); + let (tx, rx) = std::sync::mpsc::channel(); + let mut watcher = watcher(tx, Duration::from_secs(2)).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), + 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_to_root(&mut conn, path).await; + log::info!("sync end"); + } + x => { + log::info!("another {:?}", x) + } + }, + Err(e) => println!("watch error: {:?}", e), + } } } - }); - - Ok(()) + Err(e) => { + log::info!("connect ipc_daemon failed, skip config sync"); + return; + } + } } -async fn sync_config_dir(conn: &mut ConnectionTmpl, path: String) -> ResultType<()> { +async fn sync_config_to_user(conn: &mut ConnectionTmpl) -> ResultType<()> { allow_err!( - conn.send(&Data::ConfigCopyReq { - target_username: crate::username(), - dir_path: path + conn.send(&Data::SyncConfigToUserReq { + username: crate::username(), + to: Config::path("").to_str().unwrap().to_string(), }) .await ); - if let Ok(Some(data)) = conn.next_timeout(1000).await { + + if let Some(data) = conn.next_timeout(2000).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 => {} - }, + Data::SyncConfigToUserResp(success) => { + log::info!("copy and reload config dir success: {:?}", success); + } x => { - log::info!("receive another {:?}",x) + log::info!("receive another {:?}", x) + } + }; + }; + + Ok(()) +} + +async fn sync_config_to_root( + conn: &mut ConnectionTmpl, + from: PathBuf, +) -> ResultType<()> { + allow_err!( + conn.send(&Data::SyncConfigToRootReq { + from: from.to_str().unwrap().to_string() + }) + .await + ); + + if let Some(data) = conn.next_timeout(2000).await? { + match data { + Data::SyncConfigToRootResp(success) => { + log::info!("copy config to root dir success: {:?}", success); + } + x => { + log::info!("receive another {:?}", x) } }; };