ws: decouple ICE policy from force_relay — full-ICE WebRTC over WebSocket

WebSocket support folds into force_relay because a ws tunnel kills
classic TCP/UDP punching — but that conflated transport necessity with
relay policy, and the WebRTC decisions keyed off the merged flag: a ws
client built no offerer at all without TURN, and only a Relay-only-ICE
one with it. ws deployments could never reach a direct WebRTC
connection, which is exactly the path they are supposed to live on.

Split the flag. LoginConfigHandler now tracks policy_relay (the
force-always-relay option, an explicit relay request — /r ids and
retry-via-relay included — and proxy) separately; force_relay stays
policy_relay || use_ws() and keeps governing the classic paths, so
non-ws behavior is unchanged everywhere:

- the offerer's existence and ICE policy follow policy_relay: under
  pure ws the offer gathers every candidate type and may go direct;
  under relay-by-policy it stays Relay-only ICE, TURN-gated, exactly
  as before;
- the RelayResponse race applies the prefer-P2P window under ws (a
  direct ICE path is worth delaying an already-ready relay for) while
  policy relay keeps first-success semantics;
- the request carries webrtc_all_ice (hbb_common 64b54ab) so the
  controlled side knows the offer is full-ICE: it answers with full ICE
  and no TURN requirement, while offers without the bit keep today's
  relay-only answer path on every version-skew combination.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ExUfAkYbq8UC9pQCiLy8TQ
This commit is contained in:
rustdesk
2026-08-07 00:18:16 +08:00
parent c313d6dc1c
commit 585d1fb3ca
3 changed files with 49 additions and 18 deletions

View File

@@ -1294,7 +1294,11 @@ impl<T: InvokeUiSession> Session<T> {
// override only if true
if true == force_relay {
self.lc.write().unwrap().force_relay = true;
let mut lc = self.lc.write().unwrap();
lc.force_relay = true;
// An explicit retry-via-relay is user policy, not transport necessity: keep
// WebRTC on Relay-only ICE for this round like any force-always-relay session.
lc.policy_relay = true;
}
self.lc.write().unwrap().peer_info = None;
self.reconnect_count.fetch_add(1, Ordering::SeqCst);