mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
@@ -1,4 +1,5 @@
|
||||
pub use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
|
||||
use cpal::{
|
||||
traits::{DeviceTrait, HostTrait, StreamTrait},
|
||||
@@ -909,6 +910,7 @@ pub struct LoginConfigHandler {
|
||||
pub force_relay: bool,
|
||||
pub direct: Option<bool>,
|
||||
pub received: bool,
|
||||
switch_uuid: Option<String>,
|
||||
}
|
||||
|
||||
impl Deref for LoginConfigHandler {
|
||||
@@ -936,7 +938,7 @@ impl LoginConfigHandler {
|
||||
///
|
||||
/// * `id` - id of peer
|
||||
/// * `conn_type` - Connection type enum.
|
||||
pub fn initialize(&mut self, id: String, conn_type: ConnType) {
|
||||
pub fn initialize(&mut self, id: String, conn_type: ConnType, switch_uuid: Option<String>) {
|
||||
self.id = id;
|
||||
self.conn_type = conn_type;
|
||||
let config = self.load_config();
|
||||
@@ -948,6 +950,7 @@ impl LoginConfigHandler {
|
||||
self.force_relay = !self.get_option("force-always-relay").is_empty();
|
||||
self.direct = None;
|
||||
self.received = false;
|
||||
self.switch_uuid = switch_uuid;
|
||||
}
|
||||
|
||||
/// Check if the client should auto login.
|
||||
@@ -1784,6 +1787,14 @@ pub async fn handle_hash(
|
||||
interface: &impl Interface,
|
||||
peer: &mut Stream,
|
||||
) {
|
||||
lc.write().unwrap().hash = hash.clone();
|
||||
let uuid = lc.read().unwrap().switch_uuid.clone();
|
||||
if let Some(uuid) = uuid {
|
||||
if let Ok(uuid) = uuid::Uuid::from_str(&uuid) {
|
||||
send_switch_login_request(lc.clone(), peer, uuid).await;
|
||||
return;
|
||||
}
|
||||
}
|
||||
let mut password = lc.read().unwrap().password.clone();
|
||||
if password.is_empty() {
|
||||
if !password_preset.is_empty() {
|
||||
@@ -1848,6 +1859,26 @@ pub async fn handle_login_from_ui(
|
||||
send_login(lc.clone(), hasher2.finalize()[..].into(), peer).await;
|
||||
}
|
||||
|
||||
async fn send_switch_login_request(
|
||||
lc: Arc<RwLock<LoginConfigHandler>>,
|
||||
peer: &mut Stream,
|
||||
uuid: Uuid,
|
||||
) {
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_switch_sides_response(SwitchSidesResponse {
|
||||
uuid: Bytes::from(uuid.as_bytes().to_vec()),
|
||||
lr: hbb_common::protobuf::MessageField::some(
|
||||
lc.read()
|
||||
.unwrap()
|
||||
.create_login_msg(vec![])
|
||||
.login_request()
|
||||
.to_owned(),
|
||||
),
|
||||
..Default::default()
|
||||
});
|
||||
allow_err!(peer.send(&msg_out).await);
|
||||
}
|
||||
|
||||
/// Interface for client to send data and commands.
|
||||
#[async_trait]
|
||||
pub trait Interface: Send + Clone + 'static + Sized {
|
||||
|
||||
@@ -1111,6 +1111,10 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
);
|
||||
}
|
||||
}
|
||||
Some(misc::Union::SwitchBack(_)) => {
|
||||
#[cfg(feature = "flutter")]
|
||||
self.handler.switch_back(&self.handler.id);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Some(message::Union::TestDelay(t)) => {
|
||||
|
||||
@@ -298,11 +298,27 @@ fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option<Vec<Strin
|
||||
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 switch_uuid = switch_uuid.map_or("".to_string(), |p| format!("switch_uuid={}", p));
|
||||
let params = vec![switch_uuid].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(peer_id) {
|
||||
match invoke_new_connection(uni_links) {
|
||||
Ok(()) => {
|
||||
return None;
|
||||
}
|
||||
@@ -316,7 +332,6 @@ fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option<Vec<Strin
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use winapi::um::winuser::WM_USER;
|
||||
let uni_links = format!("rustdesk://connection/new/{}", peer_id);
|
||||
let res = crate::platform::send_message_to_hnwd(
|
||||
"FLUTTER_RUNNER_WIN32_WINDOW",
|
||||
"RustDesk",
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
use crate::ui_session_interface::{io_loop, InvokeUiSession, Session};
|
||||
use crate::{client::*, flutter_ffi::EventToUI};
|
||||
use flutter_rust_bridge::{StreamSink, ZeroCopyBuffer};
|
||||
use hbb_common::{
|
||||
bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType,
|
||||
ResultType,
|
||||
};
|
||||
use serde_json::json;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::CString,
|
||||
@@ -5,18 +13,6 @@ use std::{
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use flutter_rust_bridge::{StreamSink, ZeroCopyBuffer};
|
||||
|
||||
use hbb_common::{
|
||||
bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType,
|
||||
ResultType,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::ui_session_interface::{io_loop, InvokeUiSession, Session};
|
||||
|
||||
use crate::{client::*, flutter_ffi::EventToUI};
|
||||
|
||||
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";
|
||||
@@ -366,7 +362,17 @@ impl InvokeUiSession for FlutterHandler {
|
||||
("y", &display.y.to_string()),
|
||||
("width", &display.width.to_string()),
|
||||
("height", &display.height.to_string()),
|
||||
("cursor_embedded", &{if display.cursor_embedded {1} else {0}}.to_string()),
|
||||
(
|
||||
"cursor_embedded",
|
||||
&{
|
||||
if display.cursor_embedded {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
.to_string(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -382,6 +388,10 @@ impl InvokeUiSession for FlutterHandler {
|
||||
fn clipboard(&self, content: String) {
|
||||
self.push_event("clipboard", vec![("content", &content)]);
|
||||
}
|
||||
|
||||
fn switch_back(&self, peer_id: &str) {
|
||||
self.push_event("switch_back", [("peer_id", peer_id)].into());
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new remote session with the given id.
|
||||
@@ -391,7 +401,12 @@ impl InvokeUiSession for FlutterHandler {
|
||||
/// * `id` - The identifier of the remote session with prefix. Regex: [\w]*[\_]*[\d]+
|
||||
/// * `is_file_transfer` - If the session is used for file transfer.
|
||||
/// * `is_port_forward` - If the session is used for port forward.
|
||||
pub fn session_add(id: &str, is_file_transfer: bool, is_port_forward: bool) -> ResultType<()> {
|
||||
pub fn session_add(
|
||||
id: &str,
|
||||
is_file_transfer: bool,
|
||||
is_port_forward: bool,
|
||||
switch_uuid: &str,
|
||||
) -> ResultType<()> {
|
||||
let session_id = get_session_id(id.to_owned());
|
||||
LocalConfig::set_remote_id(&session_id);
|
||||
|
||||
@@ -409,11 +424,17 @@ pub fn session_add(id: &str, is_file_transfer: bool, is_port_forward: bool) -> R
|
||||
ConnType::DEFAULT_CONN
|
||||
};
|
||||
|
||||
let switch_uuid = if switch_uuid.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(switch_uuid.to_string())
|
||||
};
|
||||
|
||||
session
|
||||
.lc
|
||||
.write()
|
||||
.unwrap()
|
||||
.initialize(session_id, conn_type);
|
||||
.initialize(session_id, conn_type, switch_uuid);
|
||||
|
||||
if let Some(same_id_session) = SESSIONS.write().unwrap().insert(id.to_owned(), session) {
|
||||
same_id_session.close();
|
||||
|
||||
@@ -84,8 +84,9 @@ pub fn session_add_sync(
|
||||
id: String,
|
||||
is_file_transfer: bool,
|
||||
is_port_forward: bool,
|
||||
switch_uuid: String,
|
||||
) -> SyncReturn<String> {
|
||||
if let Err(e) = session_add(&id, is_file_transfer, is_port_forward) {
|
||||
if let Err(e) = session_add(&id, is_file_transfer, is_port_forward, &switch_uuid) {
|
||||
SyncReturn(format!("Failed to add session with id {}, {}", &id, e))
|
||||
} else {
|
||||
SyncReturn("".to_owned())
|
||||
@@ -503,6 +504,12 @@ pub fn session_elevate_with_logon(id: String, username: String, password: String
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_switch_sides(id: String) {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
session.switch_sides();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_get_sound_inputs() -> Vec<String> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
return get_sound_inputs();
|
||||
@@ -1065,6 +1072,10 @@ pub fn cm_elevate_portable(conn_id: i32) {
|
||||
crate::ui_cm_interface::elevate_portable(conn_id);
|
||||
}
|
||||
|
||||
pub fn cm_switch_back(conn_id: i32) {
|
||||
crate::ui_cm_interface::switch_back(conn_id);
|
||||
}
|
||||
|
||||
pub fn main_get_icon() -> String {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))]
|
||||
return ui_interface::get_icon();
|
||||
@@ -1107,8 +1118,8 @@ pub fn query_onlines(ids: Vec<String>) {
|
||||
crate::rendezvous_mediator::query_online_states(ids, handle_query_onlines)
|
||||
}
|
||||
|
||||
pub fn version_to_number(v: String) -> i64 {
|
||||
hbb_common::get_version_number(&v)
|
||||
pub fn version_to_number(v: String) -> SyncReturn<i64> {
|
||||
SyncReturn(hbb_common::get_version_number(&v))
|
||||
}
|
||||
|
||||
pub fn option_synced() -> bool {
|
||||
|
||||
12
src/ipc.rs
12
src/ipc.rs
@@ -166,6 +166,7 @@ pub enum Data {
|
||||
file_transfer_enabled: bool,
|
||||
restart: bool,
|
||||
recording: bool,
|
||||
from_switch: bool,
|
||||
},
|
||||
ChatMessage {
|
||||
text: String,
|
||||
@@ -207,6 +208,8 @@ pub enum Data {
|
||||
Empty,
|
||||
Disconnected,
|
||||
DataPortableService(DataPortableService),
|
||||
SwitchSidesRequest(String),
|
||||
SwitchSidesBack,
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
@@ -427,6 +430,15 @@ async fn handle(data: Data, stream: &mut Connection) {
|
||||
Data::TestRendezvousServer => {
|
||||
crate::test_rendezvous_server();
|
||||
}
|
||||
Data::SwitchSidesRequest(id) => {
|
||||
let uuid = uuid::Uuid::new_v4();
|
||||
crate::server::insert_switch_sides_uuid(id, uuid.clone());
|
||||
allow_err!(
|
||||
stream
|
||||
.send(&Data::SwitchSidesRequest(uuid.to_string()))
|
||||
.await
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", "弱"),
|
||||
("Medium", "中"),
|
||||
("Strong", "强"),
|
||||
("Switch Sides", "反转访问方向"),
|
||||
("Please confirm if you want to share your desktop?", "请确认要让对方访问你的桌面?"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", "Schwach"),
|
||||
("Medium", "Mittel"),
|
||||
("Strong", "Stark"),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", "Débil"),
|
||||
("Medium", "Media"),
|
||||
("Strong", "Fuerte"),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", "Αδύναμο"),
|
||||
("Medium", "Μέτριο"),
|
||||
("Strong", "Δυνατό"),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", "Debole"),
|
||||
("Medium", "Media"),
|
||||
("Strong", "Forte"),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", "Слабый"),
|
||||
("Medium", "Средний"),
|
||||
("Strong", "Стойкий"),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", "弱"),
|
||||
("Medium", "中"),
|
||||
("Strong", "強"),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -431,5 +431,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Weak", ""),
|
||||
("Medium", ""),
|
||||
("Strong", ""),
|
||||
("Switch Sides", ""),
|
||||
("Please confirm if you want to share your desktop?", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -784,12 +784,14 @@ extern "C" fn breakdown_signal_handler(sig: i32) {
|
||||
sig,
|
||||
stack.join("\n").to_string()
|
||||
);
|
||||
system_message(
|
||||
"RustDesk",
|
||||
&format!("Got signal {} and exit.{}", sig, info),
|
||||
true,
|
||||
)
|
||||
.ok();
|
||||
if !info.is_empty() {
|
||||
system_message(
|
||||
"RustDesk",
|
||||
&format!("Got signal {} and exit.{}", sig, info),
|
||||
true,
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ lazy_static::lazy_static! {
|
||||
static ref LOGIN_FAILURES: Arc::<Mutex<HashMap<String, (i32, i32, i32)>>> = Default::default();
|
||||
static ref SESSIONS: Arc::<Mutex<HashMap<String, Session>>> = Default::default();
|
||||
static ref ALIVE_CONNS: Arc::<Mutex<Vec<i32>>> = Default::default();
|
||||
static ref SWITCH_SIDES_UUID: Arc::<Mutex<HashMap<String, (Instant, uuid::Uuid)>>> = Default::default();
|
||||
}
|
||||
pub static CLICK_TIME: AtomicI64 = AtomicI64::new(0);
|
||||
pub static MOUSE_MOVE_TIME: AtomicI64 = AtomicI64::new(0);
|
||||
@@ -101,7 +102,9 @@ pub struct Connection {
|
||||
last_recv_time: Arc<Mutex<Instant>>,
|
||||
chat_unanswered: bool,
|
||||
close_manually: bool,
|
||||
#[allow(unused)]
|
||||
elevation_requested: bool,
|
||||
from_switch: bool,
|
||||
}
|
||||
|
||||
impl Subscriber for ConnInner {
|
||||
@@ -134,6 +137,7 @@ const MILLI1: Duration = Duration::from_millis(1);
|
||||
const SEND_TIMEOUT_VIDEO: u64 = 12_000;
|
||||
const SEND_TIMEOUT_OTHER: u64 = SEND_TIMEOUT_VIDEO * 10;
|
||||
const SESSION_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
const SWITCH_SIDES_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
impl Connection {
|
||||
pub async fn start(
|
||||
@@ -198,6 +202,7 @@ impl Connection {
|
||||
chat_unanswered: false,
|
||||
close_manually: false,
|
||||
elevation_requested: false,
|
||||
from_switch: false,
|
||||
};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
tokio::spawn(async move {
|
||||
@@ -362,6 +367,13 @@ impl Connection {
|
||||
log::error!("Failed to start portable service from cm:{:?}", e);
|
||||
}
|
||||
}
|
||||
ipc::Data::SwitchSidesBack => {
|
||||
let mut misc = Misc::new();
|
||||
misc.set_switch_back(SwitchBack::default());
|
||||
let mut msg = Message::new();
|
||||
msg.set_misc(misc);
|
||||
conn.send(msg).await;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
@@ -954,6 +966,7 @@ impl Connection {
|
||||
file_transfer_enabled: self.file_transfer_enabled(),
|
||||
restart: self.restart,
|
||||
recording: self.recording,
|
||||
from_switch: self.from_switch,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1078,29 +1091,33 @@ impl Connection {
|
||||
return Config::get_option(enable_prefix_option).is_empty();
|
||||
}
|
||||
|
||||
async fn on_message(&mut self, msg: Message) -> bool {
|
||||
if let Some(message::Union::LoginRequest(lr)) = msg.union {
|
||||
self.lr = lr.clone();
|
||||
if let Some(o) = lr.option.as_ref() {
|
||||
self.update_option(o).await;
|
||||
if let Some(q) = o.video_codec_state.clone().take() {
|
||||
scrap::codec::Encoder::update_video_encoder(
|
||||
self.inner.id(),
|
||||
scrap::codec::EncoderUpdate::State(q),
|
||||
);
|
||||
} else {
|
||||
scrap::codec::Encoder::update_video_encoder(
|
||||
self.inner.id(),
|
||||
scrap::codec::EncoderUpdate::DisableHwIfNotExist,
|
||||
);
|
||||
}
|
||||
async fn handle_login_request_without_validation(&mut self, lr: &LoginRequest) {
|
||||
self.lr = lr.clone();
|
||||
if let Some(o) = lr.option.as_ref() {
|
||||
self.update_option(o).await;
|
||||
if let Some(q) = o.video_codec_state.clone().take() {
|
||||
scrap::codec::Encoder::update_video_encoder(
|
||||
self.inner.id(),
|
||||
scrap::codec::EncoderUpdate::State(q),
|
||||
);
|
||||
} else {
|
||||
scrap::codec::Encoder::update_video_encoder(
|
||||
self.inner.id(),
|
||||
scrap::codec::EncoderUpdate::DisableHwIfNotExist,
|
||||
);
|
||||
}
|
||||
self.video_ack_required = lr.video_ack_required;
|
||||
} else {
|
||||
scrap::codec::Encoder::update_video_encoder(
|
||||
self.inner.id(),
|
||||
scrap::codec::EncoderUpdate::DisableHwIfNotExist,
|
||||
);
|
||||
}
|
||||
self.video_ack_required = lr.video_ack_required;
|
||||
}
|
||||
|
||||
async fn on_message(&mut self, msg: Message) -> bool {
|
||||
if let Some(message::Union::LoginRequest(lr)) = msg.union {
|
||||
self.handle_login_request_without_validation(&lr).await;
|
||||
if self.authorized {
|
||||
return true;
|
||||
}
|
||||
@@ -1247,6 +1264,25 @@ impl Connection {
|
||||
.unwrap()
|
||||
.update_network_delay(new_delay);
|
||||
}
|
||||
} else if let Some(message::Union::SwitchSidesResponse(_s)) = msg.union {
|
||||
#[cfg(feature = "flutter")]
|
||||
if let Some(lr) = _s.lr.clone().take() {
|
||||
self.handle_login_request_without_validation(&lr).await;
|
||||
SWITCH_SIDES_UUID
|
||||
.lock()
|
||||
.unwrap()
|
||||
.retain(|_, v| v.0.elapsed() < SWITCH_SIDES_TIMEOUT);
|
||||
let uuid_old = SWITCH_SIDES_UUID.lock().unwrap().remove(&lr.my_id);
|
||||
if let Ok(uuid) = uuid::Uuid::from_slice(_s.uuid.to_vec().as_ref()) {
|
||||
if let Some((instant, uuid_old)) = uuid_old {
|
||||
if uuid == uuid_old {
|
||||
self.from_switch = true;
|
||||
self.try_start_cm(lr.my_id.clone(), lr.my_name.clone(), true);
|
||||
self.send_logon_response().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if self.authorized {
|
||||
match msg.union {
|
||||
Some(message::Union::MouseEvent(me)) => {
|
||||
@@ -1512,7 +1548,7 @@ impl Connection {
|
||||
self.send(msg).await;
|
||||
}
|
||||
}
|
||||
Some(elevation_request::Union::Logon(r)) => {
|
||||
Some(elevation_request::Union::Logon(_r)) => {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let mut err = "No need to elevate".to_string();
|
||||
@@ -1521,7 +1557,8 @@ impl Connection {
|
||||
{
|
||||
use crate::portable_service::client;
|
||||
err = client::start_portable_service(client::StartPara::Logon(
|
||||
r.username, r.password,
|
||||
_r.username,
|
||||
_r.password,
|
||||
))
|
||||
.err()
|
||||
.map_or("".to_string(), |e| e.to_string());
|
||||
@@ -1536,6 +1573,19 @@ impl Connection {
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
#[cfg(feature = "flutter")]
|
||||
Some(misc::Union::SwitchSidesRequest(s)) => {
|
||||
if let Ok(uuid) = uuid::Uuid::from_slice(&s.uuid.to_vec()[..]) {
|
||||
crate::run_me(vec![
|
||||
"--connect",
|
||||
&self.lr.my_id,
|
||||
"--switch_uuid",
|
||||
uuid.to_string().as_ref(),
|
||||
])
|
||||
.ok();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
@@ -1756,6 +1806,13 @@ impl Connection {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_switch_sides_uuid(id: String, uuid: uuid::Uuid) {
|
||||
SWITCH_SIDES_UUID
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(id, (tokio::time::Instant::now(), uuid));
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
async fn start_ipc(
|
||||
mut rx_to_cm: mpsc::UnboundedReceiver<ipc::Data>,
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
/// [Flutter]: handle uni links for linux
|
||||
use dbus::blocking::Connection;
|
||||
use dbus_crossroads::{Crossroads, IfaceBuilder};
|
||||
use hbb_common::{log};
|
||||
use std::{error::Error, fmt, time::Duration};
|
||||
use hbb_common::log;
|
||||
#[cfg(feature = "flutter")]
|
||||
use std::collections::HashMap;
|
||||
use std::{error::Error, fmt, time::Duration};
|
||||
|
||||
const DBUS_NAME: &str = "org.rustdesk.rustdesk";
|
||||
const DBUS_PREFIX: &str = "/dbus";
|
||||
@@ -30,15 +30,16 @@ impl fmt::Display for DbusError {
|
||||
impl Error for DbusError {}
|
||||
|
||||
/// invoke new connection from dbus
|
||||
///
|
||||
///
|
||||
/// [Tips]:
|
||||
/// How to test by CLI:
|
||||
/// - use dbus-send command:
|
||||
/// `dbus-send --session --print-reply --dest=org.rustdesk.rustdesk /dbus org.rustdesk.rustdesk.NewConnection string:'PEER_ID'`
|
||||
pub fn invoke_new_connection(peer_id: String) -> Result<(), Box<dyn Error>> {
|
||||
pub fn invoke_new_connection(uni_links: String) -> Result<(), Box<dyn Error>> {
|
||||
let conn = Connection::new_session()?;
|
||||
let proxy = conn.with_proxy(DBUS_NAME, DBUS_PREFIX, DBUS_TIMEOUT);
|
||||
let (ret,): (String,) = proxy.method_call(DBUS_NAME, DBUS_METHOD_NEW_CONNECTION, (peer_id,))?;
|
||||
let (ret,): (String,) =
|
||||
proxy.method_call(DBUS_NAME, DBUS_METHOD_NEW_CONNECTION, (uni_links,))?;
|
||||
if ret != DBUS_METHOD_RETURN_SUCCESS {
|
||||
log::error!("error on call new connection to dbus server");
|
||||
return Err(Box::new(DbusError("not success".to_string())));
|
||||
@@ -67,7 +68,7 @@ fn handle_client_message(builder: &mut IfaceBuilder<()>) {
|
||||
DBUS_METHOD_NEW_CONNECTION,
|
||||
(DBUS_METHOD_NEW_CONNECTION_ID,),
|
||||
(DBUS_METHOD_RETURN,),
|
||||
move |_, _, (_peer_id,): (String,)| {
|
||||
move |_, _, (_uni_links,): (String,)| {
|
||||
#[cfg(feature = "flutter")]
|
||||
{
|
||||
use crate::flutter::{self, APP_TYPE_MAIN};
|
||||
@@ -79,7 +80,7 @@ fn handle_client_message(builder: &mut IfaceBuilder<()>) {
|
||||
{
|
||||
let data = HashMap::from([
|
||||
("name", "new_connection"),
|
||||
("peer_id", _peer_id.as_str())
|
||||
("uni_links", _uni_links.as_str()),
|
||||
]);
|
||||
if !stream.add(serde_json::ser::to_string(&data).unwrap_or("".to_string())) {
|
||||
log::error!("failed to add dbus message to flutter global dbus stream.");
|
||||
|
||||
@@ -264,6 +264,8 @@ impl InvokeUiSession for SciterHandler {
|
||||
fn update_block_input_state(&self, on: bool) {
|
||||
self.call("updateBlockInputState", &make_args!(on));
|
||||
}
|
||||
|
||||
fn switch_back(&self, _id: &str) {}
|
||||
}
|
||||
|
||||
pub struct SciterSession(Session<SciterHandler>);
|
||||
@@ -440,7 +442,7 @@ impl SciterSession {
|
||||
ConnType::DEFAULT_CONN
|
||||
};
|
||||
|
||||
session.lc.write().unwrap().initialize(id, conn_type);
|
||||
session.lc.write().unwrap().initialize(id, conn_type, None);
|
||||
|
||||
Self(session)
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ pub struct Client {
|
||||
pub file: bool,
|
||||
pub restart: bool,
|
||||
pub recording: bool,
|
||||
pub from_switch: bool,
|
||||
#[serde(skip)]
|
||||
tx: UnboundedSender<Data>,
|
||||
}
|
||||
@@ -118,6 +119,7 @@ impl<T: InvokeUiCM> ConnectionManager<T> {
|
||||
file: bool,
|
||||
restart: bool,
|
||||
recording: bool,
|
||||
from_switch: bool,
|
||||
tx: mpsc::UnboundedSender<Data>,
|
||||
) {
|
||||
let client = Client {
|
||||
@@ -134,6 +136,7 @@ impl<T: InvokeUiCM> ConnectionManager<T> {
|
||||
file,
|
||||
restart,
|
||||
recording,
|
||||
from_switch,
|
||||
tx,
|
||||
};
|
||||
CLIENTS
|
||||
@@ -241,6 +244,14 @@ pub fn get_clients_length() -> usize {
|
||||
clients.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "flutter")]
|
||||
pub fn switch_back(id: i32) {
|
||||
if let Some(client) = CLIENTS.read().unwrap().get(&id) {
|
||||
allow_err!(client.tx.send(Data::SwitchSidesBack));
|
||||
};
|
||||
}
|
||||
|
||||
impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
||||
#[cfg(windows)]
|
||||
async fn enable_cliprdr_file_context(&mut self, conn_id: i32, enabled: bool) {
|
||||
@@ -308,9 +319,9 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
||||
}
|
||||
Ok(Some(data)) => {
|
||||
match data {
|
||||
Data::Login{id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, file_transfer_enabled: _file_transfer_enabled, restart, recording} => {
|
||||
Data::Login{id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, file_transfer_enabled: _file_transfer_enabled, restart, recording, from_switch} => {
|
||||
log::debug!("conn_id: {}", id);
|
||||
self.cm.add_connection(id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, restart, recording, self.tx.clone());
|
||||
self.cm.add_connection(id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, restart, recording, from_switch,self.tx.clone());
|
||||
self.authorized = authorized;
|
||||
self.conn_id = id;
|
||||
#[cfg(windows)]
|
||||
@@ -498,6 +509,7 @@ pub async fn start_listen<T: InvokeUiCM>(
|
||||
file,
|
||||
restart,
|
||||
recording,
|
||||
from_switch,
|
||||
..
|
||||
}) => {
|
||||
current_id = id;
|
||||
@@ -514,6 +526,7 @@ pub async fn start_listen<T: InvokeUiCM>(
|
||||
file,
|
||||
restart,
|
||||
recording,
|
||||
from_switch,
|
||||
tx.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::common::{self, GrabState};
|
||||
use crate::keyboard;
|
||||
use crate::{client::Data, client::Interface};
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use hbb_common::config::{Config, LocalConfig, PeerConfig};
|
||||
use hbb_common::rendezvous_proto::ConnType;
|
||||
use hbb_common::tokio::{self, sync::mpsc};
|
||||
@@ -16,8 +17,10 @@ use hbb_common::{fs, get_version_number, log, Stream};
|
||||
use rdev::{Event, EventType::*};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use uuid::Uuid;
|
||||
pub static IS_IN: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@@ -616,6 +619,40 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
pub fn elevate_with_logon(&self, username: String, password: String) {
|
||||
self.send(Data::ElevateWithLogon(username, password));
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
pub async fn switch_sides(&self) {
|
||||
match crate::ipc::connect(1000, "").await {
|
||||
Ok(mut conn) => {
|
||||
if conn
|
||||
.send(&crate::ipc::Data::SwitchSidesRequest(self.id.to_string()))
|
||||
.await
|
||||
.is_ok()
|
||||
{
|
||||
if let Ok(Some(data)) = conn.next_timeout(1000).await {
|
||||
match data {
|
||||
crate::ipc::Data::SwitchSidesRequest(str_uuid) => {
|
||||
if let Ok(uuid) = Uuid::from_str(&str_uuid) {
|
||||
let mut misc = Misc::new();
|
||||
misc.set_switch_sides_request(SwitchSidesRequest {
|
||||
uuid: Bytes::from(uuid.as_bytes().to_vec()),
|
||||
..Default::default()
|
||||
});
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_misc(misc);
|
||||
self.send(Data::Message(msg_out));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!("server not started (will try to start): {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {
|
||||
@@ -655,6 +692,7 @@ pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
fn clipboard(&self, content: String);
|
||||
fn cancel_msgbox(&self, tag: &str);
|
||||
fn switch_back(&self, id: &str);
|
||||
}
|
||||
|
||||
impl<T: InvokeUiSession> Deref for Session<T> {
|
||||
|
||||
Reference in New Issue
Block a user