Compare commits

..
10 Commits
Author SHA1 Message Date
Tixx d1bfdde406 Bump version to 3.9.4 2026-09-03 13:09:05 +02:00
Tixx 1b83b4bb3e Add time ping handling (#503)
client -> server `t[8 bytes]`
server -> client `t[client's 8 bytes][server time 8 bytes]`

---

By creating this pull request, I understand that code that is AI
generated or otherwise automatically generated may be rejected without
further discussion.
I declare that I fully understand all code I pushed into this PR, and
wrote all this code myself and own the rights to this code.
2026-08-22 22:04:23 +02:00
Tixx e7a5050e1b Change time offset and remove comment 2026-08-14 02:24:23 +02:00
Tixx b50f82166b Increase MP.GetServerTime precision
Function will break after 272 years
2026-08-14 02:18:25 +02:00
Tixx b21d4062c6 Add MP.GetServerTime in seconds 2026-08-08 13:42:55 +02:00
Tixx cd4cc3e630 Add servertime lua function 2026-08-07 01:33:44 +02:00
Tixx a8dfa4b004 Move server time partially into header file 2026-08-07 01:33:19 +02:00
Tixx 69233f4185 Add time ping handling 2026-08-04 22:51:40 +02:00
Tixx 176de6b5a5 Add BEAMMP_MAX_CONCURRENT_CONNECTIONS env var (#496)
By creating this pull request, I understand that code that is AI
generated or otherwise automatically generated may be rejected without
further discussion.
I declare that I fully understand all code I pushed into this PR, and
wrote all this code myself and own the rights to this code.
2026-06-27 21:29:10 +02:00
Tixx e33f47e838 Add BEAMMP_MAX_CONCURRENT_CONNECTIONS env var 2026-06-18 22:32:06 +02:00
7 changed files with 58 additions and 2 deletions

No files matched your search

+1 -1
View File
@@ -129,7 +129,7 @@ private:
static inline std::mutex mShutdownHandlersMutex {};
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
static inline Version mVersion { 3, 9, 3 };
static inline Version mVersion { 3, 9, 4 };
};
/// Used to static_assert in std::visit
+1
View File
@@ -23,6 +23,7 @@
namespace Env {
enum class Key {
MAX_CONCURRENT_CONNECTIONS,
// provider settings
PROVIDER_UPDATE_MESSAGE,
PROVIDER_DISABLE_CONFIG,
+3
View File
@@ -53,7 +53,10 @@ public:
io_context& IoCtx() { return mIoCtxPoller.IoCtx(); }
uint64_t GetServerTimeMS() const { return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - TimeSyncStart).count();}
double GetServerTime() const { return std::chrono::duration<double>(std::chrono::steady_clock::now() - TimeSyncStart).count(); }
private:
std::chrono::time_point<std::chrono::steady_clock> TimeSyncStart;
TIoPollThread mIoCtxPoller;
TClientSet mClients;
mutable RWMutex mClientsMutex;
+3
View File
@@ -45,6 +45,9 @@ std::string_view Env::ToString(Env::Key key) {
case Key::PROVIDER_IP_ENV:
return "BEAMMP_PROVIDER_IP_ENV";
break;
case Key::MAX_CONCURRENT_CONNECTIONS:
return "BEAMMP_MAX_CONCURRENT_CONNECTIONS";
break;
}
return "";
}
+8
View File
@@ -1012,6 +1012,14 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI
}
MPTable.set_function("Get", &LuaAPI::MP::Get);
MPTable.set_function("GetServerTimeMS", [this](const sol::this_state ts) {
return make_object(sol::state_view(ts), this->mEngine->Server().GetServerTimeMS());
});
MPTable.set_function("GetServerTime", [this](const sol::this_state ts) {
return make_object(sol::state_view(ts), this->mEngine->Server().GetServerTime());
});
auto UtilTable = StateView.create_named_table("Util");
UtilTable.set_function("LogDebug", [this](sol::variadic_args args) {
std::string ToPrint = "";
+18 -1
View File
@@ -19,6 +19,7 @@
#include "TNetwork.h"
#include "Client.h"
#include "Common.h"
#include "Env.h"
#include "LuaAPI.h"
#include "TConnectionLimiter.h"
#include "THeartbeatThread.h"
@@ -45,8 +46,24 @@
typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO> rcv_timeout_option;
static constexpr uint8_t MAX_CONCURRENT_CONNECTIONS = 10;
static constexpr uint8_t MAX_GLOBAL_CONNECTIONS = 128;
static const uint8_t MAX_CONCURRENT_CONNECTIONS = []() -> uint8_t {
if (auto EnvVar = Env::Get(Env::Key::MAX_CONCURRENT_CONNECTIONS)) {
try {
beammp_debugf("BEAMMP_MAX_CONCURRENT_CONNECTIONS: {}", EnvVar.value());
if (const int value = std::stoi(std::string(EnvVar.value())); value > 0 && value <= MAX_GLOBAL_CONNECTIONS) {
beammp_debugf("BEAMMP_MAX_CONCURRENT_CONNECTIONS Parsed: {}", value);
return static_cast<uint8_t>(value);
}
beammp_warn("Env variable BEAMMP_MAX_CONCURRENT_CONNECTIONS is out of range, using default value.");
} catch (const std::exception&) {
beammp_warn("Error parsing Env variable BEAMMP_MAX_CONCURRENT_CONNECTIONS, using default value.");
}
}
return 10;
}();
static constexpr uint8_t READ_TIMEOUT_S = 10; // seconds
std::vector<uint8_t> StringToVector(const std::string& Str) {
+24
View File
@@ -123,6 +123,12 @@ TEST_CASE("GetPidVid") {
TServer::TServer(const std::vector<std::string_view>& Arguments) {
beammp_info("BeamMP Server v" + Application::ServerVersionString());
Application::SetSubsystemStatus("Server", Application::Status::Starting);
std::mt19937_64 TimeSyncRandomDevice(std::random_device{}());
TimeSyncStart = std::chrono::steady_clock::now()
- std::chrono::duration_cast<std::chrono::steady_clock::duration>(
std::chrono::duration<double>(std::uniform_real_distribution<double>(0.0, 2592000.0)(TimeSyncRandomDevice))
);
Application::SetSubsystemStatus("Server", Application::Status::Good);
}
@@ -210,6 +216,24 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
return;
}
switch (Code) {
case 't':
if (!udp && Packet.size() == 9) {
auto Time = GetServerTimeMS();
std::vector<uint8_t> ServerTime(sizeof(uint64_t));
std::memcpy(ServerTime.data(), &Time, sizeof(uint64_t));
auto Data = Packet;
beammp_debugf("Sending server time {} to client '{}' ({}), client time: {}", Time, LockedClient->GetName(), LockedClient->GetID(), reinterpret_cast<uint64_t>(Data.data()));
Data.insert(Data.end(), ServerTime.begin(), ServerTime.end());
if (!Network.Respond(*LockedClient, Data, true)) {
Network.DisconnectClient(*LockedClient, "Failed to send time");
}
}
return;
case 'H': // initial connection
if (udp) {
beammp_debugf("Received 'H' packet over UDP from client '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());