fix: close server window after controller disconnects

This commit is contained in:
dijunkun
2026-07-27 00:22:33 +08:00
parent 7cd0d6a351
commit 765452e3c9
7 changed files with 374 additions and 343 deletions
+75 -23
View File
@@ -1,5 +1,3 @@
#include "runtime/gui_runtime.h"
#include <algorithm>
#include <chrono>
#include <cstring>
@@ -12,6 +10,7 @@
#include "localization.h"
#include "rd_log.h"
#include "runtime/gui_runtime.h"
namespace crossdesk {
@@ -22,7 +21,7 @@ bool IsConnectionAttemptPending(ConnectionStatus status) {
return status == ConnectionStatus::Connecting ||
status == ConnectionStatus::Gathering;
}
} // namespace
} // namespace
void GuiRuntime::HandleConnectionStatusChange() {
if (signal_connected_ && peer_ && need_to_send_recent_connections_) {
@@ -31,7 +30,7 @@ void GuiRuntime::HandleConnectionStatusChange() {
j["type"] = "recent_connections_presence";
j["user_id"] = client_id_;
j["devices"] = nlohmann::json::array();
for (const auto &id : recent_connection_ids_) {
for (const auto& id : recent_connection_ids_) {
std::string pure_id = id;
size_t pos_y = pure_id.find('Y');
size_t pos_n = pure_id.find('N');
@@ -123,7 +122,7 @@ void GuiRuntime::HandleConnectionTimeouts() {
}
bool rejoin_state_changed = false;
for (auto &[_, props] : remote_sessions_) {
for (auto& [_, props] : remote_sessions_) {
if (!props || !props->connection_attempt_active_.load()) {
continue;
}
@@ -152,7 +151,7 @@ void GuiRuntime::HandleConnectionTimeouts() {
if (rejoin_state_changed) {
need_to_rejoin_ = false;
for (const auto &[_, props] : remote_sessions_) {
for (const auto& [_, props] : remote_sessions_) {
if (props && props->rejoin_) {
need_to_rejoin_ = true;
break;
@@ -161,8 +160,65 @@ void GuiRuntime::HandleConnectionTimeouts() {
}
}
int GuiRuntime::RequestSingleDevicePresence(const std::string &remote_id,
const char *password,
void GuiRuntime::HandleServerControllerDisconnected(
const std::string& remote_id, const char* reason) {
keyboard_.ReleaseRemotePressedKeys(remote_id, reason);
bool has_connected_controller = false;
bool has_web_controller = false;
std::string remaining_controller_id;
{
std::unique_lock lock(connection_status_mutex_);
connection_status_.erase(remote_id);
connection_host_names_.erase(remote_id);
for (const auto& [id, status] : connection_status_) {
if (status != ConnectionStatus::Connected) {
continue;
}
has_connected_controller = true;
has_web_controller =
has_web_controller || id.find("web") != std::string::npos;
if (remaining_controller_id.empty()) {
remaining_controller_id = id;
}
}
}
show_cursor_ = has_web_controller;
if (has_connected_controller) {
remote_client_id_ = remaining_controller_id;
return;
}
need_to_create_server_window_.store(false, std::memory_order_release);
need_to_destroy_server_window_.store(true, std::memory_order_release);
is_server_mode_ = false;
#if defined(__linux__) && !defined(__APPLE__)
if (IsWaylandSession()) {
// Keep Wayland capture session warm to avoid black screen on subsequent
// reconnects.
start_screen_capturer_ = true;
LOG_INFO(
"Keeping Wayland screen capturer running after disconnect to "
"preserve reconnect stability");
} else {
start_screen_capturer_ = false;
}
#else
start_screen_capturer_ = false;
#endif
start_speaker_capturer_ = false;
start_mouse_controller_ = false;
start_keyboard_capturer_ = false;
remote_client_id_.clear();
if (audio_capture_) {
devices_.StopSpeakerCapturer();
audio_capture_ = false;
}
devices_.ResetToInitialDisplay();
}
int GuiRuntime::RequestSingleDevicePresence(const std::string& remote_id,
const char* password,
bool remember_password) {
if (!signal_connected_ || !peer_) {
return -1;
@@ -221,7 +277,7 @@ void GuiRuntime::CloseRemoteSession(std::shared_ptr<RemoteSession> props) {
std::thread save_thread([buffer_copy, video_width, video_height, remote_id,
remote_host_name, password,
thumbnail = thumbnail_]() {
thumbnail->SaveToThumbnail((char *)buffer_copy.data(), video_width,
thumbnail->SaveToThumbnail((char*)buffer_copy.data(), video_width,
video_height, remote_id, remote_host_name,
password);
});
@@ -255,7 +311,7 @@ void GuiRuntime::CloseAllRemoteSessions() {
{
// std::shared_lock lock(remote_sessions_mutex_);
for (auto &it : remote_sessions_) {
for (auto& it : remote_sessions_) {
auto props = it.second;
CloseRemoteSession(props);
}
@@ -279,7 +335,7 @@ void GuiRuntime::WaitForThumbnailSaveTasks() {
return;
}
for (auto &thread : threads_to_join) {
for (auto& thread : threads_to_join) {
if (thread.joinable()) {
thread.join();
}
@@ -300,9 +356,8 @@ void GuiRuntime::ResetRemoteSessionResources(
}
}
std::shared_ptr<GuiRuntime::RemoteSession>
GuiRuntime::FindRemoteSession(
const std::string &remote_id) {
std::shared_ptr<GuiRuntime::RemoteSession> GuiRuntime::FindRemoteSession(
const std::string& remote_id) {
if (remote_id.empty()) {
return nullptr;
}
@@ -315,8 +370,7 @@ GuiRuntime::FindRemoteSession(
return it->second;
}
int GuiRuntime::ConnectTo(const std::string &remote_id, const char *password,
int GuiRuntime::ConnectTo(const std::string& remote_id, const char* password,
bool remember_password, bool bypass_presence_check) {
if (!bypass_presence_check && !device_presence_cache_.IsOnline(remote_id)) {
int ret =
@@ -336,19 +390,17 @@ int GuiRuntime::ConnectTo(const std::string &remote_id, const char *password,
focused_remote_id_ = remote_id;
// std::shared_lock shared_lock(remote_sessions_mutex_);
bool exists =
(remote_sessions_.find(remote_id) != remote_sessions_.end());
bool exists = (remote_sessions_.find(remote_id) != remote_sessions_.end());
// shared_lock.unlock();
if (!exists) {
PeerPtr *peer_to_init = nullptr;
PeerPtr* peer_to_init = nullptr;
std::string local_id;
{
// std::unique_lock unique_lock(remote_sessions_mutex_);
if (remote_sessions_.find(remote_id) == remote_sessions_.end()) {
remote_sessions_[remote_id] =
std::make_shared<RemoteSession>();
remote_sessions_[remote_id] = std::make_shared<RemoteSession>();
auto props = remote_sessions_[remote_id];
props->local_id_ = "C-" + std::string(client_id_);
props->remote_id_ = remote_id;
@@ -371,7 +423,7 @@ int GuiRuntime::ConnectTo(const std::string &remote_id, const char *password,
return -1;
}
for (const auto &display_info : devices_.display_info_list()) {
for (const auto& display_info : devices_.display_info_list()) {
AddVideoStream(props->peer_, display_info.name.c_str());
}
AddAudioStream(props->peer_, props->audio_label_.c_str());
@@ -429,4 +481,4 @@ int GuiRuntime::ConnectTo(const std::string &remote_id, const char *password,
return 0;
}
} // namespace crossdesk
} // namespace crossdesk
+19 -19
View File
@@ -8,16 +8,16 @@
#include "features/devices/session_device_manager.h"
#include "features/file_transfer/file_transfer_manager.h"
#include "features/input/keyboard_controller.h"
#include "features/settings/settings_manager.h"
#include "runtime/gui_state.h"
#include "runtime/peer_event_handler.h"
#include "features/settings/settings_manager.h"
namespace crossdesk {
// Shared GUI runtime. It owns subsystem controllers and cross-cutting session
// state, but no window lifecycle, ImGui view, or transport callback methods.
class GuiRuntime : protected gui_detail::GuiState {
protected:
protected:
using FileTransferState = gui_detail::FileTransferState;
using RemoteSession = gui_detail::RemoteSession;
@@ -32,35 +32,35 @@ protected:
GuiRuntime();
~GuiRuntime();
static void SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len);
static void SdlCaptureAudioOut(void *userdata, Uint8 *stream, int len);
static void SdlCaptureAudioIn(void* userdata, Uint8* stream, int len);
static void SdlCaptureAudioOut(void* userdata, Uint8* stream, int len);
int CreateConnectionPeer();
int ConnectTo(const std::string &remote_id, const char *password,
int ConnectTo(const std::string& remote_id, const char* password,
bool remember_password, bool bypass_presence_check = false);
int RequestSingleDevicePresence(const std::string &remote_id,
const char *password, bool remember_password);
int RequestSingleDevicePresence(const std::string& remote_id,
const char* password, bool remember_password);
void UpdateLabels();
void HandleRecentConnections();
void HandleConnectionStatusChange();
void HandlePendingPresenceProbe();
void HandleConnectionTimeouts();
void HandleServerControllerDisconnected(const std::string& remote_id,
const char* reason);
void HandleWindowsServiceIntegration();
void CloseRemoteSession(std::shared_ptr<RemoteSession> props);
void CloseAllRemoteSessions();
void ResetRemoteSessionResources(
std::shared_ptr<RemoteSession> props);
void ResetRemoteSessionResources(std::shared_ptr<RemoteSession> props);
void WaitForThumbnailSaveTasks();
std::shared_ptr<RemoteSession>
FindRemoteSession(const std::string &remote_id);
std::shared_ptr<RemoteSession> FindRemoteSession(
const std::string& remote_id);
void ResetRemoteServiceStatus(RemoteSession &props);
void ApplyRemoteServiceStatus(RemoteSession &props,
const ServiceStatus &status);
RemoteUnlockState
GetRemoteUnlockState(const RemoteSession &props) const;
void ResetRemoteServiceStatus(RemoteSession& props);
void ApplyRemoteServiceStatus(RemoteSession& props,
const ServiceStatus& status);
RemoteUnlockState GetRemoteUnlockState(const RemoteSession& props) const;
#if _WIN32
void ResetLocalWindowsServiceState(bool clear_pending_sas);
#endif
@@ -82,7 +82,7 @@ protected:
KeyboardController keyboard_;
PeerEventHandler peer_events_;
private:
private:
friend class ClipboardController;
friend class SessionDeviceManager;
friend class FileTransferManager;
@@ -91,6 +91,6 @@ private:
friend class PeerEventHandler;
};
} // namespace crossdesk
} // namespace crossdesk
#endif // CROSSDESK_GUI_RUNTIME_H_
#endif // CROSSDESK_GUI_RUNTIME_H_
+199 -246
View File
@@ -26,12 +26,12 @@
namespace crossdesk {
PeerEventHandler::PeerEventHandler(GuiRuntime &owner) : owner_(owner) {}
PeerEventHandler::PeerEventHandler(GuiRuntime& owner) : owner_(owner) {}
void PeerEventHandler::OnSignalMessage(const char *message, size_t size,
void *user_data) {
auto *handler = static_cast<PeerEventHandler *>(user_data);
GuiRuntime *runtime = handler ? &handler->owner_ : nullptr;
void PeerEventHandler::OnSignalMessage(const char* message, size_t size,
void* user_data) {
auto* handler = static_cast<PeerEventHandler*>(user_data);
GuiRuntime* runtime = handler ? &handler->owner_ : nullptr;
if (!runtime || !message || size == 0) {
return;
}
@@ -43,7 +43,7 @@ void PeerEventHandler::OnSignalMessage(const char *message, size_t size,
std::string type = j["type"].get<std::string>();
if (type == "presence") {
if (j.contains("devices") && j["devices"].is_array()) {
for (auto &dev : j["devices"]) {
for (auto& dev : j["devices"]) {
if (!dev.is_object()) {
continue;
}
@@ -88,11 +88,10 @@ void PeerEventHandler::OnSignalMessage(const char *message, size_t size,
}
}
void PeerEventHandler::OnSignalStatus(SignalStatus status, const char *user_id,
size_t user_id_size, void *user_data) {
auto *handler = static_cast<PeerEventHandler *>(user_data);
GuiRuntime *runtime = handler ? &handler->owner_ : nullptr;
void PeerEventHandler::OnSignalStatus(SignalStatus status, const char* user_id,
size_t user_id_size, void* user_data) {
auto* handler = static_cast<PeerEventHandler*>(user_data);
GuiRuntime* runtime = handler ? &handler->owner_ : nullptr;
if (!runtime) {
return;
}
@@ -150,13 +149,12 @@ void PeerEventHandler::OnSignalStatus(SignalStatus status, const char *user_id,
}
void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
const char *user_id,
const char* user_id,
const size_t user_id_size,
void *user_data) {
auto *handler = static_cast<PeerEventHandler *>(user_data);
GuiRuntime *runtime = handler ? &handler->owner_ : nullptr;
if (!runtime)
return;
void* user_data) {
auto* handler = static_cast<PeerEventHandler*>(user_data);
GuiRuntime* runtime = handler ? &handler->owner_ : nullptr;
if (!runtime) return;
std::string remote_id(user_id, user_id_size);
std::shared_ptr<GuiRuntime::RemoteSession> props;
@@ -178,107 +176,110 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
}
switch (status) {
case ConnectionStatus::Connected: {
runtime->ResetRemoteServiceStatus(*props);
{
RemoteAction remote_action;
remote_action.i.display_num =
runtime->devices_.display_info_list().size();
remote_action.i.display_list =
(char **)malloc(remote_action.i.display_num * sizeof(char *));
remote_action.i.left =
(int *)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.top =
(int *)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.right =
(int *)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.bottom =
(int *)malloc(remote_action.i.display_num * sizeof(int));
for (int i = 0; i < remote_action.i.display_num; i++) {
LOG_INFO("Local display [{}:{}]", i + 1,
runtime->devices_.display_info_list()[i].name);
remote_action.i.display_list[i] = (char *)malloc(
runtime->devices_.display_info_list()[i].name.length() + 1);
strncpy(remote_action.i.display_list[i],
runtime->devices_.display_info_list()[i].name.c_str(),
runtime->devices_.display_info_list()[i].name.length());
remote_action.i.display_list
[i][runtime->devices_.display_info_list()[i].name.length()] = '\0';
remote_action.i.left[i] =
runtime->devices_.display_info_list()[i].left;
remote_action.i.top[i] = runtime->devices_.display_info_list()[i].top;
remote_action.i.right[i] =
runtime->devices_.display_info_list()[i].right;
remote_action.i.bottom[i] =
runtime->devices_.display_info_list()[i].bottom;
case ConnectionStatus::Connected: {
runtime->ResetRemoteServiceStatus(*props);
{
RemoteAction remote_action;
remote_action.i.display_num =
runtime->devices_.display_info_list().size();
remote_action.i.display_list =
(char**)malloc(remote_action.i.display_num * sizeof(char*));
remote_action.i.left =
(int*)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.top =
(int*)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.right =
(int*)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.bottom =
(int*)malloc(remote_action.i.display_num * sizeof(int));
for (int i = 0; i < remote_action.i.display_num; i++) {
LOG_INFO("Local display [{}:{}]", i + 1,
runtime->devices_.display_info_list()[i].name);
remote_action.i.display_list[i] = (char*)malloc(
runtime->devices_.display_info_list()[i].name.length() + 1);
strncpy(remote_action.i.display_list[i],
runtime->devices_.display_info_list()[i].name.c_str(),
runtime->devices_.display_info_list()[i].name.length());
remote_action.i
.display_list[i][runtime->devices_.display_info_list()[i]
.name.length()] = '\0';
remote_action.i.left[i] =
runtime->devices_.display_info_list()[i].left;
remote_action.i.top[i] =
runtime->devices_.display_info_list()[i].top;
remote_action.i.right[i] =
runtime->devices_.display_info_list()[i].right;
remote_action.i.bottom[i] =
runtime->devices_.display_info_list()[i].bottom;
}
std::string host_name = GetHostName();
remote_action.type = ControlType::host_infomation;
memcpy(&remote_action.i.host_name, host_name.data(),
host_name.size());
remote_action.i.host_name[host_name.size()] = '\0';
remote_action.i.host_name_size = host_name.size();
std::string msg = remote_action.to_json();
int ret = SendReliableDataFrame(props->peer_, msg.data(), msg.size(),
runtime->control_data_label_.c_str());
remote_action_codec::Free(remote_action);
}
std::string host_name = GetHostName();
remote_action.type = ControlType::host_infomation;
memcpy(&remote_action.i.host_name, host_name.data(), host_name.size());
remote_action.i.host_name[host_name.size()] = '\0';
remote_action.i.host_name_size = host_name.size();
std::string msg = remote_action.to_json();
int ret = SendReliableDataFrame(props->peer_, msg.data(), msg.size(),
runtime->control_data_label_.c_str());
remote_action_codec::Free(remote_action);
if (!runtime->need_to_create_stream_window_ &&
!runtime->remote_sessions_.empty()) {
runtime->need_to_create_stream_window_ = true;
}
props->connection_established_ = true;
runtime->start_keyboard_capturer_ = true;
break;
}
if (!runtime->need_to_create_stream_window_ &&
!runtime->remote_sessions_.empty()) {
runtime->need_to_create_stream_window_ = true;
}
props->connection_established_ = true;
runtime->start_keyboard_capturer_ = true;
break;
}
case ConnectionStatus::Disconnected:
case ConnectionStatus::Failed:
case ConnectionStatus::Closed: {
runtime->keyboard_.ReleaseRemotePressedKeys(remote_id,
"connection_closed");
props->connection_established_ = false;
props->enable_mouse_control_ = false;
runtime->ResetRemoteServiceStatus(*props);
{
std::lock_guard<std::mutex> lock(props->video_frame_mutex_);
props->front_frame_.reset();
props->back_frame_.reset();
props->video_width_ = 0;
props->video_height_ = 0;
props->video_size_ = 0;
props->render_rect_dirty_ = true;
props->stream_cleanup_pending_ = true;
}
runtime->focus_on_stream_window_ = false;
break;
}
case ConnectionStatus::IncorrectPassword: {
runtime->password_validating_ = false;
runtime->password_validating_time_++;
if (runtime->connect_button_pressed_) {
runtime->connect_button_pressed_ = false;
case ConnectionStatus::Disconnected:
case ConnectionStatus::Failed:
case ConnectionStatus::Closed: {
runtime->keyboard_.ReleaseRemotePressedKeys(remote_id,
"connection_closed");
props->connection_established_ = false;
runtime->connect_button_label_ =
localization::connect[runtime->localization_language_index_];
props->enable_mouse_control_ = false;
runtime->ResetRemoteServiceStatus(*props);
{
std::lock_guard<std::mutex> lock(props->video_frame_mutex_);
props->front_frame_.reset();
props->back_frame_.reset();
props->video_width_ = 0;
props->video_height_ = 0;
props->video_size_ = 0;
props->render_rect_dirty_ = true;
props->stream_cleanup_pending_ = true;
}
runtime->focus_on_stream_window_ = false;
break;
}
break;
}
case ConnectionStatus::NoSuchTransmissionId:
case ConnectionStatus::RemoteUnavailable: {
if (runtime->connect_button_pressed_) {
props->connection_established_ = false;
runtime->connect_button_label_ =
localization::connect[runtime->localization_language_index_];
case ConnectionStatus::IncorrectPassword: {
runtime->password_validating_ = false;
runtime->password_validating_time_++;
if (runtime->connect_button_pressed_) {
runtime->connect_button_pressed_ = false;
props->connection_established_ = false;
runtime->connect_button_label_ =
localization::connect[runtime->localization_language_index_];
}
break;
}
break;
}
default:
break;
case ConnectionStatus::NoSuchTransmissionId:
case ConnectionStatus::RemoteUnavailable: {
if (runtime->connect_button_pressed_) {
props->connection_established_ = false;
runtime->connect_button_label_ =
localization::connect[runtime->localization_language_index_];
}
break;
}
default:
break;
}
} else {
runtime->is_client_mode_ = false;
@@ -289,155 +290,107 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
}
switch (status) {
case ConnectionStatus::Connected: {
case ConnectionStatus::Connected: {
#if _WIN32
runtime->last_windows_service_status_tick_ = 0;
runtime->last_windows_service_status_tick_ = 0;
#endif
{
RemoteAction remote_action;
remote_action.i.display_num =
runtime->devices_.display_info_list().size();
remote_action.i.display_list =
(char **)malloc(remote_action.i.display_num * sizeof(char *));
remote_action.i.left =
(int *)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.top =
(int *)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.right =
(int *)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.bottom =
(int *)malloc(remote_action.i.display_num * sizeof(int));
for (int i = 0; i < remote_action.i.display_num; i++) {
LOG_INFO("Local display [{}:{}]", i + 1,
runtime->devices_.display_info_list()[i].name);
remote_action.i.display_list[i] = (char *)malloc(
runtime->devices_.display_info_list()[i].name.length() + 1);
strncpy(remote_action.i.display_list[i],
runtime->devices_.display_info_list()[i].name.c_str(),
runtime->devices_.display_info_list()[i].name.length());
remote_action.i.display_list
[i][runtime->devices_.display_info_list()[i].name.length()] = '\0';
remote_action.i.left[i] =
runtime->devices_.display_info_list()[i].left;
remote_action.i.top[i] = runtime->devices_.display_info_list()[i].top;
remote_action.i.right[i] =
runtime->devices_.display_info_list()[i].right;
remote_action.i.bottom[i] =
runtime->devices_.display_info_list()[i].bottom;
}
std::string host_name = GetHostName();
remote_action.type = ControlType::host_infomation;
memcpy(&remote_action.i.host_name, host_name.data(), host_name.size());
remote_action.i.host_name[host_name.size()] = '\0';
remote_action.i.host_name_size = host_name.size();
std::string msg = remote_action.to_json();
int ret = SendReliableDataFrame(runtime->peer_, msg.data(), msg.size(),
runtime->control_data_label_.c_str());
remote_action_codec::Free(remote_action);
}
runtime->need_to_create_server_window_ = true;
runtime->is_server_mode_ = true;
runtime->start_screen_capturer_ = true;
runtime->start_speaker_capturer_ = true;
runtime->remote_client_id_ = remote_id;
runtime->start_mouse_controller_ = true;
{
std::shared_lock lock(runtime->connection_status_mutex_);
if (std::all_of(runtime->connection_status_.begin(),
runtime->connection_status_.end(), [](const auto &kv) {
return kv.first.find("web") != std::string::npos;
})) {
runtime->show_cursor_ = true;
}
}
break;
}
case ConnectionStatus::Disconnected:
case ConnectionStatus::Failed:
case ConnectionStatus::Closed: {
runtime->keyboard_.ReleaseRemotePressedKeys(remote_id,
"connection_closed");
bool all_disconnected = false;
{
std::shared_lock lock(runtime->connection_status_mutex_);
all_disconnected =
std::all_of(runtime->connection_status_.begin(),
runtime->connection_status_.end(), [](const auto &kv) {
return kv.second == ConnectionStatus::Closed ||
kv.second == ConnectionStatus::Failed ||
kv.second == ConnectionStatus::Disconnected;
});
}
if (all_disconnected) {
runtime->need_to_destroy_server_window_ = true;
runtime->is_server_mode_ = false;
#if defined(__linux__) && !defined(__APPLE__)
if (IsWaylandSession()) {
// Keep Wayland capture session warm to avoid black screen on
// subsequent reconnects.
runtime->start_screen_capturer_ = true;
LOG_INFO("Keeping Wayland screen capturer running after "
"disconnect to preserve reconnect stability");
} else {
runtime->start_screen_capturer_ = false;
}
#else
runtime->start_screen_capturer_ = false;
#endif
runtime->start_speaker_capturer_ = false;
runtime->start_mouse_controller_ = false;
runtime->start_keyboard_capturer_ = false;
runtime->remote_client_id_ = "";
if (props)
props->connection_established_ = false;
if (runtime->audio_capture_) {
runtime->devices_.StopSpeakerCapturer();
runtime->audio_capture_ = false;
}
{
std::unique_lock lock(runtime->connection_status_mutex_);
runtime->connection_status_.erase(remote_id);
runtime->connection_host_names_.erase(remote_id);
}
runtime->devices_.ResetToInitialDisplay();
}
RemoteAction remote_action;
remote_action.i.display_num =
runtime->devices_.display_info_list().size();
remote_action.i.display_list =
(char**)malloc(remote_action.i.display_num * sizeof(char*));
remote_action.i.left =
(int*)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.top =
(int*)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.right =
(int*)malloc(remote_action.i.display_num * sizeof(int));
remote_action.i.bottom =
(int*)malloc(remote_action.i.display_num * sizeof(int));
for (int i = 0; i < remote_action.i.display_num; i++) {
LOG_INFO("Local display [{}:{}]", i + 1,
runtime->devices_.display_info_list()[i].name);
remote_action.i.display_list[i] = (char*)malloc(
runtime->devices_.display_info_list()[i].name.length() + 1);
strncpy(remote_action.i.display_list[i],
runtime->devices_.display_info_list()[i].name.c_str(),
runtime->devices_.display_info_list()[i].name.length());
remote_action.i
.display_list[i][runtime->devices_.display_info_list()[i]
.name.length()] = '\0';
remote_action.i.left[i] =
runtime->devices_.display_info_list()[i].left;
remote_action.i.top[i] =
runtime->devices_.display_info_list()[i].top;
remote_action.i.right[i] =
runtime->devices_.display_info_list()[i].right;
remote_action.i.bottom[i] =
runtime->devices_.display_info_list()[i].bottom;
}
{
std::shared_lock lock(runtime->connection_status_mutex_);
if (std::all_of(runtime->connection_status_.begin(),
runtime->connection_status_.end(), [](const auto &kv) {
return kv.first.find("web") == std::string::npos;
})) {
runtime->show_cursor_ = false;
}
}
std::string host_name = GetHostName();
remote_action.type = ControlType::host_infomation;
memcpy(&remote_action.i.host_name, host_name.data(),
host_name.size());
remote_action.i.host_name[host_name.size()] = '\0';
remote_action.i.host_name_size = host_name.size();
break;
}
default:
break;
std::string msg = remote_action.to_json();
int ret =
SendReliableDataFrame(runtime->peer_, msg.data(), msg.size(),
runtime->control_data_label_.c_str());
remote_action_codec::Free(remote_action);
}
runtime->need_to_destroy_server_window_.store(
false, std::memory_order_release);
runtime->need_to_create_server_window_.store(true,
std::memory_order_release);
runtime->is_server_mode_ = true;
runtime->start_screen_capturer_ = true;
runtime->start_speaker_capturer_ = true;
runtime->remote_client_id_ = remote_id;
runtime->start_mouse_controller_ = true;
{
std::shared_lock lock(runtime->connection_status_mutex_);
if (std::all_of(runtime->connection_status_.begin(),
runtime->connection_status_.end(),
[](const auto& kv) {
return kv.first.find("web") != std::string::npos;
})) {
runtime->show_cursor_ = true;
}
}
break;
}
case ConnectionStatus::Disconnected:
case ConnectionStatus::Failed:
case ConnectionStatus::Closed: {
runtime->HandleServerControllerDisconnected(remote_id,
"connection_closed");
break;
}
default:
break;
}
}
}
void PeerEventHandler::OnNetStatusReport(
const char *client_id, size_t client_id_size, TraversalMode mode,
const XNetTrafficStats *net_traffic_stats, const char *user_id,
const size_t user_id_size, void *user_data) {
auto *handler = static_cast<PeerEventHandler *>(user_data);
GuiRuntime *runtime = handler ? &handler->owner_ : nullptr;
const char* client_id, size_t client_id_size, TraversalMode mode,
const XNetTrafficStats* net_traffic_stats, const char* user_id,
const size_t user_id_size, void* user_data) {
auto* handler = static_cast<PeerEventHandler*>(user_data);
GuiRuntime* runtime = handler ? &handler->owner_ : nullptr;
if (!runtime) {
return;
}
if (strchr(client_id, '@') != nullptr && strchr(user_id, '-') == nullptr) {
std::string id, password;
const char *at_pos = strchr(client_id, '@');
const char* at_pos = strchr(client_id, '@');
if (at_pos == nullptr) {
id = client_id;
password.clear();
@@ -510,4 +463,4 @@ void PeerEventHandler::OnNetStatusReport(
props->net_traffic_stats_ = *net_traffic_stats;
}
}
} // namespace crossdesk
} // namespace crossdesk