diff --git a/src/client.rs b/src/client.rs index e13ccff11..7129e7d9d 100644 --- a/src/client.rs +++ b/src/client.rs @@ -279,10 +279,10 @@ impl Client { } let (stop_udp_tx, stop_udp_rx) = oneshot::channel::<()>(); - let mut udp = + let udp = // no need to care about multiple rendezvous servers case, since it is acutally not used any more. // Shared state for UDP NAT test result - if crate::get_udp_punch_enabled() { + if crate::get_udp_punch_enabled() && !interface.is_force_relay() { if let Ok((socket, addr)) = new_direct_udp_for(&rendezvous_server).await { let udp_port = Arc::new(Mutex::new(0)); let up_cloned = udp_port.clone(); @@ -298,6 +298,57 @@ impl Client { } else { (None, None) }; + let fut = Self::_start_inner( + peer.to_owned(), + key.to_owned(), + token.to_owned(), + conn_type, + interface.clone(), + udp.clone(), + Some(stop_udp_tx), + rendezvous_server.clone(), + servers.clone(), + contained, + ); + if udp.0.is_none() { + return fut.await; + } + let mut connect_futures = Vec::new(); + connect_futures.push(fut.boxed()); + let fut = Self::_start_inner( + peer.to_owned(), + key.to_owned(), + token.to_owned(), + conn_type, + interface, + (None, None), + None, + rendezvous_server, + servers, + contained, + ); + connect_futures.push(fut.boxed()); + match select_ok(connect_futures).await { + Ok(conn) => Ok((conn.0 .0, conn.0 .1)), + Err(e) => Err(e), + } + } + + async fn _start_inner( + peer: String, + key: String, + token: String, + conn_type: ConnType, + interface: impl Interface, + mut udp: (Option>, Option>>), + stop_udp_tx: Option>, + mut rendezvous_server: String, + servers: Vec, + contained: bool, + ) -> ResultType<( + (Stream, bool, Option>, Option), + (i32, String), + )> { let mut start = Instant::now(); let mut socket = connect_tcp(&*rendezvous_server, CONNECT_TIMEOUT).await; debug_assert!(!servers.contains(&rendezvous_server)); @@ -327,9 +378,8 @@ impl Client { let my_nat_type = crate::get_nat_type(100).await; let mut is_local = false; let mut feedback = 0; - let force_relay = interface.is_force_relay() || use_ws() || Config::is_proxy(); use hbb_common::protobuf::Enum; - let nat_type = if force_relay { + let nat_type = if interface.is_force_relay() { NatType::SYMMETRIC } else { NatType::from_i32(my_nat_type).unwrap_or(NatType::UNKNOWN_NAT) @@ -337,7 +387,7 @@ impl Client { if !key.is_empty() && !token.is_empty() { // mainly for the security of token - secure_tcp(&mut socket, key) + secure_tcp(&mut socket, &key) .await .map_err(|e| anyhow!("Failed to secure tcp: {}", e))?; } else if let Some(udp) = udp.1.as_ref() { @@ -355,7 +405,7 @@ impl Client { } } // Stop UDP NAT test task if still running - let _ = stop_udp_tx.send(()); + stop_udp_tx.map(|tx| tx.send(())); let mut msg_out = RendezvousMessage::new(); let mut ipv6 = if crate::get_ipv6_punch_enabled() { if let Some((socket, addr)) = crate::get_ipv6_socket().await { @@ -375,7 +425,7 @@ impl Client { conn_type: conn_type.into(), version: crate::VERSION.to_owned(), udp_port: udp_nat_port as _, - force_relay, + force_relay: interface.is_force_relay(), socket_addr_v6: ipv6.1.unwrap_or_default(), ..Default::default() }); @@ -454,10 +504,10 @@ impl Client { } signed_id_pk = rr.pk().into(); let fut = Self::create_relay( - peer, + &peer, rr.uuid, rr.relay_server, - key, + &key, conn_type, my_addr.is_ipv4(), ); @@ -478,7 +528,7 @@ impl Client { feedback = rr.feedback; log::info!("{:?} used to establish {typ} connection", start.elapsed()); let pk = - Self::secure_connection(peer, signed_id_pk, key, &mut conn).await?; + Self::secure_connection(&peer, signed_id_pk, &key, &mut conn).await?; return Ok(((conn, false, pk, kcp), (feedback, rendezvous_server))); } _ => { @@ -506,7 +556,7 @@ impl Client { Self::connect( my_addr, peer_addr, - peer, + &peer, signed_id_pk, &relay_server, &rendezvous_server, @@ -514,8 +564,8 @@ impl Client { peer_nat_type, my_nat_type, is_local, - key, - token, + &key, + &token, conn_type, interface, udp.0, @@ -1731,7 +1781,9 @@ impl LoginConfigHandler { self.restarting_remote_device = false; self.force_relay = config::option2bool("force-always-relay", &self.get_option("force-always-relay")) - || force_relay; + || force_relay + || use_ws() + || Config::is_proxy(); if let Some((real_id, server, key)) = &self.other_server { let other_server_key = self.get_option("other-server-key"); if !other_server_key.is_empty() && key.is_empty() {