mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-24 04:12:20 +08:00
opt force_relay/relay_hint logic
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
0fafedc706
commit
aede035d20
@ -350,7 +350,7 @@ class FfiModel with ChangeNotifier {
|
||||
} else if (type == 'elevation-error') {
|
||||
showElevationError(sessionId, type, title, text, dialogManager);
|
||||
} else if (type == 'relay-hint') {
|
||||
showRelayHintDialog(sessionId, type, title, text, dialogManager);
|
||||
showRelayHintDialog(sessionId, type, title, text, dialogManager, peerId);
|
||||
} else {
|
||||
var hasRetry = evt['hasRetry'] == 'true';
|
||||
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
|
||||
@ -383,7 +383,7 @@ class FfiModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
void showRelayHintDialog(SessionID sessionId, String type, String title,
|
||||
String text, OverlayDialogManager dialogManager) {
|
||||
String text, OverlayDialogManager dialogManager, String peerId) {
|
||||
dialogManager.show(tag: '$sessionId-$type', (setState, close, context) {
|
||||
onClose() {
|
||||
closeConnection();
|
||||
@ -392,25 +392,24 @@ class FfiModel with ChangeNotifier {
|
||||
|
||||
final style =
|
||||
ElevatedButton.styleFrom(backgroundColor: Colors.green[700]);
|
||||
var hint = "\n\n${translate('relay_hint_tip')}";
|
||||
if (text.contains("10054") || text.contains("104")) {
|
||||
hint = "";
|
||||
}
|
||||
final alreadyForceAlwaysRelay = bind
|
||||
.mainGetPeerOptionSync(id: peerId, key: 'force-always-relay')
|
||||
.isNotEmpty;
|
||||
return CustomAlertDialog(
|
||||
title: null,
|
||||
content: msgboxContent(type, title,
|
||||
"${translate(text)}\n\n${translate('relay_hint_tip')}"),
|
||||
content: msgboxContent(type, title, "${translate(text)}$hint"),
|
||||
actions: [
|
||||
dialogButton('Close', onPressed: onClose, isOutline: true),
|
||||
dialogButton('Retry',
|
||||
onPressed: () => reconnect(dialogManager, sessionId, false)),
|
||||
dialogButton('Connect via relay',
|
||||
onPressed: () => reconnect(dialogManager, sessionId, true),
|
||||
buttonStyle: style),
|
||||
dialogButton('Always connect via relay', onPressed: () {
|
||||
const option = 'force-always-relay';
|
||||
bind.sessionPeerOption(
|
||||
sessionId: sessionId,
|
||||
name: option,
|
||||
value: bool2option(option, true));
|
||||
reconnect(dialogManager, sessionId, true);
|
||||
}, buttonStyle: style),
|
||||
if (!alreadyForceAlwaysRelay)
|
||||
dialogButton('Connect via relay',
|
||||
onPressed: () => reconnect(dialogManager, sessionId, true),
|
||||
buttonStyle: style),
|
||||
],
|
||||
onCancel: onClose,
|
||||
);
|
||||
|
@ -213,6 +213,8 @@ impl Client {
|
||||
conn_type: ConnType,
|
||||
interface: impl Interface,
|
||||
) -> ResultType<(Stream, bool, Option<Vec<u8>>)> {
|
||||
interface.update_direct(None);
|
||||
interface.update_received(false);
|
||||
match Self::_start(peer, key, token, conn_type, interface).await {
|
||||
Err(err) => {
|
||||
let err_str = err.to_string();
|
||||
@ -353,15 +355,8 @@ impl Client {
|
||||
my_addr.is_ipv4(),
|
||||
)
|
||||
.await?;
|
||||
let pk = Self::secure_connection(
|
||||
peer,
|
||||
signed_id_pk,
|
||||
key,
|
||||
&mut conn,
|
||||
false,
|
||||
interface,
|
||||
)
|
||||
.await?;
|
||||
let pk =
|
||||
Self::secure_connection(peer, signed_id_pk, key, &mut conn).await?;
|
||||
return Ok((conn, false, pk));
|
||||
}
|
||||
_ => {
|
||||
@ -459,6 +454,7 @@ impl Client {
|
||||
let mut conn =
|
||||
socket_client::connect_tcp_local(peer, Some(local_addr), connect_timeout).await;
|
||||
let mut direct = !conn.is_err();
|
||||
interface.update_direct(Some(direct));
|
||||
if interface.is_force_relay() || conn.is_err() {
|
||||
if !relay_server.is_empty() {
|
||||
conn = Self::request_relay(
|
||||
@ -471,6 +467,7 @@ impl Client {
|
||||
conn_type,
|
||||
)
|
||||
.await;
|
||||
interface.update_direct(Some(false));
|
||||
if conn.is_err() {
|
||||
bail!(
|
||||
"Failed to connect via relay server: {}",
|
||||
@ -490,8 +487,7 @@ impl Client {
|
||||
}
|
||||
let mut conn = conn?;
|
||||
log::info!("{:?} used to establish connection", start.elapsed());
|
||||
let pk = Self::secure_connection(peer_id, signed_id_pk, key, &mut conn, direct, interface)
|
||||
.await?;
|
||||
let pk = Self::secure_connection(peer_id, signed_id_pk, key, &mut conn).await?;
|
||||
Ok((conn, direct, pk))
|
||||
}
|
||||
|
||||
@ -501,8 +497,6 @@ impl Client {
|
||||
signed_id_pk: Vec<u8>,
|
||||
key: &str,
|
||||
conn: &mut Stream,
|
||||
direct: bool,
|
||||
interface: impl Interface,
|
||||
) -> ResultType<Option<Vec<u8>>> {
|
||||
let rs_pk = get_rs_pk(if key.is_empty() {
|
||||
hbb_common::config::RS_PUB_KEY
|
||||
@ -532,13 +526,7 @@ impl Client {
|
||||
};
|
||||
match timeout(READ_TIMEOUT, conn.next()).await? {
|
||||
Some(res) => {
|
||||
let bytes = match res {
|
||||
Ok(bytes) => bytes,
|
||||
Err(err) => {
|
||||
interface.set_force_relay(direct, false, err.to_string());
|
||||
bail!("{}", err);
|
||||
}
|
||||
};
|
||||
let bytes = res?;
|
||||
if let Ok(msg_in) = Message::parse_from_bytes(&bytes) {
|
||||
if let Some(message::Union::SignedId(si)) = msg_in.union {
|
||||
if let Ok((id, their_pk_b)) = decode_id_pk(&si.id, &sign_pk) {
|
||||
@ -1082,8 +1070,6 @@ pub struct LoginConfigHandler {
|
||||
pub direct: Option<bool>,
|
||||
pub received: bool,
|
||||
switch_uuid: Option<String>,
|
||||
pub success_time: Option<hbb_common::tokio::time::Instant>,
|
||||
pub direct_error_counter: usize,
|
||||
}
|
||||
|
||||
impl Deref for LoginConfigHandler {
|
||||
@ -1130,8 +1116,6 @@ impl LoginConfigHandler {
|
||||
self.direct = None;
|
||||
self.received = false;
|
||||
self.switch_uuid = switch_uuid;
|
||||
self.success_time = None;
|
||||
self.direct_error_counter = 0;
|
||||
}
|
||||
|
||||
/// Check if the client should auto login.
|
||||
@ -1759,20 +1743,6 @@ impl LoginConfigHandler {
|
||||
msg_out.set_misc(misc);
|
||||
msg_out
|
||||
}
|
||||
|
||||
pub fn set_force_relay(&mut self, direct: bool, received: bool, err: String) {
|
||||
self.force_relay = false;
|
||||
if direct && !received {
|
||||
let errno = errno::errno().0;
|
||||
// TODO: check mac and ios
|
||||
if cfg!(windows) && (errno == 10054 || err.contains("10054"))
|
||||
|| !cfg!(windows) && (errno == 104 || err.contains("104"))
|
||||
{
|
||||
self.force_relay = true;
|
||||
self.set_option("force-always-relay".to_owned(), "Y".to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Media data.
|
||||
@ -2317,16 +2287,48 @@ pub trait Interface: Send + Clone + 'static + Sized {
|
||||
async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream);
|
||||
|
||||
fn get_login_config_handler(&self) -> Arc<RwLock<LoginConfigHandler>>;
|
||||
fn set_force_relay(&self, direct: bool, received: bool, err: String) {
|
||||
self.get_login_config_handler()
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_force_relay(direct, received, err);
|
||||
}
|
||||
|
||||
fn is_force_relay(&self) -> bool {
|
||||
self.get_login_config_handler().read().unwrap().force_relay
|
||||
}
|
||||
fn swap_modifier_mouse(&self, _msg: &mut hbb_common::protos::message::MouseEvent) {}
|
||||
|
||||
fn update_direct(&self, direct: Option<bool>) {
|
||||
self.get_login_config_handler().write().unwrap().direct = direct;
|
||||
}
|
||||
|
||||
fn update_received(&self, received: bool) {
|
||||
self.get_login_config_handler().write().unwrap().received = received;
|
||||
}
|
||||
|
||||
fn on_establish_connection_error(&self, err: String) {
|
||||
log::error!("Connection closed: {}", err);
|
||||
let title = "Connection Error";
|
||||
let text = err.to_string();
|
||||
let lc = self.get_login_config_handler();
|
||||
let direct = lc.read().unwrap().direct;
|
||||
let received = lc.read().unwrap().received;
|
||||
let relay_condition = direct == Some(true) && !received;
|
||||
|
||||
// force relay
|
||||
let errno = errno::errno().0;
|
||||
if relay_condition
|
||||
&& (cfg!(windows) && (errno == 10054 || err.contains("10054"))
|
||||
|| !cfg!(windows) && (errno == 104 || err.contains("104")))
|
||||
{
|
||||
lc.write().unwrap().force_relay = true;
|
||||
lc.write()
|
||||
.unwrap()
|
||||
.set_option("force-always-relay".to_owned(), "Y".to_owned());
|
||||
}
|
||||
|
||||
// relay-hint
|
||||
if cfg!(feature = "flutter") && relay_condition {
|
||||
self.msgbox("relay-hint", title, &text, "");
|
||||
} else {
|
||||
self.msgbox("error", title, &text, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data used by the client interface.
|
||||
|
@ -124,7 +124,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
{
|
||||
Ok((mut peer, direct, pk)) => {
|
||||
self.handler.set_connection_type(peer.is_secured(), direct); // flutter -> connection_ready
|
||||
self.handler.set_connection_info(direct, false);
|
||||
self.handler.update_direct(Some(direct));
|
||||
if conn_type == ConnType::DEFAULT_CONN {
|
||||
self.handler
|
||||
.set_fingerprint(crate::common::pk_to_fingerprint(pk.unwrap_or_default()));
|
||||
@ -160,24 +160,14 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
if let Some(res) = res {
|
||||
match res {
|
||||
Err(err) => {
|
||||
log::error!("Connection closed: {}", err);
|
||||
self.handler.set_force_relay(direct, received, err.to_string());
|
||||
let msgtype = "error";
|
||||
let title = "Connection Error";
|
||||
let text = err.to_string();
|
||||
let show_relay_hint = self.handler.show_relay_hint(last_recv_time, msgtype, title, &text);
|
||||
if show_relay_hint{
|
||||
self.handler.msgbox("relay-hint", title, &text, "");
|
||||
} else {
|
||||
self.handler.msgbox(msgtype, title, &text, "");
|
||||
}
|
||||
self.handler.on_establish_connection_error(err.to_string());
|
||||
break;
|
||||
}
|
||||
Ok(ref bytes) => {
|
||||
last_recv_time = Instant::now();
|
||||
if !received {
|
||||
received = true;
|
||||
self.handler.set_connection_info(direct, true);
|
||||
self.handler.update_received(true);
|
||||
}
|
||||
self.data_count.fetch_add(bytes.len(), Ordering::Relaxed);
|
||||
if !self.handle_msg_from_peer(bytes, &mut peer).await {
|
||||
@ -271,8 +261,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
self.handler
|
||||
.msgbox("error", "Connection Error", &err.to_string(), "");
|
||||
self.handler.on_establish_connection_error(err.to_string());
|
||||
}
|
||||
}
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
|
@ -44,7 +44,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("wait_accept_uac_tip", "Please wait for the remote user to accept the UAC dialog."),
|
||||
("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk."),
|
||||
("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."),
|
||||
("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."),
|
||||
("relay_hint_tip", "It may not be possible to connect directly; you can try connecting via relay. Additionally, if you want to use a relay on your first attempt, you can add the \"/r\" suffix to the ID or select the option \"Always connect via relay\" in the card of recent sessions."),
|
||||
("No transfers in progress", ""),
|
||||
("idd_driver_tip", "Install virtual display driver which is used when you have no physical displays."),
|
||||
("confirm_idd_driver_tip", "The option to install the virtual display driver is checked. Note that a test certificate will be installed to trust the virtual display driver. This test certificate will only be used to trust Rustdesk drivers."),
|
||||
|
@ -81,7 +81,7 @@ pub async fn listen(
|
||||
});
|
||||
}
|
||||
Err(err) => {
|
||||
interface.msgbox("error", "Error", &err.to_string(), "");
|
||||
interface.on_establish_connection_error(err.to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -112,43 +112,6 @@ async fn connect_and_login(
|
||||
key: &str,
|
||||
token: &str,
|
||||
is_rdp: bool,
|
||||
) -> ResultType<Option<Stream>> {
|
||||
let mut res = connect_and_login_2(
|
||||
id,
|
||||
password,
|
||||
ui_receiver,
|
||||
interface.clone(),
|
||||
forward,
|
||||
key,
|
||||
token,
|
||||
is_rdp,
|
||||
)
|
||||
.await;
|
||||
if res.is_err() && interface.is_force_relay() {
|
||||
res = connect_and_login_2(
|
||||
id,
|
||||
password,
|
||||
ui_receiver,
|
||||
interface,
|
||||
forward,
|
||||
key,
|
||||
token,
|
||||
is_rdp,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
async fn connect_and_login_2(
|
||||
id: &str,
|
||||
password: &str,
|
||||
ui_receiver: &mut mpsc::UnboundedReceiver<Data>,
|
||||
interface: impl Interface,
|
||||
forward: &mut Framed<TcpStream, BytesCodec>,
|
||||
key: &str,
|
||||
token: &str,
|
||||
is_rdp: bool,
|
||||
) -> ResultType<Option<Stream>> {
|
||||
let conn_type = if is_rdp {
|
||||
ConnType::RDP
|
||||
@ -157,6 +120,7 @@ async fn connect_and_login_2(
|
||||
};
|
||||
let (mut stream, direct, _pk) =
|
||||
Client::start(id, key, token, conn_type, interface.clone()).await?;
|
||||
interface.update_direct(Some(direct));
|
||||
let mut interface = interface;
|
||||
let mut buffer = Vec::new();
|
||||
let mut received = false;
|
||||
@ -167,7 +131,10 @@ async fn connect_and_login_2(
|
||||
bail!("Timeout");
|
||||
}
|
||||
Ok(Some(Ok(bytes))) => {
|
||||
received = true;
|
||||
if !received {
|
||||
received = true;
|
||||
interface.update_received(true);
|
||||
}
|
||||
let msg_in = Message::parse_from_bytes(&bytes)?;
|
||||
match msg_in.union {
|
||||
Some(message::Union::Hash(hash)) => {
|
||||
@ -191,8 +158,6 @@ async fn connect_and_login_2(
|
||||
}
|
||||
}
|
||||
Ok(Some(Err(err))) => {
|
||||
log::error!("Connection closed: {}", err);
|
||||
interface.set_force_relay(direct, received, err.to_string());
|
||||
bail!("Connection closed: {}", err);
|
||||
}
|
||||
_ => {
|
||||
|
@ -146,12 +146,6 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.lc.read().unwrap().conn_type.eq(&ConnType::RDP)
|
||||
}
|
||||
|
||||
pub fn set_connection_info(&mut self, direct: bool, received: bool) {
|
||||
let mut lc = self.lc.write().unwrap();
|
||||
lc.direct = Some(direct);
|
||||
lc.received = received;
|
||||
}
|
||||
|
||||
pub fn get_view_style(&self) -> String {
|
||||
self.lc.read().unwrap().view_style.clone()
|
||||
}
|
||||
@ -941,38 +935,6 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
pub fn close_voice_call(&self) {
|
||||
self.send(Data::CloseVoiceCall);
|
||||
}
|
||||
|
||||
pub fn show_relay_hint(
|
||||
&mut self,
|
||||
last_recv_time: tokio::time::Instant,
|
||||
msgtype: &str,
|
||||
title: &str,
|
||||
text: &str,
|
||||
) -> bool {
|
||||
let duration = Duration::from_secs(3);
|
||||
let counter_interval = 3;
|
||||
let lock = self.lc.read().unwrap();
|
||||
let success_time = lock.success_time;
|
||||
let direct = lock.direct.unwrap_or(false);
|
||||
let received = lock.received;
|
||||
drop(lock);
|
||||
if let Some(success_time) = success_time {
|
||||
if direct && last_recv_time.duration_since(success_time) < duration {
|
||||
let retry_for_relay = direct && !received;
|
||||
let retry = check_if_retry(msgtype, title, text, retry_for_relay);
|
||||
if retry && !retry_for_relay {
|
||||
self.lc.write().unwrap().direct_error_counter += 1;
|
||||
if self.lc.read().unwrap().direct_error_counter % counter_interval == 0 {
|
||||
#[cfg(feature = "flutter")]
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.lc.write().unwrap().direct_error_counter = 0;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {
|
||||
@ -1060,9 +1022,9 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
||||
}
|
||||
|
||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str) {
|
||||
let direct = self.lc.read().unwrap().direct.unwrap_or_default();
|
||||
let direct = self.lc.read().unwrap().direct;
|
||||
let received = self.lc.read().unwrap().received;
|
||||
let retry_for_relay = direct && !received;
|
||||
let retry_for_relay = direct == Some(true) && !received;
|
||||
let retry = check_if_retry(msgtype, title, text, retry_for_relay);
|
||||
self.ui_handler.msgbox(msgtype, title, text, link, retry);
|
||||
}
|
||||
@ -1119,7 +1081,6 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
||||
"Connected, waiting for image...",
|
||||
"",
|
||||
);
|
||||
self.lc.write().unwrap().success_time = Some(tokio::time::Instant::now());
|
||||
}
|
||||
self.on_connected(self.lc.read().unwrap().conn_type);
|
||||
#[cfg(windows)]
|
||||
|
Loading…
Reference in New Issue
Block a user