patch: reduce logic in Fuse and SystemClipboard
1. also added more observability Signed-off-by: ClSlaid <cailue@bupt.edu.cn>
This commit is contained in:
parent
8f9ba44c2c
commit
fbb1d9247f
@ -181,7 +181,7 @@ impl FuseServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FuseServer {
|
impl FuseServer {
|
||||||
pub fn serve(&mut self, reply: ClipboardFile) -> Result<(), CliprdrError> {
|
pub fn serve(&self, reply: ClipboardFile) -> Result<(), CliprdrError> {
|
||||||
self.tx.send(reply).map_err(|e| {
|
self.tx.send(reply).map_err(|e| {
|
||||||
log::error!("failed to serve cliprdr reply from endpoint: {:?}", e);
|
log::error!("failed to serve cliprdr reply from endpoint: {:?}", e);
|
||||||
CliprdrError::ClipboardInternalError
|
CliprdrError::ClipboardInternalError
|
||||||
@ -190,6 +190,15 @@ impl FuseServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FuseServer {
|
||||||
|
pub fn load_file_list(&mut self, files: Vec<FileDescription>) -> Result<(), CliprdrError> {
|
||||||
|
let tree = FuseNode::build_tree(files)?;
|
||||||
|
self.files = tree;
|
||||||
|
self.generation.fetch_add(1, Ordering::Relaxed);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fuser::Filesystem for FuseServer {
|
impl fuser::Filesystem for FuseServer {
|
||||||
fn init(
|
fn init(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -499,165 +508,11 @@ impl FuseServer {
|
|||||||
paths
|
paths
|
||||||
}
|
}
|
||||||
|
|
||||||
/// fetch file list from remote
|
|
||||||
fn sync_file_system(
|
|
||||||
&mut self,
|
|
||||||
conn_id: i32,
|
|
||||||
file_group_format_id: i32,
|
|
||||||
_file_contents_format_id: i32,
|
|
||||||
) -> Result<bool, CliprdrError> {
|
|
||||||
let resp = self.send_sync_fs_request(conn_id, file_group_format_id, self.timeout)?;
|
|
||||||
let descs = match resp {
|
|
||||||
ClipboardFile::FormatDataResponse {
|
|
||||||
msg_flags,
|
|
||||||
format_data,
|
|
||||||
} => {
|
|
||||||
if msg_flags != 0x1 {
|
|
||||||
log::error!("clipboard FUSE server: received unexpected response flags");
|
|
||||||
return Err(CliprdrError::ClipboardInternalError);
|
|
||||||
}
|
|
||||||
let descs = FileDescription::parse_file_descriptors(format_data, conn_id)?;
|
|
||||||
|
|
||||||
descs
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
log::error!("clipboard FUSE server: received unexpected response type");
|
|
||||||
|
|
||||||
return Err(CliprdrError::ClipboardInternalError);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut new_tree = FuseNode::build_tree(descs)?;
|
|
||||||
let res = new_tree
|
|
||||||
.iter_mut()
|
|
||||||
.filter(|f_node| f_node.is_file() && f_node.attributes.size == 0)
|
|
||||||
.try_for_each(|f_node| self.sync_node_size(f_node));
|
|
||||||
|
|
||||||
if let Err(err) = res {
|
|
||||||
log::error!(
|
|
||||||
"clipboard FUSE server: failed to fetch file size: {:?}",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
|
|
||||||
return Err(CliprdrError::ClipboardInternalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace current file system
|
|
||||||
self.files = new_tree;
|
|
||||||
self.generation.fetch_add(1, Ordering::Relaxed);
|
|
||||||
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_sync_fs_request(
|
|
||||||
&self,
|
|
||||||
conn_id: i32,
|
|
||||||
file_group_format_id: i32,
|
|
||||||
timeout: std::time::Duration,
|
|
||||||
) -> Result<ClipboardFile, CliprdrError> {
|
|
||||||
// request file list
|
|
||||||
let data = ClipboardFile::FormatDataRequest {
|
|
||||||
requested_format_id: file_group_format_id,
|
|
||||||
};
|
|
||||||
send_data(conn_id, data);
|
|
||||||
self.rx.recv_timeout(timeout).map_err(|e| {
|
|
||||||
log::error!("failed to receive file list from channel: {:?}", e);
|
|
||||||
CliprdrError::ClipboardInternalError
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_files(
|
|
||||||
&mut self,
|
|
||||||
conn_id: i32,
|
|
||||||
file_group_format_id: i32,
|
|
||||||
file_contents_format_id: i32,
|
|
||||||
) -> Result<bool, CliprdrError> {
|
|
||||||
self.sync_file_system(conn_id, file_group_format_id, file_contents_format_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// allocate a new file descriptor
|
/// allocate a new file descriptor
|
||||||
fn alloc_fd(&self) -> u64 {
|
fn alloc_fd(&self) -> u64 {
|
||||||
self.file_handle_counter.fetch_add(1, Ordering::Relaxed)
|
self.file_handle_counter.fetch_add(1, Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// synchronize metadata with remote
|
|
||||||
fn sync_node_size(&self, node: &mut FuseNode) -> Result<(), std::io::Error> {
|
|
||||||
log::debug!(
|
|
||||||
"syncing metadata for {:?} on stream: {}",
|
|
||||||
node.name,
|
|
||||||
node.stream_id
|
|
||||||
);
|
|
||||||
|
|
||||||
let request = ClipboardFile::FileContentsRequest {
|
|
||||||
stream_id: node.stream_id,
|
|
||||||
list_index: node.inode as i32 - 2, // list index at least 2
|
|
||||||
dw_flags: 1,
|
|
||||||
|
|
||||||
n_position_low: 0,
|
|
||||||
n_position_high: 0,
|
|
||||||
cb_requested: 8,
|
|
||||||
have_clip_data_id: false,
|
|
||||||
clip_data_id: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
send_data(node.conn_id, request);
|
|
||||||
|
|
||||||
log::debug!(
|
|
||||||
"waiting for metadata sync reply for {:?} on channel {}",
|
|
||||||
node.name,
|
|
||||||
node.conn_id
|
|
||||||
);
|
|
||||||
|
|
||||||
let reply = self
|
|
||||||
.rx
|
|
||||||
.recv_timeout(self.timeout)
|
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::TimedOut, e))?;
|
|
||||||
log::debug!(
|
|
||||||
"got metadata sync reply for {:?} on channel {}",
|
|
||||||
node.name,
|
|
||||||
node.conn_id
|
|
||||||
);
|
|
||||||
|
|
||||||
let size = match reply {
|
|
||||||
ClipboardFile::FileContentsResponse {
|
|
||||||
msg_flags,
|
|
||||||
stream_id,
|
|
||||||
requested_data,
|
|
||||||
} => {
|
|
||||||
if stream_id != node.stream_id {
|
|
||||||
return Err(std::io::Error::new(
|
|
||||||
std::io::ErrorKind::Other,
|
|
||||||
"stream id mismatch",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if msg_flags & 1 == 0 {
|
|
||||||
return Err(std::io::Error::new(
|
|
||||||
std::io::ErrorKind::Other,
|
|
||||||
"failure request",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if requested_data.len() != 8 {
|
|
||||||
return Err(std::io::Error::new(
|
|
||||||
std::io::ErrorKind::Other,
|
|
||||||
"invalid data length",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let little_endian_value = u64::from_le_bytes(requested_data.try_into().unwrap());
|
|
||||||
little_endian_value
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(std::io::Error::new(
|
|
||||||
std::io::ErrorKind::Other,
|
|
||||||
"invalid reply",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
log::debug!("got metadata sync reply for {:?}: size {}", node.name, size);
|
|
||||||
|
|
||||||
node.attributes.size = size;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_node(
|
fn read_node(
|
||||||
&self,
|
&self,
|
||||||
node: &FuseNode,
|
node: &FuseNode,
|
||||||
@ -916,6 +771,7 @@ impl FuseNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn is_file(&self) -> bool {
|
pub fn is_file(&self) -> bool {
|
||||||
self.attributes.kind == FileType::File
|
self.attributes.kind == FileType::File
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,12 @@ use hbb_common::{
|
|||||||
log,
|
log,
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::Mutex;
|
||||||
use utf16string::WString;
|
use utf16string::WString;
|
||||||
|
|
||||||
use crate::{send_data, ClipboardFile, CliprdrError, CliprdrServiceContext};
|
use crate::{
|
||||||
|
platform::fuse::FileDescription, send_data, ClipboardFile, CliprdrError, CliprdrServiceContext,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{fuse::FuseServer, LDAP_EPOCH_DELTA};
|
use super::{fuse::FuseServer, LDAP_EPOCH_DELTA};
|
||||||
|
|
||||||
@ -44,13 +46,11 @@ fn add_remote_format(local_name: &str, remote_id: i32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait SysClipboard: Send + Sync {
|
trait SysClipboard: Send + Sync {
|
||||||
fn set_file_list(&self, paths: &[PathBuf]) -> Result<(), CliprdrError>;
|
|
||||||
fn stop(&self);
|
|
||||||
fn start(&self);
|
fn start(&self);
|
||||||
/// send to 0 will send to all channels
|
fn stop(&self);
|
||||||
fn send_format_list(&self, conn_id: i32) -> Result<(), CliprdrError>;
|
|
||||||
/// send to 0 will send to all channels
|
fn set_file_list(&self, paths: &[PathBuf]) -> Result<(), CliprdrError>;
|
||||||
fn send_file_list(&self, conn_id: i32) -> Result<(), CliprdrError>;
|
fn get_file_list(&self) -> Result<Vec<LocalFile>, CliprdrError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_sys_clipboard(ignore_path: &PathBuf) -> Result<Box<dyn SysClipboard>, CliprdrError> {
|
fn get_sys_clipboard(ignore_path: &PathBuf) -> Result<Box<dyn SysClipboard>, CliprdrError> {
|
||||||
@ -312,7 +312,6 @@ pub struct ClipboardContext {
|
|||||||
|
|
||||||
fuse_server: Arc<Mutex<FuseServer>>,
|
fuse_server: Arc<Mutex<FuseServer>>,
|
||||||
|
|
||||||
file_list: RwLock<Vec<LocalFile>>,
|
|
||||||
clipboard: Arc<dyn SysClipboard>,
|
clipboard: Arc<dyn SysClipboard>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,13 +327,11 @@ impl ClipboardContext {
|
|||||||
|
|
||||||
let clipboard = get_sys_clipboard(&fuse_mount_point)?;
|
let clipboard = get_sys_clipboard(&fuse_mount_point)?;
|
||||||
let clipboard = Arc::from(clipboard) as Arc<_>;
|
let clipboard = Arc::from(clipboard) as Arc<_>;
|
||||||
let file_list = RwLock::new(vec![]);
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
fuse_mount_point,
|
fuse_mount_point,
|
||||||
fuse_server,
|
fuse_server,
|
||||||
fuse_handle: Mutex::new(None),
|
fuse_handle: Mutex::new(None),
|
||||||
file_list,
|
|
||||||
clipboard,
|
clipboard,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -379,10 +376,6 @@ impl ClipboardContext {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop(&self) -> Result<(), CliprdrError> {
|
|
||||||
self.set_is_stopped()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// set clipboard data from file list
|
/// set clipboard data from file list
|
||||||
pub fn set_clipboard(&self, paths: &[PathBuf]) -> Result<(), CliprdrError> {
|
pub fn set_clipboard(&self, paths: &[PathBuf]) -> Result<(), CliprdrError> {
|
||||||
let prefix = self.fuse_mount_point.clone();
|
let prefix = self.fuse_mount_point.clone();
|
||||||
@ -404,7 +397,7 @@ impl ClipboardContext {
|
|||||||
stream_id,
|
stream_id,
|
||||||
file_idx,
|
file_idx,
|
||||||
} => {
|
} => {
|
||||||
let file_list = self.file_list.read();
|
let file_list = self.clipboard.get_file_list()?;
|
||||||
let Some(file) = file_list.get(file_idx) else {
|
let Some(file) = file_list.get(file_idx) else {
|
||||||
log::error!(
|
log::error!(
|
||||||
"invalid file index {} requested from conn: {}",
|
"invalid file index {} requested from conn: {}",
|
||||||
@ -436,7 +429,7 @@ impl ClipboardContext {
|
|||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
} => {
|
} => {
|
||||||
let file_list = self.file_list.read();
|
let file_list = self.clipboard.get_file_list()?;
|
||||||
let Some(file) = file_list.get(file_idx) else {
|
let Some(file) = file_list.get(file_idx) else {
|
||||||
log::error!(
|
log::error!(
|
||||||
"invalid file index {} requested from conn: {}",
|
"invalid file index {} requested from conn: {}",
|
||||||
@ -523,33 +516,6 @@ impl ClipboardContext {
|
|||||||
self.fuse_handle.lock().is_none()
|
self.fuse_handle.lock().is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_is_stopped(&self) -> Result<(), CliprdrError> {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
self.clipboard.stop();
|
|
||||||
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.lock().update_files(
|
|
||||||
conn_id,
|
|
||||||
FILEDESCRIPTOR_FORMAT_ID,
|
|
||||||
FILECONTENTS_FORMAT_ID,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn serve(&self, conn_id: i32, msg: ClipboardFile) -> Result<(), CliprdrError> {
|
pub fn serve(&self, conn_id: i32, msg: ClipboardFile) -> Result<(), CliprdrError> {
|
||||||
if self.is_stopped() {
|
if self.is_stopped() {
|
||||||
log::debug!("cliprdr stopped, restart it");
|
log::debug!("cliprdr stopped, restart it");
|
||||||
@ -562,9 +528,8 @@ impl ClipboardContext {
|
|||||||
ClipboardFile::MonitorReady => {
|
ClipboardFile::MonitorReady => {
|
||||||
log::debug!("server_monitor_ready called");
|
log::debug!("server_monitor_ready called");
|
||||||
|
|
||||||
// ignore capabilities for now
|
self.send_file_list(conn_id)?;
|
||||||
|
|
||||||
self.clipboard.send_file_list(0)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,17 +560,19 @@ impl ClipboardContext {
|
|||||||
|
|
||||||
add_remote_format(FILECONTENTS_FORMAT_NAME, file_contents_id);
|
add_remote_format(FILECONTENTS_FORMAT_NAME, file_contents_id);
|
||||||
add_remote_format(FILEDESCRIPTORW_FORMAT_NAME, file_descriptor_id);
|
add_remote_format(FILEDESCRIPTORW_FORMAT_NAME, file_descriptor_id);
|
||||||
self.fuse_server.lock().update_files(
|
|
||||||
conn_id,
|
// sync file system from peer
|
||||||
file_descriptor_id,
|
let data = ClipboardFile::FormatDataRequest {
|
||||||
file_contents_id,
|
requested_format_id: file_descriptor_id,
|
||||||
)?;
|
};
|
||||||
|
send_data(conn_id, data);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
ClipboardFile::FormatListResponse { msg_flags } => {
|
ClipboardFile::FormatListResponse { msg_flags } => {
|
||||||
log::debug!("server_format_list_response called");
|
log::debug!("server_format_list_response called");
|
||||||
if msg_flags != 0x1 {
|
if msg_flags != 0x1 {
|
||||||
self.clipboard.send_format_list(conn_id)
|
send_format_list(conn_id)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -625,7 +592,7 @@ impl ClipboardContext {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if format == FILEDESCRIPTORW_FORMAT_NAME {
|
if format == FILEDESCRIPTORW_FORMAT_NAME {
|
||||||
self.clipboard.send_file_list(conn_id)?;
|
self.send_file_list(conn_id)?;
|
||||||
} else if format == FILECONTENTS_FORMAT_NAME {
|
} else if format == FILECONTENTS_FORMAT_NAME {
|
||||||
log::error!(
|
log::error!(
|
||||||
"try to read file contents with FormatDataRequest from conn={}",
|
"try to read file contents with FormatDataRequest from conn={}",
|
||||||
@ -642,13 +609,27 @@ impl ClipboardContext {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
ClipboardFile::FormatDataResponse { .. } => {
|
ClipboardFile::FormatDataResponse {
|
||||||
// we don't know its corresponding request, no resend can be performed
|
msg_flags,
|
||||||
|
format_data,
|
||||||
|
} => {
|
||||||
log::debug!("server_format_data_response called");
|
log::debug!("server_format_data_response called");
|
||||||
let mut fuse_server = self.fuse_server.lock();
|
|
||||||
|
|
||||||
fuse_server.serve(msg)?;
|
if msg_flags != 0x1 {
|
||||||
let paths = fuse_server.list_root();
|
resp_format_data_failure(conn_id);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// this must be a file descriptor format data
|
||||||
|
let files = FileDescription::parse_file_descriptors(format_data.into(), conn_id)?;
|
||||||
|
|
||||||
|
let paths = {
|
||||||
|
let mut fuse_guard = self.fuse_server.lock();
|
||||||
|
fuse_guard.load_file_list(files)?;
|
||||||
|
|
||||||
|
fuse_guard.list_root()
|
||||||
|
};
|
||||||
|
|
||||||
self.set_clipboard(&paths)?;
|
self.set_clipboard(&paths)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -693,16 +674,30 @@ impl ClipboardContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_file_list(&self, conn_id: i32) -> Result<(), CliprdrError> {
|
||||||
|
let file_list = self.clipboard.get_file_list()?;
|
||||||
|
let paths = file_list.into_iter().map(|lf| lf.path).collect();
|
||||||
|
|
||||||
|
send_file_list(paths, conn_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliprdrServiceContext for ClipboardContext {
|
impl CliprdrServiceContext for ClipboardContext {
|
||||||
fn set_is_stopped(&mut self) -> Result<(), CliprdrError> {
|
fn set_is_stopped(&mut self) -> Result<(), CliprdrError> {
|
||||||
self.stop()
|
// unmount the fuse
|
||||||
|
if let Some(fuse_handle) = self.fuse_handle.lock().take() {
|
||||||
|
fuse_handle.join();
|
||||||
|
}
|
||||||
|
self.clipboard.stop();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn empty_clipboard(&mut self, _conn_id: i32) -> Result<bool, CliprdrError> {
|
fn empty_clipboard(&mut self, _conn_id: i32) -> Result<bool, CliprdrError> {
|
||||||
self.clipboard.set_file_list(&[])?;
|
self.clipboard.set_file_list(&[])?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn server_clip_file(&mut self, conn_id: i32, msg: ClipboardFile) -> Result<(), CliprdrError> {
|
fn server_clip_file(&mut self, conn_id: i32, msg: ClipboardFile) -> Result<(), CliprdrError> {
|
||||||
self.serve(conn_id, msg)
|
self.serve(conn_id, msg)
|
||||||
}
|
}
|
||||||
@ -715,3 +710,43 @@ fn resp_format_data_failure(conn_id: i32) {
|
|||||||
};
|
};
|
||||||
send_data(conn_id, data)
|
send_data(conn_id, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_format_list(conn_id: i32) -> Result<(), CliprdrError> {
|
||||||
|
log::debug!("send format list to remote, conn={}", conn_id);
|
||||||
|
let fd_format_name = get_local_format(FILEDESCRIPTOR_FORMAT_ID)
|
||||||
|
.unwrap_or(FILEDESCRIPTORW_FORMAT_NAME.to_string());
|
||||||
|
let fc_format_name =
|
||||||
|
get_local_format(FILECONTENTS_FORMAT_ID).unwrap_or(FILECONTENTS_FORMAT_NAME.to_string());
|
||||||
|
let format_list = ClipboardFile::FormatList {
|
||||||
|
format_list: vec![
|
||||||
|
(FILEDESCRIPTOR_FORMAT_ID, fd_format_name),
|
||||||
|
(FILECONTENTS_FORMAT_ID, fc_format_name),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
send_data(conn_id, format_list);
|
||||||
|
log::debug!("format list to remote dispatched, conn={}", conn_id);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_file_list(paths: Vec<PathBuf>, conn_id: i32) -> Result<(), CliprdrError> {
|
||||||
|
log::debug!("send file list to remote, conn={}", conn_id);
|
||||||
|
let files = construct_file_list(paths.as_slice())?;
|
||||||
|
|
||||||
|
let mut data = BytesMut::with_capacity(4 + 592 * files.len());
|
||||||
|
data.put_u32_le(paths.len() as u32);
|
||||||
|
for file in files.iter() {
|
||||||
|
data.put(file.as_bin().as_slice());
|
||||||
|
}
|
||||||
|
|
||||||
|
let format_data = data.to_vec();
|
||||||
|
|
||||||
|
send_data(
|
||||||
|
conn_id,
|
||||||
|
ClipboardFile::FormatDataResponse {
|
||||||
|
msg_flags: 1,
|
||||||
|
format_data,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -4,21 +4,15 @@ use std::{
|
|||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use hbb_common::{
|
use hbb_common::log;
|
||||||
bytes::{BufMut, BytesMut},
|
|
||||||
log,
|
|
||||||
};
|
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use x11_clipboard::Clipboard;
|
use x11_clipboard::Clipboard;
|
||||||
use x11rb::protocol::xproto::Atom;
|
use x11rb::protocol::xproto::Atom;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
platform::linux::{
|
platform::linux::{construct_file_list, send_format_list},
|
||||||
construct_file_list, FILECONTENTS_FORMAT_ID, FILECONTENTS_FORMAT_NAME,
|
CliprdrError,
|
||||||
FILEDESCRIPTORW_FORMAT_NAME, FILEDESCRIPTOR_FORMAT_ID,
|
|
||||||
},
|
|
||||||
send_data, ClipboardFile, CliprdrError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{encode_path_to_uri, parse_plain_uri_list, SysClipboard};
|
use super::{encode_path_to_uri, parse_plain_uri_list, SysClipboard};
|
||||||
@ -175,89 +169,8 @@ impl SysClipboard for X11Clipboard {
|
|||||||
log::debug!("stop listening file related atoms on clipboard");
|
log::debug!("stop listening file related atoms on clipboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_format_list(&self, conn_id: i32) -> Result<(), CliprdrError> {
|
fn get_file_list(&self) -> Result<Vec<super::LocalFile>, CliprdrError> {
|
||||||
if self.is_stopped() {
|
let paths = { self.former_file_list.lock().clone() };
|
||||||
log::debug!("clipboard stopped, skip sending");
|
construct_file_list(&paths)
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(paths) = self.wait_file_list()? else {
|
|
||||||
log::debug!("no files in format list, skip sending");
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
let filtered: Vec<_> = paths
|
|
||||||
.into_iter()
|
|
||||||
.filter(|pb| !pb.starts_with(&self.ignore_path))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if filtered.is_empty() {
|
|
||||||
log::debug!("no files in format list, skip sending");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
send_format_list(conn_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_file_list(&self, conn_id: i32) -> Result<(), CliprdrError> {
|
|
||||||
if self.is_stopped() {
|
|
||||||
log::debug!("clipboard stopped, skip sending");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let Some(paths) = self.wait_file_list()? else {
|
|
||||||
log::debug!("no files in format list, skip sending");
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
let filtered: Vec<_> = paths
|
|
||||||
.into_iter()
|
|
||||||
.filter(|pb| !pb.starts_with(&self.ignore_path))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if filtered.is_empty() {
|
|
||||||
log::debug!("no files in format list, skip sending");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
send_file_list(filtered, conn_id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_format_list(conn_id: i32) -> Result<(), CliprdrError> {
|
|
||||||
log::debug!("send format list to remote, conn={}", conn_id);
|
|
||||||
let format_list = ClipboardFile::FormatList {
|
|
||||||
format_list: vec![
|
|
||||||
(
|
|
||||||
FILEDESCRIPTOR_FORMAT_ID,
|
|
||||||
FILEDESCRIPTORW_FORMAT_NAME.to_string(),
|
|
||||||
),
|
|
||||||
(FILECONTENTS_FORMAT_ID, FILECONTENTS_FORMAT_NAME.to_string()),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
send_data(conn_id, format_list);
|
|
||||||
log::debug!("format list to remote dispatched, conn={}", conn_id);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_file_list(paths: Vec<PathBuf>, conn_id: i32) -> Result<(), CliprdrError> {
|
|
||||||
log::debug!("send file list to remote, conn={}", conn_id);
|
|
||||||
let files = construct_file_list(paths.as_slice())?;
|
|
||||||
|
|
||||||
let mut data = BytesMut::with_capacity(4 + 592 * files.len());
|
|
||||||
data.put_u32_le(paths.len() as u32);
|
|
||||||
for file in files.iter() {
|
|
||||||
data.put(file.as_bin().as_slice());
|
|
||||||
}
|
|
||||||
|
|
||||||
let format_data = data.to_vec();
|
|
||||||
|
|
||||||
send_data(
|
|
||||||
conn_id,
|
|
||||||
ClipboardFile::FormatDataResponse {
|
|
||||||
msg_flags: 1,
|
|
||||||
format_data,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
@ -317,6 +317,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
if stop {
|
if stop {
|
||||||
ContextSend::set_is_stopped();
|
ContextSend::set_is_stopped();
|
||||||
} else {
|
} else {
|
||||||
|
log::debug!("Send system clipboard message to remote");
|
||||||
let msg = crate::clipboard_file::clip_2_msg(clip);
|
let msg = crate::clipboard_file::clip_2_msg(clip);
|
||||||
allow_err!(peer.send(&msg).await);
|
allow_err!(peer.send(&msg).await);
|
||||||
}
|
}
|
||||||
@ -1714,6 +1715,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
|
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
fn handle_cliprdr_msg(&self, clip: hbb_common::message_proto::Cliprdr) {
|
fn handle_cliprdr_msg(&self, clip: hbb_common::message_proto::Cliprdr) {
|
||||||
|
log::debug!("handling cliprdr msg from server peer");
|
||||||
#[cfg(feature = "flutter")]
|
#[cfg(feature = "flutter")]
|
||||||
if let Some(hbb_common::message_proto::cliprdr::Union::FormatList(_)) = &clip.union {
|
if let Some(hbb_common::message_proto::cliprdr::Union::FormatList(_)) = &clip.union {
|
||||||
if self.client_conn_id
|
if self.client_conn_id
|
||||||
@ -1723,20 +1725,23 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) {
|
let Some(clip) = crate::clipboard_file::msg_2_clip(clip) else {
|
||||||
let is_stopping_allowed = clip.is_stopping_allowed_from_peer();
|
log::warn!("failed to decode cliprdr msg from server peer");
|
||||||
let file_transfer_enabled = self.handler.lc.read().unwrap().enable_file_transfer.v;
|
return;
|
||||||
let stop = is_stopping_allowed && !file_transfer_enabled;
|
};
|
||||||
log::debug!(
|
|
||||||
|
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: {}",
|
"Process clipboard message from server peer, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}",
|
||||||
stop, is_stopping_allowed, file_transfer_enabled);
|
stop, is_stopping_allowed, file_transfer_enabled);
|
||||||
if !stop {
|
if !stop {
|
||||||
let _ = ContextSend::proc(|context| -> ResultType<()> {
|
let _ = ContextSend::proc(|context| -> ResultType<()> {
|
||||||
context
|
context
|
||||||
.server_clip_file(self.client_conn_id, clip)
|
.server_clip_file(self.client_conn_id, clip)
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -480,6 +480,7 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
#[cfg(any(target_os="windows", target_os="linux"))]
|
#[cfg(any(target_os="windows", target_os="linux"))]
|
||||||
ipc::Data::ClipboardFile(clip) => {
|
ipc::Data::ClipboardFile(clip) => {
|
||||||
|
log::debug!("got clipfile from rx_from_cm, send to stream: {:?}", clip);
|
||||||
allow_err!(conn.stream.send(&clip_2_msg(clip)).await);
|
allow_err!(conn.stream.send(&clip_2_msg(clip)).await);
|
||||||
}
|
}
|
||||||
ipc::Data::PrivacyModeState((_, state)) => {
|
ipc::Data::PrivacyModeState((_, state)) => {
|
||||||
@ -1785,10 +1786,11 @@ impl Connection {
|
|||||||
update_clipboard(_cb, None);
|
update_clipboard(_cb, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(message::Union::Cliprdr(_clip)) =>
|
Some(message::Union::Cliprdr(_clip)) => {
|
||||||
{
|
log::debug!("got cliprdr file from connection:{:?}", _clip);
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
if let Some(clip) = msg_2_clip(_clip) {
|
if let Some(clip) = msg_2_clip(_clip) {
|
||||||
|
log::debug!("send cliprdr file from connection to cm");
|
||||||
self.send_to_cm(ipc::Data::ClipboardFile(clip))
|
self.send_to_cm(ipc::Data::ClipboardFile(clip))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,7 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
|||||||
}
|
}
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
Data::ClipboardFile(_clip) => {
|
Data::ClipboardFile(_clip) => {
|
||||||
#[cfg(any(windows, linux))]
|
#[cfg(any(target_os = "windows", target_os="linux"))]
|
||||||
{
|
{
|
||||||
let is_stopping_allowed = _clip.is_stopping_allowed_from_peer();
|
let is_stopping_allowed = _clip.is_stopping_allowed_from_peer();
|
||||||
let is_clipboard_enabled = ContextSend::is_enabled();
|
let is_clipboard_enabled = ContextSend::is_enabled();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user