Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
NetServer.h
Go to the documentation of this file.
1 /* Copyright (C) 2011 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 NETSERVER_H
19 #define NETSERVER_H
20 
21 #include "NetFileTransfer.h"
22 #include "NetHost.h"
23 
24 #include "ps/ThreadUtil.h"
26 
27 #include <vector>
28 
29 class CNetServerSession;
31 class CFsmEvent;
32 class ScriptInterface;
33 class CPlayerAssignmentMessage;
34 class CNetStatsTable;
35 class CSimulationMessage;
36 
37 class CNetServerWorker;
38 
40 {
41  // We haven't opened the port yet, we're just setting some stuff up.
42  // The worker thread has not been started.
44 
45  // The server is open and accepting connections. This is the screen where
46  // rules are set up by the operator and where players join and select civs
47  // and stuff.
49 
50  // All the hosts are connected and are loading the game
52 
53  // The one with all the killing ;-)
55 
56  // The game is over and someone has won. Players might linger to chat or
57  // download the replay log.
59 };
60 
61 /**
62  * Server session representation of client state
63  */
65 {
66  // The client has disconnected or been disconnected
68 
69  // The client has just connected and we're waiting for its handshake message,
70  // to agree on the protocol version
72 
73  // The client has handshook and we're waiting for its authentication message,
74  // to find its name and check its password etc
76 
77  // The client has fully joined, and is in the pregame setup stage
78  // or is loading the game.
79  // Server must be in SERVER_STATE_PREGAME or SERVER_STATE_LOADING.
81 
82  // The client has authenticated but the game was already started,
83  // so it's synchronising with the game state from other clients
85 
86  // The client is running the game.
87  // Server must be in SERVER_STATE_LOADING or SERVER_STATE_INGAME.
89 };
90 
91 /**
92  * Network server interface. Handles all the coordination between players.
93  * One person runs this object, and every player (including the host) connects their CNetClient to it.
94  *
95  * The actual work is performed by CNetServerWorker in a separate thread.
96  */
98 {
100 public:
101  /**
102  * Construct a new network server.
103  * @param autostartPlayers if positive then StartGame will be called automatically
104  * once this many players are connected (intended for the command-line testing mode).
105  */
106  CNetServer(int autostartPlayers = -1);
107 
108  ~CNetServer();
109 
110  /**
111  * Begin listening for network connections.
112  * This function is synchronous (it won't return until the connection is established).
113  * @return true on success, false on error (e.g. port already in use)
114  */
115  bool SetupConnection();
116 
117  /**
118  * Call from the GUI to update the player assignments.
119  * The given GUID will be (re)assigned to the given player ID.
120  * Any player currently using that ID will be unassigned.
121  * The changes will be asynchronously propagated to all clients.
122  */
123  void AssignPlayer(int playerID, const CStr& guid);
124 
125  /**
126  * Call from the GUI to asynchronously notify all clients that they should start loading the game.
127  */
128  void StartGame();
129 
130  /**
131  * Call from the GUI to update the game setup attributes.
132  * This must be called at least once before starting the game.
133  * The changes will be asynchronously propagated to all clients.
134  * @param attrs game attributes, in the script context of scriptInterface
135  */
136  void UpdateGameAttributes(const CScriptVal& attrs, ScriptInterface& scriptInterface);
137 
138  /**
139  * Set the turn length to a fixed value.
140  * TODO: we should replace this with some adapative lag-dependent computation.
141  */
142  void SetTurnLength(u32 msecs);
143 
144 private:
146 };
147 
148 /**
149  * Network server worker thread.
150  * (This is run in a thread so that client/server communication is not delayed
151  * by the host player's framerate - the only delay should be the network latency.)
152  *
153  * Thread-safety:
154  * - SetupConnection and constructor/destructor must be called from the main thread.
155  * - The main thread may push commands onto the Queue members,
156  * while holding the m_WorkerMutex lock.
157  * - Public functions (SendMessage, Broadcast) must be called from the network
158  * server thread.
159  */
161 {
163 
164 public:
165  // Public functions for CNetSession/CNetServerTurnManager to use:
166 
167  /**
168  * Send a message to the given network peer.
169  */
170  bool SendMessage(ENetPeer* peer, const CNetMessage* message);
171 
172  /**
173  * Send a message to all clients who have completed the full connection process
174  * (i.e. are in the pre-game or in-game states).
175  */
176  bool Broadcast(const CNetMessage* message);
177 
178 private:
179  friend class CNetServer;
181 
182  CNetServerWorker(int autostartPlayers);
184 
185  /**
186  * Begin listening for network connections.
187  * @return true on success, false on error (e.g. port already in use)
188  */
189  bool SetupConnection();
190 
191  /**
192  * Call from the GUI to update the player assignments.
193  * The given GUID will be (re)assigned to the given player ID.
194  * Any player currently using that ID will be unassigned.
195  * The changes will be propagated to all clients.
196  */
197  void AssignPlayer(int playerID, const CStr& guid);
198 
199  /**
200  * Call from the GUI to notify all clients that they should start loading the game.
201  */
202  void StartGame();
203 
204  /**
205  * Call from the GUI to update the game setup attributes.
206  * This must be called at least once before starting the game.
207  * The changes will be propagated to all clients.
208  * @param attrs game attributes, in the script context of GetScriptInterface()
209  */
210  void UpdateGameAttributes(const CScriptValRooted& attrs);
211 
212  /**
213  * Make a player name 'nicer' by limiting the length and removing forbidden characters etc.
214  */
215  static CStrW SanitisePlayerName(const CStrW& original);
216 
217  /**
218  * Make a player name unique, if it matches any existing session's name.
219  */
220  CStrW DeduplicatePlayerName(const CStrW& original);
221 
222  /**
223  * Get the script context used for game attributes.
224  */
226 
227  /**
228  * Set the turn length to a fixed value.
229  * TODO: we should replace this with some adaptive lag-dependent computation.
230  */
231  void SetTurnLength(u32 msecs);
232 
233  void AddPlayer(const CStr& guid, const CStrW& name);
234  void RemovePlayer(const CStr& guid);
235  void SendPlayerAssignments();
236 
237  void SetupSession(CNetServerSession* session);
238  bool HandleConnect(CNetServerSession* session);
239 
240  void OnUserJoin(CNetServerSession* session);
241  void OnUserLeave(CNetServerSession* session);
242 
243  static bool OnClientHandshake(void* context, CFsmEvent* event);
244  static bool OnAuthenticate(void* context, CFsmEvent* event);
245  static bool OnInGame(void* context, CFsmEvent* event);
246  static bool OnChat(void* context, CFsmEvent* event);
247  static bool OnLoadedGame(void* context, CFsmEvent* event);
248  static bool OnJoinSyncingLoadedGame(void* context, CFsmEvent* event);
249  static bool OnDisconnect(void* context, CFsmEvent* event);
250 
251  void CheckGameLoadStatus(CNetServerSession* changedSession);
252 
253  void ConstructPlayerAssignmentMessage(CPlayerAssignmentMessage& message);
254 
255  void HandleMessageReceive(const CNetMessage* message, CNetServerSession* session);
256 
257 
258  /**
259  * Internal script context for (de)serializing script messages,
260  * and for storing game attributes.
261  * (TODO: we shouldn't bother deserializing (except for debug printing of messages),
262  * we should just forward messages blindly and efficiently.)
263  */
265 
267 
269 
271 
273  std::vector<CNetServerSession*> m_Sessions;
274 
276 
278 
281 
283 
285 
286  /**
287  * A copy of all simulation commands received so far, indexed by
288  * turn number, to simplify support for rejoining etc.
289  * TODO: verify this doesn't use too much RAM.
290  */
291  std::vector<std::vector<CSimulationMessage> > m_SavedCommands;
292 
293  /**
294  * The latest copy of the simulation state, received from an existing
295  * client when a new client has asked to rejoin the game.
296  */
297  std::string m_JoinSyncFile;
298 
299 private:
300  // Thread-related stuff:
301 
302  static void* RunThread(void* data);
303  void Run();
304  bool RunStep();
305 
308 
309  bool m_Shutdown; // protected by m_WorkerMutex
310 
311  // Queues for messages sent by the game thread:
312  std::vector<std::pair<int, CStr> > m_AssignPlayerQueue; // protected by m_WorkerMutex
313  std::vector<bool> m_StartGameQueue; // protected by m_WorkerMutex
314  std::vector<std::string> m_GameAttributesQueue; // protected by m_WorkerMutex
315  std::vector<u32> m_TurnLengthQueue; // protected by m_WorkerMutex
316 };
317 
318 /// Global network server for the standard game
319 extern CNetServer *g_NetServer;
320 
321 #endif // NETSERVER_H
pthread_t m_WorkerThread
Definition: NetServer.h:306
ScriptInterface * m_ScriptInterface
Internal script context for (de)serializing script messages, and for storing game attributes...
Definition: NetServer.h:264
void StartGame()
Call from the GUI to asynchronously notify all clients that they should start loading the game...
Definition: NetServer.cpp:939
std::map< CStr, PlayerAssignment > PlayerAssignmentMap
Definition: NetHost.h:51
static bool OnClientHandshake(void *context, CFsmEvent *event)
Definition: NetServer.cpp:598
void OnUserLeave(CNetServerSession *session)
Definition: NetServer.cpp:470
static void * RunThread(void *data)
Definition: NetServer.cpp:219
std::vector< std::vector< CSimulationMessage > > m_SavedCommands
A copy of all simulation commands received so far, indexed by turn number, to simplify support for re...
Definition: NetServer.h:291
static bool OnJoinSyncingLoadedGame(void *context, CFsmEvent *event)
Definition: NetServer.cpp:761
std::string m_JoinSyncFile
The latest copy of the simulation state, received from an existing client when a new client has asked...
Definition: NetServer.h:297
Represents a signal in the state machine that a change has occurred.
Definition: fsm.h:53
void CheckGameLoadStatus(CNetServerSession *changedSession)
Definition: NetServer.cpp:824
bool SetupConnection()
Begin listening for network connections.
Definition: NetServer.cpp:928
void HandleMessageReceive(const CNetMessage *message, CNetServerSession *session)
Definition: NetServer.cpp:392
Async task for receiving the initial game state to be forwarded to another client that is rejoining a...
Definition: NetServer.cpp:61
bool SetupConnection()
Begin listening for network connections.
Definition: NetServer.cpp:157
void StartGame()
Call from the GUI to notify all clients that they should start loading the game.
Definition: NetServer.cpp:839
void AddPlayer(const CStr &guid, const CStrW &name)
Definition: NetServer.cpp:481
void UpdateGameAttributes(const CScriptValRooted &attrs)
Call from the GUI to update the game setup attributes.
Definition: NetServer.cpp:856
static bool OnChat(void *context, CFsmEvent *event)
Definition: NetServer.cpp:730
static bool OnInGame(void *context, CFsmEvent *event)
Definition: NetServer.cpp:692
CNetServer * g_NetServer
Global network server for the standard game.
Definition: NetServer.cpp:46
A trivial wrapper around a jsval.
Definition: ScriptVal.h:29
CNetServerWorker(int autostartPlayers)
Definition: NetServer.cpp:111
static CStrW SanitisePlayerName(const CStrW &original)
Make a player name &#39;nicer&#39; by limiting the length and removing forbidden characters etc...
Definition: NetServer.cpp:868
struct _ENetPeer ENetPeer
Definition: NetHost.h:30
A non-recursive mutual exclusion lock.
Definition: ThreadUtil.h:45
NetServerState
Definition: NetServer.h:39
NONCOPYABLE(CNetServerWorker)
std::vector< std::string > m_GameAttributesQueue
Definition: NetServer.h:314
CNetServer(int autostartPlayers=-1)
Construct a new network server.
Definition: NetServer.cpp:918
void SetTurnLength(u32 msecs)
Set the turn length to a fixed value.
Definition: NetServer.cpp:955
Various declarations shared by networking code.
void AssignPlayer(int playerID, const CStr &guid)
Call from the GUI to update the player assignments.
Definition: NetServer.cpp:933
ENetHost * m_Host
Definition: NetServer.h:272
void AssignPlayer(int playerID, const CStr &guid)
Call from the GUI to update the player assignments.
Definition: NetServer.cpp:549
std::vector< std::pair< int, CStr > > m_AssignPlayerQueue
Definition: NetServer.h:312
CScriptValRooted m_GameAttributes
Definition: NetServer.h:268
CStrW DeduplicatePlayerName(const CStrW &original)
Make a player name unique, if it matches any existing session&#39;s name.
Definition: NetServer.cpp:890
void UpdateGameAttributes(const CScriptVal &attrs, ScriptInterface &scriptInterface)
Call from the GUI to update the game setup attributes.
Definition: NetServer.cpp:945
NetServerSessionState
Server session representation of client state.
Definition: NetServer.h:64
void SetupSession(CNetServerSession *session)
Definition: NetServer.cpp:418
NONCOPYABLE(CNetServer)
Network server interface.
Definition: NetServer.h:97
void ConstructPlayerAssignmentMessage(CPlayerAssignmentMessage &message)
Definition: NetServer.cpp:565
ENet connection statistics profiler table.
Definition: NetStats.h:36
std::vector< bool > m_StartGameQueue
Definition: NetServer.h:313
std::vector< u32 > m_TurnLengthQueue
Definition: NetServer.h:315
std::vector< CNetServerSession * > m_Sessions
Definition: NetServer.h:273
The base class for all network messages exchanged within the game.
Definition: NetMessage.h:32
void OnUserJoin(CNetServerSession *session)
Definition: NetServer.cpp:457
int m_AutostartPlayers
Definition: NetServer.h:270
CNetServerWorker * m_Worker
Definition: NetServer.h:145
bool HandleConnect(CNetServerSession *session)
Definition: NetServer.cpp:448
CNetStatsTable * m_Stats
Definition: NetServer.h:275
uintptr_t pthread_t
Definition: wpthread.h:63
CStrW m_WelcomeMessage
Definition: NetServer.h:280
#define u32
Definition: types.h:41
void SetTurnLength(u32 msecs)
Set the turn length to a fixed value.
Definition: NetServer.cpp:592
static bool OnAuthenticate(void *context, CFsmEvent *event)
Definition: NetServer.cpp:621
struct _ENetHost ENetHost
Definition: NetHost.h:32
NetServerState m_State
Definition: NetServer.h:277
bool Broadcast(const CNetMessage *message)
Send a message to all clients who have completed the full connection process (i.e.
Definition: NetServer.cpp:197
static bool OnLoadedGame(void *context, CFsmEvent *event)
Definition: NetServer.cpp:746
bool SendMessage(ENetPeer *peer, const CNetMessage *message)
Send a message to the given network peer.
Definition: NetServer.cpp:188
Abstraction around a SpiderMonkey JSContext.
void SendPlayerAssignments()
Definition: NetServer.cpp:580
ScriptInterface & GetScriptInterface()
Get the script context used for game attributes.
Definition: NetServer.cpp:587
CStrW m_ServerName
Definition: NetServer.h:279
CNetServerTurnManager * m_ServerTurnManager
Definition: NetServer.h:284
PlayerAssignmentMap m_PlayerAssignments
Definition: NetServer.h:266
static bool OnDisconnect(void *context, CFsmEvent *event)
Definition: NetServer.cpp:812
Network server worker thread.
Definition: NetServer.h:160
The server&#39;s end of a network session.
Definition: NetSession.h:107
void RemovePlayer(const CStr &guid)
Definition: NetServer.cpp:542
CMutex m_WorkerMutex
Definition: NetServer.h:307
The server-side counterpart to CNetClientTurnManager.
Special message type for simulation commands.
Definition: NetMessage.h:113