Merge remote-tracking branch 'rustdesk/master' into flutter_desktop

# Conflicts:
#	.github/workflows/ci.yml
#	Cargo.lock
#	Cargo.toml
#	flutter/lib/common.dart
#	flutter/lib/mobile/pages/remote_page.dart
#	flutter/lib/mobile/pages/server_page.dart
#	flutter/lib/mobile/pages/settings_page.dart
#	flutter/lib/mobile/widgets/dialog.dart
#	flutter/lib/models/model.dart
#	flutter/lib/models/server_model.dart
#	src/client.rs
#	src/common.rs
#	src/ipc.rs
#	src/mobile_ffi.rs
#	src/rendezvous_mediator.rs
#	src/ui.rs
This commit is contained in:
Kingtous
2022-08-01 10:44:05 +08:00
142 changed files with 8721 additions and 2231 deletions

View File

@@ -12,6 +12,11 @@ use cpal::{
Device, Host, StreamConfig,
};
use magnum_opus::{Channels::*, Decoder as AudioDecoder};
use scrap::{
codec::{Decoder, DecoderCfg},
VpxDecoderConfig, VpxVideoCodecId,
};
use sha2::{Digest, Sha256};
use uuid::Uuid;
@@ -24,6 +29,7 @@ use hbb_common::{
log,
message_proto::{option_message::BoolOption, *},
protobuf::Message as _,
rand,
rendezvous_proto::*,
socket_client,
sodiumoxide::crypto::{box_, secretbox, sign},
@@ -39,6 +45,7 @@ pub use super::lang::*;
pub mod file_trait;
pub mod helper;
pub use helper::*;
pub const SEC30: Duration = Duration::from_secs(30);
/// Client of the remote desktop.
@@ -149,11 +156,25 @@ impl Client {
true,
));
}
let rendezvous_server = crate::get_rendezvous_server(1_000).await;
log::info!("rendezvous server: {}", rendezvous_server);
let (mut rendezvous_server, servers, contained) = crate::get_rendezvous_server(1_000).await;
let mut socket =
socket_client::connect_tcp(&*rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT).await?;
socket_client::connect_tcp(&*rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT).await;
debug_assert!(!servers.contains(&rendezvous_server));
if socket.is_err() && !servers.is_empty() {
log::info!("try the other servers: {:?}", servers);
for server in servers {
socket = socket_client::connect_tcp(&*server, any_addr, RENDEZVOUS_TIMEOUT).await;
if socket.is_ok() {
rendezvous_server = server;
break;
}
}
crate::refresh_rendezvous_server();
} else if !contained {
crate::refresh_rendezvous_server();
}
log::info!("rendezvous server: {}", rendezvous_server);
let mut socket = socket?;
let my_addr = socket.local_addr();
let mut signed_id_pk = Vec::new();
let mut relay_server = "".to_owned();
@@ -166,7 +187,7 @@ impl Client {
for i in 1..=3 {
log::info!("#{} punch attempt with {}, id: {}", i, my_addr, peer);
let mut msg_out = RendezvousMessage::new();
use hbb_common::protobuf::ProtobufEnum;
use hbb_common::protobuf::Enum;
let nat_type = NatType::from_i32(my_nat_type).unwrap_or(NatType::UNKNOWN_NAT);
msg_out.set_punch_hole_request(PunchHoleRequest {
id: peer.to_owned(),
@@ -180,7 +201,7 @@ impl Client {
if let Some(Ok(bytes)) = socket.next_timeout(i * 6000).await {
if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) {
match msg_in.union {
Some(rendezvous_message::Union::punch_hole_response(ph)) => {
Some(rendezvous_message::Union::PunchHoleResponse(ph)) => {
if ph.socket_addr.is_empty() {
if !ph.other_failure.is_empty() {
bail!(ph.other_failure);
@@ -200,22 +221,22 @@ impl Client {
}
}
} else {
peer_nat_type = ph.get_nat_type();
is_local = ph.get_is_local();
signed_id_pk = ph.pk;
peer_nat_type = ph.nat_type();
is_local = ph.is_local();
signed_id_pk = ph.pk.into();
relay_server = ph.relay_server;
peer_addr = AddrMangle::decode(&ph.socket_addr);
log::info!("Hole Punched {} = {}", peer, peer_addr);
break;
}
}
Some(rendezvous_message::Union::relay_response(rr)) => {
Some(rendezvous_message::Union::RelayResponse(rr)) => {
log::info!(
"relay requested from peer, time used: {:?}, relay_server: {}",
start.elapsed(),
rr.relay_server
);
signed_id_pk = rr.get_pk().into();
signed_id_pk = rr.pk().into();
let mut conn =
Self::create_relay(peer, rr.uuid, rr.relay_server, key, conn_type)
.await?;
@@ -359,7 +380,7 @@ impl Client {
conn: &mut Stream,
) -> ResultType<()> {
let rs_pk = get_rs_pk(if key.is_empty() {
"OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw="
hbb_common::config::RS_PUB_KEY
} else {
key
});
@@ -386,7 +407,7 @@ impl Client {
Some(res) => {
let bytes = res?;
if let Ok(msg_in) = Message::parse_from_bytes(&bytes) {
if let Some(message::Union::signed_id(si)) = msg_in.union {
if let Some(message::Union::SignedId(si)) = msg_in.union {
if let Ok((id, their_pk_b)) = decode_id_pk(&si.id, &sign_pk) {
if id == peer_id {
let their_pk_b = box_::PublicKey(their_pk_b);
@@ -396,8 +417,8 @@ impl Client {
let sealed_key = box_::seal(&key.0, &nonce, &their_pk_b, &out_sk_b);
let mut msg_out = Message::new();
msg_out.set_public_key(PublicKey {
asymmetric_value: our_pk_b.0.into(),
symmetric_value: sealed_key,
asymmetric_value: Vec::from(our_pk_b.0).into(),
symmetric_value: sealed_key.into(),
..Default::default()
});
timeout(CONNECT_TIMEOUT, conn.send(&msg_out)).await??;
@@ -470,7 +491,7 @@ impl Client {
socket.send(&msg_out).await?;
if let Some(Ok(bytes)) = socket.next_timeout(CONNECT_TIMEOUT).await {
if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) {
if let Some(rendezvous_message::Union::relay_response(rs)) = msg_in.union {
if let Some(rendezvous_message::Union::RelayResponse(rs)) = msg_in.union {
if !rs.refuse_reason.is_empty() {
bail!(rs.refuse_reason);
}
@@ -736,7 +757,12 @@ impl VideoHandler {
/// Create a new video handler.
pub fn new(latency_controller: Arc<Mutex<LatencyController>>) -> Self {
VideoHandler {
decoder: Decoder::new(VideoCodecId::VP9, (num_cpus::get() / 2) as _).unwrap(),
decoder: Decoder::new(DecoderCfg {
vpx: VpxDecoderConfig {
codec: VpxVideoCodecId::VP9,
num_threads: (num_cpus::get() / 2) as _,
},
}),
latency_controller,
rgb: Default::default(),
}
@@ -752,7 +778,7 @@ impl VideoHandler {
.update_video(vf.timestamp);
}
match &vf.union {
Some(video_frame::Union::vp9s(vp9s)) => self.handle_vp9s(vp9s),
Some(frame) => self.decoder.handle_video_frame(frame, &mut self.rgb),
_ => Ok(false),
}
}
@@ -780,7 +806,12 @@ impl VideoHandler {
/// Reset the decoder.
pub fn reset(&mut self) {
self.decoder = Decoder::new(VideoCodecId::VP9, 1).unwrap();
self.decoder = Decoder::new(DecoderCfg {
vpx: VpxDecoderConfig {
codec: VpxVideoCodecId::VP9,
num_threads: 1,
},
});
}
}
@@ -798,6 +829,9 @@ pub struct LoginConfigHandler {
pub version: i64,
pub conn_id: i32,
features: Option<Features>,
session_id: u64,
pub supported_encoding: Option<(bool, bool)>,
pub restarting_remote_device: bool,
}
impl Deref for LoginConfigHandler {
@@ -833,6 +867,9 @@ impl LoginConfigHandler {
let config = self.load_config();
self.remember = !config.password.is_empty();
self.config = config;
self.session_id = rand::random();
self.supported_encoding = None;
self.restarting_remote_device = false;
}
/// Check if the client should auto login.
@@ -946,6 +983,8 @@ impl LoginConfigHandler {
option.block_input = BoolOption::Yes.into();
} else if name == "unblock-input" {
option.block_input = BoolOption::No.into();
} else if name == "show-quality-monitor" {
config.show_quality_monitor = !config.show_quality_monitor;
} else {
let v = self.options.get(&name).is_some();
if v {
@@ -984,15 +1023,8 @@ impl LoginConfigHandler {
n += 1;
} else if q == "custom" {
let config = PeerConfig::load(&self.id);
let mut it = config.custom_image_quality.iter();
let bitrate = it.next();
let quantizer = it.next();
if let Some(bitrate) = bitrate {
if let Some(quantizer) = quantizer {
msg.custom_image_quality = bitrate << 8 | quantizer;
n += 1;
}
}
msg.custom_image_quality = config.custom_image_quality[0] << 8;
n += 1;
}
if self.get_toggle_option("show-remote-cursor") {
msg.show_remote_cursor = BoolOption::Yes.into();
@@ -1018,6 +1050,10 @@ impl LoginConfigHandler {
msg.disable_clipboard = BoolOption::Yes.into();
n += 1;
}
let state = Decoder::video_codec_state(&self.id);
msg.video_codec_state = hbb_common::protobuf::MessageField::some(state);
n += 1;
if n > 0 {
Some(msg)
} else {
@@ -1066,6 +1102,8 @@ impl LoginConfigHandler {
self.config.disable_audio
} else if name == "disable-clipboard" {
self.config.disable_clipboard
} else if name == "show-quality-monitor" {
self.config.show_quality_monitor
} else {
!self.get_option(name).is_empty()
}
@@ -1094,17 +1132,17 @@ impl LoginConfigHandler {
///
/// * `bitrate` - The given bitrate.
/// * `quantizer` - The given quantizer.
pub fn save_custom_image_quality(&mut self, bitrate: i32, quantizer: i32) -> Message {
pub fn save_custom_image_quality(&mut self, image_quality: i32) -> Message {
let mut misc = Misc::new();
misc.set_option(OptionMessage {
custom_image_quality: bitrate << 8 | quantizer,
custom_image_quality: image_quality << 8,
..Default::default()
});
let mut msg_out = Message::new();
msg_out.set_misc(misc);
let mut config = self.load_config();
config.image_quality = "custom".to_owned();
config.custom_image_quality = vec![bitrate, quantizer];
config.custom_image_quality = vec![image_quality as _];
self.save_config(config);
msg_out
}
@@ -1202,6 +1240,10 @@ impl LoginConfigHandler {
self.conn_id = pi.conn_id;
// no matter if change, for update file time
self.save_config(config);
#[cfg(feature = "hwcodec")]
{
self.supported_encoding = Some((pi.encoding.h264, pi.encoding.h265));
}
}
pub fn get_remote_dir(&self) -> String {
@@ -1231,10 +1273,11 @@ impl LoginConfigHandler {
let my_id = Config::get_id();
let mut lr = LoginRequest {
username: self.id.clone(),
password,
password: password.into(),
my_id,
my_name: crate::username(),
option: self.get_option_message(true).into(),
session_id: self.session_id,
..Default::default()
};
if self.is_file_transfer {
@@ -1254,6 +1297,26 @@ impl LoginConfigHandler {
msg_out.set_login_request(lr);
msg_out
}
pub fn change_prefer_codec(&self) -> Message {
let state = scrap::codec::Decoder::video_codec_state(&self.id);
let mut misc = Misc::new();
misc.set_option(OptionMessage {
video_codec_state: hbb_common::protobuf::MessageField::some(state),
..Default::default()
});
let mut msg_out = Message::new();
msg_out.set_misc(misc);
msg_out
}
pub fn restart_remote_device(&self) -> Message {
let mut misc = Misc::new();
misc.set_restart_remote_device(true);
let mut msg_out = Message::new();
msg_out.set_misc(misc);
msg_out
}
}
/// Media data.
@@ -1282,9 +1345,11 @@ where
let latency_controller = LatencyController::new();
let latency_controller_cl = latency_controller.clone();
// Create video_handler out of the thread below to ensure that the handler exists before client start.
// It will take a few tenths of a second for the first time, and then tens of milliseconds.
let mut video_handler = VideoHandler::new(latency_controller);
std::thread::spawn(move || {
let mut video_handler = VideoHandler::new(latency_controller);
loop {
if let Ok(data) = video_receiver.recv() {
match data {
@@ -1459,11 +1524,21 @@ fn _input_os_password(p: String, activate: bool, interface: impl Interface) {
/// * `peer` - [`Stream`] for communicating with peer.
pub async fn handle_hash(
lc: Arc<RwLock<LoginConfigHandler>>,
password_preset: &str,
hash: Hash,
interface: &impl Interface,
peer: &mut Stream,
) {
let mut password = lc.read().unwrap().password.clone();
if password.is_empty() {
if !password_preset.is_empty() {
let mut hasher = Sha256::new();
hasher.update(password_preset);
hasher.update(&hash.salt);
let res = hasher.finalize();
password = res[..].into();
}
}
if password.is_empty() {
password = lc.read().unwrap().config.password.clone();
}
@@ -1525,7 +1600,7 @@ pub trait Interface: Send + Clone + 'static + Sized {
fn msgbox(&self, msgtype: &str, title: &str, text: &str);
fn handle_login_error(&mut self, err: &str) -> bool;
fn handle_peer_info(&mut self, pi: PeerInfo);
async fn handle_hash(&mut self, hash: Hash, peer: &mut Stream);
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream);
async fn handle_login_from_ui(&mut self, password: String, remember: bool, peer: &mut Stream);
async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream);
}