mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 15:26:59 +00:00
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:
parent
31c96cee94
commit
71a84b4f1b
42
include/Buffer.h
Normal file
42
include/Buffer.h
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <WS2tcpip.h>
|
||||
#include "Buffer.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
@ -48,6 +49,7 @@ public:
|
||||
int GetCarCount();
|
||||
void ClearCars();
|
||||
int GetStatus();
|
||||
Buffer Handler;
|
||||
int GetID();
|
||||
};
|
||||
struct ClientInterface{
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "lua.hpp"
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <any>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
@ -50,17 +51,15 @@ public:
|
||||
void SetPluginName(const std::string&Name);
|
||||
void SetFileName(const std::string&Name);
|
||||
fs::file_time_type GetLastWrite();
|
||||
bool isThreadExecuting = false;
|
||||
std::string GetPluginName();
|
||||
std::string GetFileName();
|
||||
bool isExecuting = false;
|
||||
bool StopThread = false;
|
||||
bool HasThread = false;
|
||||
lua_State* GetState();
|
||||
char* GetOrigin();
|
||||
std::mutex Lock;
|
||||
void Reload();
|
||||
void Init();
|
||||
};
|
||||
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;
|
@ -12,8 +12,8 @@ void SyncResources(Client*c);
|
||||
[[noreturn]] void UDPServerMain();
|
||||
void OnDisconnect(Client*c,bool kicked);
|
||||
void UDPSend(Client*c,std::string Data);
|
||||
void TCPSend(Client*c,const std::string&Data);
|
||||
void SendLarge(Client*c,const std::string&Data);
|
||||
void TCPSend(Client*c,const std::string& Data);
|
||||
void SendLarge(Client*c,std::string Data);
|
||||
void GParser(Client*c, const std::string&Packet);
|
||||
void Respond(Client*c, const std::string& MSG, bool Rel);
|
||||
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel);
|
||||
|
@ -10,6 +10,7 @@ struct RSA{
|
||||
int e = 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_D(const std::string& Data, RSA*k);
|
||||
int Handle(EXCEPTION_POINTERS *ep,char* Origin);
|
||||
|
@ -100,7 +100,13 @@ std::string RSA_E(const std::string& Data, RSA*k){
|
||||
}
|
||||
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::stringstream ss(Data);
|
||||
std::string token,ret;
|
||||
|
@ -19,28 +19,28 @@ std::string GetPlayers(){
|
||||
return Return;
|
||||
}
|
||||
std::string GenerateCall(){
|
||||
std::string State = Private ? Sec("true") : Sec("false");
|
||||
std::string ret = Sec("uuid=");
|
||||
ret += Key+Sec("&players=")+std::to_string(CI->Size())+Sec("&maxplayers=")+std::to_string(MaxPlayers)+Sec("&port=")
|
||||
+ std::to_string(Port) + Sec("&map=") + MapName + Sec("&private=")+State+Sec("&version=")+GetSVer()+
|
||||
Sec("&clientversion=")+GetCVer()+Sec("&name=")+ServerName+Sec("&pps=")+StatReport+Sec("&modlist=")+FileList+
|
||||
Sec("&modstotalsize=")+std::to_string(MaxModSize)+Sec("&modstotal=")+std::to_string(ModsLoaded)
|
||||
+Sec("&playerslist=")+GetPlayers()+Sec("&desc=")+ServerDesc;
|
||||
std::string State = Private ? "true" : "false";
|
||||
std::string ret = "uuid=";
|
||||
ret += Key+"&players="+std::to_string(CI->Size())+"&maxplayers="+std::to_string(MaxPlayers)+"&port="
|
||||
+ std::to_string(Port) + "&map=" + MapName + "&private="+State+"&version="+GetSVer()+
|
||||
"&clientversion="+GetCVer()+"&name="+ServerName+"&pps="+StatReport+"&modlist="+FileList+
|
||||
"&modstotalsize="+std::to_string(MaxModSize)+"&modstotal="+std::to_string(ModsLoaded)
|
||||
+"&playerslist="+GetPlayers()+"&desc="+ServerDesc;
|
||||
return ret;
|
||||
}
|
||||
void Heartbeat(){
|
||||
std::string R,T;
|
||||
while(true){
|
||||
R = GenerateCall();
|
||||
if(!CustomIP.empty())R+=Sec("&ip=")+CustomIP;
|
||||
//https://beamng-mp.com/heartbeatv2
|
||||
std::string link = Sec("https://beamng-mp.com/heartbeatv2");
|
||||
if(!CustomIP.empty())R+="&ip="+CustomIP;
|
||||
std::string link = Sec("https://beammp.com/heartbeatv2");
|
||||
T = PostHTTP(link,R);
|
||||
if(T.find_first_not_of(Sec("20")) != std::string::npos){
|
||||
//Backend system refused server startup!
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
T = PostHTTP(link,R);
|
||||
if(T.find_first_not_of(Sec("20")) != std::string::npos){
|
||||
std::string Backup = Sec("https://backup1.beammp.com/heartbeatv2");
|
||||
T = PostHTTP(Backup,R);
|
||||
if(T.find_first_not_of(Sec("20")) != std::string::npos) {
|
||||
error(Sec("Backend system refused server! Check your AuthKey"));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
exit(-1);
|
||||
|
@ -8,10 +8,12 @@
|
||||
|
||||
std::string CustomIP;
|
||||
std::string GetSVer(){
|
||||
return Sec("0.60");
|
||||
static std::string r = Sec("0.63.5");
|
||||
return r;
|
||||
}
|
||||
std::string GetCVer(){
|
||||
return Sec("1.60");
|
||||
static std::string r = Sec("1.63");
|
||||
return r;
|
||||
}
|
||||
void Args(int argc, char* argv[]){
|
||||
info(Sec("BeamMP Server Running version ") + GetSVer());
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Logger.h"
|
||||
#include <iostream>
|
||||
#include <future>
|
||||
#include <utility>
|
||||
|
||||
LuaArg* CreateArg(lua_State *L,int T,int S){
|
||||
if(S > T)return nullptr;
|
||||
@ -26,6 +27,9 @@ LuaArg* CreateArg(lua_State *L,int T,int S){
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
void ClearStack(lua_State *L){
|
||||
lua_settop(L,0);
|
||||
}
|
||||
Lua* GetScript(lua_State *L){
|
||||
for(Lua*Script : PluginEngine){
|
||||
if (Script->GetState() == L)return Script;
|
||||
@ -35,33 +39,41 @@ Lua* GetScript(lua_State *L){
|
||||
void SendError(lua_State *L,const std::string&msg){
|
||||
Lua* S = GetScript(L);
|
||||
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){
|
||||
std::lock_guard<std::mutex> lockGuard(lua->Lock);
|
||||
std::packaged_task<int()> task([lua,R,arg]{return CallFunction(lua,R,arg);});
|
||||
std::future<int> f1 = task.get_future();
|
||||
std::thread t(std::move(task));
|
||||
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();
|
||||
SendError(lua->GetState(),R + " took too long to respond");
|
||||
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;
|
||||
for(Lua*Script : PluginEngine){
|
||||
if(Script->IsRegistered(Event)){
|
||||
if(local){
|
||||
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;
|
||||
}
|
||||
|
||||
@ -70,7 +82,7 @@ bool CheckLua(lua_State *L, int r){
|
||||
std::string msg = lua_tostring(L, -1);
|
||||
Lua * S = GetScript(L);
|
||||
std::string a = S->GetFileName().substr(S->GetFileName().find('\\'));
|
||||
warn(a + " | at line " + msg.substr(msg.find(':')+1));
|
||||
warn(a + " | " + msg);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -89,7 +101,7 @@ int lua_TriggerEventL(lua_State *L){
|
||||
Lua* Script = GetScript(L);
|
||||
if(Args > 0){
|
||||
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 not enough arguments expected 1 got 0"));
|
||||
@ -102,7 +114,7 @@ int lua_TriggerEventG(lua_State *L){
|
||||
Lua* Script = GetScript(L);
|
||||
if(Args > 0){
|
||||
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 not enough arguments"));
|
||||
return 0;
|
||||
@ -110,24 +122,12 @@ int lua_TriggerEventG(lua_State *L){
|
||||
|
||||
char* ThreadOrigin(Lua*lua){
|
||||
std::string T = "Thread in " + lua->GetFileName().substr(lua->GetFileName().find('\\'));
|
||||
char* Data = new char[T.size()];
|
||||
ZeroMemory(Data,T.size());
|
||||
char* Data = new char[T.size()+1];
|
||||
ZeroMemory(Data,T.size()+1);
|
||||
memcpy_s(Data,T.size(),T.c_str(),T.size());
|
||||
return Data;
|
||||
}
|
||||
|
||||
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;
|
||||
void SafeExecution(Lua* lua,const std::string& FuncName){
|
||||
lua_State* luaState = lua->GetState();
|
||||
lua_getglobal(luaState, FuncName.c_str());
|
||||
if(lua_isfunction(luaState, -1)) {
|
||||
@ -138,21 +138,20 @@ void ExecuteAsync(Lua* lua,const std::string& FuncName){
|
||||
}__except(Handle(GetExceptionInformation(),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){
|
||||
if(lua->HasThread){
|
||||
SendError(lua->GetState(),Sec("CreateThread : There is already a thread running!"));
|
||||
return;
|
||||
}
|
||||
lua->StopThread = false;
|
||||
lua->HasThread = true;
|
||||
int D = 1000 / U;
|
||||
while(!lua->StopThread){
|
||||
ExecuteAsync(lua,Func);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(D));
|
||||
}
|
||||
lua->HasThread = false;
|
||||
}
|
||||
int lua_StopThread(lua_State *L){
|
||||
GetScript(L)->StopThread = true;
|
||||
@ -329,10 +328,43 @@ int lua_HWID(lua_State *L){
|
||||
lua_pushinteger(L, -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(){
|
||||
luaL_openlibs(luaState);
|
||||
lua_register(luaState,"TriggerGlobalEvent",lua_TriggerEventG);
|
||||
lua_register(luaState,"TriggerLocalEvent",lua_TriggerEventL);
|
||||
lua_register(luaState,"TriggerClientEvent",lua_RemoteEvent);
|
||||
lua_register(luaState,"GetPlayerCount",lua_GetPlayerCount);
|
||||
lua_register(luaState,"isPlayerConnected",lua_isConnected);
|
||||
lua_register(luaState,"RegisterEvent",lua_RegisterEvent);
|
||||
@ -352,7 +384,7 @@ void Lua::Init(){
|
||||
|
||||
void Lua::Reload(){
|
||||
if(CheckLua(luaState,luaL_dofile(luaState,FileName.c_str()))){
|
||||
CallFunction(this,Sec("onInit"),{});
|
||||
CallFunction(this,Sec("onInit"), nullptr);
|
||||
}
|
||||
}
|
||||
char* Lua::GetOrigin(){
|
||||
@ -363,8 +395,6 @@ char* Lua::GetOrigin(){
|
||||
return Data;
|
||||
}
|
||||
int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){
|
||||
Lock(lua,false);
|
||||
lua->isExecuting = true;
|
||||
lua_State*luaState = lua->GetState();
|
||||
lua_getglobal(luaState, FuncName.c_str());
|
||||
if(lua_isfunction(luaState, -1)) {
|
||||
@ -372,6 +402,8 @@ int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){
|
||||
if(Arg != nullptr){
|
||||
Size = int(Arg->args.size());
|
||||
Arg->PushArgs(luaState);
|
||||
delete Arg;
|
||||
Arg = nullptr;
|
||||
}
|
||||
int R = 0;
|
||||
char* Origin = lua->GetOrigin();
|
||||
@ -385,7 +417,7 @@ int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){
|
||||
}__except(Handle(GetExceptionInformation(),Origin)){}
|
||||
delete [] Origin;
|
||||
}
|
||||
lua->isExecuting = false;
|
||||
ClearStack(luaState);
|
||||
return 0;
|
||||
}
|
||||
void Lua::SetPluginName(const std::string&Name){
|
||||
|
@ -29,8 +29,10 @@ std::string Rcv(SOCKET TCPSock){
|
||||
}
|
||||
std::string GetRole(const std::string &DID){
|
||||
if(!DID.empty()){
|
||||
std::string a = HttpRequest(Sec("https://beamng-mp.com/entitlement?did=")+DID,443);
|
||||
if(!a.empty()){
|
||||
std::string a = HttpRequest(Sec("https://beammp.com/entitlement?did=")+DID,443);
|
||||
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('"');
|
||||
if(pos != std::string::npos){
|
||||
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);
|
||||
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::stringstream stream;
|
||||
stream << std::hex << key->n << "g" << key->e << "g" << RSA_E(Sec("IDC"),key);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
void Identification(SOCKET TCPSock,Hold*S,RSA*key){
|
||||
void Identification(SOCKET TCPSock,Hold*S,RSA*Skey){
|
||||
S->TCPSock = TCPSock;
|
||||
std::thread Timeout(Check,S);
|
||||
Timeout.detach();
|
||||
std::string Name,DID,Role;
|
||||
if(!Send(TCPSock,GenerateM(key))){
|
||||
if(!Send(TCPSock,GenerateM(Skey))){
|
||||
closesocket(TCPSock);
|
||||
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 Ver = Rcv(TCPSock);
|
||||
S->Done = true;
|
||||
Ver = RSA_D(Ver,key);
|
||||
Ver = RSA_D(Ver,Skey);
|
||||
if(Ver.size() > 3 && Ver.substr(0,2) == Sec("VC")){
|
||||
Ver = Ver.substr(2);
|
||||
if(Ver.length() > 4 || Ver != GetCVer()){
|
||||
@ -93,7 +115,7 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*key){
|
||||
closesocket(TCPSock);
|
||||
return;
|
||||
}
|
||||
Res = RSA_D(Res,key);
|
||||
Res = RSA_D(Res,Skey);
|
||||
if(Res.size() < 3 || Res.substr(0,2) != Sec("NR")) {
|
||||
closesocket(TCPSock);
|
||||
return;
|
||||
@ -125,11 +147,15 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*key){
|
||||
}
|
||||
void Identify(SOCKET TCPSock){
|
||||
auto* S = new Hold;
|
||||
RSA*key = GenKey();
|
||||
RSA*Skey = GenKey();
|
||||
__try{
|
||||
Identification(TCPSock,S,key);
|
||||
}__except(1){}
|
||||
delete key;
|
||||
Identification(TCPSock,S,Skey);
|
||||
}__except(1){
|
||||
if(TCPSock != -1){
|
||||
closesocket(TCPSock);
|
||||
}
|
||||
}
|
||||
delete Skey;
|
||||
delete S;
|
||||
}
|
||||
void TCPServerMain(){
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "Settings.h"
|
||||
#include "Network.h"
|
||||
#include "Logger.h"
|
||||
#include <sstream>
|
||||
|
||||
int FC(const std::string& s,const std::string& p,int n) {
|
||||
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);
|
||||
if(c->GetCarCount() >= MaxCars ||
|
||||
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);
|
||||
std::string Destroy = "Od:" + std::to_string(c->GetID())+"-"+std::to_string(CarID);
|
||||
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(!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);
|
||||
Apply(c,VID,Packet);
|
||||
}else{
|
||||
@ -82,7 +83,7 @@ void VehicleParser(Client*c,const std::string& Pckt){
|
||||
if(PID != -1 && VID != -1 && PID == c->GetID()){
|
||||
SendToAll(nullptr,Packet,true,true);
|
||||
TriggerLuaEvent(Sec("onVehicleDeleted"),false,nullptr,
|
||||
new LuaArg{{c->GetID(),VID}});
|
||||
new LuaArg{{c->GetID(),VID}},false);
|
||||
c->DeleteCar(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){
|
||||
if(c->isSynced)return;
|
||||
c->isSynced = true;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
Respond(c,Sec("Sn")+c->GetName(),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) {
|
||||
if(client != nullptr){
|
||||
if (client != c) {
|
||||
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!"));
|
||||
}
|
||||
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"))){}
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
char Code = Packet.at(0);
|
||||
|
||||
@ -150,14 +176,13 @@ void GlobalParser(Client*c, const std::string& Packet){
|
||||
return;
|
||||
case 'C':
|
||||
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{{c->GetID(), c->GetName(), pct.substr(pct.find(':', 3) + 1)}}))break;
|
||||
SendToAll(nullptr, pct, true, true);
|
||||
pct.clear();
|
||||
if (TriggerLuaEvent(Sec("onChatMessage"), false, nullptr,new LuaArg{
|
||||
{c->GetID(), c->GetName(), Packet.substr(Packet.find(':', 3) + 1)}
|
||||
},true))break;
|
||||
SendToAll(nullptr, Packet, true, true);
|
||||
return;
|
||||
case 'E':
|
||||
SendToAll(nullptr,Packet,true,true);
|
||||
HandleEvent(c,Packet);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
|
@ -25,7 +25,7 @@ int OpenID(){
|
||||
}
|
||||
void Respond(Client*c, const std::string& MSG, bool Rel){
|
||||
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);
|
||||
else TCPSend(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){
|
||||
if(client != nullptr) {
|
||||
if (Self || client != c) {
|
||||
if (client->isSynced) {
|
||||
if (Rel) {
|
||||
if (C == 'O' || C == 'T' || Data.length() > 1000)SendLarge(client, Data);
|
||||
if (client->isSynced || (C == 'O' && Data.at(1) == 's')) {
|
||||
if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') {
|
||||
if (C == 'O' || C == 'T' ||
|
||||
Data.length() > 1000)SendLarge(client, Data);
|
||||
else TCPSend(client, Data);
|
||||
} else UDPSend(client, Data);
|
||||
}
|
||||
@ -54,6 +55,7 @@ void UpdatePlayers(){
|
||||
SendToAll(nullptr, Packet,true,true);
|
||||
}
|
||||
void OnDisconnect(Client*c,bool kicked){
|
||||
info(c->GetName() + Sec(" Connection Terminated"));
|
||||
if(c == nullptr)return;
|
||||
std::string Packet;
|
||||
for(VData*v : c->GetAllCars()){
|
||||
@ -66,17 +68,18 @@ void OnDisconnect(Client*c,bool kicked){
|
||||
Packet = Sec("L")+c->GetName()+Sec(" Left the server!");
|
||||
SendToAll(c, Packet,false,true);
|
||||
Packet.clear();
|
||||
TriggerLuaEvent(Sec("onPlayerDisconnect"),false,nullptr,new LuaArg{{c->GetID()}});
|
||||
TriggerLuaEvent(Sec("onPlayerDisconnect"),false,nullptr,new LuaArg{{c->GetID()}},false);
|
||||
c->ClearCars();
|
||||
CI->RemoveClient(c); ///Removes the Client from existence
|
||||
}
|
||||
void OnConnect(Client*c){
|
||||
info(Sec("Client connected"));
|
||||
c->SetID(OpenID());
|
||||
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);
|
||||
if(c->GetStatus() < 0)return;
|
||||
Respond(c,"M"+MapName,true); //Send the Map on connect
|
||||
info(c->GetName() + Sec(" : Connected"));
|
||||
TriggerLuaEvent(Sec("onPlayerJoining"),false,nullptr,new LuaArg{{c->GetID()}});
|
||||
TriggerLuaEvent(Sec("onPlayerJoining"),false,nullptr,new LuaArg{{c->GetID()}},false);
|
||||
}
|
@ -8,16 +8,24 @@
|
||||
|
||||
void TCPSend(Client*c,const std::string&Data){
|
||||
if(c == nullptr)return;
|
||||
int BytesSent = send(c->GetTCPSock(), Data.c_str(), int(Data.length())+1, 0);
|
||||
if (BytesSent == 0){
|
||||
std::string Send = "\n" + Data.substr(0,Data.find(char(0))) + "\n";
|
||||
size_t Sent = send(c->GetTCPSock(), Send.c_str(), int(Send.size()), 0);
|
||||
if (Sent == 0){
|
||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
||||
}else if (BytesSent < 0) {
|
||||
}else if (Sent < 0) {
|
||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
||||
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){
|
||||
if(c == nullptr)return;
|
||||
if(c == nullptr || c->GetStatus() < 0)return;
|
||||
char buf[4096];
|
||||
int len = 4096;
|
||||
ZeroMemory(buf, len);
|
||||
@ -33,18 +41,18 @@ void TCPRcv(Client*c){
|
||||
return;
|
||||
}
|
||||
std::string Buf(buf,BytesRcv);
|
||||
GParser(c, Buf);
|
||||
TCPHandle(c,Buf);
|
||||
}
|
||||
void TCPClient(Client*c){
|
||||
if(c->GetTCPSock() == -1){
|
||||
CI->RemoveClient(c);
|
||||
return;
|
||||
}
|
||||
info(Sec("Client connected"));
|
||||
OnConnect(c);
|
||||
while (c->GetStatus() > -1)TCPRcv(c);
|
||||
info(c->GetName() + Sec(" Connection Terminated"));
|
||||
OnDisconnect(c, c->GetStatus() == -2);
|
||||
__try{
|
||||
OnDisconnect(c, c->GetStatus() == -2);
|
||||
}__except(Handle(GetExceptionInformation(),Sec("OnDisconnect"))){}
|
||||
}
|
||||
void InitClient(Client*c){
|
||||
std::thread NewClient(TCPClient,c);
|
||||
|
@ -8,9 +8,11 @@
|
||||
#include "Settings.h"
|
||||
#include "Network.h"
|
||||
#include "Logger.h"
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <array>
|
||||
|
||||
int FC(const std::string& s,const std::string& p,int n);
|
||||
struct PacketData{
|
||||
int ID;
|
||||
Client* Client;
|
||||
@ -30,11 +32,11 @@ void UDPSend(Client*c,std::string Data){
|
||||
if(c == nullptr || !c->isConnected || c->GetStatus() < 0)return;
|
||||
sockaddr_in Addr = c->GetUDPAddr();
|
||||
int AddrSize = sizeof(c->GetUDPAddr());
|
||||
Data = Data.substr(0,Data.find(char(0)));
|
||||
if(Data.length() > 400){
|
||||
std::string CMP(Comp(Data));
|
||||
Data = "ABG:" + CMP;
|
||||
}
|
||||
|
||||
int sendOk = sendto(UDPSock, Data.c_str(), int(Data.size()), 0, (sockaddr *) &Addr, AddrSize);
|
||||
if (sendOk == SOCKET_ERROR) {
|
||||
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){
|
||||
for(PacketData* p : DataAcks){
|
||||
if(p->ID == ID){
|
||||
if(p != nullptr && p->ID == ID){
|
||||
DataAcks.erase(p);
|
||||
break;
|
||||
}
|
||||
@ -62,7 +64,8 @@ int SplitID(){
|
||||
else 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();
|
||||
std::string Packet;
|
||||
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 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);
|
||||
Packet = "SC|"+std::to_string(S)+"|"+std::to_string(Split)+"|"+std::to_string(ID)+"|"+
|
||||
std::to_string(SID)+"|"+pckt.substr(0,1000);
|
||||
DataAcks.insert(new PacketData{ID,c,Packet,1});
|
||||
UDPSend(c,Packet);
|
||||
pckt = pckt.substr(1000);
|
||||
S++;
|
||||
ID = PacktID();
|
||||
}
|
||||
Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+
|
||||
std::to_string(ID)+"|"+std::to_string(SID)+":"+pckt;
|
||||
Packet = "SC|"+std::to_string(S)+"|"+std::to_string(Split)+"|"+
|
||||
std::to_string(ID)+"|"+std::to_string(SID)+"|"+pckt;
|
||||
DataAcks.insert(new PacketData{ID,c,Packet,1});
|
||||
UDPSend(c,Packet);
|
||||
}else{
|
||||
@ -90,12 +93,12 @@ void SendLarge(Client*c,const std::string&Data){
|
||||
}
|
||||
struct HandledC{
|
||||
int Pos = 0;
|
||||
Client *c{};
|
||||
std::array<int, 50> HandledIDs{};
|
||||
Client *c = nullptr;
|
||||
std::array<int, 100> HandledIDs = {-1};
|
||||
};
|
||||
std::set<HandledC*> HandledIDs;
|
||||
void ResetIDs(HandledC*H){
|
||||
for(int C = 0;C < 50;C++){
|
||||
for(int C = 0;C < 100;C++){
|
||||
H->HandledIDs.at(C) = -1;
|
||||
}
|
||||
}
|
||||
@ -114,7 +117,7 @@ bool Handled(Client*c,int ID){
|
||||
for(int id : h->HandledIDs){
|
||||
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->Pos++;
|
||||
handle = true;
|
||||
@ -129,7 +132,7 @@ bool Handled(Client*c,int ID){
|
||||
if(!handle){
|
||||
HandledC *h = GetHandled(c);
|
||||
ResetIDs(h);
|
||||
if (h->Pos > 49)h->Pos = 0;
|
||||
if (h->Pos > 99)h->Pos = 0;
|
||||
h->HandledIDs.at(h->Pos) = ID;
|
||||
h->Pos++;
|
||||
h->c = c;
|
||||
@ -138,17 +141,14 @@ bool Handled(Client*c,int ID){
|
||||
return false;
|
||||
}
|
||||
std::string UDPRcvFromClient(sockaddr_in& client){
|
||||
char buf[10240];
|
||||
int clientLength = sizeof(client);
|
||||
ZeroMemory(&client, clientLength);
|
||||
ZeroMemory(buf, 10240);
|
||||
int Rcv = recvfrom(UDPSock, buf, 10240, 0, (sockaddr*)&client, &clientLength);
|
||||
std::string Ret(10240,0);
|
||||
int Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&client, &clientLength);
|
||||
if (Rcv == -1){
|
||||
error(Sec("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError()));
|
||||
return "";
|
||||
}
|
||||
std::string Ret(Rcv,0);
|
||||
memcpy_s(&Ret[0],Rcv,buf,Rcv);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
@ -161,22 +161,27 @@ SplitData*GetSplit(int SplitID){
|
||||
return SP;
|
||||
}
|
||||
void HandleChunk(Client*c,const std::string&Data){
|
||||
int pos1 = int(Data.find(':'))+1,
|
||||
pos2 = int(Data.find(':',pos1)),
|
||||
pos3 = int(Data.find('/')),
|
||||
pos4 = int(Data.find('|'));
|
||||
if(pos1 == std::string::npos)return;
|
||||
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 = Sec("TRG:") + Data.substr(pos1,pos4-pos1);
|
||||
int pos = FC(Data,"|",5);
|
||||
if(pos == -1)return;
|
||||
std::stringstream ss(Data.substr(0,pos++));
|
||||
std::string t;
|
||||
int I = -1;
|
||||
//Current Max ID SID
|
||||
std::vector<int> Num(4,0);
|
||||
while (std::getline(ss, t, '|')) {
|
||||
if(I != -1)Num.at(I) = std::stoi(t);
|
||||
I++;
|
||||
}
|
||||
std::string ack = "TRG:" + std::to_string(Num.at(2));
|
||||
UDPSend(c,ack);
|
||||
if(Handled(c,ID))return;
|
||||
SplitData* SData = GetSplit(SplitID);
|
||||
SData->Total = Max;
|
||||
SData->ID = SplitID;
|
||||
SData->Fragments.insert(std::make_pair(Current,Data.substr(pos2+1)));
|
||||
if(Handled(c,Num.at(2))){
|
||||
return;
|
||||
}
|
||||
std::string Packet = Data.substr(pos);
|
||||
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){
|
||||
std::string ToHandle;
|
||||
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);
|
||||
SplitPackets.erase(SData);
|
||||
delete SData;
|
||||
SData = nullptr;
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
if(Packet.substr(0,4) == Sec("TRG:")){
|
||||
if(Packet.substr(0,4) == "TRG:"){
|
||||
std::string pkt = Packet.substr(4);
|
||||
if(Packet.find_first_not_of("0123456789") == -1){
|
||||
AckID(stoi(Packet));
|
||||
}
|
||||
return;
|
||||
}else if(Packet.substr(0,3) == Sec("BD:")){
|
||||
}else if(Packet.substr(0,3) == "BD:"){
|
||||
auto pos = Packet.find(':',4);
|
||||
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);
|
||||
if(!Handled(c,ID)) {
|
||||
pkt = Packet.substr(pos + 1);
|
||||
GParser(c, pkt);
|
||||
}
|
||||
return;
|
||||
}else if(Packet.substr(0,2) == Sec("SC")){
|
||||
}else if(Packet.substr(0,2) == "SC"){
|
||||
HandleChunk(c,Packet);
|
||||
return;
|
||||
}
|
||||
GParser(c,Packet);
|
||||
}
|
||||
#include <thread>
|
||||
void StartLoop();
|
||||
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 < 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(){
|
||||
WSADATA data;
|
||||
if (WSAStartup(514, &data)){
|
||||
@ -237,7 +262,8 @@ void StartLoop();
|
||||
}
|
||||
|
||||
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"));
|
||||
while (true){
|
||||
@ -253,38 +279,11 @@ void StartLoop();
|
||||
if(c != nullptr && c->GetID() == ID){
|
||||
c->SetUDPAddr(client);
|
||||
c->isConnected = true;
|
||||
std::thread Parse(UDPParser,c,Data.substr(2));
|
||||
Parse.detach();
|
||||
UDPParser(c,Data.substr(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*closesocket(UDPSock);
|
||||
WSACleanup();
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user