patch: update UI, clear previous FUSE

- UI updated, now allow copy and paste file in Linux
- Too hard to implement graceful shutdown for rustdesk, just clear
  previously mounted FUSE should also works

Signed-off-by: ClSlaid <cailue@bupt.edu.cn>
This commit is contained in:
ClSlaid
2023-10-07 17:26:20 +08:00
parent d2a5edda46
commit a597c3f835
11 changed files with 81 additions and 22 deletions

View File

@@ -38,7 +38,7 @@ impl ContextSend {
}
Err(err) => {
log::error!(
"Create clipboard context for file transfer: {}",
"create clipboard context for file transfer: {}",
err.to_string()
);
}

View File

@@ -198,6 +198,18 @@ pub fn get_rx_cliprdr_server(conn_id: i32) -> Arc<TokioMutex<UnboundedReceiver<C
#[inline]
fn send_data(conn_id: i32, data: ClipboardFile) {
#[cfg(target_os = "windows")]
return send_data_to_channel(conn_id, data);
#[cfg(not(target_os = "windows"))]
if conn_id == 0 {
send_data_to_all(data);
} else {
send_data_to_channel(conn_id, data);
}
}
#[inline]
fn send_data_to_channel(conn_id: i32, data: ClipboardFile) {
// no need to handle result here
if let Some(msg_channel) = VEC_MSG_CHANNEL
.read()
@@ -205,10 +217,20 @@ fn send_data(conn_id: i32, data: ClipboardFile) {
.iter()
.find(|x| x.conn_id == conn_id)
{
log::debug!("send data to connection: {}", conn_id);
allow_err!(msg_channel.sender.send(data));
}
}
#[inline]
fn send_data_to_all(data: ClipboardFile) {
// no need to handle result here
for msg_channel in VEC_MSG_CHANNEL.read().unwrap().iter() {
log::debug!("send data to connection: {}", msg_channel.conn_id);
allow_err!(msg_channel.sender.send(data.clone()));
}
}
#[cfg(test)]
mod tests {
// #[test]

View File

@@ -126,6 +126,11 @@ impl CliprdrTxnDispatcher {
self.txn_handler
.insert((conn_id, stream_id.copied()), req.clone());
log::debug!(
"send request to conn_id={}, stream_id={:?}",
conn_id,
stream_id
);
crate::send_data(conn_id, request);
req
}
@@ -137,6 +142,7 @@ impl CliprdrTxnDispatcher {
_ => unreachable!(),
};
let key = (conn_id, stream_id.cloned());
log::debug!("recv response for {:?}", key);
match self.txn_handler.remove(&key) {
Some((_, tx)) => tx.set(response),
None => log::warn!("no request found for {:?}", key),
@@ -570,17 +576,19 @@ impl FuseServer {
fn gc_files(&self) {
{
let mut status = self.status.write();
// really update only when:
// running: Active
if *status != Status::Active {
return;
}
// received update after fetching complete
// should fetch again
if *status == Status::Building {
*status = Status::GcComplete;
return;
}
// really update only when:
// running: Active
if *status != Status::Active {
return;
}
*status = Status::Gc;
}

View File

@@ -20,7 +20,7 @@ use lazy_static::lazy_static;
use parking_lot::{Mutex, RwLock};
use utf16string::WString;
use crate::{send_data, ClipboardFile, CliprdrError, CliprdrServiceContext};
use crate::{send_data, send_data_to_all, ClipboardFile, CliprdrError, CliprdrServiceContext};
use super::{fuse::FuseServer, LDAP_EPOCH_DELTA};
@@ -364,7 +364,6 @@ impl ClipboardContext {
if fuse_handle.is_none() {
let mount_path = &self.fuse_mount_point;
create_if_not_exists(mount_path);
let mnt_opts = [
MountOption::FSName("rustdesk-cliprdr-fs".to_string()),
@@ -408,6 +407,7 @@ impl ClipboardContext {
let mut fuse_handle = self.fuse_handle.lock();
if let Some(fuse_handle) = fuse_handle.take() {
log::debug!("unmounting clipboard FUSE");
fuse_handle.join();
}
self.clipboard.stop();
@@ -446,7 +446,7 @@ impl ClipboardContext {
],
};
send_data(0, data);
send_data_to_all(data);
log::debug!("format list update sent");
}
Ok(())
@@ -649,26 +649,39 @@ fn resp_file_contents_fail(conn_id: i32, stream_id: i32) {
send_data(conn_id, resp)
}
fn create_if_not_exists(path: &PathBuf) {
if std::fs::metadata(path).is_ok() {
return;
}
std::fs::create_dir(path).unwrap();
}
impl ClipboardContext {
pub fn is_stopped(&self) -> bool {
self.fuse_handle.lock().is_none()
}
pub fn set_is_stopped(&self) -> Result<(), CliprdrError> {
// do nothing
if self.is_stopped() {
log::debug!("cliprdr already stopped");
return Ok(());
}
// unmount the fuse
if let Some(fuse_handle) = self.fuse_handle.lock().take() {
fuse_handle.join();
}
Ok(())
}
pub fn empty_clipboard(&self, conn_id: i32) -> Result<bool, CliprdrError> {
// gc all files, the clipboard is going to shutdown
if self.is_stopped() {
log::debug!("cliprdr stopped, skip emptying clipboard");
return Ok(true);
}
self.fuse_server
.update_files(conn_id, FILEDESCRIPTOR_FORMAT_ID, FILECONTENTS_FORMAT_ID)
}
pub fn serve(&self, conn_id: i32, msg: ClipboardFile) -> Result<(), CliprdrError> {
if self.is_stopped() {
log::debug!("cliprdr stopped, skip serving clipboard");
return Ok(());
}
match msg {
ClipboardFile::NotifyCallback { .. } => {
unreachable!()
@@ -683,6 +696,7 @@ impl ClipboardContext {
}
ClipboardFile::FormatList { format_list } => {
log::debug!("server_format_list called");
// filter out "FileGroupDescriptorW" and "FileContents"
let fmt_lst: Vec<(i32, String)> = format_list
.into_iter()
@@ -713,6 +727,7 @@ impl ClipboardContext {
Ok(())
}
ClipboardFile::FormatListResponse { msg_flags } => {
log::debug!("server_format_list_response called");
if msg_flags != 0x1 {
self.send_format_list(conn_id)
} else {
@@ -722,6 +737,7 @@ impl ClipboardContext {
ClipboardFile::FormatDataRequest {
requested_format_id,
} => {
log::debug!("server_format_data_request called");
let Some(format) = get_local_format(requested_format_id) else {
log::error!(
"got unsupported format data request: id={} from conn={}",
@@ -752,6 +768,7 @@ impl ClipboardContext {
}
ClipboardFile::FormatDataResponse { .. } => {
// we don't know its corresponding request, no resend can be performed
log::debug!("server_format_data_response called");
self.fuse_server.recv(conn_id, msg);
let paths = self.fuse_server.list_root();
@@ -759,6 +776,7 @@ impl ClipboardContext {
Ok(())
}
ClipboardFile::FileContentsResponse { .. } => {
log::debug!("server_file_contents_response called");
// we don't know its corresponding request, no resend can be performed
self.fuse_server.recv(conn_id, msg);
Ok(())
@@ -772,6 +790,7 @@ impl ClipboardContext {
cb_requested,
..
} => {
log::debug!("server_file_contents_request called");
let fcr = if dw_flags == 0x1 {
FileContentsRequest::Size {
stream_id,

View File

@@ -3,6 +3,7 @@ use std::{
sync::atomic::{AtomicBool, Ordering},
};
use hbb_common::log;
use once_cell::sync::OnceCell;
use x11_clipboard::Clipboard;
use x11rb::protocol::xproto::Atom;
@@ -44,6 +45,7 @@ impl X11Clipboard {
fn load(&self, target: Atom) -> Result<Vec<u8>, CliprdrError> {
let clip = get_clip()?.setter.atoms.clipboard;
let prop = get_clip()?.setter.atoms.property;
log::debug!("try to load clipboard content");
get_clip()?
.load_wait(clip, target, prop)
.map_err(|_| CliprdrError::ConversionFailure)
@@ -51,6 +53,7 @@ impl X11Clipboard {
fn store_batch(&self, batch: Vec<(Atom, Vec<u8>)>) -> Result<(), CliprdrError> {
let clip = get_clip()?.setter.atoms.clipboard;
log::debug!("try to store clipboard content");
get_clip()?
.store_batch(clip, batch)
.map_err(|_| CliprdrError::ClipboardInternalError)

View File

@@ -37,7 +37,11 @@ pub fn create_cliprdr_context(
let mut tmp_path = std::env::temp_dir();
tmp_path.push("rustdesk-cliprdr");
log::info!("check mount point existence");
log::info!("clear previously mounted cliprdr FUSE");
if let Err(e) = std::process::Command::new("umount").arg(&tmp_path).status() {
log::warn!("umount {:?} may fail: {:?}", tmp_path, e);
}
let rd_mnt = if !tmp_path.exists() {
log::info!("create mount point: {}", tmp_path.display());
std::fs::create_dir_all(tmp_path.clone())?;