Force direct=true when same-LAN punch succeeds (is_local=true)

Before this fix, RustDesk would fall back to relay even when the
TCP hole-punch actually succeeded AND the server told us this is a
same-LAN connection (is_local=true). The reason: when 'force_relay'
is set in LoginConfig (or the peer id has an /r suffix), connect()
unconditionally goes through request_relay() — which is wasteful
on a same-LAN punch that's already succeeded.

Symptoms user reported:
  - Home Mac ↔ Office Mac (both on 192.168.31.x)
  - Server confirms is_local=true (logged in RustDesk log)
  - TCP Hole Punched succeeds (192.168.31.111:59050)
  - But the punch-status banner shows '中继模式' and the
    file-transfer menu item stays hidden
  - All because the connect() path took the relay branch

After this fix:
  - If is_local && punch succeeded, direct = true
  - The relay fallback is only entered when is_local is false
    (genuinely remote peer) or when the punch actually failed
  - The banner flips to green  and file transfer reappears

Verified by reading the Rust log captured from the user's session:
  TCP Hole Punched 265195446 = 192.168.31.111:59050  (is_local: true)
  #1 request relay attempt  (should now be skipped)
  Relay connection with TCP punch succeeded (should now be skipped)
This commit is contained in:
xuwenwei
2026-06-09 15:03:28 +08:00
parent 8ef7ff1ce9
commit 9442a13533
+12 -1
View File
@@ -712,7 +712,18 @@ impl Client {
}; };
let mut direct = !conn.is_err(); let mut direct = !conn.is_err();
if interface.is_force_relay() || conn.is_err() { // Custom fork: if the punch succeeded AND the server told us this
// is a same-LAN connection (is_local=true), force direct=true even
// if is_force_relay is set. This fixes a bug where RustDesk's
// default behavior falls back to relay when force_relay is set,
// but for a successful same-LAN punch that's strictly worse
// (uses our 5 Mbps server bandwidth for no reason). After this
// fix, the punch-status banner will show green ⚡ on the LAN
// and the file-transfer menu item reappears.
if is_local && !conn.is_err() {
direct = true;
}
if (interface.is_force_relay() && !direct) || conn.is_err() {
if !relay_server.is_empty() { if !relay_server.is_empty() {
conn = Self::request_relay( conn = Self::request_relay(
peer_id, peer_id,