add udpserver, tcpserver

This commit is contained in:
Lion Kortlepel
2021-02-16 15:54:50 +01:00
committed by Anonymous275
parent f19a012509
commit bf74b1ae32
18 changed files with 401 additions and 55 deletions

View File

@@ -1,28 +1,29 @@
#include "Client.h"
#include "CustomAssert.h"
#include <memory>
// FIXME: add debug prints
void TClient::DeleteCar(int Ident) {
for (auto& v : _VehicleData) {
for (auto& v : mVehicleData) {
if (v != nullptr && v->ID() == Ident) {
_VehicleData.erase(v);
mVehicleData.erase(v);
break;
}
}
}
void TClient::ClearCars() {
_VehicleData.clear();
mVehicleData.clear();
}
int TClient::GetOpenCarID() {
int TClient::GetOpenCarID() const {
int OpenID = 0;
bool found;
do {
found = true;
for (auto& v : _VehicleData) {
for (auto& v : mVehicleData) {
if (v != nullptr && v->ID() == OpenID) {
OpenID++;
found = false;
@@ -33,15 +34,15 @@ int TClient::GetOpenCarID() {
}
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() {
return _VehicleData;
return mVehicleData;
}
std::string TClient::GetCarData(int Ident) {
for (auto& v : _VehicleData) {
for (auto& v : mVehicleData) {
if (v != nullptr && v->ID() == Ident) {
return v->Data();
}
@@ -51,7 +52,7 @@ std::string TClient::GetCarData(int Ident) {
}
void TClient::SetCarData(int Ident, const std::string& Data) {
for (auto& v : _VehicleData) {
for (auto& v : mVehicleData) {
if (v != nullptr && v->ID() == Ident) {
v->Data() = Data;
return;
@@ -59,6 +60,13 @@ void TClient::SetCarData(int Ident, const std::string& Data) {
}
DeleteCar(Ident);
}
int TClient::GetCarCount() {
return int(_VehicleData.size());
int TClient::GetCarCount() const {
return int(mVehicleData.size());
}
TServer& TClient::Server() const {
return mServer;
}
TClient::TClient(TServer& Server)
: mServer(Server) {
}

View File

@@ -1,5 +1,10 @@
#include "Common.h"
#include "TConsole.h"
#include <algorithm>
#include <array>
#include <iostream>
#include <zlib.h>
std::unique_ptr<TConsole> Application::mConsole = std::make_unique<TConsole>();
@@ -16,3 +21,46 @@ void Application::GracefullyShutdown() {
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;
}

View File

@@ -30,7 +30,7 @@ void TServer::RemoveClient(std::weak_ptr<TClient> WeakClientPtr) {
std::weak_ptr<TClient> TServer::InsertNewClient() {
debug("inserting new client (" + std::to_string(ClientCount()) + ")");
WriteLock Lock(mClientsMutex);
auto [Iter, Replaced] = mClients.insert(std::make_shared<TClient>());
auto [Iter, Replaced] = mClients.insert(std::make_shared<TClient>(*this));
return *Iter;
}

5
src/TTCPServer.cpp Normal file
View File

@@ -0,0 +1,5 @@
#include "TTCPServer.h"
TTCPServer::TTCPServer(TServer& Server)
: mServer(Server) {
}

224
src/TUDPServer.cpp Normal file
View 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);
}

View File

@@ -8,6 +8,7 @@
#include "TResourceManager.h"
#include "TServer.h"
#include "TPPSMonitor.h"
#include "TUDPServer.h"
#include <atomic>
#include <functional>
#include <iostream>
@@ -46,10 +47,12 @@ int main(int argc, char** argv) {
TServer Server(argc, argv);
[[maybe_unused]] TConfig Config("Server.cfg");
TLuaEngine LuaEngine(Server);
TResourceManager ResourceManager;
[[maybe_unused]] TPPSMonitor PPSMonitor(Server);
THeartbeatThread Heartbeat(ResourceManager, Server);
TTCPServer TCPServer(Server);
TUDPServer UDPServer(Server, PPSMonitor);
TLuaEngine LuaEngine(Server);
// TODO: replace
bool Shutdown = false;