Merge pull request #4795 from dignow/refact/win_cliprd_wait_timeout

Refact/win cliprd wait timeout
This commit is contained in:
RustDesk
2023-06-29 22:50:45 +08:00
committed by GitHub
46 changed files with 223 additions and 37 deletions

View File

@@ -150,6 +150,15 @@ extern "C"
typedef struct _cliprdr_client_context CliprdrClientContext;
struct _NOTIFICATION_MESSAGE
{
// 0 - info, 1 - warning, 2 - error
UINT32 type;
char *msg;
char *details;
};
typedef struct _NOTIFICATION_MESSAGE NOTIFICATION_MESSAGE;
typedef UINT (*pcCliprdrServerCapabilities)(CliprdrClientContext *context,
const CLIPRDR_CAPABILITIES *capabilities);
typedef UINT (*pcCliprdrClientCapabilities)(CliprdrClientContext *context,
@@ -158,6 +167,9 @@ extern "C"
const CLIPRDR_MONITOR_READY *monitorReady);
typedef UINT (*pcCliprdrTempDirectory)(CliprdrClientContext *context,
const CLIPRDR_TEMP_DIRECTORY *tempDirectory);
typedef UINT (*pcNotifyClipboardMsg)(UINT32 connID, const NOTIFICATION_MESSAGE *msg);
typedef UINT (*pcCliprdrClientFormatList)(CliprdrClientContext *context,
const CLIPRDR_FORMAT_LIST *formatList);
typedef UINT (*pcCliprdrServerFormatList)(CliprdrClientContext *context,
@@ -199,10 +211,12 @@ extern "C"
BOOL EnableOthers;
BOOL IsStopped;
UINT32 ResponseWaitTimeoutSecs;
pcCliprdrServerCapabilities ServerCapabilities;
pcCliprdrClientCapabilities ClientCapabilities;
pcCliprdrMonitorReady MonitorReady;
pcCliprdrTempDirectory TempDirectory;
pcNotifyClipboardMsg NotifyClipboardMsg;
pcCliprdrClientFormatList ClientFormatList;
pcCliprdrServerFormatList ServerFormatList;
pcCliprdrClientFormatListResponse ClientFormatListResponse;
@@ -228,4 +242,3 @@ extern "C"
#endif
#endif // WF_CLIPRDR_H__

View File

@@ -324,6 +324,14 @@ pub struct _CLIPRDR_FILE_CONTENTS_RESPONSE {
}
pub type CLIPRDR_FILE_CONTENTS_RESPONSE = _CLIPRDR_FILE_CONTENTS_RESPONSE;
pub type CliprdrClientContext = _cliprdr_client_context;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _NOTIFICATION_MESSAGE {
pub r#type: UINT32, // 0 - info, 1 - warning, 2 - error
pub msg: *const BYTE,
pub details: *const BYTE,
}
pub type NOTIFICATION_MESSAGE = _NOTIFICATION_MESSAGE;
pub type pcCliprdrServerCapabilities = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
@@ -348,6 +356,8 @@ pub type pcCliprdrTempDirectory = ::std::option::Option<
tempDirectory: *const CLIPRDR_TEMP_DIRECTORY,
) -> UINT,
>;
pub type pcNotifyClipboardMsg =
::std::option::Option<unsafe extern "C" fn(connID: UINT32, msg: *const NOTIFICATION_MESSAGE) -> UINT>;
pub type pcCliprdrClientFormatList = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
@@ -453,10 +463,12 @@ pub struct _cliprdr_client_context {
pub EnableFiles: BOOL,
pub EnableOthers: BOOL,
pub IsStopped: BOOL,
pub ResponseWaitTimeoutSecs: UINT32,
pub ServerCapabilities: pcCliprdrServerCapabilities,
pub ClientCapabilities: pcCliprdrClientCapabilities,
pub MonitorReady: pcCliprdrMonitorReady,
pub TempDirectory: pcCliprdrTempDirectory,
pub NotifyClipboardMsg: pcNotifyClipboardMsg,
pub ClientFormatList: pcCliprdrClientFormatList,
pub ServerFormatList: pcCliprdrServerFormatList,
pub ClientFormatListResponse: pcCliprdrClientFormatListResponse,
@@ -498,6 +510,8 @@ impl CliprdrClientContext {
pub fn create(
enable_files: bool,
enable_others: bool,
response_wait_timeout_secs: u32,
notify_callback: pcNotifyClipboardMsg,
client_format_list: pcCliprdrClientFormatList,
client_format_list_response: pcCliprdrClientFormatListResponse,
client_format_data_request: pcCliprdrClientFormatDataRequest,
@@ -510,10 +524,12 @@ impl CliprdrClientContext {
EnableFiles: if enable_files { TRUE } else { FALSE },
EnableOthers: if enable_others { TRUE } else { FALSE },
IsStopped: FALSE,
ResponseWaitTimeoutSecs: response_wait_timeout_secs,
ServerCapabilities: None,
ClientCapabilities: None,
MonitorReady: None,
TempDirectory: None,
NotifyClipboardMsg: notify_callback,
ClientFormatList: client_format_list,
ServerFormatList: None,
ClientFormatListResponse: client_format_list_response,

View File

@@ -2,6 +2,8 @@ use crate::cliprdr::*;
use hbb_common::log;
use std::sync::Mutex;
const CLIPBOARD_RESPONSE_WAIT_TIMEOUT_SECS: u32 = 30;
lazy_static::lazy_static! {
static ref CONTEXT_SEND: ContextSend = ContextSend{addr: Mutex::new(0)};
}
@@ -27,7 +29,11 @@ impl ContextSend {
let mut lock = CONTEXT_SEND.addr.lock().unwrap();
if enabled {
if *lock == 0 {
match crate::create_cliprdr_context(true, false) {
match crate::create_cliprdr_context(
true,
false,
CLIPBOARD_RESPONSE_WAIT_TIMEOUT_SECS,
) {
Ok(context) => {
log::info!("clipboard context for file transfer created.");
*lock = Box::into_raw(context) as _;

View File

@@ -1,6 +1,6 @@
use cliprdr::*;
use hbb_common::{
allow_err, log,
allow_err, lazy_static, log,
tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex,
@@ -19,10 +19,16 @@ pub mod context_send;
pub use context_send::*;
const ERR_CODE_SERVER_FUNCTION_NONE: u32 = 0x00000001;
const ERR_CODE_INVALID_PARAMETER: u32 = 0x00000002;
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "t", content = "c")]
pub enum ClipboardFile {
NotifyCallback {
r#type: String,
title: String,
text: String,
},
MonitorReady,
FormatList {
format_list: Vec<(i32, String)>,
@@ -167,41 +173,40 @@ pub fn server_clip_file(
conn_id: i32,
msg: ClipboardFile,
) -> u32 {
let mut ret = 0;
match msg {
ClipboardFile::NotifyCallback { .. } => {
// unreachable
}
ClipboardFile::MonitorReady => {
log::debug!("server_monitor_ready called");
let ret = server_monitor_ready(context, conn_id);
ret = server_monitor_ready(context, conn_id);
log::debug!("server_monitor_ready called, return {}", ret);
ret
}
ClipboardFile::FormatList { format_list } => {
log::debug!("server_format_list called");
let ret = server_format_list(context, conn_id, format_list);
ret = server_format_list(context, conn_id, format_list);
log::debug!("server_format_list called, return {}", ret);
ret
}
ClipboardFile::FormatListResponse { msg_flags } => {
log::debug!("format_list_response called");
let ret = server_format_list_response(context, conn_id, msg_flags);
ret = server_format_list_response(context, conn_id, msg_flags);
log::debug!("server_format_list_response called, return {}", ret);
ret
}
ClipboardFile::FormatDataRequest {
requested_format_id,
} => {
log::debug!("format_data_request called");
let ret = server_format_data_request(context, conn_id, requested_format_id);
ret = server_format_data_request(context, conn_id, requested_format_id);
log::debug!("server_format_data_request called, return {}", ret);
ret
}
ClipboardFile::FormatDataResponse {
msg_flags,
format_data,
} => {
log::debug!("format_data_response called");
let ret = server_format_data_response(context, conn_id, msg_flags, format_data);
ret = server_format_data_response(context, conn_id, msg_flags, format_data);
log::debug!("server_format_data_response called, return {}", ret);
ret
}
ClipboardFile::FileContentsRequest {
stream_id,
@@ -214,7 +219,7 @@ pub fn server_clip_file(
clip_data_id,
} => {
log::debug!("file_contents_request called");
let ret = server_file_contents_request(
ret = server_file_contents_request(
context,
conn_id,
stream_id,
@@ -227,7 +232,6 @@ pub fn server_clip_file(
clip_data_id,
);
log::debug!("server_file_contents_request called, return {}", ret);
ret
}
ClipboardFile::FileContentsResponse {
msg_flags,
@@ -235,7 +239,7 @@ pub fn server_clip_file(
requested_data,
} => {
log::debug!("file_contents_response called");
let ret = server_file_contents_response(
ret = server_file_contents_response(
context,
conn_id,
msg_flags,
@@ -243,9 +247,9 @@ pub fn server_clip_file(
requested_data,
);
log::debug!("server_file_contents_response called, return {}", ret);
ret
}
}
ret
}
pub fn server_monitor_ready(context: &mut Box<CliprdrClientContext>, conn_id: i32) -> u32 {
@@ -446,10 +450,13 @@ pub fn server_file_contents_response(
pub fn create_cliprdr_context(
enable_files: bool,
enable_others: bool,
response_wait_timeout_secs: u32,
) -> ResultType<Box<CliprdrClientContext>> {
Ok(CliprdrClientContext::create(
enable_files,
enable_others,
response_wait_timeout_secs,
Some(notify_callback),
Some(client_format_list),
Some(client_format_list_response),
Some(client_format_data_request),
@@ -459,6 +466,51 @@ pub fn create_cliprdr_context(
)?)
}
extern "C" fn notify_callback(conn_id: UINT32, msg: *const NOTIFICATION_MESSAGE) -> UINT {
log::debug!("notify_callback called");
let data = unsafe {
let msg = &*msg;
let details = if msg.details.is_null() {
Ok("")
} else {
CStr::from_ptr(msg.details as _).to_str()
};
match (CStr::from_ptr(msg.msg as _).to_str(), details) {
(Ok(m), Ok(d)) => {
let msgtype = format!(
"custom-{}-nocancel-nook-hasclose",
if msg.r#type == 0 {
"info"
} else if msg.r#type == 1 {
"warn"
} else {
"error"
}
);
let title = "Clipboard";
let text = if d.is_empty() {
m.to_string()
} else {
format!("{} {}", m, d)
};
ClipboardFile::NotifyCallback {
r#type: msgtype,
title: title.to_string(),
text,
}
}
_ => {
log::error!("notify_callback: failed to convert msg");
return ERR_CODE_INVALID_PARAMETER;
}
}
};
// no need to handle result here
send_data(conn_id as _, data);
0
}
extern "C" fn client_format_list(
_context: *mut CliprdrClientContext,
clip_format_list: *const CLIPRDR_FORMAT_LIST,

View File

@@ -1449,14 +1449,16 @@ 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(UINT32 connID, wfClipboard *clipboard, HANDLE event, void **data)
{
UINT rc = ERROR_SUCCESS;
clipboard->context->IsStopped = FALSE;
// with default 3min timeout
for (int i = 0; i < 20 * 60 * 3; i++)
DWORD waitOnceTimeoutMillis = 50;
int waitCount = 1000 * clipboard->context->ResponseWaitTimeoutSecs / waitOnceTimeoutMillis;
int i = 0;
for (; i < waitCount; i++)
{
DWORD waitRes = WaitForSingleObject(event, 50);
DWORD waitRes = WaitForSingleObject(event, waitOnceTimeoutMillis);
if (waitRes == WAIT_TIMEOUT && clipboard->context->IsStopped == FALSE)
{
continue;
@@ -1487,7 +1489,21 @@ UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void **data)
return rc;
}
if ((*data) != NULL)
if (i == waitCount)
{
NOTIFICATION_MESSAGE msg;
msg.type = 2;
msg.msg = "clipboard_wait_response_timeout_tip";
msg.details = NULL;
clipboard->context->NotifyClipboardMsg(connID, &msg);
rc = ERROR_INTERNAL_ERROR;
if (!ResetEvent(event))
{
// NOTE: critical error here, crash may be better
}
}
else if ((*data) != NULL)
{
if (!ResetEvent(event))
{
@@ -1519,7 +1535,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(connID, clipboard, clipboard->response_data_event, &clipboard->hmem);
}
UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, const void *streamid, ULONG index,
@@ -1547,7 +1563,7 @@ UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, co
return rc;
}
return wait_response_event(clipboard, clipboard->req_fevent, (void **)&clipboard->req_fdata);
return wait_response_event(connID, clipboard, clipboard->req_fevent, (void **)&clipboard->req_fdata);
}
static UINT cliprdr_send_response_filecontents(