This commit is contained in:
Anonymous275 2020-06-13 01:06:28 +03:00
parent ed6b2d236a
commit a05acee04f
15 changed files with 353 additions and 116 deletions

View File

@ -4,7 +4,7 @@ project(BeamMP-Server)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2")
include_directories(${PROJECT_SOURCE_DIR}/curl) include_directories(${PROJECT_SOURCE_DIR}/curl)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 17)
file(GLOB source_files file(GLOB source_files
"src/*.h" "src/*.hpp" "src/*.cpp" "src/*.h" "src/*.hpp" "src/*.cpp"

View File

@ -4,37 +4,65 @@
#include "LuaSystem.hpp" #include "LuaSystem.hpp"
#include "../logger.h" #include "../logger.h"
#include <filesystem>
#include <iostream>
#include <string>
#include <thread> #include <thread>
#include "../Network 2.0/Client.hpp"
std::set<Lua*> PluginEngine; std::set<Lua*> PluginEngine;
namespace fs = std::experimental::filesystem;
void RegisterFiles(const std::string& Path){ bool NewFile(const std::string&Path){
for(Lua*Script : PluginEngine){
if(Path == Script->GetFileName())return false;
}
return true;
}
void RegisterFiles(const std::string& Path,bool HotSwap){
std::string Name = Path.substr(Path.find_last_of('\\')+1); std::string Name = Path.substr(Path.find_last_of('\\')+1);
info("Loading plugin : " + Name); if(!HotSwap)info("Loading plugin : " + Name);
for (const auto &entry : fs::directory_iterator(Path)) { for (const auto &entry : fs::directory_iterator(Path)){
int pos = entry.path().string().find(".lua"); int pos = entry.path().string().find(".lua");
if (pos != std::string::npos && entry.path().string().length() - pos == 4) { if (pos != std::string::npos && entry.path().string().length() - pos == 4) {
Lua *Script = new Lua(); if(!HotSwap || NewFile(entry.path().string())){
PluginEngine.insert(Script); Lua *Script = new Lua();
Script->SetFileName(entry.path().string()); PluginEngine.insert(Script);
Script->SetPluginName(Name); Script->SetFileName(entry.path().string());
Script->Init(); Script->SetPluginName(Name);
Script->SetLastWrite(fs::last_write_time(Script->GetFileName()));
Script->Init();
if(HotSwap)info("[HOTSWAP] Added : " +
Script->GetFileName().substr(Script->GetFileName().find('\\')));
}
} }
} }
} }
void FolderList(const std::string& Path,bool HotSwap){
void FolderList(const std::string& Path){
for (const auto &entry : fs::directory_iterator(Path)) { for (const auto &entry : fs::directory_iterator(Path)) {
int pos = entry.path().filename().string().find('.'); int pos = entry.path().filename().string().find('.');
if (pos == std::string::npos) { if (pos == std::string::npos) {
RegisterFiles(entry.path().string()); RegisterFiles(entry.path().string(),HotSwap);
} }
} }
} }
[[noreturn]]void HotSwaps(const std::string& path){
while(true){
for(Lua*Script : PluginEngine){
struct stat Info{};
if(stat(Script->GetFileName().c_str(), &Info) != 0){
PluginEngine.erase(Script);
info("[HOTSWAP] Removed : "+
Script->GetFileName().substr(Script->GetFileName().find('\\')));
break;
}
if(Script->GetLastWrite() != fs::last_write_time(Script->GetFileName())){
Script->SetLastWrite(fs::last_write_time(Script->GetFileName()));
Script->Reload();
info("[HOTSWAP] Updated : "+
Script->GetFileName().substr(Script->GetFileName().find('\\')));
}
}
FolderList(path,true);
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}
void LuaMain(std::string Path){ void LuaMain(std::string Path){
Path += "/Server"; Path += "/Server";
@ -42,6 +70,8 @@ void LuaMain(std::string Path){
if(stat( Path.c_str(), &Info) != 0){ if(stat( Path.c_str(), &Info) != 0){
fs::create_directory(Path); fs::create_directory(Path);
} }
FolderList(Path); FolderList(Path,false);
std::thread t1(HotSwaps,Path);
t1.detach();
info("Lua system online"); info("Lua system online");
} }

View File

@ -1,21 +1,38 @@
/// ///
/// Created by Anonymous275 on 5/19/2020 /// Created by Anonymous275 on 5/19/2020
/// ///
#include "../Network 2.0/Client.hpp" #include "../Network 2.0/Client.hpp"
#include "LuaSystem.hpp" #include "LuaSystem.hpp"
#include "../logger.h" #include "../logger.h"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller){ LuaArg* CreateArg(lua_State *L,int T){
LuaArg* temp = new LuaArg;
for(int C = 2;C <= T;C++){
if(lua_isstring(L,C)){
temp->args.emplace_back(std::string(lua_tostring(L,C)));
}else if(lua_isinteger(L,C)){
temp->args.emplace_back(int(lua_tointeger(L,C)));
}else if(lua_isboolean(L,C)){
temp->args.emplace_back(bool(lua_toboolean(L,C)));
}else if(lua_isnumber(L,C)) {
temp->args.emplace_back(float(lua_tonumber(L, C)));
}
}
return temp;
}
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg){
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 += Script->CallFunction(Script->GetRegistered(Event)); R += Script->CallFunction(Script->GetRegistered(Event),arg);
} }
}else R += Script->CallFunction(Script->GetRegistered(Event)); }else R += Script->CallFunction(Script->GetRegistered(Event),arg);
} }
} }
return R; return R;
@ -59,9 +76,9 @@ 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); TriggerLuaEvent(lua_tostring(L, 1), true, Script, CreateArg(L,Args));
}else{ }else{
SendError(L,"TriggerLocalEvent wrong arguments need string"); SendError(L,"TriggerLocalEvent wrong argument [1] need string");
} }
}else{ }else{
SendError(L,"TriggerLocalEvent not enough arguments"); SendError(L,"TriggerLocalEvent not enough arguments");
@ -75,24 +92,24 @@ 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), true, Script); TriggerLuaEvent(lua_tostring(L, 1), false, Script, CreateArg(L,Args));
}else SendError(L,"TriggerGlobalEvent wrong arguments need string"); }else SendError(L,"TriggerGlobalEvent wrong argument [1] need string");
}else{ }else{
SendError(L,"TriggerGlobalEvent not enough arguments"); SendError(L,"TriggerGlobalEvent not enough arguments");
} }
return 0; return 0;
} }
void CallAsync(Lua* Script,const std::string&FuncName){ void CallAsync(Lua* Script,const std::string&FuncName,LuaArg* args){
Script->CallFunction(FuncName); Script->CallFunction(FuncName,args);
} }
int lua_CreateThread(lua_State *L){ int lua_CreateThread(lua_State *L){
int Args = lua_gettop(L); int Args = lua_gettop(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)) {
std::thread Worker(CallAsync,Script,lua_tostring(L,1)); std::thread Worker(CallAsync,Script,lua_tostring(L,1),CreateArg(L,Args));
Worker.detach(); Worker.detach();
}else SendError(L,"CreateThread wrong arguments need string"); }else SendError(L,"CreateThread wrong argument [1] need string");
}else SendError(L,"CreateThread not enough arguments"); }else SendError(L,"CreateThread not enough arguments");
return 0; return 0;
} }
@ -193,18 +210,35 @@ int lua_dropPlayer(lua_State *L){
if(c != nullptr){ if(c != nullptr){
Respond(c,"C:Server:You have been Kicked from the server!",true); Respond(c,"C:Server:You have been Kicked from the server!",true);
c->SetStatus(-2); c->SetStatus(-2);
closesocket(c->GetTCPSock());
} }
}else SendError(L,"DropPlayer not enough arguments"); }else SendError(L,"DropPlayer not enough arguments");
return 0; return 0;
} }
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel); void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel);
int lua_sendChat(lua_State *L){ int lua_sendChat(lua_State *L){
if(lua_isstring(L,1)){ if(lua_isinteger(L,1) || lua_isnumber(L,1)){
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 1)); if(lua_isstring(L,2)){
SendToAll(nullptr,Packet,true,true); int ID = lua_tointeger(L,1);
}else SendError(L,"SendChatMessage not enough arguments"); if(ID == -1){
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 1));
SendToAll(nullptr,Packet,true,true);
}else{
Client*c = GetClient(ID);
if(c != nullptr) {
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 1));
Respond(c, Packet, true);
}else SendError(L,"SendChatMessage invalid argument [1] invalid ID");
}
}else SendError(L,"SendChatMessage invalid argument [2] expected string");
}else SendError(L,"SendChatMessage invalid argument [1] expected number");
return 0; return 0;
} }
int lua_HWID(lua_State *L){
lua_pushinteger(L, -1);
return 1;
}
void Lua::Init(){ void Lua::Init(){
luaL_openlibs(luaState); luaL_openlibs(luaState);
lua_register(luaState,"TriggerGlobalEvent",lua_TriggerEventG); lua_register(luaState,"TriggerGlobalEvent",lua_TriggerEventG);
@ -213,23 +247,31 @@ void Lua::Init(){
lua_register(luaState,"isPlayerConnected",lua_isConnected); lua_register(luaState,"isPlayerConnected",lua_isConnected);
lua_register(luaState,"RegisterEvent",lua_RegisterEvent); lua_register(luaState,"RegisterEvent",lua_RegisterEvent);
lua_register(luaState,"GetPlayerName",lua_GetPlayerName); lua_register(luaState,"GetPlayerName",lua_GetPlayerName);
lua_register(luaState,"GetPlayerDiscordID",lua_GetDID);
lua_register(luaState,"GetPlayerVehicles",lua_GetCars); lua_register(luaState,"GetPlayerVehicles",lua_GetCars);
lua_register(luaState,"CreateThread",lua_CreateThread); lua_register(luaState,"CreateThread",lua_CreateThread);
lua_register(luaState,"SendChatMessage",lua_sendChat); lua_register(luaState,"SendChatMessage",lua_sendChat);
lua_register(luaState,"DropPlayer",lua_dropPlayer); lua_register(luaState,"DropPlayer",lua_dropPlayer);
lua_register(luaState,"GetPlayers",lua_GetAllIDs); lua_register(luaState,"GetPlayers",lua_GetAllIDs);
lua_register(luaState,"GetDID",lua_GetDID); lua_register(luaState,"GetPlayerHWID",lua_HWID);
lua_register(luaState,"Sleep",lua_Sleep); lua_register(luaState,"Sleep",lua_Sleep);
Reload();
}
void Lua::Reload(){
if(CheckLua(luaState,luaL_dofile(luaState,FileName.c_str()))){ if(CheckLua(luaState,luaL_dofile(luaState,FileName.c_str()))){
CallFunction("onInit"); CallFunction("onInit",{});
} }
} }
int Lua::CallFunction(const std::string&FuncName){ int Lua::CallFunction(const std::string&FuncName,LuaArg* Arg){
lua_getglobal(luaState, FuncName.c_str()); lua_getglobal(luaState, FuncName.c_str());
if (lua_isfunction(luaState, -1)) { if (lua_isfunction(luaState, -1)) {
/*lua_pushstring(luaState, "Anonymous275"); int Size = 0;
lua_pushinteger(luaState, 1);*/ if(Arg != nullptr){
if(CheckLua(luaState, lua_pcall(luaState, 0, 1, 0))){ Size = Arg->args.size();
Arg->PushArgs(luaState);
}
if(CheckLua(luaState, lua_pcall(luaState, Size, 1, 0))){
if(lua_isnumber(luaState,-1)){ if(lua_isnumber(luaState,-1)){
return lua_tointeger(luaState,-1); return lua_tointeger(luaState,-1);
} }
@ -275,3 +317,9 @@ std::string Lua::GetPluginName(){
lua_State* Lua::GetState(){ lua_State* Lua::GetState(){
return luaState; return luaState;
} }
void Lua::SetLastWrite(fs::file_time_type time){
LastWrote = time;
}
fs::file_time_type Lua::GetLastWrite(){
return LastWrote;
}

View File

@ -4,11 +4,39 @@
#pragma once #pragma once
#include <set> #include <set>
#include <any>
#include <vector>
#include <iostream>
#include <filesystem>
#include "../lua/lua.hpp" #include "../lua/lua.hpp"
namespace fs = std::filesystem;
struct LuaArg{
std::vector<std::any> args;
void PushArgs(lua_State *State){
for(std::any arg : args){
if(!arg.has_value())return;
std::string Type = arg.type().name();
if(Type.find("bool") != -1){
lua_pushboolean(State,std::any_cast<bool>(arg));
}
if(Type.find("basic_string") != -1 || Type.find("char") != -1){
lua_pushstring(State,std::any_cast<std::string>(arg).c_str());
}
if(Type.find("int") != -1){
lua_pushinteger(State,std::any_cast<int>(arg));
}
if(Type.find("float") != -1){
lua_pushnumber(State,std::any_cast<float>(arg));
}
}
}
};
class Lua { class Lua {
private: private:
std::set<std::pair<std::string,std::string>> RegisteredEvents; std::set<std::pair<std::string,std::string>> RegisteredEvents;
lua_State *luaState = luaL_newstate(); lua_State *luaState = luaL_newstate();
fs::file_time_type LastWrote;
std::string PluginName; std::string PluginName;
std::string FileName; std::string FileName;
@ -16,13 +44,16 @@ public:
void RegisterEvent(const std::string&Event,const std::string&FunctionName); void RegisterEvent(const std::string&Event,const std::string&FunctionName);
std::string GetRegistered(const std::string&Event); std::string GetRegistered(const std::string&Event);
void UnRegisterEvent(const std::string&Event); void UnRegisterEvent(const std::string&Event);
int CallFunction(const std::string&FuncName); int CallFunction(const std::string&FuncName,LuaArg* args);
void SetLastWrite(fs::file_time_type time);
bool IsRegistered(const std::string&Event); bool IsRegistered(const std::string&Event);
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();
std::string GetPluginName(); std::string GetPluginName();
std::string GetFileName(); std::string GetFileName();
lua_State* GetState(); lua_State* GetState();
void Reload();
void Init(); void Init();
}; };

View File

@ -6,6 +6,7 @@
#include <WS2tcpip.h> #include <WS2tcpip.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <chrono>
#include <set> #include <set>
class Client { class Client {
@ -19,8 +20,6 @@ private:
SOCKET TCPSOCK; SOCKET TCPSOCK;
int Status = 0; int Status = 0;
int ID = -1; //PlayerID int ID = -1; //PlayerID
public: public:
std::set<std::pair<int,std::string>> GetAllCars(); std::set<std::pair<int,std::string>> GetAllCars();
void AddNewCar(int ident,const std::string& Data); void AddNewCar(int ident,const std::string& Data);

View File

@ -37,7 +37,7 @@ void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel){
for(Client*client : Clients){ for(Client*client : Clients){
if(Self || client != c){ if(Self || client != c){
if(Rel){ if(Rel){
if(C == 'O' || C == 'T' || Data.length() > 1000)SendLarge(client,Data); if(C == 'C' || 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);
@ -53,7 +53,12 @@ void UpdatePlayers(){
Packet = Packet.substr(0,Packet.length()-1); Packet = Packet.substr(0,Packet.length()-1);
SendToAll(nullptr, Packet,true,true); SendToAll(nullptr, Packet,true,true);
} }
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg);
void Destroy(Client*c){
Clients.erase(c);
delete c;
}
void OnDisconnect(Client*c,bool kicked){ void OnDisconnect(Client*c,bool kicked){
std::string Packet; std::string Packet;
for(const std::pair<int,std::string>&a : c->GetAllCars()){ for(const std::pair<int,std::string>&a : c->GetAllCars()){
@ -64,13 +69,15 @@ void OnDisconnect(Client*c,bool kicked){
Packet = "L"+c->GetName()+" Left the server!"; Packet = "L"+c->GetName()+" Left the server!";
SendToAll(c, Packet,false,true); SendToAll(c, Packet,false,true);
Packet.clear(); Packet.clear();
Clients.erase(c); ///Removes the Client from existence TriggerLuaEvent("onPlayerDisconnect",false,nullptr,new LuaArg{{c->GetID()}});
Destroy(c); ///Removes the Client from existence
} }
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller); void SyncResources(Client*c);
void OnConnect(Client*c){ void OnConnect(Client*c){
c->SetID(OpenID()); c->SetID(OpenID());
std::cout << "New Client Created! ID : " << c->GetID() << std::endl; std::cout << "New Client Created! ID : " << c->GetID() << std::endl;
Respond(c,"NR",true); TriggerLuaEvent("onPlayerConnecting",false,nullptr,new LuaArg{{c->GetID()}});
SyncResources(c);
Respond(c,"M"+MapName,true); //Send the Map on connect Respond(c,"M"+MapName,true); //Send the Map on connect
TriggerLuaEvent("onPlayerJoining",false,nullptr); TriggerLuaEvent("onPlayerJoining",false,nullptr,new LuaArg{{c->GetID()}});
} }

View File

@ -14,7 +14,7 @@ void Respond(Client*c, const std::string& MSG, bool Rel);
void UpdatePlayers(); void UpdatePlayers();
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller); int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg);
void VehicleParser(Client*c, std::string Packet){ void VehicleParser(Client*c, std::string Packet){
char Code = Packet.at(1); char Code = Packet.at(1);
int PID = -1; int PID = -1;
@ -23,11 +23,12 @@ void VehicleParser(Client*c, std::string Packet){
switch(Code){ //Spawned Destroyed Switched/Moved NotFound Reset switch(Code){ //Spawned Destroyed Switched/Moved NotFound Reset
case 's': case 's':
if(Data.at(0) == '0'){ if(Data.at(0) == '0'){
if(TriggerLuaEvent("onVehicleSpawn",false,nullptr))break;
int CarID = c->GetOpenCarID(); int CarID = c->GetOpenCarID();
std::cout << c->GetName() << " CarID : " << CarID << std::endl; std::cout << c->GetName() << " CarID : " << CarID << std::endl;
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(TriggerLuaEvent("onVehicleSpawn",false,nullptr,
new LuaArg{{c->GetID(),CarID,Packet.substr(3)}})
|| c->GetCarCount() >= MaxCars){
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);
@ -37,6 +38,9 @@ void VehicleParser(Client*c, std::string Packet){
} }
} }
break; break;
case 'c':
SendToAll(c,Packet,false,true);
break;
case 'd': case 'd':
pid = Data.substr(0,Data.find('-')); pid = Data.substr(0,Data.find('-'));
vid = Data.substr(Data.find('-')+1); vid = Data.substr(Data.find('-')+1);
@ -49,17 +53,17 @@ void VehicleParser(Client*c, std::string Packet){
c->DeleteCar(VID); c->DeleteCar(VID);
} }
break; break;
case 'm':
break;
case 'r': case 'r':
SendToAll(c,Packet,false,true); SendToAll(c,Packet,false,true);
break; break;
case 'm':
break;
} }
} }
void SyncVehicles(Client*c){ void SyncVehicles(Client*c){
Respond(c,"Sn"+c->GetName(),true); Respond(c,"Sn"+c->GetName(),true);
SendToAll(c,"JWelcome "+c->GetName()+"!",false,true); SendToAll(c,"JWelcome "+c->GetName()+"!",false,true);
TriggerLuaEvent("onPlayerJoin",false,nullptr); TriggerLuaEvent("onPlayerJoin",false,nullptr,new LuaArg{{c->GetID()}});
for (Client*client : Clients) { for (Client*client : Clients) {
if (client != c) { if (client != c) {
for(const std::pair<int,std::string>&a : client->GetAllCars()){ for(const std::pair<int,std::string>&a : client->GetAllCars()){
@ -74,8 +78,10 @@ void HTTP(Client*c){
std::string a = HTTP_REQUEST("https://beamng-mp.com/entitlement?did="+c->GetDID(),443); std::string a = HTTP_REQUEST("https://beamng-mp.com/entitlement?did="+c->GetDID(),443);
if(!a.empty()){ if(!a.empty()){
int pos = a.find('"'); int pos = a.find('"');
c->SetRole(a.substr(pos+1,a.find('"',pos+1)-2)); if(c != nullptr){
if(Debug)debug("ROLE -> " + c->GetRole() + " ID -> " + c->GetDID()); c->SetRole(a.substr(pos+1,a.find('"',pos+1)-2));
if(Debug)debug("ROLE -> " + c->GetRole() + " ID -> " + c->GetDID());
}
} }
} }
} }
@ -116,7 +122,8 @@ void GlobalParser(Client*c, const std::string&Packet){
SendToAll(c,Packet,false,true); SendToAll(c,Packet,false,true);
break; break;
case 'C': case 'C':
if(TriggerLuaEvent("onChatMessage",false,nullptr))break; if(TriggerLuaEvent("onChatMessage",false,nullptr,
new LuaArg{{c->GetID(),c->GetName(),Packet.substr(Packet.find(':',3)+1)}}))break;
SendToAll(nullptr,Packet,true,true); SendToAll(nullptr,Packet,true,true);
break; break;
case 'E': case 'E':

View File

@ -12,17 +12,16 @@ void TCPSend(Client*c,const std::string&Data){
int BytesSent = send(c->GetTCPSock(), Data.c_str(), int(Data.length())+1, 0); int BytesSent = send(c->GetTCPSock(), Data.c_str(), int(Data.length())+1, 0);
if (BytesSent == 0){ if (BytesSent == 0){
std::cout << "(TCP) Connection closing..." << std::endl; std::cout << "(TCP) Connection closing..." << std::endl;
c->SetStatus(-1); if(c->GetStatus() > -1)c->SetStatus(-1);
} }
else if (BytesSent < 0) { else if (BytesSent < 0) {
std::cout << "(TCP) send failed with error: " << WSAGetLastError() << std::endl; std::cout << "(TCP) send failed with error: " << WSAGetLastError() << std::endl;
if(c->GetStatus() > -1)c->SetStatus(-1);
closesocket(c->GetTCPSock()); closesocket(c->GetTCPSock());
c->SetStatus(-1);
} }
} }
void GlobalParser(Client*c, const std::string&Packet); void GlobalParser(Client*c, const std::string&Packet);
void TCPRcv(Client*c){ void TCPRcv(Client*c){
char buf[4096]; char buf[4096];
int len = 4096; int len = 4096;
@ -30,12 +29,12 @@ void TCPRcv(Client*c){
int BytesRcv = recv(c->GetTCPSock(), buf, len,0); int BytesRcv = recv(c->GetTCPSock(), buf, len,0);
if (BytesRcv == 0){ if (BytesRcv == 0){
std::cout << "(TCP) Connection closing..." << std::endl; std::cout << "(TCP) Connection closing..." << std::endl;
c->SetStatus(-1); if(c->GetStatus() > -1)c->SetStatus(-1);
} }
else if (BytesRcv < 0) { else if (BytesRcv < 0) {
std::cout << "(TCP) recv failed with error: " << WSAGetLastError() << std::endl; std::cout << "(TCP) recv failed with error: " << WSAGetLastError() << std::endl;
if(c->GetStatus() > -1)c->SetStatus(-1);
closesocket(c->GetTCPSock()); closesocket(c->GetTCPSock());
c->SetStatus(-1);
} }
GlobalParser(c, std::string(buf)); GlobalParser(c, std::string(buf));
} }

View File

@ -0,0 +1,118 @@
///
/// Created by Anonymous275 on 6/10/2020
///
#include <string>
#include "../Settings.hpp"
#include "Client.hpp"
#include <iostream>
#include <fstream>
#include <thread>
#include <any>
void GrabRole(Client*c);
void STCPSend(Client*c,const std::any& Data,size_t Size){
char *MSG;
if(std::string(Data.type().name()).find("string") != std::string::npos){
MSG = (char*)(std::any_cast<std::string>(Data).c_str());
}else MSG = std::any_cast<char*>(Data);
if(Size == 0)Size = strlen(MSG)+1;
int BytesSent = send(c->GetTCPSock(), MSG, Size, 0);
if (BytesSent == 0){
std::cout << "(TCP) Connection closing..." << std::endl;
if(c->GetStatus() > -1)c->SetStatus(-1);
}
else if (BytesSent < 0) {
std::cout << "(TCP) send failed with error: " << WSAGetLastError() << std::endl;
if(c->GetStatus() > -1)c->SetStatus(-1);
closesocket(c->GetTCPSock());
}
}
void SendFile(Client*c,const std::string&Name){
std::cout << c->GetName() << " requesting : "
<< Name.substr(Name.find_last_of('/')) << std::endl;
struct stat Info{};
if(stat(Name.c_str(), &Info) != 0){
STCPSend(c,std::string("Cannot Open"),0);
return;
}
std::ifstream f(Name.c_str(), std::ios::binary);
f.seekg(0, std::ios_base::end);
std::streampos fileSize = f.tellg();
size_t Size = fileSize,Sent = 0,Diff;
char* Data = new char[Size];
f.seekg(0, std::ios_base::beg);
f.read(Data, fileSize);
f.close();
char* Chunk;
int Split = 64000;
while(c->GetStatus() > -1 && Sent < Size){
Diff = Size - Sent;
if(Diff > Split){
Chunk = new char[Split];
memcpy_s(Chunk,Split,Data+Sent,Split);
STCPSend(c,Chunk,Split);
Sent += Split;
}else{
Chunk = new char[Diff];
memcpy_s(Chunk,Diff,Data+Sent,Diff);
STCPSend(c,Chunk,Diff);
Sent += Diff;
}
}
delete[] Data;
delete[] Chunk;
}
void Parse(Client*c,char*data){
std::string Packet = data;
if(Packet.empty())return;
char Code = Packet.at(0),SubCode = 0;
if(Packet.length() > 1)SubCode = Packet.at(1);
switch (Code) {
case 'f':
SendFile(c,Packet.substr(1));
return;
case 'S':
if(SubCode == 'R'){
std::cout << "Sending File Info" << std::endl;
STCPSend(c,FileList+FileSizes,0);
}
return;
case 'N':
if(SubCode == 'R'){
c->SetName(Packet.substr(2,Packet.find(':')-2));
c->SetDID(Packet.substr(Packet.find(':')+1));
GrabRole(c);
}
std::cout << "Name : " << c->GetName() << std::endl;
return;
}
}
bool STCPRecv(Client*c){
char buf[200];
int len = 200;
ZeroMemory(buf, len);
int BytesRcv = recv(c->GetTCPSock(), buf, len,0);
if (BytesRcv == 0){
std::cout << "(TCP) Connection closing..." << std::endl;
if(c->GetStatus() > -1)c->SetStatus(-1);
return false;
}
else if (BytesRcv < 0) {
std::cout << "(TCP) recv failed with error: " << WSAGetLastError() << std::endl;
if(c->GetStatus() > -1)c->SetStatus(-1);
closesocket(c->GetTCPSock());
return false;
}
if(strcmp(buf,"Done") == 0)return false;
char* Ret = new char[BytesRcv];
memcpy_s(Ret,BytesRcv,buf,BytesRcv);
ZeroMemory(buf, len);
Parse(c,Ret);
return true;
}
void SyncResources(Client*c){
while(c->GetStatus() > -1 && STCPRecv(c));
}

View File

@ -5,7 +5,7 @@
#include <algorithm> #include <algorithm>
#include <filesystem> #include <filesystem>
namespace fs = std::experimental::filesystem; namespace fs = std::filesystem;
std::string FileList; std::string FileList;
std::string FileSizes; std::string FileSizes;
@ -13,12 +13,12 @@ std::string FileSizes;
void LuaMain(std::string Path); void LuaMain(std::string Path);
void HandleResources(std::string path){ void HandleResources(std::string path){
struct stat info{}; struct stat info{};
if(stat( path.c_str(), &info) != 0){ if(stat(path.c_str(), &info) != 0){
fs::create_directory(path); fs::create_directory(path);
} }
LuaMain(path); LuaMain(path);
path += "/Client"; path += "/Client";
if(stat( path.c_str(), &info) != 0) { if(stat(path.c_str(), &info) != 0) {
fs::create_directory(path); fs::create_directory(path);
} }
for (const auto & entry : fs::directory_iterator(path)){ for (const auto & entry : fs::directory_iterator(path)){

View File

@ -8,12 +8,12 @@
#include "logger.h" #include "logger.h"
void GenerateConfig(); void GenerateConfig();
string RemoveComments(const string& Line); std::string RemoveComments(const std::string& Line);
void SetValues(const string& Line, int Index); void SetValues(const std::string& Line, int Index);
string MapName = "/levels/gridmap/info.json"; std::string MapName = "/levels/gridmap/info.json";
string ServerName = "BeamMP Server"; std::string ServerName = "BeamMP Server";
string Resource = "Resources"; std::string Resource = "Resources";
string Key; std::string Key;
bool Private = false; bool Private = false;
bool Debug = false; bool Debug = false;
int MaxPlayers = 10; int MaxPlayers = 10;
@ -22,15 +22,15 @@ int MaxCars = 1;
//Generates or Reads Config //Generates or Reads Config
void ParseConfig(){ void ParseConfig(){
ifstream InFileStream; std::ifstream InFileStream;
InFileStream.open("Server.cfg"); InFileStream.open("Server.cfg");
if(InFileStream.good()){ //Checks if Config Exists if(InFileStream.good()){ //Checks if Config Exists
info("Config Found Updating Values"); info("Config Found Updating Values");
string line; std::string line;
int index = 1; int index = 1;
while (getline(InFileStream, line)) { while (getline(InFileStream, line)) {
if(line.rfind('#', 0) != 0){ //Checks if it starts as Comment if(line.rfind('#', 0) != 0){ //Checks if it starts as Comment
string CleanLine = RemoveComments(line); //Cleans it from the Comments std::string CleanLine = RemoveComments(line); //Cleans it from the Comments
SetValues(CleanLine,index); //sets the values SetValues(CleanLine,index); //sets the values
index++; index++;
} }
@ -44,7 +44,7 @@ void ParseConfig(){
void SetValues(const string& Line, int Index) { void SetValues(const std::string& Line, int Index) {
int i = 0, state = 0; int i = 0, state = 0;
char Data[50] = ""; char Data[50] = "";
bool Switch = false; bool Switch = false;
@ -67,18 +67,18 @@ void SetValues(const string& Line, int Index) {
for (int C = 1; C <= i; C++){ for (int C = 1; C <= i; C++){
Data[C-1] = Data[C]; Data[C-1] = Data[C];
} }
string::size_type sz; std::string::size_type sz;
bool Boolean = std::string(Data).find("true") != string::npos;//searches for "true" bool Boolean = std::string(Data).find("true") != std::string::npos;//searches for "true"
switch (Index){ switch (Index){
case 1 : Debug = Boolean;//checks and sets the Debug Value case 1 : Debug = Boolean;//checks and sets the Debug Value
break; break;
case 2 : Private = Boolean;//checks and sets the Private Value case 2 : Private = Boolean;//checks and sets the Private Value
break; break;
case 3 : Port = stoi(Data, &sz);//sets the Port case 3 : Port = std::stoi(Data, &sz);//sets the Port
break; break;
case 4 : MaxCars = stoi(Data, &sz);//sets the Max Car amount case 4 : MaxCars = std::stoi(Data, &sz);//sets the Max Car amount
break; break;
case 5 : MaxPlayers = stoi(Data, &sz); //sets the Max Amount of player case 5 : MaxPlayers = std::stoi(Data, &sz); //sets the Max Amount of player
break; break;
case 6 : MapName = Data; //Map case 6 : MapName = Data; //Map
break; break;
@ -94,7 +94,7 @@ void SetValues(const string& Line, int Index) {
//generates default Config //generates default Config
void GenerateConfig(){ void GenerateConfig(){
ofstream FileStream; std::ofstream FileStream;
FileStream.open ("Server.cfg"); FileStream.open ("Server.cfg");
FileStream << "# This is the BeamMP Server Configuration File\n" FileStream << "# This is the BeamMP Server Configuration File\n"
"Debug = false # true or false to enable debug console output\n" "Debug = false # true or false to enable debug console output\n"
@ -110,7 +110,7 @@ void GenerateConfig(){
} }
string RemoveComments(const string& Line){ std::string RemoveComments(const std::string& Line){
int i = 0; int i = 0;
char Data[50] = ""; char Data[50] = "";
for(char c : Line) { for(char c : Line) {

View File

@ -9,7 +9,7 @@
#include "Settings.hpp" #include "Settings.hpp"
#include "Network 2.0/Client.hpp" #include "Network 2.0/Client.hpp"
string HTTP_REQUEST(const std::string&,int); std::string HTTP_REQUEST(const std::string&,int);
std::string PostHTTP(const std::string& IP,const std::string& Fields); std::string PostHTTP(const std::string& IP,const std::string& Fields);
std::string HTA(const std::string& hex) std::string HTA(const std::string& hex)
{ {
@ -29,8 +29,8 @@ void Heartbeat()
while(true) while(true)
{ {
State = Private ? "true" : "false"; State = Private ? "true" : "false";
R = "uuid="+Key+"&players="+to_string(Clients.size())+"&maxplayers="+to_string(MaxPlayers)+"&port=" R = "uuid="+Key+"&players="+std::to_string(Clients.size())+"&maxplayers="+std::to_string(MaxPlayers)+"&port="
+ to_string(Port) + "&map=" + MapName + "&private="+State+"&version="+ServerVersion+ + std::to_string(Port) + "&map=" + MapName + "&private="+State+"&version="+ServerVersion+
"&clientversion="+ClientVersion+"&name="+ServerName; "&clientversion="+ClientVersion+"&name="+ServerName;
if(!CustomIP.empty())R+="&ip="+CustomIP; if(!CustomIP.empty())R+="&ip="+CustomIP;
// https://beamng-mp.com/heartbeatv2 // https://beamng-mp.com/heartbeatv2

View File

@ -7,7 +7,6 @@
#include "logger.h" #include "logger.h"
#include <string> #include <string>
void addToLog(const std::string& Data); void addToLog(const std::string& Data);
using namespace std;
int loggerlevel; int loggerlevel;
void setLoggerLevel(int level) { void setLoggerLevel(int level) {
@ -15,7 +14,7 @@ void setLoggerLevel(int level) {
loggerlevel = level; loggerlevel = level;
} }
stringstream getDate() { std::stringstream getDate() {
// current date/time based on current system // current date/time based on current system
time_t now = time(nullptr); time_t now = time(nullptr);
tm* ltm = localtime(&now); tm* ltm = localtime(&now);
@ -26,25 +25,25 @@ stringstream getDate() {
int minutes = ltm->tm_min; int minutes = ltm->tm_min;
int seconds = ltm->tm_sec; int seconds = ltm->tm_sec;
string month_string; std::string month_string;
if (month < 10) month_string = "0" + to_string(month); if (month < 10) month_string = "0" + std::to_string(month);
else month_string = to_string(month); else month_string = std::to_string(month);
string day_string; std::string day_string;
if (day < 10) day_string = "0" + to_string(day); if (day < 10) day_string = "0" + std::to_string(day);
else day_string = to_string(day); else day_string = std::to_string(day);
string hours_string; std::string hours_string;
if (hours < 10) hours_string = "0" + to_string(hours); if (hours < 10) hours_string = "0" + std::to_string(hours);
else hours_string = to_string(hours); else hours_string = std::to_string(hours);
string minutes_string; std::string minutes_string;
if (minutes < 10) minutes_string = "0" + to_string(minutes); if (minutes < 10) minutes_string = "0" + std::to_string(minutes);
else minutes_string = to_string(minutes); else minutes_string = std::to_string(minutes);
string seconds_string; std::string seconds_string;
if (seconds < 10) seconds_string = "0" + to_string(seconds); if (seconds < 10) seconds_string = "0" + std::to_string(seconds);
else seconds_string = to_string(seconds); else seconds_string = std::to_string(seconds);
std::stringstream date; std::stringstream date;
date date
@ -62,14 +61,14 @@ stringstream getDate() {
void info(const std::string& toPrint) { void info(const std::string& toPrint) {
if (loggerlevel <= 2){ if (loggerlevel <= 2){
cout << getDate().str() << "[INFO] " << toPrint << endl; std::cout << getDate().str() << "[INFO] " << toPrint << std::endl;
addToLog(getDate().str() + "[INFO] " + toPrint + "\n"); addToLog(getDate().str() + "[INFO] " + toPrint + "\n");
} }
} }
void error(const std::string& toPrint) { void error(const std::string& toPrint) {
if (loggerlevel <= 4) { if (loggerlevel <= 4) {
cout << getDate().str() << "[ERROR] " << toPrint << endl; std::cout << getDate().str() << "[ERROR] " << toPrint << std::endl;
addToLog(getDate().str() + "[ERROR] " + toPrint + "\n"); addToLog(getDate().str() + "[ERROR] " + toPrint + "\n");
} }
} }
@ -77,7 +76,7 @@ void error(const std::string& toPrint) {
void warn(const std::string& toPrint) { void warn(const std::string& toPrint) {
if (loggerlevel <= 3) { if (loggerlevel <= 3) {
cout << getDate().str() << "[WARN] " << toPrint << endl; std::cout << getDate().str() << "[WARN] " << toPrint << std::endl;
addToLog(getDate().str() + "[WARN] " + toPrint + "\n"); addToLog(getDate().str() + "[WARN] " + toPrint + "\n");
} }
} }
@ -85,7 +84,7 @@ void warn(const std::string& toPrint) {
void debug(const std::string& toPrint) { void debug(const std::string& toPrint) {
if (loggerlevel <= 1) { if (loggerlevel <= 1) {
cout << getDate().str() << "[DEBUG] " << toPrint << endl; std::cout << getDate().str() << "[DEBUG] " << toPrint << std::endl;
addToLog(getDate().str() + "[DEBUG] " + toPrint + "\n"); addToLog(getDate().str() + "[DEBUG] " + toPrint + "\n");
} }
} }

View File

@ -6,9 +6,8 @@
#include <ctime> #include <ctime>
#include <sstream> #include <sstream>
#include <string.h> #include <string.h>
using namespace std;
extern int loggerlevel; extern int loggerlevel;
stringstream getDate(); std::stringstream getDate();
void setLoggerLevel(int level); void setLoggerLevel(int level);
void info(const std::string& toPrint); void info(const std::string& toPrint);
void warn(const std::string& toPrint); void warn(const std::string& toPrint);

View File

@ -14,7 +14,7 @@
void DebugData(); void DebugData();
void LogInit(); void LogInit();
void ParseConfig(); void ParseConfig();
void addToLog(const string& Data); void addToLog(const std::string& Data);
//void ServerMain(int Port, int MaxClients); //void ServerMain(int Port, int MaxClients);
void HeartbeatInit(); void HeartbeatInit();
std::string ServerVersion = "0.3"; std::string ServerVersion = "0.3";
@ -49,11 +49,11 @@ int main(int argc, char* argv[]) {
void DebugData(){ void DebugData(){
debug(string("Debug : ") + (Debug?"true":"false")); debug(std::string("Debug : ") + (Debug?"true":"false"));
debug(string("Private : ") + (Private?"true":"false")); debug(std::string("Private : ") + (Private?"true":"false"));
debug("Port : " + to_string(Port)); debug("Port : " + std::to_string(Port));
debug("Max Cars : " + to_string(MaxCars)); debug("Max Cars : " + std::to_string(MaxCars));
debug("MaxPlayers : " + to_string(MaxPlayers)); debug("MaxPlayers : " + std::to_string(MaxPlayers));
debug("MapName : " + MapName); debug("MapName : " + MapName);
debug("ServerName : " + ServerName ); debug("ServerName : " + ServerName );
debug("File : " + Resource); debug("File : " + Resource);
@ -62,13 +62,13 @@ void DebugData(){
void LogInit(){ void LogInit(){
ofstream LFS; std::ofstream LFS;
LFS.open ("Server.log"); LFS.open ("Server.log");
LFS.close(); LFS.close();
} }
void addToLog(const string& Data){ void addToLog(const std::string& Data){
ofstream LFS; std::ofstream LFS;
LFS.open ("Server.log", std::ios_base::app); LFS.open ("Server.log", std::ios_base::app);
LFS << Data.c_str(); LFS << Data.c_str();
LFS.close(); LFS.close();