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

View File

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

View File

@ -5,11 +5,15 @@
#include <CustomAssert.h>
#include <Http.h>
#include <array>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/system/detail/error_code.hpp>
#include <cstring>
TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager)
: mServer(Server)
, mPPSMonitor(PPSMonitor)
, mIoCtx {}
, mUDPSock(mIoCtx)
, mResourceManager(ResourceManager) {
Application::SetSubsystemStatus("TCPNetwork", Application::Status::Starting);
Application::SetSubsystemStatus("UDPNetwork", Application::Status::Starting);
@ -42,40 +46,25 @@ TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& R
void TNetwork::UDPServerMain() {
RegisterThread("UDPServer");
#if defined(BEAMMP_WINDOWS)
WSADATA data;
if (WSAStartup(514, &data)) {
beammp_error(("Can't start Winsock!"));
// return;
}
#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) {
mUDPSock = ip::udp::socket(mIoCtx);
ip::udp::endpoint UdpListenEndpoint(ip::udp::v4(), Application::Settings.Port);
boost::system::error_code ec;
mUDPSock.bind(UdpListenEndpoint, ec);
if (ec) {
beammp_error("bind() failed: " + GetPlatformAgnosticErrorString());
std::this_thread::sleep_for(std::chrono::seconds(5));
exit(-1); // TODO: Wtf.
// return;
Application::GracefullyShutdown();
}
Application::SetSubsystemStatus("UDPNetwork", Application::Status::Good);
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"));
while (!Application::IsShuttingDown()) {
try {
sockaddr_in client {};
ip::udp::endpoint 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 {
std::shared_ptr<TClient> Client;
@ -995,7 +984,7 @@ void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Re
return;
}
bool TNetwork::UDPSend(TClient& Client, std::string Data) const {
bool TNetwork::UDPSend(TClient& Client, std::string Data) {
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
@ -1003,28 +992,15 @@ bool TNetwork::UDPSend(TClient& Client, std::string Data) const {
// this is fine can can be ignored :^)
return true;
}
sockaddr_in Addr = Client.GetUDPAddr();
auto AddrSize = sizeof(Client.GetUDPAddr());
const auto Addr = 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, 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"));
boost::system::error_code ec;
mUDPSock.send_to(buffer(Data), Addr, 0, ec);
if (ec) {
beammp_debugf("UDP sendto() failed: {}", ec.what());
if (Client.GetStatus() > -1)
Client.SetStatus(-1);
return false;
@ -1032,18 +1008,14 @@ bool TNetwork::UDPSend(TClient& Client, std::string Data) const {
return true;
}
std::string TNetwork::UDPRcvFromClient(sockaddr_in& client) const {
size_t clientLength = sizeof(client);
std::string TNetwork::UDPRcvFromClient(ip::udp::endpoint& ClientEndpoint) {
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, reinterpret_cast<struct sockaddr*>(&client), reinterpret_cast<socklen_t*>(&clientLength));
#endif // WIN32
if (Rcv == -1) {
beammp_error("(UDP) Error receiving from client! recvfrom() failed: " + GetPlatformAgnosticErrorString());
boost::system::error_code ec;
const auto Rcv = mUDPSock.receive_from(mutable_buffer(Ret.data(), Ret.size()), ClientEndpoint, 0, ec);
if (ec) {
beammp_errorf("UDP recvfrom() failed: {}", ec.what());
return "";
}
// FIXME: This breaks binary data due to \0.
return std::string(Ret.begin(), Ret.begin() + Rcv);
}