From f4c6c4f6c4a4c4013c83f193a4477b4b0f4cb7fb Mon Sep 17 00:00:00 2001 From: kingtous Date: Tue, 26 Apr 2022 14:56:15 +0800 Subject: [PATCH 01/27] feat: add file digest --- libs/hbb_common/protos/message.proto | 19 +++++ libs/hbb_common/src/fs.rs | 44 +++++++++- src/client.rs | 8 ++ src/ui/file_transfer.tis | 23 ++++++ src/ui/remote.rs | 116 ++++++++++++++++++++++++++- 5 files changed, 205 insertions(+), 5 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 9fba78a92..b4a87ad7f 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -245,6 +245,7 @@ message FileAction { oneof union { ReadDir read_dir = 1; FileTransferSendRequest send = 2; + FileTransferSendConfirmRequest send_confirm = 9; FileTransferReceiveRequest receive = 3; FileDirCreate create = 4; FileRemoveDir remove_dir = 5; @@ -262,14 +263,23 @@ message FileResponse { FileTransferBlock block = 2; FileTransferError error = 3; FileTransferDone done = 4; + FileTransferDigest digest = 5; } } +message FileTransferDigest { + int32 id = 1; + sint32 file_num = 2; + uint64 last_edit_timestamp = 3; + uint64 file_size = 4; +} + message FileTransferBlock { int32 id = 1; sint32 file_num = 2; bytes data = 3; bool compressed = 4; + uint32 blk_id = 5; } message FileTransferError { @@ -284,6 +294,15 @@ message FileTransferSendRequest { bool include_hidden = 3; } +message FileTransferSendConfirmRequest { + int32 id = 1; + sint32 file_num = 2; + oneof union { + bool skip = 3; + uint32 offset_blk = 4; + } +} + message FileTransferDone { int32 id = 1; sint32 file_num = 2; diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 475f4dfc6..554330ab2 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -5,8 +5,10 @@ use crate::{ compress::{compress, decompress}, config::{Config, COMPRESS_LEVEL}, }; +use log::log; #[cfg(windows)] use std::os::windows::prelude::*; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use tokio::{fs::File, io::*}; pub fn read_dir(path: &PathBuf, include_hidden: bool) -> ResultType { @@ -184,6 +186,11 @@ pub fn get_recursive_files(path: &str, include_hidden: bool) -> ResultType bool { + return Path::new(file_path).exists(); +} + #[derive(Default)] pub struct TransferJob { id: i32, @@ -194,6 +201,7 @@ pub struct TransferJob { total_size: u64, finished_size: u64, transferred: u64, + default_overwrite_strategy: Option, } #[inline] @@ -220,6 +228,7 @@ fn is_compressed_file(name: &str) -> bool { impl TransferJob { pub fn new_write(id: i32, path: String, files: Vec) -> Self { + println!("new write {}", path); let total_size = files.iter().map(|x| x.size as u64).sum(); Self { id, @@ -231,6 +240,7 @@ impl TransferJob { } pub fn new_read(id: i32, path: String, include_hidden: bool) -> ResultType { + println!("new read {}", path); let files = get_recursive_files(&path, include_hidden)?; let total_size = files.iter().map(|x| x.size as u64).sum(); Ok(Self { @@ -342,7 +352,7 @@ impl TransferJob { } #[inline] - fn join(&self, name: &str) -> PathBuf { + pub fn join(&self, name: &str) -> PathBuf { if name.is_empty() { self.path.clone() } else { @@ -413,6 +423,13 @@ impl TransferJob { ..Default::default() })) } + pub fn set_overwrite_strategy(&mut self, overwrite_strategy: Option) { + self.default_overwrite_strategy = overwrite_strategy; + } + + pub fn default_overwrite_strategy(&self) -> Option { + self.default_overwrite_strategy + } } #[inline] @@ -468,6 +485,7 @@ pub fn new_receive(id: i32, path: String, files: Vec) -> Message { #[inline] pub fn new_send(id: i32, path: String, include_hidden: bool) -> Message { + println!("new send: {},id : {}", path, id); let mut action = FileAction::new(); action.set_send(FileTransferSendRequest { id, @@ -558,3 +576,27 @@ pub fn create_dir(dir: &str) -> ResultType<()> { std::fs::create_dir_all(get_path(dir))?; Ok(()) } + +#[inline] +pub fn is_write_need_confirmation( + file_path: &str, + digest: &FileTransferDigest, +) -> ResultType { + let path = Path::new(file_path); + if path.exists() && path.is_file() { + let metadata = std::fs::metadata(path)?; + let modified_time = metadata.modified()?; + let remote_mt = Duration::from_millis(digest.last_edit_timestamp); + let local_mt = modified_time.duration_since(UNIX_EPOCH)?; + // if + // is_recv && remote_mt >= local_mt) || (!is_recv && remote_mt <= local_mt) || + if remote_mt == local_mt && digest.file_size == metadata.len() { + // I'm recving or sending an newer modified file! + // or a + return Ok(false); + } + Ok(true) + } else { + Ok(false) + } +} diff --git a/src/client.rs b/src/client.rs index cfe02c20c..e8d339262 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1323,6 +1323,8 @@ pub enum Data { AddPortForward((i32, String, i32)), ToggleClipboardFile, NewRDP, + // ConfirmOverrideFile((i32, String, String, bool, bool)), + SetConfirmOverrideFile((i32, i32, bool, bool)), } #[derive(Clone)] @@ -1332,6 +1334,12 @@ pub enum Key { _Raw(u32), } +#[derive(Clone)] +pub enum OverrideStrategy { + Skip, + Overwrite, +} + lazy_static::lazy_static! { pub static ref KEY_MAP: HashMap<&'static str, Key> = [ diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index d66a8688e..87cb0b17b 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -679,6 +679,7 @@ function confirmDelete(id ,path, is_remote) { } handler.confirmDeleteFiles = function(id, i, name) { + stdout.println("id=" + id +", i=" +",name="+name); var jt = file_transfer.job_table; var job = jt.job_map[id]; if (!job) return; @@ -716,6 +717,28 @@ handler.confirmDeleteFiles = function(id, i, name) { }); } +handler.overrideFileConfirm = function(id, file_num, to) { + var jt = file_transfer.job_table; + var job = jt.job_map[id]; + stdout.println("job type: " + job.type); + stdout.println(id + path + to); + stdout.println(JSON.stringify(job)); + msgbox("custom-skip", "Confirm Write Strategy", "
\ +
" + translate('Overwrite') + translate('files') + ".
\ +
" + translate('This file exists in your computer, skip or overwrite this file?') + "
\ + " + to + "
\ +
" + translate('Do this for all conflicts') + "
\ + ", function(res=null) { + if (!res) { + jt.updateJobStatus(id, -1, "cancel"); + } else if (res.skip) { + handler.set_write_override(id,file_num,false,true); // + } else { + handler.set_write_override(id,file_num,true,false); // + } + }); +} + function save_file_transfer_close_state() { var local_dir = file_transfer.local_folder_view.fd.path || ""; var local_show_hidden = file_transfer.local_folder_view.show_hidden ? "Y" : ""; diff --git a/src/ui/remote.rs b/src/ui/remote.rs index de9ca032c..e4e3265a9 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -3,6 +3,7 @@ use crate::clipboard_file::*; use crate::{ client::*, common::{self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL}, + VERSION, }; #[cfg(windows)] use clipboard::{ @@ -10,10 +11,11 @@ use clipboard::{ get_rx_clip_client, server_clip_file, }; use enigo::{self, Enigo, KeyboardControllable}; +use hbb_common::fs::{get_string, is_file_exists}; use hbb_common::{ allow_err, - config::{Config, LocalConfig, PeerConfig}, - fs, log, + config::{self, Config, LocalConfig, PeerConfig}, + fs, get_version_number, log, message_proto::{permission_info::Permission, *}, protobuf::Message as _, rendezvous_proto::ConnType, @@ -216,6 +218,7 @@ impl sciter::EventHandler for Handler { fn toggle_option(String); fn get_remember(); fn peer_platform(); + fn set_write_override(i32,i32, bool,bool); // , } } @@ -536,6 +539,22 @@ impl Handler { self.lc.read().unwrap().remember } + fn set_write_override( + &mut self, + job_id: i32, + file_num: i32, + is_override: bool, + remember: bool, + ) -> bool { + self.send(Data::SetConfirmOverrideFile(( + job_id, + file_num, + is_override, + remember, + ))); + true + } + fn t(&self, name: String) -> String { crate::client::translate(name) } @@ -1498,6 +1517,7 @@ impl Remote { } async fn handle_msg_from_ui(&mut self, data: Data, peer: &mut Stream) -> bool { + println!("new msg from ui"); match data { Data::Close => { return false; @@ -1514,8 +1534,9 @@ impl Remote { allow_err!(peer.send(&msg).await); } Data::SendFiles((id, path, to, include_hidden, is_remote)) => { + println!("send files, is remote {}", is_remote); if is_remote { - log::debug!("New job {}, write to {} from remote {}", id, to, path); + println!("New job {}, write to {} from remote {}", id, to, path); self.write_jobs .push(fs::TransferJob::new_write(id, to, Vec::new())); allow_err!(peer.send(&fs::new_send(id, path, include_hidden)).await); @@ -1525,7 +1546,7 @@ impl Remote { self.handle_job_status(id, -1, Some(err.to_string())); } Ok(job) => { - log::debug!( + println!( "New job {}, read {} to remote {}, {} files", id, path, @@ -1558,6 +1579,27 @@ impl Remote { } } } + Data::SetConfirmOverrideFile((id, file_num, need_override, remember)) => { + if let Some(job) = fs::get_job(id, &mut self.write_jobs) { + if remember { + job.set_overwrite_strategy(Some(need_override)); + } + let mut msg = Message::new(); + let mut file_action = FileAction::new(); + file_action.set_send_confirm(FileTransferSendConfirmRequest { + id, + file_num, + union: if need_override { + Some(file_transfer_send_confirm_request::Union::offset_blk(0)) + } else { + Some(file_transfer_send_confirm_request::Union::skip(true)) + }, + ..Default::default() + }); + msg.set_file_action(file_action); + allow_err!(peer.send(&msg).await); + } + } Data::RemoveDirAll((id, path, is_remote)) => { let sep = self.handler.get_path_sep(is_remote); if is_remote { @@ -1784,7 +1826,11 @@ impl Remote { } Some(message::Union::file_response(fr)) => match fr.union { Some(file_response::Union::dir(fd)) => { + println!("file_response is dir: {}", fd.path); let entries = fd.entries.to_vec(); + for entry in &entries { + println!("dir file: {}", entry.name); + } let mut m = make_fd(fd.id, &entries, fd.id > 0); if fd.id <= 0 { m.set_item("path", fd.path); @@ -1796,15 +1842,77 @@ impl Remote { job.files = entries; } } + Some(file_response::Union::digest(digest)) => { + if let Some(job) = fs::get_job(digest.id, &mut self.write_jobs) { + if let Some(file) = job.files().get(digest.file_num as usize) { + let write_path = get_string(&job.join(&file.name)); + let overwrite_strategy = job.default_overwrite_strategy(); + match fs::is_write_need_confirmation(&write_path, &digest) { + Ok(res) => { + if res { + // need confirm + if overwrite_strategy.is_none() { + self.handler.call( + "overrideFileConfirm", + &make_args!( + digest.id, + digest.file_num, + write_path + ), + ); + } else { + let mut msg = Message::new(); + let mut file_action = FileAction::new(); + file_action + .set_send_confirm(FileTransferSendConfirmRequest { + id: digest.id, + file_num: digest.file_num, + union: Some( + if overwrite_strategy.unwrap() { + file_transfer_send_confirm_request::Union::offset_blk(0) + } else { + file_transfer_send_confirm_request::Union::skip(true) + }, + ), + ..Default::default() + }); + msg.set_file_action(file_action); + allow_err!(peer.send(&msg).await); + } + } else { + // file with digest need send + let mut msg = Message::new(); + let mut file_action = FileAction::new(); + file_action + .set_send_confirm(FileTransferSendConfirmRequest { + id: digest.id, + file_num: digest.file_num, + union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)), + ..Default::default() + }); + msg.set_file_action(file_action); + allow_err!(peer.send(&msg).await); + } + } + Err(err) => { + println!("error recving digest: {}", err); + } + } + } + } + } Some(file_response::Union::block(block)) => { + println!("file response block, file num: {}", block.file_num); if let Some(job) = fs::get_job(block.id, &mut self.write_jobs) { if let Err(_err) = job.write(block, None).await { // to-do: add "skip" for writing job + println!("error: {}", _err); } self.update_jobs_status(); } } Some(file_response::Union::done(d)) => { + println!("file response done"); if let Some(job) = fs::get_job(d.id, &mut self.write_jobs) { job.modify_time(); fs::remove_job(d.id, &mut self.write_jobs); From b08877031f08b3df003cc48faefbb3850663f08a Mon Sep 17 00:00:00 2001 From: kingtous Date: Tue, 26 Apr 2022 16:21:34 +0800 Subject: [PATCH 02/27] feat: server connections --- libs/hbb_common/src/fs.rs | 70 ++++++++++++++++++++++++++++++++++++--- src/client.rs | 7 ---- src/server/connection.rs | 5 +++ 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 554330ab2..58676edab 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -1,4 +1,4 @@ -use crate::{bail, message_proto::*, ResultType}; +use crate::{bail, message_proto::*, ResultType, Stream}; use std::path::{Path, PathBuf}; // https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html use crate::{ @@ -198,6 +198,8 @@ pub struct TransferJob { files: Vec, file_num: i32, file: Option, + file_confirmed: bool, + file_is_waiting: bool, total_size: u64, finished_size: u64, transferred: u64, @@ -360,7 +362,7 @@ impl TransferJob { } } - pub async fn read(&mut self) -> ResultType> { + pub async fn read(&mut self, stream: &mut Stream) -> ResultType> { let file_num = self.file_num as usize; if file_num >= self.files.len() { self.file.take(); @@ -371,13 +373,41 @@ impl TransferJob { match File::open(self.join(&name)).await { Ok(file) => { self.file = Some(file); + self.file_confirmed = false; + self.file_is_waiting = false; } Err(err) => { self.file_num += 1; + self.file_confirmed = false; + self.file_is_waiting = false; return Err(err.into()); } } } + if !self.file_confirmed() { + if !self.file_is_waiting() { + let mut msg = Message::new(); + let mut resp = FileResponse::new(); + let meta = self.file.as_ref().unwrap().metadata().await?; + let last_modified = meta + .modified()? + .duration_since(SystemTime::UNIX_EPOCH)? + .as_secs(); + resp.set_digest(FileTransferDigest { + id: self.id, + file_num: self.file_num, + last_edit_timestamp: last_modified, + file_size: meta.len(), + unknown_fields: Default::default(), + cached_size: Default::default(), + }); + self.set_file_is_waiting(true); + msg.set_file_response(resp); + stream.send(&msg); + println!("digest message is sent. waiting for confirm."); + } + return Ok(None); + } const BUF_SIZE: usize = 128 * 1024; let mut buf: Vec = Vec::with_capacity(BUF_SIZE); unsafe { @@ -390,6 +420,8 @@ impl TransferJob { Err(err) => { self.file_num += 1; self.file = None; + self.file_confirmed = false; + self.file_is_waiting = false; return Err(err.into()); } Ok(n) => { @@ -404,6 +436,8 @@ impl TransferJob { if offset == 0 { self.file_num += 1; self.file = None; + self.file_confirmed = false; + self.file_is_waiting = false; } else { self.finished_size += offset as u64; if !is_compressed_file(name) { @@ -430,6 +464,30 @@ impl TransferJob { pub fn default_overwrite_strategy(&self) -> Option { self.default_overwrite_strategy } + + pub fn set_file_confirmed(&mut self, file_confirmed: bool) { + self.file_confirmed = file_confirmed; + } + + pub fn set_file_is_waiting(&mut self, file_is_waiting: bool) { + self.file_is_waiting = file_is_waiting; + } + + pub fn file_is_waiting(&self) -> bool { + self.file_is_waiting + } + + pub fn file_confirmed(&self) -> bool { + self.file_confirmed + } + + pub fn skip_current_file(&mut self) -> bool { + self.file.take(); + self.set_file_confirmed(false); + self.set_file_is_waiting(false); + self.file_num += 1; + true + } } #[inline] @@ -527,7 +585,7 @@ pub async fn handle_read_jobs( ) -> ResultType<()> { let mut finished = Vec::new(); for job in jobs.iter_mut() { - match job.read().await { + match job.read(stream).await { Err(err) => { stream .send(&new_error(job.id(), err, job.file_num())) @@ -537,8 +595,10 @@ pub async fn handle_read_jobs( stream.send(&new_block(block)).await?; } Ok(None) => { - finished.push(job.id()); - stream.send(&new_done(job.id(), job.file_num())).await?; + if !job.file_confirmed && !job.file_is_waiting { + finished.push(job.id()); + stream.send(&new_done(job.id(), job.file_num())).await?; + } } } } diff --git a/src/client.rs b/src/client.rs index e8d339262..50e264dba 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1323,7 +1323,6 @@ pub enum Data { AddPortForward((i32, String, i32)), ToggleClipboardFile, NewRDP, - // ConfirmOverrideFile((i32, String, String, bool, bool)), SetConfirmOverrideFile((i32, i32, bool, bool)), } @@ -1334,12 +1333,6 @@ pub enum Key { _Raw(u32), } -#[derive(Clone)] -pub enum OverrideStrategy { - Skip, - Overwrite, -} - lazy_static::lazy_static! { pub static ref KEY_MAP: HashMap<&'static str, Key> = [ diff --git a/src/server/connection.rs b/src/server/connection.rs index e726ba5b0..c3a265ba3 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -6,6 +6,7 @@ use crate::common::update_clipboard; use crate::ipc; #[cfg(any(target_os = "android", target_os = "ios"))] use crate::{common::MOBILE_INFO2, mobile::connection_manager::start_channel}; +use hbb_common::message_proto::file_transfer_send_confirm_request::Union; use hbb_common::{ config::Config, fs, @@ -1018,6 +1019,10 @@ impl Connection { self.send_fs(ipc::FS::CancelWrite { id: c.id }); fs::remove_job(c.id, &mut self.read_jobs); } + Some(file_action::Union::send_confirm(r)) => { + // + println!("recv send confirm request"); + } _ => {} } } From 5caf28ebe650b8793bc6361e1e5213f304824460 Mon Sep 17 00:00:00 2001 From: kingtous Date: Tue, 26 Apr 2022 16:33:54 +0800 Subject: [PATCH 03/27] add: send confirm request logic --- src/server/connection.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index c3a265ba3..9e85613a5 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -6,6 +6,7 @@ use crate::common::update_clipboard; use crate::ipc; #[cfg(any(target_os = "android", target_os = "ios"))] use crate::{common::MOBILE_INFO2, mobile::connection_manager::start_channel}; +use hbb_common::log::debug; use hbb_common::message_proto::file_transfer_send_confirm_request::Union; use hbb_common::{ config::Config, @@ -1020,8 +1021,33 @@ impl Connection { fs::remove_job(c.id, &mut self.read_jobs); } Some(file_action::Union::send_confirm(r)) => { - // + let job_it = self + .read_jobs + .iter_mut() + .filter(|job| job.id() == r.id) + .next(); println!("recv send confirm request"); + if let Some(job) = job_it { + if job.file_num() != r.file_num { + debug!("file num truncated, ignoring"); + } else { + match r.union { + Some(file_transfer_send_confirm_request::Union::skip(s)) => { + if s { + println!("skip current file"); + job.skip_current_file(); + } else { + job.set_file_confirmed(true); + } + } + Some(file_transfer_send_confirm_request::Union::offset_blk(offset)) => { + println!("file confirmed"); + job.set_file_confirmed(true); + }, + _ => {} + } + } + } } _ => {} } From 8854fcbe85448fd3447c249d2e71eeb85ae7c81d Mon Sep 17 00:00:00 2001 From: kingtous Date: Wed, 27 Apr 2022 10:45:20 +0800 Subject: [PATCH 04/27] add: automatic accept confirm log --- Cargo.toml | 2 +- libs/hbb_common/src/fs.rs | 87 +++++++++++++++++++++++++++++---------- src/ipc.rs | 6 +++ src/server/connection.rs | 40 +++++++----------- src/ui/cm.rs | 28 +++++++++++++ src/ui/file_transfer.tis | 15 +++++-- src/ui/remote.rs | 21 ++++++---- 7 files changed, 140 insertions(+), 59 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c2c7186bf..e54ac875d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ default-run = "rustdesk" [lib] name = "librustdesk" -crate-type = ["cdylib", "staticlib", "rlib"] +crate-type = ["cdylib", "staticlib", "rlib"] [[bin]] name = "naming" diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 58676edab..a4b242d05 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -198,11 +198,11 @@ pub struct TransferJob { files: Vec, file_num: i32, file: Option, - file_confirmed: bool, - file_is_waiting: bool, total_size: u64, finished_size: u64, transferred: u64, + file_confirmed: bool, + file_is_waiting: bool, default_overwrite_strategy: Option, } @@ -315,6 +315,7 @@ impl TransferJob { } pub async fn write(&mut self, block: FileTransferBlock, raw: Option<&[u8]>) -> ResultType<()> { + println!("write file transfer blk[{},{}]", block.id, block.file_num); if block.id != self.id { bail!("Wrong id"); } @@ -386,25 +387,8 @@ impl TransferJob { } if !self.file_confirmed() { if !self.file_is_waiting() { - let mut msg = Message::new(); - let mut resp = FileResponse::new(); - let meta = self.file.as_ref().unwrap().metadata().await?; - let last_modified = meta - .modified()? - .duration_since(SystemTime::UNIX_EPOCH)? - .as_secs(); - resp.set_digest(FileTransferDigest { - id: self.id, - file_num: self.file_num, - last_edit_timestamp: last_modified, - file_size: meta.len(), - unknown_fields: Default::default(), - cached_size: Default::default(), - }); + self.send_current_digest(stream).await?; self.set_file_is_waiting(true); - msg.set_file_response(resp); - stream.send(&msg); - println!("digest message is sent. waiting for confirm."); } return Ok(None); } @@ -457,6 +441,32 @@ impl TransferJob { ..Default::default() })) } + + async fn send_current_digest(&mut self, stream: &mut Stream) -> ResultType<()> { + let mut msg = Message::new(); + let mut resp = FileResponse::new(); + let meta = self.file.as_ref().unwrap().metadata().await?; + let last_modified = meta + .modified()? + .duration_since(SystemTime::UNIX_EPOCH)? + .as_secs(); + resp.set_digest(FileTransferDigest { + id: self.id, + file_num: self.file_num, + last_edit_timestamp: last_modified, + file_size: meta.len(), + unknown_fields: Default::default(), + cached_size: Default::default(), + }); + msg.set_file_response(resp); + stream.send(&msg).await?; + println!( + "id: {}, file_num:{}, digest message is sent. waiting for confirm. msg: {:?}", + self.id, self.file_num, msg + ); + Ok(()) + } + pub fn set_overwrite_strategy(&mut self, overwrite_strategy: Option) { self.default_overwrite_strategy = overwrite_strategy; } @@ -488,6 +498,29 @@ impl TransferJob { self.file_num += 1; true } + + pub fn confirm(&mut self, r: &FileTransferSendConfirmRequest) -> bool { + if self.file_num() != r.file_num { + log::debug!("file num truncated, ignoring"); + } else { + match r.union { + Some(file_transfer_send_confirm_request::Union::skip(s)) => { + if s { + log::debug!("skip current file"); + self.skip_current_file(); + } else { + self.set_file_confirmed(true); + } + } + Some(file_transfer_send_confirm_request::Union::offset_blk(offset)) => { + println!("file confirmed"); + self.set_file_confirmed(true); + } + _ => {} + } + } + true + } } #[inline] @@ -506,6 +539,7 @@ pub fn new_error(id: i32, err: T, file_num: i32) -> Me #[inline] pub fn new_dir(id: i32, path: String, files: Vec) -> Message { + println!("[fs.rs:510] create new dir"); let mut resp = FileResponse::new(); resp.set_dir(FileDirectory { id, @@ -585,6 +619,7 @@ pub async fn handle_read_jobs( ) -> ResultType<()> { let mut finished = Vec::new(); for job in jobs.iter_mut() { + // println!("[fs.rs:588] handle_read_jobs. {:?}", job.id); match job.read(stream).await { Err(err) => { stream @@ -598,6 +633,8 @@ pub async fn handle_read_jobs( if !job.file_confirmed && !job.file_is_waiting { finished.push(job.id()); stream.send(&new_done(job.id(), job.file_num())).await?; + } else { + log::info!("waiting confirmation."); } } } @@ -646,8 +683,16 @@ pub fn is_write_need_confirmation( if path.exists() && path.is_file() { let metadata = std::fs::metadata(path)?; let modified_time = metadata.modified()?; - let remote_mt = Duration::from_millis(digest.last_edit_timestamp); + let remote_mt = Duration::from_secs(digest.last_edit_timestamp); let local_mt = modified_time.duration_since(UNIX_EPOCH)?; + println!( + "{:?}:rm:{},lm:{},rf:{},lf:{}", + path, + remote_mt.as_secs(), + local_mt.as_secs(), + digest.file_size, + metadata.len() + ); // if // is_recv && remote_mt >= local_mt) || (!is_recv && remote_mt <= local_mt) || if remote_mt == local_mt && digest.file_size == metadata.len() { diff --git a/src/ipc.rs b/src/ipc.rs index f09367a1a..6d6671e33 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -59,6 +59,12 @@ pub enum FS { id: i32, file_num: i32, }, + CheckDigest { + id: i32, + file_num: i32, + file_size: u64, + modified_time: u64, + }, } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/src/server/connection.rs b/src/server/connection.rs index 9e85613a5..9809db695 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -21,6 +21,7 @@ use hbb_common::{ }, tokio_util::codec::{BytesCodec, Framed}, }; +use libc::{printf, send}; #[cfg(any(target_os = "android", target_os = "ios"))] use scrap::android::call_input_service_mouse_input; use serde_json::{json, value::Value}; @@ -273,7 +274,7 @@ impl Connection { } } ipc::Data::RawMessage(bytes) => { - allow_err!(conn.stream.send_raw(bytes).await); + conn.stream.send_raw(bytes).await; } #[cfg(windows)] ipc::Data::ClipbaordFile(_clip) => { @@ -892,6 +893,7 @@ impl Connection { } } } else if self.authorized { + // println!("on_message: {:?}", msg); match msg.union { Some(message::Union::mouse_event(me)) => { #[cfg(any(target_os = "android", target_os = "ios"))] @@ -953,6 +955,7 @@ impl Connection { } } Some(message::Union::file_action(fa)) => { + println!("recv file_action, {:?}", fa); if self.file_transfer.is_some() { match fa.union { Some(file_action::Union::read_dir(rd)) => { @@ -985,6 +988,7 @@ impl Connection { } } Some(file_action::Union::receive(r)) => { + println!("[connection.rs:891] recv FileTransferReceiveRequest"); self.send_fs(ipc::FS::NewWrite { path: r.path, id: r.id, @@ -1021,32 +1025,9 @@ impl Connection { fs::remove_job(c.id, &mut self.read_jobs); } Some(file_action::Union::send_confirm(r)) => { - let job_it = self - .read_jobs - .iter_mut() - .filter(|job| job.id() == r.id) - .next(); println!("recv send confirm request"); - if let Some(job) = job_it { - if job.file_num() != r.file_num { - debug!("file num truncated, ignoring"); - } else { - match r.union { - Some(file_transfer_send_confirm_request::Union::skip(s)) => { - if s { - println!("skip current file"); - job.skip_current_file(); - } else { - job.set_file_confirmed(true); - } - } - Some(file_transfer_send_confirm_request::Union::offset_blk(offset)) => { - println!("file confirmed"); - job.set_file_confirmed(true); - }, - _ => {} - } - } + if let Some(job) = fs::get_job(r.id, &mut self.read_jobs) { + job.confirm(&r); } } _ => {} @@ -1068,6 +1049,12 @@ impl Connection { file_num: d.file_num, }); } + Some(file_response::Union::digest(d)) => self.send_fs(ipc::FS::CheckDigest { + id: d.id, + file_num: d.file_num, + file_size: d.file_size, + modified_time: d.last_edit_timestamp, + }), _ => {} }, Some(message::Union::misc(misc)) => match misc.union { @@ -1209,6 +1196,7 @@ impl Connection { } fn read_dir(&mut self, dir: &str, include_hidden: bool) { + // println!("[connection.rs:1130] read_dir"); let dir = dir.to_string(); self.send_fs(ipc::FS::ReadDir { dir, diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 1fafedde7..27dee8ee9 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -133,6 +133,7 @@ impl ConnectionManager { dir, include_hidden, } => { + // println!("[cm.rs:126] ipc::FS::ReadDir recved"); Self::read_dir(&dir, include_hidden, conn).await; } ipc::FS::RemoveDir { @@ -153,6 +154,7 @@ impl ConnectionManager { id, mut files, } => { + println!("new write in ipc::FS::NewWrite"); write_jobs.push(fs::TransferJob::new_write( id, path, @@ -179,6 +181,30 @@ impl ConnectionManager { fs::remove_job(id, write_jobs); } } + ipc::FS::CheckDigest { + id, + file_num, + file_size, + modified_time, + } => { + if let Some(job) = fs::get_job(id, write_jobs) { + // TODO + let mut msg_out = Message::new(); + let mut file_action = FileAction::new(); + file_action.set_send_confirm(FileTransferSendConfirmRequest { + id, + file_num, + union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)), + ..Default::default() + }); + msg_out.set_file_action(file_action); + println!( + "[CHECK DIGEST] dig dest recved. confirmed. msg: {:?}", + msg_out + ); + Self::send(msg_out, conn).await; + } + } ipc::FS::WriteBlock { id, file_num, @@ -238,6 +264,7 @@ impl ConnectionManager { let mut file_response = FileResponse::new(); file_response.set_dir(fd); msg_out.set_file_response(file_response); + // println!("[cm.rs:229] set dir"); Self::send(msg_out, conn).await; } } @@ -300,6 +327,7 @@ impl ConnectionManager { } async fn send(msg: Message, conn: &mut Connection) { + println!("send msg: {:?}", msg); match msg.write_to_bytes() { Ok(bytes) => allow_err!(conn.send(&Data::RawMessage(bytes)).await), err => allow_err!(err), diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index 87cb0b17b..97fbc9404 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -721,20 +721,27 @@ handler.overrideFileConfirm = function(id, file_num, to) { var jt = file_transfer.job_table; var job = jt.job_map[id]; stdout.println("job type: " + job.type); - stdout.println(id + path + to); stdout.println(JSON.stringify(job)); msgbox("custom-skip", "Confirm Write Strategy", "
\
" + translate('Overwrite') + translate('files') + ".
\ -
" + translate('This file exists in your computer, skip or overwrite this file?') + "
\ +
" + translate('This file exists, skip or overwrite this file?') + "
\ " + to + "
\
" + translate('Do this for all conflicts') + "
\ ", function(res=null) { if (!res) { jt.updateJobStatus(id, -1, "cancel"); } else if (res.skip) { - handler.set_write_override(id,file_num,false,true); // + if (res.remember){ + handler.set_write_override(id,file_num,false,true); // + } else { + handler.set_write_override(id,file_num,false,false); // + } } else { - handler.set_write_override(id,file_num,true,false); // + if (res.remember){ + handler.set_write_override(id,file_num,true,true); // + } else { + handler.set_write_override(id,file_num,true,false); // + } } }); } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index e4e3265a9..e134ea4d7 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -12,6 +12,7 @@ use clipboard::{ }; use enigo::{self, Enigo, KeyboardControllable}; use hbb_common::fs::{get_string, is_file_exists}; +use hbb_common::log::log; use hbb_common::{ allow_err, config::{self, Config, LocalConfig, PeerConfig}, @@ -1517,7 +1518,7 @@ impl Remote { } async fn handle_msg_from_ui(&mut self, data: Data, peer: &mut Stream) -> bool { - println!("new msg from ui"); + // log::info!("new msg from ui, {}",data); match data { Data::Close => { return false; @@ -1759,6 +1760,7 @@ impl Remote { async fn handle_msg_from_peer(&mut self, data: &[u8], peer: &mut Stream) -> bool { if let Ok(msg_in) = Message::parse_from_bytes(&data) { + println!("recved msg from peer, decoded: {:?}", msg_in); match msg_in.union { Some(message::Union::video_frame(vf)) => { if !self.first_frame { @@ -1826,11 +1828,7 @@ impl Remote { } Some(message::Union::file_response(fr)) => match fr.union { Some(file_response::Union::dir(fd)) => { - println!("file_response is dir: {}", fd.path); let entries = fd.entries.to_vec(); - for entry in &entries { - println!("dir file: {}", entry.name); - } let mut m = make_fd(fd.id, &entries, fd.id > 0); if fd.id <= 0 { m.set_item("path", fd.path); @@ -1843,6 +1841,7 @@ impl Remote { } } Some(file_response::Union::digest(digest)) => { + log::info!("recv file transfer digest"); if let Some(job) = fs::get_job(digest.id, &mut self.write_jobs) { if let Some(file) = job.files().get(digest.file_num as usize) { let write_path = get_string(&job.join(&file.name)); @@ -1902,7 +1901,7 @@ impl Remote { } } Some(file_response::Union::block(block)) => { - println!("file response block, file num: {}", block.file_num); + log::info!("file response block, file num: {}", block.file_num); if let Some(job) = fs::get_job(block.id, &mut self.write_jobs) { if let Err(_err) = job.write(block, None).await { // to-do: add "skip" for writing job @@ -1912,7 +1911,7 @@ impl Remote { } } Some(file_response::Union::done(d)) => { - println!("file response done"); + log::info!("file response done"); if let Some(job) = fs::get_job(d.id, &mut self.write_jobs) { job.modify_time(); fs::remove_job(d.id, &mut self.write_jobs); @@ -1999,6 +1998,14 @@ impl Remote { self.audio_sender.send(MediaData::AudioFrame(frame)).ok(); } } + Some(message::Union::file_action(action)) => match action.union { + Some(file_action::Union::send_confirm(c)) => { + if let Some(job) = fs::get_job(c.id, &mut self.read_jobs) { + job.confirm(&c); + } + } + _ => {} + }, _ => {} } } From 51caeafebd7b2d97a06a57be9fd13c14b68955ba Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 28 Apr 2022 16:06:52 +0800 Subject: [PATCH 05/27] add: server override --- libs/hbb_common/src/fs.rs | 31 +++++++++++++++++-------- src/server/connection.rs | 4 +--- src/ui/cm.rs | 49 ++++++++++++++++++++++++++++++--------- src/ui/remote.rs | 38 +++++++++++------------------- 4 files changed, 74 insertions(+), 48 deletions(-) diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index a4b242d05..57dba0b53 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -506,7 +506,7 @@ impl TransferJob { match r.union { Some(file_transfer_send_confirm_request::Union::skip(s)) => { if s { - log::debug!("skip current file"); + println!("skip current file"); self.skip_current_file(); } else { self.set_file_confirmed(true); @@ -561,6 +561,15 @@ pub fn new_block(block: FileTransferBlock) -> Message { msg_out } +#[inline] +pub fn new_send_confirm(r: FileTransferSendConfirmRequest) -> Message { + let mut msg_out = Message::new(); + let mut action = FileAction::new(); + action.set_send_confirm(r); + msg_out.set_file_action(action); + msg_out +} + #[inline] pub fn new_receive(id: i32, path: String, files: Vec) -> Message { let mut action = FileAction::new(); @@ -678,14 +687,14 @@ pub fn create_dir(dir: &str) -> ResultType<()> { pub fn is_write_need_confirmation( file_path: &str, digest: &FileTransferDigest, -) -> ResultType { +) -> ResultType> { let path = Path::new(file_path); if path.exists() && path.is_file() { let metadata = std::fs::metadata(path)?; let modified_time = metadata.modified()?; let remote_mt = Duration::from_secs(digest.last_edit_timestamp); let local_mt = modified_time.duration_since(UNIX_EPOCH)?; - println!( + log::info!( "{:?}:rm:{},lm:{},rf:{},lf:{}", path, remote_mt.as_secs(), @@ -693,15 +702,17 @@ pub fn is_write_need_confirmation( digest.file_size, metadata.len() ); - // if - // is_recv && remote_mt >= local_mt) || (!is_recv && remote_mt <= local_mt) || if remote_mt == local_mt && digest.file_size == metadata.len() { - // I'm recving or sending an newer modified file! - // or a - return Ok(false); + return Ok(None); } - Ok(true) + Ok(Some(FileTransferDigest { + id: digest.id, + file_num: digest.file_num, + last_edit_timestamp: local_mt.as_secs(), + file_size: metadata.len(), + ..Default::default() + })) } else { - Ok(false) + Ok(None) } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 9809db695..3c0ee3810 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -955,7 +955,7 @@ impl Connection { } } Some(message::Union::file_action(fa)) => { - println!("recv file_action, {:?}", fa); + log::info!("recv file_action, {:?}", fa); if self.file_transfer.is_some() { match fa.union { Some(file_action::Union::read_dir(rd)) => { @@ -988,7 +988,6 @@ impl Connection { } } Some(file_action::Union::receive(r)) => { - println!("[connection.rs:891] recv FileTransferReceiveRequest"); self.send_fs(ipc::FS::NewWrite { path: r.path, id: r.id, @@ -1025,7 +1024,6 @@ impl Connection { fs::remove_job(c.id, &mut self.read_jobs); } Some(file_action::Union::send_confirm(r)) => { - println!("recv send confirm request"); if let Some(job) = fs::get_job(r.id, &mut self.read_jobs) { job.confirm(&r); } diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 27dee8ee9..945d17fd1 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -3,6 +3,8 @@ use crate::ipc::{self, new_listener, Connection, Data}; use clipboard::{ create_cliprdr_context, empty_clipboard, get_rx_clip_client, server_clip_file, set_conn_enabled, }; +use hbb_common::fs::{get_string, is_write_need_confirmation, new_send_confirm}; +use hbb_common::log::log; use hbb_common::{ allow_err, config::Config, @@ -10,6 +12,7 @@ use hbb_common::{ message_proto::*, protobuf::Message as _, tokio::{self, sync::mpsc, task::spawn_blocking}, + ResultType, }; use sciter::{make_args, Element, Value, HELEMENT}; use std::{ @@ -188,21 +191,45 @@ impl ConnectionManager { modified_time, } => { if let Some(job) = fs::get_job(id, write_jobs) { - // TODO - let mut msg_out = Message::new(); - let mut file_action = FileAction::new(); - file_action.set_send_confirm(FileTransferSendConfirmRequest { + let mut req = FileTransferSendConfirmRequest { id, file_num, union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)), ..Default::default() - }); - msg_out.set_file_action(file_action); - println!( - "[CHECK DIGEST] dig dest recved. confirmed. msg: {:?}", - msg_out - ); - Self::send(msg_out, conn).await; + }; + let digest = FileTransferDigest { + id, + file_num, + last_edit_timestamp: modified_time, + file_size, + ..Default::default() + }; + if let Some(file) = job.files().get(file_num as usize) { + let path = get_string(&job.join(&file.name)); + match is_write_need_confirmation(&path, &digest) { + Ok(digest) => { + if digest.is_none() { + log::info!("skip job {}, file_num {}", id, file_num); + req.set_skip(true); + let msg_out = new_send_confirm(req); + Self::send(msg_out, conn).await; + } else { + // upload to server, but server has the same file, request + println!( + "server has the same file, send server digest to local" + ); + let mut msg_out = Message::new(); + let mut fr = FileResponse::new(); + fr.set_digest(digest.unwrap()); + msg_out.set_file_response(fr); + Self::send(msg_out, conn).await; + } + } + Err(err) => { + Self::send(fs::new_error(id, err, file_num), conn).await; + } + } + } } } ipc::FS::WriteBlock { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index e134ea4d7..88075b8aa 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -11,7 +11,7 @@ use clipboard::{ get_rx_clip_client, server_clip_file, }; use enigo::{self, Enigo, KeyboardControllable}; -use hbb_common::fs::{get_string, is_file_exists}; +use hbb_common::fs::{get_string, is_file_exists, new_send_confirm}; use hbb_common::log::log; use hbb_common::{ allow_err, @@ -1760,7 +1760,7 @@ impl Remote { async fn handle_msg_from_peer(&mut self, data: &[u8], peer: &mut Stream) -> bool { if let Ok(msg_in) = Message::parse_from_bytes(&data) { - println!("recved msg from peer, decoded: {:?}", msg_in); + // println!("recved msg from peer, decoded: {:?}", msg_in); match msg_in.union { Some(message::Union::video_frame(vf)) => { if !self.first_frame { @@ -1841,14 +1841,13 @@ impl Remote { } } Some(file_response::Union::digest(digest)) => { - log::info!("recv file transfer digest"); if let Some(job) = fs::get_job(digest.id, &mut self.write_jobs) { if let Some(file) = job.files().get(digest.file_num as usize) { let write_path = get_string(&job.join(&file.name)); let overwrite_strategy = job.default_overwrite_strategy(); match fs::is_write_need_confirmation(&write_path, &digest) { Ok(res) => { - if res { + if res.is_some() { // need confirm if overwrite_strategy.is_none() { self.handler.call( @@ -1860,36 +1859,27 @@ impl Remote { ), ); } else { - let mut msg = Message::new(); - let mut file_action = FileAction::new(); - file_action - .set_send_confirm(FileTransferSendConfirmRequest { + let msg = new_send_confirm( + FileTransferSendConfirmRequest { id: digest.id, file_num: digest.file_num, - union: Some( - if overwrite_strategy.unwrap() { - file_transfer_send_confirm_request::Union::offset_blk(0) - } else { - file_transfer_send_confirm_request::Union::skip(true) - }, - ), + union: if overwrite_strategy.unwrap() { + Some(file_transfer_send_confirm_request::Union::offset_blk(0)) + } else { + Some(file_transfer_send_confirm_request::Union::skip(true)) + }, ..Default::default() - }); - msg.set_file_action(file_action); + }, + ); allow_err!(peer.send(&msg).await); } } else { - // file with digest need send - let mut msg = Message::new(); - let mut file_action = FileAction::new(); - file_action - .set_send_confirm(FileTransferSendConfirmRequest { + let msg= new_send_confirm(FileTransferSendConfirmRequest { id: digest.id, file_num: digest.file_num, - union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)), + union: Some(file_transfer_send_confirm_request::Union::skip(true)), ..Default::default() }); - msg.set_file_action(file_action); allow_err!(peer.send(&msg).await); } } From c17e77148ede5e071a82e0302377a6ad224be8dd Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 28 Apr 2022 17:42:22 +0800 Subject: [PATCH 06/27] add: remote ret back override confirmation --- libs/hbb_common/protos/message.proto | 3 +- libs/hbb_common/src/fs.rs | 3 +- src/client.rs | 18 ++-- src/ipc.rs | 1 + src/server/connection.rs | 1 + src/ui/cm.rs | 16 +-- src/ui/file_transfer.tis | 10 +- src/ui/remote.rs | 145 ++++++++++++++++----------- 8 files changed, 117 insertions(+), 80 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index b4a87ad7f..fe45434b1 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -245,13 +245,13 @@ message FileAction { oneof union { ReadDir read_dir = 1; FileTransferSendRequest send = 2; - FileTransferSendConfirmRequest send_confirm = 9; FileTransferReceiveRequest receive = 3; FileDirCreate create = 4; FileRemoveDir remove_dir = 5; FileRemoveFile remove_file = 6; ReadAllFiles all_files = 7; FileTransferCancel cancel = 8; + FileTransferSendConfirmRequest send_confirm = 9; } } @@ -272,6 +272,7 @@ message FileTransferDigest { sint32 file_num = 2; uint64 last_edit_timestamp = 3; uint64 file_size = 4; + bool is_upload = 5; } message FileTransferBlock { diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 57dba0b53..eb5510423 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -455,8 +455,7 @@ impl TransferJob { file_num: self.file_num, last_edit_timestamp: last_modified, file_size: meta.len(), - unknown_fields: Default::default(), - cached_size: Default::default(), + ..Default::default() }); msg.set_file_response(resp); stream.send(&msg).await?; diff --git a/src/client.rs b/src/client.rs index 50e264dba..0c4c4a3df 100644 --- a/src/client.rs +++ b/src/client.rs @@ -533,14 +533,14 @@ impl AudioHandler { } self.simple = Some(Simple::new( - None, // Use the default server - &crate::get_app_name(), // Our application’s name - Direction::Playback, // We want a playback stream - None, // Use the default device - "playback", // Description of our stream - &spec, // Our sample format - None, // Use default channel map - None, // Use default buffering attributes + None, // Use the default server + &crate::get_app_name(), // Our application’s name + Direction::Playback, // We want a playback stream + None, // Use the default device + "playback", // Description of our stream + &spec, // Our sample format + None, // Use default channel map + None, // Use default buffering attributes )?); self.sample_rate = (format0.sample_rate, format0.sample_rate); Ok(()) @@ -1323,7 +1323,7 @@ pub enum Data { AddPortForward((i32, String, i32)), ToggleClipboardFile, NewRDP, - SetConfirmOverrideFile((i32, i32, bool, bool)), + SetConfirmOverrideFile((i32, i32, bool, bool, bool)), } #[derive(Clone)] diff --git a/src/ipc.rs b/src/ipc.rs index 6d6671e33..0a9a2d6c5 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -64,6 +64,7 @@ pub enum FS { file_num: i32, file_size: u64, modified_time: u64, + is_upload: bool, }, } diff --git a/src/server/connection.rs b/src/server/connection.rs index 3c0ee3810..0b15c3659 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1052,6 +1052,7 @@ impl Connection { file_num: d.file_num, file_size: d.file_size, modified_time: d.last_edit_timestamp, + is_upload: true, }), _ => {} }, diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 945d17fd1..ed6f47d96 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -189,6 +189,7 @@ impl ConnectionManager { file_num, file_size, modified_time, + is_upload, } => { if let Some(job) = fs::get_job(id, write_jobs) { let mut req = FileTransferSendConfirmRequest { @@ -208,21 +209,22 @@ impl ConnectionManager { let path = get_string(&job.join(&file.name)); match is_write_need_confirmation(&path, &digest) { Ok(digest) => { - if digest.is_none() { - log::info!("skip job {}, file_num {}", id, file_num); - req.set_skip(true); - let msg_out = new_send_confirm(req); - Self::send(msg_out, conn).await; - } else { + if let Some(mut digest) = digest { // upload to server, but server has the same file, request + digest.is_upload = is_upload; println!( "server has the same file, send server digest to local" ); let mut msg_out = Message::new(); let mut fr = FileResponse::new(); - fr.set_digest(digest.unwrap()); + fr.set_digest(digest); msg_out.set_file_response(fr); Self::send(msg_out, conn).await; + } else { + log::info!("skip job {}, file_num {}", id, file_num); + req.set_skip(true); + let msg_out = new_send_confirm(req); + Self::send(msg_out, conn).await; } } Err(err) => { diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index 97fbc9404..9f0e74a1a 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -717,7 +717,7 @@ handler.confirmDeleteFiles = function(id, i, name) { }); } -handler.overrideFileConfirm = function(id, file_num, to) { +handler.overrideFileConfirm = function(id, file_num, to, is_upload) { var jt = file_transfer.job_table; var job = jt.job_map[id]; stdout.println("job type: " + job.type); @@ -732,15 +732,15 @@ handler.overrideFileConfirm = function(id, file_num, to) { jt.updateJobStatus(id, -1, "cancel"); } else if (res.skip) { if (res.remember){ - handler.set_write_override(id,file_num,false,true); // + handler.set_write_override(id,file_num,false,true, is_upload); // } else { - handler.set_write_override(id,file_num,false,false); // + handler.set_write_override(id,file_num,false,false,is_upload); // } } else { if (res.remember){ - handler.set_write_override(id,file_num,true,true); // + handler.set_write_override(id,file_num,true,true,is_upload); // } else { - handler.set_write_override(id,file_num,true,false); // + handler.set_write_override(id,file_num,true,false,is_upload); // } } }); diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 88075b8aa..b460d6402 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -219,7 +219,7 @@ impl sciter::EventHandler for Handler { fn toggle_option(String); fn get_remember(); fn peer_platform(); - fn set_write_override(i32,i32, bool,bool); // , + fn set_write_override(i32,i32, bool,bool,bool); // , } } @@ -546,12 +546,14 @@ impl Handler { file_num: i32, is_override: bool, remember: bool, + is_upload: bool, ) -> bool { self.send(Data::SetConfirmOverrideFile(( job_id, file_num, is_override, remember, + is_upload, ))); true } @@ -1580,25 +1582,43 @@ impl Remote { } } } - Data::SetConfirmOverrideFile((id, file_num, need_override, remember)) => { - if let Some(job) = fs::get_job(id, &mut self.write_jobs) { - if remember { - job.set_overwrite_strategy(Some(need_override)); + Data::SetConfirmOverrideFile((id, file_num, need_override, remember, is_upload)) => { + if is_upload { + if let Some(job) = fs::get_job(id, &mut self.read_jobs) { + if remember { + job.set_overwrite_strategy(Some(need_override)); + } + job.confirm(&FileTransferSendConfirmRequest { + id, + file_num, + union: if need_override { + Some(file_transfer_send_confirm_request::Union::offset_blk(0)) + } else { + Some(file_transfer_send_confirm_request::Union::skip(true)) + }, + ..Default::default() + }); + } + } else { + if let Some(job) = fs::get_job(id, &mut self.write_jobs) { + if remember { + job.set_overwrite_strategy(Some(need_override)); + } + let mut msg = Message::new(); + let mut file_action = FileAction::new(); + file_action.set_send_confirm(FileTransferSendConfirmRequest { + id, + file_num, + union: if need_override { + Some(file_transfer_send_confirm_request::Union::offset_blk(0)) + } else { + Some(file_transfer_send_confirm_request::Union::skip(true)) + }, + ..Default::default() + }); + msg.set_file_action(file_action); + allow_err!(peer.send(&msg).await); } - let mut msg = Message::new(); - let mut file_action = FileAction::new(); - file_action.set_send_confirm(FileTransferSendConfirmRequest { - id, - file_num, - union: if need_override { - Some(file_transfer_send_confirm_request::Union::offset_blk(0)) - } else { - Some(file_transfer_send_confirm_request::Union::skip(true)) - }, - ..Default::default() - }); - msg.set_file_action(file_action); - allow_err!(peer.send(&msg).await); } } Data::RemoveDirAll((id, path, is_remote)) => { @@ -1841,50 +1861,63 @@ impl Remote { } } Some(file_response::Union::digest(digest)) => { - if let Some(job) = fs::get_job(digest.id, &mut self.write_jobs) { - if let Some(file) = job.files().get(digest.file_num as usize) { - let write_path = get_string(&job.join(&file.name)); - let overwrite_strategy = job.default_overwrite_strategy(); - match fs::is_write_need_confirmation(&write_path, &digest) { - Ok(res) => { - if res.is_some() { - // need confirm - if overwrite_strategy.is_none() { - self.handler.call( - "overrideFileConfirm", - &make_args!( - digest.id, - digest.file_num, - write_path - ), - ); - } else { - let msg = new_send_confirm( - FileTransferSendConfirmRequest { - id: digest.id, - file_num: digest.file_num, - union: if overwrite_strategy.unwrap() { - Some(file_transfer_send_confirm_request::Union::offset_blk(0)) - } else { - Some(file_transfer_send_confirm_request::Union::skip(true)) + if digest.is_upload { + if let Some(job) = fs::get_job(digest.id, &mut self.read_jobs) { + if let Some(file) = job.files().get(digest.file_num as usize) { + let read_path = get_string(&job.join(&file.name)); + self.handler.call( + "overrideFileConfirm", + &make_args!(digest.id, digest.file_num, read_path, true), + ); + } + } + } else { + if let Some(job) = fs::get_job(digest.id, &mut self.write_jobs) { + if let Some(file) = job.files().get(digest.file_num as usize) { + let write_path = get_string(&job.join(&file.name)); + let overwrite_strategy = job.default_overwrite_strategy(); + match fs::is_write_need_confirmation(&write_path, &digest) { + Ok(res) => { + if res.is_some() { + // need confirm + if overwrite_strategy.is_none() { + self.handler.call( + "overrideFileConfirm", + &make_args!( + digest.id, + digest.file_num, + write_path, + false + ), + ); + } else { + let msg = new_send_confirm( + FileTransferSendConfirmRequest { + id: digest.id, + file_num: digest.file_num, + union: if overwrite_strategy.unwrap() { + Some(file_transfer_send_confirm_request::Union::offset_blk(0)) + } else { + Some(file_transfer_send_confirm_request::Union::skip(true)) + }, + ..Default::default() }, - ..Default::default() - }, - ); - allow_err!(peer.send(&msg).await); - } - } else { - let msg= new_send_confirm(FileTransferSendConfirmRequest { + ); + allow_err!(peer.send(&msg).await); + } + } else { + let msg= new_send_confirm(FileTransferSendConfirmRequest { id: digest.id, file_num: digest.file_num, union: Some(file_transfer_send_confirm_request::Union::skip(true)), ..Default::default() }); - allow_err!(peer.send(&msg).await); + allow_err!(peer.send(&msg).await); + } + } + Err(err) => { + println!("error recving digest: {}", err); } - } - Err(err) => { - println!("error recving digest: {}", err); } } } From 96c7202e4ba304322f87420858c429c4b7f139be Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 28 Apr 2022 18:09:06 +0800 Subject: [PATCH 07/27] add: remote ret back override confirmation[2/2] --- src/ui/file_transfer.tis | 2 +- src/ui/remote.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index 9f0e74a1a..f93b90ddf 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -695,7 +695,6 @@ handler.confirmDeleteFiles = function(id, i, name) { ", function(res=null) { if (!res) { jt.updateJobStatus(id, i - 1, "cancel"); - file_transfer.job_table.cancelDeletePolling(); } else if (res.skip) { if (res.remember){ jt.updateJobStatus(id, i, "cancel"); @@ -730,6 +729,7 @@ handler.overrideFileConfirm = function(id, file_num, to, is_upload) { ", function(res=null) { if (!res) { jt.updateJobStatus(id, -1, "cancel"); + handler.cancel_job(id); } else if (res.skip) { if (res.remember){ handler.set_write_override(id,file_num,false,true, is_upload); // diff --git a/src/ui/remote.rs b/src/ui/remote.rs index b460d6402..fc2869e7b 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -219,7 +219,7 @@ impl sciter::EventHandler for Handler { fn toggle_option(String); fn get_remember(); fn peer_platform(); - fn set_write_override(i32,i32, bool,bool,bool); // , + fn set_write_override(i32, i32, bool, bool, bool); } } From 050952e5e8bbd2c8df2a2a3b79985268f0079f70 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sun, 8 May 2022 16:08:30 +0800 Subject: [PATCH 08/27] fix: confirmDelete -> cancel Delete --- src/lang/cn.rs | 2 ++ src/lang/ru.rs | 2 ++ src/lang/template.rs | 2 ++ src/lang/tw.rs | 2 ++ src/ui/cm.rs | 4 ---- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index c7849b11b..bfbef4875 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -266,6 +266,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_start_service_tip", "点击 [启动服务] 或打开 [屏幕录制] 权限开启手机屏幕共享服务。"), ("Account", "账号"), ("Quit", "退出"), + ("Overwrite", "覆盖"), + ("This file exists, skip or overwrite this file?", "这个文件/文件夹已存在,跳过/覆盖?") ("doc_mac_permission", "https://rustdesk.com/docs/zh-cn/manual/mac/#启用权限"), ("Help", "帮助"), ].iter().cloned().collect(); diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 0249b4eee..5ce96ab33 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -266,6 +266,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_start_service_tip", "Нажмите [Запуск промежуточного сервера] или ОТКРЫТЬ разрешение [Скриншот], чтобы запустить службу демонстрации экрана."), ("Account", "Аккаунт"), ("Quit", "Выйти"), + ("Overwrite", "крышка"), + ("This file exists, skip or overwrite this file?", "Этот файл существует, пропустить или перезаписать этот файл?") ("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"), ("Help", "Помощь"), ].iter().cloned().collect(); diff --git a/src/lang/template.rs b/src/lang/template.rs index 9cfed1283..84be6ed8d 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -265,6 +265,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_version_audio_tip", ""), ("android_start_service_tip", ""), ("Account", ""), + ("Overwrite", ""), + ("This file exists, skip or overwrite this file?", "") ("Quit", ""), ("doc_mac_permission", ""), ("Help", ""), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 6d9e2814a..b8e422d4b 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -266,6 +266,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_start_service_tip", "點擊 [啟動服務] 或打開 [屏幕錄製] 權限開啟手機屏幕共享服務。"), ("Account", "帳戶"), ("Quit", "退出"), + ("Overwrite", "覆蓋"), + ("This file exists, skip or overwrite this file?", "這個文件/文件夾已存在,跳過/覆蓋?") ("doc_mac_permission", "https://rustdesk.com/docs/zh-tw/manual/mac/#啟用權限"), ("Help", "幫助"), ].iter().cloned().collect(); diff --git a/src/ui/cm.rs b/src/ui/cm.rs index ed6f47d96..9a4779664 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -136,7 +136,6 @@ impl ConnectionManager { dir, include_hidden, } => { - // println!("[cm.rs:126] ipc::FS::ReadDir recved"); Self::read_dir(&dir, include_hidden, conn).await; } ipc::FS::RemoveDir { @@ -157,7 +156,6 @@ impl ConnectionManager { id, mut files, } => { - println!("new write in ipc::FS::NewWrite"); write_jobs.push(fs::TransferJob::new_write( id, path, @@ -293,7 +291,6 @@ impl ConnectionManager { let mut file_response = FileResponse::new(); file_response.set_dir(fd); msg_out.set_file_response(file_response); - // println!("[cm.rs:229] set dir"); Self::send(msg_out, conn).await; } } @@ -356,7 +353,6 @@ impl ConnectionManager { } async fn send(msg: Message, conn: &mut Connection) { - println!("send msg: {:?}", msg); match msg.write_to_bytes() { Ok(bytes) => allow_err!(conn.send(&Data::RawMessage(bytes)).await), err => allow_err!(err), From 4975c9b54dde4608b7d9822aff5ec623ba144711 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 28 Apr 2022 18:23:12 +0800 Subject: [PATCH 09/27] add: overwrite version limit, remove debug log --- libs/hbb_common/src/fs.rs | 58 ++++++++++++++++++++++++++------------- src/server/connection.rs | 9 +++--- src/ui/cm.rs | 11 ++++++-- src/ui/file_transfer.tis | 5 +--- src/ui/remote.rs | 19 +++++++------ 5 files changed, 62 insertions(+), 40 deletions(-) diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index eb5510423..57772bd0d 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -1,4 +1,4 @@ -use crate::{bail, message_proto::*, ResultType, Stream}; +use crate::{bail, get_version_number, message_proto::*, ResultType, Stream}; use std::path::{Path, PathBuf}; // https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html use crate::{ @@ -191,6 +191,10 @@ pub fn is_file_exists(file_path: &str) -> bool { return Path::new(file_path).exists(); } +pub fn can_enable_overwrite_detection(version: i64) -> bool { + version >= get_version_number("1.1.9") +} + #[derive(Default)] pub struct TransferJob { id: i32, @@ -201,6 +205,7 @@ pub struct TransferJob { total_size: u64, finished_size: u64, transferred: u64, + enable_overwrite_detection: bool, file_confirmed: bool, file_is_waiting: bool, default_overwrite_strategy: Option, @@ -229,20 +234,31 @@ fn is_compressed_file(name: &str) -> bool { } impl TransferJob { - pub fn new_write(id: i32, path: String, files: Vec) -> Self { - println!("new write {}", path); + pub fn new_write( + id: i32, + path: String, + files: Vec, + enable_override_detection: bool, + ) -> Self { + log::info!("new write {}", path); let total_size = files.iter().map(|x| x.size as u64).sum(); Self { id, path: get_path(&path), files, total_size, + enable_overwrite_detection: enable_override_detection, ..Default::default() } } - pub fn new_read(id: i32, path: String, include_hidden: bool) -> ResultType { - println!("new read {}", path); + pub fn new_read( + id: i32, + path: String, + include_hidden: bool, + enable_override_detection: bool, + ) -> ResultType { + log::info!("new read {}", path); let files = get_recursive_files(&path, include_hidden)?; let total_size = files.iter().map(|x| x.size as u64).sum(); Ok(Self { @@ -250,6 +266,7 @@ impl TransferJob { path: get_path(&path), files, total_size, + enable_overwrite_detection: enable_override_detection, ..Default::default() }) } @@ -315,7 +332,6 @@ impl TransferJob { } pub async fn write(&mut self, block: FileTransferBlock, raw: Option<&[u8]>) -> ResultType<()> { - println!("write file transfer blk[{},{}]", block.id, block.file_num); if block.id != self.id { bail!("Wrong id"); } @@ -385,12 +401,14 @@ impl TransferJob { } } } - if !self.file_confirmed() { - if !self.file_is_waiting() { - self.send_current_digest(stream).await?; - self.set_file_is_waiting(true); + if self.enable_overwrite_detection { + if !self.file_confirmed() { + if !self.file_is_waiting() { + self.send_current_digest(stream).await?; + self.set_file_is_waiting(true); + } + return Ok(None); } - return Ok(None); } const BUF_SIZE: usize = 128 * 1024; let mut buf: Vec = Vec::with_capacity(BUF_SIZE); @@ -459,9 +477,11 @@ impl TransferJob { }); msg.set_file_response(resp); stream.send(&msg).await?; - println!( + log::info!( "id: {}, file_num:{}, digest message is sent. waiting for confirm. msg: {:?}", - self.id, self.file_num, msg + self.id, + self.file_num, + msg ); Ok(()) } @@ -500,19 +520,19 @@ impl TransferJob { pub fn confirm(&mut self, r: &FileTransferSendConfirmRequest) -> bool { if self.file_num() != r.file_num { - log::debug!("file num truncated, ignoring"); + log::info!("file num truncated, ignoring"); } else { match r.union { Some(file_transfer_send_confirm_request::Union::skip(s)) => { if s { - println!("skip current file"); + log::info!("skip file id:{}, file_num:{}", r.id, r.file_num); self.skip_current_file(); } else { self.set_file_confirmed(true); } } Some(file_transfer_send_confirm_request::Union::offset_blk(offset)) => { - println!("file confirmed"); + log::info!("file confirmed"); self.set_file_confirmed(true); } _ => {} @@ -538,7 +558,6 @@ pub fn new_error(id: i32, err: T, file_num: i32) -> Me #[inline] pub fn new_dir(id: i32, path: String, files: Vec) -> Message { - println!("[fs.rs:510] create new dir"); let mut resp = FileResponse::new(); resp.set_dir(FileDirectory { id, @@ -585,7 +604,7 @@ pub fn new_receive(id: i32, path: String, files: Vec) -> Message { #[inline] pub fn new_send(id: i32, path: String, include_hidden: bool) -> Message { - println!("new send: {},id : {}", path, id); + log::info!("new send: {},id : {}", path, id); let mut action = FileAction::new(); action.set_send(FileTransferSendRequest { id, @@ -638,7 +657,8 @@ pub async fn handle_read_jobs( stream.send(&new_block(block)).await?; } Ok(None) => { - if !job.file_confirmed && !job.file_is_waiting { + if !job.enable_overwrite_detection || (!job.file_confirmed && !job.file_is_waiting) + { finished.push(job.id()); stream.send(&new_done(job.id(), job.file_num())).await?; } else { diff --git a/src/server/connection.rs b/src/server/connection.rs index 0b15c3659..5ecee471c 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -12,6 +12,7 @@ use hbb_common::{ config::Config, fs, futures::{SinkExt, StreamExt}, + get_version_number, message_proto::{option_message::BoolOption, permission_info::Permission}, sleep, timeout, tokio::{ @@ -893,7 +894,6 @@ impl Connection { } } } else if self.authorized { - // println!("on_message: {:?}", msg); match msg.union { Some(message::Union::mouse_event(me)) => { #[cfg(any(target_os = "android", target_os = "ios"))] @@ -973,9 +973,9 @@ impl Connection { } Some(file_action::Union::send(s)) => { let id = s.id; - let path = s.path; - match fs::TransferJob::new_read(id, path.clone(), s.include_hidden) - { + let od = + can_enable_overwrite_detection(get_version_number(VERSION)); + match fs::TransferJob::new_read(id, s.path.clone(), s.include_hidden) { Err(err) => { self.send(fs::new_error(id, err, 0)).await; } @@ -1195,7 +1195,6 @@ impl Connection { } fn read_dir(&mut self, dir: &str, include_hidden: bool) { - // println!("[connection.rs:1130] read_dir"); let dir = dir.to_string(); self.send_fs(ipc::FS::ReadDir { dir, diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 9a4779664..444e26529 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -1,14 +1,17 @@ use crate::ipc::{self, new_listener, Connection, Data}; +use crate::VERSION; #[cfg(windows)] use clipboard::{ create_cliprdr_context, empty_clipboard, get_rx_clip_client, server_clip_file, set_conn_enabled, }; -use hbb_common::fs::{get_string, is_write_need_confirmation, new_send_confirm}; +use hbb_common::fs::{ + can_enable_overwrite_detection, get_string, is_write_need_confirmation, new_send_confirm, +}; use hbb_common::log::log; use hbb_common::{ allow_err, config::Config, - fs, log, + fs, get_version_number, log, message_proto::*, protobuf::Message as _, tokio::{self, sync::mpsc, task::spawn_blocking}, @@ -156,6 +159,7 @@ impl ConnectionManager { id, mut files, } => { + let od = can_enable_overwrite_detection(get_version_number(VERSION)); write_jobs.push(fs::TransferJob::new_write( id, path, @@ -167,6 +171,7 @@ impl ConnectionManager { ..Default::default() }) .collect(), + od, )); } ipc::FS::CancelWrite { id } => { @@ -210,7 +215,7 @@ impl ConnectionManager { if let Some(mut digest) = digest { // upload to server, but server has the same file, request digest.is_upload = is_upload; - println!( + log::info!( "server has the same file, send server digest to local" ); let mut msg_out = Message::new(); diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index f93b90ddf..8152408d8 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -679,7 +679,6 @@ function confirmDelete(id ,path, is_remote) { } handler.confirmDeleteFiles = function(id, i, name) { - stdout.println("id=" + id +", i=" +",name="+name); var jt = file_transfer.job_table; var job = jt.job_map[id]; if (!job) return; @@ -695,6 +694,7 @@ handler.confirmDeleteFiles = function(id, i, name) { ", function(res=null) { if (!res) { jt.updateJobStatus(id, i - 1, "cancel"); + file_transfer.job_table.confirmDeletePolling(); } else if (res.skip) { if (res.remember){ jt.updateJobStatus(id, i, "cancel"); @@ -718,9 +718,6 @@ handler.confirmDeleteFiles = function(id, i, name) { handler.overrideFileConfirm = function(id, file_num, to, is_upload) { var jt = file_transfer.job_table; - var job = jt.job_map[id]; - stdout.println("job type: " + job.type); - stdout.println(JSON.stringify(job)); msgbox("custom-skip", "Confirm Write Strategy", "
\
" + translate('Overwrite') + translate('files') + ".
\
" + translate('This file exists, skip or overwrite this file?') + "
\ diff --git a/src/ui/remote.rs b/src/ui/remote.rs index fc2869e7b..8a1492393 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -11,7 +11,9 @@ use clipboard::{ get_rx_clip_client, server_clip_file, }; use enigo::{self, Enigo, KeyboardControllable}; -use hbb_common::fs::{get_string, is_file_exists, new_send_confirm}; +use hbb_common::fs::{ + can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm, +}; use hbb_common::log::log; use hbb_common::{ allow_err, @@ -1537,25 +1539,27 @@ impl Remote { allow_err!(peer.send(&msg).await); } Data::SendFiles((id, path, to, include_hidden, is_remote)) => { - println!("send files, is remote {}", is_remote); + log::info!("send files, is remote {}", is_remote); + let od = can_enable_overwrite_detection(self.handler.lc.read().unwrap().version); if is_remote { - println!("New job {}, write to {} from remote {}", id, to, path); + log::debug!("New job {}, write to {} from remote {}", id, to, path); self.write_jobs - .push(fs::TransferJob::new_write(id, to, Vec::new())); + .push(fs::TransferJob::new_write(id, to, Vec::new(), od)); allow_err!(peer.send(&fs::new_send(id, path, include_hidden)).await); } else { - match fs::TransferJob::new_read(id, path.clone(), include_hidden) { + match fs::TransferJob::new_read(id, path.clone(), include_hidden, od) { Err(err) => { self.handle_job_status(id, -1, Some(err.to_string())); } Ok(job) => { - println!( + log::debug!( "New job {}, read {} to remote {}, {} files", id, path, to, job.files().len() ); + let config = self.handler.lc.read().unwrap().version; let m = make_fd(job.id(), job.files(), true); self.handler.call("updateFolderFiles", &make_args!(m)); let files = job.files().clone(); @@ -1780,7 +1784,6 @@ impl Remote { async fn handle_msg_from_peer(&mut self, data: &[u8], peer: &mut Stream) -> bool { if let Ok(msg_in) = Message::parse_from_bytes(&data) { - // println!("recved msg from peer, decoded: {:?}", msg_in); match msg_in.union { Some(message::Union::video_frame(vf)) => { if !self.first_frame { @@ -1928,13 +1931,11 @@ impl Remote { if let Some(job) = fs::get_job(block.id, &mut self.write_jobs) { if let Err(_err) = job.write(block, None).await { // to-do: add "skip" for writing job - println!("error: {}", _err); } self.update_jobs_status(); } } Some(file_response::Union::done(d)) => { - log::info!("file response done"); if let Some(job) = fs::get_job(d.id, &mut self.write_jobs) { job.modify_time(); fs::remove_job(d.id, &mut self.write_jobs); From cdecb3589a7e168be374c8da91c68f179073aee9 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 28 Apr 2022 21:56:09 +0800 Subject: [PATCH 10/27] refactor: change version to 1.2.0 --- Cargo.lock | 2 +- Cargo.toml | 2 +- libs/hbb_common/src/fs.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cae72342a..af87a1907 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3954,7 +3954,7 @@ dependencies = [ [[package]] name = "rustdesk" -version = "1.1.9" +version = "1.2.0" dependencies = [ "android_logger 0.11.0", "arboard", diff --git a/Cargo.toml b/Cargo.toml index e54ac875d..dbc6307b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustdesk" -version = "1.1.9" +version = "1.2.0" authors = ["rustdesk "] edition = "2021" build= "build.rs" diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 57772bd0d..7180cbdd7 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -192,7 +192,7 @@ pub fn is_file_exists(file_path: &str) -> bool { } pub fn can_enable_overwrite_detection(version: i64) -> bool { - version >= get_version_number("1.1.9") + version >= get_version_number("1.2.0") } #[derive(Default)] From 74b3cb1c5884acbeb7eb4b9e0d87933e04d14ad3 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 29 Apr 2022 00:42:06 +0800 Subject: [PATCH 11/27] fix: skip issue --- libs/hbb_common/src/fs.rs | 19 ++-- src/server/connection.rs | 2 +- src/ui/cm.rs | 37 ++++--- src/ui/remote.rs | 207 ++++++++++++++++++++++---------------- 4 files changed, 158 insertions(+), 107 deletions(-) diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 7180cbdd7..9a040a00c 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -191,6 +191,7 @@ pub fn is_file_exists(file_path: &str) -> bool { return Path::new(file_path).exists(); } +#[inline] pub fn can_enable_overwrite_detection(version: i64) -> bool { version >= get_version_number("1.2.0") } @@ -525,14 +526,14 @@ impl TransferJob { match r.union { Some(file_transfer_send_confirm_request::Union::skip(s)) => { if s { - log::info!("skip file id:{}, file_num:{}", r.id, r.file_num); + log::debug!("skip file id:{}, file_num:{}", r.id, r.file_num); self.skip_current_file(); } else { self.set_file_confirmed(true); } } Some(file_transfer_send_confirm_request::Union::offset_blk(offset)) => { - log::info!("file confirmed"); + log::debug!("file confirmed"); self.set_file_confirmed(true); } _ => {} @@ -702,11 +703,17 @@ pub fn create_dir(dir: &str) -> ResultType<()> { Ok(()) } +pub enum DigestCheckResult { + IsSame, + NeedConfirm(FileTransferDigest), + NoSuchFile, +} + #[inline] pub fn is_write_need_confirmation( file_path: &str, digest: &FileTransferDigest, -) -> ResultType> { +) -> ResultType { let path = Path::new(file_path); if path.exists() && path.is_file() { let metadata = std::fs::metadata(path)?; @@ -722,9 +729,9 @@ pub fn is_write_need_confirmation( metadata.len() ); if remote_mt == local_mt && digest.file_size == metadata.len() { - return Ok(None); + return Ok(DigestCheckResult::IsSame); } - Ok(Some(FileTransferDigest { + Ok(DigestCheckResult::NeedConfirm(FileTransferDigest { id: digest.id, file_num: digest.file_num, last_edit_timestamp: local_mt.as_secs(), @@ -732,6 +739,6 @@ pub fn is_write_need_confirmation( ..Default::default() })) } else { - Ok(None) + Ok(DigestCheckResult::NoSuchFile) } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 5ecee471c..b0f651884 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -275,7 +275,7 @@ impl Connection { } } ipc::Data::RawMessage(bytes) => { - conn.stream.send_raw(bytes).await; + allow_err!(conn.stream.send_raw(bytes).await); } #[cfg(windows)] ipc::Data::ClipbaordFile(_clip) => { diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 444e26529..7eb99a4c2 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -6,6 +6,7 @@ use clipboard::{ }; use hbb_common::fs::{ can_enable_overwrite_detection, get_string, is_write_need_confirmation, new_send_confirm, + DigestCheckResult, }; use hbb_common::log::log; use hbb_common::{ @@ -211,23 +212,29 @@ impl ConnectionManager { if let Some(file) = job.files().get(file_num as usize) { let path = get_string(&job.join(&file.name)); match is_write_need_confirmation(&path, &digest) { - Ok(digest) => { - if let Some(mut digest) = digest { - // upload to server, but server has the same file, request - digest.is_upload = is_upload; - log::info!( + Ok(digest_result) => { + match digest_result { + DigestCheckResult::IsSame => { + req.set_skip(true); + let msg_out = new_send_confirm(req); + Self::send(msg_out, conn).await; + } + DigestCheckResult::NeedConfirm(mut digest) => { + // upload to server, but server has the same file, request + digest.is_upload = is_upload; + log::info!( "server has the same file, send server digest to local" ); - let mut msg_out = Message::new(); - let mut fr = FileResponse::new(); - fr.set_digest(digest); - msg_out.set_file_response(fr); - Self::send(msg_out, conn).await; - } else { - log::info!("skip job {}, file_num {}", id, file_num); - req.set_skip(true); - let msg_out = new_send_confirm(req); - Self::send(msg_out, conn).await; + let mut msg_out = Message::new(); + let mut fr = FileResponse::new(); + fr.set_digest(digest); + msg_out.set_file_response(fr); + Self::send(msg_out, conn).await; + } + DigestCheckResult::NoSuchFile => { + let msg_out = new_send_confirm(req); + Self::send(msg_out, conn).await; + } } } Err(err) => { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 8a1492393..f53f121aa 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -12,7 +12,7 @@ use clipboard::{ }; use enigo::{self, Enigo, KeyboardControllable}; use hbb_common::fs::{ - can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm, + can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm, DigestCheckResult, }; use hbb_common::log::log; use hbb_common::{ @@ -1849,104 +1849,141 @@ impl Remote { } } } - Some(message::Union::file_response(fr)) => match fr.union { - Some(file_response::Union::dir(fd)) => { - let entries = fd.entries.to_vec(); - let mut m = make_fd(fd.id, &entries, fd.id > 0); - if fd.id <= 0 { - m.set_item("path", fd.path); - } - self.handler.call("updateFolderFiles", &make_args!(m)); - if let Some(job) = fs::get_job(fd.id, &mut self.write_jobs) { - job.set_files(entries); - } else if let Some(job) = self.remove_jobs.get_mut(&fd.id) { - job.files = entries; - } - } - Some(file_response::Union::digest(digest)) => { - if digest.is_upload { - if let Some(job) = fs::get_job(digest.id, &mut self.read_jobs) { - if let Some(file) = job.files().get(digest.file_num as usize) { - let read_path = get_string(&job.join(&file.name)); - self.handler.call( - "overrideFileConfirm", - &make_args!(digest.id, digest.file_num, read_path, true), - ); - } + Some(message::Union::file_response(fr)) => { + match fr.union { + Some(file_response::Union::dir(fd)) => { + let entries = fd.entries.to_vec(); + let mut m = make_fd(fd.id, &entries, fd.id > 0); + if fd.id <= 0 { + m.set_item("path", fd.path); } - } else { - if let Some(job) = fs::get_job(digest.id, &mut self.write_jobs) { - if let Some(file) = job.files().get(digest.file_num as usize) { - let write_path = get_string(&job.join(&file.name)); - let overwrite_strategy = job.default_overwrite_strategy(); - match fs::is_write_need_confirmation(&write_path, &digest) { - Ok(res) => { - if res.is_some() { - // need confirm - if overwrite_strategy.is_none() { - self.handler.call( - "overrideFileConfirm", - &make_args!( - digest.id, - digest.file_num, - write_path, - false - ), - ); - } else { - let msg = new_send_confirm( - FileTransferSendConfirmRequest { - id: digest.id, - file_num: digest.file_num, - union: if overwrite_strategy.unwrap() { - Some(file_transfer_send_confirm_request::Union::offset_blk(0)) - } else { - Some(file_transfer_send_confirm_request::Union::skip(true)) - }, - ..Default::default() - }, - ); - allow_err!(peer.send(&msg).await); - } - } else { - let msg= new_send_confirm(FileTransferSendConfirmRequest { + self.handler.call("updateFolderFiles", &make_args!(m)); + if let Some(job) = fs::get_job(fd.id, &mut self.write_jobs) { + job.set_files(entries); + } else if let Some(job) = self.remove_jobs.get_mut(&fd.id) { + job.files = entries; + } + } + Some(file_response::Union::digest(digest)) => { + if digest.is_upload { + if let Some(job) = fs::get_job(digest.id, &mut self.read_jobs) { + if let Some(file) = job.files().get(digest.file_num as usize) { + let read_path = get_string(&job.join(&file.name)); + let overwrite_strategy = job.default_overwrite_strategy(); + if let Some(overwrite) = overwrite_strategy { + let req = FileTransferSendConfirmRequest { id: digest.id, file_num: digest.file_num, - union: Some(file_transfer_send_confirm_request::Union::skip(true)), + union: Some(if overwrite { + file_transfer_send_confirm_request::Union::offset_blk(0) + } else { + file_transfer_send_confirm_request::Union::skip( + true, + ) + }), ..Default::default() - }); - allow_err!(peer.send(&msg).await); - } + }; + job.confirm(&req); + let msg = new_send_confirm(req); + allow_err!(peer.send(&msg).await); + } else { + self.handler.call( + "overrideFileConfirm", + &make_args!( + digest.id, + digest.file_num, + read_path, + true + ), + ); } - Err(err) => { - println!("error recving digest: {}", err); + } + } + } else { + if let Some(job) = fs::get_job(digest.id, &mut self.write_jobs) { + if let Some(file) = job.files().get(digest.file_num as usize) { + let write_path = get_string(&job.join(&file.name)); + let overwrite_strategy = job.default_overwrite_strategy(); + match fs::is_write_need_confirmation(&write_path, &digest) { + Ok(res) => match res { + DigestCheckResult::IsSame => { + let msg= new_send_confirm(FileTransferSendConfirmRequest { + id: digest.id, + file_num: digest.file_num, + union: Some(file_transfer_send_confirm_request::Union::skip(true)), + ..Default::default() + }); + allow_err!(peer.send(&msg).await); + } + DigestCheckResult::NeedConfirm(digest) => { + if let Some(overwrite) = overwrite_strategy { + let msg = new_send_confirm( + FileTransferSendConfirmRequest { + id: digest.id, + file_num: digest.file_num, + union: Some(if overwrite { + file_transfer_send_confirm_request::Union::offset_blk(0) + } else { + file_transfer_send_confirm_request::Union::skip(true) + }), + ..Default::default() + }, + ); + allow_err!(peer.send(&msg).await); + } else { + self.handler.call( + "overrideFileConfirm", + &make_args!( + digest.id, + digest.file_num, + write_path, + false + ), + ); + } + } + DigestCheckResult::NoSuchFile => { + let msg = new_send_confirm( + FileTransferSendConfirmRequest { + id: digest.id, + file_num: digest.file_num, + union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)), + ..Default::default() + }, + ); + allow_err!(peer.send(&msg).await); + } + }, + Err(err) => { + println!("error recving digest: {}", err); + } } } } } } - } - Some(file_response::Union::block(block)) => { - log::info!("file response block, file num: {}", block.file_num); - if let Some(job) = fs::get_job(block.id, &mut self.write_jobs) { - if let Err(_err) = job.write(block, None).await { - // to-do: add "skip" for writing job + Some(file_response::Union::block(block)) => { + log::info!("file response block, file num: {}", block.file_num); + if let Some(job) = fs::get_job(block.id, &mut self.write_jobs) { + if let Err(_err) = job.write(block, None).await { + // to-do: add "skip" for writing job + } + self.update_jobs_status(); } - self.update_jobs_status(); } - } - Some(file_response::Union::done(d)) => { - if let Some(job) = fs::get_job(d.id, &mut self.write_jobs) { - job.modify_time(); - fs::remove_job(d.id, &mut self.write_jobs); + Some(file_response::Union::done(d)) => { + if let Some(job) = fs::get_job(d.id, &mut self.write_jobs) { + job.modify_time(); + fs::remove_job(d.id, &mut self.write_jobs); + } + self.handle_job_status(d.id, d.file_num, None); } - self.handle_job_status(d.id, d.file_num, None); + Some(file_response::Union::error(e)) => { + self.handle_job_status(e.id, e.file_num, Some(e.error)); + } + _ => {} } - Some(file_response::Union::error(e)) => { - self.handle_job_status(e.id, e.file_num, Some(e.error)); - } - _ => {} - }, + } Some(message::Union::misc(misc)) => match misc.union { Some(misc::Union::audio_format(f)) => { self.audio_sender.send(MediaData::AudioFormat(f)).ok(); From 265e3c760ea763b0289c9fc6d165b92abc2f7c4f Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 29 Apr 2022 01:24:04 +0800 Subject: [PATCH 12/27] fix: confirmDelete -> cancel Delete --- src/ui/file_transfer.tis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index 8152408d8..13c312483 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -694,7 +694,7 @@ handler.confirmDeleteFiles = function(id, i, name) {
", function(res=null) { if (!res) { jt.updateJobStatus(id, i - 1, "cancel"); - file_transfer.job_table.confirmDeletePolling(); + file_transfer.job_table.cancelDeletePolling(); } else if (res.skip) { if (res.remember){ jt.updateJobStatus(id, i, "cancel"); From 02f214e39a904f4b4130f055d6aba0bbe327d855 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 29 Apr 2022 16:47:45 +0800 Subject: [PATCH 13/27] opt: name, imports --- libs/hbb_common/protos/message.proto | 2 +- libs/hbb_common/src/fs.rs | 18 ++++-------------- src/ipc.rs | 2 +- src/server/connection.rs | 3 +-- src/ui/cm.rs | 8 +++----- src/ui/remote.rs | 2 +- 6 files changed, 11 insertions(+), 24 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index fe45434b1..ed90eab3e 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -270,7 +270,7 @@ message FileResponse { message FileTransferDigest { int32 id = 1; sint32 file_num = 2; - uint64 last_edit_timestamp = 3; + uint64 last_modified = 3; uint64 file_size = 4; bool is_upload = 5; } diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 9a040a00c..c372143f0 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -5,7 +5,6 @@ use crate::{ compress::{compress, decompress}, config::{Config, COMPRESS_LEVEL}, }; -use log::log; #[cfg(windows)] use std::os::windows::prelude::*; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -472,7 +471,7 @@ impl TransferJob { resp.set_digest(FileTransferDigest { id: self.id, file_num: self.file_num, - last_edit_timestamp: last_modified, + last_modified, file_size: meta.len(), ..Default::default() }); @@ -647,7 +646,6 @@ pub async fn handle_read_jobs( ) -> ResultType<()> { let mut finished = Vec::new(); for job in jobs.iter_mut() { - // println!("[fs.rs:588] handle_read_jobs. {:?}", job.id); match job.read(stream).await { Err(err) => { stream @@ -663,7 +661,7 @@ pub async fn handle_read_jobs( finished.push(job.id()); stream.send(&new_done(job.id(), job.file_num())).await?; } else { - log::info!("waiting confirmation."); + // waiting confirmation. } } } @@ -718,23 +716,15 @@ pub fn is_write_need_confirmation( if path.exists() && path.is_file() { let metadata = std::fs::metadata(path)?; let modified_time = metadata.modified()?; - let remote_mt = Duration::from_secs(digest.last_edit_timestamp); + let remote_mt = Duration::from_secs(digest.last_modified); let local_mt = modified_time.duration_since(UNIX_EPOCH)?; - log::info!( - "{:?}:rm:{},lm:{},rf:{},lf:{}", - path, - remote_mt.as_secs(), - local_mt.as_secs(), - digest.file_size, - metadata.len() - ); if remote_mt == local_mt && digest.file_size == metadata.len() { return Ok(DigestCheckResult::IsSame); } Ok(DigestCheckResult::NeedConfirm(FileTransferDigest { id: digest.id, file_num: digest.file_num, - last_edit_timestamp: local_mt.as_secs(), + last_modified: local_mt.as_secs(), file_size: metadata.len(), ..Default::default() })) diff --git a/src/ipc.rs b/src/ipc.rs index 0a9a2d6c5..7dde792e3 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -63,7 +63,7 @@ pub enum FS { id: i32, file_num: i32, file_size: u64, - modified_time: u64, + last_modified: u64, is_upload: bool, }, } diff --git a/src/server/connection.rs b/src/server/connection.rs index b0f651884..c1984e0e3 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -955,7 +955,6 @@ impl Connection { } } Some(message::Union::file_action(fa)) => { - log::info!("recv file_action, {:?}", fa); if self.file_transfer.is_some() { match fa.union { Some(file_action::Union::read_dir(rd)) => { @@ -1051,7 +1050,7 @@ impl Connection { id: d.id, file_num: d.file_num, file_size: d.file_size, - modified_time: d.last_edit_timestamp, + last_modified: d.last_modified, is_upload: true, }), _ => {} diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 7eb99a4c2..03708b04f 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -192,7 +192,7 @@ impl ConnectionManager { id, file_num, file_size, - modified_time, + last_modified, is_upload, } => { if let Some(job) = fs::get_job(id, write_jobs) { @@ -205,7 +205,7 @@ impl ConnectionManager { let digest = FileTransferDigest { id, file_num, - last_edit_timestamp: modified_time, + last_modified, file_size, ..Default::default() }; @@ -222,9 +222,6 @@ impl ConnectionManager { DigestCheckResult::NeedConfirm(mut digest) => { // upload to server, but server has the same file, request digest.is_upload = is_upload; - log::info!( - "server has the same file, send server digest to local" - ); let mut msg_out = Message::new(); let mut fr = FileResponse::new(); fr.set_digest(digest); @@ -365,6 +362,7 @@ impl ConnectionManager { } async fn send(msg: Message, conn: &mut Connection) { + println!("send msg: {:?}", msg); match msg.write_to_bytes() { Ok(bytes) => allow_err!(conn.send(&Data::RawMessage(bytes)).await), err => allow_err!(err), diff --git a/src/ui/remote.rs b/src/ui/remote.rs index f53f121aa..1d07aaff8 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -768,6 +768,7 @@ impl Handler { } fn reconnect(&mut self) { + println!("reconnecting"); let cloned = self.clone(); let mut lock = self.write().unwrap(); lock.thread.take().map(|t| t.join()); @@ -1559,7 +1560,6 @@ impl Remote { to, job.files().len() ); - let config = self.handler.lc.read().unwrap().version; let m = make_fd(job.id(), job.files(), true); self.handler.call("updateFolderFiles", &make_args!(m)); let files = job.files().clone(); From 529e5104c7c8f277add8b6f32ec7de0563567ffa Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sun, 8 May 2022 16:09:37 +0800 Subject: [PATCH 14/27] fix: comma --- src/lang/cn.rs | 2 +- src/lang/tw.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index bfbef4875..b2a3dc9a4 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -267,7 +267,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Account", "账号"), ("Quit", "退出"), ("Overwrite", "覆盖"), - ("This file exists, skip or overwrite this file?", "这个文件/文件夹已存在,跳过/覆盖?") + ("This file exists, skip or overwrite this file?", "这个文件/文件夹已存在,跳过/覆盖?"), ("doc_mac_permission", "https://rustdesk.com/docs/zh-cn/manual/mac/#启用权限"), ("Help", "帮助"), ].iter().cloned().collect(); diff --git a/src/lang/tw.rs b/src/lang/tw.rs index b8e422d4b..5ce7713d9 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -267,7 +267,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Account", "帳戶"), ("Quit", "退出"), ("Overwrite", "覆蓋"), - ("This file exists, skip or overwrite this file?", "這個文件/文件夾已存在,跳過/覆蓋?") + ("This file exists, skip or overwrite this file?", "這個文件/文件夾已存在,跳過/覆蓋?"), ("doc_mac_permission", "https://rustdesk.com/docs/zh-tw/manual/mac/#啟用權限"), ("Help", "幫助"), ].iter().cloned().collect(); From 74a3799b78f042268a1447f929b6b2e0a50ccf39 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sun, 8 May 2022 21:01:03 +0800 Subject: [PATCH 15/27] add: meta info --- libs/hbb_common/protos/message.proto | 8 ++++ libs/hbb_common/src/config.rs | 18 +++++-- libs/hbb_common/src/fs.rs | 35 ++++++++++++-- src/client.rs | 25 +++++----- src/ui/remote.rs | 72 ++++++++++++++++++++-------- 5 files changed, 117 insertions(+), 41 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index ed90eab3e..448108887 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -304,6 +304,14 @@ message FileTransferSendConfirmRequest { } } +message FileTransferDirOffsetRequest { + int32 id = 1; + // start from file_num + sint32 file_num = 2; + // current file blk offset + uint32 offset_blk = 3; +} + message FileTransferDone { int32 id = 1; sint32 file_num = 2; diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index a7c1bc634..c9878d0ff 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -1,8 +1,3 @@ -use crate::log; -use directories_next::ProjectDirs; -use rand::Rng; -use serde_derive::{Deserialize, Serialize}; -use sodiumoxide::crypto::sign; use std::{ collections::HashMap, fs, @@ -145,6 +140,8 @@ pub struct PeerConfig { pub options: HashMap, #[serde(default)] pub info: PeerInfoSerde, + #[serde(default)] + pub transfer: TransferSerde, } #[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)] @@ -157,6 +154,16 @@ pub struct PeerInfoSerde { pub platform: String, } +#[derive(Debug, Default, Serialize, Deserialize, Clone)] +pub struct TransferSerde { + #[serde(default)] + pub write_jobs: Vec, + #[serde(default)] + pub read_jobs: Vec, + #[serde(default)] + pub remove_jobs: Vec, +} + fn patch(path: PathBuf) -> PathBuf { if let Some(_tmp) = path.to_str() { #[cfg(windows)] @@ -864,6 +871,7 @@ impl LanPeers { #[cfg(test)] mod tests { use super::*; + #[test] fn test_serialize() { let cfg: Config = Default::default(); diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index c372143f0..e4c36e922 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -1,14 +1,17 @@ -use crate::{bail, get_version_number, message_proto::*, ResultType, Stream}; +#[cfg(windows)] +use std::os::windows::prelude::*; use std::path::{Path, PathBuf}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use serde_derive::{Deserialize, Serialize}; +use tokio::{fs::File, io::*}; + +use crate::{bail, get_version_number, message_proto::*, ResultType, Stream}; // https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html use crate::{ compress::{compress, decompress}, config::{Config, COMPRESS_LEVEL}, }; -#[cfg(windows)] -use std::os::windows::prelude::*; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; -use tokio::{fs::File, io::*}; pub fn read_dir(path: &PathBuf, include_hidden: bool) -> ResultType { let mut dir = FileDirectory { @@ -211,6 +214,20 @@ pub struct TransferJob { default_overwrite_strategy: Option, } +#[derive(Debug, Default, Serialize, Deserialize, Clone)] +pub struct TransferJobMeta { + pub id: i32, + pub path: PathBuf, + pub file_num: i32, +} + +#[derive(Debug, Default, Serialize, Deserialize, Clone)] +pub struct RemoveJobMeta { + pub path: String, + pub is_remote: bool, + pub no_confirm: bool, +} + #[inline] fn get_ext(name: &str) -> &str { if let Some(i) = name.rfind(".") { @@ -540,6 +557,14 @@ impl TransferJob { } true } + + pub fn gen_meta(&self) -> TransferJobMeta { + TransferJobMeta { + id: self.id, + path: self.path.clone(), + file_num: self.file_num, + } + } } #[inline] diff --git a/src/client.rs b/src/client.rs index 0c4c4a3df..e6be8b855 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,9 +1,20 @@ +use std::{ + collections::HashMap, + net::SocketAddr, + ops::Deref, + sync::{mpsc, Arc, RwLock}, +}; + pub use async_trait::async_trait; #[cfg(not(any(target_os = "android", target_os = "linux")))] use cpal::{ traits::{DeviceTrait, HostTrait, StreamTrait}, Device, Host, StreamConfig, }; +use magnum_opus::{Channels::*, Decoder as AudioDecoder}; +use sha2::{Digest, Sha256}; +use uuid::Uuid; + use hbb_common::{ allow_err, anyhow::{anyhow, Context}, @@ -19,24 +30,15 @@ use hbb_common::{ tokio::time::Duration, AddrMangle, ResultType, Stream, }; -use magnum_opus::{Channels::*, Decoder as AudioDecoder}; use scrap::{Decoder, Image, VideoCodecId}; -use sha2::{Digest, Sha256}; -use std::{ - collections::HashMap, - net::SocketAddr, - ops::Deref, - sync::{mpsc, Arc, RwLock}, -}; -use uuid::Uuid; + +pub use super::lang::*; pub mod file_trait; pub use file_trait::FileManager; pub const SEC30: Duration = Duration::from_secs(30); pub struct Client; -pub use super::lang::*; - #[cfg(not(any(target_os = "android", target_os = "linux")))] lazy_static::lazy_static! { static ref AUDIO_HOST: Host = cpal::default_host(); @@ -1324,6 +1326,7 @@ pub enum Data { ToggleClipboardFile, NewRDP, SetConfirmOverrideFile((i32, i32, bool, bool, bool)), + ResumeTransfer, } #[derive(Clone)] diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 1d07aaff8..5fb7b3561 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1,18 +1,29 @@ -#[cfg(windows)] -use crate::clipboard_file::*; -use crate::{ - client::*, - common::{self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL}, - VERSION, +use std::{ + collections::HashMap, + ops::Deref, + sync::{Arc, Mutex, RwLock}, }; + +use sciter::{ + dom::{ + event::{EventReason, BEHAVIOR_EVENTS, EVENT_GROUPS, PHASE_MASK}, + Element, HELEMENT, + }, + make_args, + video::{video_destination, AssetPtr, COLOR_SPACE}, + Value, +}; + #[cfg(windows)] use clipboard::{ cliprdr::CliprdrClientContext, create_cliprdr_context as create_clipboard_file_context, get_rx_clip_client, server_clip_file, }; use enigo::{self, Enigo, KeyboardControllable}; +use hbb_common::config::TransferSerde; use hbb_common::fs::{ - can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm, DigestCheckResult, + can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm, + DigestCheckResult, RemoveJobMeta, }; use hbb_common::log::log; use hbb_common::{ @@ -30,19 +41,13 @@ use hbb_common::{ }, Stream, }; -use sciter::{ - dom::{ - event::{EventReason, BEHAVIOR_EVENTS, EVENT_GROUPS, PHASE_MASK}, - Element, HELEMENT, - }, - make_args, - video::{video_destination, AssetPtr, COLOR_SPACE}, - Value, -}; -use std::{ - collections::HashMap, - ops::Deref, - sync::{Arc, Mutex, RwLock}, + +#[cfg(windows)] +use crate::clipboard_file::*; +use crate::{ + client::*, + common::{self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL}, + VERSION, }; type Video = AssetPtr; @@ -1314,6 +1319,7 @@ async fn io_loop(handler: Handler) { clipboard_file_context: None, }; remote.io_loop(&key, &token).await; + remote.sync_jobs_status_to_local(); } struct RemoveJob { @@ -1336,6 +1342,14 @@ impl RemoveJob { last_update_job_status: Instant::now(), } } + + pub fn gen_meta(&self) -> RemoveJobMeta { + RemoveJobMeta { + path: self.path.clone(), + is_remote: self.is_remote, + no_confirm: self.no_confirm, + } + } } struct Remote { @@ -1438,6 +1452,7 @@ impl Remote { } } } + self.sync_jobs_status_to_local(); log::debug!("Exit io_loop of id={}", self.handler.id); } Err(err) => { @@ -1782,6 +1797,23 @@ impl Remote { } } + async fn sync_jobs_status_to_local(&mut self) -> bool { + let mut config: PeerConfig = self.handler.load_config(); + let mut transfer_metas = TransferSerde::default(); + for job in self.read_jobs.iter() { + transfer_metas.read_jobs.push(job.gen_meta()); + } + for job in self.write_jobs.iter() { + transfer_metas.write_jobs.push(job.gen_meta()); + } + for job in self.remove_jobs.values() { + transfer_metas.remove_jobs.push(job.gen_meta()); + } + config.transfer = transfer_metas; + self.handler.save_config(config); + true + } + async fn handle_msg_from_peer(&mut self, data: &[u8], peer: &mut Stream) -> bool { if let Ok(msg_in) = Message::parse_from_bytes(&data) { match msg_in.union { From 83c75409e8e29e858bd5c6d4cd4593208e400819 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 12 May 2022 14:16:06 +0800 Subject: [PATCH 16/27] add: msg --- libs/hbb_common/protos/message.proto | 1 + src/ipc.rs | 5 +++++ src/server/connection.rs | 8 ++++++++ src/ui/remote.rs | 9 +++++++-- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 448108887..00c4bda49 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -264,6 +264,7 @@ message FileResponse { FileTransferError error = 3; FileTransferDone done = 4; FileTransferDigest digest = 5; + FileTransferDirOffsetRequest offset = 6; } } diff --git a/src/ipc.rs b/src/ipc.rs index 7dde792e3..b976f2ec6 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -59,6 +59,11 @@ pub enum FS { id: i32, file_num: i32, }, + WriteOffset { + id: i32, + file_num: i32, + offset_blk: u32 + }, CheckDigest { id: i32, file_num: i32, diff --git a/src/server/connection.rs b/src/server/connection.rs index c1984e0e3..92368fc0c 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1053,6 +1053,14 @@ impl Connection { last_modified: d.last_modified, is_upload: true, }), + Some(file_response::Union::offset(offset)) => { + // TODO: i32 + // self.send_fs(ipc::FS::WriteOffset { + // id: offset.id, + // file_num: offset.file_num, + // offset_blk: offset.offset_blk, + // }); + } _ => {} }, Some(message::Union::misc(misc)) => match misc.union { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 5fb7b3561..bc7da1791 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1319,7 +1319,7 @@ async fn io_loop(handler: Handler) { clipboard_file_context: None, }; remote.io_loop(&key, &token).await; - remote.sync_jobs_status_to_local(); + remote.sync_jobs_status_to_local().await; } struct RemoveJob { @@ -1452,7 +1452,7 @@ impl Remote { } } } - self.sync_jobs_status_to_local(); + self.sync_jobs_status_to_local().await; log::debug!("Exit io_loop of id={}", self.handler.id); } Err(err) => { @@ -1798,6 +1798,7 @@ impl Remote { } async fn sync_jobs_status_to_local(&mut self) -> bool { + println!("sync job status"); let mut config: PeerConfig = self.handler.load_config(); let mut transfer_metas = TransferSerde::default(); for job in self.read_jobs.iter() { @@ -1896,6 +1897,10 @@ impl Remote { job.files = entries; } } + Some(file_response::Union::offset(offset)) => { + // TODO: offset + // upload + } Some(file_response::Union::digest(digest)) => { if digest.is_upload { if let Some(job) = fs::get_job(digest.id, &mut self.read_jobs) { From 2caa2db46324080b4ac98f0eea96abd8340a77bd Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 12 May 2022 14:19:15 +0800 Subject: [PATCH 17/27] fix: --- src/ui/cm.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 03708b04f..182886f5e 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -270,6 +270,11 @@ impl ConnectionManager { } } } + ipc::FS::WriteOffset { + id,file_num,offset_blk + } => { + + } }, #[cfg(windows)] Data::ClipbaordFile(_clip) => { From 11e0d2cbf1591ef8087d48db31eaf152cd3e54f3 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 12 May 2022 15:55:36 +0800 Subject: [PATCH 18/27] add: job logic --- libs/hbb_common/src/fs.rs | 23 +++++++++++++++++++++-- src/server/connection.rs | 2 +- src/ui/cm.rs | 6 +++++- src/ui/file_transfer.tis | 26 ++++++++++++++++++++++++++ src/ui/remote.rs | 38 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 89 insertions(+), 6 deletions(-) diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index e4c36e922..8ae9e0114 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -201,7 +201,10 @@ pub fn can_enable_overwrite_detection(version: i64) -> bool { #[derive(Default)] pub struct TransferJob { id: i32, + remote: String, path: PathBuf, + show_hidden: bool, + is_remote: bool, files: Vec, file_num: i32, file: Option, @@ -217,7 +220,9 @@ pub struct TransferJob { #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct TransferJobMeta { pub id: i32, - pub path: PathBuf, + pub remote: String, + pub to: String, + pub show_hidden: bool, pub file_num: i32, } @@ -253,7 +258,10 @@ fn is_compressed_file(name: &str) -> bool { impl TransferJob { pub fn new_write( id: i32, + remote: String, path: String, + show_hidden: bool, + is_remote: bool, files: Vec, enable_override_detection: bool, ) -> Self { @@ -261,7 +269,10 @@ impl TransferJob { let total_size = files.iter().map(|x| x.size as u64).sum(); Self { id, + remote, path: get_path(&path), + show_hidden, + is_remote, files, total_size, enable_overwrite_detection: enable_override_detection, @@ -271,7 +282,10 @@ impl TransferJob { pub fn new_read( id: i32, + remote: String, path: String, + show_hidden: bool, + is_remote: bool, include_hidden: bool, enable_override_detection: bool, ) -> ResultType { @@ -280,7 +294,10 @@ impl TransferJob { let total_size = files.iter().map(|x| x.size as u64).sum(); Ok(Self { id, + remote, path: get_path(&path), + show_hidden, + is_remote, files, total_size, enable_overwrite_detection: enable_override_detection, @@ -561,8 +578,10 @@ impl TransferJob { pub fn gen_meta(&self) -> TransferJobMeta { TransferJobMeta { id: self.id, - path: self.path.clone(), + remote: self.remote.to_string(), + to: self.path.to_string_lossy().to_string(), file_num: self.file_num, + show_hidden: self.show_hidden } } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 92368fc0c..d3a33b21c 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -974,7 +974,7 @@ impl Connection { let id = s.id; let od = can_enable_overwrite_detection(get_version_number(VERSION)); - match fs::TransferJob::new_read(id, s.path.clone(), s.include_hidden) { + match fs::TransferJob::new_read(id, s.path.clone(), s.include_hidden, od) { Err(err) => { self.send(fs::new_error(id, err, 0)).await; } diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 182886f5e..b86775c79 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -161,9 +161,13 @@ impl ConnectionManager { mut files, } => { let od = can_enable_overwrite_detection(get_version_number(VERSION)); + // cm has no show_hidden context write_jobs.push(fs::TransferJob::new_write( id, + "".to_string(), path, + false, + false, files .drain(..) .map(|f| FileEntry { @@ -172,7 +176,7 @@ impl ConnectionManager { ..Default::default() }) .collect(), - od, + od, )); } ipc::FS::CancelWrite { id } => { diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index 13c312483..c03cfcef4 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -100,6 +100,12 @@ class JobTable: Reactor.Component { refreshDir(is_remote); } + function clearAllJobs() { + this.jobs = []; + this.job_map = {}; + this.update(); + } + function send(path, is_remote) { var to; var show_hidden; @@ -124,6 +130,14 @@ class JobTable: Reactor.Component { self.timer(30ms, function() { self.update(); }); } + function addJob(id, path, to, show_hidden, is_remote) { + this.jobs.push({ type: "transfer", + id: id, path: path, to: to, + include_hidden: show_hidden, + is_remote: is_remote }); + this.job_map[id] = this.jobs[this.jobs.length - 1]; + } + function addDelDir(path, is_remote) { var id = jobIdCounter; jobIdCounter += 1; @@ -649,6 +663,18 @@ handler.jobError = function(id, err, file_num = -1) { file_transfer.job_table.updateJobStatus(id, file_num, err); } +handler.clearAllJobs = function() { + file_transfer.job_table.clearAllJobs(); +} + +handler.addJob = function (id, path, to, file_num, show_hidden, is_remote) { + file_transfer.job_table.addJob(id,path,to,file_num,show_hidden,is_remote); +} + +handler.updateTransferList = function () { + file_transfer.job_table.update(); +} + function refreshDir(is_remote) { if (is_remote) file_transfer.remote_folder_view.refreshDir(); else file_transfer.local_folder_view.refreshDir(); diff --git a/src/ui/remote.rs b/src/ui/remote.rs index bc7da1791..60cc72fbd 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1387,6 +1387,10 @@ impl Remote { } self.handler .call("setConnectionType", &make_args!(peer.is_secured(), direct)); + + if conn_type == ConnType::FILE_TRANSFER { + self.load_last_jobs().await; + } // just build for now #[cfg(not(windows))] @@ -1537,6 +1541,36 @@ impl Remote { Some(tx) } + async fn load_last_jobs(&mut self) { + self.handler.call("clearAllJobs",&make_args!()); + let pc = self.handler.load_config(); + if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() { + // no last jobs + return; + } + // TODO: can add a confirm dialog + let mut cnt = 0; + for job in pc.transfer.read_jobs.iter() { + self.handler.call("addJob",&make_args!( + cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, false + )); + self.handler.send_files(cnt, job.remote.clone(), + job.to.clone(), job.show_hidden, false); + cnt += 1; + println!("restore read_job: {:?}",job); + } + for job in pc.transfer.write_jobs.iter() { + self.handler.call("addJob",&make_args!( + cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, true + )); + self.handler.send_files(cnt, job.remote.clone(), + job.to.clone(), job.show_hidden, true); + cnt += 1; + println!("restore write_job: {:?}",job); + } + self.handler.call("updateTransferList", &make_args!()); + } + async fn handle_msg_from_ui(&mut self, data: Data, peer: &mut Stream) -> bool { // log::info!("new msg from ui, {}",data); match data { @@ -1560,10 +1594,10 @@ impl Remote { if is_remote { log::debug!("New job {}, write to {} from remote {}", id, to, path); self.write_jobs - .push(fs::TransferJob::new_write(id, to, Vec::new(), od)); + .push(fs::TransferJob::new_write(id, path.clone(),to,include_hidden,is_remote, Vec::new(), od)); allow_err!(peer.send(&fs::new_send(id, path, include_hidden)).await); } else { - match fs::TransferJob::new_read(id, path.clone(), include_hidden, od) { + match fs::TransferJob::new_read(id, path.clone(),to.clone(),include_hidden,is_remote, include_hidden, od) { Err(err) => { self.handle_job_status(id, -1, Some(err.to_string())); } From b3f523f65e661c33c553327f86a8a8440a4cad3d Mon Sep 17 00:00:00 2001 From: Kingtous Date: Thu, 12 May 2022 16:29:34 +0800 Subject: [PATCH 19/27] fix: serde --- libs/hbb_common/src/fs.rs | 8 ++++++++ src/ui/remote.rs | 2 ++ 2 files changed, 10 insertions(+) diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 8ae9e0114..60413ff43 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -219,17 +219,25 @@ pub struct TransferJob { #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct TransferJobMeta { + #[serde(default)] pub id: i32, + #[serde(default)] pub remote: String, + #[serde(default)] pub to: String, + #[serde(default)] pub show_hidden: bool, + #[serde(default)] pub file_num: i32, } #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct RemoveJobMeta { + #[serde(default)] pub path: String, + #[serde(default)] pub is_remote: bool, + #[serde(default)] pub no_confirm: bool, } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 60cc72fbd..ad69f243a 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1542,6 +1542,7 @@ impl Remote { } async fn load_last_jobs(&mut self) { + println!("start load last jobs"); self.handler.call("clearAllJobs",&make_args!()); let pc = self.handler.load_config(); if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() { @@ -1845,6 +1846,7 @@ impl Remote { transfer_metas.remove_jobs.push(job.gen_meta()); } config.transfer = transfer_metas; + println!("{:?}", config.transfer); self.handler.save_config(config); true } From 77bb821ecfc9addd707ef51496d4bad881480849 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 13 May 2022 09:30:52 +0800 Subject: [PATCH 20/27] fix: to string --- libs/hbb_common/src/config.rs | 6 ++-- libs/hbb_common/src/fs.rs | 6 +++- src/main.rs | 5 ++-- src/ui/cm.rs | 1 - src/ui/remote.rs | 52 +++++++++++++++++++---------------- 5 files changed, 38 insertions(+), 32 deletions(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index c9878d0ff..7cb735466 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -157,11 +157,9 @@ pub struct PeerInfoSerde { #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct TransferSerde { #[serde(default)] - pub write_jobs: Vec, + pub write_jobs: Vec, #[serde(default)] - pub read_jobs: Vec, - #[serde(default)] - pub remove_jobs: Vec, + pub read_jobs: Vec, } fn patch(path: PathBuf) -> PathBuf { diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 60413ff43..92d4f6b3a 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -229,6 +229,8 @@ pub struct TransferJobMeta { pub show_hidden: bool, #[serde(default)] pub file_num: i32, + #[serde(default)] + pub is_remote: bool } #[derive(Debug, Default, Serialize, Deserialize, Clone)] @@ -583,13 +585,15 @@ impl TransferJob { true } + #[inline] pub fn gen_meta(&self) -> TransferJobMeta { TransferJobMeta { id: self.id, remote: self.remote.to_string(), to: self.path.to_string_lossy().to_string(), file_num: self.file_num, - show_hidden: self.show_hidden + show_hidden: self.show_hidden, + is_remote: self.is_remote } } } diff --git a/src/main.rs b/src/main.rs index d802b8ae9..c1dd29a05 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,12 +39,13 @@ fn main() { println!("{}", crate::VERSION); return; } - #[cfg(not(feature = "inline"))] + // TODO: 提交去除inline + #[cfg(feature = "inline")] { use hbb_common::env_logger::*; init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); } - #[cfg(feature = "inline")] + #[cfg(not(feature = "inline"))] { let mut path = hbb_common::config::Config::log_path(); if args.len() > 0 && args[0].starts_with("--") { diff --git a/src/ui/cm.rs b/src/ui/cm.rs index b86775c79..3992985e5 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -371,7 +371,6 @@ impl ConnectionManager { } async fn send(msg: Message, conn: &mut Connection) { - println!("send msg: {:?}", msg); match msg.write_to_bytes() { Ok(bytes) => allow_err!(conn.send(&Data::RawMessage(bytes)).await), err => allow_err!(err), diff --git a/src/ui/remote.rs b/src/ui/remote.rs index ad69f243a..59db974a4 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -20,7 +20,7 @@ use clipboard::{ get_rx_clip_client, server_clip_file, }; use enigo::{self, Enigo, KeyboardControllable}; -use hbb_common::config::TransferSerde; +use hbb_common::{config::TransferSerde, fs::TransferJobMeta}; use hbb_common::fs::{ can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm, DigestCheckResult, RemoveJobMeta, @@ -1319,7 +1319,6 @@ async fn io_loop(handler: Handler) { clipboard_file_context: None, }; remote.io_loop(&key, &token).await; - remote.sync_jobs_status_to_local().await; } struct RemoveJob { @@ -1551,23 +1550,29 @@ impl Remote { } // TODO: can add a confirm dialog let mut cnt = 0; - for job in pc.transfer.read_jobs.iter() { - self.handler.call("addJob",&make_args!( - cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, false - )); - self.handler.send_files(cnt, job.remote.clone(), - job.to.clone(), job.show_hidden, false); - cnt += 1; - println!("restore read_job: {:?}",job); + for job_str in pc.transfer.read_jobs.iter() { + let job: Result = serde_json::from_str(&job_str); + if let Ok(job) = job { + self.handler.call("addJob",&make_args!( + cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, false + )); + self.handler.send_files(cnt, job.remote.clone(), + job.to.clone(), job.show_hidden, false); + cnt += 1; + println!("restore read_job: {:?}",job); + } } - for job in pc.transfer.write_jobs.iter() { - self.handler.call("addJob",&make_args!( - cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, true - )); - self.handler.send_files(cnt, job.remote.clone(), - job.to.clone(), job.show_hidden, true); - cnt += 1; - println!("restore write_job: {:?}",job); + for job_str in pc.transfer.write_jobs.iter() { + let job: Result = serde_json::from_str(&job_str); + if let Ok(job) = job { + self.handler.call("addJob",&make_args!( + cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, true + )); + self.handler.send_files(cnt, job.remote.clone(), + job.to.clone(), job.show_hidden, true); + cnt += 1; + println!("restore write_job: {:?}",job); + } } self.handler.call("updateTransferList", &make_args!()); } @@ -1595,7 +1600,7 @@ impl Remote { if is_remote { log::debug!("New job {}, write to {} from remote {}", id, to, path); self.write_jobs - .push(fs::TransferJob::new_write(id, path.clone(),to,include_hidden,is_remote, Vec::new(), od)); + .push(fs::TransferJob::new_write(id, path.clone(),to,include_hidden, is_remote, Vec::new(), od)); allow_err!(peer.send(&fs::new_send(id, path, include_hidden)).await); } else { match fs::TransferJob::new_read(id, path.clone(),to.clone(),include_hidden,is_remote, include_hidden, od) { @@ -1837,13 +1842,12 @@ impl Remote { let mut config: PeerConfig = self.handler.load_config(); let mut transfer_metas = TransferSerde::default(); for job in self.read_jobs.iter() { - transfer_metas.read_jobs.push(job.gen_meta()); + let json_str = serde_json::to_string(&job.gen_meta()).unwrap(); + transfer_metas.read_jobs.push(json_str); } for job in self.write_jobs.iter() { - transfer_metas.write_jobs.push(job.gen_meta()); - } - for job in self.remove_jobs.values() { - transfer_metas.remove_jobs.push(job.gen_meta()); + let json_str = serde_json::to_string(&job.gen_meta()).unwrap(); + transfer_metas.write_jobs.push(json_str); } config.transfer = transfer_metas; println!("{:?}", config.transfer); From 9dbd94daac4877d342991956c5bb718835ae41e0 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 13 May 2022 10:37:16 +0800 Subject: [PATCH 21/27] feat: load last job --- src/ui/file_transfer.tis | 16 +++++++++++----- src/ui/remote.rs | 19 ++++++++----------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index c03cfcef4..dc1b4310d 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -130,12 +130,16 @@ class JobTable: Reactor.Component { self.timer(30ms, function() { self.update(); }); } - function addJob(id, path, to, show_hidden, is_remote) { - this.jobs.push({ type: "transfer", - id: id, path: path, to: to, - include_hidden: show_hidden, - is_remote: is_remote }); + function addJob(id, path, to, file_num, show_hidden, is_remote) { + var job = { type: "transfer", + id: id, path: path, to: to, + include_hidden: show_hidden, + is_remote: is_remote }; + this.jobs.push(job); this.job_map[id] = this.jobs[this.jobs.length - 1]; + jobIdCounter = id + 1; + handler.send_files(id, path, to, show_hidden, is_remote); + stdout.println(JSON.stringify(job)); } function addDelDir(path, is_remote) { @@ -617,6 +621,7 @@ function initializeFileTransfer() } handler.updateFolderFiles = function(fd) { + stdout.println("update folder files: " + JSON.stringify(fd)); fd.entries = fd.entries || []; if (fd.id > 0) { var jt = file_transfer.job_table; @@ -668,6 +673,7 @@ handler.clearAllJobs = function() { } handler.addJob = function (id, path, to, file_num, show_hidden, is_remote) { + stdout.println("restore job: " + is_remote); file_transfer.job_table.addJob(id,path,to,file_num,show_hidden,is_remote); } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 59db974a4..58ada23d8 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1386,10 +1386,6 @@ impl Remote { } self.handler .call("setConnectionType", &make_args!(peer.is_secured(), direct)); - - if conn_type == ConnType::FILE_TRANSFER { - self.load_last_jobs().await; - } // just build for now #[cfg(not(windows))] @@ -1541,7 +1537,7 @@ impl Remote { } async fn load_last_jobs(&mut self) { - println!("start load last jobs"); + log::info!("start load last jobs"); self.handler.call("clearAllJobs",&make_args!()); let pc = self.handler.load_config(); if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() { @@ -1549,15 +1545,13 @@ impl Remote { return; } // TODO: can add a confirm dialog - let mut cnt = 0; + let mut cnt = 1; for job_str in pc.transfer.read_jobs.iter() { let job: Result = serde_json::from_str(&job_str); if let Ok(job) = job { self.handler.call("addJob",&make_args!( cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, false )); - self.handler.send_files(cnt, job.remote.clone(), - job.to.clone(), job.show_hidden, false); cnt += 1; println!("restore read_job: {:?}",job); } @@ -1568,8 +1562,6 @@ impl Remote { self.handler.call("addJob",&make_args!( cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, true )); - self.handler.send_files(cnt, job.remote.clone(), - job.to.clone(), job.show_hidden, true); cnt += 1; println!("restore write_job: {:?}",job); } @@ -1895,6 +1887,10 @@ impl Remote { }); } } + + if self.handler.is_file_transfer() { + self.load_last_jobs().await; + } } _ => {} }, @@ -1932,6 +1928,7 @@ impl Remote { } self.handler.call("updateFolderFiles", &make_args!(m)); if let Some(job) = fs::get_job(fd.id, &mut self.write_jobs) { + log::info!("job set_files: {:?}",entries); job.set_files(entries); } else if let Some(job) = self.remove_jobs.get_mut(&fd.id) { job.files = entries; @@ -2040,7 +2037,7 @@ impl Remote { } } Some(file_response::Union::block(block)) => { - log::info!("file response block, file num: {}", block.file_num); + log::info!("file response block, file id:{}, file num: {}",block.id, block.file_num); if let Some(job) = fs::get_job(block.id, &mut self.write_jobs) { if let Err(_err) = job.write(block, None).await { // to-do: add "skip" for writing job From a2bc2a21bbe4e4b8be2781d8229ede2f40b81637 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 13 May 2022 11:23:30 +0800 Subject: [PATCH 22/27] add: file_num offset --- libs/hbb_common/protos/message.proto | 2 ++ libs/hbb_common/src/fs.rs | 10 ++++++++-- src/client.rs | 2 +- src/ipc.rs | 1 + src/server/connection.rs | 3 ++- src/ui/cm.rs | 3 +++ src/ui/file_transfer.tis | 4 ++-- src/ui/remote.rs | 12 ++++++------ 8 files changed, 25 insertions(+), 12 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 00c4bda49..8360b355c 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -294,6 +294,7 @@ message FileTransferSendRequest { int32 id = 1; string path = 2; bool include_hidden = 3; + int32 file_num = 4; } message FileTransferSendConfirmRequest { @@ -322,6 +323,7 @@ message FileTransferReceiveRequest { int32 id = 1; string path = 2; // path written to repeated FileEntry files = 3; + int32 file_num = 4; } message FileRemoveDir { diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 92d4f6b3a..6711ff901 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -270,6 +270,7 @@ impl TransferJob { id: i32, remote: String, path: String, + file_num: i32, show_hidden: bool, is_remote: bool, files: Vec, @@ -281,6 +282,7 @@ impl TransferJob { id, remote, path: get_path(&path), + file_num, show_hidden, is_remote, files, @@ -294,6 +296,7 @@ impl TransferJob { id: i32, remote: String, path: String, + file_num: i32, show_hidden: bool, is_remote: bool, include_hidden: bool, @@ -306,6 +309,7 @@ impl TransferJob { id, remote, path: get_path(&path), + file_num, show_hidden, is_remote, files, @@ -645,12 +649,13 @@ pub fn new_send_confirm(r: FileTransferSendConfirmRequest) -> Message { } #[inline] -pub fn new_receive(id: i32, path: String, files: Vec) -> Message { +pub fn new_receive(id: i32, path: String, file_num: i32, files: Vec) -> Message { let mut action = FileAction::new(); action.set_receive(FileTransferReceiveRequest { id, path, files: files.into(), + file_num, ..Default::default() }); let mut msg_out = Message::new(); @@ -659,13 +664,14 @@ pub fn new_receive(id: i32, path: String, files: Vec) -> Message { } #[inline] -pub fn new_send(id: i32, path: String, include_hidden: bool) -> Message { +pub fn new_send(id: i32, path: String, file_num: i32, include_hidden: bool) -> Message { log::info!("new send: {},id : {}", path, id); let mut action = FileAction::new(); action.set_send(FileTransferSendRequest { id, path, include_hidden, + file_num, ..Default::default() }); let mut msg_out = Message::new(); diff --git a/src/client.rs b/src/client.rs index e6be8b855..5b6366849 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1313,7 +1313,7 @@ pub enum Data { Close, Login((String, bool)), Message(Message), - SendFiles((i32, String, String, bool, bool)), + SendFiles((i32, String, String, i32, bool, bool)), RemoveDirAll((i32, String, bool)), ConfirmDeleteFiles((i32, i32)), SetNoConfirm(i32), diff --git a/src/ipc.rs b/src/ipc.rs index b976f2ec6..2388a7d9c 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -44,6 +44,7 @@ pub enum FS { NewWrite { path: String, id: i32, + file_num: i32, files: Vec<(String, u64)>, }, CancelWrite { diff --git a/src/server/connection.rs b/src/server/connection.rs index d3a33b21c..eca6407db 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -974,7 +974,7 @@ impl Connection { let id = s.id; let od = can_enable_overwrite_detection(get_version_number(VERSION)); - match fs::TransferJob::new_read(id, s.path.clone(), s.include_hidden, od) { + match fs::TransferJob::new_read(id, s.path.clone(), s.file_num, s.include_hidden, od) { Err(err) => { self.send(fs::new_error(id, err, 0)).await; } @@ -990,6 +990,7 @@ impl Connection { self.send_fs(ipc::FS::NewWrite { path: r.path, id: r.id, + file_num: r.file_num, files: r .files .to_vec() diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 3992985e5..546aca557 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -158,14 +158,17 @@ impl ConnectionManager { ipc::FS::NewWrite { path, id, + file_num, mut files, } => { let od = can_enable_overwrite_detection(get_version_number(VERSION)); // cm has no show_hidden context + // dummy remote, show_hidden, is_remote write_jobs.push(fs::TransferJob::new_write( id, "".to_string(), path, + file_num, false, false, files diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index dc1b4310d..026bb94a5 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -125,7 +125,7 @@ class JobTable: Reactor.Component { include_hidden: show_hidden, is_remote: is_remote }); this.job_map[id] = this.jobs[this.jobs.length - 1]; - handler.send_files(id, path, to, show_hidden, is_remote); + handler.send_files(id, path, to, 0, show_hidden, is_remote); var self = this; self.timer(30ms, function() { self.update(); }); } @@ -138,7 +138,7 @@ class JobTable: Reactor.Component { this.jobs.push(job); this.job_map[id] = this.jobs[this.jobs.length - 1]; jobIdCounter = id + 1; - handler.send_files(id, path, to, show_hidden, is_remote); + handler.send_files(id, path, to, file_num, show_hidden, is_remote); stdout.println(JSON.stringify(job)); } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 58ada23d8..b9e50d128 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -204,7 +204,7 @@ impl sciter::EventHandler for Handler { fn confirm_delete_files(i32, i32); fn set_no_confirm(i32); fn cancel_job(i32); - fn send_files(i32, String, String, bool, bool); + fn send_files(i32, String, String, i32, bool, bool); fn get_platform(bool); fn get_path_sep(bool); fn get_icon_path(i32, String); @@ -1586,16 +1586,16 @@ impl Remote { Data::Message(msg) => { allow_err!(peer.send(&msg).await); } - Data::SendFiles((id, path, to, include_hidden, is_remote)) => { + Data::SendFiles((id, path, to,file_num, include_hidden, is_remote)) => { log::info!("send files, is remote {}", is_remote); let od = can_enable_overwrite_detection(self.handler.lc.read().unwrap().version); if is_remote { log::debug!("New job {}, write to {} from remote {}", id, to, path); self.write_jobs - .push(fs::TransferJob::new_write(id, path.clone(),to,include_hidden, is_remote, Vec::new(), od)); - allow_err!(peer.send(&fs::new_send(id, path, include_hidden)).await); + .push(fs::TransferJob::new_write(id, path.clone(),to,file_num, include_hidden, is_remote, Vec::new(), od)); + allow_err!(peer.send(&fs::new_send(id, path,file_num, include_hidden)).await); } else { - match fs::TransferJob::new_read(id, path.clone(),to.clone(),include_hidden,is_remote, include_hidden, od) { + match fs::TransferJob::new_read(id, path.clone(),to.clone(), file_num,include_hidden,is_remote, include_hidden, od) { Err(err) => { self.handle_job_status(id, -1, Some(err.to_string())); } @@ -1612,7 +1612,7 @@ impl Remote { let files = job.files().clone(); self.read_jobs.push(job); self.timer = time::interval(MILLI1); - allow_err!(peer.send(&fs::new_receive(id, to, files)).await); + allow_err!(peer.send(&fs::new_receive(id, to, file_num, files)).await); } } } From 52fd312ff3e84b2253e93619e339707965b68c44 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 13 May 2022 11:40:56 +0800 Subject: [PATCH 23/27] opt: clean code --- libs/hbb_common/protos/message.proto | 9 --------- src/server/connection.rs | 8 -------- src/ui/remote.rs | 11 +++-------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 8360b355c..a8edb9563 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -264,7 +264,6 @@ message FileResponse { FileTransferError error = 3; FileTransferDone done = 4; FileTransferDigest digest = 5; - FileTransferDirOffsetRequest offset = 6; } } @@ -306,14 +305,6 @@ message FileTransferSendConfirmRequest { } } -message FileTransferDirOffsetRequest { - int32 id = 1; - // start from file_num - sint32 file_num = 2; - // current file blk offset - uint32 offset_blk = 3; -} - message FileTransferDone { int32 id = 1; sint32 file_num = 2; diff --git a/src/server/connection.rs b/src/server/connection.rs index eca6407db..f9f3e0264 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1054,14 +1054,6 @@ impl Connection { last_modified: d.last_modified, is_upload: true, }), - Some(file_response::Union::offset(offset)) => { - // TODO: i32 - // self.send_fs(ipc::FS::WriteOffset { - // id: offset.id, - // file_num: offset.file_num, - // offset_blk: offset.offset_blk, - // }); - } _ => {} }, Some(message::Union::misc(misc)) => match misc.union { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index b9e50d128..35fda8b10 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1550,7 +1550,7 @@ impl Remote { let job: Result = serde_json::from_str(&job_str); if let Ok(job) = job { self.handler.call("addJob",&make_args!( - cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, false + cnt,job.to.clone(),job.remote.clone(),job.file_num,job.show_hidden, false )); cnt += 1; println!("restore read_job: {:?}",job); @@ -1595,7 +1595,7 @@ impl Remote { .push(fs::TransferJob::new_write(id, path.clone(),to,file_num, include_hidden, is_remote, Vec::new(), od)); allow_err!(peer.send(&fs::new_send(id, path,file_num, include_hidden)).await); } else { - match fs::TransferJob::new_read(id, path.clone(),to.clone(), file_num,include_hidden,is_remote, include_hidden, od) { + match fs::TransferJob::new_read(id, to.clone(), path.clone(), file_num,include_hidden,is_remote, include_hidden, od) { Err(err) => { self.handle_job_status(id, -1, Some(err.to_string())); } @@ -1830,7 +1830,7 @@ impl Remote { } async fn sync_jobs_status_to_local(&mut self) -> bool { - println!("sync job status"); + log::info!("sync transfer job status"); let mut config: PeerConfig = self.handler.load_config(); let mut transfer_metas = TransferSerde::default(); for job in self.read_jobs.iter() { @@ -1842,7 +1842,6 @@ impl Remote { transfer_metas.write_jobs.push(json_str); } config.transfer = transfer_metas; - println!("{:?}", config.transfer); self.handler.save_config(config); true } @@ -1934,10 +1933,6 @@ impl Remote { job.files = entries; } } - Some(file_response::Union::offset(offset)) => { - // TODO: offset - // upload - } Some(file_response::Union::digest(digest)) => { if digest.is_upload { if let Some(job) = fs::get_job(digest.id, &mut self.read_jobs) { From 8a6c3fe70a72f7496632f6c18b15cb8a5c6c64c5 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 13 May 2022 11:42:01 +0800 Subject: [PATCH 24/27] fix: invert inline --- src/main.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index c1dd29a05..d802b8ae9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,13 +39,12 @@ fn main() { println!("{}", crate::VERSION); return; } - // TODO: 提交去除inline - #[cfg(feature = "inline")] + #[cfg(not(feature = "inline"))] { use hbb_common::env_logger::*; init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); } - #[cfg(not(feature = "inline"))] + #[cfg(feature = "inline")] { let mut path = hbb_common::config::Config::log_path(); if args.len() > 0 && args[0].starts_with("--") { From c96c0df64570ba5b51c8a5a4c765279b45dd673f Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 13 May 2022 14:46:37 +0800 Subject: [PATCH 25/27] fix: rebase conflict --- libs/hbb_common/src/config.rs | 5 +++ libs/hbb_common/src/fs.rs | 7 ++-- src/client.rs | 16 ++++---- src/client/file_trait.rs | 3 +- src/lang/ru.rs | 2 +- src/server/connection.rs | 14 ++++++- src/ui/cm.rs | 10 ++--- src/ui/remote.rs | 73 +++++++++++++++++++++++++++-------- 8 files changed, 92 insertions(+), 38 deletions(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 7cb735466..ce0fc509a 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -1,3 +1,8 @@ +use crate::log; +use directories_next::ProjectDirs; +use rand::Rng; +use serde_derive::{Deserialize, Serialize}; +use sodiumoxide::crypto::sign; use std::{ collections::HashMap, fs, diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 6711ff901..13915ac0b 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -230,7 +230,7 @@ pub struct TransferJobMeta { #[serde(default)] pub file_num: i32, #[serde(default)] - pub is_remote: bool + pub is_remote: bool, } #[derive(Debug, Default, Serialize, Deserialize, Clone)] @@ -299,11 +299,10 @@ impl TransferJob { file_num: i32, show_hidden: bool, is_remote: bool, - include_hidden: bool, enable_override_detection: bool, ) -> ResultType { log::info!("new read {}", path); - let files = get_recursive_files(&path, include_hidden)?; + let files = get_recursive_files(&path, show_hidden)?; let total_size = files.iter().map(|x| x.size as u64).sum(); Ok(Self { id, @@ -597,7 +596,7 @@ impl TransferJob { to: self.path.to_string_lossy().to_string(), file_num: self.file_num, show_hidden: self.show_hidden, - is_remote: self.is_remote + is_remote: self.is_remote, } } } diff --git a/src/client.rs b/src/client.rs index 5b6366849..d31c43266 100644 --- a/src/client.rs +++ b/src/client.rs @@ -535,14 +535,14 @@ impl AudioHandler { } self.simple = Some(Simple::new( - None, // Use the default server - &crate::get_app_name(), // Our application’s name - Direction::Playback, // We want a playback stream - None, // Use the default device - "playback", // Description of our stream - &spec, // Our sample format - None, // Use default channel map - None, // Use default buffering attributes + None, // Use the default server + &crate::get_app_name(), // Our application’s name + Direction::Playback, // We want a playback stream + None, // Use the default device + "playback", // Description of our stream + &spec, // Our sample format + None, // Use default channel map + None, // Use default buffering attributes )?); self.sample_rate = (format0.sample_rate, format0.sample_rate); Ok(()) diff --git a/src/client/file_trait.rs b/src/client/file_trait.rs index 0e6e97e42..fd0b2a694 100644 --- a/src/client/file_trait.rs +++ b/src/client/file_trait.rs @@ -80,9 +80,10 @@ pub trait FileManager: Interface { id: i32, path: String, to: String, + file_num: i32, include_hidden: bool, is_remote: bool, ) { - self.send(Data::SendFiles((id, path, to, include_hidden, is_remote))); + self.send(Data::SendFiles((id, path, to, file_num, include_hidden, is_remote))); } } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 5ce96ab33..e3cf96dae 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -267,7 +267,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Account", "Аккаунт"), ("Quit", "Выйти"), ("Overwrite", "крышка"), - ("This file exists, skip or overwrite this file?", "Этот файл существует, пропустить или перезаписать этот файл?") + ("This file exists, skip or overwrite this file?", "Этот файл существует, пропустить или перезаписать этот файл?"), ("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"), ("Help", "Помощь"), ].iter().cloned().collect(); diff --git a/src/server/connection.rs b/src/server/connection.rs index f9f3e0264..f4780ea4d 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -3,9 +3,10 @@ use super::{input_service::*, *}; use crate::clipboard_file::*; #[cfg(not(any(target_os = "android", target_os = "ios")))] use crate::common::update_clipboard; -use crate::ipc; #[cfg(any(target_os = "android", target_os = "ios"))] use crate::{common::MOBILE_INFO2, mobile::connection_manager::start_channel}; +use crate::{ipc, VERSION}; +use hbb_common::fs::can_enable_overwrite_detection; use hbb_common::log::debug; use hbb_common::message_proto::file_transfer_send_confirm_request::Union; use hbb_common::{ @@ -974,7 +975,16 @@ impl Connection { let id = s.id; let od = can_enable_overwrite_detection(get_version_number(VERSION)); - match fs::TransferJob::new_read(id, s.path.clone(), s.file_num, s.include_hidden, od) { + let path = s.path.clone(); + match fs::TransferJob::new_read( + id, + "".to_string(), + path.clone(), + s.file_num, + s.include_hidden, + false, + od, + ) { Err(err) => { self.send(fs::new_error(id, err, 0)).await; } diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 546aca557..421750200 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -179,7 +179,7 @@ impl ConnectionManager { ..Default::default() }) .collect(), - od, + od, )); } ipc::FS::CancelWrite { id } => { @@ -278,10 +278,10 @@ impl ConnectionManager { } } ipc::FS::WriteOffset { - id,file_num,offset_blk - } => { - - } + id, + file_num, + offset_blk, + } => {} }, #[cfg(windows)] Data::ClipbaordFile(_clip) => { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 35fda8b10..c1f8c63cb 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -20,7 +20,6 @@ use clipboard::{ get_rx_clip_client, server_clip_file, }; use enigo::{self, Enigo, KeyboardControllable}; -use hbb_common::{config::TransferSerde, fs::TransferJobMeta}; use hbb_common::fs::{ can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm, DigestCheckResult, RemoveJobMeta, @@ -41,6 +40,7 @@ use hbb_common::{ }, Stream, }; +use hbb_common::{config::TransferSerde, fs::TransferJobMeta}; #[cfg(windows)] use crate::clipboard_file::*; @@ -1538,7 +1538,7 @@ impl Remote { async fn load_last_jobs(&mut self) { log::info!("start load last jobs"); - self.handler.call("clearAllJobs",&make_args!()); + self.handler.call("clearAllJobs", &make_args!()); let pc = self.handler.load_config(); if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() { // no last jobs @@ -1549,21 +1549,37 @@ impl Remote { for job_str in pc.transfer.read_jobs.iter() { let job: Result = serde_json::from_str(&job_str); if let Ok(job) = job { - self.handler.call("addJob",&make_args!( - cnt,job.to.clone(),job.remote.clone(),job.file_num,job.show_hidden, false - )); + self.handler.call( + "addJob", + &make_args!( + cnt, + job.to.clone(), + job.remote.clone(), + job.file_num, + job.show_hidden, + false + ), + ); cnt += 1; - println!("restore read_job: {:?}",job); + println!("restore read_job: {:?}", job); } } for job_str in pc.transfer.write_jobs.iter() { let job: Result = serde_json::from_str(&job_str); if let Ok(job) = job { - self.handler.call("addJob",&make_args!( - cnt,job.remote.clone(),job.to.clone(),job.file_num,job.show_hidden, true - )); + self.handler.call( + "addJob", + &make_args!( + cnt, + job.remote.clone(), + job.to.clone(), + job.file_num, + job.show_hidden, + true + ), + ); cnt += 1; - println!("restore write_job: {:?}",job); + println!("restore write_job: {:?}", job); } } self.handler.call("updateTransferList", &make_args!()); @@ -1586,16 +1602,35 @@ impl Remote { Data::Message(msg) => { allow_err!(peer.send(&msg).await); } - Data::SendFiles((id, path, to,file_num, include_hidden, is_remote)) => { + Data::SendFiles((id, path, to, file_num, include_hidden, is_remote)) => { log::info!("send files, is remote {}", is_remote); let od = can_enable_overwrite_detection(self.handler.lc.read().unwrap().version); if is_remote { log::debug!("New job {}, write to {} from remote {}", id, to, path); - self.write_jobs - .push(fs::TransferJob::new_write(id, path.clone(),to,file_num, include_hidden, is_remote, Vec::new(), od)); - allow_err!(peer.send(&fs::new_send(id, path,file_num, include_hidden)).await); + self.write_jobs.push(fs::TransferJob::new_write( + id, + path.clone(), + to, + file_num, + include_hidden, + is_remote, + Vec::new(), + od, + )); + allow_err!( + peer.send(&fs::new_send(id, path, file_num, include_hidden)) + .await + ); } else { - match fs::TransferJob::new_read(id, to.clone(), path.clone(), file_num,include_hidden,is_remote, include_hidden, od) { + match fs::TransferJob::new_read( + id, + to.clone(), + path.clone(), + file_num, + include_hidden, + is_remote, + od, + ) { Err(err) => { self.handle_job_status(id, -1, Some(err.to_string())); } @@ -1927,7 +1962,7 @@ impl Remote { } self.handler.call("updateFolderFiles", &make_args!(m)); if let Some(job) = fs::get_job(fd.id, &mut self.write_jobs) { - log::info!("job set_files: {:?}",entries); + log::info!("job set_files: {:?}", entries); job.set_files(entries); } else if let Some(job) = self.remove_jobs.get_mut(&fd.id) { job.files = entries; @@ -2032,7 +2067,11 @@ impl Remote { } } Some(file_response::Union::block(block)) => { - log::info!("file response block, file id:{}, file num: {}",block.id, block.file_num); + log::info!( + "file response block, file id:{}, file num: {}", + block.id, + block.file_num + ); if let Some(job) = fs::get_job(block.id, &mut self.write_jobs) { if let Err(_err) = job.write(block, None).await { // to-do: add "skip" for writing job From d186dd26a295b415fb5413e9ae4e5daa673e1b9c Mon Sep 17 00:00:00 2001 From: Kingtous Date: Fri, 13 May 2022 15:11:56 +0800 Subject: [PATCH 26/27] fix: change state to sync jobs to adapt master branch logic --- src/ui/file_transfer.tis | 2 +- src/ui/remote.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index 026bb94a5..bcf59b388 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -621,7 +621,7 @@ function initializeFileTransfer() } handler.updateFolderFiles = function(fd) { - stdout.println("update folder files: " + JSON.stringify(fd)); + // stdout.println("update folder files: " + JSON.stringify(fd)); fd.entries = fd.entries || []; if (fd.id > 0) { var jt = file_transfer.job_table; diff --git a/src/ui/remote.rs b/src/ui/remote.rs index c1f8c63cb..89ad6b9e3 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -1319,6 +1319,7 @@ async fn io_loop(handler: Handler) { clipboard_file_context: None, }; remote.io_loop(&key, &token).await; + remote.sync_jobs_status_to_local().await; } struct RemoveJob { @@ -1451,7 +1452,6 @@ impl Remote { } } } - self.sync_jobs_status_to_local().await; log::debug!("Exit io_loop of id={}", self.handler.id); } Err(err) => { @@ -1876,6 +1876,7 @@ impl Remote { let json_str = serde_json::to_string(&job.gen_meta()).unwrap(); transfer_metas.write_jobs.push(json_str); } + log::info!("meta: {:?}",transfer_metas); config.transfer = transfer_metas; self.handler.save_config(config); true From 39eb1b7211af9dc2fd48f456036e5abfdfa656d7 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 14 May 2022 11:58:47 +0800 Subject: [PATCH 27/27] opt: add resume btn --- libs/hbb_common/src/fs.rs | 19 +++++++---- src/client.rs | 3 +- src/client/file_trait.rs | 16 ++++++++++ src/ui/file_transfer.css | 4 +++ src/ui/file_transfer.tis | 30 +++++++++++++++--- src/ui/remote.rs | 67 ++++++++++++++++++++++++++++++++++++++- 6 files changed, 126 insertions(+), 13 deletions(-) diff --git a/libs/hbb_common/src/fs.rs b/libs/hbb_common/src/fs.rs index 13915ac0b..4ba132f57 100644 --- a/libs/hbb_common/src/fs.rs +++ b/libs/hbb_common/src/fs.rs @@ -200,13 +200,15 @@ pub fn can_enable_overwrite_detection(version: i64) -> bool { #[derive(Default)] pub struct TransferJob { - id: i32, - remote: String, - path: PathBuf, - show_hidden: bool, - is_remote: bool, - files: Vec, - file_num: i32, + pub id: i32, + pub remote: String, + pub path: PathBuf, + pub show_hidden: bool, + pub is_remote: bool, + pub is_last_job: bool, + pub file_num: i32, + pub files: Vec, + file: Option, total_size: u64, finished_size: u64, @@ -707,6 +709,9 @@ pub async fn handle_read_jobs( ) -> ResultType<()> { let mut finished = Vec::new(); for job in jobs.iter_mut() { + if job.is_last_job { + continue; + } match job.read(stream).await { Err(err) => { stream diff --git a/src/client.rs b/src/client.rs index d31c43266..e191df80f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1326,7 +1326,8 @@ pub enum Data { ToggleClipboardFile, NewRDP, SetConfirmOverrideFile((i32, i32, bool, bool, bool)), - ResumeTransfer, + AddJob((i32, String, String, i32, bool, bool)), + ResumeJob((i32, bool)), } #[derive(Clone)] diff --git a/src/client/file_trait.rs b/src/client/file_trait.rs index fd0b2a694..be790b035 100644 --- a/src/client/file_trait.rs +++ b/src/client/file_trait.rs @@ -86,4 +86,20 @@ pub trait FileManager: Interface { ) { self.send(Data::SendFiles((id, path, to, file_num, include_hidden, is_remote))); } + + fn add_job( + &mut self, + id: i32, + path: String, + to: String, + file_num: i32, + include_hidden: bool, + is_remote: bool, + ) { + self.send(Data::AddJob((id, path, to, file_num, include_hidden, is_remote))); + } + + fn resume_job(&mut self, id: i32, is_remote: bool){ + self.send(Data::ResumeJob((id,is_remote))); + } } diff --git a/src/ui/file_transfer.css b/src/ui/file_transfer.css index d1e1a4072..9b45ea2b7 100644 --- a/src/ui/file_transfer.css +++ b/src/ui/file_transfer.css @@ -220,6 +220,10 @@ table.job-table tr.is_remote svg { transform: scale(-1, 1); } +table.job-table tr.is_remote div.svg_continue svg { + transform: scale(1, 1); +} + table.job-table tr td div.text { width: *; overflow-x: hidden; diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index bcf59b388..7d50bdf7a 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -19,6 +19,7 @@ var svg_refresh = ; var svg_cancel = ; +var svg_continue = ; var svg_computer = @@ -100,6 +101,13 @@ class JobTable: Reactor.Component { refreshDir(is_remote); } + event click $(svg.continue) (_, me) { + var job = this.jobs[me.parent.parent.parent.index]; + var id = job.id; + this.continueJob(id); + this.update(); + } + function clearAllJobs() { this.jobs = []; this.job_map = {}; @@ -123,7 +131,9 @@ class JobTable: Reactor.Component { this.jobs.push({ type: "transfer", id: id, path: path, to: to, include_hidden: show_hidden, - is_remote: is_remote }); + is_remote: is_remote, + is_last: false + }); this.job_map[id] = this.jobs[this.jobs.length - 1]; handler.send_files(id, path, to, 0, show_hidden, is_remote); var self = this; @@ -134,14 +144,23 @@ class JobTable: Reactor.Component { var job = { type: "transfer", id: id, path: path, to: to, include_hidden: show_hidden, - is_remote: is_remote }; + is_remote: is_remote, is_last: true, file_num: file_num }; this.jobs.push(job); this.job_map[id] = this.jobs[this.jobs.length - 1]; jobIdCounter = id + 1; - handler.send_files(id, path, to, file_num, show_hidden, is_remote); + handler.add_job(id, path, to, file_num, show_hidden, is_remote); stdout.println(JSON.stringify(job)); } + function continueJob(id) { + var job = this.job_map[id]; + if (job == null || !job.is_last){ + return; + } + job.is_last = false; + handler.resume_job(job.id, job.is_remote); + } + function addDelDir(path, is_remote) { var id = jobIdCounter; jobIdCounter += 1; @@ -276,6 +295,9 @@ class JobTable: Reactor.Component {
{job.path}
{this.getStatus(job)}
+
+ {svg_continue} +
{svg_cancel} ; } @@ -673,7 +695,7 @@ handler.clearAllJobs = function() { } handler.addJob = function (id, path, to, file_num, show_hidden, is_remote) { - stdout.println("restore job: " + is_remote); + // stdout.println("restore job: " + is_remote); file_transfer.job_table.addJob(id,path,to,file_num,show_hidden,is_remote); } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 89ad6b9e3..34db3d507 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -22,7 +22,7 @@ use clipboard::{ use enigo::{self, Enigo, KeyboardControllable}; use hbb_common::fs::{ can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm, - DigestCheckResult, RemoveJobMeta, + DigestCheckResult, RemoveJobMeta, get_job, }; use hbb_common::log::log; use hbb_common::{ @@ -205,6 +205,8 @@ impl sciter::EventHandler for Handler { fn set_no_confirm(i32); fn cancel_job(i32); fn send_files(i32, String, String, i32, bool, bool); + fn add_job(i32, String, String, i32, bool, bool); + fn resume_job(i32, bool); fn get_platform(bool); fn get_path_sep(bool); fn get_icon_path(i32, String); @@ -1652,6 +1654,69 @@ impl Remote { } } } + Data::AddJob((id, path, to, file_num, include_hidden, is_remote)) => { + let od = can_enable_overwrite_detection(self.handler.lc.read().unwrap().version); + if is_remote { + log::debug!("new write waiting job {}, write to {} from remote {}", id, to, path); + let mut job = fs::TransferJob::new_write( + id, + path.clone(), + to, + file_num, + include_hidden, + is_remote, + Vec::new(), + od, + ); + job.is_last_job = true; + self.write_jobs.push(job); + } else { + match fs::TransferJob::new_read( + id, + to.clone(), + path.clone(), + file_num, + include_hidden, + is_remote, + od, + ) { + Err(err) => { + self.handle_job_status(id, -1, Some(err.to_string())); + } + Ok(mut job) => { + log::debug!( + "new read waiting job {}, read {} to remote {}, {} files", + id, + path, + to, + job.files().len() + ); + let m = make_fd(job.id(), job.files(), true); + self.handler.call("updateFolderFiles", &make_args!(m)); + job.is_last_job = true; + self.read_jobs.push(job); + self.timer = time::interval(MILLI1); + } + } + } + } + Data::ResumeJob((id, is_remote)) => { + if is_remote { + if let Some(job) = get_job(id, &mut self.write_jobs) { + job.is_last_job = false; + allow_err!( + peer.send(&fs::new_send(id, job.remote.clone(), job.file_num, job.show_hidden)) + .await + ); + } + } else { + if let Some(job) = get_job(id, &mut self.read_jobs) { + job.is_last_job = false; + allow_err!(peer.send(&fs::new_receive(id, job.path.to_string_lossy().to_string(), + job.file_num, job.files.clone())).await); + } + } + } Data::SetNoConfirm(id) => { if let Some(job) = self.remove_jobs.get_mut(&id) { job.no_confirm = true;