mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2026-04-09 09:16:09 +00:00
simple setup
This commit is contained in:
@@ -1,254 +0,0 @@
|
||||
// Copyright (c) 2019-present Anonymous275.
|
||||
// BeamMP Launcher code is not in the public domain and is not free software.
|
||||
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||
///
|
||||
/// Created by Anonymous275 on 7/20/2020
|
||||
///
|
||||
#include "Network/network.h"
|
||||
#include "Security/Init.h"
|
||||
|
||||
#include "Http.h"
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "Startup.h"
|
||||
#include "Logger.h"
|
||||
#include <charconv>
|
||||
#include <thread>
|
||||
#include <set>
|
||||
|
||||
extern int TraceBack;
|
||||
std::set<std::string>* ConfList = nullptr;
|
||||
bool TCPTerminate = false;
|
||||
int DEFAULT_PORT = 4444;
|
||||
bool Terminate = false;
|
||||
bool LoginAuth = false;
|
||||
std::string UlStatus;
|
||||
std::string MStatus;
|
||||
bool ModLoaded;
|
||||
int ping = -1;
|
||||
|
||||
void StartSync(const std::string &Data){
|
||||
std::string IP = GetAddr(Data.substr(1,Data.find(':')-1));
|
||||
if(IP.find('.') == -1){
|
||||
if(IP == "DNS")UlStatus ="UlConnection Failed! (DNS Lookup Failed)";
|
||||
else UlStatus = "UlConnection Failed! (WSA failed to start)";
|
||||
ListOfMods = "-";
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
CheckLocalKey();
|
||||
UlStatus = "UlLoading...";
|
||||
TCPTerminate = false;
|
||||
Terminate = false;
|
||||
ConfList->clear();
|
||||
ping = -1;
|
||||
std::thread GS(TCPGameServer,IP,std::stoi(Data.substr(Data.find(':')+1)));
|
||||
GS.detach();
|
||||
info("Connecting to server");
|
||||
}
|
||||
void Parse(std::string Data,SOCKET CSocket){
|
||||
char Code = Data.at(0), SubCode = 0;
|
||||
if(Data.length() > 1)SubCode = Data.at(1);
|
||||
switch (Code){
|
||||
case 'A':
|
||||
Data = Data.substr(0,1);
|
||||
break;
|
||||
case 'B':
|
||||
NetReset();
|
||||
Terminate = true;
|
||||
TCPTerminate = true;
|
||||
Data = Code + HTTP::Post("https://backend.beammp.com/servers","");
|
||||
break;
|
||||
case 'C':
|
||||
ListOfMods.clear();
|
||||
StartSync(Data);
|
||||
while(ListOfMods.empty() && !Terminate){
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
if(ListOfMods == "-")Data = "L";
|
||||
else Data = "L"+ListOfMods;
|
||||
break;
|
||||
case 'U':
|
||||
if(SubCode == 'l')Data = UlStatus;
|
||||
if(SubCode == 'p'){
|
||||
if(ping > 800){
|
||||
Data = "Up-2";
|
||||
}else Data = "Up" + std::to_string(ping);
|
||||
}
|
||||
if(!SubCode){
|
||||
std::string Ping;
|
||||
if(ping > 800)Ping = "-2";
|
||||
else Ping = std::to_string(ping);
|
||||
Data = std::string(UlStatus) + "\n" + "Up" + Ping;
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
Data = MStatus;
|
||||
break;
|
||||
case 'Q':
|
||||
if(SubCode == 'S'){
|
||||
NetReset();
|
||||
Terminate = true;
|
||||
TCPTerminate = true;
|
||||
ping = -1;
|
||||
}
|
||||
if(SubCode == 'G')exit(2);
|
||||
Data.clear();
|
||||
break;
|
||||
case 'R': //will send mod name
|
||||
if(ConfList->find(Data) == ConfList->end()){
|
||||
ConfList->insert(Data);
|
||||
ModLoaded = true;
|
||||
}
|
||||
Data.clear();
|
||||
break;
|
||||
case 'Z':
|
||||
Data = "Z" + GetVer();
|
||||
break;
|
||||
case 'N':
|
||||
if (SubCode == 'c'){
|
||||
Data = "N{\"Auth\":"+std::to_string(LoginAuth)+"}";
|
||||
}else{
|
||||
Data = "N" + Login(Data.substr(Data.find(':') + 1));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Data.clear();
|
||||
break;
|
||||
}
|
||||
if(!Data.empty() && CSocket != -1){
|
||||
int res = send(CSocket, (Data+"\n").c_str(), int(Data.size())+1, 0);
|
||||
if(res < 0){
|
||||
debug("(Core) send failed with error: " + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
}
|
||||
}
|
||||
void GameHandler(SOCKET Client){
|
||||
|
||||
int32_t Size,Temp,Rcv;
|
||||
char Header[10] = {0};
|
||||
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));
|
||||
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;
|
||||
|
||||
std::thread Respond(Parse, Ret, Client);
|
||||
Respond.detach();
|
||||
}while(Temp > 0);
|
||||
if (Temp == 0) {
|
||||
debug("(Core) Connection closing");
|
||||
} else {
|
||||
debug("(Core) recv failed with error: " + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
NetReset();
|
||||
KillSocket(Client);
|
||||
}
|
||||
void localRes(){
|
||||
MStatus = " ";
|
||||
UlStatus = "Ulstart";
|
||||
if(ConfList != nullptr){
|
||||
ConfList->clear();
|
||||
delete ConfList;
|
||||
ConfList = nullptr;
|
||||
}
|
||||
ConfList = new std::set<std::string>;
|
||||
}
|
||||
void CoreMain() {
|
||||
debug("Core Network on start!");
|
||||
WSADATA wsaData;
|
||||
SOCKET LSocket,CSocket;
|
||||
struct addrinfo *res = nullptr;
|
||||
struct addrinfo hints{};
|
||||
int iRes = WSAStartup(514, &wsaData); //2.2
|
||||
if (iRes)debug("WSAStartup failed with error: " + std::to_string(iRes));
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT).c_str(), &hints, &res);
|
||||
if (iRes){
|
||||
debug("(Core) addr info failed with error: " + std::to_string(iRes));
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
LSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (LSocket == -1){
|
||||
debug("(Core) socket failed with error: " + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(res);
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
iRes = bind(LSocket, res->ai_addr, int(res->ai_addrlen));
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
error("(Core) bind failed with error: " + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(res);
|
||||
KillSocket(LSocket);
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
iRes = listen(LSocket, SOMAXCONN);
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
debug("(Core) listen failed with error: " + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(res);
|
||||
KillSocket(LSocket);
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
do{
|
||||
CSocket = accept(LSocket, nullptr, nullptr);
|
||||
if (CSocket == -1) {
|
||||
error("(Core) accept failed with error: " + std::to_string(WSAGetLastError()));
|
||||
continue;
|
||||
}
|
||||
localRes();
|
||||
info("Game Connected!");
|
||||
GameHandler(CSocket);
|
||||
warn("Game Reconnecting...");
|
||||
}while(CSocket);
|
||||
KillSocket(LSocket);
|
||||
WSACleanup();
|
||||
}
|
||||
int Handle(EXCEPTION_POINTERS *ep){
|
||||
char* hex = new char[100];
|
||||
sprintf_s(hex,100, "%lX", ep->ExceptionRecord->ExceptionCode);
|
||||
except("(Core) Code : " + std::string(hex));
|
||||
delete [] hex;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
[[noreturn]] void CoreNetwork(){
|
||||
while(true) {
|
||||
#ifndef __MINGW32__
|
||||
__try{
|
||||
#endif
|
||||
CoreMain();
|
||||
#ifndef __MINGW32__
|
||||
}__except(Handle(GetExceptionInformation())){}
|
||||
#endif
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright (c) 2019-present Anonymous275.
|
||||
// BeamMP Launcher code is not in the public domain and is not free software.
|
||||
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||
///
|
||||
/// Created by Anonymous275 on 9/25/2020
|
||||
///
|
||||
|
||||
#include <string>
|
||||
#include <winsock2.h>
|
||||
#include "Logger.h"
|
||||
|
||||
std::string GetAddr(const std::string&IP){
|
||||
if(IP.find_first_not_of("0123456789.") == -1)return IP;
|
||||
WSADATA wsaData;
|
||||
hostent *host;
|
||||
if(WSAStartup(514, &wsaData) != 0){
|
||||
error("WSA Startup Failed!");
|
||||
WSACleanup();
|
||||
return "";
|
||||
}
|
||||
host = gethostbyname(IP.c_str());
|
||||
if(!host){
|
||||
error("DNS lookup failed! on " + IP);
|
||||
WSACleanup();
|
||||
return "DNS";
|
||||
}
|
||||
std::string Ret = inet_ntoa(*((struct in_addr *)host->h_addr));
|
||||
WSACleanup();
|
||||
return Ret;
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
// Copyright (c) 2019-present Anonymous275.
|
||||
// BeamMP Launcher code is not in the public domain and is not free software.
|
||||
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||
///
|
||||
/// Created by Anonymous275 on 7/25/2020
|
||||
///
|
||||
#include "Network/network.h"
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "Logger.h"
|
||||
#include <charconv>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> PingStart,PingEnd;
|
||||
bool GConnected = false;
|
||||
bool CServer = true;
|
||||
SOCKET CSocket = -1;
|
||||
SOCKET GSocket = -1;
|
||||
|
||||
int KillSocket(uint64_t Dead){
|
||||
if(Dead == (SOCKET)-1){
|
||||
debug("Kill socket got -1 returning...");
|
||||
return 0;
|
||||
}
|
||||
shutdown(Dead,SD_BOTH);
|
||||
int a = closesocket(Dead);
|
||||
if(a != 0){
|
||||
warn("Failed to close socket!");
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
bool CheckBytes(uint32_t Bytes){
|
||||
if(Bytes == 0){
|
||||
debug("(Proxy) Connection closing");
|
||||
return false;
|
||||
}else if(Bytes < 0){
|
||||
debug("(Proxy) send failed with error: " + std::to_string(WSAGetLastError()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameSend(std::string Data){
|
||||
static std::mutex Lock;
|
||||
std::scoped_lock Guard(Lock);
|
||||
if(TCPTerminate || !GConnected || CSocket == -1)return;
|
||||
int32_t Size,Temp,Sent;
|
||||
Data += '\n';
|
||||
Size = int32_t(Data.size());
|
||||
Sent = 0;
|
||||
#ifdef DEBUG
|
||||
if(Size > 1000){
|
||||
debug("Launcher -> game (" +std::to_string(Size)+")");
|
||||
}
|
||||
#endif
|
||||
do{
|
||||
if(Sent > -1){
|
||||
Temp = send(CSocket, &Data[Sent], Size - Sent, 0);
|
||||
}
|
||||
if(!CheckBytes(Temp))return;
|
||||
Sent += Temp;
|
||||
}while(Sent < Size);
|
||||
}
|
||||
void ServerSend(std::string 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());
|
||||
if(DLen > 3)C = Data.at(0);
|
||||
if (C == 'O' || C == 'T')Ack = true;
|
||||
if(C == 'N' || C == 'W' || C == 'Y' || C == 'V' || C == 'E' || C == 'C')Rel = true;
|
||||
if(Ack || Rel){
|
||||
if(Ack || DLen > 1000)SendLarge(Data);
|
||||
else 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(){
|
||||
TCPTerminate = false;
|
||||
GConnected = false;
|
||||
Terminate = false;
|
||||
UlStatus = "Ulstart";
|
||||
MStatus = " ";
|
||||
if(UDPSock != (SOCKET)(-1)){
|
||||
debug("Terminating UDP Socket : " + std::to_string(TCPSock));
|
||||
KillSocket(UDPSock);
|
||||
}
|
||||
UDPSock = -1;
|
||||
if(TCPSock != (SOCKET)(-1)){
|
||||
debug("Terminating TCP Socket : " + std::to_string(TCPSock));
|
||||
KillSocket(TCPSock);
|
||||
}
|
||||
TCPSock = -1;
|
||||
if(GSocket != (SOCKET)(-1)){
|
||||
debug("Terminating GTCP Socket : " + std::to_string(GSocket));
|
||||
KillSocket(GSocket);
|
||||
}
|
||||
GSocket = -1;
|
||||
}
|
||||
|
||||
SOCKET SetupListener(){
|
||||
if(GSocket != -1)return GSocket;
|
||||
struct addrinfo *result = nullptr;
|
||||
struct addrinfo hints{};
|
||||
WSADATA wsaData;
|
||||
int iRes = WSAStartup(514, &wsaData); //2.2
|
||||
if (iRes != 0) {
|
||||
error("(Proxy) WSAStartup failed with error: " + std::to_string(iRes));
|
||||
return -1;
|
||||
}
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT+1).c_str(), &hints, &result);
|
||||
if (iRes != 0) {
|
||||
error("(Proxy) info failed with error: " + std::to_string(iRes));
|
||||
WSACleanup();
|
||||
}
|
||||
GSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
if (GSocket == -1) {
|
||||
error("(Proxy) socket failed with error: " + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(result);
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
iRes = bind(GSocket, result->ai_addr, (int) result->ai_addrlen);
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
error("(Proxy) bind failed with error: " + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(result);
|
||||
KillSocket(GSocket);
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
freeaddrinfo(result);
|
||||
iRes = listen(GSocket, SOMAXCONN);
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
error("(Proxy) listen failed with error: " + std::to_string(WSAGetLastError()));
|
||||
KillSocket(GSocket);
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
return GSocket;
|
||||
}
|
||||
void AutoPing(){
|
||||
while(!Terminate){
|
||||
ServerSend("p",false);
|
||||
PingStart = std::chrono::high_resolution_clock::now();
|
||||
std::this_thread::sleep_for(std::chrono::seconds (1));
|
||||
}
|
||||
}
|
||||
int ClientID = -1;
|
||||
void ParserAsync(const std::string& Data){
|
||||
if(Data.empty())return;
|
||||
char Code = Data.at(0),SubCode = 0;
|
||||
if(Data.length() > 1)SubCode = Data.at(1);
|
||||
switch (Code) {
|
||||
case 'p':
|
||||
PingEnd = std::chrono::high_resolution_clock::now();
|
||||
if(PingStart > PingEnd)ping = 0;
|
||||
else ping = int(std::chrono::duration_cast<std::chrono::milliseconds>(PingEnd-PingStart).count());
|
||||
return;
|
||||
case 'M':
|
||||
MStatus = Data;
|
||||
UlStatus = "Uldone";
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
GameSend(Data);
|
||||
}
|
||||
void ServerParser(const std::string& Data){
|
||||
ParserAsync(Data);
|
||||
}
|
||||
void NetMain(const std::string& IP, int Port){
|
||||
std::thread Ping(AutoPing);
|
||||
Ping.detach();
|
||||
UDPClientMain(IP,Port);
|
||||
CServer = true;
|
||||
Terminate = true;
|
||||
info("Connection Terminated!");
|
||||
}
|
||||
void TCPGameServer(const std::string& IP, int Port){
|
||||
GSocket = SetupListener();
|
||||
while (!TCPTerminate && GSocket != -1){
|
||||
debug("MAIN LOOP OF GAME SERVER");
|
||||
GConnected = false;
|
||||
if(!CServer){
|
||||
warn("Connection still alive terminating");
|
||||
NetReset();
|
||||
TCPTerminate = true;
|
||||
Terminate = true;
|
||||
break;
|
||||
}
|
||||
if(CServer) {
|
||||
std::thread Client(TCPClientMain, IP, Port);
|
||||
Client.detach();
|
||||
}
|
||||
CSocket = accept(GSocket, nullptr, nullptr);
|
||||
if (CSocket == -1) {
|
||||
debug("(Proxy) accept failed with error: " + std::to_string(WSAGetLastError()));
|
||||
break;
|
||||
}
|
||||
debug("(Proxy) Game Connected!");
|
||||
GConnected = true;
|
||||
if(CServer){
|
||||
std::thread t1(NetMain, IP, Port);
|
||||
t1.detach();
|
||||
CServer = false;
|
||||
}
|
||||
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
|
||||
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));
|
||||
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()));
|
||||
}
|
||||
TCPTerminate = true;
|
||||
GConnected = false;
|
||||
Terminate = true;
|
||||
if(CSocket != SOCKET_ERROR)KillSocket(CSocket);
|
||||
debug("END OF GAME SERVER");
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
// Copyright (c) 2019-present Anonymous275.
|
||||
// BeamMP Launcher code is not in the public domain and is not free software.
|
||||
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||
///
|
||||
/// Created by Anonymous275 on 7/18/2020
|
||||
///
|
||||
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
|
||||
#include <iostream>
|
||||
#include <Logger.h>
|
||||
#include <fstream>
|
||||
#include "Http.h"
|
||||
#include <mutex>
|
||||
#include <cmath>
|
||||
#include <httplib.h>
|
||||
|
||||
std::string HTTP::Codes_[] =
|
||||
{
|
||||
"Success","Unknown","Connection","BindIPAddress",
|
||||
"Read","Write","ExceedRedirectCount","Canceled",
|
||||
"SSLConnection","SSLLoadingCerts","SSLServerVerification",
|
||||
"UnsupportedMultipartBoundaryChars","Compression"
|
||||
};
|
||||
bool HTTP::isDownload = false;
|
||||
std::string HTTP::Get(const std::string &IP) {
|
||||
static std::mutex Lock;
|
||||
std::scoped_lock Guard(Lock);
|
||||
|
||||
auto pos = IP.find('/',10);
|
||||
|
||||
httplib::Client cli(IP.substr(0, pos).c_str());
|
||||
cli.set_connection_timeout(std::chrono::seconds(10));
|
||||
auto res = cli.Get(IP.substr(pos).c_str(), ProgressBar);
|
||||
std::string Ret;
|
||||
|
||||
if(res.error() == 0){
|
||||
if(res->status == 200){
|
||||
Ret = res->body;
|
||||
}else error(res->reason);
|
||||
|
||||
}else{
|
||||
if(isDownload) {
|
||||
std::cout << "\n";
|
||||
}
|
||||
error("HTTP Get failed on " + Codes_[res.error()]);
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
std::string HTTP::Post(const std::string& IP, const std::string& Fields) {
|
||||
static std::mutex Lock;
|
||||
std::scoped_lock Guard(Lock);
|
||||
|
||||
auto pos = IP.find('/',10);
|
||||
|
||||
httplib::Client cli(IP.substr(0, pos).c_str());
|
||||
cli.set_connection_timeout(std::chrono::seconds(10));
|
||||
std::string Ret;
|
||||
|
||||
if(!Fields.empty()) {
|
||||
httplib::Result res = cli.Post(IP.substr(pos).c_str(), Fields, "application/json");
|
||||
|
||||
if(res.error() == 0) {
|
||||
if (res->status != 200) {
|
||||
error(res->reason);
|
||||
}
|
||||
Ret = res->body;
|
||||
}else{
|
||||
error("HTTP Post failed on " + Codes_[res.error()]);
|
||||
}
|
||||
}else{
|
||||
httplib::Result res = cli.Post(IP.substr(pos).c_str());
|
||||
if(res.error() == 0) {
|
||||
if (res->status != 200) {
|
||||
error(res->reason);
|
||||
}
|
||||
Ret = res->body;
|
||||
}else{
|
||||
error("HTTP Post failed on " + Codes_[res.error()]);
|
||||
}
|
||||
}
|
||||
|
||||
if(Ret.empty())return "-1";
|
||||
else return Ret;
|
||||
}
|
||||
|
||||
bool HTTP::ProgressBar(size_t c, size_t t){
|
||||
if(isDownload) {
|
||||
static double last_progress, progress_bar_adv;
|
||||
progress_bar_adv = round(c / double(t) * 25);
|
||||
std::cout << "\r";
|
||||
std::cout << "Progress : [ ";
|
||||
std::cout << round(c / double(t) * 100);
|
||||
std::cout << "% ] [";
|
||||
int i;
|
||||
for (i = 0; i <= progress_bar_adv; i++)std::cout << "#";
|
||||
for (i = 0; i < 25 - progress_bar_adv; i++)std::cout << ".";
|
||||
std::cout << "]";
|
||||
last_progress = round(c / double(t) * 100);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HTTP::Download(const std::string &IP, const std::string &Path) {
|
||||
static std::mutex Lock;
|
||||
std::scoped_lock Guard(Lock);
|
||||
|
||||
isDownload = true;
|
||||
std::string Ret = Get(IP);
|
||||
isDownload = false;
|
||||
|
||||
if(Ret.empty())return false;
|
||||
|
||||
std::ofstream File(Path, std::ios::binary);
|
||||
if(File.is_open()) {
|
||||
File << Ret;
|
||||
File.close();
|
||||
std::cout << "\n";
|
||||
info("Download Complete!");
|
||||
}else{
|
||||
error("Failed to open file directory: " + Path);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
// Copyright (c) 2019-present Anonymous275.
|
||||
// BeamMP Launcher code is not in the public domain and is not free software.
|
||||
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||
///
|
||||
/// Created by Anonymous275 on 4/11/2020
|
||||
///
|
||||
|
||||
#include "Network/network.h"
|
||||
#include <ws2tcpip.h>
|
||||
#include <filesystem>
|
||||
#include "Startup.h"
|
||||
#include "Logger.h"
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <future>
|
||||
#include <cmath>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
std::string ListOfMods;
|
||||
std::vector<std::string> Split(const std::string& String,const std::string& delimiter){
|
||||
std::vector<std::string> Val;
|
||||
size_t pos;
|
||||
std::string token,s = String;
|
||||
while ((pos = s.find(delimiter)) != std::string::npos) {
|
||||
token = s.substr(0, pos);
|
||||
if(!token.empty())Val.push_back(token);
|
||||
s.erase(0, pos + delimiter.length());
|
||||
}
|
||||
if(!s.empty())Val.push_back(s);
|
||||
return Val;
|
||||
}
|
||||
|
||||
void CheckForDir(){
|
||||
if(!fs::exists("Resources")){
|
||||
_wmkdir(L"Resources");
|
||||
}
|
||||
}
|
||||
void WaitForConfirm(){
|
||||
while(!Terminate && !ModLoaded){
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
ModLoaded = false;
|
||||
}
|
||||
|
||||
|
||||
void Abord(){
|
||||
Terminate = true;
|
||||
TCPTerminate = true;
|
||||
info("Terminated!");
|
||||
}
|
||||
|
||||
std::string Auth(SOCKET Sock){
|
||||
TCPSend("VC" + GetVer(),Sock);
|
||||
|
||||
auto Res = TCPRcv(Sock);
|
||||
|
||||
if(Res.empty() || Res[0] == 'E'){
|
||||
Abord();
|
||||
return "";
|
||||
}
|
||||
|
||||
TCPSend(PublicKey,Sock);
|
||||
if(Terminate)return "";
|
||||
|
||||
Res = TCPRcv(Sock);
|
||||
if(Res.empty() || Res[0] != 'P'){
|
||||
Abord();
|
||||
return "";
|
||||
}
|
||||
|
||||
Res = Res.substr(1);
|
||||
if(Res.find_first_not_of("0123456789") == std::string::npos){
|
||||
ClientID = std::stoi(Res);
|
||||
}else{
|
||||
Abord();
|
||||
UUl("Authentication failed!");
|
||||
return "";
|
||||
}
|
||||
TCPSend("SR",Sock);
|
||||
if(Terminate)return "";
|
||||
|
||||
Res = TCPRcv(Sock);
|
||||
|
||||
if(Res[0] == 'E'){
|
||||
Abord();
|
||||
return "";
|
||||
}
|
||||
|
||||
if(Res.empty() || Res == "-"){
|
||||
info("Didn't Receive any mods...");
|
||||
ListOfMods = "-";
|
||||
TCPSend("Done",Sock);
|
||||
info("Done!");
|
||||
return "";
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
void UpdateUl(bool D,const std::string&msg){
|
||||
if(D)UlStatus = "UlDownloading Resource " + msg;
|
||||
else UlStatus = "UlLoading Resource " + msg;
|
||||
}
|
||||
|
||||
void AsyncUpdate(uint64_t& Rcv,uint64_t Size,const std::string& Name){
|
||||
do {
|
||||
double pr = double(Rcv) / double(Size) * 100;
|
||||
std::string Per = std::to_string(trunc(pr * 10) / 10);
|
||||
UpdateUl(true, Name + " (" + Per.substr(0, Per.find('.') + 2) + "%)");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}while(!Terminate && Rcv < Size);
|
||||
}
|
||||
|
||||
char* TCPRcvRaw(SOCKET Sock,uint64_t& GRcv, uint64_t Size){
|
||||
if(Sock == -1){
|
||||
Terminate = true;
|
||||
UUl("Invalid Socket");
|
||||
return nullptr;
|
||||
}
|
||||
char* File = new char[Size];
|
||||
uint64_t Rcv = 0;
|
||||
do{
|
||||
int Len = int(Size-Rcv);
|
||||
if(Len > 1000000)Len = 1000000;
|
||||
int32_t Temp = recv(Sock, &File[Rcv], Len, MSG_WAITALL);
|
||||
if(Temp < 1){
|
||||
info(std::to_string(Temp));
|
||||
UUl("Socket Closed Code 1");
|
||||
KillSocket(Sock);
|
||||
Terminate = true;
|
||||
delete[] File;
|
||||
return nullptr;
|
||||
}
|
||||
Rcv += Temp;
|
||||
GRcv += Temp;
|
||||
}while(Rcv < Size && !Terminate);
|
||||
return File;
|
||||
}
|
||||
void MultiKill(SOCKET Sock,SOCKET Sock1){
|
||||
KillSocket(Sock1);
|
||||
KillSocket(Sock);
|
||||
Terminate = true;
|
||||
}
|
||||
SOCKET InitDSock(){
|
||||
SOCKET DSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
SOCKADDR_IN ServerAddr;
|
||||
if(DSock < 1){
|
||||
KillSocket(DSock);
|
||||
Terminate = true;
|
||||
return 0;
|
||||
}
|
||||
ServerAddr.sin_family = AF_INET;
|
||||
ServerAddr.sin_port = htons(LastPort);
|
||||
inet_pton(AF_INET, LastIP.c_str(), &ServerAddr.sin_addr);
|
||||
if(connect(DSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)) != 0){
|
||||
KillSocket(DSock);
|
||||
Terminate = true;
|
||||
return 0;
|
||||
}
|
||||
char Code[2] = {'D',char(ClientID)};
|
||||
if(send(DSock,Code,2,0) != 2){
|
||||
KillSocket(DSock);
|
||||
Terminate = true;
|
||||
return 0;
|
||||
}
|
||||
return DSock;
|
||||
}
|
||||
|
||||
std::string MultiDownload(SOCKET MSock,SOCKET DSock, uint64_t Size, const std::string& Name){
|
||||
|
||||
uint64_t GRcv = 0, MSize = Size/2, DSize = Size - MSize;
|
||||
|
||||
std::thread Au(AsyncUpdate,std::ref(GRcv), Size, Name);
|
||||
|
||||
std::packaged_task<char*()> task([&] { return TCPRcvRaw(MSock,GRcv,MSize); });
|
||||
std::future<char*> f1 = task.get_future();
|
||||
std::thread Dt(std::move(task));
|
||||
Dt.detach();
|
||||
|
||||
char* DData = TCPRcvRaw(DSock,GRcv,DSize);
|
||||
|
||||
if(!DData){
|
||||
MultiKill(MSock,DSock);
|
||||
return "";
|
||||
}
|
||||
|
||||
f1.wait();
|
||||
char* MData = f1.get();
|
||||
|
||||
if(!MData){
|
||||
MultiKill(MSock,DSock);
|
||||
return "";
|
||||
}
|
||||
|
||||
if(Au.joinable())Au.join();
|
||||
|
||||
|
||||
///omg yes very ugly my god but i was in a rush will revisit
|
||||
std::string Ret(Size,0);
|
||||
memcpy_s(&Ret[0],MSize,MData,MSize);
|
||||
delete[]MData;
|
||||
|
||||
memcpy_s(&Ret[MSize],DSize,DData,DSize);
|
||||
delete[]DData;
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void InvalidResource(const std::string& File){
|
||||
UUl("Invalid mod \"" + File + "\"");
|
||||
warn("The server tried to sync \"" + File + "\" that is not a .zip file!");
|
||||
Terminate = true;
|
||||
}
|
||||
|
||||
void SyncResources(SOCKET Sock){
|
||||
std::string Ret = Auth(Sock);
|
||||
if(Ret.empty())return;
|
||||
|
||||
info("Checking Resources...");
|
||||
CheckForDir();
|
||||
|
||||
std::vector<std::string> list = Split(Ret, ";");
|
||||
std::vector<std::string> FNames(list.begin(), list.begin() + (list.size() / 2));
|
||||
std::vector<std::string> FSizes(list.begin() + (list.size() / 2), list.end());
|
||||
list.clear();
|
||||
Ret.clear();
|
||||
|
||||
int Amount = 0,Pos = 0;
|
||||
std::string a,t;
|
||||
for(const std::string&name : FNames){
|
||||
if(!name.empty()){
|
||||
t += name.substr(name.find_last_of('/') + 1) + ";";
|
||||
}
|
||||
}
|
||||
if(t.empty())ListOfMods = "-";
|
||||
else ListOfMods = t;
|
||||
t.clear();
|
||||
for(auto FN = FNames.begin(),FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN,++FS) {
|
||||
auto pos = FN->find_last_of('/');
|
||||
auto ZIP = FN->find(".zip");
|
||||
if (ZIP == std::string::npos || FN->length() - ZIP != 4) {
|
||||
InvalidResource(*FN);
|
||||
return;
|
||||
}
|
||||
if (pos == std::string::npos)continue;
|
||||
Amount++;
|
||||
}
|
||||
if(!FNames.empty())info("Syncing...");
|
||||
SOCKET DSock = InitDSock();
|
||||
for(auto FN = FNames.begin(),FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN,++FS) {
|
||||
auto pos = FN->find_last_of('/');
|
||||
if (pos != std::string::npos) {
|
||||
a = "Resources" + FN->substr(pos);
|
||||
} else continue;
|
||||
Pos++;
|
||||
if (fs::exists(a)) {
|
||||
if (FS->find_first_not_of("0123456789") != std::string::npos)continue;
|
||||
if (fs::file_size(a) == std::stoull(*FS)){
|
||||
UpdateUl(false,std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + a.substr(a.find_last_of('/')));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
try {
|
||||
if(!fs::exists(GetGamePath() + "mods/multiplayer")){
|
||||
fs::create_directories(GetGamePath() + "mods/multiplayer");
|
||||
}
|
||||
fs::copy_file(a, GetGamePath() + "mods/multiplayer" + a.substr(a.find_last_of('/')),
|
||||
fs::copy_options::overwrite_existing);
|
||||
} catch (std::exception& e) {
|
||||
error("Failed copy to the mods folder! " + std::string(e.what()));
|
||||
Terminate = true;
|
||||
continue;
|
||||
}
|
||||
WaitForConfirm();
|
||||
continue;
|
||||
}else remove(a.c_str());
|
||||
}
|
||||
CheckForDir();
|
||||
std::string FName = a.substr(a.find_last_of('/'));
|
||||
do {
|
||||
TCPSend("f" + *FN,Sock);
|
||||
|
||||
std::string Data = TCPRcv(Sock);
|
||||
if (Data == "CO" || Terminate){
|
||||
Terminate = true;
|
||||
UUl("Server cannot find " + FName);
|
||||
break;
|
||||
}
|
||||
|
||||
std::string Name = std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + FName;
|
||||
|
||||
Data = MultiDownload(Sock,DSock,std::stoull(*FS), Name);
|
||||
|
||||
if(Terminate)break;
|
||||
UpdateUl(false,std::to_string(Pos)+"/"+std::to_string(Amount)+": "+FName);
|
||||
std::ofstream LFS;
|
||||
LFS.open(a.c_str(), std::ios_base::app | std::ios::binary);
|
||||
if (LFS.is_open()) {
|
||||
LFS.write(&Data[0], Data.size());
|
||||
LFS.close();
|
||||
}
|
||||
|
||||
}while(fs::file_size(a) != std::stoull(*FS) && !Terminate);
|
||||
if(!Terminate){
|
||||
if(!fs::exists(GetGamePath() + "mods/multiplayer")){
|
||||
fs::create_directories(GetGamePath() + "mods/multiplayer");
|
||||
}
|
||||
fs::copy_file(a,GetGamePath() + "mods/multiplayer" + FName, fs::copy_options::overwrite_existing);
|
||||
}
|
||||
WaitForConfirm();
|
||||
}
|
||||
KillSocket(DSock);
|
||||
if(!Terminate){
|
||||
TCPSend("Done",Sock);
|
||||
info("Done!");
|
||||
}else{
|
||||
UlStatus = "Ulstart";
|
||||
info("Connection Terminated!");
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright (c) 2019-present Anonymous275.
|
||||
// BeamMP Launcher code is not in the public domain and is not free software.
|
||||
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||
///
|
||||
/// Created by Anonymous275 on 5/8/2020
|
||||
///
|
||||
#include "Zlib/Compressor.h"
|
||||
#include "Network/network.h"
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
#include "Logger.h"
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
SOCKET UDPSock = -1;
|
||||
sockaddr_in* ToServer = nullptr;
|
||||
|
||||
void UDPSend(std::string Data){
|
||||
if(ClientID == -1 || UDPSock == -1)return;
|
||||
if(Data.length() > 400){
|
||||
std::string CMP(Comp(Data));
|
||||
Data = "ABG:" + CMP;
|
||||
}
|
||||
std::string Packet = char(ClientID+1) + std::string(":") + Data;
|
||||
int sendOk = sendto(UDPSock, Packet.c_str(), int(Packet.size()), 0, (sockaddr*)ToServer, sizeof(*ToServer));
|
||||
if (sendOk == SOCKET_ERROR)error("Error Code : " + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
|
||||
|
||||
void SendLarge(std::string Data){
|
||||
if(Data.length() > 400){
|
||||
std::string CMP(Comp(Data));
|
||||
Data = "ABG:" + CMP;
|
||||
}
|
||||
TCPSend(Data,TCPSock);
|
||||
}
|
||||
|
||||
void UDPParser(std::string Packet){
|
||||
if(Packet.substr(0,4) == "ABG:"){
|
||||
Packet = DeComp(Packet.substr(4));
|
||||
}
|
||||
ServerParser(Packet);
|
||||
}
|
||||
void UDPRcv(){
|
||||
sockaddr_in FromServer{};
|
||||
int clientLength = sizeof(FromServer);
|
||||
ZeroMemory(&FromServer, clientLength);
|
||||
std::string Ret(10240,0);
|
||||
if(UDPSock == -1)return;
|
||||
int32_t Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&FromServer, &clientLength);
|
||||
if (Rcv == SOCKET_ERROR)return;
|
||||
UDPParser(Ret.substr(0,Rcv));
|
||||
}
|
||||
void UDPClientMain(const std::string& IP,int Port){
|
||||
WSADATA data;
|
||||
if (WSAStartup(514, &data)){
|
||||
error("Can't start Winsock!");
|
||||
return;
|
||||
}
|
||||
delete ToServer;
|
||||
ToServer = new sockaddr_in;
|
||||
ToServer->sin_family = AF_INET;
|
||||
ToServer->sin_port = htons(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");
|
||||
while(!Terminate)UDPRcv();
|
||||
KillSocket(UDPSock);
|
||||
WSACleanup();
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
// Copyright (c) 2019-present Anonymous275.
|
||||
// BeamMP Launcher code is not in the public domain and is not free software.
|
||||
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||
///
|
||||
/// Created by Anonymous275 on 5/8/2020
|
||||
///
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include "Logger.h"
|
||||
#include <iostream>
|
||||
#include <ws2tcpip.h>
|
||||
#include <Zlib/Compressor.h>
|
||||
|
||||
#include "Network/network.h"
|
||||
|
||||
|
||||
int LastPort;
|
||||
std::string LastIP;
|
||||
SOCKET TCPSock = -1;
|
||||
|
||||
bool CheckBytes(int32_t Bytes){
|
||||
if (Bytes == 0){
|
||||
debug("(TCP) Connection closing... CheckBytes(16)");
|
||||
Terminate = true;
|
||||
return false;
|
||||
}else if (Bytes < 0) {
|
||||
debug("(TCP CB) recv failed with error: " + std::to_string(WSAGetLastError()));
|
||||
KillSocket(TCPSock);
|
||||
Terminate = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void UUl(const std::string& R){
|
||||
UlStatus = "UlDisconnected: " + R;
|
||||
}
|
||||
|
||||
void TCPSend(const std::string&Data,uint64_t Sock){
|
||||
if(Sock == -1){
|
||||
Terminate = true;
|
||||
UUl("Invalid Socket");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t Size,Sent,Temp;
|
||||
std::string Send(4,0);
|
||||
Size = int32_t(Data.size());
|
||||
memcpy(&Send[0],&Size,sizeof(Size));
|
||||
Send += Data;
|
||||
// Do not use Size before this point for anything but the header
|
||||
Sent = 0;
|
||||
Size += 4;
|
||||
do{
|
||||
if (size_t(Sent) >= Send.size()) {
|
||||
error("string OOB in " + std::string(__func__));
|
||||
UUl("TCP Send OOB");
|
||||
return;
|
||||
}
|
||||
Temp = send(Sock, &Send[Sent], Size - Sent, 0);
|
||||
if(!CheckBytes(Temp)){
|
||||
UUl("Socket Closed Code 2");
|
||||
return;
|
||||
}
|
||||
Sent += Temp;
|
||||
}while(Sent < Size);
|
||||
}
|
||||
|
||||
std::string TCPRcv(SOCKET Sock){
|
||||
if(Sock == -1){
|
||||
Terminate = true;
|
||||
UUl("Invalid Socket");
|
||||
return "";
|
||||
}
|
||||
int32_t Header,BytesRcv = 0,Temp;
|
||||
std::vector<char> 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));
|
||||
|
||||
if(!CheckBytes(BytesRcv)){
|
||||
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);
|
||||
|
||||
std::string Ret(Data.data(),Header);
|
||||
|
||||
if (Ret.substr(0, 4) == "ABG:") {
|
||||
Ret = DeComp(Ret.substr(4));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
//debug("Parsing from server -> " + std::to_string(Ret.size()));
|
||||
#endif
|
||||
if(Ret[0] == 'E')UUl(Ret.substr(1));
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void TCPClientMain(const std::string& IP,int Port){
|
||||
LastIP = IP;
|
||||
LastPort = Port;
|
||||
WSADATA wsaData;
|
||||
SOCKADDR_IN ServerAddr;
|
||||
int RetCode;
|
||||
WSAStartup(514, &wsaData); //2.2
|
||||
TCPSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if(TCPSock == -1){
|
||||
printf("Client: socket failed! Error code: %d\n", WSAGetLastError());
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
ServerAddr.sin_family = AF_INET;
|
||||
ServerAddr.sin_port = htons(Port);
|
||||
inet_pton(AF_INET, IP.c_str(), &ServerAddr.sin_addr);
|
||||
RetCode = connect(TCPSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr));
|
||||
if(RetCode != 0){
|
||||
UlStatus = "UlConnection Failed!";
|
||||
error("Client: connect failed! Error code: " + std::to_string(WSAGetLastError()));
|
||||
KillSocket(TCPSock);
|
||||
WSACleanup();
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
info("Connected!");
|
||||
|
||||
char Code = 'C';
|
||||
send(TCPSock, &Code, 1, 0);
|
||||
SyncResources(TCPSock);
|
||||
while(!Terminate){
|
||||
ServerParser(TCPRcv(TCPSock));
|
||||
}
|
||||
GameSend("T");
|
||||
////Game Send Terminate
|
||||
if(KillSocket(TCPSock) != 0)
|
||||
debug("(TCP) Cannot close socket. Error code: " + std::to_string(WSAGetLastError()));
|
||||
|
||||
if(WSACleanup() != 0)
|
||||
debug("(TCP) Client: WSACleanup() failed!...");
|
||||
}
|
||||
Reference in New Issue
Block a user