diff --git a/libs/hbb_common/protos/rendezvous.proto b/libs/hbb_common/protos/rendezvous.proto index c71084785..bd058ac4d 100644 --- a/libs/hbb_common/protos/rendezvous.proto +++ b/libs/hbb_common/protos/rendezvous.proto @@ -6,11 +6,19 @@ message RegisterPeer { int32 serial = 2; } +enum ConnType { + DEFAULT_CONN = 0; + FILE_TRANSFER = 1; + PORT_FORWARD = 2; + RDP = 3; +} + message RegisterPeerResponse { bool request_pk = 2; } message PunchHoleRequest { string id = 1; NatType nat_type = 2; + ConnType conn_type = 4; } message PunchHole { @@ -52,6 +60,11 @@ message RegisterPkResponse { enum Result { OK = 1; UUID_MISMATCH = 2; + ID_EXISTS = 3; + TOO_FREQUENT = 4; + INVALID_ID_FORMAT = 5; + NOT_SUPPORT = 6; + SERVER_ERROR = 7; } Result result = 1; } @@ -62,6 +75,8 @@ message PunchHoleResponse { enum Failure { ID_NOT_EXIST = 1; OFFLINE = 2; + LICENCE_MISMATCH = 3; + LICENCE_OVERUSE = 4; } Failure failure = 3; string relay_server = 4; @@ -69,6 +84,7 @@ message PunchHoleResponse { NatType nat_type = 5; bool is_local = 6; } + string other_failure = 7; } message ConfigUpdate { @@ -82,6 +98,7 @@ message RequestRelay { bytes socket_addr = 3; string relay_server = 4; bool secure = 5; + ConnType conn_type = 7; } message RelayResponse { @@ -92,6 +109,7 @@ message RelayResponse { string id = 4; bytes pk = 5; } + string refuse_reason = 6; } message SoftwareUpdate { string url = 1; } diff --git a/libs/scrap/build.rs b/libs/scrap/build.rs index 87d205ce0..749ee5f42 100644 --- a/libs/scrap/build.rs +++ b/libs/scrap/build.rs @@ -27,7 +27,7 @@ fn find_package(name: &str) -> Vec { println!("cargo:info={}", target); path.push("installed"); path.push(target); - let mut lib = name.trim_start_matches("lib").to_string(); + let lib = name.trim_start_matches("lib").to_string(); println!("{}", format!("cargo:rustc-link-lib=static={}", lib)); println!( "{}", diff --git a/src/client.rs b/src/client.rs index e62eb19c1..cfa782e47 100644 --- a/src/client.rs +++ b/src/client.rs @@ -100,7 +100,7 @@ impl Drop for OboePlayer { } impl Client { - pub async fn start(peer: &str) -> ResultType<(Stream, bool)> { + pub 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(); let rendezvous_server = crate::get_rendezvous_server(1_000).await; @@ -125,6 +125,7 @@ impl Client { msg_out.set_punch_hole_request(PunchHoleRequest { id: peer.to_owned(), nat_type: nat_type.into(), + conn_type: conn_type.into(), ..Default::default() }); socket.send(&msg_out).await?; @@ -140,7 +141,14 @@ impl Client { punch_hole_response::Failure::OFFLINE => { bail!("Remote desktop is offline"); } - _ => {} + punch_hole_response::Failure::LICENCE_MISMATCH => { + bail!("Key mismatch"); + } + _ => { + if !ph.other_failure.is_empty() { + bail!(ph.other_failure); + } + } } } else { peer_nat_type = ph.get_nat_type(); @@ -160,7 +168,8 @@ impl Client { ); pk = rr.get_pk().into(); let mut conn = - Self::create_relay(peer, rr.uuid, rr.relay_server).await?; + Self::create_relay(peer, rr.uuid, rr.relay_server, conn_type) + .await?; Self::secure_connection(peer, pk, &mut conn).await?; return Ok((conn, false)); } @@ -199,6 +208,7 @@ impl Client { peer_nat_type, my_nat_type, is_local, + conn_type, ) .await } @@ -214,8 +224,9 @@ impl Client { peer_nat_type: NatType, my_nat_type: i32, is_local: bool, + conn_type: ConnType, ) -> ResultType<(Stream, bool)> { - let mut direct_failures = 0; + let direct_failures = PeerConfig::load(peer_id).direct_failures; let mut connect_timeout = 0; const MIN: u64 = 1000; if is_local || peer_nat_type == NatType::SYMMETRIC { @@ -231,13 +242,14 @@ impl Client { } if my_nat_type == NatType::ASYMMETRIC as i32 { connect_timeout = CONNECT_TIMEOUT; + if direct_failures > 0 { + connect_timeout = punch_time_used * 6; + } } else if my_nat_type == NatType::SYMMETRIC as i32 { connect_timeout = MIN; } } if connect_timeout == 0 { - let config = PeerConfig::load(peer_id); - direct_failures = config.direct_failures; let n = if direct_failures > 0 { 3 } else { 6 }; connect_timeout = punch_time_used * (n as u64); } @@ -257,10 +269,14 @@ impl Client { relay_server.to_owned(), rendezvous_server, pk.len() == sign::PUBLICKEYBYTES, + conn_type, ) .await; if conn.is_err() { - bail!("Failed to connect via relay server"); + bail!( + "Failed to connect via relay server: {}", + conn.err().unwrap() + ); } } else { bail!("Failed to make direct connection to remote desktop"); @@ -318,7 +334,7 @@ impl Client { } } else { // fall back to non-secure connection in case pk mismatch - // to-do: pop up a warning dialog to let user choose if continue + log::info!("pk mismatch, fall back to non-secure"); let mut msg_out = Message::new(); msg_out.set_public_key(PublicKey::new()); timeout(CONNECT_TIMEOUT, conn.send(&msg_out)).await??; @@ -342,6 +358,7 @@ impl Client { relay_server: String, rendezvous_server: SocketAddr, secure: bool, + conn_type: ConnType, ) -> ResultType { let any_addr = Config::get_any_listen_addr(); let mut succeed = false; @@ -371,7 +388,10 @@ impl Client { socket.send(&msg_out).await?; if let Some(Ok(bytes)) = socket.next_timeout(i * 3000).await { if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) { - if let Some(rendezvous_message::Union::relay_response(_)) = msg_in.union { + if let Some(rendezvous_message::Union::relay_response(rs)) = msg_in.union { + if !rs.refuse_reason.is_empty() { + bail!(rs.refuse_reason); + } succeed = true; break; } @@ -381,10 +401,15 @@ impl Client { if !succeed { bail!(""); } - Self::create_relay(peer, uuid, relay_server).await + Self::create_relay(peer, uuid, relay_server, conn_type).await } - async fn create_relay(peer: &str, uuid: String, relay_server: String) -> ResultType { + async fn create_relay( + peer: &str, + uuid: String, + relay_server: String, + conn_type: ConnType, + ) -> ResultType { let mut conn = FramedStream::new( crate::check_port(relay_server, RELAY_PORT), Config::get_any_listen_addr(), @@ -396,6 +421,7 @@ impl Client { msg_out.set_request_relay(RequestRelay { id: peer.to_owned(), uuid, + conn_type: conn_type.into(), ..Default::default() }); conn.send(&msg_out).await?; diff --git a/src/port_forward.rs b/src/port_forward.rs index d74717bb6..2cd5fd901 100644 --- a/src/port_forward.rs +++ b/src/port_forward.rs @@ -6,6 +6,7 @@ use hbb_common::{ log, message_proto::*, protobuf::Message as _, + rendezvous_proto::ConnType, tcp, timeout, tokio::{self, net::TcpStream, sync::mpsc}, tokio_util::codec::{BytesCodec, Framed}, @@ -39,7 +40,7 @@ pub async fn listen( log::info!("new connection from {:?}", addr); let id = id.clone(); let mut forward = Framed::new(forward, BytesCodec::new()); - match connect_and_login(&id, &mut ui_receiver, interface.clone(), &mut forward).await { + match connect_and_login(&id, &mut ui_receiver, interface.clone(), &mut forward, is_rdp).await { Ok(Some(stream)) => { let interface = interface.clone(); tokio::spawn(async move { @@ -76,8 +77,14 @@ async fn connect_and_login( ui_receiver: &mut mpsc::UnboundedReceiver, interface: impl Interface, forward: &mut Framed, + is_rdp: bool, ) -> ResultType> { - let (mut stream, _) = Client::start(&id).await?; + let conn_type = if is_rdp { + ConnType::RDP + } else { + ConnType::PORT_FORWARD + }; + let (mut stream, _) = Client::start(id, conn_type).await?; let mut interface = interface; let mut buffer = Vec::new(); loop { diff --git a/src/rendezvous_mediator.rs b/src/rendezvous_mediator.rs index cda13250c..3832f6d9f 100644 --- a/src/rendezvous_mediator.rs +++ b/src/rendezvous_mediator.rs @@ -155,6 +155,7 @@ impl RendezvousMediator { register_pk_response::Result::UUID_MISMATCH => { allow_err!(rz.handle_uuid_mismatch(&mut socket).await); } + _ => {} } } Some(rendezvous_message::Union::punch_hole(ph)) => { diff --git a/src/ui.rs b/src/ui.rs index c3ba28f7f..e467317d3 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -511,9 +511,9 @@ impl UI { format!("{}.{}", p.to_string_lossy(), self.get_software_ext()) } - fn create_shortcut(&self, id: String) { + fn create_shortcut(&self, _id: String) { #[cfg(windows)] - crate::platform::windows::create_shortcut(&id).ok(); + crate::platform::windows::create_shortcut(&_id).ok(); } fn open_url(&self, url: String) { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 572e6eabd..3d90603cf 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -9,6 +9,7 @@ use hbb_common::{ fs, log, message_proto::*, protobuf::Message as _, + rendezvous_proto::ConnType, sleep, tokio::{ self, @@ -494,6 +495,7 @@ impl Handler { fn set_no_confirm(&mut self, id: i32) { self.send(Data::SetNoConfirm(id)); } + fn remove_dir(&mut self, id: i32, path: String, is_remote: bool) { if is_remote { self.send(Data::RemoveDir((id, path))); @@ -1144,7 +1146,12 @@ impl Remote { async fn io_loop(&mut self) { let stop_clipboard = self.start_clipboard(); let mut last_recv_time = Instant::now(); - match Client::start(&self.handler.id).await { + let conn_type = if self.handler.is_file_transfer() { + ConnType::FILE_TRANSFER + } else { + ConnType::default() + }; + match Client::start(&self.handler.id, conn_type).await { Ok((mut peer, direct)) => { self.handler .call("setConnectionType", &make_args!(peer.is_secured(), direct));