[fix] fix stuck connecting state when remote device is offline, refs #57

This commit is contained in:
dijunkun
2026-07-05 00:52:21 +08:00
parent 0681f6540d
commit 5db309243b
8 changed files with 210 additions and 3 deletions
+5
View File
@@ -249,6 +249,11 @@ int Render::ConnectTo(const std::string& remote_id, const char* password,
// std::shared_lock read_lock(client_properties_mutex_);
auto props = client_properties_[remote_id];
if (!props->connection_established_) {
props->connection_status_.store(ConnectionStatus::Connecting);
props->connection_attempt_active_.store(true);
props->connection_attempt_started_at_ = std::chrono::steady_clock::now();
show_connection_status_window_ = true;
props->remember_password_ = remember_password;
if (strcmp(password, "") != 0 &&
strcmp(password, props->remote_password_) != 0) {
+75
View File
@@ -46,6 +46,13 @@ namespace crossdesk {
namespace {
constexpr uint64_t kCaptureResumeKeyFrameGapMs = 500;
constexpr auto kPresenceProbeTimeout = std::chrono::seconds(5);
constexpr auto kConnectionAttemptTimeout = std::chrono::seconds(20);
bool IsConnectionAttemptPending(ConnectionStatus status) {
return status == ConnectionStatus::Connecting ||
status == ConnectionStatus::Gathering;
}
const ImWchar* GetMultilingualGlyphRanges() {
static std::vector<ImWchar> glyph_ranges;
@@ -2078,6 +2085,7 @@ void Render::MainLoop() {
HandleRecentConnections();
HandleConnectionStatusChange();
HandlePendingPresenceProbe();
HandleConnectionTimeouts();
HandleStreamWindow();
HandleServerWindow();
HandleWindowsServiceIntegration();
@@ -2398,6 +2406,72 @@ void Render::HandlePendingPresenceProbe() {
show_offline_warning_window_ = true;
}
void Render::HandleConnectionTimeouts() {
const auto now = std::chrono::steady_clock::now();
bool presence_probe_timed_out = false;
std::string presence_remote_id;
{
std::lock_guard<std::mutex> lock(pending_presence_probe_mutex_);
if (pending_presence_probe_ && !pending_presence_result_ready_ &&
now - pending_presence_probe_started_at_ >= kPresenceProbeTimeout) {
presence_probe_timed_out = true;
presence_remote_id = pending_presence_remote_id_;
pending_presence_probe_ = false;
pending_presence_result_ready_ = false;
pending_presence_online_ = false;
pending_presence_remote_id_.clear();
pending_presence_password_.clear();
pending_presence_remember_password_ = false;
}
}
if (presence_probe_timed_out) {
offline_warning_text_ =
localization::device_offline[localization_language_index_];
show_offline_warning_window_ = true;
LOG_WARN("Presence probe timed out for [{}]", presence_remote_id);
}
bool rejoin_state_changed = false;
for (auto& [_, props] : client_properties_) {
if (!props || !props->connection_attempt_active_.load()) {
continue;
}
const ConnectionStatus status = props->connection_status_.load();
if (!IsConnectionAttemptPending(status)) {
props->connection_attempt_active_.store(false);
continue;
}
if (now - props->connection_attempt_started_at_ <
kConnectionAttemptTimeout) {
continue;
}
LOG_WARN("Connection to [{}] timed out, status={}", props->remote_id_,
static_cast<int>(status));
props->connection_attempt_active_.store(false);
props->connection_established_ = false;
props->rejoin_ = false;
props->connection_status_.store(ConnectionStatus::Failed);
focused_remote_id_ = props->remote_id_;
show_connection_status_window_ = true;
rejoin_state_changed = true;
}
if (rejoin_state_changed) {
need_to_rejoin_ = false;
for (const auto& [_, props] : client_properties_) {
if (props && props->rejoin_) {
need_to_rejoin_ = true;
break;
}
}
}
}
int Render::RequestSingleDevicePresence(const std::string& remote_id,
const char* password,
bool remember_password) {
@@ -2410,6 +2484,7 @@ int Render::RequestSingleDevicePresence(const std::string& remote_id,
pending_presence_probe_ = true;
pending_presence_result_ready_ = false;
pending_presence_online_ = false;
pending_presence_probe_started_at_ = std::chrono::steady_clock::now();
pending_presence_remote_id_ = remote_id;
pending_presence_password_ = password ? password : "";
pending_presence_remember_password_ = remember_password;
+4
View File
@@ -110,6 +110,8 @@ class Render {
SignalStatus signal_status_ = SignalStatus::SignalClosed;
bool connection_established_ = false;
bool rejoin_ = false;
std::atomic<bool> connection_attempt_active_ = false;
std::chrono::steady_clock::time_point connection_attempt_started_at_;
bool net_traffic_stats_button_pressed_ = false;
bool enable_mouse_control_ = true;
bool mouse_controller_is_started_ = false;
@@ -220,6 +222,7 @@ class Render {
void HandleRecentConnections();
void HandleConnectionStatusChange();
void HandlePendingPresenceProbe();
void HandleConnectionTimeouts();
void HandleStreamWindow();
void HandleServerWindow();
void Cleanup();
@@ -833,6 +836,7 @@ class Render {
bool pending_presence_probe_ = false;
bool pending_presence_result_ready_ = false;
bool pending_presence_online_ = false;
std::chrono::steady_clock::time_point pending_presence_probe_started_at_;
std::string pending_presence_remote_id_ = "";
std::string pending_presence_password_ = "";
bool pending_presence_remember_password_ = false;
+6 -1
View File
@@ -1507,6 +1507,10 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id,
render->is_client_mode_ = true;
render->show_connection_status_window_ = true;
props->connection_status_.store(status);
if (status != ConnectionStatus::Connecting &&
status != ConnectionStatus::Gathering) {
props->connection_attempt_active_.store(false);
}
switch (status) {
case ConnectionStatus::Connected: {
@@ -1608,7 +1612,8 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id,
}
break;
}
case ConnectionStatus::NoSuchTransmissionId: {
case ConnectionStatus::NoSuchTransmissionId:
case ConnectionStatus::RemoteUnavailable: {
if (render->connect_button_pressed_) {
props->connection_established_ = false;
render->connect_button_label_ =
+14 -1
View File
@@ -180,6 +180,19 @@ bool Render::ConnectionStatusWindow(
DestroyPeer(&props->peer_);
ret_flag = true;
}
} else if (ConnectionStatus::RemoteUnavailable == status) {
text = localization::device_offline[localization_language_index_];
ImGui::SetCursorPosX(connection_status_window_width * 0.43f);
ImGui::SetCursorPosY(connection_status_window_height * 0.67f);
// ok
if (ImGui::Button(localization::ok[localization_language_index_].c_str()) ||
ImGui::IsKeyPressed(ImGuiKey_Enter) ||
ImGui::IsKeyPressed(ImGuiKey_Escape)) {
show_connection_status_window_ = false;
re_enter_remote_id_ = true;
DestroyPeer(&props->peer_);
ret_flag = true;
}
}
auto text_width = ImGui::CalcTextSize(text.c_str()).x;
@@ -193,4 +206,4 @@ bool Render::ConnectionStatusWindow(
return ret_flag;
}
} // namespace crossdesk
} // namespace crossdesk