mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2026-04-10 09:46:16 +00:00
Compare commits
5 Commits
better-hea
...
95-ipv6-su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
169b14490c | ||
|
|
a60ff48c08 | ||
|
|
da3b49aa12 | ||
|
|
e505874af9 | ||
|
|
2f0a9fba99 |
@@ -12,6 +12,8 @@ set(CMAKE_CXX_STANDARD 20)
|
|||||||
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||||
|
|
||||||
|
add_compile_definitions(CPPHTTPLIB_OPENSSL_SUPPORT)
|
||||||
|
|
||||||
file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "src/*/*.hpp" "include/*.h" "include/*/*.h" "include/*/*/*.h" "include/*.hpp" "include/*/*.hpp" "include/*/*/*.hpp")
|
file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "src/*/*.hpp" "include/*.h" "include/*/*.h" "include/*/*/*.h" "include/*.hpp" "include/*/*.hpp" "include/*/*/*.hpp")
|
||||||
find_package(httplib CONFIG REQUIRED)
|
find_package(httplib CONFIG REQUIRED)
|
||||||
find_package(nlohmann_json CONFIG REQUIRED)
|
find_package(nlohmann_json CONFIG REQUIRED)
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
#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,15 +7,12 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Helpers.h"
|
|
||||||
#include <span>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include "linuxfixes.h"
|
#include "linuxfixes.h"
|
||||||
#include <bits/types/siginfo_t.h>
|
#include <bits/types/siginfo_t.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
|
||||||
#include <sys/ucontext.h>
|
#include <sys/ucontext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -42,16 +39,16 @@ extern std::string PrivateKey;
|
|||||||
extern std::string ListOfMods;
|
extern std::string ListOfMods;
|
||||||
int KillSocket(uint64_t Dead);
|
int KillSocket(uint64_t Dead);
|
||||||
void UUl(const std::string& R);
|
void UUl(const std::string& R);
|
||||||
void UDPSend(const std::vector<char>& Data);
|
void UDPSend(std::string Data);
|
||||||
bool CheckBytes(int32_t Bytes);
|
bool CheckBytes(int32_t Bytes);
|
||||||
void GameSend(std::string_view Data);
|
void GameSend(std::string_view Data);
|
||||||
void SendLarge(const std::vector<char>& Data);
|
void SendLarge(std::string Data);
|
||||||
std::string TCPRcv(uint64_t Sock);
|
std::string TCPRcv(uint64_t Sock);
|
||||||
void SyncResources(uint64_t TCPSock);
|
void SyncResources(uint64_t TCPSock);
|
||||||
std::string GetAddr(const std::string& IP);
|
std::string GetAddr(const std::string& IP);
|
||||||
void ServerParser(std::string_view Data);
|
void ServerParser(std::string_view Data);
|
||||||
std::string Login(const std::string& fields);
|
std::string Login(const std::string& fields);
|
||||||
void TCPSend(const std::vector<char>& Data, uint64_t Sock);
|
void TCPSend(const std::string& Data, uint64_t Sock);
|
||||||
void TCPClientMain(const std::string& IP, int Port);
|
void TCPClientMain(const std::string& IP, int Port);
|
||||||
void UDPClientMain(const std::string& IP, int Port);
|
void UDPClientMain(const std::string& IP, int Port);
|
||||||
void TCPGameServer(const std::string& IP, int Port);
|
void TCPGameServer(const std::string& IP, int Port);
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
#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);
|
|
||||||
@@ -19,12 +19,11 @@ std::vector<char> Comp(std::span<const char> input) {
|
|||||||
auto max_size = compressBound(input.size());
|
auto max_size = compressBound(input.size());
|
||||||
std::vector<char> output(max_size);
|
std::vector<char> output(max_size);
|
||||||
uLongf output_size = output.size();
|
uLongf output_size = output.size();
|
||||||
int res = compress2(
|
int res = compress(
|
||||||
reinterpret_cast<Bytef*>(output.data()),
|
reinterpret_cast<Bytef*>(output.data()),
|
||||||
&output_size,
|
&output_size,
|
||||||
reinterpret_cast<const Bytef*>(input.data()),
|
reinterpret_cast<const Bytef*>(input.data()),
|
||||||
static_cast<uLongf>(input.size()),
|
static_cast<uLongf>(input.size()));
|
||||||
3);
|
|
||||||
if (res != Z_OK) {
|
if (res != Z_OK) {
|
||||||
error("zlib compress() failed: " + std::to_string(res));
|
error("zlib compress() failed: " + std::to_string(res));
|
||||||
throw std::runtime_error("zlib compress() failed");
|
throw std::runtime_error("zlib compress() failed");
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
#include "vdf_parser.hpp"
|
#include "vdf_parser.hpp"
|
||||||
#include <cerrno>
|
|
||||||
#include <cstring>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -53,6 +51,7 @@ std::string GetGamePath() {
|
|||||||
std::string Ver = CheckVer(GetGameDir());
|
std::string Ver = CheckVer(GetGameDir());
|
||||||
Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1));
|
Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1));
|
||||||
Path += Ver + "\\";
|
Path += Ver + "\\";
|
||||||
|
info("Game user path: '" + Path + "'");
|
||||||
return Path;
|
return Path;
|
||||||
}
|
}
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
@@ -65,6 +64,7 @@ std::string GetGamePath() {
|
|||||||
std::string Ver = CheckVer(GetGameDir());
|
std::string Ver = CheckVer(GetGameDir());
|
||||||
Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1));
|
Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1));
|
||||||
Path += Ver + "/";
|
Path += Ver + "/";
|
||||||
|
info("Game user path: '" + Path + "'");
|
||||||
return Path;
|
return Path;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -92,27 +92,11 @@ void StartGame(std::string Dir) {
|
|||||||
}
|
}
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
void StartGame(std::string Dir) {
|
void StartGame(std::string Dir) {
|
||||||
|
int status;
|
||||||
std::string filename = (Dir + "/BinLinux/BeamNG.drive.x64");
|
std::string filename = (Dir + "/BinLinux/BeamNG.drive.x64");
|
||||||
char* argv[] = { filename.data(), NULL };
|
char* argv[] = { filename.data(), NULL };
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int result = posix_spawn(&pid, filename.c_str(), NULL, NULL, argv, environ);
|
||||||
posix_spawn_file_actions_t file_actions;
|
|
||||||
auto status = posix_spawn_file_actions_init(&file_actions);
|
|
||||||
// disable stdout
|
|
||||||
if (status != 0) {
|
|
||||||
error(std::string("posix_spawn_file_actions_init failed: ") + std::strerror(errno));
|
|
||||||
}
|
|
||||||
status = posix_spawn_file_actions_addclose(&file_actions, STDOUT_FILENO);
|
|
||||||
if (status != 0) {
|
|
||||||
error(std::string("posix_spawn_file_actions_addclose for STDOUT failed: ") + std::strerror(errno));
|
|
||||||
}
|
|
||||||
status = posix_spawn_file_actions_addclose(&file_actions, STDERR_FILENO);
|
|
||||||
if (status != 0) {
|
|
||||||
error(std::string("posix_spawn_file_actions_addclose for STDERR failed: ") + std::strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
// launch the game
|
|
||||||
int result = posix_spawn(&pid, filename.c_str(), &file_actions, NULL, argv, environ);
|
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
error("Failed to Launch the game! launcher closing soon");
|
error("Failed to Launch the game! launcher closing soon");
|
||||||
@@ -122,11 +106,6 @@ void StartGame(std::string Dir) {
|
|||||||
error("Game Closed! launcher closing soon");
|
error("Game Closed! launcher closing soon");
|
||||||
}
|
}
|
||||||
|
|
||||||
status = posix_spawn_file_actions_destroy(&file_actions);
|
|
||||||
if (status != 0) {
|
|
||||||
warn(std::string("posix_spawn_file_actions_destroy failed: ") + std::strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
#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());
|
|
||||||
}
|
|
||||||
@@ -50,35 +50,35 @@ void addToLog(const std::string& Line) {
|
|||||||
}
|
}
|
||||||
void info(const std::string& toPrint) {
|
void info(const std::string& toPrint) {
|
||||||
std::string Print = getDate() + "[INFO] " + toPrint + "\n";
|
std::string Print = getDate() + "[INFO] " + toPrint + "\n";
|
||||||
std::cout << Print << std::flush;
|
std::cout << Print;
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
void debug(const std::string& toPrint) {
|
void debug(const std::string& toPrint) {
|
||||||
if (!Dev)
|
if (!Dev)
|
||||||
return;
|
return;
|
||||||
std::string Print = getDate() + "[DEBUG] " + toPrint + "\n";
|
std::string Print = getDate() + "[DEBUG] " + toPrint + "\n";
|
||||||
std::cout << Print << std::flush;
|
std::cout << Print;
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
void warn(const std::string& toPrint) {
|
void warn(const std::string& toPrint) {
|
||||||
std::string Print = getDate() + "[WARN] " + toPrint + "\n";
|
std::string Print = getDate() + "[WARN] " + toPrint + "\n";
|
||||||
std::cout << Print << std::flush;
|
std::cout << Print;
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
void error(const std::string& toPrint) {
|
void error(const std::string& toPrint) {
|
||||||
std::string Print = getDate() + "[ERROR] " + toPrint + "\n";
|
std::string Print = getDate() + "[ERROR] " + toPrint + "\n";
|
||||||
std::cout << Print << std::flush;
|
std::cout << Print;
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
void fatal(const std::string& toPrint) {
|
void fatal(const std::string& toPrint) {
|
||||||
std::string Print = getDate() + "[FATAL] " + toPrint + "\n";
|
std::string Print = getDate() + "[FATAL] " + toPrint + "\n";
|
||||||
std::cout << Print << std::flush;
|
std::cout << Print;
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
_Exit(-1);
|
_Exit(-1);
|
||||||
}
|
}
|
||||||
void except(const std::string& toPrint) {
|
void except(const std::string& toPrint) {
|
||||||
std::string Print = getDate() + "[EXCEP] " + toPrint + "\n";
|
std::string Print = getDate() + "[EXCEP] " + toPrint + "\n";
|
||||||
std::cout << Print << std::flush;
|
std::cout << Print;
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
///
|
///
|
||||||
#include "Http.h"
|
#include "Http.h"
|
||||||
#include "Network/network.hpp"
|
#include "Network/network.hpp"
|
||||||
#include "NetworkHelpers.h"
|
|
||||||
#include "Security/Init.h"
|
#include "Security/Init.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@@ -40,6 +39,7 @@ bool Terminate = false;
|
|||||||
bool LoginAuth = false;
|
bool LoginAuth = false;
|
||||||
std::string Username = "";
|
std::string Username = "";
|
||||||
std::string UserRole = "";
|
std::string UserRole = "";
|
||||||
|
int UserID = -1;
|
||||||
std::string UlStatus;
|
std::string UlStatus;
|
||||||
std::string MStatus;
|
std::string MStatus;
|
||||||
bool ModLoaded;
|
bool ModLoaded;
|
||||||
@@ -68,62 +68,42 @@ void StartSync(const std::string& Data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsAllowedLink(const std::string& Link) {
|
bool IsAllowedLink(const std::string& Link) {
|
||||||
std::vector<std::string> allowed_links = {
|
std::regex link_pattern(R"(https:\/\/(?:\w+)?(?:\.)?(?:beammp\.com|discord\.gg))");
|
||||||
R"(patreon\.com\/beammp$)",
|
std::smatch link_match;
|
||||||
R"(discord\.gg\/beammp$)",
|
return std::regex_search(Link, link_match, link_pattern) && link_match.position() == 0;
|
||||||
R"(forum\.beammp\.com$)",
|
|
||||||
R"(beammp\.com$)",
|
|
||||||
R"(patreon\.com\/beammp\/$)",
|
|
||||||
R"(discord\.gg\/beammp\/$)",
|
|
||||||
R"(forum\.beammp\.com\/$)",
|
|
||||||
R"(beammp\.com\/$)",
|
|
||||||
R"(docs\.beammp\.com$)",
|
|
||||||
R"(wiki\.beammp\.com$)",
|
|
||||||
R"(docs\.beammp\.com\/$)",
|
|
||||||
R"(wiki\.beammp\.com\/$)",
|
|
||||||
R"(docs\.beammp\.com\/.*$)",
|
|
||||||
R"(wiki\.beammp\.com\/.*$)",
|
|
||||||
};
|
|
||||||
for (const auto& allowed_link : allowed_links) {
|
|
||||||
if (std::regex_match(Link, std::regex(std::string(R"(^http(s)?:\/\/)") + allowed_link))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parse(std::span<char> InData, SOCKET CSocket) {
|
void Parse(std::string Data, SOCKET CSocket) {
|
||||||
std::string OutData;
|
char Code = Data.at(0), SubCode = 0;
|
||||||
char Code = InData[0], SubCode = 0;
|
if (Data.length() > 1)
|
||||||
if (InData.size() > 1)
|
SubCode = Data.at(1);
|
||||||
SubCode = InData[1];
|
|
||||||
switch (Code) {
|
switch (Code) {
|
||||||
case 'A':
|
case 'A':
|
||||||
OutData = "A";
|
Data = Data.substr(0, 1);
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
NetReset();
|
NetReset();
|
||||||
Terminate = true;
|
Terminate = true;
|
||||||
TCPTerminate = true;
|
TCPTerminate = true;
|
||||||
OutData = Code + HTTP::Get("https://backend.beammp.com/servers-info");
|
Data = Code + HTTP::Get("https://backend.beammp.com/servers-info");
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
ListOfMods.clear();
|
ListOfMods.clear();
|
||||||
StartSync(std::string(InData.data(), InData.size()));
|
StartSync(Data);
|
||||||
while (ListOfMods.empty() && !Terminate) {
|
while (ListOfMods.empty() && !Terminate) {
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
}
|
}
|
||||||
if (ListOfMods == "-")
|
if (ListOfMods == "-")
|
||||||
OutData = "L";
|
Data = "L";
|
||||||
else
|
else
|
||||||
OutData = "L" + ListOfMods;
|
Data = "L" + ListOfMods;
|
||||||
break;
|
break;
|
||||||
case 'O': // open default browser with URL
|
case 'O': // open default browser with URL
|
||||||
if (IsAllowedLink(bytespan_to_string(InData.subspan(1)))) {
|
if (IsAllowedLink(Data.substr(1))) {
|
||||||
#if defined(__linux)
|
#if defined(__linux)
|
||||||
if (char* browser = getenv("BROWSER"); browser != nullptr && !std::string_view(browser).empty()) {
|
if (char* browser = getenv("BROWSER"); browser != nullptr && !std::string_view(browser).empty()) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
auto arg = bytespan_to_string(InData.subspan(1));
|
auto arg = Data.substr(1);
|
||||||
char* argv[] = { browser, arg.data() };
|
char* argv[] = { browser, arg.data() };
|
||||||
auto status = posix_spawn(&pid, browser, nullptr, nullptr, argv, environ);
|
auto status = posix_spawn(&pid, browser, nullptr, nullptr, argv, environ);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
@@ -135,27 +115,27 @@ void Parse(std::span<char> InData, SOCKET CSocket) {
|
|||||||
error(std::string("posix_spawn: ") + strerror(status));
|
error(std::string("posix_spawn: ") + strerror(status));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error("Failed to open the following link in the browser because the $BROWSER environment variable is not set: " + bytespan_to_string(InData.subspan(1)));
|
error("Failed to open the following link in the browser because the $BROWSER environment variable is not set: " + Data.substr(1));
|
||||||
}
|
}
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
ShellExecuteA(nullptr, "open", InData.subspan(1).data(), nullptr, nullptr, SW_SHOW); /// TODO: Look at when working on linux port
|
ShellExecuteA(nullptr, "open", Data.substr(1).c_str(), nullptr, nullptr, SW_SHOW); /// TODO: Look at when working on linux port
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
info("Opening Link \"" + bytespan_to_string(InData.subspan(1)) + "\"");
|
info("Opening Link \"" + Data.substr(1) + "\"");
|
||||||
}
|
}
|
||||||
OutData.clear();
|
Data.clear();
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
OutData = Code + std::to_string(ProxyPort);
|
Data = Code + std::to_string(ProxyPort);
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
if (SubCode == 'l')
|
if (SubCode == 'l')
|
||||||
OutData = UlStatus;
|
Data = UlStatus;
|
||||||
if (SubCode == 'p') {
|
if (SubCode == 'p') {
|
||||||
if (ping > 800) {
|
if (ping > 800) {
|
||||||
OutData = "Up-2";
|
Data = "Up-2";
|
||||||
} else
|
} else
|
||||||
OutData = "Up" + std::to_string(ping);
|
Data = "Up" + std::to_string(ping);
|
||||||
}
|
}
|
||||||
if (!SubCode) {
|
if (!SubCode) {
|
||||||
std::string Ping;
|
std::string Ping;
|
||||||
@@ -163,11 +143,11 @@ void Parse(std::span<char> InData, SOCKET CSocket) {
|
|||||||
Ping = "-2";
|
Ping = "-2";
|
||||||
else
|
else
|
||||||
Ping = std::to_string(ping);
|
Ping = std::to_string(ping);
|
||||||
OutData = std::string(UlStatus) + "\n" + "Up" + Ping;
|
Data = std::string(UlStatus) + "\n" + "Up" + Ping;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
OutData = MStatus;
|
Data = MStatus;
|
||||||
break;
|
break;
|
||||||
case 'Q':
|
case 'Q':
|
||||||
if (SubCode == 'S') {
|
if (SubCode == 'S') {
|
||||||
@@ -178,19 +158,17 @@ void Parse(std::span<char> InData, SOCKET CSocket) {
|
|||||||
}
|
}
|
||||||
if (SubCode == 'G')
|
if (SubCode == 'G')
|
||||||
exit(2);
|
exit(2);
|
||||||
OutData.clear();
|
Data.clear();
|
||||||
break;
|
break;
|
||||||
case 'R': // will send mod name
|
case 'R': // will send mod name
|
||||||
{
|
if (ConfList->find(Data) == ConfList->end()) {
|
||||||
auto str = bytespan_to_string(InData);
|
ConfList->insert(Data);
|
||||||
if (ConfList->find(str) == ConfList->end()) {
|
|
||||||
ConfList->insert(str);
|
|
||||||
ModLoaded = true;
|
ModLoaded = true;
|
||||||
}
|
}
|
||||||
OutData.clear();
|
Data.clear();
|
||||||
} break;
|
break;
|
||||||
case 'Z':
|
case 'Z':
|
||||||
OutData = "Z" + GetVer();
|
Data = "Z" + GetVer();
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
if (SubCode == 'c') {
|
if (SubCode == 'c') {
|
||||||
@@ -203,38 +181,66 @@ void Parse(std::span<char> InData, SOCKET CSocket) {
|
|||||||
if (!UserRole.empty()) {
|
if (!UserRole.empty()) {
|
||||||
Auth["role"] = UserRole;
|
Auth["role"] = UserRole;
|
||||||
}
|
}
|
||||||
OutData = "N" + Auth.dump();
|
if (UserID != -1) {
|
||||||
|
Auth["id"] = UserID;
|
||||||
|
}
|
||||||
|
Data = "N" + Auth.dump();
|
||||||
} else {
|
} else {
|
||||||
auto indata_str = bytespan_to_string(InData);
|
Data = "N" + Login(Data.substr(Data.find(':') + 1));
|
||||||
OutData = "N" + Login(indata_str.substr(indata_str.find(':') + 1));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
OutData.clear();
|
Data.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!OutData.empty() && CSocket != -1) {
|
if (!Data.empty() && CSocket != -1) {
|
||||||
uint32_t DataSize = OutData.size();
|
int res = send(CSocket, (Data + "\n").c_str(), int(Data.size()) + 1, 0);
|
||||||
std::vector<char> ToSend(sizeof(DataSize) + OutData.size());
|
|
||||||
std::copy_n(reinterpret_cast<char*>(&DataSize), sizeof(DataSize), ToSend.begin());
|
|
||||||
std::copy_n(OutData.data(), OutData.size(), ToSend.begin() + sizeof(DataSize));
|
|
||||||
int res = send(CSocket, ToSend.data(), int(ToSend.size()), 0);
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
debug("(Core) send failed with error: " + std::to_string(WSAGetLastError()));
|
debug("(Core) send failed with error: " + std::to_string(WSAGetLastError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GameHandler(SOCKET Client) {
|
void GameHandler(SOCKET Client) {
|
||||||
std::vector<char> data {};
|
|
||||||
|
int32_t Size, Temp, Rcv;
|
||||||
|
char Header[10] = { 0 };
|
||||||
do {
|
do {
|
||||||
try {
|
Rcv = 0;
|
||||||
ReceiveFromGame(Client, data);
|
do {
|
||||||
Parse(data, Client);
|
Temp = recv(Client, &Header[Rcv], 1, 0);
|
||||||
} catch (const std::exception& e) {
|
if (Temp < 1)
|
||||||
error(std::string("Error while receiving from game: ") + e.what());
|
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));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (true);
|
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()));
|
||||||
|
}
|
||||||
NetReset();
|
NetReset();
|
||||||
KillSocket(Client);
|
KillSocket(Client);
|
||||||
}
|
}
|
||||||
@@ -263,7 +269,7 @@ void CoreMain() {
|
|||||||
|
|
||||||
ZeroMemory(&hints, sizeof(hints));
|
ZeroMemory(&hints, sizeof(hints));
|
||||||
|
|
||||||
hints.ai_family = AF_INET;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
@@ -280,11 +286,6 @@ void CoreMain() {
|
|||||||
WSACleanup();
|
WSACleanup();
|
||||||
return;
|
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));
|
iRes = bind(LSocket, res->ai_addr, int(res->ai_addrlen));
|
||||||
if (iRes == SOCKET_ERROR) {
|
if (iRes == SOCKET_ERROR) {
|
||||||
error("(Core) bind failed with error: " + std::to_string(WSAGetLastError()));
|
error("(Core) bind failed with error: " + std::to_string(WSAGetLastError()));
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "IPRegex.h"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@@ -19,8 +20,9 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
std::string GetAddr(const std::string& IP) {
|
std::string GetAddr(const std::string& IP) {
|
||||||
if (IP.find_first_not_of("0123456789.") == -1)
|
if (!std::regex_match(IP, IP_REGEX)) {
|
||||||
return IP;
|
return IP;
|
||||||
|
}
|
||||||
hostent* host;
|
hostent* host;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
|
|||||||
@@ -5,12 +5,7 @@
|
|||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/25/2020
|
/// Created by Anonymous275 on 7/25/2020
|
||||||
///
|
///
|
||||||
#include "Helpers.h"
|
|
||||||
#include "Network/network.hpp"
|
#include "Network/network.hpp"
|
||||||
#include "NetworkHelpers.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include <span>
|
|
||||||
#include <vector>
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@@ -61,17 +56,13 @@ bool CheckBytes(uint32_t Bytes) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameSend(std::string_view RawData) {
|
void GameSend(std::string_view Data) {
|
||||||
static std::mutex Lock;
|
static std::mutex Lock;
|
||||||
std::scoped_lock Guard(Lock);
|
std::scoped_lock Guard(Lock);
|
||||||
if (TCPTerminate || !GConnected || CSocket == -1)
|
if (TCPTerminate || !GConnected || CSocket == -1)
|
||||||
return;
|
return;
|
||||||
int32_t Size, Temp, Sent;
|
int32_t Size, Temp, Sent;
|
||||||
uint32_t DataSize = RawData.size();
|
Size = int32_t(Data.size());
|
||||||
std::vector<char> Data(sizeof(DataSize) + RawData.size());
|
|
||||||
std::copy_n(reinterpret_cast<char*>(&DataSize), sizeof(DataSize), Data.begin());
|
|
||||||
std::copy_n(RawData.data(), RawData.size(), Data.begin() + sizeof(DataSize));
|
|
||||||
Size = Data.size();
|
|
||||||
Sent = 0;
|
Sent = 0;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (Size > 1000) {
|
if (Size > 1000) {
|
||||||
@@ -87,18 +78,20 @@ void GameSend(std::string_view RawData) {
|
|||||||
Sent += Temp;
|
Sent += Temp;
|
||||||
} while (Sent < Size);
|
} while (Sent < Size);
|
||||||
// send separately to avoid an allocation for += "\n"
|
// send separately to avoid an allocation for += "\n"
|
||||||
/*Temp = send(CSocket, "\n", 1, 0);
|
Temp = send(CSocket, "\n", 1, 0);
|
||||||
if (!CheckBytes(Temp)) {
|
if (!CheckBytes(Temp)) {
|
||||||
return;
|
return;
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
void ServerSend(std::string Data, bool Rel) {
|
||||||
void ServerSend(const std::vector<char>& Data, bool Rel) {
|
|
||||||
if (Terminate || Data.empty())
|
if (Terminate || Data.empty())
|
||||||
return;
|
return;
|
||||||
|
if (Data.find("Zp") != std::string::npos && Data.size() > 500) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
char C = 0;
|
char C = 0;
|
||||||
bool Ack = false;
|
bool Ack = false;
|
||||||
int DLen = int(Data.size());
|
int DLen = int(Data.length());
|
||||||
if (DLen > 3)
|
if (DLen > 3)
|
||||||
C = Data.at(0);
|
C = Data.at(0);
|
||||||
if (C == 'O' || C == 'T')
|
if (C == 'O' || C == 'T')
|
||||||
@@ -114,6 +107,14 @@ void ServerSend(const std::vector<char>& Data, bool Rel) {
|
|||||||
TCPSend(Data, TCPSock);
|
TCPSend(Data, TCPSock);
|
||||||
} else
|
} else
|
||||||
UDPSend(Data);
|
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() {
|
void NetReset() {
|
||||||
@@ -155,7 +156,7 @@ SOCKET SetupListener() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ZeroMemory(&hints, sizeof(hints));
|
ZeroMemory(&hints, sizeof(hints));
|
||||||
hints.ai_family = AF_INET;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
@@ -171,11 +172,6 @@ SOCKET SetupListener() {
|
|||||||
WSACleanup();
|
WSACleanup();
|
||||||
return -1;
|
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);
|
iRes = bind(GSocket, result->ai_addr, (int)result->ai_addrlen);
|
||||||
if (iRes == SOCKET_ERROR) {
|
if (iRes == SOCKET_ERROR) {
|
||||||
error("(Proxy) bind failed with error: " + std::to_string(WSAGetLastError()));
|
error("(Proxy) bind failed with error: " + std::to_string(WSAGetLastError()));
|
||||||
@@ -196,7 +192,7 @@ SOCKET SetupListener() {
|
|||||||
}
|
}
|
||||||
void AutoPing() {
|
void AutoPing() {
|
||||||
while (!Terminate) {
|
while (!Terminate) {
|
||||||
ServerSend(strtovec("p"), false);
|
ServerSend("p", false);
|
||||||
PingStart = std::chrono::high_resolution_clock::now();
|
PingStart = std::chrono::high_resolution_clock::now();
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
}
|
}
|
||||||
@@ -264,18 +260,42 @@ void TCPGameServer(const std::string& IP, int Port) {
|
|||||||
t1.detach();
|
t1.detach();
|
||||||
CServer = false;
|
CServer = false;
|
||||||
}
|
}
|
||||||
std::vector<char> data {};
|
int32_t Size, Temp, Rcv;
|
||||||
|
char Header[10] = { 0 };
|
||||||
|
|
||||||
// Read byte by byte until '>' is rcved then get the size and read based on it
|
// Read byte by byte until '>' is rcved then get the size and read based on it
|
||||||
do {
|
do {
|
||||||
try {
|
Rcv = 0;
|
||||||
ReceiveFromGame(CSocket, data);
|
|
||||||
ServerSend(data, false);
|
do {
|
||||||
} catch (const std::exception& e) {
|
Temp = recv(CSocket, &Header[Rcv], 1, 0);
|
||||||
error(std::string("Error while receiving from game: ") + e.what());
|
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));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (!TCPTerminate);
|
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()));
|
||||||
}
|
}
|
||||||
TCPTerminate = true;
|
TCPTerminate = true;
|
||||||
GConnected = false;
|
GConnected = false;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/18/2020
|
/// Created by Anonymous275 on 7/18/2020
|
||||||
///
|
///
|
||||||
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
|
||||||
|
|
||||||
#include "Http.h"
|
#include "Http.h"
|
||||||
#include <Logger.h>
|
#include <Logger.h>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ void Abord() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string Auth(SOCKET Sock) {
|
std::string Auth(SOCKET Sock) {
|
||||||
TCPSend(strtovec("VC" + GetVer()), Sock);
|
TCPSend("VC" + GetVer(), Sock);
|
||||||
|
|
||||||
auto Res = TCPRcv(Sock);
|
auto Res = TCPRcv(Sock);
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ std::string Auth(SOCKET Sock) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
TCPSend(strtovec(PublicKey), Sock);
|
TCPSend(PublicKey, Sock);
|
||||||
if (Terminate)
|
if (Terminate)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ std::string Auth(SOCKET Sock) {
|
|||||||
UUl("Authentication failed!");
|
UUl("Authentication failed!");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
TCPSend(strtovec("SR"), Sock);
|
TCPSend("SR", Sock);
|
||||||
if (Terminate)
|
if (Terminate)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ std::string Auth(SOCKET Sock) {
|
|||||||
if (Res.empty() || Res == "-") {
|
if (Res.empty() || Res == "-") {
|
||||||
info("Didn't Receive any mods...");
|
info("Didn't Receive any mods...");
|
||||||
ListOfMods = "-";
|
ListOfMods = "-";
|
||||||
TCPSend(strtovec("Done"), Sock);
|
TCPSend("Done", Sock);
|
||||||
info("Done!");
|
info("Done!");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -169,16 +169,16 @@ void MultiKill(SOCKET Sock, SOCKET Sock1) {
|
|||||||
Terminate = true;
|
Terminate = true;
|
||||||
}
|
}
|
||||||
SOCKET InitDSock() {
|
SOCKET InitDSock() {
|
||||||
SOCKET DSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
SOCKET DSock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||||
SOCKADDR_IN ServerAddr;
|
SOCKADDR_IN ServerAddr;
|
||||||
if (DSock < 1) {
|
if (DSock < 1) {
|
||||||
KillSocket(DSock);
|
KillSocket(DSock);
|
||||||
Terminate = true;
|
Terminate = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ServerAddr.sin_family = AF_INET;
|
ServerAddr.sin_family = AF_UNSPEC;
|
||||||
ServerAddr.sin_port = htons(LastPort);
|
ServerAddr.sin_port = htons(LastPort);
|
||||||
inet_pton(AF_INET, LastIP.c_str(), &ServerAddr.sin_addr);
|
inet_pton(AF_UNSPEC, LastIP.c_str(), &ServerAddr.sin_addr);
|
||||||
if (connect(DSock, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)) != 0) {
|
if (connect(DSock, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)) != 0) {
|
||||||
KillSocket(DSock);
|
KillSocket(DSock);
|
||||||
Terminate = true;
|
Terminate = true;
|
||||||
@@ -320,7 +320,7 @@ void SyncResources(SOCKET Sock) {
|
|||||||
CheckForDir();
|
CheckForDir();
|
||||||
std::string FName = a.substr(a.find_last_of('/'));
|
std::string FName = a.substr(a.find_last_of('/'));
|
||||||
do {
|
do {
|
||||||
TCPSend(strtovec("f" + *FN), Sock);
|
TCPSend("f" + *FN, Sock);
|
||||||
|
|
||||||
std::string Data = TCPRcv(Sock);
|
std::string Data = TCPRcv(Sock);
|
||||||
if (Data == "CO" || Terminate) {
|
if (Data == "CO" || Terminate) {
|
||||||
@@ -362,7 +362,7 @@ void SyncResources(SOCKET Sock) {
|
|||||||
}
|
}
|
||||||
KillSocket(DSock);
|
KillSocket(DSock);
|
||||||
if (!Terminate) {
|
if (!Terminate) {
|
||||||
TCPSend(strtovec("Done"), Sock);
|
TCPSend("Done", Sock);
|
||||||
info("Done!");
|
info("Done!");
|
||||||
} else {
|
} else {
|
||||||
UlStatus = "Ulstart";
|
UlStatus = "Ulstart";
|
||||||
|
|||||||
@@ -26,15 +26,12 @@
|
|||||||
SOCKET UDPSock = -1;
|
SOCKET UDPSock = -1;
|
||||||
sockaddr_in* ToServer = nullptr;
|
sockaddr_in* ToServer = nullptr;
|
||||||
|
|
||||||
void UDPSend(const std::vector<char>& RawData) {
|
void UDPSend(std::string Data) {
|
||||||
if (ClientID == -1 || UDPSock == -1)
|
if (ClientID == -1 || UDPSock == -1)
|
||||||
return;
|
return;
|
||||||
std::string Data;
|
if (Data.length() > 400) {
|
||||||
if (Data.size() > 400) {
|
auto res = Comp(std::span<char>(Data.data(), Data.size()));
|
||||||
auto res = Comp(RawData);
|
|
||||||
Data = "ABG:" + std::string(res.data(), res.size());
|
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;
|
std::string Packet = char(ClientID + 1) + std::string(":") + Data;
|
||||||
int sendOk = sendto(UDPSock, Packet.c_str(), int(Packet.size()), 0, (sockaddr*)ToServer, sizeof(*ToServer));
|
int sendOk = sendto(UDPSock, Packet.c_str(), int(Packet.size()), 0, (sockaddr*)ToServer, sizeof(*ToServer));
|
||||||
@@ -42,14 +39,12 @@ void UDPSend(const std::vector<char>& RawData) {
|
|||||||
error("Error Code : " + std::to_string(WSAGetLastError()));
|
error("Error Code : " + std::to_string(WSAGetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendLarge(const std::vector<char>& Data) {
|
void SendLarge(std::string Data) {
|
||||||
if (Data.size() > 400) {
|
if (Data.length() > 400) {
|
||||||
auto res = Comp(Data);
|
auto res = Comp(std::span<char>(Data.data(), Data.size()));
|
||||||
res.insert(res.begin(), {'A', 'B', 'G', ':'});
|
Data = "ABG:" + std::string(res.data(), res.size());
|
||||||
TCPSend(res, TCPSock);
|
|
||||||
} else {
|
|
||||||
TCPSend(Data, TCPSock);
|
|
||||||
}
|
}
|
||||||
|
TCPSend(Data, TCPSock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPParser(std::string_view Packet) {
|
void UDPParser(std::string_view Packet) {
|
||||||
@@ -90,13 +85,13 @@ void UDPClientMain(const std::string& IP, int Port) {
|
|||||||
|
|
||||||
delete ToServer;
|
delete ToServer;
|
||||||
ToServer = new sockaddr_in;
|
ToServer = new sockaddr_in;
|
||||||
ToServer->sin_family = AF_INET;
|
ToServer->sin_family = AF_UNSPEC;
|
||||||
ToServer->sin_port = htons(Port);
|
ToServer->sin_port = htons(Port);
|
||||||
inet_pton(AF_INET, IP.c_str(), &ToServer->sin_addr);
|
inet_pton(AF_UNSPEC, IP.c_str(), &ToServer->sin_addr);
|
||||||
UDPSock = socket(AF_INET, SOCK_DGRAM, 0);
|
UDPSock = socket(AF_UNSPEC, SOCK_DGRAM, 0);
|
||||||
GameSend("P" + std::to_string(ClientID));
|
GameSend("P" + std::to_string(ClientID));
|
||||||
TCPSend(strtovec("H"), TCPSock);
|
TCPSend("H", TCPSock);
|
||||||
UDPSend(strtovec("p"));
|
UDPSend("p");
|
||||||
while (!Terminate)
|
while (!Terminate)
|
||||||
UDPRcv();
|
UDPRcv();
|
||||||
KillSocket(UDPSock);
|
KillSocket(UDPSock);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ void UUl(const std::string& R) {
|
|||||||
UlStatus = "UlDisconnected: " + R;
|
UlStatus = "UlDisconnected: " + R;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPSend(const std::vector<char>& Data, uint64_t Sock) {
|
void TCPSend(const std::string& Data, uint64_t Sock) {
|
||||||
if (Sock == -1) {
|
if (Sock == -1) {
|
||||||
Terminate = true;
|
Terminate = true;
|
||||||
UUl("Invalid Socket");
|
UUl("Invalid Socket");
|
||||||
@@ -57,7 +57,7 @@ void TCPSend(const std::vector<char>& Data, uint64_t Sock) {
|
|||||||
std::string Send(4, 0);
|
std::string Send(4, 0);
|
||||||
Size = int32_t(Data.size());
|
Size = int32_t(Data.size());
|
||||||
memcpy(&Send[0], &Size, sizeof(Size));
|
memcpy(&Send[0], &Size, sizeof(Size));
|
||||||
Send += std::string(Data.data(), Data.size());
|
Send += Data;
|
||||||
// Do not use Size before this point for anything but the header
|
// Do not use Size before this point for anything but the header
|
||||||
Sent = 0;
|
Sent = 0;
|
||||||
Size += 4;
|
Size += 4;
|
||||||
@@ -113,7 +113,7 @@ std::string TCPRcv(SOCKET Sock) {
|
|||||||
|
|
||||||
if (Ret.substr(0, 4) == "ABG:") {
|
if (Ret.substr(0, 4) == "ABG:") {
|
||||||
auto substr = Ret.substr(4);
|
auto substr = Ret.substr(4);
|
||||||
auto res = DeComp(strtovec(substr));
|
auto res = DeComp(std::span<char>(substr.data(), substr.size()));
|
||||||
Ret = std::string(res.data(), res.size());
|
Ret = std::string(res.data(), res.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ void TCPClientMain(const std::string& IP, int Port) {
|
|||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
WSAStartup(514, &wsaData); // 2.2
|
WSAStartup(514, &wsaData); // 2.2
|
||||||
#endif
|
#endif
|
||||||
TCPSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
TCPSock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
|
||||||
if (TCPSock == -1) {
|
if (TCPSock == -1) {
|
||||||
printf("Client: socket failed! Error code: %d\n", WSAGetLastError());
|
printf("Client: socket failed! Error code: %d\n", WSAGetLastError());
|
||||||
@@ -142,9 +142,9 @@ void TCPClientMain(const std::string& IP, int Port) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerAddr.sin_family = AF_INET;
|
ServerAddr.sin_family = AF_UNSPEC;
|
||||||
ServerAddr.sin_port = htons(Port);
|
ServerAddr.sin_port = htons(Port);
|
||||||
inet_pton(AF_INET, IP.c_str(), &ServerAddr.sin_addr);
|
inet_pton(AF_UNSPEC, IP.c_str(), &ServerAddr.sin_addr);
|
||||||
RetCode = connect(TCPSock, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr));
|
RetCode = connect(TCPSock, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr));
|
||||||
if (RetCode != 0) {
|
if (RetCode != 0) {
|
||||||
UlStatus = "UlConnection Failed!";
|
UlStatus = "UlConnection Failed!";
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
#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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,6 +18,7 @@ std::string PrivateKey;
|
|||||||
extern bool LoginAuth;
|
extern bool LoginAuth;
|
||||||
extern std::string Username;
|
extern std::string Username;
|
||||||
extern std::string UserRole;
|
extern std::string UserRole;
|
||||||
|
extern int UserID;
|
||||||
|
|
||||||
void UpdateKey(const char* newKey) {
|
void UpdateKey(const char* newKey) {
|
||||||
if (newKey && std::isalnum(newKey[0])) {
|
if (newKey && std::isalnum(newKey[0])) {
|
||||||
@@ -48,6 +49,7 @@ std::string Login(const std::string& fields) {
|
|||||||
if (fields == "LO") {
|
if (fields == "LO") {
|
||||||
Username = "";
|
Username = "";
|
||||||
UserRole = "";
|
UserRole = "";
|
||||||
|
UserID = -1;
|
||||||
LoginAuth = false;
|
LoginAuth = false;
|
||||||
UpdateKey(nullptr);
|
UpdateKey(nullptr);
|
||||||
return "";
|
return "";
|
||||||
@@ -74,6 +76,9 @@ std::string Login(const std::string& fields) {
|
|||||||
if (d.contains("role")) {
|
if (d.contains("role")) {
|
||||||
UserRole = d["role"].get<std::string>();
|
UserRole = d["role"].get<std::string>();
|
||||||
}
|
}
|
||||||
|
if (d.contains("id")) {
|
||||||
|
UserID = d["id"].get<int>();
|
||||||
|
}
|
||||||
if (d.contains("private_key")) {
|
if (d.contains("private_key")) {
|
||||||
UpdateKey(d["private_key"].get<std::string>().c_str());
|
UpdateKey(d["private_key"].get<std::string>().c_str());
|
||||||
}
|
}
|
||||||
@@ -129,6 +134,9 @@ void CheckLocalKey() {
|
|||||||
if (d.contains("role")) {
|
if (d.contains("role")) {
|
||||||
UserRole = d["role"].get<std::string>();
|
UserRole = d["role"].get<std::string>();
|
||||||
}
|
}
|
||||||
|
if (d.contains("id")) {
|
||||||
|
UserID = d["id"].get<int>();
|
||||||
|
}
|
||||||
// info(Role);
|
// info(Role);
|
||||||
} else {
|
} else {
|
||||||
info("Auto-Authentication unsuccessful please re-login!");
|
info("Auto-Authentication unsuccessful please re-login!");
|
||||||
|
|||||||
@@ -81,10 +81,10 @@ std::string GetEN() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GetVer() {
|
std::string GetVer() {
|
||||||
return "2.1";
|
return "2.0";
|
||||||
}
|
}
|
||||||
std::string GetPatch() {
|
std::string GetPatch() {
|
||||||
return ".0";
|
return ".99";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetEP(char* P) {
|
std::string GetEP(char* P) {
|
||||||
@@ -172,7 +172,7 @@ void CheckForUpdates(int argc, char* args[], const std::string& CV) {
|
|||||||
system("clear");
|
system("clear");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (FileHash != LatestHash && IsOutdated(Version(VersionStrToInts(GetVer() + GetPatch())), Version(VersionStrToInts(LatestVersion)))) {
|
if (FileHash != LatestHash && IsOutdated(Version(VersionStrToInts(GetVer() + GetPatch())), Version(VersionStrToInts(LatestVersion))) && !Dev) {
|
||||||
info("Launcher update found!");
|
info("Launcher update found!");
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
error("Auto update is NOT implemented for the Linux version. Please update manually ASAP as updates contain security patches.");
|
error("Auto update is NOT implemented for the Linux version. Please update manually ASAP as updates contain security patches.");
|
||||||
@@ -204,13 +204,6 @@ void CustomPort(int argc, char* argv[]) {
|
|||||||
if (argc > 2)
|
if (argc > 2)
|
||||||
Dev = true;
|
Dev = true;
|
||||||
}
|
}
|
||||||
for (int i = 1; i < argc; ++i) {
|
|
||||||
if (std::string_view(argv[i]) == "--dev") {
|
|
||||||
Dev = true;
|
|
||||||
} else if (std::string_view(argv[i]) == "--no-dev") {
|
|
||||||
Dev = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -252,15 +245,7 @@ void InitLauncher(int argc, char* argv[]) {
|
|||||||
CheckLocalKey();
|
CheckLocalKey();
|
||||||
ConfigInit();
|
ConfigInit();
|
||||||
CustomPort(argc, argv);
|
CustomPort(argc, argv);
|
||||||
bool update = true;
|
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
|
||||||
for (int i = 1; i < argc; ++i) {
|
|
||||||
if (std::string_view(argv[i]) == "--no-update") {
|
|
||||||
update = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (update) {
|
|
||||||
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
void InitLauncher(int argc, char* argv[]) {
|
void InitLauncher(int argc, char* argv[]) {
|
||||||
@@ -270,15 +255,7 @@ void InitLauncher(int argc, char* argv[]) {
|
|||||||
CheckLocalKey();
|
CheckLocalKey();
|
||||||
ConfigInit();
|
ConfigInit();
|
||||||
CustomPort(argc, argv);
|
CustomPort(argc, argv);
|
||||||
bool update = true;
|
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
|
||||||
for (int i = 1; i < argc; ++i) {
|
|
||||||
if (std::string_view(argv[i]) == "--no-update") {
|
|
||||||
update = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (update) {
|
|
||||||
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -341,8 +318,6 @@ void PreGame(const std::string& GamePath) {
|
|||||||
|
|
||||||
CheckMP(GetGamePath() + "mods/multiplayer");
|
CheckMP(GetGamePath() + "mods/multiplayer");
|
||||||
|
|
||||||
info("Game user path: '" + GetGamePath() + "'");
|
|
||||||
|
|
||||||
if (!Dev) {
|
if (!Dev) {
|
||||||
std::string LatestHash = HTTP::Get("https://backend.beammp.com/sha/mod?branch=" + Branch + "&pk=" + PublicKey);
|
std::string LatestHash = HTTP::Get("https://backend.beammp.com/sha/mod?branch=" + Branch + "&pk=" + PublicKey);
|
||||||
transform(LatestHash.begin(), LatestHash.end(), LatestHash.begin(), ::tolower);
|
transform(LatestHash.begin(), LatestHash.end(), LatestHash.begin(), ::tolower);
|
||||||
|
|||||||
Reference in New Issue
Block a user