mirror of
https://github.com/SantaSpeen/BeamMP-Server.git
synced 2025-07-03 10:55:25 +00:00
Merge TUDPServer and TTCPServer into TNetwork
this gets rid of a bunch of unclear cases which I mistakenly created while refactoring for this rewrite. One example is having to call into TTCPServer to do UDP sending in some cases.
This commit is contained in:
parent
05c5fb047c
commit
40cae31885
@ -15,7 +15,7 @@ elseif (UNIX)
|
|||||||
message(STATUS "sanitize is ON")
|
message(STATUS "sanitize is ON")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,thread")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,thread")
|
||||||
endif (SANITIZE)
|
endif (SANITIZE)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
# this has to happen before -DDEBUG since it wont compile properly with -DDEBUG
|
# this has to happen before -DDEBUG since it wont compile properly with -DDEBUG
|
||||||
include_directories("asio/asio/include")
|
include_directories("asio/asio/include")
|
||||||
@ -44,8 +44,7 @@ add_executable(BeamMP-Server
|
|||||||
include/Http.h src/Http.cpp
|
include/Http.h src/Http.cpp
|
||||||
include/SocketIO.h src/SocketIO.cpp
|
include/SocketIO.h src/SocketIO.cpp
|
||||||
include/TPPSMonitor.h src/TPPSMonitor.cpp
|
include/TPPSMonitor.h src/TPPSMonitor.cpp
|
||||||
include/TUDPServer.h src/TUDPServer.cpp
|
include/TNetwork.h src/TNetwork.cpp)
|
||||||
include/TTCPServer.h src/TTCPServer.cpp)
|
|
||||||
|
|
||||||
target_include_directories(BeamMP-Server PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/commandline")
|
target_include_directories(BeamMP-Server PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/commandline")
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
class TConfig {
|
class TConfig {
|
||||||
public:
|
public:
|
||||||
TConfig(const std::string& ConfigFile);
|
explicit TConfig(const std::string& ConfigFile);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string RemoveComments(const std::string& Line);
|
static std::string RemoveComments(const std::string& Line);
|
||||||
|
@ -4,15 +4,14 @@
|
|||||||
#include "IThreaded.h"
|
#include "IThreaded.h"
|
||||||
#include "TLuaFile.h"
|
#include "TLuaFile.h"
|
||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
#include <optional>
|
|
||||||
#include <lua.hpp>
|
#include <lua.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
class TLuaEngine : public IThreaded {
|
class TLuaEngine : public IThreaded {
|
||||||
public:
|
public:
|
||||||
explicit TLuaEngine(TServer& Server, TTCPServer& TCPServer, TUDPServer& UDPServer);
|
explicit TLuaEngine(TServer& Server, TNetwork& Network);
|
||||||
//~TLuaEngine();
|
|
||||||
|
|
||||||
using TSetOfLuaFile = std::set<std::unique_ptr<TLuaFile>>;
|
using TSetOfLuaFile = std::set<std::unique_ptr<TLuaFile>>;
|
||||||
|
|
||||||
@ -21,19 +20,17 @@ public:
|
|||||||
[[nodiscard]] const TSetOfLuaFile& LuaFiles() const { return mLuaFiles; }
|
[[nodiscard]] const TSetOfLuaFile& LuaFiles() const { return mLuaFiles; }
|
||||||
[[nodiscard]] TServer& Server() { return mServer; }
|
[[nodiscard]] TServer& Server() { return mServer; }
|
||||||
[[nodiscard]] const TServer& Server() const { return mServer; }
|
[[nodiscard]] const TServer& Server() const { return mServer; }
|
||||||
|
[[nodiscard]] TNetwork& Network() { return mNetwork; }
|
||||||
|
[[nodiscard]] const TNetwork& Network() const { return mNetwork; }
|
||||||
|
|
||||||
std::optional<std::reference_wrapper<TLuaFile>> GetScript(lua_State* L);
|
std::optional<std::reference_wrapper<TLuaFile>> GetScript(lua_State* L);
|
||||||
|
|
||||||
TTCPServer& TCPServer() { return mTCPServer; }
|
|
||||||
TUDPServer& UDPServer() { return mUDPServer; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void FolderList(const std::string& Path, bool HotSwap);
|
void FolderList(const std::string& Path, bool HotSwap);
|
||||||
void RegisterFiles(const std::string& Path, bool HotSwap);
|
void RegisterFiles(const std::string& Path, bool HotSwap);
|
||||||
bool NewFile(const std::string& Path);
|
bool NewFile(const std::string& Path);
|
||||||
|
|
||||||
TTCPServer& mTCPServer;
|
TNetwork& mNetwork;
|
||||||
TUDPServer& mUDPServer;
|
|
||||||
TServer& mServer;
|
TServer& mServer;
|
||||||
std::string mPath;
|
std::string mPath;
|
||||||
bool mShutdown { false };
|
bool mShutdown { false };
|
||||||
|
@ -1,20 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Client.h"
|
|
||||||
#include "Common.h"
|
|
||||||
#include "Compat.h"
|
#include "Compat.h"
|
||||||
#include "IThreaded.h"
|
#include "TResourceManager.h"
|
||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
class TResourceManager;
|
class TNetwork {
|
||||||
|
|
||||||
class TTCPServer : public IThreaded {
|
|
||||||
public:
|
public:
|
||||||
explicit TTCPServer(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager);
|
TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager);
|
||||||
//~TTCPServer();
|
|
||||||
|
|
||||||
void operator()() override;
|
|
||||||
|
|
||||||
bool TCPSend(TClient& c, const std::string& Data, bool IsSync = false);
|
bool TCPSend(TClient& c, const std::string& Data, bool IsSync = false);
|
||||||
void SendLarge(TClient& c, std::string Data, bool isSync = false);
|
void SendLarge(TClient& c, std::string Data, bool isSync = false);
|
||||||
@ -22,26 +14,28 @@ public:
|
|||||||
std::shared_ptr<TClient> CreateClient(SOCKET TCPSock);
|
std::shared_ptr<TClient> CreateClient(SOCKET TCPSock);
|
||||||
std::string TCPRcv(TClient& c);
|
std::string TCPRcv(TClient& c);
|
||||||
void ClientKick(TClient& c, const std::string& R);
|
void ClientKick(TClient& c, const std::string& R);
|
||||||
|
|
||||||
void SetUDPServer(TUDPServer& UDPServer);
|
|
||||||
|
|
||||||
TUDPServer& UDPServer() { return mUDPServer->get(); }
|
|
||||||
|
|
||||||
void SyncClient(const std::weak_ptr<TClient>& c);
|
void SyncClient(const std::weak_ptr<TClient>& c);
|
||||||
void Identify(SOCKET TCPSock);
|
void Identify(SOCKET TCPSock);
|
||||||
void Authentication(SOCKET TCPSock);
|
void Authentication(SOCKET TCPSock);
|
||||||
bool CheckBytes(TClient& c, int32_t BytesRcv);
|
bool CheckBytes(TClient& c, int32_t BytesRcv);
|
||||||
void SyncResources(TClient& c);
|
void SyncResources(TClient& c);
|
||||||
|
void UDPSend(TClient& Client, std::string Data) const;
|
||||||
|
void SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel);
|
||||||
void UpdatePlayer(TClient& Client);
|
void UpdatePlayer(TClient& Client);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<std::reference_wrapper<TUDPServer>> mUDPServer { std::nullopt };
|
void UDPServerMain();
|
||||||
|
void TCPServerMain();
|
||||||
|
|
||||||
TServer& mServer;
|
TServer& mServer;
|
||||||
TPPSMonitor& mPPSMonitor;
|
TPPSMonitor& mPPSMonitor;
|
||||||
TResourceManager& mResourceManager;
|
SOCKET mUDPSock {};
|
||||||
bool mShutdown { false };
|
bool mShutdown { false };
|
||||||
|
TResourceManager& mResourceManager;
|
||||||
|
std::thread mUDPThread;
|
||||||
|
std::thread mTCPThread;
|
||||||
|
|
||||||
|
std::string UDPRcvFromClient(sockaddr_in& client) const;
|
||||||
void HandleDownload(SOCKET TCPSock);
|
void HandleDownload(SOCKET TCPSock);
|
||||||
void OnConnect(const std::weak_ptr<TClient>& c);
|
void OnConnect(const std::weak_ptr<TClient>& c);
|
||||||
void TCPClient(const std::weak_ptr<TClient>& c);
|
void TCPClient(const std::weak_ptr<TClient>& c);
|
||||||
@ -51,4 +45,4 @@ private:
|
|||||||
void SendFile(TClient& c, const std::string& Name);
|
void SendFile(TClient& c, const std::string& Name);
|
||||||
static bool TCPSendRaw(SOCKET C, char* Data, int32_t Size);
|
static bool TCPSendRaw(SOCKET C, char* Data, int32_t Size);
|
||||||
static void SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name);
|
static void SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name);
|
||||||
};
|
};
|
@ -3,6 +3,9 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
class TNetwork;
|
||||||
|
|
||||||
class TPPSMonitor : public IThreaded {
|
class TPPSMonitor : public IThreaded {
|
||||||
public:
|
public:
|
||||||
explicit TPPSMonitor(TServer& Server);
|
explicit TPPSMonitor(TServer& Server);
|
||||||
@ -12,13 +15,13 @@ public:
|
|||||||
void SetInternalPPS(int NewPPS) { mInternalPPS = NewPPS; }
|
void SetInternalPPS(int NewPPS) { mInternalPPS = NewPPS; }
|
||||||
void IncrementInternalPPS() { ++mInternalPPS; }
|
void IncrementInternalPPS() { ++mInternalPPS; }
|
||||||
[[nodiscard]] int InternalPPS() const { return mInternalPPS; }
|
[[nodiscard]] int InternalPPS() const { return mInternalPPS; }
|
||||||
void SetTCPServer(TTCPServer& Server) { mTCPServer = std::ref(Server); }
|
void SetNetwork(TNetwork& Server) { mNetwork = std::ref(Server); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TTCPServer& TCPServer() { return mTCPServer->get(); }
|
TNetwork& Network() { return mNetwork->get(); }
|
||||||
|
|
||||||
TServer& mServer;
|
TServer& mServer;
|
||||||
std::optional<std::reference_wrapper<TTCPServer>> mTCPServer { std::nullopt };
|
std::optional<std::reference_wrapper<TNetwork>> mNetwork { std::nullopt };
|
||||||
bool mShutdown { false };
|
bool mShutdown { false };
|
||||||
int mInternalPPS { 0 };
|
int mInternalPPS { 0 };
|
||||||
};
|
};
|
@ -8,8 +8,7 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
class TClient;
|
class TClient;
|
||||||
class TUDPServer;
|
class TNetwork;
|
||||||
class TTCPServer;
|
|
||||||
class TPPSMonitor;
|
class TPPSMonitor;
|
||||||
|
|
||||||
class TServer final {
|
class TServer final {
|
||||||
@ -25,12 +24,12 @@ public:
|
|||||||
void ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn);
|
void ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn);
|
||||||
size_t ClientCount() const;
|
size_t ClientCount() const;
|
||||||
|
|
||||||
static void GlobalParser(const std::weak_ptr<TClient>& Client, std::string Packet, TPPSMonitor& PPSMonitor, TUDPServer& UDPServer, TTCPServer& TCPServer);
|
static void GlobalParser(const std::weak_ptr<TClient>& Client, std::string Packet, TPPSMonitor& PPSMonitor, TNetwork& Network);
|
||||||
static void HandleEvent(TClient& c, const std::string& Data);
|
static void HandleEvent(TClient& c, const std::string& Data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TClientSet mClients;
|
TClientSet mClients;
|
||||||
mutable RWMutex mClientsMutex;
|
mutable RWMutex mClientsMutex;
|
||||||
static void ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPServer, TUDPServer& UDPServer);
|
static void ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network);
|
||||||
static void Apply(TClient& c, int VID, const std::string& pckt);
|
static void Apply(TClient& c, int VID, const std::string& pckt);
|
||||||
};
|
};
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Client.h"
|
|
||||||
#include "Common.h"
|
|
||||||
#include "Compat.h"
|
|
||||||
#include "IThreaded.h"
|
|
||||||
#include "TPPSMonitor.h"
|
|
||||||
#include "TServer.h"
|
|
||||||
|
|
||||||
class TUDPServer : public IThreaded {
|
|
||||||
public:
|
|
||||||
explicit TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor, TTCPServer& TCPServer);
|
|
||||||
//~TUDPServer();
|
|
||||||
|
|
||||||
void operator()() override;
|
|
||||||
|
|
||||||
void UDPSend(TClient& Client, std::string Data) const;
|
|
||||||
void SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel);
|
|
||||||
|
|
||||||
private:
|
|
||||||
TServer& mServer;
|
|
||||||
TPPSMonitor& mPPSMonitor;
|
|
||||||
TTCPServer& mTCPServer;
|
|
||||||
SOCKET mUDPSock {};
|
|
||||||
bool mShutdown { false };
|
|
||||||
|
|
||||||
std::string UDPRcvFromClient(sockaddr_in& client) const;
|
|
||||||
};
|
|
@ -21,6 +21,7 @@ void Application::GracefullyShutdown() {
|
|||||||
Handler();
|
Handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Comp(std::string Data) {
|
std::string Comp(std::string Data) {
|
||||||
std::array<char, Biggest> C {};
|
std::array<char, Biggest> C {};
|
||||||
// obsolete
|
// obsolete
|
||||||
|
@ -9,9 +9,8 @@ namespace fs = std::filesystem;
|
|||||||
// necessary as lua relies on global state
|
// necessary as lua relies on global state
|
||||||
TLuaEngine* TheEngine;
|
TLuaEngine* TheEngine;
|
||||||
|
|
||||||
TLuaEngine::TLuaEngine(TServer& Server, TTCPServer& TCPServer, TUDPServer& UDPServer)
|
TLuaEngine::TLuaEngine(TServer& Server, TNetwork& Network)
|
||||||
: mTCPServer(TCPServer)
|
: mNetwork(Network)
|
||||||
, mUDPServer(UDPServer)
|
|
||||||
, mServer(Server) {
|
, mServer(Server) {
|
||||||
TheEngine = this;
|
TheEngine = this;
|
||||||
if (!fs::exists(Application::Settings.Resource)) {
|
if (!fs::exists(Application::Settings.Resource)) {
|
||||||
@ -101,6 +100,3 @@ bool TLuaEngine::NewFile(const std::string& Path) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*TLuaEngine::~TLuaEngine() {
|
|
||||||
}*/
|
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "CustomAssert.h"
|
#include "CustomAssert.h"
|
||||||
#include "TLuaEngine.h"
|
#include "TLuaEngine.h"
|
||||||
|
#include "TNetwork.h"
|
||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
#include "TTCPServer.h"
|
|
||||||
#include "TUDPServer.h"
|
|
||||||
|
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -172,7 +171,7 @@ char* ThreadOrigin(TLuaFile* lua) {
|
|||||||
memcpy(Data, T.c_str(), T.size());
|
memcpy(Data, T.c_str(), T.size());
|
||||||
return Data;
|
return Data;
|
||||||
}
|
}
|
||||||
void SafeExecution(TLuaEngine& Engine, TLuaFile* lua, const std::string& FuncName) {
|
void SafeExecution(TLuaFile* lua, const std::string& FuncName) {
|
||||||
lua_State* luaState = lua->GetState();
|
lua_State* luaState = lua->GetState();
|
||||||
lua_getglobal(luaState, FuncName.c_str());
|
lua_getglobal(luaState, FuncName.c_str());
|
||||||
if (lua_isfunction(luaState, -1)) {
|
if (lua_isfunction(luaState, -1)) {
|
||||||
@ -192,19 +191,21 @@ void SafeExecution(TLuaEngine& Engine, TLuaFile* lua, const std::string& FuncNam
|
|||||||
ClearStack(luaState);
|
ClearStack(luaState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteAsync(TLuaEngine& Engine, TLuaFile* lua, const std::string& FuncName) {
|
void ExecuteAsync(TLuaFile* lua, const std::string& FuncName) {
|
||||||
std::lock_guard<std::mutex> lockGuard(lua->Lock);
|
std::lock_guard<std::mutex> lockGuard(lua->Lock);
|
||||||
SafeExecution(Engine, lua, FuncName);
|
SafeExecution(lua, FuncName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallAsync(TLuaFile* lua, const std::string& Func, int U) {
|
void CallAsync(TLuaFile* lua, const std::string& Func, int U) {
|
||||||
//DebugPrintTID();
|
//DebugPrintTID();
|
||||||
lua->SetStopThread(false);
|
lua->SetStopThread(false);
|
||||||
int D = 1000 / U;
|
int D = 1000 / U;
|
||||||
while (!lua->GetStopThread()) {
|
while (!lua->GetStopThread()) {
|
||||||
ExecuteAsync(Engine(), 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) {
|
||||||
auto MaybeScript = Engine().GetScript(L);
|
auto MaybeScript = Engine().GetScript(L);
|
||||||
Assert(MaybeScript.has_value());
|
Assert(MaybeScript.has_value());
|
||||||
@ -321,22 +322,22 @@ int lua_GetAllPlayers(lua_State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int lua_GetIdentifiers(lua_State* L){
|
int lua_GetIdentifiers(lua_State* L) {
|
||||||
if(lua_isnumber(L,1)){
|
if (lua_isnumber(L, 1)) {
|
||||||
auto MaybeClient = GetClient(Engine().Server(), int(lua_tonumber(L, 1)));
|
auto MaybeClient = GetClient(Engine().Server(), int(lua_tonumber(L, 1)));
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient && !MaybeClient.value().expired()) {
|
||||||
auto IDs = MaybeClient.value().lock()->GetIdentifiers();
|
auto IDs = MaybeClient.value().lock()->GetIdentifiers();
|
||||||
if(IDs.empty())
|
if (IDs.empty())
|
||||||
return 0;
|
return 0;
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
for(const std::string& ID : IDs){
|
for (const std::string& ID : IDs) {
|
||||||
lua_pushstring(L, ID.substr(0,ID.find(':')).c_str());
|
lua_pushstring(L, ID.substr(0, ID.find(':')).c_str());
|
||||||
lua_pushstring(L, ID.c_str());
|
lua_pushstring(L, ID.c_str());
|
||||||
lua_settable(L, -3);
|
lua_settable(L, -3);
|
||||||
}
|
}
|
||||||
}else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
}else{
|
} else {
|
||||||
SendError(Engine(), L, "lua_GetIdentifiers wrong arguments");
|
SendError(Engine(), L, "lua_GetIdentifiers wrong arguments");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -382,7 +383,7 @@ int lua_dropPlayer(lua_State* L) {
|
|||||||
Reason = std::string((" Reason : ")) + lua_tostring(L, 2);
|
Reason = std::string((" Reason : ")) + lua_tostring(L, 2);
|
||||||
}
|
}
|
||||||
auto c = MaybeClient.value().lock();
|
auto c = MaybeClient.value().lock();
|
||||||
Engine().TCPServer().Respond(*c, "C:Server:You have been Kicked from the server! " + Reason, true);
|
Engine().Network().Respond(*c, "C:Server:You have been Kicked from the server! " + Reason, true);
|
||||||
c->SetStatus(-2);
|
c->SetStatus(-2);
|
||||||
info(("Closing socket due to kick"));
|
info(("Closing socket due to kick"));
|
||||||
CloseSocketProper(c->GetTCPSock());
|
CloseSocketProper(c->GetTCPSock());
|
||||||
@ -396,7 +397,7 @@ int lua_sendChat(lua_State* L) {
|
|||||||
int ID = int(lua_tointeger(L, 1));
|
int ID = int(lua_tointeger(L, 1));
|
||||||
if (ID == -1) {
|
if (ID == -1) {
|
||||||
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
|
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
|
||||||
Engine().UDPServer().SendToAll(nullptr, Packet, true, true);
|
Engine().Network().SendToAll(nullptr, Packet, true, true);
|
||||||
} else {
|
} else {
|
||||||
auto MaybeClient = GetClient(Engine().Server(), ID);
|
auto MaybeClient = GetClient(Engine().Server(), ID);
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
if (MaybeClient && !MaybeClient.value().expired()) {
|
||||||
@ -404,7 +405,7 @@ int lua_sendChat(lua_State* L) {
|
|||||||
if (!c->IsSynced())
|
if (!c->IsSynced())
|
||||||
return 0;
|
return 0;
|
||||||
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
|
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
|
||||||
Engine().TCPServer().Respond(*c, Packet, true);
|
Engine().Network().Respond(*c, Packet, true);
|
||||||
} else
|
} else
|
||||||
SendError(Engine(), L, ("SendChatMessage invalid argument [1] invalid ID"));
|
SendError(Engine(), L, ("SendChatMessage invalid argument [1] invalid ID"));
|
||||||
}
|
}
|
||||||
@ -431,7 +432,7 @@ int lua_RemoveVehicle(lua_State* L) {
|
|||||||
auto c = MaybeClient.value().lock();
|
auto c = MaybeClient.value().lock();
|
||||||
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);
|
||||||
Engine().UDPServer().SendToAll(nullptr, Destroy, true, true);
|
Engine().Network().SendToAll(nullptr, Destroy, true, true);
|
||||||
c->DeleteCar(VID);
|
c->DeleteCar(VID);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -463,7 +464,7 @@ 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)
|
if (ID == -1)
|
||||||
Engine().UDPServer().SendToAll(nullptr, Packet, true, true);
|
Engine().Network().SendToAll(nullptr, Packet, true, true);
|
||||||
else {
|
else {
|
||||||
auto MaybeClient = GetClient(Engine().Server(), ID);
|
auto MaybeClient = GetClient(Engine().Server(), ID);
|
||||||
if (!MaybeClient || MaybeClient.value().expired()) {
|
if (!MaybeClient || MaybeClient.value().expired()) {
|
||||||
@ -471,7 +472,7 @@ int lua_RemoteEvent(lua_State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
auto c = MaybeClient.value().lock();
|
auto c = MaybeClient.value().lock();
|
||||||
Engine().TCPServer().Respond(*c, Packet, true);
|
Engine().Network().Respond(*c, Packet, true);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,195 @@
|
|||||||
#include "TTCPServer.h"
|
#include "TNetwork.h"
|
||||||
#include "TLuaEngine.h"
|
|
||||||
#include "TLuaFile.h"
|
#include "Client.h"
|
||||||
#include "TResourceManager.h"
|
|
||||||
#include "TUDPServer.h"
|
|
||||||
#include <CustomAssert.h>
|
#include <CustomAssert.h>
|
||||||
#include <Http.h>
|
#include <Http.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager)
|
||||||
|
: mServer(Server)
|
||||||
|
, mPPSMonitor(PPSMonitor)
|
||||||
|
, mResourceManager(ResourceManager) {
|
||||||
|
Application::RegisterShutdownHandler([&] {
|
||||||
|
if (mUDPThread.joinable()) {
|
||||||
|
debug("shutting down TCPServer");
|
||||||
|
mShutdown = true;
|
||||||
|
mUDPThread.detach();
|
||||||
|
debug("shut down TCPServer");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Application::RegisterShutdownHandler([&] {
|
||||||
|
if (mUDPThread.joinable()) {
|
||||||
|
debug("shutting down TCPServer");
|
||||||
|
mShutdown = true;
|
||||||
|
mTCPThread.detach();
|
||||||
|
debug("shut down TCPServer");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mTCPThread = std::thread(&TNetwork::TCPServerMain, this);
|
||||||
|
mUDPThread = std::thread(&TNetwork::UDPServerMain, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TNetwork::UDPServerMain() {
|
||||||
|
#ifdef WIN32
|
||||||
|
WSADATA data;
|
||||||
|
if (WSAStartup(514, &data)) {
|
||||||
|
error(("Can't start Winsock!"));
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mUDPSock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
// Create a server hint structure for the server
|
||||||
|
sockaddr_in serverAddr {};
|
||||||
|
serverAddr.sin_addr.S_un.S_addr = ADDR_ANY; //Any Local
|
||||||
|
serverAddr.sin_family = AF_INET; // Address format is IPv4
|
||||||
|
serverAddr.sin_port = htons(Application::Settings.Port); // Convert from little to big endian
|
||||||
|
|
||||||
|
// Try and bind the socket to the IP and port
|
||||||
|
if (bind(mUDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
|
||||||
|
error(("Can't bind socket!") + std::to_string(WSAGetLastError()));
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
|
exit(-1);
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
#else // unix
|
||||||
|
mUDPSock = 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(Application::Settings.Port)); // Convert from little to big endian
|
||||||
|
|
||||||
|
// Try and bind the socket to the IP and port
|
||||||
|
if (bind(mUDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) {
|
||||||
|
error(("Can't bind socket!") + std::string(strerror(errno)));
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
|
exit(-1);
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
info(("Vehicle data network online on port ") + std::to_string(Application::Settings.Port) + (" with a Max of ")
|
||||||
|
+ std::to_string(Application::Settings.MaxPlayers) + (" Clients"));
|
||||||
|
while (!mShutdown) {
|
||||||
|
try {
|
||||||
|
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;
|
||||||
|
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
|
||||||
|
if (!ClientPtr.expired()) {
|
||||||
|
auto Client = ClientPtr.lock();
|
||||||
|
if (Client->GetID() == ID) {
|
||||||
|
Client->SetUDPAddr(client);
|
||||||
|
Client->SetIsConnected(true);
|
||||||
|
TServer::GlobalParser(ClientPtr, Data.substr(2), mPPSMonitor, *this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
error(("fatal: ") + std::string(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TNetwork::TCPServerMain() {
|
||||||
|
#ifdef WIN32
|
||||||
|
WSADATA wsaData;
|
||||||
|
if (WSAStartup(514, &wsaData)) {
|
||||||
|
error("Can't start Winsock!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SOCKET client, Listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
sockaddr_in addr {};
|
||||||
|
addr.sin_addr.S_un.S_addr = ADDR_ANY;
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(Application::Settings.Port);
|
||||||
|
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
|
error("Can't bind socket! " + std::to_string(WSAGetLastError()));
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
if (Listener == -1) {
|
||||||
|
error("Invalid listening socket");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (listen(Listener, SOMAXCONN)) {
|
||||||
|
error("listener failed " + std::to_string(GetLastError()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info("Vehicle event network online");
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
client = accept(Listener, nullptr, nullptr);
|
||||||
|
if (client == -1) {
|
||||||
|
warn("Got an invalid client socket on connect! Skipping...");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::thread ID(&TTCPServer::Identify, this, client);
|
||||||
|
ID.detach();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
error("fatal: " + std::string(e.what()));
|
||||||
|
}
|
||||||
|
} while (client);
|
||||||
|
|
||||||
|
CloseSocketProper(client);
|
||||||
|
WSACleanup();
|
||||||
|
#else // unix
|
||||||
|
// wondering why we need slightly different implementations of this?
|
||||||
|
// ask ms.
|
||||||
|
SOCKET client = -1;
|
||||||
|
SOCKET Listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
int optval = 1;
|
||||||
|
setsockopt(Listener, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
|
||||||
|
// TODO: check optval or return value idk
|
||||||
|
sockaddr_in addr {};
|
||||||
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(uint16_t(Application::Settings.Port));
|
||||||
|
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) != 0) {
|
||||||
|
error(("Can't bind socket! ") + std::string(strerror(errno)));
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
if (Listener == -1) {
|
||||||
|
error(("Invalid listening socket"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (listen(Listener, SOMAXCONN)) {
|
||||||
|
error(("listener failed ") + std::string(strerror(errno)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info(("Vehicle event network online"));
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
if (mShutdown) {
|
||||||
|
debug("shutdown during TCP wait for accept loop");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
client = accept(Listener, nullptr, nullptr);
|
||||||
|
if (client == -1) {
|
||||||
|
warn(("Got an invalid client socket on connect! Skipping..."));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::thread ID(&TNetwork::Identify, this, client);
|
||||||
|
ID.detach(); // TODO: Add to a queue and attempt to join periodically
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
error(("fatal: ") + std::string(e.what()));
|
||||||
|
}
|
||||||
|
} while (client);
|
||||||
|
|
||||||
|
debug("all ok, arrived at " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
||||||
|
|
||||||
|
CloseSocketProper(client);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#undef GetObject //Fixes Windows
|
#undef GetObject //Fixes Windows
|
||||||
|
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
@ -14,24 +197,7 @@
|
|||||||
#include "rapidjson/writer.h"
|
#include "rapidjson/writer.h"
|
||||||
namespace json = rapidjson;
|
namespace json = rapidjson;
|
||||||
|
|
||||||
bool TCPSend(std::weak_ptr<TClient> c, const std::string& Data);
|
void TNetwork::Identify(SOCKET TCPSock) {
|
||||||
bool TCPSend(TClient& c, const std::string& Data);
|
|
||||||
|
|
||||||
TTCPServer::TTCPServer(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager)
|
|
||||||
: mServer(Server)
|
|
||||||
, mPPSMonitor(PPSMonitor)
|
|
||||||
, mResourceManager(ResourceManager) {
|
|
||||||
Application::RegisterShutdownHandler([&] {if (mThread.joinable()) {
|
|
||||||
debug("shutting down TCPServer");
|
|
||||||
mShutdown = true;
|
|
||||||
// FIXME: Join once TCPServer can timeout on a read, accept, etc.
|
|
||||||
mThread.detach();
|
|
||||||
debug("shut down TCPServer");
|
|
||||||
} });
|
|
||||||
Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TTCPServer::Identify(SOCKET TCPSock) {
|
|
||||||
char Code;
|
char Code;
|
||||||
if (recv(TCPSock, &Code, 1, 0) != 1) {
|
if (recv(TCPSock, &Code, 1, 0) != 1) {
|
||||||
CloseSocketProper(TCPSock);
|
CloseSocketProper(TCPSock);
|
||||||
@ -46,7 +212,7 @@ void TTCPServer::Identify(SOCKET TCPSock) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::HandleDownload(SOCKET TCPSock) {
|
void TNetwork::HandleDownload(SOCKET TCPSock) {
|
||||||
char D;
|
char D;
|
||||||
if (recv(TCPSock, &D, 1, 0) != 1) {
|
if (recv(TCPSock, &D, 1, 0) != 1) {
|
||||||
CloseSocketProper(TCPSock);
|
CloseSocketProper(TCPSock);
|
||||||
@ -64,7 +230,7 @@ void TTCPServer::HandleDownload(SOCKET TCPSock) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::Authentication(SOCKET TCPSock) {
|
void TNetwork::Authentication(SOCKET TCPSock) {
|
||||||
auto Client = CreateClient(TCPSock);
|
auto Client = CreateClient(TCPSock);
|
||||||
|
|
||||||
std::string Rc;
|
std::string Rc;
|
||||||
@ -160,13 +326,13 @@ void TTCPServer::Authentication(SOCKET TCPSock) {
|
|||||||
ClientKick(*Client, "Server full!");
|
ClientKick(*Client, "Server full!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TClient> TTCPServer::CreateClient(SOCKET TCPSock) {
|
std::shared_ptr<TClient> TNetwork::CreateClient(SOCKET TCPSock) {
|
||||||
auto c = std::make_shared<TClient>(mServer);
|
auto c = std::make_shared<TClient>(mServer);
|
||||||
c->SetTCPSock(TCPSock);
|
c->SetTCPSock(TCPSock);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTCPServer::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
|
bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
|
||||||
if (!IsSync) {
|
if (!IsSync) {
|
||||||
if (c.IsSyncing()) {
|
if (c.IsSyncing()) {
|
||||||
c.EnqueueMissedPacketDuringSyncing(Data);
|
c.EnqueueMissedPacketDuringSyncing(Data);
|
||||||
@ -204,7 +370,7 @@ bool TTCPServer::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTCPServer::CheckBytes(TClient& c, int32_t BytesRcv) {
|
bool TNetwork::CheckBytes(TClient& c, int32_t BytesRcv) {
|
||||||
if (BytesRcv == 0) {
|
if (BytesRcv == 0) {
|
||||||
debug("(TCP) Connection closing...");
|
debug("(TCP) Connection closing...");
|
||||||
if (c.GetStatus() > -1)
|
if (c.GetStatus() > -1)
|
||||||
@ -225,7 +391,7 @@ bool TTCPServer::CheckBytes(TClient& c, int32_t BytesRcv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TTCPServer::TCPRcv(TClient& c) {
|
std::string TNetwork::TCPRcv(TClient& c) {
|
||||||
int32_t Header, BytesRcv = 0, Temp;
|
int32_t Header, BytesRcv = 0, Temp;
|
||||||
if (c.GetStatus() < 0)
|
if (c.GetStatus() < 0)
|
||||||
return "";
|
return "";
|
||||||
@ -289,14 +455,14 @@ std::string TTCPServer::TCPRcv(TClient& c) {
|
|||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::ClientKick(TClient& c, const std::string& R) {
|
void TNetwork::ClientKick(TClient& c, const std::string& R) {
|
||||||
info("Client kicked: " + R);
|
info("Client kicked: " + R);
|
||||||
TCPSend(c, "E" + R);
|
TCPSend(c, "E" + R);
|
||||||
c.SetStatus(-2);
|
c.SetStatus(-2);
|
||||||
CloseSocketProper(c.GetTCPSock());
|
CloseSocketProper(c.GetTCPSock());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::TCPClient(const std::weak_ptr<TClient>& c) {
|
void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
||||||
// TODO: the c.expired() might cause issues here, remove if you end up here with your debugger
|
// TODO: the c.expired() might cause issues here, remove if you end up here with your debugger
|
||||||
if (c.expired() || c.lock()->GetTCPSock() == -1) {
|
if (c.expired() || c.lock()->GetTCPSock() == -1) {
|
||||||
mServer.RemoveClient(c);
|
mServer.RemoveClient(c);
|
||||||
@ -310,7 +476,7 @@ void TTCPServer::TCPClient(const std::weak_ptr<TClient>& c) {
|
|||||||
if (Client->GetStatus() <= -1) {
|
if (Client->GetStatus() <= -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TServer::GlobalParser(c, TCPRcv(*Client), mPPSMonitor, UDPServer(), *this);
|
TServer::GlobalParser(c, TCPRcv(*Client), mPPSMonitor, *this);
|
||||||
}
|
}
|
||||||
if (!c.expired()) {
|
if (!c.expired()) {
|
||||||
auto Client = c.lock();
|
auto Client = c.lock();
|
||||||
@ -320,7 +486,7 @@ void TTCPServer::TCPClient(const std::weak_ptr<TClient>& c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::UpdatePlayer(TClient& Client) {
|
void TNetwork::UpdatePlayer(TClient& Client) {
|
||||||
std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::Settings.MaxPlayers) + ":";
|
std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::Settings.MaxPlayers) + ":";
|
||||||
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
mServer.ForEachClient([&](const std::weak_ptr<TClient>& ClientPtr) -> bool {
|
||||||
if (!ClientPtr.expired()) {
|
if (!ClientPtr.expired()) {
|
||||||
@ -333,7 +499,7 @@ void TTCPServer::UpdatePlayer(TClient& Client) {
|
|||||||
Respond(Client, Packet, true);
|
Respond(Client, Packet, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked) {
|
void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked) {
|
||||||
Assert(!ClientPtr.expired());
|
Assert(!ClientPtr.expired());
|
||||||
auto LockedClientPtr = ClientPtr.lock();
|
auto LockedClientPtr = ClientPtr.lock();
|
||||||
TClient& c = *LockedClientPtr;
|
TClient& c = *LockedClientPtr;
|
||||||
@ -346,13 +512,13 @@ void TTCPServer::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kick
|
|||||||
} // End Vehicle Data Lock Scope
|
} // End Vehicle Data Lock Scope
|
||||||
for (auto& v : VehicleData) {
|
for (auto& v : VehicleData) {
|
||||||
Packet = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(v.ID());
|
Packet = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(v.ID());
|
||||||
UDPServer().SendToAll(&c, Packet, false, true);
|
SendToAll(&c, Packet, false, true);
|
||||||
}
|
}
|
||||||
if (kicked)
|
if (kicked)
|
||||||
Packet = ("L") + c.GetName() + (" was kicked!");
|
Packet = ("L") + c.GetName() + (" was kicked!");
|
||||||
else
|
else
|
||||||
Packet = ("L") + c.GetName() + (" left the server!");
|
Packet = ("L") + c.GetName() + (" left the server!");
|
||||||
UDPServer().SendToAll(&c, Packet, false, true);
|
SendToAll(&c, Packet, false, true);
|
||||||
Packet.clear();
|
Packet.clear();
|
||||||
TriggerLuaEvent(("onPlayerDisconnect"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID() } }), false);
|
TriggerLuaEvent(("onPlayerDisconnect"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID() } }), false);
|
||||||
if (c.GetTCPSock())
|
if (c.GetTCPSock())
|
||||||
@ -362,7 +528,7 @@ void TTCPServer::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kick
|
|||||||
mServer.RemoveClient(ClientPtr);
|
mServer.RemoveClient(ClientPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TTCPServer::OpenID() {
|
int TNetwork::OpenID() {
|
||||||
int ID = 0;
|
int ID = 0;
|
||||||
bool found;
|
bool found;
|
||||||
do {
|
do {
|
||||||
@ -381,7 +547,7 @@ int TTCPServer::OpenID() {
|
|||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::OnConnect(const std::weak_ptr<TClient>& c) {
|
void TNetwork::OnConnect(const std::weak_ptr<TClient>& c) {
|
||||||
Assert(!c.expired());
|
Assert(!c.expired());
|
||||||
info("Client connected");
|
info("Client connected");
|
||||||
auto LockedClient = c.lock();
|
auto LockedClient = c.lock();
|
||||||
@ -396,7 +562,7 @@ void TTCPServer::OnConnect(const std::weak_ptr<TClient>& c) {
|
|||||||
TriggerLuaEvent("onPlayerJoining", false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID() } }), false);
|
TriggerLuaEvent("onPlayerJoining", false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID() } }), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::SyncResources(TClient& c) {
|
void TNetwork::SyncResources(TClient& c) {
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
try {
|
try {
|
||||||
#endif
|
#endif
|
||||||
@ -416,7 +582,7 @@ void TTCPServer::SyncResources(TClient& c) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::Parse(TClient& c, const std::string& Packet) {
|
void TNetwork::Parse(TClient& c, const std::string& Packet) {
|
||||||
if (Packet.empty())
|
if (Packet.empty())
|
||||||
return;
|
return;
|
||||||
char Code = Packet.at(0), SubCode = 0;
|
char Code = Packet.at(0), SubCode = 0;
|
||||||
@ -440,7 +606,7 @@ void TTCPServer::Parse(TClient& c, const std::string& Packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::SendFile(TClient& c, const std::string& Name) {
|
void TNetwork::SendFile(TClient& c, const std::string& Name) {
|
||||||
info(c.GetName() + " requesting : " + Name.substr(Name.find_last_of('/')));
|
info(c.GetName() + " requesting : " + Name.substr(Name.find_last_of('/')));
|
||||||
|
|
||||||
if (!std::filesystem::exists(Name)) {
|
if (!std::filesystem::exists(Name)) {
|
||||||
@ -482,7 +648,7 @@ void TTCPServer::SendFile(TClient& c, const std::string& Name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name) {
|
void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name) {
|
||||||
std::ifstream f(Name.c_str(), std::ios::binary);
|
std::ifstream f(Name.c_str(), std::ios::binary);
|
||||||
uint32_t Split = 0x7735940; //125MB
|
uint32_t Split = 0x7735940; //125MB
|
||||||
char* Data;
|
char* Data;
|
||||||
@ -522,7 +688,7 @@ void TTCPServer::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const s
|
|||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTCPServer::TCPSendRaw(SOCKET C, char* Data, int32_t Size) {
|
bool TNetwork::TCPSendRaw(SOCKET C, char* Data, int32_t Size) {
|
||||||
intmax_t Sent = 0;
|
intmax_t Sent = 0;
|
||||||
do {
|
do {
|
||||||
intmax_t Temp = send(C, &Data[Sent], int(Size - Sent), 0);
|
intmax_t Temp = send(C, &Data[Sent], int(Size - Sent), 0);
|
||||||
@ -536,7 +702,7 @@ bool TTCPServer::TCPSendRaw(SOCKET C, char* Data, int32_t Size) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::SendLarge(TClient& c, std::string Data, bool isSync) {
|
void TNetwork::SendLarge(TClient& c, std::string Data, bool isSync) {
|
||||||
if (Data.length() > 400) {
|
if (Data.length() > 400) {
|
||||||
std::string CMP(Comp(Data));
|
std::string CMP(Comp(Data));
|
||||||
Data = "ABG:" + CMP;
|
Data = "ABG:" + CMP;
|
||||||
@ -544,7 +710,7 @@ void TTCPServer::SendLarge(TClient& c, std::string Data, bool isSync) {
|
|||||||
TCPSend(c, Data, isSync);
|
TCPSend(c, Data, isSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::Respond(TClient& c, const std::string& MSG, bool Rel, bool isSync) {
|
void TNetwork::Respond(TClient& c, const std::string& MSG, bool Rel, bool isSync) {
|
||||||
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) {
|
if (C == 'O' || C == 'T' || MSG.length() > 1000) {
|
||||||
@ -553,11 +719,11 @@ void TTCPServer::Respond(TClient& c, const std::string& MSG, bool Rel, bool isSy
|
|||||||
TCPSend(c, MSG, isSync);
|
TCPSend(c, MSG, isSync);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UDPServer().UDPSend(c, MSG);
|
UDPSend(c, MSG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::SyncClient(const std::weak_ptr<TClient>& c) {
|
void TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
||||||
if (c.expired()) {
|
if (c.expired()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -567,7 +733,7 @@ void TTCPServer::SyncClient(const std::weak_ptr<TClient>& c) {
|
|||||||
// Syncing, later set isSynced
|
// Syncing, later set isSynced
|
||||||
// after syncing is done, we apply all packets they missed
|
// after syncing is done, we apply all packets they missed
|
||||||
Respond(*LockedClient, ("Sn") + LockedClient->GetName(), true);
|
Respond(*LockedClient, ("Sn") + LockedClient->GetName(), true);
|
||||||
UDPServer().SendToAll(LockedClient.get(), ("JWelcome ") + LockedClient->GetName() + "!", false, true);
|
SendToAll(LockedClient.get(), ("JWelcome ") + LockedClient->GetName() + "!", false, true);
|
||||||
TriggerLuaEvent(("onPlayerJoin"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID() } }), false);
|
TriggerLuaEvent(("onPlayerJoin"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID() } }), false);
|
||||||
LockedClient->SetIsSyncing(true);
|
LockedClient->SetIsSyncing(true);
|
||||||
bool Return = false;
|
bool Return = false;
|
||||||
@ -600,104 +766,91 @@ void TTCPServer::SyncClient(const std::weak_ptr<TClient>& c) {
|
|||||||
info(LockedClient->GetName() + (" is now synced!"));
|
info(LockedClient->GetName() + (" is now synced!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::SetUDPServer(TUDPServer& UDPServer) {
|
void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel) {
|
||||||
mUDPServer = std::ref(UDPServer);
|
if (!Self)
|
||||||
|
Assert(c);
|
||||||
|
char C = Data.at(0);
|
||||||
|
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
|
||||||
|
if (!ClientPtr.expired()) {
|
||||||
|
auto Client = ClientPtr.lock();
|
||||||
|
if (Self || Client.get() != c) {
|
||||||
|
if (Client->IsSynced() || Client->IsSyncing()) {
|
||||||
|
if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') {
|
||||||
|
if (C == 'O' || C == 'T' || Data.length() > 1000)
|
||||||
|
SendLarge(*Client, Data);
|
||||||
|
else
|
||||||
|
TCPSend(*Client, Data);
|
||||||
|
} else
|
||||||
|
UDPSend(*Client, Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTCPServer::operator()() {
|
void TNetwork::UDPSend(TClient& Client, std::string Data) const {
|
||||||
while (!mUDPServer.has_value()) {
|
if (!Client.IsConnected() || Client.GetStatus() < 0) {
|
||||||
// hard spin
|
// this can happen if we try to send a packet to a client that is either
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
// 1. not yet fully connected, or
|
||||||
|
// 2. disconnected and not yet fully removed
|
||||||
|
// this is fine can can be ignored :^)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sockaddr_in Addr = Client.GetUDPAddr();
|
||||||
|
auto AddrSize = sizeof(Client.GetUDPAddr());
|
||||||
|
if (Data.length() > 400) {
|
||||||
|
std::string CMP(Comp(Data));
|
||||||
|
Data = "ABG:" + CMP;
|
||||||
}
|
}
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
WSADATA wsaData;
|
int sendOk;
|
||||||
if (WSAStartup(514, &wsaData)) {
|
int len = static_cast<int>(Data.size());
|
||||||
error("Can't start Winsock!");
|
#else
|
||||||
return;
|
int64_t sendOk;
|
||||||
}
|
size_t len = Data.size();
|
||||||
SOCKET client, Listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
#endif // WIN32
|
||||||
sockaddr_in addr {};
|
|
||||||
addr.sin_addr.S_un.S_addr = ADDR_ANY;
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(Application::Settings.Port);
|
|
||||||
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
|
||||||
error("Can't bind socket! " + std::to_string(WSAGetLastError()));
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
if (Listener == -1) {
|
|
||||||
error("Invalid listening socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (listen(Listener, SOMAXCONN)) {
|
|
||||||
error("listener failed " + std::to_string(GetLastError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
info("Vehicle event network online");
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
client = accept(Listener, nullptr, nullptr);
|
|
||||||
if (client == -1) {
|
|
||||||
warn("Got an invalid client socket on connect! Skipping...");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::thread ID(&TTCPServer::Identify, this, client);
|
|
||||||
ID.detach();
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
error("fatal: " + std::string(e.what()));
|
|
||||||
}
|
|
||||||
} while (client);
|
|
||||||
|
|
||||||
CloseSocketProper(client);
|
sendOk = sendto(mUDPSock, Data.c_str(), len, 0, (sockaddr*)&Addr, int(AddrSize));
|
||||||
WSACleanup();
|
#ifdef WIN32
|
||||||
|
if (sendOk == -1) {
|
||||||
|
debug(("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError()));
|
||||||
|
if (Client.GetStatus() > -1)
|
||||||
|
Client.SetStatus(-1);
|
||||||
|
} else if (sendOk == 0) {
|
||||||
|
debug(("(UDP) sendto returned 0"));
|
||||||
|
if (Client.GetStatus() > -1)
|
||||||
|
Client.SetStatus(-1);
|
||||||
|
}
|
||||||
#else // unix
|
#else // unix
|
||||||
// wondering why we need slightly different implementations of this?
|
if (sendOk == -1) {
|
||||||
// ask ms.
|
debug(("(UDP) Send Failed Code : ") + std::string(strerror(errno)));
|
||||||
SOCKET client = -1;
|
if (Client.GetStatus() > -1)
|
||||||
SOCKET Listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
Client.SetStatus(-1);
|
||||||
int optval = 1;
|
} else if (sendOk == 0) {
|
||||||
setsockopt(Listener, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
|
debug(("(UDP) sendto returned 0"));
|
||||||
// TODO: check optval or return value idk
|
if (Client.GetStatus() > -1)
|
||||||
sockaddr_in addr {};
|
Client.SetStatus(-1);
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(uint16_t(Application::Settings.Port));
|
|
||||||
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) != 0) {
|
|
||||||
error(("Can't bind socket! ") + std::string(strerror(errno)));
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
if (Listener == -1) {
|
#endif // WIN32
|
||||||
error(("Invalid listening socket"));
|
}
|
||||||
return;
|
|
||||||
}
|
std::string TNetwork::UDPRcvFromClient(sockaddr_in& client) const {
|
||||||
if (listen(Listener, SOMAXCONN)) {
|
size_t clientLength = sizeof(client);
|
||||||
error(("listener failed ") + std::string(strerror(errno)));
|
std::array<char, 1024> Ret {};
|
||||||
return;
|
#ifdef WIN32
|
||||||
}
|
auto Rcv = recvfrom(mUDPSock, Ret.data(), int(Ret.size()), 0, (sockaddr*)&client, (int*)&clientLength);
|
||||||
info(("Vehicle event network online"));
|
#else // unix
|
||||||
do {
|
int64_t Rcv = recvfrom(mUDPSock, Ret.data(), Ret.size(), 0, (sockaddr*)&client, (socklen_t*)&clientLength);
|
||||||
try {
|
#endif // WIN32
|
||||||
if (mShutdown) {
|
|
||||||
debug("shutdown during TCP wait for accept loop");
|
if (Rcv == -1) {
|
||||||
break;
|
#ifdef WIN32
|
||||||
}
|
error(("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError()));
|
||||||
client = accept(Listener, nullptr, nullptr);
|
#else // unix
|
||||||
if (client == -1) {
|
error(("(UDP) Error receiving from Client! Code : ") + std::string(strerror(errno)));
|
||||||
warn(("Got an invalid client socket on connect! Skipping..."));
|
#endif // WIN32
|
||||||
continue;
|
return "";
|
||||||
}
|
}
|
||||||
std::thread ID(&TTCPServer::Identify, this, client);
|
return std::string(Ret.begin(), Ret.begin() + Rcv);
|
||||||
ID.detach(); // TODO: Add to a queue and attempt to join periodically
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
error(("fatal: ") + std::string(e.what()));
|
|
||||||
}
|
|
||||||
} while (client);
|
|
||||||
|
|
||||||
debug("all ok, arrived at " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
|
||||||
|
|
||||||
CloseSocketProper(client);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*TTCPServer::~TTCPServer() {
|
|
||||||
}*/
|
|
@ -1,6 +1,6 @@
|
|||||||
#include "TPPSMonitor.h"
|
#include "TPPSMonitor.h"
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
#include "TTCPServer.h"
|
#include "TNetwork.h"
|
||||||
|
|
||||||
TPPSMonitor::TPPSMonitor(TServer& Server)
|
TPPSMonitor::TPPSMonitor(TServer& Server)
|
||||||
: mServer(Server) {
|
: mServer(Server) {
|
||||||
@ -16,7 +16,7 @@ TPPSMonitor::TPPSMonitor(TServer& Server)
|
|||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
void TPPSMonitor::operator()() {
|
void TPPSMonitor::operator()() {
|
||||||
while (!mTCPServer) {
|
while (!mNetwork) {
|
||||||
// hard spi
|
// hard spi
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ void TPPSMonitor::operator()() {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
for (auto& ClientToKick : TimedOutClients) {
|
for (auto& ClientToKick : TimedOutClients) {
|
||||||
TCPServer().ClientKick(*ClientToKick, "Timeout (no ping for >10 seconds)");
|
Network().ClientKick(*ClientToKick, "Timeout (no ping for >10 seconds)");
|
||||||
}
|
}
|
||||||
TimedOutClients.clear();
|
TimedOutClients.clear();
|
||||||
if (C == 0 || mInternalPPS == 0) {
|
if (C == 0 || mInternalPPS == 0) {
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "TPPSMonitor.h"
|
#include "TPPSMonitor.h"
|
||||||
#include "TTCPServer.h"
|
#include "TNetwork.h"
|
||||||
#include "TUDPServer.h"
|
|
||||||
#include <TLuaFile.h>
|
#include <TLuaFile.h>
|
||||||
#include <any>
|
#include <any>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -14,8 +13,6 @@
|
|||||||
#include "rapidjson/stringbuffer.h"
|
#include "rapidjson/stringbuffer.h"
|
||||||
#include "rapidjson/writer.h"
|
#include "rapidjson/writer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace json = rapidjson;
|
namespace json = rapidjson;
|
||||||
|
|
||||||
TServer::TServer(int argc, char** argv) {
|
TServer::TServer(int argc, char** argv) {
|
||||||
@ -64,7 +61,7 @@ size_t TServer::ClientCount() const {
|
|||||||
return mClients.size();
|
return mClients.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Packet, TPPSMonitor& PPSMonitor, TUDPServer& UDPServer, TTCPServer& TCPServer) {
|
void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Packet, TPPSMonitor& PPSMonitor, TNetwork& Network) {
|
||||||
if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) {
|
if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -86,7 +83,7 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
|
|||||||
//V to Z
|
//V to Z
|
||||||
if (Code <= 90 && Code >= 86) {
|
if (Code <= 90 && Code >= 86) {
|
||||||
PPSMonitor.IncrementInternalPPS();
|
PPSMonitor.IncrementInternalPPS();
|
||||||
UDPServer.SendToAll(LockedClient.get(), Packet, false, false);
|
Network.SendToAll(LockedClient.get(), Packet, false, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (Code) {
|
switch (Code) {
|
||||||
@ -94,24 +91,24 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string("got 'H' packet: '") + Packet + "' (" + std::to_string(Packet.size()) + ")");
|
debug(std::string("got 'H' packet: '") + Packet + "' (" + std::to_string(Packet.size()) + ")");
|
||||||
#endif
|
#endif
|
||||||
TCPServer.SyncClient(Client);
|
Network.SyncClient(Client);
|
||||||
return;
|
return;
|
||||||
case 'p':
|
case 'p':
|
||||||
TCPServer.Respond(*LockedClient, ("p"), false);
|
Network.Respond(*LockedClient, ("p"), false);
|
||||||
TCPServer.UpdatePlayer(*LockedClient);
|
Network.UpdatePlayer(*LockedClient);
|
||||||
LockedClient->UpdatePingTime();
|
LockedClient->UpdatePingTime();
|
||||||
return;
|
return;
|
||||||
case 'O':
|
case 'O':
|
||||||
if (Packet.length() > 1000) {
|
if (Packet.length() > 1000) {
|
||||||
debug(("Received data from: ") + LockedClient->GetName() + (" Size: ") + std::to_string(Packet.length()));
|
debug(("Received data from: ") + LockedClient->GetName() + (" Size: ") + std::to_string(Packet.length()));
|
||||||
}
|
}
|
||||||
ParseVehicle(*LockedClient, Packet, TCPServer, UDPServer);
|
ParseVehicle(*LockedClient, Packet, Network);
|
||||||
return;
|
return;
|
||||||
case 'J':
|
case 'J':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(("got 'J' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
debug(std::string(("got 'J' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
UDPServer.SendToAll(LockedClient.get(), Packet, false, true);
|
Network.SendToAll(LockedClient.get(), Packet, false, true);
|
||||||
return;
|
return;
|
||||||
case 'C':
|
case 'C':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -122,7 +119,7 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
|
|||||||
Res = TriggerLuaEvent("onChatMessage", false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID(), LockedClient->GetName(), Packet.substr(Packet.find(':', 3) + 1) } }), true);
|
Res = TriggerLuaEvent("onChatMessage", false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID(), LockedClient->GetName(), Packet.substr(Packet.find(':', 3) + 1) } }), true);
|
||||||
if (std::any_cast<int>(Res))
|
if (std::any_cast<int>(Res))
|
||||||
break;
|
break;
|
||||||
UDPServer.SendToAll(nullptr, Packet, true, true);
|
Network.SendToAll(nullptr, Packet, true, true);
|
||||||
return;
|
return;
|
||||||
case 'E':
|
case 'E':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -156,13 +153,13 @@ void TServer::HandleEvent(TClient& c, const std::string& Data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPServer, TUDPServer& UDPServer) {
|
void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network) {
|
||||||
if (Pckt.length() < 4)
|
if (Pckt.length() < 4)
|
||||||
return;
|
return;
|
||||||
std::string Packet = Pckt;
|
std::string Packet = Pckt;
|
||||||
char Code = Packet.at(1);
|
char Code = Packet.at(1);
|
||||||
int PID = -1;
|
int PID = -1;
|
||||||
int VID = -1,Pos;
|
int VID = -1, Pos;
|
||||||
std::string Data = Packet.substr(3), pid, vid;
|
std::string Data = Packet.substr(3), pid, vid;
|
||||||
switch (Code) { //Spawned Destroyed Switched/Moved NotFound Reset
|
switch (Code) { //Spawned Destroyed Switched/Moved NotFound Reset
|
||||||
case 's':
|
case 's':
|
||||||
@ -175,13 +172,13 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPS
|
|||||||
Packet = "Os:" + c.GetRoles() + ":" + c.GetName() + ":" + std::to_string(c.GetID()) + "-" + std::to_string(CarID) + Packet.substr(4);
|
Packet = "Os:" + c.GetRoles() + ":" + c.GetName() + ":" + std::to_string(c.GetID()) + "-" + std::to_string(CarID) + Packet.substr(4);
|
||||||
auto Res = TriggerLuaEvent(("onVehicleSpawn"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), CarID, Packet.substr(3) } }), true);
|
auto Res = TriggerLuaEvent(("onVehicleSpawn"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), CarID, Packet.substr(3) } }), true);
|
||||||
if (c.GetCarCount() >= Application::Settings.MaxCars || std::any_cast<int>(Res)) {
|
if (c.GetCarCount() >= Application::Settings.MaxCars || std::any_cast<int>(Res)) {
|
||||||
TCPServer.Respond(c, Packet, true);
|
Network.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);
|
||||||
TCPServer.Respond(c, Destroy, true);
|
Network.Respond(c, Destroy, true);
|
||||||
debug(c.GetName() + (" (force : car limit/lua) removed ID ") + std::to_string(CarID));
|
debug(c.GetName() + (" (force : car limit/lua) removed ID ") + std::to_string(CarID));
|
||||||
} else {
|
} else {
|
||||||
c.AddNewCar(CarID, Packet);
|
c.AddNewCar(CarID, Packet);
|
||||||
UDPServer.SendToAll(nullptr, Packet, true, true);
|
Network.SendToAll(nullptr, Packet, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -200,11 +197,11 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPS
|
|||||||
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID, Packet.substr(3) } }),
|
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID, Packet.substr(3) } }),
|
||||||
true);
|
true);
|
||||||
if (!std::any_cast<int>(Res)) {
|
if (!std::any_cast<int>(Res)) {
|
||||||
UDPServer.SendToAll(&c, Packet, false, true);
|
Network.SendToAll(&c, Packet, false, true);
|
||||||
Apply(c, VID, Packet);
|
Apply(c, VID, Packet);
|
||||||
} else {
|
} else {
|
||||||
std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(VID);
|
std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(VID);
|
||||||
TCPServer.Respond(c, Destroy, true);
|
Network.Respond(c, Destroy, true);
|
||||||
c.DeleteCar(VID);
|
c.DeleteCar(VID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,7 +217,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPS
|
|||||||
VID = stoi(vid);
|
VID = stoi(vid);
|
||||||
}
|
}
|
||||||
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
||||||
UDPServer.SendToAll(nullptr, Packet, true, true);
|
Network.SendToAll(nullptr, Packet, true, true);
|
||||||
TriggerLuaEvent(("onVehicleDeleted"), false, nullptr,
|
TriggerLuaEvent(("onVehicleDeleted"), false, nullptr,
|
||||||
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID } }), false);
|
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID } }), false);
|
||||||
c.DeleteCar(VID);
|
c.DeleteCar(VID);
|
||||||
@ -233,7 +230,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPS
|
|||||||
#endif
|
#endif
|
||||||
Pos = int(Data.find('-'));
|
Pos = int(Data.find('-'));
|
||||||
pid = Data.substr(0, Pos++);
|
pid = Data.substr(0, Pos++);
|
||||||
vid = Data.substr(Pos,Data.find(':') - Pos);
|
vid = Data.substr(Pos, Data.find(':') - Pos);
|
||||||
|
|
||||||
if (pid.find_first_not_of("0123456789") == std::string::npos && vid.find_first_not_of("0123456789") == std::string::npos) {
|
if (pid.find_first_not_of("0123456789") == std::string::npos && vid.find_first_not_of("0123456789") == std::string::npos) {
|
||||||
PID = stoi(pid);
|
PID = stoi(pid);
|
||||||
@ -243,16 +240,16 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TTCPServer& TCPS
|
|||||||
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
||||||
Data = Data.substr(Data.find('{'));
|
Data = Data.substr(Data.find('{'));
|
||||||
TriggerLuaEvent("onVehicleReset", false, nullptr,
|
TriggerLuaEvent("onVehicleReset", false, nullptr,
|
||||||
std::make_unique<TLuaArg>(TLuaArg {{ c.GetID(), VID, Data}}),
|
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID, Data } }),
|
||||||
false);
|
false);
|
||||||
UDPServer.SendToAll(&c, Packet, false, true);
|
Network.SendToAll(&c, Packet, false, true);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 't':
|
case 't':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(("got 'Ot' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
debug(std::string(("got 'Ot' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
UDPServer.SendToAll(&c, Packet, false, true);
|
Network.SendToAll(&c, Packet, false, true);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -1,182 +0,0 @@
|
|||||||
#include "TUDPServer.h"
|
|
||||||
#include "CustomAssert.h"
|
|
||||||
#include "TTCPServer.h"
|
|
||||||
#include <any>
|
|
||||||
#include <array>
|
|
||||||
#include <cstring>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
TUDPServer::TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor, TTCPServer& TCPServer)
|
|
||||||
: mServer(Server)
|
|
||||||
, mPPSMonitor(PPSMonitor)
|
|
||||||
, mTCPServer(TCPServer) {
|
|
||||||
Application::RegisterShutdownHandler([&] {if (mThread.joinable()) {
|
|
||||||
debug("shutting down UDPServer");
|
|
||||||
mShutdown = true;
|
|
||||||
// FIXME: Once we use boost for UDP, set up a timeout so this doesn't block
|
|
||||||
mThread.detach();
|
|
||||||
debug("shut down UDPServer");
|
|
||||||
} });
|
|
||||||
Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TUDPServer::operator()() {
|
|
||||||
#ifdef WIN32
|
|
||||||
WSADATA data;
|
|
||||||
if (WSAStartup(514, &data)) {
|
|
||||||
error(("Can't start Winsock!"));
|
|
||||||
//return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mUDPSock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
||||||
// Create a server hint structure for the server
|
|
||||||
sockaddr_in serverAddr {};
|
|
||||||
serverAddr.sin_addr.S_un.S_addr = ADDR_ANY; //Any Local
|
|
||||||
serverAddr.sin_family = AF_INET; // Address format is IPv4
|
|
||||||
serverAddr.sin_port = htons(Application::Settings.Port); // Convert from little to big endian
|
|
||||||
|
|
||||||
// Try and bind the socket to the IP and port
|
|
||||||
if (bind(mUDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
|
|
||||||
error(("Can't bind socket!") + std::to_string(WSAGetLastError()));
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
|
||||||
exit(-1);
|
|
||||||
//return;
|
|
||||||
}
|
|
||||||
#else // unix
|
|
||||||
mUDPSock = 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(Application::Settings.Port)); // Convert from little to big endian
|
|
||||||
|
|
||||||
// Try and bind the socket to the IP and port
|
|
||||||
if (bind(mUDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) {
|
|
||||||
error(("Can't bind socket!") + std::string(strerror(errno)));
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
|
||||||
exit(-1);
|
|
||||||
//return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
info(("Vehicle data network online on port ") + std::to_string(Application::Settings.Port) + (" with a Max of ")
|
|
||||||
+ std::to_string(Application::Settings.MaxPlayers) + (" Clients"));
|
|
||||||
while (!mShutdown) {
|
|
||||||
try {
|
|
||||||
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;
|
|
||||||
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
|
|
||||||
if (!ClientPtr.expired()) {
|
|
||||||
auto Client = ClientPtr.lock();
|
|
||||||
if (Client->GetID() == ID) {
|
|
||||||
Client->SetUDPAddr(client);
|
|
||||||
Client->SetIsConnected(true);
|
|
||||||
TServer::GlobalParser(ClientPtr, Data.substr(2), mPPSMonitor, *this, mTCPServer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
error(("fatal: ") + std::string(e.what()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TUDPServer::SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel) {
|
|
||||||
if (!Self)
|
|
||||||
Assert(c);
|
|
||||||
char C = Data.at(0);
|
|
||||||
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
|
|
||||||
if (!ClientPtr.expired()) {
|
|
||||||
auto Client = ClientPtr.lock();
|
|
||||||
if (Self || Client.get() != c) {
|
|
||||||
if (Client->IsSynced() || Client->IsSyncing()) {
|
|
||||||
if (Rel || C == 'W' || C == 'Y' || C == 'V' || C == 'E') {
|
|
||||||
if (C == 'O' || C == 'T' || Data.length() > 1000)
|
|
||||||
mTCPServer.SendLarge(*Client, Data);
|
|
||||||
else
|
|
||||||
mTCPServer.TCPSend(*Client, Data);
|
|
||||||
} else
|
|
||||||
UDPSend(*Client, Data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void TUDPServer::UDPSend(TClient& Client, std::string Data) const {
|
|
||||||
if (!Client.IsConnected() || Client.GetStatus() < 0) {
|
|
||||||
// this can happen if we try to send a packet to a client that is either
|
|
||||||
// 1. not yet fully connected, or
|
|
||||||
// 2. disconnected and not yet fully removed
|
|
||||||
// this is fine can can be ignored :^)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sockaddr_in Addr = Client.GetUDPAddr();
|
|
||||||
auto AddrSize = sizeof(Client.GetUDPAddr());
|
|
||||||
if (Data.length() > 400) {
|
|
||||||
std::string CMP(Comp(Data));
|
|
||||||
Data = "ABG:" + CMP;
|
|
||||||
}
|
|
||||||
#ifdef WIN32
|
|
||||||
int sendOk;
|
|
||||||
int len = static_cast<int>(Data.size());
|
|
||||||
#else
|
|
||||||
int64_t sendOk;
|
|
||||||
size_t len = Data.size();
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
sendOk = sendto(mUDPSock, Data.c_str(), len, 0, (sockaddr*)&Addr, int(AddrSize));
|
|
||||||
#ifdef WIN32
|
|
||||||
if (sendOk == -1) {
|
|
||||||
debug(("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError()));
|
|
||||||
if (Client.GetStatus() > -1)
|
|
||||||
Client.SetStatus(-1);
|
|
||||||
} else if (sendOk == 0) {
|
|
||||||
debug(("(UDP) sendto returned 0"));
|
|
||||||
if (Client.GetStatus() > -1)
|
|
||||||
Client.SetStatus(-1);
|
|
||||||
}
|
|
||||||
#else // unix
|
|
||||||
if (sendOk == -1) {
|
|
||||||
debug(("(UDP) Send Failed Code : ") + std::string(strerror(errno)));
|
|
||||||
if (Client.GetStatus() > -1)
|
|
||||||
Client.SetStatus(-1);
|
|
||||||
} else if (sendOk == 0) {
|
|
||||||
debug(("(UDP) sendto returned 0"));
|
|
||||||
if (Client.GetStatus() > -1)
|
|
||||||
Client.SetStatus(-1);
|
|
||||||
}
|
|
||||||
#endif // WIN32
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TUDPServer::UDPRcvFromClient(sockaddr_in& client) const {
|
|
||||||
size_t clientLength = sizeof(client);
|
|
||||||
std::array<char, 1024> Ret {};
|
|
||||||
#ifdef WIN32
|
|
||||||
auto Rcv = recvfrom(mUDPSock, Ret.data(), int(Ret.size()), 0, (sockaddr*)&client, (int*)&clientLength);
|
|
||||||
#else // unix
|
|
||||||
int64_t Rcv = recvfrom(mUDPSock, Ret.data(), Ret.size(), 0, (sockaddr*)&client, (socklen_t*)&clientLength);
|
|
||||||
#endif // WIN32
|
|
||||||
|
|
||||||
if (Rcv == -1) {
|
|
||||||
#ifdef WIN32
|
|
||||||
error(("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError()));
|
|
||||||
#else // unix
|
|
||||||
error(("(UDP) Error receiving from Client! Code : ") + std::string(strerror(errno)));
|
|
||||||
#endif // WIN32
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return std::string(Ret.begin(), Ret.begin() + Rcv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*TUDPServer::~TUDPServer() {
|
|
||||||
}*/
|
|
11
src/main.cpp
11
src/main.cpp
@ -2,11 +2,10 @@
|
|||||||
#include "TConfig.h"
|
#include "TConfig.h"
|
||||||
#include "THeartbeatThread.h"
|
#include "THeartbeatThread.h"
|
||||||
#include "TLuaEngine.h"
|
#include "TLuaEngine.h"
|
||||||
|
#include "TNetwork.h"
|
||||||
#include "TPPSMonitor.h"
|
#include "TPPSMonitor.h"
|
||||||
#include "TResourceManager.h"
|
#include "TResourceManager.h"
|
||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
#include "TUDPServer.h"
|
|
||||||
#include <TTCPServer.h>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#ifdef __unix
|
#ifdef __unix
|
||||||
@ -52,11 +51,9 @@ int main(int argc, char** argv) {
|
|||||||
TResourceManager ResourceManager;
|
TResourceManager ResourceManager;
|
||||||
TPPSMonitor PPSMonitor(Server);
|
TPPSMonitor PPSMonitor(Server);
|
||||||
THeartbeatThread Heartbeat(ResourceManager, Server);
|
THeartbeatThread Heartbeat(ResourceManager, Server);
|
||||||
TTCPServer TCPServer(Server, PPSMonitor, ResourceManager);
|
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
||||||
TUDPServer UDPServer(Server, PPSMonitor, TCPServer);
|
TLuaEngine LuaEngine(Server, Network);
|
||||||
TLuaEngine LuaEngine(Server, TCPServer, UDPServer);
|
PPSMonitor.SetNetwork(Network);
|
||||||
TCPServer.SetUDPServer(UDPServer);
|
|
||||||
PPSMonitor.SetTCPServer(TCPServer);
|
|
||||||
Application::Console().InitializeLuaConsole(LuaEngine);
|
Application::Console().InitializeLuaConsole(LuaEngine);
|
||||||
|
|
||||||
// TODO: replace
|
// TODO: replace
|
||||||
|
Loading…
x
Reference in New Issue
Block a user