mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
feat: add dbus and cli connect support
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::env::Args;
|
||||
|
||||
use hbb_common::log;
|
||||
|
||||
// shared by flutter and sciter main function
|
||||
@@ -11,6 +13,7 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||
let mut is_setup = false;
|
||||
let mut _is_elevate = false;
|
||||
let mut _is_run_as_system = false;
|
||||
let mut _is_connect = false;
|
||||
for arg in std::env::args() {
|
||||
// to-do: how to pass to flutter?
|
||||
if i == 0 && crate::common::is_setup(&arg) {
|
||||
@@ -20,14 +23,16 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||
_is_elevate = true;
|
||||
} else if arg == "--run-as-system" {
|
||||
_is_run_as_system = true;
|
||||
} else if arg == "--connect" {
|
||||
_is_connect = true;
|
||||
} else {
|
||||
args.push(arg);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if args.contains(&"--install".to_string()) {
|
||||
is_setup = true;
|
||||
if _is_connect {
|
||||
return core_main_invoke_new_connection(std::env::args());
|
||||
}
|
||||
if is_setup {
|
||||
if args.is_empty() {
|
||||
@@ -208,3 +213,36 @@ fn import_config(path: &str) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// invoke a new connection
|
||||
///
|
||||
/// [Note]
|
||||
/// this is for invoke new connection from dbus
|
||||
fn core_main_invoke_new_connection(mut args: Args) -> Option<Vec<String>> {
|
||||
args
|
||||
.position(|element| {
|
||||
return element == "--connect";
|
||||
})
|
||||
.unwrap();
|
||||
let peer_id = args.next().unwrap_or("".to_string());
|
||||
if peer_id.is_empty() {
|
||||
eprintln!("please provide a valid peer id");
|
||||
return None;
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use crate::dbus::invoke_new_connection;
|
||||
|
||||
match invoke_new_connection(peer_id) {
|
||||
Ok(()) => {
|
||||
return None;
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("{}", err.as_ref());
|
||||
// return Some to invoke this new connection by self
|
||||
return Some(Vec::new());
|
||||
}
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -801,6 +801,17 @@ pub fn main_is_release() -> bool {
|
||||
is_release()
|
||||
}
|
||||
|
||||
pub fn main_start_dbus_server() {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use crate::dbus::start_dbus_server;
|
||||
// spawn new thread to start dbus server
|
||||
std::thread::spawn(|| {
|
||||
let _ = start_dbus_server();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_send_mouse(id: String, msg: String) {
|
||||
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(&msg) {
|
||||
let alt = m.get("alt").is_some();
|
||||
|
||||
@@ -30,6 +30,8 @@ mod clipboard_service;
|
||||
mod wayland;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod uinput;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod dbus;
|
||||
pub mod input_service;
|
||||
} else {
|
||||
mod clipboard_service {
|
||||
|
||||
92
src/server/dbus.rs
Normal file
92
src/server/dbus.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
/// Url handler based on dbus
|
||||
///
|
||||
/// Note:
|
||||
/// On linux, we use dbus to communicate multiple rustdesk process.
|
||||
/// [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, collections::HashMap};
|
||||
|
||||
const DBUS_NAME: &str = "org.rustdesk.rustdesk";
|
||||
const DBUS_PREFIX: &str = "/dbus";
|
||||
const DBUS_METHOD_NEW_CONNECTION: &str = "NewConnection";
|
||||
const DBUS_METHOD_NEW_CONNECTION_ID: &str = "id";
|
||||
const DBUS_METHOD_RETURN: &str = "ret";
|
||||
const DBUS_METHOD_RETURN_SUCCESS: &str = "ok";
|
||||
const DBUS_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DbusError(String);
|
||||
|
||||
impl fmt::Display for DbusError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "RustDesk DBus Error: {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
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>> {
|
||||
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,))?;
|
||||
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())));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// start dbus server
|
||||
///
|
||||
/// [Blocking]:
|
||||
/// The function will block current thread to serve dbus server.
|
||||
/// So it's suitable to spawn a new thread dedicated to dbus server.
|
||||
pub fn start_dbus_server() -> Result<(), Box<dyn Error>> {
|
||||
let conn: Connection = Connection::new_session()?;
|
||||
let _ = conn.request_name(DBUS_NAME, false, true, false)?;
|
||||
let mut cr = Crossroads::new();
|
||||
let token = cr.register(DBUS_NAME, handle_client_message);
|
||||
cr.insert(DBUS_PREFIX, &[token], ());
|
||||
cr.serve(&conn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_client_message(builder: &mut IfaceBuilder<()>) {
|
||||
// register new connection dbus
|
||||
builder.method(
|
||||
DBUS_METHOD_NEW_CONNECTION,
|
||||
(DBUS_METHOD_NEW_CONNECTION_ID,),
|
||||
(DBUS_METHOD_RETURN,),
|
||||
move |_, _, (peer_id,): (String,)| {
|
||||
#[cfg(feature = "flutter")]
|
||||
{
|
||||
use crate::flutter::{self, APP_TYPE_MAIN};
|
||||
|
||||
if let Some(stream) = flutter::GLOBAL_EVENT_STREAM
|
||||
.write()
|
||||
.unwrap()
|
||||
.get(APP_TYPE_MAIN)
|
||||
{
|
||||
let data = HashMap::from([
|
||||
("name", "new_connection"),
|
||||
("peer_id", peer_id.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.");
|
||||
}
|
||||
} else {
|
||||
log::error!("failed to find main event stream");
|
||||
}
|
||||
}
|
||||
return Ok((DBUS_METHOD_RETURN_SUCCESS.to_string(),));
|
||||
},
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user