SuperTuxKart
Loading...
Searching...
No Matches
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
51class GameSetup;
52class LobbyProtocol;
53class Network;
55class NetworkString;
57class Server;
58class ServerLobby;
59class ChildLoop;
60class SocketAddress;
61class STKPeer;
62
63using namespace irr;
64
65enum ENetCommandType : unsigned int
66{
67 ECT_SEND_PACKET = 0,
68 ECT_DISCONNECT = 1,
69 ECT_RESET = 2
70};
71
73{
74private:
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
109
111 uint32_t m_host_id = 0;
112
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);
175public:
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 //-------------------------------------------------------------------------
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);
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
static STKHost * m_stk_host[PT_COUNT]
Singleton pointer to the instance.
Definition: stk_host.hpp:76
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 shutdown()
Called from the main thread when the network infrastructure is to be shut down.
Definition: stk_host.cpp:387
void mainLoop(ProcessType pt)
Thread function checking if data is received.
Definition: stk_host.cpp:793
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::shared_ptr< STKPeer > getServerPeerForClient() const
Return the only server peer for client.
Definition: stk_host.cpp:1327
void init()
Initialises the internal data structures and starts the protocol manager and the debug console.
Definition: stk_host.cpp:313
std::unique_ptr< SocketAddress > m_public_address
The public address found by stun (if WAN is used).
Definition: stk_host.hpp:131
void setPublicAddress(short family)
Set the public address using stun protocol.
Definition: stk_host.cpp:635
std::unique_ptr< SocketAddress > m_stun_ipv4
The public IPv4 address stun server used.
Definition: stk_host.hpp:137
void handleDirectSocketRequest(Network *direct_socket, std::shared_ptr< ServerLobby > sl, std::map< std::string, uint64_t > &ctp)
Handles a direct request given to a socket.
Definition: stk_host.cpp:1235
std::string m_public_ipv6_address
The public IPv6 address found by stun (if WAN is used).
Definition: stk_host.hpp:134
void sendPacketExcept(STKPeer *peer, NetworkString *data, bool reliable=true)
Sends data to all validated peers except the specified currently in game.
Definition: stk_host.cpp:1371
uint32_t m_host_id
Host id of this host.
Definition: stk_host.hpp:111
std::string getValidPublicAddress() const
Return an valid public IPv4 or IPv6 address with port, empty if both are unset, IPv6 will come first ...
Definition: stk_host.cpp:1603
static std::shared_ptr< LobbyProtocol > create(ChildLoop *cl=NULL)
Creates the STKHost.
Definition: stk_host.cpp:77
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
void disconnectAllPeers(bool timeout_waiting=false)
Disconnect all connected peers.
Definition: stk_host.cpp:738
void startListening()
Starts the listening of events from ENet.
Definition: stk_host.cpp:767
void updatePlayers(unsigned *ingame=NULL, unsigned *waiting=NULL, unsigned *total=NULL)
Update players count in server.
Definition: stk_host.cpp:1561
std::map< ENetPeer *, std::shared_ptr< STKPeer > > m_peers
The list of peers connected to this instance.
Definition: stk_host.hpp:102
static BareNetworkString getStunRequest(uint8_t *stun_tansaction_id)
Get the stun network string required for binding request.
Definition: stk_host.cpp:397
std::vector< std::tuple< ENetPeer *, ENetPacket *, uint32_t, ENetCommandType, ENetAddress > > m_enet_cmd
Let (atm enet_peer_send and enet_peer_disconnect) run in the listening thread.
Definition: stk_host.hpp:96
uint32_t getMyHostId() const
Returns the host id of this host.
Definition: stk_host.hpp:344
void sendPacketToAllPeers(NetworkString *data, bool reliable=true)
Sends data to all validated peers currently in game.
Definition: stk_host.cpp:1355
void sendPacketToAllPeersWith(std::function< bool(STKPeer *)> predicate, NetworkString *data, bool reliable=true)
Sends data to peers with custom rule.
Definition: stk_host.cpp:1392
const irr::core::stringw & getErrorMessage() const
Returns the last error (or "" if no error has happened).
Definition: stk_host.hpp:297
bool isClientServer() const
True if this is a client and server in graphics mode made by server creation screen.
Definition: stk_host.cpp:1595
bool requestedShutdown() const
Returns true if a shutdown of the network infrastructure was requested.
Definition: stk_host.hpp:302
void setErrorMessage(const irr::core::stringw &message)
Sets an error message for the gui.
Definition: stk_host.cpp:754
std::thread m_network_console
Network console thread.
Definition: stk_host.hpp:87
~STKHost()
Destructor.
Definition: stk_host.cpp:349
uint32_t m_next_unique_host_id
Next unique host id.
Definition: stk_host.hpp:108
Network * m_network
ENet host interfacing sockets.
Definition: stk_host.hpp:84
void stopListening()
Stops the listening of events from ENet.
Definition: stk_host.cpp:778
std::vector< std::shared_ptr< STKPeer > > getPeers() const
Returns a copied list of peers.
Definition: stk_host.hpp:313
std::vector< std::shared_ptr< NetworkPlayerProfile > > getPlayersForNewGame(bool *has_always_on_spectators=NULL) const
Get the players for starting a new game.
Definition: stk_host.cpp:1530
bool peerExists(const SocketAddress &peer_address)
Tells if a peer is known.
Definition: stk_host.cpp:1308
void sendToServer(NetworkString *data, bool reliable=true)
Sends a message from a client to the server.
Definition: stk_host.cpp:1408
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
void sendPacketToAllPeersInServer(NetworkString *data, bool reliable=true)
Sends data to all validated peers currently in server.
Definition: stk_host.cpp:1340
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
static STKHost * get()
Returns the instance of STKHost.
Definition: stk_host.hpp:185
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:54
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:106
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