Commit Graph

33 Commits

Author SHA1 Message Date
rustdesk
4b4cb10823 port forward: a legacy window stays legacy until it is reopened
Review: the merged `Claimed | Legacy` arm gave a legacy window a hot
transition to a tunnel — every accept re-negotiated, and a peer upgraded
while the window stayed open was promoted underneath live connections.
The product does not need a mode switch inside a window's lifetime, and
the transition was extra state-machine surface for nothing: reopening
the window picks up an upgraded peer.

The two arms are separate again. `Claimed` negotiates once and the
peer's answer fixes the window's mode. `Legacy` logs in for every accept
as before, asks for no tunnel — `LoginConfigHandler::port_forward_mux`
carries the request per login, so the raw pipe never has to talk to a
peer that thinks it agreed to multiplex — and ignores what the peer
reports. Both arms keep skipping a local socket that hung up during
login.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
2026-09-04 19:51:38 +08:00
rustdesk
7f2f4c41a8 port forward: apply the whole-branch review
Correctness:
- listen(): the Legacy arm is merged with the Claimed arm. On its own it
  ignored outcome.local_eof, so a client that hung up during login still
  got a target connect, an audit record and a CM row on the controlled
  side, and ignored outcome.mux, so a peer upgraded while a legacy window
  stayed open answered as a tunnel while the controller went raw.
- Refusal dialogs are deduplicated per quiet spell (10 s) rather than per
  tunnel lifetime; the lifetime set went silent for the rest of a
  long-lived window after the first burst.
- Android's CM listener handles UpdatePortForward; it fell into `_ => {}`.
- relay_socket_to_tunnel reads into one scratch buffer per channel and
  sends an exact-size copy. A frame owning its 64 KiB read allocation
  pinned it until sent, once per byte on interactive traffic.

Consistency and cleanups:
- The controlled side's refusal text is the raw pipe's wording, RDP
  substitution included.
- connection.rs: the PortForwardChannel arm is a one-line hook, the CM
  label is pushed from the 1 s tick alone, and the unreachable inner.tx
  fall-through is gone.
- The Ready enum is removed; wait_ready() returns Option<Claim>.
- SendCredit::add wakes with notify_one alone.
- on_ui_command() replaces the two ui_receiver handlers in listen().
- TunnelHandle is no longer re-exported (unused-import warning).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
2026-09-04 19:51:38 +08:00
rustdesk
9e89587081 port forward: fix round 1 review findings
Drop the mux default-false assignment now that definite-assignment proves
every path that reads it has set it; the enable-port-forward-mux config
commit picks up the missing attribution trailers; the default-on test
pins the enable- prefix itself rather than option2bool's weaker fallback.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
2026-09-04 19:51:38 +08:00
rustdesk
064b78787e port forward: share one multiplexed tunnel across a window's listeners
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
2026-09-04 19:51:38 +08:00
RustDesk
978c901f49 port forward: a login's target and challenge travel with its own accept (#16069)
* port forward: mappings take turns at the window's login slots

A window's mappings log in concurrently, and each login is built from
the shared `LoginConfigHandler`: `create_login_msg` reads
`port_forward`, which `listen()` set before connecting, and
`handle_login_from_ui` reads `hash`, which the last `Hash` to arrive
set. Two mappings logging in at once could swap targets, bridging a
local socket to the other's target, and answer each other's challenge,
failing one login. The window's password prompt is broadcast to every
mapping, so one whose `Hash` had not arrived answered with whatever the
handler held.

Each mapping now fills `port_forward` and `hash` and sends its login
under a per-window turn lock, and keeps its own `Hash` beside the
connection: a password typed before it arrived is left to the mapping
that prompted, which stores the salted password in the shared handler
for the others to log in with.

The fix stays in `port_forward.rs`. `LoginConfigHandler` gains the lock
and a setter for its private `hash`; `Interface`, `Session` and the
login functions keep their signatures.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab

* port forward: the lock and the hash setter are crate-private; test the hash that arrives late on its real path

Both exist only so `port_forward.rs` can reach the handler's private
`hash`; neither is API.

The test for a password typed before a connection's hash ended by
answering the prompt again once the hash was there. What happens in the
code is that the hash's arrival runs `handle_hash`, which logs in with
the password the prompting mapping stored; the test now ends there, with
no preset password. Answering the prompt with one's own challenge while
the handler holds another's is a test of its own.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab

* port forward: a password typed before the connection's hash answers it when it comes

The previous commit dropped such a password, counting on the mapping
that prompted having stored it in the shared handler by the time this
connection's `Hash` arrived. The broadcast wakes both mappings at once
and `select!` picks between a ready `Hash` and a ready password at
random, so this one could reach `handle_hash` first, find the handler
empty, and prompt again.

The connection keeps the password until its `Hash` arrives and answers
with it then. `login_from_ui` takes the challenge it answers; the wait
is `connect_and_login`'s, in `hash_arrived`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 19:39:09 +08:00
RustDesk
5a78be03e3 feat(rdp): title the mstsc window after the peer instead of "localhost" (#15781)
* feat(rdp): title the mstsc window after the peer instead of "localhost"

The RDP tunnel launched `mstsc /v:localhost:<port>`, so with several
sessions open every window is titled "localhost" and servers cannot be
told apart.

mstsc titles the session window after the launched .rdp file's base
name, so write a temp .rdp file (containing only the tunnel address)
named after the peer alias, cached hostname, or id, and launch that
instead. Falls back to the old /v: form when no usable name remains
after filename sanitization or the file cannot be written. Credential
handling is unchanged: cmdkey targets "localhost", which is still the
host mstsc resolves credentials against.

Fixes rustdesk/rustdesk#15775 (discussion)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(rdp): set mstsc title without temporary files

  Keep launching mstsc with /v so Default.rdp settings are preserved
  and unsigned RDP file warnings and policy restrictions are avoided.

  Track the launched mstsc process and reapply the peer name when the
  window title is reset during connection or reconnection.

Signed-off-by: 21pages <sunboeasy@gmail.com>

* docs(rdp): clarify mstsc title limitation

Signed-off-by: 21pages <sunboeasy@gmail.com>

* feat(rdp): show peer identity with hostname in mstsc title

Signed-off-by: 21pages <sunboeasy@gmail.com>

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: 21pages <sunboeasy@gmail.com>
2026-08-17 13:30:18 +08:00
rustdesk
947cb3f17b propagates the hash-handler continuation result through both connection loops, allowing incoming-only rejection to terminate the connection while preserving existing login flows. 2026-08-10 16:45:27 +08:00
fufesou
28930c0463 fix: non-E2EE show dialog (#15514)
* fix: non-E2EE show dialog

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: build web, bridge

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: direct IP access, do not snow non-E2EE dialog

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: non E2EE dialog, update contents

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: non-E2EE, show dialog, port forward

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: non-E2EE dialog, port forward, ignore direct IP access

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: non-E2EE is_direct_ip_access()

Signed-off-by: fufesou <linlong1266@gmail.com>

* Simple refactor

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: non-E2EE dialog, port forward, close socket on disconnect

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: non-E2EE dialog, incorrect reuse of Data::Close

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-07-06 17:05:11 +08:00
fufesou
cc7fe4efdc Fix/generate py target injection (#15248)
* fix: generate.py, target injection

Signed-off-by: fufesou <linlong1266@gmail.com>

* refact: logs

Signed-off-by: fufesou <linlong1266@gmail.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Update port_forward.rs

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-11 23:09:34 +08:00
rustdesk
82a9fd1540 change port forward listen to localhost 2026-02-24 21:57:55 +08:00
21pages
a0659a277a show TCP/UDP/IPv6 in tooltip (#12613)
* add punch type log

Signed-off-by: 21pages <sunboeasy@gmail.com>

* show TCP/UDP/IPv6 in tooltip

Signed-off-by: 21pages <sunboeasy@gmail.com>

* Skip udp punch if udp nat port is 0

Signed-off-by: 21pages <sunboeasy@gmail.com>

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-08-11 16:13:31 +08:00
rustdesk
7792ac1481 udp punch and ipv6 punch 2025-06-12 21:32:28 +08:00
rustdesk
d0a54a6cc6 hc 2024-07-14 05:47:42 +08:00
21pages
2e16a2be56 fix port forward 2fa (#6956)
Signed-off-by: 21pages <pages21@163.com>
2024-01-22 19:57:23 +08:00
fufesou
06987c4ca9 refact, flutter sessions lock
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2023-10-03 09:51:21 +08:00
dignow
fad88c2718 refact, tab to window, remove rust cache data
Signed-off-by: dignow <linlong1265@gmail.com>
2023-08-14 21:04:24 +08:00
dignow
aeae2b3ef7 Fix, check if is cached peer info when handle_peer_info
Signed-off-by: dignow <linlong1265@gmail.com>
2023-08-13 21:46:39 +08:00
21pages
aede035d20 opt force_relay/relay_hint logic
Signed-off-by: 21pages <pages21@163.com>
2023-07-01 22:48:09 +08:00
21pages
0fafedc706 add error message judgement to set_force_relay
Signed-off-by: 21pages <pages21@163.com>
2023-07-01 13:40:57 +08:00
Kingtous
56f1b75b52 fix: port forward & RDP check 2023-05-15 00:33:58 +08:00
21pages
1100b2a465 show fingerprint
Signed-off-by: 21pages <pages21@163.com>
2023-04-19 15:52:15 +08:00
fufesou
10eddc139c linux virtual display, init commit
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2023-04-03 13:16:49 +08:00
fufesou
77de0d05f9 msgbox & translations
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-10-17 22:00:44 +08:00
csf
fcc62febb1 update port-forward
1. fix multi remote port override.
2. add connection.rs port-forward failed to close
2022-08-29 19:45:06 +08:00
21pages
0649a49d17 fix 10054: change direct to relay when RST
Signed-off-by: 21pages <pages21@163.com>
2022-08-24 16:26:09 +08:00
rustdesk
06ce3661f4 issue #1051 2022-07-27 00:31:20 +08:00
rustdesk
d3fc6ccd9c upgrade tokio 2022-07-15 01:29:52 +08:00
tom
c6c5d2cb98 upgrade protobuf to 3.1.0 and use with-bytes feature, issues:958 2022-07-14 17:20:01 +08:00
rustdesk
c1bad84a86 100% open source 2022-05-12 17:35:25 +08:00
rustdesk
e6744d031d connection type 2021-07-27 23:53:12 +08:00
rustdesk
05c4dacbe9 ipc windows work 2021-06-26 01:14:22 +08:00
rustdesk
dc3fcda2c9 tokio1, windows not test yet 2021-06-25 19:42:51 +08:00
rustdesk
d1013487e2 source code 2021-03-29 15:59:14 +08:00