From 1dfbaa1e02e70fc0d7e08153b06ab513cc8a10b7 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 28 Apr 2024 14:22:21 +0800 Subject: [PATCH] fix: test if valid server, control if try test with proxy (#7858) * fix: test if valid server, control if try test with proxy Signed-off-by: fufesou * fix: build Signed-off-by: fufesou --------- Signed-off-by: fufesou --- flutter/lib/common.dart | 8 +-- .../desktop/pages/desktop_setting_page.dart | 7 ++- flutter/lib/mobile/widgets/dialog.dart | 9 --- flutter/lib/web/bridge.dart | 5 +- libs/hbb_common/src/socket_client.rs | 56 ++++++++++--------- src/flutter_ffi.rs | 6 +- src/ui.rs | 6 +- src/ui/index.tis | 6 +- src/ui_interface.rs | 4 +- 9 files changed, 55 insertions(+), 52 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 3106aaaaf..40c4d46e0 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -2978,16 +2978,16 @@ Future setServerConfig( } // id if (config.idServer.isNotEmpty && errMsgs != null) { - errMsgs[0].value = - translate(await bind.mainTestIfValidServer(server: config.idServer)); + errMsgs[0].value = translate(await bind.mainTestIfValidServer( + server: config.idServer, testWithProxy: true)); if (errMsgs[0].isNotEmpty) { return false; } } // relay if (config.relayServer.isNotEmpty && errMsgs != null) { - errMsgs[1].value = - translate(await bind.mainTestIfValidServer(server: config.relayServer)); + errMsgs[1].value = translate(await bind.mainTestIfValidServer( + server: config.relayServer, testWithProxy: true)); if (errMsgs[1].isNotEmpty) { return false; } diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index ba61ef7aa..fab7b56d7 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -2079,7 +2079,12 @@ void changeSocks5Proxy() async { password = pwdController.text.trim(); if (proxy.isNotEmpty) { - proxyMsg = translate(await bind.mainTestIfValidServer(server: proxy)); + String domainPort = proxy; + if (domainPort.contains('://')) { + domainPort = domainPort.split('://')[1]; + } + proxyMsg = translate(await bind.mainTestIfValidServer( + server: domainPort, testWithProxy: false)); if (proxyMsg.isEmpty) { // ignore } else { diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 68d253d7b..391bec669 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -283,12 +283,3 @@ void setPrivacyModeDialog( ); }, backDismiss: true, clickMaskDismiss: true); } - -Future validateAsync(String value) async { - value = value.trim(); - if (value.isEmpty) { - return null; - } - final res = await bind.mainTestIfValidServer(server: value); - return res.isEmpty ? null : res; -} diff --git a/flutter/lib/web/bridge.dart b/flutter/lib/web/bridge.dart index 1ccc266ac..87a478508 100644 --- a/flutter/lib/web/bridge.dart +++ b/flutter/lib/web/bridge.dart @@ -680,7 +680,8 @@ class RustdeskImpl { return Future(() => js.context.callMethod('setByName', ['options', json])); } - Future mainTestIfValidServer({required String server, dynamic hint}) { + Future mainTestIfValidServer( + {required String server, required bool testWithProxy, dynamic hint}) { // TODO: implement return Future.value(''); } @@ -788,7 +789,7 @@ class RustdeskImpl { throw UnimplementedError(); } - Future mainGetHttpStatus({required String url, dynamic hint}){ + Future mainGetHttpStatus({required String url, dynamic hint}) { throw UnimplementedError(); } diff --git a/libs/hbb_common/src/socket_client.rs b/libs/hbb_common/src/socket_client.rs index 668a07d7d..0264b70dd 100644 --- a/libs/hbb_common/src/socket_client.rs +++ b/libs/hbb_common/src/socket_client.rs @@ -1,13 +1,11 @@ use crate::{ config::{Config, NetworkType}, - proxy::IntoProxyScheme, tcp::FramedStream, udp::FramedSocket, ResultType, }; use anyhow::Context; use std::net::SocketAddr; -use log::info; use tokio::net::ToSocketAddrs; use tokio_socks::{IntoTargetAddr, TargetAddr}; @@ -51,25 +49,28 @@ pub fn increase_port(host: T, offset: i32) -> String { host } -pub fn test_if_valid_server(host: &str) -> String { - info!("Testing server validity for host: {}", host); +pub fn test_if_valid_server(host: &str, test_with_proxy: bool) -> String { + let host = check_port(host, 0); use std::net::ToSocketAddrs; - let host = if !host.contains("://") { - // We just add a scheme for testing the domain and port parts, - // we don't care about the scheme, so "http://" is used for simple. - format!("http://{}", host) + if test_with_proxy && NetworkType::ProxySocks == Config::get_network_type() { + test_if_valid_server_for_proxy_(&host) } else { - host.to_string() - }; + match host.to_socket_addrs() { + Err(err) => err.to_string(), + Ok(_) => "".to_owned(), + } + } +} - // Even if the current network type is a proxy type, - // the system DNS should be used to resolve the proxy server address. - host.into_proxy_scheme() - .and_then(|scheme| scheme.get_host_and_port()) - .and_then(|domain| domain.to_socket_addrs().map_err(Into::into)) - .map(|_| "".to_owned()) // on success, return an empty string - .unwrap_or_else(|e| e.to_string()) // on error, convert the error into a string +#[inline] +pub fn test_if_valid_server_for_proxy_(host: &str) -> String { + // `&host.into_target_addr()` is defined in `tokio-socs`, but is a common pattern for testing, + // it can be used for both `socks` and `http` proxy. + match &host.into_target_addr() { + Err(err) => err.to_string(), + Ok(_) => "".to_owned(), + } } pub trait IsResolvedSocketAddr { @@ -254,15 +255,20 @@ mod tests { #[test] fn test_test_if_valid_server() { - assert!(!test_if_valid_server("a").is_empty()); + assert!(!test_if_valid_server("a", false).is_empty()); // on Linux, "1" is resolved to "0.0.0.1" - assert!(test_if_valid_server("1.1.1.1").is_empty()); - assert!(test_if_valid_server("1.1.1.1:1").is_empty()); - assert!(test_if_valid_server("abcd.com:1").is_empty()); - assert!(test_if_valid_server("http://abcd.com:1").is_empty()); - assert!(test_if_valid_server("https://abcd.com:1").is_empty()); - assert!(test_if_valid_server("socks5://abcd.com:1").is_empty()); - assert!(test_if_valid_server("https://1.1.1.1:1").is_empty()); + assert!(test_if_valid_server("1.1.1.1", false).is_empty()); + assert!(test_if_valid_server("1.1.1.1:1", false).is_empty()); + assert!(test_if_valid_server("abcd.com", false).is_empty()); + assert!(test_if_valid_server("abcd.com:1", false).is_empty()); + + // with proxy + // `:0` indicates `let host = check_port(host, 0);` is called. + assert!(test_if_valid_server_for_proxy_("a:0").is_empty()); + assert!(test_if_valid_server_for_proxy_("1.1.1.1:0").is_empty()); + assert!(test_if_valid_server_for_proxy_("1.1.1.1:1").is_empty()); + assert!(test_if_valid_server_for_proxy_("abc.com:0").is_empty()); + assert!(test_if_valid_server_for_proxy_("abcd.com:1").is_empty()); } #[test] diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 518dd47dd..a41e8b7a1 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -809,8 +809,8 @@ pub fn main_set_options(json: String) { } } -pub fn main_test_if_valid_server(server: String) -> String { - test_if_valid_server(server) +pub fn main_test_if_valid_server(server: String, test_with_proxy: bool) -> String { + test_if_valid_server(server, test_with_proxy) } pub fn main_set_socks(proxy: String, username: String, password: String) { @@ -895,7 +895,7 @@ pub fn main_get_api_server() -> String { } pub fn main_http_request(url: String, method: String, body: Option, header: String) { - http_request(url,method, body, header) + http_request(url, method, body, header) } pub fn main_get_local_option(key: String) -> SyncReturn { diff --git a/src/ui.rs b/src/ui.rs index 2e9ea2f91..16a7b1a65 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -272,8 +272,8 @@ impl UI { m } - fn test_if_valid_server(&self, host: String) -> String { - test_if_valid_server(host) + fn test_if_valid_server(&self, host: String, test_with_proxy: bool) -> String { + test_if_valid_server(host, test_with_proxy) } fn get_sound_inputs(&self) -> Value { @@ -689,7 +689,7 @@ impl sciter::EventHandler for UI { fn forget_password(String); fn set_peer_option(String, String, String); fn get_license(); - fn test_if_valid_server(String); + fn test_if_valid_server(String, bool); fn get_sound_inputs(); fn set_options(Value); fn set_option(String, String); diff --git a/src/ui/index.tis b/src/ui/index.tis index f202d0fad..260e23e95 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -441,11 +441,11 @@ class MyIdMenu: Reactor.Component { var key = (res.key || "").trim(); if (id == old_id && relay == old_relay && key == old_key && api == old_api) return; if (id) { - var err = handler.test_if_valid_server(id); + var err = handler.test_if_valid_server(id, true); if (err) return translate("ID Server") + ": " + err; } if (relay) { - var err = handler.test_if_valid_server(relay); + var err = handler.test_if_valid_server(relay, true); if (err) return translate("Relay Server") + ": " + err; } if (api) { @@ -476,7 +476,7 @@ class MyIdMenu: Reactor.Component { var password = (res.password || "").trim(); if (proxy == old_proxy && username == old_username && password == old_password) return; if (proxy) { - var err = handler.test_if_valid_server(proxy); + var err = handler.test_if_valid_server(proxy, false); if (err) return translate("Server") + ": " + err; } handler.set_socks(proxy, username, password); diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 313b6e562..af8655a41 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -280,8 +280,8 @@ pub fn get_options() -> String { } #[inline] -pub fn test_if_valid_server(host: String) -> String { - hbb_common::socket_client::test_if_valid_server(&host) +pub fn test_if_valid_server(host: String, test_with_proxy: bool) -> String { + hbb_common::socket_client::test_if_valid_server(&host, test_with_proxy) } #[inline]