new mac service and local config
This commit is contained in:
parent
05ac26e5fe
commit
3566b0ee7a
70
Cargo.lock
generated
70
Cargo.lock
generated
@ -1168,25 +1168,6 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
[[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]]
|
[[package]]
|
||||||
name = "fuchsia-cprng"
|
name = "fuchsia-cprng"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -1805,26 +1786,6 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
@ -2205,18 +2166,6 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"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]]
|
[[package]]
|
||||||
name = "mio-named-pipes"
|
name = "mio-named-pipes"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@ -2368,24 +2317,6 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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]]
|
[[package]]
|
||||||
name = "ntapi"
|
name = "ntapi"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@ -3349,7 +3280,6 @@ dependencies = [
|
|||||||
"mac_address",
|
"mac_address",
|
||||||
"machine-uid",
|
"machine-uid",
|
||||||
"magnum-opus",
|
"magnum-opus",
|
||||||
"notify",
|
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"objc",
|
"objc",
|
||||||
"parity-tokio-ipc",
|
"parity-tokio-ipc",
|
||||||
|
@ -72,7 +72,6 @@ cocoa = "0.24"
|
|||||||
dispatch = "0.2"
|
dispatch = "0.2"
|
||||||
core-foundation = "0.9"
|
core-foundation = "0.9"
|
||||||
core-graphics = "0.22"
|
core-graphics = "0.22"
|
||||||
notify = "4.0.17"
|
|
||||||
include_dir = "0.7.2"
|
include_dir = "0.7.2"
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
psimple = { package = "libpulse-simple-binding", version = "2.25" }
|
psimple = { package = "libpulse-simple-binding", version = "2.25" }
|
||||||
|
@ -22,10 +22,7 @@ const SERIAL: i32 = 1;
|
|||||||
#[cfg(target_os = "macos")] // 128x128 on 160x160 canvas, then shrink to 128, mac looks better with padding
|
#[cfg(target_os = "macos")] // 128x128 on 160x160 canvas, then shrink to 128, mac looks better with padding
|
||||||
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUAAAAAcf8Acf8Acf8Acv8Acf8Acf8Acf8Acf8AcP8Acf8Ab/8AcP8Acf////8AaP/z+f/o8v/k7v/5/v/T5f8AYP/u9v/X6f+hx/+Kuv95pP8Aef/B1/+TwP9xoP8BdP/g6P+Irv9ZmP8Bgf/E3f98q/9sn/+01f+Es/9nm/9Jif8hhv8off/M4P+syP+avP86iP/c7f+xy/9yqf9Om/9hk/9Rjv+60P99tv9fpf88lv8yjf8Tgf8deP+kvP8BiP8NeP8hkP80gP8oj2VLAAAADXRSTlMA7o7qLvnaxZ1FOxYPjH9HWgAABHJJREFUeNrtm+tW4jAQgBfwuu7MtIUWsOUiCCioIIgLiqvr+z/UHq/LJKVkmwTcc/r9E2nzlU4mSTP9lpGRkZGR8VX5cZjfL+yCEXYL+/nDH//U/Pd8DgyTy39Xbv7oIAcWyB0cqbW/sweW2NtRaj8H1sgpGOwUIAH7Bkd7YJW9dXFwAJY5WNP/cmCZQnJvzIN18on5LwfWySXlxEPYAIcad8D6PdiHDbCfIFCADVBIENiFDbCbIACKPPXrZ+cP8E6/0znvP4EymgIEravIRcTxu8HxNSJ60a8W0AYECKrlAN+YwAthCd9wm1Ug6wKzIn5SgRduXfwkqDasCjx0XFzi9PV6zwNcIuhcWBOg+ikySq8C9UD4dEKWBCoOcspvAuLHTo9sCDQiFPHotRM48j8G5gVur1FdAN2uaYEuiz7xFsgEJ2RUoMUakXuBTHHoGxQYOBhHjeUBAefEnMAowFhaLBOKuOemBBbxLRQrH2PBCgMvNCPQGMeevTb9zLrPxz2Mo+QbEaijzPUcOOHMQZkKGRAIPem39+bypREMPTkQW/oCfk866zAkiIFG4yIKRE/aAnfiSd0WrORY6pFdXQEqi9mvAQm0RIOSnoCcZ8vJoz3diCnjRk+g8VP4/fuQDJ2Lxr6WwG0gXs9aTpDzW0vgDBlVUpixR8gYk44AD8FrUKHr8JQJGgIDnoDqoALxmWPQSi9AVVzm8gKUuEPGr/QCvptwJkbSYT/TC4S8C96DGjTj86aHtAI0x2WaBIq0eSYYpRa4EsdWVVwWu9O0Aj6f6dyBMnwEraeOgSYu0wZlauzA47QCbT7DgAQSE+hZWoEBF/BBmWOewNMK3BsSqKUW4MGcWqCSVmDkbvkXGKQOwg6PAUO9oL3xXhA20yaiCjuwYygRVQlUOTWTCf2SuNJTxeFjgaHByGuAIvd8ItdPLTDhS7IuqEE1YSKVOgbayLhSFQhMzYh8hwfBs1r7c505YVIQYEdNoKwxK06MJiyrpUFHiF0NAfCQUVHoiRclIXJIR6C2fqG37pBHvcWpgwzvAtYwkR5UGV2e42UISdBJETl3mg8ouo54Rcnti1/vaT+iuUQBt500Cgo4U10BeHSkk57FB0JjWkKRMWgLUA0lLodtImAQdaMiiri3+gIAPZQoutHNsgKF1aaDMhMyIdBf8Th+Bh8MTjGWCpl5Wv43tDmnF+IUVMrcZgRoiAxhtrloYizNkZaAnF5leglbNhj0wYCAbCDvGb0mP4nib7O7ZlcYQ2m1gPtIZgVgGNNMeaVAaWR+57TrqgtUnm3sHQ+kYeE6fufUubG1ez50FXbPnWgBlgSABmN3TTcsRl2yWkHRrwbiunvk/W2+Mg1hPZplPDeXRbZzStFH15s1QIVd3UImP5z/bHpeeQLvRJ7XLFUffQIlCvqlXETQbgN9/rlYABGosv+Vi9m2Xs639YLGrZd0br+odetlvdsvbN56abfd4vbCzv9Q3v/ygoOV21A4OPpfXvH4Ai+5ZGRkZGRkbJA/t/I0QMzoMiEAAAAASUVORK5CYII=
|
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUAAAAAcf8Acf8Acf8Acv8Acf8Acf8Acf8Acf8AcP8Acf8Ab/8AcP8Acf////8AaP/z+f/o8v/k7v/5/v/T5f8AYP/u9v/X6f+hx/+Kuv95pP8Aef/B1/+TwP9xoP8BdP/g6P+Irv9ZmP8Bgf/E3f98q/9sn/+01f+Es/9nm/9Jif8hhv8off/M4P+syP+avP86iP/c7f+xy/9yqf9Om/9hk/9Rjv+60P99tv9fpf88lv8yjf8Tgf8deP+kvP8BiP8NeP8hkP80gP8oj2VLAAAADXRSTlMA7o7qLvnaxZ1FOxYPjH9HWgAABHJJREFUeNrtm+tW4jAQgBfwuu7MtIUWsOUiCCioIIgLiqvr+z/UHq/LJKVkmwTcc/r9E2nzlU4mSTP9lpGRkZGR8VX5cZjfL+yCEXYL+/nDH//U/Pd8DgyTy39Xbv7oIAcWyB0cqbW/sweW2NtRaj8H1sgpGOwUIAH7Bkd7YJW9dXFwAJY5WNP/cmCZQnJvzIN18on5LwfWySXlxEPYAIcad8D6PdiHDbCfIFCADVBIENiFDbCbIACKPPXrZ+cP8E6/0znvP4EymgIEravIRcTxu8HxNSJ60a8W0AYECKrlAN+YwAthCd9wm1Ug6wKzIn5SgRduXfwkqDasCjx0XFzi9PV6zwNcIuhcWBOg+ikySq8C9UD4dEKWBCoOcspvAuLHTo9sCDQiFPHotRM48j8G5gVur1FdAN2uaYEuiz7xFsgEJ2RUoMUakXuBTHHoGxQYOBhHjeUBAefEnMAowFhaLBOKuOemBBbxLRQrH2PBCgMvNCPQGMeevTb9zLrPxz2Mo+QbEaijzPUcOOHMQZkKGRAIPem39+bypREMPTkQW/oCfk866zAkiIFG4yIKRE/aAnfiSd0WrORY6pFdXQEqi9mvAQm0RIOSnoCcZ8vJoz3diCnjRk+g8VP4/fuQDJ2Lxr6WwG0gXs9aTpDzW0vgDBlVUpixR8gYk44AD8FrUKHr8JQJGgIDnoDqoALxmWPQSi9AVVzm8gKUuEPGr/QCvptwJkbSYT/TC4S8C96DGjTj86aHtAI0x2WaBIq0eSYYpRa4EsdWVVwWu9O0Aj6f6dyBMnwEraeOgSYu0wZlauzA47QCbT7DgAQSE+hZWoEBF/BBmWOewNMK3BsSqKUW4MGcWqCSVmDkbvkXGKQOwg6PAUO9oL3xXhA20yaiCjuwYygRVQlUOTWTCf2SuNJTxeFjgaHByGuAIvd8ItdPLTDhS7IuqEE1YSKVOgbayLhSFQhMzYh8hwfBs1r7c505YVIQYEdNoKwxK06MJiyrpUFHiF0NAfCQUVHoiRclIXJIR6C2fqG37pBHvcWpgwzvAtYwkR5UGV2e42UISdBJETl3mg8ouo54Rcnti1/vaT+iuUQBt500Cgo4U10BeHSkk57FB0JjWkKRMWgLUA0lLodtImAQdaMiiri3+gIAPZQoutHNsgKF1aaDMhMyIdBf8Th+Bh8MTjGWCpl5Wv43tDmnF+IUVMrcZgRoiAxhtrloYizNkZaAnF5leglbNhj0wYCAbCDvGb0mP4nib7O7ZlcYQ2m1gPtIZgVgGNNMeaVAaWR+57TrqgtUnm3sHQ+kYeE6fufUubG1ez50FXbPnWgBlgSABmN3TTcsRl2yWkHRrwbiunvk/W2+Mg1hPZplPDeXRbZzStFH15s1QIVd3UImP5z/bHpeeQLvRJ7XLFUffQIlCvqlXETQbgN9/rlYABGosv+Vi9m2Xs639YLGrZd0br+odetlvdsvbN56abfd4vbCzv9Q3v/ygoOV21A4OPpfXvH4Ai+5ZGRkZGRkbJA/t/I0QMzoMiEAAAAASUVORK5CYII=
|
||||||
";
|
";
|
||||||
#[cfg(windows)] // windows, 32x32, bigger very ugly after shrink
|
#[cfg(not(target_os = "macos"))] // 128x128 no padding
|
||||||
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAolBMVEUAAAAAcf8Acf8Acf8AcP8Acf8Acf8Acf8AcP8Acf/////9/v/7/f+gyv9wr/8Ld/8GdP/A3P+nzv+Qwf9mqv8lhv8UfP+Kvv88k/8zjv/x+P/Y6f/U5//J4f/F3/+x1P+pz/+izP+Cuv9Zov9Qnv9FmP8gg//f7f+42P96tv9fpv8ui//1+f/q8//o8v/Q5f+ax/+Zxv+VxP+Fu/9rrf8rif+x1o3FAAAACXRSTlMAv/RPTPKHioRsIqhAAAABNklEQVQ4y4WT6XaCQAyFB7S2GUD2RaxSKGDV7sv7v1on4djEluL9Ncn5biaZk1FKzSwbRmVbM2V0DRNaGD9Maq6sacBS9jRwpUTw1Ww7SEOvkwQDaeVofQeJ1nrXjgD3pTaqCDCg/xs4OBrlwUGTHvxzoHAx69Y9+Hk5oGdAsCNXSoHfEN1JYEme4KcfvO9WAmtMBNx6jIaCgSPGLbAyvKRhAEcrAxAKTSZiACu+gNSbyWwZeKdQKj91yRXWIOWZTMgATun6EtjgczNQaKMEWD0+xJ6B4AnvECVqdKwYoJ50hIPyw25AANkzpsLB00cYOIUEoHU0uVaQVcMxBwlgVZJ3Orz+3ahH6gP2tBgfYzsZmdo1fGIzRx5Irn2WxKaHeJnKtb/4cS5/PbWACd0oo/n/39/4vwGFYSxtSYV4OAAAAABJRU5ErkJggg==
|
|
||||||
";
|
|
||||||
#[cfg(target_os = "linux")] // 128x128 no padding
|
|
||||||
pub const ICON: &str = "data:image/png;base64,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
|
pub const ICON: &str = "data:image/png;base64,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
|
||||||
";
|
";
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
@ -36,6 +33,7 @@ type Size = (i32, i32, i32, i32);
|
|||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load()));
|
static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load()));
|
||||||
static ref CONFIG2: Arc<RwLock<Config2>> = Arc::new(RwLock::new(Config2::load()));
|
static ref CONFIG2: Arc<RwLock<Config2>> = Arc::new(RwLock::new(Config2::load()));
|
||||||
|
static ref LOCAL_CONFIG: Arc<RwLock<LocalConfig>> = Arc::new(RwLock::new(LocalConfig::load()));
|
||||||
pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default();
|
pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default();
|
||||||
}
|
}
|
||||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
@ -61,7 +59,7 @@ pub enum NetworkType {
|
|||||||
ProxySocks,
|
ProxySocks,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
id: String,
|
id: String,
|
||||||
@ -88,12 +86,8 @@ pub struct Socks5Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// more variable configs
|
// more variable configs
|
||||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
pub struct Config2 {
|
pub struct Config2 {
|
||||||
#[serde(default)]
|
|
||||||
remote_id: String, // latest used one
|
|
||||||
#[serde(default)]
|
|
||||||
size: Size,
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
rendezvous_server: String,
|
rendezvous_server: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -193,14 +187,23 @@ impl Config2 {
|
|||||||
Config::load_::<Config2>("2")
|
Config::load_::<Config2>("2")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload(&mut self) {
|
pub fn file() -> PathBuf {
|
||||||
let new_config = Config2::load();
|
Config::file_("2")
|
||||||
*self = new_config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store(&self) {
|
fn store(&self) {
|
||||||
Config::store_(self, "2");
|
Config::store_(self, "2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get() -> Config2 {
|
||||||
|
return CONFIG2.read().unwrap().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(cfg: Config2) {
|
||||||
|
let mut lock = CONFIG2.write().unwrap();
|
||||||
|
*lock = cfg;
|
||||||
|
lock.store();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@ -222,11 +225,6 @@ impl Config {
|
|||||||
cfg
|
cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload(&mut self) {
|
|
||||||
let new_config = Config::load();
|
|
||||||
*self = new_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn store_<T: serde::Serialize>(config: &T, suffix: &str) {
|
fn store_<T: serde::Serialize>(config: &T, suffix: &str) {
|
||||||
let file = Self::file_(suffix);
|
let file = Self::file_(suffix);
|
||||||
if let Err(err) = confy::store_path(file, config) {
|
if let Err(err) = confy::store_path(file, config) {
|
||||||
@ -623,33 +621,6 @@ impl Config {
|
|||||||
salt
|
salt
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_size() -> Size {
|
|
||||||
CONFIG2.read().unwrap().size
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_size(x: i32, y: i32, w: i32, h: i32) {
|
|
||||||
let mut config = CONFIG2.write().unwrap();
|
|
||||||
let size = (x, y, w, h);
|
|
||||||
if size == config.size || size.2 < 300 || size.3 < 300 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
config.size = size;
|
|
||||||
config.store();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_remote_id(remote_id: &str) {
|
|
||||||
let mut config = CONFIG2.write().unwrap();
|
|
||||||
if remote_id == config.remote_id {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
config.remote_id = remote_id.into();
|
|
||||||
config.store();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_remote_id() -> String {
|
|
||||||
CONFIG2.read().unwrap().remote_id.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_socks(socks: Option<Socks5Server>) {
|
pub fn set_socks(socks: Option<Socks5Server>) {
|
||||||
let mut config = CONFIG2.write().unwrap();
|
let mut config = CONFIG2.write().unwrap();
|
||||||
if config.socks == socks {
|
if config.socks == socks {
|
||||||
@ -670,91 +641,14 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_config_to_user<P: AsRef<Path>>(target_username: String, to_dir: P) -> bool {
|
pub fn get() -> Config {
|
||||||
let config1_root_file_path = Config::file_("");
|
return CONFIG.read().unwrap().clone();
|
||||||
let config1_filename = config1_root_file_path.file_name();
|
|
||||||
|
|
||||||
let config2_root_file_path = Config::file_("2");
|
|
||||||
let config2_filename = config2_root_file_path.file_name();
|
|
||||||
|
|
||||||
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()));
|
|
||||||
|
|
||||||
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()
|
|
||||||
);
|
|
||||||
|
|
||||||
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
|
|
||||||
),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
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<P: AsRef<Path>>(from_file_path: P) -> bool {
|
pub fn set(cfg: Config) {
|
||||||
if let Some(filename) = from_file_path.as_ref().file_name() {
|
let mut lock = CONFIG.write().unwrap();
|
||||||
let to = Config::path(filename);
|
*lock = cfg;
|
||||||
return match std::fs::copy(from_file_path, &to) {
|
lock.store();
|
||||||
Ok(count) => {
|
|
||||||
if count > 0 {
|
|
||||||
return std::process::Command::new("chown")
|
|
||||||
.arg("root")
|
|
||||||
.arg(&to.to_str().unwrap().to_string())
|
|
||||||
.spawn()
|
|
||||||
.is_ok();
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("sync_config_to_root failed: {}", e);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,9 +695,7 @@ impl PeerConfig {
|
|||||||
&& p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml")
|
&& p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml")
|
||||||
})
|
})
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
let t = fs::metadata(p)
|
let t = crate::get_modified_time(&p);
|
||||||
.map(|m| m.modified().unwrap_or(SystemTime::UNIX_EPOCH))
|
|
||||||
.unwrap_or(SystemTime::UNIX_EPOCH);
|
|
||||||
let id = p
|
let id = p
|
||||||
.file_stem()
|
.file_stem()
|
||||||
.map(|p| p.to_str().unwrap_or(""))
|
.map(|p| p.to_str().unwrap_or(""))
|
||||||
@ -826,27 +718,84 @@ impl PeerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
pub struct Fav {
|
pub struct LocalConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub peers: Vec<String>,
|
remote_id: String, // latest used one
|
||||||
|
#[serde(default)]
|
||||||
|
size: Size,
|
||||||
|
#[serde(default)]
|
||||||
|
pub fav: Vec<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
options: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fav {
|
impl LocalConfig {
|
||||||
pub fn load() -> Fav {
|
fn load() -> LocalConfig {
|
||||||
let _ = CONFIG.read().unwrap(); // for lock
|
Config::load_::<LocalConfig>("_local")
|
||||||
match confy::load_path(&Config::file_("_fav")) {
|
}
|
||||||
Ok(fav) => fav,
|
|
||||||
Err(err) => {
|
fn store(&self) {
|
||||||
log::error!("Failed to load fav: {}", err);
|
Config::store_(self, "_local");
|
||||||
Default::default()
|
}
|
||||||
}
|
|
||||||
|
pub fn get_size() -> Size {
|
||||||
|
LOCAL_CONFIG.read().unwrap().size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_size(x: i32, y: i32, w: i32, h: i32) {
|
||||||
|
let mut config = LOCAL_CONFIG.write().unwrap();
|
||||||
|
let size = (x, y, w, h);
|
||||||
|
if size == config.size || size.2 < 300 || size.3 < 300 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
config.size = size;
|
||||||
|
config.store();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_remote_id(remote_id: &str) {
|
||||||
|
let mut config = LOCAL_CONFIG.write().unwrap();
|
||||||
|
if remote_id == config.remote_id {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
config.remote_id = remote_id.into();
|
||||||
|
config.store();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_remote_id() -> String {
|
||||||
|
LOCAL_CONFIG.read().unwrap().remote_id.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_fav(fav: Vec<String>) {
|
||||||
|
let mut lock = LOCAL_CONFIG.write().unwrap();
|
||||||
|
if lock.fav == fav {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lock.fav = fav;
|
||||||
|
lock.store();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_fav() -> Vec<String> {
|
||||||
|
LOCAL_CONFIG.read().unwrap().fav.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_option(k: &str) -> String {
|
||||||
|
if let Some(v) = LOCAL_CONFIG.read().unwrap().options.get(k) {
|
||||||
|
v.clone()
|
||||||
|
} else {
|
||||||
|
"".to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store(peers: Vec<String>) {
|
pub fn set_option(k: String, v: String) {
|
||||||
let f = Fav { peers };
|
let mut config = LOCAL_CONFIG.write().unwrap();
|
||||||
if let Err(err) = confy::store_path(Config::file_("_fav"), f) {
|
let v2 = if v.is_empty() { None } else { Some(&v) };
|
||||||
log::error!("Failed to store fav: {}", err);
|
if v2 != config.options.get(&k) {
|
||||||
|
if v2.is_none() {
|
||||||
|
config.options.remove(&k);
|
||||||
|
} else {
|
||||||
|
config.options.insert(k, v);
|
||||||
|
}
|
||||||
|
config.store();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,6 +187,12 @@ pub fn get_version_number(v: &str) -> i64 {
|
|||||||
n
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_modified_time(path: &std::path::Path) -> SystemTime {
|
||||||
|
std::fs::metadata(&path)
|
||||||
|
.map(|m| m.modified().unwrap_or(UNIX_EPOCH))
|
||||||
|
.unwrap_or(UNIX_EPOCH)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -465,3 +465,8 @@ pub fn is_ip(id: &str) -> bool {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.is_match(id)
|
.is_match(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_app_name() -> &'static str {
|
||||||
|
hbb_common::config::APP_NAME
|
||||||
|
}
|
||||||
|
55
src/ipc.rs
55
src/ipc.rs
@ -3,7 +3,7 @@ pub use clipboard::ClipbaordFile;
|
|||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err, bail, bytes,
|
allow_err, bail, bytes,
|
||||||
bytes_codec::BytesCodec,
|
bytes_codec::BytesCodec,
|
||||||
config::{self, Config},
|
config::{self, Config, Config2},
|
||||||
futures::StreamExt as _,
|
futures::StreamExt as _,
|
||||||
futures_util::sink::SinkExt,
|
futures_util::sink::SinkExt,
|
||||||
log, timeout, tokio,
|
log, timeout, tokio,
|
||||||
@ -96,15 +96,8 @@ pub enum Data {
|
|||||||
Socks(Option<config::Socks5Server>),
|
Socks(Option<config::Socks5Server>),
|
||||||
FS(FS),
|
FS(FS),
|
||||||
Test,
|
Test,
|
||||||
SyncConfigToRootReq {
|
SyncConfig(Option<(Config, Config2)>),
|
||||||
from: String,
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
},
|
|
||||||
SyncConfigToRootResp(bool),
|
|
||||||
SyncConfigToUserReq {
|
|
||||||
username: String,
|
|
||||||
to: String,
|
|
||||||
},
|
|
||||||
SyncConfigToUserResp(bool),
|
|
||||||
ClipbaordFile(ClipbaordFile),
|
ClipbaordFile(ClipbaordFile),
|
||||||
ClipboardFileEnabled(bool),
|
ClipboardFileEnabled(bool),
|
||||||
}
|
}
|
||||||
@ -173,6 +166,30 @@ pub async fn new_listener(postfix: &str) -> ResultType<Incoming> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CheckIfRestart(String, Vec<String>, String);
|
||||||
|
|
||||||
|
impl CheckIfRestart {
|
||||||
|
pub fn new() -> CheckIfRestart {
|
||||||
|
CheckIfRestart(
|
||||||
|
Config::get_option("stop-service"),
|
||||||
|
Config::get_rendezvous_servers(),
|
||||||
|
Config::get_option("audio-input"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Drop for CheckIfRestart {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.0 != Config::get_option("stop-service")
|
||||||
|
|| self.1 != Config::get_rendezvous_servers()
|
||||||
|
{
|
||||||
|
RendezvousMediator::restart();
|
||||||
|
}
|
||||||
|
if self.2 != Config::get_option("audio-input") {
|
||||||
|
crate::audio_service::restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle(data: Data, stream: &mut Connection) {
|
async fn handle(data: Data, stream: &mut Connection) {
|
||||||
match data {
|
match data {
|
||||||
Data::SystemInfo(_) => {
|
Data::SystemInfo(_) => {
|
||||||
@ -280,21 +297,15 @@ async fn handle(data: Data, stream: &mut Connection) {
|
|||||||
let t = Config::get_nat_type();
|
let t = Config::get_nat_type();
|
||||||
allow_err!(stream.send(&Data::NatType(Some(t))).await);
|
allow_err!(stream.send(&Data::NatType(Some(t))).await);
|
||||||
}
|
}
|
||||||
Data::SyncConfigToRootReq { from } => {
|
Data::SyncConfig(Some((config, config2))) => {
|
||||||
allow_err!(
|
Config::set(config);
|
||||||
stream
|
Config2::set(config2);
|
||||||
.send(&Data::SyncConfigToRootResp(Config::sync_config_to_root(
|
allow_err!(stream.send(&Data::SyncConfig(None)).await);
|
||||||
from
|
|
||||||
)))
|
|
||||||
.await
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Data::SyncConfigToUserReq { username, to } => {
|
Data::SyncConfig(None) => {
|
||||||
allow_err!(
|
allow_err!(
|
||||||
stream
|
stream
|
||||||
.send(&Data::SyncConfigToUserResp(Config::sync_config_to_user(
|
.send(&Data::SyncConfig(Some((Config::get(), Config2::get()))))
|
||||||
username, to
|
|
||||||
)))
|
|
||||||
.await
|
.await
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use hbb_common::{config::Config, log};
|
use hbb_common::{config::LocalConfig, log};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
mod cn;
|
mod cn;
|
||||||
@ -19,7 +19,7 @@ pub fn translate(name: String) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn translate_locale(name: String, locale: &str) -> String {
|
pub fn translate_locale(name: String, locale: &str) -> String {
|
||||||
let mut lang = Config::get_option("lang");
|
let mut lang = LocalConfig::get_option("lang");
|
||||||
if lang.is_empty() {
|
if lang.is_empty() {
|
||||||
lang = locale
|
lang = locale
|
||||||
.split("-")
|
.split("-")
|
||||||
|
@ -104,11 +104,12 @@ pub fn is_can_screen_recording(prompt: bool) -> bool {
|
|||||||
pub fn is_installed_daemon(prompt: bool) -> bool {
|
pub fn is_installed_daemon(prompt: bool) -> bool {
|
||||||
let daemon = format!("{}_service.plist", crate::get_full_name());
|
let daemon = format!("{}_service.plist", crate::get_full_name());
|
||||||
let agent = format!("{}_server.plist", crate::get_full_name());
|
let agent = format!("{}_server.plist", crate::get_full_name());
|
||||||
|
let agent_plist_file = format!("/Library/LaunchAgents/{}", agent);
|
||||||
if !prompt {
|
if !prompt {
|
||||||
if !std::path::Path::new(&format!("/Library/LaunchDaemons/{}", daemon)).exists() {
|
if !std::path::Path::new(&format!("/Library/LaunchDaemons/{}", daemon)).exists() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if !std::path::Path::new(&format!("/Library/LaunchAgents/{}", agent)).exists() {
|
if !std::path::Path::new(&agent_plist_file).exists() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -123,43 +124,92 @@ pub fn is_installed_daemon(prompt: bool) -> bool {
|
|||||||
let agent_plist = PRIVILEGES_SCRIPTS_DIR.get_file(&agent).unwrap();
|
let agent_plist = PRIVILEGES_SCRIPTS_DIR.get_file(&agent).unwrap();
|
||||||
let agent_plist_body = agent_plist.contents_utf8().unwrap();
|
let agent_plist_body = agent_plist.contents_utf8().unwrap();
|
||||||
|
|
||||||
match std::process::Command::new("osascript")
|
std::thread::spawn(move || {
|
||||||
.arg("-e")
|
match std::process::Command::new("osascript")
|
||||||
.arg(install_script_body)
|
.arg("-e")
|
||||||
.arg(daemon_plist_body)
|
.arg(install_script_body)
|
||||||
.arg(agent_plist_body)
|
.arg(daemon_plist_body)
|
||||||
.arg(&get_active_username())
|
.arg(agent_plist_body)
|
||||||
.spawn()
|
.arg(&get_active_username())
|
||||||
{
|
.output()
|
||||||
Ok(_) => {
|
{
|
||||||
std::process::exit(0);
|
Err(e) => {
|
||||||
|
log::error!("run osascript failed: {}", e);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if std::path::Path::new(&agent_plist_file).exists() {
|
||||||
|
std::process::Command::new("osascript")
|
||||||
|
.arg("-e")
|
||||||
|
.arg(
|
||||||
|
PRIVILEGES_SCRIPTS_DIR
|
||||||
|
.get_file("run.scpt")
|
||||||
|
.unwrap()
|
||||||
|
.contents_utf8()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.arg(&format!(
|
||||||
|
"sleep 0.5; launchctl load -w {}; sleep 0.5; open /Applications/{}.app",
|
||||||
|
agent_plist_file,
|
||||||
|
crate::get_app_name()
|
||||||
|
))
|
||||||
|
.spawn()
|
||||||
|
.ok();
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(100)); // avoid exit crash
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
});
|
||||||
log::error!("run osascript failed: {}", e);
|
false
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn launch(load: bool) {
|
pub fn uninstall() -> bool {
|
||||||
// to-do: do together with win/linux about refactory start/stop service
|
// to-do: do together with win/linux about refactory start/stop service
|
||||||
if !is_installed() || !is_installed_daemon(false) {
|
if !is_installed_daemon(false) {
|
||||||
return;
|
return false;
|
||||||
}
|
|
||||||
let mut script_filename = "load.scpt";
|
|
||||||
if !load {
|
|
||||||
script_filename = "unload.scpt";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let script_file = PRIVILEGES_SCRIPTS_DIR.get_file(script_filename).unwrap();
|
let script_file = PRIVILEGES_SCRIPTS_DIR.get_file("uninstall.scpt").unwrap();
|
||||||
let script_body = script_file.contents_utf8().unwrap();
|
let script_body = script_file.contents_utf8().unwrap();
|
||||||
|
|
||||||
std::process::Command::new("osascript")
|
std::thread::spawn(move || {
|
||||||
.arg("-e")
|
match std::process::Command::new("osascript")
|
||||||
.arg(script_body)
|
.arg("-e")
|
||||||
.arg(&get_active_username())
|
.arg(script_body)
|
||||||
.spawn()
|
.arg(&get_active_username())
|
||||||
.ok();
|
.output()
|
||||||
|
{
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("run osascript failed: {}", e);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let agent = format!("{}_server.plist", crate::get_full_name());
|
||||||
|
let agent_plist_file = format!("/Library/LaunchAgents/{}", agent);
|
||||||
|
if !std::path::Path::new(&agent_plist_file).exists() {
|
||||||
|
crate::ipc::set_option("stop-service", "Y");
|
||||||
|
std::process::Command::new("osascript")
|
||||||
|
.arg("-e")
|
||||||
|
.arg(
|
||||||
|
PRIVILEGES_SCRIPTS_DIR
|
||||||
|
.get_file("run.scpt")
|
||||||
|
.unwrap()
|
||||||
|
.contents_utf8()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.arg(&format!(
|
||||||
|
"sleep 0.5; launchctl remove {}_server; sleep 0.5; open /Applications/{}.app",
|
||||||
|
crate::get_full_name(),
|
||||||
|
crate::get_app_name()
|
||||||
|
))
|
||||||
|
.spawn()
|
||||||
|
.ok();
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(100)); // avoid exit crash
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cursor_pos() -> Option<(i32, i32)> {
|
pub fn get_cursor_pos() -> Option<(i32, i32)> {
|
||||||
@ -352,6 +402,24 @@ pub fn lock_screen() {
|
|||||||
|
|
||||||
pub fn start_os_service() {
|
pub fn start_os_service() {
|
||||||
log::info!("{}", crate::username());
|
log::info!("{}", crate::username());
|
||||||
|
|
||||||
|
std::thread::spawn(move || loop {
|
||||||
|
let exe = std::env::current_exe().unwrap_or_default();
|
||||||
|
let tm0 = hbb_common::get_modified_time(&exe);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(300));
|
||||||
|
if hbb_common::get_modified_time(&exe) != tm0 {
|
||||||
|
log::info!("{:?} updated, will restart", exe);
|
||||||
|
std::process::Command::new("pkill")
|
||||||
|
.args(&["-f", exe.to_str().unwrap_or("")])
|
||||||
|
.output()
|
||||||
|
.ok();
|
||||||
|
std::process::exit(0); // self not killed by above pkill
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if let Err(err) = crate::ipc::start("_service") {
|
if let Err(err) = crate::ipc::start("_service") {
|
||||||
log::error!("Failed to start ipc_service: {}", err);
|
log::error!("Failed to start ipc_service: {}", err);
|
||||||
}
|
}
|
||||||
@ -425,7 +493,7 @@ pub fn is_installed() -> bool {
|
|||||||
if let Ok(p) = std::env::current_exe() {
|
if let Ok(p) = std::env::current_exe() {
|
||||||
return p.to_str().unwrap_or_default().contains(&format!(
|
return p.to_str().unwrap_or_default().contains(&format!(
|
||||||
"/Applications/{}.app",
|
"/Applications/{}.app",
|
||||||
hbb_common::config::APP_NAME
|
crate::get_app_name(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
on run {daemon_file, agent_file, user}
|
on run {daemon_file, agent_file, user}
|
||||||
|
|
||||||
set sh1 to "echo " & quoted form of daemon_file & " > /Library/LaunchDaemons/com.carriez.RustDesk_service.plist && chown root:wheel /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;"
|
set sh1 to "echo " & quoted form of daemon_file & " > /Library/LaunchDaemons/com.carriez.RustDesk_service.plist && chown root:wheel /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;"
|
||||||
|
|
||||||
set sh2 to "echo " & quoted form of agent_file & " > /Library/LaunchAgents/com.carriez.RustDesk_server.plist && chown root:wheel /Library/LaunchAgents/com.carriez.RustDesk_server.plist;"
|
set sh2 to "echo " & quoted form of agent_file & " > /Library/LaunchAgents/com.carriez.RustDesk_server.plist && chown root:wheel /Library/LaunchAgents/com.carriez.RustDesk_server.plist;"
|
||||||
|
|
||||||
set sh3 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
|
set sh3 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
|
||||||
|
|
||||||
set sh4 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk2.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
|
set sh4 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk2.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
|
||||||
|
|
||||||
set sh5 to "launchctl unload -w /Library/LaunchAgents/com.carriez.RustDesk_server.plist; launchctl load -w /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;"
|
set sh5 to "launchctl load -w /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;"
|
||||||
|
|
||||||
set sh6 to "pkill -f rustdesk; launchctl unload -w /Library/LaunchAgents/com.carriez.RustDesk_server.plist; launchctl load -w /Library/LaunchAgents/com.carriez.RustDesk_server.plist; open /Applications/RustDesk.app"
|
|
||||||
|
|
||||||
set sh to sh1 & sh2 & sh3 & sh4 & sh5
|
set sh to sh1 & sh2 & sh3 & sh4 & sh5
|
||||||
|
|
||||||
do shell script sh with prompt "RustDesk want to install daemon and agent" with administrator privileges
|
do shell script sh with prompt "RustDesk want to install daemon and agent" with administrator privileges
|
||||||
do shell script sh6
|
|
||||||
end run
|
end run
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
on run {user}
|
|
||||||
|
|
||||||
set sh1 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
|
|
||||||
|
|
||||||
set sh2 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk2.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
|
|
||||||
|
|
||||||
set sh3 to "launchctl load -w /Library/LaunchDaemons/com.carriez.rustdesk_service.plist;"
|
|
||||||
|
|
||||||
set sh4 to "launchctl load -w /Library/LaunchAgents/com.carriez.rustdesk_server.plist;"
|
|
||||||
|
|
||||||
set sh to sh1 & sh2 & sh3
|
|
||||||
|
|
||||||
do shell script sh with prompt "RustDesk want to launch daemon" with administrator privileges
|
|
||||||
do shell script sh4
|
|
||||||
|
|
||||||
end run
|
|
@ -1,6 +0,0 @@
|
|||||||
set sh1 to "launchctl unload -w /Library/LaunchDaemons/com.carriez.rustdesk_service.plist;"
|
|
||||||
set sh2 to "launchctl unload -w /Library/LaunchAgents/com.carriez.rustdesk_server.plist;"
|
|
||||||
|
|
||||||
do shell script sh1 with prompt "RustDesk want to unload daemon" with administrator privileges
|
|
||||||
do shell script sh2
|
|
||||||
|
|
133
src/server.rs
133
src/server.rs
@ -1,12 +1,10 @@
|
|||||||
#[cfg(target_os = "macos")]
|
|
||||||
use crate::ipc::ConnectionTmpl;
|
|
||||||
use crate::ipc::Data;
|
use crate::ipc::Data;
|
||||||
use connection::{ConnInner, Connection};
|
pub use connection::*;
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
anyhow::{anyhow, Context},
|
anyhow::{anyhow, Context},
|
||||||
bail,
|
bail,
|
||||||
config::{Config, CONNECT_TIMEOUT, RELAY_PORT},
|
config::{Config, Config2, CONNECT_TIMEOUT, RELAY_PORT},
|
||||||
log,
|
log,
|
||||||
message_proto::*,
|
message_proto::*,
|
||||||
protobuf::{Message as _, ProtobufEnum},
|
protobuf::{Message as _, ProtobufEnum},
|
||||||
@ -15,10 +13,6 @@ use hbb_common::{
|
|||||||
sodiumoxide::crypto::{box_, secretbox, sign},
|
sodiumoxide::crypto::{box_, secretbox, sign},
|
||||||
timeout, tokio, ResultType, Stream,
|
timeout, tokio, ResultType, Stream,
|
||||||
};
|
};
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use notify::{watcher, RecursiveMode, Watcher};
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use parity_tokio_ipc::ConnectionClient;
|
|
||||||
use service::{GenericService, Service, ServiceTmpl, Subscriber};
|
use service::{GenericService, Service, ServiceTmpl, Subscriber};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@ -339,101 +333,46 @@ async fn sync_and_watch_config_dir() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match crate::ipc::connect(1000, "_service").await {
|
for i in 1..=6 {
|
||||||
Ok(mut conn) => {
|
sleep(i as f32 * 0.3).await;
|
||||||
match sync_config_to_user(&mut conn).await {
|
match crate::ipc::connect(1000, "_service").await {
|
||||||
Err(e) => log::error!("sync config to user failed:{}", e),
|
Ok(mut conn) => {
|
||||||
_ => {}
|
if conn.send(&Data::SyncConfig(None)).await.is_ok() {
|
||||||
}
|
if let Ok(Some(data)) = conn.next_timeout(1000).await {
|
||||||
|
match data {
|
||||||
tokio::spawn(async move {
|
Data::SyncConfig(Some((config, config2))) => {
|
||||||
log::info!(
|
let _chk = crate::ipc::CheckIfRestart::new();
|
||||||
"watching config dir: {}",
|
Config::set(config);
|
||||||
Config::path("").to_str().unwrap().to_string()
|
Config2::set(config2);
|
||||||
);
|
log::info!("sync config from root");
|
||||||
|
}
|
||||||
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();
|
|
||||||
|
|
||||||
|
let mut cfg0 = (Config::get(), Config2::get());
|
||||||
loop {
|
loop {
|
||||||
let ev = rx.recv();
|
sleep(0.3).await;
|
||||||
match ev {
|
let cfg = (Config::get(), Config2::get());
|
||||||
Ok(event) => match event {
|
if cfg != cfg0 {
|
||||||
notify::DebouncedEvent::Write(path) => {
|
cfg0 = cfg;
|
||||||
log::info!(
|
log::info!("config updated, sync to root");
|
||||||
"config file changed, call ipc_service to sync: {}",
|
match conn.send(&Data::SyncConfig(Some(cfg0.clone()))).await {
|
||||||
path.to_str().unwrap().to_string()
|
Err(e) => {
|
||||||
);
|
log::error!("sync config to root failed: {}", e);
|
||||||
|
|
||||||
match sync_config_to_root(&mut conn, path).await {
|
|
||||||
Err(e) => log::error!("sync config to root failed: {}", e),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
x => {
|
_ => {
|
||||||
log::debug!("another {:?}", x)
|
conn.next_timeout(1000).await.ok();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(e) => println!("watch error: {:?}", e),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
Err(_) => {
|
||||||
Err(_) => {
|
log::info!("#{} try: failed to connect to ipc_service", i);
|
||||||
log::info!("connect ipc_service failed, skip config sync");
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
log::error!("skipped config sync");
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
async fn sync_config_to_user(conn: &mut ConnectionTmpl<ConnectionClient>) -> ResultType<()> {
|
|
||||||
allow_err!(
|
|
||||||
conn.send(&Data::SyncConfigToUserReq {
|
|
||||||
username: crate::username(),
|
|
||||||
to: Config::path("").to_str().unwrap().to_string(),
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(data) = conn.next_timeout(2000).await? {
|
|
||||||
match data {
|
|
||||||
Data::SyncConfigToUserResp(success) => {
|
|
||||||
log::info!("copy and reload config dir success: {:?}", success);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
async fn sync_config_to_root(
|
|
||||||
conn: &mut ConnectionTmpl<ConnectionClient>,
|
|
||||||
from: std::path::PathBuf,
|
|
||||||
) -> ResultType<()> {
|
|
||||||
allow_err!(
|
|
||||||
conn.send(&Data::SyncConfigToRootReq {
|
|
||||||
from: from.to_str().unwrap().to_string()
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
);
|
|
||||||
|
|
||||||
// todo: this code will block outer loop, resolve it later.
|
|
||||||
// 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)
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
36
src/ui.rs
36
src/ui.rs
@ -8,7 +8,7 @@ use crate::common::SOFTWARE_UPDATE_URL;
|
|||||||
use crate::ipc;
|
use crate::ipc;
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
config::{self, Config, Fav, PeerConfig, APP_NAME, ICON},
|
config::{self, Config, LocalConfig, PeerConfig, APP_NAME, ICON},
|
||||||
log, sleep,
|
log, sleep,
|
||||||
tokio::{self, time},
|
tokio::{self, time},
|
||||||
};
|
};
|
||||||
@ -221,11 +221,11 @@ impl UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_remote_id(&mut self) -> String {
|
fn get_remote_id(&mut self) -> String {
|
||||||
Config::get_remote_id()
|
LocalConfig::get_remote_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_remote_id(&mut self, id: String) {
|
fn set_remote_id(&mut self, id: String) {
|
||||||
Config::set_remote_id(&id);
|
LocalConfig::set_remote_id(&id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn goto_install(&mut self) {
|
fn goto_install(&mut self) {
|
||||||
@ -275,7 +275,11 @@ impl UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_local_option(&self, key: String) -> String {
|
fn get_local_option(&self, key: String) -> String {
|
||||||
Config::get_option(&key)
|
LocalConfig::get_option(&key)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_local_option(&self, key: String, value: String) {
|
||||||
|
LocalConfig::set_option(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peer_has_password(&self, id: String) -> bool {
|
fn peer_has_password(&self, id: String) -> bool {
|
||||||
@ -353,6 +357,13 @@ impl UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_option(&self, key: String, value: String) {
|
fn set_option(&self, key: String, value: String) {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
if &key == "stop-service" {
|
||||||
|
let is_stop = value == "Y";
|
||||||
|
if is_stop && crate::platform::macos::uninstall() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
let mut options = self.2.lock().unwrap();
|
let mut options = self.2.lock().unwrap();
|
||||||
if value.is_empty() {
|
if value.is_empty() {
|
||||||
options.remove(&key);
|
options.remove(&key);
|
||||||
@ -360,11 +371,6 @@ impl UI {
|
|||||||
options.insert(key.clone(), value.clone());
|
options.insert(key.clone(), value.clone());
|
||||||
}
|
}
|
||||||
ipc::set_options(options.clone()).ok();
|
ipc::set_options(options.clone()).ok();
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
if &key == "stop-service" {
|
|
||||||
crate::platform::macos::launch(value != "Y");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: ui prompt
|
// TODO: ui prompt
|
||||||
@ -431,11 +437,11 @@ impl UI {
|
|||||||
|
|
||||||
fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) {
|
fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) {
|
||||||
crate::server::input_service::fix_key_down_timeout_at_exit();
|
crate::server::input_service::fix_key_down_timeout_at_exit();
|
||||||
Config::set_size(x, y, w, h);
|
LocalConfig::set_size(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_size(&mut self) -> Value {
|
fn get_size(&mut self) -> Value {
|
||||||
let s = Config::get_size();
|
let s = LocalConfig::get_size();
|
||||||
let mut v = Value::array(0);
|
let mut v = Value::array(0);
|
||||||
v.push(s.0);
|
v.push(s.0);
|
||||||
v.push(s.1);
|
v.push(s.1);
|
||||||
@ -470,7 +476,7 @@ impl UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_fav(&self) -> Value {
|
fn get_fav(&self) -> Value {
|
||||||
Value::from_iter(Fav::load().peers)
|
Value::from_iter(LocalConfig::get_fav())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store_fav(&self, fav: Value) {
|
fn store_fav(&self, fav: Value) {
|
||||||
@ -482,10 +488,11 @@ impl UI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Fav::store(tmp);
|
LocalConfig::set_fav(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_recent_sessions(&mut self) -> Value {
|
fn get_recent_sessions(&mut self) -> Value {
|
||||||
|
// to-do: limit number of recent sessions, and remove old peer file
|
||||||
let peers: Vec<Value> = PeerConfig::peers()
|
let peers: Vec<Value> = PeerConfig::peers()
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|p| Self::get_peer_value(p.0, p.2))
|
.map(|p| Self::get_peer_value(p.0, p.2))
|
||||||
@ -701,6 +708,7 @@ impl sciter::EventHandler for UI {
|
|||||||
fn get_options();
|
fn get_options();
|
||||||
fn get_option(String);
|
fn get_option(String);
|
||||||
fn get_local_option(String);
|
fn get_local_option(String);
|
||||||
|
fn set_local_option(String, String);
|
||||||
fn get_peer_option(String, String);
|
fn get_peer_option(String, String);
|
||||||
fn peer_has_password(String);
|
fn peer_has_password(String);
|
||||||
fn forget_password(String);
|
fn forget_password(String);
|
||||||
@ -830,7 +838,7 @@ fn check_connect_status(
|
|||||||
reconnect: bool,
|
reconnect: bool,
|
||||||
) -> (Arc<Mutex<(i32, bool)>>, Arc<Mutex<HashMap<String, String>>>) {
|
) -> (Arc<Mutex<(i32, bool)>>, Arc<Mutex<HashMap<String, String>>>) {
|
||||||
let status = Arc::new(Mutex::new((0, false)));
|
let status = Arc::new(Mutex::new((0, false)));
|
||||||
let options = Arc::new(Mutex::new(HashMap::new()));
|
let options = Arc::new(Mutex::new(Config::get_options()));
|
||||||
let cloned = status.clone();
|
let cloned = status.clone();
|
||||||
let cloned_options = options.clone();
|
let cloned_options = options.clone();
|
||||||
std::thread::spawn(move || check_connect_status_(reconnect, cloned, cloned_options));
|
std::thread::spawn(move || check_connect_status_(reconnect, cloned, cloned_options));
|
||||||
|
@ -66,7 +66,7 @@ class SessionStyle: Reactor.Component {
|
|||||||
event click $(span.inactive) {
|
event click $(span.inactive) {
|
||||||
var option = getSessionsStyleOption(this.type);
|
var option = getSessionsStyleOption(this.type);
|
||||||
var sessionsStyle = getSessionsStyle(this.type);
|
var sessionsStyle = getSessionsStyle(this.type);
|
||||||
handler.set_option(option, sessionsStyle == "tile" ? "list" : "tile");
|
handler.set_local_option(option, sessionsStyle == "tile" ? "list" : "tile");
|
||||||
app.multipleSessions.update();
|
app.multipleSessions.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,7 +294,7 @@ class MultipleSessions: Reactor.Component {
|
|||||||
if (el.id == "lan") {
|
if (el.id == "lan") {
|
||||||
discover();
|
discover();
|
||||||
}
|
}
|
||||||
handler.set_option('show-sessions-type', el.id || "");
|
handler.set_local_option('show-sessions-type', el.id || "");
|
||||||
this.stupidUpdate();
|
this.stupidUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ view.windowMinSize = (500, 300);
|
|||||||
var app;
|
var app;
|
||||||
var tmp = handler.get_connect_status();
|
var tmp = handler.get_connect_status();
|
||||||
var connect_status = tmp[0];
|
var connect_status = tmp[0];
|
||||||
var service_stopped = false;
|
var service_stopped = handler.get_option("stop-service") == "Y";
|
||||||
var software_update_url = "";
|
var software_update_url = "";
|
||||||
var key_confirmed = tmp[1];
|
var key_confirmed = tmp[1];
|
||||||
var system_error = "";
|
var system_error = "";
|
||||||
@ -368,7 +368,7 @@ class App: Reactor.Component
|
|||||||
{is_win && handler.is_installed() && !software_update_url && handler.is_installed_lower_version() ? <UpgradeMe /> : ""}
|
{is_win && handler.is_installed() && !software_update_url && handler.is_installed_lower_version() ? <UpgradeMe /> : ""}
|
||||||
{is_can_screen_recording ? "": <CanScreenRecording />}
|
{is_can_screen_recording ? "": <CanScreenRecording />}
|
||||||
{is_can_screen_recording && !handler.is_process_trusted(false) ? <TrustMe /> : ""}
|
{is_can_screen_recording && !handler.is_process_trusted(false) ? <TrustMe /> : ""}
|
||||||
{is_can_screen_recording && handler.is_process_trusted(false) && handler.is_installed() && !handler.is_installed_daemon(false) ? <InstallDaemon /> : ""}
|
{!service_stopped && is_can_screen_recording && handler.is_process_trusted(false) && handler.is_installed() && !handler.is_installed_daemon(false) ? <InstallDaemon /> : ""}
|
||||||
{system_error ? <SystemError /> : ""}
|
{system_error ? <SystemError /> : ""}
|
||||||
{!system_error && handler.is_login_wayland() && !handler.current_is_wayland() ? <FixWayland /> : ""}
|
{!system_error && handler.is_login_wayland() && !handler.current_is_wayland() ? <FixWayland /> : ""}
|
||||||
{!system_error && handler.current_is_wayland() ? <ModifyDefaultLogin /> : ""}
|
{!system_error && handler.current_is_wayland() ? <ModifyDefaultLogin /> : ""}
|
||||||
@ -772,8 +772,7 @@ function checkConnectStatus() {
|
|||||||
var tmp = !!handler.get_option("stop-service");
|
var tmp = !!handler.get_option("stop-service");
|
||||||
if (tmp != service_stopped) {
|
if (tmp != service_stopped) {
|
||||||
service_stopped = tmp;
|
service_stopped = tmp;
|
||||||
app.connect_status.update();
|
app.update();
|
||||||
myIdMenu.update();
|
|
||||||
}
|
}
|
||||||
tmp = handler.get_connect_status();
|
tmp = handler.get_connect_status();
|
||||||
if (tmp[0] != connect_status) {
|
if (tmp[0] != connect_status) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user