mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2026-04-14 11:46:06 +00:00
V1.6
Rewrite
This commit is contained in:
198
src/Network/Core.cpp
Normal file
198
src/Network/Core.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 7/20/2020
|
||||
///
|
||||
#include "Network/network.h"
|
||||
#include "Security/Enc.h"
|
||||
#include "Curl/http.h"
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#include "Memory.h"
|
||||
#include "Logger.h"
|
||||
#include <thread>
|
||||
#include <set>
|
||||
std::set<std::string>* ConfList = nullptr;
|
||||
bool TCPTerminate = false;
|
||||
int DEFAULT_PORT = 4444;
|
||||
bool Terminate = false;
|
||||
std::string UlStatus;
|
||||
std::string MStatus;
|
||||
bool once = false;
|
||||
bool ModLoaded;
|
||||
long long ping = -1;
|
||||
void StartSync(const std::string &Data){
|
||||
UlStatus = Sec("UlLoading...");
|
||||
TCPTerminate = false;
|
||||
Terminate = false;
|
||||
ConfList->clear();
|
||||
ping = -1;
|
||||
std::thread GS(TCPGameServer,Data.substr(1,Data.find(':')-1),std::stoi(Data.substr(Data.find(':')+1)));
|
||||
GS.detach();
|
||||
}
|
||||
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;
|
||||
//if(!Dev){
|
||||
Data = Code + HTTP_REQUEST(Sec("s1.yourthought.co.uk/servers-info"),3599);
|
||||
//}else Data.clear();
|
||||
break;
|
||||
case 'C':
|
||||
ListOfMods.clear();
|
||||
StartSync(Data);
|
||||
info(Sec("Connecting to server"));
|
||||
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')Data = "Up" + std::to_string(ping);
|
||||
if(!SubCode)Data = std::string(UlStatus) + "\n" + "Up" + std::to_string(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;
|
||||
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(Sec("(Core) send failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
}
|
||||
}
|
||||
void GameHandler(SOCKET Client){
|
||||
if (!once){
|
||||
std::thread Memory(MemoryInit);
|
||||
Memory.detach();
|
||||
once = true;
|
||||
}
|
||||
char buf[64000];
|
||||
int res,len = 64000;
|
||||
do{
|
||||
res = recv(Client, buf, len, 0);
|
||||
if(res < 1)break;
|
||||
std::string data(buf, res);
|
||||
std::thread Respond(Parse, data, Client);
|
||||
Respond.detach();
|
||||
}while(res > 0);
|
||||
if (res == 0) {
|
||||
debug(Sec("(Core) Connection closing"));
|
||||
} else {
|
||||
debug(Sec("(Core) recv failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
closesocket(Client);
|
||||
}
|
||||
void localRes(){
|
||||
MStatus = " ";
|
||||
UlStatus = Sec("Ulstart");
|
||||
if(ConfList != nullptr){
|
||||
ConfList->clear();
|
||||
delete ConfList;
|
||||
ConfList = nullptr;
|
||||
}
|
||||
ConfList = new std::set<std::string>;
|
||||
}
|
||||
void CoreMain() {
|
||||
debug(Sec("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(Sec("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(Sec("(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(Sec("(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(Sec("(Core) bind failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(res);
|
||||
closesocket(LSocket);
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
iRes = listen(LSocket, SOMAXCONN);
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
debug(Sec("(Core) listen failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(res);
|
||||
closesocket(LSocket);
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
do{
|
||||
CSocket = accept(LSocket, nullptr, nullptr);
|
||||
if (CSocket == -1) {
|
||||
error(Sec("(Core) accept failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
continue;
|
||||
}
|
||||
localRes();
|
||||
info(Sec("Game Connected!"));
|
||||
GameHandler(CSocket);
|
||||
warn(Sec("Game Reconnecting..."));
|
||||
}while(CSocket);
|
||||
closesocket(LSocket);
|
||||
WSACleanup();
|
||||
}
|
||||
int Handle(EXCEPTION_POINTERS *ep){
|
||||
char* hex = new char[100];
|
||||
sprintf_s(hex,100, "%lX", ep->ExceptionRecord->ExceptionCode);
|
||||
except(Sec("(Core) Code : ") + std::string(hex));
|
||||
delete [] hex;
|
||||
return 1;
|
||||
}
|
||||
[[noreturn]] void CoreNetwork(){
|
||||
while(true){
|
||||
__try{
|
||||
CoreMain();
|
||||
}__except(Handle(GetExceptionInformation())){}
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
202
src/Network/GlobalHandler.cpp
Normal file
202
src/Network/GlobalHandler.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 7/25/2020
|
||||
///
|
||||
#include "Network/network.h"
|
||||
#include "Security/Enc.h"
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#include "Logger.h"
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
std::chrono::time_point<std::chrono::steady_clock> PingStart,PingEnd;
|
||||
bool GConnected = false;
|
||||
bool CServer = true;
|
||||
extern SOCKET UDPSock;
|
||||
extern SOCKET TCPSock;
|
||||
SOCKET CSocket;
|
||||
void GameSend(const std::string&Data){
|
||||
if(TCPTerminate || !GConnected || CSocket == -1)return;
|
||||
int iSRes = send(CSocket, (Data + "\n").c_str(), int(Data.size()) + 1, 0);
|
||||
if (iSRes == SOCKET_ERROR) {
|
||||
debug(Sec("(Proxy) send failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
} else if (Data.length() > 1000){
|
||||
debug(Sec("(Launcher->Game) Bytes sent: ") + std::to_string(iSRes));
|
||||
}
|
||||
}
|
||||
void ServerSend(std::string Data, bool Rel){
|
||||
if(Terminate || Data.empty())return;
|
||||
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(Ack || Rel){
|
||||
if(Ack || DLen > 1000)SendLarge(Data);
|
||||
else TCPSend(Data);
|
||||
}else UDPSend(Data);
|
||||
|
||||
if (DLen > 1000) {
|
||||
debug(Sec("(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 = Sec("Ulstart");
|
||||
MStatus = " ";
|
||||
if(UDPSock != SOCKET_ERROR)closesocket(UDPSock);
|
||||
UDPSock = -1;
|
||||
if(TCPSock != SOCKET_ERROR)closesocket(TCPSock);
|
||||
TCPSock = -1;
|
||||
ClearAll();
|
||||
}
|
||||
|
||||
SOCKET SetupListener(){
|
||||
static SOCKET LSocket = -1;
|
||||
if(LSocket != -1)return LSocket;
|
||||
struct addrinfo *result = nullptr;
|
||||
struct addrinfo hints{};
|
||||
WSADATA wsaData;
|
||||
int iRes = WSAStartup(514, &wsaData); //2.2
|
||||
if (iRes != 0) {
|
||||
error(Sec("(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(Sec("(Proxy) info failed with error: ") + std::to_string(iRes));
|
||||
WSACleanup();
|
||||
}
|
||||
LSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
if (LSocket == -1) {
|
||||
error(Sec("(Proxy) socket failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(result);
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
iRes = bind(LSocket, result->ai_addr, (int) result->ai_addrlen);
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
error(Sec("(Proxy) bind failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
freeaddrinfo(result);
|
||||
closesocket(LSocket);
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
freeaddrinfo(result);
|
||||
iRes = listen(LSocket, SOMAXCONN);
|
||||
if (iRes == SOCKET_ERROR) {
|
||||
error(Sec("(Proxy) listen failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
closesocket(LSocket);
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
return LSocket;
|
||||
}
|
||||
void AutoPing(){
|
||||
while(!Terminate){
|
||||
ServerSend(Sec("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':
|
||||
ClientID = std::stoi(Data.substr(1));
|
||||
break;
|
||||
case 'p':
|
||||
PingEnd = std::chrono::high_resolution_clock::now();
|
||||
if(PingStart > PingEnd)ping = 0;
|
||||
else ping = std::chrono::duration_cast<std::chrono::milliseconds>(PingEnd-PingStart).count();
|
||||
return;
|
||||
case 'M':
|
||||
MStatus = Data;
|
||||
UlStatus = Sec("Uldone");
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
GameSend(Data);
|
||||
}
|
||||
void ServerParser(const std::string& Data){
|
||||
std::thread Async(ParserAsync,Data);
|
||||
Async.detach();
|
||||
}
|
||||
void NetMain(const std::string& IP, int Port){
|
||||
std::thread Ping(AutoPing);
|
||||
Ping.detach();
|
||||
UDPClientMain(IP,Port);
|
||||
CServer = true;
|
||||
Terminate = true;
|
||||
info(Sec("Connection Terminated!"));
|
||||
}
|
||||
void TCPGameServer(const std::string& IP, int Port){
|
||||
SOCKET LSocket = SetupListener();
|
||||
while (!TCPTerminate && LSocket != -1){
|
||||
GConnected = false;
|
||||
if(!CServer){
|
||||
warn(Sec("Connection still alive terminating"));
|
||||
NetReset();
|
||||
TCPTerminate = true;
|
||||
Terminate = true;
|
||||
break;
|
||||
}
|
||||
if(CServer) {
|
||||
std::thread Client(TCPClientMain, IP, Port);
|
||||
Client.detach();
|
||||
}
|
||||
CSocket = accept(LSocket, nullptr, nullptr);
|
||||
if (CSocket == -1) {
|
||||
error(Sec("(Proxy) accept failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
break;
|
||||
}
|
||||
debug(Sec("(Proxy) Game Connected!"));
|
||||
GConnected = true;
|
||||
if(CServer){
|
||||
std::thread t1(NetMain, IP, Port);
|
||||
t1.detach();
|
||||
CServer = false;
|
||||
}
|
||||
char buf[10000];
|
||||
int Res,len = 10000;
|
||||
ZeroMemory(buf, len);
|
||||
do{
|
||||
Res = recv(CSocket,buf,len,0);
|
||||
if(Res < 1)break;
|
||||
std::string t;
|
||||
std::string buff(Res,0);
|
||||
memcpy_s(&buff[0],Res,buf,Res);
|
||||
std::stringstream ss(buff);
|
||||
int S = 0;
|
||||
while (std::getline(ss, t, '\n')) {
|
||||
ServerSend(t,false);
|
||||
S++;
|
||||
}
|
||||
if(S > 3)std::cout << S << std::endl;
|
||||
}while(Res > 0);
|
||||
if(Res == 0)debug(Sec("(Proxy) Connection closing"));
|
||||
else debug(Sec("(Proxy) recv failed error : ") + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
TCPTerminate = true;
|
||||
GConnected = false;
|
||||
Terminate = true;
|
||||
if(LSocket == -1){
|
||||
UlStatus = Sec("Critical error! check the launcher logs");
|
||||
}
|
||||
if(CSocket != SOCKET_ERROR)closesocket(CSocket);
|
||||
}
|
||||
87
src/Network/Http.cpp
Normal file
87
src/Network/Http.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 7/18/2020
|
||||
///
|
||||
#define CURL_STATICLIB
|
||||
#include "Security/Game.h"
|
||||
#include "Security/Enc.h"
|
||||
#include "Curl/curl.h"
|
||||
#include <iostream>
|
||||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp){
|
||||
((std::string*)userp)->append((char*)contents, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
std::string HTTP_REQUEST(const std::string& IP,int port){
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
std::string readBuffer;
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_PORT, port);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
if(res != CURLE_OK)return "-1";
|
||||
}
|
||||
curl_global_cleanup();
|
||||
return readBuffer;
|
||||
}
|
||||
|
||||
int nb_bar;
|
||||
double last_progress, progress_bar_adv;
|
||||
int progress_bar (void *bar, double t, double d){
|
||||
if(last_progress != round(d/t*100)){
|
||||
nb_bar = 25;
|
||||
progress_bar_adv = round(d/t*nb_bar);
|
||||
std::cout<<"\r";
|
||||
std::cout<<Sec("Progress : [ ");
|
||||
if(t!=0)std::cout<<round(d/t*100);else std::cout<<0;
|
||||
std::cout << "% ] [";
|
||||
int i;
|
||||
for(i = 0; i <= progress_bar_adv; i++)std::cout<<"#";
|
||||
for(i = 0; i < nb_bar - progress_bar_adv; i++)std::cout<<".";
|
||||
std::cout<<"]";
|
||||
last_progress = round(d/t*100);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
struct File {
|
||||
const char *filename;
|
||||
FILE *stream;
|
||||
};
|
||||
static size_t my_fwrite(void *buffer,size_t size,size_t nmemb,void *stream){
|
||||
auto *out = (struct File*)stream;
|
||||
if(!out->stream) {
|
||||
fopen_s(&out->stream,out->filename,Sec("wb"));
|
||||
if(!out->stream)return -1;
|
||||
}
|
||||
return fwrite(buffer, size, nmemb, out->stream);
|
||||
}
|
||||
int Download(const std::string& URL,const std::string& Path,bool close){
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct File file = {Path.c_str(),nullptr};
|
||||
//curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
curl = curl_easy_init();
|
||||
if(curl){
|
||||
curl_easy_setopt(curl, CURLOPT_URL,URL.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_bar);
|
||||
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
if(res != CURLE_OK)return res;
|
||||
}
|
||||
if(file.stream)fclose(file.stream);
|
||||
if(!close)SecureMods();
|
||||
curl_global_cleanup();
|
||||
std::cout << std::endl;
|
||||
return -1;
|
||||
}
|
||||
225
src/Network/Resources.cpp
Normal file
225
src/Network/Resources.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 4/11/2020
|
||||
///
|
||||
#include "Discord/discord_info.h"
|
||||
#include "Network/network.h"
|
||||
#include "Security/Enc.h"
|
||||
#include <WS2tcpip.h>
|
||||
#include <filesystem>
|
||||
#include "Startup.h"
|
||||
#include "Logger.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace fs = std::experimental::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 STCPSend(SOCKET socket,const std::string&Data){
|
||||
if(socket == -1){
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
int BytesSent = send(socket, Data.c_str(), int(Data.length())+1, 0);
|
||||
if (BytesSent == 0){
|
||||
debug(Sec("(TCP) Connection closing..."));
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
else if (BytesSent < 0) {
|
||||
debug(Sec("(TCP) send failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
closesocket(socket);
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
std::pair<char*,size_t> STCPRecv(SOCKET socket){
|
||||
char buf[64000];
|
||||
int len = 64000;
|
||||
ZeroMemory(buf, len);
|
||||
int BytesRcv = recv(socket, buf, len,0);
|
||||
if (BytesRcv == 0){
|
||||
info(Sec("(TCP) Connection closing..."));
|
||||
Terminate = true;
|
||||
return std::make_pair((char*)"",0);
|
||||
}else if (BytesRcv < 0) {
|
||||
info(Sec("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
closesocket(socket);
|
||||
Terminate = true;
|
||||
return std::make_pair((char*)"",0);
|
||||
}
|
||||
char* Ret = new char[BytesRcv];
|
||||
memcpy_s(Ret,BytesRcv,buf,BytesRcv);
|
||||
ZeroMemory(buf, len);
|
||||
return std::make_pair(Ret,BytesRcv);
|
||||
}
|
||||
void CheckForDir(){
|
||||
struct stat info{};
|
||||
if(stat( Sec("Resources"), &info) != 0){
|
||||
_wmkdir(SecW(L"Resources"));
|
||||
}
|
||||
}
|
||||
void WaitForConfirm(){
|
||||
while(!Terminate && !ModLoaded){
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
ModLoaded = false;
|
||||
}
|
||||
|
||||
int N,E;
|
||||
void Parse(const std::string& msg){
|
||||
std::stringstream ss(msg);
|
||||
std::string t;
|
||||
while (std::getline(ss, t, 'g')) {
|
||||
if(t.find_first_not_of(Sec("0123456789abcdef")) != std::string::npos)return;
|
||||
if(N == 0){
|
||||
N = std::stoi(t, nullptr, 16);
|
||||
}else if(E == 0){
|
||||
E = std::stoi(t, nullptr, 16);
|
||||
}else return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string HandShake(SOCKET Sock){
|
||||
N = 0;E = 0;
|
||||
auto Res = STCPRecv(Sock);
|
||||
std::string msg(Res.first,Res.second);
|
||||
Parse(msg);
|
||||
if(N != 0 && E != 0) {
|
||||
msg = RSA_E("NR" + GetDName() + ":" + GetDID(),E,N);
|
||||
if(!msg.empty()) {
|
||||
STCPSend(Sock,msg);
|
||||
STCPSend(Sock, RSA_E("VC" + GetVer(),E,N));
|
||||
Res = STCPRecv(Sock);
|
||||
msg = Res.first;
|
||||
}
|
||||
}
|
||||
if(N == 0 || E == 0 || msg.size() < 2 || msg.substr(0,2) != "WS"){
|
||||
Terminate = true;
|
||||
TCPTerminate = true;
|
||||
UlStatus = Sec("UlDisconnected: full or outdated server");
|
||||
info(Sec("Terminated!"));
|
||||
return "";
|
||||
}
|
||||
STCPSend(Sock,Sec("SR"));
|
||||
Res = STCPRecv(Sock);
|
||||
if(strlen(Res.first) == 0 || std::string(Res.first) == "-"){
|
||||
info(Sec("Didn't Receive any mods..."));
|
||||
ListOfMods = "-";
|
||||
STCPSend(Sock,Sec("Done"));
|
||||
info(Sec("Done!"));
|
||||
return "";
|
||||
}
|
||||
return Res.first;
|
||||
}
|
||||
|
||||
void SyncResources(SOCKET Sock){
|
||||
std::string Ret = HandShake(Sock);
|
||||
if(Ret.empty())return;
|
||||
|
||||
info(Sec("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('/');
|
||||
if (pos == std::string::npos)continue;
|
||||
Amount++;
|
||||
}
|
||||
if(!FNames.empty())info(Sec("Syncing..."));
|
||||
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 = Sec("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::stoi(*FS)){
|
||||
UlStatus = Sec("UlLoading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) +
|
||||
"): " + a.substr(a.find_last_of('/'));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
fs::copy_file(a, Sec("BeamNG/mods")+a.substr(a.find_last_of('/')), fs::copy_options::overwrite_existing);
|
||||
WaitForConfirm();
|
||||
continue;
|
||||
}else remove(a.c_str());
|
||||
}
|
||||
CheckForDir();
|
||||
do {
|
||||
STCPSend(Sock, "f" + *FN);
|
||||
int Recv = 0,Size = std::stoi(*FS);
|
||||
char*File = new char[Size];
|
||||
ZeroMemory(File,Size);
|
||||
do {
|
||||
auto Pair = STCPRecv(Sock);
|
||||
char* Data = Pair.first;
|
||||
size_t BytesRcv = Pair.second;
|
||||
if (strcmp(Data, Sec("Cannot Open")) == 0 || Terminate){
|
||||
if(BytesRcv != 0)delete[] Data;
|
||||
break;
|
||||
}
|
||||
memcpy_s(File+Recv,BytesRcv,Data,BytesRcv);
|
||||
Recv += int(BytesRcv);
|
||||
float per = float(Recv)/std::stof(*FS) * 100;
|
||||
std::string Percent = std::to_string(truncf(per * 10) / 10);
|
||||
UlStatus = Sec("UlDownloading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) +
|
||||
"): " + a.substr(a.find_last_of('/')) + " (" +
|
||||
Percent.substr(0, Percent.find('.') + 2) + "%)";
|
||||
delete[] Data;
|
||||
} while (Recv != Size && Recv < Size && !Terminate);
|
||||
if(Terminate)break;
|
||||
UlStatus = Sec("UlLoading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) +
|
||||
"): " + a.substr(a.find_last_of('/'));
|
||||
std::ofstream LFS;
|
||||
LFS.open(a.c_str(), std::ios_base::app | std::ios::binary);
|
||||
if (LFS.is_open()) {
|
||||
LFS.write(File, Recv);
|
||||
LFS.close();
|
||||
}
|
||||
ZeroMemory(File,Size);
|
||||
delete[] File;
|
||||
}while(fs::file_size(a) != std::stoi(*FS) && !Terminate);
|
||||
if(!Terminate)fs::copy_file(a,Sec("BeamNG/mods")+a.substr(a.find_last_of('/')), fs::copy_options::overwrite_existing);
|
||||
WaitForConfirm();
|
||||
}
|
||||
FNames.clear();
|
||||
FSizes.clear();
|
||||
a.clear();
|
||||
if(!Terminate){
|
||||
STCPSend(Sock,Sec("Done"));
|
||||
info(Sec("Done!"));
|
||||
}else{
|
||||
UlStatus = Sec("Ulstart");
|
||||
info(Sec("Connection Terminated!"));
|
||||
}
|
||||
}
|
||||
228
src/Network/VehicleData.cpp
Normal file
228
src/Network/VehicleData.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 5/8/2020
|
||||
///
|
||||
#include "Zlib/Compressor.h"
|
||||
#include "Network/network.h"
|
||||
#include "Security/Enc.h"
|
||||
#include <WS2tcpip.h>
|
||||
#include "Logger.h"
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <set>
|
||||
|
||||
SOCKET UDPSock;
|
||||
sockaddr_in ToServer{};
|
||||
struct PacketData{
|
||||
int ID;
|
||||
std::string Data;
|
||||
int Tries;
|
||||
};
|
||||
struct SplitData{
|
||||
int Total{};
|
||||
int ID{};
|
||||
std::set<std::pair<int,std::string>> Fragments;
|
||||
};
|
||||
std::set<SplitData*> SplitPackets;
|
||||
std::set<PacketData*> BigDataAcks;
|
||||
void ClearAll(){
|
||||
for(SplitData*S : SplitPackets){
|
||||
if(S != nullptr){
|
||||
delete S;
|
||||
S = nullptr;
|
||||
}
|
||||
}
|
||||
for(PacketData*S : BigDataAcks){
|
||||
if(S != nullptr){
|
||||
delete S;
|
||||
S = nullptr;
|
||||
}
|
||||
}
|
||||
SplitPackets.clear();
|
||||
BigDataAcks.clear();
|
||||
}
|
||||
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(Sec("Error Code : ") + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
|
||||
void LOOP(){
|
||||
while(UDPSock != -1) {
|
||||
for (PacketData* p : BigDataAcks) {
|
||||
if(p != nullptr && p->Tries < 20){
|
||||
p->Tries++;
|
||||
UDPSend(p->Data);
|
||||
}else{
|
||||
BigDataAcks.erase(p);
|
||||
if(p != nullptr){
|
||||
delete p;
|
||||
p = nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
}
|
||||
|
||||
void AckID(int ID){
|
||||
for(PacketData* p : BigDataAcks){
|
||||
if(p != nullptr && p->ID == ID){
|
||||
p->Tries = 25;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int PackID(){
|
||||
static int ID = -1;
|
||||
if(ID > 999999)ID = 0;
|
||||
else ID++;
|
||||
return ID;
|
||||
}
|
||||
int SplitID(){
|
||||
static int SID = -1;
|
||||
if(SID > 999999)SID = 0;
|
||||
else SID++;
|
||||
return SID;
|
||||
}
|
||||
void SendLarge(const std::string&Data){
|
||||
int ID = PackID();
|
||||
std::string Packet;
|
||||
if(Data.length() > 1000){
|
||||
std::string pckt = Data;
|
||||
int S = 1,Split = int(ceil(float(pckt.length()) / 1000));
|
||||
int SID = SplitID();
|
||||
while(pckt.length() > 1000){
|
||||
Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+std::to_string(ID)+"|"+
|
||||
std::to_string(SID)+":"+pckt.substr(0,1000);
|
||||
BigDataAcks.insert(new PacketData{ID,Packet,1});
|
||||
UDPSend(Packet);
|
||||
pckt = pckt.substr(1000);
|
||||
S++;
|
||||
ID = PackID();
|
||||
}
|
||||
Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+
|
||||
std::to_string(ID)+"|"+std::to_string(SID)+":"+pckt;
|
||||
BigDataAcks.insert(new PacketData{ID,Packet,1});
|
||||
UDPSend(Packet);
|
||||
}else{
|
||||
Packet = "BD:" + std::to_string(ID) + ":" + Data;
|
||||
BigDataAcks.insert(new PacketData{ID,Packet,1});
|
||||
UDPSend(Packet);
|
||||
}
|
||||
}
|
||||
std::array<int, 50> HandledIDs;
|
||||
void IDReset(){
|
||||
for(int C = 0;C < 50;C++){
|
||||
HandledIDs.at(C) = -1;
|
||||
}
|
||||
}
|
||||
bool Handled(int ID){
|
||||
static int Pos = 0;
|
||||
for(int id : HandledIDs){
|
||||
if(id == ID)return true;
|
||||
}
|
||||
if(Pos > 49)Pos = 0;
|
||||
HandledIDs.at(Pos) = ID;
|
||||
Pos++;
|
||||
return false;
|
||||
}
|
||||
SplitData*GetSplit(int SplitID){
|
||||
for(SplitData* a : SplitPackets){
|
||||
if(a != nullptr && a->ID == SplitID)return a;
|
||||
}
|
||||
auto* a = new SplitData();
|
||||
SplitPackets.insert(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
void ServerParser(const std::string& Data);
|
||||
void HandleChunk(const std::string&Data){
|
||||
int pos1 = int(Data.find(':'))+1,pos2 = int(Data.find(':',pos1)),pos3 = int(Data.find('/'));
|
||||
int pos4 = int(Data.find('|'));
|
||||
int Max = stoi(Data.substr(pos3+1,pos1-pos3-2));
|
||||
int Current = stoi(Data.substr(2,pos3-2));
|
||||
int ID = stoi(Data.substr(pos1,pos4-pos1));
|
||||
int SplitID = stoi(Data.substr(pos4+1,pos2-pos4-1));
|
||||
std::string ack = "TRG:" + Data.substr(pos1,pos4-pos1);
|
||||
UDPSend(ack);
|
||||
if(Handled(ID))return;
|
||||
warn("Handeling Packet ID : " + std::to_string(ID));
|
||||
SplitData* SData = GetSplit(SplitID);
|
||||
SData->Total = Max;
|
||||
SData->ID = SplitID;
|
||||
SData->Fragments.insert(std::make_pair(Current,Data.substr(pos2+1)));
|
||||
if(SData->Fragments.size() == SData->Total){
|
||||
std::string ToHandle;
|
||||
for(const std::pair<int,std::string>& a : SData->Fragments){
|
||||
ToHandle += a.second;
|
||||
}
|
||||
ServerParser(ToHandle);
|
||||
SplitPackets.erase(SData);
|
||||
delete SData;
|
||||
SData = nullptr;
|
||||
}
|
||||
}
|
||||
void UDPParser(std::string Packet){
|
||||
if(Packet.substr(0,4) == "ABG:"){
|
||||
Packet = DeComp(Packet.substr(4));
|
||||
}
|
||||
if(Packet.substr(0,4) == "TRG:"){
|
||||
AckID(stoi(Packet.substr(4)));
|
||||
debug(Sec("Got Ack for data"));
|
||||
return;
|
||||
}else if(Packet.substr(0,3) == "BD:"){
|
||||
auto pos = Packet.find(':',4);
|
||||
int ID = stoi(Packet.substr(3,pos-3));
|
||||
std::string pckt = "TRG:" + std::to_string(ID);
|
||||
UDPSend(pckt);
|
||||
if(!Handled(ID)) {
|
||||
pckt = Packet.substr(pos + 1);
|
||||
ServerParser(pckt);
|
||||
}
|
||||
return;
|
||||
}else if(Packet.substr(0,2) == "SC"){
|
||||
HandleChunk(Packet);
|
||||
return;
|
||||
}
|
||||
ServerParser(Packet);
|
||||
}
|
||||
void UDPRcv(){
|
||||
char buf[10240];
|
||||
int len = 10240;
|
||||
sockaddr_in FromServer{};
|
||||
int clientLength = sizeof(FromServer);
|
||||
ZeroMemory(&FromServer, clientLength);
|
||||
ZeroMemory(buf, len);
|
||||
if(UDPSock == -1)return;
|
||||
int Rcv = recvfrom(UDPSock, buf, len, 0, (sockaddr*)&FromServer, &clientLength);
|
||||
if (Rcv == SOCKET_ERROR)return;
|
||||
std::string Ret(Rcv,0);
|
||||
memcpy_s(&Ret[0],Rcv,buf,Rcv);
|
||||
UDPParser(Ret);
|
||||
}
|
||||
void UDPClientMain(const std::string& IP,int Port){
|
||||
WSADATA data;
|
||||
if (WSAStartup(514, &data)){
|
||||
error(Sec("Can't start Winsock!"));
|
||||
return;
|
||||
}
|
||||
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);
|
||||
std::thread Ack(LOOP);
|
||||
Ack.detach();
|
||||
IDReset();
|
||||
TCPSend(Sec("P"));
|
||||
UDPSend(Sec("p"));
|
||||
while(!Terminate)UDPRcv();
|
||||
closesocket(UDPSock);
|
||||
WSACleanup();
|
||||
}
|
||||
92
src/Network/VehicleEvent.cpp
Normal file
92
src/Network/VehicleEvent.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 5/8/2020
|
||||
///
|
||||
|
||||
#include <chrono>
|
||||
#include "Logger.h"
|
||||
#include <iostream>
|
||||
#include <WS2tcpip.h>
|
||||
#include "Security/Enc.h"
|
||||
#include "Network/network.h"
|
||||
|
||||
SOCKET TCPSock;
|
||||
void TCPSend(const std::string&Data){
|
||||
if(TCPSock == -1){
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
int BytesSent = send(TCPSock, Data.c_str(), int(Data.length())+1, 0);
|
||||
if (BytesSent == 0){
|
||||
debug(Sec("(TCP) Connection closing..."));
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
else if (BytesSent < 0) {
|
||||
debug(Sec("(TCP) send failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
closesocket(TCPSock);
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ServerParser(const std::string& Data);
|
||||
void TCPRcv(){
|
||||
char buf[4096];
|
||||
int len = 4096;
|
||||
ZeroMemory(buf, len);
|
||||
if(TCPSock == -1){
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
int BytesRcv = recv(TCPSock, buf, len,0);
|
||||
if (BytesRcv == 0){
|
||||
debug(Sec("(TCP) Connection closing..."));
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
else if (BytesRcv < 0) {
|
||||
debug(Sec("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError()));
|
||||
closesocket(TCPSock);
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
ServerParser(std::string(buf));
|
||||
}
|
||||
|
||||
void SyncResources(SOCKET TCPSock);
|
||||
void TCPClientMain(const std::string& IP,int 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(Sec("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 = Sec("UlConnection Failed!");
|
||||
std::cout << Sec("Client: connect failed! Error code: ") << WSAGetLastError() << std::endl;
|
||||
closesocket(TCPSock);
|
||||
WSACleanup();
|
||||
Terminate = true;
|
||||
return;
|
||||
}
|
||||
getsockname(TCPSock, (SOCKADDR *)&ServerAddr, (int *)sizeof(ServerAddr));
|
||||
|
||||
SyncResources(TCPSock);
|
||||
while(!Terminate)TCPRcv();
|
||||
GameSend(Sec("T"));
|
||||
////Game Send Terminate
|
||||
if(closesocket(TCPSock) != 0)
|
||||
debug(Sec("(TCP) Cannot close socket. Error code: ") + std::to_string(WSAGetLastError()));
|
||||
|
||||
if(WSACleanup() != 0)
|
||||
debug(Sec("(TCP) Client: WSACleanup() failed!..."));
|
||||
}
|
||||
Reference in New Issue
Block a user