feat: rust connection implementation

This commit is contained in:
Kingtous
2023-02-06 11:42:25 +08:00
parent a04980fa13
commit b412a7122b
8 changed files with 220 additions and 81 deletions

View File

@@ -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
}

View File

@@ -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");
}
}
}
}
_ => {}
}