SuperTuxKart
server_lobby.hpp
1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2018 SuperTuxKart-Team
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 3
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 #ifndef SERVER_LOBBY_HPP
20 #define SERVER_LOBBY_HPP
21 
22 #include "network/protocols/lobby_protocol.hpp"
23 #include "utils/cpp2011.hpp"
24 #include "utils/time.hpp"
25 
26 #include "irrString.h"
27 
28 #include <algorithm>
29 #include <array>
30 #include <atomic>
31 #include <functional>
32 #include <map>
33 #include <memory>
34 #include <mutex>
35 #include <set>
36 
37 class BareNetworkString;
38 class DatabaseConnector;
39 class NetworkItemManager;
40 class NetworkString;
42 class STKPeer;
43 class SocketAddress;
44 class Ranking;
45 
46 namespace Online
47 {
48  class Request;
49 }
50 
51 class ServerLobby : public LobbyProtocol
52 {
53 public:
54  /* The state for a small finite state machine. */
55  enum ServerState : unsigned int
56  {
57  SET_PUBLIC_ADDRESS, // Waiting to receive its public ip address
58  REGISTER_SELF_ADDRESS, // Register with STK online server
59  WAITING_FOR_START_GAME, // In lobby, waiting for (auto) start game
60  SELECTING, // kart, track, ... selection started
61  LOAD_WORLD, // Server starts loading world
62  WAIT_FOR_WORLD_LOADED, // Wait for clients and server to load world
63  WAIT_FOR_RACE_STARTED, // Wait for all clients to have started the race
64  RACING, // racing
65  WAIT_FOR_RACE_STOPPED, // Wait server for stopping all race protocols
66  RESULT_DISPLAY, // Show result screen
67  ERROR_LEAVE, // shutting down server
68  EXITING
69  };
70 private:
71  struct KeyData
72  {
73  std::string m_aes_key;
74  std::string m_aes_iv;
75  irr::core::stringw m_name;
76  std::string m_country_code;
77  bool m_tried = false;
78  };
79 
80 #ifdef ENABLE_SQLITE3
81  DatabaseConnector* m_db_connector;
82 
83  void pollDatabase();
84 #endif
85 
86  std::atomic<ServerState> m_state;
87 
88  /* The state used in multiple threads when reseting server. */
89  enum ResetState : unsigned int
90  {
91  RS_NONE, // Default state
92  RS_WAITING, // Waiting for reseting finished
93  RS_ASYNC_RESET // Finished reseting server in main thread, now async
94  // thread
95  };
96 
97  std::atomic<ResetState> m_rs_state;
98 
100  std::weak_ptr<STKPeer> m_ai_peer;
101 
105  std::vector<std::shared_ptr<NetworkPlayerProfile> > m_ai_profiles;
106 
107  std::atomic<uint32_t> m_server_owner_id;
108 
111  std::pair<std::set<std::string>, std::set<std::string> > m_available_kts;
112 
114  std::atomic_bool m_server_has_loaded_world;
115 
116  bool m_registered_for_once_only;
117 
118  bool m_save_server_config;
119 
121  std::map<std::weak_ptr<STKPeer>, bool,
122  std::owner_less<std::weak_ptr<STKPeer> > > m_peers_ready;
123 
124  std::weak_ptr<Online::Request> m_server_registering;
125 
127  std::atomic<int64_t> m_timeout;
128 
129  std::mutex m_keys_mutex;
130 
131  std::map<uint32_t, KeyData> m_keys;
132 
133  std::map<std::weak_ptr<STKPeer>,
134  std::pair<uint32_t, BareNetworkString>,
135  std::owner_less<std::weak_ptr<STKPeer> > > m_pending_connection;
136 
137  std::map<std::string, uint64_t> m_pending_peer_connection;
138 
139  std::shared_ptr<Ranking> m_ranking;
140 
141  /* Saved the last game result */
142  NetworkString* m_result_ns;
143 
144  /* Used to make sure clients are having same item list at start */
145  BareNetworkString* m_items_complete_state;
146 
147  std::atomic<uint32_t> m_server_id_online;
148 
149  std::atomic<uint32_t> m_client_server_host_id;
150 
151  std::atomic<int> m_difficulty;
152 
153  std::atomic<int> m_game_mode;
154 
155  std::atomic<int> m_lobby_players;
156 
157  std::atomic<int> m_current_ai_count;
158 
159  std::atomic<uint64_t> m_last_success_poll_time;
160 
161  uint64_t m_last_unsuccess_poll_time, m_server_started_at, m_server_delay;
162 
163  // Default game settings if no one has ever vote, and save inside here for
164  // final vote (for live join)
165  PeerVote* m_default_vote;
166 
167  int m_battle_hit_capture_limit;
168 
169  float m_battle_time_limit;
170 
171  unsigned m_item_seed;
172 
173  uint32_t m_winner_peer_id;
174 
175  uint64_t m_client_starting_time;
176 
177  // Calculated before each game started
178  unsigned m_ai_count;
179 
180  // connection management
181  void clientDisconnected(Event* event);
182  void connectionRequested(Event* event);
183  // kart selection
184  void kartSelectionRequested(Event* event);
185  // Track(s) votes
186  void handlePlayerVote(Event *event);
187  void playerFinishedResult(Event *event);
188  void registerServer(bool first_time);
189  void finishedLoadingWorldClient(Event *event);
191  void kickHost(Event* event);
192  void changeTeam(Event* event);
193  void handleChat(Event* event);
194  void unregisterServer(bool now,
195  std::weak_ptr<ServerLobby> sl = std::weak_ptr<ServerLobby>());
196  void updateServerOwner();
197  void handleServerConfiguration(Event* event);
198  void updateTracksForMode();
199  bool checkPeersReady(bool ignore_ai_peer) const;
200  void resetPeersReady()
201  {
202  for (auto it = m_peers_ready.begin(); it != m_peers_ready.end();)
203  {
204  if (it->first.expired())
205  {
206  it = m_peers_ready.erase(it);
207  }
208  else
209  {
210  it->second = false;
211  it++;
212  }
213  }
214  }
215  void addPeerConnection(const std::string& addr_str)
216  {
217  m_pending_peer_connection[addr_str] = StkTime::getMonoTimeMs();
218  }
219  void removeExpiredPeerConnection()
220  {
221  // Remove connect to peer protocol running more than a 45 seconds
222  // (from stk addons poll server request),
223  for (auto it = m_pending_peer_connection.begin();
224  it != m_pending_peer_connection.end();)
225  {
226  if (StkTime::getMonoTimeMs() - it->second > 45000)
227  it = m_pending_peer_connection.erase(it);
228  else
229  it++;
230  }
231  }
232  void replaceKeys(std::map<uint32_t, KeyData>& new_keys)
233  {
234  std::lock_guard<std::mutex> lock(m_keys_mutex);
235  std::swap(m_keys, new_keys);
236  }
237  void handlePendingConnection();
238  void handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
239  BareNetworkString& data,
240  uint32_t online_id,
241  const irr::core::stringw& online_name,
242  bool is_pending_connection,
243  std::string country_code = "");
244  bool decryptConnectionRequest(std::shared_ptr<STKPeer> peer,
245  BareNetworkString& data,
246  const std::string& key,
247  const std::string& iv,
248  uint32_t online_id,
249  const irr::core::stringw& online_name,
250  const std::string& country_code);
251  bool handleAllVotes(PeerVote* winner, uint32_t* winner_peer_id);
252  template<typename T>
253  void findMajorityValue(const std::map<T, unsigned>& choices, unsigned cur_players,
254  T* best_choice, float* rate);
255  void getRankingForPlayer(std::shared_ptr<NetworkPlayerProfile> p);
256  void submitRankingsToAddons();
257  void computeNewRankings();
258  void checkRaceFinished();
259  void getHitCaptureLimit();
260  void configPeersStartTime();
261  void resetServer();
262  void addWaitingPlayersToGame();
263  void changeHandicap(Event* event);
264  void handlePlayerDisconnection() const;
266  std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
267  NetworkString* getLoadWorldMessage(
268  std::vector<std::shared_ptr<NetworkPlayerProfile> >& players,
269  bool live_join) const;
270  void encodePlayers(BareNetworkString* bns,
271  std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
272  std::vector<std::shared_ptr<NetworkPlayerProfile> > getLivePlayers() const;
273  void setPlayerKarts(const NetworkString& ns, STKPeer* peer) const;
274  bool handleAssets(const NetworkString& ns, STKPeer* peer);
275  void liveJoinRequest(Event* event);
276  void rejectLiveJoin(STKPeer* peer, BackLobbyReason blr);
277  bool canLiveJoinNow() const;
278  bool worldIsActive() const;
279  int getReservedId(std::shared_ptr<NetworkPlayerProfile>& p,
280  unsigned local_id) const;
281  void handleKartInfo(Event* event);
282  void clientInGameWantsToBackLobby(Event* event);
284  std::set<std::shared_ptr<STKPeer>> getSpectatorsByLimit();
285  void kickPlayerWithReason(STKPeer* peer, const char* reason) const;
286  void testBannedForIP(STKPeer* peer) const;
287  void testBannedForIPv6(STKPeer* peer) const;
288  void testBannedForOnlineId(STKPeer* peer, uint32_t online_id) const;
289  void writePlayerReport(Event* event);
290  bool supportsAI();
291  void updateAddons();
292 public:
293  // Having those variable private would just require a bunch of boilerplate
294  // code to access them... What's the point?
295 
298  std::weak_ptr<STKPeer> m_server_owner;
299 
301  // FIXME: We should use two different variables instead of this weird
302  // structure that contains both a list of tracks and a list of karts
303  std::pair<std::set<std::string>, std::set<std::string> > m_official_kts;
304 
306  // FIXME: We should use two different variables instead of this weird
307  // structure that contains both a list of tracks and a list of karts
308  std::pair<std::set<std::string>, std::set<std::string> > m_addon_kts;
309 
311  std::set<std::string> m_addon_arenas;
312 
314  std::set<std::string> m_addon_soccers;
315 
316  std::map<std::weak_ptr<STKPeer>, std::set<irr::core::stringw>,
317  std::owner_less<std::weak_ptr<STKPeer> > > m_peers_muted_players;
318 
319  ServerLobby();
320  virtual ~ServerLobby();
321 
322  virtual bool notifyEventAsynchronous(Event* event) OVERRIDE;
323  virtual bool notifyEvent(Event* event) OVERRIDE;
324  virtual void setup() OVERRIDE;
325  virtual void update(int ticks) OVERRIDE;
326  virtual void asynchronousUpdate() OVERRIDE;
327 
328  void updatePlayerList(bool update_when_reset_server = false);
329  void startSelection(const Event *event=NULL);
331  void finishedLoadingWorld() OVERRIDE;
332  ServerState getCurrentState() const { return m_state.load(); }
333  void updateBanList();
334  bool waitingForPlayers() const;
335  virtual bool allPlayersReady() const OVERRIDE
336  { return m_state.load() >= WAIT_FOR_RACE_STARTED; }
337  virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
338  bool allowJoinedPlayersWaiting() const;
339  void setSaveServerConfig(bool val) { m_save_server_config = val; }
340  float getStartupBoostOrPenaltyForKart(uint32_t ping, unsigned kart_id);
341  int getDifficulty() const { return m_difficulty.load(); }
342  int getGameMode() const { return m_game_mode.load(); }
343  int getLobbyPlayers() const { return m_lobby_players.load(); }
344  void saveInitialItems(std::shared_ptr<NetworkItemManager> nim);
345  void saveIPBanTable(const SocketAddress& addr);
346  void listBanTable();
347  void initServerStatsTable();
348  bool isAIProfile(const std::shared_ptr<NetworkPlayerProfile>& npp) const
349  {
350  return std::find(m_ai_profiles.begin(), m_ai_profiles.end(), npp) !=
351  m_ai_profiles.end();
352  }
353  uint32_t getServerIdOnline() const { return m_server_id_online; }
354  uint32_t getClientServerHostId() const { return m_client_server_host_id.load(); }
355  void setClientServerHostId(uint32_t id) { m_client_server_host_id = id; }
356  static int m_fixed_laps;
357  bool playerReportsTableExists() const;
358  GameSetup* getGameSetup() { return m_game_setup; }
359  ProcessType getProcessType() { return m_process_type; }
360 }; // class ServerLobby
361 
362 #endif // SERVER_LOBBY_HPP
Describes a chain of 8-bit unsigned integers.
Definition: network_string.hpp:53
Class representing an event that need to pass trough the system. This is used to remove ENet dependen...
Definition: event.hpp:73
Used to store the needed data about the players that join a game. This class stores all the possible ...
Definition: game_setup.hpp:43
Base class for both client and server lobby. The lobbies are started when a server opens a game,...
Definition: lobby_protocol.hpp:47
GameSetup * m_game_setup
Stores data about the online game to play.
Definition: lobby_protocol.hpp:141
The network item manager is responsible for handling all network related item manager tasks - synchro...
Definition: network_item_manager.hpp:45
Contains the profile of a player.
Definition: network_player_profile.hpp:42
A new implementation of NetworkString, which has a fixed format: Byte 0: The type of the message,...
Definition: network_string.hpp:422
A simple structure to store a vote from a client: track name, number of laps and reverse or not.
Definition: peer_vote.hpp:30
Definition: ranking.hpp:57
Represents a peer. This class is used to interface the ENetPeer structure.
Definition: stk_peer.hpp:76
Definition: server_lobby.hpp:52
virtual void setup() OVERRIDE
A previous GameSetup is deleted and a new one is created.
Definition: server_lobby.cpp:372
void computeNewRankings()
Compute the new player's rankings used in ranked servers.
Definition: server_lobby.cpp:2373
std::pair< std::set< std::string >, std::set< std::string > > m_available_kts
Available karts and tracks for all clients, this will be initialized with data in server first.
Definition: server_lobby.hpp:111
std::atomic_bool m_server_has_loaded_world
Keeps track of the server state.
Definition: server_lobby.hpp:114
void handlePlayerVote(Event *event)
Called when a player votes for track(s), it will auto correct client data if it sends some invalid da...
Definition: server_lobby.cpp:3177
void finishedLoadingWorldClient(Event *event)
Called when a client notifies the server that it has loaded the world.
Definition: server_lobby.cpp:3487
void updateTracksForMode()
Called whenever server is reset or game mode is changed.
Definition: server_lobby.cpp:293
void kartSelectionRequested(Event *event)
Called when a player asks to select karts.
Definition: server_lobby.cpp:3154
std::pair< std::set< std::string >, std::set< std::string > > m_addon_kts
Addon karts and tracks available in server.
Definition: server_lobby.hpp:308
void finishedLoadingLiveJoinClient(Event *event)
Finally put the kart in the world and inform client the current world status, (including current conf...
Definition: server_lobby.cpp:1403
int getReservedId(std::shared_ptr< NetworkPlayerProfile > &p, unsigned local_id) const
Decide where to put the live join player depends on his team and game mode.
Definition: server_lobby.cpp:1339
void handleServerConfiguration(Event *event)
Called when the server owner request to change game mode or difficulty.
Definition: server_lobby.cpp:3915
std::set< std::string > m_addon_arenas
Addon arenas available in server.
Definition: server_lobby.hpp:311
void changeHandicap(Event *event)
Called when a player want to change his handicap.
Definition: server_lobby.cpp:4023
void registerServer(bool first_time)
Register this server (i.e.
Definition: server_lobby.cpp:1710
void unregisterServer(bool now, std::weak_ptr< ServerLobby > sl=std::weak_ptr< ServerLobby >())
Unregister this server (i.e.
Definition: server_lobby.cpp:1804
std::vector< std::shared_ptr< NetworkPlayerProfile > > getLivePlayers() const
Get a list of current ingame players for live join or spectate.
Definition: server_lobby.cpp:1302
void clientInGameWantsToBackLobby(Event *event)
Client if currently in-game (including spectator) wants to go back to lobby.
Definition: server_lobby.cpp:4264
virtual bool notifyEvent(Event *event) OVERRIDE
Notify a protocol matching the Event type of that event.
Definition: server_lobby.cpp:423
void checkIncomingConnectionRequests()
Query the STK server for connection requests.
Definition: server_lobby.cpp:2165
void rejectLiveJoin(STKPeer *peer, BackLobbyReason blr)
STKPeer peer will be reset back to the lobby with reason BackLobbyReason blr
Definition: server_lobby.cpp:1208
void clientSelectingAssetsWantsToBackLobby(Event *event)
Client if currently select assets wants to go back to lobby.
Definition: server_lobby.cpp:4348
std::weak_ptr< STKPeer > m_ai_peer
AI peer which holds the list of reserved AI for dedicated server.
Definition: server_lobby.hpp:100
void handleKartInfo(Event *event)
Tell the client RemoteKartInfo of a player when some player joining live.
Definition: server_lobby.cpp:4228
void checkRaceFinished()
Checks if the race is finished, and if so informs the clients and switches to state RESULT_DISPLAY,...
Definition: server_lobby.cpp:2296
virtual ~ServerLobby()
Destructor.
Definition: server_lobby.cpp:202
std::pair< std::set< std::string >, std::set< std::string > > m_official_kts
Official karts and tracks available in server.
Definition: server_lobby.hpp:303
void configPeersStartTime()
This function is called when all clients have loaded the world and are therefore ready to start the r...
Definition: server_lobby.cpp:3646
std::vector< std::shared_ptr< NetworkPlayerProfile > > m_ai_profiles
AI profiles for all-in-one graphical client server, this will be a fixed count thorough the live time...
Definition: server_lobby.hpp:105
void startSelection(const Event *event=NULL)
Instructs all clients to start the kart selection.
Definition: server_lobby.cpp:1868
bool handleAllVotes(PeerVote *winner, uint32_t *winner_peer_id)
Select the track to be used based on all votes being received.
Definition: server_lobby.cpp:3279
bool worldIsActive() const
Returns true if world is active for clients to live join, spectate or going back to lobby live.
Definition: server_lobby.cpp:1197
virtual void update(int ticks) OVERRIDE
Simple finite state machine.
Definition: server_lobby.cpp:1503
std::atomic< int64_t > m_timeout
Timeout counter for various state.
Definition: server_lobby.hpp:127
void clientDisconnected(Event *event)
Called when a client disconnects.
Definition: server_lobby.cpp:2421
std::set< std::string > m_addon_soccers
Addon soccers available in server.
Definition: server_lobby.hpp:314
void liveJoinRequest(Event *event)
This message is like kartSelectionRequested, but it will send the peer load world message if he can j...
Definition: server_lobby.cpp:1228
void handlePlayerDisconnection() const
Update and see if any player disconnects, if so eliminate the kart in world, so this function must be...
Definition: server_lobby.cpp:4049
std::weak_ptr< STKPeer > m_server_owner
Hold the next connected peer for server owner if current one expired (disconnected).
Definition: server_lobby.hpp:298
void updatePlayerList(bool update_when_reset_server=false)
Called when any players change their setting (team for example), or connection / disconnection,...
Definition: server_lobby.cpp:2983
ServerLobby()
This is the central game setup protocol running in the server.
Definition: server_lobby.cpp:146
void addLiveJoinPlaceholder(std::vector< std::shared_ptr< NetworkPlayerProfile > > &players) const
Add reserved players for live join later if required.
Definition: server_lobby.cpp:4123
virtual void asynchronousUpdate() OVERRIDE
Find out the public IP server or poll STK server asynchronously.
Definition: server_lobby.cpp:784
void playerFinishedResult(Event *event)
Called when a client clicks on 'ok' on the race result screen.
Definition: server_lobby.cpp:3500
bool canLiveJoinNow() const
Returns true if server can be live joined or spectating.
Definition: server_lobby.cpp:1161
virtual bool notifyEventAsynchronous(Event *event) OVERRIDE
Notify a protocol matching the Event type of that event.
Definition: server_lobby.cpp:604
void finishedLoadingWorld() OVERRIDE
Called from the RaceManager of the server when the world is loaded.
Definition: server_lobby.cpp:3473
std::map< std::weak_ptr< STKPeer >, bool, std::owner_less< std::weak_ptr< STKPeer > > > m_peers_ready
Counts how many peers have finished loading the world.
Definition: server_lobby.hpp:122
Describes a IPv4 or IPv6 address in sockaddr_in(6) format, suitable in using with sendto.
Definition: socket_address.hpp:47
static uint64_t getMonoTimeMs()
Returns a time based since the starting of stk (monotonic clock).
Definition: time.hpp:113
Definition: server_lobby.hpp:72