diff --git a/libs/clipboard/src/cliprdr.rs b/libs/clipboard/src/cliprdr.rs index 08d4021e8..f8d5d84b0 100644 --- a/libs/clipboard/src/cliprdr.rs +++ b/libs/clipboard/src/cliprdr.rs @@ -239,8 +239,6 @@ pub type CLIPRDR_FORMAT = _CLIPRDR_FORMAT; pub struct _CLIPRDR_FORMAT_LIST { pub connID: UINT32, pub msgType: UINT16, - pub msgFlags: UINT16, - pub dataLen: UINT32, pub numFormats: UINT32, pub formats: *mut CLIPRDR_FORMAT, } diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index 7c6ccae0d..4d1632292 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -1,6 +1,6 @@ use cliprdr::*; use hbb_common::{ - log, + allow_err, log, tokio::sync::{ mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, Mutex as TokioMutex, @@ -12,7 +12,7 @@ use std::{ boxed::Box, collections::HashMap, ffi::{CStr, CString}, - sync::Mutex, + sync::{Arc, Mutex, RwLock}, }; pub mod cliprdr; @@ -20,25 +20,20 @@ pub mod cliprdr; #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(tag = "t", content = "c")] pub enum ClipbaordFile { - ServerFormatList { - conn_id: i32, + FormatList { format_list: Vec<(i32, String)>, }, - ServerFormatListResponse { - conn_id: i32, + FormatListResponse { msg_flags: i32, }, - ServerFormatDataRequest { - conn_id: i32, + FormatDataRequest { requested_format_id: i32, }, - ServerFormatDataResponse { - conn_id: i32, + FormatDataResponse { msg_flags: i32, format_data: Vec, }, FileContentsRequest { - conn_id: i32, stream_id: i32, list_index: i32, dw_flags: i32, @@ -49,7 +44,6 @@ pub enum ClipbaordFile { clip_data_id: i32, }, FileContentsResponse { - conn_id: i32, msg_flags: i32, stream_id: i32, requested_data: Vec, @@ -61,18 +55,76 @@ struct ConnEnabled { conn_enabled: HashMap, } -lazy_static::lazy_static! { - static ref MSG_CHANNEL_CLIENT: (UnboundedSender<(i32, ClipbaordFile)>, TokioMutex>) = { - let (tx, rx) = unbounded_channel(); - (tx, TokioMutex::new(rx)) - }; +struct MsgChannel { + peer_id: String, + conn_id: i32, + sender: UnboundedSender, + receiver: Arc>>, +} +lazy_static::lazy_static! { + static ref VEC_MSG_CHANNEL: RwLock> = Default::default(); static ref CLIP_CONN_ENABLED: Mutex = Mutex::new(ConnEnabled::default()); } -#[inline(always)] -pub fn get_rx_clip_client<'a>() -> &'a TokioMutex> { - &MSG_CHANNEL_CLIENT.1 +#[inline] +pub async fn get_rx_cliprdr_client<'a>( + peer_id: &str, +) -> (i32, Arc>>) { + let mut lock = VEC_MSG_CHANNEL.write().unwrap(); + match lock.iter().find(|x| x.peer_id == peer_id.to_owned()) { + Some(msg_channel) => (msg_channel.conn_id, msg_channel.receiver.clone()), + None => { + 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 msg_channel = MsgChannel { + peer_id: peer_id.to_owned(), + conn_id, + sender, + receiver, + }; + lock.push(msg_channel); + (conn_id, receiver2) + } + } +} + +#[inline] +pub async fn get_rx_cliprdr_server<'a>( + conn_id: i32, +) -> Arc>> { + let mut lock = VEC_MSG_CHANNEL.write().unwrap(); + match lock.iter().find(|x| x.conn_id == conn_id) { + Some(msg_channel) => msg_channel.receiver.clone(), + None => { + let (sender, receiver) = unbounded_channel(); + let receiver = Arc::new(TokioMutex::new(receiver)); + let receiver2 = receiver.clone(); + let msg_channel = MsgChannel { + peer_id: "".to_owned(), + conn_id, + sender, + receiver, + }; + lock.push(msg_channel); + receiver2 + } + } +} + +#[inline] +fn send_data(conn_id: i32, data: ClipbaordFile) { + // no need to handle result here + if let Some(msg_channel) = VEC_MSG_CHANNEL + .read() + .unwrap() + .iter() + .find(|x| x.conn_id == conn_id) + { + allow_err!(msg_channel.sender.send(data)); + } } pub fn set_conn_enabled(conn_id: i32, enabled: bool) { @@ -88,61 +140,40 @@ pub fn empty_clipboard(context: &mut Box, conn_id: i32) -> pub fn server_clip_file( context: &mut Box, - s_conn_id: i32, + conn_id: i32, msg: ClipbaordFile, ) -> u32 { match msg { - ClipbaordFile::ServerFormatList { - mut conn_id, - format_list, - } => { - if s_conn_id != 0 { - conn_id = s_conn_id as i32; - } + ClipbaordFile::FormatList { format_list } => { log::debug!("server_format_list called"); let ret = server_format_list(context, conn_id, format_list); log::debug!("server_format_list called, return {}", ret); ret } - ClipbaordFile::ServerFormatListResponse { - mut conn_id, - msg_flags, - } => { - if s_conn_id != 0 { - conn_id = s_conn_id as i32; - } + ClipbaordFile::FormatListResponse { msg_flags } => { log::debug!("format_list_response called"); let ret = server_format_list_response(context, conn_id, msg_flags); log::debug!("server_format_list_response called, return {}", ret); ret } - ClipbaordFile::ServerFormatDataRequest { - mut conn_id, + ClipbaordFile::FormatDataRequest { requested_format_id, } => { - if s_conn_id != 0 { - conn_id = s_conn_id as i32; - } log::debug!("format_data_request called"); let ret = server_format_data_request(context, conn_id, requested_format_id); log::debug!("server_format_data_request called, return {}", ret); ret } - ClipbaordFile::ServerFormatDataResponse { - mut conn_id, + ClipbaordFile::FormatDataResponse { msg_flags, format_data, } => { - if s_conn_id != 0 { - conn_id = s_conn_id as i32; - } log::debug!("format_data_response called"); let ret = server_format_data_response(context, conn_id, msg_flags, format_data); log::debug!("server_format_data_response called, return {}", ret); ret } ClipbaordFile::FileContentsRequest { - mut conn_id, stream_id, list_index, dw_flags, @@ -152,9 +183,6 @@ pub fn server_clip_file( have_clip_data_id, clip_data_id, } => { - if s_conn_id != 0 { - conn_id = s_conn_id as i32; - } log::debug!("file_contents_request called"); let ret = server_file_contents_request( context, @@ -172,14 +200,10 @@ pub fn server_clip_file( ret } ClipbaordFile::FileContentsResponse { - mut conn_id, msg_flags, stream_id, requested_data, } => { - if s_conn_id != 0 { - conn_id = s_conn_id as i32; - } log::debug!("file_contents_response called"); let ret = server_file_contents_response( context, @@ -225,8 +249,6 @@ pub fn server_format_list( let format_list = CLIPRDR_FORMAT_LIST { connID: conn_id as UINT32, msgType: 0 as UINT16, - msgFlags: 0 as UINT16, - dataLen: 0 as UINT32, numFormats: num_formats, formats: formats.as_mut_ptr(), }; @@ -243,6 +265,7 @@ pub fn server_format_list( ret as u32 } } + pub fn server_format_list_response( context: &mut Box, conn_id: i32, @@ -262,6 +285,7 @@ pub fn server_format_list_response( ret as u32 } } + pub fn server_format_data_request( context: &mut Box, conn_id: i32, @@ -280,6 +304,7 @@ pub fn server_format_data_request( ret as u32 } } + pub fn server_format_data_response( context: &mut Box, conn_id: i32, @@ -301,6 +326,7 @@ pub fn server_format_data_response( ret as u32 } } + pub fn server_file_contents_request( context: &mut Box, conn_id: i32, @@ -335,6 +361,7 @@ pub fn server_file_contents_request( ret as u32 } } + pub fn server_file_contents_response( context: &mut Box, conn_id: i32, @@ -398,7 +425,7 @@ extern "C" fn client_format_list( ) -> UINT { log::debug!("client_format_list called"); - let conn_id; + // let conn_id; let mut format_list: Vec<(i32, String)> = Vec::new(); unsafe { let mut i = 0u32; @@ -420,14 +447,15 @@ extern "C" fn client_format_list( // log::debug!("format list item {}: format id: {}, format name: {}", i, format_data.formatId, &format_name); i += 1; } - conn_id = (*clip_format_list).connID as i32; + // conn_id = (*clip_format_list).connID as i32; } - let data = ClipbaordFile::ServerFormatList { - conn_id, - format_list, - }; + let data = ClipbaordFile::FormatList { format_list }; // no need to handle result here - MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap(); + VEC_MSG_CHANNEL + .read() + .unwrap() + .iter() + .for_each(|msg_channel| allow_err!(msg_channel.sender.send(data.clone()))); 0 } @@ -444,9 +472,8 @@ extern "C" fn client_format_list_response( conn_id = (*format_list_response).connID as i32; msg_flags = (*format_list_response).msgFlags as i32; } - let data = ClipbaordFile::ServerFormatListResponse { conn_id, msg_flags }; - // no need to handle result here - MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap(); + let data = ClipbaordFile::FormatListResponse { msg_flags }; + send_data(conn_id, data); 0 } @@ -463,12 +490,11 @@ extern "C" fn client_format_data_request( conn_id = (*format_data_request).connID as i32; requested_format_id = (*format_data_request).requestedFormatId as i32; } - let data = ClipbaordFile::ServerFormatDataRequest { - conn_id, + let data = ClipbaordFile::FormatDataRequest { requested_format_id, }; // no need to handle result here - MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap(); + send_data(conn_id, data); 0 } @@ -495,13 +521,11 @@ extern "C" fn client_format_data_response( .to_vec(); } } - let data = ClipbaordFile::ServerFormatDataResponse { - conn_id, + let data = ClipbaordFile::FormatDataResponse { msg_flags, format_data, }; - // no need to handle result here - MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap(); + send_data(conn_id, data); 0 } @@ -544,7 +568,6 @@ extern "C" fn client_file_contents_request( } let data = ClipbaordFile::FileContentsRequest { - conn_id, stream_id, list_index, dw_flags, @@ -554,8 +577,7 @@ extern "C" fn client_file_contents_request( have_clip_data_id, clip_data_id, }; - // no need to handle result here - MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap(); + send_data(conn_id, data); 0 } @@ -585,13 +607,11 @@ extern "C" fn client_file_contents_response( } } let data = ClipbaordFile::FileContentsResponse { - conn_id, msg_flags, stream_id, requested_data, }; - // no need to handle result here - MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap(); + send_data(conn_id, data); 0 } diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index f55eeb718..58c7a301e 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -193,6 +193,7 @@ struct _CliprdrDataObject ULONG m_nStreams; IStream **m_pStream; void *m_pData; + DWORD m_processID; UINT32 m_connID; }; typedef struct _CliprdrDataObject CliprdrDataObject; @@ -246,7 +247,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr); BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr); BOOL wf_do_empty_cliprdr(wfClipboard *clipboard); -static BOOL wf_create_file_obj(UINT32 connID, wfClipboard *cliprdrrdr, IDataObject **ppDataObject); +static BOOL wf_create_file_obj(UINT32 *connID, wfClipboard *clipboard, IDataObject **ppDataObject); static void wf_destroy_file_obj(IDataObject *instance); static UINT32 get_remote_format_id(wfClipboard *clipboard, UINT32 local_format); static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UINT32 format); @@ -673,6 +674,12 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO if (!pFormatEtc || !pMedium || !instance) return E_INVALIDARG; + // Not the same process id + if (instance->m_processID != GetCurrentProcessId()) + { + return E_INVALIDARG; + } + clipboard = (wfClipboard *)instance->m_pData; if (!clipboard->context->CheckEnabled(instance->m_connID)) { @@ -892,6 +899,7 @@ static CliprdrDataObject *CliprdrDataObject_New(UINT32 connID, FORMATETC *fmtetc instance->m_pData = data; instance->m_nStreams = 0; instance->m_pStream = NULL; + instance->m_processID = GetCurrentProcessId(); instance->m_connID = connID; if (count > 0) @@ -966,7 +974,7 @@ static BOOL wf_create_file_obj(UINT32 *connID, wfClipboard *clipboard, IDataObje stgmeds[1].tymed = TYMED_ISTREAM; stgmeds[1].pstm = NULL; stgmeds[1].pUnkForRelease = NULL; - *ppDataObject = (IDataObject *)CliprdrDataObject_New(*connID, fmtetc, stgmeds, 2, clipboard); + *ppDataObject = (IDataObject *)CliprdrDataObject_New(*connID, *(connID + 1), fmtetc, stgmeds, 2, clipboard); return (*ppDataObject) ? TRUE : FALSE; } @@ -1669,7 +1677,8 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM DEBUG_CLIPRDR("info: WM_RENDERFORMAT"); // https://docs.microsoft.com/en-us/windows/win32/dataxchg/wm-renderformat?redirectedfrom=MSDN - if (cliprdr_send_data_request(0, 0, clipboard, (UINT32)wParam) != 0) + // to-do: ensure usage of 0 + if (cliprdr_send_data_request(0, clipboard, (UINT32)wParam) != 0) { DEBUG_CLIPRDR("error: cliprdr_send_data_request failed."); break; diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 4bb015866..aaa02c327 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -360,38 +360,31 @@ message FileDirCreate { // main logic from freeRDP message CliprdrMonitorReady { - int32 conn_id = 1; } message CliprdrFormat { - int32 conn_id = 1; int32 id = 2; string format = 3; } message CliprdrServerFormatList { - int32 conn_id = 1; repeated CliprdrFormat formats = 2; } message CliprdrServerFormatListResponse { - int32 conn_id = 1; int32 msg_flags = 2; } message CliprdrServerFormatDataRequest { - int32 conn_id = 1; int32 requested_format_id = 2; } message CliprdrServerFormatDataResponse { - int32 conn_id = 1; int32 msg_flags = 2; bytes format_data = 3; } message CliprdrFileContentsRequest { - int32 conn_id = 1; int32 stream_id = 2; int32 list_index = 3; int32 dw_flags = 4; @@ -403,7 +396,6 @@ message CliprdrFileContentsRequest { } message CliprdrFileContentsResponse { - int32 conn_id = 1; int32 msg_flags = 3; int32 stream_id = 4; bytes requested_data = 5;