FastEngine 0.9.4
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
C_server.hpp
1/*
2 * Copyright 2025 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _FGE_C_SERVER_HPP_INCLUDED
18#define _FGE_C_SERVER_HPP_INCLUDED
19
20#include "FastEngine/fge_extern.hpp"
21#include "C_socket.hpp"
22#include "FastEngine/network/C_clientList.hpp"
23#include "FastEngine/network/C_netCommand.hpp"
24#include "FastEngine/network/C_packet.hpp"
25#include "FastEngine/network/C_packetLZ4.hpp"
26#include "FastEngine/network/C_protocol.hpp"
27#include <condition_variable>
28#include <future>
29#include <memory>
30#include <mutex>
31#include <queue>
32#include <thread>
33
34#if defined(FGE_ENABLE_SERVER_NETWORK_RANDOM_LOST) || defined(FGE_ENABLE_CLIENT_NETWORK_RANDOM_LOST)
35 #include "FastEngine/C_random.hpp"
36#endif
37
38#define FGE_SERVER_DEFAULT_MAXPACKET 200
39#define FGE_SERVER_MAX_TIME_DIFFERENCE_REALM \
40 std::chrono::milliseconds \
41 { \
42 2000 \
43 }
44
45#define FGE_SERVER_PACKET_RECEPTION_TIMEOUT_MS 250
46
47namespace fge
48{
49using ObjectSid = uint32_t;
50} // namespace fge
51
52namespace fge::net
53{
54
57
58enum class FluxProcessResults
59{
60 USER_RETRIEVABLE,
61
62 INTERNALLY_HANDLED,
63 INTERNALLY_DISCARDED,
64
65 NONE_AVAILABLE
66};
67
68enum class ReturnEvents
69{
70 REVT_SIMPLE,
71 REVT_OBJECT,
72 REVT_ASK_FULL_UPDATE,
73 REVT_CUSTOM
74};
75
87class FGE_API NetFluxUdp
88{
89public:
90 NetFluxUdp() = default;
91 NetFluxUdp(NetFluxUdp const& r) = delete;
92 NetFluxUdp(NetFluxUdp&& r) noexcept = delete;
93 virtual ~NetFluxUdp();
94
95 NetFluxUdp& operator=(NetFluxUdp const& r) = delete;
96 NetFluxUdp& operator=(NetFluxUdp&& r) noexcept = delete;
97
98 void clearPackets();
99 [[nodiscard]] ReceivedPacketPtr popNextPacket();
100
101 [[nodiscard]] std::size_t getPacketsSize() const;
102 [[nodiscard]] bool isEmpty() const;
103
104 void setMaxPackets(std::size_t n);
105 [[nodiscard]] std::size_t getMaxPackets() const;
106
107protected:
108 bool pushPacket(ReceivedPacketPtr&& fluxPck);
109 void forcePushPacket(ReceivedPacketPtr fluxPck);
110 void forcePushPacketFront(ReceivedPacketPtr fluxPck);
111 [[nodiscard]] FluxProcessResults processReorder(Client& client,
112 ReceivedPacketPtr& packet,
113 ProtocolPacket::CounterType currentCounter,
114 bool ignoreRealm);
115
116 mutable std::mutex _g_mutexFlux;
117 std::deque<ReceivedPacketPtr> _g_packets;
118 std::size_t _g_remainingPackets{0};
119
120private:
121 std::size_t g_maxPackets = FGE_SERVER_DEFAULT_MAXPACKET;
122
123 friend class ServerSideNetUdp;
124};
125
126class FGE_API ServerNetFluxUdp : public NetFluxUdp
127{
128public:
129 explicit ServerNetFluxUdp(ServerSideNetUdp& server) :
130 NetFluxUdp(),
131 g_server(&server)
132 {}
133 ~ServerNetFluxUdp() override = default;
134
135 void processClients();
136 [[nodiscard]] FluxProcessResults
137 process(ClientSharedPtr& refClient, ReceivedPacketPtr& packet, bool allowUnknownClient);
138
139 void disconnectAllClients(std::chrono::milliseconds delay = std::chrono::milliseconds(0)) const;
140
141 ClientList _clients;
142
145
151
156 _onClientObjectReturnEvent;
158
159private:
160 [[nodiscard]] bool verifyRealm(ClientSharedPtr const& refClient, ReceivedPacketPtr const& packet);
161 [[nodiscard]] NetCommandResults
162 checkCommands(ClientSharedPtr const& refClient, CommandQueue& commands, ReceivedPacketPtr& packet);
163
164 [[nodiscard]] FluxProcessResults processUnknownClient(ClientSharedPtr& refClient, ReceivedPacketPtr& packet);
165 [[nodiscard]] FluxProcessResults processAcknowledgedClient(ClientList::Data& refClientData,
166 ReceivedPacketPtr& packet);
167 [[nodiscard]] FluxProcessResults processMTUDiscoveredClient(ClientList::Data& refClientData,
168 ReceivedPacketPtr& packet);
169
170 ServerSideNetUdp* g_server{nullptr};
171 std::chrono::milliseconds g_commandsUpdateTick{0};
172 std::chrono::steady_clock::time_point g_lastCommandUpdateTimePoint{std::chrono::steady_clock::now()};
173};
174
188class FGE_API ServerSideNetUdp
189{
190public:
191 explicit ServerSideNetUdp(IpAddress::Types addressType = IpAddress::Types::Ipv4);
192 ServerSideNetUdp(ServerSideNetUdp const& r) = delete;
193 ServerSideNetUdp(ServerSideNetUdp&& r) noexcept = delete;
194 ~ServerSideNetUdp();
195
196 ServerSideNetUdp& operator=(ServerSideNetUdp const& r) = delete;
197 ServerSideNetUdp& operator=(ServerSideNetUdp&& r) noexcept = delete;
198
199 void setVersioningString(std::string_view versioningString);
200 [[nodiscard]] std::string const& getVersioningString() const;
201
202 [[nodiscard]] bool
203 start(Port bindPort, IpAddress const& bindIp, IpAddress::Types addressType = IpAddress::Types::None);
204 [[nodiscard]] bool start(IpAddress::Types addressType = IpAddress::Types::None);
205 void stop();
206
222 [[nodiscard]] ServerNetFluxUdp* newFlux();
223
224 [[nodiscard]] ServerNetFluxUdp* getFlux(std::size_t index);
225 [[nodiscard]] ServerNetFluxUdp* getDefaultFlux();
226
227 [[nodiscard]] std::size_t getFluxSize() const;
228
229 [[nodiscard]] IpAddress::Types getAddressType() const;
230
231 void closeFlux(NetFluxUdp* flux);
232 void closeAllFlux();
233
234 void repushPacket(ReceivedPacketPtr&& packet);
235
244 [[nodiscard]] bool isRunning() const;
245
246 void notifyNewClient(Identity const& identity, ClientSharedPtr const& client);
247
248 void sendTo(TransmitPacketPtr& pck, Client const& client, Identity const& id);
249 void sendTo(TransmitPacketPtr& pck, Identity const& id);
250
251 [[nodiscard]] void* getCryptContext() const;
252
253private:
254 void threadReception();
255 void threadTransmission();
256
257 std::unique_ptr<std::thread> g_threadReception;
258 std::unique_ptr<std::thread> g_threadTransmission;
259
260 std::condition_variable g_transmissionNotifier;
261
262 mutable std::mutex g_mutexServer;
263
264 std::vector<std::unique_ptr<ServerNetFluxUdp>> g_fluxes;
265 ServerNetFluxUdp g_defaultFlux;
266 std::queue<std::pair<TransmitPacketPtr, Identity>> g_transmissionQueue;
267
268 std::unordered_map<Identity, std::weak_ptr<Client>, IdentityHash> g_clientsMap;
269
270 SocketUdp g_socket;
271 bool g_running;
272
273 void* g_crypt_ctx;
274
275 std::string g_versioningString;
276};
277
285class FGE_API ClientSideNetUdp : public NetFluxUdp
286{
287public:
288 explicit ClientSideNetUdp(IpAddress::Types addressType = IpAddress::Types::Ipv4);
289 ClientSideNetUdp(ClientSideNetUdp const& r) = delete;
290 ClientSideNetUdp(ClientSideNetUdp&& r) noexcept = delete;
291 ~ClientSideNetUdp() override;
292
293 ClientSideNetUdp& operator=(ClientSideNetUdp const& r) = delete;
294 ClientSideNetUdp& operator=(ClientSideNetUdp&& r) noexcept = delete;
295
296 [[nodiscard]] bool start(Port bindPort,
297 IpAddress const& bindIp,
298 Port connectRemotePort,
299 IpAddress const& connectRemoteAddress,
300 IpAddress::Types addressType = IpAddress::Types::None);
301 void stop();
302
303 void notifyTransmission();
304 [[nodiscard]] bool isRunning() const;
305
306 [[nodiscard]] std::future<uint16_t> retrieveMTU();
307 [[nodiscard]] std::future<bool> connect(std::string_view versioningString = std::string_view{});
308 [[nodiscard]] std::future<void> disconnect();
309
310 [[nodiscard]] IpAddress::Types getAddressType() const;
311
312 [[nodiscard]] std::size_t waitForPackets(std::chrono::milliseconds time_ms);
313
314 [[nodiscard]] Identity const& getClientIdentity() const;
315
316 template<class TPacket = Packet>
317 void sendTo(TransmitPacketPtr& pck, Identity const& id);
318
319 [[nodiscard]] FluxProcessResults process(ReceivedPacketPtr& packet);
320
321 void resetReturnPacket();
322 TransmitPacketPtr& startReturnEvent(ReturnEvents event);
323 TransmitPacketPtr& startObjectReturnEvent(uint16_t commandIndex, ObjectSid parentSid, ObjectSid targetSid);
324 void endReturnEvent();
325
326 void simpleReturnEvent(uint16_t id);
327 void askFullUpdateReturnEvent();
328
329 void enableReturnPacket(bool enable);
330 [[nodiscard]] bool isReturnPacketEnabled() const;
331
332 [[nodiscard]] TransmitPacketPtr prepareAndRetrieveReturnPacket();
333
334 Client _client; //But it is the server :O
335
336 CallbackHandler<ClientSideNetUdp&> _onClientTimeout;
337 CallbackHandler<ClientSideNetUdp&> _onClientDisconnected;
338
340
341private:
342 void threadReception();
343 void threadTransmission();
344
345 std::recursive_mutex g_mutexCommands;
346 CommandQueue g_commands;
347
348 std::unique_ptr<std::thread> g_threadReception;
349 std::unique_ptr<std::thread> g_threadTransmission;
350
351 std::condition_variable g_transmissionNotifier;
352 std::condition_variable g_receptionNotifier;
353
354 SocketUdp g_socket;
355 bool g_running{false};
356
357 Identity g_clientIdentity;
358
359 PacketDefragmentation g_defragmentation;
360
361 bool g_returnPacketEnabled{false};
362 TransmitPacketPtr g_returnPacket;
363 bool g_returnPacketEventStarted{false};
364 std::size_t g_returnPacketStartPosition{0};
365 bool g_isAskingFullUpdate{false};
366 uint16_t g_returnPacketEventCount{0};
367 std::chrono::steady_clock::time_point g_returnPacketTimePoint;
368
369 void* g_crypt_ctx{nullptr};
370};
371
372} // namespace fge::net
373
374#include "C_server.inl"
375
376#endif // _FGE_C_SERVER_HPP_INCLUDED
This class is used to handle callbacks in a safe way.
Definition C_callback.hpp:189
A list of clients used by a server.
Definition C_clientList.hpp:60
A client side network manager.
Definition C_server.hpp:286
void sendTo(TransmitPacketPtr &pck, Identity const &id)
Definition C_server.inl:23
Class that represent the identity of a client.
Definition C_client.hpp:220
A class to represent an IP address.
Definition C_ipAddress.hpp:57
A network flux.
Definition C_server.hpp:88
Definition C_protocol.hpp:287
Definition C_server.hpp:127
A server side network manager.
Definition C_server.hpp:189
void notifyTransmission()
Notify the transmission thread.
ServerNetFluxUdp * newFlux()
Create a new flux.
A wrapper for UDP sockets inheriting from Socket.
Definition C_socket.hpp:348
Definition C_clientList.hpp:63
A class to hash an Identity (useful for std::unordered_map or other containers)
Definition C_identity.hpp:52
A class to represent a client or server identity with an IP address and a port.
Definition C_identity.hpp:31