diff --git a/include/Client.hpp b/include/Client.hpp index 310c320..11f5c1f 100644 --- a/include/Client.hpp +++ b/include/Client.hpp @@ -3,7 +3,12 @@ /// #pragma once +#ifdef __WIN32 #include +#else +#include +#define SOCKET int +#endif #include "Buffer.h" #include #include @@ -67,4 +72,4 @@ struct ClientInterface{ } }; -extern ClientInterface* CI; \ No newline at end of file +extern ClientInterface* CI; diff --git a/include/Lua/LuaSystem.hpp b/include/Lua/LuaSystem.hpp index e7f1461..1bf5a43 100644 --- a/include/Lua/LuaSystem.hpp +++ b/include/Lua/LuaSystem.hpp @@ -11,7 +11,9 @@ #include #include #include -namespace fs = std::experimental::filesystem; + +namespace fs = std::filesystem; + struct LuaArg{ std::vector args; void PushArgs(lua_State *State){ @@ -64,4 +66,4 @@ public: }; int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* args); int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg,bool Wait); -extern std::set PluginEngine; \ No newline at end of file +extern std::set PluginEngine; diff --git a/include/Security/Enc.h b/include/Security/Enc.h index e418232..02bd72a 100644 --- a/include/Security/Enc.h +++ b/include/Security/Enc.h @@ -2,7 +2,11 @@ /// Created by Anonymous275 on 7/28/2020 /// #pragma once +#ifdef __linux +#define EXCEPTION_POINTERS void +#else #include +#endif #include #include "Xor.h" struct RSA{ diff --git a/include/Security/Xor.h b/include/Security/Xor.h index a7b2874..d4f0d91 100644 --- a/include/Security/Xor.h +++ b/include/Security/Xor.h @@ -5,6 +5,7 @@ #include #include #include +#include #define BEGIN_NAMESPACE(x) namespace x { #define END_NAMESPACE } @@ -68,10 +69,10 @@ BEGIN_NAMESPACE(XorCompileTime) public: template - constexpr __forceinline XorString(const Char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... } + constexpr inline XorString(const Char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... } {} - __forceinline decltype(auto) decrypt(){ + inline decltype(auto) decrypt(){ for (size_t i = 0; i < N; ++i) { _encrypted[i] = dec(_encrypted[i]); } @@ -83,14 +84,14 @@ BEGIN_NAMESPACE(XorCompileTime) static auto w_printf = [](const char* fmt, ...) { va_list args; va_start(args, fmt); - vprintf_s(fmt, args); + vprintf(fmt, args); va_end(args); }; static auto w_printf_s = [](const char* fmt, ...) { va_list args; va_start(args, fmt); - vprintf_s(fmt, args); + vprintf(fmt, args); va_end(args); }; @@ -113,7 +114,7 @@ BEGIN_NAMESPACE(XorCompileTime) static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) { va_list args; va_start(args, fmt); - vsprintf_s(buf, buf_size, fmt, args); + vsnprintf(buf, buf_size, fmt, args); va_end(args); }; @@ -121,7 +122,7 @@ BEGIN_NAMESPACE(XorCompileTime) int ret; va_list args; va_start(args, fmt); - ret = vsprintf_s(buf, buf_size, fmt, args); + ret = vsnprintf(buf, buf_size, fmt, args); va_end(args); return ret; }; diff --git a/include/UnixCompat.h b/include/UnixCompat.h new file mode 100644 index 0000000..a5d23e1 --- /dev/null +++ b/include/UnixCompat.h @@ -0,0 +1,30 @@ +// Author: lionkor + +#pragma once + +// This header defines unix equivalents of common win32 functions. + +#ifndef __WIN32 + +#include +#include +#include + +// ZeroMemory is just a {0} or a memset(addr, 0, len), and it's a macro on MSVC +inline void ZeroMemory(void* dst, size_t len) { + assert(std::memset(dst, 0, len) != nullptr); +} +// provides unix equivalent of closesocket call in win32 +inline void closesocket(int socket) { + close(socket); +} + +#ifndef __try +#define __try +#endif + +#ifndef __except +#define __except(x) /**/ +#endif + +#endif // __WIN32 diff --git a/src/Compressor.cpp b/src/Compressor.cpp index 9733650..65e7630 100644 --- a/src/Compressor.cpp +++ b/src/Compressor.cpp @@ -3,11 +3,15 @@ /// #include "Zlib/zlib.h" #include +#include +#include +#include #define Biggest 30000 std::string Comp(std::string Data){ - char*C = new char[Biggest]; - memset(C, 0, Biggest); + std::array C; + // obsolete + C.fill(0); z_stream defstream; defstream.zalloc = Z_NULL; defstream.zfree = Z_NULL; @@ -15,20 +19,20 @@ std::string Comp(std::string Data){ defstream.avail_in = (uInt)Data.length(); defstream.next_in = (Bytef *)&Data[0]; defstream.avail_out = Biggest; - defstream.next_out = reinterpret_cast(C); + defstream.next_out = reinterpret_cast(C.data()); deflateInit(&defstream, Z_BEST_COMPRESSION); deflate(&defstream, Z_SYNC_FLUSH); deflate(&defstream, Z_FINISH); deflateEnd(&defstream); int TO = defstream.total_out; std::string Ret(TO,0); - memcpy_s(&Ret[0],TO,C,TO); - delete [] C; + std::copy_n(C.begin(), TO, Ret.begin()); return Ret; } std::string DeComp(std::string Compressed){ - char*C = new char[Biggest]; - memset(C, 0, Biggest); + std::array C; + // not needed + C.fill(0); z_stream infstream; infstream.zalloc = Z_NULL; infstream.zfree = Z_NULL; @@ -36,14 +40,13 @@ std::string DeComp(std::string Compressed){ infstream.avail_in = Biggest; infstream.next_in = (Bytef *)(&Compressed[0]); infstream.avail_out = Biggest; - infstream.next_out = (Bytef *)(C); + infstream.next_out = (Bytef *)(C.data()); inflateInit(&infstream); inflate(&infstream, Z_SYNC_FLUSH); inflate(&infstream, Z_FINISH); inflateEnd(&infstream); int TO = infstream.total_out; std::string Ret(TO,0); - memcpy_s(&Ret[0],TO,C,TO); - delete [] C; + std::copy_n(C.begin(), TO, Ret.begin()); return Ret; -} \ No newline at end of file +} diff --git a/src/Console.cpp b/src/Console.cpp index 1d01193..b78ba6c 100644 --- a/src/Console.cpp +++ b/src/Console.cpp @@ -3,10 +3,14 @@ /// #include "Lua/LuaSystem.hpp" +#ifdef __WIN32 #include +#include +#else // *nix +typedef unsigned long DWORD, *PDWORD, *LPDWORD; +#endif // __WIN32 #include "Logger.h" #include -#include #include #include #include @@ -47,6 +51,7 @@ void ConsoleOut(const std::string& msg){ } } void SetupConsole(){ +#ifdef __WIN32 DWORD outMode = 0; HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); if (stdoutHandle == INVALID_HANDLE_VALUE){ @@ -66,10 +71,11 @@ void SetupConsole(){ std::this_thread::sleep_for(std::chrono::seconds(3)); exit(GetLastError()); } +#endif // __WIN32 } [[noreturn]] void ReadCin(){ while (true){ - int In = _getch(); + int In = getchar(); if (In == 13) { if(!CInputBuff.empty()) { HandleInput(CInputBuff); @@ -90,4 +96,4 @@ void ConsoleInit(){ In.detach(); std::thread Out(OutputRefresh); Out.detach(); -} \ No newline at end of file +} diff --git a/src/Enc.cpp b/src/Enc.cpp index e2ec495..4c7d12f 100644 --- a/src/Enc.cpp +++ b/src/Enc.cpp @@ -3,11 +3,12 @@ /// #include "Security/Enc.h" #include "Settings.h" -#include +//#include #include "Logger.h" #include #include #include +#include int Rand(){ std::random_device r; @@ -85,9 +86,10 @@ int Dec(int value,int d,int n){ } int Handle(EXCEPTION_POINTERS *ep,char* Origin){ + assert(false); std::stringstream R; R << Sec("Code : ") << std::hex - << ep->ExceptionRecord->ExceptionCode + //<< ep->ExceptionRecord->ExceptionCode << std::dec << Sec(" Origin : ") << Origin; except(R.str()); return 1; @@ -116,4 +118,4 @@ std::string RSA_D(const std::string& Data, RSA*k){ ret += char(Dec(c,k->d,k->n)); } return ret; -} \ No newline at end of file +} diff --git a/src/Init/Resources.cpp b/src/Init/Resources.cpp index 233f192..06f7500 100644 --- a/src/Init/Resources.cpp +++ b/src/Init/Resources.cpp @@ -6,7 +6,9 @@ #include "Settings.h" #include #include "Logger.h" -namespace fs = std::experimental::filesystem; + +namespace fs = std::filesystem; + uint64_t MaxModSize = 0; std::string FileSizes; std::string FileList; @@ -30,4 +32,4 @@ void InitRes(){ if(ModsLoaded){ info(Sec("Loaded ")+std::to_string(ModsLoaded)+Sec(" Mods")); } -} \ No newline at end of file +} diff --git a/src/Init/Startup.cpp b/src/Init/Startup.cpp index 7e7a7ee..cf4f70e 100644 --- a/src/Init/Startup.cpp +++ b/src/Init/Startup.cpp @@ -5,6 +5,7 @@ #include "Client.hpp" #include "Logger.h" #include +#include std::string CustomIP; std::string GetSVer(){ @@ -31,4 +32,4 @@ void InitServer(int argc, char* argv[]){ InitLog(); Args(argc,argv); CI = new ClientInterface; -} \ No newline at end of file +} diff --git a/src/Lua/LuaMain.cpp b/src/Lua/LuaMain.cpp index f788c91..d155725 100644 --- a/src/Lua/LuaMain.cpp +++ b/src/Lua/LuaMain.cpp @@ -8,6 +8,11 @@ #include "Logger.h" #include +#ifdef __linux +// we need this for `struct stat` +#include +#endif // __linux + std::set PluginEngine; bool NewFile(const std::string&Path){ for(Lua*Script : PluginEngine){ diff --git a/src/Lua/LuaSystem.cpp b/src/Lua/LuaSystem.cpp index 1d7e44c..bae4c78 100644 --- a/src/Lua/LuaSystem.cpp +++ b/src/Lua/LuaSystem.cpp @@ -8,6 +8,7 @@ #include "Settings.h" #include "Network.h" #include "Logger.h" +#include "UnixCompat.h" #include #include #include @@ -134,7 +135,7 @@ char* ThreadOrigin(Lua*lua){ std::string T = "Thread in " + lua->GetFileName().substr(lua->GetFileName().find('\\')); char* Data = new char[T.size()+1]; ZeroMemory(Data,T.size()+1); - memcpy_s(Data,T.size(),T.c_str(),T.size()); + memcpy(Data, T.c_str(),T.size()); return Data; } void SafeExecution(Lua* lua,const std::string& FuncName){ @@ -142,10 +143,15 @@ void SafeExecution(Lua* lua,const std::string& FuncName){ lua_getglobal(luaState, FuncName.c_str()); if(lua_isfunction(luaState, -1)) { char* Origin = ThreadOrigin(lua); +#ifdef __WIN32 __try{ int R = lua_pcall(luaState, 0, 0, 0); CheckLua(luaState, R); }__except(Handle(GetExceptionInformation(),Origin)){} +#else // unix + int R = lua_pcall(luaState, 0, 0, 0); + CheckLua(luaState, R); +#endif // __WIN32 delete [] Origin; } ClearStack(luaState); @@ -492,7 +498,7 @@ char* Lua::GetOrigin(){ std::string T = GetFileName().substr(GetFileName().find('\\')); char* Data = new char[T.size()]; ZeroMemory(Data,T.size()); - memcpy_s(Data,T.size(),T.c_str(),T.size()); + memcpy(Data,T.c_str(),T.size()); return Data; } int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){ @@ -508,14 +514,18 @@ int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){ } int R = 0; char* Origin = lua->GetOrigin(); +#ifdef __WIN32 __try{ +#endif // __WIN32 R = lua_pcall(luaState, Size, 1, 0); if (CheckLua(luaState, R)){ if (lua_isnumber(luaState, -1)) { return int(lua_tointeger(luaState, -1)); } } +#ifdef __WIN32 }__except(Handle(GetExceptionInformation(),Origin)){} +#endif // __WIN32 delete [] Origin; } ClearStack(luaState); diff --git a/src/Network/Auth.cpp b/src/Network/Auth.cpp index ed3f7bc..4bc7ddb 100644 --- a/src/Network/Auth.cpp +++ b/src/Network/Auth.cpp @@ -8,6 +8,10 @@ #include "Logger.h" #include #include +#include +#include "UnixCompat.h" + + struct Hold{ SOCKET TCPSock{}; bool Done = false; @@ -148,17 +152,31 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*Skey){ void Identify(SOCKET TCPSock){ auto* S = new Hold; RSA*Skey = GenKey(); + // this disgusting ifdef stuff is needed because for some + // reason MSVC defines __try and __except and libg++ defines + // __try and __catch so its all a big mess if we leave this in or undefine + // the macros +#ifdef __WIN32 __try{ +#endif // __WIN32 Identification(TCPSock,S,Skey); +#ifdef __WIN32 }__except(1){ +#endif // __WIN32 + if(TCPSock != -1){ closesocket(TCPSock); } +#ifdef __WIN32 } +#endif // __WIN32 + delete Skey; delete S; } + void TCPServerMain(){ +#ifdef __WIN32 WSADATA wsaData; if (WSAStartup(514, &wsaData)){ error(Sec("Can't start Winsock!")); @@ -195,4 +213,38 @@ void TCPServerMain(){ closesocket(client); WSACleanup(); -} \ No newline at end of file +#else // unix + // wondering why we need slightly different implementations of this? + // ask ms. + SOCKET client, Listener = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + sockaddr_in addr{}; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + addr.sin_port = htons(Port); + if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) != 0){ + error(Sec("Can't bind socket! ") + std::string(strerror(errno))); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(-1); + } + if(Listener == -1){ + error(Sec("Invalid listening socket")); + return; + } + if(listen(Listener,SOMAXCONN)){ + error(Sec("listener failed ")+ std::string(strerror(errno))); + return; + } + info(Sec("Vehicle event network online")); + do{ + client = accept(Listener, nullptr, nullptr); + if(client == -1){ + warn(Sec("Got an invalid client socket on connect! Skipping...")); + continue; + } + std::thread ID(Identify,client); + ID.detach(); + }while(client); + + closesocket(client); +#endif // __WIN32 +} diff --git a/src/Network/GParser.cpp b/src/Network/GParser.cpp index 60f40ad..a22f483 100644 --- a/src/Network/GParser.cpp +++ b/src/Network/GParser.cpp @@ -7,8 +7,10 @@ #include "Settings.h" #include "Network.h" #include "Logger.h" +#include "UnixCompat.h" #include + int FC(const std::string& s,const std::string& p,int n) { auto i = s.find(p); int j; @@ -116,10 +118,14 @@ void SyncClient(Client*c){ } info(c->GetName() + Sec(" is now synced!")); } -void ParseVeh(Client*c, const std::string&Packet){ +void ParseVeh(Client*c, const std::string& Packet){ +#ifdef __WIN32 __try{ VehicleParser(c,Packet); }__except(Handle(GetExceptionInformation(),Sec("Vehicle Handler"))){} +#else // unix + VehicleParser(c,Packet); +#endif // __WIN32 } void HandleEvent(Client*c ,const std::string&Data){ @@ -189,8 +195,12 @@ void GlobalParser(Client*c, const std::string& Pack){ } } -void GParser(Client*c, const std::string&Packet){ +void GParser(Client*c, const std::string& Packet){ +#ifdef __WIN32 __try{ GlobalParser(c, Packet); }__except(Handle(GetExceptionInformation(),Sec("Global Handler"))){} -} \ No newline at end of file +#else + GlobalParser(c, Packet); +#endif // __WIN32 +} diff --git a/src/Network/Sync.cpp b/src/Network/Sync.cpp index 0431d78..137a6cd 100644 --- a/src/Network/Sync.cpp +++ b/src/Network/Sync.cpp @@ -5,8 +5,14 @@ #include "Client.hpp" #include "Settings.h" #include "Logger.h" +#include "UnixCompat.h" #include +#ifdef __linux +// we need this for `struct stat` +#include +#endif // __linux + void STCPSend(Client*c,std::string Data){ if(c == nullptr)return; int BytesSent; @@ -100,4 +106,4 @@ void SyncResources(Client*c){ except(Sec("Exception! : ") + std::string(e.what())); c->SetStatus(-1); } -} \ No newline at end of file +} diff --git a/src/Network/TCPHandler.cpp b/src/Network/TCPHandler.cpp index 630c180..fcc8f3a 100644 --- a/src/Network/TCPHandler.cpp +++ b/src/Network/TCPHandler.cpp @@ -4,6 +4,7 @@ #include "Security/Enc.h" #include "Network.h" #include "Logger.h" +#include "UnixCompat.h" #include void TCPSend(Client*c,const std::string&Data){ @@ -18,11 +19,15 @@ void TCPSend(Client*c,const std::string&Data){ } } void TCPHandle(Client*c,const std::string& data){ +#ifdef __WIN32 __try{ +#endif // __WIN32 c->Handler.Handle(c,data); +#ifdef __WIN32 }__except(1){ c->Handler.clear(); } +#endif // __WIN32 } void TCPRcv(Client*c){ if(c == nullptr || c->GetStatus() < 0)return; @@ -35,7 +40,11 @@ void TCPRcv(Client*c){ if(c->GetStatus() > -1)c->SetStatus(-1); return; }else if (BytesRcv < 0) { +#ifdef __WIN32 debug(Sec("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError())); +#else // unix + debug(Sec("(TCP) recv failed with error: ") + std::string(strerror(errno))); +#endif // __WIN32 if(c->GetStatus() > -1)c->SetStatus(-1); closesocket(c->GetTCPSock()); return; @@ -50,11 +59,15 @@ void TCPClient(Client*c){ } OnConnect(c); while (c->GetStatus() > -1)TCPRcv(c); +#ifdef __WIN32 __try{ +#endif // __WIN32 OnDisconnect(c, c->GetStatus() == -2); +#ifdef __WIN32 }__except(Handle(GetExceptionInformation(),Sec("OnDisconnect"))){} +#endif // __WIN32 } void InitClient(Client*c){ std::thread NewClient(TCPClient,c); NewClient.detach(); -} \ No newline at end of file +} diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp index 4680642..64a8743 100644 --- a/src/Network/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -8,14 +8,17 @@ #include "Settings.h" #include "Network.h" #include "Logger.h" +#include "UnixCompat.h" #include #include #include #include +#include +#include int FC(const std::string& s,const std::string& p,int n); struct PacketData{ int ID; - Client* Client; + ::Client* Client; std::string Data; int Tries; }; @@ -38,10 +41,17 @@ void UDPSend(Client*c,std::string Data){ Data = "ABG:" + CMP; } int sendOk = sendto(UDPSock, Data.c_str(), int(Data.size()), 0, (sockaddr *) &Addr, AddrSize); - if (sendOk == SOCKET_ERROR) { +#ifdef __WIN32 + if (sendOk != 0) { debug(Sec("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError())); if(c->GetStatus() > -1)c->SetStatus(-1); } +#else // unix + if (sendOk != 0) { + debug(Sec("(UDP) Send Failed Code : ") + std::string(strerror(errno))); + if(c->GetStatus() > -1)c->SetStatus(-1); + } +#endif // __WIN32 } void AckID(int ID){ @@ -144,9 +154,13 @@ std::string UDPRcvFromClient(sockaddr_in& client){ int clientLength = sizeof(client); ZeroMemory(&client, clientLength); std::string Ret(10240,0); - int Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&client, &clientLength); + int Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&client, (socklen_t*)&clientLength); if (Rcv == -1){ +#ifdef __WIN32 error(Sec("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError())); +#else // unix + error(Sec("(UDP) Error receiving from Client! Code : ") + std::string(strerror(errno))); +#endif // __WIN32 return ""; } return Ret; @@ -240,6 +254,7 @@ void LOOP(){ } } [[noreturn]] void UDPServerMain(){ +#ifdef __WIN32 WSADATA data; if (WSAStartup(514, &data)){ error(Sec("Can't start Winsock!")); @@ -286,4 +301,46 @@ void LOOP(){ /*closesocket(UDPSock); WSACleanup(); return;*/ -} \ No newline at end of file +#else // unix + UDPSock = socket(AF_INET, SOCK_DGRAM, 0); + // Create a server hint structure for the server + sockaddr_in serverAddr{}; + serverAddr.sin_addr.s_addr = INADDR_ANY; //Any Local + serverAddr.sin_family = AF_INET; // Address format is IPv4 + serverAddr.sin_port = htons(Port); // Convert from little to big endian + + // Try and bind the socket to the IP and port + if (bind(UDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) != 0){ + error(Sec("Can't bind socket!") + std::string(strerror(errno))); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(-1); + //return; + } + + DataAcks.clear(); + 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){ + sockaddr_in client{}; + std::string Data = UDPRcvFromClient(client); //Receives any data from Socket + auto Pos = Data.find(':'); + if(Data.empty() || Pos < 0 || Pos > 2)continue; + /*char clientIp[256]; + ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet + inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/ + uint8_t ID = Data.at(0)-1; + for(Client*c : CI->Clients){ + if(c != nullptr && c->GetID() == ID){ + c->SetUDPAddr(client); + c->isConnected = true; + UDPParser(c,Data.substr(2)); + } + } + } + /*closesocket(UDPSock); // TODO: Why not this? We did this in TCPServerMain? + return; + */ +#endif // __WIN32 +} diff --git a/src/logger.cpp b/src/logger.cpp index 222e038..72020df 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -19,7 +19,11 @@ std::string getDate() { auto s = std::chrono::duration_cast(tp);tp -= s; time_t tt = std::chrono::system_clock::to_time_t(now); tm local_tm{}; +#ifdef __WIN32 localtime_s(&local_tm,&tt); +#else // unix + localtime_r(&tt, &local_tm); +#endif // __WIN32 std::stringstream date; int S = local_tm.tm_sec; int M = local_tm.tm_min;