mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-28 23:59:05 +08:00
refactor remote interface
This commit is contained in:
parent
694896abda
commit
bdcb848a75
@ -1651,6 +1651,12 @@ pub trait Interface: Send + Clone + 'static + Sized {
|
||||
fn handle_login_error(&mut self, err: &str) -> bool;
|
||||
fn handle_peer_info(&mut self, pi: PeerInfo);
|
||||
fn set_force_relay(&mut self, direct: bool, received: bool);
|
||||
fn is_file_transfer(&self) -> bool;
|
||||
fn is_port_forward(&self) -> bool;
|
||||
fn is_rdp(&self) -> bool;
|
||||
fn on_error(&self, err: &str) {
|
||||
self.msgbox("error", "Error", err);
|
||||
}
|
||||
fn is_force_relay(&self) -> bool;
|
||||
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream);
|
||||
async fn handle_login_from_ui(&mut self, password: String, remember: bool, peer: &mut Stream);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use hbb_common::{fs, message_proto::*};
|
||||
use hbb_common::{fs, message_proto::*, log};
|
||||
|
||||
use super::{Data, Interface};
|
||||
|
||||
@ -114,4 +114,26 @@ pub trait FileManager: Interface {
|
||||
fn resume_job(&self, id: i32, is_remote: bool) {
|
||||
self.send(Data::ResumeJob((id, is_remote)));
|
||||
}
|
||||
|
||||
fn set_confirm_override_file(
|
||||
&self,
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
need_override: bool,
|
||||
remember: bool,
|
||||
is_upload: bool,
|
||||
) {
|
||||
log::info!(
|
||||
"confirm file transfer, job: {}, need_override: {}",
|
||||
id,
|
||||
need_override
|
||||
);
|
||||
self.send(Data::SetConfirmOverrideFile((
|
||||
id,
|
||||
file_num,
|
||||
need_override,
|
||||
remember,
|
||||
is_upload,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,9 @@ pub(super) const APP_TYPE_MAIN: &str = "main";
|
||||
pub(super) const APP_TYPE_DESKTOP_REMOTE: &str = "remote";
|
||||
pub(super) const APP_TYPE_DESKTOP_FILE_TRANSFER: &str = "file transfer";
|
||||
|
||||
const MILLI1: Duration = Duration::from_millis(1);
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
// static ref SESSION: Arc<RwLock<Option<Session>>> = Default::default();
|
||||
pub static ref SESSIONS: RwLock<HashMap<String,Session>> = Default::default();
|
||||
pub static ref GLOBAL_EVENT_STREAM: RwLock<HashMap<String, StreamSink<String>>> = Default::default(); // rust to dart event channel
|
||||
}
|
||||
@ -48,9 +49,6 @@ lazy_static::lazy_static! {
|
||||
static SERVER_CLIPBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||
static SERVER_KEYBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
// pub fn get_session<'a>(id: &str) -> Option<&'a Session> {
|
||||
// SESSIONS.read().unwrap().get(id)
|
||||
// }
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Session {
|
||||
@ -113,10 +111,6 @@ impl Session {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current session instance.
|
||||
// pub fn get() -> Arc<RwLock<Option<Session>>> {
|
||||
// SESSION.clone()
|
||||
// }
|
||||
|
||||
/// Get the option of the current session.
|
||||
///
|
||||
@ -252,57 +246,6 @@ impl Session {
|
||||
self.send_msg(msg_out);
|
||||
}
|
||||
|
||||
// file trait
|
||||
/// Send file over the current session.
|
||||
// pub fn send_files(
|
||||
// id: i32,
|
||||
// path: String,
|
||||
// to: String,
|
||||
// file_num: i32,
|
||||
// include_hidden: bool,
|
||||
// is_remote: bool,
|
||||
// ) {
|
||||
// if let Some(session) = SESSION.write().unwrap().as_mut() {
|
||||
// session.send_files(id, path, to, file_num, include_hidden, is_remote);
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO into file trait
|
||||
/// Confirm file override.
|
||||
pub fn set_confirm_override_file(
|
||||
&self,
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
need_override: bool,
|
||||
remember: bool,
|
||||
is_upload: bool,
|
||||
) {
|
||||
log::info!(
|
||||
"confirm file transfer, job: {}, need_override: {}",
|
||||
id,
|
||||
need_override
|
||||
);
|
||||
self.send(Data::SetConfirmOverrideFile((
|
||||
id,
|
||||
file_num,
|
||||
need_override,
|
||||
remember,
|
||||
is_upload,
|
||||
)));
|
||||
}
|
||||
|
||||
/// Static method to send message over the current session.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `msg` - The message to send.
|
||||
// #[inline]
|
||||
// pub fn send_msg_static(msg: Message) {
|
||||
// if let Some(session) = SESSION.read().unwrap().as_ref() {
|
||||
// session.send_msg(msg);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Push an event to the event queue.
|
||||
/// An event is stored as json in the event queue.
|
||||
///
|
||||
@ -595,6 +538,18 @@ impl Interface for Session {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_file_transfer(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn is_port_forward(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn is_rdp(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str) {
|
||||
let has_retry = if check_if_retry(msgtype, title, text) {
|
||||
"true"
|
||||
@ -706,7 +661,6 @@ impl Interface for Session {
|
||||
}
|
||||
}
|
||||
|
||||
const MILLI1: Duration = Duration::from_millis(1);
|
||||
|
||||
struct Connection {
|
||||
video_handler: VideoHandler,
|
||||
|
@ -48,6 +48,7 @@ mod port_forward;
|
||||
mod tray;
|
||||
|
||||
mod ui_interface;
|
||||
mod ui_session_interface;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub mod clipboard_file;
|
||||
|
@ -146,7 +146,7 @@ pub fn start(args: &mut [String]) {
|
||||
let args: Vec<String> = iter.map(|x| x.clone()).collect();
|
||||
frame.set_title(&id);
|
||||
frame.register_behavior("native-remote", move || {
|
||||
Box::new(remote::Handler::new(
|
||||
Box::new(remote::SciterSession::new(
|
||||
cmd.clone(),
|
||||
id.clone(),
|
||||
pass.clone(),
|
||||
|
870
src/ui/remote.rs
870
src/ui/remote.rs
File diff suppressed because it is too large
Load Diff
257
src/ui_session_interface.rs
Normal file
257
src/ui_session_interface.rs
Normal file
@ -0,0 +1,257 @@
|
||||
use crate::client::{
|
||||
self, check_if_retry, handle_hash, handle_login_from_ui, handle_test_delay, input_os_password,
|
||||
FileManager, LoginConfigHandler, QualityStatus, load_config,
|
||||
};
|
||||
use crate::{client::Data, client::Interface};
|
||||
use async_trait::async_trait;
|
||||
use hbb_common::config::PeerConfig;
|
||||
use hbb_common::message_proto::{CursorData, Hash, PeerInfo, TestDelay, CursorPosition};
|
||||
use hbb_common::tokio::{
|
||||
self,
|
||||
sync::mpsc,
|
||||
time::{self, Duration, Instant, Interval},
|
||||
};
|
||||
use hbb_common::{get_version_number, log, Stream};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Session<T: InvokeUi> {
|
||||
pub cmd: String,
|
||||
pub id: String,
|
||||
pub password: String,
|
||||
pub args: Vec<String>,
|
||||
pub lc: Arc<RwLock<LoginConfigHandler>>,
|
||||
pub sender: Arc<RwLock<Option<mpsc::UnboundedSender<Data>>>>,
|
||||
pub ui_handler: T,
|
||||
}
|
||||
|
||||
impl<T: InvokeUi> Session<T> {
|
||||
pub fn get_option(&self, k: String) -> String {
|
||||
self.lc.read().unwrap().get_option(&k)
|
||||
}
|
||||
|
||||
pub fn set_option(&self, k: String, v: String) {
|
||||
self.lc.write().unwrap().set_option(k, v);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn load_config(&self) -> PeerConfig {
|
||||
load_config(&self.id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn save_config(&self, config: PeerConfig) {
|
||||
self.lc.write().unwrap().save_config(config);
|
||||
}
|
||||
|
||||
pub fn is_restarting_remote_device(&self) -> bool {
|
||||
self.lc.read().unwrap().restarting_remote_device
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn peer_platform(&self) -> String {
|
||||
self.lc.read().unwrap().info.platform.clone()
|
||||
}
|
||||
|
||||
pub fn get_platform(&mut self, is_remote: bool) -> String {
|
||||
if is_remote {
|
||||
self.peer_platform()
|
||||
} else {
|
||||
whoami::platform().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_path_sep(&mut self, is_remote: bool) -> &'static str {
|
||||
let p = self.get_platform(is_remote);
|
||||
if &p == "Windows" {
|
||||
return "\\";
|
||||
} else {
|
||||
return "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InvokeUi: Send + Sync + Clone + 'static + Sized + Default {
|
||||
fn set_cursor_data(&self, cd: CursorData);
|
||||
fn set_cursor_id(&self, id: String);
|
||||
fn set_cursor_position(&self, cp:CursorPosition);
|
||||
fn set_display(&self, x: i32, y: i32, w: i32, h: i32);
|
||||
fn update_privacy_mode(&self);
|
||||
fn set_permission(&self, name: &str, value: bool);
|
||||
fn update_pi(&self, pi: PeerInfo);
|
||||
fn close_success(&self);
|
||||
fn update_quality_status(&self, qs: QualityStatus);
|
||||
fn set_connection_type(&self,is_secured: bool, direct: bool);
|
||||
fn job_error(&self,id:i32, err:String, file_num:i32);
|
||||
fn job_done(&self,id:i32, file_num:i32);
|
||||
fn clear_all_jobs(&self);
|
||||
fn add_job(&self, id:i32, path:String, to:String, file_num:i32, show_hidden:bool, is_remote:bool);
|
||||
fn update_transfer_list(&self);
|
||||
// fn update_folder_files(&self); // TODO
|
||||
fn confirm_delete_files(&self,id:i32, i:i32, name:String);
|
||||
fn override_file_confirm(&self, id:i32, file_num:i32, to:String, is_upload:bool);
|
||||
fn job_progress(&self, id:i32, file_num:i32, speed:f64, finished_size:f64);
|
||||
fn adapt_size(&self);
|
||||
}
|
||||
|
||||
|
||||
impl<T: InvokeUi> Deref for Session<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.ui_handler
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InvokeUi> DerefMut for Session<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.ui_handler
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InvokeUi> FileManager for Session<T> {}
|
||||
|
||||
#[async_trait]
|
||||
impl<T: InvokeUi> Interface for Session<T> {
|
||||
fn send(&self, data: Data) {
|
||||
if let Some(sender) = self.sender.read().unwrap().as_ref() {
|
||||
sender.send(data).ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn is_file_transfer(&self) -> bool {
|
||||
self.cmd == "--file-transfer"
|
||||
}
|
||||
|
||||
fn is_port_forward(&self) -> bool {
|
||||
self.cmd == "--port-forward" || self.is_rdp()
|
||||
}
|
||||
|
||||
fn is_rdp(&self) -> bool {
|
||||
self.cmd == "--rdp"
|
||||
}
|
||||
|
||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str) {
|
||||
let retry = check_if_retry(msgtype, title, text);
|
||||
// self.call2("msgbox_retry", &make_args!(msgtype, title, text, retry));
|
||||
}
|
||||
|
||||
fn handle_login_error(&mut self, err: &str) -> bool {
|
||||
self.lc.write().unwrap().handle_login_error(err, self)
|
||||
}
|
||||
|
||||
fn handle_peer_info(&mut self, pi: PeerInfo) {
|
||||
// let mut pi_sciter = Value::map();
|
||||
let username = self.lc.read().unwrap().get_username(&pi);
|
||||
// pi_sciter.set_item("username", username.clone());
|
||||
// pi_sciter.set_item("hostname", pi.hostname.clone());
|
||||
// pi_sciter.set_item("platform", pi.platform.clone());
|
||||
// pi_sciter.set_item("sas_enabled", pi.sas_enabled);
|
||||
if get_version_number(&pi.version) < get_version_number("1.1.10") {
|
||||
self.set_permission("restart", false);
|
||||
}
|
||||
if self.is_file_transfer() {
|
||||
if pi.username.is_empty() {
|
||||
self.on_error("No active console user logged on, please connect and logon first.");
|
||||
return;
|
||||
}
|
||||
} else if !self.is_port_forward() {
|
||||
if pi.displays.is_empty() {
|
||||
self.lc.write().unwrap().handle_peer_info(username, pi);
|
||||
self.update_privacy_mode();
|
||||
self.msgbox("error", "Remote Error", "No Display");
|
||||
return;
|
||||
}
|
||||
// let mut displays = Value::array(0);
|
||||
// for ref d in pi.displays.iter() {
|
||||
// let mut display = Value::map();
|
||||
// display.set_item("x", d.x);
|
||||
// display.set_item("y", d.y);
|
||||
// display.set_item("width", d.width);
|
||||
// display.set_item("height", d.height);
|
||||
// displays.push(display);
|
||||
// }
|
||||
// pi_sciter.set_item("displays", displays);
|
||||
let mut current = pi.current_display as usize;
|
||||
if current >= pi.displays.len() {
|
||||
current = 0;
|
||||
}
|
||||
// pi_sciter.set_item("current_display", current as i32);
|
||||
let current = &pi.displays[current];
|
||||
self.set_display(current.x, current.y, current.width, current.height);
|
||||
// https://sciter.com/forums/topic/color_spaceiyuv-crash
|
||||
// Nothing spectacular in decoder – done on CPU side.
|
||||
// So if you can do BGRA translation on your side – the better.
|
||||
// BGRA is used as internal image format so it will not require additional transformations.
|
||||
// VIDEO.lock().unwrap().as_mut().map(|v| {
|
||||
// let ok = v.start_streaming(
|
||||
// (current.width as _, current.height as _),
|
||||
// COLOR_SPACE::Rgb32,
|
||||
// None,
|
||||
// );
|
||||
// log::info!("[video] initialized: {:?}", ok);
|
||||
// });
|
||||
let p = self.lc.read().unwrap().should_auto_login();
|
||||
if !p.is_empty() {
|
||||
input_os_password(p, true, self.clone());
|
||||
}
|
||||
}
|
||||
self.lc.write().unwrap().handle_peer_info(username, pi);
|
||||
self.update_privacy_mode();
|
||||
// self.update_pi(pi);
|
||||
if self.is_file_transfer() {
|
||||
self.close_success();
|
||||
} else if !self.is_port_forward() {
|
||||
self.msgbox("success", "Successful", "Connected, waiting for image...");
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let mut path = std::env::temp_dir();
|
||||
path.push(&self.id);
|
||||
let path = path.with_extension(crate::get_app_name().to_lowercase());
|
||||
std::fs::File::create(&path).ok();
|
||||
if let Some(path) = path.to_str() {
|
||||
crate::platform::windows::add_recent_document(&path);
|
||||
}
|
||||
}
|
||||
// self.start_keyboard_hook(); // TODO
|
||||
}
|
||||
|
||||
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream) {
|
||||
handle_hash(self.lc.clone(), pass, hash, self, peer).await;
|
||||
}
|
||||
|
||||
async fn handle_login_from_ui(&mut self, password: String, remember: bool, peer: &mut Stream) {
|
||||
handle_login_from_ui(self.lc.clone(), password, remember, peer).await;
|
||||
}
|
||||
|
||||
async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream) {
|
||||
if !t.from_client {
|
||||
self.update_quality_status(QualityStatus {
|
||||
delay: Some(t.last_delay as _),
|
||||
target_bitrate: Some(t.target_bitrate as _),
|
||||
..Default::default()
|
||||
});
|
||||
handle_test_delay(t, peer).await;
|
||||
}
|
||||
}
|
||||
|
||||
fn set_force_relay(&mut self, direct: bool, received: bool) {
|
||||
let mut lc = self.lc.write().unwrap();
|
||||
lc.force_relay = false;
|
||||
if direct && !received {
|
||||
let errno = errno::errno().0;
|
||||
log::info!("errno is {}", errno);
|
||||
// TODO: check mac and ios
|
||||
if cfg!(windows) && errno == 10054 || !cfg!(windows) && errno == 104 {
|
||||
lc.force_relay = true;
|
||||
lc.set_option("force-always-relay".to_owned(), "Y".to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_force_relay(&self) -> bool {
|
||||
self.lc.read().unwrap().force_relay
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user