mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
feat: rust connection implementation
This commit is contained in:
@@ -5,7 +5,7 @@ use std::{
|
||||
|
||||
use hbb_common::{
|
||||
log,
|
||||
message_proto::{video_frame, VideoFrame},
|
||||
message_proto::{video_frame, VideoFrame, Message, VoiceCallRequest, VoiceCallResponse}, get_time,
|
||||
};
|
||||
|
||||
const MAX_LATENCY: i64 = 500;
|
||||
@@ -115,3 +115,24 @@ pub struct QualityStatus {
|
||||
pub target_bitrate: Option<i32>,
|
||||
pub codec_format: Option<CodecFormat>,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_voice_call_request(is_connect: bool) -> Message {
|
||||
let mut req = VoiceCallRequest::new();
|
||||
req.is_connect = is_connect;
|
||||
req.req_timestamp = get_time();
|
||||
let mut msg = Message::new();
|
||||
msg.set_voice_call_request(req);
|
||||
msg
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_voice_call_response(request_timestamp: i64, accepted: bool) -> Message {
|
||||
let mut resp = VoiceCallResponse::new();
|
||||
resp.accepted = accepted;
|
||||
resp.req_timestamp = request_timestamp;
|
||||
resp.ack_timestamp = get_time();
|
||||
let mut msg = Message::new();
|
||||
msg.set_voice_call_response(resp);
|
||||
msg
|
||||
}
|
||||
@@ -1,38 +1,40 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::num::NonZeroI64;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[cfg(windows)]
|
||||
use clipboard::{cliprdr::CliprdrClientContext, ContextSend};
|
||||
use hbb_common::{allow_err, message_proto::*, sleep, get_time};
|
||||
use hbb_common::{fs, log, Stream};
|
||||
use hbb_common::config::{PeerConfig, TransferSerde};
|
||||
use hbb_common::fs::{
|
||||
can_enable_overwrite_detection, DigestCheckResult, get_job, get_string, new_send_confirm,
|
||||
can_enable_overwrite_detection, get_job, get_string, new_send_confirm, DigestCheckResult,
|
||||
RemoveJobMeta,
|
||||
};
|
||||
use hbb_common::message_proto::permission_info::Permission;
|
||||
use hbb_common::protobuf::Message as _;
|
||||
use hbb_common::rendezvous_proto::ConnType;
|
||||
use hbb_common::tokio::sync::mpsc::error::TryRecvError;
|
||||
#[cfg(windows)]
|
||||
use hbb_common::tokio::sync::Mutex as TokioMutex;
|
||||
use hbb_common::tokio::{
|
||||
self,
|
||||
sync::mpsc,
|
||||
time::{self, Duration, Instant, Interval},
|
||||
};
|
||||
use hbb_common::tokio::sync::mpsc::error::TryRecvError;
|
||||
#[cfg(windows)]
|
||||
use hbb_common::tokio::sync::Mutex as TokioMutex;
|
||||
use hbb_common::{allow_err, get_time, message_proto::*, sleep};
|
||||
use hbb_common::{fs, log, Stream};
|
||||
|
||||
use crate::{audio_service, CLIENT_SERVER, common, ConnInner};
|
||||
use crate::{client::Data, client::Interface};
|
||||
use crate::client::{
|
||||
Client, CodecFormat, LoginConfigHandler, MediaData, MediaSender, MILLI1, QualityStatus, SEC30,
|
||||
SERVER_CLIPBOARD_ENABLED, SERVER_FILE_TRANSFER_ENABLED, SERVER_KEYBOARD_ENABLED,
|
||||
new_voice_call_request, Client, CodecFormat, LoginConfigHandler, MediaData, MediaSender,
|
||||
QualityStatus, MILLI1, SEC30, SERVER_CLIPBOARD_ENABLED, SERVER_FILE_TRANSFER_ENABLED,
|
||||
SERVER_KEYBOARD_ENABLED,
|
||||
};
|
||||
use crate::common::{get_default_sound_input, set_sound_input};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::common::{check_clipboard, CLIPBOARD_INTERVAL, ClipboardContext, update_clipboard};
|
||||
use crate::common::{check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL};
|
||||
use crate::common::{get_default_sound_input, set_sound_input};
|
||||
use crate::ui_session_interface::{InvokeUiSession, Session};
|
||||
use crate::{audio_service, common, ConnInner, CLIENT_SERVER};
|
||||
use crate::{client::Data, client::Interface};
|
||||
|
||||
pub struct Remote<T: InvokeUiSession> {
|
||||
handler: Session<T>,
|
||||
@@ -41,7 +43,8 @@ pub struct Remote<T: InvokeUiSession> {
|
||||
receiver: mpsc::UnboundedReceiver<Data>,
|
||||
sender: mpsc::UnboundedSender<Data>,
|
||||
// Stop sending local audio to remote client.
|
||||
stop_local_audio_sender: Option<std::sync::mpsc::Sender<()>>,
|
||||
stop_voice_call_sender: Option<std::sync::mpsc::Sender<()>>,
|
||||
voice_call_request_timestamp: Option<NonZeroI64>,
|
||||
old_clipboard: Arc<Mutex<String>>,
|
||||
read_jobs: Vec<fs::TransferJob>,
|
||||
write_jobs: Vec<fs::TransferJob>,
|
||||
@@ -83,7 +86,8 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
data_count: Arc::new(AtomicUsize::new(0)),
|
||||
frame_count,
|
||||
video_format: CodecFormat::Unknown,
|
||||
stop_local_audio_sender: None,
|
||||
stop_voice_call_sender: None,
|
||||
voice_call_request_timestamp: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +221,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
log::debug!("Exit io_loop of id={}", self.handler.id);
|
||||
// Stop client audio server.
|
||||
if let Some(s) = self.stop_local_audio_sender.take() {
|
||||
if let Some(s) = self.stop_voice_call_sender.take() {
|
||||
s.send(()).ok();
|
||||
}
|
||||
}
|
||||
@@ -261,8 +265,15 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
}
|
||||
|
||||
// Start a local audio recorder, records audio and send to remote
|
||||
fn start_client_audio(&mut self) -> Option<std::sync::mpsc::Sender<()>> {
|
||||
fn stop_voice_call(&mut self) {
|
||||
let voice_call_sender = std::mem::replace(&mut self.stop_voice_call_sender, None);
|
||||
if let Some(stopper) = voice_call_sender {
|
||||
let _ = stopper.send(());
|
||||
}
|
||||
}
|
||||
|
||||
// Start a voice call recorder, records audio and send to remote
|
||||
fn start_voice_call(&mut self) -> Option<std::sync::mpsc::Sender<()>> {
|
||||
if self.handler.is_file_transfer() || self.handler.is_port_forward() {
|
||||
return None;
|
||||
}
|
||||
@@ -731,19 +742,17 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
allow_err!(peer.send(&msg).await);
|
||||
}
|
||||
Data::NewVoiceCall => {
|
||||
let mut request = VoiceCallRequest::new();
|
||||
request.is_connect = true;
|
||||
request.req_timestamp = get_time();
|
||||
let mut msg = Message::new();
|
||||
msg.set_voice_call_request(request);
|
||||
let msg = new_voice_call_request(true);
|
||||
// Save the voice call request timestamp for the further validation.
|
||||
self.voice_call_request_timestamp = Some(
|
||||
NonZeroI64::new(msg.voice_call_request().req_timestamp)
|
||||
.unwrap_or(NonZeroI64::new(get_time()).unwrap()),
|
||||
);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
}
|
||||
Data::CloseVoiceCall => {
|
||||
let mut request = VoiceCallRequest::new();
|
||||
request.is_connect = false;
|
||||
request.req_timestamp = get_time();
|
||||
let mut msg = Message::new();
|
||||
msg.set_voice_call_request(request);
|
||||
self.stop_voice_call();
|
||||
let msg = new_voice_call_request(false);
|
||||
allow_err!(peer.send(&msg).await);
|
||||
}
|
||||
_ => {}
|
||||
@@ -1238,11 +1247,25 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
self.handler
|
||||
.msgbox(&msgbox.msgtype, &msgbox.title, &msgbox.text, &link);
|
||||
}
|
||||
Some(message::Union::VoiceCallRequest(request)) => {
|
||||
// TODO
|
||||
Some(message::Union::VoiceCallRequest(_request)) => {
|
||||
// TODO: maybe we will do voice call from the peer.
|
||||
}
|
||||
Some(message::Union::VoiceCallResponse(response)) => {
|
||||
// TODO
|
||||
let ts = std::mem::replace(&mut self.voice_call_request_timestamp, None);
|
||||
if let Some(ts) = ts {
|
||||
if response.req_timestamp != ts.get() {
|
||||
log::debug!("Possible encountering a voice call attack.");
|
||||
} else {
|
||||
if response.accepted {
|
||||
// The peer accepts the voice call.
|
||||
self.handler.on_voice_call_start();
|
||||
self.stop_voice_call_sender = self.start_voice_call();
|
||||
} else {
|
||||
// The peer refused the voice call.
|
||||
self.handler.on_voice_call_stop("Refused");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user