From 0b589a74c9cfc805fe1d71f403a6c15c811a5cfd Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sun, 22 Sep 2024 20:31:25 +0200 Subject: [PATCH 1/2] refactor tcp receive to be less weird --- src/Network/VehicleEvent.cpp | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/Network/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp index 7201763..b31f097 100644 --- a/src/Network/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -82,32 +82,26 @@ std::string TCPRcv(SOCKET Sock) { UUl("Invalid Socket"); return ""; } - int32_t Header, BytesRcv = 0, Temp; + int32_t Header, Temp; std::vector Data(sizeof(Header)); - do { - Temp = recv(Sock, &Data[BytesRcv], 4 - BytesRcv, 0); - if (!CheckBytes(Temp)) { - UUl("Socket Closed Code 3"); - return ""; - } - BytesRcv += Temp; - } while (BytesRcv < 4); - memcpy(&Header, &Data[0], sizeof(Header)); + Temp = recv(Sock, Data.data(), sizeof(Header), MSG_WAITALL); + if (!CheckBytes(Temp)) { + UUl("Socket Closed Code 3"); + return ""; + } + memcpy(&Header, Data.data(), sizeof(Header)); - if (!CheckBytes(BytesRcv)) { + if (!CheckBytes(Temp)) { UUl("Socket Closed Code 4"); return ""; } - Data.resize(Header); - BytesRcv = 0; - do { - Temp = recv(Sock, &Data[BytesRcv], Header - BytesRcv, 0); - if (!CheckBytes(Temp)) { - UUl("Socket Closed Code 5"); - return ""; - } - BytesRcv += Temp; - } while (BytesRcv < Header); + + Data.resize(Header, 0); + Temp = recv(Sock, Data.data(), Header, MSG_WAITALL); + if (!CheckBytes(Temp)) { + UUl("Socket Closed Code 5"); + return ""; + } std::string Ret(Data.data(), Header); From cd17df5cc2be900c73ab2d63da4e01c515189649 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sun, 22 Sep 2024 21:37:52 +0200 Subject: [PATCH 2/2] add more debug statements, wait for threads before shutting down --- src/Network/GlobalHandler.cpp | 25 ++++++++++++++++++------- src/Network/VehicleData.cpp | 16 ++++++++++++---- src/Network/VehicleEvent.cpp | 10 ++++++++-- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/Network/GlobalHandler.cpp b/src/Network/GlobalHandler.cpp index dc4b580..272128d 100644 --- a/src/Network/GlobalHandler.cpp +++ b/src/Network/GlobalHandler.cpp @@ -6,6 +6,7 @@ /// Created by Anonymous275 on 7/25/2020 /// #include "Network/network.hpp" +#include #include #if defined(_WIN32) #include @@ -124,17 +125,17 @@ void NetReset() { UlStatus = "Ulstart"; MStatus = " "; if (UDPSock != (SOCKET)(-1)) { - debug("Terminating UDP Socket : " + std::to_string(TCPSock)); + debug("Terminating UDP Socket: " + std::to_string(TCPSock)); KillSocket(UDPSock); } UDPSock = -1; if (TCPSock != (SOCKET)(-1)) { - debug("Terminating TCP Socket : " + std::to_string(TCPSock)); + debug("Terminating TCP Socket: " + std::to_string(TCPSock)); KillSocket(TCPSock); } TCPSock = -1; if (GSocket != (SOCKET)(-1)) { - debug("Terminating GTCP Socket : " + std::to_string(GSocket)); + debug("Terminating GTCP Socket: " + std::to_string(GSocket)); KillSocket(GSocket); } GSocket = -1; @@ -234,6 +235,8 @@ void NetMain(const std::string& IP, int Port) { } void TCPGameServer(const std::string& IP, int Port) { GSocket = SetupListener(); + std::unique_ptr ClientThread {}; + std::unique_ptr NetMainThread {}; while (!TCPTerminate && GSocket != -1) { debug("MAIN LOOP OF GAME SERVER"); GConnected = false; @@ -245,8 +248,7 @@ void TCPGameServer(const std::string& IP, int Port) { break; } if (CServer) { - std::thread Client(TCPClientMain, IP, Port); - Client.detach(); + ClientThread = std::make_unique(TCPClientMain, IP, Port); } CSocket = accept(GSocket, nullptr, nullptr); if (CSocket == -1) { @@ -256,8 +258,7 @@ void TCPGameServer(const std::string& IP, int Port) { debug("(Proxy) Game Connected!"); GConnected = true; if (CServer) { - std::thread t1(NetMain, IP, Port); - t1.detach(); + NetMainThread = std::make_unique(NetMain, IP, Port); CServer = false; } int32_t Size, Temp, Rcv; @@ -300,6 +301,16 @@ void TCPGameServer(const std::string& IP, int Port) { TCPTerminate = true; GConnected = false; Terminate = true; + if (ClientThread) { + debug("Waiting for client thread"); + ClientThread->join(); + debug("Client thread done"); + } + if (NetMainThread) { + debug("Waiting for net main thread"); + NetMainThread->join(); + debug("Net main thread done"); + } if (CSocket != SOCKET_ERROR) KillSocket(CSocket); debug("END OF GAME SERVER"); diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp index 2331464..860724c 100644 --- a/src/Network/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -7,6 +7,7 @@ /// #include "Network/network.hpp" #include "Zlib/Compressor.h" +#include #if defined(_WIN32) #include @@ -50,9 +51,13 @@ void SendLarge(std::string Data) { void UDPParser(std::string_view Packet) { if (Packet.substr(0, 4) == "ABG:") { auto substr = Packet.substr(4); - auto res = DeComp(std::span(substr.data(), substr.size())); - std::string DeCompPacket = std::string(res.data(), res.size()); - ServerParser(DeCompPacket); + try { + auto res = DeComp(std::span(substr.data(), substr.size())); + std::string DeCompPacket = std::string(res.data(), res.size()); + ServerParser(DeCompPacket); + } catch (const std::runtime_error& err) { + error("Error in decompression of UDP, ignoring"); + } } else { ServerParser(Packet); } @@ -92,8 +97,11 @@ void UDPClientMain(const std::string& IP, int Port) { GameSend("P" + std::to_string(ClientID)); TCPSend("H", TCPSock); UDPSend("p"); - while (!Terminate) + debug("Starting UDP receive loop"); + while (!Terminate) { UDPRcv(); + } + debug("UDP receive loop done"); KillSocket(UDPSock); WSACleanup(); } diff --git a/src/Network/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp index b31f097..cc70ef6 100644 --- a/src/Network/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -107,8 +107,14 @@ std::string TCPRcv(SOCKET Sock) { if (Ret.substr(0, 4) == "ABG:") { auto substr = Ret.substr(4); - auto res = DeComp(std::span(substr.data(), substr.size())); - Ret = std::string(res.data(), res.size()); + try { + auto res = DeComp(std::span(substr.data(), substr.size())); + Ret = std::string(res.data(), res.size()); + } catch (const std::runtime_error& err) { + // this happens e.g. when we're out of memory, or when we get incomplete data + error("Decompression failed"); + return ""; + } } #ifdef DEBUG