Add login lock session plumbing

This commit is contained in:
2026-06-11 01:22:32 -04:00
parent f18d5a468c
commit 6a4789b248
5 changed files with 104 additions and 0 deletions
+53
View File
@@ -170,6 +170,59 @@ void configure_from_json(const phosg::JSON& json) {
configure(cfg);
}
asio::awaitable<LoginLockAcquireResult> acquire_login_lock(
uint32_t account_id,
const std::string& version_name,
const std::string& existing_session_nonce) {
auto cfg = get_config();
LoginLockAcquireResult ret;
if (!cfg.enabled || !cfg.enable_login_locks) {
co_return ret;
}
if (!existing_session_nonce.empty()) {
ret.session_nonce = existing_session_nonce;
co_return ret;
}
ret.session_nonce = std::format("{}-{}-{}", source_label(cfg), account_id, now_usecs());
std::fprintf(stderr,
"[AccountSync] warning login_locks enabled but coordinator acquire is not implemented; allowing account_id=%010u source=%s version=%s nonce=%s\n",
static_cast<unsigned int>(account_id),
source_label(cfg).c_str(),
version_name.c_str(),
ret.session_nonce.c_str());
co_return ret;
}
void notify_login_session_end(
uint32_t account_id,
const std::string& session_nonce,
const std::string& version_name) {
auto cfg = get_config();
if (!cfg.enabled || !cfg.enable_login_locks) {
return;
}
std::fprintf(stderr,
"[AccountSync] event=login_session_end source=%s source_region=%s source_ship=%s account_store=%s account_id=%010u session_nonce=%s version=%s\n",
source_label(cfg).c_str(),
cfg.source_region.c_str(),
cfg.source_ship.c_str(),
cfg.account_store.c_str(),
static_cast<unsigned int>(account_id),
session_nonce.c_str(),
version_name.c_str());
auto line = base_event_json(cfg, "login_session_end", account_id) +
std::format(",\"session_nonce\":\"{}\",\"version\":\"{}\"}}",
json_escape(session_nonce),
json_escape(version_name));
append_spool_line(cfg, line);
}
void notify_account_saved(uint32_t account_id, const std::string& filename) {
auto cfg = get_config();
if (!cfg.enabled || !cfg.notify_account_saves) {
+20
View File
@@ -2,6 +2,8 @@
#include <cstddef>
#include <cstdint>
#include <asio.hpp>
#include <string>
#include <phosg/JSON.hh>
@@ -33,6 +35,24 @@ struct Config {
void configure(const Config& cfg);
void configure_from_json(const phosg::JSON& json);
struct LoginLockAcquireResult {
bool allowed = true;
bool fail_open_used = false;
std::string session_nonce;
std::string message;
std::string holder_source;
};
asio::awaitable<LoginLockAcquireResult> acquire_login_lock(
uint32_t account_id,
const std::string& version_name,
const std::string& existing_session_nonce);
void notify_login_session_end(
uint32_t account_id,
const std::string& session_nonce,
const std::string& version_name);
void notify_account_saved(uint32_t account_id, const std::string& filename);
void notify_backup_saved(uint32_t account_id, size_t slot, const std::string& filename);
+9
View File
@@ -278,6 +278,15 @@ Client::~Client() {
this->bb_character_index);
}
}
if (this->account_sync_lock_acquired && this->login && this->login->account) {
AccountSync::notify_login_session_end(
this->login->account->account_id,
this->account_sync_session_nonce,
phosg::name_for_enum(this->version()));
this->account_sync_lock_acquired = false;
}
this->log.info_f("Deleted");
}
+3
View File
@@ -132,6 +132,9 @@ public:
uint64_t xb_user_id = 0;
uint32_t xb_unknown_a1b = 0;
std::shared_ptr<Login> login;
bool account_sync_lock_acquired = false;
uint32_t account_sync_lock_account_id = 0;
std::string account_sync_session_nonce;
std::shared_ptr<ProxySession> proxy_session;
// Patch server state (only used for PC_PATCH and BB_PATCH versions)
+19
View File
@@ -558,6 +558,25 @@ asio::awaitable<void> start_login_server_procedure(std::shared_ptr<Client> c) {
static asio::awaitable<void> on_login_complete(std::shared_ptr<Client> c) {
auto s = c->require_server_state();
if (c->login && c->login->account) {
auto lock_res = co_await AccountSync::acquire_login_lock(
c->login->account->account_id,
phosg::name_for_enum(c->version()),
c->account_sync_session_nonce);
if (!lock_res.allowed) {
c->log.info_f("Login lock denied: {}", lock_res.message);
c->channel->disconnect();
co_return;
}
if (!lock_res.session_nonce.empty()) {
c->account_sync_lock_acquired = true;
c->account_sync_lock_account_id = c->login->account->account_id;
c->account_sync_session_nonce = lock_res.session_nonce;
}
}
c->convert_account_to_temporary_if_nte();
if (!is_v4(c->version())) {