allow use websocket (#11677)

1. Enable the RustDesk client to use WebSocket for either controlling or being controlled.
2. Fix TCP sending `register_pk` frequently

Note:
1. Because hbb_common directly uses `use_ws` to read config directly, rustdesk also directly reads config

Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
21pages
2025-05-09 12:18:49 +08:00
committed by GitHub
parent 86bbdf7a5d
commit 9475743b4e
61 changed files with 413 additions and 64 deletions

View File

@@ -147,9 +147,13 @@ const String kOptionDirectxCapture = "enable-directx-capture";
const String kOptionAllowRemoteCmModification = "allow-remote-cm-modification";
const String kOptionEnableTrustedDevices = "enable-trusted-devices";
// network options
const String kOptionAllowWebSocket = "allow-websocket";
// buildin opitons
const String kOptionHideServerSetting = "hide-server-settings";
const String kOptionHideProxySetting = "hide-proxy-settings";
const String kOptionHideWebSocketSetting = "hide-websocket-settings";
const String kOptionHideRemotePrinterSetting = "hide-remote-printer-settings";
const String kOptionHideSecuritySetting = "hide-security-settings";
const String kOptionHideNetworkSetting = "hide-network-settings";

View File

@@ -1475,11 +1475,70 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
bind.mainGetBuildinOption(key: kOptionHideServerSetting) == 'Y';
final hideProxy =
isWeb || bind.mainGetBuildinOption(key: kOptionHideProxySetting) == 'Y';
// final hideWebSocket = isWeb ||
// bind.mainGetBuildinOption(key: kOptionHideWebSocketSetting) == 'Y';
final hideWebSocket = true;
if (hideServer && hideProxy) {
if (hideServer && hideProxy && hideWebSocket) {
return Offstage();
}
// Helper function to create network setting ListTiles
Widget listTile({
required IconData icon,
required String title,
VoidCallback? onTap,
Widget? trailing,
bool showTooltip = false,
String tooltipMessage = '',
}) {
final titleWidget = showTooltip
? Row(
children: [
Tooltip(
waitDuration: Duration(milliseconds: 1000),
message: translate(tooltipMessage),
child: Row(
children: [
Text(
translate(title),
style: TextStyle(fontSize: _kContentFontSize),
),
SizedBox(width: 5),
Icon(
Icons.help_outline,
size: 14,
color: Theme.of(context)
.textTheme
.titleLarge
?.color
?.withOpacity(0.7),
),
],
),
),
],
)
: Text(
translate(title),
style: TextStyle(fontSize: _kContentFontSize),
);
return ListTile(
leading: Icon(icon, color: _accentColor),
title: titleWidget,
enabled: !locked,
onTap: onTap,
trailing: trailing,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
contentPadding: EdgeInsets.symmetric(horizontal: 16),
minLeadingWidth: 0,
horizontalTitleGap: 10,
);
}
return _Card(
title: 'Network',
children: [
@@ -1488,39 +1547,36 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!hideServer)
ListTile(
leading: Icon(Icons.dns_outlined, color: _accentColor),
title: Text(
translate('ID/Relay Server'),
style: TextStyle(fontSize: _kContentFontSize),
),
enabled: !locked,
listTile(
icon: Icons.dns_outlined,
title: 'ID/Relay Server',
onTap: () => showServerSettings(gFFI.dialogManager),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
contentPadding: EdgeInsets.symmetric(horizontal: 16),
minLeadingWidth: 0,
horizontalTitleGap: 10,
),
if (!hideServer && !hideProxy)
if (!hideServer && (!hideProxy || !hideWebSocket))
Divider(height: 1, indent: 16, endIndent: 16),
if (!hideProxy)
ListTile(
leading:
Icon(Icons.network_ping_outlined, color: _accentColor),
title: Text(
translate('Socks5/Http(s) Proxy'),
style: TextStyle(fontSize: _kContentFontSize),
),
enabled: !locked,
listTile(
icon: Icons.network_ping_outlined,
title: 'Socks5/Http(s) Proxy',
onTap: changeSocks5Proxy,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
if (!hideProxy && !hideWebSocket)
Divider(height: 1, indent: 16, endIndent: 16),
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(() {});
},
),
contentPadding: EdgeInsets.symmetric(horizontal: 16),
minLeadingWidth: 0,
horizontalTitleGap: 10,
),
],
),

View File

@@ -80,6 +80,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
var _enableDirectIPAccess = false;
var _enableRecordSession = false;
var _enableHardwareCodec = false;
var _allowWebSocket = false;
var _autoRecordIncomingSession = false;
var _autoRecordOutgoingSession = false;
var _allowAutoDisconnect = false;
@@ -91,6 +92,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
var _hideServer = false;
var _hideProxy = false;
var _hideNetwork = false;
var _hideWebSocket = false;
var _enableTrustedDevices = false;
_SettingsState() {
@@ -105,6 +107,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
bind.mainGetOptionSync(key: kOptionEnableRecordSession));
_enableHardwareCodec = option2bool(kOptionEnableHwcodec,
bind.mainGetOptionSync(key: kOptionEnableHwcodec));
_allowWebSocket = mainGetBoolOptionSync(kOptionAllowWebSocket);
_autoRecordIncomingSession = option2bool(kOptionAllowAutoRecordIncoming,
bind.mainGetOptionSync(key: kOptionAllowAutoRecordIncoming));
_autoRecordOutgoingSession = option2bool(kOptionAllowAutoRecordOutgoing,
@@ -120,6 +123,8 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
_hideProxy = bind.mainGetBuildinOption(key: kOptionHideProxySetting) == 'Y';
_hideNetwork =
bind.mainGetBuildinOption(key: kOptionHideNetworkSetting) == 'Y';
_hideWebSocket =
true; //bind.mainGetBuildinOption(key: kOptionHideWebSocketSetting) == 'Y';
_enableTrustedDevices = mainGetBoolOptionSync(kOptionEnableTrustedDevices);
}
@@ -667,6 +672,21 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
onPressed: (context) {
changeSocks5Proxy();
}),
if (!disabledSettings && !_hideNetwork && !_hideWebSocket)
SettingsTile.switchTile(
title: Text(translate('Use WebSocket')),
initialValue: _allowWebSocket,
onToggle: isOptionFixed(kOptionAllowWebSocket)
? null
: (v) async {
await mainSetBoolOption(kOptionAllowWebSocket, v);
final newValue =
await mainGetBoolOption(kOptionAllowWebSocket);
setState(() {
_allowWebSocket = newValue;
});
},
),
SettingsTile(
title: Text(translate('Language')),
leading: Icon(Icons.translate),

View File

@@ -49,14 +49,15 @@ class PlatformFFI {
}
bool registerEventHandler(
String eventName, String handlerName, HandleEvent handler) {
String eventName, String handlerName, HandleEvent handler,
{bool replace = false}) {
debugPrint('registerEventHandler $eventName $handlerName');
var handlers = _eventHandlers[eventName];
if (handlers == null) {
_eventHandlers[eventName] = {handlerName: handler};
return true;
} else {
if (handlers.containsKey(handlerName)) {
if (!replace && handlers.containsKey(handlerName)) {
return false;
} else {
handlers[handlerName] = handler;

View File

@@ -1852,5 +1852,49 @@ class RustdeskImpl {
throw UnimplementedError("sessionGetConnToken");
}
String mainGetPrinterNames({dynamic hint}) {
return '';
}
Future<void> sessionPrinterResponse(
{required UuidValue sessionId,
required int id,
required String path,
required String printerName,
dynamic hint}) {
throw UnimplementedError("sessionPrinterResponse");
}
Future<String> mainGetCommon({required String key, dynamic hint}) {
throw UnimplementedError("mainGetCommon");
}
String mainGetCommonSync({required String key, dynamic hint}) {
throw UnimplementedError("mainGetCommonSync");
}
Future<void> mainSetCommon(
{required String key, required String value, dynamic hint}) {
throw UnimplementedError("mainSetCommon");
}
Future<String> sessionHandleScreenshot(
{required UuidValue sessionId, required String action, dynamic hint}) {
throw UnimplementedError("sessionHandleScreenshot");
}
String? sessionGetCommonSync(
{required UuidValue sessionId,
required String key,
required String param,
dynamic hint}) {
throw UnimplementedError("sessionGetCommonSync");
}
Future<void> sessionTakeScreenshot(
{required UuidValue sessionId, required int display, dynamic hint}) {
throw UnimplementedError("sessionTakeScreenshot");
}
void dispose() {}
}