mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
Merge branch 'master' into lan_discovery
This commit is contained in:
130
src/client.rs
130
src/client.rs
@@ -14,8 +14,8 @@ use hbb_common::{
|
||||
message_proto::*,
|
||||
protobuf::Message as _,
|
||||
rendezvous_proto::*,
|
||||
socket_client,
|
||||
sodiumoxide::crypto::{box_, secretbox, sign},
|
||||
tcp::FramedStream,
|
||||
timeout,
|
||||
tokio::time::Duration,
|
||||
AddrMangle, ResultType, Stream,
|
||||
@@ -35,6 +35,8 @@ pub const SEC30: Duration = Duration::from_secs(30);
|
||||
|
||||
pub struct Client;
|
||||
|
||||
pub use super::lang::*;
|
||||
|
||||
#[cfg(not(any(target_os = "android")))]
|
||||
lazy_static::lazy_static! {
|
||||
static ref AUDIO_HOST: Host = cpal::default_host();
|
||||
@@ -102,14 +104,39 @@ impl Drop for OboePlayer {
|
||||
|
||||
impl Client {
|
||||
pub async fn start(peer: &str, conn_type: ConnType) -> ResultType<(Stream, bool)> {
|
||||
match Self::_start(peer, conn_type).await {
|
||||
Err(err) => {
|
||||
let err_str = err.to_string();
|
||||
if err_str.starts_with("Failed") {
|
||||
bail!(err_str + ": Please try later");
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
Ok(x) => Ok(x),
|
||||
}
|
||||
}
|
||||
|
||||
async fn _start(peer: &str, conn_type: ConnType) -> ResultType<(Stream, bool)> {
|
||||
// to-do: remember the port for each peer, so that we can retry easier
|
||||
let any_addr = Config::get_any_listen_addr();
|
||||
if crate::is_ip(peer) {
|
||||
return Ok((
|
||||
socket_client::connect_tcp(
|
||||
crate::check_port(peer, RELAY_PORT + 1),
|
||||
any_addr,
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await?,
|
||||
true,
|
||||
));
|
||||
}
|
||||
let rendezvous_server = crate::get_rendezvous_server(1_000).await;
|
||||
log::info!("rendezvous server: {}", rendezvous_server);
|
||||
let mut socket = FramedStream::new(rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT)
|
||||
.await
|
||||
.with_context(|| "Failed to connect to rendezvous server")?;
|
||||
let my_addr = socket.get_ref().local_addr()?;
|
||||
|
||||
let mut socket =
|
||||
socket_client::connect_tcp(&*rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT).await?;
|
||||
let my_addr = socket.local_addr();
|
||||
let mut pk = Vec::new();
|
||||
let mut relay_server = "".to_owned();
|
||||
|
||||
@@ -204,7 +231,7 @@ impl Client {
|
||||
peer,
|
||||
pk,
|
||||
&relay_server,
|
||||
rendezvous_server,
|
||||
&rendezvous_server,
|
||||
time_used,
|
||||
peer_nat_type,
|
||||
my_nat_type,
|
||||
@@ -220,7 +247,7 @@ impl Client {
|
||||
peer_id: &str,
|
||||
pk: Vec<u8>,
|
||||
relay_server: &str,
|
||||
rendezvous_server: SocketAddr,
|
||||
rendezvous_server: &str,
|
||||
punch_time_used: u64,
|
||||
peer_nat_type: NatType,
|
||||
my_nat_type: i32,
|
||||
@@ -261,7 +288,8 @@ impl Client {
|
||||
}
|
||||
log::info!("peer address: {}, timeout: {}", peer, connect_timeout);
|
||||
let start = std::time::Instant::now();
|
||||
let mut conn = FramedStream::new(peer, local_addr, connect_timeout).await;
|
||||
// NOTICE: Socks5 is be used event in intranet. Which may be not a good way.
|
||||
let mut conn = socket_client::connect_tcp(peer, local_addr, connect_timeout).await;
|
||||
let direct = !conn.is_err();
|
||||
if conn.is_err() {
|
||||
if !relay_server.is_empty() {
|
||||
@@ -296,28 +324,51 @@ impl Client {
|
||||
}
|
||||
|
||||
async fn secure_connection(peer_id: &str, pk: Vec<u8>, conn: &mut Stream) -> ResultType<()> {
|
||||
let mut pk = pk;
|
||||
const RS_PK: &[u8; 32] = &[
|
||||
177, 155, 15, 73, 116, 147, 172, 11, 55, 38, 92, 168, 30, 116, 213, 196, 12, 134, 130,
|
||||
170, 181, 161, 192, 176, 132, 229, 139, 178, 17, 165, 150, 51,
|
||||
];
|
||||
if !pk.is_empty() {
|
||||
let tmp = sign::PublicKey(*RS_PK);
|
||||
if let Ok(data) = sign::verify(&pk, &tmp) {
|
||||
pk = data;
|
||||
} else {
|
||||
log::error!("Handshake failed: invalid public key from rendezvous server");
|
||||
pk.clear();
|
||||
}
|
||||
}
|
||||
if pk.len() != sign::PUBLICKEYBYTES {
|
||||
// send an empty message out in case server is setting up secure and waiting for first message
|
||||
conn.send(&Message::new()).await?;
|
||||
return Ok(());
|
||||
}
|
||||
let mut pk_ = [0u8; sign::PUBLICKEYBYTES];
|
||||
pk_[..].copy_from_slice(&pk);
|
||||
let pk = sign::PublicKey(pk_);
|
||||
let mut tmp = [0u8; sign::PUBLICKEYBYTES];
|
||||
tmp[..].copy_from_slice(&pk);
|
||||
let sign_pk = sign::PublicKey(tmp);
|
||||
match timeout(CONNECT_TIMEOUT, conn.next()).await? {
|
||||
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 {
|
||||
let their_pk_b = if si.pk.len() == box_::PUBLICKEYBYTES {
|
||||
let mut pk_ = [0u8; box_::PUBLICKEYBYTES];
|
||||
pk_[..].copy_from_slice(&si.pk);
|
||||
box_::PublicKey(pk_)
|
||||
} else {
|
||||
bail!("Handshake failed: invalid public box key length from peer");
|
||||
};
|
||||
if let Ok(id) = sign::verify(&si.id, &pk) {
|
||||
if id == peer_id.as_bytes() {
|
||||
if let Ok(data) = sign::verify(&si.id, &sign_pk) {
|
||||
let s = String::from_utf8_lossy(&data);
|
||||
let mut it = s.split("\0");
|
||||
let id = it.next().unwrap_or_default();
|
||||
let pk =
|
||||
base64::decode(it.next().unwrap_or_default()).unwrap_or_default();
|
||||
let their_pk_b = if pk.len() == box_::PUBLICKEYBYTES {
|
||||
let mut pk_ = [0u8; box_::PUBLICKEYBYTES];
|
||||
pk_[..].copy_from_slice(&pk);
|
||||
box_::PublicKey(pk_)
|
||||
} else {
|
||||
log::error!(
|
||||
"Handshake failed: invalid public box key length from peer"
|
||||
);
|
||||
conn.send(&Message::new()).await?;
|
||||
return Ok(());
|
||||
};
|
||||
if id == peer_id {
|
||||
let (our_pk_b, out_sk_b) = box_::gen_keypair();
|
||||
let key = secretbox::gen_key();
|
||||
let nonce = box_::Nonce([0u8; box_::NONCEBYTES]);
|
||||
@@ -331,7 +382,8 @@ impl Client {
|
||||
timeout(CONNECT_TIMEOUT, conn.send(&msg_out)).await??;
|
||||
conn.set_key(key);
|
||||
} else {
|
||||
bail!("Handshake failed: sign failure");
|
||||
log::error!("Handshake failed: sign failure");
|
||||
conn.send(&Message::new()).await?;
|
||||
}
|
||||
} else {
|
||||
// fall back to non-secure connection in case pk mismatch
|
||||
@@ -341,10 +393,12 @@ impl Client {
|
||||
timeout(CONNECT_TIMEOUT, conn.send(&msg_out)).await??;
|
||||
}
|
||||
} else {
|
||||
bail!("Handshake failed: invalid message type");
|
||||
log::error!("Handshake failed: invalid message type");
|
||||
conn.send(&Message::new()).await?;
|
||||
}
|
||||
} else {
|
||||
bail!("Handshake failed: invalid message format");
|
||||
log::error!("Handshake failed: invalid message format");
|
||||
conn.send(&Message::new()).await?;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
@@ -357,7 +411,7 @@ impl Client {
|
||||
async fn request_relay(
|
||||
peer: &str,
|
||||
relay_server: String,
|
||||
rendezvous_server: SocketAddr,
|
||||
rendezvous_server: &str,
|
||||
secure: bool,
|
||||
conn_type: ConnType,
|
||||
) -> ResultType<Stream> {
|
||||
@@ -366,9 +420,11 @@ impl Client {
|
||||
let mut uuid = "".to_owned();
|
||||
for i in 1..=3 {
|
||||
// use different socket due to current hbbs implement requiring different nat address for each attempt
|
||||
let mut socket = FramedStream::new(rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT)
|
||||
.await
|
||||
.with_context(|| "Failed to connect to rendezvous server")?;
|
||||
let mut socket =
|
||||
socket_client::connect_tcp(rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT)
|
||||
.await
|
||||
.with_context(|| "Failed to connect to rendezvous server")?;
|
||||
|
||||
let mut msg_out = RendezvousMessage::new();
|
||||
uuid = Uuid::new_v4().to_string();
|
||||
log::info!(
|
||||
@@ -411,7 +467,7 @@ impl Client {
|
||||
relay_server: String,
|
||||
conn_type: ConnType,
|
||||
) -> ResultType<Stream> {
|
||||
let mut conn = FramedStream::new(
|
||||
let mut conn = socket_client::connect_tcp(
|
||||
crate::check_port(relay_server, RELAY_PORT),
|
||||
Config::get_any_listen_addr(),
|
||||
CONNECT_TIMEOUT,
|
||||
@@ -530,7 +586,10 @@ impl AudioHandler {
|
||||
);
|
||||
audio_buffer.lock().unwrap().extend(buffer);
|
||||
} else {
|
||||
audio_buffer.lock().unwrap().extend(buffer.iter().cloned());
|
||||
audio_buffer
|
||||
.lock()
|
||||
.unwrap()
|
||||
.extend(buffer[0..n].iter().cloned());
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_os = "android"))]
|
||||
@@ -548,7 +607,8 @@ impl AudioHandler {
|
||||
device: &Device,
|
||||
) -> ResultType<()> {
|
||||
let err_fn = move |err| {
|
||||
log::error!("an error occurred on stream: {}", err);
|
||||
// too many errors, will improve later
|
||||
log::trace!("an error occurred on stream: {}", err);
|
||||
};
|
||||
let audio_buffer = self.audio_buffer.clone();
|
||||
let stream = device.build_output_stream(
|
||||
@@ -583,7 +643,7 @@ pub struct VideoHandler {
|
||||
impl VideoHandler {
|
||||
pub fn new() -> Self {
|
||||
VideoHandler {
|
||||
decoder: Decoder::new(VideoCodecId::VP9, 1).unwrap(),
|
||||
decoder: Decoder::new(VideoCodecId::VP9, 0).unwrap(),
|
||||
rgb: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -625,6 +685,7 @@ pub struct LoginConfigHandler {
|
||||
pub port_forward: (String, i32),
|
||||
pub support_press: bool,
|
||||
pub support_refresh: bool,
|
||||
pub version: i64,
|
||||
}
|
||||
|
||||
impl Deref for LoginConfigHandler {
|
||||
@@ -659,6 +720,12 @@ impl LoginConfigHandler {
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
pub fn set_option(&mut self, k: String, v: String) {
|
||||
let mut config = self.load_config();
|
||||
config.options.insert(k, v);
|
||||
self.save_config(config);
|
||||
}
|
||||
|
||||
pub fn save_view_style(&mut self, value: String) {
|
||||
let mut config = self.load_config();
|
||||
config.view_style = value;
|
||||
@@ -875,6 +942,7 @@ impl LoginConfigHandler {
|
||||
if !pi.version.is_empty() {
|
||||
self.support_press = true;
|
||||
self.support_refresh = true;
|
||||
self.version = crate::get_version_number(&pi.version);
|
||||
}
|
||||
let serde = PeerInfoSerde {
|
||||
username,
|
||||
|
||||
Reference in New Issue
Block a user