refact: tls, native-tls fallback rustls-tls (#13263)

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2025-11-03 23:21:01 +08:00
committed by GitHub
parent 44a28aa5bd
commit 910dcf2036
70 changed files with 1184 additions and 318 deletions

View File

@@ -1443,7 +1443,8 @@ jobs:
rpm \
unzip \
wget \
xz-utils
xz-utils \
libssl-dev
# we have libopus compiled by us.
apt-get remove -y libopus-dev || true
# output devs
@@ -1723,12 +1724,13 @@ jobs:
unzip \
wget \
xz-utils \
zip
zip \
libssl-dev
# arm-linux needs CMake and vcokg built from source as there
# are no prebuilts available from Kitware and Microsoft
if [ "${{ matrix.job.vcpkg-triplet }}" = "arm-linux" ]; then
# install gcc/g++ 8 for vcpkg and OpenSSL headers for CMake
apt-get install -y gcc-8 g++-8 libssl-dev
apt-get install -y gcc-8 g++-8
# bootstrap CMake amd add it to PATH
git clone --depth 1 https://github.com/kitware/cmake -b "v${{ env.SCITER_ARMV7_CMAKE_VERSION }}" /tmp/cmake
pushd /tmp/cmake

228
Cargo.lock generated
View File

@@ -328,13 +328,13 @@ dependencies = [
[[package]]
name = "async-compression"
version = "0.4.11"
version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5"
checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0"
dependencies = [
"flate2",
"compression-codecs",
"compression-core",
"futures-core",
"memchr",
"pin-project-lite",
"tokio",
]
@@ -1269,6 +1269,23 @@ dependencies = [
"memchr",
]
[[package]]
name = "compression-codecs"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23"
dependencies = [
"compression-core",
"flate2",
"memchr",
]
[[package]]
name = "compression-core"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb"
[[package]]
name = "concurrent-queue"
version = "2.5.0"
@@ -3360,14 +3377,14 @@ dependencies = [
"tokio",
"tokio-native-tls",
"tokio-rustls",
"tokio-socks 0.5.2-3",
"tokio-socks",
"tokio-tungstenite",
"tokio-util",
"toml 0.7.8",
"tungstenite",
"url",
"uuid",
"webpki-roots 1.0.0",
"webpki-roots 1.0.4",
"whoami",
"winapi 0.3.9",
"zstd 0.13.1",
@@ -3521,18 +3538,20 @@ dependencies = [
[[package]]
name = "hyper"
version = "1.6.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
dependencies = [
"atomic-waker",
"bytes",
"futures-channel",
"futures-util",
"futures-core",
"http",
"http-body",
"httparse",
"itoa 1.0.11",
"pin-project-lite",
"pin-utils",
"smallvec",
"tokio",
"want",
@@ -3540,9 +3559,9 @@ dependencies = [
[[package]]
name = "hyper-rustls"
version = "0.27.6"
version = "0.27.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d"
checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
dependencies = [
"http",
"hyper",
@@ -3553,7 +3572,7 @@ dependencies = [
"tokio",
"tokio-rustls",
"tower-service",
"webpki-roots 1.0.0",
"webpki-roots 1.0.4",
]
[[package]]
@@ -3574,17 +3593,21 @@ dependencies = [
[[package]]
name = "hyper-util"
version = "0.1.12"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9f1e950e0d9d1d3c47184416723cf29c0d1f93bd8cccf37e4beb6b44f31710"
checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
dependencies = [
"base64 0.22.1",
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"http",
"http-body",
"hyper",
"ipnet",
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.5.10",
"tokio",
@@ -3753,9 +3776,19 @@ dependencies = [
[[package]]
name = "ipnet"
version = "2.9.0"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
name = "iri-string"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
dependencies = [
"memchr",
"serde 1.0.203",
]
[[package]]
name = "is-terminal"
@@ -4302,12 +4335,6 @@ dependencies = [
"objc",
]
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@@ -5218,6 +5245,15 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "300.5.3+3.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6bad8cd0233b63971e232cc9c5e83039375b8586d2312f31fda85db8f888c2"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.104"
@@ -5226,6 +5262,7 @@ checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
dependencies = [
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
@@ -5939,9 +5976,9 @@ dependencies = [
[[package]]
name = "quinn"
version = "0.11.8"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8"
checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
dependencies = [
"bytes",
"cfg_aliases 0.2.1",
@@ -5959,9 +5996,9 @@ dependencies = [
[[package]]
name = "quinn-proto"
version = "0.11.12"
version = "0.11.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e"
checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31"
dependencies = [
"bytes",
"getrandom 0.3.2",
@@ -5980,9 +6017,9 @@ dependencies = [
[[package]]
name = "quinn-udp"
version = "0.5.12"
version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842"
checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
dependencies = [
"cfg_aliases 0.2.1",
"libc",
@@ -6341,8 +6378,9 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.12.15"
source = "git+https://github.com/rustdesk-org/reqwest#9e859438203a71eb86ddc294fbebfde14cba7f7c"
version = "0.12.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f"
dependencies = [
"async-compression",
"base64 0.22.1",
@@ -6357,18 +6395,14 @@ dependencies = [
"hyper-rustls",
"hyper-tls",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"quinn",
"rustls",
"rustls-native-certs",
"rustls-pemfile",
"rustls-pki-types",
"serde 1.0.203",
"serde_json 1.0.118",
@@ -6377,16 +6411,15 @@ dependencies = [
"tokio",
"tokio-native-tls",
"tokio-rustls",
"tokio-socks 0.5.2",
"tokio-util",
"tower",
"tower-http",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"webpki-roots 0.26.9",
"windows-registry",
"webpki-roots 1.0.4",
]
[[package]]
@@ -6587,6 +6620,7 @@ dependencies = [
"objc",
"objc_id",
"once_cell",
"openssl",
"os-version",
"pam",
"parity-tokio-ipc",
@@ -6725,15 +6759,6 @@ dependencies = [
"security-framework 3.5.1",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.11.0"
@@ -7935,18 +7960,6 @@ dependencies = [
"tokio-util",
]
[[package]]
name = "tokio-socks"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f"
dependencies = [
"either",
"futures-util",
"thiserror 1.0.61",
"tokio",
]
[[package]]
name = "tokio-tungstenite"
version = "0.26.2"
@@ -8082,6 +8095,24 @@ dependencies = [
"tower-service",
]
[[package]]
name = "tower-http"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
dependencies = [
"bitflags 2.9.1",
"bytes",
"futures-util",
"http",
"http-body",
"iri-string",
"pin-project-lite",
"tower",
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
@@ -8867,9 +8898,9 @@ dependencies = [
[[package]]
name = "webpki-roots"
version = "1.0.0"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb"
checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e"
dependencies = [
"rustls-pki-types",
]
@@ -9194,17 +9225,6 @@ dependencies = [
"windows-link",
]
[[package]]
name = "windows-registry"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
dependencies = [
"windows-result 0.3.2",
"windows-strings 0.3.1",
"windows-targets 0.53.0",
]
[[package]]
name = "windows-result"
version = "0.1.2"
@@ -9318,29 +9338,13 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
dependencies = [
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
name = "windows-version"
version = "0.1.1"
@@ -9377,12 +9381,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.32.0"
@@ -9413,12 +9411,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.32.0"
@@ -9449,24 +9441,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.32.0"
@@ -9497,12 +9477,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.32.0"
@@ -9533,12 +9507,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@@ -9557,12 +9525,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.32.0"
@@ -9593,12 +9555,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winit"
version = "0.30.9"

View File

@@ -83,6 +83,8 @@ shutdown_hooks = "0.1"
totp-rs = { version = "5.4", default-features = false, features = ["gen_secret", "otpauth"] }
stunclient = "0.4"
kcp-sys= { git = "https://github.com/rustdesk-org/kcp-sys"}
reqwest = { version = "0.12", features = ["blocking", "socks", "json", "native-tls", "rustls-tls", "rustls-tls-native-roots", "gzip"], default-features=false }
[target.'cfg(not(target_os = "linux"))'.dependencies]
# https://github.com/rustdesk/rustdesk/discussions/10197, not use cpal on linux
cpal = { git = "https://github.com/rustdesk-org/cpal", branch = "osx-screencapturekit" }
@@ -165,13 +167,6 @@ fontdb = "0.23"
bytemuck = "1.23"
ttf-parser = "0.25"
[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies]
# https://github.com/rustdesk/rustdesk-server-pro/issues/189, using native-tls for better tls support
reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "native-tls", "gzip"], default-features=false }
[target.'cfg(not(any(target_os = "macos", target_os = "windows")))'.dependencies]
reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "rustls-tls", "rustls-tls-native-roots", "gzip"], default-features=false }
[target.'cfg(target_os = "linux")'.dependencies]
psimple = { package = "libpulse-simple-binding", version = "2.27" }
pulse = { package = "libpulse-binding", version = "2.27" }
@@ -192,6 +187,9 @@ termios = "0.3"
terminfo = "0.8"
winit = "0.30"
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
openssl = { version = "0.10", features = ["vendored"] }
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.13"
jni = "0.21"

View File

@@ -400,6 +400,8 @@ Future<bool?> loginDialog() async {
String? passwordMsg;
var isInProgress = false;
final RxString curOP = ''.obs;
// Track hover state for the close icon
bool isCloseHovered = false;
final loginOptions = [].obs;
Future.delayed(Duration.zero, () async {
@@ -557,21 +559,27 @@ Future<bool?> loginDialog() async {
Text(
translate('Login'),
).marginOnly(top: MyTheme.dialogPadding),
InkWell(
child: Icon(
Icons.close,
size: 25,
// No need to handle the branch of null.
// Because we can ensure the color is not null when debug.
color: Theme.of(context)
.textTheme
.titleLarge
?.color
?.withOpacity(0.55),
MouseRegion(
onEnter: (_) => setState(() => isCloseHovered = true),
onExit: (_) => setState(() => isCloseHovered = false),
child: InkWell(
child: Icon(
Icons.close,
size: 25,
// No need to handle the branch of null.
// Because we can ensure the color is not null when debug.
color: isCloseHovered
? Colors.white
: Theme.of(context)
.textTheme
.titleLarge
?.color
?.withOpacity(0.55),
),
onTap: onDialogCancel,
hoverColor: Colors.red,
borderRadius: BorderRadius.circular(5),
),
onTap: onDialogCancel,
hoverColor: Colors.red,
borderRadius: BorderRadius.circular(5),
).marginOnly(top: 10, right: 15),
],
);

View File

@@ -162,8 +162,11 @@ const String kOptionShowVirtualJoystick = "show-virtual-joystick";
// network options
const String kOptionAllowWebSocket = "allow-websocket";
const String kOptionAllowInsecureTLSFallback = "allow-insecure-tls-fallback";
const String kOptionDisableUdp = "disable-udp";
const String kOptionEnableFlutterHttpOnRust = "enable-flutter-http-on-rust";
// buildin opitons
// builtin options
const String kOptionHideServerSetting = "hide-server-settings";
const String kOptionHideProxySetting = "hide-proxy-settings";
const String kOptionHideWebSocketSetting = "hide-websocket-settings";

View File

@@ -1585,6 +1585,27 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
);
}
Widget switchWidget(IconData icon, String title, String tooltipMessage,
String optionKey) =>
listTile(
icon: icon,
title: title,
showTooltip: true,
tooltipMessage: tooltipMessage,
trailing: Switch(
value: mainGetBoolOptionSync(optionKey),
onChanged: locked || isOptionFixed(optionKey)
? null
: (value) {
mainSetBoolOption(optionKey, value);
setState(() {});
},
),
);
final outgoingOnly = bind.isOutgoingOnly();
final divider = const Divider(height: 1, indent: 16, endIndent: 16);
return _Card(
title: 'Network',
children: [
@@ -1596,33 +1617,65 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
listTile(
icon: Icons.dns_outlined,
title: 'ID/Relay Server',
onTap: () => showServerSettings(gFFI.dialogManager),
onTap: () => showServerSettings(gFFI.dialogManager, setState),
),
if (!hideServer && (!hideProxy || !hideWebSocket))
Divider(height: 1, indent: 16, endIndent: 16),
if (!hideProxy && !hideServer) divider,
if (!hideProxy)
listTile(
icon: Icons.network_ping_outlined,
title: 'Socks5/Http(s) Proxy',
onTap: changeSocks5Proxy,
),
if (!hideProxy && !hideWebSocket)
Divider(height: 1, indent: 16, endIndent: 16),
if (!hideWebSocket && (!hideServer || !hideProxy)) divider,
if (!hideWebSocket)
listTile(
icon: Icons.web_asset_outlined,
title: 'Use WebSocket',
showTooltip: true,
tooltipMessage: 'websocket_tip',
trailing: Switch(
value: mainGetBoolOptionSync(kOptionAllowWebSocket),
onChanged: locked
? null
: (value) {
mainSetBoolOption(kOptionAllowWebSocket, value);
setState(() {});
},
),
switchWidget(
Icons.web_asset_outlined,
'Use WebSocket',
'${translate('websocket_tip')}\n\n${translate('oss-not-support-tip')}',
kOptionAllowWebSocket),
if (!isWeb)
futureBuilder(
future: bind.mainIsUsingPublicServer(),
hasData: (isUsingPublicServer) {
if (isUsingPublicServer) {
return Offstage();
} else {
return Column(
children: [
if (!hideServer || !hideProxy || !hideWebSocket)
divider,
switchWidget(
Icons.no_encryption_outlined,
'Allow insecure TLS fallback',
'allow-insecure-tls-fallback-tip',
kOptionAllowInsecureTLSFallback),
if (!outgoingOnly) divider,
if (!outgoingOnly)
listTile(
icon: Icons.lan_outlined,
title: 'Disable UDP',
showTooltip: true,
tooltipMessage:
'${translate('disable-udp-tip')}\n\n${translate('oss-not-support-tip')}',
trailing: Switch(
value: bind.mainGetOptionSync(
key: kOptionDisableUdp) ==
'Y',
onChanged:
locked || isOptionFixed(kOptionDisableUdp)
? null
: (value) async {
await bind.mainSetOption(
key: kOptionDisableUdp,
value: value ? 'Y' : 'N');
setState(() {});
},
),
),
],
);
}
},
),
],
),
@@ -1742,9 +1795,9 @@ class _DisplayState extends State<_Display> {
}
Widget trackpadSpeed(BuildContext context) {
final initSpeed = (int.tryParse(
bind.mainGetUserDefaultOption(key: kKeyTrackpadSpeed)) ??
kDefaultTrackpadSpeed);
final initSpeed =
(int.tryParse(bind.mainGetUserDefaultOption(key: kKeyTrackpadSpeed)) ??
kDefaultTrackpadSpeed);
final curSpeed = SimpleWrapper(initSpeed);
void onDebouncer(int v) {
bind.mainSetUserDefaultOption(

View File

@@ -156,7 +156,7 @@ class _ScanPageState extends State<ScanPage> {
try {
final sc = ServerConfig.decode(data.substring(7));
Timer(Duration(milliseconds: 60), () {
showServerSettingsWithValue(sc, gFFI.dialogManager);
showServerSettingsWithValue(sc, gFFI.dialogManager, null);
});
} catch (e) {
showToast('Invalid QR code');

View File

@@ -94,7 +94,10 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
var _hideWebSocket = false;
var _enableTrustedDevices = false;
var _enableUdpPunch = false;
var _allowInsecureTlsFallback = false;
var _disableUdp = false;
var _enableIpv6Punch = false;
var _isUsingPublicServer = false;
_SettingsState() {
_enableAbr = option2bool(
@@ -109,6 +112,9 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
_enableHardwareCodec = option2bool(kOptionEnableHwcodec,
bind.mainGetOptionSync(key: kOptionEnableHwcodec));
_allowWebSocket = mainGetBoolOptionSync(kOptionAllowWebSocket);
_allowInsecureTlsFallback =
mainGetBoolOptionSync(kOptionAllowInsecureTLSFallback);
_disableUdp = bind.mainGetOptionSync(key: kOptionDisableUdp) == 'Y';
_autoRecordIncomingSession = option2bool(kOptionAllowAutoRecordIncoming,
bind.mainGetOptionSync(key: kOptionAllowAutoRecordIncoming));
_autoRecordOutgoingSession = option2bool(kOptionAllowAutoRecordOutgoing,
@@ -200,6 +206,13 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
update = true;
_buildDate = buildDate;
}
final isUsingPublicServer = await bind.mainIsUsingPublicServer();
if (_isUsingPublicServer != isUsingPublicServer) {
update = true;
_isUsingPublicServer = isUsingPublicServer;
}
if (update) {
setState(() {});
}
@@ -667,7 +680,10 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
title: Text(translate('ID/Relay Server')),
leading: Icon(Icons.cloud),
onPressed: (context) {
showServerSettings(gFFI.dialogManager);
showServerSettings(gFFI.dialogManager, (callback) async {
_isUsingPublicServer = await bind.mainIsUsingPublicServer();
setState(callback);
});
}),
if (!isIOS && !_hideNetwork && !_hideProxy)
SettingsTile(
@@ -691,6 +707,38 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
});
},
),
if (!_isUsingPublicServer)
SettingsTile.switchTile(
title: Text(translate('Allow insecure TLS fallback')),
initialValue: _allowInsecureTlsFallback,
onToggle: isOptionFixed(kOptionAllowInsecureTLSFallback)
? null
: (v) async {
await mainSetBoolOption(
kOptionAllowInsecureTLSFallback, v);
final newValue = mainGetBoolOptionSync(
kOptionAllowInsecureTLSFallback);
setState(() {
_allowInsecureTlsFallback = newValue;
});
},
),
if (isAndroid && !outgoingOnly && !_isUsingPublicServer)
SettingsTile.switchTile(
title: Text(translate('Disable UDP')),
initialValue: _disableUdp,
onToggle: isOptionFixed(kOptionDisableUdp)
? null
: (v) async {
await bind.mainSetOption(
key: kOptionDisableUdp, value: v ? 'Y' : 'N');
final newValue =
bind.mainGetOptionSync(key: kOptionDisableUdp) == 'Y';
setState(() {
_disableUdp = newValue;
});
},
),
if (!incomingOnly)
SettingsTile.switchTile(
title: Text(translate('Enable UDP hole punching')),

View File

@@ -147,18 +147,22 @@ void setTemporaryPasswordLengthDialog(
}, backDismiss: true, clickMaskDismiss: true);
}
void showServerSettings(OverlayDialogManager dialogManager) async {
void showServerSettings(OverlayDialogManager dialogManager,
void Function(VoidCallback) setState) async {
Map<String, dynamic> options = {};
try {
options = jsonDecode(await bind.mainGetOptions());
} catch (e) {
print("Invalid server config: $e");
}
showServerSettingsWithValue(ServerConfig.fromOptions(options), dialogManager);
showServerSettingsWithValue(
ServerConfig.fromOptions(options), dialogManager, setState);
}
void showServerSettingsWithValue(
ServerConfig serverConfig, OverlayDialogManager dialogManager) async {
ServerConfig serverConfig,
OverlayDialogManager dialogManager,
void Function(VoidCallback)? upSetState) async {
var isInProgress = false;
final idCtrl = TextEditingController(text: serverConfig.idServer);
final relayCtrl = TextEditingController(text: serverConfig.relayServer);
@@ -288,6 +292,7 @@ void showServerSettingsWithValue(
if (await submit()) {
close();
showToast(translate('Successful'));
upSetState?.call(() {});
} else {
showToast(translate('Failed'));
}

View File

@@ -1,7 +1,9 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:http/http.dart' as http;
import '../models/platform_model.dart';
import 'package:flutter_hbb/common.dart';
export 'package:http/http.dart' show Response;
enum HttpMethod { get, post, put, delete }
@@ -15,11 +17,19 @@ class HttpService {
}) async {
headers ??= {'Content-Type': 'application/json'};
// Determine if there is currently a proxy setting, and if so, use FFI to call the Rust HTTP method.
final isProxy = await bind.mainGetProxyStatus();
// Use Rust HTTP implementation for non-web platforms for consistency.
var useFlutterHttp = (isWeb || kIsWeb);
if (!useFlutterHttp) {
final enableFlutterHttpOnRust =
mainGetLocalBoolOptionSync(kOptionEnableFlutterHttpOnRust);
// Use flutter http if:
// Not `enableFlutterHttpOnRust` and no proxy is set
useFlutterHttp =
!(enableFlutterHttpOnRust || await bind.mainGetProxyStatus());
}
if (!isProxy) {
return await _pollFultterHttp(url, method, headers: headers, body: body);
if (useFlutterHttp) {
return await _pollFlutterHttp(url, method, headers: headers, body: body);
}
String headersJson = jsonEncode(headers);
@@ -34,7 +44,7 @@ class HttpService {
return _parseHttpResponse(resJson);
}
Future<http.Response> _pollFultterHttp(
Future<http.Response> _pollFlutterHttp(
Uri url,
HttpMethod method, {
Map<String, String>? headers,
@@ -87,7 +97,8 @@ class HttpService {
int statusCode = parsedJson['status_code'];
return http.Response(body, statusCode, headers: headers);
} catch (e) {
throw Exception('Failed to parse response: $e');
print('Failed to parse response\n$responseJson\nError:\n$e');
throw Exception('Failed to parse response.\n$responseJson');
}
}
}

View File

@@ -13,6 +13,7 @@ use hbb_common::whoami;
use hbb_common::{
allow_err,
anyhow::{anyhow, Context},
async_recursion::async_recursion,
bail, base64,
bytes::Bytes,
config::{
@@ -27,6 +28,7 @@ use hbb_common::{
socket_client,
sodiumoxide::crypto::{box_, secretbox, sign},
timeout,
tls::{get_cached_tls_accept_invalid_cert, get_cached_tls_type, upsert_tls_cache, TlsType},
tokio::{
self,
net::UdpSocket,
@@ -36,7 +38,7 @@ use hbb_common::{
};
use crate::{
hbbs_http::create_http_client_async,
hbbs_http::{create_http_client_async, get_url_for_tls},
ui_interface::{get_option, set_option},
};
@@ -908,15 +910,35 @@ pub fn check_software_update() {
}
}
// No need to check `danger_accept_invalid_cert` for now.
// Because the url is always `https://api.rustdesk.com/version/latest`.
#[tokio::main(flavor = "current_thread")]
pub async fn do_check_software_update() -> hbb_common::ResultType<()> {
let (request, url) =
hbb_common::version_check_request(hbb_common::VER_TYPE_RUSTDESK_CLIENT.to_string());
let latest_release_response = create_http_client_async()
.post(url)
.json(&request)
.send()
.await?;
let proxy_conf = Config::get_socks();
let tls_url = get_url_for_tls(&url, &proxy_conf);
let tls_type = get_cached_tls_type(tls_url);
let is_tls_not_cached = tls_type.is_none();
let tls_type = tls_type.unwrap_or(TlsType::Rustls);
let client = create_http_client_async(tls_type, false);
let latest_release_response = match client.post(&url).json(&request).send().await {
Ok(resp) => {
upsert_tls_cache(tls_url, tls_type, false);
resp
}
Err(err) => {
if is_tls_not_cached && err.is_request() {
let tls_type = TlsType::NativeTls;
let client = create_http_client_async(tls_type, false);
let resp = client.post(&url).json(&request).send().await?;
upsert_tls_cache(tls_url, tls_type, false);
resp
} else {
return Err(err.into());
}
}
};
let bytes = latest_release_response.bytes().await?;
let resp: hbb_common::VersionCheckResponse = serde_json::from_slice(&bytes)?;
let response_url = resp.url;
@@ -1067,7 +1089,38 @@ pub fn get_audit_server(api: String, custom: String, typ: String) -> String {
}
pub async fn post_request(url: String, body: String, header: &str) -> ResultType<String> {
let mut req = create_http_client_async().post(url);
let proxy_conf = Config::get_socks();
let tls_url = get_url_for_tls(&url, &proxy_conf);
let tls_type = get_cached_tls_type(tls_url);
let danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(tls_url);
let response = post_request_(
&url,
tls_url,
body.clone(),
header,
tls_type,
danger_accept_invalid_cert,
danger_accept_invalid_cert,
)
.await?;
Ok(response.text().await?)
}
#[async_recursion]
async fn post_request_(
url: &str,
tls_url: &str,
body: String,
header: &str,
tls_type: Option<TlsType>,
danger_accept_invalid_cert: Option<bool>,
original_danger_accept_invalid_cert: Option<bool>,
) -> ResultType<reqwest::Response> {
let mut req = create_http_client_async(
tls_type.unwrap_or(TlsType::Rustls),
danger_accept_invalid_cert.unwrap_or(false),
)
.post(url);
if !header.is_empty() {
let tmp: Vec<&str> = header.split(": ").collect();
if tmp.len() == 2 {
@@ -1076,7 +1129,66 @@ pub async fn post_request(url: String, body: String, header: &str) -> ResultType
}
req = req.header("Content-Type", "application/json");
let to = std::time::Duration::from_secs(12);
Ok(req.body(body).timeout(to).send().await?.text().await?)
if tls_type.is_some() && danger_accept_invalid_cert.is_some() {
// This branch is used to reduce a `clone()` when both `tls_type` and
// `danger_accept_invalid_cert` are cached.
match req.body(body.clone()).timeout(to).send().await {
Ok(resp) => {
upsert_tls_cache(
tls_url,
tls_type.unwrap_or(TlsType::Rustls),
danger_accept_invalid_cert.unwrap_or(false),
);
Ok(resp)
}
Err(e) => Err(anyhow!("{:?}", e)),
}
} else {
match req.body(body.clone()).timeout(to).send().await {
Ok(resp) => {
upsert_tls_cache(
tls_url,
tls_type.unwrap_or(TlsType::Rustls),
danger_accept_invalid_cert.unwrap_or(false),
);
Ok(resp)
}
Err(e) => {
if (tls_type.is_none() || danger_accept_invalid_cert.is_none()) && e.is_request() {
if danger_accept_invalid_cert.is_none() {
log::warn!(
"HTTP request failed: {:?}, try again, danger accept invalid cert",
e
);
post_request_(
url,
tls_url,
body,
header,
tls_type,
Some(true),
original_danger_accept_invalid_cert,
)
.await
} else {
log::warn!("HTTP request failed: {:?}, try again with native-tls", e);
post_request_(
url,
tls_url,
body,
header,
Some(TlsType::NativeTls),
original_danger_accept_invalid_cert,
original_danger_accept_invalid_cert,
)
.await
}
} else {
Err(anyhow!("{:?}", e))
}
}
}
}
}
#[tokio::main(flavor = "current_thread")]
@@ -1084,22 +1196,29 @@ pub async fn post_request_sync(url: String, body: String, header: &str) -> Resul
post_request(url, body, header).await
}
#[tokio::main(flavor = "current_thread")]
pub async fn http_request_sync(
url: String,
method: String,
#[async_recursion]
async fn get_http_response_async(
url: &str,
tls_url: &str,
method: &str,
body: Option<String>,
header: String,
) -> ResultType<String> {
let http_client = create_http_client_async();
let mut http_client = match method.as_str() {
header: &str,
tls_type: Option<TlsType>,
danger_accept_invalid_cert: Option<bool>,
original_danger_accept_invalid_cert: Option<bool>,
) -> ResultType<reqwest::Response> {
let http_client = create_http_client_async(
tls_type.unwrap_or(TlsType::Rustls),
danger_accept_invalid_cert.unwrap_or(false),
);
let mut http_client = match method {
"get" => http_client.get(url),
"post" => http_client.post(url),
"put" => http_client.put(url),
"delete" => http_client.delete(url),
_ => return Err(anyhow!("The HTTP request method is not supported!")),
};
let v = serde_json::from_str(header.as_str())?;
let v = serde_json::from_str(header)?;
if let Value::Object(obj) = v {
for (key, value) in obj.iter() {
@@ -1109,15 +1228,105 @@ pub async fn http_request_sync(
return Err(anyhow!("HTTP header information parsing failed!"));
}
if let Some(b) = body {
http_client = http_client.body(b);
if tls_type.is_some() && danger_accept_invalid_cert.is_some() {
if let Some(b) = body {
http_client = http_client.body(b);
}
match http_client
.timeout(std::time::Duration::from_secs(12))
.send()
.await
{
Ok(resp) => {
upsert_tls_cache(
tls_url,
tls_type.unwrap_or(TlsType::Rustls),
danger_accept_invalid_cert.unwrap_or(false),
);
Ok(resp)
}
Err(e) => Err(anyhow!("{:?}", e)),
}
} else {
if let Some(b) = body.clone() {
http_client = http_client.body(b);
}
match http_client
.timeout(std::time::Duration::from_secs(12))
.send()
.await
{
Ok(resp) => {
upsert_tls_cache(
tls_url,
tls_type.unwrap_or(TlsType::Rustls),
danger_accept_invalid_cert.unwrap_or(false),
);
Ok(resp)
}
Err(e) => {
if (tls_type.is_none() || danger_accept_invalid_cert.is_none()) && e.is_request() {
if danger_accept_invalid_cert.is_none() {
log::warn!(
"HTTP request failed: {:?}, try again, danger accept invalid cert",
e
);
get_http_response_async(
url,
tls_url,
method,
body,
header,
tls_type,
Some(true),
original_danger_accept_invalid_cert,
)
.await
} else {
log::warn!("HTTP request failed: {:?}, try again with native-tls", e);
get_http_response_async(
url,
tls_url,
method,
body,
header,
Some(TlsType::NativeTls),
original_danger_accept_invalid_cert,
original_danger_accept_invalid_cert,
)
.await
}
} else {
Err(anyhow!("{:?}", e))
}
}
}
}
}
let response = http_client
.timeout(std::time::Duration::from_secs(12))
.send()
.await?;
#[tokio::main(flavor = "current_thread")]
pub async fn http_request_sync(
url: String,
method: String,
body: Option<String>,
header: String,
) -> ResultType<String> {
let proxy_conf = Config::get_socks();
let tls_url = get_url_for_tls(&url, &proxy_conf);
let tls_type = get_cached_tls_type(tls_url);
let danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(tls_url);
let response = get_http_response_async(
&url,
tls_url,
&method,
body.clone(),
&header,
tls_type,
danger_accept_invalid_cert,
danger_accept_invalid_cert,
)
.await?;
// Serialize response headers
let mut response_headers = serde_json::map::Map::new();
for (key, value) in response.headers() {
@@ -1772,7 +1981,7 @@ pub fn verify_login(_raw: &str, _id: &str) -> bool {
#[inline]
pub fn is_udp_disabled() -> bool {
get_builtin_option(keys::OPTION_DISABLE_UDP) == "Y"
Config::get_option(keys::OPTION_DISABLE_UDP) == "Y"
}
// this crate https://github.com/yoshd/stun-client supports nat type

View File

@@ -951,10 +951,19 @@ pub fn main_set_option(key: String, value: String) {
);
}
if key.eq("custom-rendezvous-server")
// If `is_allow_tls_fallback` and https proxy is used, we need to restart rendezvous mediator.
// No need to check if https proxy is used, because this option does not change frequently
// and restarting mediator is safe even https proxy is not used.
let is_allow_tls_fallback = key.eq(config::keys::OPTION_ALLOW_INSECURE_TLS_FALLBACK);
if is_allow_tls_fallback
|| key.eq("custom-rendezvous-server")
|| key.eq(config::keys::OPTION_ALLOW_WEBSOCKET)
|| key.eq(config::keys::OPTION_DISABLE_UDP)
|| key.eq("api-server")
{
if is_allow_tls_fallback {
hbb_common::tls::reset_tls_cache();
}
set_option(key, value.clone());
#[cfg(target_os = "android")]
crate::rendezvous_mediator::RendezvousMediator::restart();
@@ -2692,7 +2701,11 @@ pub fn session_get_common_sync(
SyncReturn(session_get_common(session_id, key, param))
}
pub fn session_get_common(session_id: SessionID, key: String, #[allow(unused_variables)] param: String) -> Option<String> {
pub fn session_get_common(
session_id: SessionID,
key: String,
#[allow(unused_variables)] param: String,
) -> Option<String> {
if let Some(s) = sessions::get_session_by_session_id(&session_id) {
let v = if key == "is_screenshot_supported" {
s.is_screenshot_supported().to_string()

View File

@@ -4,12 +4,14 @@ use serde_json::{Map, Value};
#[cfg(feature = "flutter")]
pub mod account;
pub mod downloader;
mod http_client;
pub mod record_upload;
pub mod sync;
pub mod downloader;
pub use http_client::create_http_client;
pub use http_client::create_http_client_async;
pub use http_client::{
create_http_client_async, create_http_client_async_with_url, create_http_client_with_url,
get_url_for_tls,
};
#[derive(Debug)]
pub enum HbbHttpResponse<T> {

View File

@@ -1,5 +1,5 @@
use super::HbbHttpResponse;
use crate::hbbs_http::create_http_client;
use crate::hbbs_http::create_http_client_with_url;
use hbb_common::{config::LocalConfig, log, ResultType};
use reqwest::blocking::Client;
use serde_derive::{Deserialize, Serialize};
@@ -104,7 +104,7 @@ pub struct AuthBody {
}
pub struct OidcSession {
client: Client,
client: Option<Client>,
state_msg: &'static str,
failed_msg: String,
code_url: Option<OidcAuthUrl>,
@@ -131,7 +131,7 @@ impl Default for UserStatus {
impl OidcSession {
fn new() -> Self {
Self {
client: create_http_client(),
client: None,
state_msg: REQUESTING_ACCOUNT_AUTH,
failed_msg: "".to_owned(),
code_url: None,
@@ -142,24 +142,36 @@ impl OidcSession {
}
}
fn ensure_client(api_server: &str) {
let mut write_guard = OIDC_SESSION.write().unwrap();
if write_guard.client.is_none() {
// This URL is used to detect the appropriate TLS implementation for the server.
let login_option_url = format!("{}/api/login-options", &api_server);
let client = create_http_client_with_url(&login_option_url);
write_guard.client = Some(client);
}
}
fn auth(
api_server: &str,
op: &str,
id: &str,
uuid: &str,
) -> ResultType<HbbHttpResponse<OidcAuthUrl>> {
let resp = OIDC_SESSION
.read()
.unwrap()
.client
.post(format!("{}/api/oidc/auth", api_server))
.json(&serde_json::json!({
"op": op,
"id": id,
"uuid": uuid,
"deviceInfo": crate::ui_interface::get_login_device_info(),
}))
.send()?;
Self::ensure_client(api_server);
let resp = if let Some(client) = &OIDC_SESSION.read().unwrap().client {
client
.post(format!("{}/api/oidc/auth", api_server))
.json(&serde_json::json!({
"op": op,
"id": id,
"uuid": uuid,
"deviceInfo": crate::ui_interface::get_login_device_info(),
}))
.send()?
} else {
hbb_common::bail!("http client not initialized");
};
let status = resp.status();
match resp.try_into() {
Ok(v) => Ok(v),
@@ -179,13 +191,12 @@ impl OidcSession {
&format!("{}/api/oidc/auth-query", api_server),
&[("code", code), ("id", id), ("uuid", uuid)],
)?;
Ok(OIDC_SESSION
.read()
.unwrap()
.client
.get(url)
.send()?
.try_into()?)
Self::ensure_client(api_server);
if let Some(client) = &OIDC_SESSION.read().unwrap().client {
Ok(client.get(url).send()?.try_into()?)
} else {
hbb_common::bail!("http client not initialized")
}
}
fn reset(&mut self) {

View File

@@ -1,4 +1,4 @@
use super::create_http_client_async;
use super::create_http_client_async_with_url;
use hbb_common::{
bail,
lazy_static::lazy_static,
@@ -132,7 +132,7 @@ async fn do_download(
auto_del_dur: Option<Duration>,
mut rx_cancel: UnboundedReceiver<()>,
) -> ResultType<bool> {
let client = create_http_client_async();
let client = create_http_client_async_with_url(&url).await;
let mut is_all_downloaded = false;
tokio::select! {

View File

@@ -1,23 +1,49 @@
use hbb_common::config::Config;
use hbb_common::log::info;
use hbb_common::proxy::{Proxy, ProxyScheme};
use reqwest::blocking::Client as SyncClient;
use reqwest::Client as AsyncClient;
use hbb_common::{
async_recursion::async_recursion,
config::{Config, Socks5Server},
log::{self, info},
proxy::{Proxy, ProxyScheme},
tls::{
get_cached_tls_accept_invalid_cert, get_cached_tls_type, is_plain, upsert_tls_cache,
TlsType,
},
};
use reqwest::{blocking::Client as SyncClient, Client as AsyncClient};
macro_rules! configure_http_client {
($builder:expr, $Client: ty) => {{
($builder:expr, $tls_type:expr, $danger_accept_invalid_cert:expr, $Client: ty) => {{
// https://github.com/rustdesk/rustdesk/issues/11569
// https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.no_proxy
let mut builder = $builder.no_proxy();
#[cfg(any(target_os = "android", target_os = "ios"))]
match hbb_common::verifier::client_config() {
Ok(client_config) => {
builder = builder.use_preconfigured_tls(client_config);
match $tls_type {
TlsType::Plain => {}
TlsType::NativeTls => {
builder = builder.use_native_tls();
if $danger_accept_invalid_cert {
builder = builder.danger_accept_invalid_certs(true);
}
}
Err(e) => {
hbb_common::log::error!("Failed to get client config: {}", e);
TlsType::Rustls => {
#[cfg(any(target_os = "android", target_os = "ios"))]
match hbb_common::verifier::client_config($danger_accept_invalid_cert) {
Ok(client_config) => {
builder = builder.use_preconfigured_tls(client_config);
}
Err(e) => {
hbb_common::log::error!("Failed to get client config: {}", e);
}
}
#[cfg(not(any(target_os = "android", target_os = "ios")))]
{
builder = builder.use_rustls_tls();
if $danger_accept_invalid_cert {
builder = builder.danger_accept_invalid_certs(true);
}
}
}
}
let client = if let Some(conf) = Config::get_socks() {
let proxy_result = Proxy::from_conf(&conf, None);
@@ -70,12 +96,241 @@ macro_rules! configure_http_client {
}};
}
pub fn create_http_client() -> SyncClient {
pub fn create_http_client(tls_type: TlsType, danger_accept_invalid_cert: bool) -> SyncClient {
let builder = SyncClient::builder();
configure_http_client!(builder, SyncClient)
configure_http_client!(builder, tls_type, danger_accept_invalid_cert, SyncClient)
}
pub fn create_http_client_async() -> AsyncClient {
pub fn create_http_client_async(
tls_type: TlsType,
danger_accept_invalid_cert: bool,
) -> AsyncClient {
let builder = AsyncClient::builder();
configure_http_client!(builder, AsyncClient)
configure_http_client!(builder, tls_type, danger_accept_invalid_cert, AsyncClient)
}
pub fn get_url_for_tls<'a>(url: &'a str, proxy_conf: &'a Option<Socks5Server>) -> &'a str {
if is_plain(url) {
if let Some(conf) = proxy_conf {
if conf.proxy.starts_with("https://") {
return &conf.proxy;
}
}
}
url
}
pub fn create_http_client_with_url(url: &str) -> SyncClient {
let proxy_conf = Config::get_socks();
let tls_url = get_url_for_tls(url, &proxy_conf);
let tls_type = get_cached_tls_type(tls_url);
let is_tls_type_cached = tls_type.is_some();
let tls_type = tls_type.unwrap_or(TlsType::Rustls);
let tls_danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(tls_url);
create_http_client_with_url_(
url,
tls_url,
tls_type,
is_tls_type_cached,
tls_danger_accept_invalid_cert,
tls_danger_accept_invalid_cert,
)
}
fn create_http_client_with_url_(
url: &str,
tls_url: &str,
tls_type: TlsType,
is_tls_type_cached: bool,
danger_accept_invalid_cert: Option<bool>,
original_danger_accept_invalid_cert: Option<bool>,
) -> SyncClient {
let mut client = create_http_client(tls_type, danger_accept_invalid_cert.unwrap_or(false));
if is_tls_type_cached && original_danger_accept_invalid_cert.is_some() {
return client;
}
if let Err(e) = client.head(url).send() {
if e.is_request() {
match (tls_type, is_tls_type_cached, danger_accept_invalid_cert) {
(TlsType::Rustls, _, None) => {
log::warn!(
"Failed to connect to server {} with rustls-tls: {:?}, trying accept invalid cert",
tls_url,
e
);
client = create_http_client_with_url_(
url,
tls_url,
tls_type,
is_tls_type_cached,
Some(true),
original_danger_accept_invalid_cert,
);
}
(TlsType::Rustls, false, Some(_)) => {
log::warn!(
"Failed to connect to server {} with rustls-tls: {:?}, trying native-tls",
tls_url,
e
);
client = create_http_client_with_url_(
url,
tls_url,
TlsType::NativeTls,
is_tls_type_cached,
original_danger_accept_invalid_cert,
original_danger_accept_invalid_cert,
);
}
(TlsType::NativeTls, _, None) => {
log::warn!(
"Failed to connect to server {} with native-tls: {:?}, trying accept invalid cert",
tls_url,
e
);
client = create_http_client_with_url_(
url,
tls_url,
tls_type,
is_tls_type_cached,
Some(true),
original_danger_accept_invalid_cert,
);
}
_ => {
log::error!(
"Failed to connect to server {} with {:?}, err: {:?}.",
tls_url,
tls_type,
e
);
}
}
} else {
log::warn!(
"Failed to connect to server {} with {:?}, err: {}.",
tls_url,
tls_type,
e
);
}
} else {
log::info!(
"Successfully connected to server {} with {:?}",
tls_url,
tls_type
);
upsert_tls_cache(
tls_url,
tls_type,
danger_accept_invalid_cert.unwrap_or(false),
);
}
client
}
pub async fn create_http_client_async_with_url(url: &str) -> AsyncClient {
let proxy_conf = Config::get_socks();
let tls_url = get_url_for_tls(url, &proxy_conf);
let tls_type = get_cached_tls_type(tls_url);
let is_tls_type_cached = tls_type.is_some();
let tls_type = tls_type.unwrap_or(TlsType::Rustls);
let danger_accept_invalid_cert = get_cached_tls_accept_invalid_cert(tls_url);
create_http_client_async_with_url_(
url,
tls_url,
tls_type,
is_tls_type_cached,
danger_accept_invalid_cert,
danger_accept_invalid_cert,
)
.await
}
#[async_recursion]
async fn create_http_client_async_with_url_(
url: &str,
tls_url: &str,
tls_type: TlsType,
is_tls_type_cached: bool,
danger_accept_invalid_cert: Option<bool>,
original_danger_accept_invalid_cert: Option<bool>,
) -> AsyncClient {
let mut client =
create_http_client_async(tls_type, danger_accept_invalid_cert.unwrap_or(false));
if is_tls_type_cached && original_danger_accept_invalid_cert.is_some() {
return client;
}
if let Err(e) = client.head(url).send().await {
match (tls_type, is_tls_type_cached, danger_accept_invalid_cert) {
(TlsType::Rustls, _, None) => {
log::warn!(
"Failed to connect to server {} with rustls-tls: {:?}, trying accept invalid cert",
tls_url,
e
);
client = create_http_client_async_with_url_(
url,
tls_url,
tls_type,
is_tls_type_cached,
Some(true),
original_danger_accept_invalid_cert,
)
.await;
}
(TlsType::Rustls, false, Some(_)) => {
log::warn!(
"Failed to connect to server {} with rustls-tls: {:?}, trying native-tls",
tls_url,
e
);
client = create_http_client_async_with_url_(
url,
tls_url,
TlsType::NativeTls,
is_tls_type_cached,
original_danger_accept_invalid_cert,
original_danger_accept_invalid_cert,
)
.await;
}
(TlsType::NativeTls, _, None) => {
log::warn!(
"Failed to connect to server {} with native-tls: {:?}, trying accept invalid cert",
tls_url,
e
);
client = create_http_client_async_with_url_(
url,
tls_url,
tls_type,
is_tls_type_cached,
Some(true),
original_danger_accept_invalid_cert,
)
.await;
}
_ => {
log::error!(
"Failed to connect to server {} with {:?}, err: {:?}.",
tls_url,
tls_type,
e
);
}
}
} else {
log::info!(
"Successfully connected to server {} with {:?}",
tls_url,
tls_type
);
upsert_tls_cache(
tls_url,
tls_type,
danger_accept_invalid_cert.unwrap_or(false),
);
}
client
}

View File

@@ -1,4 +1,4 @@
use crate::hbbs_http::create_http_client;
use crate::hbbs_http::create_http_client_with_url;
use bytes::Bytes;
use hbb_common::{bail, config::Config, lazy_static, log, ResultType};
use reqwest::blocking::{Body, Client};
@@ -25,51 +25,57 @@ pub fn is_enable() -> bool {
}
pub fn run(rx: Receiver<RecordState>) {
let mut uploader = RecordUploader {
client: create_http_client(),
api_server: crate::get_api_server(
std::thread::spawn(move || {
let api_server = crate::get_api_server(
Config::get_option("api-server"),
Config::get_option("custom-rendezvous-server"),
),
filepath: Default::default(),
filename: Default::default(),
upload_size: Default::default(),
running: Default::default(),
last_send: Instant::now(),
};
std::thread::spawn(move || loop {
if let Err(e) = match rx.recv() {
Ok(state) => match state {
RecordState::NewFile(filepath) => uploader.handle_new_file(filepath),
RecordState::NewFrame => {
if uploader.running {
uploader.handle_frame(false)
} else {
Ok(())
);
// This URL is used for TLS connectivity testing and fallback detection.
let login_option_url = format!("{}/api/login-options", &api_server);
let client = create_http_client_with_url(&login_option_url);
let mut uploader = RecordUploader {
client,
api_server,
filepath: Default::default(),
filename: Default::default(),
upload_size: Default::default(),
running: Default::default(),
last_send: Instant::now(),
};
loop {
if let Err(e) = match rx.recv() {
Ok(state) => match state {
RecordState::NewFile(filepath) => uploader.handle_new_file(filepath),
RecordState::NewFrame => {
if uploader.running {
uploader.handle_frame(false)
} else {
Ok(())
}
}
}
RecordState::WriteTail => {
if uploader.running {
uploader.handle_tail()
} else {
Ok(())
RecordState::WriteTail => {
if uploader.running {
uploader.handle_tail()
} else {
Ok(())
}
}
}
RecordState::RemoveFile => {
if uploader.running {
uploader.handle_remove()
} else {
Ok(())
RecordState::RemoveFile => {
if uploader.running {
uploader.handle_remove()
} else {
Ok(())
}
}
},
Err(e) => {
log::trace!("upload thread stop: {}", e);
break;
}
},
Err(e) => {
log::trace!("upload thread stop: {}", e);
break;
} {
uploader.running = false;
log::error!("upload stop: {}", e);
}
} {
uploader.running = false;
log::error!("upload stop: {}", e);
}
});
}

View File

@@ -363,6 +363,8 @@ pub struct CheckIfRestart {
audio_input: String,
voice_call_input: String,
ws: String,
disable_udp: String,
allow_insecure_tls_fallback: String,
api_server: String,
}
@@ -374,17 +376,31 @@ impl CheckIfRestart {
audio_input: Config::get_option("audio-input"),
voice_call_input: Config::get_option("voice-call-input"),
ws: Config::get_option(OPTION_ALLOW_WEBSOCKET),
disable_udp: Config::get_option(config::keys::OPTION_DISABLE_UDP),
allow_insecure_tls_fallback: Config::get_option(
config::keys::OPTION_ALLOW_INSECURE_TLS_FALLBACK,
),
api_server: Config::get_option("api-server"),
}
}
}
impl Drop for CheckIfRestart {
fn drop(&mut self) {
if self.stop_service != Config::get_option("stop-service")
// If https proxy is used, we need to restart rendezvous mediator.
// No need to check if https proxy is used, because this option does not change frequently
// and restarting mediator is safe even https proxy is not used.
let allow_insecure_tls_fallback_changed = self.allow_insecure_tls_fallback
!= Config::get_option(config::keys::OPTION_ALLOW_INSECURE_TLS_FALLBACK);
if allow_insecure_tls_fallback_changed
|| self.stop_service != Config::get_option("stop-service")
|| self.rendezvous_servers != Config::get_rendezvous_servers()
|| self.ws != Config::get_option(OPTION_ALLOW_WEBSOCKET)
|| self.disable_udp != Config::get_option(config::keys::OPTION_DISABLE_UDP)
|| self.api_server != Config::get_option("api-server")
{
if allow_insecure_tls_fallback_changed {
hbb_common::tls::reset_tls_cache();
}
RendezvousMediator::restart();
}
if self.audio_input != Config::get_option("audio-input") {

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Edita la nota"),
("Alias", "Alias"),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -721,6 +721,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Show virtual joystick", "显示虚拟摇杆"),
("Edit note", "编辑备注"),
("Alias", "别名"),
("ScrollEdge", ""),
("ScrollEdge", "边缘滚动"),
("Allow insecure TLS fallback", "允许回退到不安全的 TLS 连接"),
("allow-insecure-tls-fallback-tip", "默认情况下,对于使用 TLS 的协议RustDesk 会验证服务器证书。\n启用此选项后在验证失败时RustDesk 将转为跳过验证步骤并继续连接。"),
("Disable UDP", "禁用 UDP"),
("disable-udp-tip", "控制是否仅使用TCP。\n启用此选项后RustDesk 将不再使用UDP 21116而是使用TCP 21116。"),
("oss-not-support-tip", "注意RustDesk 开源服务器(oss server) 不包含此功能。"),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Hinweis bearbeiten"),
("Alias", "Alias"),
("ScrollEdge", "Scrollen am Rand"),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -258,5 +258,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("websocket_tip", "When using WebSocket, only relay connections are supported."),
("terminal-admin-login-tip", "Please input the administrator username and password of the controlled side."),
("elevation_username_tip", "Input username or domain\\username"),
("allow-insecure-tls-fallback-tip", "By default, RustDesk verifies the server certificate for protocols using TLS.\nWith this option enabled, RustDesk will fall back to skipping the verification step and proceed in case of verification failure."),
("disable-udp-tip", "Controls whether to use TCP only.\nWhen this option enabled, RustDesk will not use UDP 21116 any more, TCP 21116 will be used instead."),
("oss-not-support-tip", "NOTE: RustDesk server oss doesn't include this feature."),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Editar nota"),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -496,12 +496,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("resolution_custom_tip", "Käytä mukautettua resoluutiota"),
("Collapse toolbar", "Tiivistä työkalupalkki"),
("Accept and Elevate", "Hyväksy ja korota oikeudet"),
("accept_and_elevate_btn_tooltip", "Hyväksy ja korota oikeudet järjestelmänvalvojaksi"),
("clipboard_wait_response_timeout_tip", "Leikepöydän pyyntö aikakatkaistiin ei vastausta etäpäästä."),
("Incoming connection", "Saapuva yhteys"),
("Outgoing connection", "Lähtevä yhteys"),
("Exit", "Poistu"),
("Open", "Avaa"),
("accept_and_elevate_btn_tooltip", "Hyväksy ja korota oikeudet järjestelmänvalvojaksi"),
("clipboard_wait_response_timeout_tip", "Leikepöydän pyyntö aikakatkaistiin ei vastausta etäpäästä."),
("Incoming connection", "Saapuva yhteys"),
("Outgoing connection", "Lähtevä yhteys"),
("Exit", "Poistu"),
("Open", "Avaa"),
("logout_tip", "Haluatko varmasti kirjautua ulos?"),
("Service", "Palvelu"),
("Start", "Käynnistä"),
@@ -721,5 +721,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Show virtual joystick", "Näytä virtuaalinen ohjain"),
("Edit note", "Muokkaa muistiinpanoa"),
("Alias", "Alias"),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Modifier la note"),
("Alias", "Alias"),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Jegyzet szerkesztése"),
("Alias", "Álnév"),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Modifica nota"),
("Alias", "Alias"),
("ScrollEdge", "Bordo scorrimento"),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "メモを編集"),
("Alias", "エイリアス"),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "노트 편집"),
("Alias", "별명"),
("ScrollEdge", "가장자리 스크롤"),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Opmerking bewerken"),
("Alias", "Alias"),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Edytuj notatkę"),
("Alias", "Alias"),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "Изменить заметку"),
("Alias", "Псевдоним"),
("ScrollEdge", "Прокрутка по краю"),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", "編輯備註"),
("Alias", "別名"),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -722,5 +722,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Edit note", ""),
("Alias", ""),
("ScrollEdge", ""),
("Allow insecure TLS fallback", ""),
("allow-insecure-tls-fallback-tip", ""),
("Disable UDP", ""),
("disable-udp-tip", ""),
("oss-not-support-tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,6 +284,18 @@ impl UI {
crate::using_public_server()
}
fn is_incoming_only(&self) -> bool {
hbb_common::config::is_incoming_only()
}
pub fn is_outgoing_only(&self) -> bool {
hbb_common::config::is_outgoing_only()
}
pub fn is_custom_client(&self) -> bool {
crate::common::is_custom_client()
}
fn get_options(&self) -> Value {
let hashmap: HashMap<String, String> =
serde_json::from_str(&get_options()).unwrap_or_default();
@@ -671,6 +683,9 @@ impl sciter::EventHandler for UI {
fn get_api_server();
fn is_xfce();
fn using_public_server();
fn is_custom_client();
fn is_outgoing_only();
fn is_incoming_only();
fn get_id();
fn temporary_password();
fn update_temporary_password();

View File

@@ -9,7 +9,9 @@ var app;
var tmp = handler.get_connect_status();
var connect_status = tmp[0];
var service_stopped = handler.get_option("stop-service") == "Y";
var disable_udp = handler.get_option("disable-udp") == "Y";
var using_public_server = handler.using_public_server();
var outgoing_only = handler.is_outgoing_only();
var software_update_url = "";
var key_confirmed = tmp[1];
var system_error = "";
@@ -326,8 +328,10 @@ class MyIdMenu: Reactor.Component {
<div .separator />
<li #custom-server>{translate('ID/Relay Server')}</li>
<li #whitelist title={translate('whitelist_tip')}>{translate('IP Whitelisting')}</li>
<li #socks5-server>{translate('Socks5 Proxy')}</li>
{ false && <li #allow-websocket><span>{svg_checkmark}</span>{translate('Use WebSocket')}</li> }
<li #socks5-server>{translate('Socks5/Http(s) Proxy')}</li>
<li #allow-websocket><span>{svg_checkmark}</span>{translate('Use WebSocket')}</li>
{!using_public_server && !outgoing_only && <li #disable-udp class={disable_udp ? "selected" : "line-through"}><span>{svg_checkmark}</span>{translate('Disable UDP')}</li>}
{!using_public_server && <li #allow-insecure-tls-fallback><span>{svg_checkmark}</span>{translate('Allow insecure TLS fallback')}</li>}
<div .separator />
<li #stop-service class={service_stopped ? "line-through" : "selected"}><span>{svg_checkmark}</span>{translate("Enable service")}</li>
{is_win && handler.is_installed() ? <ShareRdp /> : ""}
@@ -473,7 +477,7 @@ class MyIdMenu: Reactor.Component {
var old_proxy = socks5[0] || "";
var old_username = socks5[1] || "";
var old_password = socks5[2] || "";
msgbox("custom-server", "Socks5 Proxy", <div .form .set-password>
msgbox("custom-server", "Socks5/Http(s) Proxy", <div .form .set-password>
<div><span>{translate("Server")}:</span><input|text .outline-focus name='proxy' value={old_proxy} /></div>
<div><span>{translate("Username")}:</span><input|text name='username' value={old_username} /></div>
<div><span>{translate("Password")}:</span><PasswordComponent value={old_password} /></div>
@@ -485,11 +489,18 @@ 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, false);
var domain_port = proxy;
var protocol_index = domain_port.indexOf('://');
if (protocol_index !== -1) {
domain_port = domain_port.substring(protocol_index + 3);
}
var err = handler.test_if_valid_server(domain_port, false);
if (err) return translate("Server") + ": " + err;
}
handler.set_socks(proxy, username, password);
}, 240);
} else if (me.id == "disable-udp") {
handler.set_option("disable-udp", handler.get_option("disable-udp") == "Y" ? "N" : "Y");
} else if (me.id == "stop-service") {
handler.set_option("stop-service", service_stopped ? "" : "Y");
} else if (me.id == "change-id") {
@@ -1196,6 +1207,11 @@ function checkConnectStatus() {
updateAbPeer();
app.update();
}
tmp = handler.get_option("disable-udp") == "Y";
if (tmp != disable_udp) {
disable_udp = tmp;
app.update();
}
check_if_overlay();
checkConnectStatus();
});

View File

@@ -1,4 +1,4 @@
use crate::{common::do_check_software_update, hbbs_http::create_http_client};
use crate::{common::do_check_software_update, hbbs_http::create_http_client_with_url};
use hbb_common::{bail, config, log, ResultType};
use std::{
io::Write,
@@ -146,7 +146,7 @@ fn check_update(manually: bool) -> ResultType<()> {
format!("{}/rustdesk-{}-x86-sciter.exe", download_url, version)
};
log::debug!("New version available: {}", &version);
let client = create_http_client();
let client = create_http_client_with_url(&download_url);
let Some(file_path) = get_download_file_from_url(&download_url) else {
bail!("Failed to get the file path from the URL: {}", download_url);
};