a333a261fd
Signed-off-by: fufesou <shuanglongchen@yeah.net>
345 lines
12 KiB
Rust
345 lines
12 KiB
Rust
use hbb_common::log;
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
|
use hbb_common::platform::register_breakdown_handler;
|
|
|
|
/// shared by flutter and sciter main function
|
|
///
|
|
/// [Note]
|
|
/// If it returns [`None`], then the process will terminate, and flutter gui will not be started.
|
|
/// If it returns [`Some`], then the process will continue, and flutter gui will be started.
|
|
pub fn core_main() -> Option<Vec<String>> {
|
|
// https://docs.rs/flexi_logger/latest/flexi_logger/error_info/index.html#write
|
|
// though async logger more efficient, but it also causes more problems, disable it for now
|
|
// let mut _async_logger_holder: Option<flexi_logger::LoggerHandle> = None;
|
|
let mut args = Vec::new();
|
|
let mut flutter_args = Vec::new();
|
|
let mut i = 0;
|
|
let mut _is_elevate = false;
|
|
let mut _is_run_as_system = false;
|
|
let mut _is_quick_support = false;
|
|
let mut _is_flutter_connect = false;
|
|
let mut arg_exe = Default::default();
|
|
for arg in std::env::args() {
|
|
// to-do: how to pass to flutter?
|
|
if i == 0 {
|
|
arg_exe = arg;
|
|
} else if i > 0 {
|
|
#[cfg(feature = "flutter")]
|
|
if arg == "--connect" {
|
|
_is_flutter_connect = true;
|
|
}
|
|
if arg == "--elevate" {
|
|
_is_elevate = true;
|
|
} else if arg == "--run-as-system" {
|
|
_is_run_as_system = true;
|
|
} else if arg == "--quick_support" {
|
|
_is_quick_support = true;
|
|
} else {
|
|
args.push(arg);
|
|
}
|
|
}
|
|
i += 1;
|
|
}
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
|
register_breakdown_handler();
|
|
#[cfg(target_os = "linux")]
|
|
#[cfg(feature = "flutter")]
|
|
{
|
|
let (k, v) = ("LIBGL_ALWAYS_SOFTWARE", "true");
|
|
if !hbb_common::config::Config::get_option("allow-always-software-render").is_empty() {
|
|
std::env::set_var(k, v);
|
|
} else {
|
|
std::env::remove_var(k);
|
|
}
|
|
}
|
|
#[cfg(feature = "flutter")]
|
|
if _is_flutter_connect {
|
|
return core_main_invoke_new_connection(std::env::args());
|
|
}
|
|
let click_setup = cfg!(windows) && args.is_empty() && crate::common::is_setup(&arg_exe);
|
|
if click_setup {
|
|
args.push("--install".to_owned());
|
|
flutter_args.push("--install".to_string());
|
|
}
|
|
if args.contains(&"--noinstall".to_string()) {
|
|
args.clear();
|
|
}
|
|
if args.len() > 0 && args[0] == "--version" {
|
|
println!("{}", crate::VERSION);
|
|
return None;
|
|
}
|
|
#[cfg(windows)]
|
|
{
|
|
_is_quick_support |= !crate::platform::is_installed()
|
|
&& args.is_empty()
|
|
&& (arg_exe.to_lowercase().ends_with("qs.exe")
|
|
|| (!click_setup && crate::platform::is_elevated(None).unwrap_or(false)));
|
|
crate::portable_service::client::set_quick_support(_is_quick_support);
|
|
}
|
|
#[cfg(debug_assertions)]
|
|
{
|
|
use hbb_common::env_logger::*;
|
|
init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info"));
|
|
}
|
|
#[cfg(not(debug_assertions))]
|
|
{
|
|
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::*;
|
|
if let Ok(x) = Logger::try_with_env_or_str("debug") {
|
|
// _async_logger_holder =
|
|
x.log_to_file(FileSpec::default().directory(path))
|
|
//.write_mode(WriteMode::Async)
|
|
.format(opt_format)
|
|
.rotate(
|
|
Criterion::Age(Age::Day),
|
|
Naming::Timestamps,
|
|
Cleanup::KeepLogFiles(6),
|
|
)
|
|
.start()
|
|
.ok();
|
|
}
|
|
}
|
|
#[cfg(windows)]
|
|
if !crate::platform::is_installed()
|
|
&& args.is_empty()
|
|
&& _is_quick_support
|
|
&& !_is_elevate
|
|
&& !_is_run_as_system
|
|
{
|
|
use crate::portable_service::client;
|
|
if let Err(e) = client::start_portable_service(client::StartPara::Direct) {
|
|
log::error!("Failed to start portable service:{:?}", e);
|
|
}
|
|
}
|
|
#[cfg(windows)]
|
|
if !crate::platform::is_installed() && (_is_elevate || _is_run_as_system) {
|
|
crate::platform::elevate_or_run_as_system(click_setup, _is_elevate, _is_run_as_system);
|
|
return None;
|
|
}
|
|
if args.is_empty() {
|
|
std::thread::spawn(move || crate::start_server(false));
|
|
} else {
|
|
#[cfg(windows)]
|
|
{
|
|
use crate::platform;
|
|
if args[0] == "--uninstall" {
|
|
if let Err(err) = platform::uninstall_me() {
|
|
log::error!("Failed to uninstall: {}", err);
|
|
}
|
|
return None;
|
|
} else if args[0] == "--after-install" {
|
|
if let Err(err) = platform::run_after_install() {
|
|
log::error!("Failed to after-install: {}", err);
|
|
}
|
|
return None;
|
|
} else if args[0] == "--before-uninstall" {
|
|
if let Err(err) = platform::run_before_uninstall() {
|
|
log::error!("Failed to before-uninstall: {}", err);
|
|
}
|
|
return None;
|
|
} else if args[0] == "--update" {
|
|
hbb_common::allow_err!(platform::update_me());
|
|
return None;
|
|
} else if args[0] == "--reinstall" {
|
|
hbb_common::allow_err!(platform::uninstall_me());
|
|
hbb_common::allow_err!(platform::install_me(
|
|
"desktopicon startmenu",
|
|
"".to_owned(),
|
|
false,
|
|
false,
|
|
));
|
|
return None;
|
|
} else if args[0] == "--silent-install" {
|
|
hbb_common::allow_err!(platform::install_me(
|
|
"desktopicon startmenu",
|
|
"".to_owned(),
|
|
true,
|
|
args.len() > 1,
|
|
));
|
|
return None;
|
|
} else if args[0] == "--extract" {
|
|
#[cfg(feature = "with_rc")]
|
|
hbb_common::allow_err!(crate::rc::extract_resources(&args[1]));
|
|
return None;
|
|
} else if args[0] == "--portable-service" {
|
|
crate::platform::elevate_or_run_as_system(
|
|
click_setup,
|
|
_is_elevate,
|
|
_is_run_as_system,
|
|
);
|
|
return None;
|
|
}
|
|
}
|
|
if args[0] == "--remove" {
|
|
if args.len() == 2 {
|
|
// sleep a while so that process of removed exe exit
|
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
|
std::fs::remove_file(&args[1]).ok();
|
|
return None;
|
|
}
|
|
} else if args[0] == "--tray" {
|
|
crate::tray::start_tray();
|
|
return None;
|
|
} else if args[0] == "--service" {
|
|
log::info!("start --service");
|
|
crate::start_os_service();
|
|
return None;
|
|
} else if args[0] == "--server" {
|
|
log::info!("start --server with user {}", crate::username());
|
|
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
|
{
|
|
crate::start_server(true);
|
|
return None;
|
|
}
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
let handler = std::thread::spawn(move || crate::start_server(true));
|
|
crate::tray::start_tray();
|
|
// prevent server exit when encountering errors from tray
|
|
hbb_common::allow_err!(handler.join());
|
|
}
|
|
} else if args[0] == "--import-config" {
|
|
if args.len() == 2 {
|
|
let filepath;
|
|
let path = std::path::Path::new(&args[1]);
|
|
if !path.is_absolute() {
|
|
let mut cur = std::env::current_dir().unwrap();
|
|
cur.push(path);
|
|
filepath = cur.to_str().unwrap().to_string();
|
|
} else {
|
|
filepath = path.to_str().unwrap().to_string();
|
|
}
|
|
import_config(&filepath);
|
|
}
|
|
return None;
|
|
} else if args[0] == "--password" {
|
|
if args.len() == 2 {
|
|
if crate::platform::is_root() {
|
|
crate::ipc::set_permanent_password(args[1].to_owned()).unwrap();
|
|
} else {
|
|
println!("Administrative privileges required!");
|
|
}
|
|
}
|
|
return None;
|
|
} else if args[0] == "--check-hwcodec-config" {
|
|
#[cfg(feature = "hwcodec")]
|
|
scrap::hwcodec::check_config();
|
|
return None;
|
|
} else if args[0] == "--cm" {
|
|
// call connection manager to establish connections
|
|
// meanwhile, return true to call flutter window to show control panel
|
|
crate::ui_interface::start_option_status_sync();
|
|
}
|
|
}
|
|
//_async_logger_holder.map(|x| x.flush());
|
|
#[cfg(feature = "flutter")]
|
|
return Some(flutter_args);
|
|
#[cfg(not(feature = "flutter"))]
|
|
return Some(args);
|
|
}
|
|
|
|
fn import_config(path: &str) {
|
|
use hbb_common::{config::*, get_exe_time, get_modified_time};
|
|
let path2 = path.replace(".toml", "2.toml");
|
|
let path2 = std::path::Path::new(&path2);
|
|
let path = std::path::Path::new(path);
|
|
log::info!("import config from {:?} and {:?}", path, path2);
|
|
let config: Config = load_path(path.into());
|
|
if config.is_empty() {
|
|
log::info!("Empty source config, skipped");
|
|
return;
|
|
}
|
|
if get_modified_time(&path) > get_modified_time(&Config::file())
|
|
&& get_modified_time(&path) < get_exe_time()
|
|
{
|
|
if store_path(Config::file(), config).is_err() {
|
|
log::info!("config written");
|
|
}
|
|
}
|
|
let config2: Config2 = load_path(path2.into());
|
|
if get_modified_time(&path2) > get_modified_time(&Config2::file()) {
|
|
if store_path(Config2::file(), config2).is_err() {
|
|
log::info!("config2 written");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// invoke a new connection
|
|
///
|
|
/// [Note]
|
|
/// this is for invoke new connection from dbus.
|
|
/// If it returns [`None`], then the process will terminate, and flutter gui will not be started.
|
|
/// If it returns [`Some`], then the process will continue, and flutter gui will be started.
|
|
#[cfg(feature = "flutter")]
|
|
fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option<Vec<String>> {
|
|
args.position(|element| {
|
|
return element == "--connect";
|
|
})?;
|
|
let peer_id = args.next().unwrap_or("".to_string());
|
|
if peer_id.is_empty() {
|
|
eprintln!("please provide a valid peer id");
|
|
return None;
|
|
}
|
|
let mut switch_uuid = None;
|
|
while let Some(item) = args.next() {
|
|
if item == "--switch_uuid" {
|
|
switch_uuid = args.next();
|
|
}
|
|
}
|
|
let mut param_array = vec![];
|
|
if switch_uuid.is_some() {
|
|
let switch_uuid = switch_uuid.map_or("".to_string(), |p| format!("switch_uuid={}", p));
|
|
param_array.push(switch_uuid);
|
|
}
|
|
|
|
let params = param_array.join("&");
|
|
let params_flag = if params.is_empty() { "" } else { "?" };
|
|
#[allow(unused)]
|
|
let uni_links = format!(
|
|
"rustdesk://connection/new/{}{}{}",
|
|
peer_id, params_flag, params
|
|
);
|
|
|
|
#[cfg(target_os = "linux")]
|
|
{
|
|
use crate::dbus::invoke_new_connection;
|
|
|
|
match invoke_new_connection(uni_links) {
|
|
Ok(()) => {
|
|
return None;
|
|
}
|
|
Err(err) => {
|
|
log::error!("{}", err.as_ref());
|
|
// return Some to invoke this new connection by self
|
|
return Some(Vec::new());
|
|
}
|
|
}
|
|
}
|
|
#[cfg(windows)]
|
|
{
|
|
use winapi::um::winuser::WM_USER;
|
|
let res = crate::platform::send_message_to_hnwd(
|
|
"FLUTTER_RUNNER_WIN32_WINDOW",
|
|
"RustDesk",
|
|
(WM_USER + 2) as _, // referred from unilinks desktop pub
|
|
uni_links.as_str(),
|
|
false,
|
|
);
|
|
return if res { None } else { Some(Vec::new()) };
|
|
}
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
return if let Err(_) = crate::ipc::send_url_scheme(uni_links) {
|
|
Some(Vec::new())
|
|
} else {
|
|
None
|
|
};
|
|
}
|
|
}
|