mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2025-07-01 23:46:59 +00:00
implement receiving new header format
This commit is contained in:
parent
88a9d4a1b1
commit
7c24020124
11
include/Helpers.h
Normal file
11
include/Helpers.h
Normal file
@ -0,0 +1,11 @@
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#pragma once
|
||||
|
||||
using ByteSpan = std::span<const char>;
|
||||
|
||||
std::string bytespan_to_string(ByteSpan span);
|
||||
|
||||
std::vector<char> strtovec(std::string_view str);
|
@ -7,12 +7,15 @@
|
||||
///
|
||||
|
||||
#pragma once
|
||||
#include "Helpers.h"
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
#ifdef __linux__
|
||||
#include "linuxfixes.h"
|
||||
#include <bits/types/siginfo_t.h>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <sys/ucontext.h>
|
||||
#endif
|
||||
|
||||
@ -39,16 +42,16 @@ extern std::string PrivateKey;
|
||||
extern std::string ListOfMods;
|
||||
int KillSocket(uint64_t Dead);
|
||||
void UUl(const std::string& R);
|
||||
void UDPSend(std::string Data);
|
||||
void UDPSend(const std::vector<char>& Data);
|
||||
bool CheckBytes(int32_t Bytes);
|
||||
void GameSend(std::string_view Data);
|
||||
void SendLarge(std::string Data);
|
||||
void SendLarge(const std::vector<char>& Data);
|
||||
std::string TCPRcv(uint64_t Sock);
|
||||
void SyncResources(uint64_t TCPSock);
|
||||
std::string GetAddr(const std::string& IP);
|
||||
void ServerParser(std::string_view Data);
|
||||
std::string Login(const std::string& fields);
|
||||
void TCPSend(const std::string& Data, uint64_t Sock);
|
||||
void TCPSend(const std::vector<char>& Data, uint64_t Sock);
|
||||
void TCPClientMain(const std::string& IP, int Port);
|
||||
void UDPClientMain(const std::string& IP, int Port);
|
||||
void TCPGameServer(const std::string& IP, int Port);
|
||||
|
11
include/NetworkHelpers.h
Normal file
11
include/NetworkHelpers.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__linux__)
|
||||
#include "linuxfixes.h"
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#include <vector>
|
||||
|
||||
void ReceiveFromGame(SOCKET socket, std::vector<char>& out_data);
|
9
src/Helpers.cpp
Normal file
9
src/Helpers.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "Helpers.h"
|
||||
|
||||
std::string bytespan_to_string(ByteSpan span) {
|
||||
return std::string(span.data(), span.size());
|
||||
}
|
||||
|
||||
std::vector<char> strtovec(std::string_view str) {
|
||||
return std::vector<char>(str.begin(), str.end());
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
///
|
||||
#include "Http.h"
|
||||
#include "Network/network.hpp"
|
||||
#include "NetworkHelpers.h"
|
||||
#include "Security/Init.h"
|
||||
#include <cstdlib>
|
||||
#include <regex>
|
||||
@ -72,37 +73,38 @@ bool IsAllowedLink(const std::string& Link) {
|
||||
return std::regex_search(Link, link_match, link_pattern) && link_match.position() == 0;
|
||||
}
|
||||
|
||||
void Parse(std::string Data, SOCKET CSocket) {
|
||||
char Code = Data.at(0), SubCode = 0;
|
||||
if (Data.length() > 1)
|
||||
SubCode = Data.at(1);
|
||||
void Parse(std::span<char> InData, SOCKET CSocket) {
|
||||
std::string OutData;
|
||||
char Code = InData[0], SubCode = 0;
|
||||
if (InData.size() > 1)
|
||||
SubCode = InData[1];
|
||||
switch (Code) {
|
||||
case 'A':
|
||||
Data = Data.substr(0, 1);
|
||||
OutData = "A";
|
||||
break;
|
||||
case 'B':
|
||||
NetReset();
|
||||
Terminate = true;
|
||||
TCPTerminate = true;
|
||||
Data = Code + HTTP::Get("https://backend.beammp.com/servers-info");
|
||||
OutData = Code + HTTP::Get("https://backend.beammp.com/servers-info");
|
||||
break;
|
||||
case 'C':
|
||||
ListOfMods.clear();
|
||||
StartSync(Data);
|
||||
StartSync(std::string(InData.data(), InData.size()));
|
||||
while (ListOfMods.empty() && !Terminate) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
if (ListOfMods == "-")
|
||||
Data = "L";
|
||||
OutData = "L";
|
||||
else
|
||||
Data = "L" + ListOfMods;
|
||||
OutData = "L" + ListOfMods;
|
||||
break;
|
||||
case 'O': // open default browser with URL
|
||||
if (IsAllowedLink(Data.substr(1))) {
|
||||
if (IsAllowedLink(bytespan_to_string(InData.subspan(1)))) {
|
||||
#if defined(__linux)
|
||||
if (char* browser = getenv("BROWSER"); browser != nullptr && !std::string_view(browser).empty()) {
|
||||
pid_t pid;
|
||||
auto arg = Data.substr(1);
|
||||
auto arg = bytespan_to_string(InData.subspan(1));
|
||||
char* argv[] = { browser, arg.data() };
|
||||
auto status = posix_spawn(&pid, browser, nullptr, nullptr, argv, environ);
|
||||
if (status == 0) {
|
||||
@ -114,27 +116,27 @@ void Parse(std::string Data, SOCKET CSocket) {
|
||||
error(std::string("posix_spawn: ") + strerror(status));
|
||||
}
|
||||
} else {
|
||||
error("Failed to open the following link in the browser because the $BROWSER environment variable is not set: " + Data.substr(1));
|
||||
error("Failed to open the following link in the browser because the $BROWSER environment variable is not set: " + bytespan_to_string(InData.subspan(1)));
|
||||
}
|
||||
#elif defined(WIN32)
|
||||
ShellExecuteA(nullptr, "open", Data.substr(1).c_str(), nullptr, nullptr, SW_SHOW); /// TODO: Look at when working on linux port
|
||||
ShellExecuteA(nullptr, "open", InData.subspan(1).data(), nullptr, nullptr, SW_SHOW); /// TODO: Look at when working on linux port
|
||||
#endif
|
||||
|
||||
info("Opening Link \"" + Data.substr(1) + "\"");
|
||||
info("Opening Link \"" + bytespan_to_string(InData.subspan(1)) + "\"");
|
||||
}
|
||||
Data.clear();
|
||||
OutData.clear();
|
||||
break;
|
||||
case 'P':
|
||||
Data = Code + std::to_string(ProxyPort);
|
||||
OutData = Code + std::to_string(ProxyPort);
|
||||
break;
|
||||
case 'U':
|
||||
if (SubCode == 'l')
|
||||
Data = UlStatus;
|
||||
OutData = UlStatus;
|
||||
if (SubCode == 'p') {
|
||||
if (ping > 800) {
|
||||
Data = "Up-2";
|
||||
OutData = "Up-2";
|
||||
} else
|
||||
Data = "Up" + std::to_string(ping);
|
||||
OutData = "Up" + std::to_string(ping);
|
||||
}
|
||||
if (!SubCode) {
|
||||
std::string Ping;
|
||||
@ -142,11 +144,11 @@ void Parse(std::string Data, SOCKET CSocket) {
|
||||
Ping = "-2";
|
||||
else
|
||||
Ping = std::to_string(ping);
|
||||
Data = std::string(UlStatus) + "\n" + "Up" + Ping;
|
||||
OutData = std::string(UlStatus) + "\n" + "Up" + Ping;
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
Data = MStatus;
|
||||
OutData = MStatus;
|
||||
break;
|
||||
case 'Q':
|
||||
if (SubCode == 'S') {
|
||||
@ -157,17 +159,19 @@ void Parse(std::string Data, SOCKET CSocket) {
|
||||
}
|
||||
if (SubCode == 'G')
|
||||
exit(2);
|
||||
Data.clear();
|
||||
OutData.clear();
|
||||
break;
|
||||
case 'R': // will send mod name
|
||||
if (ConfList->find(Data) == ConfList->end()) {
|
||||
ConfList->insert(Data);
|
||||
{
|
||||
auto str = bytespan_to_string(InData);
|
||||
if (ConfList->find(str) == ConfList->end()) {
|
||||
ConfList->insert(str);
|
||||
ModLoaded = true;
|
||||
}
|
||||
Data.clear();
|
||||
break;
|
||||
OutData.clear();
|
||||
} break;
|
||||
case 'Z':
|
||||
Data = "Z" + GetVer();
|
||||
OutData = "Z" + GetVer();
|
||||
break;
|
||||
case 'N':
|
||||
if (SubCode == 'c') {
|
||||
@ -180,20 +184,21 @@ void Parse(std::string Data, SOCKET CSocket) {
|
||||
if (!UserRole.empty()) {
|
||||
Auth["role"] = UserRole;
|
||||
}
|
||||
Data = "N" + Auth.dump();
|
||||
OutData = "N" + Auth.dump();
|
||||
} else {
|
||||
Data = "N" + Login(Data.substr(Data.find(':') + 1));
|
||||
auto indata_str = bytespan_to_string(InData);
|
||||
OutData = "N" + Login(indata_str.substr(indata_str.find(':') + 1));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Data.clear();
|
||||
OutData.clear();
|
||||
break;
|
||||
}
|
||||
if (!Data.empty() && CSocket != -1) {
|
||||
uint32_t DataSize = Data.size();
|
||||
std::vector<char> ToSend(sizeof(DataSize) + Data.size());
|
||||
if (!OutData.empty() && CSocket != -1) {
|
||||
uint32_t DataSize = OutData.size();
|
||||
std::vector<char> ToSend(sizeof(DataSize) + OutData.size());
|
||||
std::copy_n(reinterpret_cast<char*>(&DataSize), sizeof(DataSize), ToSend.begin());
|
||||
std::copy_n(Data.data(), Data.size(), ToSend.begin() + sizeof(DataSize));
|
||||
std::copy_n(OutData.data(), OutData.size(), ToSend.begin() + sizeof(DataSize));
|
||||
int res = send(CSocket, ToSend.data(), int(ToSend.size()), 0);
|
||||
if (res < 0) {
|
||||
debug("(Core) send failed with error: " + std::to_string(WSAGetLastError()));
|
||||
@ -201,46 +206,16 @@ void Parse(std::string Data, SOCKET CSocket) {
|
||||
}
|
||||
}
|
||||
void GameHandler(SOCKET Client) {
|
||||
|
||||
int32_t Size, Temp, Rcv;
|
||||
char Header[10] = { 0 };
|
||||
std::vector<char> data {};
|
||||
do {
|
||||
Rcv = 0;
|
||||
do {
|
||||
Temp = recv(Client, &Header[Rcv], 1, 0);
|
||||
if (Temp < 1)
|
||||
break;
|
||||
if (!isdigit(Header[Rcv]) && Header[Rcv] != '>') {
|
||||
error("(Core) Invalid lua communication");
|
||||
KillSocket(Client);
|
||||
return;
|
||||
}
|
||||
} while (Header[Rcv++] != '>');
|
||||
if (Temp < 1)
|
||||
break;
|
||||
if (std::from_chars(Header, &Header[Rcv], Size).ptr[0] != '>') {
|
||||
debug("(Core) Invalid lua Header -> " + std::string(Header, Rcv));
|
||||
try {
|
||||
ReceiveFromGame(Client, data);
|
||||
Parse(data, Client);
|
||||
} catch (const std::exception& e) {
|
||||
error(std::string("Error while receiving from game: ") + e.what());
|
||||
break;
|
||||
}
|
||||
std::string Ret(Size, 0);
|
||||
Rcv = 0;
|
||||
|
||||
do {
|
||||
Temp = recv(Client, &Ret[Rcv], Size - Rcv, 0);
|
||||
if (Temp < 1)
|
||||
break;
|
||||
Rcv += Temp;
|
||||
} while (Rcv < Size);
|
||||
if (Temp < 1)
|
||||
break;
|
||||
|
||||
Parse(Ret, Client);
|
||||
} while (Temp > 0);
|
||||
if (Temp == 0) {
|
||||
debug("(Core) Connection closing");
|
||||
} else {
|
||||
debug("(Core) recv failed with error: " + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
} while (true);
|
||||
NetReset();
|
||||
KillSocket(Client);
|
||||
}
|
||||
@ -286,6 +261,11 @@ void CoreMain() {
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
#if defined (__linux__)
|
||||
int opt = 1;
|
||||
if (setsockopt(LSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
|
||||
error("setsockopt(SO_REUSEADDR) failed");
|
||||
#endif
|
||||
iRes = bind(LSocket, res->ai_addr, int(res->ai_addrlen));
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
error("(Core) bind failed with error: " + std::to_string(WSAGetLastError()));
|
||||
|
@ -5,8 +5,11 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 7/25/2020
|
||||
///
|
||||
#include "Helpers.h"
|
||||
#include "Network/network.hpp"
|
||||
#include "NetworkHelpers.h"
|
||||
#include <algorithm>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
#include <zlib.h>
|
||||
#if defined(_WIN32)
|
||||
@ -89,15 +92,13 @@ void GameSend(std::string_view RawData) {
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
void ServerSend(std::string Data, bool Rel) {
|
||||
|
||||
void ServerSend(const std::vector<char>& Data, bool Rel) {
|
||||
if (Terminate || Data.empty())
|
||||
return;
|
||||
if (Data.find("Zp") != std::string::npos && Data.size() > 500) {
|
||||
abort();
|
||||
}
|
||||
char C = 0;
|
||||
bool Ack = false;
|
||||
int DLen = int(Data.length());
|
||||
int DLen = int(Data.size());
|
||||
if (DLen > 3)
|
||||
C = Data.at(0);
|
||||
if (C == 'O' || C == 'T')
|
||||
@ -113,14 +114,6 @@ void ServerSend(std::string Data, bool Rel) {
|
||||
TCPSend(Data, TCPSock);
|
||||
} else
|
||||
UDPSend(Data);
|
||||
|
||||
if (DLen > 1000) {
|
||||
debug("(Launcher->Server) Bytes sent: " + std::to_string(Data.length()) + " : "
|
||||
+ Data.substr(0, 10)
|
||||
+ Data.substr(Data.length() - 10));
|
||||
} else if (C == 'Z') {
|
||||
// debug("(Game->Launcher) : " + Data);
|
||||
}
|
||||
}
|
||||
|
||||
void NetReset() {
|
||||
@ -178,6 +171,11 @@ SOCKET SetupListener() {
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
#if defined (__linux__)
|
||||
int opt = 1;
|
||||
if (setsockopt(GSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
|
||||
error("setsockopt(SO_REUSEADDR) failed");
|
||||
#endif
|
||||
iRes = bind(GSocket, result->ai_addr, (int)result->ai_addrlen);
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
error("(Proxy) bind failed with error: " + std::to_string(WSAGetLastError()));
|
||||
@ -198,7 +196,7 @@ SOCKET SetupListener() {
|
||||
}
|
||||
void AutoPing() {
|
||||
while (!Terminate) {
|
||||
ServerSend("p", false);
|
||||
ServerSend(strtovec("p"), false);
|
||||
PingStart = std::chrono::high_resolution_clock::now();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
@ -266,42 +264,18 @@ void TCPGameServer(const std::string& IP, int Port) {
|
||||
t1.detach();
|
||||
CServer = false;
|
||||
}
|
||||
int32_t Size, Temp, Rcv;
|
||||
char Header[10] = { 0 };
|
||||
std::vector<char> data {};
|
||||
|
||||
// Read byte by byte until '>' is rcved then get the size and read based on it
|
||||
do {
|
||||
Rcv = 0;
|
||||
|
||||
do {
|
||||
Temp = recv(CSocket, &Header[Rcv], 1, 0);
|
||||
if (Temp < 1 || TCPTerminate)
|
||||
break;
|
||||
} while (Header[Rcv++] != '>');
|
||||
if (Temp < 1 || TCPTerminate)
|
||||
break;
|
||||
if (std::from_chars(Header, &Header[Rcv], Size).ptr[0] != '>') {
|
||||
debug("(Game) Invalid lua Header -> " + std::string(Header, Rcv));
|
||||
try {
|
||||
ReceiveFromGame(CSocket, data);
|
||||
ServerSend(data, false);
|
||||
} catch (const std::exception& e) {
|
||||
error(std::string("Error while receiving from game: ") + e.what());
|
||||
break;
|
||||
}
|
||||
std::string Ret(Size, 0);
|
||||
Rcv = 0;
|
||||
do {
|
||||
Temp = recv(CSocket, &Ret[Rcv], Size - Rcv, 0);
|
||||
if (Temp < 1)
|
||||
break;
|
||||
Rcv += Temp;
|
||||
} while (Rcv < Size && !TCPTerminate);
|
||||
if (Temp < 1 || TCPTerminate)
|
||||
break;
|
||||
|
||||
ServerSend(Ret, false);
|
||||
|
||||
} while (Temp > 0 && !TCPTerminate);
|
||||
if (Temp == 0)
|
||||
debug("(Proxy) Connection closing");
|
||||
else
|
||||
debug("(Proxy) recv failed error : " + std::to_string(WSAGetLastError()));
|
||||
} while (!TCPTerminate);
|
||||
}
|
||||
TCPTerminate = true;
|
||||
GConnected = false;
|
||||
|
@ -73,7 +73,7 @@ void Abord() {
|
||||
}
|
||||
|
||||
std::string Auth(SOCKET Sock) {
|
||||
TCPSend("VC" + GetVer(), Sock);
|
||||
TCPSend(strtovec("VC" + GetVer()), Sock);
|
||||
|
||||
auto Res = TCPRcv(Sock);
|
||||
|
||||
@ -82,7 +82,7 @@ std::string Auth(SOCKET Sock) {
|
||||
return "";
|
||||
}
|
||||
|
||||
TCPSend(PublicKey, Sock);
|
||||
TCPSend(strtovec(PublicKey), Sock);
|
||||
if (Terminate)
|
||||
return "";
|
||||
|
||||
@ -100,7 +100,7 @@ std::string Auth(SOCKET Sock) {
|
||||
UUl("Authentication failed!");
|
||||
return "";
|
||||
}
|
||||
TCPSend("SR", Sock);
|
||||
TCPSend(strtovec("SR"), Sock);
|
||||
if (Terminate)
|
||||
return "";
|
||||
|
||||
@ -114,7 +114,7 @@ std::string Auth(SOCKET Sock) {
|
||||
if (Res.empty() || Res == "-") {
|
||||
info("Didn't Receive any mods...");
|
||||
ListOfMods = "-";
|
||||
TCPSend("Done", Sock);
|
||||
TCPSend(strtovec("Done"), Sock);
|
||||
info("Done!");
|
||||
return "";
|
||||
}
|
||||
@ -320,7 +320,7 @@ void SyncResources(SOCKET Sock) {
|
||||
CheckForDir();
|
||||
std::string FName = a.substr(a.find_last_of('/'));
|
||||
do {
|
||||
TCPSend("f" + *FN, Sock);
|
||||
TCPSend(strtovec("f" + *FN), Sock);
|
||||
|
||||
std::string Data = TCPRcv(Sock);
|
||||
if (Data == "CO" || Terminate) {
|
||||
@ -362,7 +362,7 @@ void SyncResources(SOCKET Sock) {
|
||||
}
|
||||
KillSocket(DSock);
|
||||
if (!Terminate) {
|
||||
TCPSend("Done", Sock);
|
||||
TCPSend(strtovec("Done"), Sock);
|
||||
info("Done!");
|
||||
} else {
|
||||
UlStatus = "Ulstart";
|
||||
|
@ -26,12 +26,15 @@
|
||||
SOCKET UDPSock = -1;
|
||||
sockaddr_in* ToServer = nullptr;
|
||||
|
||||
void UDPSend(std::string Data) {
|
||||
void UDPSend(const std::vector<char>& RawData) {
|
||||
if (ClientID == -1 || UDPSock == -1)
|
||||
return;
|
||||
if (Data.length() > 400) {
|
||||
auto res = Comp(std::span<char>(Data.data(), Data.size()));
|
||||
std::string Data;
|
||||
if (Data.size() > 400) {
|
||||
auto res = Comp(RawData);
|
||||
Data = "ABG:" + std::string(res.data(), res.size());
|
||||
} else {
|
||||
Data = std::string(RawData.data(), RawData.size());
|
||||
}
|
||||
std::string Packet = char(ClientID + 1) + std::string(":") + Data;
|
||||
int sendOk = sendto(UDPSock, Packet.c_str(), int(Packet.size()), 0, (sockaddr*)ToServer, sizeof(*ToServer));
|
||||
@ -39,12 +42,14 @@ void UDPSend(std::string Data) {
|
||||
error("Error Code : " + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
|
||||
void SendLarge(std::string Data) {
|
||||
if (Data.length() > 400) {
|
||||
auto res = Comp(std::span<char>(Data.data(), Data.size()));
|
||||
Data = "ABG:" + std::string(res.data(), res.size());
|
||||
}
|
||||
void SendLarge(const std::vector<char>& Data) {
|
||||
if (Data.size() > 400) {
|
||||
auto res = Comp(Data);
|
||||
res.insert(res.begin(), {'A', 'B', 'G', ':'});
|
||||
TCPSend(res, TCPSock);
|
||||
} else {
|
||||
TCPSend(Data, TCPSock);
|
||||
}
|
||||
}
|
||||
|
||||
void UDPParser(std::string_view Packet) {
|
||||
@ -90,8 +95,8 @@ void UDPClientMain(const std::string& IP, int Port) {
|
||||
inet_pton(AF_INET, IP.c_str(), &ToServer->sin_addr);
|
||||
UDPSock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
GameSend("P" + std::to_string(ClientID));
|
||||
TCPSend("H", TCPSock);
|
||||
UDPSend("p");
|
||||
TCPSend(strtovec("H"), TCPSock);
|
||||
UDPSend(strtovec("p"));
|
||||
while (!Terminate)
|
||||
UDPRcv();
|
||||
KillSocket(UDPSock);
|
||||
|
@ -46,7 +46,7 @@ void UUl(const std::string& R) {
|
||||
UlStatus = "UlDisconnected: " + R;
|
||||
}
|
||||
|
||||
void TCPSend(const std::string& Data, uint64_t Sock) {
|
||||
void TCPSend(const std::vector<char>& Data, uint64_t Sock) {
|
||||
if (Sock == -1) {
|
||||
Terminate = true;
|
||||
UUl("Invalid Socket");
|
||||
@ -57,7 +57,7 @@ void TCPSend(const std::string& Data, uint64_t Sock) {
|
||||
std::string Send(4, 0);
|
||||
Size = int32_t(Data.size());
|
||||
memcpy(&Send[0], &Size, sizeof(Size));
|
||||
Send += Data;
|
||||
Send += std::string(Data.data(), Data.size());
|
||||
// Do not use Size before this point for anything but the header
|
||||
Sent = 0;
|
||||
Size += 4;
|
||||
@ -113,7 +113,7 @@ std::string TCPRcv(SOCKET Sock) {
|
||||
|
||||
if (Ret.substr(0, 4) == "ABG:") {
|
||||
auto substr = Ret.substr(4);
|
||||
auto res = DeComp(std::span<char>(substr.data(), substr.size()));
|
||||
auto res = DeComp(strtovec(substr));
|
||||
Ret = std::string(res.data(), res.size());
|
||||
}
|
||||
|
||||
|
35
src/NetworkHelpers.cpp
Normal file
35
src/NetworkHelpers.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "NetworkHelpers.h"
|
||||
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#if defined(__linux__)
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
static uint32_t RecvHeader(SOCKET socket) {
|
||||
std::array<uint8_t, sizeof(uint32_t)> header_buffer {};
|
||||
auto n = recv(socket, reinterpret_cast<char*>(header_buffer.data()), header_buffer.size(), MSG_WAITALL);
|
||||
if (n < 0) {
|
||||
throw std::runtime_error(std::string("recv() of header failed: ") + std::strerror(errno));
|
||||
} else if (n == 0) {
|
||||
throw std::runtime_error("Game disconnected");
|
||||
}
|
||||
return *reinterpret_cast<uint32_t*>(header_buffer.data());
|
||||
}
|
||||
|
||||
/// Throws!!!
|
||||
void ReceiveFromGame(SOCKET socket, std::vector<char>& out_data) {
|
||||
auto header = RecvHeader(socket);
|
||||
out_data.resize(header);
|
||||
auto n = recv(socket, reinterpret_cast<char*>(out_data.data()), out_data.size(), MSG_WAITALL);
|
||||
if (n < 0) {
|
||||
throw std::runtime_error(std::string("recv() of data failed: ") + std::strerror(errno));
|
||||
} else if (n == 0) {
|
||||
throw std::runtime_error("Game disconnected");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user