Server update 0.63.5

- async lua implementation
- cleaner backend heartbeat
- two way encryption on connect
- async tcp buffer
- disconnect handler
- cleaned UDP implementation
This commit is contained in:
Anonymous275 2020-10-16 17:05:31 +03:00
parent 31c96cee94
commit 71a84b4f1b
14 changed files with 314 additions and 169 deletions

42
include/Buffer.h Normal file
View File

@ -0,0 +1,42 @@
///
/// Created by Anonymous275 on 8/25/2020
///
#pragma once
#include <mutex>
class Client;
void GParser(Client*c, const std::string&Packet);
class Buffer{
public:
void Handle(Client*c,const std::string& Data){
if(c == nullptr)return;
Buf += Data;
Manage(c);
}
void clear(){
Buf.clear();
}
private:
std::string Buf;
void Manage(Client*c){
if(!Buf.empty()){
std::string::size_type p;
if (Buf.at(0) == '\n'){
p = Buf.find('\n',1);
if(p != -1){
std::string R = Buf.substr(1,p-1);
std::string_view B(R.c_str(),R.find(char(0)));
GParser(c, B.data());
Buf = Buf.substr(p+1);
Manage(c);
}
}else{
p = Buf.find('\n');
if(p == -1)Buf.clear();
else{
Buf = Buf.substr(p);
Manage(c);
}
}
}
}
};

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <WS2tcpip.h> #include <WS2tcpip.h>
#include "Buffer.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <chrono> #include <chrono>
@ -48,6 +49,7 @@ public:
int GetCarCount(); int GetCarCount();
void ClearCars(); void ClearCars();
int GetStatus(); int GetStatus();
Buffer Handler;
int GetID(); int GetID();
}; };
struct ClientInterface{ struct ClientInterface{

View File

@ -8,6 +8,7 @@
#include "lua.hpp" #include "lua.hpp"
#include <vector> #include <vector>
#include <thread> #include <thread>
#include <mutex>
#include <set> #include <set>
#include <any> #include <any>
namespace fs = std::experimental::filesystem; namespace fs = std::experimental::filesystem;
@ -50,17 +51,15 @@ public:
void SetPluginName(const std::string&Name); void SetPluginName(const std::string&Name);
void SetFileName(const std::string&Name); void SetFileName(const std::string&Name);
fs::file_time_type GetLastWrite(); fs::file_time_type GetLastWrite();
bool isThreadExecuting = false;
std::string GetPluginName(); std::string GetPluginName();
std::string GetFileName(); std::string GetFileName();
bool isExecuting = false;
bool StopThread = false; bool StopThread = false;
bool HasThread = false;
lua_State* GetState(); lua_State* GetState();
char* GetOrigin(); char* GetOrigin();
std::mutex Lock;
void Reload(); void Reload();
void Init(); void Init();
}; };
int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* args); int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* args);
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg); int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg,bool Wait);
extern std::set<Lua*> PluginEngine; extern std::set<Lua*> PluginEngine;

View File

@ -12,8 +12,8 @@ void SyncResources(Client*c);
[[noreturn]] void UDPServerMain(); [[noreturn]] void UDPServerMain();
void OnDisconnect(Client*c,bool kicked); void OnDisconnect(Client*c,bool kicked);
void UDPSend(Client*c,std::string Data); void UDPSend(Client*c,std::string Data);
void TCPSend(Client*c,const std::string&Data); void TCPSend(Client*c,const std::string& Data);
void SendLarge(Client*c,const std::string&Data); void SendLarge(Client*c,std::string Data);
void GParser(Client*c, const std::string&Packet); void GParser(Client*c, const std::string&Packet);
void Respond(Client*c, const std::string& MSG, bool Rel); void Respond(Client*c, const std::string& MSG, bool Rel);
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel); void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel);

View File

@ -10,6 +10,7 @@ struct RSA{
int e = 0; int e = 0;
int d = 0; int d = 0;
}; };
std::string RSA_E(const std::string& Data,int e, int n);
std::string RSA_E(const std::string& Data, RSA*k); std::string RSA_E(const std::string& Data, RSA*k);
std::string RSA_D(const std::string& Data, RSA*k); std::string RSA_D(const std::string& Data, RSA*k);
int Handle(EXCEPTION_POINTERS *ep,char* Origin); int Handle(EXCEPTION_POINTERS *ep,char* Origin);

View File

@ -100,7 +100,13 @@ std::string RSA_E(const std::string& Data, RSA*k){
} }
return stream.str(); return stream.str();
} }
std::string RSA_E(const std::string& Data,int e, int n){
std::stringstream stream;
for(const char&c : Data){
stream << std::hex << Enc(uint8_t(c),e,n) << "g";
}
return stream.str();
}
std::string RSA_D(const std::string& Data, RSA*k){ std::string RSA_D(const std::string& Data, RSA*k){
std::stringstream ss(Data); std::stringstream ss(Data);
std::string token,ret; std::string token,ret;

View File

@ -19,28 +19,28 @@ std::string GetPlayers(){
return Return; return Return;
} }
std::string GenerateCall(){ std::string GenerateCall(){
std::string State = Private ? Sec("true") : Sec("false"); std::string State = Private ? "true" : "false";
std::string ret = Sec("uuid="); std::string ret = "uuid=";
ret += Key+Sec("&players=")+std::to_string(CI->Size())+Sec("&maxplayers=")+std::to_string(MaxPlayers)+Sec("&port=") ret += Key+"&players="+std::to_string(CI->Size())+"&maxplayers="+std::to_string(MaxPlayers)+"&port="
+ std::to_string(Port) + Sec("&map=") + MapName + Sec("&private=")+State+Sec("&version=")+GetSVer()+ + std::to_string(Port) + "&map=" + MapName + "&private="+State+"&version="+GetSVer()+
Sec("&clientversion=")+GetCVer()+Sec("&name=")+ServerName+Sec("&pps=")+StatReport+Sec("&modlist=")+FileList+ "&clientversion="+GetCVer()+"&name="+ServerName+"&pps="+StatReport+"&modlist="+FileList+
Sec("&modstotalsize=")+std::to_string(MaxModSize)+Sec("&modstotal=")+std::to_string(ModsLoaded) "&modstotalsize="+std::to_string(MaxModSize)+"&modstotal="+std::to_string(ModsLoaded)
+Sec("&playerslist=")+GetPlayers()+Sec("&desc=")+ServerDesc; +"&playerslist="+GetPlayers()+"&desc="+ServerDesc;
return ret; return ret;
} }
void Heartbeat(){ void Heartbeat(){
std::string R,T; std::string R,T;
while(true){ while(true){
R = GenerateCall(); R = GenerateCall();
if(!CustomIP.empty())R+=Sec("&ip=")+CustomIP; if(!CustomIP.empty())R+="&ip="+CustomIP;
//https://beamng-mp.com/heartbeatv2 std::string link = Sec("https://beammp.com/heartbeatv2");
std::string link = Sec("https://beamng-mp.com/heartbeatv2");
T = PostHTTP(link,R); T = PostHTTP(link,R);
if(T.find_first_not_of(Sec("20")) != std::string::npos){ if(T.find_first_not_of(Sec("20")) != std::string::npos){
//Backend system refused server startup! //Backend system refused server startup!
std::this_thread::sleep_for(std::chrono::seconds(10)); std::this_thread::sleep_for(std::chrono::seconds(10));
T = PostHTTP(link,R); std::string Backup = Sec("https://backup1.beammp.com/heartbeatv2");
if(T.find_first_not_of(Sec("20")) != std::string::npos){ T = PostHTTP(Backup,R);
if(T.find_first_not_of(Sec("20")) != std::string::npos) {
error(Sec("Backend system refused server! Check your AuthKey")); error(Sec("Backend system refused server! Check your AuthKey"));
std::this_thread::sleep_for(std::chrono::seconds(3)); std::this_thread::sleep_for(std::chrono::seconds(3));
exit(-1); exit(-1);

View File

@ -8,10 +8,12 @@
std::string CustomIP; std::string CustomIP;
std::string GetSVer(){ std::string GetSVer(){
return Sec("0.60"); static std::string r = Sec("0.63.5");
return r;
} }
std::string GetCVer(){ std::string GetCVer(){
return Sec("1.60"); static std::string r = Sec("1.63");
return r;
} }
void Args(int argc, char* argv[]){ void Args(int argc, char* argv[]){
info(Sec("BeamMP Server Running version ") + GetSVer()); info(Sec("BeamMP Server Running version ") + GetSVer());

View File

@ -9,6 +9,7 @@
#include "Logger.h" #include "Logger.h"
#include <iostream> #include <iostream>
#include <future> #include <future>
#include <utility>
LuaArg* CreateArg(lua_State *L,int T,int S){ LuaArg* CreateArg(lua_State *L,int T,int S){
if(S > T)return nullptr; if(S > T)return nullptr;
@ -26,6 +27,9 @@ LuaArg* CreateArg(lua_State *L,int T,int S){
} }
return temp; return temp;
} }
void ClearStack(lua_State *L){
lua_settop(L,0);
}
Lua* GetScript(lua_State *L){ Lua* GetScript(lua_State *L){
for(Lua*Script : PluginEngine){ for(Lua*Script : PluginEngine){
if (Script->GetState() == L)return Script; if (Script->GetState() == L)return Script;
@ -35,33 +39,41 @@ Lua* GetScript(lua_State *L){
void SendError(lua_State *L,const std::string&msg){ void SendError(lua_State *L,const std::string&msg){
Lua* S = GetScript(L); Lua* S = GetScript(L);
std::string a = S->GetFileName().substr(S->GetFileName().find('\\')); std::string a = S->GetFileName().substr(S->GetFileName().find('\\'));
warn(a + Sec(" | Incorrect Call of ") +msg); warn(a + Sec(" | Incorrect Call of ") + msg);
} }
int Trigger(Lua*lua,const std::string& R, LuaArg*arg){ int Trigger(Lua*lua,const std::string& R, LuaArg*arg){
std::lock_guard<std::mutex> lockGuard(lua->Lock);
std::packaged_task<int()> task([lua,R,arg]{return CallFunction(lua,R,arg);}); std::packaged_task<int()> task([lua,R,arg]{return CallFunction(lua,R,arg);});
std::future<int> f1 = task.get_future(); std::future<int> f1 = task.get_future();
std::thread t(std::move(task)); std::thread t(std::move(task));
t.detach(); t.detach();
auto status = f1.wait_for(std::chrono::seconds(3)); auto status = f1.wait_for(std::chrono::seconds(5));
if(status != std::future_status::timeout)return f1.get(); if(status != std::future_status::timeout)return f1.get();
SendError(lua->GetState(),R + " took too long to respond"); SendError(lua->GetState(),R + " took too long to respond");
return 0; return 0;
} }
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg){ int FutureWait(Lua*lua,const std::string& R, LuaArg*arg,bool Wait){
std::packaged_task<int()> task([lua,R,arg]{return Trigger(lua,R,arg);});
std::future<int> f1 = task.get_future();
std::thread t(std::move(task));
t.detach();
int T = 0;
if(Wait)T = 6;
auto status = f1.wait_for(std::chrono::seconds(T));
if(status != std::future_status::timeout)return f1.get();
return 0;
}
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg,bool Wait){
int R = 0; int R = 0;
for(Lua*Script : PluginEngine){ for(Lua*Script : PluginEngine){
if(Script->IsRegistered(Event)){ if(Script->IsRegistered(Event)){
if(local){ if(local){
if (Script->GetPluginName() == Caller->GetPluginName()){ if (Script->GetPluginName() == Caller->GetPluginName()){
R += Trigger(Script,Script->GetRegistered(Event),arg); R += FutureWait(Script,Script->GetRegistered(Event),arg,Wait);
} }
}else R += Trigger(Script,Script->GetRegistered(Event), arg); }else R += FutureWait(Script,Script->GetRegistered(Event), arg,Wait);
} }
} }
if(arg != nullptr){
delete arg;
arg = nullptr;
}
return R; return R;
} }
@ -70,7 +82,7 @@ bool CheckLua(lua_State *L, int r){
std::string msg = lua_tostring(L, -1); std::string msg = lua_tostring(L, -1);
Lua * S = GetScript(L); Lua * S = GetScript(L);
std::string a = S->GetFileName().substr(S->GetFileName().find('\\')); std::string a = S->GetFileName().substr(S->GetFileName().find('\\'));
warn(a + " | at line " + msg.substr(msg.find(':')+1)); warn(a + " | " + msg);
return false; return false;
} }
return true; return true;
@ -89,7 +101,7 @@ int lua_TriggerEventL(lua_State *L){
Lua* Script = GetScript(L); Lua* Script = GetScript(L);
if(Args > 0){ if(Args > 0){
if(lua_isstring(L,1)){ if(lua_isstring(L,1)){
TriggerLuaEvent(lua_tostring(L, 1), true, Script, CreateArg(L,Args,2)); TriggerLuaEvent(lua_tostring(L, 1), true, Script, CreateArg(L,Args,2),false);
}else SendError(L,Sec("TriggerLocalEvent wrong argument [1] need string")); }else SendError(L,Sec("TriggerLocalEvent wrong argument [1] need string"));
}else{ }else{
SendError(L,Sec("TriggerLocalEvent not enough arguments expected 1 got 0")); SendError(L,Sec("TriggerLocalEvent not enough arguments expected 1 got 0"));
@ -102,7 +114,7 @@ int lua_TriggerEventG(lua_State *L){
Lua* Script = GetScript(L); Lua* Script = GetScript(L);
if(Args > 0){ if(Args > 0){
if(lua_isstring(L,1)) { if(lua_isstring(L,1)) {
TriggerLuaEvent(lua_tostring(L, 1), false, Script, CreateArg(L,Args,2)); TriggerLuaEvent(lua_tostring(L, 1), false, Script, CreateArg(L,Args,2),false);
}else SendError(L,Sec("TriggerGlobalEvent wrong argument [1] need string")); }else SendError(L,Sec("TriggerGlobalEvent wrong argument [1] need string"));
}else SendError(L,Sec("TriggerGlobalEvent not enough arguments")); }else SendError(L,Sec("TriggerGlobalEvent not enough arguments"));
return 0; return 0;
@ -110,24 +122,12 @@ int lua_TriggerEventG(lua_State *L){
char* ThreadOrigin(Lua*lua){ char* ThreadOrigin(Lua*lua){
std::string T = "Thread in " + lua->GetFileName().substr(lua->GetFileName().find('\\')); std::string T = "Thread in " + lua->GetFileName().substr(lua->GetFileName().find('\\'));
char* Data = new char[T.size()]; char* Data = new char[T.size()+1];
ZeroMemory(Data,T.size()); ZeroMemory(Data,T.size()+1);
memcpy_s(Data,T.size(),T.c_str(),T.size()); memcpy_s(Data,T.size(),T.c_str(),T.size());
return Data; return Data;
} }
void SafeExecution(Lua* lua,const std::string& FuncName){
void Lock(Lua* lua,bool thread){
bool Lock;
do{
if(thread){
Lock = lua->isExecuting;
}else Lock = lua->isThreadExecuting;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}while(Lock);
}
void ExecuteAsync(Lua* lua,const std::string& FuncName){
Lock(lua,true);
lua->isThreadExecuting = true;
lua_State* luaState = lua->GetState(); lua_State* luaState = lua->GetState();
lua_getglobal(luaState, FuncName.c_str()); lua_getglobal(luaState, FuncName.c_str());
if(lua_isfunction(luaState, -1)) { if(lua_isfunction(luaState, -1)) {
@ -138,21 +138,20 @@ void ExecuteAsync(Lua* lua,const std::string& FuncName){
}__except(Handle(GetExceptionInformation(),Origin)){} }__except(Handle(GetExceptionInformation(),Origin)){}
delete [] Origin; delete [] Origin;
} }
lua->isThreadExecuting = false; ClearStack(luaState);
}
void ExecuteAsync(Lua* lua,const std::string& FuncName){
std::lock_guard<std::mutex> lockGuard(lua->Lock);
SafeExecution(lua,FuncName);
} }
void CallAsync(Lua* lua,const std::string& Func,int U){ void CallAsync(Lua* lua,const std::string& Func,int U){
if(lua->HasThread){
SendError(lua->GetState(),Sec("CreateThread : There is already a thread running!"));
return;
}
lua->StopThread = false; lua->StopThread = false;
lua->HasThread = true;
int D = 1000 / U; int D = 1000 / U;
while(!lua->StopThread){ while(!lua->StopThread){
ExecuteAsync(lua,Func); ExecuteAsync(lua,Func);
std::this_thread::sleep_for(std::chrono::milliseconds(D)); std::this_thread::sleep_for(std::chrono::milliseconds(D));
} }
lua->HasThread = false;
} }
int lua_StopThread(lua_State *L){ int lua_StopThread(lua_State *L){
GetScript(L)->StopThread = true; GetScript(L)->StopThread = true;
@ -329,10 +328,43 @@ int lua_HWID(lua_State *L){
lua_pushinteger(L, -1); lua_pushinteger(L, -1);
return 1; return 1;
} }
int lua_RemoteEvent(lua_State *L){
int Args = lua_gettop(L);
if(Args != 3){
SendError(L,Sec("TriggerClientEvent invalid argument count expected 3 got ") + std::to_string(Args));
return 0;
}
if(!lua_isnumber(L,1)){
SendError(L,Sec("TriggerClientEvent invalid argument [1] expected number"));
return 0;
}
if(!lua_isstring(L,2)){
SendError(L,Sec("TriggerClientEvent invalid argument [2] expected string"));
return 0;
}
if(!lua_isstring(L,3)){
SendError(L,Sec("TriggerClientEvent invalid argument [3] expected string"));
return 0;
}
int ID = int(lua_tointeger(L,1));
std::string Packet = "E:" + std::string(lua_tostring(L,2)) + ":" + std::string(lua_tostring(L,3));
if(ID == -1){
SendToAll(nullptr,Packet,true,true);
}else{
Client *c = GetClient(ID);
if(c == nullptr){
SendError(L,Sec("TriggerClientEvent invalid Player ID"));
return 0;
}
Respond(c,Packet,true);
}
return 0;
}
void Lua::Init(){ void Lua::Init(){
luaL_openlibs(luaState); luaL_openlibs(luaState);
lua_register(luaState,"TriggerGlobalEvent",lua_TriggerEventG); lua_register(luaState,"TriggerGlobalEvent",lua_TriggerEventG);
lua_register(luaState,"TriggerLocalEvent",lua_TriggerEventL); lua_register(luaState,"TriggerLocalEvent",lua_TriggerEventL);
lua_register(luaState,"TriggerClientEvent",lua_RemoteEvent);
lua_register(luaState,"GetPlayerCount",lua_GetPlayerCount); lua_register(luaState,"GetPlayerCount",lua_GetPlayerCount);
lua_register(luaState,"isPlayerConnected",lua_isConnected); lua_register(luaState,"isPlayerConnected",lua_isConnected);
lua_register(luaState,"RegisterEvent",lua_RegisterEvent); lua_register(luaState,"RegisterEvent",lua_RegisterEvent);
@ -352,7 +384,7 @@ void Lua::Init(){
void Lua::Reload(){ void Lua::Reload(){
if(CheckLua(luaState,luaL_dofile(luaState,FileName.c_str()))){ if(CheckLua(luaState,luaL_dofile(luaState,FileName.c_str()))){
CallFunction(this,Sec("onInit"),{}); CallFunction(this,Sec("onInit"), nullptr);
} }
} }
char* Lua::GetOrigin(){ char* Lua::GetOrigin(){
@ -363,8 +395,6 @@ char* Lua::GetOrigin(){
return Data; return Data;
} }
int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){ int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){
Lock(lua,false);
lua->isExecuting = true;
lua_State*luaState = lua->GetState(); lua_State*luaState = lua->GetState();
lua_getglobal(luaState, FuncName.c_str()); lua_getglobal(luaState, FuncName.c_str());
if(lua_isfunction(luaState, -1)) { if(lua_isfunction(luaState, -1)) {
@ -372,6 +402,8 @@ int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){
if(Arg != nullptr){ if(Arg != nullptr){
Size = int(Arg->args.size()); Size = int(Arg->args.size());
Arg->PushArgs(luaState); Arg->PushArgs(luaState);
delete Arg;
Arg = nullptr;
} }
int R = 0; int R = 0;
char* Origin = lua->GetOrigin(); char* Origin = lua->GetOrigin();
@ -385,7 +417,7 @@ int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){
}__except(Handle(GetExceptionInformation(),Origin)){} }__except(Handle(GetExceptionInformation(),Origin)){}
delete [] Origin; delete [] Origin;
} }
lua->isExecuting = false; ClearStack(luaState);
return 0; return 0;
} }
void Lua::SetPluginName(const std::string&Name){ void Lua::SetPluginName(const std::string&Name){

View File

@ -29,8 +29,10 @@ std::string Rcv(SOCKET TCPSock){
} }
std::string GetRole(const std::string &DID){ std::string GetRole(const std::string &DID){
if(!DID.empty()){ if(!DID.empty()){
std::string a = HttpRequest(Sec("https://beamng-mp.com/entitlement?did=")+DID,443); std::string a = HttpRequest(Sec("https://beammp.com/entitlement?did=")+DID,443);
if(!a.empty()){ std::string b = HttpRequest(Sec("https://backup1.beammp.com/entitlement?did=")+DID,443);
if(!a.empty() || !b.empty()){
if(a != b)a = b;
auto pos = a.find('"'); auto pos = a.find('"');
if(pos != std::string::npos){ if(pos != std::string::npos){
return a.substr(pos+1,a.find('"',pos+1)-2); return a.substr(pos+1,a.find('"',pos+1)-2);
@ -63,26 +65,46 @@ void CreateClient(SOCKET TCPSock,const std::string &Name, const std::string &DID
CI->AddClient(c); CI->AddClient(c);
InitClient(c); InitClient(c);
} }
std::pair<int,int> Parse(const std::string& msg){
std::stringstream ss(msg);
std::string t;
std::pair<int,int> a = {0,0}; //N then E
while (std::getline(ss, t, 'g')) {
if(t.find_first_not_of(Sec("0123456789abcdef")) != std::string::npos)return a;
if(a.first == 0){
a.first = std::stoi(t, nullptr, 16);
}else if(a.second == 0){
a.second = std::stoi(t, nullptr, 16);
}else return a;
}
return {0,0};
}
std::string GenerateM(RSA*key){ std::string GenerateM(RSA*key){
std::stringstream stream; std::stringstream stream;
stream << std::hex << key->n << "g" << key->e << "g" << RSA_E(Sec("IDC"),key); stream << std::hex << key->n << "g" << key->e << "g" << RSA_E(Sec("IDC"),key);
return stream.str(); return stream.str();
} }
void Identification(SOCKET TCPSock,Hold*S,RSA*key){ void Identification(SOCKET TCPSock,Hold*S,RSA*Skey){
S->TCPSock = TCPSock; S->TCPSock = TCPSock;
std::thread Timeout(Check,S); std::thread Timeout(Check,S);
Timeout.detach(); Timeout.detach();
std::string Name,DID,Role; std::string Name,DID,Role;
if(!Send(TCPSock,GenerateM(key))){ if(!Send(TCPSock,GenerateM(Skey))){
closesocket(TCPSock); closesocket(TCPSock);
return; return;
} }
std::string msg = Rcv(TCPSock);
auto Keys = Parse(msg);
if(!Send(TCPSock,RSA_E("HC",Keys.second,Keys.first))){
closesocket(TCPSock);
return;
}
std::string Res = Rcv(TCPSock); std::string Res = Rcv(TCPSock);
std::string Ver = Rcv(TCPSock); std::string Ver = Rcv(TCPSock);
S->Done = true; S->Done = true;
Ver = RSA_D(Ver,key); Ver = RSA_D(Ver,Skey);
if(Ver.size() > 3 && Ver.substr(0,2) == Sec("VC")){ if(Ver.size() > 3 && Ver.substr(0,2) == Sec("VC")){
Ver = Ver.substr(2); Ver = Ver.substr(2);
if(Ver.length() > 4 || Ver != GetCVer()){ if(Ver.length() > 4 || Ver != GetCVer()){
@ -93,7 +115,7 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*key){
closesocket(TCPSock); closesocket(TCPSock);
return; return;
} }
Res = RSA_D(Res,key); Res = RSA_D(Res,Skey);
if(Res.size() < 3 || Res.substr(0,2) != Sec("NR")) { if(Res.size() < 3 || Res.substr(0,2) != Sec("NR")) {
closesocket(TCPSock); closesocket(TCPSock);
return; return;
@ -125,11 +147,15 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*key){
} }
void Identify(SOCKET TCPSock){ void Identify(SOCKET TCPSock){
auto* S = new Hold; auto* S = new Hold;
RSA*key = GenKey(); RSA*Skey = GenKey();
__try{ __try{
Identification(TCPSock,S,key); Identification(TCPSock,S,Skey);
}__except(1){} }__except(1){
delete key; if(TCPSock != -1){
closesocket(TCPSock);
}
}
delete Skey;
delete S; delete S;
} }
void TCPServerMain(){ void TCPServerMain(){

View File

@ -7,6 +7,7 @@
#include "Settings.h" #include "Settings.h"
#include "Network.h" #include "Network.h"
#include "Logger.h" #include "Logger.h"
#include <sstream>
int FC(const std::string& s,const std::string& p,int n) { int FC(const std::string& s,const std::string& p,int n) {
auto i = s.find(p); auto i = s.find(p);
@ -42,7 +43,7 @@ void VehicleParser(Client*c,const std::string& Pckt){
Packet = "Os:"+c->GetRole()+":"+c->GetName()+":"+std::to_string(c->GetID())+"-"+std::to_string(CarID)+Packet.substr(4); Packet = "Os:"+c->GetRole()+":"+c->GetName()+":"+std::to_string(c->GetID())+"-"+std::to_string(CarID)+Packet.substr(4);
if(c->GetCarCount() >= MaxCars || if(c->GetCarCount() >= MaxCars ||
TriggerLuaEvent(Sec("onVehicleSpawn"),false,nullptr, TriggerLuaEvent(Sec("onVehicleSpawn"),false,nullptr,
new LuaArg{{c->GetID(),CarID,Packet.substr(3)}})){ new LuaArg{{c->GetID(),CarID,Packet.substr(3)}},true)){
Respond(c,Packet,true); Respond(c,Packet,true);
std::string Destroy = "Od:" + std::to_string(c->GetID())+"-"+std::to_string(CarID); std::string Destroy = "Od:" + std::to_string(c->GetID())+"-"+std::to_string(CarID);
Respond(c,Destroy,true); Respond(c,Destroy,true);
@ -62,7 +63,7 @@ void VehicleParser(Client*c,const std::string& Pckt){
} }
if(PID != -1 && VID != -1 && PID == c->GetID()){ if(PID != -1 && VID != -1 && PID == c->GetID()){
if(!TriggerLuaEvent(Sec("onVehicleEdited"),false,nullptr, if(!TriggerLuaEvent(Sec("onVehicleEdited"),false,nullptr,
new LuaArg{{c->GetID(),VID,Packet.substr(3)}})) { new LuaArg{{c->GetID(),VID,Packet.substr(3)}},true)) {
SendToAll(c, Packet, false, true); SendToAll(c, Packet, false, true);
Apply(c,VID,Packet); Apply(c,VID,Packet);
}else{ }else{
@ -82,7 +83,7 @@ void VehicleParser(Client*c,const std::string& Pckt){
if(PID != -1 && VID != -1 && PID == c->GetID()){ if(PID != -1 && VID != -1 && PID == c->GetID()){
SendToAll(nullptr,Packet,true,true); SendToAll(nullptr,Packet,true,true);
TriggerLuaEvent(Sec("onVehicleDeleted"),false,nullptr, TriggerLuaEvent(Sec("onVehicleDeleted"),false,nullptr,
new LuaArg{{c->GetID(),VID}}); new LuaArg{{c->GetID(),VID}},false);
c->DeleteCar(VID); c->DeleteCar(VID);
debug(c->GetName() + Sec(" deleted car with ID ") + std::to_string(VID)); debug(c->GetName() + Sec(" deleted car with ID ") + std::to_string(VID));
} }
@ -96,19 +97,23 @@ void VehicleParser(Client*c,const std::string& Pckt){
} }
void SyncClient(Client*c){ void SyncClient(Client*c){
if(c->isSynced)return; if(c->isSynced)return;
c->isSynced = true;
std::this_thread::sleep_for(std::chrono::seconds(1));
Respond(c,Sec("Sn")+c->GetName(),true); Respond(c,Sec("Sn")+c->GetName(),true);
SendToAll(c,Sec("JWelcome ")+c->GetName()+"!",false,true); SendToAll(c,Sec("JWelcome ")+c->GetName()+"!",false,true);
TriggerLuaEvent(Sec("onPlayerJoin"),false,nullptr,new LuaArg{{c->GetID()}}); TriggerLuaEvent(Sec("onPlayerJoin"),false,nullptr,new LuaArg{{c->GetID()}},false);
for (Client*client : CI->Clients) { for (Client*client : CI->Clients) {
if(client != nullptr){ if(client != nullptr){
if (client != c) { if (client != c) {
for (VData *v : client->GetAllCars()) { for (VData *v : client->GetAllCars()) {
Respond(c, v->Data, true); if(v != nullptr){
Respond(c, v->Data, true);
std::this_thread::sleep_for(std::chrono::seconds(2));
}
} }
} }
} }
} }
c->isSynced = true;
info(c->GetName() + Sec(" is now synced!")); info(c->GetName() + Sec(" is now synced!"));
} }
void ParseVeh(Client*c, const std::string&Packet){ void ParseVeh(Client*c, const std::string&Packet){
@ -117,9 +122,30 @@ void ParseVeh(Client*c, const std::string&Packet){
}__except(Handle(GetExceptionInformation(),Sec("Vehicle Handler"))){} }__except(Handle(GetExceptionInformation(),Sec("Vehicle Handler"))){}
} }
void GlobalParser(Client*c, const std::string& Packet){ void HandleEvent(Client*c ,const std::string&Data){
std::stringstream ss(Data);
std::string t,Name;
int a = 0;
while (std::getline(ss, t, ':')) {
switch(a){
case 1:
Name = t;
break;
case 2:
TriggerLuaEvent(Name, false, nullptr,new LuaArg{{c->GetID(),t}},false);
break;
default:
break;
}
if(a == 2)break;
a++;
}
}
void GlobalParser(Client*c, const std::string& Pack){
static int lastRecv = 0; static int lastRecv = 0;
if(Packet.empty() || c == nullptr)return; if(Pack.empty() || c == nullptr)return;
std::string Packet = Pack.substr(0,Pack.find(char(0)));
std::string pct; std::string pct;
char Code = Packet.at(0); char Code = Packet.at(0);
@ -150,14 +176,13 @@ void GlobalParser(Client*c, const std::string& Packet){
return; return;
case 'C': case 'C':
if(Packet.length() < 4 || Packet.find(':', 3) == -1)break; if(Packet.length() < 4 || Packet.find(':', 3) == -1)break;
pct = "C:" + c->GetName() + Packet.substr(Packet.find(':', 3)); if (TriggerLuaEvent(Sec("onChatMessage"), false, nullptr,new LuaArg{
if (TriggerLuaEvent(Sec("onChatMessage"), false, nullptr, {c->GetID(), c->GetName(), Packet.substr(Packet.find(':', 3) + 1)}
new LuaArg{{c->GetID(), c->GetName(), pct.substr(pct.find(':', 3) + 1)}}))break; },true))break;
SendToAll(nullptr, pct, true, true); SendToAll(nullptr, Packet, true, true);
pct.clear();
return; return;
case 'E': case 'E':
SendToAll(nullptr,Packet,true,true); HandleEvent(c,Packet);
return; return;
default: default:
return; return;

View File

@ -25,7 +25,7 @@ int OpenID(){
} }
void Respond(Client*c, const std::string& MSG, bool Rel){ void Respond(Client*c, const std::string& MSG, bool Rel){
char C = MSG.at(0); char C = MSG.at(0);
if(Rel){ if(Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E'){
if(C == 'O' || C == 'T' || MSG.length() > 1000)SendLarge(c,MSG); if(C == 'O' || C == 'T' || MSG.length() > 1000)SendLarge(c,MSG);
else TCPSend(c,MSG); else TCPSend(c,MSG);
}else UDPSend(c,MSG); }else UDPSend(c,MSG);
@ -35,9 +35,10 @@ void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel){
for(Client*client : CI->Clients){ for(Client*client : CI->Clients){
if(client != nullptr) { if(client != nullptr) {
if (Self || client != c) { if (Self || client != c) {
if (client->isSynced) { if (client->isSynced || (C == 'O' && Data.at(1) == 's')) {
if (Rel) { if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') {
if (C == 'O' || C == 'T' || Data.length() > 1000)SendLarge(client, Data); if (C == 'O' || C == 'T' ||
Data.length() > 1000)SendLarge(client, Data);
else TCPSend(client, Data); else TCPSend(client, Data);
} else UDPSend(client, Data); } else UDPSend(client, Data);
} }
@ -54,6 +55,7 @@ void UpdatePlayers(){
SendToAll(nullptr, Packet,true,true); SendToAll(nullptr, Packet,true,true);
} }
void OnDisconnect(Client*c,bool kicked){ void OnDisconnect(Client*c,bool kicked){
info(c->GetName() + Sec(" Connection Terminated"));
if(c == nullptr)return; if(c == nullptr)return;
std::string Packet; std::string Packet;
for(VData*v : c->GetAllCars()){ for(VData*v : c->GetAllCars()){
@ -66,17 +68,18 @@ void OnDisconnect(Client*c,bool kicked){
Packet = Sec("L")+c->GetName()+Sec(" Left the server!"); Packet = Sec("L")+c->GetName()+Sec(" Left the server!");
SendToAll(c, Packet,false,true); SendToAll(c, Packet,false,true);
Packet.clear(); Packet.clear();
TriggerLuaEvent(Sec("onPlayerDisconnect"),false,nullptr,new LuaArg{{c->GetID()}}); TriggerLuaEvent(Sec("onPlayerDisconnect"),false,nullptr,new LuaArg{{c->GetID()}},false);
c->ClearCars(); c->ClearCars();
CI->RemoveClient(c); ///Removes the Client from existence CI->RemoveClient(c); ///Removes the Client from existence
} }
void OnConnect(Client*c){ void OnConnect(Client*c){
info(Sec("Client connected"));
c->SetID(OpenID()); c->SetID(OpenID());
info(Sec("Assigned ID ") + std::to_string(c->GetID()) + Sec(" to ") + c->GetName()); info(Sec("Assigned ID ") + std::to_string(c->GetID()) + Sec(" to ") + c->GetName());
TriggerLuaEvent(Sec("onPlayerConnecting"),false,nullptr,new LuaArg{{c->GetID()}}); TriggerLuaEvent(Sec("onPlayerConnecting"),false,nullptr,new LuaArg{{c->GetID()}},false);
SyncResources(c); SyncResources(c);
if(c->GetStatus() < 0)return; if(c->GetStatus() < 0)return;
Respond(c,"M"+MapName,true); //Send the Map on connect Respond(c,"M"+MapName,true); //Send the Map on connect
info(c->GetName() + Sec(" : Connected")); info(c->GetName() + Sec(" : Connected"));
TriggerLuaEvent(Sec("onPlayerJoining"),false,nullptr,new LuaArg{{c->GetID()}}); TriggerLuaEvent(Sec("onPlayerJoining"),false,nullptr,new LuaArg{{c->GetID()}},false);
} }

View File

@ -8,16 +8,24 @@
void TCPSend(Client*c,const std::string&Data){ void TCPSend(Client*c,const std::string&Data){
if(c == nullptr)return; if(c == nullptr)return;
int BytesSent = send(c->GetTCPSock(), Data.c_str(), int(Data.length())+1, 0); std::string Send = "\n" + Data.substr(0,Data.find(char(0))) + "\n";
if (BytesSent == 0){ size_t Sent = send(c->GetTCPSock(), Send.c_str(), int(Send.size()), 0);
if (Sent == 0){
if(c->GetStatus() > -1)c->SetStatus(-1); if(c->GetStatus() > -1)c->SetStatus(-1);
}else if (BytesSent < 0) { }else if (Sent < 0) {
if(c->GetStatus() > -1)c->SetStatus(-1); if(c->GetStatus() > -1)c->SetStatus(-1);
closesocket(c->GetTCPSock()); closesocket(c->GetTCPSock());
} }
} }
void TCPHandle(Client*c,const std::string& data){
__try{
c->Handler.Handle(c,data);
}__except(1){
c->Handler.clear();
}
}
void TCPRcv(Client*c){ void TCPRcv(Client*c){
if(c == nullptr)return; if(c == nullptr || c->GetStatus() < 0)return;
char buf[4096]; char buf[4096];
int len = 4096; int len = 4096;
ZeroMemory(buf, len); ZeroMemory(buf, len);
@ -33,18 +41,18 @@ void TCPRcv(Client*c){
return; return;
} }
std::string Buf(buf,BytesRcv); std::string Buf(buf,BytesRcv);
GParser(c, Buf); TCPHandle(c,Buf);
} }
void TCPClient(Client*c){ void TCPClient(Client*c){
if(c->GetTCPSock() == -1){ if(c->GetTCPSock() == -1){
CI->RemoveClient(c); CI->RemoveClient(c);
return; return;
} }
info(Sec("Client connected"));
OnConnect(c); OnConnect(c);
while (c->GetStatus() > -1)TCPRcv(c); while (c->GetStatus() > -1)TCPRcv(c);
info(c->GetName() + Sec(" Connection Terminated")); __try{
OnDisconnect(c, c->GetStatus() == -2); OnDisconnect(c, c->GetStatus() == -2);
}__except(Handle(GetExceptionInformation(),Sec("OnDisconnect"))){}
} }
void InitClient(Client*c){ void InitClient(Client*c){
std::thread NewClient(TCPClient,c); std::thread NewClient(TCPClient,c);

View File

@ -8,9 +8,11 @@
#include "Settings.h" #include "Settings.h"
#include "Network.h" #include "Network.h"
#include "Logger.h" #include "Logger.h"
#include <sstream>
#include <vector> #include <vector>
#include <thread>
#include <array> #include <array>
int FC(const std::string& s,const std::string& p,int n);
struct PacketData{ struct PacketData{
int ID; int ID;
Client* Client; Client* Client;
@ -30,11 +32,11 @@ void UDPSend(Client*c,std::string Data){
if(c == nullptr || !c->isConnected || c->GetStatus() < 0)return; if(c == nullptr || !c->isConnected || c->GetStatus() < 0)return;
sockaddr_in Addr = c->GetUDPAddr(); sockaddr_in Addr = c->GetUDPAddr();
int AddrSize = sizeof(c->GetUDPAddr()); int AddrSize = sizeof(c->GetUDPAddr());
Data = Data.substr(0,Data.find(char(0)));
if(Data.length() > 400){ if(Data.length() > 400){
std::string CMP(Comp(Data)); std::string CMP(Comp(Data));
Data = "ABG:" + CMP; Data = "ABG:" + CMP;
} }
int sendOk = sendto(UDPSock, Data.c_str(), int(Data.size()), 0, (sockaddr *) &Addr, AddrSize); int sendOk = sendto(UDPSock, Data.c_str(), int(Data.size()), 0, (sockaddr *) &Addr, AddrSize);
if (sendOk == SOCKET_ERROR) { if (sendOk == SOCKET_ERROR) {
debug(Sec("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError())); debug(Sec("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError()));
@ -44,7 +46,7 @@ void UDPSend(Client*c,std::string Data){
void AckID(int ID){ void AckID(int ID){
for(PacketData* p : DataAcks){ for(PacketData* p : DataAcks){
if(p->ID == ID){ if(p != nullptr && p->ID == ID){
DataAcks.erase(p); DataAcks.erase(p);
break; break;
} }
@ -62,7 +64,8 @@ int SplitID(){
else SID++; else SID++;
return SID; return SID;
} }
void SendLarge(Client*c,const std::string&Data){ void SendLarge(Client*c,std::string Data){
Data = Data.substr(0,Data.find(char(0)));
int ID = PacktID(); int ID = PacktID();
std::string Packet; std::string Packet;
if(Data.length() > 1000){ if(Data.length() > 1000){
@ -70,16 +73,16 @@ void SendLarge(Client*c,const std::string&Data){
int S = 1,Split = int(ceil(float(pckt.length()) / 1000)); int S = 1,Split = int(ceil(float(pckt.length()) / 1000));
int SID = SplitID(); int SID = SplitID();
while(pckt.length() > 1000){ while(pckt.length() > 1000){
Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+std::to_string(ID)+"|"+ Packet = "SC|"+std::to_string(S)+"|"+std::to_string(Split)+"|"+std::to_string(ID)+"|"+
std::to_string(SID)+":"+pckt.substr(0,1000); std::to_string(SID)+"|"+pckt.substr(0,1000);
DataAcks.insert(new PacketData{ID,c,Packet,1}); DataAcks.insert(new PacketData{ID,c,Packet,1});
UDPSend(c,Packet); UDPSend(c,Packet);
pckt = pckt.substr(1000); pckt = pckt.substr(1000);
S++; S++;
ID = PacktID(); ID = PacktID();
} }
Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+ Packet = "SC|"+std::to_string(S)+"|"+std::to_string(Split)+"|"+
std::to_string(ID)+"|"+std::to_string(SID)+":"+pckt; std::to_string(ID)+"|"+std::to_string(SID)+"|"+pckt;
DataAcks.insert(new PacketData{ID,c,Packet,1}); DataAcks.insert(new PacketData{ID,c,Packet,1});
UDPSend(c,Packet); UDPSend(c,Packet);
}else{ }else{
@ -90,12 +93,12 @@ void SendLarge(Client*c,const std::string&Data){
} }
struct HandledC{ struct HandledC{
int Pos = 0; int Pos = 0;
Client *c{}; Client *c = nullptr;
std::array<int, 50> HandledIDs{}; std::array<int, 100> HandledIDs = {-1};
}; };
std::set<HandledC*> HandledIDs; std::set<HandledC*> HandledIDs;
void ResetIDs(HandledC*H){ void ResetIDs(HandledC*H){
for(int C = 0;C < 50;C++){ for(int C = 0;C < 100;C++){
H->HandledIDs.at(C) = -1; H->HandledIDs.at(C) = -1;
} }
} }
@ -114,7 +117,7 @@ bool Handled(Client*c,int ID){
for(int id : h->HandledIDs){ for(int id : h->HandledIDs){
if(id == ID)return true; if(id == ID)return true;
} }
if(h->Pos > 49)h->Pos = 0; if(h->Pos > 99)h->Pos = 0;
h->HandledIDs.at(h->Pos) = ID; h->HandledIDs.at(h->Pos) = ID;
h->Pos++; h->Pos++;
handle = true; handle = true;
@ -129,7 +132,7 @@ bool Handled(Client*c,int ID){
if(!handle){ if(!handle){
HandledC *h = GetHandled(c); HandledC *h = GetHandled(c);
ResetIDs(h); ResetIDs(h);
if (h->Pos > 49)h->Pos = 0; if (h->Pos > 99)h->Pos = 0;
h->HandledIDs.at(h->Pos) = ID; h->HandledIDs.at(h->Pos) = ID;
h->Pos++; h->Pos++;
h->c = c; h->c = c;
@ -138,17 +141,14 @@ bool Handled(Client*c,int ID){
return false; return false;
} }
std::string UDPRcvFromClient(sockaddr_in& client){ std::string UDPRcvFromClient(sockaddr_in& client){
char buf[10240];
int clientLength = sizeof(client); int clientLength = sizeof(client);
ZeroMemory(&client, clientLength); ZeroMemory(&client, clientLength);
ZeroMemory(buf, 10240); std::string Ret(10240,0);
int Rcv = recvfrom(UDPSock, buf, 10240, 0, (sockaddr*)&client, &clientLength); int Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&client, &clientLength);
if (Rcv == -1){ if (Rcv == -1){
error(Sec("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError())); error(Sec("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError()));
return ""; return "";
} }
std::string Ret(Rcv,0);
memcpy_s(&Ret[0],Rcv,buf,Rcv);
return Ret; return Ret;
} }
@ -161,22 +161,27 @@ SplitData*GetSplit(int SplitID){
return SP; return SP;
} }
void HandleChunk(Client*c,const std::string&Data){ void HandleChunk(Client*c,const std::string&Data){
int pos1 = int(Data.find(':'))+1, int pos = FC(Data,"|",5);
pos2 = int(Data.find(':',pos1)), if(pos == -1)return;
pos3 = int(Data.find('/')), std::stringstream ss(Data.substr(0,pos++));
pos4 = int(Data.find('|')); std::string t;
if(pos1 == std::string::npos)return; int I = -1;
int Max = stoi(Data.substr(pos3+1,pos1-pos3-2)); //Current Max ID SID
int Current = stoi(Data.substr(2,pos3-2)); std::vector<int> Num(4,0);
int ID = stoi(Data.substr(pos1,pos4-pos1)); while (std::getline(ss, t, '|')) {
int SplitID = stoi(Data.substr(pos4+1,pos2-pos4-1)); if(I != -1)Num.at(I) = std::stoi(t);
std::string ack = Sec("TRG:") + Data.substr(pos1,pos4-pos1); I++;
}
std::string ack = "TRG:" + std::to_string(Num.at(2));
UDPSend(c,ack); UDPSend(c,ack);
if(Handled(c,ID))return; if(Handled(c,Num.at(2))){
SplitData* SData = GetSplit(SplitID); return;
SData->Total = Max; }
SData->ID = SplitID; std::string Packet = Data.substr(pos);
SData->Fragments.insert(std::make_pair(Current,Data.substr(pos2+1))); SplitData* SData = GetSplit(Num.at(3));
SData->Total = Num.at(1);
SData->ID = Num.at(3);
SData->Fragments.insert(std::make_pair(Num.at(0),Packet));
if(SData->Fragments.size() == SData->Total){ if(SData->Fragments.size() == SData->Total){
std::string ToHandle; std::string ToHandle;
for(const std::pair<int,std::string>& a : SData->Fragments){ for(const std::pair<int,std::string>& a : SData->Fragments){
@ -184,36 +189,56 @@ void HandleChunk(Client*c,const std::string&Data){
} }
GParser(c,ToHandle); GParser(c,ToHandle);
SplitPackets.erase(SData); SplitPackets.erase(SData);
delete SData;
SData = nullptr;
} }
} }
void UDPParser(Client*c,std::string Packet){ void UDPParser(Client*c,std::string Packet){
if(Packet.substr(0,4) == Sec("ABG:")){ if(Packet.substr(0,4) == "ABG:"){
Packet = DeComp(Packet.substr(4)); Packet = DeComp(Packet.substr(4));
} }
if(Packet.substr(0,4) == Sec("TRG:")){ if(Packet.substr(0,4) == "TRG:"){
std::string pkt = Packet.substr(4); std::string pkt = Packet.substr(4);
if(Packet.find_first_not_of("0123456789") == -1){ if(Packet.find_first_not_of("0123456789") == -1){
AckID(stoi(Packet)); AckID(stoi(Packet));
} }
return; return;
}else if(Packet.substr(0,3) == Sec("BD:")){ }else if(Packet.substr(0,3) == "BD:"){
auto pos = Packet.find(':',4); auto pos = Packet.find(':',4);
int ID = stoi(Packet.substr(3,pos-3)); int ID = stoi(Packet.substr(3,pos-3));
std::string pkt = Sec("TRG:") + std::to_string(ID); std::string pkt = "TRG:" + std::to_string(ID);
UDPSend(c,pkt); UDPSend(c,pkt);
if(!Handled(c,ID)) { if(!Handled(c,ID)) {
pkt = Packet.substr(pos + 1); pkt = Packet.substr(pos + 1);
GParser(c, pkt); GParser(c, pkt);
} }
return; return;
}else if(Packet.substr(0,2) == Sec("SC")){ }else if(Packet.substr(0,2) == "SC"){
HandleChunk(c,Packet); HandleChunk(c,Packet);
return; return;
} }
GParser(c,Packet); GParser(c,Packet);
} }
#include <thread> void LOOP(){
void StartLoop(); while(UDPSock != -1) {
for (PacketData* p : DataAcks){
if(p != nullptr) {
if (p->Client == nullptr || p->Client->GetTCPSock() == -1) {
DataAcks.erase(p);
break;
}
if (p->Tries < 15) {
UDPSend(p->Client, p->Data);
p->Tries++;
} else {
DataAcks.erase(p);
break;
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
}
[[noreturn]] void UDPServerMain(){ [[noreturn]] void UDPServerMain(){
WSADATA data; WSADATA data;
if (WSAStartup(514, &data)){ if (WSAStartup(514, &data)){
@ -237,7 +262,8 @@ void StartLoop();
} }
DataAcks.clear(); DataAcks.clear();
StartLoop(); std::thread Ack(LOOP);
Ack.detach();
info(Sec("Vehicle data network online on port ")+std::to_string(Port)+Sec(" with a Max of ")+std::to_string(MaxPlayers)+Sec(" Clients")); info(Sec("Vehicle data network online on port ")+std::to_string(Port)+Sec(" with a Max of ")+std::to_string(MaxPlayers)+Sec(" Clients"));
while (true){ while (true){
@ -253,38 +279,11 @@ void StartLoop();
if(c != nullptr && c->GetID() == ID){ if(c != nullptr && c->GetID() == ID){
c->SetUDPAddr(client); c->SetUDPAddr(client);
c->isConnected = true; c->isConnected = true;
std::thread Parse(UDPParser,c,Data.substr(2)); UDPParser(c,Data.substr(2));
Parse.detach();
} }
} }
} }
/*closesocket(UDPSock); /*closesocket(UDPSock);
WSACleanup(); WSACleanup();
return;*/ return;*/
} }
void LOOP(){
while(UDPSock != -1) {
for (PacketData* p : DataAcks){
if(p != nullptr) {
if (p->Client == nullptr || p->Client->GetTCPSock() == -1) {
DataAcks.erase(p);
break;
}
if (p->Tries < 20) {
UDPSend(p->Client, p->Data);
p->Tries++;
} else {
DataAcks.erase(p);
delete p;
p = nullptr;
break;
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
void StartLoop(){
std::thread Ack(LOOP);
Ack.detach();
}