port forward: the login's target travels with the accept, not the handler

`listen()` wrote `lc.port_forward` (and, on this branch, `port_forward_mux`)
into the window's shared `LoginConfigHandler` before connecting, and
`create_login_msg` read them back only when the peer's `Hash` arrived.
Two mappings logging in at the same time could therefore swap targets:
on master that bridged a local socket to the wrong target, and with a
tunnel bound to its login's target it also left the mapping refusing
every later accept until it was recreated.

The target is now a `PortForward` carried by the interface clone that
handles one accept, passed explicitly down to `create_login_msg`; the
handler no longer has a field to race on. No lock spans the login.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
This commit is contained in:
rustdesk
2026-09-04 18:02:17 +08:00
parent 80cd800375
commit 2e75e45588
4 changed files with 73 additions and 25 deletions

View File

@@ -1342,6 +1342,9 @@ mod tests {
fn handle_login_error(&self, _err: &str) -> bool {
false
}
fn with_port_forward(&self, _port_forward: PortForward) -> Self {
self.clone()
}
fn handle_peer_info(&self, _pi: PeerInfo) {}
fn set_multiple_windows_session(&self, _sessions: Vec<WindowsSession>) {}
async fn handle_hash(&self, _pass: &str, _hash: Hash, _peer: &mut Stream) -> bool {