mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 23:35:41 +00:00
add udpserver, tcpserver
This commit is contained in:
parent
f19a012509
commit
bf74b1ae32
2
.idea/.gitignore
generated
vendored
2
.idea/.gitignore
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/workspace.xml
|
|
2
.idea/.name
generated
2
.idea/.name
generated
@ -1 +1 @@
|
|||||||
Server
|
TUDPServer.cpp
|
2
.idea/BeamNG-MP-Server.iml
generated
2
.idea/BeamNG-MP-Server.iml
generated
@ -1,2 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
|
3
.idea/misc.xml
generated
3
.idea/misc.xml
generated
@ -1,7 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
<component name="JavaScriptSettings">
|
|
||||||
<option name="languageLevel" value="ES6" />
|
|
||||||
</component>
|
|
||||||
</project>
|
</project>
|
3
.idea/vcs.xml
generated
3
.idea/vcs.xml
generated
@ -2,6 +2,9 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/asio" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/include/commandline" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/include/commandline" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/rapidjson" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/socket.io-client-cpp" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -44,7 +44,7 @@ add_executable(BeamMP-Server
|
|||||||
include/THeartbeatThread.h src/THeartbeatThread.cpp
|
include/THeartbeatThread.h src/THeartbeatThread.cpp
|
||||||
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/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")
|
||||||
|
|
||||||
|
@ -8,46 +8,52 @@
|
|||||||
#include "Compat.h"
|
#include "Compat.h"
|
||||||
#include "VehicleData.h"
|
#include "VehicleData.h"
|
||||||
|
|
||||||
|
class TServer;
|
||||||
|
|
||||||
class TClient final {
|
class TClient final {
|
||||||
public:
|
public:
|
||||||
using TSetOfVehicleData = std::unordered_set<std::unique_ptr<TVehicleData>>;
|
using TSetOfVehicleData = std::unordered_set<std::unique_ptr<TVehicleData>>;
|
||||||
|
|
||||||
|
explicit TClient(TServer& Server);
|
||||||
|
|
||||||
void AddNewCar(int Ident, const std::string& Data);
|
void AddNewCar(int Ident, const std::string& Data);
|
||||||
void SetCarData(int Ident, const std::string& Data);
|
void SetCarData(int Ident, const std::string& Data);
|
||||||
TSetOfVehicleData& GetAllCars();
|
TSetOfVehicleData& GetAllCars();
|
||||||
void SetName(const std::string& Name) { _Name = Name; }
|
void SetName(const std::string& Name) { mName = Name; }
|
||||||
void SetRoles(const std::string& Role) { _Role = Role; }
|
void SetRoles(const std::string& Role) { mRole = Role; }
|
||||||
std::string GetCarData(int Ident);
|
std::string GetCarData(int Ident);
|
||||||
void SetUDPAddr(sockaddr_in Addr) { _UDPAddress = Addr; }
|
void SetUDPAddr(sockaddr_in Addr) { mUDPAddress = Addr; }
|
||||||
void SetDownSock(SOCKET CSock) { _Socket[1] = CSock; }
|
void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; }
|
||||||
void SetTCPSock(SOCKET CSock) { _Socket[0] = CSock; }
|
void SetTCPSock(SOCKET CSock) { mSocket[0] = CSock; }
|
||||||
void SetStatus(int Status) { _Status = Status; }
|
void SetStatus(int Status) { mStatus = Status; }
|
||||||
void DeleteCar(int Ident);
|
void DeleteCar(int Ident);
|
||||||
sockaddr_in GetUDPAddr() { return _UDPAddress; }
|
sockaddr_in GetUDPAddr() const { return mUDPAddress; }
|
||||||
std::string GetRoles() { return _Role; }
|
std::string GetRoles() const { return mRole; }
|
||||||
std::string GetName() { return _Name; }
|
std::string GetName() const { return mName; }
|
||||||
SOCKET GetDownSock() { return _Socket[1]; }
|
SOCKET GetDownSock() const { return mSocket[1]; }
|
||||||
SOCKET GetTCPSock() { return _Socket[0]; }
|
SOCKET GetTCPSock() const { return mSocket[0]; }
|
||||||
void SetID(int ID) { _ID = ID; }
|
void SetID(int ID) { mID = ID; }
|
||||||
int GetOpenCarID();
|
int GetOpenCarID() const;
|
||||||
int GetCarCount();
|
int GetCarCount() const;
|
||||||
void ClearCars();
|
void ClearCars();
|
||||||
int GetStatus() { return _Status; }
|
int GetStatus() const { return mStatus; }
|
||||||
int GetID() { return _ID; }
|
int GetID() const { return mID; }
|
||||||
bool IsConnected() const { return _IsConnected; }
|
bool IsConnected() const { return mIsConnected; }
|
||||||
bool IsSynced() const { return _IsSynced; }
|
bool IsSynced() const { return mIsSynced; }
|
||||||
bool IsGuest() const { return _IsGuest; }
|
bool IsGuest() const { return mIsGuest; }
|
||||||
|
TServer& Server() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _IsConnected = false;
|
TServer& mServer;
|
||||||
bool _IsSynced = false;
|
bool mIsConnected = false;
|
||||||
bool _IsGuest = false;
|
bool mIsSynced = false;
|
||||||
TSetOfVehicleData _VehicleData;
|
bool mIsGuest = false;
|
||||||
std::string _Name = "Unknown Client";
|
TSetOfVehicleData mVehicleData;
|
||||||
SOCKET _Socket[2] { SOCKET(-1) };
|
std::string mName = "Unknown Client";
|
||||||
sockaddr_in _UDPAddress;
|
SOCKET mSocket[2] { SOCKET(-1) };
|
||||||
std::string _Role;
|
sockaddr_in mUDPAddress {}; // is this initialization OK?
|
||||||
std::string _DID;
|
std::string mRole;
|
||||||
int _Status = 0;
|
std::string mDID;
|
||||||
int _ID = -1;
|
int mStatus = 0;
|
||||||
|
int mID = -1;
|
||||||
};
|
};
|
||||||
|
@ -76,3 +76,8 @@ static inline void debug(const std::string& str) {
|
|||||||
static inline void luaprint(const std::string& str) {
|
static inline void luaprint(const std::string& str) {
|
||||||
Application::Console().Write(std::string("[LUA] ") + str);
|
Application::Console().Write(std::string("[LUA] ") + str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define Biggest 30000
|
||||||
|
std::string Comp(std::string Data);
|
||||||
|
std::string DeComp(std::string Compressed);
|
||||||
|
|
||||||
|
@ -4,13 +4,18 @@
|
|||||||
|
|
||||||
#ifdef __unix
|
#ifdef __unix
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
using SOCKET = int;
|
using SOCKET = int;
|
||||||
using DWORD = unsigned long;
|
using DWORD = unsigned long;
|
||||||
using PDWORD = unsigned long*;
|
using PDWORD = unsigned long*;
|
||||||
using LPDWORD = unsigned long*;
|
using LPDWORD = unsigned long*;
|
||||||
char _getch(void);
|
char _getch();
|
||||||
|
inline void CloseSocketProper(int socket) {
|
||||||
|
shutdown(socket, SHUT_RDWR);
|
||||||
|
close(socket);
|
||||||
|
}
|
||||||
#endif // unix
|
#endif // unix
|
||||||
|
|
||||||
// ======================= WIN32 =======================
|
// ======================= WIN32 =======================
|
||||||
@ -18,6 +23,10 @@ char _getch(void);
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
inline void CloseSocketProper(int socket) {
|
||||||
|
shutdown(socket, SHUT_RDWR);
|
||||||
|
close(socket);
|
||||||
|
}
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
// ======================= OTHER =======================
|
// ======================= OTHER =======================
|
||||||
@ -25,4 +34,3 @@ char _getch(void);
|
|||||||
#if !defined(WIN32) && !defined(__unix)
|
#if !defined(WIN32) && !defined(__unix)
|
||||||
#error "OS not supported"
|
#error "OS not supported"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -10,8 +10,11 @@ public:
|
|||||||
|
|
||||||
void operator()() override;
|
void operator()() override;
|
||||||
|
|
||||||
private:
|
void SetInternalPPS(int NewPPS) { mInternalPPS = NewPPS; }
|
||||||
|
void IncrementInternalPPS() { ++mInternalPPS; }
|
||||||
|
[[nodiscard]] int InternalPPS() const { return mInternalPPS; }
|
||||||
|
|
||||||
|
private:
|
||||||
TServer& mServer;
|
TServer& mServer;
|
||||||
bool mShutdown { false };
|
bool mShutdown { false };
|
||||||
int mInternalPPS { 0 };
|
int mInternalPPS { 0 };
|
||||||
|
14
include/TTCPServer.h
Normal file
14
include/TTCPServer.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Compat.h"
|
||||||
|
#include "IThreaded.h"
|
||||||
|
#include "TServer.h"
|
||||||
|
|
||||||
|
class TTCPServer : public IThreaded {
|
||||||
|
public:
|
||||||
|
explicit TTCPServer(TServer& Server);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TServer& mServer;
|
||||||
|
};
|
26
include/TUDPServer.h
Normal file
26
include/TUDPServer.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#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);
|
||||||
|
|
||||||
|
void operator()() override;
|
||||||
|
|
||||||
|
void UDPSend(TClient& Client, std::string Data) const;
|
||||||
|
void SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UDPParser(TClient& Client, std::string Packet);
|
||||||
|
|
||||||
|
TServer& mServer;
|
||||||
|
TPPSMonitor& mPPSMonitor;
|
||||||
|
SOCKET mUDPSock;
|
||||||
|
std::string UDPRcvFromClient(sockaddr_in& client) const;
|
||||||
|
};
|
@ -1,28 +1,29 @@
|
|||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
|
|
||||||
|
#include "CustomAssert.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
// FIXME: add debug prints
|
// FIXME: add debug prints
|
||||||
|
|
||||||
void TClient::DeleteCar(int Ident) {
|
void TClient::DeleteCar(int Ident) {
|
||||||
for (auto& v : _VehicleData) {
|
for (auto& v : mVehicleData) {
|
||||||
if (v != nullptr && v->ID() == Ident) {
|
if (v != nullptr && v->ID() == Ident) {
|
||||||
_VehicleData.erase(v);
|
mVehicleData.erase(v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TClient::ClearCars() {
|
void TClient::ClearCars() {
|
||||||
_VehicleData.clear();
|
mVehicleData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int TClient::GetOpenCarID() {
|
int TClient::GetOpenCarID() const {
|
||||||
int OpenID = 0;
|
int OpenID = 0;
|
||||||
bool found;
|
bool found;
|
||||||
do {
|
do {
|
||||||
found = true;
|
found = true;
|
||||||
for (auto& v : _VehicleData) {
|
for (auto& v : mVehicleData) {
|
||||||
if (v != nullptr && v->ID() == OpenID) {
|
if (v != nullptr && v->ID() == OpenID) {
|
||||||
OpenID++;
|
OpenID++;
|
||||||
found = false;
|
found = false;
|
||||||
@ -33,15 +34,15 @@ int TClient::GetOpenCarID() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TClient::AddNewCar(int Ident, const std::string& Data) {
|
void TClient::AddNewCar(int Ident, const std::string& Data) {
|
||||||
_VehicleData.insert(std::make_unique<TVehicleData>(TVehicleData { Ident, Data }));
|
mVehicleData.insert(std::make_unique<TVehicleData>(TVehicleData { Ident, Data }));
|
||||||
}
|
}
|
||||||
|
|
||||||
TClient::TSetOfVehicleData& TClient::GetAllCars() {
|
TClient::TSetOfVehicleData& TClient::GetAllCars() {
|
||||||
return _VehicleData;
|
return mVehicleData;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TClient::GetCarData(int Ident) {
|
std::string TClient::GetCarData(int Ident) {
|
||||||
for (auto& v : _VehicleData) {
|
for (auto& v : mVehicleData) {
|
||||||
if (v != nullptr && v->ID() == Ident) {
|
if (v != nullptr && v->ID() == Ident) {
|
||||||
return v->Data();
|
return v->Data();
|
||||||
}
|
}
|
||||||
@ -51,7 +52,7 @@ std::string TClient::GetCarData(int Ident) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TClient::SetCarData(int Ident, const std::string& Data) {
|
void TClient::SetCarData(int Ident, const std::string& Data) {
|
||||||
for (auto& v : _VehicleData) {
|
for (auto& v : mVehicleData) {
|
||||||
if (v != nullptr && v->ID() == Ident) {
|
if (v != nullptr && v->ID() == Ident) {
|
||||||
v->Data() = Data;
|
v->Data() = Data;
|
||||||
return;
|
return;
|
||||||
@ -59,6 +60,13 @@ void TClient::SetCarData(int Ident, const std::string& Data) {
|
|||||||
}
|
}
|
||||||
DeleteCar(Ident);
|
DeleteCar(Ident);
|
||||||
}
|
}
|
||||||
int TClient::GetCarCount() {
|
int TClient::GetCarCount() const {
|
||||||
return int(_VehicleData.size());
|
return int(mVehicleData.size());
|
||||||
|
}
|
||||||
|
TServer& TClient::Server() const {
|
||||||
|
return mServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
TClient::TClient(TServer& Server)
|
||||||
|
: mServer(Server) {
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
#include "TConsole.h"
|
#include "TConsole.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
std::unique_ptr<TConsole> Application::mConsole = std::make_unique<TConsole>();
|
std::unique_ptr<TConsole> Application::mConsole = std::make_unique<TConsole>();
|
||||||
|
|
||||||
@ -16,3 +21,46 @@ void Application::GracefullyShutdown() {
|
|||||||
Handler();
|
Handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::string Comp(std::string Data) {
|
||||||
|
std::array<char, Biggest> C {};
|
||||||
|
// obsolete
|
||||||
|
C.fill(0);
|
||||||
|
z_stream defstream;
|
||||||
|
defstream.zalloc = Z_NULL;
|
||||||
|
defstream.zfree = Z_NULL;
|
||||||
|
defstream.opaque = Z_NULL;
|
||||||
|
defstream.avail_in = (uInt)Data.length();
|
||||||
|
defstream.next_in = (Bytef*)&Data[0];
|
||||||
|
defstream.avail_out = Biggest;
|
||||||
|
defstream.next_out = reinterpret_cast<Bytef*>(C.data());
|
||||||
|
deflateInit(&defstream, Z_BEST_COMPRESSION);
|
||||||
|
deflate(&defstream, Z_SYNC_FLUSH);
|
||||||
|
deflate(&defstream, Z_FINISH);
|
||||||
|
deflateEnd(&defstream);
|
||||||
|
size_t TO = defstream.total_out;
|
||||||
|
std::string Ret(TO, 0);
|
||||||
|
std::copy_n(C.begin(), TO, Ret.begin());
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DeComp(std::string Compressed) {
|
||||||
|
std::array<char, Biggest> C {};
|
||||||
|
// not needed
|
||||||
|
C.fill(0);
|
||||||
|
z_stream infstream;
|
||||||
|
infstream.zalloc = Z_NULL;
|
||||||
|
infstream.zfree = Z_NULL;
|
||||||
|
infstream.opaque = Z_NULL;
|
||||||
|
infstream.avail_in = Biggest;
|
||||||
|
infstream.next_in = (Bytef*)(&Compressed[0]);
|
||||||
|
infstream.avail_out = Biggest;
|
||||||
|
infstream.next_out = (Bytef*)(C.data());
|
||||||
|
inflateInit(&infstream);
|
||||||
|
inflate(&infstream, Z_SYNC_FLUSH);
|
||||||
|
inflate(&infstream, Z_FINISH);
|
||||||
|
inflateEnd(&infstream);
|
||||||
|
size_t TO = infstream.total_out;
|
||||||
|
std::string Ret(TO, 0);
|
||||||
|
std::copy_n(C.begin(), TO, Ret.begin());
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
@ -30,7 +30,7 @@ void TServer::RemoveClient(std::weak_ptr<TClient> WeakClientPtr) {
|
|||||||
std::weak_ptr<TClient> TServer::InsertNewClient() {
|
std::weak_ptr<TClient> TServer::InsertNewClient() {
|
||||||
debug("inserting new client (" + std::to_string(ClientCount()) + ")");
|
debug("inserting new client (" + std::to_string(ClientCount()) + ")");
|
||||||
WriteLock Lock(mClientsMutex);
|
WriteLock Lock(mClientsMutex);
|
||||||
auto [Iter, Replaced] = mClients.insert(std::make_shared<TClient>());
|
auto [Iter, Replaced] = mClients.insert(std::make_shared<TClient>(*this));
|
||||||
return *Iter;
|
return *Iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
src/TTCPServer.cpp
Normal file
5
src/TTCPServer.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "TTCPServer.h"
|
||||||
|
|
||||||
|
TTCPServer::TTCPServer(TServer& Server)
|
||||||
|
: mServer(Server) {
|
||||||
|
}
|
224
src/TUDPServer.cpp
Normal file
224
src/TUDPServer.cpp
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
#include "TUDPServer.h"
|
||||||
|
#include "CustomAssert.h"
|
||||||
|
#include <any>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
TUDPServer::TUDPServer(TServer& Server, TPPSMonitor& PPSMonitor)
|
||||||
|
: mServer(Server)
|
||||||
|
, mPPSMonitor(PPSMonitor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (true) {
|
||||||
|
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->SetConnected(true);
|
||||||
|
UDPParser(*Client, Data.substr(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
error(("fatal: ") + std::string(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void TUDPServer::UDPParser(TClient& Client, std::string Packet) {
|
||||||
|
if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (Packet.substr(0, 4) == "ABG:") {
|
||||||
|
Packet = DeComp(Packet.substr(4));
|
||||||
|
}
|
||||||
|
if (Packet.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::any Res;
|
||||||
|
char Code = Packet.at(0);
|
||||||
|
|
||||||
|
//V to Z
|
||||||
|
if (Code <= 90 && Code >= 86) {
|
||||||
|
mPPSMonitor.IncrementInternalPPS();
|
||||||
|
SendToAll(&Client, Packet, false, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (Code) {
|
||||||
|
case 'H': // initial connection
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug(std::string("got 'H' packet: '") + Packet + "' (" + std::to_string(Packet.size()) + ")");
|
||||||
|
#endif
|
||||||
|
SyncClient(Client);
|
||||||
|
return;
|
||||||
|
case 'p':
|
||||||
|
Respond(Client, ("p"), false);
|
||||||
|
UpdatePlayers();
|
||||||
|
return;
|
||||||
|
case 'O':
|
||||||
|
if (Packet.length() > 1000) {
|
||||||
|
debug(("Received data from: ") + Client->GetName() + (" Size: ") + std::to_string(Packet.length()));
|
||||||
|
}
|
||||||
|
ParseVeh(Client, Packet);
|
||||||
|
return;
|
||||||
|
case 'J':
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug(std::string(("got 'J' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
|
#endif
|
||||||
|
SendToAll(Client, Packet, false, true);
|
||||||
|
return;
|
||||||
|
case 'C':
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug(std::string(("got 'C' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
|
#endif
|
||||||
|
if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos)
|
||||||
|
break;
|
||||||
|
Res = TriggerLuaEvent("onChatMessage", false, nullptr, std::make_unique<LuaArg>(LuaArg { { Client->GetID(), Client->GetName(), Packet.substr(Packet.find(':', 3) + 1) } }), true);
|
||||||
|
if (std::any_cast<int>(Res))
|
||||||
|
break;
|
||||||
|
SendToAll(nullptr, Packet, true, true);
|
||||||
|
return;
|
||||||
|
case 'E':
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug(std::string(("got 'E' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
|
#endif
|
||||||
|
HandleEvent(Client, Packet);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
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 TUDPServer::UDPSend(TClient& Client, std::string Data) const {
|
||||||
|
if (!Client.IsConnected() || Client.GetStatus() < 0) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug(Client.GetName() + ": !IsConnected() or GetStatus() < 0");
|
||||||
|
#endif // DEBUG
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sockaddr_in Addr = Client.GetUDPAddr();
|
||||||
|
socklen_t 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, 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 {};
|
||||||
|
int64_t Rcv = recvfrom(mUDPSock, Ret.data(), Ret.size(), 0, (sockaddr*)&client, (socklen_t*)&clientLength);
|
||||||
|
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);
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
#include "TResourceManager.h"
|
#include "TResourceManager.h"
|
||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
#include "TPPSMonitor.h"
|
#include "TPPSMonitor.h"
|
||||||
|
#include "TUDPServer.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -46,10 +47,12 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
TServer Server(argc, argv);
|
TServer Server(argc, argv);
|
||||||
[[maybe_unused]] TConfig Config("Server.cfg");
|
[[maybe_unused]] TConfig Config("Server.cfg");
|
||||||
TLuaEngine LuaEngine(Server);
|
|
||||||
TResourceManager ResourceManager;
|
TResourceManager ResourceManager;
|
||||||
[[maybe_unused]] TPPSMonitor PPSMonitor(Server);
|
[[maybe_unused]] TPPSMonitor PPSMonitor(Server);
|
||||||
THeartbeatThread Heartbeat(ResourceManager, Server);
|
THeartbeatThread Heartbeat(ResourceManager, Server);
|
||||||
|
TTCPServer TCPServer(Server);
|
||||||
|
TUDPServer UDPServer(Server, PPSMonitor);
|
||||||
|
TLuaEngine LuaEngine(Server);
|
||||||
|
|
||||||
// TODO: replace
|
// TODO: replace
|
||||||
bool Shutdown = false;
|
bool Shutdown = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user