From 2da5401fd48664d40a984d7a9839849877e169db Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 11 Oct 2022 20:36:19 -0700 Subject: [PATCH] add global init and update wayland error map Signed-off-by: fufesou --- libs/hbb_common/src/platform/linux.rs | 31 +++++++++++++- libs/scrap/src/common/mod.rs | 1 + libs/scrap/src/common/wayland.rs | 16 ++++++- src/common.rs | 35 ++++++++++++++- src/main.rs | 12 ++++++ src/server.rs | 2 +- src/server/connection.rs | 2 +- src/server/wayland.rs | 62 +++++++++++++++++++++++++-- src/ui_interface.rs | 2 +- 9 files changed, 151 insertions(+), 12 deletions(-) diff --git a/libs/hbb_common/src/platform/linux.rs b/libs/hbb_common/src/platform/linux.rs index 08e091337..0473a3bbc 100644 --- a/libs/hbb_common/src/platform/linux.rs +++ b/libs/hbb_common/src/platform/linux.rs @@ -1,5 +1,31 @@ use crate::ResultType; +lazy_static::lazy_static! { + pub static ref DISTRO: Disto = Disto::new(); +} + +pub struct Disto { + pub name: String, + pub version_id: String, +} + +impl Disto { + fn new() -> Self { + let name = run_cmds("awk -F'=' '/^NAME=/ {print $2}' /etc/os-release".to_owned()) + .unwrap_or_default() + .trim() + .trim_matches('"') + .to_string(); + let version_id = + run_cmds("awk -F'=' '/^VERSION_ID=/ {print $2}' /etc/os-release".to_owned()) + .unwrap_or_default() + .trim() + .trim_matches('"') + .to_string(); + Self { name, version_id } + } +} + pub fn get_display_server() -> String { let session = get_value_of_seat0(0); get_display_server_of_session(&session) @@ -81,8 +107,9 @@ pub fn get_value_of_seat0(i: usize) -> String { } // loginctl has not given the expected output. try something else. - if let Ok(sid) = std::env::var("XDG_SESSION_ID") { // could also execute "cat /proc/self/sessionid" - return sid.to_owned(); + if let Ok(sid) = std::env::var("XDG_SESSION_ID") { + // could also execute "cat /proc/self/sessionid" + return sid.to_owned(); } return "".to_owned(); diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index fe817c00a..468efb88e 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -12,6 +12,7 @@ cfg_if! { mod x11; pub use self::linux::*; pub use self::x11::Frame; + pub use self::wayland::set_map_err; } else { mod x11; pub use self::x11::*; diff --git a/libs/scrap/src/common/wayland.rs b/libs/scrap/src/common/wayland.rs index e33cbe745..6ad2d84cb 100644 --- a/libs/scrap/src/common/wayland.rs +++ b/libs/scrap/src/common/wayland.rs @@ -1,11 +1,23 @@ use crate::common::{x11::Frame, TraitCapturer}; use crate::wayland::{capturable::*, *}; -use std::{io, time::Duration}; +use std::{io, sync::RwLock, time::Duration}; pub struct Capturer(Display, Box, bool, Vec); +lazy_static::lazy_static! { + static ref MAP_ERR: RwLock io::Error>> = Default::default(); +} + +pub fn set_map_err(f: fn(err: String) -> io::Error) { + *MAP_ERR.write().unwrap() = Some(f); +} + fn map_err(err: E) -> io::Error { - io::Error::new(io::ErrorKind::Other, err.to_string()) + if let Some(f) = *MAP_ERR.read().unwrap() { + f(err.to_string()) + } else { + io::Error::new(io::ErrorKind::Other, err.to_string()) + } } impl Capturer { diff --git a/src/common.rs b/src/common.rs index 129e948cf..9beed2e90 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,4 +1,7 @@ -use std::sync::{Arc, Mutex}; +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; #[cfg(not(any(target_os = "android", target_os = "ios")))] pub use arboard::Clipboard as ClipboardContext; @@ -31,6 +34,36 @@ lazy_static::lazy_static! { pub static ref DEVICE_NAME: Arc> = Default::default(); } +lazy_static::lazy_static! { + static ref GLOBAL_INIT_FUNCS: Mutex bool>> = Default::default(); + static ref GLOBAL_CLEAN_FUNCS: Mutex> = Default::default(); +} + +pub fn reg_global_init(key: String, f: fn() -> bool) { + GLOBAL_INIT_FUNCS.lock().unwrap().insert(key, f); +} + +pub fn reg_global_clean(key: String, f: fn()) { + GLOBAL_CLEAN_FUNCS.lock().unwrap().insert(key, f); +} + +pub fn global_init() -> bool { + for (k, f) in GLOBAL_INIT_FUNCS.lock().unwrap().iter() { + println!("Init {}", k); + if !f() { + return false; + } + } + true +} + +pub fn global_clean() { + for (k, f) in GLOBAL_CLEAN_FUNCS.lock().unwrap().iter() { + println!("Clean {}", k); + f(); + } +} + #[inline] pub fn valid_for_numlock(evt: &KeyEvent) -> bool { if let Some(key_event::Union::ControlKey(ck)) = evt.union { diff --git a/src/main.rs b/src/main.rs index 23559ed8a..ac8fd5219 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,21 +6,32 @@ use librustdesk::*; #[cfg(any(target_os = "android", target_os = "ios"))] fn main() { + if !common::global_init() { + return; + } common::test_rendezvous_server(); common::test_nat_type(); #[cfg(target_os = "android")] crate::common::check_software_update(); + common::global_clean(); } #[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))] fn main() { + if !common::global_init() { + return; + } if let Some(args) = crate::core_main::core_main().as_mut() { ui::start(args); } + common::global_clean(); } #[cfg(feature = "cli")] fn main() { + if !common::global_init() { + return; + } use hbb_common::log; use clap::App; let args = format!( @@ -64,4 +75,5 @@ fn main() { let token = LocalConfig::get_option("access_token"); cli::start_one_port_forward(options[0].clone(), port, remote_host, remote_port, key, token); } + common::global_clean(); } \ No newline at end of file diff --git a/src/server.rs b/src/server.rs index cb3fd7c9d..58aab8fd1 100644 --- a/src/server.rs +++ b/src/server.rs @@ -27,7 +27,7 @@ cfg_if::cfg_if! { if #[cfg(not(any(target_os = "android", target_os = "ios")))] { mod clipboard_service; #[cfg(target_os = "linux")] -mod wayland; +pub(crate) mod wayland; #[cfg(target_os = "linux")] pub mod uinput; #[cfg(target_os = "linux")] diff --git a/src/server/connection.rs b/src/server/connection.rs index d111757bf..8e3f80bb9 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -745,7 +745,7 @@ impl Connection { try_activate_screen(); match super::video_service::get_displays().await { Err(err) => { - res.set_error(format!("X11 error: {}", err)); + res.set_error(format!("Error: {}", err)); } Ok((current, displays)) => { pi.displays = displays.into(); diff --git a/src/server/wayland.rs b/src/server/wayland.rs index 1ac2c18be..c12d1e8da 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -1,10 +1,53 @@ use super::*; -use hbb_common::allow_err; -use scrap::{Capturer, Display, Frame, TraitCapturer}; -use std::io::Result; +use hbb_common::{allow_err, platform::linux::DISTRO}; +use scrap::{set_map_err, Capturer, Display, Frame, TraitCapturer}; +use std::io; + +pub const SCRAP_UBUNTU_HIGHER_REQUIRED: &str = "Wayland requires Ubuntu 21.04 or higher version."; +pub const SCRAP_OTHER_VERSION_OR_X11_REQUIRED: &str = + "Wayland requires higher version of linux distro. Please try X11 desktop or change your OS."; +pub const SCRAP_X11_REQUIRED: &str = "X11 is required"; +pub const SCRAP_X11_REF_URL: &str = "https://rustdesk.com/docs/en/manual/linux/#x11-required"; lazy_static::lazy_static! { static ref CAP_DISPLAY_INFO: RwLock = RwLock::new(0); + static ref LOG_SCRAP_COUNT: Mutex = Mutex::new(0); + static ref GLOBAL_INIT_REG_HELPER: u8 = { + set_map_err(map_err_scrap); + 0u8 + }; +} + +pub fn map_err_scrap(err: String) -> io::Error { + if DISTRO.name.to_uppercase() == "Ubuntu".to_uppercase() { + if DISTRO.version_id < "21".to_owned() { + io::Error::new(io::ErrorKind::Other, SCRAP_UBUNTU_HIGHER_REQUIRED) + } else { + try_log(&err); + io::Error::new(io::ErrorKind::Other, err) + } + } else { + try_log(&err); + if err.contains("org.freedesktop.portal") + || err.contains("pipewire") + || err.contains("dbus") + { + io::Error::new(io::ErrorKind::Other, SCRAP_OTHER_VERSION_OR_X11_REQUIRED) + } else { + io::Error::new(io::ErrorKind::Other, SCRAP_X11_REQUIRED) + } + } +} + +fn try_log(err: &String) { + let mut lock_count = LOG_SCRAP_COUNT.lock().unwrap(); + if *lock_count >= 1000000 { + return; + } + if *lock_count % 10000 == 0 { + log::error!("Failed scrap {}", err); + } + *lock_count += 1; } struct CapturerPtr(*mut Capturer); @@ -16,7 +59,7 @@ impl Clone for CapturerPtr { } impl TraitCapturer for CapturerPtr { - fn frame<'a>(&'a mut self, timeout: Duration) -> Result> { + fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result> { unsafe { (*self.0).frame(timeout) } } @@ -187,3 +230,14 @@ pub(super) fn get_capturer() -> ResultType { bail!("Failed to get capturer display info"); } } + +pub fn common_get_error() -> String { + if DISTRO.name.to_uppercase() == "Ubuntu".to_uppercase() { + if DISTRO.version_id < "21".to_owned() { + return "".to_owned(); + } + } else { + // to-do: check other distros + } + return "".to_owned(); +} diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 9952a5b35..9ef512fd7 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -547,7 +547,7 @@ pub fn get_error() -> String { { let dtype = crate::platform::linux::get_display_server(); if "wayland" == dtype { - return "".to_owned(); + return crate::server::wayland::common_get_error(); } if dtype != "x11" { return format!(