SuperTuxKart
stk_host.hpp
Go to the documentation of this file.
1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2013-2015 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 
22 #ifndef STK_HOST_HPP
23 #define STK_HOST_HPP
24 
25 #include "utils/stk_process.hpp"
26 #include "utils/synchronised.hpp"
27 #include "utils/time.hpp"
28 
29 #include "irrString.h"
30 
31 // enet.h includes win32.h, which without lean_and_mean includes
32 // winspool.h, which defines MAX_PRIORITY as a macro, which then
33 // results in request_manager.hpp not being compilable.
34 #define WIN32_LEAN_AND_MEAN
35 #include <enet/enet.h>
36 
37 #include <atomic>
38 #include <cassert>
39 #include <cstring>
40 #include <list>
41 #include <functional>
42 #include <map>
43 #include <memory>
44 #include <mutex>
45 #include <set>
46 #include <thread>
47 #include <tuple>
48 #include <vector>
49 
50 class BareNetworkString;
51 class GameSetup;
52 class LobbyProtocol;
53 class Network;
55 class NetworkString;
57 class Server;
58 class ServerLobby;
59 class ChildLoop;
60 class SocketAddress;
61 class STKPeer;
62 
63 using namespace irr;
64 
65 enum ENetCommandType : unsigned int
66 {
67  ECT_SEND_PACKET = 0,
68  ECT_DISCONNECT = 1,
69  ECT_RESET = 2
70 };
71 
72 class STKHost
73 {
74 private:
76  static STKHost* m_stk_host[PT_COUNT];
77 
80 
81  std::thread m_client_loop_thread;
82 
85 
87  std::thread m_network_console;
88 
90  mutable std::mutex m_peers_mutex;
91 
94  std::vector<std::tuple</*peer receive*/ENetPeer*,
95  /*packet to send*/ENetPacket*, /*integer data*/uint32_t,
96  ENetCommandType, ENetAddress> > m_enet_cmd;
97 
99  std::mutex m_enet_cmd_mutex;
100 
102  std::map<ENetPeer*, std::shared_ptr<STKPeer> > m_peers;
103 
108  uint32_t m_next_unique_host_id = 0;
109 
111  uint32_t m_host_id = 0;
112 
114  std::thread m_listening_thread;
115 
118  std::atomic_bool m_shutdown;
119 
121  std::atomic_bool m_authorised;
122 
124  std::atomic<uint64_t> m_exit_timeout;
125 
128  irr::core::stringw m_error_message;
129 
131  std::unique_ptr<SocketAddress> m_public_address;
132 
135 
137  std::unique_ptr<SocketAddress> m_stun_ipv4;
138 
140  std::unique_ptr<SocketAddress> m_stun_ipv6;
141 
143 
144  std::atomic<uint32_t> m_client_ping;
145 
146  std::atomic<uint32_t> m_upload_speed;
147 
148  std::atomic<uint32_t> m_download_speed;
149 
150  std::atomic<uint32_t> m_players_in_game;
151 
152  std::atomic<uint32_t> m_players_waiting;
153 
154  std::atomic<uint32_t> m_total_players;
155 
156  std::atomic<int64_t> m_network_timer;
157 
158  std::unique_ptr<NetworkTimerSynchronizer> m_nts;
159 
160  // ------------------------------------------------------------------------
161  STKHost(bool server);
162  // ------------------------------------------------------------------------
163  ~STKHost();
164  // ------------------------------------------------------------------------
165  void init();
166  // ------------------------------------------------------------------------
167  void handleDirectSocketRequest(Network* direct_socket,
168  std::shared_ptr<ServerLobby> sl,
169  std::map<std::string, uint64_t>& ctp);
170  // ------------------------------------------------------------------------
171  void mainLoop(ProcessType pt);
172  // ------------------------------------------------------------------------
173  void getIPFromStun(int socket, const std::string& stun_address,
174  short family, SocketAddress* result);
175 public:
177  static bool m_enable_console;
178 
182  static std::shared_ptr<LobbyProtocol> create(ChildLoop* cl = NULL);
183  // ------------------------------------------------------------------------
185  static STKHost *get()
186  {
187  ProcessType pt = STKProcess::getType();
188  assert(m_stk_host[pt] != NULL);
189  return m_stk_host[pt];
190  } // get
191  // ------------------------------------------------------------------------
192  static STKHost *getByType(ProcessType pt)
193  {
194  assert(m_stk_host[pt] != NULL);
195  return m_stk_host[pt];
196  } // get
197  // ------------------------------------------------------------------------
198  static void destroy()
199  {
200  ProcessType pt = STKProcess::getType();
201  assert(m_stk_host[pt] != NULL);
202  delete m_stk_host[pt];
203  m_stk_host[pt] = NULL;
204  } // destroy
205  // ------------------------------------------------------------------------
207  static bool existHost()
208  { return m_stk_host[STKProcess::getType()] != NULL; }
209  // ------------------------------------------------------------------------
210  static void clear() { memset(m_stk_host, 0, sizeof(m_stk_host)); }
211  // ------------------------------------------------------------------------
212  const SocketAddress& getPublicAddress() const
213  { return *m_public_address.get(); }
214  // ------------------------------------------------------------------------
215  const std::string& getPublicIPv6Address() const
216  { return m_public_ipv6_address; }
217  // ------------------------------------------------------------------------
218  std::string getValidPublicAddress() const;
219  // ------------------------------------------------------------------------
220  const SocketAddress* getStunIPv4Address() const
221  { return m_stun_ipv4.get(); }
222  // ------------------------------------------------------------------------
223  const SocketAddress* getStunIPv6Address() const
224  { return m_stun_ipv6.get(); }
225  // ------------------------------------------------------------------------
226  uint16_t getPrivatePort() const;
227  // ------------------------------------------------------------------------
228  void setPublicAddress(short family);
229  // ------------------------------------------------------------------------
230  void disconnectAllPeers(bool timeout_waiting = false);
231  //-------------------------------------------------------------------------
240  {
241  m_shutdown.store(true);
242  } // requestExit
243  //-------------------------------------------------------------------------
244  void shutdown();
245  //-------------------------------------------------------------------------
246  void sendPacketToAllPeersInServer(NetworkString *data,
247  bool reliable = true);
248  // ------------------------------------------------------------------------
249  void sendPacketToAllPeers(NetworkString *data, bool reliable = true);
250  // ------------------------------------------------------------------------
251  void sendPacketToAllPeersWith(std::function<bool(STKPeer*)> predicate,
252  NetworkString* data, bool reliable = true);
253  // ------------------------------------------------------------------------
257  bool isAuthorisedToControl() const { return m_authorised.load(); }
258  // ------------------------------------------------------------------------
260  void setAuthorisedToControl(bool authorised)
261  { m_authorised.store(authorised); }
262  // ------------------------------------------------------------------------
263  std::vector<std::shared_ptr<NetworkPlayerProfile> >
264  getAllPlayerProfiles() const;
265  // ------------------------------------------------------------------------
266  std::set<uint32_t> getAllPlayerOnlineIds() const;
267  // ------------------------------------------------------------------------
268  std::shared_ptr<STKPeer> findPeerByHostId(uint32_t id) const;
269  // ------------------------------------------------------------------------
270  std::shared_ptr<STKPeer> findPeerByName(const core::stringw& name) const;
271  // ------------------------------------------------------------------------
272  void sendPacketExcept(STKPeer* peer, NetworkString *data,
273  bool reliable = true);
274  // ------------------------------------------------------------------------
275  void setupClient(int peer_count, int channel_limit,
276  uint32_t max_incoming_bandwidth,
277  uint32_t max_outgoing_bandwidth);
278  // ------------------------------------------------------------------------
279  void startListening();
280  // ------------------------------------------------------------------------
281  void stopListening();
282  // ------------------------------------------------------------------------
283  bool peerExists(const SocketAddress& peer_address);
284  // ------------------------------------------------------------------------
285  std::shared_ptr<STKPeer> getServerPeerForClient() const;
286  // ------------------------------------------------------------------------
287  void setErrorMessage(const irr::core::stringw &message);
288  // ------------------------------------------------------------------------
289  void addEnetCommand(ENetPeer* peer, ENetPacket* packet, uint32_t i,
290  ENetCommandType ect, ENetAddress ea)
291  {
292  std::lock_guard<std::mutex> lock(m_enet_cmd_mutex);
293  m_enet_cmd.emplace_back(peer, packet, i, ect, ea);
294  }
295  // ------------------------------------------------------------------------
297  const irr::core::stringw& getErrorMessage() const
298  { return m_error_message; }
299  // ------------------------------------------------------------------------
302  bool requestedShutdown() const { return m_shutdown.load(); }
303  // ------------------------------------------------------------------------
304  int receiveRawPacket(char *buffer, int buffer_len,
305  SocketAddress* sender, int max_tries = -1);
306  // ------------------------------------------------------------------------
307  void sendRawPacket(const BareNetworkString &buffer,
308  const SocketAddress& dst);
309  // ------------------------------------------------------------------------
310  Network* getNetwork() const { return m_network; }
311  // ------------------------------------------------------------------------
313  std::vector<std::shared_ptr<STKPeer> > getPeers() const
314  {
315  std::lock_guard<std::mutex> lock(m_peers_mutex);
316  std::vector<std::shared_ptr<STKPeer> > peers;
317  for (auto p : m_peers)
318  {
319  peers.push_back(p.second);
320  }
321  return peers;
322  }
323  // ------------------------------------------------------------------------
325  unsigned int getNextHostId() const
326  {
327  assert(m_next_unique_host_id >= 0);
328  return m_next_unique_host_id;
329  }
330  // ------------------------------------------------------------------------
331  void setNextHostId(uint32_t id) { m_next_unique_host_id = id; }
332  // ------------------------------------------------------------------------
334  unsigned int getPeerCount() const
335  {
336  std::lock_guard<std::mutex> lock(m_peers_mutex);
337  return (unsigned)m_peers.size();
338  }
339  // ------------------------------------------------------------------------
341  void setMyHostId(uint32_t my_host_id) { m_host_id = my_host_id; }
342  // ------------------------------------------------------------------------
344  uint32_t getMyHostId() const { return m_host_id; }
345  // ------------------------------------------------------------------------
346  void sendToServer(NetworkString *data, bool reliable = true);
347  // ------------------------------------------------------------------------
348  bool isClientServer() const;
349  // ------------------------------------------------------------------------
350  void initClientNetwork(ENetEvent& event, Network* new_network);
351  // ------------------------------------------------------------------------
352  std::map<uint32_t, uint32_t> getPeerPings()
353  { return m_peer_pings.getAtomic(); }
354  // ------------------------------------------------------------------------
355  uint32_t getClientPingToServer() const
356  { return m_client_ping.load(std::memory_order_relaxed); }
357  // ------------------------------------------------------------------------
358  NetworkTimerSynchronizer* getNetworkTimerSynchronizer() const
359  { return m_nts.get(); }
360  // ------------------------------------------------------------------------
361  uint64_t getNetworkTimer() const
362  { return StkTime::getMonoTimeMs() - m_network_timer.load(); }
363  // ------------------------------------------------------------------------
364  void setNetworkTimer(uint64_t ticks)
365  {
366  m_network_timer.store(
367  (int64_t)StkTime::getMonoTimeMs() - (int64_t)ticks);
368  }
369  // ------------------------------------------------------------------------
370  std::pair<int, int> getAllPlayersTeamInfo() const;
371  // ------------------------------------------------------------------------
372  /* Return upload speed in bytes per second. */
373  unsigned getUploadSpeed() const { return m_upload_speed.load(); }
374  // ------------------------------------------------------------------------
375  /* Return download speed in bytes per second. */
376  unsigned getDownloadSpeed() const { return m_download_speed.load(); }
377  // ------------------------------------------------------------------------
378  void updatePlayers(unsigned* ingame = NULL,
379  unsigned* waiting = NULL,
380  unsigned* total = NULL);
381  // ------------------------------------------------------------------------
382  uint32_t getPlayersInGame() const { return m_players_in_game.load(); }
383  // ------------------------------------------------------------------------
384  uint32_t getWaitingPlayers() const { return m_players_waiting.load(); }
385  // ------------------------------------------------------------------------
386  uint32_t getTotalPlayers() const { return m_total_players.load(); }
387  // ------------------------------------------------------------------------
388  std::vector<std::shared_ptr<NetworkPlayerProfile> >
389  getPlayersForNewGame(bool* has_always_on_spectators = NULL) const;
390  // ------------------------------------------------------------------------
391  void replaceNetwork(Network* new_network)
392  {
393  m_network = new_network;
394  }
395  // ------------------------------------------------------------------------
396  static BareNetworkString getStunRequest(uint8_t* stun_tansaction_id);
397  // ------------------------------------------------------------------------
398  ChildLoop* getChildLoop() const { return m_client_loop; }
399 }; // class STKHost
400 
401 #endif // STK_HOST_HPP
Describes a chain of 8-bit unsigned integers.
Definition: network_string.hpp:53
Definition: child_loop.hpp:34
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
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
Definition: network_timer_synchronizer.hpp:34
Definition: network.hpp:46
Represents the local host.
Definition: stk_host.hpp:73
static bool existHost()
Checks if the STKHost has been created.
Definition: stk_host.hpp:207
std::atomic_bool m_shutdown
Flag which is set from the protocol manager thread which triggers a shutdown of the STKHost (and the ...
Definition: stk_host.hpp:118
void setMyHostId(uint32_t my_host_id)
Sets the global host id of this host (client use).
Definition: stk_host.hpp:341
std::thread m_listening_thread
Id of thread listening to enet events.
Definition: stk_host.hpp:114
std::atomic_bool m_authorised
True if this local host is authorised to control a server.
Definition: stk_host.hpp:121
void requestShutdown()
Requests that the network infrastructure is to be shut down.
Definition: stk_host.hpp:239
unsigned int getNextHostId() const
Returns the next (unique) host id.
Definition: stk_host.hpp:325
unsigned int getPeerCount() const
Returns the number of currently connected peers.
Definition: stk_host.hpp:334
std::unique_ptr< SocketAddress > m_public_address
The public address found by stun (if WAN is used).
Definition: stk_host.hpp:131
std::unique_ptr< SocketAddress > m_stun_ipv4
The public IPv4 address stun server used.
Definition: stk_host.hpp:137
std::string m_public_ipv6_address
The public IPv6 address found by stun (if WAN is used).
Definition: stk_host.hpp:134
const irr::core::stringw & getErrorMessage() const
Returns the last error (or "" if no error has happened).
Definition: stk_host.hpp:297
std::mutex m_peers_mutex
Make sure the removing or adding a peer is thread-safe.
Definition: stk_host.hpp:90
static bool m_enable_console
If a network console should be started.
Definition: stk_host.hpp:177
std::atomic< uint64_t > m_exit_timeout
Use as a timeout to waiting a disconnect event when exiting.
Definition: stk_host.hpp:124
std::map< ENetPeer *, std::shared_ptr< STKPeer > > m_peers
The list of peers connected to this instance.
Definition: stk_host.hpp:102
uint32_t getMyHostId() const
Returns the host id of this host.
Definition: stk_host.hpp:344
static STKHost * get()
Returns the instance of STKHost.
Definition: stk_host.hpp:185
std::vector< std::shared_ptr< STKPeer > > getPeers() const
Returns a copied list of peers.
Definition: stk_host.hpp:313
bool requestedShutdown() const
Returns true if a shutdown of the network infrastructure was requested.
Definition: stk_host.hpp:302
std::thread m_network_console
Network console thread.
Definition: stk_host.hpp:87
Network * m_network
ENet host interfacing sockets.
Definition: stk_host.hpp:84
std::unique_ptr< SocketAddress > m_stun_ipv6
The public IPv6 address stun server used.
Definition: stk_host.hpp:140
ChildLoop * m_client_loop
Separate process of server instance.
Definition: stk_host.hpp:79
bool isAuthorisedToControl() const
Returns true if this client instance is allowed to control the server.
Definition: stk_host.hpp:257
void setAuthorisedToControl(bool authorised)
Sets if this local host is authorised to control the server.
Definition: stk_host.hpp:260
irr::core::stringw m_error_message
An error message, which is set by a protocol to be displayed in the GUI.
Definition: stk_host.hpp:128
std::mutex m_enet_cmd_mutex
Protect m_enet_cmd from multiple threads usage.
Definition: stk_host.hpp:99
Represents a peer. This class is used to interface the ENetPeer structure.
Definition: stk_peer.hpp:76
Definition: server_lobby.hpp:52
Definition: server.hpp:44
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
A variable that is automatically synchronised using pthreads mutex.
Definition: synchronised.hpp:28
TYPE getAtomic() const
Returns a copy of this variable.
Definition: synchronised.hpp:68