switch udp networking to boost implementation

This commit is contained in:
Lion Kortlepel 2022-10-05 12:14:25 +02:00
parent 30482d290a
commit 6e97a3cd6e
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
5 changed files with 41 additions and 57 deletions

View File

@ -119,6 +119,7 @@ set(BeamMP_Sources
include/ArgsParser.h src/ArgsParser.cpp include/ArgsParser.h src/ArgsParser.cpp
include/TPluginMonitor.h src/TPluginMonitor.cpp include/TPluginMonitor.h src/TPluginMonitor.cpp
include/Environment.h include/Environment.h
include/BoostAliases.h
) )
set(BeamMP_Includes set(BeamMP_Includes

5
include/BoostAliases.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <boost/asio.hpp>
using namespace boost::asio;

View File

@ -7,6 +7,7 @@
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
#include "BoostAliases.h"
#include "Common.h" #include "Common.h"
#include "Compat.h" #include "Compat.h"
#include "VehicleData.h" #include "VehicleData.h"
@ -46,14 +47,15 @@ public:
void SetIdentifier(const std::string& key, const std::string& value) { mIdentifiers[key] = value; } void SetIdentifier(const std::string& key, const std::string& value) { mIdentifiers[key] = value; }
std::string GetCarData(int Ident); std::string GetCarData(int Ident);
std::string GetCarPositionRaw(int Ident); std::string GetCarPositionRaw(int Ident);
void SetUDPAddr(sockaddr_in Addr) { mUDPAddress = Addr; } void SetUDPAddr(const ip::udp::endpoint& Addr) { mUDPAddress = Addr; }
void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; } void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; }
void SetTCPSock(SOCKET CSock) { mSocket[0] = CSock; } void SetTCPSock(SOCKET CSock) { mSocket[0] = CSock; }
void SetStatus(int Status) { mStatus = Status; } void SetStatus(int Status) { mStatus = Status; }
// locks // locks
void DeleteCar(int Ident); void DeleteCar(int Ident);
[[nodiscard]] const std::unordered_map<std::string, std::string>& GetIdentifiers() const { return mIdentifiers; } [[nodiscard]] const std::unordered_map<std::string, std::string>& GetIdentifiers() const { return mIdentifiers; }
[[nodiscard]] sockaddr_in GetUDPAddr() const { return mUDPAddress; } [[nodiscard]] const ip::udp::endpoint& GetUDPAddr() const { return mUDPAddress; }
[[nodiscard]] ip::udp::endpoint& GetUDPAddr() { return mUDPAddress; }
[[nodiscard]] SOCKET GetDownSock() const { return mSocket[1]; } [[nodiscard]] SOCKET GetDownSock() const { return mSocket[1]; }
[[nodiscard]] SOCKET GetTCPSock() const { return mSocket[0]; } [[nodiscard]] SOCKET GetTCPSock() const { return mSocket[0]; }
[[nodiscard]] std::string GetRoles() const { return mRole; } [[nodiscard]] std::string GetRoles() const { return mRole; }
@ -100,7 +102,7 @@ private:
SparseArray<std::string> mVehiclePosition; SparseArray<std::string> mVehiclePosition;
std::string mName = "Unknown Client"; std::string mName = "Unknown Client";
SOCKET mSocket[2] { SOCKET(0), SOCKET(0) }; SOCKET mSocket[2] { SOCKET(0), SOCKET(0) };
sockaddr_in mUDPAddress {}; // is this initialization OK? yes it is ip::udp::endpoint mUDPAddress {};
int mUnicycleID = -1; int mUnicycleID = -1;
std::string mRole; std::string mRole;
std::string mDID; std::string mDID;

View File

@ -1,8 +1,11 @@
#pragma once #pragma once
#include "BoostAliases.h"
#include "Compat.h" #include "Compat.h"
#include "TResourceManager.h" #include "TResourceManager.h"
#include "TServer.h" #include "TServer.h"
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/udp.hpp>
struct TConnection; struct TConnection;
@ -21,7 +24,7 @@ public:
void Authentication(const TConnection& ClientConnection); void Authentication(const TConnection& ClientConnection);
[[nodiscard]] bool CheckBytes(TClient& c, int32_t BytesRcv); [[nodiscard]] bool CheckBytes(TClient& c, int32_t BytesRcv);
void SyncResources(TClient& c); void SyncResources(TClient& c);
[[nodiscard]] bool UDPSend(TClient& Client, std::string Data) const; [[nodiscard]] bool UDPSend(TClient& Client, std::string Data);
void SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel); void SendToAll(TClient* c, const std::string& Data, bool Self, bool Rel);
void UpdatePlayer(TClient& Client); void UpdatePlayer(TClient& Client);
@ -31,12 +34,13 @@ private:
TServer& mServer; TServer& mServer;
TPPSMonitor& mPPSMonitor; TPPSMonitor& mPPSMonitor;
SOCKET mUDPSock {}; io_context mIoCtx;
ip::udp::socket mUDPSock;
TResourceManager& mResourceManager; TResourceManager& mResourceManager;
std::thread mUDPThread; std::thread mUDPThread;
std::thread mTCPThread; std::thread mTCPThread;
std::string UDPRcvFromClient(sockaddr_in& client) const; std::string UDPRcvFromClient(ip::udp::endpoint& ClientEndpoint);
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);

View File

@ -5,11 +5,15 @@
#include <CustomAssert.h> #include <CustomAssert.h>
#include <Http.h> #include <Http.h>
#include <array> #include <array>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/system/detail/error_code.hpp>
#include <cstring> #include <cstring>
TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager) TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager)
: mServer(Server) : mServer(Server)
, mPPSMonitor(PPSMonitor) , mPPSMonitor(PPSMonitor)
, mIoCtx {}
, mUDPSock(mIoCtx)
, mResourceManager(ResourceManager) { , mResourceManager(ResourceManager) {
Application::SetSubsystemStatus("TCPNetwork", Application::Status::Starting); Application::SetSubsystemStatus("TCPNetwork", Application::Status::Starting);
Application::SetSubsystemStatus("UDPNetwork", Application::Status::Starting); Application::SetSubsystemStatus("UDPNetwork", Application::Status::Starting);
@ -42,40 +46,25 @@ TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& R
void TNetwork::UDPServerMain() { void TNetwork::UDPServerMain() {
RegisterThread("UDPServer"); RegisterThread("UDPServer");
#if defined(BEAMMP_WINDOWS) mUDPSock = ip::udp::socket(mIoCtx);
WSADATA data; ip::udp::endpoint UdpListenEndpoint(ip::udp::v4(), Application::Settings.Port);
if (WSAStartup(514, &data)) { boost::system::error_code ec;
beammp_error(("Can't start Winsock!")); mUDPSock.bind(UdpListenEndpoint, ec);
// return; if (ec) {
}
#endif // WINDOWS
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, reinterpret_cast<struct sockaddr*>(&serverAddr), sizeof(serverAddr)) != 0) {
beammp_error("bind() failed: " + GetPlatformAgnosticErrorString()); beammp_error("bind() failed: " + GetPlatformAgnosticErrorString());
std::this_thread::sleep_for(std::chrono::seconds(5)); std::this_thread::sleep_for(std::chrono::seconds(5));
exit(-1); // TODO: Wtf. Application::GracefullyShutdown();
// return;
} }
Application::SetSubsystemStatus("UDPNetwork", Application::Status::Good); Application::SetSubsystemStatus("UDPNetwork", Application::Status::Good);
beammp_info(("Vehicle data network online on port ") + std::to_string(Application::Settings.Port) + (" with a Max of ") beammp_info(("Vehicle data network online on port ") + std::to_string(Application::Settings.Port) + (" with a Max of ")
+ std::to_string(Application::Settings.MaxPlayers) + (" Clients")); + std::to_string(Application::Settings.MaxPlayers) + (" Clients"));
while (!Application::IsShuttingDown()) { while (!Application::IsShuttingDown()) {
try { try {
sockaddr_in client {}; ip::udp::endpoint client {};
std::string Data = UDPRcvFromClient(client); // Receives any data from Socket std::string Data = UDPRcvFromClient(client); // Receives any data from Socket
size_t Pos = Data.find(':'); size_t Pos = Data.find(':');
if (Data.empty() || Pos > 2) if (Data.empty() || Pos > 2)
continue; 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; uint8_t ID = uint8_t(Data.at(0)) - 1;
mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool { mServer.ForEachClient([&](std::weak_ptr<TClient> ClientPtr) -> bool {
std::shared_ptr<TClient> Client; std::shared_ptr<TClient> Client;
@ -995,7 +984,7 @@ void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Re
return; return;
} }
bool TNetwork::UDPSend(TClient& Client, std::string Data) const { bool TNetwork::UDPSend(TClient& Client, std::string Data) {
if (!Client.IsConnected() || Client.GetStatus() < 0) { if (!Client.IsConnected() || Client.GetStatus() < 0) {
// this can happen if we try to send a packet to a client that is either // this can happen if we try to send a packet to a client that is either
// 1. not yet fully connected, or // 1. not yet fully connected, or
@ -1003,28 +992,15 @@ bool TNetwork::UDPSend(TClient& Client, std::string Data) const {
// this is fine can can be ignored :^) // this is fine can can be ignored :^)
return true; return true;
} }
sockaddr_in Addr = Client.GetUDPAddr(); const auto Addr = Client.GetUDPAddr();
auto AddrSize = sizeof(Client.GetUDPAddr());
if (Data.length() > 400) { if (Data.length() > 400) {
std::string CMP(Comp(Data)); std::string CMP(Comp(Data));
Data = "ABG:" + CMP; Data = "ABG:" + CMP;
} }
#ifdef WIN32 boost::system::error_code ec;
int sendOk; mUDPSock.send_to(buffer(Data), Addr, 0, ec);
int len = static_cast<int>(Data.size()); if (ec) {
#else beammp_debugf("UDP sendto() failed: {}", ec.what());
int64_t sendOk;
size_t len = Data.size();
#endif // WIN32
sendOk = sendto(mUDPSock, Data.c_str(), len, 0, reinterpret_cast<struct sockaddr*>(&Addr), int(AddrSize));
if (sendOk == -1) {
beammp_debug("(UDP) sendto() failed: " + GetPlatformAgnosticErrorString());
if (Client.GetStatus() > -1)
Client.SetStatus(-1);
return false;
} else if (sendOk == 0) {
beammp_debug(("(UDP) sendto() returned 0"));
if (Client.GetStatus() > -1) if (Client.GetStatus() > -1)
Client.SetStatus(-1); Client.SetStatus(-1);
return false; return false;
@ -1032,18 +1008,14 @@ bool TNetwork::UDPSend(TClient& Client, std::string Data) const {
return true; return true;
} }
std::string TNetwork::UDPRcvFromClient(sockaddr_in& client) const { std::string TNetwork::UDPRcvFromClient(ip::udp::endpoint& ClientEndpoint) {
size_t clientLength = sizeof(client);
std::array<char, 1024> Ret {}; std::array<char, 1024> Ret {};
#ifdef WIN32 boost::system::error_code ec;
auto Rcv = recvfrom(mUDPSock, Ret.data(), int(Ret.size()), 0, (sockaddr*)&client, (int*)&clientLength); const auto Rcv = mUDPSock.receive_from(mutable_buffer(Ret.data(), Ret.size()), ClientEndpoint, 0, ec);
#else // unix if (ec) {
int64_t Rcv = recvfrom(mUDPSock, Ret.data(), Ret.size(), 0, reinterpret_cast<struct sockaddr*>(&client), reinterpret_cast<socklen_t*>(&clientLength)); beammp_errorf("UDP recvfrom() failed: {}", ec.what());
#endif // WIN32
if (Rcv == -1) {
beammp_error("(UDP) Error receiving from client! recvfrom() failed: " + GetPlatformAgnosticErrorString());
return ""; return "";
} }
// FIXME: This breaks binary data due to \0.
return std::string(Ret.begin(), Ret.begin() + Rcv); return std::string(Ret.begin(), Ret.begin() + Rcv);
} }