From 2f64172eada819f82a7f7e2947954d3553451016 Mon Sep 17 00:00:00 2001 From: dijunkun Date: Wed, 10 Dec 2025 00:09:49 +0800 Subject: [PATCH] [feat] use new client id and password if server switched --- src/gui/panels/local_peer_panel.cpp | 38 +++++- src/gui/render.cpp | 188 +++++++++++++++++++++++----- src/gui/render.h | 19 +++ src/gui/render_callback.cpp | 98 ++++++++++++--- 4 files changed, 289 insertions(+), 54 deletions(-) diff --git a/src/gui/panels/local_peer_panel.cpp b/src/gui/panels/local_peer_panel.cpp index adee432..62a9803 100644 --- a/src/gui/panels/local_peer_panel.cpp +++ b/src/gui/panels/local_peer_panel.cpp @@ -233,15 +233,41 @@ int Render::LocalWindow() { sizeof(password_saved_) - 1); password_saved_[sizeof(password_saved_) - 1] = '\0'; - std::string client_id_with_password = - std::string(client_id_) + "@" + password_saved_; - strncpy(client_id_with_password_, client_id_with_password.c_str(), - sizeof(client_id_with_password_) - 1); - client_id_with_password_[sizeof(client_id_with_password_) - 1] = - '\0'; + // if self hosted + if (config_center_->IsSelfHosted()) { + std::string self_hosted_id_str; + if (strlen(self_hosted_id_) > 0) { + const char* at_pos = strchr(self_hosted_id_, '@'); + if (at_pos != nullptr) { + self_hosted_id_str = + std::string(self_hosted_id_, at_pos - self_hosted_id_); + } else { + self_hosted_id_str = self_hosted_id_; + } + } else { + self_hosted_id_str = client_id_; + } + + std::string new_self_hosted_id = + self_hosted_id_str + "@" + password_saved_; + memset(&self_hosted_id_, 0, sizeof(self_hosted_id_)); + strncpy(self_hosted_id_, new_self_hosted_id.c_str(), + sizeof(self_hosted_id_) - 1); + self_hosted_id_[sizeof(self_hosted_id_) - 1] = '\0'; + + } else { + std::string client_id_with_password = + std::string(client_id_) + "@" + password_saved_; + strncpy(client_id_with_password_, client_id_with_password.c_str(), + sizeof(client_id_with_password_) - 1); + client_id_with_password_[sizeof(client_id_with_password_) - 1] = + '\0'; + } SaveSettingsIntoCacheFile(); + memset(new_password_, 0, sizeof(new_password_)); + LeaveConnection(peer_, client_id_); DestroyPeer(&peer_); focus_on_input_widget_ = true; diff --git a/src/gui/render.cpp b/src/gui/render.cpp index f69e42a..206092a 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -203,22 +203,41 @@ Render::~Render() {} int Render::SaveSettingsIntoCacheFile() { cd_cache_mutex_.lock(); - std::ofstream cd_cache_file(cache_path_ + "/secure_cache.enc", - std::ios::binary); - if (!cd_cache_file) { + + std::ofstream cd_cache_v2_file(cache_path_ + "/secure_cache_v2.enc", + std::ios::binary); + if (!cd_cache_v2_file) { cd_cache_mutex_.unlock(); return -1; } - memset(&cd_cache_.client_id_with_password, 0, - sizeof(cd_cache_.client_id_with_password)); - memcpy(cd_cache_.client_id_with_password, client_id_with_password_, + memset(&cd_cache_v2_.client_id_with_password, 0, + sizeof(cd_cache_v2_.client_id_with_password)); + memcpy(cd_cache_v2_.client_id_with_password, client_id_with_password_, sizeof(client_id_with_password_)); - memcpy(&cd_cache_.key, &aes128_key_, sizeof(aes128_key_)); - memcpy(&cd_cache_.iv, &aes128_iv_, sizeof(aes128_iv_)); + memcpy(&cd_cache_v2_.key, &aes128_key_, sizeof(aes128_key_)); + memcpy(&cd_cache_v2_.iv, &aes128_iv_, sizeof(aes128_iv_)); + + memset(&cd_cache_v2_.self_hosted_id, 0, sizeof(cd_cache_v2_.self_hosted_id)); + memcpy(cd_cache_v2_.self_hosted_id, self_hosted_id_, sizeof(self_hosted_id_)); + + cd_cache_v2_file.write(reinterpret_cast(&cd_cache_v2_), + sizeof(CDCacheV2)); + cd_cache_v2_file.close(); + + std::ofstream cd_cache_file(cache_path_ + "/secure_cache.enc", + std::ios::binary); + if (cd_cache_file) { + memset(&cd_cache_.client_id_with_password, 0, + sizeof(cd_cache_.client_id_with_password)); + memcpy(cd_cache_.client_id_with_password, client_id_with_password_, + sizeof(client_id_with_password_)); + memcpy(&cd_cache_.key, &aes128_key_, sizeof(aes128_key_)); + memcpy(&cd_cache_.iv, &aes128_iv_, sizeof(aes128_iv_)); + cd_cache_file.write(reinterpret_cast(&cd_cache_), sizeof(CDCache)); + cd_cache_file.close(); + } - cd_cache_file.write(reinterpret_cast(&cd_cache_), sizeof(CDCache)); - cd_cache_file.close(); cd_cache_mutex_.unlock(); return 0; @@ -226,33 +245,81 @@ int Render::SaveSettingsIntoCacheFile() { int Render::LoadSettingsFromCacheFile() { cd_cache_mutex_.lock(); - std::ifstream cd_cache_file(cache_path_ + "/secure_cache.enc", - std::ios::binary); - if (!cd_cache_file) { + + std::ifstream cd_cache_v2_file(cache_path_ + "/secure_cache_v2.enc", + std::ios::binary); + bool v2_file_exists = cd_cache_v2_file.good(); + + if (v2_file_exists) { + cd_cache_v2_file.read(reinterpret_cast(&cd_cache_v2_), + sizeof(CDCacheV2)); + cd_cache_v2_file.close(); + + memset(&client_id_with_password_, 0, sizeof(client_id_with_password_)); + memcpy(client_id_with_password_, cd_cache_v2_.client_id_with_password, + sizeof(client_id_with_password_)); + + memset(&self_hosted_id_, 0, sizeof(self_hosted_id_)); + memcpy(self_hosted_id_, cd_cache_v2_.self_hosted_id, + sizeof(self_hosted_id_)); + + memcpy(aes128_key_, cd_cache_v2_.key, sizeof(cd_cache_v2_.key)); + memcpy(aes128_iv_, cd_cache_v2_.iv, sizeof(cd_cache_v2_.iv)); + + LOG_INFO("Load settings from v2 cache file"); + } else { + std::ifstream cd_cache_file(cache_path_ + "/secure_cache.enc", + std::ios::binary); + if (!cd_cache_file) { + cd_cache_mutex_.unlock(); + + memset(password_saved_, 0, sizeof(password_saved_)); + memset(aes128_key_, 0, sizeof(aes128_key_)); + memset(aes128_iv_, 0, sizeof(aes128_iv_)); + memset(self_hosted_id_, 0, sizeof(self_hosted_id_)); + + thumbnail_.reset(); + thumbnail_ = std::make_shared(cache_path_ + "/thumbnails/"); + thumbnail_->GetKeyAndIv(aes128_key_, aes128_iv_); + thumbnail_->DeleteAllFilesInDirectory(); + + SaveSettingsIntoCacheFile(); + + return -1; + } + + cd_cache_file.read(reinterpret_cast(&cd_cache_), sizeof(CDCache)); + cd_cache_file.close(); + + memset(&cd_cache_v2_.client_id_with_password, 0, + sizeof(cd_cache_v2_.client_id_with_password)); + memcpy(cd_cache_v2_.client_id_with_password, + cd_cache_.client_id_with_password, + sizeof(cd_cache_.client_id_with_password)); + memcpy(&cd_cache_v2_.key, &cd_cache_.key, sizeof(cd_cache_.key)); + memcpy(&cd_cache_v2_.iv, &cd_cache_.iv, sizeof(cd_cache_.iv)); + + memset(&cd_cache_v2_.self_hosted_id, 0, + sizeof(cd_cache_v2_.self_hosted_id)); + + memset(&client_id_with_password_, 0, sizeof(client_id_with_password_)); + memcpy(client_id_with_password_, cd_cache_.client_id_with_password, + sizeof(client_id_with_password_)); + + memset(&self_hosted_id_, 0, sizeof(self_hosted_id_)); + + memcpy(aes128_key_, cd_cache_.key, sizeof(cd_cache_.key)); + memcpy(aes128_iv_, cd_cache_.iv, sizeof(cd_cache_.iv)); + cd_cache_mutex_.unlock(); - - memset(password_saved_, 0, sizeof(password_saved_)); - memset(aes128_key_, 0, sizeof(aes128_key_)); - memset(aes128_iv_, 0, sizeof(aes128_iv_)); - - thumbnail_.reset(); - thumbnail_ = std::make_shared(cache_path_ + "/thumbnails/"); - thumbnail_->GetKeyAndIv(aes128_key_, aes128_iv_); - thumbnail_->DeleteAllFilesInDirectory(); - SaveSettingsIntoCacheFile(); + cd_cache_mutex_.lock(); - return -1; + LOG_INFO("Migrated settings from v1 to v2 cache file"); } - cd_cache_file.read(reinterpret_cast(&cd_cache_), sizeof(CDCache)); - cd_cache_file.close(); cd_cache_mutex_.unlock(); - memset(&client_id_with_password_, 0, sizeof(client_id_with_password_)); - memcpy(client_id_with_password_, cd_cache_.client_id_with_password, - sizeof(client_id_with_password_)); - if (strchr(client_id_with_password_, '@') != nullptr) { std::string id, password; const char* at_pos = strchr(client_id_with_password_, '@'); @@ -273,9 +340,6 @@ int Render::LoadSettingsFromCacheFile() { password_saved_[sizeof(password_saved_) - 1] = '\0'; } - memcpy(aes128_key_, cd_cache_.key, sizeof(cd_cache_.key)); - memcpy(aes128_iv_, cd_cache_.iv, sizeof(cd_cache_.iv)); - thumbnail_.reset(); thumbnail_ = std::make_shared(cache_path_ + "/thumbnails/", aes128_key_, aes128_iv_); @@ -480,11 +544,68 @@ int Render::CreateConnectionPeer() { signal_server_port = config_center_->GetSignalServerPort(); coturn_server_port = config_center_->GetCoturnServerPort(); tls_cert_path = config_center_->GetCertFilePath(); + + std::string current_self_hosted_ip = config_center_->GetSignalServerHost(); + bool use_cached_id = false; + + // Check secure_cache_v2.enc exists or not + std::ifstream v2_file(cache_path_ + "/secure_cache_v2.enc", + std::ios::binary); + if (v2_file.good()) { + CDCacheV2 temp_cache; + v2_file.read(reinterpret_cast(&temp_cache), sizeof(CDCacheV2)); + v2_file.close(); + + if (strlen(temp_cache.self_hosted_id) > 0) { + memset(&self_hosted_id_, 0, sizeof(self_hosted_id_)); + strncpy(self_hosted_id_, temp_cache.self_hosted_id, + sizeof(self_hosted_id_) - 1); + self_hosted_id_[sizeof(self_hosted_id_) - 1] = '\0'; + use_cached_id = true; + + std::string id, password; + const char* at_pos = strchr(self_hosted_id_, '@'); + if (at_pos == nullptr) { + id = self_hosted_id_; + password.clear(); + } else { + id.assign(self_hosted_id_, at_pos - self_hosted_id_); + password = at_pos + 1; + } + + memset(&client_id_, 0, sizeof(client_id_)); + strncpy(client_id_, id.c_str(), sizeof(client_id_) - 1); + client_id_[sizeof(client_id_) - 1] = '\0'; + + memset(&password_saved_, 0, sizeof(password_saved_)); + strncpy(password_saved_, password.c_str(), sizeof(password_saved_) - 1); + password_saved_[sizeof(password_saved_) - 1] = '\0'; + } + } else { + memset(&self_hosted_id_, 0, sizeof(self_hosted_id_)); + LOG_INFO( + "secure_cache_v2.enc not found, will use empty id to get new id from " + "server"); + } + + if (use_cached_id && strlen(self_hosted_id_) > 0) { + memset(&self_hosted_user_id_, 0, sizeof(self_hosted_user_id_)); + strncpy(self_hosted_user_id_, self_hosted_id_, + sizeof(self_hosted_user_id_) - 1); + self_hosted_user_id_[sizeof(self_hosted_user_id_) - 1] = '\0'; + params_.user_id = self_hosted_user_id_; + } else { + memset(&self_hosted_user_id_, 0, sizeof(self_hosted_user_id_)); + params_.user_id = self_hosted_user_id_; + LOG_INFO( + "Using empty id for self-hosted server, server will assign new id"); + } } else { signal_server_ip = config_center_->GetDefaultServerHost(); signal_server_port = config_center_->GetDefaultSignalServerPort(); coturn_server_port = config_center_->GetDefaultCoturnServerPort(); tls_cert_path = config_center_->GetDefaultCertFilePath(); + params_.user_id = client_id_with_password_; } // self hosted server config @@ -554,7 +675,6 @@ int Render::CreateConnectionPeer() { params_.on_connection_status = OnConnectionStatusCb; params_.net_status_report = NetStatusReport; - params_.user_id = client_id_with_password_; params_.user_data = this; peer_ = CreatePeer(¶ms_); diff --git a/src/gui/render.h b/src/gui/render.h index f27f48c..917ec0f 100644 --- a/src/gui/render.h +++ b/src/gui/render.h @@ -277,8 +277,25 @@ class Render { unsigned char iv[16]; }; + struct CDCacheV2 { + char client_id_with_password[17]; + int language; + int video_quality; + int video_frame_rate; + int video_encode_format; + bool enable_hardware_video_codec; + bool enable_turn; + bool enable_srtp; + + unsigned char key[16]; + unsigned char iv[16]; + + char self_hosted_id[17]; + }; + private: CDCache cd_cache_; + CDCacheV2 cd_cache_v2_; std::mutex cd_cache_mutex_; std::unique_ptr config_center_; ConfigCenter::LANGUAGE localization_language_ = @@ -470,6 +487,8 @@ class Render { char client_id_display_[12] = ""; char client_id_with_password_[17] = ""; char password_saved_[7] = ""; + char self_hosted_id_[17] = ""; + char self_hosted_user_id_[17] = ""; int language_button_value_ = 0; int video_quality_button_value_ = 0; int video_frame_rate_button_value_ = 1; diff --git a/src/gui/render_callback.cpp b/src/gui/render_callback.cpp index a416426..2c5e692 100644 --- a/src/gui/render_callback.cpp +++ b/src/gui/render_callback.cpp @@ -1,4 +1,5 @@ #include +#include #include "device_controller.h" #include "localization.h" @@ -556,24 +557,93 @@ void Render::NetStatusReport(const char* client_id, size_t client_id_size, password = at_pos + 1; } - memset(&render->client_id_, 0, sizeof(render->client_id_)); - strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1); - render->client_id_[sizeof(render->client_id_) - 1] = '\0'; + bool is_self_hosted = render->config_center_->IsSelfHosted(); - memset(&render->password_saved_, 0, sizeof(render->password_saved_)); - strncpy(render->password_saved_, password.c_str(), - sizeof(render->password_saved_) - 1); - render->password_saved_[sizeof(render->password_saved_) - 1] = '\0'; + if (is_self_hosted) { + memset(&render->client_id_, 0, sizeof(render->client_id_)); + strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1); + render->client_id_[sizeof(render->client_id_) - 1] = '\0'; - memset(&render->client_id_with_password_, 0, - sizeof(render->client_id_with_password_)); - strncpy(render->client_id_with_password_, client_id, - sizeof(render->client_id_with_password_) - 1); - render->client_id_with_password_[sizeof(render->client_id_with_password_) - + memset(&render->password_saved_, 0, sizeof(render->password_saved_)); + strncpy(render->password_saved_, password.c_str(), + sizeof(render->password_saved_) - 1); + render->password_saved_[sizeof(render->password_saved_) - 1] = '\0'; + + memset(&render->self_hosted_id_, 0, sizeof(render->self_hosted_id_)); + strncpy(render->self_hosted_id_, client_id, + sizeof(render->self_hosted_id_) - 1); + render->self_hosted_id_[sizeof(render->self_hosted_id_) - 1] = '\0'; + + LOG_INFO("Use self-hosted client id [{}] and save to cache file", id); + + render->cd_cache_mutex_.lock(); + + std::ifstream v2_file_read(render->cache_path_ + "/secure_cache_v2.enc", + std::ios::binary); + if (v2_file_read.good()) { + v2_file_read.read(reinterpret_cast(&render->cd_cache_v2_), + sizeof(CDCacheV2)); + v2_file_read.close(); + } else { + memset(&render->cd_cache_v2_, 0, sizeof(CDCacheV2)); + memset(&render->cd_cache_v2_.client_id_with_password, 0, + sizeof(render->cd_cache_v2_.client_id_with_password)); + strncpy(render->cd_cache_v2_.client_id_with_password, + render->client_id_with_password_, + sizeof(render->cd_cache_v2_.client_id_with_password)); + memcpy(&render->cd_cache_v2_.key, &render->aes128_key_, + sizeof(render->cd_cache_v2_.key)); + memcpy(&render->cd_cache_v2_.iv, &render->aes128_iv_, + sizeof(render->cd_cache_v2_.iv)); + } + + memset(&render->cd_cache_v2_.self_hosted_id, 0, + sizeof(render->cd_cache_v2_.self_hosted_id)); + strncpy(render->cd_cache_v2_.self_hosted_id, client_id, + sizeof(render->cd_cache_v2_.self_hosted_id) - 1); + render->cd_cache_v2_ + .self_hosted_id[sizeof(render->cd_cache_v2_.self_hosted_id) - 1] = + '\0'; + + memset(&render->cd_cache_v2_.client_id_with_password, 0, + sizeof(render->cd_cache_v2_.client_id_with_password)); + strncpy(render->cd_cache_v2_.client_id_with_password, + render->client_id_with_password_, + sizeof(render->cd_cache_v2_.client_id_with_password)); + memcpy(&render->cd_cache_v2_.key, &render->aes128_key_, + sizeof(render->cd_cache_v2_.key)); + memcpy(&render->cd_cache_v2_.iv, &render->aes128_iv_, + sizeof(render->cd_cache_v2_.iv)); + std::ofstream cd_cache_v2_file( + render->cache_path_ + "/secure_cache_v2.enc", std::ios::binary); + if (cd_cache_v2_file) { + cd_cache_v2_file.write(reinterpret_cast(&render->cd_cache_v2_), + sizeof(CDCacheV2)); + cd_cache_v2_file.close(); + } + + render->cd_cache_mutex_.unlock(); + } else { + memset(&render->client_id_, 0, sizeof(render->client_id_)); + strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1); + render->client_id_[sizeof(render->client_id_) - 1] = '\0'; + + memset(&render->password_saved_, 0, sizeof(render->password_saved_)); + strncpy(render->password_saved_, password.c_str(), + sizeof(render->password_saved_) - 1); + render->password_saved_[sizeof(render->password_saved_) - 1] = '\0'; + + memset(&render->client_id_with_password_, 0, + sizeof(render->client_id_with_password_)); + strncpy(render->client_id_with_password_, client_id, + sizeof(render->client_id_with_password_) - 1); + render + ->client_id_with_password_[sizeof(render->client_id_with_password_) - 1] = '\0'; - LOG_INFO("Use client id [{}] and save id into cache file", id); - render->SaveSettingsIntoCacheFile(); + LOG_INFO("Use client id [{}] and save id into cache file", id); + render->SaveSettingsIntoCacheFile(); + } } std::string remote_id(user_id, user_id_size);