mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 23:35:41 +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
|
#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{
|
||||||
|
@ -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;
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
@ -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){
|
||||||
|
@ -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(){
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
@ -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);
|
||||||
|
@ -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();
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user