Merge branch 'master' into lan_discovery

This commit is contained in:
RustDesk
2022-01-10 17:34:51 +08:00
committed by GitHub
68 changed files with 3775 additions and 1605 deletions

View File

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