mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
@@ -16,6 +16,7 @@ use hbb_common::{config::RENDEZVOUS_PORT, futures::future::join_all};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub const CLIPBOARD_NAME: &'static str = "clipboard";
|
||||
pub const CLIPRDR_NAME: &'static str = "cliprdr";
|
||||
pub const CLIPBOARD_INTERVAL: u64 = 333;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
|
||||
@@ -29,6 +29,8 @@ use std::{
|
||||
|
||||
mod audio_service;
|
||||
mod clipboard_service;
|
||||
#[cfg(windows)]
|
||||
pub mod cliprdr_service;
|
||||
mod connection;
|
||||
pub mod input_service;
|
||||
mod service;
|
||||
@@ -61,6 +63,8 @@ pub fn new() -> ServerPtr {
|
||||
server.add_service(Box::new(audio_service::new()));
|
||||
server.add_service(Box::new(video_service::new()));
|
||||
server.add_service(Box::new(clipboard_service::new()));
|
||||
#[cfg(windows)]
|
||||
server.add_service(Box::new(cliprdr_service::new()));
|
||||
server.add_service(Box::new(input_service::new_cursor()));
|
||||
server.add_service(Box::new(input_service::new_pos()));
|
||||
Arc::new(RwLock::new(server))
|
||||
|
||||
104
src/server/cliprdr_service.rs
Normal file
104
src/server/cliprdr_service.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use super::*;
|
||||
use clipboard::{create_cliprdr_context, get_rx_client_msg, server_msg, ConnID};
|
||||
use hbb_common::{
|
||||
log,
|
||||
tokio::sync::{
|
||||
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
||||
Mutex as TokioMutex,
|
||||
},
|
||||
tokio::time::{self, Duration, Instant},
|
||||
ResultType,
|
||||
};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
pub use crate::common::CLIPRDR_NAME as NAME;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref MSG_CHANNEL_SERVER: (UnboundedSender<(ConnID, Cliprdr)>, TokioMutex<UnboundedReceiver<(ConnID, Cliprdr)>>) = {
|
||||
let (tx, rx) = unbounded_channel();
|
||||
(tx, TokioMutex::new(rx))
|
||||
};
|
||||
}
|
||||
|
||||
static RUNNING: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub fn new() -> GenericService {
|
||||
let sp = GenericService::new(NAME, true);
|
||||
sp.run::<_>(listen::run);
|
||||
sp
|
||||
}
|
||||
|
||||
pub fn handle_serve_cliprdr_msg(id: i32, msg: Cliprdr) {
|
||||
if RUNNING.load(Ordering::SeqCst) {
|
||||
log::debug!("handle handle_serve_cliprdr_msg");
|
||||
MSG_CHANNEL_SERVER
|
||||
.0
|
||||
.send((
|
||||
ConnID {
|
||||
server_conn_id: id as u32,
|
||||
remote_conn_id: 0,
|
||||
},
|
||||
msg,
|
||||
))
|
||||
.unwrap();
|
||||
} else {
|
||||
// should not reach this branch
|
||||
}
|
||||
}
|
||||
|
||||
mod listen {
|
||||
use super::*;
|
||||
|
||||
static WAIT: Duration = Duration::from_millis(1500);
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn run(sp: GenericService) -> ResultType<()> {
|
||||
let mut cliprdr_context = create_cliprdr_context(true, false)?;
|
||||
|
||||
RUNNING.store(false, Ordering::SeqCst);
|
||||
|
||||
let mut timer = time::interval_at(Instant::now() + WAIT, WAIT);
|
||||
let mut client_rx = get_rx_client_msg().lock().await;
|
||||
let mut server_rx = MSG_CHANNEL_SERVER.1.lock().await;
|
||||
while sp.ok() {
|
||||
RUNNING.store(true, Ordering::SeqCst);
|
||||
|
||||
tokio::select! {
|
||||
msg = client_rx.recv() => {
|
||||
match msg {
|
||||
Some((conn_id, msg)) => {
|
||||
if conn_id.server_conn_id == 0 {
|
||||
sp.send(msg)
|
||||
} else {
|
||||
sp.send_to(msg, conn_id.server_conn_id as i32)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
msg = server_rx.recv() => {
|
||||
match msg {
|
||||
Some((conn_id, msg)) => {
|
||||
let res = server_msg(&mut cliprdr_context, conn_id, msg);
|
||||
if res != 0 {
|
||||
// log::warn!("failed to process message for {}", id);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = timer.tick() => {},
|
||||
}
|
||||
sp.snapshot(|_| Ok(()))?;
|
||||
}
|
||||
|
||||
RUNNING.store(false, Ordering::SeqCst);
|
||||
log::info!("Clipboard listener stopped!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -224,6 +224,10 @@ impl Connection {
|
||||
s.write().unwrap().subscribe(
|
||||
super::clipboard_service::NAME,
|
||||
conn.inner.clone(), conn.clipboard_enabled() && conn.keyboard);
|
||||
#[cfg(windows)]
|
||||
s.write().unwrap().subscribe(
|
||||
super::cliprdr_service::NAME,
|
||||
conn.inner.clone(), conn.clipboard_enabled() && conn.keyboard);
|
||||
}
|
||||
} else if &name == "audio" {
|
||||
conn.audio = enabled;
|
||||
@@ -600,6 +604,8 @@ impl Connection {
|
||||
}
|
||||
if !self.clipboard_enabled() || !self.keyboard {
|
||||
noperms.push(super::clipboard_service::NAME);
|
||||
#[cfg(windows)]
|
||||
noperms.push(super::cliprdr_service::NAME);
|
||||
}
|
||||
if !self.audio_enabled() {
|
||||
noperms.push(super::audio_service::NAME);
|
||||
@@ -824,6 +830,11 @@ impl Connection {
|
||||
update_clipboard(cb, None);
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
Some(message::Union::cliprdr(clip)) => {
|
||||
log::debug!("received cliprdr msg");
|
||||
cliprdr_service::handle_serve_cliprdr_msg(self.inner.id, clip)
|
||||
}
|
||||
Some(message::Union::file_action(fa)) => {
|
||||
if self.file_transfer.is_some() {
|
||||
match fa.union {
|
||||
@@ -993,6 +1004,12 @@ impl Connection {
|
||||
self.inner.clone(),
|
||||
self.clipboard_enabled() && self.keyboard,
|
||||
);
|
||||
#[cfg(windows)]
|
||||
s.write().unwrap().subscribe(
|
||||
super::cliprdr_service::NAME,
|
||||
self.inner.clone(),
|
||||
self.clipboard_enabled() && self.keyboard,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,12 @@ impl<T: Subscriber + From<ConnInner>> ServiceTmpl<T> {
|
||||
self.send_shared(Arc::new(msg));
|
||||
}
|
||||
|
||||
pub fn send_to(&self, msg: Message, id: i32) {
|
||||
if let Some(s) = self.0.write().unwrap().subscribes.get_mut(&id) {
|
||||
s.send(Arc::new(msg));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_shared(&self, msg: Arc<Message>) {
|
||||
let mut lock = self.0.write().unwrap();
|
||||
for s in lock.subscribes.values_mut() {
|
||||
|
||||
@@ -2,6 +2,10 @@ use crate::client::*;
|
||||
use crate::common::{
|
||||
self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use clipboard::{
|
||||
cliprdr::CliprdrClientContext, create_cliprdr_context, get_rx_client_msg, server_msg, ConnID,
|
||||
};
|
||||
use enigo::{self, Enigo, KeyboardControllable};
|
||||
use hbb_common::{
|
||||
allow_err,
|
||||
@@ -1159,6 +1163,16 @@ async fn io_loop(handler: Handler) {
|
||||
.as_mut()
|
||||
.map(|v| v.render_frame(data).ok());
|
||||
});
|
||||
|
||||
#[cfg(windows)]
|
||||
let cliprdr_context = match create_cliprdr_context(true, false) {
|
||||
Ok(context) => Some(context),
|
||||
Err(err) => {
|
||||
handler.msgbox("error", "Create clipboard error", &err.to_string());
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let mut remote = Remote {
|
||||
handler,
|
||||
video_sender,
|
||||
@@ -1172,6 +1186,10 @@ async fn io_loop(handler: Handler) {
|
||||
timer: time::interval(SEC30),
|
||||
last_update_jobs_status: (Instant::now(), Default::default()),
|
||||
first_frame: false,
|
||||
#[cfg(windows)]
|
||||
cliprdr_context,
|
||||
#[cfg(windows)]
|
||||
pid: std::process::id(),
|
||||
};
|
||||
remote.io_loop().await;
|
||||
}
|
||||
@@ -1211,6 +1229,10 @@ struct Remote {
|
||||
timer: Interval,
|
||||
last_update_jobs_status: (Instant, HashMap<i32, u64>),
|
||||
first_frame: bool,
|
||||
#[cfg(windows)]
|
||||
cliprdr_context: Option<Box<CliprdrClientContext>>,
|
||||
#[cfg(windows)]
|
||||
pid: u32,
|
||||
}
|
||||
|
||||
impl Remote {
|
||||
@@ -1230,6 +1252,13 @@ impl Remote {
|
||||
}
|
||||
self.handler
|
||||
.call("setConnectionType", &make_args!(peer.is_secured(), direct));
|
||||
|
||||
// just build for now
|
||||
#[cfg(not(windows))]
|
||||
let (_client_tx, mut client_rx) = mpsc::unbounded_channel::<i32>();
|
||||
#[cfg(windows)]
|
||||
let mut client_rx = get_rx_client_msg().lock().await;
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
res = peer.next() => {
|
||||
@@ -1260,6 +1289,21 @@ impl Remote {
|
||||
}
|
||||
}
|
||||
}
|
||||
msg = client_rx.recv() => {
|
||||
#[cfg(not(windows))]
|
||||
println!("{:?}", msg);
|
||||
#[cfg(windows)]
|
||||
match msg {
|
||||
Some((conn_id, msg)) => {
|
||||
if conn_id.remote_conn_id == 0 || conn_id.remote_conn_id == self.pid {
|
||||
allow_err!(peer.send(&msg).await);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = self.timer.tick() => {
|
||||
if last_recv_time.elapsed() >= SEC30 {
|
||||
self.handler.msgbox("error", "Connection Error", "Timeout");
|
||||
@@ -1631,6 +1675,24 @@ impl Remote {
|
||||
update_clipboard(cb, Some(&self.old_clipboard));
|
||||
}
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
Some(message::Union::cliprdr(clip)) => {
|
||||
log::debug!("received cliprdr msg");
|
||||
#[cfg(windows)]
|
||||
if !self.handler.lc.read().unwrap().disable_clipboard {
|
||||
if let Some(context) = &mut self.cliprdr_context {
|
||||
let res = server_msg(
|
||||
context,
|
||||
ConnID {
|
||||
server_conn_id: 0,
|
||||
remote_conn_id: self.pid,
|
||||
},
|
||||
clip,
|
||||
);
|
||||
log::debug!("server msg returns {}", res);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(message::Union::file_response(fr)) => match fr.union {
|
||||
Some(file_response::Union::dir(fd)) => {
|
||||
let entries = fd.entries.to_vec();
|
||||
|
||||
Reference in New Issue
Block a user