more on custom client

This commit is contained in:
rustdesk 2024-03-12 21:47:29 +08:00
parent f644053811
commit fc875f7ad6
13 changed files with 159 additions and 47 deletions

View File

@ -1522,7 +1522,7 @@ class LastWindowPosition {
} }
String get windowFramePrefix => String get windowFramePrefix =>
bind.isQs() ? "${kWindowPrefix}qs_" : kWindowPrefix; bind.isIncomingOnly() ? "${kWindowPrefix}qs_" : kWindowPrefix;
/// Save window position and size on exit /// Save window position and size on exit
/// Note that windowId must be provided if it's subwindow /// Note that windowId must be provided if it's subwindow
@ -1793,11 +1793,11 @@ Future<bool> restoreWindowPosition(WindowType type,
} }
if (lpos.isMaximized == true) { if (lpos.isMaximized == true) {
await restorePos(); await restorePos();
if (!bind.isQs()) { if (!bind.isIncomingOnly()) {
await windowManager.maximize(); await windowManager.maximize();
} }
} else { } else {
if (!bind.isQs()) { if (!bind.isIncomingOnly()) {
await windowManager.setSize(size); await windowManager.setSize(size);
} }
await restorePos(); await restorePos();

View File

@ -134,7 +134,7 @@ class _OnlineStatusWidgetState extends State<OnlineStatusWidget> {
) )
], ],
)), )),
).paddingOnly(right: bind.isQs() ? 8 : 0); ).paddingOnly(right: bind.isIncomingOnly() ? 8 : 0);
} }
updateStatus() async { updateStatus() async {

View File

@ -58,7 +58,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
super.build(context); super.build(context);
final children = [buildLeftPane(context)]; final children = [buildLeftPane(context)];
if (!bind.isQs()) { if (!bind.isIncomingOnly()) {
children.addAll([ children.addAll([
const VerticalDivider(width: 1), const VerticalDivider(width: 1),
Expanded(child: buildRightPane(context)), Expanded(child: buildRightPane(context)),
@ -79,7 +79,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
future: buildHelpCards(), future: buildHelpCards(),
builder: (_, data) { builder: (_, data) {
if (data.hasData) { if (data.hasData) {
if (bind.isQs()) { if (bind.isIncomingOnly()) {
Future.delayed(Duration(milliseconds: 300), () { Future.delayed(Duration(milliseconds: 300), () {
_updateWindowSize(); _updateWindowSize();
}); });
@ -92,7 +92,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
), ),
buildPluginEntry(), buildPluginEntry(),
]; ];
if (bind.isQs()) { if (bind.isIncomingOnly()) {
children.addAll([ children.addAll([
Divider(), Divider(),
Container( Container(
@ -104,7 +104,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: gFFI.serverModel, value: gFFI.serverModel,
child: Container( child: Container(
width: bind.isQs() ? 280.0 : 200.0, width: bind.isIncomingOnly() ? 280.0 : 200.0,
color: Theme.of(context).colorScheme.background, color: Theme.of(context).colorScheme.background,
child: DesktopScrollWrapper( child: DesktopScrollWrapper(
scrollController: _leftPaneScrollController, scrollController: _leftPaneScrollController,
@ -474,7 +474,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
children: [ children: [
Container( Container(
margin: margin:
EdgeInsets.fromLTRB(0, marginTop, 0, bind.isQs() ? marginTop : 0), EdgeInsets.fromLTRB(0, marginTop, 0, bind.isIncomingOnly() ? marginTop : 0),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
@ -693,7 +693,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
}); });
_uniLinksSubscription = listenUniLinks(); _uniLinksSubscription = listenUniLinks();
if (bind.isQs()) { if (bind.isIncomingOnly()) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_updateWindowSize(); _updateWindowSize();
}); });

View File

@ -112,7 +112,7 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
_TabInfo('Account', Icons.person_outline, Icons.person), _TabInfo('Account', Icons.person_outline, Icons.person),
_TabInfo('About', Icons.info_outline, Icons.info) _TabInfo('About', Icons.info_outline, Icons.info)
]; ];
if (!bind.isQs()) { if (!bind.isIncomingOnly()) {
settingTabs.insert( settingTabs.insert(
3, 3,
_TabInfo('Display', Icons.desktop_windows_outlined, _TabInfo('Display', Icons.desktop_windows_outlined,
@ -133,7 +133,7 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
_Account(), _Account(),
_About(), _About(),
]; ];
if (!bind.isQs()) { if (!bind.isIncomingOnly()) {
children.insert(3, _Display()); children.insert(3, _Display());
if (bind.pluginFeatureIsEnabled()) { if (bind.pluginFeatureIsEnabled()) {
children.insert(4, _Plugin()); children.insert(4, _Plugin());
@ -325,7 +325,7 @@ class _GeneralState extends State<_General> {
Widget other() { Widget other() {
final children = <Widget>[]; final children = <Widget>[];
if (!bind.isQs()) { if (!bind.isIncomingOnly()) {
children.add(_OptionCheckBox(context, children.add(_OptionCheckBox(context,
'Confirm before closing multiple tabs', 'enable-confirm-closing-tabs', 'Confirm before closing multiple tabs', 'enable-confirm-closing-tabs',
isServer: false)); isServer: false));
@ -334,7 +334,7 @@ class _GeneralState extends State<_General> {
_OptionCheckBox(context, 'Adaptive bitrate', 'enable-abr'), _OptionCheckBox(context, 'Adaptive bitrate', 'enable-abr'),
wallpaper() wallpaper()
]); ]);
if (!bind.isQs()) { if (!bind.isIncomingOnly()) {
children.addAll([ children.addAll([
_OptionCheckBox( _OptionCheckBox(
context, context,

View File

@ -54,7 +54,7 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
page: DesktopHomePage( page: DesktopHomePage(
key: const ValueKey(kTabLabelHomePage), key: const ValueKey(kTabLabelHomePage),
))); )));
if (bind.isQs()) { if (bind.isIncomingOnly()) {
tabController.onSelected = (key) { tabController.onSelected = (key) {
if (key == kTabLabelHomePage) { if (key == kTabLabelHomePage) {
windowManager.setSize(getDesktopQsHomeSize()); windowManager.setSize(getDesktopQsHomeSize());
@ -81,7 +81,7 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
body: DesktopTab( body: DesktopTab(
controller: tabController, controller: tabController,
tail: Offstage( tail: Offstage(
offstage: bind.isQs(), offstage: bind.isIncomingOnly(),
child: ActionIcon( child: ActionIcon(
message: 'Settings', message: 'Settings',
icon: IconFont.menu, icon: IconFont.menu,

View File

@ -165,7 +165,7 @@ class DesktopTabController {
})); }));
} }
}); });
if ((isDesktop && bind.isQs()) || callOnSelected) { if ((isDesktop && bind.isIncomingOnly()) || callOnSelected) {
if (state.value.tabs.length > index) { if (state.value.tabs.length > index) {
final key = state.value.tabs[index].key; final key = state.value.tabs[index].key;
onSelected?.call(key); onSelected?.call(key);

View File

@ -142,7 +142,7 @@ void runMainApp(bool startService) async {
} }
windowManager.setOpacity(1); windowManager.setOpacity(1);
windowManager.setTitle(getWindowName()); windowManager.setTitle(getWindowName());
windowManager.setResizable(!bind.isQs()); windowManager.setResizable(!bind.isIncomingOnly());
}); });
} }

View File

@ -964,7 +964,13 @@ impl Config {
} }
pub fn get_permanent_password() -> String { pub fn get_permanent_password() -> String {
CONFIG.read().unwrap().password.clone() let mut password = CONFIG.read().unwrap().password.clone();
if password.is_empty() {
if let Some(v) = HARD_SETTINGS.read().unwrap().get("password") {
password = v.to_owned();
}
}
password
} }
pub fn set_salt(salt: &str) { pub fn set_salt(salt: &str) {
@ -1857,6 +1863,58 @@ fn get_or(
.cloned() .cloned()
} }
#[inline]
pub fn is_incoming_only() -> bool {
HARD_SETTINGS
.read()
.unwrap()
.get("conn-type")
.map_or(false, |x| x == ("incoming"))
}
#[inline]
pub fn is_outgoing_only() -> bool {
HARD_SETTINGS
.read()
.unwrap()
.get("conn-type")
.map_or(false, |x| x == ("outgoing"))
}
#[inline]
fn is_some_hard_opton(name: &str) -> bool {
HARD_SETTINGS
.read()
.unwrap()
.get(name)
.map_or(false, |x| x == ("Y"))
}
#[inline]
pub fn is_disable_tcp_listen() -> bool {
is_some_hard_opton("disable-tcp-listen")
}
#[inline]
pub fn is_disable_settings() -> bool {
is_some_hard_opton("disable-settings")
}
#[inline]
pub fn is_disable_ab() -> bool {
is_some_hard_opton("disable-ab")
}
#[inline]
pub fn is_disable_account() -> bool {
is_some_hard_opton("disable-account")
}
#[inline]
pub fn is_disable_installation() -> bool {
is_some_hard_opton("disable-installation")
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -1477,6 +1477,11 @@ impl ClipboardContext {
} }
pub fn load_custom_client() { pub fn load_custom_client() {
#[cfg(debug_assertions)]
if let Ok(data) = std::fs::read_to_string("./custom.txt") {
read_custom_client(data.trim());
return;
}
let Ok(cmd) = std::env::current_exe() else { let Ok(cmd) = std::env::current_exe() else {
return; return;
}; };
@ -1488,7 +1493,7 @@ pub fn load_custom_client() {
log::error!("Failed to read custom client config"); log::error!("Failed to read custom client config");
return; return;
}; };
read_custom_client(&data); read_custom_client(&data.trim());
} }
} }
@ -1512,7 +1517,13 @@ pub fn read_custom_client(config: &str) {
log::error!("Failed to parse custom client config"); log::error!("Failed to parse custom client config");
return; return;
}; };
if let Some(default_settings) = data.remove("default_settings") {
if let Some(app_name) = data.remove("app-name") {
if let Some(app_name) = app_name.as_str() {
*config::APP_NAME.write().unwrap() = app_name.to_owned();
}
}
if let Some(default_settings) = data.remove("default-settings") {
if let Some(default_settings) = default_settings.as_object() { if let Some(default_settings) = default_settings.as_object() {
for (k, v) in default_settings { for (k, v) in default_settings {
let Some(v) = v.as_str() else { let Some(v) = v.as_str() else {
@ -1537,7 +1548,7 @@ pub fn read_custom_client(config: &str) {
} }
} }
} }
if let Some(overwrite_settings) = data.remove("overwrite_settings") { if let Some(overwrite_settings) = data.remove("override-settings") {
if let Some(overwrite_settings) = overwrite_settings.as_object() { if let Some(overwrite_settings) = overwrite_settings.as_object() {
for (k, v) in overwrite_settings { for (k, v) in overwrite_settings {
let Some(v) = v.as_str() else { let Some(v) = v.as_str() else {

View File

@ -3,7 +3,7 @@ use crate::client::translate;
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::platform::breakdown_callback; use crate::platform::breakdown_callback;
use hbb_common::log; use hbb_common::{config, log};
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
use hbb_common::platform::register_breakdown_handler; use hbb_common::platform::register_breakdown_handler;
@ -63,7 +63,7 @@ pub fn core_main() -> Option<Vec<String>> {
] ]
.contains(&arg.as_str()) .contains(&arg.as_str())
{ {
if crate::flutter_ffi::is_qs().0 { if config::is_incoming_only() {
return None; return None;
} else { } else {
_is_flutter_invoke_new_connection = true; _is_flutter_invoke_new_connection = true;
@ -96,7 +96,7 @@ pub fn core_main() -> Option<Vec<String>> {
#[cfg(feature = "flutter")] #[cfg(feature = "flutter")]
{ {
let (k, v) = ("LIBGL_ALWAYS_SOFTWARE", "1"); let (k, v) = ("LIBGL_ALWAYS_SOFTWARE", "1");
if !hbb_common::config::Config::get_option("allow-always-software-render").is_empty() { if !config::Config::get_option("allow-always-software-render").is_empty() {
std::env::set_var(k, v); std::env::set_var(k, v);
} else { } else {
std::env::remove_var(k); std::env::remove_var(k);
@ -111,7 +111,7 @@ pub fn core_main() -> Option<Vec<String>> {
return core_main_invoke_new_connection(std::env::args()); return core_main_invoke_new_connection(std::env::args());
} }
let click_setup = cfg!(windows) && args.is_empty() && crate::common::is_setup(&arg_exe); let click_setup = cfg!(windows) && args.is_empty() && crate::common::is_setup(&arg_exe);
if click_setup { if click_setup && !config::is_disable_installation(){
args.push("--install".to_owned()); args.push("--install".to_owned());
flutter_args.push("--install".to_string()); flutter_args.push("--install".to_string());
} }
@ -188,6 +188,9 @@ pub fn core_main() -> Option<Vec<String>> {
} }
return None; return None;
} else if args[0] == "--silent-install" { } else if args[0] == "--silent-install" {
if config::is_disable_installation() {
return None;
}
let res = platform::install_me( let res = platform::install_me(
"desktopicon startmenu", "desktopicon startmenu",
"".to_owned(), "".to_owned(),
@ -202,7 +205,7 @@ pub fn core_main() -> Option<Vec<String>> {
} }
}; };
Toast::new(Toast::POWERSHELL_APP_ID) Toast::new(Toast::POWERSHELL_APP_ID)
.title(&hbb_common::config::APP_NAME.read().unwrap()) .title(&config::APP_NAME.read().unwrap())
.text1(&text) .text1(&text)
.sound(Some(Sound::Default)) .sound(Some(Sound::Default))
.duration(Duration::Short) .duration(Duration::Short)

View File

@ -42,6 +42,8 @@ lazy_static::lazy_static! {
fn initialize(app_dir: &str) { fn initialize(app_dir: &str) {
flutter::async_tasks::start_flutter_async_runner(); flutter::async_tasks::start_flutter_async_runner();
*config::APP_DIR.write().unwrap() = app_dir.to_owned(); *config::APP_DIR.write().unwrap() = app_dir.to_owned();
// core_main's load_custom_client does not work for flutter since it is only applied to its load_library in main.c
crate::load_custom_client();
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
{ {
// flexi_logger can't work when android_logger initialized. // flexi_logger can't work when android_logger initialized.
@ -62,7 +64,12 @@ fn initialize(app_dir: &str) {
#[cfg(target_os = "ios")] #[cfg(target_os = "ios")]
{ {
use hbb_common::env_logger::*; use hbb_common::env_logger::*;
init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "debug")); init_fro_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "debug"));
}
#[cfg(not(any(target_os = "android", target_os = "ios")))]
{
// core_main's init_log does not work for flutter since it is only applied to its load_library in main.c
hbb_common::init_log(false, "flutter_ffi");
} }
} }
@ -1813,8 +1820,29 @@ pub fn main_support_remove_wallpaper() -> bool {
support_remove_wallpaper() support_remove_wallpaper()
} }
pub fn is_qs() -> SyncReturn<bool> { pub fn is_incoming_only() -> SyncReturn<bool> {
SyncReturn(get_hard_option("connection-type".to_owned()) == "incoming") SyncReturn(config::is_incoming_only())
}
pub fn is_outgoing_only() -> SyncReturn<bool> {
SyncReturn(config::is_outgoing_only())
}
pub fn is_disable_settings() -> SyncReturn<bool> {
SyncReturn(config::is_disable_settings())
}
pub fn is_disable_ab() -> SyncReturn<bool> {
SyncReturn(config::is_disable_ab())
}
pub fn is_disable_account() -> SyncReturn<bool> {
SyncReturn(config::is_disable_account())
}
// windows only
pub fn is_disable_installation() -> SyncReturn<bool> {
SyncReturn(config::is_disable_installation())
} }
/// Send a url scheme throught the ipc. /// Send a url scheme throught the ipc.

View File

@ -1205,6 +1205,15 @@ if exist \"{tmp_path}\\{app_name} Tray.lnk\" del /f /q \"{tmp_path}\\{app_name}
Config::set_option("api-server".into(), lic.api); Config::set_option("api-server".into(), lic.api);
} }
let tray_shortcuts = if config::is_outgoing_only() {
"".to_owned()
} else {
format!("
cscript \"{tray_shortcut}\"
copy /Y \"{tmp_path}\\{app_name} Tray.lnk\" \"%PROGRAMDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\\"
")
};
let cmds = format!( let cmds = format!(
" "
{uninstall_str} {uninstall_str}
@ -1227,8 +1236,7 @@ reg add {subkey} /f /v EstimatedSize /t REG_DWORD /d {size}
reg add {subkey} /f /v WindowsInstaller /t REG_DWORD /d 0 reg add {subkey} /f /v WindowsInstaller /t REG_DWORD /d 0
cscript \"{mk_shortcut}\" cscript \"{mk_shortcut}\"
cscript \"{uninstall_shortcut}\" cscript \"{uninstall_shortcut}\"
cscript \"{tray_shortcut}\" {tray_shortcuts}
copy /Y \"{tmp_path}\\{app_name} Tray.lnk\" \"%PROGRAMDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\\"
{shortcuts} {shortcuts}
copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{path}\\\" copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{path}\\\"
{dels} {dels}
@ -1237,19 +1245,11 @@ copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{path}\\\"
{after_install} {after_install}
{sleep} {sleep}
", ",
version=crate::VERSION, version = crate::VERSION,
build_date=crate::BUILD_DATE, build_date = crate::BUILD_DATE,
after_install=get_after_install(&exe), after_install = get_after_install(&exe),
sleep=if debug { sleep = if debug { "timeout 300" } else { "" },
"timeout 300" dels = if debug { "" } else { &dels },
} else {
""
},
dels=if debug {
""
} else {
&dels
},
copy_exe = copy_exe_cmd(&src_exe, &exe, &path)?, copy_exe = copy_exe_cmd(&src_exe, &exe, &path)?,
import_config = get_import_config(&exe), import_config = get_import_config(&exe),
); );
@ -2383,6 +2383,9 @@ oLink.Save
} }
fn get_import_config(exe: &str) -> String { fn get_import_config(exe: &str) -> String {
if config::is_outgoing_only() {
return "".to_string();
}
format!(" format!("
sc stop {app_name} sc stop {app_name}
sc delete {app_name} sc delete {app_name}
@ -2397,6 +2400,9 @@ sc delete {app_name}
} }
fn get_create_service(exe: &str) -> String { fn get_create_service(exe: &str) -> String {
if config::is_outgoing_only() {
return "".to_string();
}
let stop = Config::get_option("stop-service") == "Y"; let stop = Config::get_option("stop-service") == "Y";
if stop { if stop {
format!(" format!("

View File

@ -12,7 +12,7 @@ use uuid::Uuid;
use hbb_common::{ use hbb_common::{
allow_err, allow_err,
anyhow::{self, bail}, anyhow::{self, bail},
config::{Config, CONNECT_TIMEOUT, READ_TIMEOUT, REG_INTERVAL, RENDEZVOUS_PORT}, config::{self, Config, CONNECT_TIMEOUT, READ_TIMEOUT, REG_INTERVAL, RENDEZVOUS_PORT},
futures::future::join_all, futures::future::join_all,
log, log,
protobuf::Message as _, protobuf::Message as _,
@ -61,6 +61,11 @@ impl RendezvousMediator {
} }
pub async fn start_all() { pub async fn start_all() {
if config::is_outgoing_only() {
loop {
sleep(1.).await;
}
}
crate::hbbs_http::sync::start(); crate::hbbs_http::sync::start();
let mut nat_tested = false; let mut nat_tested = false;
check_zombie(); check_zombie();
@ -449,7 +454,7 @@ impl RendezvousMediator {
async fn handle_intranet(&self, fla: FetchLocalAddr, server: ServerPtr) -> ResultType<()> { async fn handle_intranet(&self, fla: FetchLocalAddr, server: ServerPtr) -> ResultType<()> {
let relay_server = self.get_relay_server(fla.relay_server); let relay_server = self.get_relay_server(fla.relay_server);
if !is_ipv4(&self.addr) { if !is_ipv4(&self.addr) || config::is_disable_tcp_listen() {
// nat64, go relay directly, because current hbbs will crash if demangle ipv6 address // nat64, go relay directly, because current hbbs will crash if demangle ipv6 address
let uuid = Uuid::new_v4().to_string(); let uuid = Uuid::new_v4().to_string();
return self return self
@ -488,6 +493,7 @@ impl RendezvousMediator {
let relay_server = self.get_relay_server(ph.relay_server); let relay_server = self.get_relay_server(ph.relay_server);
if ph.nat_type.enum_value() == Ok(NatType::SYMMETRIC) if ph.nat_type.enum_value() == Ok(NatType::SYMMETRIC)
|| Config::get_nat_type() == NatType::SYMMETRIC as i32 || Config::get_nat_type() == NatType::SYMMETRIC as i32
|| config::is_disable_tcp_listen()
{ {
let uuid = Uuid::new_v4().to_string(); let uuid = Uuid::new_v4().to_string();
return self return self