mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
commit
b49abe02eb
5
.clang-format
Normal file
5
.clang-format
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
BasedOnStyle: WebKit
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
|
||||||
|
...
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -459,3 +459,4 @@ out/build/x86-Debug/.cmake/api/v1/reply/target-cmake-main-Debug-540e487569703b71
|
|||||||
out/build/x86-Debug/.cmake/api/v1/reply/index-2020-01-28T17-35-38-0764.json
|
out/build/x86-Debug/.cmake/api/v1/reply/index-2020-01-28T17-35-38-0764.json
|
||||||
out/build/x86-Debug/.cmake/api/v1/reply/codemodel-v2-6a61e390ef8eaf17e9f8.json
|
out/build/x86-Debug/.cmake/api/v1/reply/codemodel-v2-6a61e390ef8eaf17e9f8.json
|
||||||
out/build/x86-Debug/Server.cfg
|
out/build/x86-Debug/Server.cfg
|
||||||
|
*Server.cfg*
|
||||||
|
@ -1,9 +1,28 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(Server)
|
project(Server)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -g")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -s")
|
||||||
|
elseif (WIN32)
|
||||||
|
# This might cause issues with old windows headers, but it's worth the trouble to keep the code
|
||||||
|
# completely cross platform. For fixes to common issues arising from /permissive- visit:
|
||||||
|
# https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /permissive-")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
find_package(Boost 1.71.0 REQUIRED COMPONENTS system thread)
|
||||||
file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "include/*.h" "include/*/*.h" "include/*.hpp" "include/*/*.hpp")
|
file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "include/*.h" "include/*/*.h" "include/*.hpp" "include/*/*.hpp")
|
||||||
add_executable(${PROJECT_NAME} ${source_files})
|
add_executable(BeamMP-Server ${source_files})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Server")
|
target_include_directories(BeamMP-Server PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> ${Boost_INCLUDE_DIRS})
|
||||||
target_link_libraries(${PROJECT_NAME} libcurl_a urlmon ws2_32 lua53 zlibstatic)
|
|
||||||
|
if (UNIX)
|
||||||
|
target_link_libraries(BeamMP-Server curl lua5.3 krb5 z pthread stdc++fs ${Boost_LINK_DIRS})
|
||||||
|
elseif (WIN32)
|
||||||
|
target_link_libraries(BeamMP-Server libcurl_a urlmon ws2_32 lua53 zlibstatic ${Boost_LINK_DIRS})
|
||||||
|
endif ()
|
||||||
|
@ -3,12 +3,13 @@
|
|||||||
///
|
///
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include "CustomAssert.h"
|
||||||
class Client;
|
class Client;
|
||||||
void GParser(Client*c, const std::string&Packet);
|
void GParser(Client*c, const std::string&Packet);
|
||||||
class Buffer{
|
class Buffer{
|
||||||
public:
|
public:
|
||||||
void Handle(Client*c,const std::string& Data){
|
void Handle(Client*c,const std::string& Data){
|
||||||
if(c == nullptr)return;
|
Assert(c);
|
||||||
Buf += Data;
|
Buf += Data;
|
||||||
Manage(c);
|
Manage(c);
|
||||||
}
|
}
|
||||||
@ -18,11 +19,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::string Buf;
|
std::string Buf;
|
||||||
void Manage(Client*c){
|
void Manage(Client*c){
|
||||||
|
Assert(c);
|
||||||
if(!Buf.empty()){
|
if(!Buf.empty()){
|
||||||
std::string::size_type p;
|
std::string::size_type p;
|
||||||
if (Buf.at(0) == '\n'){
|
if (Buf.at(0) == '\n'){
|
||||||
p = Buf.find('\n',1);
|
p = Buf.find('\n',1);
|
||||||
if(p != -1){
|
if(p != std::string::npos){
|
||||||
std::string R = Buf.substr(1,p-1);
|
std::string R = Buf.substr(1,p-1);
|
||||||
std::string_view B(R.c_str(),R.find(char(0)));
|
std::string_view B(R.c_str(),R.find(char(0)));
|
||||||
GParser(c, B.data());
|
GParser(c, B.data());
|
||||||
@ -31,7 +33,7 @@ private:
|
|||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
p = Buf.find('\n');
|
p = Buf.find('\n');
|
||||||
if(p == -1)Buf.clear();
|
if(p == std::string::npos)Buf.clear();
|
||||||
else{
|
else{
|
||||||
Buf = Buf.substr(p);
|
Buf = Buf.substr(p);
|
||||||
Manage(c);
|
Manage(c);
|
||||||
|
@ -3,8 +3,14 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#ifdef WIN32
|
||||||
#include <WS2tcpip.h>
|
#include <WS2tcpip.h>
|
||||||
|
#else
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#define SOCKET int
|
||||||
|
#endif
|
||||||
#include "Buffer.h"
|
#include "Buffer.h"
|
||||||
|
#include "CustomAssert.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@ -60,6 +66,7 @@ struct ClientInterface{
|
|||||||
c = nullptr;
|
c = nullptr;
|
||||||
}
|
}
|
||||||
void AddClient(Client *c){
|
void AddClient(Client *c){
|
||||||
|
Assert(c);
|
||||||
Clients.insert(c);
|
Clients.insert(c);
|
||||||
}
|
}
|
||||||
int Size(){
|
int Size(){
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
* Define WIN32 when build target is Win32 API
|
* Define WIN32 when build target is Win32 API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (defined(_WIN32) || defined(__WIN32__)) && \
|
#if (defined(_WIN32) || defined(WIN32__)) && \
|
||||||
!defined(WIN32) && !defined(__SYMBIAN32__)
|
!defined(WIN32) && !defined(__SYMBIAN32__)
|
||||||
#define WIN32
|
#define WIN32
|
||||||
#endif
|
#endif
|
||||||
|
67
include/CustomAssert.h
Normal file
67
include/CustomAssert.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Author: lionkor
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Asserts are to be used anywhere where assumptions about state are made
|
||||||
|
* implicitly. AssertNotReachable is used where code should never go, like in
|
||||||
|
* default switch cases which shouldn't trigger. They make it explicit
|
||||||
|
* that a place cannot normally be reached and make it an error if they do.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
static const char* const ANSI_RESET = "\u001b[0m";
|
||||||
|
|
||||||
|
static const char* const ANSI_BLACK = "\u001b[30m";
|
||||||
|
static const char* const ANSI_RED = "\u001b[31m";
|
||||||
|
static const char* const ANSI_GREEN = "\u001b[32m";
|
||||||
|
static const char* const ANSI_YELLOW = "\u001b[33m";
|
||||||
|
static const char* const ANSI_BLUE = "\u001b[34m";
|
||||||
|
static const char* const ANSI_MAGENTA = "\u001b[35m";
|
||||||
|
static const char* const ANSI_CYAN = "\u001b[36m";
|
||||||
|
static const char* const ANSI_WHITE = "\u001b[37m";
|
||||||
|
|
||||||
|
static const char* const ANSI_BLACK_BOLD = "\u001b[30;1m";
|
||||||
|
static const char* const ANSI_RED_BOLD = "\u001b[31;1m";
|
||||||
|
static const char* const ANSI_GREEN_BOLD = "\u001b[32;1m";
|
||||||
|
static const char* const ANSI_YELLOW_BOLD = "\u001b[33;1m";
|
||||||
|
static const char* const ANSI_BLUE_BOLD = "\u001b[34;1m";
|
||||||
|
static const char* const ANSI_MAGENTA_BOLD = "\u001b[35;1m";
|
||||||
|
static const char* const ANSI_CYAN_BOLD = "\u001b[36;1m";
|
||||||
|
static const char* const ANSI_WHITE_BOLD = "\u001b[37;1m";
|
||||||
|
|
||||||
|
static const char* const ANSI_BOLD = "\u001b[1m";
|
||||||
|
static const char* const ANSI_UNDERLINE = "\u001b[4m";
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
inline void _assert([[maybe_unused]] const char* file, [[maybe_unused]] const char* function, [[maybe_unused]] unsigned line,
|
||||||
|
[[maybe_unused]] const char* condition_string, [[maybe_unused]] bool result) {
|
||||||
|
if (!result) {
|
||||||
|
std::cout << std::flush << "(debug build) TID "
|
||||||
|
<< std::this_thread::get_id() << ": ASSERTION FAILED: at "
|
||||||
|
<< file << ":" << line << " \n\t-> in "
|
||||||
|
<< function << ", Line " << line << ": \n\t\t-> "
|
||||||
|
<< "Failed Condition: " << condition_string << std::endl;
|
||||||
|
std::cout << "... terminating ..." << std::endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Assert(cond) _assert(__FILE__, __func__, __LINE__, #cond, (cond))
|
||||||
|
#define AssertNotReachable() _assert(__FILE__, __func__, __LINE__, "reached unreachable code", false)
|
||||||
|
#else
|
||||||
|
// In release build, these macros turn into NOPs. The compiler will optimize these out.
|
||||||
|
#define Assert(x) \
|
||||||
|
do { \
|
||||||
|
} while (false)
|
||||||
|
#define AssertNotReachable() \
|
||||||
|
do { \
|
||||||
|
} while (false)
|
||||||
|
#endif // DEBUG
|
@ -2,10 +2,15 @@
|
|||||||
/// Created by Anonymous275 on 4/2/2020.
|
/// Created by Anonymous275 on 4/2/2020.
|
||||||
///
|
///
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
extern std::mutex MLock;
|
||||||
void InitLog();
|
void InitLog();
|
||||||
|
#define DebugPrintTID() DebugPrintTIDInternal(__func__)
|
||||||
|
void DebugPrintTIDInternal(const std::string& func); // prints the current thread id in debug mode, to make tracing of crashes and asserts easier
|
||||||
void ConsoleOut(const std::string& msg);
|
void ConsoleOut(const std::string& msg);
|
||||||
|
void QueueAbort();
|
||||||
void except(const std::string& toPrint);
|
void except(const std::string& toPrint);
|
||||||
void debug(const std::string& toPrint);
|
void debug(const std::string& toPrint);
|
||||||
void error(const std::string& toPrint);
|
void error(const std::string& toPrint);
|
||||||
|
@ -3,31 +3,35 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "lua.hpp"
|
||||||
|
#include <any>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "lua.hpp"
|
#include <memory>
|
||||||
#include <vector>
|
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <any>
|
#include <thread>
|
||||||
namespace fs = std::experimental::filesystem;
|
#include <vector>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
struct LuaArg {
|
struct LuaArg {
|
||||||
std::vector<std::any> args;
|
std::vector<std::any> args;
|
||||||
void PushArgs(lua_State* State) {
|
void PushArgs(lua_State* State) {
|
||||||
for (std::any arg : args) {
|
for (std::any arg : args) {
|
||||||
if(!arg.has_value())return;
|
if (!arg.has_value())
|
||||||
|
return;
|
||||||
std::string Type = arg.type().name();
|
std::string Type = arg.type().name();
|
||||||
if(Type.find("bool") != -1){
|
if (Type.find("bool") != std::string::npos) {
|
||||||
lua_pushboolean(State, std::any_cast<bool>(arg));
|
lua_pushboolean(State, std::any_cast<bool>(arg));
|
||||||
}
|
}
|
||||||
if(Type.find("basic_string") != -1 || Type.find("char") != -1){
|
if (Type.find("basic_string") != std::string::npos || Type.find("char") != std::string::npos) {
|
||||||
lua_pushstring(State, std::any_cast<std::string>(arg).c_str());
|
lua_pushstring(State, std::any_cast<std::string>(arg).c_str());
|
||||||
}
|
}
|
||||||
if(Type.find("int") != -1){
|
if (Type.find("int") != std::string::npos) {
|
||||||
lua_pushinteger(State, std::any_cast<int>(arg));
|
lua_pushinteger(State, std::any_cast<int>(arg));
|
||||||
}
|
}
|
||||||
if(Type.find("float") != -1){
|
if (Type.find("float") != std::string::npos) {
|
||||||
lua_pushnumber(State, std::any_cast<float>(arg));
|
lua_pushnumber(State, std::any_cast<float>(arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,15 +40,19 @@ struct LuaArg{
|
|||||||
|
|
||||||
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 { nullptr };
|
||||||
fs::file_time_type LastWrote;
|
fs::file_time_type _LastWrote;
|
||||||
std::string PluginName;
|
std::string _PluginName;
|
||||||
std::string FileName;
|
std::string _FileName;
|
||||||
|
bool _StopThread = false;
|
||||||
|
bool _Console = false;
|
||||||
|
// this is called by the ctor to ensure RAII
|
||||||
|
void Init();
|
||||||
|
|
||||||
public:
|
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) const;
|
||||||
void UnRegisterEvent(const std::string& Event);
|
void UnRegisterEvent(const std::string& Event);
|
||||||
void SetLastWrite(fs::file_time_type time);
|
void SetLastWrite(fs::file_time_type time);
|
||||||
bool IsRegistered(const std::string& Event);
|
bool IsRegistered(const std::string& Event);
|
||||||
@ -52,16 +60,19 @@ public:
|
|||||||
void Execute(const std::string& Command);
|
void Execute(const std::string& Command);
|
||||||
void SetFileName(const std::string& Name);
|
void SetFileName(const std::string& Name);
|
||||||
fs::file_time_type GetLastWrite();
|
fs::file_time_type GetLastWrite();
|
||||||
std::string GetPluginName();
|
std::string GetPluginName() const;
|
||||||
std::string GetFileName();
|
std::string GetFileName() const;
|
||||||
bool StopThread = false;
|
|
||||||
bool Console = false;
|
|
||||||
lua_State* GetState();
|
lua_State* GetState();
|
||||||
char* GetOrigin();
|
const lua_State* GetState() const;
|
||||||
|
std::string GetOrigin();
|
||||||
std::mutex Lock;
|
std::mutex Lock;
|
||||||
void Reload();
|
void Reload();
|
||||||
void Init();
|
Lua(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote, bool Console = false);
|
||||||
|
Lua(bool Console = false);
|
||||||
|
~Lua();
|
||||||
|
void SetStopThread(bool StopThread) { _StopThread = StopThread; }
|
||||||
|
bool GetStopThread() const { return _StopThread; }
|
||||||
};
|
};
|
||||||
int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* args);
|
int CallFunction(Lua* lua, const std::string& FuncName, std::unique_ptr<LuaArg> args);
|
||||||
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg,bool Wait);
|
int TriggerLuaEvent(const std::string& Event, bool local, Lua* Caller, std::unique_ptr<LuaArg> arg, bool Wait);
|
||||||
extern std::set<Lua*> PluginEngine;
|
extern std::set<std::unique_ptr<Lua>> PluginEngine;
|
||||||
|
@ -706,7 +706,7 @@
|
|||||||
** Define it as a help when debugging C code.
|
** Define it as a help when debugging C code.
|
||||||
*/
|
*/
|
||||||
#if defined(LUA_USE_APICHECK)
|
#if defined(LUA_USE_APICHECK)
|
||||||
#include <assert.h>
|
#include <CustomAssert.h>
|
||||||
#define luai_apicheck(l,e) assert(e)
|
#define luai_apicheck(l,e) assert(e)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#ifdef __linux
|
||||||
|
#define EXCEPTION_POINTERS void
|
||||||
|
#else
|
||||||
#include <WS2tcpip.h>
|
#include <WS2tcpip.h>
|
||||||
|
#endif
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Xor.h"
|
#include "Xor.h"
|
||||||
struct RSA{
|
struct RSA{
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#define BEGIN_NAMESPACE(x) namespace x {
|
#define BEGIN_NAMESPACE(x) namespace x {
|
||||||
#define END_NAMESPACE }
|
#define END_NAMESPACE }
|
||||||
@ -68,10 +69,10 @@ BEGIN_NAMESPACE(XorCompileTime)
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template <size_t... Is>
|
template <size_t... Is>
|
||||||
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) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
_encrypted[i] = dec(_encrypted[i]);
|
_encrypted[i] = dec(_encrypted[i]);
|
||||||
}
|
}
|
||||||
@ -83,14 +84,14 @@ BEGIN_NAMESPACE(XorCompileTime)
|
|||||||
static auto w_printf = [](const char* fmt, ...) {
|
static auto w_printf = [](const char* fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vprintf_s(fmt, args);
|
vprintf(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto w_printf_s = [](const char* fmt, ...) {
|
static auto w_printf_s = [](const char* fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vprintf_s(fmt, args);
|
vprintf(fmt, args);
|
||||||
va_end(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, ...) {
|
static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vsprintf_s(buf, buf_size, fmt, args);
|
vsnprintf(buf, buf_size, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,7 +122,7 @@ BEGIN_NAMESPACE(XorCompileTime)
|
|||||||
int ret;
|
int ret;
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
ret = vsprintf_s(buf, buf_size, fmt, args);
|
ret = vsnprintf(buf, buf_size, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
30
include/UnixCompat.h
Normal file
30
include/UnixCompat.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Author: lionkor
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// This header defines unix equivalents of common win32 functions.
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
|
||||||
|
#include "CustomAssert.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// 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
|
@ -176,7 +176,7 @@
|
|||||||
#if defined(_WINDOWS) && !defined(WINDOWS)
|
#if defined(_WINDOWS) && !defined(WINDOWS)
|
||||||
# define WINDOWS
|
# define WINDOWS
|
||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
|
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(WIN32__)
|
||||||
# ifndef WIN32
|
# ifndef WIN32
|
||||||
# define WIN32
|
# define WIN32
|
||||||
# endif
|
# endif
|
||||||
|
@ -133,7 +133,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||||||
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
||||||
# define OS_CODE 7
|
# define OS_CODE 7
|
||||||
# ifndef Z_SOLO
|
# ifndef Z_SOLO
|
||||||
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != WIN32_os
|
||||||
# include <unix.h> /* for fdopen */
|
# include <unix.h> /* for fdopen */
|
||||||
# else
|
# else
|
||||||
# ifndef fdopen
|
# ifndef fdopen
|
||||||
|
@ -3,11 +3,15 @@
|
|||||||
///
|
///
|
||||||
#include "Zlib/zlib.h"
|
#include "Zlib/zlib.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#define Biggest 30000
|
#define Biggest 30000
|
||||||
std::string Comp(std::string Data){
|
std::string Comp(std::string Data){
|
||||||
char*C = new char[Biggest];
|
std::array<char, Biggest> C;
|
||||||
memset(C, 0, Biggest);
|
// obsolete
|
||||||
|
C.fill(0);
|
||||||
z_stream defstream;
|
z_stream defstream;
|
||||||
defstream.zalloc = Z_NULL;
|
defstream.zalloc = Z_NULL;
|
||||||
defstream.zfree = Z_NULL;
|
defstream.zfree = Z_NULL;
|
||||||
@ -15,20 +19,20 @@ std::string Comp(std::string Data){
|
|||||||
defstream.avail_in = (uInt)Data.length();
|
defstream.avail_in = (uInt)Data.length();
|
||||||
defstream.next_in = (Bytef *)&Data[0];
|
defstream.next_in = (Bytef *)&Data[0];
|
||||||
defstream.avail_out = Biggest;
|
defstream.avail_out = Biggest;
|
||||||
defstream.next_out = reinterpret_cast<Bytef *>(C);
|
defstream.next_out = reinterpret_cast<Bytef *>(C.data());
|
||||||
deflateInit(&defstream, Z_BEST_COMPRESSION);
|
deflateInit(&defstream, Z_BEST_COMPRESSION);
|
||||||
deflate(&defstream, Z_SYNC_FLUSH);
|
deflate(&defstream, Z_SYNC_FLUSH);
|
||||||
deflate(&defstream, Z_FINISH);
|
deflate(&defstream, Z_FINISH);
|
||||||
deflateEnd(&defstream);
|
deflateEnd(&defstream);
|
||||||
int TO = defstream.total_out;
|
size_t TO = defstream.total_out;
|
||||||
std::string Ret(TO,0);
|
std::string Ret(TO,0);
|
||||||
memcpy_s(&Ret[0],TO,C,TO);
|
std::copy_n(C.begin(), TO, Ret.begin());
|
||||||
delete [] C;
|
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
std::string DeComp(std::string Compressed){
|
std::string DeComp(std::string Compressed){
|
||||||
char*C = new char[Biggest];
|
std::array<char, Biggest> C;
|
||||||
memset(C, 0, Biggest);
|
// not needed
|
||||||
|
C.fill(0);
|
||||||
z_stream infstream;
|
z_stream infstream;
|
||||||
infstream.zalloc = Z_NULL;
|
infstream.zalloc = Z_NULL;
|
||||||
infstream.zfree = Z_NULL;
|
infstream.zfree = Z_NULL;
|
||||||
@ -36,14 +40,13 @@ std::string DeComp(std::string Compressed){
|
|||||||
infstream.avail_in = Biggest;
|
infstream.avail_in = Biggest;
|
||||||
infstream.next_in = (Bytef *)(&Compressed[0]);
|
infstream.next_in = (Bytef *)(&Compressed[0]);
|
||||||
infstream.avail_out = Biggest;
|
infstream.avail_out = Biggest;
|
||||||
infstream.next_out = (Bytef *)(C);
|
infstream.next_out = (Bytef *)(C.data());
|
||||||
inflateInit(&infstream);
|
inflateInit(&infstream);
|
||||||
inflate(&infstream, Z_SYNC_FLUSH);
|
inflate(&infstream, Z_SYNC_FLUSH);
|
||||||
inflate(&infstream, Z_FINISH);
|
inflate(&infstream, Z_FINISH);
|
||||||
inflateEnd(&infstream);
|
inflateEnd(&infstream);
|
||||||
int TO = infstream.total_out;
|
size_t TO = infstream.total_out;
|
||||||
std::string Ret(TO,0);
|
std::string Ret(TO,0);
|
||||||
memcpy_s(&Ret[0],TO,C,TO);
|
std::copy_n(C.begin(), TO, Ret.begin());
|
||||||
delete [] C;
|
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
@ -3,34 +3,44 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
#include "Lua/LuaSystem.hpp"
|
#include "Lua/LuaSystem.hpp"
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <conio.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#else // *nix
|
||||||
|
typedef unsigned long DWORD, *PDWORD, *LPDWORD;
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif // WIN32
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <conio.h>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
std::vector<std::string> QConsoleOut;
|
std::vector<std::string> QConsoleOut;
|
||||||
std::string CInputBuff;
|
std::string CInputBuff;
|
||||||
std::mutex MLock;
|
std::mutex MLock;
|
||||||
Lua* LuaConsole;
|
std::unique_ptr<Lua> LuaConsole;
|
||||||
void HandleInput(const std::string& cmd) {
|
void HandleInput(const std::string& cmd) {
|
||||||
|
std::cout << std::endl;
|
||||||
if (cmd == "exit") {
|
if (cmd == "exit") {
|
||||||
exit(0);
|
exit(0);
|
||||||
}else LuaConsole->Execute(cmd);
|
} else
|
||||||
|
LuaConsole->Execute(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessOut() {
|
void ProcessOut() {
|
||||||
static size_t len = 2;
|
static size_t len = 2;
|
||||||
if(QConsoleOut.empty() && len == CInputBuff.length())return;
|
if (QConsoleOut.empty() && len == CInputBuff.length())
|
||||||
|
return;
|
||||||
printf("%c[2K\r", 27);
|
printf("%c[2K\r", 27);
|
||||||
for (const std::string& msg : QConsoleOut)
|
for (const std::string& msg : QConsoleOut)
|
||||||
if(!msg.empty())std::cout << msg;
|
if (!msg.empty())
|
||||||
|
std::cout << msg;
|
||||||
MLock.lock();
|
MLock.lock();
|
||||||
QConsoleOut.clear();
|
QConsoleOut.clear();
|
||||||
MLock.unlock();
|
MLock.unlock();
|
||||||
std::cout << "> " << CInputBuff;
|
std::cout << "> " << CInputBuff << std::flush;
|
||||||
len = CInputBuff.length();
|
len = CInputBuff.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,12 +51,39 @@ void ConsoleOut(const std::string& msg){
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void OutputRefresh() {
|
[[noreturn]] void OutputRefresh() {
|
||||||
|
DebugPrintTID();
|
||||||
while (true) {
|
while (true) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
ProcessOut();
|
ProcessOut();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
static int _getch() {
|
||||||
|
char buf = 0;
|
||||||
|
struct termios old;
|
||||||
|
fflush(stdout);
|
||||||
|
if (tcgetattr(0, &old) < 0)
|
||||||
|
perror("tcsetattr()");
|
||||||
|
old.c_lflag &= ~unsigned(ICANON);
|
||||||
|
old.c_lflag &= ~unsigned(ECHO);
|
||||||
|
old.c_cc[VMIN] = 1;
|
||||||
|
old.c_cc[VTIME] = 0;
|
||||||
|
if (tcsetattr(0, TCSANOW, &old) < 0)
|
||||||
|
perror("tcsetattr ICANON");
|
||||||
|
if (read(0, &buf, 1) < 0)
|
||||||
|
perror("read()");
|
||||||
|
old.c_lflag |= ICANON;
|
||||||
|
old.c_lflag |= ECHO;
|
||||||
|
if (tcsetattr(0, TCSADRAIN, &old) < 0)
|
||||||
|
perror("tcsetattr ~ICANON");
|
||||||
|
// no echo printf("%c\n", buf);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
void SetupConsole() {
|
void SetupConsole() {
|
||||||
|
#ifdef WIN32
|
||||||
DWORD outMode = 0;
|
DWORD outMode = 0;
|
||||||
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
if (stdoutHandle == INVALID_HANDLE_VALUE) {
|
if (stdoutHandle == INVALID_HANDLE_VALUE) {
|
||||||
@ -66,25 +103,34 @@ void SetupConsole(){
|
|||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||||
exit(GetLastError());
|
exit(GetLastError());
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#endif // WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void ReadCin() {
|
[[noreturn]] void ReadCin() {
|
||||||
|
DebugPrintTID();
|
||||||
while (true) {
|
while (true) {
|
||||||
int In = _getch();
|
int In = _getch();
|
||||||
if (In == 13) {
|
if (In == 13 || In == '\n') {
|
||||||
if (!CInputBuff.empty()) {
|
if (!CInputBuff.empty()) {
|
||||||
HandleInput(CInputBuff);
|
HandleInput(CInputBuff);
|
||||||
CInputBuff.clear();
|
CInputBuff.clear();
|
||||||
}
|
}
|
||||||
} else if (In == 8) {
|
} else if (In == 8) {
|
||||||
if(!CInputBuff.empty())CInputBuff.pop_back();
|
if (!CInputBuff.empty())
|
||||||
}else CInputBuff += char(In);
|
CInputBuff.pop_back();
|
||||||
|
} else if (In == 4) {
|
||||||
|
CInputBuff = "exit";
|
||||||
|
HandleInput(CInputBuff);
|
||||||
|
CInputBuff.clear();
|
||||||
|
} else {
|
||||||
|
CInputBuff += char(In);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ConsoleInit() {
|
void ConsoleInit() {
|
||||||
SetupConsole();
|
SetupConsole();
|
||||||
LuaConsole = new Lua();
|
LuaConsole = std::make_unique<Lua>(true);
|
||||||
LuaConsole->Console = true;
|
|
||||||
LuaConsole->Init();
|
|
||||||
printf("> ");
|
printf("> ");
|
||||||
std::thread In(ReadCin);
|
std::thread In(ReadCin);
|
||||||
In.detach();
|
In.detach();
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
///
|
///
|
||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include <windows.h>
|
#include "CustomAssert.h"
|
||||||
|
//#include <windows.h>
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -84,7 +85,9 @@ int Dec(int value,int d,int n){
|
|||||||
return log_power(value, d, n);
|
return log_power(value, d, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
int Handle(EXCEPTION_POINTERS *ep,char* Origin){
|
int Handle(EXCEPTION_POINTERS *ep,char* Origin){
|
||||||
|
Assert(false);
|
||||||
std::stringstream R;
|
std::stringstream R;
|
||||||
R << Sec("Code : ") << std::hex
|
R << Sec("Code : ") << std::hex
|
||||||
<< ep->ExceptionRecord->ExceptionCode
|
<< ep->ExceptionRecord->ExceptionCode
|
||||||
@ -92,6 +95,10 @@ int Handle(EXCEPTION_POINTERS *ep,char* Origin){
|
|||||||
except(R.str());
|
except(R.str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// stub
|
||||||
|
int Handle(EXCEPTION_POINTERS *, char*) { return 1; }
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
std::string RSA_E(const std::string& Data, RSA*k){
|
std::string RSA_E(const std::string& Data, RSA*k){
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
///
|
///
|
||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "CustomAssert.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -33,13 +34,13 @@ void SetValues(const std::string& Line, int Index) {
|
|||||||
}
|
}
|
||||||
Data = Data.substr(1);
|
Data = Data.substr(1);
|
||||||
std::string::size_type sz;
|
std::string::size_type sz;
|
||||||
bool Boolean = std::string(Data).find("true") != -1;//searches for "true"
|
bool FoundTrue = std::string(Data).find("true") != std::string::npos;//searches for "true"
|
||||||
switch (Index) {
|
switch (Index) {
|
||||||
case 1 :
|
case 1 :
|
||||||
Debug = Boolean;//checks and sets the Debug Value
|
Debug = FoundTrue;//checks and sets the Debug Value
|
||||||
break;
|
break;
|
||||||
case 2 :
|
case 2 :
|
||||||
Private = Boolean;//checks and sets the Private Value
|
Private = FoundTrue;//checks and sets the Private Value
|
||||||
break;
|
break;
|
||||||
case 3 :
|
case 3 :
|
||||||
Port = std::stoi(Data, &sz);//sets the Port
|
Port = std::stoi(Data, &sz);//sets the Port
|
||||||
@ -77,6 +78,7 @@ std::string RemoveComments(const std::string& Line){
|
|||||||
return Return;
|
return Return;
|
||||||
}
|
}
|
||||||
void LoadConfig(std::ifstream& IFS){
|
void LoadConfig(std::ifstream& IFS){
|
||||||
|
Assert(IFS.is_open());
|
||||||
std::string line;
|
std::string line;
|
||||||
int index = 1;
|
int index = 1;
|
||||||
while (getline(IFS, line)) {
|
while (getline(IFS, line)) {
|
||||||
|
@ -29,6 +29,7 @@ std::string GenerateCall(){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
void Heartbeat(){
|
void Heartbeat(){
|
||||||
|
DebugPrintTID();
|
||||||
std::string R,T;
|
std::string R,T;
|
||||||
while(true){
|
while(true){
|
||||||
R = GenerateCall();
|
R = GenerateCall();
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
namespace fs = std::experimental::filesystem;
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
uint64_t MaxModSize = 0;
|
uint64_t MaxModSize = 0;
|
||||||
std::string FileSizes;
|
std::string FileSizes;
|
||||||
std::string FileList;
|
std::string FileList;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
std::string CustomIP;
|
std::string CustomIP;
|
||||||
std::string GetSVer(){
|
std::string GetSVer(){
|
||||||
|
@ -2,34 +2,39 @@
|
|||||||
/// Created by Anonymous275 on 5/20/2020
|
/// Created by Anonymous275 on 5/20/2020
|
||||||
///
|
///
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
#include "Lua/LuaSystem.hpp"
|
#include "Lua/LuaSystem.hpp"
|
||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Logger.h"
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
std::set<Lua*> PluginEngine;
|
#ifdef __linux
|
||||||
|
// we need this for `struct stat`
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif // __linux
|
||||||
|
|
||||||
|
std::set<std::unique_ptr<Lua>> PluginEngine;
|
||||||
bool NewFile(const std::string& Path) {
|
bool NewFile(const std::string& Path) {
|
||||||
for(Lua*Script : PluginEngine){
|
for (auto& Script : PluginEngine) {
|
||||||
if(Path == Script->GetFileName())return false;
|
if (Path == Script->GetFileName())
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void RegisterFiles(const std::string& Path, bool HotSwap) {
|
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);
|
||||||
if(!HotSwap)info(Sec("Loading plugin : ") + Name);
|
if (!HotSwap)
|
||||||
|
info(Sec("Loading plugin : ") + Name);
|
||||||
for (const auto& entry : fs::directory_iterator(Path)) {
|
for (const auto& entry : fs::directory_iterator(Path)) {
|
||||||
auto pos = entry.path().string().find(Sec(".lua"));
|
auto pos = entry.path().string().find(Sec(".lua"));
|
||||||
if (pos != std::string::npos && entry.path().string().length() - pos == 4) {
|
if (pos != std::string::npos && entry.path().string().length() - pos == 4) {
|
||||||
if (!HotSwap || NewFile(entry.path().string())) {
|
if (!HotSwap || NewFile(entry.path().string())) {
|
||||||
Lua *Script = new Lua();
|
auto FileName = entry.path().string();
|
||||||
PluginEngine.insert(Script);
|
std::unique_ptr<Lua> ScriptToInsert(new Lua(Name, FileName, fs::last_write_time(FileName)));
|
||||||
Script->SetFileName(entry.path().string());
|
auto& Script = *ScriptToInsert;
|
||||||
Script->SetPluginName(Name);
|
PluginEngine.insert(std::move(ScriptToInsert));
|
||||||
Script->SetLastWrite(fs::last_write_time(Script->GetFileName()));
|
if (HotSwap)
|
||||||
Script->Init();
|
info(Sec("[HOTSWAP] Added : ") + Script.GetFileName().substr(Script.GetFileName().find('\\')));
|
||||||
if(HotSwap)info(Sec("[HOTSWAP] Added : ") +
|
|
||||||
Script->GetFileName().substr(Script->GetFileName().find('\\')));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,20 +48,19 @@ void FolderList(const std::string& Path,bool HotSwap){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
[[noreturn]] void HotSwaps(const std::string& path) {
|
[[noreturn]] void HotSwaps(const std::string& path) {
|
||||||
|
DebugPrintTID();
|
||||||
while (true) {
|
while (true) {
|
||||||
for(Lua*Script : PluginEngine){
|
for (auto& Script : PluginEngine) {
|
||||||
struct stat Info {};
|
struct stat Info {};
|
||||||
if (stat(Script->GetFileName().c_str(), &Info) != 0) {
|
if (stat(Script->GetFileName().c_str(), &Info) != 0) {
|
||||||
Script->StopThread = true;
|
Script->SetStopThread(true);
|
||||||
PluginEngine.erase(Script);
|
PluginEngine.erase(Script);
|
||||||
info(Sec("[HOTSWAP] Removed : ")+
|
info(Sec("[HOTSWAP] Removed : ") + Script->GetFileName().substr(Script->GetFileName().find('\\')));
|
||||||
Script->GetFileName().substr(Script->GetFileName().find('\\')));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (Script->GetLastWrite() != fs::last_write_time(Script->GetFileName())) {
|
if (Script->GetLastWrite() != fs::last_write_time(Script->GetFileName())) {
|
||||||
Script->StopThread = true;
|
Script->SetStopThread(true);
|
||||||
info(Sec("[HOTSWAP] Updated : ")+
|
info(Sec("[HOTSWAP] Updated : ") + Script->GetFileName().substr(Script->GetFileName().find('\\')));
|
||||||
Script->GetFileName().substr(Script->GetFileName().find('\\')));
|
|
||||||
Script->SetLastWrite(fs::last_write_time(Script->GetFileName()));
|
Script->SetLastWrite(fs::last_write_time(Script->GetFileName()));
|
||||||
Script->Reload();
|
Script->Reload();
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,21 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
#include "Lua/LuaSystem.hpp"
|
#include "Lua/LuaSystem.hpp"
|
||||||
#include "Security/Enc.h"
|
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
#include "Settings.h"
|
|
||||||
#include "Network.h"
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <iostream>
|
#include "Network.h"
|
||||||
|
#include "Security/Enc.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
#include "UnixCompat.h"
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
LuaArg* CreateArg(lua_State *L,int T,int S){
|
std::unique_ptr<LuaArg> CreateArg(lua_State* L, int T, int S) {
|
||||||
if(S > T)return nullptr;
|
if (S > T)
|
||||||
auto* temp = new LuaArg;
|
return nullptr;
|
||||||
|
std::unique_ptr<LuaArg> temp(new LuaArg);
|
||||||
for (int C = S; C <= T; C++) {
|
for (int C = S; C <= T; C++) {
|
||||||
if (lua_isstring(L, C)) {
|
if (lua_isstring(L, C)) {
|
||||||
temp->args.emplace_back(std::string(lua_tostring(L, C)));
|
temp->args.emplace_back(std::string(lua_tostring(L, C)));
|
||||||
@ -31,50 +34,61 @@ LuaArg* CreateArg(lua_State *L,int T,int S){
|
|||||||
void ClearStack(lua_State* L) {
|
void ClearStack(lua_State* L) {
|
||||||
lua_settop(L, 0);
|
lua_settop(L, 0);
|
||||||
}
|
}
|
||||||
Lua* GetScript(lua_State *L){
|
std::optional<std::reference_wrapper<Lua>> GetScript(lua_State* L) {
|
||||||
for(Lua*Script : PluginEngine){
|
for (auto& Script : PluginEngine) {
|
||||||
if (Script->GetState() == L)return Script;
|
if (Script->GetState() == L)
|
||||||
|
return *Script;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
void SendError(lua_State* L, const std::string& msg) {
|
void SendError(lua_State* L, const std::string& msg) {
|
||||||
Lua* S = GetScript(L);
|
Assert(L);
|
||||||
|
auto MaybeS = GetScript(L);
|
||||||
std::string a;
|
std::string a;
|
||||||
if(S == nullptr)a = Sec("Console");
|
if (!MaybeS.has_value()) {
|
||||||
else a = S->GetFileName().substr(S->GetFileName().find('\\'));
|
a = Sec("_Console");
|
||||||
|
} else {
|
||||||
|
Lua& S = MaybeS.value();
|
||||||
|
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, std::unique_ptr<LuaArg> arg) {
|
||||||
std::lock_guard<std::mutex> lockGuard(lua->Lock);
|
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(std::unique_ptr<LuaArg>)> task([lua, R](std::unique_ptr<LuaArg> arg) { return CallFunction(lua, R, std::move(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), std::move(arg));
|
||||||
t.detach();
|
t.detach();
|
||||||
auto status = f1.wait_for(std::chrono::seconds(5));
|
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 FutureWait(Lua*lua,const std::string& R, LuaArg*arg,bool Wait){
|
int FutureWait(Lua* lua, const std::string& R, std::unique_ptr<LuaArg> arg, bool Wait) {
|
||||||
std::packaged_task<int()> task([lua,R,arg]{return Trigger(lua,R,arg);});
|
Assert(lua);
|
||||||
|
std::packaged_task<int(std::unique_ptr<LuaArg>)> task([lua, R](std::unique_ptr<LuaArg> arg) { return Trigger(lua, R, std::move(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), std::move(arg));
|
||||||
t.detach();
|
t.detach();
|
||||||
int T = 0;
|
int T = 0;
|
||||||
if(Wait)T = 6;
|
if (Wait)
|
||||||
|
T = 6;
|
||||||
auto status = f1.wait_for(std::chrono::seconds(T));
|
auto status = f1.wait_for(std::chrono::seconds(T));
|
||||||
if(status != std::future_status::timeout)return f1.get();
|
if (status != std::future_status::timeout)
|
||||||
|
return f1.get();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg,bool Wait){
|
int TriggerLuaEvent(const std::string& Event, bool local, Lua* Caller, std::unique_ptr<LuaArg> arg, bool Wait) {
|
||||||
int R = 0;
|
int R = 0;
|
||||||
for(Lua*Script : PluginEngine){
|
for (auto& 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 += FutureWait(Script,Script->GetRegistered(Event),arg,Wait);
|
R += FutureWait(Script.get(), Script->GetRegistered(Event), std::move(arg), Wait);
|
||||||
}
|
}
|
||||||
}else R += FutureWait(Script,Script->GetRegistered(Event), arg,Wait);
|
} else
|
||||||
|
R += FutureWait(Script.get(), Script->GetRegistered(Event), std::move(arg), Wait);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return R;
|
return R;
|
||||||
@ -82,7 +96,7 @@ int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg,b
|
|||||||
bool ConsoleCheck(lua_State* L, int r) {
|
bool ConsoleCheck(lua_State* L, int r) {
|
||||||
if (r != LUA_OK) {
|
if (r != LUA_OK) {
|
||||||
std::string msg = lua_tostring(L, -1);
|
std::string msg = lua_tostring(L, -1);
|
||||||
warn(Sec("Console | ") + msg);
|
warn(Sec("_Console | ") + msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -90,29 +104,40 @@ bool ConsoleCheck(lua_State *L, int r){
|
|||||||
bool CheckLua(lua_State* L, int r) {
|
bool CheckLua(lua_State* L, int r) {
|
||||||
if (r != LUA_OK) {
|
if (r != LUA_OK) {
|
||||||
std::string msg = lua_tostring(L, -1);
|
std::string msg = lua_tostring(L, -1);
|
||||||
Lua * S = GetScript(L);
|
auto MaybeS = GetScript(L);
|
||||||
std::string a = S->GetFileName().substr(S->GetFileName().find('\\'));
|
if (MaybeS.has_value()) {
|
||||||
|
Lua& S = MaybeS.value();
|
||||||
|
std::string a = S.GetFileName().substr(S.GetFileName().find('\\'));
|
||||||
warn(a + " | " + msg);
|
warn(a + " | " + msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// What the fuck, what do we do?!
|
||||||
|
AssertNotReachable();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lua_RegisterEvent(lua_State* L) {
|
int lua_RegisterEvent(lua_State* L) {
|
||||||
int Args = lua_gettop(L);
|
int Args = lua_gettop(L);
|
||||||
Lua* Script = GetScript(L);
|
auto MaybeScript = GetScript(L);
|
||||||
|
Assert(MaybeScript.has_value());
|
||||||
|
Lua& Script = MaybeScript.value();
|
||||||
if (Args == 2 && lua_isstring(L, 1) && lua_isstring(L, 2)) {
|
if (Args == 2 && lua_isstring(L, 1) && lua_isstring(L, 2)) {
|
||||||
Script->RegisterEvent(lua_tostring(L,1),lua_tostring(L,2));
|
Script.RegisterEvent(lua_tostring(L, 1), lua_tostring(L, 2));
|
||||||
}else SendError(L,Sec("RegisterEvent invalid argument count expected 2 got ") + std::to_string(Args));
|
} else
|
||||||
|
SendError(L, Sec("RegisterEvent invalid argument count expected 2 got ") + std::to_string(Args));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_TriggerEventL(lua_State* L) {
|
int lua_TriggerEventL(lua_State* L) {
|
||||||
int Args = lua_gettop(L);
|
int Args = lua_gettop(L);
|
||||||
Lua* Script = GetScript(L);
|
auto MaybeScript = GetScript(L);
|
||||||
|
Assert(MaybeScript.has_value());
|
||||||
|
Lua& Script = MaybeScript.value();
|
||||||
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),false);
|
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"));
|
||||||
}
|
}
|
||||||
@ -121,12 +146,16 @@ int lua_TriggerEventL(lua_State *L){
|
|||||||
|
|
||||||
int lua_TriggerEventG(lua_State* L) {
|
int lua_TriggerEventG(lua_State* L) {
|
||||||
int Args = lua_gettop(L);
|
int Args = lua_gettop(L);
|
||||||
Lua* Script = GetScript(L);
|
auto MaybeScript = GetScript(L);
|
||||||
|
Assert(MaybeScript.has_value());
|
||||||
|
Lua& Script = MaybeScript.value();
|
||||||
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),false);
|
TriggerLuaEvent(lua_tostring(L, 1), false, &Script, CreateArg(L, Args, 2), false);
|
||||||
}else SendError(L,Sec("TriggerGlobalEvent wrong argument [1] need string"));
|
} else
|
||||||
}else SendError(L,Sec("TriggerGlobalEvent not enough arguments"));
|
SendError(L, Sec("TriggerGlobalEvent wrong argument [1] need string"));
|
||||||
|
} else
|
||||||
|
SendError(L, Sec("TriggerGlobalEvent not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +163,7 @@ 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() + 1];
|
char* Data = new char[T.size() + 1];
|
||||||
ZeroMemory(Data, 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;
|
return Data;
|
||||||
}
|
}
|
||||||
void SafeExecution(Lua* lua, const std::string& FuncName) {
|
void SafeExecution(Lua* lua, const std::string& FuncName) {
|
||||||
@ -142,10 +171,16 @@ void SafeExecution(Lua* lua,const std::string& FuncName){
|
|||||||
lua_getglobal(luaState, FuncName.c_str());
|
lua_getglobal(luaState, FuncName.c_str());
|
||||||
if (lua_isfunction(luaState, -1)) {
|
if (lua_isfunction(luaState, -1)) {
|
||||||
char* Origin = ThreadOrigin(lua);
|
char* Origin = ThreadOrigin(lua);
|
||||||
|
#ifdef WIN32
|
||||||
__try {
|
__try {
|
||||||
int R = lua_pcall(luaState, 0, 0, 0);
|
int R = lua_pcall(luaState, 0, 0, 0);
|
||||||
CheckLua(luaState, R);
|
CheckLua(luaState, R);
|
||||||
}__except(Handle(GetExceptionInformation(),Origin)){}
|
} __except (Handle(GetExceptionInformation(), Origin)) {
|
||||||
|
}
|
||||||
|
#else // unix
|
||||||
|
int R = lua_pcall(luaState, 0, 0, 0);
|
||||||
|
CheckLua(luaState, R);
|
||||||
|
#endif // WIN32
|
||||||
delete[] Origin;
|
delete[] Origin;
|
||||||
}
|
}
|
||||||
ClearStack(luaState);
|
ClearStack(luaState);
|
||||||
@ -156,15 +191,19 @@ void ExecuteAsync(Lua* lua,const std::string& FuncName){
|
|||||||
SafeExecution(lua, FuncName);
|
SafeExecution(lua, FuncName);
|
||||||
}
|
}
|
||||||
void CallAsync(Lua* lua, const std::string& Func, int U) {
|
void CallAsync(Lua* lua, const std::string& Func, int U) {
|
||||||
lua->StopThread = false;
|
DebugPrintTID();
|
||||||
|
lua->SetStopThread(false);
|
||||||
int D = 1000 / U;
|
int D = 1000 / U;
|
||||||
while(!lua->StopThread){
|
while (!lua->GetStopThread()) {
|
||||||
ExecuteAsync(lua, Func);
|
ExecuteAsync(lua, Func);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(D));
|
std::this_thread::sleep_for(std::chrono::milliseconds(D));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int lua_StopThread(lua_State* L) {
|
int lua_StopThread(lua_State* L) {
|
||||||
GetScript(L)->StopThread = true;
|
auto MaybeScript = GetScript(L);
|
||||||
|
Assert(MaybeScript.has_value());
|
||||||
|
// ugly, but whatever, this is safe as fuck
|
||||||
|
MaybeScript.value().get().SetStopThread(true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_CreateThread(lua_State* L) {
|
int lua_CreateThread(lua_State* L) {
|
||||||
@ -175,12 +214,19 @@ int lua_CreateThread(lua_State *L){
|
|||||||
if (lua_isinteger(L, 2) || lua_isnumber(L, 2)) {
|
if (lua_isinteger(L, 2) || lua_isnumber(L, 2)) {
|
||||||
int U = int(lua_tointeger(L, 2));
|
int U = int(lua_tointeger(L, 2));
|
||||||
if (U > 0 && U < 501) {
|
if (U > 0 && U < 501) {
|
||||||
std::thread t1(CallAsync,GetScript(L),STR,U);
|
auto MaybeScript = GetScript(L);
|
||||||
|
Assert(MaybeScript.has_value());
|
||||||
|
Lua& Script = MaybeScript.value();
|
||||||
|
std::thread t1(CallAsync, &Script, STR, U);
|
||||||
t1.detach();
|
t1.detach();
|
||||||
}else SendError(L,Sec("CreateThread wrong argument [2] number must be between 1 and 500"));
|
} else
|
||||||
}else SendError(L,Sec("CreateThread wrong argument [2] need number"));
|
SendError(L, Sec("CreateThread wrong argument [2] number must be between 1 and 500"));
|
||||||
}else SendError(L,Sec("CreateThread wrong argument [1] need string"));
|
} else
|
||||||
}else SendError(L,Sec("CreateThread not enough arguments"));
|
SendError(L, Sec("CreateThread wrong argument [2] need number"));
|
||||||
|
} else
|
||||||
|
SendError(L, Sec("CreateThread wrong argument [1] need string"));
|
||||||
|
} else
|
||||||
|
SendError(L, Sec("CreateThread not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_Sleep(lua_State* L) {
|
int lua_Sleep(lua_State* L) {
|
||||||
@ -195,7 +241,8 @@ int lua_Sleep(lua_State *L){
|
|||||||
}
|
}
|
||||||
Client* GetClient(int ID) {
|
Client* GetClient(int ID) {
|
||||||
for (Client* c : CI->Clients) {
|
for (Client* c : CI->Clients) {
|
||||||
if(c != nullptr && c->GetID() == ID)return c;
|
if (c != nullptr && c->GetID() == ID)
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -203,8 +250,10 @@ int lua_isConnected(lua_State *L){
|
|||||||
if (lua_isnumber(L, 1)) {
|
if (lua_isnumber(L, 1)) {
|
||||||
int ID = int(lua_tonumber(L, 1));
|
int ID = int(lua_tonumber(L, 1));
|
||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if(c != nullptr)lua_pushboolean(L, c->isConnected);
|
if (c != nullptr)
|
||||||
else return 0;
|
lua_pushboolean(L, c->isConnected);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("isConnected not enough arguments"));
|
SendError(L, Sec("isConnected not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
@ -215,8 +264,10 @@ int lua_GetPlayerName(lua_State *L){
|
|||||||
if (lua_isnumber(L, 1)) {
|
if (lua_isnumber(L, 1)) {
|
||||||
int ID = int(lua_tonumber(L, 1));
|
int ID = int(lua_tonumber(L, 1));
|
||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if(c != nullptr)lua_pushstring(L, c->GetName().c_str());
|
if (c != nullptr)
|
||||||
else return 0;
|
lua_pushstring(L, c->GetName().c_str());
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("GetPlayerName not enough arguments"));
|
SendError(L, Sec("GetPlayerName not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
@ -231,8 +282,10 @@ int lua_GetDID(lua_State *L){
|
|||||||
if (lua_isnumber(L, 1)) {
|
if (lua_isnumber(L, 1)) {
|
||||||
int ID = int(lua_tonumber(L, 1));
|
int ID = int(lua_tonumber(L, 1));
|
||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if(c != nullptr)lua_pushstring(L, c->GetDID().c_str());
|
if (c != nullptr)
|
||||||
else return 0;
|
lua_pushstring(L, c->GetDID().c_str());
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("GetDID not enough arguments"));
|
SendError(L, Sec("GetDID not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
@ -243,13 +296,15 @@ int lua_GetAllPlayers(lua_State *L){
|
|||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (Client* c : CI->Clients) {
|
for (Client* c : CI->Clients) {
|
||||||
if(c == nullptr)continue;
|
if (c == nullptr)
|
||||||
|
continue;
|
||||||
lua_pushinteger(L, c->GetID());
|
lua_pushinteger(L, c->GetID());
|
||||||
lua_pushstring(L, c->GetName().c_str());
|
lua_pushstring(L, c->GetName().c_str());
|
||||||
lua_settable(L, -3);
|
lua_settable(L, -3);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if(CI->Clients.empty())return 0;
|
if (CI->Clients.empty())
|
||||||
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int lua_GetCars(lua_State* L) {
|
int lua_GetCars(lua_State* L) {
|
||||||
@ -266,8 +321,10 @@ int lua_GetCars(lua_State *L){
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(c->GetAllCars().empty())return 0;
|
if (c->GetAllCars().empty())
|
||||||
}else return 0;
|
return 0;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("GetPlayerVehicles not enough arguments"));
|
SendError(L, Sec("GetPlayerVehicles not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
@ -279,8 +336,10 @@ int lua_dropPlayer(lua_State *L){
|
|||||||
if (lua_isnumber(L, 1)) {
|
if (lua_isnumber(L, 1)) {
|
||||||
int ID = int(lua_tonumber(L, 1));
|
int ID = int(lua_tonumber(L, 1));
|
||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if(c == nullptr)return 0;
|
if (c == nullptr)
|
||||||
if(c->GetRole() == Sec("MDEV"))return 0;
|
return 0;
|
||||||
|
if (c->GetRole() == Sec("MDEV"))
|
||||||
|
return 0;
|
||||||
std::string Reason;
|
std::string Reason;
|
||||||
if (Args > 1 && lua_isstring(L, 2)) {
|
if (Args > 1 && lua_isstring(L, 2)) {
|
||||||
Reason = std::string(Sec(" Reason : ")) + lua_tostring(L, 2);
|
Reason = std::string(Sec(" Reason : ")) + lua_tostring(L, 2);
|
||||||
@ -289,7 +348,8 @@ int lua_dropPlayer(lua_State *L){
|
|||||||
c->SetStatus(-2);
|
c->SetStatus(-2);
|
||||||
closesocket(c->GetTCPSock());
|
closesocket(c->GetTCPSock());
|
||||||
|
|
||||||
}else SendError(L,Sec("DropPlayer not enough arguments"));
|
} else
|
||||||
|
SendError(L, Sec("DropPlayer not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_sendChat(lua_State* L) {
|
int lua_sendChat(lua_State* L) {
|
||||||
@ -302,13 +362,17 @@ int lua_sendChat(lua_State *L){
|
|||||||
} else {
|
} else {
|
||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
if(!c->isSynced)return 0;
|
if (!c->isSynced)
|
||||||
|
return 0;
|
||||||
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
|
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
|
||||||
Respond(c, Packet, true);
|
Respond(c, Packet, true);
|
||||||
}else SendError(L,Sec("SendChatMessage invalid argument [1] invalid ID"));
|
} else
|
||||||
|
SendError(L, Sec("SendChatMessage invalid argument [1] invalid ID"));
|
||||||
}
|
}
|
||||||
}else SendError(L,Sec("SendChatMessage invalid argument [2] expected string"));
|
} else
|
||||||
}else SendError(L,Sec("SendChatMessage invalid argument [1] expected number"));
|
SendError(L, Sec("SendChatMessage invalid argument [2] expected string"));
|
||||||
|
} else
|
||||||
|
SendError(L, Sec("SendChatMessage invalid argument [1] expected number"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_RemoveVehicle(lua_State* L) {
|
int lua_RemoveVehicle(lua_State* L) {
|
||||||
@ -325,13 +389,15 @@ int lua_RemoveVehicle(lua_State *L){
|
|||||||
SendError(L, Sec("RemoveVehicle invalid Player ID"));
|
SendError(L, Sec("RemoveVehicle invalid Player ID"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(c->GetRole() == "MDEV")return 0;
|
if (c->GetRole() == "MDEV")
|
||||||
|
return 0;
|
||||||
if (!c->GetCarData(VID).empty()) {
|
if (!c->GetCarData(VID).empty()) {
|
||||||
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
|
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
|
||||||
SendToAll(nullptr, Destroy, true, true);
|
SendToAll(nullptr, Destroy, true, true);
|
||||||
c->DeleteCar(VID);
|
c->DeleteCar(VID);
|
||||||
}
|
}
|
||||||
}else SendError(L,Sec("RemoveVehicle invalid argument expected number"));
|
} else
|
||||||
|
SendError(L, Sec("RemoveVehicle invalid argument expected number"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_HWID(lua_State* L) {
|
int lua_HWID(lua_State* L) {
|
||||||
@ -358,7 +424,8 @@ int lua_RemoteEvent(lua_State *L){
|
|||||||
}
|
}
|
||||||
int ID = int(lua_tointeger(L, 1));
|
int ID = int(lua_tointeger(L, 1));
|
||||||
std::string Packet = "E:" + std::string(lua_tostring(L, 2)) + ":" + std::string(lua_tostring(L, 3));
|
std::string Packet = "E:" + std::string(lua_tostring(L, 2)) + ":" + std::string(lua_tostring(L, 3));
|
||||||
if(ID == -1)SendToAll(nullptr,Packet,true,true);
|
if (ID == -1)
|
||||||
|
SendToAll(nullptr, Packet, true, true);
|
||||||
else {
|
else {
|
||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if (c == nullptr) {
|
if (c == nullptr) {
|
||||||
@ -369,7 +436,7 @@ int lua_RemoteEvent(lua_State *L){
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_ServerExit(lua_State *L){
|
int lua_ServerExit(lua_State*) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
int lua_Set(lua_State* L) {
|
int lua_Set(lua_State* L) {
|
||||||
@ -382,60 +449,63 @@ int lua_Set(lua_State *L){
|
|||||||
SendError(L, Sec("set invalid argument [1] expected number"));
|
SendError(L, Sec("set invalid argument [1] expected number"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Lua* Src = GetScript(L);
|
auto MaybeSrc = GetScript(L);
|
||||||
std::string Name;
|
std::string Name;
|
||||||
if(Src == nullptr)Name = Sec("Console");
|
if (!MaybeSrc.has_value()) {
|
||||||
else Name = Src->GetPluginName();
|
Name = Sec("_Console");
|
||||||
|
} else {
|
||||||
|
Name = MaybeSrc.value().get().GetPluginName();
|
||||||
|
}
|
||||||
int C = int(lua_tointeger(L, 1));
|
int C = int(lua_tointeger(L, 1));
|
||||||
switch (C) {
|
switch (C) {
|
||||||
case 0: //debug
|
case 0: //debug
|
||||||
if (lua_isboolean(L, 2)) {
|
if (lua_isboolean(L, 2)) {
|
||||||
Debug = lua_toboolean(L, 2);
|
Debug = lua_toboolean(L, 2);
|
||||||
info(Name + Sec(" | Debug -> ") + (Debug ? "true" : "false"));
|
info(Name + Sec(" | Debug -> ") + (Debug ? "true" : "false"));
|
||||||
}
|
} else
|
||||||
else SendError(L,Sec("set invalid argument [2] expected boolean for ID : 0"));
|
SendError(L, Sec("set invalid argument [2] expected boolean for ID : 0"));
|
||||||
break;
|
break;
|
||||||
case 1: //private
|
case 1: //private
|
||||||
if (lua_isboolean(L, 2)) {
|
if (lua_isboolean(L, 2)) {
|
||||||
Private = lua_toboolean(L, 2);
|
Private = lua_toboolean(L, 2);
|
||||||
info(Name + Sec(" | Private -> ") + (Private ? "true" : "false"));
|
info(Name + Sec(" | Private -> ") + (Private ? "true" : "false"));
|
||||||
}
|
} else
|
||||||
else SendError(L,Sec("set invalid argument [2] expected boolean for ID : 1"));
|
SendError(L, Sec("set invalid argument [2] expected boolean for ID : 1"));
|
||||||
break;
|
break;
|
||||||
case 2: //max cars
|
case 2: //max cars
|
||||||
if (lua_isnumber(L, 2)) {
|
if (lua_isnumber(L, 2)) {
|
||||||
MaxCars = int(lua_tointeger(L, 2));
|
MaxCars = int(lua_tointeger(L, 2));
|
||||||
info(Name + Sec(" | MaxCars -> ") + std::to_string(MaxCars));
|
info(Name + Sec(" | MaxCars -> ") + std::to_string(MaxCars));
|
||||||
}
|
} else
|
||||||
else SendError(L,Sec("set invalid argument [2] expected number for ID : 2"));
|
SendError(L, Sec("set invalid argument [2] expected number for ID : 2"));
|
||||||
break;
|
break;
|
||||||
case 3: //max players
|
case 3: //max players
|
||||||
if (lua_isnumber(L, 2)) {
|
if (lua_isnumber(L, 2)) {
|
||||||
MaxPlayers = int(lua_tointeger(L, 2));
|
MaxPlayers = int(lua_tointeger(L, 2));
|
||||||
info(Name + Sec(" | MaxPlayers -> ") + std::to_string(MaxPlayers));
|
info(Name + Sec(" | MaxPlayers -> ") + std::to_string(MaxPlayers));
|
||||||
}
|
} else
|
||||||
else SendError(L,Sec("set invalid argument [2] expected number for ID : 3"));
|
SendError(L, Sec("set invalid argument [2] expected number for ID : 3"));
|
||||||
break;
|
break;
|
||||||
case 4: //Map
|
case 4: //Map
|
||||||
if (lua_isstring(L, 2)) {
|
if (lua_isstring(L, 2)) {
|
||||||
MapName = lua_tostring(L, 2);
|
MapName = lua_tostring(L, 2);
|
||||||
info(Name + Sec(" | MapName -> ") + MapName);
|
info(Name + Sec(" | MapName -> ") + MapName);
|
||||||
}
|
} else
|
||||||
else SendError(L,Sec("set invalid argument [2] expected string for ID : 4"));
|
SendError(L, Sec("set invalid argument [2] expected string for ID : 4"));
|
||||||
break;
|
break;
|
||||||
case 5: //Name
|
case 5: //Name
|
||||||
if (lua_isstring(L, 2)) {
|
if (lua_isstring(L, 2)) {
|
||||||
ServerName = lua_tostring(L, 2);
|
ServerName = lua_tostring(L, 2);
|
||||||
info(Name + Sec(" | ServerName -> ") + ServerName);
|
info(Name + Sec(" | ServerName -> ") + ServerName);
|
||||||
}
|
} else
|
||||||
else SendError(L,Sec("set invalid argument [2] expected string for ID : 5"));
|
SendError(L, Sec("set invalid argument [2] expected string for ID : 5"));
|
||||||
break;
|
break;
|
||||||
case 6: //Desc
|
case 6: //Desc
|
||||||
if (lua_isstring(L, 2)) {
|
if (lua_isstring(L, 2)) {
|
||||||
ServerDesc = lua_tostring(L, 2);
|
ServerDesc = lua_tostring(L, 2);
|
||||||
info(Name + Sec(" | ServerDesc -> ") + ServerDesc);
|
info(Name + Sec(" | ServerDesc -> ") + ServerDesc);
|
||||||
}
|
} else
|
||||||
else SendError(L,Sec("set invalid argument [2] expected string for ID : 6"));
|
SendError(L, Sec("set invalid argument [2] expected string for ID : 6"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warn(Sec("Invalid config ID : ") + std::to_string(C));
|
warn(Sec("Invalid config ID : ") + std::to_string(C));
|
||||||
@ -454,7 +524,68 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lua::Lua(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote, bool Console)
|
||||||
|
: luaState(luaL_newstate()) {
|
||||||
|
Assert(luaState);
|
||||||
|
if (!PluginName.empty()) {
|
||||||
|
SetPluginName(PluginName);
|
||||||
|
}
|
||||||
|
if (!FileName.empty()) {
|
||||||
|
SetFileName(FileName);
|
||||||
|
}
|
||||||
|
SetLastWrite(LastWrote);
|
||||||
|
_Console = Console;
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua::Lua(bool Console)
|
||||||
|
: luaState(luaL_newstate()) {
|
||||||
|
_Console = Console;
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua::Execute(const std::string& Command) {
|
||||||
|
if (ConsoleCheck(luaState, luaL_dostring(luaState, Command.c_str()))) {
|
||||||
|
lua_settop(luaState, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Lua::Reload() {
|
||||||
|
if (CheckLua(luaState, luaL_dofile(luaState, _FileName.c_str()))) {
|
||||||
|
CallFunction(this, Sec("onInit"), nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string Lua::GetOrigin() {
|
||||||
|
return GetFileName().substr(GetFileName().find('\\'));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallFunction(Lua* lua, const std::string& FuncName, std::unique_ptr<LuaArg> Arg) {
|
||||||
|
lua_State* luaState = lua->GetState();
|
||||||
|
lua_getglobal(luaState, FuncName.c_str());
|
||||||
|
if (lua_isfunction(luaState, -1)) {
|
||||||
|
int Size = 0;
|
||||||
|
if (Arg != nullptr) {
|
||||||
|
Size = int(Arg->args.size());
|
||||||
|
Arg->PushArgs(luaState);
|
||||||
|
}
|
||||||
|
std::string Origin = lua->GetOrigin();
|
||||||
|
int R = lua_pcall(luaState, Size, 1, 0);
|
||||||
|
if (CheckLua(luaState, R)) {
|
||||||
|
if (lua_isnumber(luaState, -1)) {
|
||||||
|
return int(lua_tointeger(luaState, -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClearStack(luaState);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void Lua::SetPluginName(const std::string& Name) {
|
||||||
|
_PluginName = Name;
|
||||||
|
}
|
||||||
|
void Lua::SetFileName(const std::string& Name) {
|
||||||
|
_FileName = Name;
|
||||||
|
}
|
||||||
void Lua::Init() {
|
void Lua::Init() {
|
||||||
|
Assert(luaState);
|
||||||
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);
|
||||||
@ -476,92 +607,57 @@ void Lua::Init(){
|
|||||||
lua_register(luaState, "Sleep", lua_Sleep);
|
lua_register(luaState, "Sleep", lua_Sleep);
|
||||||
lua_register(luaState, "print", lua_Print);
|
lua_register(luaState, "print", lua_Print);
|
||||||
lua_register(luaState, "Set", lua_Set);
|
lua_register(luaState, "Set", lua_Set);
|
||||||
if(!Console)Reload();
|
if (!_Console)
|
||||||
}
|
Reload();
|
||||||
void Lua::Execute(const std::string& Command){
|
|
||||||
if(ConsoleCheck(luaState,luaL_dostring(luaState,Command.c_str()))){
|
|
||||||
lua_settop(luaState, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Lua::Reload(){
|
|
||||||
if(CheckLua(luaState,luaL_dofile(luaState,FileName.c_str()))){
|
|
||||||
CallFunction(this,Sec("onInit"), nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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());
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
int CallFunction(Lua*lua,const std::string& FuncName,LuaArg* Arg){
|
|
||||||
lua_State*luaState = lua->GetState();
|
|
||||||
lua_getglobal(luaState, FuncName.c_str());
|
|
||||||
if(lua_isfunction(luaState, -1)) {
|
|
||||||
int Size = 0;
|
|
||||||
if(Arg != nullptr){
|
|
||||||
Size = int(Arg->args.size());
|
|
||||||
Arg->PushArgs(luaState);
|
|
||||||
delete Arg;
|
|
||||||
Arg = nullptr;
|
|
||||||
}
|
|
||||||
int R = 0;
|
|
||||||
char* Origin = lua->GetOrigin();
|
|
||||||
__try{
|
|
||||||
R = lua_pcall(luaState, Size, 1, 0);
|
|
||||||
if (CheckLua(luaState, R)){
|
|
||||||
if (lua_isnumber(luaState, -1)) {
|
|
||||||
return int(lua_tointeger(luaState, -1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}__except(Handle(GetExceptionInformation(),Origin)){}
|
|
||||||
delete [] Origin;
|
|
||||||
}
|
|
||||||
ClearStack(luaState);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void Lua::SetPluginName(const std::string&Name){
|
|
||||||
PluginName = Name;
|
|
||||||
}
|
|
||||||
void Lua::SetFileName(const std::string&Name){
|
|
||||||
FileName = Name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lua::RegisterEvent(const std::string& Event, const std::string& FunctionName) {
|
void Lua::RegisterEvent(const std::string& Event, const std::string& FunctionName) {
|
||||||
RegisteredEvents.insert(std::make_pair(Event,FunctionName));
|
_RegisteredEvents.insert(std::make_pair(Event, FunctionName));
|
||||||
}
|
}
|
||||||
void Lua::UnRegisterEvent(const std::string& Event) {
|
void Lua::UnRegisterEvent(const std::string& Event) {
|
||||||
for(const std::pair<std::string,std::string>& a : RegisteredEvents){
|
for (const std::pair<std::string, std::string>& a : _RegisteredEvents) {
|
||||||
if (a.first == Event) {
|
if (a.first == Event) {
|
||||||
RegisteredEvents.erase(a);
|
_RegisteredEvents.erase(a);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool Lua::IsRegistered(const std::string& Event) {
|
bool Lua::IsRegistered(const std::string& Event) {
|
||||||
for(const std::pair<std::string,std::string>& a : RegisteredEvents){
|
for (const std::pair<std::string, std::string>& a : _RegisteredEvents) {
|
||||||
if(a.first == Event)return true;
|
if (a.first == Event)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string Lua::GetRegistered(const std::string&Event){
|
std::string Lua::GetRegistered(const std::string& Event) const {
|
||||||
for(const std::pair<std::string,std::string>& a : RegisteredEvents){
|
for (const std::pair<std::string, std::string>& a : _RegisteredEvents) {
|
||||||
if(a.first == Event)return a.second;
|
if (a.first == Event)
|
||||||
|
return a.second;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
std::string Lua::GetFileName(){
|
std::string Lua::GetFileName() const {
|
||||||
return FileName;
|
return _FileName;
|
||||||
}
|
}
|
||||||
std::string Lua::GetPluginName(){
|
std::string Lua::GetPluginName() const {
|
||||||
return PluginName;
|
return _PluginName;
|
||||||
}
|
}
|
||||||
lua_State* Lua::GetState() {
|
lua_State* Lua::GetState() {
|
||||||
return luaState;
|
return luaState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lua_State* Lua::GetState() const {
|
||||||
|
return luaState;
|
||||||
|
}
|
||||||
|
|
||||||
void Lua::SetLastWrite(fs::file_time_type time) {
|
void Lua::SetLastWrite(fs::file_time_type time) {
|
||||||
LastWrote = time;
|
_LastWrote = time;
|
||||||
}
|
}
|
||||||
fs::file_time_type Lua::GetLastWrite() {
|
fs::file_time_type Lua::GetLastWrite() {
|
||||||
return LastWrote;
|
return _LastWrote;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua::~Lua() {
|
||||||
|
info("closing lua state");
|
||||||
|
lua_close(luaState);
|
||||||
}
|
}
|
||||||
|
@ -8,23 +8,50 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "UnixCompat.h"
|
||||||
|
|
||||||
|
|
||||||
struct Hold{
|
struct Hold{
|
||||||
SOCKET TCPSock{};
|
SOCKET TCPSock{};
|
||||||
bool Done = false;
|
bool Done = false;
|
||||||
};
|
};
|
||||||
bool Send(SOCKET TCPSock,std::string Data){
|
bool Send(SOCKET TCPSock,std::string Data){
|
||||||
|
#ifdef WIN32
|
||||||
int BytesSent;
|
int BytesSent;
|
||||||
BytesSent = send(TCPSock, Data.c_str(), int(Data.size()), 0);
|
int len = static_cast<int>(Data.size());
|
||||||
|
#else
|
||||||
|
int64_t BytesSent;
|
||||||
|
size_t len = Data.size();
|
||||||
|
#endif // WIN32
|
||||||
|
BytesSent = send(TCPSock, Data.c_str(), len, 0);
|
||||||
Data.clear();
|
Data.clear();
|
||||||
if (BytesSent <= 0)return false;
|
if (BytesSent <= 0)return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
std::string Rcv(SOCKET TCPSock){
|
std::string Rcv(SOCKET TCPSock){
|
||||||
char buf[6768];
|
uint32_t RealSize;
|
||||||
int len = 6768;
|
int64_t BytesRcv = recv(TCPSock, &RealSize, sizeof(RealSize), 0);
|
||||||
ZeroMemory(buf, len);
|
if (BytesRcv != sizeof(RealSize)) {
|
||||||
int BytesRcv = recv(TCPSock, buf, len,0);
|
error(std::string(Sec("invalid packet: expected 4, got ")) + std::to_string(BytesRcv));
|
||||||
if (BytesRcv <= 0)return "";
|
return "";
|
||||||
|
}
|
||||||
|
// RealSize is big-endian, so we convert it to host endianness
|
||||||
|
RealSize = ntohl(RealSize);
|
||||||
|
debug(std::string("got ") + std::to_string(RealSize) + " as size");
|
||||||
|
if (RealSize > 7000) {
|
||||||
|
error(Sec("Larger than allowed TCP packet received"));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
char buf[7000];
|
||||||
|
std::fill_n(buf, 7000, 0);
|
||||||
|
BytesRcv = recv(TCPSock, buf, RealSize, 0);
|
||||||
|
if (BytesRcv != RealSize) {
|
||||||
|
debug("expected " + std::to_string(RealSize) + " bytes, got " + std::to_string(BytesRcv) + " instead");
|
||||||
|
}
|
||||||
|
if (BytesRcv <= 0)
|
||||||
|
return "";
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
}
|
}
|
||||||
std::string GetRole(const std::string &DID){
|
std::string GetRole(const std::string &DID){
|
||||||
@ -86,17 +113,21 @@ std::string GenerateM(RSA*key){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Identification(SOCKET TCPSock,Hold*S,RSA*Skey){
|
void Identification(SOCKET TCPSock,Hold*S,RSA*Skey){
|
||||||
|
Assert(S);
|
||||||
|
Assert(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(Skey))){
|
if(!Send(TCPSock,GenerateM(Skey))){
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(TCPSock);
|
closesocket(TCPSock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string msg = Rcv(TCPSock);
|
std::string msg = Rcv(TCPSock);
|
||||||
auto Keys = Parse(msg);
|
auto Keys = Parse(msg);
|
||||||
if(!Send(TCPSock,RSA_E("HC",Keys.second,Keys.first))){
|
if(!Send(TCPSock,RSA_E("HC",Keys.second,Keys.first))){
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(TCPSock);
|
closesocket(TCPSock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -108,26 +139,31 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*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()){
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(TCPSock);
|
closesocket(TCPSock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(TCPSock);
|
closesocket(TCPSock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Res = RSA_D(Res,Skey);
|
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")) {
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(TCPSock);
|
closesocket(TCPSock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(Res.find(':') == std::string::npos){
|
if(Res.find(':') == std::string::npos){
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(TCPSock);
|
closesocket(TCPSock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Name = Res.substr(2,Res.find(':')-2);
|
Name = Res.substr(2,Res.find(':')-2);
|
||||||
DID = Res.substr(Res.find(':')+1);
|
DID = Res.substr(Res.find(':')+1);
|
||||||
Role = GetRole(DID);
|
Role = GetRole(DID);
|
||||||
if(Role.empty() || Role.find(Sec("Error")) != -1){
|
if(Role.empty() || Role.find(Sec("Error")) != std::string::npos){
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(TCPSock);
|
closesocket(TCPSock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -135,6 +171,7 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*Skey){
|
|||||||
for(Client*c: CI->Clients){
|
for(Client*c: CI->Clients){
|
||||||
if(c != nullptr){
|
if(c != nullptr){
|
||||||
if(c->GetDID() == DID){
|
if(c->GetDID() == DID){
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(c->GetTCPSock());
|
closesocket(c->GetTCPSock());
|
||||||
c->SetStatus(-2);
|
c->SetStatus(-2);
|
||||||
break;
|
break;
|
||||||
@ -142,23 +179,40 @@ void Identification(SOCKET TCPSock,Hold*S,RSA*Skey){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(Role == Sec("MDEV") || CI->Size() < Max()){
|
if(Role == Sec("MDEV") || CI->Size() < Max()){
|
||||||
|
debug("Identification success");
|
||||||
CreateClient(TCPSock,Name,DID,Role);
|
CreateClient(TCPSock,Name,DID,Role);
|
||||||
}else closesocket(TCPSock);
|
} else {
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
|
closesocket(TCPSock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void Identify(SOCKET TCPSock){
|
void Identify(SOCKET TCPSock){
|
||||||
auto* S = new Hold;
|
auto* S = new Hold;
|
||||||
RSA*Skey = GenKey();
|
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{
|
__try{
|
||||||
|
#endif // WIN32
|
||||||
Identification(TCPSock,S,Skey);
|
Identification(TCPSock,S,Skey);
|
||||||
|
#ifdef WIN32
|
||||||
}__except(1){
|
}__except(1){
|
||||||
if(TCPSock != -1){
|
if(TCPSock != -1){
|
||||||
|
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
closesocket(TCPSock);
|
closesocket(TCPSock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
delete Skey;
|
delete Skey;
|
||||||
delete S;
|
delete S;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPServerMain(){
|
void TCPServerMain(){
|
||||||
|
DebugPrintTID();
|
||||||
|
#ifdef WIN32
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
if (WSAStartup(514, &wsaData)){
|
if (WSAStartup(514, &wsaData)){
|
||||||
error(Sec("Can't start Winsock!"));
|
error(Sec("Can't start Winsock!"));
|
||||||
@ -195,4 +249,39 @@ void TCPServerMain(){
|
|||||||
|
|
||||||
closesocket(client);
|
closesocket(client);
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
#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(uint16_t(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);
|
||||||
|
|
||||||
|
debug("all ok, arrived at " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
|
closesocket(client);
|
||||||
|
#endif // WIN32
|
||||||
}
|
}
|
@ -7,8 +7,10 @@
|
|||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Network.h"
|
#include "Network.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "UnixCompat.h"
|
||||||
#include <sstream>
|
#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);
|
||||||
int j;
|
int j;
|
||||||
@ -19,6 +21,7 @@ int FC(const std::string& s,const std::string& p,int n) {
|
|||||||
else return -1;
|
else return -1;
|
||||||
}
|
}
|
||||||
void Apply(Client*c,int VID,const std::string& pckt){
|
void Apply(Client*c,int VID,const std::string& pckt){
|
||||||
|
Assert(c);
|
||||||
std::string Packet = pckt;
|
std::string Packet = pckt;
|
||||||
std::string VD = c->GetCarData(VID);
|
std::string VD = c->GetCarData(VID);
|
||||||
Packet = Packet.substr(FC(Packet, ",", 2) + 1);
|
Packet = Packet.substr(FC(Packet, ",", 2) + 1);
|
||||||
@ -29,6 +32,7 @@ void Apply(Client*c,int VID,const std::string& pckt){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VehicleParser(Client*c,const std::string& Pckt){
|
void VehicleParser(Client*c,const std::string& Pckt){
|
||||||
|
Assert(c);
|
||||||
if(c == nullptr || Pckt.length() < 4)return;
|
if(c == nullptr || Pckt.length() < 4)return;
|
||||||
std::string Packet = Pckt;
|
std::string Packet = Pckt;
|
||||||
char Code = Packet.at(1);
|
char Code = Packet.at(1);
|
||||||
@ -43,7 +47,8 @@ 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)}},true)){
|
std::unique_ptr<LuaArg>(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);
|
||||||
@ -63,7 +68,8 @@ 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)}},true)) {
|
std::unique_ptr<LuaArg>(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{
|
||||||
@ -83,7 +89,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}},false);
|
std::unique_ptr<LuaArg>(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));
|
||||||
}
|
}
|
||||||
@ -92,16 +98,18 @@ void VehicleParser(Client*c,const std::string& Pckt){
|
|||||||
SendToAll(c,Packet,false,true);
|
SendToAll(c,Packet,false,true);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
AssertNotReachable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SyncClient(Client*c){
|
void SyncClient(Client*c){
|
||||||
|
Assert(c);
|
||||||
if(c->isSynced)return;
|
if(c->isSynced)return;
|
||||||
c->isSynced = true;
|
c->isSynced = true;
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
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()}},false);
|
TriggerLuaEvent(Sec("onPlayerJoin"),false,nullptr,std::unique_ptr<LuaArg>(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) {
|
||||||
@ -117,12 +125,18 @@ void SyncClient(Client*c){
|
|||||||
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){
|
||||||
|
Assert(c);
|
||||||
|
#ifdef WIN32
|
||||||
__try{
|
__try{
|
||||||
VehicleParser(c,Packet);
|
VehicleParser(c,Packet);
|
||||||
}__except(Handle(GetExceptionInformation(),Sec("Vehicle Handler"))){}
|
}__except(Handle(GetExceptionInformation(),Sec("Vehicle Handler"))){}
|
||||||
|
#else // unix
|
||||||
|
VehicleParser(c,Packet);
|
||||||
|
#endif // WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleEvent(Client*c ,const std::string&Data){
|
void HandleEvent(Client*c ,const std::string&Data){
|
||||||
|
Assert(c);
|
||||||
std::stringstream ss(Data);
|
std::stringstream ss(Data);
|
||||||
std::string t,Name;
|
std::string t,Name;
|
||||||
int a = 0;
|
int a = 0;
|
||||||
@ -132,7 +146,7 @@ void HandleEvent(Client*c ,const std::string&Data){
|
|||||||
Name = t;
|
Name = t;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
TriggerLuaEvent(Name, false, nullptr,new LuaArg{{c->GetID(),t}},false);
|
TriggerLuaEvent(Name, false, nullptr,std::unique_ptr<LuaArg>(new LuaArg{{c->GetID(),t}}),false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -143,7 +157,8 @@ void HandleEvent(Client*c ,const std::string&Data){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GlobalParser(Client*c, const std::string& Pack){
|
void GlobalParser(Client*c, const std::string& Pack){
|
||||||
static int lastRecv = 0;
|
Assert(c);
|
||||||
|
[[maybe_unused]] static int lastRecv = 0;
|
||||||
if(Pack.empty() || c == nullptr)return;
|
if(Pack.empty() || c == nullptr)return;
|
||||||
std::string Packet = Pack.substr(0,Pack.find(char(0)));
|
std::string Packet = Pack.substr(0,Pack.find(char(0)));
|
||||||
std::string pct;
|
std::string pct;
|
||||||
@ -157,7 +172,7 @@ void GlobalParser(Client*c, const std::string& Pack){
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (Code) {
|
switch (Code) {
|
||||||
case 'P':
|
case 'P': // initial connection
|
||||||
Respond(c, Sec("P") + std::to_string(c->GetID()),true);
|
Respond(c, Sec("P") + std::to_string(c->GetID()),true);
|
||||||
SyncClient(c);
|
SyncClient(c);
|
||||||
return;
|
return;
|
||||||
@ -175,10 +190,11 @@ void GlobalParser(Client*c, const std::string& Pack){
|
|||||||
SendToAll(c,Packet,false,true);
|
SendToAll(c,Packet,false,true);
|
||||||
return;
|
return;
|
||||||
case 'C':
|
case 'C':
|
||||||
if(Packet.length() < 4 || Packet.find(':', 3) == -1)break;
|
if(Packet.length() < 4 || Packet.find(':', 3) == std::string::npos)break;
|
||||||
if (TriggerLuaEvent(Sec("onChatMessage"), false, nullptr,new LuaArg{
|
if (TriggerLuaEvent(Sec("onChatMessage"), false, nullptr,
|
||||||
|
std::unique_ptr<LuaArg>(new LuaArg{
|
||||||
{c->GetID(), c->GetName(), Packet.substr(Packet.find(':', 3) + 1)}
|
{c->GetID(), c->GetName(), Packet.substr(Packet.find(':', 3) + 1)}
|
||||||
},true))break;
|
}),true))break;
|
||||||
SendToAll(nullptr, Packet, true, true);
|
SendToAll(nullptr, Packet, true, true);
|
||||||
return;
|
return;
|
||||||
case 'E':
|
case 'E':
|
||||||
@ -190,7 +206,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){
|
||||||
|
Assert(c);
|
||||||
|
#ifdef WIN32
|
||||||
__try{
|
__try{
|
||||||
GlobalParser(c, Packet);
|
GlobalParser(c, Packet);
|
||||||
}__except(Handle(GetExceptionInformation(),Sec("Global Handler"))){}
|
}__except(Handle(GetExceptionInformation(),Sec("Global Handler"))){}
|
||||||
|
#else
|
||||||
|
GlobalParser(c, Packet);
|
||||||
|
#endif // WIN32
|
||||||
}
|
}
|
@ -3,6 +3,7 @@
|
|||||||
///
|
///
|
||||||
#define CURL_STATICLIB
|
#define CURL_STATICLIB
|
||||||
#include "Curl/curl.h"
|
#include "Curl/curl.h"
|
||||||
|
#include "CustomAssert.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp){
|
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp){
|
||||||
((std::string*)userp)->append((char*)contents, size * nmemb);
|
((std::string*)userp)->append((char*)contents, size * nmemb);
|
||||||
@ -13,6 +14,7 @@ std::string HttpRequest(const std::string& IP,int port){
|
|||||||
CURLcode res;
|
CURLcode res;
|
||||||
std::string readBuffer;
|
std::string readBuffer;
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
|
Assert(curl);
|
||||||
if(curl) {
|
if(curl) {
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
||||||
curl_easy_setopt(curl, CURLOPT_PORT, port);
|
curl_easy_setopt(curl, CURLOPT_PORT, port);
|
||||||
@ -30,6 +32,7 @@ std::string PostHTTP(const std::string& IP,const std::string& Fields){
|
|||||||
CURLcode res;
|
CURLcode res;
|
||||||
std::string readBuffer;
|
std::string readBuffer;
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
|
Assert(curl);
|
||||||
if(curl) {
|
if(curl) {
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size());
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size());
|
||||||
|
@ -24,6 +24,7 @@ int OpenID(){
|
|||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
void Respond(Client*c, const std::string& MSG, bool Rel){
|
void Respond(Client*c, const std::string& MSG, bool Rel){
|
||||||
|
Assert(c);
|
||||||
char C = MSG.at(0);
|
char C = MSG.at(0);
|
||||||
if(Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E'){
|
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);
|
||||||
@ -31,6 +32,9 @@ void Respond(Client*c, const std::string& MSG, bool Rel){
|
|||||||
}else UDPSend(c,MSG);
|
}else UDPSend(c,MSG);
|
||||||
}
|
}
|
||||||
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel){
|
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel){
|
||||||
|
if (!Self) {
|
||||||
|
Assert(c);
|
||||||
|
}
|
||||||
char C = Data.at(0);
|
char C = Data.at(0);
|
||||||
for(Client*client : CI->Clients){
|
for(Client*client : CI->Clients){
|
||||||
if(client != nullptr) {
|
if(client != nullptr) {
|
||||||
@ -55,6 +59,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){
|
||||||
|
Assert(c);
|
||||||
info(c->GetName() + Sec(" Connection Terminated"));
|
info(c->GetName() + Sec(" Connection Terminated"));
|
||||||
if(c == nullptr)return;
|
if(c == nullptr)return;
|
||||||
std::string Packet;
|
std::string Packet;
|
||||||
@ -68,18 +73,19 @@ 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()}},false);
|
TriggerLuaEvent(Sec("onPlayerDisconnect"),false,nullptr,std::unique_ptr<LuaArg>(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){
|
||||||
|
Assert(c);
|
||||||
info(Sec("Client connected"));
|
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()}},false);
|
TriggerLuaEvent(Sec("onPlayerConnecting"),false,nullptr,std::unique_ptr<LuaArg>(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()}},false);
|
TriggerLuaEvent(Sec("onPlayerJoining"),false,nullptr,std::unique_ptr<LuaArg>(new LuaArg{{c->GetID()}}),false);
|
||||||
}
|
}
|
@ -30,6 +30,7 @@ void Monitor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]]void Stat(){
|
[[noreturn]]void Stat(){
|
||||||
|
DebugPrintTID();
|
||||||
while(true){
|
while(true){
|
||||||
Monitor();
|
Monitor();
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
@ -1,25 +1,42 @@
|
|||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 8/1/2020
|
/// Created by Anonymous275 on 8/1/2020
|
||||||
///
|
///
|
||||||
#include "Security/Enc.h"
|
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
#include "Settings.h"
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "Security/Enc.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
#include "UnixCompat.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#ifdef __linux
|
||||||
|
// we need this for `struct stat`
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif // __linux
|
||||||
|
|
||||||
void STCPSend(Client* c, std::string Data) {
|
void STCPSend(Client* c, std::string Data) {
|
||||||
if(c == nullptr)return;
|
Assert(c);
|
||||||
|
if (c == nullptr)
|
||||||
|
return;
|
||||||
|
#ifdef WIN32
|
||||||
int BytesSent;
|
int BytesSent;
|
||||||
BytesSent = send(c->GetTCPSock(), Data.c_str(), int(Data.size()), 0);
|
int len = static_cast<int>(Data.size());
|
||||||
|
#else
|
||||||
|
int64_t BytesSent;
|
||||||
|
size_t len = Data.size();
|
||||||
|
#endif // WIN32
|
||||||
|
BytesSent = send(c->GetTCPSock(), Data.c_str(), len, 0);
|
||||||
Data.clear();
|
Data.clear();
|
||||||
if (BytesSent == 0) {
|
if (BytesSent == 0) {
|
||||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
} else if (BytesSent < 0) {
|
} else if (BytesSent < 0) {
|
||||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
closesocket(c->GetTCPSock());
|
closesocket(c->GetTCPSock());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SendFile(Client* c, const std::string& Name) {
|
void SendFile(Client* c, const std::string& Name) {
|
||||||
|
Assert(c);
|
||||||
info(c->GetName() + Sec(" requesting : ") + Name.substr(Name.find_last_of('/')));
|
info(c->GetName() + Sec(" requesting : ") + Name.substr(Name.find_last_of('/')));
|
||||||
struct stat Info {};
|
struct stat Info {};
|
||||||
if (stat(Name.c_str(), &Info) != 0) {
|
if (stat(Name.c_str(), &Info) != 0) {
|
||||||
@ -29,20 +46,22 @@ void SendFile(Client*c,const std::string&Name){
|
|||||||
std::ifstream f(Name.c_str(), std::ios::binary);
|
std::ifstream f(Name.c_str(), std::ios::binary);
|
||||||
f.seekg(0, std::ios_base::end);
|
f.seekg(0, std::ios_base::end);
|
||||||
std::streampos fileSize = f.tellg();
|
std::streampos fileSize = f.tellg();
|
||||||
size_t Size = fileSize,Sent = 0,Diff;
|
size_t Size = size_t(fileSize);
|
||||||
int Split = 64000;
|
size_t Sent = 0;
|
||||||
|
size_t Diff;
|
||||||
|
int64_t Split = 64000;
|
||||||
while (c->GetStatus() > -1 && Sent < Size) {
|
while (c->GetStatus() > -1 && Sent < Size) {
|
||||||
Diff = Size - Sent;
|
Diff = Size - Sent;
|
||||||
if(Diff > Split){
|
if (Diff > size_t(Split)) {
|
||||||
std::string Data(Split,0);
|
std::string Data(size_t(Split), 0);
|
||||||
f.seekg(Sent, std::ios_base::beg);
|
f.seekg(int64_t(Sent), std::ios_base::beg);
|
||||||
f.read(&Data[0], Split);
|
f.read(&Data[0], Split);
|
||||||
STCPSend(c, Data);
|
STCPSend(c, Data);
|
||||||
Sent += Split;
|
Sent += size_t(Split);
|
||||||
} else {
|
} else {
|
||||||
std::string Data(Diff, 0);
|
std::string Data(Diff, 0);
|
||||||
f.seekg(Sent, std::ios_base::beg);
|
f.seekg(int64_t(Sent), std::ios_base::beg);
|
||||||
f.read(&Data[0], Diff);
|
f.read(&Data[0], int64_t(Diff));
|
||||||
STCPSend(c, Data);
|
STCPSend(c, Data);
|
||||||
Sent += Diff;
|
Sent += Diff;
|
||||||
}
|
}
|
||||||
@ -51,9 +70,12 @@ void SendFile(Client*c,const std::string&Name){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Parse(Client* c, const std::string& Packet) {
|
void Parse(Client* c, const std::string& Packet) {
|
||||||
if(c == nullptr || Packet.empty())return;
|
Assert(c);
|
||||||
|
if (c == nullptr || Packet.empty())
|
||||||
|
return;
|
||||||
char Code = Packet.at(0), SubCode = 0;
|
char Code = Packet.at(0), SubCode = 0;
|
||||||
if(Packet.length() > 1)SubCode = Packet.at(1);
|
if (Packet.length() > 1)
|
||||||
|
SubCode = Packet.at(1);
|
||||||
switch (Code) {
|
switch (Code) {
|
||||||
case 'f':
|
case 'f':
|
||||||
SendFile(c, Packet.substr(1));
|
SendFile(c, Packet.substr(1));
|
||||||
@ -62,7 +84,8 @@ void Parse(Client*c,const std::string&Packet){
|
|||||||
if (SubCode == 'R') {
|
if (SubCode == 'R') {
|
||||||
debug(Sec("Sending Mod Info"));
|
debug(Sec("Sending Mod Info"));
|
||||||
std::string ToSend = FileList + FileSizes;
|
std::string ToSend = FileList + FileSizes;
|
||||||
if(ToSend.empty())ToSend = "-";
|
if (ToSend.empty())
|
||||||
|
ToSend = "-";
|
||||||
STCPSend(c, ToSend);
|
STCPSend(c, ToSend);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -71,31 +94,39 @@ void Parse(Client*c,const std::string&Packet){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool STCPRecv(Client* c) {
|
bool STCPRecv(Client* c) {
|
||||||
if(c == nullptr)return false;
|
Assert(c);
|
||||||
|
if (c == nullptr)
|
||||||
|
return false;
|
||||||
char buf[200];
|
char buf[200];
|
||||||
int len = 200;
|
size_t len = 200;
|
||||||
ZeroMemory(buf, len);
|
ZeroMemory(buf, len);
|
||||||
int BytesRcv = recv(c->GetTCPSock(), buf, len,0);
|
int64_t BytesRcv = recv(c->GetTCPSock(), buf, len, 0);
|
||||||
if (BytesRcv == 0) {
|
if (BytesRcv == 0) {
|
||||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
closesocket(c->GetTCPSock());
|
closesocket(c->GetTCPSock());
|
||||||
return false;
|
return false;
|
||||||
} else if (BytesRcv < 0) {
|
} else if (BytesRcv < 0) {
|
||||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
closesocket(c->GetTCPSock());
|
closesocket(c->GetTCPSock());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(strcmp(buf,"Done") == 0)return false;
|
if (strcmp(buf, "Done") == 0)
|
||||||
std::string Ret(buf,BytesRcv);
|
return false;
|
||||||
|
std::string Ret(buf, size_t(BytesRcv));
|
||||||
Parse(c, Ret);
|
Parse(c, Ret);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyncResources(Client* c) {
|
void SyncResources(Client* c) {
|
||||||
if(c == nullptr)return;
|
Assert(c);
|
||||||
|
if (c == nullptr)
|
||||||
|
return;
|
||||||
try {
|
try {
|
||||||
STCPSend(c, Sec("WS"));
|
STCPSend(c, Sec("WS"));
|
||||||
while(c->GetStatus() > -1 && STCPRecv(c));
|
while (c->GetStatus() > -1 && STCPRecv(c))
|
||||||
|
;
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
except(Sec("Exception! : ") + std::string(e.what()));
|
except(Sec("Exception! : ") + std::string(e.what()));
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
|
@ -4,12 +4,21 @@
|
|||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Network.h"
|
#include "Network.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "UnixCompat.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
void TCPSend(Client*c,const std::string&Data){
|
void TCPSend(Client*c,const std::string&Data){
|
||||||
|
Assert(c);
|
||||||
if(c == nullptr)return;
|
if(c == nullptr)return;
|
||||||
std::string Send = "\n" + Data.substr(0,Data.find(char(0))) + "\n";
|
std::string Send = "\n" + Data.substr(0,Data.find(char(0))) + "\n";
|
||||||
size_t Sent = send(c->GetTCPSock(), Send.c_str(), int(Send.size()), 0);
|
#ifdef WIN32
|
||||||
|
int Sent;
|
||||||
|
int len = static_cast<int>(Send.size());
|
||||||
|
#else
|
||||||
|
int64_t Sent;
|
||||||
|
size_t len = Send.size();
|
||||||
|
#endif // WIN32
|
||||||
|
Sent = send(c->GetTCPSock(), Send.c_str(), len, 0);
|
||||||
if (Sent == 0){
|
if (Sent == 0){
|
||||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
if(c->GetStatus() > -1)c->SetStatus(-1);
|
||||||
}else if (Sent < 0) {
|
}else if (Sent < 0) {
|
||||||
@ -18,41 +27,51 @@ void TCPSend(Client*c,const std::string&Data){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TCPHandle(Client*c,const std::string& data){
|
void TCPHandle(Client*c,const std::string& data){
|
||||||
|
Assert(c);
|
||||||
|
#ifdef WIN32
|
||||||
__try{
|
__try{
|
||||||
|
#endif // WIN32
|
||||||
c->Handler.Handle(c,data);
|
c->Handler.Handle(c,data);
|
||||||
|
#ifdef WIN32
|
||||||
}__except(1){
|
}__except(1){
|
||||||
c->Handler.clear();
|
c->Handler.clear();
|
||||||
}
|
}
|
||||||
|
#endif // WIN32
|
||||||
}
|
}
|
||||||
void TCPRcv(Client*c){
|
void TCPRcv(Client*c){
|
||||||
|
Assert(c);
|
||||||
if(c == nullptr || c->GetStatus() < 0)return;
|
if(c == nullptr || c->GetStatus() < 0)return;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
int len = 4096;
|
size_t len = 4096;
|
||||||
ZeroMemory(buf, len);
|
ZeroMemory(buf, len);
|
||||||
int BytesRcv = recv(c->GetTCPSock(), buf, len,0);
|
int64_t BytesRcv = recv(c->GetTCPSock(), buf, len,0);
|
||||||
if (BytesRcv == 0){
|
if (BytesRcv == 0){
|
||||||
debug(Sec("(TCP) Connection closing..."));
|
debug(Sec("(TCP) Connection closing..."));
|
||||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
if(c->GetStatus() > -1)c->SetStatus(-1);
|
||||||
return;
|
return;
|
||||||
}else if (BytesRcv < 0) {
|
}else if (BytesRcv < 0) {
|
||||||
|
#ifdef WIN32
|
||||||
debug(Sec("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError()));
|
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);
|
if(c->GetStatus() > -1)c->SetStatus(-1);
|
||||||
closesocket(c->GetTCPSock());
|
closesocket(c->GetTCPSock());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string Buf(buf,BytesRcv);
|
std::string Buf(buf,(size_t(BytesRcv)));
|
||||||
TCPHandle(c,Buf);
|
TCPHandle(c,Buf);
|
||||||
}
|
}
|
||||||
void TCPClient(Client*c){
|
void TCPClient(Client*c){
|
||||||
|
DebugPrintTID();
|
||||||
|
Assert(c);
|
||||||
if(c->GetTCPSock() == -1){
|
if(c->GetTCPSock() == -1){
|
||||||
CI->RemoveClient(c);
|
CI->RemoveClient(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OnConnect(c);
|
OnConnect(c);
|
||||||
while (c->GetStatus() > -1)TCPRcv(c);
|
while (c->GetStatus() > -1)TCPRcv(c);
|
||||||
__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);
|
||||||
|
@ -2,20 +2,23 @@
|
|||||||
/// Created by Anonymous275 on 5/8/2020
|
/// Created by Anonymous275 on 5/8/2020
|
||||||
///
|
///
|
||||||
///UDP
|
///UDP
|
||||||
#include "Security/Enc.h"
|
|
||||||
#include "Compressor.h"
|
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
#include "Settings.h"
|
#include "Compressor.h"
|
||||||
#include "Network.h"
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <sstream>
|
#include "Network.h"
|
||||||
#include <vector>
|
#include "Security/Enc.h"
|
||||||
#include <thread>
|
#include "Settings.h"
|
||||||
|
#include "UnixCompat.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
int FC(const std::string& s, const std::string& p, int n);
|
int FC(const std::string& s, const std::string& p, int n);
|
||||||
struct PacketData {
|
struct PacketData {
|
||||||
int ID;
|
int ID;
|
||||||
Client* Client;
|
::Client* Client;
|
||||||
std::string Data;
|
std::string Data;
|
||||||
int Tries;
|
int Tries;
|
||||||
};
|
};
|
||||||
@ -29,19 +32,42 @@ SOCKET UDPSock;
|
|||||||
std::set<PacketData*> DataAcks;
|
std::set<PacketData*> DataAcks;
|
||||||
std::set<SplitData*> SplitPackets;
|
std::set<SplitData*> SplitPackets;
|
||||||
void UDPSend(Client* c, std::string Data) {
|
void UDPSend(Client* c, std::string Data) {
|
||||||
if(c == nullptr || !c->isConnected || c->GetStatus() < 0)return;
|
Assert(c);
|
||||||
|
if (c == nullptr || !c->isConnected || c->GetStatus() < 0)
|
||||||
|
return;
|
||||||
sockaddr_in Addr = c->GetUDPAddr();
|
sockaddr_in Addr = c->GetUDPAddr();
|
||||||
int AddrSize = sizeof(c->GetUDPAddr());
|
socklen_t AddrSize = sizeof(c->GetUDPAddr());
|
||||||
Data = Data.substr(0, Data.find(char(0)));
|
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);
|
#ifdef WIN32
|
||||||
if (sendOk == SOCKET_ERROR) {
|
int sendOk;
|
||||||
|
int len = static_cast<int>(Data.size());
|
||||||
|
#else
|
||||||
|
int64_t sendOk;
|
||||||
|
size_t len = Data.size();
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
|
sendOk = sendto(UDPSock, Data.c_str(), len, 0, (sockaddr*)&Addr, AddrSize);
|
||||||
|
#ifdef WIN32
|
||||||
|
if (sendOk != 0) {
|
||||||
debug(Sec("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError()));
|
debug(Sec("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError()));
|
||||||
if(c->GetStatus() > -1)c->SetStatus(-1);
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
}
|
}
|
||||||
|
#else // unix
|
||||||
|
if (sendOk == -1) {
|
||||||
|
debug(Sec("(UDP) Send Failed Code : ") + std::string(strerror(errno)));
|
||||||
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
|
} else if (sendOk == 0) {
|
||||||
|
debug(Sec("(UDP) sendto returned 0"));
|
||||||
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
|
}
|
||||||
|
#endif // WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
void AckID(int ID) {
|
void AckID(int ID) {
|
||||||
@ -54,17 +80,22 @@ void AckID(int ID){
|
|||||||
}
|
}
|
||||||
int PacktID() {
|
int PacktID() {
|
||||||
static int ID = -1;
|
static int ID = -1;
|
||||||
if(ID > 999999)ID = 0;
|
if (ID > 999999)
|
||||||
else ID++;
|
ID = 0;
|
||||||
|
else
|
||||||
|
ID++;
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
int SplitID() {
|
int SplitID() {
|
||||||
static int SID = -1;
|
static int SID = -1;
|
||||||
if(SID > 999999)SID = 0;
|
if (SID > 999999)
|
||||||
else SID++;
|
SID = 0;
|
||||||
|
else
|
||||||
|
SID++;
|
||||||
return SID;
|
return SID;
|
||||||
}
|
}
|
||||||
void SendLarge(Client* c, std::string Data) {
|
void SendLarge(Client* c, std::string Data) {
|
||||||
|
Assert(c);
|
||||||
Data = Data.substr(0, Data.find(char(0)));
|
Data = Data.substr(0, Data.find(char(0)));
|
||||||
int ID = PacktID();
|
int ID = PacktID();
|
||||||
std::string Packet;
|
std::string Packet;
|
||||||
@ -73,16 +104,14 @@ void SendLarge(Client*c,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 {
|
||||||
@ -92,17 +121,18 @@ void SendLarge(Client*c,std::string Data){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct HandledC {
|
struct HandledC {
|
||||||
int Pos = 0;
|
size_t Pos = 0;
|
||||||
Client* c = nullptr;
|
Client* c = nullptr;
|
||||||
std::array<int, 100> HandledIDs = { -1 };
|
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 < 100;C++){
|
for (size_t C = 0; C < 100; C++) {
|
||||||
H->HandledIDs.at(C) = -1;
|
H->HandledIDs.at(C) = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HandledC* GetHandled(Client* c) {
|
HandledC* GetHandled(Client* c) {
|
||||||
|
Assert(c);
|
||||||
for (HandledC* h : HandledIDs) {
|
for (HandledC* h : HandledIDs) {
|
||||||
if (h->c == c) {
|
if (h->c == c) {
|
||||||
return h;
|
return h;
|
||||||
@ -111,13 +141,16 @@ HandledC*GetHandled(Client*c){
|
|||||||
return new HandledC();
|
return new HandledC();
|
||||||
}
|
}
|
||||||
bool Handled(Client* c, int ID) {
|
bool Handled(Client* c, int ID) {
|
||||||
|
Assert(c);
|
||||||
bool handle = false;
|
bool handle = false;
|
||||||
for (HandledC* h : HandledIDs) {
|
for (HandledC* h : HandledIDs) {
|
||||||
if (h->c == c) {
|
if (h->c == c) {
|
||||||
for (int id : h->HandledIDs) {
|
for (int id : h->HandledIDs) {
|
||||||
if(id == ID)return true;
|
if (id == ID)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if(h->Pos > 99)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;
|
||||||
@ -132,7 +165,8 @@ 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 > 99)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;
|
||||||
@ -141,12 +175,16 @@ bool Handled(Client*c,int ID){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string UDPRcvFromClient(sockaddr_in& client) {
|
std::string UDPRcvFromClient(sockaddr_in& client) {
|
||||||
int clientLength = sizeof(client);
|
size_t clientLength = sizeof(client);
|
||||||
ZeroMemory(&client, clientLength);
|
ZeroMemory(&client, clientLength);
|
||||||
std::string Ret(10240, 0);
|
std::string Ret(10240, 0);
|
||||||
int Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&client, &clientLength);
|
int64_t Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&client, (socklen_t*)&clientLength);
|
||||||
if (Rcv == -1) {
|
if (Rcv == -1) {
|
||||||
|
#ifdef WIN32
|
||||||
error(Sec("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError()));
|
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 "";
|
||||||
}
|
}
|
||||||
return Ret;
|
return Ret;
|
||||||
@ -154,22 +192,26 @@ std::string UDPRcvFromClient(sockaddr_in& client){
|
|||||||
|
|
||||||
SplitData* GetSplit(int SplitID) {
|
SplitData* GetSplit(int SplitID) {
|
||||||
for (SplitData* a : SplitPackets) {
|
for (SplitData* a : SplitPackets) {
|
||||||
if(a->ID == SplitID)return a;
|
if (a->ID == SplitID)
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
auto* SP = new SplitData();
|
auto* SP = new SplitData();
|
||||||
SplitPackets.insert(SP);
|
SplitPackets.insert(SP);
|
||||||
return SP;
|
return SP;
|
||||||
}
|
}
|
||||||
void HandleChunk(Client* c, const std::string& Data) {
|
void HandleChunk(Client* c, const std::string& Data) {
|
||||||
|
Assert(c);
|
||||||
int pos = FC(Data, "|", 5);
|
int pos = FC(Data, "|", 5);
|
||||||
if(pos == -1)return;
|
if (pos == -1)
|
||||||
std::stringstream ss(Data.substr(0,pos++));
|
return;
|
||||||
|
std::stringstream ss(Data.substr(0, size_t(pos++)));
|
||||||
std::string t;
|
std::string t;
|
||||||
int I = -1;
|
int I = -1;
|
||||||
//Current Max ID SID
|
//Current Max ID SID
|
||||||
std::vector<int> Num(4, 0);
|
std::vector<int> Num(4, 0);
|
||||||
while (std::getline(ss, t, '|')) {
|
while (std::getline(ss, t, '|')) {
|
||||||
if(I != -1)Num.at(I) = std::stoi(t);
|
if (I >= 0)
|
||||||
|
Num.at(size_t(I)) = std::stoi(t);
|
||||||
I++;
|
I++;
|
||||||
}
|
}
|
||||||
std::string ack = "TRG:" + std::to_string(Num.at(2));
|
std::string ack = "TRG:" + std::to_string(Num.at(2));
|
||||||
@ -177,12 +219,12 @@ void HandleChunk(Client*c,const std::string&Data){
|
|||||||
if (Handled(c, Num.at(2))) {
|
if (Handled(c, Num.at(2))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string Packet = Data.substr(pos);
|
std::string Packet = Data.substr(size_t(pos));
|
||||||
SplitData* SData = GetSplit(Num.at(3));
|
SplitData* SData = GetSplit(Num.at(3));
|
||||||
SData->Total = Num.at(1);
|
SData->Total = Num.at(1);
|
||||||
SData->ID = Num.at(3);
|
SData->ID = Num.at(3);
|
||||||
SData->Fragments.insert(std::make_pair(Num.at(0), Packet));
|
SData->Fragments.insert(std::make_pair(Num.at(0), Packet));
|
||||||
if(SData->Fragments.size() == SData->Total){
|
if (SData->Fragments.size() == size_t(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) {
|
||||||
ToHandle += a.second;
|
ToHandle += a.second;
|
||||||
@ -194,12 +236,13 @@ void HandleChunk(Client*c,const std::string&Data){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void UDPParser(Client* c, std::string Packet) {
|
void UDPParser(Client* c, std::string Packet) {
|
||||||
|
Assert(c);
|
||||||
if (Packet.substr(0, 4) == "ABG:") {
|
if (Packet.substr(0, 4) == "ABG:") {
|
||||||
Packet = DeComp(Packet.substr(4));
|
Packet = DeComp(Packet.substr(4));
|
||||||
}
|
}
|
||||||
if (Packet.substr(0, 4) == "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") == std::string::npos) {
|
||||||
AckID(stoi(Packet));
|
AckID(stoi(Packet));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -220,6 +263,7 @@ void UDPParser(Client*c,std::string Packet){
|
|||||||
GParser(c, Packet);
|
GParser(c, Packet);
|
||||||
}
|
}
|
||||||
void LOOP() {
|
void LOOP() {
|
||||||
|
DebugPrintTID();
|
||||||
while (UDPSock != -1) {
|
while (UDPSock != -1) {
|
||||||
for (PacketData* p : DataAcks) {
|
for (PacketData* p : DataAcks) {
|
||||||
if (p != nullptr) {
|
if (p != nullptr) {
|
||||||
@ -240,6 +284,7 @@ void LOOP(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
[[noreturn]] void UDPServerMain() {
|
[[noreturn]] void UDPServerMain() {
|
||||||
|
#ifdef WIN32
|
||||||
WSADATA data;
|
WSADATA data;
|
||||||
if (WSAStartup(514, &data)) {
|
if (WSAStartup(514, &data)) {
|
||||||
error(Sec("Can't start Winsock!"));
|
error(Sec("Can't start Winsock!"));
|
||||||
@ -270,7 +315,8 @@ void LOOP(){
|
|||||||
sockaddr_in client {};
|
sockaddr_in client {};
|
||||||
std::string Data = UDPRcvFromClient(client); //Receives any data from Socket
|
std::string Data = UDPRcvFromClient(client); //Receives any data from Socket
|
||||||
auto Pos = Data.find(':');
|
auto Pos = Data.find(':');
|
||||||
if(Data.empty() || Pos < 0 || Pos > 2)continue;
|
if (Data.empty() || Pos < 0 || Pos > 2)
|
||||||
|
continue;
|
||||||
/*char clientIp[256];
|
/*char clientIp[256];
|
||||||
ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet
|
ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet
|
||||||
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/
|
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/
|
||||||
@ -286,4 +332,47 @@ void LOOP(){
|
|||||||
/*closesocket(UDPSock);
|
/*closesocket(UDPSock);
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
return;*/
|
return;*/
|
||||||
|
#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(uint16_t(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
|
||||||
|
size_t Pos = Data.find(':');
|
||||||
|
if (Data.empty() || 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 = uint8_t(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
|
||||||
}
|
}
|
@ -1,25 +1,45 @@
|
|||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/17/2020
|
/// Created by Anonymous275 on 7/17/2020
|
||||||
///
|
///
|
||||||
|
#include "Logger.h"
|
||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Logger.h"
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <fstream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
void DebugPrintTIDInternal(const std::string& func) {
|
||||||
|
// we need to print to cout here as we might crash before all console output is handled,
|
||||||
|
// due to segfaults or asserts.
|
||||||
|
#ifdef DEBUG
|
||||||
|
MLock.lock();
|
||||||
|
printf("%c[2K\r", 27);
|
||||||
|
std::cout << "(debug build) Thread '" << std::this_thread::get_id() << "' is " << func << std::endl;
|
||||||
|
MLock.unlock();
|
||||||
|
#endif // DEBUG
|
||||||
|
}
|
||||||
|
|
||||||
std::string getDate() {
|
std::string getDate() {
|
||||||
typedef std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>::type> days;
|
typedef std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>::type> days;
|
||||||
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
||||||
std::chrono::system_clock::duration tp = now.time_since_epoch();
|
std::chrono::system_clock::duration tp = now.time_since_epoch();
|
||||||
days d = std::chrono::duration_cast<days>(tp);tp -= d;
|
days d = std::chrono::duration_cast<days>(tp);
|
||||||
auto h = std::chrono::duration_cast<std::chrono::hours>(tp);tp -= h;
|
tp -= d;
|
||||||
auto m = std::chrono::duration_cast<std::chrono::minutes>(tp);tp -= m;
|
auto h = std::chrono::duration_cast<std::chrono::hours>(tp);
|
||||||
auto s = std::chrono::duration_cast<std::chrono::seconds>(tp);tp -= s;
|
tp -= h;
|
||||||
|
auto m = std::chrono::duration_cast<std::chrono::minutes>(tp);
|
||||||
|
tp -= m;
|
||||||
|
auto s = std::chrono::duration_cast<std::chrono::seconds>(tp);
|
||||||
|
tp -= s;
|
||||||
time_t tt = std::chrono::system_clock::to_time_t(now);
|
time_t tt = std::chrono::system_clock::to_time_t(now);
|
||||||
tm local_tm {};
|
tm local_tm {};
|
||||||
|
#ifdef WIN32
|
||||||
localtime_s(&local_tm, &tt);
|
localtime_s(&local_tm, &tt);
|
||||||
|
#else // unix
|
||||||
|
localtime_r(&tt, &local_tm);
|
||||||
|
#endif // WIN32
|
||||||
std::stringstream date;
|
std::stringstream date;
|
||||||
int S = local_tm.tm_sec;
|
int S = local_tm.tm_sec;
|
||||||
int M = local_tm.tm_min;
|
int M = local_tm.tm_min;
|
||||||
@ -43,7 +63,8 @@ void InitLog(){
|
|||||||
LFS.open(Sec("Server.log"));
|
LFS.open(Sec("Server.log"));
|
||||||
if (!LFS.is_open()) {
|
if (!LFS.is_open()) {
|
||||||
error(Sec("logger file init failed!"));
|
error(Sec("logger file init failed!"));
|
||||||
}else LFS.close();
|
} else
|
||||||
|
LFS.close();
|
||||||
}
|
}
|
||||||
std::mutex LogLock;
|
std::mutex LogLock;
|
||||||
void addToLog(const std::string& Line) {
|
void addToLog(const std::string& Line) {
|
||||||
@ -60,7 +81,8 @@ void info(const std::string& toPrint) {
|
|||||||
LogLock.unlock();
|
LogLock.unlock();
|
||||||
}
|
}
|
||||||
void debug(const std::string& toPrint) {
|
void debug(const std::string& toPrint) {
|
||||||
if(!Debug)return;
|
if (!Debug)
|
||||||
|
return;
|
||||||
LogLock.lock();
|
LogLock.lock();
|
||||||
std::string Print = getDate() + Sec("[DEBUG] ") + toPrint + "\n";
|
std::string Print = getDate() + Sec("[DEBUG] ") + toPrint + "\n";
|
||||||
ConsoleOut(Print);
|
ConsoleOut(Print);
|
||||||
@ -80,7 +102,8 @@ void error(const std::string& toPrint) {
|
|||||||
std::string Print = getDate() + Sec("[ERROR] ") + toPrint + "\n";
|
std::string Print = getDate() + Sec("[ERROR] ") + toPrint + "\n";
|
||||||
ConsoleOut(Print);
|
ConsoleOut(Print);
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
if(ECounter > 10)exit(7);
|
if (ECounter > 10)
|
||||||
|
exit(7);
|
||||||
ECounter++;
|
ECounter++;
|
||||||
LogLock.unlock();
|
LogLock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
#include "Startup.h"
|
#include "Startup.h"
|
||||||
|
#include "CustomAssert.h"
|
||||||
|
#include "Curl/curl.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
[[noreturn]] void loop(){
|
[[noreturn]] void loop(){
|
||||||
|
DebugPrintTID();
|
||||||
while(true){
|
while(true){
|
||||||
std::cout.flush();
|
std::cout.flush();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(600));
|
std::this_thread::sleep_for(std::chrono::milliseconds(600));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
DebugPrintTID();
|
||||||
|
// curl needs to be initialized to properly deallocate its resources later
|
||||||
|
Assert(curl_global_init(CURL_GLOBAL_DEFAULT) == CURLE_OK);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::thread t1(loop);
|
std::thread t1(loop);
|
||||||
t1.detach();
|
t1.detach();
|
||||||
@ -20,5 +26,7 @@ int main(int argc, char* argv[]) {
|
|||||||
HBInit();
|
HBInit();
|
||||||
StatInit();
|
StatInit();
|
||||||
NetMain();
|
NetMain();
|
||||||
|
// clean up curl at the end to be sure
|
||||||
|
curl_global_cleanup();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user