2022-07-18 18:20:00 +08:00
use std ::{
collections ::HashMap ,
process ::Child ,
sync ::{ Arc , Mutex } ,
} ;
2022-08-01 20:42:30 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
use hbb_common ::password_security ;
2022-05-26 18:11:00 +08:00
use hbb_common ::{
allow_err ,
2022-11-10 21:25:12 +08:00
config ::{ self , Config , LocalConfig , PeerConfig } ,
2022-11-10 10:27:13 +08:00
directories_next , log , sleep ,
2022-11-10 21:25:12 +08:00
tokio ::{ self , sync ::mpsc , time } ,
} ;
use hbb_common ::{
config ::{ RENDEZVOUS_PORT , RENDEZVOUS_TIMEOUT } ,
2022-05-26 18:11:00 +08:00
futures ::future ::join_all ,
protobuf ::Message as _ ,
rendezvous_proto ::* ,
} ;
2022-07-18 18:20:00 +08:00
2022-11-09 15:04:24 +08:00
#[ cfg(feature = " flutter " ) ]
use crate ::hbbs_http ::account ;
2022-11-13 18:11:13 +08:00
use crate ::{ common ::SOFTWARE_UPDATE_URL , ipc } ;
2022-05-26 18:11:00 +08:00
type Message = RendezvousMessage ;
2022-11-10 21:25:12 +08:00
pub type Children = Arc < Mutex < ( bool , HashMap < ( String , String ) , Child > ) > > ;
2022-05-26 18:11:00 +08:00
type Status = ( i32 , bool , i64 , String ) ; // (status_num, key_confirmed, mouse_time, id)
lazy_static ::lazy_static! {
2022-11-10 21:25:12 +08:00
static ref UI_STATUS : Arc < Mutex < Status > > = Arc ::new ( Mutex ::new ( ( 0 , false , 0 , " " . to_owned ( ) ) ) ) ;
static ref OPTIONS : Arc < Mutex < HashMap < String , String > > > = Arc ::new ( Mutex ::new ( Config ::get_options ( ) ) ) ;
static ref ASYNC_JOB_STATUS : Arc < Mutex < String > > = Default ::default ( ) ;
static ref TEMPORARY_PASSWD : Arc < Mutex < String > > = Arc ::new ( Mutex ::new ( " " . to_owned ( ) ) ) ;
2022-11-23 09:41:05 +08:00
pub static ref OPTION_SYNCED : Arc < Mutex < bool > > = Default ::default ( ) ;
2022-05-26 18:11:00 +08:00
}
2022-08-03 21:51:35 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
lazy_static ::lazy_static! {
pub static ref SENDER : Mutex < mpsc ::UnboundedSender < ipc ::Data > > = Mutex ::new ( check_connect_status ( true ) ) ;
}
2022-11-10 21:25:12 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " , feature = " flutter " )) ]
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_id ( ) -> String {
2022-08-03 21:51:35 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
return Config ::get_id ( ) ;
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
return ipc ::get_id ( ) ;
2022-05-26 18:11:00 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn goto_install ( ) {
allow_err! ( crate ::run_me ( vec! [ " --install " ] ) ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-10-26 06:40:22 -07:00
pub fn install_me ( _options : String , _path : String , _silent : bool , _debug : bool ) {
2022-05-26 18:11:00 +08:00
#[ cfg(windows) ]
std ::thread ::spawn ( move | | {
2022-07-18 18:20:00 +08:00
allow_err! ( crate ::platform ::windows ::install_me (
2022-10-26 06:40:22 -07:00
& _options , _path , _silent , _debug
2022-07-18 18:20:00 +08:00
) ) ;
2022-05-26 18:11:00 +08:00
std ::process ::exit ( 0 ) ;
} ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn update_me ( _path : String ) {
#[ cfg(target_os = " linux " ) ]
{
std ::process ::Command ::new ( " pkexec " )
. args ( & [ " apt " , " install " , " -f " , & _path ] )
. spawn ( )
. ok ( ) ;
std ::fs ::remove_file ( & _path ) . ok ( ) ;
crate ::run_me ( Vec ::< & str > ::new ( ) ) . ok ( ) ;
}
#[ cfg(windows) ]
{
let mut path = _path ;
if path . is_empty ( ) {
if let Ok ( tmp ) = std ::env ::current_exe ( ) {
path = tmp . to_string_lossy ( ) . to_string ( ) ;
}
}
std ::process ::Command ::new ( path )
. arg ( " --update " )
. spawn ( )
. ok ( ) ;
std ::process ::exit ( 0 ) ;
}
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn run_without_install ( ) {
crate ::run_me ( vec! [ " --noinstall " ] ) . ok ( ) ;
std ::process ::exit ( 0 ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn show_run_without_install ( ) -> bool {
let mut it = std ::env ::args ( ) ;
if let Some ( tmp ) = it . next ( ) {
if crate ::is_setup ( & tmp ) {
return it . next ( ) = = None ;
}
}
false
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_license ( ) -> String {
#[ cfg(windows) ]
if let Some ( lic ) = crate ::platform ::windows ::get_license ( ) {
2022-10-31 14:59:57 +08:00
#[ cfg(feature = " flutter " ) ]
2022-11-10 21:25:12 +08:00
return format! ( " Key: {} \n Host: {} \n Api: {} " , lic . key , lic . host , lic . api ) ;
2022-10-31 14:59:57 +08:00
// default license format is html formed (sciter)
2022-11-10 21:25:12 +08:00
#[ cfg(not(feature = " flutter " )) ]
2022-05-26 18:11:00 +08:00
return format! (
" <br /> Key: {} <br /> Host: {} Api: {} " ,
lic . key , lic . host , lic . api
) ;
}
Default ::default ( )
}
2022-11-10 21:25:12 +08:00
#[ inline ]
2023-02-19 12:52:41 +08:00
#[ cfg(target_os = " windows " ) ]
2022-11-10 21:25:12 +08:00
pub fn get_option_opt ( key : & str ) -> Option < String > {
OPTIONS . lock ( ) . unwrap ( ) . get ( key ) . map ( | x | x . clone ( ) )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_option ( key : String ) -> String {
2022-08-08 17:53:51 +08:00
get_option_ ( & key )
2022-05-26 18:11:00 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
fn get_option_ ( key : & str ) -> String {
let map = OPTIONS . lock ( ) . unwrap ( ) ;
if let Some ( v ) = map . get ( key ) {
v . to_owned ( )
} else {
" " . to_owned ( )
}
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_local_option ( key : String ) -> String {
LocalConfig ::get_option ( & key )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn set_local_option ( key : String , value : String ) {
LocalConfig ::set_option ( key , value ) ;
}
2022-11-10 07:26:09 -08:00
#[ cfg(any(target_os = " android " , target_os = " ios " , feature = " flutter " )) ]
2022-11-10 21:25:12 +08:00
#[ inline ]
pub fn get_local_flutter_config ( key : String ) -> String {
LocalConfig ::get_flutter_config ( & key )
}
2022-11-10 07:26:09 -08:00
#[ cfg(any(target_os = " android " , target_os = " ios " , feature = " flutter " )) ]
2022-11-10 21:25:12 +08:00
#[ inline ]
pub fn set_local_flutter_config ( key : String , value : String ) {
LocalConfig ::set_flutter_config ( key , value ) ;
}
2022-12-29 14:28:15 +08:00
#[ cfg(feature = " flutter " ) ]
2022-12-27 16:45:13 +08:00
#[ inline ]
pub fn get_kb_layout_type ( ) -> String {
LocalConfig ::get_kb_layout_type ( )
}
2022-12-29 14:28:15 +08:00
#[ cfg(feature = " flutter " ) ]
2022-12-27 16:45:13 +08:00
#[ inline ]
pub fn set_kb_layout_type ( kb_layout_type : String ) {
LocalConfig ::set_kb_layout_type ( kb_layout_type ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn peer_has_password ( id : String ) -> bool {
! PeerConfig ::load ( & id ) . password . is_empty ( )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn forget_password ( id : String ) {
let mut c = PeerConfig ::load ( & id ) ;
c . password . clear ( ) ;
c . store ( & id ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_peer_option ( id : String , name : String ) -> String {
let c = PeerConfig ::load ( & id ) ;
c . options . get ( & name ) . unwrap_or ( & " " . to_owned ( ) ) . to_owned ( )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn set_peer_option ( id : String , name : String , value : String ) {
let mut c = PeerConfig ::load ( & id ) ;
if value . is_empty ( ) {
c . options . remove ( & name ) ;
} else {
c . options . insert ( name , value ) ;
}
c . store ( & id ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn using_public_server ( ) -> bool {
2023-01-26 11:25:05 +08:00
option_env! ( " RENDEZVOUS_SERVER " ) . unwrap_or ( " " ) . is_empty ( )
2023-01-18 14:22:41 +08:00
& & crate ::get_custom_rendezvous_server ( get_option_ ( " custom-rendezvous-server " ) ) . is_empty ( )
2022-05-26 18:11:00 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-07-18 18:20:00 +08:00
pub fn get_options ( ) -> String {
2022-05-26 18:11:00 +08:00
let options = OPTIONS . lock ( ) . unwrap ( ) ;
2022-07-18 18:20:00 +08:00
let mut m = serde_json ::Map ::new ( ) ;
2022-05-26 18:11:00 +08:00
for ( k , v ) in options . iter ( ) {
2022-07-18 18:20:00 +08:00
m . insert ( k . into ( ) , v . to_owned ( ) . into ( ) ) ;
2022-05-26 18:11:00 +08:00
}
2022-07-18 18:20:00 +08:00
serde_json ::to_string ( & m ) . unwrap ( )
2022-05-26 18:11:00 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn test_if_valid_server ( host : String ) -> String {
hbb_common ::socket_client ::test_if_valid_server ( & host )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-11-10 21:25:12 +08:00
#[ cfg(feature = " flutter " ) ]
2022-11-13 18:11:13 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-05-26 18:11:00 +08:00
pub fn get_sound_inputs ( ) -> Vec < String > {
let mut a = Vec ::new ( ) ;
2022-09-08 21:40:43 +08:00
#[ cfg(not(target_os = " linux " )) ]
2022-05-26 18:11:00 +08:00
{
fn get_sound_inputs_ ( ) -> Vec < String > {
let mut out = Vec ::new ( ) ;
use cpal ::traits ::{ DeviceTrait , HostTrait } ;
let host = cpal ::default_host ( ) ;
if let Ok ( devices ) = host . devices ( ) {
for device in devices {
if device . default_input_config ( ) . is_err ( ) {
continue ;
}
if let Ok ( name ) = device . name ( ) {
out . push ( name ) ;
}
}
}
out
}
let inputs = Arc ::new ( Mutex ::new ( Vec ::new ( ) ) ) ;
let cloned = inputs . clone ( ) ;
// can not call below in UI thread, because conflict with sciter sound com initialization
std ::thread ::spawn ( move | | * cloned . lock ( ) . unwrap ( ) = get_sound_inputs_ ( ) )
. join ( )
. ok ( ) ;
for name in inputs . lock ( ) . unwrap ( ) . drain ( .. ) {
a . push ( name ) ;
}
}
2022-09-13 22:37:16 +08:00
#[ cfg(target_os = " linux " ) ]
2022-05-26 18:11:00 +08:00
{
let inputs : Vec < String > = crate ::platform ::linux ::get_pa_sources ( )
. drain ( .. )
. map ( | x | x . 1 )
. collect ( ) ;
for name in inputs {
a . push ( name ) ;
}
}
a
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn set_options ( m : HashMap < String , String > ) {
2022-08-08 17:53:51 +08:00
* OPTIONS . lock ( ) . unwrap ( ) = m . clone ( ) ;
2022-08-03 21:51:35 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-08-08 17:53:51 +08:00
ipc ::set_options ( m ) . ok ( ) ;
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
Config ::set_options ( m ) ;
2022-05-26 18:11:00 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn set_option ( key : String , value : String ) {
2022-08-08 17:53:51 +08:00
let mut options = OPTIONS . lock ( ) . unwrap ( ) ;
#[ cfg(target_os = " macos " ) ]
if & key = = " stop-service " {
let is_stop = value = = " Y " ;
2023-02-23 20:01:50 +08:00
if is_stop & & crate ::platform ::macos ::uninstall ( true ) {
2022-08-08 17:53:51 +08:00
return ;
2022-08-01 20:42:30 +08:00
}
2022-05-26 18:11:00 +08:00
}
2022-08-08 17:53:51 +08:00
if value . is_empty ( ) {
options . remove ( & key ) ;
} else {
options . insert ( key . clone ( ) , value . clone ( ) ) ;
}
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
ipc ::set_options ( options . clone ( ) ) . ok ( ) ;
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
Config ::set_option ( key , value ) ;
2022-05-26 18:11:00 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn install_path ( ) -> String {
#[ cfg(windows) ]
return crate ::platform ::windows ::get_install_info ( ) . 1 ;
#[ cfg(not(windows)) ]
return " " . to_owned ( ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_socks ( ) -> Vec < String > {
2022-08-03 21:51:35 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
return Vec ::new ( ) ;
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
{
let s = ipc ::get_socks ( ) ;
match s {
None = > Vec ::new ( ) ,
Some ( s ) = > {
let mut v = Vec ::new ( ) ;
v . push ( s . proxy ) ;
v . push ( s . username ) ;
v . push ( s . password ) ;
v
}
2022-05-26 18:11:00 +08:00
}
}
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn set_socks ( proxy : String , username : String , password : String ) {
2022-08-03 21:51:35 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-05-26 18:11:00 +08:00
ipc ::set_socks ( config ::Socks5Server {
proxy ,
username ,
password ,
} )
. ok ( ) ;
}
2022-11-10 21:25:12 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn is_installed ( ) -> bool {
2022-11-10 21:25:12 +08:00
crate ::platform ::is_installed ( )
}
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
#[ inline ]
2022-11-10 10:27:13 +08:00
pub fn is_installed ( ) -> bool {
2022-09-23 16:56:28 +08:00
false
2022-05-26 18:11:00 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn is_rdp_service_open ( ) -> bool {
#[ cfg(windows) ]
return is_installed ( ) & & crate ::platform ::windows ::is_rdp_service_open ( ) ;
#[ cfg(not(windows)) ]
return false ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn is_share_rdp ( ) -> bool {
#[ cfg(windows) ]
return crate ::platform ::windows ::is_share_rdp ( ) ;
#[ cfg(not(windows)) ]
return false ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn set_share_rdp ( _enable : bool ) {
#[ cfg(windows) ]
crate ::platform ::windows ::set_share_rdp ( _enable ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn is_installed_lower_version ( ) -> bool {
#[ cfg(not(windows)) ]
return false ;
#[ cfg(windows) ]
{
let installed_version = crate ::platform ::windows ::get_installed_version ( ) ;
let a = hbb_common ::get_version_number ( crate ::VERSION ) ;
let b = hbb_common ::get_version_number ( & installed_version ) ;
return a > b ;
}
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_mouse_time ( ) -> f64 {
let ui_status = UI_STATUS . lock ( ) . unwrap ( ) ;
let res = ui_status . 2 as f64 ;
return res ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn check_mouse_time ( ) {
2022-09-07 18:57:49 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
{
2022-09-05 20:05:23 +08:00
let sender = SENDER . lock ( ) . unwrap ( ) ;
allow_err! ( sender . send ( ipc ::Data ::MouseMoveTime ( 0 ) ) ) ;
}
2022-05-26 18:11:00 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_connect_status ( ) -> Status {
let ui_statue = UI_STATUS . lock ( ) . unwrap ( ) ;
let res = ui_statue . clone ( ) ;
res
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-08-01 20:42:30 +08:00
pub fn temporary_password ( ) -> String {
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
return password_security ::temporary_password ( ) ;
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
return TEMPORARY_PASSWD . lock ( ) . unwrap ( ) . clone ( ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-08-01 14:33:08 +08:00
pub fn update_temporary_password ( ) {
2022-08-01 20:42:30 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
password_security ::update_temporary_password ( ) ;
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-08-01 14:33:08 +08:00
allow_err! ( ipc ::update_temporary_password ( ) ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-08-01 14:33:08 +08:00
pub fn permanent_password ( ) -> String {
2022-08-01 20:42:30 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
return Config ::get_permanent_password ( ) ;
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
return ipc ::get_permanent_password ( ) ;
2022-08-01 14:33:08 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-08-01 20:42:30 +08:00
pub fn set_permanent_password ( password : String ) {
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
Config ::set_permanent_password ( & password ) ;
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
allow_err! ( ipc ::set_permanent_password ( password ) ) ;
2022-08-01 14:33:08 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_peer ( id : String ) -> PeerConfig {
PeerConfig ::load ( & id )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_fav ( ) -> Vec < String > {
LocalConfig ::get_fav ( )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn store_fav ( fav : Vec < String > ) {
LocalConfig ::set_fav ( fav ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn is_process_trusted ( _prompt : bool ) -> bool {
#[ cfg(target_os = " macos " ) ]
return crate ::platform ::macos ::is_process_trusted ( _prompt ) ;
#[ cfg(not(target_os = " macos " )) ]
return true ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn is_can_screen_recording ( _prompt : bool ) -> bool {
#[ cfg(target_os = " macos " ) ]
return crate ::platform ::macos ::is_can_screen_recording ( _prompt ) ;
#[ cfg(not(target_os = " macos " )) ]
return true ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn is_installed_daemon ( _prompt : bool ) -> bool {
#[ cfg(target_os = " macos " ) ]
return crate ::platform ::macos ::is_installed_daemon ( _prompt ) ;
#[ cfg(not(target_os = " macos " )) ]
return true ;
}
2023-01-06 12:20:26 +08:00
#[ inline ]
2023-01-20 21:03:30 +08:00
#[ cfg(feature = " flutter " ) ]
2023-01-06 12:20:26 +08:00
pub fn is_can_input_monitoring ( _prompt : bool ) -> bool {
#[ cfg(target_os = " macos " ) ]
return crate ::platform ::macos ::is_can_input_monitoring ( _prompt ) ;
#[ cfg(not(target_os = " macos " )) ]
return true ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_error ( ) -> String {
2022-06-27 12:09:27 +08:00
#[ cfg(not(any(feature = " cli " ))) ]
2022-05-26 18:11:00 +08:00
#[ cfg(target_os = " linux " ) ]
{
let dtype = crate ::platform ::linux ::get_display_server ( ) ;
if " wayland " = = dtype {
2022-10-11 20:36:19 -07:00
return crate ::server ::wayland ::common_get_error ( ) ;
2022-05-26 18:11:00 +08:00
}
if dtype ! = " x11 " {
return format! (
" {} {}, {} " ,
2023-02-10 17:38:08 +08:00
crate ::client ::translate ( " Unsupported display server " . to_owned ( ) ) ,
2022-05-26 18:11:00 +08:00
dtype ,
2023-02-10 17:38:08 +08:00
crate ::client ::translate ( " x11 expected " . to_owned ( ) ) ,
2022-05-26 18:11:00 +08:00
) ;
}
}
return " " . to_owned ( ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn is_login_wayland ( ) -> bool {
#[ cfg(target_os = " linux " ) ]
return crate ::platform ::linux ::is_login_wayland ( ) ;
#[ cfg(not(target_os = " linux " )) ]
return false ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn current_is_wayland ( ) -> bool {
#[ cfg(target_os = " linux " ) ]
return crate ::platform ::linux ::current_is_wayland ( ) ;
#[ cfg(not(target_os = " linux " )) ]
return false ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_new_version ( ) -> String {
hbb_common ::get_version_from_url ( & * SOFTWARE_UPDATE_URL . lock ( ) . unwrap ( ) )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_version ( ) -> String {
crate ::VERSION . to_owned ( )
}
2022-11-10 21:25:12 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " , feature = " flutter " )) ]
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_app_name ( ) -> String {
crate ::get_app_name ( )
}
2023-02-10 17:09:31 +08:00
#[ cfg(windows) ]
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn create_shortcut ( _id : String ) {
crate ::platform ::windows ::create_shortcut ( & _id ) . ok ( ) ;
}
2022-11-10 21:25:12 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " , feature = " flutter " )) ]
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn discover ( ) {
std ::thread ::spawn ( move | | {
2022-08-02 13:10:09 +08:00
allow_err! ( crate ::lan ::discover ( ) ) ;
2022-05-26 18:11:00 +08:00
} ) ;
}
2022-12-07 16:30:44 +08:00
#[ cfg(feature = " flutter " ) ]
2022-11-28 18:16:29 +08:00
pub fn peer_to_map ( id : String , p : PeerConfig ) -> HashMap < & 'static str , String > {
HashMap ::< & str , String > ::from_iter ( [
( " id " , id ) ,
( " username " , p . info . username . clone ( ) ) ,
( " hostname " , p . info . hostname . clone ( ) ) ,
( " platform " , p . info . platform . clone ( ) ) ,
(
" alias " ,
p . options . get ( " alias " ) . unwrap_or ( & " " . to_owned ( ) ) . to_owned ( ) ,
) ,
] )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-09-21 21:20:19 +08:00
pub fn get_lan_peers ( ) -> Vec < HashMap < & 'static str , String > > {
2022-08-24 23:22:50 +08:00
config ::LanPeers ::load ( )
2022-08-02 13:10:09 +08:00
. peers
. iter ( )
. map ( | peer | {
2022-09-21 21:20:19 +08:00
HashMap ::< & str , String > ::from_iter ( [
( " id " , peer . id . clone ( ) ) ,
( " username " , peer . username . clone ( ) ) ,
( " hostname " , peer . hostname . clone ( ) ) ,
( " platform " , peer . platform . clone ( ) ) ,
] )
2022-08-02 13:10:09 +08:00
} )
2022-08-24 23:22:50 +08:00
. collect ( )
2022-05-26 18:11:00 +08:00
}
2023-02-24 13:13:51 +08:00
#[ inline ]
pub fn remove_discovered ( id : String ) {
let mut peers = config ::LanPeers ::load ( ) . peers ;
peers . retain ( | x | x . id ! = id ) ;
config ::LanPeers ::store ( & peers ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_uuid ( ) -> String {
2022-08-01 14:33:08 +08:00
base64 ::encode ( hbb_common ::get_uuid ( ) )
2022-05-26 18:11:00 +08:00
}
2022-11-10 21:25:12 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " , feature = " flutter " )) ]
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn change_id ( id : String ) {
* ASYNC_JOB_STATUS . lock ( ) . unwrap ( ) = " " . to_owned ( ) ;
let old_id = get_id ( ) ;
std ::thread ::spawn ( move | | {
2022-12-28 13:52:13 +08:00
* ASYNC_JOB_STATUS . lock ( ) . unwrap ( ) = change_id_shared ( id , old_id ) . to_owned ( ) ;
2022-05-26 18:11:00 +08:00
} ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn post_request ( url : String , body : String , header : String ) {
* ASYNC_JOB_STATUS . lock ( ) . unwrap ( ) = " " . to_owned ( ) ;
std ::thread ::spawn ( move | | {
* ASYNC_JOB_STATUS . lock ( ) . unwrap ( ) = match crate ::post_request_sync ( url , body , & header ) {
Err ( err ) = > err . to_string ( ) ,
Ok ( text ) = > text ,
} ;
} ) ;
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_async_job_status ( ) -> String {
ASYNC_JOB_STATUS . lock ( ) . unwrap ( ) . clone ( )
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-08-13 12:43:35 +08:00
pub fn get_langs ( ) -> String {
2023-03-03 11:36:12 +08:00
use serde_json ::json ;
let mut x : Vec < ( & str , String ) > = crate ::lang ::LANGS
. iter ( )
. map ( | a | ( a . 0 , format! ( " {} - {} " , a . 1 , a . 0 ) ) )
. collect ( ) ;
x . sort_by ( | a , b | a . 0. cmp ( b . 0 ) ) ;
json! ( x ) . to_string ( )
2022-08-13 12:43:35 +08:00
}
2022-09-15 17:31:28 +08:00
#[ inline ]
pub fn default_video_save_directory ( ) -> String {
2022-10-12 16:06:15 +08:00
let appname = crate ::get_app_name ( ) ;
2022-10-25 10:16:11 +09:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
if let Ok ( home ) = config ::APP_HOME_DIR . read ( ) {
let mut path = home . to_owned ( ) ;
path . push_str ( " /RustDesk/ScreenRecord " ) ;
return path ;
}
2022-10-12 16:06:15 +08:00
if let Some ( user ) = directories_next ::UserDirs ::new ( ) {
if let Some ( video_dir ) = user . video_dir ( ) {
return video_dir . join ( appname ) . to_string_lossy ( ) . to_string ( ) ;
}
}
2022-10-25 10:16:11 +09:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-11-13 18:11:13 +08:00
if let Some ( home ) = crate ::platform ::get_active_user_home ( ) {
2022-10-12 16:06:15 +08:00
let name = if cfg! ( target_os = " macos " ) {
" Movies "
} else {
" Videos "
} ;
return home . join ( name ) . join ( appname ) . to_string_lossy ( ) . to_string ( ) ;
}
2022-10-25 10:16:11 +09:00
2022-10-12 16:06:15 +08:00
if let Ok ( exe ) = std ::env ::current_exe ( ) {
if let Some ( dir ) = exe . parent ( ) {
return dir . join ( " videos " ) . to_string_lossy ( ) . to_string ( ) ;
}
}
" " . to_owned ( )
2022-09-15 17:31:28 +08:00
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-05-26 18:11:00 +08:00
pub fn get_api_server ( ) -> String {
crate ::get_api_server (
get_option_ ( " api-server " ) ,
get_option_ ( " custom-rendezvous-server " ) ,
)
}
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-08-15 11:08:42 +08:00
pub fn has_hwcodec ( ) -> bool {
2022-09-16 20:31:01 +08:00
#[ cfg(not(any(feature = " hwcodec " , feature = " mediacodec " ))) ]
2022-08-15 11:08:42 +08:00
return false ;
2022-09-16 20:31:01 +08:00
#[ cfg(any(feature = " hwcodec " , feature = " mediacodec " )) ]
2022-08-15 11:08:42 +08:00
return true ;
}
2022-11-10 21:25:12 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
#[ inline ]
pub fn is_root ( ) -> bool {
crate ::platform ::is_root ( )
}
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
2022-09-27 13:30:49 +08:00
#[ inline ]
pub fn is_root ( ) -> bool {
2022-09-29 13:07:37 +08:00
false
2022-09-27 13:30:49 +08:00
}
2022-11-10 21:25:12 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " , feature = " flutter " )) ]
2022-09-13 22:48:14 +08:00
#[ inline ]
2022-08-19 15:44:19 +08:00
pub fn check_super_user_permission ( ) -> bool {
2022-11-08 16:52:45 +08:00
#[ cfg(feature = " flatpak " ) ]
return true ;
2023-02-25 04:55:37 -08:00
#[ cfg(any(windows, target_os = " linux " , target_os = " macos " )) ]
2022-08-19 15:44:19 +08:00
return crate ::platform ::check_super_user_permission ( ) . unwrap_or ( false ) ;
2023-02-25 04:55:37 -08:00
#[ cfg(not(any(windows, target_os = " linux " , target_os = " macos " ))) ]
return true ;
2022-08-19 15:44:19 +08:00
}
2022-09-05 12:39:11 -04:00
#[ allow(dead_code) ]
2022-11-10 21:25:12 +08:00
pub fn check_zombie ( children : Children ) {
2022-05-26 18:11:00 +08:00
let mut deads = Vec ::new ( ) ;
loop {
2022-11-10 21:25:12 +08:00
let mut lock = children . lock ( ) . unwrap ( ) ;
2022-05-26 18:11:00 +08:00
let mut n = 0 ;
for ( id , c ) in lock . 1. iter_mut ( ) {
if let Ok ( Some ( _ ) ) = c . try_wait ( ) {
deads . push ( id . clone ( ) ) ;
n + = 1 ;
}
}
for ref id in deads . drain ( .. ) {
lock . 1. remove ( id ) ;
}
if n > 0 {
lock . 0 = true ;
}
drop ( lock ) ;
std ::thread ::sleep ( std ::time ::Duration ::from_millis ( 100 ) ) ;
}
}
2022-11-20 15:53:08 +08:00
pub fn start_option_status_sync ( ) {
2022-11-28 20:20:45 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
{
let _sender = SENDER . lock ( ) . unwrap ( ) ;
}
2022-11-20 15:53:08 +08:00
}
// not call directly
fn check_connect_status ( reconnect : bool ) -> mpsc ::UnboundedSender < ipc ::Data > {
2022-05-26 18:11:00 +08:00
let ( tx , rx ) = mpsc ::unbounded_channel ::< ipc ::Data > ( ) ;
std ::thread ::spawn ( move | | check_connect_status_ ( reconnect , rx ) ) ;
tx
}
2022-11-09 15:04:24 +08:00
#[ cfg(feature = " flutter " ) ]
2022-10-22 22:19:14 +08:00
pub fn account_auth ( op : String , id : String , uuid : String ) {
account ::OidcSession ::account_auth ( op , id , uuid ) ;
2022-10-20 23:03:54 +08:00
}
2022-11-09 15:04:24 +08:00
#[ cfg(feature = " flutter " ) ]
2022-10-22 22:19:14 +08:00
pub fn account_auth_cancel ( ) {
account ::OidcSession ::auth_cancel ( ) ;
}
2022-11-09 15:04:24 +08:00
#[ cfg(feature = " flutter " ) ]
2022-10-22 22:19:14 +08:00
pub fn account_auth_result ( ) -> String {
serde_json ::to_string ( & account ::OidcSession ::get_result ( ) ) . unwrap_or_default ( )
2022-10-20 23:03:54 +08:00
}
2023-02-01 19:56:57 +08:00
#[ cfg(feature = " flutter " ) ]
pub fn set_user_default_option ( key : String , value : String ) {
use hbb_common ::config ::UserDefaultConfig ;
UserDefaultConfig ::load ( ) . set ( key , value ) ;
}
#[ cfg(feature = " flutter " ) ]
pub fn get_user_default_option ( key : String ) -> String {
use hbb_common ::config ::UserDefaultConfig ;
UserDefaultConfig ::load ( ) . get ( & key )
}
2023-01-09 02:30:35 -05:00
// notice: avoiding create ipc connection repeatedly,
2022-05-26 18:11:00 +08:00
// because windows named pipe has serious memory leak issue.
#[ tokio::main(flavor = " current_thread " ) ]
2022-11-20 15:53:08 +08:00
async fn check_connect_status_ ( reconnect : bool , rx : mpsc ::UnboundedReceiver < ipc ::Data > ) {
2022-05-26 18:11:00 +08:00
let mut key_confirmed = false ;
let mut rx = rx ;
let mut mouse_time = 0 ;
let mut id = " " . to_owned ( ) ;
loop {
if let Ok ( mut c ) = ipc ::connect ( 1000 , " " ) . await {
let mut timer = time ::interval ( time ::Duration ::from_secs ( 1 ) ) ;
loop {
tokio ::select! {
res = c . next ( ) = > {
match res {
Err ( err ) = > {
log ::error! ( " ipc connection closed: {} " , err ) ;
break ;
}
Ok ( Some ( ipc ::Data ::MouseMoveTime ( v ) ) ) = > {
mouse_time = v ;
UI_STATUS . lock ( ) . unwrap ( ) . 2 = v ;
}
Ok ( Some ( ipc ::Data ::Options ( Some ( v ) ) ) ) = > {
2022-11-23 09:41:05 +08:00
* OPTIONS . lock ( ) . unwrap ( ) = v ;
* OPTION_SYNCED . lock ( ) . unwrap ( ) = true ;
2022-05-26 18:11:00 +08:00
}
Ok ( Some ( ipc ::Data ::Config ( ( name , Some ( value ) ) ) ) ) = > {
if name = = " id " {
id = value ;
2022-08-01 20:42:30 +08:00
} else if name = = " temporary-password " {
* TEMPORARY_PASSWD . lock ( ) . unwrap ( ) = value ;
2022-05-26 18:11:00 +08:00
}
}
Ok ( Some ( ipc ::Data ::OnlineStatus ( Some ( ( mut x , c ) ) ) ) ) = > {
if x > 0 {
x = 1
}
key_confirmed = c ;
* UI_STATUS . lock ( ) . unwrap ( ) = ( x as _ , key_confirmed , mouse_time , id . clone ( ) ) ;
}
_ = > { }
}
}
Some ( data ) = rx . recv ( ) = > {
allow_err! ( c . send ( & data ) . await ) ;
}
_ = timer . tick ( ) = > {
c . send ( & ipc ::Data ::OnlineStatus ( None ) ) . await . ok ( ) ;
c . send ( & ipc ::Data ::Options ( None ) ) . await . ok ( ) ;
c . send ( & ipc ::Data ::Config ( ( " id " . to_owned ( ) , None ) ) ) . await . ok ( ) ;
2022-08-01 20:42:30 +08:00
c . send ( & ipc ::Data ::Config ( ( " temporary-password " . to_owned ( ) , None ) ) ) . await . ok ( ) ;
2022-05-26 18:11:00 +08:00
}
}
}
}
if ! reconnect {
OPTIONS
. lock ( )
. unwrap ( )
. insert ( " ipc-closed " . to_owned ( ) , " Y " . to_owned ( ) ) ;
break ;
}
* UI_STATUS . lock ( ) . unwrap ( ) = ( - 1 , key_confirmed , mouse_time , id . clone ( ) ) ;
sleep ( 1. ) . await ;
}
}
2022-11-23 09:41:05 +08:00
#[ allow(dead_code) ]
pub fn option_synced ( ) -> bool {
OPTION_SYNCED . lock ( ) . unwrap ( ) . clone ( )
}
2022-11-10 21:25:12 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " , feature = " flutter " )) ]
2022-09-07 18:57:49 +08:00
#[ tokio::main(flavor = " current_thread " ) ]
pub ( crate ) async fn send_to_cm ( data : & ipc ::Data ) {
if let Ok ( mut c ) = ipc ::connect ( 1000 , " _cm " ) . await {
c . send ( data ) . await . ok ( ) ;
}
}
2022-05-26 18:11:00 +08:00
const INVALID_FORMAT : & 'static str = " Invalid format " ;
const UNKNOWN_ERROR : & 'static str = " Unknown error " ;
#[ tokio::main(flavor = " current_thread " ) ]
2022-12-28 13:52:13 +08:00
pub async fn change_id_shared ( id : String , old_id : String ) -> & 'static str {
2022-05-26 18:11:00 +08:00
if ! hbb_common ::is_valid_custom_id ( & id ) {
return INVALID_FORMAT ;
}
2022-09-16 21:52:08 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-05-26 18:11:00 +08:00
let uuid = machine_uid ::get ( ) . unwrap_or ( " " . to_owned ( ) ) ;
2022-09-16 21:52:08 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
let uuid = base64 ::encode ( hbb_common ::get_uuid ( ) ) ;
2022-05-26 18:11:00 +08:00
if uuid . is_empty ( ) {
2022-09-16 21:52:08 +08:00
log ::error! ( " Failed to change id, uuid is_empty " ) ;
2022-05-26 18:11:00 +08:00
return UNKNOWN_ERROR ;
}
2022-09-16 21:52:08 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-05-26 18:11:00 +08:00
let rendezvous_servers = crate ::ipc ::get_rendezvous_servers ( 1_000 ) . await ;
2022-09-16 21:52:08 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
let rendezvous_servers = Config ::get_rendezvous_servers ( ) ;
2022-05-26 18:11:00 +08:00
let mut futs = Vec ::new ( ) ;
let err : Arc < Mutex < & str > > = Default ::default ( ) ;
for rendezvous_server in rendezvous_servers {
let err = err . clone ( ) ;
let id = id . to_owned ( ) ;
let uuid = uuid . clone ( ) ;
let old_id = old_id . clone ( ) ;
futs . push ( tokio ::spawn ( async move {
let tmp = check_id ( rendezvous_server , old_id , id , uuid ) . await ;
if ! tmp . is_empty ( ) {
* err . lock ( ) . unwrap ( ) = tmp ;
}
} ) ) ;
}
join_all ( futs ) . await ;
let err = * err . lock ( ) . unwrap ( ) ;
if err . is_empty ( ) {
2022-09-16 21:52:08 +08:00
#[ cfg(not(any(target_os = " android " , target_os = " ios " ))) ]
2022-05-26 18:11:00 +08:00
crate ::ipc ::set_config_async ( " id " , id . to_owned ( ) ) . await . ok ( ) ;
2022-09-16 21:52:08 +08:00
#[ cfg(any(target_os = " android " , target_os = " ios " )) ]
{
Config ::set_key_confirmed ( false ) ;
Config ::set_id ( & id ) ;
}
2022-05-26 18:11:00 +08:00
}
err
}
async fn check_id (
rendezvous_server : String ,
old_id : String ,
id : String ,
uuid : String ,
) -> & 'static str {
2022-12-28 13:52:13 +08:00
if let Ok ( mut socket ) = hbb_common ::socket_client ::connect_tcp (
2022-05-26 18:11:00 +08:00
crate ::check_port ( rendezvous_server , RENDEZVOUS_PORT ) ,
RENDEZVOUS_TIMEOUT ,
)
. await
{
let mut msg_out = Message ::new ( ) ;
msg_out . set_register_pk ( RegisterPk {
old_id ,
id ,
uuid : uuid . into ( ) ,
.. Default ::default ( )
} ) ;
let mut ok = false ;
if socket . send ( & msg_out ) . await . is_ok ( ) {
if let Some ( Ok ( bytes ) ) = socket . next_timeout ( 3_000 ) . await {
if let Ok ( msg_in ) = RendezvousMessage ::parse_from_bytes ( & bytes ) {
match msg_in . union {
2022-08-01 14:33:08 +08:00
Some ( rendezvous_message ::Union ::RegisterPkResponse ( rpr ) ) = > {
2022-05-26 18:11:00 +08:00
match rpr . result . enum_value_or_default ( ) {
register_pk_response ::Result ::OK = > {
ok = true ;
}
register_pk_response ::Result ::ID_EXISTS = > {
return " Not available " ;
}
register_pk_response ::Result ::TOO_FREQUENT = > {
return " Too frequent " ;
}
register_pk_response ::Result ::NOT_SUPPORT = > {
return " server_not_support " ;
}
2022-09-16 21:52:08 +08:00
register_pk_response ::Result ::SERVER_ERROR = > {
return " Server error " ;
}
2022-05-26 18:11:00 +08:00
register_pk_response ::Result ::INVALID_ID_FORMAT = > {
return INVALID_FORMAT ;
}
_ = > { }
}
}
_ = > { }
}
}
}
}
if ! ok {
return UNKNOWN_ERROR ;
}
} else {
return " Failed to connect to rendezvous server " ;
}
" "
}
2023-02-26 11:23:43 +08:00
// if it's relay id, return id processed, otherwise return original id
pub fn handle_relay_id ( id : String ) -> String {
if id . ends_with ( r "\r" ) | | id . ends_with ( r "/r" ) {
id [ 0 .. id . len ( ) - 2 ] . to_string ( )
} else {
id
}
}