WIP file transfer

This commit is contained in:
csf 2022-09-05 10:27:33 +08:00
parent f385127f3b
commit 09b769d92f
7 changed files with 196 additions and 191 deletions

View File

@ -2,6 +2,7 @@ use crate::client::{
Client, CodecFormat, FileManager, MediaData, MediaSender, QualityStatus, MILLI1, SEC30,
SERVER_CLIPBOARD_ENABLED, SERVER_FILE_TRANSFER_ENABLED, SERVER_KEYBOARD_ENABLED,
};
use crate::common;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::common::{check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL};
@ -21,7 +22,7 @@ use hbb_common::tokio::{
sync::mpsc,
time::{self, Duration, Instant, Interval},
};
use hbb_common::{allow_err, message_proto::*};
use hbb_common::{allow_err, message_proto::*, sleep};
use hbb_common::{fs, log, Stream};
use std::collections::HashMap;
@ -270,7 +271,6 @@ impl<T: InvokeUi> Remote<T> {
// TODO
fn load_last_jobs(&mut self) {
log::info!("start load last jobs");
self.handler.clear_all_jobs();
let pc = self.handler.load_config();
if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() {
@ -280,33 +280,17 @@ impl<T: InvokeUi> Remote<T> {
// TODO: can add a confirm dialog
let mut cnt = 1;
for job_str in pc.transfer.read_jobs.iter() {
let job: Result<TransferJobMeta, serde_json::Error> = serde_json::from_str(&job_str);
if let Ok(job) = job {
self.handler.add_job(
cnt,
job.to.clone(),
job.remote.clone(),
job.file_num,
job.show_hidden,
false,
);
if !job_str.is_empty() {
self.handler.load_last_job(cnt, job_str);
cnt += 1;
println!("restore read_job: {:?}", job);
log::info!("restore read_job: {:?}", job_str);
}
}
for job_str in pc.transfer.write_jobs.iter() {
let job: Result<TransferJobMeta, serde_json::Error> = serde_json::from_str(&job_str);
if let Ok(job) = job {
self.handler.add_job(
cnt,
job.remote.clone(),
job.to.clone(),
job.file_num,
job.show_hidden,
true,
);
if !job_str.is_empty() {
self.handler.load_last_job(cnt, job_str);
cnt += 1;
println!("restore write_job: {:?}", job);
log::info!("restore write_job: {:?}", job_str);
}
}
self.handler.update_transfer_list();
@ -373,8 +357,7 @@ impl<T: InvokeUi> Remote<T> {
to,
job.files().len()
);
// let m = make_fd(job.id(), job.files(), true);
// self.handler.call("updateFolderFiles", &make_args!(m)); // TODO
self.handler.update_folder_files(job.id(), job.files(), path,!is_remote, true);
#[cfg(not(windows))]
let files = job.files().clone();
#[cfg(windows)]
@ -433,8 +416,7 @@ impl<T: InvokeUi> Remote<T> {
to,
job.files().len()
);
// let m = make_fd(job.id(), job.files(), true);
// self.handler.call("updateFolderFiles", &make_args!(m));
self.handler.update_folder_files(job.id(), job.files(), path,!is_remote, true);
job.is_last_job = true;
self.read_jobs.push(job);
self.timer = time::interval(MILLI1);
@ -546,8 +528,7 @@ impl<T: InvokeUi> Remote<T> {
} else {
match fs::get_recursive_files(&path, include_hidden) {
Ok(entries) => {
// let m = make_fd(id, &entries, true);
// self.handler.call("updateFolderFiles", &make_args!(m));
self.handler.update_folder_files(id, &entries, path.clone(),!is_remote, false);
self.remove_jobs
.insert(id, RemoveJob::new(entries, path, sep, is_remote));
}
@ -749,28 +730,28 @@ impl<T: InvokeUi> Remote<T> {
}
Some(login_response::Union::PeerInfo(pi)) => {
self.handler.handle_peer_info(pi);
// self.check_clipboard_file_context();
// if !(self.handler.is_file_transfer()
// || self.handler.is_port_forward()
// || !SERVER_CLIPBOARD_ENABLED.load(Ordering::SeqCst)
// || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst)
// || self.handler.lc.read().unwrap().disable_clipboard)
// {
// let txt = self.old_clipboard.lock().unwrap().clone();
// if !txt.is_empty() {
// let msg_out = crate::create_clipboard_msg(txt);
// let sender = self.sender.clone();
// tokio::spawn(async move {
// // due to clipboard service interval time
// sleep(common::CLIPBOARD_INTERVAL as f32 / 1_000.).await;
// sender.send(Data::Message(msg_out)).ok();
// });
// }
// }
self.check_clipboard_file_context();
if !(self.handler.is_file_transfer()
|| self.handler.is_port_forward()
|| !SERVER_CLIPBOARD_ENABLED.load(Ordering::SeqCst)
|| !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst)
|| self.handler.lc.read().unwrap().disable_clipboard)
{
let txt = self.old_clipboard.lock().unwrap().clone();
if !txt.is_empty() {
let msg_out = crate::create_clipboard_msg(txt);
let sender = self.sender.clone();
tokio::spawn(async move {
// due to clipboard service interval time
sleep(common::CLIPBOARD_INTERVAL as f32 / 1_000.).await;
sender.send(Data::Message(msg_out)).ok();
});
}
}
// if self.handler.is_file_transfer() {
// self.load_last_jobs().await;
// }
if self.handler.is_file_transfer() {
self.load_last_jobs();
}
}
_ => {}
},
@ -823,11 +804,7 @@ impl<T: InvokeUi> Remote<T> {
fs::transform_windows_path(&mut entries);
}
}
// 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));
self.handler.update_folder_files(fd.id, &entries, fd.path, false, fd.id > 0);
if let Some(job) = fs::get_job(fd.id, &mut self.write_jobs) {
log::info!("job set_files: {:?}", entries);
job.set_files(entries);

View File

@ -666,49 +666,3 @@ pub fn make_privacy_mode_msg(state: back_notification::PrivacyModeState) -> Mess
msg_out.set_misc(misc);
msg_out
}
pub fn make_fd_to_json(fd: FileDirectory) -> String {
use serde_json::json;
let mut fd_json = serde_json::Map::new();
fd_json.insert("id".into(), json!(fd.id));
fd_json.insert("path".into(), json!(fd.path));
let mut entries = vec![];
for entry in fd.entries {
let mut entry_map = serde_json::Map::new();
entry_map.insert("entry_type".into(), json!(entry.entry_type.value()));
entry_map.insert("name".into(), json!(entry.name));
entry_map.insert("size".into(), json!(entry.size));
entry_map.insert("modified_time".into(), json!(entry.modified_time));
entries.push(entry_map);
}
fd_json.insert("entries".into(), json!(entries));
serde_json::to_string(&fd_json).unwrap_or("".into())
}
pub fn make_fd_flutter(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> String {
let mut m = serde_json::Map::new();
m.insert("id".into(), json!(id));
let mut a = vec![];
let mut n: u64 = 0;
for entry in entries {
n += entry.size;
if only_count {
continue;
}
let mut e = serde_json::Map::new();
e.insert("name".into(), json!(entry.name.to_owned()));
let tmp = entry.entry_type.value();
e.insert("type".into(), json!(if tmp == 0 { 1 } else { tmp }));
e.insert("time".into(), json!(entry.modified_time as f64));
e.insert("size".into(), json!(entry.size as f64));
a.push(e);
}
if only_count {
m.insert("num_entries".into(), json!(entries.len() as i32));
} else {
m.insert("entries".into(), json!(a));
}
m.insert("total_size".into(), json!(n as f64));
serde_json::to_string(&m).unwrap_or("".into())
}

View File

@ -5,7 +5,10 @@ use std::{
use flutter_rust_bridge::{StreamSink, ZeroCopyBuffer};
use hbb_common::{bail, config::LocalConfig, message_proto::*, ResultType, rendezvous_proto::ConnType};
use hbb_common::{
bail, config::LocalConfig, message_proto::*, rendezvous_proto::ConnType, ResultType,
};
use serde_json::json;
use crate::ui_session_interface::{io_loop, InvokeUi, Session};
@ -85,6 +88,7 @@ impl InvokeUi for FlutterHandler {
self.push_event("permission", vec![(name, &value.to_string())]);
}
// unused in flutter
fn close_success(&self) {}
fn update_quality_status(&self, status: QualityStatus) {
@ -118,7 +122,14 @@ impl InvokeUi for FlutterHandler {
}
fn job_error(&self, id: i32, err: String, file_num: i32) {
self.push_event("job_error", vec![("id", &id.to_string()), ("err", &err)]);
self.push_event(
"job_error",
vec![
("id", &id.to_string()),
("err", &err),
("file_num", &file_num.to_string()),
],
);
}
fn job_done(&self, id: i32, file_num: i32) {
@ -128,29 +139,43 @@ impl InvokeUi for FlutterHandler {
);
}
fn clear_all_jobs(&self) {
// todo!()
// unused in flutter
fn clear_all_jobs(&self) {}
fn load_last_job(&self, _cnt: i32, job_json: &str) {
self.push_event("load_last_job", vec![("value", job_json)]);
}
fn add_job(
fn update_folder_files(
&self,
id: i32,
entries: &Vec<FileEntry>,
path: String,
to: String,
file_num: i32,
show_hidden: bool,
is_remote: bool,
is_local: bool,
only_count: bool,
) {
// todo!()
// TODO opt
if only_count {
self.push_event(
"update_folder_files",
vec![("info", &make_fd_flutter(id, entries, only_count))],
);
} else {
self.push_event(
"file_dir",
vec![
("value", &make_fd_to_json(id, path, entries)),
("is_local", "false"),
],
);
}
}
fn update_transfer_list(&self) {
// todo!()
}
// unused in flutter
fn update_transfer_list(&self) {}
fn confirm_delete_files(&self, id: i32, i: i32, name: String) {
// todo!()
}
// unused in flutter // TEST flutter
fn confirm_delete_files(&self, _id: i32, _i: i32, _name: String) {}
fn override_file_confirm(&self, id: i32, file_num: i32, to: String, is_upload: bool) {
self.push_event(
@ -176,6 +201,7 @@ impl InvokeUi for FlutterHandler {
);
}
// unused in flutter
fn adapt_size(&self) {}
fn on_rgba(&self, data: &[u8]) {
@ -283,11 +309,7 @@ pub fn session_add(id: &str, is_file_transfer: bool, is_port_forward: bool) -> R
.unwrap()
.initialize(session_id, conn_type);
if let Some(same_id_session) = SESSIONS
.write()
.unwrap()
.insert(id.to_owned(), session)
{
if let Some(same_id_session) = SESSIONS.write().unwrap().insert(id.to_owned(), session) {
same_id_session.close();
}
@ -946,30 +968,47 @@ pub fn get_session_id(id: String) -> String {
};
}
// async fn start_one_port_forward(
// handler: Session,
// port: i32,
// remote_host: String,
// remote_port: i32,
// receiver: mpsc::UnboundedReceiver<Data>,
// key: &str,
// token: &str,
// ) {
// if let Err(err) = crate::port_forward::listen(
// handler.id.clone(),
// String::new(), // TODO
// port,
// handler.clone(),
// receiver,
// key,
// token,
// handler.lc.clone(),
// remote_host,
// remote_port,
// )
// .await
// {
// handler.on_error(&format!("Failed to listen on {}: {}", port, err));
// }
// log::info!("port forward (:{}) exit", port);
// }
pub fn make_fd_to_json(id: i32, path: String, entries: &Vec<FileEntry>) -> String {
let mut fd_json = serde_json::Map::new();
fd_json.insert("id".into(), json!(id));
fd_json.insert("path".into(), json!(path));
let mut entries_out = vec![];
for entry in entries {
let mut entry_map = serde_json::Map::new();
entry_map.insert("entry_type".into(), json!(entry.entry_type.value()));
entry_map.insert("name".into(), json!(entry.name));
entry_map.insert("size".into(), json!(entry.size));
entry_map.insert("modified_time".into(), json!(entry.modified_time));
entries_out.push(entry_map);
}
fd_json.insert("entries".into(), json!(entries_out));
serde_json::to_string(&fd_json).unwrap_or("".into())
}
pub fn make_fd_flutter(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> String {
let mut m = serde_json::Map::new();
m.insert("id".into(), json!(id));
let mut a = vec![];
let mut n: u64 = 0;
for entry in entries {
n += entry.size;
if only_count {
continue;
}
let mut e = serde_json::Map::new();
e.insert("name".into(), json!(entry.name.to_owned()));
let tmp = entry.entry_type.value();
e.insert("type".into(), json!(if tmp == 0 { 1 } else { tmp }));
e.insert("time".into(), json!(entry.modified_time as f64));
e.insert("size".into(), json!(entry.size as f64));
a.push(e);
}
if only_count {
m.insert("num_entries".into(), json!(entries.len() as i32));
} else {
m.insert("entries".into(), json!(a));
}
m.insert("total_size".into(), json!(n as f64));
serde_json::to_string(&m).unwrap_or("".into())
}

View File

@ -5,16 +5,14 @@ use std::{
};
use flutter_rust_bridge::{StreamSink, SyncReturn, ZeroCopyBuffer};
use serde_json::{json, Number, Value};
use serde_json::json;
use hbb_common::ResultType;
use hbb_common::{
config::{self, Config, LocalConfig, PeerConfig, ONLINE},
config::{self, LocalConfig, PeerConfig, ONLINE},
fs, log,
};
use hbb_common::{password_security, ResultType};
use crate::{client::file_trait::FileManager, flutter::{session_add, session_start_}};
use crate::common::make_fd_to_json;
use crate::flutter::connection_manager::{self, get_clients_length, get_clients_state};
use crate::flutter::{self, SESSIONS};
use crate::start_server;
@ -30,6 +28,10 @@ use crate::ui_interface::{
set_peer_option, set_permanent_password, set_socks, store_fav, test_if_valid_server,
update_temporary_password, using_public_server,
};
use crate::{
client::file_trait::FileManager,
flutter::{make_fd_to_json, session_add, session_start_},
};
fn initialize(app_dir: &str) {
*config::APP_DIR.write().unwrap() = app_dir.to_owned();
@ -110,7 +112,11 @@ pub fn host_stop_system_key_propagate(stopped: bool) {
// FIXME: -> ResultType<()> cannot be parsed by frb_codegen
// thread 'main' panicked at 'Failed to parse function output type `ResultType<()>`', $HOME\.cargo\git\checkouts\flutter_rust_bridge-ddba876d3ebb2a1e\e5adce5\frb_codegen\src\parser\mod.rs:151:25
pub fn session_add_sync(id: String, is_file_transfer: bool, is_port_forward: bool) -> SyncReturn<String> {
pub fn session_add_sync(
id: String,
is_file_transfer: bool,
is_port_forward: bool,
) -> SyncReturn<String> {
if let Err(e) = session_add(&id, is_file_transfer, is_port_forward) {
SyncReturn(format!("Failed to add session with id {}, {}", &id, e))
} else {
@ -346,10 +352,8 @@ pub fn session_create_dir(id: String, act_id: i32, path: String, is_remote: bool
}
pub fn session_read_local_dir_sync(id: String, path: String, show_hidden: bool) -> String {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
if let Ok(fd) = fs::read_dir(&fs::get_path(&path), show_hidden) {
return make_fd_to_json(fd);
}
if let Ok(fd) = fs::read_dir(&fs::get_path(&path), show_hidden) {
return make_fd_to_json(fd.id, path, &fd.entries);
}
"".to_string()
}

View File

@ -695,7 +695,7 @@ handler.clearAllJobs = function() {
file_transfer.job_table.clearAllJobs();
}
handler.addJob = function (id, path, to, file_num, show_hidden, is_remote) {
handler.addJob = function (id, path, to, file_num, show_hidden, is_remote) { // load last job
// stdout.println("restore job: " + is_remote);
file_transfer.job_table.addJob(id,path,to,file_num,show_hidden,is_remote);
}

View File

@ -23,7 +23,9 @@ use clipboard::{
get_rx_clip_client, server_clip_file,
};
use hbb_common::{allow_err, log, message_proto::*, rendezvous_proto::ConnType};
use hbb_common::{
allow_err, fs::TransferJobMeta, log, message_proto::*, rendezvous_proto::ConnType,
};
#[cfg(windows)]
use crate::clipboard_file::*;
@ -43,7 +45,6 @@ static mut IS_ALT_GR: bool = false;
/// SciterHandler
/// * element
/// * thread TODO check if flutter need
/// * close_state for file path when close
#[derive(Clone, Default)]
pub struct SciterHandler {
@ -155,16 +156,36 @@ impl InvokeUi for SciterHandler {
self.call("clearAllJobs", &make_args!());
}
fn add_job(
fn load_last_job(&self, cnt: i32, job_json: &str) {
let job: Result<TransferJobMeta, serde_json::Error> = serde_json::from_str(job_json);
if let Ok(job) = job {
let path;
let to;
if job.is_remote {
path = job.remote.clone();
to = job.to.clone();
} else {
path = job.to.clone();
to = job.remote.clone();
}
self.call(
"addJob",
&make_args!(cnt, path, to, job.file_num, job.show_hidden, job.is_remote),
);
}
}
fn update_folder_files(
&self,
id: i32,
entries: &Vec<FileEntry>,
path: String,
to: String,
file_num: i32,
show_hidden: bool,
is_remote: bool,
_is_local: bool,
only_count: bool,
) {
todo!()
let mut m = make_fd(id, entries, only_count);
m.set_item("path", path);
self.call("updateFolderFiles", &make_args!(m));
}
fn update_transfer_list(&self) {
@ -686,15 +707,18 @@ impl SciterSession {
}
pub fn make_fd(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> Value {
log::debug!("make_fd");
let mut m = Value::map();
m.set_item("id", id);
let mut a = Value::array(0);
let mut n: u64 = 0;
for entry in entries {
log::debug!("for");
n += entry.size;
if only_count {
continue;
}
log::debug!("for1");
let mut e = Value::map();
e.set_item("name", entry.name.to_owned());
let tmp = entry.entry_type.value();
@ -703,11 +727,11 @@ pub fn make_fd(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> Value {
e.set_item("size", entry.size as f64);
a.push(e);
}
if only_count {
m.set_item("num_entries", entries.len() as i32);
} else {
if !only_count {
m.set_item("entries", a);
}
m.set_item("num_entries", entries.len() as i32);
m.set_item("total_size", n as f64);
log::debug!("make_fd end");
m
}

View File

@ -1,11 +1,11 @@
use crate::client::io_loop::Remote;
use crate::client::{
check_if_retry, handle_hash, handle_login_from_ui, handle_test_delay,
input_os_password, load_config, send_mouse, start_video_audio_threads, FileManager, Key,
LoginConfigHandler, QualityStatus, KEY_MAP, SERVER_KEYBOARD_ENABLED,
};
#[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::client::get_key_state;
use crate::client::io_loop::Remote;
use crate::client::{
check_if_retry, handle_hash, handle_login_from_ui, handle_test_delay, input_os_password,
load_config, send_mouse, start_video_audio_threads, FileManager, Key, LoginConfigHandler,
QualityStatus, KEY_MAP, SERVER_KEYBOARD_ENABLED,
};
use crate::common;
use crate::{client::Data, client::Interface};
use async_trait::async_trait;
@ -19,7 +19,7 @@ use hbb_common::{allow_err, message_proto::*};
use hbb_common::{fs, get_version_number, log, Stream};
use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
use std::sync::atomic::{AtomicUsize, Ordering, AtomicBool};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, RwLock};
/// IS_IN KEYBOARD_HOOKED sciter only
@ -556,18 +556,17 @@ pub trait InvokeUi: Send + Sync + Clone + 'static + Sized + Default {
fn job_error(&self, id: i32, err: String, file_num: i32);
fn job_done(&self, id: i32, file_num: i32);
fn clear_all_jobs(&self);
fn add_job(
&self,
id: i32,
path: String,
to: String,
file_num: i32,
show_hidden: bool,
is_remote: bool,
);
fn new_message(&self, msg: String);
fn update_transfer_list(&self);
// fn update_folder_files(&self); // TODO flutter with file_dir and update_folder_files
fn load_last_job(&self, cnt: i32, job_json: &str);
fn update_folder_files(
&self,
id: i32,
entries: &Vec<FileEntry>,
path: String,
is_local: bool,
only_count: bool,
);
fn confirm_delete_files(&self, id: i32, i: i32, name: String);
fn override_file_confirm(&self, id: i32, file_num: i32, to: String, is_upload: bool);
fn update_block_input_state(&self, on: bool);
@ -604,11 +603,19 @@ impl<T: InvokeUi> Interface for Session<T> {
}
fn is_file_transfer(&self) -> bool {
self.lc.read().unwrap().conn_type.eq(&ConnType::FILE_TRANSFER)
self.lc
.read()
.unwrap()
.conn_type
.eq(&ConnType::FILE_TRANSFER)
}
fn is_port_forward(&self) -> bool {
self.lc.read().unwrap().conn_type.eq(&ConnType::PORT_FORWARD)
self.lc
.read()
.unwrap()
.conn_type
.eq(&ConnType::PORT_FORWARD)
}
fn is_rdp(&self) -> bool {