[feat] probe presence before connect and show warning if offline

This commit is contained in:
dijunkun
2026-03-10 17:46:44 +08:00
parent 3e31ba102d
commit 91bde91238
4 changed files with 123 additions and 10 deletions

View File

@@ -165,12 +165,18 @@ static int InputTextCallback(ImGuiInputTextCallbackData* data) {
} }
int Render::ConnectTo(const std::string& remote_id, const char* password, int Render::ConnectTo(const std::string& remote_id, const char* password,
bool remember_password) { bool remember_password, bool bypass_presence_check) {
if (!device_presence_.IsOnline(remote_id)) { if (!bypass_presence_check && !device_presence_.IsOnline(remote_id)) {
offline_warning_text_ = int ret =
localization::device_offline[localization_language_index_]; RequestSingleDevicePresence(remote_id, password, remember_password);
show_offline_warning_window_ = true; if (ret != 0) {
LOG_WARN("Skip connect to [{}]: device is offline", remote_id); offline_warning_text_ =
localization::device_offline[localization_language_index_];
show_offline_warning_window_ = true;
LOG_WARN("Presence probe failed for [{}], ret={}", remote_id, ret);
} else {
LOG_INFO("Presence probe requested for [{}] before connect", remote_id);
}
return -1; return -1;
} }

View File

@@ -1605,6 +1605,7 @@ void Render::MainLoop() {
UpdateLabels(); UpdateLabels();
HandleRecentConnections(); HandleRecentConnections();
HandleConnectionStatusChange(); HandleConnectionStatusChange();
HandlePendingPresenceProbe();
HandleStreamWindow(); HandleStreamWindow();
HandleServerWindow(); HandleServerWindow();
@@ -1684,6 +1685,84 @@ void Render::HandleConnectionStatusChange() {
need_to_send_recent_connections_ = false; need_to_send_recent_connections_ = false;
} }
void Render::HandlePendingPresenceProbe() {
bool has_action = false;
bool should_connect = false;
bool remember_password = false;
std::string remote_id;
std::string password;
{
std::lock_guard<std::mutex> lock(pending_presence_probe_mutex_);
if (!pending_presence_probe_ || !pending_presence_result_ready_) {
return;
}
has_action = true;
should_connect = pending_presence_online_;
remote_id = pending_presence_remote_id_;
password = pending_presence_password_;
remember_password = pending_presence_remember_password_;
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 (!has_action) {
return;
}
if (should_connect) {
ConnectTo(remote_id, password.c_str(), remember_password, true);
return;
}
offline_warning_text_ =
localization::device_offline[localization_language_index_];
show_offline_warning_window_ = true;
}
int Render::RequestSingleDevicePresence(const std::string& remote_id,
const char* password,
bool remember_password) {
if (!signal_connected_ || !peer_) {
return -1;
}
{
std::lock_guard<std::mutex> lock(pending_presence_probe_mutex_);
pending_presence_probe_ = true;
pending_presence_result_ready_ = false;
pending_presence_online_ = false;
pending_presence_remote_id_ = remote_id;
pending_presence_password_ = password ? password : "";
pending_presence_remember_password_ = remember_password;
}
nlohmann::json j;
j["type"] = "recent_connections_presence";
j["user_id"] = client_id_;
j["devices"] = nlohmann::json::array({remote_id});
auto s = j.dump();
int ret = SendSignalMessage(peer_, s.data(), s.size());
if (ret != 0) {
std::lock_guard<std::mutex> lock(pending_presence_probe_mutex_);
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;
}
return ret;
}
void Render::HandleStreamWindow() { void Render::HandleStreamWindow() {
if (need_to_create_stream_window_) { if (need_to_create_stream_window_) {
CreateStreamWindow(); CreateStreamWindow();

View File

@@ -194,6 +194,7 @@ class Render {
void UpdateInteractions(); void UpdateInteractions();
void HandleRecentConnections(); void HandleRecentConnections();
void HandleConnectionStatusChange(); void HandleConnectionStatusChange();
void HandlePendingPresenceProbe();
void HandleStreamWindow(); void HandleStreamWindow();
void HandleServerWindow(); void HandleServerWindow();
void Cleanup(); void Cleanup();
@@ -243,7 +244,9 @@ class Render {
private: private:
int ConnectTo(const std::string& remote_id, const char* password, int ConnectTo(const std::string& remote_id, const char* password,
bool remember_password); bool remember_password, bool bypass_presence_check = false);
int RequestSingleDevicePresence(const std::string& remote_id,
const char* password, bool remember_password);
int CreateMainWindow(); int CreateMainWindow();
int DestroyMainWindow(); int DestroyMainWindow();
int CreateStreamWindow(); int CreateStreamWindow();
@@ -690,6 +693,13 @@ class Render {
std::unordered_map<std::string, std::string> connection_host_names_; std::unordered_map<std::string, std::string> connection_host_names_;
std::string selected_server_remote_id_ = ""; std::string selected_server_remote_id_ = "";
std::string selected_server_remote_hostname_ = ""; std::string selected_server_remote_hostname_ = "";
std::mutex pending_presence_probe_mutex_;
bool pending_presence_probe_ = false;
bool pending_presence_result_ready_ = false;
bool pending_presence_online_ = false;
std::string pending_presence_remote_id_ = "";
std::string pending_presence_password_ = "";
bool pending_presence_remember_password_ = false;
FileTransferState file_transfer_; FileTransferState file_transfer_;
}; };
} // namespace crossdesk } // namespace crossdesk

View File

@@ -48,6 +48,15 @@ void Render::OnSignalMessageCb(const char* message, size_t size,
std::string id = dev["id"].get<std::string>(); std::string id = dev["id"].get<std::string>();
bool online = dev["online"].get<bool>(); bool online = dev["online"].get<bool>();
render->device_presence_.SetOnline(id, online); render->device_presence_.SetOnline(id, online);
{
std::lock_guard<std::mutex> lock(
render->pending_presence_probe_mutex_);
if (render->pending_presence_probe_ &&
render->pending_presence_remote_id_ == id) {
render->pending_presence_result_ready_ = true;
render->pending_presence_online_ = online;
}
}
} }
} }
} else if (type == "presence_update") { } else if (type == "presence_update") {
@@ -57,6 +66,15 @@ void Render::OnSignalMessageCb(const char* message, size_t size,
bool online = j["online"].get<bool>(); bool online = j["online"].get<bool>();
if (!id.empty()) { if (!id.empty()) {
render->device_presence_.SetOnline(id, online); render->device_presence_.SetOnline(id, online);
{
std::lock_guard<std::mutex> lock(
render->pending_presence_probe_mutex_);
if (render->pending_presence_probe_ &&
render->pending_presence_remote_id_ == id) {
render->pending_presence_result_ready_ = true;
render->pending_presence_online_ = online;
}
}
} }
} }
} }
@@ -498,9 +516,9 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size,
const double bps = const double bps =
(static_cast<double>(delta_bytes) * 8.0) / delta_seconds; (static_cast<double>(delta_bytes) * 8.0) / delta_seconds;
if (bps > 0.0) { if (bps > 0.0) {
const double capped = (std::min)( const double capped =
bps, (std::min)(bps, static_cast<double>(
static_cast<double>((std::numeric_limits<uint32_t>::max)())); (std::numeric_limits<uint32_t>::max)()));
estimated_rate_bps = static_cast<uint32_t>(capped); estimated_rate_bps = static_cast<uint32_t>(capped);
} }
} }