From ccd2cbd760aa22802df38074144190a0194c3644 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 18 Jun 2023 20:23:54 +0800 Subject: [PATCH 01/13] try fix clipboard, flutter version Signed-off-by: fufesou --- libs/clipboard/src/cliprdr.h | 3 - libs/clipboard/src/cliprdr.rs | 6 -- libs/clipboard/src/context_send.rs | 54 ++++++++++------- libs/clipboard/src/lib.rs | 64 ++++++-------------- libs/clipboard/src/windows/wf_cliprdr.c | 22 +------ libs/hbb_common/src/config.rs | 13 +++++ src/client.rs | 1 + src/client/io_loop.rs | 20 +++++-- src/core_main.rs | 2 + src/ipc.rs | 3 +- src/server/connection.rs | 21 +++---- src/ui_cm_interface.rs | 77 +++++++++---------------- src/ui_interface.rs | 15 +++++ src/ui_session_interface.rs | 1 + 14 files changed, 136 insertions(+), 166 deletions(-) diff --git a/libs/clipboard/src/cliprdr.h b/libs/clipboard/src/cliprdr.h index 717309579..2fa16e201 100644 --- a/libs/clipboard/src/cliprdr.h +++ b/libs/clipboard/src/cliprdr.h @@ -191,8 +191,6 @@ extern "C" typedef UINT (*pcCliprdrServerFileContentsResponse)( CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse); - typedef BOOL (*pcCheckEnabled)(UINT32 connID); - // TODO: hide more members of clipboard context struct _cliprdr_client_context { @@ -200,7 +198,6 @@ extern "C" BOOL enableFiles; BOOL enableOthers; - pcCheckEnabled CheckEnabled; pcCliprdrServerCapabilities ServerCapabilities; pcCliprdrClientCapabilities ClientCapabilities; pcCliprdrMonitorReady MonitorReady; diff --git a/libs/clipboard/src/cliprdr.rs b/libs/clipboard/src/cliprdr.rs index 08d4021e8..2bc626536 100644 --- a/libs/clipboard/src/cliprdr.rs +++ b/libs/clipboard/src/cliprdr.rs @@ -444,9 +444,6 @@ pub type pcCliprdrServerFileContentsResponse = ::std::option::Option< fileContentsResponse: *const CLIPRDR_FILE_CONTENTS_RESPONSE, ) -> UINT, >; -pub type pcCheckEnabled = ::std::option::Option< - unsafe extern "C" fn(connID: UINT32) -> BOOL, ->; // TODO: hide more members of clipboard context #[repr(C)] @@ -455,7 +452,6 @@ pub struct _cliprdr_client_context { pub custom: *mut ::std::os::raw::c_void, pub enableFiles: BOOL, pub enableOthers: BOOL, - pub CheckEnabled: pcCheckEnabled, pub ServerCapabilities: pcCliprdrServerCapabilities, pub ClientCapabilities: pcCliprdrClientCapabilities, pub MonitorReady: pcCliprdrMonitorReady, @@ -504,7 +500,6 @@ impl CliprdrClientContext { pub fn create( enable_files: bool, enable_others: bool, - check_enabled: pcCheckEnabled, client_format_list: pcCliprdrClientFormatList, client_format_list_response: pcCliprdrClientFormatListResponse, client_format_data_request: pcCliprdrClientFormatDataRequest, @@ -516,7 +511,6 @@ impl CliprdrClientContext { custom: 0 as *mut _, enableFiles: if enable_files { TRUE } else { FALSE }, enableOthers: if enable_others { TRUE } else { FALSE }, - CheckEnabled: check_enabled, ServerCapabilities: None, ClientCapabilities: None, MonitorReady: None, diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index b19270a37..896def40e 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -1,28 +1,36 @@ use crate::cliprdr::*; use hbb_common::log; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; lazy_static::lazy_static! { - static ref CONTEXT_SEND: ContextSend = ContextSend{addr: Mutex::new(0)}; + static ref CONTEXT_SEND: Arc> = Arc::new(Mutex::new(ContextSend::new())); } pub struct ContextSend { - addr: Mutex, + server_enabled: bool, + addr: u64, } impl ContextSend { - pub fn is_enabled() -> bool { - *CONTEXT_SEND.addr.lock().unwrap() != 0 + fn new() -> Self { + Self { + server_enabled: false, + addr: 0, + } } - pub fn enable(enabled: bool) { - let mut lock = CONTEXT_SEND.addr.lock().unwrap(); + pub fn is_server_enabled() -> bool { + CONTEXT_SEND.lock().unwrap().server_enabled + } + + pub fn enable(enabled: bool, is_server_side: bool, is_server_process: bool) { + let mut lock = CONTEXT_SEND.lock().unwrap(); if enabled { - if *lock == 0 { - match crate::create_cliprdr_context(true, false, crate::ProcessSide::ClientSide) { + if lock.addr == 0 { + match crate::create_cliprdr_context(true, false) { Ok(context) => { log::info!("clipboard context for file transfer created."); - *lock = Box::into_raw(context) as _; + lock.addr = Box::into_raw(context) as _; } Err(err) => { log::error!( @@ -32,25 +40,29 @@ impl ContextSend { } } } + if is_server_side { + lock.server_enabled = true; + } } else { - if *lock != 0 { - unsafe { - let _ = Box::from_raw(*lock as *mut CliprdrClientContext); + if lock.addr != 0 { + if is_server_process { + unsafe { + let _ = Box::from_raw(lock.addr as *mut CliprdrClientContext); + } + log::info!("clipboard context for file transfer destroyed."); + lock.addr = 0; } - log::info!("clipboard context for file transfer destroyed."); - *lock = 0; + lock.server_enabled = false; } } } pub fn proc) -> u32>(f: F) -> u32 { - let mut lock = CONTEXT_SEND.addr.lock().unwrap(); - if *lock != 0 { + let lock = CONTEXT_SEND.lock().unwrap(); + if lock.addr != 0 { unsafe { - let mut context = Box::from_raw(*lock as *mut CliprdrClientContext); - let res = f(&mut context); - *lock = Box::into_raw(context) as _; - res + let mut context = Box::from_raw(lock.addr as *mut CliprdrClientContext); + f(&mut context) } } else { 0 diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index fb2255796..dc1d4ca74 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -10,7 +10,6 @@ use hbb_common::{ use serde_derive::{Deserialize, Serialize}; use std::{ boxed::Box, - collections::HashMap, ffi::{CStr, CString}, sync::{Arc, Mutex, RwLock}, }; @@ -53,11 +52,6 @@ pub enum ClipboardFile { }, } -#[derive(Default)] -struct ConnEnabled { - conn_enabled: HashMap, -} - struct MsgChannel { session_uuid: SessionID, conn_id: i32, @@ -65,17 +59,20 @@ struct MsgChannel { receiver: Arc>>, } -#[derive(PartialEq)] -pub enum ProcessSide { - UnknownSide, - ClientSide, - ServerSide, -} - lazy_static::lazy_static! { static ref VEC_MSG_CHANNEL: RwLock> = Default::default(); - static ref CLIP_CONN_ENABLED: Mutex = Mutex::new(ConnEnabled::default()); - static ref PROCESS_SIDE: RwLock = RwLock::new(ProcessSide::UnknownSide); + static ref CLIENT_CONN_ID_COUNTER: Mutex = Mutex::new(0); +} + +impl ClipboardFile { + pub fn is_stopping_allowed(&self) -> bool { + match self { + ClipboardFile::MonitorReady + | ClipboardFile::FormatList { .. } + | ClipboardFile::FormatDataRequest { .. } => true, + _ => false, + } + } } pub fn get_client_conn_id(session_uuid: &SessionID) -> Option { @@ -87,6 +84,12 @@ pub fn get_client_conn_id(session_uuid: &SessionID) -> Option { .map(|x| x.conn_id) } +fn get_conn_id() -> i32 { + let mut lock = CLIENT_CONN_ID_COUNTER.lock().unwrap(); + *lock += 1; + *lock +} + pub fn get_rx_cliprdr_client( session_uuid: &SessionID, ) -> (i32, Arc>>) { @@ -100,7 +103,7 @@ pub fn get_rx_cliprdr_client( let (sender, receiver) = unbounded_channel(); let receiver = Arc::new(TokioMutex::new(receiver)); let receiver2 = receiver.clone(); - let conn_id = lock.len() as i32 + 1; + let conn_id = get_conn_id(); let msg_channel = MsgChannel { session_uuid: session_uuid.to_owned(), conn_id, @@ -146,13 +149,6 @@ fn send_data(conn_id: i32, data: ClipboardFile) { } } -pub fn set_conn_enabled(conn_id: i32, enabled: bool) { - let mut lock = CLIP_CONN_ENABLED.lock().unwrap(); - if conn_id != 0 { - let _ = lock.conn_enabled.insert(conn_id, enabled); - } -} - pub fn empty_clipboard(context: &mut Box, conn_id: i32) -> bool { unsafe { TRUE == cliprdr::empty_cliprdr(&mut (**context), conn_id as u32) } } @@ -430,14 +426,10 @@ pub fn server_file_contents_response( pub fn create_cliprdr_context( enable_files: bool, enable_others: bool, - process_side: ProcessSide, ) -> ResultType> { - *PROCESS_SIDE.write().unwrap() = process_side; - Ok(CliprdrClientContext::create( enable_files, enable_others, - Some(check_enabled), Some(client_format_list), Some(client_format_list_response), Some(client_format_data_request), @@ -447,24 +439,6 @@ pub fn create_cliprdr_context( )?) } -extern "C" fn check_enabled(conn_id: UINT32) -> BOOL { - if *PROCESS_SIDE.read().unwrap() == ProcessSide::ClientSide { - return TRUE; - } - - let lock = CLIP_CONN_ENABLED.lock().unwrap(); - let mut connd_enabled = false; - if conn_id != 0 { - if let Some(true) = lock.conn_enabled.get(&(conn_id as i32)) { - connd_enabled = true; - } - } else { - connd_enabled = true; - } - - return if connd_enabled { TRUE } else { FALSE }; -} - extern "C" fn client_format_list( _context: *mut CliprdrClientContext, clip_format_list: *const CLIPRDR_FORMAT_LIST, diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index a66150c40..c17390cb4 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -681,10 +681,6 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO } clipboard = (wfClipboard *)instance->m_pData; - if (!clipboard->context->CheckEnabled(instance->m_connID)) - { - return E_INVALIDARG; - } if (!clipboard) return E_INVALIDARG; @@ -1470,14 +1466,7 @@ static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UIN DWORD waitRes = WaitForSingleObject(clipboard->response_data_event, 50); if (waitRes == WAIT_TIMEOUT) { - if (clipboard->context->CheckEnabled(connID)) - { - continue; - } - else - { - break; - } + continue; } if (waitRes != WAIT_OBJECT_0) @@ -1542,14 +1531,7 @@ UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, co DWORD waitRes = WaitForSingleObject(clipboard->req_fevent, 50); if (waitRes == WAIT_TIMEOUT) { - if (clipboard->context->CheckEnabled(connID)) - { - continue; - } - else - { - break; - } + continue; } if (waitRes != WAIT_OBJECT_0) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 53f49ab1d..866671d31 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -2,6 +2,7 @@ use std::{ collections::HashMap, fs, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, + ops::{Deref, DerefMut}, path::{Path, PathBuf}, sync::{Arc, Mutex, RwLock}, time::{Duration, Instant, SystemTime}, @@ -132,6 +133,18 @@ macro_rules! serde_field_bool { UserDefaultConfig::read().get($field_name) == "Y" } } + impl Deref for $struct_name { + type Target = bool; + + fn deref(&self) -> &Self::Target { + &self.v + } + } + impl DerefMut for $struct_name { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.v + } + } }; } diff --git a/src/client.rs b/src/client.rs index 8fda02d9d..df719a063 100644 --- a/src/client.rs +++ b/src/client.rs @@ -2336,6 +2336,7 @@ pub enum Data { CancelJob(i32), RemovePortForward(i32), AddPortForward((i32, String, i32)), + #[cfg(not(feature = "flutter"))] ToggleClipboardFile, NewRDP, SetConfirmOverrideFile((i32, i32, bool, bool, bool)), diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 084968883..53e910f1a 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -6,7 +6,7 @@ use std::sync::{ }; #[cfg(windows)] -use clipboard::{cliprdr::CliprdrClientContext, ContextSend}; +use clipboard::{cliprdr::CliprdrClientContext, ClipboardFile, ContextSend}; use crossbeam_queue::ArrayQueue; use hbb_common::config::{PeerConfig, TransferSerde}; use hbb_common::fs::{ @@ -58,7 +58,7 @@ pub struct Remote { last_update_jobs_status: (Instant, HashMap), first_frame: bool, #[cfg(windows)] - client_conn_id: i32, // used for clipboard + client_conn_id: i32, // used for file clipboard data_count: Arc, frame_count: Arc, video_format: CodecFormat, @@ -207,7 +207,15 @@ impl Remote { #[cfg(windows)] match _msg { Some(clip) => { - allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); + let mut send_msg = true; + if clip.is_stopping_allowed() { + if !(*self.handler.server_file_transfer_enabled.read().unwrap() && self.handler.lc.read().unwrap().enable_file_transfer.v) { + send_msg = false; + } + } + if send_msg { + allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); + } } None => { // unreachable!() @@ -389,6 +397,7 @@ impl Remote { .handle_login_from_ui(os_username, os_password, password, remember, peer) .await; } + #[cfg(not(feature = "flutter"))] Data::ToggleClipboardFile => { self.check_clipboard_file_context(); } @@ -938,6 +947,7 @@ impl Remote { } Some(login_response::Union::PeerInfo(pi)) => { self.handler.handle_peer_info(pi); + #[cfg(not(feature = "flutter"))] self.check_clipboard_file_context(); if !(self.handler.is_file_transfer() || self.handler.is_port_forward()) { #[cfg(feature = "flutter")] @@ -1188,7 +1198,6 @@ impl Remote { if !p.enabled && self.handler.is_file_transfer() { return true; } - self.check_clipboard_file_context(); self.handler.set_permission("file", p.enabled); } Ok(Permission::Restart) => { @@ -1525,12 +1534,13 @@ impl Remote { true } + #[cfg(not(feature = "flutter"))] fn check_clipboard_file_context(&self) { #[cfg(windows)] { let enabled = *self.handler.server_file_transfer_enabled.read().unwrap() && self.handler.lc.read().unwrap().enable_file_transfer.v; - ContextSend::enable(enabled); + ContextSend::enable(enabled, false, false); } } diff --git a/src/core_main.rs b/src/core_main.rs index aa9069bbf..59c72fa66 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -122,6 +122,8 @@ pub fn core_main() -> Option> { #[cfg(not(any(target_os = "android", target_os = "ios")))] init_plugins(&args); if args.is_empty() { + #[cfg(windows)] + clipboard::ContextSend::enable(true, false, false); std::thread::spawn(move || crate::start_server(false)); } else { #[cfg(windows)] diff --git a/src/ipc.rs b/src/ipc.rs index 5b89ba482..c275f88dd 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -202,7 +202,6 @@ pub enum Data { SyncConfig(Option>), #[cfg(not(any(target_os = "android", target_os = "ios")))] ClipboardFile(ClipboardFile), - ClipboardFileEnabled(bool), PrivacyModeState((i32, PrivacyModeState)), TestRendezvousServer, #[cfg(not(any(target_os = "android", target_os = "ios")))] @@ -242,7 +241,7 @@ pub async fn start(postfix: &str) -> ResultType<()> { loop { match stream.next().await { Err(err) => { - log::trace!("ipc{} connection closed: {}", postfix, err); + log::trace!("ipc '{}' connection closed: {}", postfix, err); break; } Ok(Some(data)) => { diff --git a/src/server/connection.rs b/src/server/connection.rs index 3a82a6594..960360d6a 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -282,6 +282,7 @@ impl Connection { keyboard: Connection::permission("enable-keyboard"), clipboard: Connection::permission("enable-clipboard"), audio: Connection::permission("enable-audio"), + // to-do: make sure is the option correct here file: Connection::permission("enable-file-transfer"), restart: Connection::permission("enable-remote-restart"), recording: Connection::permission("enable-record-session"), @@ -424,7 +425,6 @@ impl Connection { } else if &name == "file" { conn.file = enabled; conn.send_permission(Permission::File, enabled).await; - conn.send_to_cm(ipc::Data::ClipboardFileEnabled(conn.file_transfer_enabled())); } else if &name == "restart" { conn.restart = enabled; conn.send_permission(Permission::Restart, enabled).await; @@ -437,9 +437,9 @@ impl Connection { allow_err!(conn.stream.send_raw(bytes).await); } #[cfg(windows)] - ipc::Data::ClipboardFile(_clip) => { - if conn.file_transfer_enabled() { - allow_err!(conn.stream.send(&clip_2_msg(_clip)).await); + ipc::Data::ClipboardFile(clip) => { + if !clip.is_stopping_allowed() || conn.file_transfer_enabled() { + allow_err!(conn.stream.send(&clip_2_msg(clip)).await); } } ipc::Data::PrivacyModeState((_, state)) => { @@ -1136,7 +1136,7 @@ impl Connection { clipboard: self.clipboard, audio: self.audio, file: self.file, - file_transfer_enabled: self.file_transfer_enabled(), + file_transfer_enabled: self.file, restart: self.restart, recording: self.recording, from_switch: self.from_switch, @@ -1636,11 +1636,9 @@ impl Connection { } } Some(message::Union::Cliprdr(_clip)) => { - if self.file_transfer_enabled() { - #[cfg(windows)] - if let Some(clip) = msg_2_clip(_clip) { - self.send_to_cm(ipc::Data::ClipboardFile(clip)) - } + #[cfg(windows)] + if let Some(clip) = msg_2_clip(_clip) { + self.send_to_cm(ipc::Data::ClipboardFile(clip)) } } Some(message::Union::FileAction(fa)) => { @@ -2073,9 +2071,6 @@ impl Connection { if let Ok(q) = o.enable_file_transfer.enum_value() { if q != BoolOption::NotSet { self.enable_file_transfer = q == BoolOption::Yes; - self.send_to_cm(ipc::Data::ClipboardFileEnabled( - self.file_transfer_enabled(), - )); } } if let Ok(q) = o.disable_clipboard.enum_value() { diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index d34b7a299..b4b5636b1 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -11,14 +11,12 @@ use std::{ }, }; -#[cfg(windows)] -use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, set_conn_enabled, ContextSend}; -use serde_derive::Serialize; - #[cfg(not(any(target_os = "android", target_os = "ios")))] use crate::ipc::Connection; #[cfg(not(any(target_os = "ios")))] use crate::ipc::{self, Data}; +#[cfg(windows)] +use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, ContextSend}; #[cfg(not(any(target_os = "android", target_os = "ios")))] use hbb_common::tokio::sync::mpsc::unbounded_channel; #[cfg(windows)] @@ -37,6 +35,7 @@ use hbb_common::{ task::spawn_blocking, }, }; +use serde_derive::Serialize; #[derive(Serialize, Clone)] pub struct Client { @@ -131,8 +130,7 @@ impl ConnectionManager { restart: bool, recording: bool, from_switch: bool, - #[cfg(not(any(target_os = "ios")))] - tx: mpsc::UnboundedSender, + #[cfg(not(any(target_os = "ios")))] tx: mpsc::UnboundedSender, ) { let client = Client { id, @@ -303,42 +301,12 @@ pub fn switch_back(id: i32) { #[cfg(not(any(target_os = "android", target_os = "ios")))] impl IpcTaskRunner { - #[cfg(windows)] - async fn enable_cliprdr_file_context(&mut self, conn_id: i32, enabled: bool) { - if conn_id == 0 { - return; - } - - let pre_enabled = ContextSend::is_enabled(); - ContextSend::enable(enabled); - if !pre_enabled && ContextSend::is_enabled() { - allow_err!( - self.stream - .send(&Data::ClipboardFile(clipboard::ClipboardFile::MonitorReady)) - .await - ); - } - set_conn_enabled(conn_id, enabled); - if !enabled { - ContextSend::proc(|context: &mut Box| -> u32 { - empty_clipboard(context, conn_id); - 0 - }); - } - } - async fn run(&mut self) { use hbb_common::config::LocalConfig; // for tmp use, without real conn id let mut write_jobs: Vec = Vec::new(); - #[cfg(windows)] - if self.conn_id > 0 { - self.enable_cliprdr_file_context(self.conn_id, self.file_transfer_enabled) - .await; - } - #[cfg(windows)] let rx_clip1; let mut rx_clip; @@ -382,15 +350,11 @@ impl IpcTaskRunner { break; } Data::Close => { - #[cfg(windows)] - self.enable_cliprdr_file_context(self.conn_id, false).await; log::info!("cm ipc connection closed from connection request"); break; } Data::Disconnected => { self.close = false; - #[cfg(windows)] - self.enable_cliprdr_file_context(self.conn_id, false).await; log::info!("cm ipc connection disconnect"); break; } @@ -414,21 +378,18 @@ impl IpcTaskRunner { handle_fs(fs, &mut write_jobs, &self.tx).await; } } - #[cfg(windows)] + #[cfg(not(any(target_os = "android", target_os = "ios")))] Data::ClipboardFile(_clip) => { #[cfg(windows)] { - let conn_id = self.conn_id; - ContextSend::proc(|context: &mut Box| -> u32 { - clipboard::server_clip_file(context, conn_id, _clip) - }); + if !_clip.is_stopping_allowed() || self.file_transfer_enabled { + let conn_id = self.conn_id; + ContextSend::proc(|context: &mut Box| -> u32 { + clipboard::server_clip_file(context, conn_id, _clip) + }); + } } } - #[cfg(windows)] - Data::ClipboardFileEnabled(_enabled) => { - #[cfg(windows)] - self.enable_cliprdr_file_context(self.conn_id, _enabled).await; - } Data::Theme(dark) => { self.cm.change_theme(dark); } @@ -457,6 +418,11 @@ impl IpcTaskRunner { } } Some(data) = self.rx.recv() => { + if let Data::SwitchPermission{name, enabled} = &data { + if name == "file" { + self.file_transfer_enabled = *enabled; + } + } if self.stream.send(&data).await.is_err() { break; } @@ -464,7 +430,9 @@ impl IpcTaskRunner { clip_file = rx_clip.recv() => match clip_file { Some(_clip) => { #[cfg(windows)] - allow_err!(self.tx.send(Data::ClipboardFile(_clip))); + if !_clip.is_stopping_allowed() || self.file_transfer_enabled { + allow_err!(self.tx.send(Data::ClipboardFile(_clip))); + } } None => { // @@ -517,6 +485,13 @@ pub async fn start_ipc(cm: ConnectionManager) { allow_err!(crate::privacy_win_mag::start()); }); + #[cfg(target_os = "windows")] + ContextSend::enable( + Config::get_option("enable-file-transfer").is_empty(), + true, + crate::is_server(), + ); + match ipc::new_listener("_cm").await { Ok(mut incoming) => { while let Some(result) = incoming.next().await { diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 38e29b056..0945e59af 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -857,6 +857,8 @@ async fn check_connect_status_(reconnect: bool, rx: mpsc::UnboundedReceiver { *OPTIONS.lock().unwrap() = v; *OPTION_SYNCED.lock().unwrap() = true; + + #[cfg(target_os="windows")] + { + let b = OPTIONS.lock().unwrap().get("enable-file-transfer").map(|x| x.to_string()).unwrap_or_default(); + if b != enable_file_transfer { + clipboard::ContextSend::enable( + b.is_empty(), + true, + crate::is_server(), + ); + enable_file_transfer = b; + } + } } Ok(Some(ipc::Data::Config((name, Some(value))))) => { if name == "id" { diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 5fd1ef918..aec45bdcc 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -198,6 +198,7 @@ impl Session { pub fn toggle_option(&mut self, name: String) { let msg = self.lc.write().unwrap().toggle_option(name.clone()); + #[cfg(not(feature = "flutter"))] if name == "enable-file-transfer" { self.send(Data::ToggleClipboardFile); } From a903ec065b926d230e3b17673fc36ac48706ab1e Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 18 Jun 2023 22:55:38 +0800 Subject: [PATCH 02/13] win, clipboard, debug Signed-off-by: fufesou --- libs/clipboard/src/context_send.rs | 4 +- libs/clipboard/src/lib.rs | 63 ++++++++++++++++++------------ src/ui_cm_interface.rs | 1 + 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index 896def40e..f640639a4 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -62,7 +62,9 @@ impl ContextSend { if lock.addr != 0 { unsafe { let mut context = Box::from_raw(lock.addr as *mut CliprdrClientContext); - f(&mut context) + let code = f(&mut context); + std::mem::forget(context); + code } } else { 0 diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index dc1d4ca74..33107f121 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -18,6 +18,8 @@ pub mod cliprdr; pub mod context_send; pub use context_send::*; +const ERR_CODE_SERVER_FUNCTION_NONE: u32 = 0x00000001; + #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(tag = "t", content = "c")] pub enum ClipboardFile { @@ -247,8 +249,12 @@ pub fn server_monitor_ready(context: &mut Box, conn_id: i3 msgFlags: 0 as UINT16, dataLen: 0 as UINT32, }; - let ret = ((**context).MonitorReady.unwrap())(&mut (**context), &monitor_ready); - ret as u32 + if let Some(f) = (**context).MonitorReady { + let ret = f(&mut (**context), &monitor_ready); + ret as u32 + } else { + ERR_CODE_SERVER_FUNCTION_NONE + } } } @@ -289,7 +295,11 @@ pub fn server_format_list( formats: formats.as_mut_ptr(), }; - let ret = ((**context).ServerFormatList.unwrap())(&mut (**context), &format_list); + let ret = if let Some(f) = (**context).ServerFormatList { + f(&mut (**context), &format_list) + } else { + ERR_CODE_SERVER_FUNCTION_NONE + }; for f in formats { if !f.formatName.is_null() { @@ -315,10 +325,11 @@ pub fn server_format_list_response( dataLen: 0 as UINT32, }; - let ret = - (**context).ServerFormatListResponse.unwrap()(&mut (**context), &format_list_response); - - ret as u32 + if let Some(f) = (**context).ServerFormatListResponse { + f(&mut (**context), &format_list_response) + } else { + ERR_CODE_SERVER_FUNCTION_NONE + } } } @@ -335,9 +346,11 @@ pub fn server_format_data_request( dataLen: 0 as UINT32, requestedFormatId: requested_format_id as UINT32, }; - let ret = - ((**context).ServerFormatDataRequest.unwrap())(&mut (**context), &format_data_request); - ret as u32 + if let Some(f) = (**context).ServerFormatDataRequest { + f(&mut (**context), &format_data_request) + } else { + ERR_CODE_SERVER_FUNCTION_NONE + } } } @@ -355,11 +368,11 @@ pub fn server_format_data_response( dataLen: format_data.len() as UINT32, requestedFormatData: format_data.as_mut_ptr(), }; - let ret = ((**context).ServerFormatDataResponse.unwrap())( - &mut (**context), - &format_data_response, - ); - ret as u32 + if let Some(f) = (**context).ServerFormatDataResponse { + f(&mut (**context), &format_data_response) + } else { + ERR_CODE_SERVER_FUNCTION_NONE + } } } @@ -390,11 +403,11 @@ pub fn server_file_contents_request( haveClipDataId: if have_clip_data_id { TRUE } else { FALSE }, clipDataId: clip_data_id as UINT32, }; - let ret = ((**context).ServerFileContentsRequest.unwrap())( - &mut (**context), - &file_contents_request, - ); - ret as u32 + if let Some(f) = (**context).ServerFileContentsRequest { + f(&mut (**context), &file_contents_request) + } else { + ERR_CODE_SERVER_FUNCTION_NONE + } } } @@ -415,11 +428,11 @@ pub fn server_file_contents_response( cbRequested: requested_data.len() as UINT32, requestedData: requested_data.as_mut_ptr(), }; - let ret = ((**context).ServerFileContentsResponse.unwrap())( - &mut (**context), - &file_contents_response, - ); - ret as u32 + if let Some(f) = (**context).ServerFileContentsResponse { + f(&mut (**context), &file_contents_response) + } else { + ERR_CODE_SERVER_FUNCTION_NONE + } } } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index b4b5636b1..3f05d1d12 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -419,6 +419,7 @@ impl IpcTaskRunner { } Some(data) = self.rx.recv() => { if let Data::SwitchPermission{name, enabled} = &data { + #[cfg(windows)] if name == "file" { self.file_transfer_enabled = *enabled; } From c5698df3aa9dc3c96be305910aad0e9060d1b967 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 20:49:04 +0800 Subject: [PATCH 03/13] add debug msg Signed-off-by: fufesou --- libs/clipboard/src/lib.rs | 6 +++--- src/client/io_loop.rs | 13 ++++++------- src/server/connection.rs | 6 +++++- src/ui_cm_interface.rs | 18 ++++++++++++++---- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index 33107f121..728158358 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -485,9 +485,9 @@ extern "C" fn client_format_list( let data = ClipboardFile::FormatList { format_list }; // no need to handle result here if conn_id == 0 { - VEC_MSG_CHANNEL - .read() - .unwrap() + // msg_channel is used for debug, VEC_MSG_CHANNEL cannot be inspected by the debugger. + let msg_channel = VEC_MSG_CHANNEL.read().unwrap(); + msg_channel .iter() .for_each(|msg_channel| allow_err!(msg_channel.sender.send(data.clone()))); } else { diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 53e910f1a..c4b344b11 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -207,13 +207,12 @@ impl Remote { #[cfg(windows)] match _msg { Some(clip) => { - let mut send_msg = true; - if clip.is_stopping_allowed() { - if !(*self.handler.server_file_transfer_enabled.read().unwrap() && self.handler.lc.read().unwrap().enable_file_transfer.v) { - send_msg = false; - } - } - if send_msg { + let is_stopping_allowed = clip.is_stopping_allowed(); + let server_file_transfer_enabled = *self.handler.server_file_transfer_enabled.read().unwrap(); + let enable_file_transfer = self.handler.lc.read().unwrap().enable_file_transfer.v; + let stop = is_stopping_allowed && !(server_file_transfer_enabled && enable_file_transfer); + log::debug!("Process clipboard message from system, stop: {}, is_stopping_allowed: {}, server_file_transfer_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, server_file_transfer_enabled, file_transfer_enabled); + if !stop { allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 960360d6a..6f0ce6a47 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -438,7 +438,11 @@ impl Connection { } #[cfg(windows)] ipc::Data::ClipboardFile(clip) => { - if !clip.is_stopping_allowed() || conn.file_transfer_enabled() { + let is_stopping_allowed = clip.is_stopping_allowed(); + let enable_file_transfer = conn.file_transfer_enabled(); + let stop = is_stopping_allowed && !enable_file_transfer; + log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); + if !stop { allow_err!(conn.stream.send(&clip_2_msg(clip)).await); } } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index 3f05d1d12..485ce3750 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -16,7 +16,7 @@ use crate::ipc::Connection; #[cfg(not(any(target_os = "ios")))] use crate::ipc::{self, Data}; #[cfg(windows)] -use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, ContextSend}; +use clipboard::{cliprdr::CliprdrClientContext, ContextSend}; #[cfg(not(any(target_os = "android", target_os = "ios")))] use hbb_common::tokio::sync::mpsc::unbounded_channel; #[cfg(windows)] @@ -382,7 +382,11 @@ impl IpcTaskRunner { Data::ClipboardFile(_clip) => { #[cfg(windows)] { - if !_clip.is_stopping_allowed() || self.file_transfer_enabled { + let is_stopping_allowed = _clip.is_stopping_allowed(); + let file_transfer_enabled = self.file_transfer_enabled; + let stop = is_stopping_allowed && !file_transfer_enabled; + log::debug!("Process clipboard message from peer, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); + if !stop { let conn_id = self.conn_id; ContextSend::proc(|context: &mut Box| -> u32 { clipboard::server_clip_file(context, conn_id, _clip) @@ -431,8 +435,14 @@ impl IpcTaskRunner { clip_file = rx_clip.recv() => match clip_file { Some(_clip) => { #[cfg(windows)] - if !_clip.is_stopping_allowed() || self.file_transfer_enabled { - allow_err!(self.tx.send(Data::ClipboardFile(_clip))); + { + let is_stopping_allowed = _clip.is_stopping_allowed(); + let file_transfer_enabled = self.file_transfer_enabled; + let stop = is_stopping_allowed && !file_transfer_enabled; + log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); + if !stop { + allow_err!(self.tx.send(Data::ClipboardFile(_clip))); + } } } None => { From 681fd736c96525b822abd65dec1694a8622ed310 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 19:42:02 +0800 Subject: [PATCH 04/13] win, clipboard debug Signed-off-by: fufesou --- src/ui_cm_interface.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index 485ce3750..a0c10a77e 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -326,6 +326,17 @@ impl IpcTaskRunner { (_tx_clip, rx_clip) = unbounded_channel::(); } + #[cfg(windows)] + { + if ContextSend::is_server_enabled() { + allow_err!( + self.stream + .send(&Data::ClipboardFile(clipboard::ClipboardFile::MonitorReady)) + .await + ); + } + } + self.running = false; loop { tokio::select! { From 66b5b0b5806db845a6060ad03d5bc7ce7c8855de Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 20:52:32 +0800 Subject: [PATCH 05/13] fix build Signed-off-by: fufesou --- src/client/io_loop.rs | 4 ++-- src/server/connection.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index c4b344b11..18f5b7c4a 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -209,8 +209,8 @@ impl Remote { Some(clip) => { let is_stopping_allowed = clip.is_stopping_allowed(); let server_file_transfer_enabled = *self.handler.server_file_transfer_enabled.read().unwrap(); - let enable_file_transfer = self.handler.lc.read().unwrap().enable_file_transfer.v; - let stop = is_stopping_allowed && !(server_file_transfer_enabled && enable_file_transfer); + let file_transfer_enabled = self.handler.lc.read().unwrap().enable_file_transfer.v; + let stop = is_stopping_allowed && !(server_file_transfer_enabled && file_transfer_enabled); log::debug!("Process clipboard message from system, stop: {}, is_stopping_allowed: {}, server_file_transfer_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, server_file_transfer_enabled, file_transfer_enabled); if !stop { allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); diff --git a/src/server/connection.rs b/src/server/connection.rs index 6f0ce6a47..963c567e2 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -439,8 +439,8 @@ impl Connection { #[cfg(windows)] ipc::Data::ClipboardFile(clip) => { let is_stopping_allowed = clip.is_stopping_allowed(); - let enable_file_transfer = conn.file_transfer_enabled(); - let stop = is_stopping_allowed && !enable_file_transfer; + let file_transfer_enabled = conn.file_transfer_enabled(); + let stop = is_stopping_allowed && !file_transfer_enabled; log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); if !stop { allow_err!(conn.stream.send(&clip_2_msg(clip)).await); From f12e86be3a73c0ed7878cf17c27b0c43db9271a3 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 21:23:16 +0800 Subject: [PATCH 06/13] empty clipboard after session Signed-off-by: fufesou --- src/client/io_loop.rs | 11 ++++++++++- src/ui_cm_interface.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 18f5b7c4a..0769d3bea 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -6,7 +6,7 @@ use std::sync::{ }; #[cfg(windows)] -use clipboard::{cliprdr::CliprdrClientContext, ClipboardFile, ContextSend}; +use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, ContextSend}; use crossbeam_queue::ArrayQueue; use hbb_common::config::{PeerConfig, TransferSerde}; use hbb_common::fs::{ @@ -270,6 +270,15 @@ impl Remote { } #[cfg(not(any(target_os = "android", target_os = "ios")))] Client::try_stop_clipboard(&self.handler.session_id); + + #[cfg(windows)] + { + let conn_id = self.client_conn_id; + ContextSend::proc(|context: &mut Box| -> u32 { + empty_clipboard(context, conn_id); + 0 + }); + } } fn handle_job_status(&mut self, id: i32, file_num: i32, err: Option) { diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index a0c10a77e..c1ef08e7f 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -16,7 +16,7 @@ use crate::ipc::Connection; #[cfg(not(any(target_os = "ios")))] use crate::ipc::{self, Data}; #[cfg(windows)] -use clipboard::{cliprdr::CliprdrClientContext, ContextSend}; +use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, ContextSend}; #[cfg(not(any(target_os = "android", target_os = "ios")))] use hbb_common::tokio::sync::mpsc::unbounded_channel; #[cfg(windows)] @@ -171,6 +171,14 @@ impl ConnectionManager { .map(|c| c.disconnected = true); } + #[cfg(windows)] + { + ContextSend::proc(|context: &mut Box| -> u32 { + empty_clipboard(context, id); + 0 + }); + } + #[cfg(any(target_os = "android"))] if CLIENTS .read() From 224085363340f6d319ea127f1ccc4196478db096 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 21:44:32 +0800 Subject: [PATCH 07/13] debug server clipboard enabled Signed-off-by: fufesou --- libs/clipboard/src/context_send.rs | 1 + src/server/connection.rs | 8 +++++--- src/ui_cm_interface.rs | 10 ++++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index f640639a4..2c9780249 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -19,6 +19,7 @@ impl ContextSend { } } + #[inline] pub fn is_server_enabled() -> bool { CONTEXT_SEND.lock().unwrap().server_enabled } diff --git a/src/server/connection.rs b/src/server/connection.rs index 963c567e2..afcac136f 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -439,9 +439,10 @@ impl Connection { #[cfg(windows)] ipc::Data::ClipboardFile(clip) => { let is_stopping_allowed = clip.is_stopping_allowed(); + let is_clipboard_enabled = clipboard::ContextSend::is_server_enabled(); let file_transfer_enabled = conn.file_transfer_enabled(); - let stop = is_stopping_allowed && !file_transfer_enabled; - log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); + let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); + log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); if !stop { allow_err!(conn.stream.send(&clip_2_msg(clip)).await); } @@ -1639,7 +1640,8 @@ impl Connection { update_clipboard(_cb, None); } } - Some(message::Union::Cliprdr(_clip)) => { + Some(message::Union::Cliprdr(_clip)) => + { #[cfg(windows)] if let Some(clip) = msg_2_clip(_clip) { self.send_to_cm(ipc::Data::ClipboardFile(clip)) diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index c1ef08e7f..dc81b905e 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -402,9 +402,10 @@ impl IpcTaskRunner { #[cfg(windows)] { let is_stopping_allowed = _clip.is_stopping_allowed(); + let is_clipboard_enabled = ContextSend::is_server_enabled(); let file_transfer_enabled = self.file_transfer_enabled; - let stop = is_stopping_allowed && !file_transfer_enabled; - log::debug!("Process clipboard message from peer, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); + let stop = !is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); + log::debug!("Process clipboard message from peer, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); if !stop { let conn_id = self.conn_id; ContextSend::proc(|context: &mut Box| -> u32 { @@ -456,9 +457,10 @@ impl IpcTaskRunner { #[cfg(windows)] { let is_stopping_allowed = _clip.is_stopping_allowed(); + let is_clipboard_enabled = ContextSend::is_server_enabled(); let file_transfer_enabled = self.file_transfer_enabled; - let stop = is_stopping_allowed && !file_transfer_enabled; - log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); + let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); + log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); if !stop { allow_err!(self.tx.send(Data::ClipboardFile(_clip))); } From 5a8c2d9cd0dfa2589ffe4aea6489c93d95387cf2 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 22:06:08 +0800 Subject: [PATCH 08/13] win, clipboard, debug Signed-off-by: fufesou --- libs/clipboard/src/context_send.rs | 16 ++++++++-------- src/server/connection.rs | 5 ++--- src/ui_cm_interface.rs | 6 +++--- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index 2c9780249..e847e3a72 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -7,24 +7,24 @@ lazy_static::lazy_static! { } pub struct ContextSend { - server_enabled: bool, + cm_enabled: bool, addr: u64, } impl ContextSend { fn new() -> Self { Self { - server_enabled: false, + cm_enabled: false, addr: 0, } } #[inline] - pub fn is_server_enabled() -> bool { - CONTEXT_SEND.lock().unwrap().server_enabled + pub fn is_cm_enabled() -> bool { + CONTEXT_SEND.lock().unwrap().cm_enabled } - pub fn enable(enabled: bool, is_server_side: bool, is_server_process: bool) { + pub fn enable(enabled: bool, is_cm_side: bool, is_server_process: bool) { let mut lock = CONTEXT_SEND.lock().unwrap(); if enabled { if lock.addr == 0 { @@ -41,8 +41,8 @@ impl ContextSend { } } } - if is_server_side { - lock.server_enabled = true; + if is_cm_side { + lock.cm_enabled = true; } } else { if lock.addr != 0 { @@ -53,7 +53,7 @@ impl ContextSend { log::info!("clipboard context for file transfer destroyed."); lock.addr = 0; } - lock.server_enabled = false; + lock.cm_enabled = false; } } } diff --git a/src/server/connection.rs b/src/server/connection.rs index afcac136f..968c2ed80 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -439,10 +439,9 @@ impl Connection { #[cfg(windows)] ipc::Data::ClipboardFile(clip) => { let is_stopping_allowed = clip.is_stopping_allowed(); - let is_clipboard_enabled = clipboard::ContextSend::is_server_enabled(); let file_transfer_enabled = conn.file_transfer_enabled(); - let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); - log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); + let stop = is_stopping_allowed && !file_transfer_enabled; + log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); if !stop { allow_err!(conn.stream.send(&clip_2_msg(clip)).await); } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index dc81b905e..4c9d54153 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -336,7 +336,7 @@ impl IpcTaskRunner { #[cfg(windows)] { - if ContextSend::is_server_enabled() { + if ContextSend::is_cm_enabled() { allow_err!( self.stream .send(&Data::ClipboardFile(clipboard::ClipboardFile::MonitorReady)) @@ -402,7 +402,7 @@ impl IpcTaskRunner { #[cfg(windows)] { let is_stopping_allowed = _clip.is_stopping_allowed(); - let is_clipboard_enabled = ContextSend::is_server_enabled(); + let is_clipboard_enabled = ContextSend::is_cm_enabled(); let file_transfer_enabled = self.file_transfer_enabled; let stop = !is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); log::debug!("Process clipboard message from peer, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); @@ -457,7 +457,7 @@ impl IpcTaskRunner { #[cfg(windows)] { let is_stopping_allowed = _clip.is_stopping_allowed(); - let is_clipboard_enabled = ContextSend::is_server_enabled(); + let is_clipboard_enabled = ContextSend::is_cm_enabled(); let file_transfer_enabled = self.file_transfer_enabled; let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); From 733e4236c4db494e3c9cac5ef25278cf6398afd3 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 22:52:17 +0800 Subject: [PATCH 09/13] avoid waiting too long if the clipboard message is blocked Signed-off-by: fufesou --- libs/clipboard/src/cliprdr.h | 9 +- libs/clipboard/src/cliprdr.rs | 23 ++-- libs/clipboard/src/context_send.rs | 7 + libs/clipboard/src/windows/wf_cliprdr.c | 171 +++++++++++------------- src/client/io_loop.rs | 4 +- src/server/connection.rs | 4 +- src/ui_cm_interface.rs | 8 +- 7 files changed, 111 insertions(+), 115 deletions(-) diff --git a/libs/clipboard/src/cliprdr.h b/libs/clipboard/src/cliprdr.h index 2fa16e201..57cae5f8f 100644 --- a/libs/clipboard/src/cliprdr.h +++ b/libs/clipboard/src/cliprdr.h @@ -194,10 +194,11 @@ extern "C" // TODO: hide more members of clipboard context struct _cliprdr_client_context { - void *custom; - BOOL enableFiles; - BOOL enableOthers; + void *Custom; + BOOL EnableFiles; + BOOL EnableOthers; + BOOL IsStopped; pcCliprdrServerCapabilities ServerCapabilities; pcCliprdrClientCapabilities ClientCapabilities; pcCliprdrMonitorReady MonitorReady; @@ -219,7 +220,7 @@ extern "C" pcCliprdrClientFileContentsResponse ClientFileContentsResponse; pcCliprdrServerFileContentsResponse ServerFileContentsResponse; - UINT32 lastRequestedFormatId; + UINT32 LastRequestedFormatId; }; #ifdef __cplusplus diff --git a/libs/clipboard/src/cliprdr.rs b/libs/clipboard/src/cliprdr.rs index 2bc626536..e5bc3e7ef 100644 --- a/libs/clipboard/src/cliprdr.rs +++ b/libs/clipboard/src/cliprdr.rs @@ -449,9 +449,10 @@ pub type pcCliprdrServerFileContentsResponse = ::std::option::Option< #[repr(C)] #[derive(Debug, Clone)] pub struct _cliprdr_client_context { - pub custom: *mut ::std::os::raw::c_void, - pub enableFiles: BOOL, - pub enableOthers: BOOL, + pub Custom: *mut ::std::os::raw::c_void, + pub EnableFiles: BOOL, + pub EnableOthers: BOOL, + pub IsStopped: BOOL, pub ServerCapabilities: pcCliprdrServerCapabilities, pub ClientCapabilities: pcCliprdrClientCapabilities, pub MonitorReady: pcCliprdrMonitorReady, @@ -472,7 +473,7 @@ pub struct _cliprdr_client_context { pub ServerFileContentsRequest: pcCliprdrServerFileContentsRequest, pub ClientFileContentsResponse: pcCliprdrClientFileContentsResponse, pub ServerFileContentsResponse: pcCliprdrServerFileContentsResponse, - pub lastRequestedFormatId: UINT32, + pub LastRequestedFormatId: UINT32, } // #[link(name = "user32")] @@ -480,10 +481,7 @@ pub struct _cliprdr_client_context { extern "C" { pub(crate) fn init_cliprdr(context: *mut CliprdrClientContext) -> BOOL; pub(crate) fn uninit_cliprdr(context: *mut CliprdrClientContext) -> BOOL; - pub(crate) fn empty_cliprdr( - context: *mut CliprdrClientContext, - connID: UINT32, - ) -> BOOL; + pub(crate) fn empty_cliprdr(context: *mut CliprdrClientContext, connID: UINT32) -> BOOL; } #[derive(Error, Debug)] @@ -508,9 +506,10 @@ impl CliprdrClientContext { client_file_contents_response: pcCliprdrClientFileContentsResponse, ) -> Result, CliprdrError> { let context = CliprdrClientContext { - custom: 0 as *mut _, - enableFiles: if enable_files { TRUE } else { FALSE }, - enableOthers: if enable_others { TRUE } else { FALSE }, + Custom: 0 as *mut _, + EnableFiles: if enable_files { TRUE } else { FALSE }, + EnableOthers: if enable_others { TRUE } else { FALSE }, + IsStopped: FALSE, ServerCapabilities: None, ClientCapabilities: None, MonitorReady: None, @@ -531,7 +530,7 @@ impl CliprdrClientContext { ServerFileContentsRequest: None, ClientFileContentsResponse: client_file_contents_response, ServerFileContentsResponse: None, - lastRequestedFormatId: 0, + LastRequestedFormatId: 0, }; let mut context = Box::new(context); unsafe { diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index e847e3a72..a195850f2 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -24,6 +24,13 @@ impl ContextSend { CONTEXT_SEND.lock().unwrap().cm_enabled } + pub fn set_is_stopped() { + let _res = Self::proc(|c| { + c.IsStopped = TRUE; + 0 + }); + } + pub fn enable(enabled: bool, is_cm_side: bool, is_server_process: bool) { let mut lock = CONTEXT_SEND.lock().unwrap(); if enabled { diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index c17390cb4..8bfc69d93 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -1,3 +1,5 @@ +// to-do: TOO MANY compilation warnings. Fix them. + /** * FreeRDP: A Remote Desktop Protocol Implementation * Windows Clipboard Redirection @@ -136,11 +138,13 @@ typedef struct _FORMAT_IDS FORMAT_IDS; #define TAG "windows" #ifdef WITH_DEBUG_CLIPRDR -#define DEBUG_CLIPRDR(fmt, ...) fprintf(stderr, "DEBUG %s[%d] %s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);fflush(stderr) +#define DEBUG_CLIPRDR(fmt, ...) \ + fprintf(stderr, "DEBUG %s[%d] %s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + fflush(stderr) #else #define DEBUG_CLIPRDR(fmt, ...) \ - do \ - { \ + do \ + { \ } while (0) #endif @@ -1440,6 +1444,55 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID) return rc; } +UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void *data) +{ + UINT rc = ERROR_INTERNAL_ERROR; + clipboard->context->IsStopped = FALSE; + // with default 3min timeout + for (int i = 0; i < 20 * 60 * 3; i++) + { + DWORD waitRes = WaitForSingleObject(event, 50); + if (waitRes == WAIT_TIMEOUT && clipboard->context->IsStopped == FALSE) + { + continue; + } + + if (clipboard->context->IsStopped == TRUE) + { + wf_do_empty_cliprdr(clipboard); + } + + if (waitRes != WAIT_OBJECT_0) + { + return ERROR_INTERNAL_ERROR; + } + + if (!ResetEvent(event)) + { + // NOTE: critical error here, crash may be better + rc = ERROR_INTERNAL_ERROR; + } + + if (data == NULL) + { + rc = ERROR_INTERNAL_ERROR; + } + + return rc; + } + + if (data != NULL) + { + if (!ResetEvent(event)) + { + // NOTE: critical error here, crash may be better + } + return ERROR_SUCCESS; + } + + return ERROR_INTERNAL_ERROR; +} + static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UINT32 formatId) { UINT rc; @@ -1460,44 +1513,7 @@ static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UIN return rc; } - // with default 3min timeout - for (int i = 0; i < 20 * 60 * 3; i++) - { - DWORD waitRes = WaitForSingleObject(clipboard->response_data_event, 50); - if (waitRes == WAIT_TIMEOUT) - { - continue; - } - - if (waitRes != WAIT_OBJECT_0) - { - return ERROR_INTERNAL_ERROR; - } - - if (!ResetEvent(clipboard->response_data_event)) - { - // NOTE: critical error here, crash may be better - rc = ERROR_INTERNAL_ERROR; - } - - if (!clipboard->hmem) - { - rc = ERROR_INTERNAL_ERROR; - } - - return rc; - } - - if (clipboard->hmem) - { - if (!ResetEvent(clipboard->response_data_event)) - { - // NOTE: critical error here, crash may be better - } - return ERROR_SUCCESS; - } - - return ERROR_INTERNAL_ERROR; + wait_response_event(clipboard, clipboard->response_data_event, clipboard->hmem); } UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, const void *streamid, ULONG index, @@ -1525,43 +1541,7 @@ UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, co return rc; } - // with default 3min timeout - for (int i = 0; i < 20 * 60 * 3; i++) - { - DWORD waitRes = WaitForSingleObject(clipboard->req_fevent, 50); - if (waitRes == WAIT_TIMEOUT) - { - continue; - } - - if (waitRes != WAIT_OBJECT_0) - { - return ERROR_INTERNAL_ERROR; - } - - if (!ResetEvent(clipboard->req_fevent)) - { - // NOTE: critical error here, crash may be better - rc = ERROR_INTERNAL_ERROR; - } - if (!clipboard->req_fdata) - { - rc = ERROR_INTERNAL_ERROR; - } - - return rc; - } - - if (clipboard->req_fdata) - { - if (!ResetEvent(clipboard->req_fevent)) - { - // NOTE: critical error here, crash may be better - } - return ERROR_SUCCESS; - } - - return ERROR_INTERNAL_ERROR; + return wait_response_event(clipboard, clipboard->req_fevent, clipboard->req_fdata); } static UINT cliprdr_send_response_filecontents( @@ -2069,8 +2049,8 @@ static BOOL wf_cliprdr_traverse_directory(wfClipboard *clipboard, WCHAR *Dir, si while (FindNextFileW(hFind, &FindFileData)) { // if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && - // wcscmp(FindFileData.cFileName, _T(".")) == 0 || - // wcscmp(FindFileData.cFileName, _T("..")) == 0) + // wcscmp(FindFileData.cFileName, _T(".")) == 0 || + // wcscmp(FindFileData.cFileName, _T("..")) == 0) if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && wcscmp(FindFileData.cFileName, L".") == 0 || wcscmp(FindFileData.cFileName, L"..") == 0) @@ -2123,7 +2103,8 @@ static UINT wf_cliprdr_send_client_capabilities(wfClipboard *clipboard) return ERROR_INTERNAL_ERROR; // Ignore ClientCapabilities for now - if (!clipboard->context->ClientCapabilities) { + if (!clipboard->context->ClientCapabilities) + { return CHANNEL_RC_OK; } @@ -2147,7 +2128,7 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext *context, const CLIPRDR_MONITOR_READY *monitorReady) { UINT rc; - wfClipboard *clipboard = (wfClipboard *)context->custom; + wfClipboard *clipboard = (wfClipboard *)context->Custom; if (!context || !monitorReady) return ERROR_INTERNAL_ERROR; @@ -2171,7 +2152,7 @@ static UINT wf_cliprdr_server_capabilities(CliprdrClientContext *context, { UINT32 index; CLIPRDR_CAPABILITY_SET *capabilitySet; - wfClipboard *clipboard = (wfClipboard *)context->custom; + wfClipboard *clipboard = (wfClipboard *)context->Custom; if (!context || !capabilities) return ERROR_INTERNAL_ERROR; @@ -2205,7 +2186,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context, UINT32 i; formatMapping *mapping; CLIPRDR_FORMAT *format; - wfClipboard *clipboard = (wfClipboard *)context->custom; + wfClipboard *clipboard = (wfClipboard *)context->Custom; if (!clear_format_map(clipboard)) return ERROR_INTERNAL_ERROR; @@ -2241,7 +2222,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context, if (file_transferring(clipboard)) { - if (context->enableFiles) + if (context->EnableFiles) { UINT32 *p_conn_id = (UINT32 *)calloc(1, sizeof(UINT32)); *p_conn_id = formatList->connID; @@ -2255,7 +2236,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context, } else { - if (context->enableOthers) + if (context->EnableOthers) { if (!try_open_clipboard(clipboard->hwnd)) return CHANNEL_RC_OK; /* Ignore, other app holding clipboard */ @@ -2264,7 +2245,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context, { // Modified: do not apply delayed rendering // for (i = 0; i < (UINT32)clipboard->map_size; i++) - // SetClipboardData(clipboard->format_mappings[i].local_format_id, NULL); + // SetClipboardData(clipboard->format_mappings[i].local_format_id, NULL); FORMAT_IDS *format_ids = (FORMAT_IDS *)calloc(1, sizeof(FORMAT_IDS)); format_ids->connID = formatList->connID; @@ -2399,7 +2380,7 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context, goto exit; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { @@ -2579,7 +2560,7 @@ wf_cliprdr_server_format_data_response(CliprdrClientContext *context, break; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { rc = ERROR_INTERNAL_ERROR; @@ -2660,7 +2641,7 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context, goto exit; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { @@ -2838,7 +2819,7 @@ exit: } // if (sRc != CHANNEL_RC_OK) - // return sRc; + // return sRc; return rc; } @@ -2863,7 +2844,7 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context, break; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { rc = ERROR_INTERNAL_ERROR; @@ -2951,7 +2932,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr) cliprdr->ServerFormatDataResponse = wf_cliprdr_server_format_data_response; cliprdr->ServerFileContentsRequest = wf_cliprdr_server_file_contents_request; cliprdr->ServerFileContentsResponse = wf_cliprdr_server_file_contents_response; - cliprdr->custom = (void *)clipboard; + cliprdr->Custom = (void *)clipboard; return TRUE; error: wf_cliprdr_uninit(clipboard, cliprdr); @@ -2963,7 +2944,7 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr) if (!clipboard || !cliprdr) return FALSE; - cliprdr->custom = NULL; + cliprdr->Custom = NULL; /* discard all contexts in clipboard */ if (try_open_clipboard(clipboard->hwnd)) @@ -3038,7 +3019,7 @@ BOOL empty_cliprdr(CliprdrClientContext *context, UINT32 connID) return TRUE; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { return FALSE; diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 0769d3bea..2957a0bc8 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -212,7 +212,9 @@ impl Remote { let file_transfer_enabled = self.handler.lc.read().unwrap().enable_file_transfer.v; let stop = is_stopping_allowed && !(server_file_transfer_enabled && file_transfer_enabled); log::debug!("Process clipboard message from system, stop: {}, is_stopping_allowed: {}, server_file_transfer_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, server_file_transfer_enabled, file_transfer_enabled); - if !stop { + if stop { + ContextSend::set_is_stopped(); + } else { allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 968c2ed80..7ca6aac72 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -442,7 +442,9 @@ impl Connection { let file_transfer_enabled = conn.file_transfer_enabled(); let stop = is_stopping_allowed && !file_transfer_enabled; log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); - if !stop { + if stop { + clipboard::ContextSend::set_is_stopped(); + } else { allow_err!(conn.stream.send(&clip_2_msg(clip)).await); } } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index 4c9d54153..067c22de1 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -406,7 +406,9 @@ impl IpcTaskRunner { let file_transfer_enabled = self.file_transfer_enabled; let stop = !is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); log::debug!("Process clipboard message from peer, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); - if !stop { + if stop { + ContextSend::set_is_stopped(); + } else { let conn_id = self.conn_id; ContextSend::proc(|context: &mut Box| -> u32 { clipboard::server_clip_file(context, conn_id, _clip) @@ -461,7 +463,9 @@ impl IpcTaskRunner { let file_transfer_enabled = self.file_transfer_enabled; let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); - if !stop { + if stop { + ContextSend::set_is_stopped(); + } else { allow_err!(self.tx.send(Data::ClipboardFile(_clip))); } } From 773bb1bad71374a7baedb7aa4dc647a2fdc41f3d Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 23:14:19 +0800 Subject: [PATCH 10/13] win, clipboard, debug Signed-off-by: fufesou --- libs/clipboard/src/windows/wf_cliprdr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index 8bfc69d93..a097bbf83 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -1446,7 +1446,7 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID) UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void *data) { - UINT rc = ERROR_INTERNAL_ERROR; + UINT rc = ERROR_SUCCESS; clipboard->context->IsStopped = FALSE; // with default 3min timeout for (int i = 0; i < 20 * 60 * 3; i++) @@ -1460,6 +1460,7 @@ UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void *data) if (clipboard->context->IsStopped == TRUE) { wf_do_empty_cliprdr(clipboard); + rc = ERROR_INTERNAL_ERROR; } if (waitRes != WAIT_OBJECT_0) From 53a1aeac61df082570ab7eb79e3d916153b84f59 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 20 Jun 2023 00:05:23 +0800 Subject: [PATCH 11/13] win, clipboard, debug Signed-off-by: fufesou --- libs/clipboard/src/lib.rs | 7 +++++++ src/client/io_loop.rs | 25 +++++++++++++++---------- src/ipc.rs | 1 + src/server/connection.rs | 13 ++++--------- src/ui_cm_interface.rs | 23 +++++++++++++++++++---- 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index 728158358..c63817415 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -75,6 +75,13 @@ impl ClipboardFile { _ => false, } } + + pub fn is_stopping_allowed_from_peer(&self) -> bool { + match self { + ClipboardFile::MonitorReady | ClipboardFile::FormatList { .. } => true, + _ => false, + } + } } pub fn get_client_conn_id(session_uuid: &SessionID) -> Option { diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 2957a0bc8..e830309d0 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -1556,18 +1556,23 @@ impl Remote { #[cfg(windows)] fn handle_cliprdr_msg(&self, clip: hbb_common::message_proto::Cliprdr) { - if !self.handler.lc.read().unwrap().disable_clipboard.v { - #[cfg(feature = "flutter")] - if let Some(hbb_common::message_proto::cliprdr::Union::FormatList(_)) = &clip.union { - if self.client_conn_id - != clipboard::get_client_conn_id(&crate::flutter::get_cur_session_id()) - .unwrap_or(0) - { - return; - } + #[cfg(feature = "flutter")] + if let Some(hbb_common::message_proto::cliprdr::Union::FormatList(_)) = &clip.union { + if self.client_conn_id + != clipboard::get_client_conn_id(&crate::flutter::get_cur_session_id()).unwrap_or(0) + { + return; } + } - if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) { + if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) { + let is_stopping_allowed = clip.is_stopping_allowed_from_peer(); + let file_transfer_enabled = self.handler.lc.read().unwrap().enable_file_transfer.v; + let stop = is_stopping_allowed && !file_transfer_enabled; + log::debug!( + "Process clipboard message from server peer, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", + stop, is_stopping_allowed, file_transfer_enabled); + if !stop { ContextSend::proc(|context: &mut Box| -> u32 { clipboard::server_clip_file(context, self.client_conn_id, clip) }); diff --git a/src/ipc.rs b/src/ipc.rs index c275f88dd..83a48107c 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -202,6 +202,7 @@ pub enum Data { SyncConfig(Option>), #[cfg(not(any(target_os = "android", target_os = "ios")))] ClipboardFile(ClipboardFile), + ClipboardFileEnabled(bool), PrivacyModeState((i32, PrivacyModeState)), TestRendezvousServer, #[cfg(not(any(target_os = "android", target_os = "ios")))] diff --git a/src/server/connection.rs b/src/server/connection.rs index 7ca6aac72..3c614791d 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -438,15 +438,7 @@ impl Connection { } #[cfg(windows)] ipc::Data::ClipboardFile(clip) => { - let is_stopping_allowed = clip.is_stopping_allowed(); - let file_transfer_enabled = conn.file_transfer_enabled(); - let stop = is_stopping_allowed && !file_transfer_enabled; - log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); - if stop { - clipboard::ContextSend::set_is_stopped(); - } else { - allow_err!(conn.stream.send(&clip_2_msg(clip)).await); - } + allow_err!(conn.stream.send(&clip_2_msg(clip)).await); } ipc::Data::PrivacyModeState((_, state)) => { let msg_out = match state { @@ -2078,6 +2070,9 @@ impl Connection { if let Ok(q) = o.enable_file_transfer.enum_value() { if q != BoolOption::NotSet { self.enable_file_transfer = q == BoolOption::Yes; + self.send_to_cm(ipc::Data::ClipboardFileEnabled( + self.file_transfer_enabled(), + )); } } if let Ok(q) = o.disable_clipboard.enum_value() { diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index 067c22de1..af3bf2b3a 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -72,6 +72,8 @@ struct IpcTaskRunner { conn_id: i32, #[cfg(windows)] file_transfer_enabled: bool, + #[cfg(windows)] + file_transfer_enabled_peer: bool, } lazy_static::lazy_static! { @@ -401,11 +403,13 @@ impl IpcTaskRunner { Data::ClipboardFile(_clip) => { #[cfg(windows)] { - let is_stopping_allowed = _clip.is_stopping_allowed(); + let is_stopping_allowed = _clip.is_stopping_allowed_from_peer(); let is_clipboard_enabled = ContextSend::is_cm_enabled(); let file_transfer_enabled = self.file_transfer_enabled; let stop = !is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); - log::debug!("Process clipboard message from peer, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); + log::debug!( + "Process clipboard message from client peer, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", + stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); if stop { ContextSend::set_is_stopped(); } else { @@ -416,6 +420,12 @@ impl IpcTaskRunner { } } } + Data::ClipboardFileEnabled(_enabled) => { + #[cfg(windows)] + { + self.file_transfer_enabled_peer =_enabled; + } + } Data::Theme(dark) => { self.cm.change_theme(dark); } @@ -461,8 +471,11 @@ impl IpcTaskRunner { let is_stopping_allowed = _clip.is_stopping_allowed(); let is_clipboard_enabled = ContextSend::is_cm_enabled(); let file_transfer_enabled = self.file_transfer_enabled; - let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); - log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); + let file_transfer_enabled_peer = self.file_transfer_enabled_peer; + let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled && file_transfer_enabled_peer); + log::debug!( + "Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}, file_transfer_enabled_peer: {}", + stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled, file_transfer_enabled_peer); if stop { ContextSend::set_is_stopped(); } else { @@ -492,6 +505,8 @@ impl IpcTaskRunner { conn_id: 0, #[cfg(windows)] file_transfer_enabled: false, + #[cfg(windows)] + file_transfer_enabled_peer: false, }; while task_runner.running { From 0094d306a86db4c84bbbfc4640367cfc42395acb Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 20 Jun 2023 00:32:43 +0800 Subject: [PATCH 12/13] win, clipboard, fix pointer Signed-off-by: fufesou --- libs/clipboard/src/windows/wf_cliprdr.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index a097bbf83..4d0d4532d 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -358,6 +358,7 @@ static HRESULT STDMETHODCALLTYPE CliprdrStream_Read(IStream *This, void *pv, ULO { CopyMemory(pv, clipboard->req_fdata, clipboard->req_fsize); free(clipboard->req_fdata); + clipboard->req_fdata = NULL; } *pcbRead = clipboard->req_fsize; @@ -569,6 +570,7 @@ static CliprdrStream *CliprdrStream_New(UINT32 connID, ULONG index, void *pData, instance->m_lSize.QuadPart = *((LONGLONG *)clipboard->req_fdata); free(clipboard->req_fdata); + clipboard->req_fdata = NULL; } else success = TRUE; @@ -1444,7 +1446,7 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID) return rc; } -UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void *data) +UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void **data) { UINT rc = ERROR_SUCCESS; clipboard->context->IsStopped = FALSE; @@ -1474,7 +1476,7 @@ UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void *data) rc = ERROR_INTERNAL_ERROR; } - if (data == NULL) + if ((*data) == NULL) { rc = ERROR_INTERNAL_ERROR; } @@ -1482,7 +1484,7 @@ UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void *data) return rc; } - if (data != NULL) + if ((*data) != NULL) { if (!ResetEvent(event)) { @@ -1514,7 +1516,7 @@ static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UIN return rc; } - wait_response_event(clipboard, clipboard->response_data_event, clipboard->hmem); + wait_response_event(clipboard, clipboard->response_data_event, &clipboard->hmem); } UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, const void *streamid, ULONG index, @@ -1542,7 +1544,7 @@ UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, co return rc; } - return wait_response_event(clipboard, clipboard->req_fevent, clipboard->req_fdata); + return wait_response_event(clipboard, clipboard->req_fevent, (void**)&clipboard->req_fdata); } static UINT cliprdr_send_response_filecontents( From 7740492fb062e22c319704d306afdf67a90bbd42 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 20 Jun 2023 00:50:01 +0800 Subject: [PATCH 13/13] win, clipboard, debug Signed-off-by: fufesou --- libs/clipboard/src/context_send.rs | 48 +++++++++++------------------- src/client/io_loop.rs | 2 +- src/core_main.rs | 2 +- src/ui_cm_interface.rs | 12 +++----- src/ui_interface.rs | 6 +--- 5 files changed, 24 insertions(+), 46 deletions(-) diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index a195850f2..16363250e 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -1,27 +1,19 @@ use crate::cliprdr::*; use hbb_common::log; -use std::sync::{Arc, Mutex}; +use std::sync::Mutex; lazy_static::lazy_static! { - static ref CONTEXT_SEND: Arc> = Arc::new(Mutex::new(ContextSend::new())); + static ref CONTEXT_SEND: ContextSend = ContextSend{addr: Mutex::new(0)}; } pub struct ContextSend { - cm_enabled: bool, - addr: u64, + addr: Mutex, } impl ContextSend { - fn new() -> Self { - Self { - cm_enabled: false, - addr: 0, - } - } - #[inline] - pub fn is_cm_enabled() -> bool { - CONTEXT_SEND.lock().unwrap().cm_enabled + pub fn is_enabled() -> bool { + *CONTEXT_SEND.addr.lock().unwrap() != 0 } pub fn set_is_stopped() { @@ -31,14 +23,14 @@ impl ContextSend { }); } - pub fn enable(enabled: bool, is_cm_side: bool, is_server_process: bool) { - let mut lock = CONTEXT_SEND.lock().unwrap(); + pub fn enable(enabled: bool) { + let mut lock = CONTEXT_SEND.addr.lock().unwrap(); if enabled { - if lock.addr == 0 { + if *lock == 0 { match crate::create_cliprdr_context(true, false) { Ok(context) => { log::info!("clipboard context for file transfer created."); - lock.addr = Box::into_raw(context) as _; + *lock = Box::into_raw(context) as _; } Err(err) => { log::error!( @@ -48,28 +40,22 @@ impl ContextSend { } } } - if is_cm_side { - lock.cm_enabled = true; - } } else { - if lock.addr != 0 { - if is_server_process { - unsafe { - let _ = Box::from_raw(lock.addr as *mut CliprdrClientContext); - } - log::info!("clipboard context for file transfer destroyed."); - lock.addr = 0; + if *lock != 0 { + unsafe { + let _ = Box::from_raw(*lock as *mut CliprdrClientContext); } - lock.cm_enabled = false; + log::info!("clipboard context for file transfer destroyed."); + *lock = 0; } } } pub fn proc) -> u32>(f: F) -> u32 { - let lock = CONTEXT_SEND.lock().unwrap(); - if lock.addr != 0 { + let lock = CONTEXT_SEND.addr.lock().unwrap(); + if *lock != 0 { unsafe { - let mut context = Box::from_raw(lock.addr as *mut CliprdrClientContext); + let mut context = Box::from_raw(*lock as *mut CliprdrClientContext); let code = f(&mut context); std::mem::forget(context); code diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index e830309d0..d75b53888 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -1550,7 +1550,7 @@ impl Remote { { let enabled = *self.handler.server_file_transfer_enabled.read().unwrap() && self.handler.lc.read().unwrap().enable_file_transfer.v; - ContextSend::enable(enabled, false, false); + ContextSend::enable(enabled); } } diff --git a/src/core_main.rs b/src/core_main.rs index 59c72fa66..f8741a72f 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -123,7 +123,7 @@ pub fn core_main() -> Option> { init_plugins(&args); if args.is_empty() { #[cfg(windows)] - clipboard::ContextSend::enable(true, false, false); + clipboard::ContextSend::enable(true); std::thread::spawn(move || crate::start_server(false)); } else { #[cfg(windows)] diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index af3bf2b3a..7e46fd314 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -338,7 +338,7 @@ impl IpcTaskRunner { #[cfg(windows)] { - if ContextSend::is_cm_enabled() { + if ContextSend::is_enabled() { allow_err!( self.stream .send(&Data::ClipboardFile(clipboard::ClipboardFile::MonitorReady)) @@ -404,7 +404,7 @@ impl IpcTaskRunner { #[cfg(windows)] { let is_stopping_allowed = _clip.is_stopping_allowed_from_peer(); - let is_clipboard_enabled = ContextSend::is_cm_enabled(); + let is_clipboard_enabled = ContextSend::is_enabled(); let file_transfer_enabled = self.file_transfer_enabled; let stop = !is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); log::debug!( @@ -469,7 +469,7 @@ impl IpcTaskRunner { #[cfg(windows)] { let is_stopping_allowed = _clip.is_stopping_allowed(); - let is_clipboard_enabled = ContextSend::is_cm_enabled(); + let is_clipboard_enabled = ContextSend::is_enabled(); let file_transfer_enabled = self.file_transfer_enabled; let file_transfer_enabled_peer = self.file_transfer_enabled_peer; let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled && file_transfer_enabled_peer); @@ -537,11 +537,7 @@ pub async fn start_ipc(cm: ConnectionManager) { }); #[cfg(target_os = "windows")] - ContextSend::enable( - Config::get_option("enable-file-transfer").is_empty(), - true, - crate::is_server(), - ); + ContextSend::enable(Config::get_option("enable-file-transfer").is_empty()); match ipc::new_listener("_cm").await { Ok(mut incoming) => { diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 0945e59af..a901fd4e6 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -882,11 +882,7 @@ async fn check_connect_status_(reconnect: bool, rx: mpsc::UnboundedReceiver