SuperTuxKart
Loading...
Searching...
No Matches
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#ifdef ENABLE_SQLITE3
38#include <sqlite3.h>
39#endif
40
43class NetworkString;
45class STKPeer;
46class SocketAddress;
47
48namespace Online
49{
50 class Request;
51}
52
54{
55public:
56 /* The state for a small finite state machine. */
57 enum ServerState : unsigned int
58 {
59 SET_PUBLIC_ADDRESS, // Waiting to receive its public ip address
60 REGISTER_SELF_ADDRESS, // Register with STK online server
61 WAITING_FOR_START_GAME, // In lobby, waiting for (auto) start game
62 SELECTING, // kart, track, ... selection started
63 LOAD_WORLD, // Server starts loading world
64 WAIT_FOR_WORLD_LOADED, // Wait for clients and server to load world
65 WAIT_FOR_RACE_STARTED, // Wait for all clients to have started the race
66 RACING, // racing
67 WAIT_FOR_RACE_STOPPED, // Wait server for stopping all race protocols
68 RESULT_DISPLAY, // Show result screen
69 ERROR_LEAVE, // shutting down server
70 EXITING
71 };
72private:
73 struct KeyData
74 {
75 std::string m_aes_key;
76 std::string m_aes_iv;
77 irr::core::stringw m_name;
78 std::string m_country_code;
79 bool m_tried = false;
80 };
81 bool m_player_reports_table_exists;
82
83#ifdef ENABLE_SQLITE3
84 sqlite3* m_db;
85
86 std::string m_server_stats_table;
87
88 bool m_ip_ban_table_exists;
89
90 bool m_ipv6_ban_table_exists;
91
92 bool m_online_id_ban_table_exists;
93
94 bool m_ip_geolocation_table_exists;
95
96 bool m_ipv6_geolocation_table_exists;
97
98 uint64_t m_last_poll_db_time;
99
100 void pollDatabase();
101
102 bool easySQLQuery(const std::string& query,
103 std::function<void(sqlite3_stmt* stmt)> bind_function = nullptr) const;
104
105 void checkTableExists(const std::string& table, bool& result);
106
107 std::string ip2Country(const SocketAddress& addr) const;
108
109 std::string ipv62Country(const SocketAddress& addr) const;
110#endif
111 void initDatabase();
112
113 void destroyDatabase();
114
115 std::atomic<ServerState> m_state;
116
117 /* The state used in multiple threads when reseting server. */
118 enum ResetState : unsigned int
119 {
120 RS_NONE, // Default state
121 RS_WAITING, // Waiting for reseting finished
122 RS_ASYNC_RESET // Finished reseting server in main thread, now async
123 // thread
124 };
125
126 std::atomic<ResetState> m_rs_state;
127
130 std::weak_ptr<STKPeer> m_server_owner;
131
133 std::weak_ptr<STKPeer> m_ai_peer;
134
138 std::vector<std::shared_ptr<NetworkPlayerProfile> > m_ai_profiles;
139
140 std::atomic<uint32_t> m_server_owner_id;
141
143 std::pair<std::set<std::string>, std::set<std::string> > m_official_kts;
144
146 std::pair<std::set<std::string>, std::set<std::string> > m_addon_kts;
147
149 std::set<std::string> m_addon_arenas;
150
152 std::set<std::string> m_addon_soccers;
153
156 std::pair<std::set<std::string>, std::set<std::string> > m_available_kts;
157
160
161 bool m_registered_for_once_only;
162
163 bool m_save_server_config;
164
166 std::map<std::weak_ptr<STKPeer>, bool,
167 std::owner_less<std::weak_ptr<STKPeer> > > m_peers_ready;
168
169 std::map<std::weak_ptr<STKPeer>, std::set<irr::core::stringw>,
170 std::owner_less<std::weak_ptr<STKPeer> > > m_peers_muted_players;
171
172 std::weak_ptr<Online::Request> m_server_registering;
173
175 std::atomic<int64_t> m_timeout;
176
177 std::mutex m_keys_mutex;
178
179 std::map<uint32_t, KeyData> m_keys;
180
181 std::map<std::weak_ptr<STKPeer>,
182 std::pair<uint32_t, BareNetworkString>,
183 std::owner_less<std::weak_ptr<STKPeer> > > m_pending_connection;
184
185 std::map<std::string, uint64_t> m_pending_peer_connection;
186
187 /* Ranking related variables */
188 // If updating the base points, update the base points distribution in DB
189 const double BASE_RANKING_POINTS = 4000.0; // Given to a new player on 1st connection to a ranked server
190 const double BASE_RATING_DEVIATION = 1000.0; // Given to a new player on 1st connection to a ranked server
191 const double MIN_RATING_DEVIATION = 100.0; // A server cron job makes RD go up if a player is inactive
192 const double BASE_RD_PER_DISCONNECT = 15.0;
193 const double VAR_RD_PER_DISCONNECT = 3.0;
194 const double MAX_SCALING_TIME = 360.0;
195 const double BASE_POINTS_PER_SECOND = 0.18;
196 const double HANDICAP_OFFSET = 2000.0;
197
199 std::map<uint32_t, std::weak_ptr<NetworkPlayerProfile> > m_ranked_players;
200
202 std::map<uint32_t, double> m_raw_scores;
203
205 std::map<uint32_t, double> m_rating_deviations;
206
209 std::map<uint32_t, double> m_scores;
210
213 std::map<uint32_t, double> m_max_scores;
214
216 std::map<uint32_t, uint64_t> m_num_ranked_disconnects;
217
219 std::map<uint32_t, unsigned> m_num_ranked_races;
220
221 /* Saved the last game result */
222 NetworkString* m_result_ns;
223
224 /* Used to make sure clients are having same item list at start */
225 BareNetworkString* m_items_complete_state;
226
227 std::atomic<uint32_t> m_server_id_online;
228
229 std::atomic<uint32_t> m_client_server_host_id;
230
231 std::atomic<int> m_difficulty;
232
233 std::atomic<int> m_game_mode;
234
235 std::atomic<int> m_lobby_players;
236
237 std::atomic<int> m_current_ai_count;
238
239 std::atomic<uint64_t> m_last_success_poll_time;
240
241 uint64_t m_last_unsuccess_poll_time, m_server_started_at, m_server_delay;
242
243 // Default game settings if no one has ever vote, and save inside here for
244 // final vote (for live join)
245 PeerVote* m_default_vote;
246
247 int m_battle_hit_capture_limit;
248
249 float m_battle_time_limit;
250
251 unsigned m_item_seed;
252
253 uint32_t m_winner_peer_id;
254
255 uint64_t m_client_starting_time;
256
257 // Calculated before each game started
258 unsigned m_ai_count;
259
260 // connection management
261 void clientDisconnected(Event* event);
262 void connectionRequested(Event* event);
263 // kart selection
264 void kartSelectionRequested(Event* event);
265 // Track(s) votes
266 void handlePlayerVote(Event *event);
267 void playerFinishedResult(Event *event);
268 void registerServer(bool first_time);
271 void kickHost(Event* event);
272 void changeTeam(Event* event);
273 void handleChat(Event* event);
274 void unregisterServer(bool now,
275 std::weak_ptr<ServerLobby> sl = std::weak_ptr<ServerLobby>());
276 void updatePlayerList(bool update_when_reset_server = false);
277 void updateServerOwner();
278 void handleServerConfiguration(Event* event);
279 void updateTracksForMode();
280 bool checkPeersReady(bool ignore_ai_peer) const;
281 void resetPeersReady()
282 {
283 for (auto it = m_peers_ready.begin(); it != m_peers_ready.end();)
284 {
285 if (it->first.expired())
286 {
287 it = m_peers_ready.erase(it);
288 }
289 else
290 {
291 it->second = false;
292 it++;
293 }
294 }
295 }
296 void addPeerConnection(const std::string& addr_str)
297 {
298 m_pending_peer_connection[addr_str] = StkTime::getMonoTimeMs();
299 }
300 void removeExpiredPeerConnection()
301 {
302 // Remove connect to peer protocol running more than a 45 seconds
303 // (from stk addons poll server request),
304 for (auto it = m_pending_peer_connection.begin();
305 it != m_pending_peer_connection.end();)
306 {
307 if (StkTime::getMonoTimeMs() - it->second > 45000)
308 it = m_pending_peer_connection.erase(it);
309 else
310 it++;
311 }
312 }
313 void replaceKeys(std::map<uint32_t, KeyData>& new_keys)
314 {
315 std::lock_guard<std::mutex> lock(m_keys_mutex);
316 std::swap(m_keys, new_keys);
317 }
318 void handlePendingConnection();
319 void handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
320 BareNetworkString& data,
321 uint32_t online_id,
322 const irr::core::stringw& online_name,
323 bool is_pending_connection,
324 std::string country_code = "");
325 bool decryptConnectionRequest(std::shared_ptr<STKPeer> peer,
326 BareNetworkString& data,
327 const std::string& key,
328 const std::string& iv,
329 uint32_t online_id,
330 const irr::core::stringw& online_name,
331 const std::string& country_code);
332 bool handleAllVotes(PeerVote* winner, uint32_t* winner_peer_id);
333 void getRankingForPlayer(std::shared_ptr<NetworkPlayerProfile> p);
334 void submitRankingsToAddons();
335 void computeNewRankings();
336 void clearDisconnectedRankedPlayer();
337 double getModeFactor();
338 double getModeSpread();
339 double getTimeSpread(double time);
340 double getUncertaintySpread(uint32_t online_id);
341 double scalingValueForTime(double time);
342 double computeH2HResult(double player1_time, double player2_time);
343 double computeDataAccuracy(double player1_rd, double player2_rd,
344 double player1_scores, double player2_scores,
345 int player_count, bool handicap_used);
346 void checkRaceFinished();
347 void getHitCaptureLimit();
349 void resetServer();
350 void addWaitingPlayersToGame();
351 void changeHandicap(Event* event);
352 void handlePlayerDisconnection() const;
354 std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
355 NetworkString* getLoadWorldMessage(
356 std::vector<std::shared_ptr<NetworkPlayerProfile> >& players,
357 bool live_join) const;
358 void encodePlayers(BareNetworkString* bns,
359 std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
360 std::vector<std::shared_ptr<NetworkPlayerProfile> > getLivePlayers() const;
361 void setPlayerKarts(const NetworkString& ns, STKPeer* peer) const;
362 bool handleAssets(const NetworkString& ns, STKPeer* peer);
363 void handleServerCommand(Event* event, std::shared_ptr<STKPeer> peer);
364 void liveJoinRequest(Event* event);
365 void rejectLiveJoin(STKPeer* peer, BackLobbyReason blr);
366 bool canLiveJoinNow() const;
367 bool worldIsActive() const;
368 int getReservedId(std::shared_ptr<NetworkPlayerProfile>& p,
369 unsigned local_id) const;
370 void handleKartInfo(Event* event);
373 std::set<std::shared_ptr<STKPeer>> getSpectatorsByLimit();
374 void kickPlayerWithReason(STKPeer* peer, const char* reason) const;
375 void testBannedForIP(STKPeer* peer) const;
376 void testBannedForIPv6(STKPeer* peer) const;
377 void testBannedForOnlineId(STKPeer* peer, uint32_t online_id) const;
378 void writeDisconnectInfoTable(STKPeer* peer);
379 void writePlayerReport(Event* event);
380 bool supportsAI();
381 void updateAddons();
382public:
383 ServerLobby();
384 virtual ~ServerLobby();
385
386 virtual bool notifyEventAsynchronous(Event* event) OVERRIDE;
387 virtual bool notifyEvent(Event* event) OVERRIDE;
388 virtual void setup() OVERRIDE;
389 virtual void update(int ticks) OVERRIDE;
390 virtual void asynchronousUpdate() OVERRIDE;
391
392 void startSelection(const Event *event=NULL);
394 void finishedLoadingWorld() OVERRIDE;
395 ServerState getCurrentState() const { return m_state.load(); }
396 void updateBanList();
397 bool waitingForPlayers() const;
398 virtual bool allPlayersReady() const OVERRIDE
399 { return m_state.load() >= WAIT_FOR_RACE_STARTED; }
400 virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
401 bool allowJoinedPlayersWaiting() const;
402 void setSaveServerConfig(bool val) { m_save_server_config = val; }
403 float getStartupBoostOrPenaltyForKart(uint32_t ping, unsigned kart_id);
404 int getDifficulty() const { return m_difficulty.load(); }
405 int getGameMode() const { return m_game_mode.load(); }
406 int getLobbyPlayers() const { return m_lobby_players.load(); }
407 void saveInitialItems(std::shared_ptr<NetworkItemManager> nim);
408 void saveIPBanTable(const SocketAddress& addr);
409 void listBanTable();
410 void initServerStatsTable();
411 bool isAIProfile(const std::shared_ptr<NetworkPlayerProfile>& npp) const
412 {
413 return std::find(m_ai_profiles.begin(), m_ai_profiles.end(), npp) !=
414 m_ai_profiles.end();
415 }
416 uint32_t getServerIdOnline() const { return m_server_id_online; }
417 void setClientServerHostId(uint32_t id) { m_client_server_host_id = id; }
418 static int m_fixed_laps;
419}; // class ServerLobby
420
421#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
Base class for both client and server lobby. The lobbies are started when a server opens a game,...
Definition: lobby_protocol.hpp:47
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
Represents a peer. This class is used to interface the ENetPeer structure.
Definition: stk_peer.hpp:76
Definition: server_lobby.hpp:54
virtual void setup() OVERRIDE
A previous GameSetup is deleted and a new one is created.
Definition: server_lobby.cpp:708
double getModeSpread()
Returns the mode spread factor, used so that a similar difference in skill will result in a similar r...
Definition: server_lobby.cpp:3204
void computeNewRankings()
Compute the new player's rankings used in ranked servers.
Definition: server_lobby.cpp:2950
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:156
std::atomic_bool m_server_has_loaded_world
Keeps track of the server state.
Definition: server_lobby.hpp:159
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:4164
std::map< uint32_t, double > m_rating_deviations
The rating uncertainty for each current player.
Definition: server_lobby.hpp:205
void finishedLoadingWorldClient(Event *event)
Called when a client notifies the server that it has loaded the world.
Definition: server_lobby.cpp:4484
void updateTracksForMode()
Called whenever server is reset or game mode is changed.
Definition: server_lobby.cpp:629
void kartSelectionRequested(Event *event)
Called when a player asks to select karts.
Definition: server_lobby.cpp:4141
std::pair< std::set< std::string >, std::set< std::string > > m_addon_kts
Addon karts and tracks available in server.
Definition: server_lobby.hpp:146
std::map< uint32_t, unsigned > m_num_ranked_races
Number of ranked races done for each current players.
Definition: server_lobby.hpp:219
std::map< uint32_t, double > m_raw_scores
Multi-session rating for each current player.
Definition: server_lobby.hpp:202
std::map< uint32_t, double > m_max_scores
The maximum rating obtained for each current player.
Definition: server_lobby.hpp:213
double scalingValueForTime(double time)
Compute the scaling value of a given time This is linear to race duration, getTimeSpread takes care o...
Definition: server_lobby.cpp:3231
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:1990
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:1926
void handleServerConfiguration(Event *event)
Called when the server owner request to change game mode or difficulty.
Definition: server_lobby.cpp:5081
std::set< std::string > m_addon_arenas
Addon arenas available in server.
Definition: server_lobby.hpp:149
void changeHandicap(Event *event)
Called when a player want to change his handicap.
Definition: server_lobby.cpp:5189
void registerServer(bool first_time)
Register this server (i.e.
Definition: server_lobby.cpp:2297
void unregisterServer(bool now, std::weak_ptr< ServerLobby > sl=std::weak_ptr< ServerLobby >())
Unregister this server (i.e.
Definition: server_lobby.cpp:2390
std::vector< std::shared_ptr< NetworkPlayerProfile > > getLivePlayers() const
Get a list of current ingame players for live join or spectate.
Definition: server_lobby.cpp:1889
double getModeFactor()
Returns the mode race importance factor, used to make ranking move slower in more random modes.
Definition: server_lobby.cpp:3193
void clientInGameWantsToBackLobby(Event *event)
Client if currently in-game (including spectator) wants to go back to lobby.
Definition: server_lobby.cpp:5433
virtual bool notifyEvent(Event *event) OVERRIDE
Notify a protocol matching the Event type of that event.
Definition: server_lobby.cpp:759
void checkIncomingConnectionRequests()
Query the STK server for connection requests.
Definition: server_lobby.cpp:2742
void rejectLiveJoin(STKPeer *peer, BackLobbyReason blr)
STKPeer peer will be reset back to the lobby with reason BackLobbyReason blr
Definition: server_lobby.cpp:1795
void clientSelectingAssetsWantsToBackLobby(Event *event)
Client if currently select assets wants to go back to lobby.
Definition: server_lobby.cpp:5517
std::map< uint32_t, double > m_scores
A single number compounding "raw score" and RD, for rating display to players and rankings.
Definition: server_lobby.hpp:209
std::weak_ptr< STKPeer > m_ai_peer
AI peer which holds the list of reserved AI for dedicated server.
Definition: server_lobby.hpp:133
double getTimeSpread(double time)
Returns the time spread factor.
Definition: server_lobby.cpp:3221
void handleKartInfo(Event *event)
Tell the client RemoteKartInfo of a player when some player joining live.
Definition: server_lobby.cpp:5397
void checkRaceFinished()
Checks if the race is finished, and if so informs the clients and switches to state RESULT_DISPLAY,...
Definition: server_lobby.cpp:2873
virtual ~ServerLobby()
Destructor.
Definition: server_lobby.cpp:258
std::pair< std::set< std::string >, std::set< std::string > > m_official_kts
Official karts and tracks available in server.
Definition: server_lobby.hpp:143
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:4674
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:138
void startSelection(const Event *event=NULL)
Instructs all clients to start the kart selection.
Definition: server_lobby.cpp:2454
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:4266
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:1784
virtual void update(int ticks) OVERRIDE
Simple finite state machine.
Definition: server_lobby.cpp:2090
std::atomic< int64_t > m_timeout
Timeout counter for various state.
Definition: server_lobby.hpp:175
std::map< uint32_t, uint64_t > m_num_ranked_disconnects
Number of disconnects in the previous 64 ranked races for each current players.
Definition: server_lobby.hpp:216
void clientDisconnected(Event *event)
Called when a client disconnects.
Definition: server_lobby.cpp:3329
std::set< std::string > m_addon_soccers
Addon soccers available in server.
Definition: server_lobby.hpp:152
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:1815
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:5215
std::weak_ptr< STKPeer > m_server_owner
Hold the next connected peer for server owner if current one expired (disconnected).
Definition: server_lobby.hpp:130
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:3970
ServerLobby()
This is the central game setup protocol running in the server.
Definition: server_lobby.cpp:207
double computeDataAccuracy(double player1_rd, double player2_rd, double player1_scores, double player2_scores, int player_count, bool handicap_used)
Computes a relative factor indicating how much informative value the new race result gives us.
Definition: server_lobby.cpp:3292
void addLiveJoinPlaceholder(std::vector< std::shared_ptr< NetworkPlayerProfile > > &players) const
Add reserved players for live join later if required.
Definition: server_lobby.cpp:5292
virtual void asynchronousUpdate() OVERRIDE
Find out the public IP server or poll STK server asynchronously.
Definition: server_lobby.cpp:1397
std::map< uint32_t, std::weak_ptr< NetworkPlayerProfile > > m_ranked_players
Online id to profile map, handling disconnection in ranked server.
Definition: server_lobby.hpp:199
double computeH2HResult(double player1_time, double player2_time)
Computes the score of a head-to-head minimatch.
Definition: server_lobby.cpp:3242
void playerFinishedResult(Event *event)
Called when a client clicks on 'ok' on the race result screen.
Definition: server_lobby.cpp:4497
bool canLiveJoinNow() const
Returns true if server can be live joined or spectating.
Definition: server_lobby.cpp:1748
virtual bool notifyEventAsynchronous(Event *event) OVERRIDE
Notify a protocol matching the Event type of that event.
Definition: server_lobby.cpp:918
void finishedLoadingWorld() OVERRIDE
Called from the RaceManager of the server when the world is loaded.
Definition: server_lobby.cpp:4470
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:167
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:106
Definition: server_lobby.hpp:74