mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-31 00:51:04 +03:00
feat(fs): delegate win --server file reading to CM (#13736)
- Route Windows server-to-client file reads through CM instead of the connection layer - Add FS IPC commands (ReadFile, CancelRead, SendConfirmForRead, ReadAllFiles) and CM data messages (ReadJobInitResult, FileBlockFromCM, FileReadDone, FileReadError, FileDigestFromCM, AllFilesResult) - Track pending read validations and read jobs to coordinate CM-driven file transfers and clean them up on completion, cancellation, and errors - Enforce a configurable file-transfer-max-files limit for ReadAllFiles and add stronger file name/path validation on the CM side - Improve Flutter file transfer UX and robustness: - Use explicit percent/percentText progress fields - Derive speed and cancel actions from the active job - Handle job errors via FileModel.handleJobError and complete pending recursive tasks on failure - Wrap recursive directory operations in try/catch and await sendRemoveEmptyDir when removing empty directories Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
93
src/ipc.rs
93
src/ipc.rs
@@ -112,6 +112,33 @@ pub enum FS {
|
||||
path: String,
|
||||
new_name: String,
|
||||
},
|
||||
// CM-side file reading operations (Windows only)
|
||||
// These enable Connection Manager to read files and stream them back to Connection
|
||||
ReadFile {
|
||||
path: String,
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
include_hidden: bool,
|
||||
conn_id: i32,
|
||||
overwrite_detection: bool,
|
||||
},
|
||||
CancelRead {
|
||||
id: i32,
|
||||
conn_id: i32,
|
||||
},
|
||||
SendConfirmForRead {
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
skip: bool,
|
||||
offset_blk: u32,
|
||||
conn_id: i32,
|
||||
},
|
||||
ReadAllFiles {
|
||||
path: String,
|
||||
id: i32,
|
||||
include_hidden: bool,
|
||||
conn_id: i32,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -268,6 +295,72 @@ pub enum Data {
|
||||
#[cfg(windows)]
|
||||
ControlledSessionCount(usize),
|
||||
CmErr(String),
|
||||
// CM-side file reading responses (Windows only)
|
||||
// These are sent from CM back to Connection when CM handles file reading
|
||||
/// Response to ReadFile: contains initial file list or error
|
||||
ReadJobInitResult {
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
include_hidden: bool,
|
||||
conn_id: i32,
|
||||
/// Serialized protobuf bytes of FileDirectory, or error string
|
||||
result: Result<Vec<u8>, String>,
|
||||
},
|
||||
/// File data block read by CM.
|
||||
///
|
||||
/// The actual data is sent separately via `send_raw()` after this message to avoid
|
||||
/// JSON encoding overhead for large binary data. This mirrors the `WriteBlock` pattern.
|
||||
///
|
||||
/// **Protocol:**
|
||||
/// - Sender: `send(FileBlockFromCM{...})` then `send_raw(data)`
|
||||
/// - Receiver: `next()` returns `FileBlockFromCM`, then `next_raw()` returns data bytes
|
||||
///
|
||||
/// **Note on empty data (e.g., empty files):**
|
||||
/// Empty data is supported. The IPC connection uses `BytesCodec` with `raw=false` (default),
|
||||
/// which prefixes each frame with a length header. So `send_raw(Bytes::new())` sends a
|
||||
/// 1-byte frame (length=0), and `next_raw()` correctly returns an empty `BytesMut`.
|
||||
/// See `libs/hbb_common/src/bytes_codec.rs` test `test_codec2` for verification.
|
||||
FileBlockFromCM {
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
/// Data is sent separately via `send_raw()` to avoid JSON encoding overhead.
|
||||
/// This field is skipped during serialization; sender must call `send_raw()` after sending.
|
||||
/// Receiver must call `next_raw()` and populate this field manually.
|
||||
#[serde(skip)]
|
||||
data: bytes::Bytes,
|
||||
compressed: bool,
|
||||
conn_id: i32,
|
||||
},
|
||||
/// File read completed successfully
|
||||
FileReadDone {
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
conn_id: i32,
|
||||
},
|
||||
/// File read failed with error
|
||||
FileReadError {
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
err: String,
|
||||
conn_id: i32,
|
||||
},
|
||||
/// Digest info from CM for overwrite detection
|
||||
FileDigestFromCM {
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
last_modified: u64,
|
||||
file_size: u64,
|
||||
is_resume: bool,
|
||||
conn_id: i32,
|
||||
},
|
||||
/// Response to ReadAllFiles: recursive directory listing
|
||||
AllFilesResult {
|
||||
id: i32,
|
||||
conn_id: i32,
|
||||
path: String,
|
||||
/// Serialized protobuf bytes of FileDirectory, or error string
|
||||
result: Result<Vec<u8>, String>,
|
||||
},
|
||||
CheckHwcodec,
|
||||
#[cfg(feature = "flutter")]
|
||||
VideoConnCount(Option<usize>),
|
||||
|
||||
Reference in New Issue
Block a user