Remove some arc, and add some custom client

This commit is contained in:
rustdesk 2024-03-10 12:48:00 +08:00
parent 866ec097c0
commit 7060257051
6 changed files with 174 additions and 59 deletions

View File

@ -112,4 +112,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
COCOAPODS: 1.12.1 COCOAPODS: 1.15.2

View File

@ -5,7 +5,7 @@ use std::{
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{Arc, Mutex, RwLock}, sync::{Mutex, RwLock},
time::{Duration, Instant, SystemTime}, time::{Duration, Instant, SystemTime},
}; };
@ -46,41 +46,42 @@ pub const CONFIG_OPTION_ALLOW_LINUX_HEADLESS: &str = "allow-linux-headless";
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref ORG: Arc<RwLock<String>> = Arc::new(RwLock::new("com.carriez".to_owned())); pub static ref ORG: RwLock<String> = RwLock::new("com.carriez".to_owned());
} }
type Size = (i32, i32, i32, i32); type Size = (i32, i32, i32, i32);
type KeyPair = (Vec<u8>, Vec<u8>); type KeyPair = (Vec<u8>, Vec<u8>);
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load())); static ref CONFIG: RwLock<Config> = RwLock::new(Config::load());
static ref CONFIG2: Arc<RwLock<Config2>> = Arc::new(RwLock::new(Config2::load())); static ref CONFIG2: RwLock<Config2> = RwLock::new(Config2::load());
static ref LOCAL_CONFIG: Arc<RwLock<LocalConfig>> = Arc::new(RwLock::new(LocalConfig::load())); static ref LOCAL_CONFIG: RwLock<LocalConfig> = RwLock::new(LocalConfig::load());
static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default(); static ref ONLINE: Mutex<HashMap<String, i64>> = Default::default();
pub static ref PROD_RENDEZVOUS_SERVER: Arc<RwLock<String>> = Arc::new(RwLock::new(match option_env!("RENDEZVOUS_SERVER") { pub static ref PROD_RENDEZVOUS_SERVER: RwLock<String> = RwLock::new(match option_env!("RENDEZVOUS_SERVER") {
Some(key) if !key.is_empty() => key, Some(key) if !key.is_empty() => key,
_ => "", _ => "",
}.to_owned())); }.to_owned());
pub static ref EXE_RENDEZVOUS_SERVER: Arc<RwLock<String>> = Default::default(); pub static ref EXE_RENDEZVOUS_SERVER: RwLock<String> = Default::default();
pub static ref APP_NAME: Arc<RwLock<String>> = Arc::new(RwLock::new("RustDesk".to_owned())); pub static ref APP_NAME: RwLock<String> = RwLock::new("RustDesk".to_owned());
static ref KEY_PAIR: Arc<Mutex<Option<KeyPair>>> = Default::default(); static ref KEY_PAIR: Mutex<Option<KeyPair>> = Default::default();
static ref USER_DEFAULT_CONFIG: Arc<RwLock<(UserDefaultConfig, Instant)>> = Arc::new(RwLock::new((UserDefaultConfig::load(), Instant::now()))); static ref USER_DEFAULT_CONFIG: RwLock<(UserDefaultConfig, Instant)> = RwLock::new((UserDefaultConfig::load(), Instant::now()));
pub static ref NEW_STORED_PEER_CONFIG: Arc<Mutex<HashSet<String>>> = Default::default(); pub static ref NEW_STORED_PEER_CONFIG: Mutex<HashSet<String>> = Default::default();
pub static ref DEFAULT_SETTINGS: Arc<RwLock<HashMap<String, String>>> = Default::default(); pub static ref DEFAULT_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref OVERWRITE_SETTINGS: Arc<RwLock<HashMap<String, String>>> = Default::default(); pub static ref OVERWRITE_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref DEFAULT_DISPLAY_SETTINGS: Arc<RwLock<HashMap<String, String>>> = Default::default(); pub static ref DEFAULT_DISPLAY_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref OVERWRITE_DISPLAY_SETTINGS: Arc<RwLock<HashMap<String, String>>> = Default::default(); pub static ref OVERWRITE_DISPLAY_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref DEFAULT_LOCAL_SETTINGS: Arc<RwLock<HashMap<String, String>>> = Default::default(); pub static ref DEFAULT_LOCAL_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref OVERWRITE_LOCAL_SETTINGS: Arc<RwLock<HashMap<String, String>>> = Default::default(); pub static ref OVERWRITE_LOCAL_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref HARD_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
} }
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref APP_DIR: Arc<RwLock<String>> = Default::default(); pub static ref APP_DIR: RwLock<String> = Default::default();
} }
#[cfg(any(target_os = "android", target_os = "ios"))] #[cfg(any(target_os = "android", target_os = "ios"))]
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref APP_HOME_DIR: Arc<RwLock<String>> = Default::default(); pub static ref APP_HOME_DIR: RwLock<String> = Default::default();
} }
pub const LINK_DOCS_HOME: &str = "https://rustdesk.com/docs/en/"; pub const LINK_DOCS_HOME: &str = "https://rustdesk.com/docs/en/";
@ -922,17 +923,13 @@ impl Config {
} }
pub fn get_option(k: &str) -> String { pub fn get_option(k: &str) -> String {
if let Some(v) = OVERWRITE_SETTINGS.read().unwrap().get(k) { get_or(
return v.clone(); &OVERWRITE_SETTINGS,
} &CONFIG2.read().unwrap().options,
if let Some(v) = CONFIG2.read().unwrap().options.get(k) { &DEFAULT_SETTINGS,
v.clone() k,
} else { )
if let Some(v) = DEFAULT_SETTINGS.read().unwrap().get(k) { .unwrap_or_default()
return v.clone();
}
"".to_owned()
}
} }
pub fn set_option(k: String, v: String) { pub fn set_option(k: String, v: String) {
@ -1381,17 +1378,13 @@ impl LocalConfig {
} }
pub fn get_option(k: &str) -> String { pub fn get_option(k: &str) -> String {
if let Some(v) = OVERWRITE_LOCAL_SETTINGS.read().unwrap().get(k) { get_or(
return v.clone(); &OVERWRITE_LOCAL_SETTINGS,
} &LOCAL_CONFIG.read().unwrap().options,
if let Some(v) = LOCAL_CONFIG.read().unwrap().options.get(k) { &DEFAULT_LOCAL_SETTINGS,
v.clone() k,
} else { )
if let Some(v) = DEFAULT_LOCAL_SETTINGS.read().unwrap().get(k) { .unwrap_or_default()
return v.clone();
}
"".to_owned()
}
} }
pub fn set_option(k: String, v: String) { pub fn set_option(k: String, v: String) {
@ -1608,18 +1601,13 @@ impl UserDefaultConfig {
} }
} }
fn get_after(&self, key: &str) -> Option<String> { fn get_after(&self, k: &str) -> Option<String> {
if let Some(v) = OVERWRITE_DISPLAY_SETTINGS.read().unwrap().get(key) { get_or(
return Some(v.clone()); &OVERWRITE_DISPLAY_SETTINGS,
} &self.options,
if let Some(v) = self.options.get(key) { &DEFAULT_DISPLAY_SETTINGS,
Some(v.clone()) k,
} else { )
if let Some(v) = DEFAULT_DISPLAY_SETTINGS.read().unwrap().get(key) {
return Some(v.clone());
}
None
}
} }
} }
@ -1854,6 +1842,21 @@ deserialize_default!(deserialize_hashmap_string_string, HashMap<String, String>)
deserialize_default!(deserialize_hashmap_string_bool, HashMap<String, bool>); deserialize_default!(deserialize_hashmap_string_bool, HashMap<String, bool>);
deserialize_default!(deserialize_hashmap_resolutions, HashMap<String, Resolution>); deserialize_default!(deserialize_hashmap_resolutions, HashMap<String, Resolution>);
#[inline]
fn get_or(
a: &RwLock<HashMap<String, String>>,
b: &HashMap<String, String>,
c: &RwLock<HashMap<String, String>>,
k: &str,
) -> Option<String> {
a.read()
.unwrap()
.get(k)
.or(b.get(k))
.or(c.read().unwrap().get(k))
.cloned()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -1467,6 +1467,102 @@ impl ClipboardContext {
} }
} }
pub fn load_custom_client() {
let Ok(cmd) = std::env::current_exe() else {
return;
};
let Some(path) = cmd.parent().map(|x| x.join("custom.txt")) else {
return;
};
if path.is_file() {
let Ok(data) = std::fs::read_to_string(&path) else {
log::error!("Failed to read custom client config");
return;
};
read_custom_client(&data);
}
}
pub fn read_custom_client(config: &str) {
let Ok(data) = decode64(config) else {
log::error!("Failed to decode custom client config");
return;
};
const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";
let Some(pk) = get_rs_pk(KEY) else {
log::error!("Failed to parse public key of custom client");
return;
};
let Ok(data) = sign::verify(&data, &pk) else {
log::error!("Failed to dec custom client config");
return;
};
let Ok(mut data) =
serde_json::from_slice::<std::collections::HashMap<String, serde_json::Value>>(&data)
else {
log::error!("Failed to parse custom client config");
return;
};
if let Some(default_settings) = data.remove("default_settings") {
if let Some(default_settings) = default_settings.as_object() {
for (k, v) in default_settings {
let Some(v) = v.as_str() else {
continue;
};
if k.starts_with("$$") {
config::DEFAULT_DISPLAY_SETTINGS
.write()
.unwrap()
.insert(k.clone(), v[2..].to_owned());
} else if k.starts_with("$") {
config::DEFAULT_LOCAL_SETTINGS
.write()
.unwrap()
.insert(k.clone(), v[1..].to_owned());
} else {
config::DEFAULT_SETTINGS
.write()
.unwrap()
.insert(k.clone(), v.to_owned());
}
}
}
}
if let Some(overwrite_settings) = data.remove("overwrite_settings") {
if let Some(overwrite_settings) = overwrite_settings.as_object() {
for (k, v) in overwrite_settings {
let Some(v) = v.as_str() else {
continue;
};
if k.starts_with("$$") {
config::OVERWRITE_DISPLAY_SETTINGS
.write()
.unwrap()
.insert(k.clone(), v[2..].to_owned());
} else if k.starts_with("$") {
config::OVERWRITE_LOCAL_SETTINGS
.write()
.unwrap()
.insert(k.clone(), v[1..].to_owned());
} else {
config::OVERWRITE_SETTINGS
.write()
.unwrap()
.insert(k.clone(), v.to_owned());
}
}
}
}
for (k, v) in data {
if let Some(v) = v.as_str() {
config::HARD_SETTINGS
.write()
.unwrap()
.insert(k, v.to_owned());
};
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -38,6 +38,7 @@ fn is_empty_uni_link(arg: &str) -> bool {
/// If it returns [`Some`], then the process will continue, and flutter gui will be started. /// If it returns [`Some`], then the process will continue, and flutter gui will be started.
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
pub fn core_main() -> Option<Vec<String>> { pub fn core_main() -> Option<Vec<String>> {
crate::load_custom_client();
#[cfg(windows)] #[cfg(windows)]
crate::platform::windows::bootstrap(); crate::platform::windows::bootstrap();
let mut args = Vec::new(); let mut args = Vec::new();

View File

@ -1814,7 +1814,7 @@ pub fn main_support_remove_wallpaper() -> bool {
} }
pub fn is_qs() -> SyncReturn<bool> { pub fn is_qs() -> SyncReturn<bool> {
SyncReturn(false) SyncReturn(get_hard_option("connection-type") == "incoming");
} }
/// Send a url scheme throught the ipc. /// Send a url scheme throught the ipc.
@ -2052,6 +2052,10 @@ pub fn main_has_valid_2fa_sync() -> SyncReturn<bool> {
SyncReturn(has_valid_2fa()) SyncReturn(has_valid_2fa())
} }
pub fn main_get_hard_option(key: String) -> SyncReturn<String> {
SyncReturn(get_hard_option(key))
}
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
pub mod server_side { pub mod server_side {
use hbb_common::{config, log}; use hbb_common::{config, log};

View File

@ -3,8 +3,9 @@ use hbb_common::password_security;
use hbb_common::{ use hbb_common::{
allow_err, allow_err,
bytes::Bytes, bytes::Bytes,
config::{self, Config, LocalConfig, PeerConfig}, config::{
config::{CONNECT_TIMEOUT, RENDEZVOUS_PORT}, self, Config, LocalConfig, PeerConfig, CONNECT_TIMEOUT, HARD_SETTINGS, RENDEZVOUS_PORT,
},
directories_next, directories_next,
futures::future::join_all, futures::future::join_all,
log, log,
@ -171,6 +172,16 @@ pub fn get_local_option(key: String) -> String {
LocalConfig::get_option(&key) LocalConfig::get_option(&key)
} }
#[inline]
pub fn get_hard_option(key: String) -> String {
config::HARD_SETTINGS
.read()
.unwrap()
.get(&key)
.cloned()
.unwrap_or_default()
}
#[inline] #[inline]
pub fn set_local_option(key: String, value: String) { pub fn set_local_option(key: String, value: String) {
LocalConfig::set_option(key, value); LocalConfig::set_option(key, value);