[fix] reuse stale sessions and stored passwords when reconnecting

This commit is contained in:
dijunkun
2026-09-21 00:51:50 +08:00
parent 4797af9260
commit 89b39803e8
4 changed files with 58 additions and 7 deletions
@@ -477,7 +477,42 @@ int GuiRuntime::ConnectTo(const std::string& remote_id, const char* password,
LOG_INFO("Connect to [{}]", remote_id);
focused_remote_id_ = remote_id;
bool exists = FindRemoteSession(remote_id) != nullptr;
auto stale = FindRemoteSession(remote_id);
bool exists = stale != nullptr;
if (stale) {
// A failed CreatePeer or a completed close can leave a session record
// without a reusable peer. Recreate it instead of leaving the UI in
// Connecting forever while JoinConnection has nothing to call.
if (stale->peer_ == nullptr) {
std::unique_lock lock(remote_sessions_mutex_);
auto it = remote_sessions_.find(remote_id);
if (it != remote_sessions_.end() && it->second == stale) {
remote_sessions_.erase(it);
exists = false;
LOG_INFO("[{}] Recreating stale remote session before connect",
remote_id);
}
}
if (exists && !stale->closing_.load() &&
!stale->connection_established_) {
const auto status = stale->connection_status_.load();
if (status == ConnectionStatus::Disconnected ||
status == ConnectionStatus::Failed ||
status == ConnectionStatus::Closed) {
// The recreated session starts with an empty password; callers that
// pass none expect the one stored by the previous attempt to be reused.
const bool keep_stored_password = !password || !*password;
pending_reconnects_[remote_id] = {
keep_stored_password ? std::string(stale->remote_password_)
: std::string(password),
remember_password};
CloseRemoteSession(stale);
LOG_INFO("[{}] Reconnecting after terminal peer status {}", remote_id,
static_cast<int>(status));
return 0;
}
}
}
if (!exists) {
PeerPtr* peer_to_init = nullptr;
@@ -1,6 +1,7 @@
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
@@ -114,8 +115,14 @@ int main() {
"connection_attempt_active_");
ok &= ExpectNotContains("connection_runtime.cpp", connection_runtime_cpp,
"kConnectionAttemptTimeout");
ok &= ExpectNotContains("connection_runtime.cpp", connection_runtime_cpp,
"ConnectionStatus::Failed");
// Reading a terminal transport status to reconnect is valid. This guard
// prohibits synthesizing a failure locally, not comparisons with Failed.
const std::regex synthetic_failure(
R"((connection_status_\s*(=\s*|\.\s*(store|exchange)\s*\(\s*)|OnConnectionStatus\s*\(\s*)ConnectionStatus::Failed\b)");
if (std::regex_search(connection_runtime_cpp, synthetic_failure)) {
std::cerr << "connection_runtime.cpp synthesizes a Failed status\n";
ok = false;
}
ok &= ExpectContains("peer_event_handler.cpp", peer_event_handler_cpp,
"props->connection_status_.store(status);");
ok &= ExpectContains("peer_event_handler.cpp", peer_event_handler_cpp,
@@ -1,3 +1,4 @@
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iostream>
@@ -27,7 +28,12 @@ std::string ReadFile(const std::filesystem::path &path) {
std::ostringstream stream;
stream << file.rdbuf();
return stream.str();
std::string contents = stream.str();
// Normalize CRLF checkouts so multi-line expectations match on Windows
// hosts with core.autocrlf enabled.
contents.erase(std::remove(contents.begin(), contents.end(), '\r'),
contents.end());
return contents;
}
bool ExpectContains(const char *name, const std::string &value,
@@ -86,7 +92,7 @@ int main() {
ok &= ExpectContains("targets.lua", targets,
"target(\"crossdesk_session_helper\")");
ok &= ExpectContains("targets.lua", targets,
"add_files(crossdesk_windows_resource)");
"add_files(crossdesk_windows_resource,");
ok &= ExpectContains("session_helper_main.cpp", session_helper,
"EnablePerMonitorDpiAwareness");
ok &= ExpectContains("session_helper_main.cpp", session_helper,
@@ -170,7 +176,8 @@ int main() {
"Local Windows service temporarily unavailable");
ok &= ExpectContains(
"screen_capturer_win.cpp", screen_capturer_cpp,
"Windows capturer secure desktop service temporarily unavailable");
"Windows capturer secure desktop service temporarily \"\n"
" \"unavailable");
ok &= ExpectContains(
"screen_capturer_win.cpp", screen_capturer_cpp,
"Windows capturer secure desktop transient frame query failed");
+3 -1
View File
@@ -31,7 +31,9 @@ int main() {
static_cast<int>(crossdesk::ControlType::service_status) == 5 &&
static_cast<int>(crossdesk::ControlType::service_command) == 6 &&
static_cast<int>(crossdesk::ControlType::keyboard_state) == 7 &&
static_cast<int>(crossdesk::ControlType::cursor_state) == 8,
static_cast<int>(crossdesk::ControlType::cursor_state) == 8 &&
static_cast<int>(crossdesk::ControlType::privacy_command) == 9 &&
static_cast<int>(crossdesk::ControlType::privacy_status) == 10,
"ControlType wire values changed");
ok &= Expect(static_cast<int>(crossdesk::RemoteCursorShape::default_cursor) ==
0 &&