mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-16 17:51:04 +03:00
feat: remote printer (#11231)
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -46,6 +46,7 @@ use std::{
|
||||
collections::HashMap,
|
||||
ffi::c_void,
|
||||
num::NonZeroI64,
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc, RwLock,
|
||||
@@ -549,13 +550,20 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
allow_err!(peer.send(&msg).await);
|
||||
}
|
||||
Data::SendFiles((id, path, to, file_num, include_hidden, is_remote)) => {
|
||||
Data::SendFiles((id, r#type, 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);
|
||||
let to = match r#type {
|
||||
fs::JobType::Generic => fs::DataSource::FilePath(PathBuf::from(&to)),
|
||||
fs::JobType::Printer => {
|
||||
fs::DataSource::MemoryCursor(std::io::Cursor::new(Vec::new()))
|
||||
}
|
||||
};
|
||||
self.write_jobs.push(fs::TransferJob::new_write(
|
||||
id,
|
||||
r#type,
|
||||
path.clone(),
|
||||
to,
|
||||
file_num,
|
||||
@@ -565,14 +573,15 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
od,
|
||||
));
|
||||
allow_err!(
|
||||
peer.send(&fs::new_send(id, path, file_num, include_hidden))
|
||||
peer.send(&fs::new_send(id, r#type, path, file_num, include_hidden))
|
||||
.await
|
||||
);
|
||||
} else {
|
||||
match fs::TransferJob::new_read(
|
||||
id,
|
||||
r#type,
|
||||
to.clone(),
|
||||
path.clone(),
|
||||
fs::DataSource::FilePath(PathBuf::from(&path)),
|
||||
file_num,
|
||||
include_hidden,
|
||||
is_remote,
|
||||
@@ -616,7 +625,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Data::AddJob((id, path, to, file_num, include_hidden, is_remote)) => {
|
||||
Data::AddJob((id, r#type, 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!(
|
||||
@@ -627,8 +636,9 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
);
|
||||
let mut job = fs::TransferJob::new_write(
|
||||
id,
|
||||
r#type,
|
||||
path.clone(),
|
||||
to,
|
||||
fs::DataSource::FilePath(PathBuf::from(&to)),
|
||||
file_num,
|
||||
include_hidden,
|
||||
is_remote,
|
||||
@@ -640,8 +650,9 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
} else {
|
||||
match fs::TransferJob::new_read(
|
||||
id,
|
||||
r#type,
|
||||
to.clone(),
|
||||
path.clone(),
|
||||
fs::DataSource::FilePath(PathBuf::from(&path)),
|
||||
file_num,
|
||||
include_hidden,
|
||||
is_remote,
|
||||
@@ -679,6 +690,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
allow_err!(
|
||||
peer.send(&fs::new_send(
|
||||
id,
|
||||
fs::JobType::Generic,
|
||||
job.remote.clone(),
|
||||
job.file_num,
|
||||
job.show_hidden
|
||||
@@ -688,17 +700,25 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
} 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(),
|
||||
job.total_size(),
|
||||
))
|
||||
.await
|
||||
);
|
||||
match &job.data_source {
|
||||
fs::DataSource::FilePath(p) => {
|
||||
job.is_last_job = false;
|
||||
allow_err!(
|
||||
peer.send(&fs::new_receive(
|
||||
id,
|
||||
p.to_string_lossy().to_string(),
|
||||
job.file_num,
|
||||
job.files.clone(),
|
||||
job.total_size(),
|
||||
))
|
||||
.await
|
||||
);
|
||||
}
|
||||
fs::DataSource::MemoryCursor(_) => {
|
||||
// unreachable!()
|
||||
log::error!("Resume job with memory cursor");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -803,11 +823,10 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
});
|
||||
msg_out.set_file_action(file_action);
|
||||
allow_err!(peer.send(&msg_out).await);
|
||||
if let Some(job) = fs::get_job(id, &mut self.write_jobs) {
|
||||
if let Some(job) = fs::remove_job(id, &mut self.write_jobs) {
|
||||
job.remove_download_file();
|
||||
fs::remove_job(id, &mut self.write_jobs);
|
||||
}
|
||||
fs::remove_job(id, &mut self.read_jobs);
|
||||
let _ = fs::remove_job(id, &mut self.read_jobs);
|
||||
self.remove_jobs.remove(&id);
|
||||
}
|
||||
Data::RemoveDir((id, path)) => {
|
||||
@@ -1402,92 +1421,105 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
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(if overwrite {
|
||||
file_transfer_send_confirm_request::Union::OffsetBlk(0)
|
||||
} else {
|
||||
file_transfer_send_confirm_request::Union::Skip(
|
||||
true,
|
||||
)
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
job.confirm(&req);
|
||||
let msg = new_send_confirm(req);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
} else {
|
||||
self.handler.override_file_confirm(
|
||||
digest.id,
|
||||
digest.file_num,
|
||||
read_path,
|
||||
true,
|
||||
digest.is_identical,
|
||||
);
|
||||
if let fs::DataSource::FilePath(p) = &job.data_source {
|
||||
let read_path =
|
||||
get_string(&fs::TransferJob::join(p, &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(if overwrite {
|
||||
file_transfer_send_confirm_request::Union::OffsetBlk(0)
|
||||
} else {
|
||||
file_transfer_send_confirm_request::Union::Skip(
|
||||
true,
|
||||
)
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
job.confirm(&req);
|
||||
let msg = new_send_confirm(req);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
} else {
|
||||
self.handler.override_file_confirm(
|
||||
digest.id,
|
||||
digest.file_num,
|
||||
read_path,
|
||||
true,
|
||||
digest.is_identical,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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 req = FileTransferSendConfirmRequest {
|
||||
if let fs::DataSource::FilePath(p) = &job.data_source {
|
||||
let write_path =
|
||||
get_string(&fs::TransferJob::join(p, &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 req = FileTransferSendConfirmRequest {
|
||||
id: digest.id,
|
||||
file_num: digest.file_num,
|
||||
union: Some(file_transfer_send_confirm_request::Union::Skip(true)),
|
||||
..Default::default()
|
||||
};
|
||||
job.confirm(&req);
|
||||
let msg = new_send_confirm(req);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
}
|
||||
DigestCheckResult::NeedConfirm(digest) => {
|
||||
if let Some(overwrite) = overwrite_strategy {
|
||||
let req = FileTransferSendConfirmRequest {
|
||||
id: digest.id,
|
||||
file_num: digest.file_num,
|
||||
union: Some(if overwrite {
|
||||
file_transfer_send_confirm_request::Union::OffsetBlk(0)
|
||||
} else {
|
||||
file_transfer_send_confirm_request::Union::Skip(true)
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
job.confirm(&req);
|
||||
let msg = new_send_confirm(req);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
} else {
|
||||
self.handler.override_file_confirm(
|
||||
digest.id,
|
||||
digest.file_num,
|
||||
write_path,
|
||||
false,
|
||||
digest.is_identical,
|
||||
);
|
||||
}
|
||||
}
|
||||
DigestCheckResult::NoSuchFile => {
|
||||
let req = FileTransferSendConfirmRequest {
|
||||
DigestCheckResult::NeedConfirm(digest) => {
|
||||
if let Some(overwrite) = overwrite_strategy
|
||||
{
|
||||
let req =
|
||||
FileTransferSendConfirmRequest {
|
||||
id: digest.id,
|
||||
file_num: digest.file_num,
|
||||
union: Some(if overwrite {
|
||||
file_transfer_send_confirm_request::Union::OffsetBlk(0)
|
||||
} else {
|
||||
file_transfer_send_confirm_request::Union::Skip(true)
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
job.confirm(&req);
|
||||
let msg = new_send_confirm(req);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
} else {
|
||||
self.handler.override_file_confirm(
|
||||
digest.id,
|
||||
digest.file_num,
|
||||
write_path,
|
||||
false,
|
||||
digest.is_identical,
|
||||
);
|
||||
}
|
||||
}
|
||||
DigestCheckResult::NoSuchFile => {
|
||||
let req = FileTransferSendConfirmRequest {
|
||||
id: digest.id,
|
||||
file_num: digest.file_num,
|
||||
union: Some(file_transfer_send_confirm_request::Union::OffsetBlk(0)),
|
||||
..Default::default()
|
||||
};
|
||||
job.confirm(&req);
|
||||
let msg = new_send_confirm(req);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
job.confirm(&req);
|
||||
let msg = new_send_confirm(req);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
println!("error receiving digest: {}", err);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
println!("error receiving digest: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1499,23 +1531,56 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
if let Err(_err) = job.write(block).await {
|
||||
// to-do: add "skip" for writing job
|
||||
}
|
||||
self.update_jobs_status();
|
||||
if job.r#type == fs::JobType::Generic {
|
||||
self.update_jobs_status();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(file_response::Union::Done(d)) => {
|
||||
let mut err: Option<String> = None;
|
||||
if let Some(job) = fs::get_job(d.id, &mut self.write_jobs) {
|
||||
let mut job_type = fs::JobType::Generic;
|
||||
let mut printer_data = None;
|
||||
if let Some(job) = fs::remove_job(d.id, &mut self.write_jobs) {
|
||||
job.modify_time();
|
||||
err = job.job_error();
|
||||
fs::remove_job(d.id, &mut self.write_jobs);
|
||||
job_type = job.r#type;
|
||||
printer_data = job.get_buf_data();
|
||||
}
|
||||
match job_type {
|
||||
fs::JobType::Generic => {
|
||||
self.handle_job_status(d.id, d.file_num, err);
|
||||
}
|
||||
fs::JobType::Printer =>
|
||||
{
|
||||
#[cfg(target_os = "windows")]
|
||||
if let Some(data) = printer_data {
|
||||
let printer_name = self
|
||||
.handler
|
||||
.printer_names
|
||||
.write()
|
||||
.unwrap()
|
||||
.remove(&d.id);
|
||||
crate::platform::send_raw_data_to_printer(
|
||||
printer_name,
|
||||
data,
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.handle_job_status(d.id, d.file_num, err);
|
||||
}
|
||||
Some(file_response::Union::Error(e)) => {
|
||||
if let Some(_job) = fs::get_job(e.id, &mut self.write_jobs) {
|
||||
fs::remove_job(e.id, &mut self.write_jobs);
|
||||
let job_type = fs::remove_job(e.id, &mut self.write_jobs)
|
||||
.map(|j| j.r#type)
|
||||
.unwrap_or(fs::JobType::Generic);
|
||||
match job_type {
|
||||
fs::JobType::Generic => {
|
||||
self.handle_job_status(e.id, e.file_num, Some(e.error));
|
||||
}
|
||||
fs::JobType::Printer => {
|
||||
log::error!("Printer job error: {}", e.error);
|
||||
}
|
||||
}
|
||||
self.handle_job_status(e.id, e.file_num, Some(e.error));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -1739,6 +1804,41 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
}
|
||||
Some(message::Union::FileAction(action)) => match action.union {
|
||||
Some(file_action::Union::Send(_s)) => match _s.file_type.enum_value() {
|
||||
#[cfg(target_os = "windows")]
|
||||
Ok(file_transfer_send_request::FileType::Printer) => {
|
||||
#[cfg(feature = "flutter")]
|
||||
let action = LocalConfig::get_option(
|
||||
config::keys::OPTION_PRINTER_INCOMING_JOB_ACTION,
|
||||
);
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
let action = "";
|
||||
if action == "dismiss" {
|
||||
// Just ignore the incoming print job.
|
||||
} else {
|
||||
let id = fs::get_next_job_id();
|
||||
#[cfg(feature = "flutter")]
|
||||
let allow_auto_print = LocalConfig::get_bool_option(
|
||||
config::keys::OPTION_PRINTER_ALLOW_AUTO_PRINT,
|
||||
);
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
let allow_auto_print = false;
|
||||
if allow_auto_print {
|
||||
let printer_name = if action == "" {
|
||||
"".to_string()
|
||||
} else {
|
||||
LocalConfig::get_option(
|
||||
config::keys::OPTION_PRINTER_SELECTED_NAME,
|
||||
)
|
||||
};
|
||||
self.handler.printer_response(id, _s.path, printer_name);
|
||||
} else {
|
||||
self.handler.printer_request(id, _s.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Some(file_action::Union::SendConfirm(c)) => {
|
||||
if let Some(job) = fs::get_job(c.id, &mut self.read_jobs) {
|
||||
job.confirm(&c);
|
||||
@@ -2004,7 +2104,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
async fn handle_cliprdr_msg(
|
||||
&mut self,
|
||||
clip: hbb_common::message_proto::Cliprdr,
|
||||
peer: &mut Stream,
|
||||
_peer: &mut Stream,
|
||||
) {
|
||||
log::debug!("handling cliprdr msg from server peer");
|
||||
#[cfg(feature = "flutter")]
|
||||
@@ -2074,7 +2174,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
|
||||
if let Some(msg) = out_msg {
|
||||
allow_err!(peer.send(&msg).await);
|
||||
allow_err!(_peer.send(&msg).await);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user