mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-08-17 16:57:05 +00:00
switch udp networking to boost implementation
This commit is contained in:
parent
30482d290a
commit
6e97a3cd6e
@ -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
5
include/BoostAliases.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
|
using namespace boost::asio;
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user