From 105fd6d4c9108f8a0c9a4c582a2fd5f17c023eea Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 22 Jun 2024 22:47:31 +0200 Subject: [PATCH 1/4] rewrite compression and decompression to limit at 30 MB --- include/Common.h | 54 +++--------------------------------------------- src/Common.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 52 deletions(-) diff --git a/include/Common.h b/include/Common.h index 18fe84a..c35b325 100644 --- a/include/Common.h +++ b/include/Common.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -289,57 +290,8 @@ void RegisterThread(const std::string& str); void LogChatMessage(const std::string& name, int id, const std::string& msg); -#define Biggest 30000 - -template -inline T Comp(const T& Data) { - std::array C {}; - // obsolete - C.fill(0); - z_stream defstream; - defstream.zalloc = nullptr; - defstream.zfree = nullptr; - defstream.opaque = nullptr; - defstream.avail_in = uInt(Data.size()); - defstream.next_in = const_cast(reinterpret_cast(&Data[0])); - defstream.avail_out = Biggest; - defstream.next_out = reinterpret_cast(C.data()); - deflateInit(&defstream, Z_BEST_COMPRESSION); - deflate(&defstream, Z_SYNC_FLUSH); - deflate(&defstream, Z_FINISH); - deflateEnd(&defstream); - size_t TotalOut = defstream.total_out; - T Ret; - Ret.resize(TotalOut); - std::fill(Ret.begin(), Ret.end(), 0); - std::copy_n(C.begin(), TotalOut, Ret.begin()); - return Ret; -} - -template -inline T DeComp(const T& Compressed) { - std::array C {}; - // not needed - C.fill(0); - z_stream infstream; - infstream.zalloc = nullptr; - infstream.zfree = nullptr; - infstream.opaque = nullptr; - infstream.avail_in = Biggest; - infstream.next_in = const_cast(reinterpret_cast(&Compressed[0])); - infstream.avail_out = Biggest; - infstream.next_out = const_cast(reinterpret_cast(C.data())); - inflateInit(&infstream); - inflate(&infstream, Z_SYNC_FLUSH); - inflate(&infstream, Z_FINISH); - inflateEnd(&infstream); - size_t TotalOut = infstream.total_out; - T Ret; - Ret.resize(TotalOut); - std::fill(Ret.begin(), Ret.end(), 0); - std::copy_n(C.begin(), TotalOut, Ret.begin()); - return Ret; -} +std::vector Comp(std::span input); +std::vector DeComp(std::span input); std::string GetPlatformAgnosticErrorString(); #define S_DSN SU_RAW diff --git a/src/Common.cpp b/src/Common.cpp index e2b0719..52aea27 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -22,13 +22,14 @@ #include "TConsole.h" #include #include +#include #include +#include #include #include #include #include #include -#include #include "Compat.h" #include "CustomAssert.h" @@ -386,3 +387,51 @@ void SplitString(const std::string& str, const char delim, std::vector DeComp(std::span input) { + beammp_debugf("got {} bytes of input data", input.size()); + + std::vector output_buffer(std::min(input.size() * 5, 15 * 1024 * 1024)); + + uLongf output_size = output_buffer.size(); + + while (true) { + int res = uncompress( + reinterpret_cast(output_buffer.data()), + &output_size, + reinterpret_cast(input.data()), + static_cast(input.size())); + if (res == Z_BUF_ERROR) { + if (output_buffer.size() > 30 * 1024 * 1024) { + throw std::runtime_error("decompressed packet size of 30 MB exceeded"); + } + beammp_warn("zlib uncompress() failed, trying with 2x buffer size of " + std::to_string(output_buffer.size() * 2)); + output_buffer.resize(output_buffer.size() * 2); + output_size = output_buffer.size(); + } else if (res != Z_OK) { + beammp_error("zlib uncompress() failed: " + std::to_string(res)); + throw std::runtime_error("zlib uncompress() failed"); + } else if (res == Z_OK) { + break; + } + } + output_buffer.resize(output_size); + return output_buffer; +} + +std::vector Comp(std::span input) { + auto max_size = compressBound(input.size()); + std::vector output(max_size); + uLongf output_size = output.size(); + int res = compress( + reinterpret_cast(output.data()), + &output_size, + reinterpret_cast(input.data()), + static_cast(input.size())); + if (res != Z_OK) { + beammp_error("zlib compress() failed: " + std::to_string(res)); + throw std::runtime_error("zlib compress() failed"); + } + beammp_debug("zlib compressed " + std::to_string(input.size()) + " B to " + std::to_string(output_size) + " B"); + output.resize(output_size); + return output; +} From bfb0675efa8d697b3697b7806a9dd0fe2f7125e2 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 22 Jun 2024 23:51:01 +0200 Subject: [PATCH 2/4] send large packets over tcp --- src/TNetwork.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index e88ac53..be5c10b 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -882,7 +882,7 @@ bool TNetwork::SendLarge(TClient& c, std::vector Data, bool isSync) { bool TNetwork::Respond(TClient& c, const std::vector& MSG, bool Rel, bool isSync) { char C = MSG.at(0); - if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') { + if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E' || compressBound(MSG.size()) > 1024) { if (C == 'O' || C == 'T' || MSG.size() > 1000) { return SendLarge(c, MSG, isSync); } else { From 07a8d49046594686a19673cf51e9691007cc6e9c Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 22 Jun 2024 23:56:18 +0200 Subject: [PATCH 3/4] fix tcp send also --- src/TNetwork.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index be5c10b..eabb2fd 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -28,6 +28,7 @@ #include #include #include +#include typedef boost::asio::detail::socket_option::integer rcv_timeout_option; @@ -965,7 +966,7 @@ void TNetwork::SendToAll(TClient* c, const std::vector& Data, bool Self } if (Self || Client.get() != c) { if (Client->IsSynced() || Client->IsSyncing()) { - if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') { + if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E' || compressBound(Data.size()) > 1024) { if (C == 'O' || C == 'T' || Data.size() > 1000) { if (Data.size() > 400) { auto CompressedData = Data; From 28a9690a64a41c7ee4c22546b60b0ddec65e906b Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sun, 23 Jun 2024 21:58:32 +0200 Subject: [PATCH 4/4] validate Ot packets --- src/TServer.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/TServer.cpp b/src/TServer.cpp index db1541a..f0411bf 100644 --- a/src/TServer.cpp +++ b/src/TServer.cpp @@ -403,13 +403,21 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ } return; } - case 't': + case 't': { beammp_trace(std::string(("got 'Ot' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); + auto MaybePidVid = GetPidVid(Data.substr(0, Data.find(':', 1))); + if (MaybePidVid) { + std::tie(PID, VID) = MaybePidVid.value(); + } + if (PID != -1 && VID != -1 && PID == c.GetID()) { + Network.SendToAll(&c, StringToVector(Packet), false, true); + } + return; + } + case 'm': { Network.SendToAll(&c, StringToVector(Packet), false, true); return; - case 'm': - Network.SendToAll(&c, StringToVector(Packet), true, true); - return; + } default: beammp_trace(std::string(("possibly not implemented: '") + Packet + ("' (") + std::to_string(Packet.size()) + (")"))); return;