From ed9fc9aa7b6f5631a000e4a5eaa55344720e21d0 Mon Sep 17 00:00:00 2001 From: Edo Date: Tue, 21 Mar 2023 18:14:11 +0000 Subject: [PATCH] [RCon]: Properly fix rare crash (#861) --- src/Components/Modules/RCon.cpp | 115 +++++++++++++++++--------------- src/Components/Modules/RCon.hpp | 2 + 2 files changed, 63 insertions(+), 54 deletions(-) diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index 029c42bc..ddab0636 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -143,6 +143,63 @@ namespace Components } } + void RCon::RconExecuter(const Network::Address& address, std::string data) + { + Utils::String::Trim(data); + + const auto pos = data.find_first_of(' '); + if (pos == std::string::npos) + { + Logger::Print(Game::CON_CHANNEL_NETWORK, "Invalid RCon request from {}\n", address.getString()); + return; + } + + auto password = data.substr(0, pos); + auto command = data.substr(pos + 1); + + // B3 sends the password inside quotes :S + if (!password.empty() && password[0] == '"' && password.back() == '"') + { + password.pop_back(); + password.erase(password.begin()); + } + + const auto svPassword = RconPassword.get(); + if (svPassword.empty()) + { + Logger::Print(Game::CON_CHANNEL_NETWORK, "RCon request from {} dropped. No password set!\n", address.getString()); + return; + } + + if (svPassword != password) + { + Logger::Print(Game::CON_CHANNEL_NETWORK, "Invalid RCon password sent from {}\n", address.getString()); + return; + } + + static std::string outputBuffer; + outputBuffer.clear(); + +#ifndef _DEBUG + if (RconLogRequests.get()) +#endif + { + Logger::Print(Game::CON_CHANNEL_NETWORK, "Executing RCon request from {}: {}\n", address.getString(), command); + } + + Logger::PipeOutput([](const std::string& output) + { + outputBuffer.append(output); + }); + + Command::Execute(command, true); + + Logger::PipeOutput(nullptr); + + Network::SendCommand(address, "print", outputBuffer); + outputBuffer.clear(); + } + RCon::RCon() { Events::OnSVInit(AddCommands); @@ -213,61 +270,11 @@ namespace Components RateLimitCleanup(time); - std::string data_ = data; - Utils::String::Trim(data_); - - const auto pos = data.find_first_of(' '); - if (pos == std::string::npos) + auto rconData = data; + Scheduler::Once([address, s = std::move(rconData)] { - Logger::Print(Game::CON_CHANNEL_NETWORK, "Invalid RCon request from {}\n", address.getString()); - return; - } - - auto password = data.substr(0, pos); - auto command = data.substr(pos + 1); - - // B3 sends the password inside quotes :S - if (!password.empty() && password[0] == '"' && password.back() == '"') - { - password.pop_back(); - password.erase(password.begin()); - } - - const auto svPassword = RconPassword.get(); - - if (svPassword.empty()) - { - Logger::Print(Game::CON_CHANNEL_NETWORK, "RCon request from {} dropped. No password set!\n", address.getString()); - return; - } - - if (svPassword != password) - { - Logger::Print(Game::CON_CHANNEL_NETWORK, "Invalid RCon password sent from {}\n", address.getString()); - return; - } - - static std::string outputBuffer; - outputBuffer.clear(); - -#ifndef DEBUG - if (RconLogRequests.get()) -#endif - { - Logger::Print(Game::CON_CHANNEL_NETWORK, "Executing RCon request from {}: {}\n", address.getString(), command); - } - - Logger::PipeOutput([](const std::string& output) - { - outputBuffer.append(output); - }); - - Command::Execute(command, true); - - Logger::PipeOutput(nullptr); - - Network::SendCommand(address, "print", outputBuffer); - outputBuffer.clear(); + RconExecuter(address, s); + }, Scheduler::Pipeline::MAIN); }); Network::OnClientPacket("rconRequest", [](const Network::Address& address, [[maybe_unused]] const std::string& data) diff --git a/src/Components/Modules/RCon.hpp b/src/Components/Modules/RCon.hpp index 907592c6..eef8d404 100644 --- a/src/Components/Modules/RCon.hpp +++ b/src/Components/Modules/RCon.hpp @@ -47,5 +47,7 @@ namespace Components static bool IsRateLimitCheckDisabled(); static bool RateLimitCheck(const Network::Address& address, int time); static void RateLimitCleanup(int time); + + static void RconExecuter(const Network::Address& address, std::string data); }; }