r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
AsioServer.hpp
Go to the documentation of this file.
1///
2/// @file AsioServer.hpp
3/// @brief This file contains the server network implementation for Asio
4/// @namespace srv
5///
6
7#pragma once
8
9#include <functional>
10#include <string>
11#include <thread>
12#include <unordered_map>
13#include <vector>
14
15#define ASIO_STANDALONE
16#include "asio.hpp"
17
20
21namespace srv
22{
23
24 ///
25 /// @class AsioServer
26 /// @brief Network implementation with asio for server
27 /// @namespace srv
28 ///
29 class AsioServer final : public INetworkServer
30 {
31 public:
32 using PacketHandler = std::function<void(const asio::ip::udp::endpoint &, const rnp::PacketHeader &,
33 const std::vector<uint8_t> &)>;
34 using ClientInfo = struct
35 {
36 asio::ip::udp::endpoint endpoint;
37 std::string playerName;
38 uint32_t lastSequence;
39 bool connected;
40 std::uint16_t playerId;
41 std::uint32_t sessionId;
42 std::uint32_t clientCaps;
43 };
44
45 AsioServer();
46 ~AsioServer() override;
47
48 AsioServer(const AsioServer &) = delete;
49 AsioServer(AsioServer &&) = delete;
50 AsioServer &operator=(const AsioServer &) = delete;
52
53 void init(const std::string &host, uint16_t port) override;
54 [[nodiscard]] const std::string getName() const override { return "Network_Asio_Server"; }
55 [[nodiscard]] utl::PluginType getType() const override { return utl::PluginType::NETWORK_SERVER; }
56
57 void start() override;
58 void stop() override;
59
60 void sendConnectAccept(const asio::ip::udp::endpoint &client, std::uint32_t sessionId);
61 void sendWorldState(const asio::ip::udp::endpoint &client, std::uint32_t serverTick,
62 const std::vector<rnp::EntityState> &entities);
63 void sendWorldState(const asio::ip::udp::endpoint &client, const std::vector<uint8_t> &worldData);
64 void sendEntityEvent(const asio::ip::udp::endpoint &client, std::uint32_t serverTick,
65 const std::vector<rnp::EventRecord> &events);
66 void sendEvents(const asio::ip::udp::endpoint &client, const std::vector<rnp::EventRecord> &events);
67 void sendPong(const asio::ip::udp::endpoint &client, std::uint32_t nonce, std::uint32_t sendTimeMs);
68 void sendPong(const asio::ip::udp::endpoint &client);
69 void sendError(const asio::ip::udp::endpoint &client, rnp::ErrorCode errorCode,
70 const std::string &errorMessage);
71 void sendError(const asio::ip::udp::endpoint &client, const std::string &errorMessage);
72 void sendAck(const asio::ip::udp::endpoint &client, std::uint32_t cumulative, std::uint32_t ackBits);
73 void broadcastToAll(const std::vector<uint8_t> &data);
74 void broadcastEntityEvents(std::uint32_t serverTick, const std::vector<rnp::EventRecord> &events);
75 void broadcastEvents(const std::vector<rnp::EventRecord> &events);
76
78 void setTickRate(std::uint16_t tickRate) { m_tickRateHz = tickRate; }
79 void setServerCapabilities(std::uint32_t caps) { m_serverCaps = caps; }
80
81 const std::unordered_map<asio::ip::udp::endpoint, ClientInfo> &getClients() const { return m_clients; }
82
83 private:
84 void startReceive();
85 void handleReceive(const asio::error_code &error, std::size_t bytesTransferred);
86 void handleSend(const asio::error_code &error, std::size_t bytesTransferred);
87 void processPacket(const asio::ip::udp::endpoint &sender, const std::vector<uint8_t> &data);
88 void addClient(const asio::ip::udp::endpoint &endpoint, const std::string &playerName,
89 std::uint32_t clientCaps, std::uint32_t sessionId);
90 void removeClient(const asio::ip::udp::endpoint &endpoint);
91 std::uint16_t getPlayerId(const asio::ip::udp::endpoint &endpoint) const;
92 std::uint32_t getSessionId(const asio::ip::udp::endpoint &endpoint) const;
93 void handleReliablePacket(const asio::ip::udp::endpoint &sender, const rnp::PacketHeader &header);
94 void processAck(const asio::ip::udp::endpoint &sender, const std::vector<uint8_t> &payload);
95 void retransmitReliable();
96
97 asio::io_context m_ioContext;
98 asio::ip::udp::socket m_socket;
99 asio::ip::udp::endpoint m_remoteEndpoint;
100 std::array<uint8_t, rnp::MAX_PAYLOAD + 16> m_recvBuffer;
101
102 std::unique_ptr<asio::executor_work_guard<asio::io_context::executor_type>> m_workGuard;
103 std::thread m_ioThread;
104 std::unordered_map<asio::ip::udp::endpoint, ClientInfo> m_clients;
105 std::unordered_map<rnp::PacketType, PacketHandler> m_packetHandlers;
106 uint32_t m_sequenceNumber = 0;
107 std::uint16_t m_nextPlayerId = 1;
108 std::uint32_t m_nextSessionId = 1;
109 std::uint16_t m_tickRateHz = 60;
110 std::uint16_t m_mtuPayloadBytes = 508;
111 std::uint32_t m_serverCaps = 0;
112 std::unordered_map<std::uint32_t, std::vector<uint8_t>> m_pendingReliable;
113 std::unordered_map<asio::ip::udp::endpoint, std::uint32_t> m_clientLastAck;
114 }; // class AsioServer
115} // namespace srv
This file contains the server network interface.
This file contains the network protocol.
Network implementation with asio for server.
void sendError(const asio::ip::udp::endpoint &client, rnp::ErrorCode errorCode, const std::string &errorMessage)
const std::unordered_map< asio::ip::udp::endpoint, ClientInfo > & getClients() const
std::unordered_map< std::uint32_t, std::vector< uint8_t > > m_pendingReliable
std::uint16_t m_mtuPayloadBytes
std::unordered_map< asio::ip::udp::endpoint, std::uint32_t > m_clientLastAck
void processAck(const asio::ip::udp::endpoint &sender, const std::vector< uint8_t > &payload)
~AsioServer() override
AsioServer(const AsioServer &)=delete
std::unique_ptr< asio::executor_work_guard< asio::io_context::executor_type > > m_workGuard
void handleReliablePacket(const asio::ip::udp::endpoint &sender, const rnp::PacketHeader &header)
void sendEvents(const asio::ip::udp::endpoint &client, const std::vector< rnp::EventRecord > &events)
std::function< void(const asio::ip::udp::endpoint &, const rnp::PacketHeader &, const std::vector< uint8_t > &)> PacketHandler
AsioServer(AsioServer &&)=delete
asio::ip::udp::socket m_socket
void setPacketHandler(rnp::PacketType type, PacketHandler handler)
void broadcastEntityEvents(std::uint32_t serverTick, const std::vector< rnp::EventRecord > &events)
void handleReceive(const asio::error_code &error, std::size_t bytesTransferred)
void sendPong(const asio::ip::udp::endpoint &client, std::uint32_t nonce, std::uint32_t sendTimeMs)
struct { asio::ip::udp::endpoint endpoint; std::string playerName; uint32_t lastSequence; bool connected; std::uint16_t playerId; std::uint32_t sessionId; std::uint32_t clientCaps; } ClientInfo
void broadcastEvents(const std::vector< rnp::EventRecord > &events)
void sendConnectAccept(const asio::ip::udp::endpoint &client, std::uint32_t sessionId)
std::array< uint8_t, rnp::MAX_PAYLOAD+16 > m_recvBuffer
std::uint32_t m_serverCaps
std::uint32_t m_nextSessionId
void removeClient(const asio::ip::udp::endpoint &endpoint)
void processPacket(const asio::ip::udp::endpoint &sender, const std::vector< uint8_t > &data)
void handleSend(const asio::error_code &error, std::size_t bytesTransferred)
void init(const std::string &host, uint16_t port) override
void setServerCapabilities(std::uint32_t caps)
AsioServer & operator=(const AsioServer &)=delete
std::uint32_t getSessionId(const asio::ip::udp::endpoint &endpoint) const
void broadcastToAll(const std::vector< uint8_t > &data)
std::unordered_map< rnp::PacketType, PacketHandler > m_packetHandlers
std::uint16_t getPlayerId(const asio::ip::udp::endpoint &endpoint) const
std::uint16_t m_tickRateHz
utl::PluginType getType() const override
void setTickRate(std::uint16_t tickRate)
void addClient(const asio::ip::udp::endpoint &endpoint, const std::string &playerName, std::uint32_t clientCaps, std::uint32_t sessionId)
void start() override
std::uint16_t m_nextPlayerId
uint32_t m_sequenceNumber
asio::io_context m_ioContext
void sendAck(const asio::ip::udp::endpoint &client, std::uint32_t cumulative, std::uint32_t ackBits)
const std::string getName() const override
asio::ip::udp::endpoint m_remoteEndpoint
void sendEntityEvent(const asio::ip::udp::endpoint &client, std::uint32_t serverTick, const std::vector< rnp::EventRecord > &events)
std::thread m_ioThread
void sendWorldState(const asio::ip::udp::endpoint &client, std::uint32_t serverTick, const std::vector< rnp::EntityState > &entities)
AsioServer & operator=(AsioServer &&)=delete
std::unordered_map< asio::ip::udp::endpoint, ClientInfo > m_clients
void stop() override
void retransmitReliable()
Interface for the server network.
ErrorCode
Error codes.
Definition Protocol.hpp:67
PacketType
Packet types according to RNP specification.
Definition Protocol.hpp:24
PluginType
Definition IPlugin.hpp:15
Packet header according to RNP specification (Big Endian) Total size: 16 bytes.
Definition Protocol.hpp:115