From cf44e2041e3987432c95d7e21d97e207bbf86acb Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Mon, 28 Mar 2022 18:17:29 -0700 Subject: [PATCH] add card config backup --- src/ProxyServer.cc | 36 +++++++++++++++++++++++++++++++----- src/ProxyServer.hh | 3 ++- src/SendCommands.cc | 10 +++++----- src/ServerShell.cc | 16 +++++++++------- 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/ProxyServer.cc b/src/ProxyServer.cc index 8fd3ea8b..6bee1cf9 100644 --- a/src/ProxyServer.cc +++ b/src/ProxyServer.cc @@ -41,7 +41,8 @@ static void flush_and_free_bufferevent(struct bufferevent* bev) { ProxyServer::ProxyServer( shared_ptr base, shared_ptr state) - : base(base), + : save_quests(false), + base(base), state(state) { } void ProxyServer::listen(uint16_t port, GameVersion version) { @@ -290,8 +291,7 @@ ProxyServer::LinkedSession::LinkedSession( local_port(local_port), version(version), sub_version(0), // This is set during resume() - guild_card_number(0), - save_quests(false) { + guild_card_number(0) { memset(this->client_config_data, 0, 0x20); memset(&this->next_destination, 0, sizeof(this->next_destination)); struct sockaddr_in* dest_sin = reinterpret_cast(&this->next_destination); @@ -653,7 +653,7 @@ void ProxyServer::LinkedSession::on_server_input() { case 0x44: case 0xA6: { - if (!this->save_quests) { + if (!this->server->save_quests) { break; } @@ -693,7 +693,7 @@ void ProxyServer::LinkedSession::on_server_input() { case 0x13: case 0xA7: { - if (!this->save_quests) { + if (!this->server->save_quests) { break; } @@ -744,6 +744,32 @@ void ProxyServer::LinkedSession::on_server_input() { } break; } + + case 0xB8: { + if (!this->server->save_quests) { + break; + } + if (data.size() < 4) { + log(WARNING, "[ProxyServer/%08" PRIX32 "] Card list data size is too small; skipping file", + this->license->serial_number); + break; + } + + StringReader r(data); + size_t size = r.get_u32l(); + if (r.remaining() < size) { + log(WARNING, "[ProxyServer/%08" PRIX32 "] Card list data size extends beyond end of command; skipping file", + this->license->serial_number); + break; + } + + string output_filename = string_printf("cardupdate.mnr.%" PRIu64, now()); + save_file(output_filename, r.read(size)); + + log(INFO, "[ProxyServer/%08" PRIX32 "] Wrote %zu bytes to %s", + this->license->serial_number, size, output_filename.c_str()); + break; + } } if (should_forward) { diff --git a/src/ProxyServer.hh b/src/ProxyServer.hh index 99542638..13197680 100644 --- a/src/ProxyServer.hh +++ b/src/ProxyServer.hh @@ -62,7 +62,6 @@ public: const std::string& output_filename, uint32_t remaining_bytes); }; - bool save_quests; std::unordered_map saving_quest_files; LinkedSession( @@ -100,6 +99,8 @@ public: std::shared_ptr get_session(); void delete_session(uint32_t serial_number); + bool save_quests; + private: struct ListeningSocket { ProxyServer* server; diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 76a75a48..d5a6828f 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -2102,12 +2102,12 @@ void send_give_experience(shared_ptr l, shared_ptr c, void send_ep3_card_list_update(shared_ptr c) { auto file_data = file_cache.get("system/ep3/cardupdate.mnr"); - string data("\0\0\0\0", 4); - *reinterpret_cast(data.data()) = file_data->size(); - data += *file_data; - data.resize((data.size() + 3) & ~3); + StringWriter w; + w.put_u32l(file_data->size()); + w.write(*file_data); + w.str().resize((w.str().size() + 3) & (~3)); - send_command(c, 0xB8, 0x00, data); + send_command(c, 0xB8, 0x00, w.str()); } // sends the client a generic rank diff --git a/src/ServerShell.cc b/src/ServerShell.cc index a6e2238e..42b4f8a8 100644 --- a/src/ServerShell.cc +++ b/src/ServerShell.cc @@ -303,14 +303,16 @@ Proxy commands (these will only work when exactly one client is connected):\n\ session->send_to_end(data, true); } else if (command_name == "set-save-quests") { - auto session = this->get_proxy_session(); - - if (command_args == "on") { - session->save_quests = true; - } else if (command_args == "off") { - session->save_quests = false; + if (this->state->proxy_server.get()) { + if (command_args == "on") { + this->state->proxy_server->save_quests = true; + } else if (command_args == "off") { + this->state->proxy_server->save_quests = false; + } else { + throw invalid_argument("argument must be \"on\" or \"off\""); + } } else { - throw invalid_argument("argument must be \"on\" or \"off\""); + throw invalid_argument("proxy server is not available"); }