Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
NetClient.h
Go to the documentation of this file.
1/* Copyright (C) 2024 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef NETCLIENT_H
19#define NETCLIENT_H
20
21#include "network/FSM.h"
23#include "network/NetHost.h"
25
26#include "ps/CStr.h"
27
28#include <ctime>
29#include <deque>
30#include <thread>
31
32class CGame;
35class ScriptInterface;
36
37typedef struct _ENetHost ENetHost;
38
39// NetClient session FSM states
40enum
41{
50};
51
52/**
53 * Network client.
54 * This code is run by every player (including the host, if they are not
55 * a dedicated server).
56 * It provides an interface between the GUI, the network (via CNetClientSession),
57 * and the game (via CGame and CNetClientTurnManager).
58 */
59class CNetClient : public CFsm<CNetClient>
60{
62
63public:
64 /**
65 * Construct a client associated with the given game object.
66 * The game must exist for the lifetime of this object.
67 */
68 CNetClient(CGame* game);
69
70 virtual ~CNetClient();
71
72 /**
73 * We assume that adding a tracing function that's only called
74 * during GC is better for performance than using a
75 * PersistentRooted<T> where each value needs to be added to
76 * the root set.
77 */
78 static void Trace(JSTracer *trc, void *data)
79 {
80 reinterpret_cast<CNetClient*>(data)->TraceMember(trc);
81 }
82
83 void TraceMember(JSTracer *trc);
84
85 /**
86 * Set the user's name that will be displayed to all players.
87 * This must not be called after the connection setup.
88 */
89 void SetUserName(const CStrW& username);
90
91 /**
92 * Store the JID of the host.
93 * This is needed for the secure lobby authentication.
94 */
95 void SetHostJID(const CStr& jid);
96
97 void SetControllerSecret(const std::string& secret);
98
99 bool IsController() const { return m_IsController; }
100
101 /**
102 * Set the game password.
103 * Must be called after SetUserName, as that is used to hash further.
104 */
105 void SetGamePassword(const CStr& hashedPassword);
106
107 /**
108 * Returns the GUID of the local client.
109 * Used for distinguishing observers.
110 */
111 CStr GetGUID() const { return m_GUID; }
112
113 /**
114 * Set connection data to the remote networked server.
115 * @param address IP address or host name to connect to
116 */
117 void SetupServerData(CStr address, u16 port, bool stun);
118
119 /**
120 * Set up a connection to the remote networked server.
121 * Must call SetupServerData first.
122 * @return true on success, false on connection failure
123 */
124 bool SetupConnection(ENetHost* enetClient);
125
126 /**
127 * Request connection information over the lobby.
128 */
130
131 /**
132 * Connect to the remote networked server using lobby.
133 * Push netstatus messages on failure.
134 * @param localNetwork - if true, assume we are trying to connect on the local network.
135 * @return true on success, false on connection failure
136 */
137 bool TryToConnect(const CStr& hostJID, bool localNetwork);
138
139 /**
140 * Destroy the connection to the server.
141 * This client probably cannot be used again.
142 */
143 void DestroyConnection();
144
145 /**
146 * Poll the connection for messages from the server and process them, and send
147 * any queued messages.
148 * This must be called frequently (i.e. once per frame).
149 */
150 void Poll();
151
152 /**
153 * Locally triggers a GUI message if the connection to the server is being lost or has bad latency.
154 */
156
157 /**
158 * Retrieves the next queued GUI message, and removes it from the queue.
159 * The returned value is in the GetScriptInterface() JS context.
160 *
161 * This is the only mechanism for the networking code to send messages to
162 * the GUI - it is pull-based (instead of push) so the engine code does not
163 * need to know anything about the code structure of the GUI scripts.
164 *
165 * The structure of the messages is <code>{ "type": "...", ... }</code>.
166 * The exact types and associated data are not specified anywhere - the
167 * implementation and GUI scripts must make the same assumptions.
168 *
169 * @return next message, or the value 'undefined' if the queue is empty
170 */
171 void GuiPoll(JS::MutableHandleValue);
172
173 /**
174 * Add a message to the queue, to be read by GuiPoll.
175 * The script value must be in the GetScriptInterface() JS context.
176 */
177 template<typename... Args>
178 void PushGuiMessage(Args const&... args)
179 {
181
182 JS::RootedValue message(rq.cx);
183 Script::CreateObject(rq, &message, args...);
184 m_GuiMessageQueue.push_back(JS::Heap<JS::Value>(message));
185 }
186
187 /**
188 * Return a concatenation of all messages in the GUI queue,
189 * for test cases to easily verify the queue contents.
190 */
191 std::string TestReadGuiMessages();
192
193 /**
194 * Get the script interface associated with this network client,
195 * which is equivalent to the one used by the CGame in the constructor.
196 */
198
199 /**
200 * Send a message to the server.
201 * @param message message to send
202 * @return true on success
203 */
204 bool SendMessage(const CNetMessage* message);
205
206 /**
207 * Call when the network connection has been successfully initiated.
208 */
209 void HandleConnect();
210
211 /**
212 * Call when the network connection has been lost.
213 */
214 void HandleDisconnect(u32 reason);
215
216 /**
217 * Call when a message has been received from the network.
218 */
219 bool HandleMessage(CNetMessage* message);
220
221 /**
222 * Call when the game has started and all data files have been loaded,
223 * to signal to the server that we are ready to begin the game.
224 */
225 void LoadFinished();
226
227 void SendGameSetupMessage(JS::MutableHandleValue attrs, const ScriptInterface& scriptInterface);
228
229 void SendAssignPlayerMessage(const int playerID, const CStr& guid);
230
231 void SendChatMessage(const std::wstring& text);
232
233 void SendReadyMessage(const int status);
234
236
237 void SendStartGameMessage(const CStr& initAttribs);
238
239 /**
240 * Call when the client has rejoined a running match and finished
241 * the loading screen.
242 */
243 void SendRejoinedMessage();
244
245 /**
246 * Call to kick/ban a client
247 */
248 void SendKickPlayerMessage(const CStrW& playerName, bool ban);
249
250 /**
251 * Call when the client has paused or unpaused the game.
252 */
253 void SendPausedMessage(bool pause);
254
255 /**
256 * @return Whether the NetClient is shutting down.
257 */
258 bool ShouldShutdown() const;
259
260 /**
261 * Called when fetching connection data from the host failed, to inform JS code.
262 */
263 void HandleGetServerDataFailed(const CStr& error);
264private:
265
267
268 // Net message / FSM transition handlers
269 static bool OnConnect(CNetClient* client, CFsmEvent* event);
270 static bool OnHandshake(CNetClient* client, CFsmEvent* event);
271 static bool OnHandshakeResponse(CNetClient* client, CFsmEvent* event);
272 static bool OnAuthenticateRequest(CNetClient* client, CFsmEvent* event);
273 static bool OnAuthenticate(CNetClient* client, CFsmEvent* event);
274 static bool OnChat(CNetClient* client, CFsmEvent* event);
275 static bool OnReady(CNetClient* client, CFsmEvent* event);
276 static bool OnGameSetup(CNetClient* client, CFsmEvent* event);
277 static bool OnPlayerAssignment(CNetClient* client, CFsmEvent* event);
278 static bool OnInGame(CNetClient* client, CFsmEvent* event);
279 static bool OnGameStart(CNetClient* client, CFsmEvent* event);
280 static bool OnJoinSyncStart(CNetClient* client, CFsmEvent* event);
281 static bool OnJoinSyncEndCommandBatch(CNetClient* client, CFsmEvent* event);
282 static bool OnRejoined(CNetClient* client, CFsmEvent* event);
283 static bool OnKicked(CNetClient* client, CFsmEvent* event);
284 static bool OnClientTimeout(CNetClient* client, CFsmEvent* event);
285 static bool OnClientPerformance(CNetClient* client, CFsmEvent* event);
286 static bool OnClientsLoading(CNetClient* client, CFsmEvent* event);
287 static bool OnClientPaused(CNetClient* client, CFsmEvent* event);
288 static bool OnLoadedGame(CNetClient* client, CFsmEvent* event);
289
290 /**
291 * Take ownership of a session object, and use it for all network communication.
292 */
293 void SetAndOwnSession(CNetClientSession* session);
294
295 /**
296 * Push a message onto the GUI queue listing the current player assignments.
297 */
299
302
307
308 /**
309 * Password to join the game.
310 */
312
313 /// The 'secret' used to identify the controller of the game.
315
316 /// Note that this is just a "gui hint" with no actual impact on being controller.
317 bool m_IsController = false;
318
319 /// Current network session (or NULL if not connected)
321
322 std::thread m_PollingThread;
323
324 /// Turn manager associated with the current game (or NULL if we haven't started the game yet)
326
327 /// Unique-per-game identifier of this client, used to identify the sender of simulation commands
329
330 /// True if the player is currently rejoining or has already rejoined the game.
332
333 /// Latest copy of player assignments heard from the server
335
336 /// Globally unique identifier to distinguish users beyond the lifetime of a single network session
337 CStr m_GUID;
338
339 /// Queue of messages for GuiPoll
340 std::deque<JS::Heap<JS::Value>> m_GuiMessageQueue;
341
342 /// Serialized game state received when joining an in-progress game
343 std::string m_JoinSyncBuffer;
344
345 /// Time when the server was last checked for timeouts and bad latency
347};
348
349/// Global network client for the standard game
350extern CNetClient *g_NetClient;
351
352#endif // NETCLIENT_H
struct _ENetHost ENetHost
Definition: NetClient.h:37
@ NCS_UNCONNECTED
Definition: NetClient.h:42
@ NCS_PREGAME
Definition: NetClient.h:46
@ NCS_JOIN_SYNCING
Definition: NetClient.h:48
@ NCS_CONNECT
Definition: NetClient.h:43
@ NCS_LOADING
Definition: NetClient.h:47
@ NCS_AUTHENTICATE
Definition: NetClient.h:45
@ NCS_INGAME
Definition: NetClient.h:49
@ NCS_HANDSHAKE
Definition: NetClient.h:44
CNetClient * g_NetClient
Global network client for the standard game.
Definition: NetClient.cpp:54
Various declarations shared by networking code.
std::map< CStr, PlayerAssignment > PlayerAssignmentMap
Definition: NetHost.h:54
Represents a signal in the state machine that a change has occurred.
Definition: FSM.h:33
Manages states, events, actions and transitions between states.
Definition: FSM.h:68
The container that holds the rules, resources and attributes of the game.
Definition: Game.h:43
The client end of a network session.
Definition: NetSession.h:68
Implementation of CTurnManager for network clients.
Definition: NetClientTurnManager.h:30
Network client.
Definition: NetClient.h:60
void CheckServerConnection()
Locally triggers a GUI message if the connection to the server is being lost or has bad latency.
Definition: NetClient.cpp:332
static bool OnGameSetup(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:713
static bool OnJoinSyncStart(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:782
static void Trace(JSTracer *trc, void *data)
We assume that adding a tracing function that's only called during GC is better for performance than ...
Definition: NetClient.h:78
static bool OnKicked(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:834
static bool OnJoinSyncEndCommandBatch(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:807
static bool OnInGame(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:939
static bool OnGameStart(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:753
void SendAssignPlayerMessage(const int playerID, const CStr &guid)
Definition: NetClient.cpp:457
const ScriptInterface & GetScriptInterface()
Get the script interface associated with this network client, which is equivalent to the one used by ...
Definition: NetClient.cpp:392
std::deque< JS::Heap< JS::Value > > m_GuiMessageQueue
Queue of messages for GuiPoll.
Definition: NetClient.h:340
std::string TestReadGuiMessages()
Return a concatenation of all messages in the GUI queue, for test cases to easily verify the queue co...
Definition: NetClient.cpp:376
NONCOPYABLE(CNetClient)
bool m_UseSTUN
Definition: NetClient.h:306
CStrW m_UserName
Definition: NetClient.h:301
CStr GetGUID() const
Returns the GUID of the local client.
Definition: NetClient.h:111
void PushGuiMessage(Args const &... args)
Add a message to the queue, to be read by GuiPoll.
Definition: NetClient.h:178
static bool OnConnect(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:605
static bool OnClientsLoading(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:889
CStr m_ServerAddress
Definition: NetClient.h:304
void SendKickPlayerMessage(const CStrW &playerName, bool ban)
Call to kick/ban a client.
Definition: NetClient.cpp:498
static bool OnClientPaused(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:906
std::string m_JoinSyncBuffer
Serialized game state received when joining an in-progress game.
Definition: NetClient.h:343
static bool OnClientTimeout(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:848
void GuiPoll(JS::MutableHandleValue)
Retrieves the next queued GUI message, and removes it from the queue.
Definition: NetClient.cpp:364
bool IsController() const
Definition: NetClient.h:99
static bool OnAuthenticate(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:665
void PostPlayerAssignmentsToScript()
Push a message onto the GUI queue listing the current player assignments.
Definition: NetClient.cpp:397
std::thread m_PollingThread
Definition: NetClient.h:322
void SetupConnectionViaLobby()
Request connection information over the lobby.
Definition: NetClient.cpp:177
static bool OnReady(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:699
static bool OnAuthenticateRequest(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:657
void SendGameSetupMessage(JS::MutableHandleValue attrs, const ScriptInterface &scriptInterface)
Definition: NetClient.cpp:450
CStr m_HostJID
Definition: NetClient.h:303
void SendRejoinedMessage()
Call when the client has rejoined a running match and finished the loading screen.
Definition: NetClient.cpp:492
virtual ~CNetClient()
Definition: NetClient.cpp:126
bool SetupConnection(ENetHost *enetClient)
Set up a connection to the remote networked server.
Definition: NetClient.cpp:167
static bool OnPlayerAssignment(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:726
bool SendMessage(const CNetMessage *message)
Send a message to the server.
Definition: NetClient.cpp:423
std::string m_ControllerSecret
The 'secret' used to identify the controller of the game.
Definition: NetClient.h:314
void DestroyConnection()
Destroy the connection to the server.
Definition: NetClient.cpp:306
u32 m_HostID
Unique-per-game identifier of this client, used to identify the sender of simulation commands.
Definition: NetClient.h:328
void SetHostJID(const CStr &jid)
Store the JID of the host.
Definition: NetClient.cpp:149
void SendReadyMessage(const int status)
Definition: NetClient.cpp:472
CStr m_GUID
Globally unique identifier to distinguish users beyond the lifetime of a single network session.
Definition: NetClient.h:337
void SendStartGameMessage(const CStr &initAttribs)
Definition: NetClient.cpp:485
static bool OnChat(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:685
CStr m_Password
Password to join the game.
Definition: NetClient.h:311
u16 m_ServerPort
Definition: NetClient.h:305
static bool OnRejoined(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:821
static bool OnClientPerformance(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:865
bool m_Rejoin
True if the player is currently rejoining or has already rejoined the game.
Definition: NetClient.h:331
void HandleDisconnect(u32 reason)
Call when the network connection has been lost.
Definition: NetClient.cpp:436
bool ShouldShutdown() const
CNetClient(CGame *game)
Construct a client associated with the given game object.
Definition: NetClient.cpp:56
void TraceMember(JSTracer *trc)
Definition: NetClient.cpp:136
CNetClientSession * m_Session
Current network session (or NULL if not connected)
Definition: NetClient.h:320
void LoadFinished()
Call when the game has started and all data files have been loaded, to signal to the server that we a...
Definition: NetClient.cpp:556
static bool OnHandshake(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:616
void SetGamePassword(const CStr &hashedPassword)
Set the game password.
Definition: NetClient.cpp:154
bool TryToConnect(const CStr &hostJID, bool localNetwork)
Connect to the remote networked server using lobby.
Definition: NetClient.cpp:203
static bool OnLoadedGame(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:920
bool HandleMessage(CNetMessage *message)
Call when a message has been received from the network.
Definition: NetClient.cpp:513
void SendClearAllReadyMessage()
Definition: NetClient.cpp:479
void Poll()
Poll the connection for messages from the server and process them, and send any queued messages.
Definition: NetClient.cpp:321
std::time_t m_LastConnectionCheck
Time when the server was last checked for timeouts and bad latency.
Definition: NetClient.h:346
void HandleConnect()
Call when the network connection has been successfully initiated.
Definition: NetClient.cpp:431
void SendChatMessage(const std::wstring &text)
Definition: NetClient.cpp:465
void SetupServerData(CStr address, u16 port, bool stun)
Set connection data to the remote networked server.
Definition: NetClient.cpp:182
void SetUserName(const CStrW &username)
Set the user's name that will be displayed to all players.
Definition: NetClient.cpp:142
bool m_IsController
Note that this is just a "gui hint" with no actual impact on being controller.
Definition: NetClient.h:317
void HandleGetServerDataFailed(const CStr &error)
Called when fetching connection data from the host failed, to inform JS code.
Definition: NetClient.cpp:191
PlayerAssignmentMap m_PlayerAssignments
Latest copy of player assignments heard from the server.
Definition: NetClient.h:334
void SendAuthenticateMessage()
Definition: NetClient.cpp:596
void SetAndOwnSession(CNetClientSession *session)
Take ownership of a session object, and use it for all network communication.
Definition: NetClient.cpp:300
static bool OnHandshakeResponse(CNetClient *client, CFsmEvent *event)
Definition: NetClient.cpp:629
void SetControllerSecret(const std::string &secret)
Definition: NetClient.cpp:161
void SendPausedMessage(bool pause)
Call when the client has paused or unpaused the game.
Definition: NetClient.cpp:506
CGame * m_Game
Definition: NetClient.h:300
CNetClientTurnManager * m_ClientTurnManager
Turn manager associated with the current game (or NULL if we haven't started the game yet)
Definition: NetClient.h:325
The base class for all network messages exchanged within the game.
Definition: NetMessage.h:33
Abstraction around a SpiderMonkey JS::Realm.
Definition: ScriptInterface.h:72
Spidermonkey maintains some 'local' state via the JSContext* object.
Definition: ScriptRequest.h:60
JSContext * cx
Definition: ScriptRequest.h:92
JS::Value CreateObject(const ScriptRequest &rq)
Create a plain object (i.e.
Definition: Object.h:214
bool error(JSContext *cx, uint argc, JS::Value *vp)
Definition: ScriptInterface.cpp:173
uint16_t u16
Definition: types.h:38
uint32_t u32
Definition: types.h:39