SuperTuxKart
stk_peer.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 
23 #ifndef STK_PEER_HPP
24 #define STK_PEER_HPP
25 
26 #include "utils/no_copy.hpp"
27 #include "utils/time.hpp"
28 #include "utils/types.hpp"
29 
30 #include <enet/enet.h>
31 
32 #include <array>
33 #include <atomic>
34 #include <deque>
35 #include <memory>
36 #include <numeric>
37 #include <set>
38 #include <string>
39 #include <vector>
40 
41 class Crypto;
43 class NetworkString;
44 class STKHost;
45 class SocketAddress;
46 
47 enum PeerDisconnectInfo : unsigned int
48 {
50  PDI_NORMAL = 1,
51  PDI_KICK = 2,
53 }; // PeerDisconnectInfo
54 
55 enum AddonScore : int
56 {
57  AS_KART = 0,
58  AS_TRACK = 1,
59  AS_ARENA = 2,
60  AS_SOCCER = 3,
61  AS_TOTAL = 4,
62 }; // AddonScore
63 
64 enum AlwaysSpectateMode : uint8_t
65 {
66  ASM_NONE = 0,
68  ASM_FULL = 2,
69 }; // AlwaysSpectateMode
70 
75 class STKPeer : public NoCopy
76 {
77 protected:
79  ENetPeer* m_enet_peer;
80 
81  ENetAddress m_address;
82 
84  std::atomic_bool m_validated;
85 
87  std::atomic_bool m_waiting_for_game;
88 
89  std::atomic_bool m_spectator;
90 
91  std::atomic_bool m_disconnected;
92 
93  std::atomic_bool m_warned_for_high_ping;
94 
95  std::atomic<uint8_t> m_always_spectate;
96 
98  uint32_t m_host_id;
99 
100  std::unique_ptr<SocketAddress> m_socket_address;
101 
102  STKHost* m_host;
103 
104  std::vector<std::shared_ptr<NetworkPlayerProfile> > m_players;
105 
106  uint64_t m_connected_time;
107 
108  std::atomic<int64_t> m_last_activity;
109 
110  std::atomic<int64_t> m_last_message;
111 
112  int m_consecutive_messages;
113 
115  std::pair<std::set<std::string>, std::set<std::string> > m_available_kts;
116 
117  std::unique_ptr<Crypto> m_crypto;
118 
119  std::deque<uint32_t> m_previous_pings;
120 
121  std::atomic<uint32_t> m_average_ping;
122 
123  std::atomic<int> m_packet_loss;
124 
125  std::set<unsigned> m_available_kart_ids;
126 
127  std::string m_user_version;
128 
131  std::set<std::string> m_client_capabilities;
132 
133  std::array<int, AS_TOTAL> m_addons_scores;
134 public:
135  STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id);
136  // ------------------------------------------------------------------------
137  ~STKPeer();
138  // ------------------------------------------------------------------------
139  void sendPacket(NetworkString *data, bool reliable = true,
140  bool encrypted = true);
141  // ------------------------------------------------------------------------
142  void disconnect();
143  // ------------------------------------------------------------------------
144  void kick();
145  // ------------------------------------------------------------------------
146  void reset();
147  // ------------------------------------------------------------------------
148  bool isConnected() const;
149  // ------------------------------------------------------------------------
150  bool isSamePeer(const STKPeer* peer) const;
151  bool isSamePeer(const ENetPeer* peer) const;
152  // ------------------------------------------------------------------------
153  std::vector<std::shared_ptr<NetworkPlayerProfile> >& getPlayerProfiles()
154  { return m_players; }
155  // ------------------------------------------------------------------------
156  bool hasPlayerProfiles() const { return !m_players.empty(); }
157  // ------------------------------------------------------------------------
158  void cleanPlayerProfiles() { m_players.clear(); }
159  // ------------------------------------------------------------------------
160  void addPlayer(std::shared_ptr<NetworkPlayerProfile> p)
161  { m_players.push_back(p); }
162  // ------------------------------------------------------------------------
163  void setValidated(bool val) { m_validated.store(val); }
164  // ------------------------------------------------------------------------
166  bool isValidated() const { return m_validated.load(); }
167  // ------------------------------------------------------------------------
169  uint32_t getHostId() const { return m_host_id; }
170  // ------------------------------------------------------------------------
171  float getConnectedTime() const
172  { return float(StkTime::getMonoTimeMs() - m_connected_time) / 1000.0f; }
173  // ------------------------------------------------------------------------
174  void setAvailableKartsTracks(std::set<std::string>& k,
175  std::set<std::string>& t)
176  { m_available_kts = std::make_pair(std::move(k), std::move(t)); }
177  // ------------------------------------------------------------------------
178  void eraseServerKarts(const std::set<std::string>& server_karts,
179  std::set<std::string>& karts_erase) const
180  {
181  if (m_available_kts.first.empty())
182  return;
183  for (const std::string& server_kart : server_karts)
184  {
185  if (m_available_kts.first.find(server_kart) ==
186  m_available_kts.first.end())
187  {
188  karts_erase.insert(server_kart);
189  }
190  }
191  }
192  // ------------------------------------------------------------------------
193  void eraseServerTracks(const std::set<std::string>& server_tracks,
194  std::set<std::string>& tracks_erase) const
195  {
196  if (m_available_kts.second.empty())
197  return;
198  for (const std::string& server_track : server_tracks)
199  {
200  if (m_available_kts.second.find(server_track) ==
201  m_available_kts.second.end())
202  {
203  tracks_erase.insert(server_track);
204  }
205  }
206  }
207  // ------------------------------------------------------------------------
208  std::pair<std::set<std::string>, std::set<std::string> >
209  getClientAssets() const { return m_available_kts; }
210  // ------------------------------------------------------------------------
211  void setPingInterval(uint32_t interval)
212  { enet_peer_ping_interval(m_enet_peer, interval); }
213  // ------------------------------------------------------------------------
214  uint32_t getPing();
215  // ------------------------------------------------------------------------
216  Crypto* getCrypto() const { return m_crypto.get(); }
217  // ------------------------------------------------------------------------
218  void setCrypto(std::unique_ptr<Crypto>&& c);
219  // ------------------------------------------------------------------------
220  uint32_t getAveragePing() const { return m_average_ping.load(); }
221  // ------------------------------------------------------------------------
222  ENetPeer* getENetPeer() const { return m_enet_peer; }
223  // ------------------------------------------------------------------------
224  void setWaitingForGame(bool val) { m_waiting_for_game.store(val); }
225  // ------------------------------------------------------------------------
226  bool isWaitingForGame() const { return m_waiting_for_game.load(); }
227  // ------------------------------------------------------------------------
228  void setSpectator(bool val) { m_spectator.store(val); }
229  // ------------------------------------------------------------------------
230  bool isSpectator() const { return m_spectator.load(); }
231  // ------------------------------------------------------------------------
232  bool isDisconnected() const { return m_disconnected.load(); }
233  // ------------------------------------------------------------------------
234  void setDisconnected(bool val) { return m_disconnected.store(val); }
235  // ------------------------------------------------------------------------
236  bool hasWarnedForHighPing() const { return m_warned_for_high_ping.load(); }
237  // ------------------------------------------------------------------------
238  void setWarnedForHighPing(bool val) { m_warned_for_high_ping.store(val); }
239  // ------------------------------------------------------------------------
240  void clearAvailableKartIDs() { m_available_kart_ids.clear(); }
241  // ------------------------------------------------------------------------
242  void addAvailableKartID(unsigned id) { m_available_kart_ids.insert(id); }
243  // ------------------------------------------------------------------------
244  bool availableKartID(unsigned id)
245  { return m_available_kart_ids.find(id) != m_available_kart_ids.end(); }
246  // ------------------------------------------------------------------------
247  const std::set<unsigned>& getAvailableKartIDs() const
248  { return m_available_kart_ids; }
249  // ------------------------------------------------------------------------
250  void setUserVersion(const std::string& uv) { m_user_version = uv; }
251  // ------------------------------------------------------------------------
252  const std::string& getUserVersion() const { return m_user_version; }
253  // ------------------------------------------------------------------------
254  void updateLastActivity()
255  { m_last_activity.store((int64_t)StkTime::getMonoTimeMs()); }
256  // ------------------------------------------------------------------------
257  int idleForSeconds() const
258  {
259  int64_t diff =
260  (int64_t)StkTime::getMonoTimeMs() - m_last_activity.load();
261  if (diff < 0)
262  return 0;
263  return (int)(diff / 1000);
264  }
265  // ------------------------------------------------------------------------
266  void setClientCapabilities(std::set<std::string>& caps)
267  { m_client_capabilities = std::move(caps); }
268  // ------------------------------------------------------------------------
269  const std::set<std::string>& getClientCapabilities() const
270  { return m_client_capabilities; }
271  // ------------------------------------------------------------------------
272  bool isAIPeer() const { return m_user_version == "AI"; }
273  // ------------------------------------------------------------------------
274  void setPacketLoss(int loss) { m_packet_loss.store(loss); }
275  // ------------------------------------------------------------------------
276  int getPacketLoss() const { return m_packet_loss.load(); }
277  // ------------------------------------------------------------------------
278  const std::array<int, AS_TOTAL>& getAddonsScores() const
279  { return m_addons_scores; }
280  // ------------------------------------------------------------------------
281  void setAddonsScores(const std::array<int, AS_TOTAL>& scores)
282  { m_addons_scores = scores; }
283  // ------------------------------------------------------------------------
284  void updateLastMessage()
285  { m_last_message.store((int64_t)StkTime::getMonoTimeMs()); }
286  // ------------------------------------------------------------------------
287  int64_t getLastMessage() const
288  { return m_last_message; }
289  // ------------------------------------------------------------------------
290  void updateConsecutiveMessages(bool too_fast)
291  {
292  if (too_fast)
293  m_consecutive_messages++;
294  else
295  m_consecutive_messages = 0;
296  }
297  // ------------------------------------------------------------------------
298  int getConsecutiveMessages() const { return m_consecutive_messages; }
299  // ------------------------------------------------------------------------
300  const SocketAddress& getAddress() const { return *m_socket_address.get(); }
301  // ------------------------------------------------------------------------
302  void setAlwaysSpectate(AlwaysSpectateMode mode)
303  { m_always_spectate.store(mode); }
304  // ------------------------------------------------------------------------
305  AlwaysSpectateMode getAlwaysSpectate() const
306  { return (AlwaysSpectateMode)m_always_spectate.load(); }
307  // ------------------------------------------------------------------------
308  bool alwaysSpectate() const
309  { return m_always_spectate.load() != ASM_NONE; }
310  // ------------------------------------------------------------------------
311  void resetAlwaysSpectateFull()
312  {
313  if (m_always_spectate.load() == ASM_FULL)
314  m_always_spectate.store(ASM_NONE);
315  }
316 }; // STKPeer
317 
318 #endif // STK_PEER_HPP
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
Utility class, you can inherit from this class to disallow the assignment operator and copy construct...
Definition: no_copy.hpp:26
Represents the local host.
Definition: stk_host.hpp:73
Represents a peer. This class is used to interface the ENetPeer structure.
Definition: stk_peer.hpp:76
std::pair< std::set< std::string >, std::set< std::string > > m_available_kts
Available karts and tracks from this peer.
Definition: stk_peer.hpp:115
uint32_t getPing()
Returns the ping to this peer from host, it waits for 3 seconds for a stable ping returned by enet me...
Definition: stk_peer.cpp:165
bool isSamePeer(const STKPeer *peer) const
Returns if this STKPeer is the same as the given peer.
Definition: stk_peer.cpp:148
STKPeer(ENetPeer *enet_peer, STKHost *host, uint32_t host_id)
Constructor for an empty peer.
Definition: stk_peer.cpp:38
void reset()
Forcefully disconnects a peer (used by server).
Definition: stk_peer.cpp:89
void kick()
Kick this peer (used by server).
Definition: stk_peer.cpp:77
std::atomic_bool m_waiting_for_game
True if this peer is waiting for game.
Definition: stk_peer.hpp:87
void sendPacket(NetworkString *data, bool reliable=true, bool encrypted=true)
Sends a packet to this host.
Definition: stk_peer.cpp:103
bool isValidated() const
Returns if the client is validated by server.
Definition: stk_peer.hpp:166
bool isConnected() const
Returns if the peer is connected or not.
Definition: stk_peer.cpp:139
std::atomic_bool m_validated
True if this peer is validated by server.
Definition: stk_peer.hpp:84
std::set< std::string > m_client_capabilities
List of client capabilities set when connecting it, to determine features available in same version.
Definition: stk_peer.hpp:131
uint32_t m_host_id
Host id of this peer.
Definition: stk_peer.hpp:98
ENetPeer * m_enet_peer
Pointer to the corresponding ENet peer data structure.
Definition: stk_peer.hpp:79
uint32_t getHostId() const
Returns the host id of this peer.
Definition: stk_peer.hpp:169
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
PeerDisconnectInfo
Definition: stk_peer.hpp:48
@ PDI_TIMEOUT
Timeout disconnected (default in enet).
Definition: stk_peer.hpp:49
@ PDI_KICK
Kick disconnection.
Definition: stk_peer.hpp:51
@ PDI_NORMAL
Normal disconnction with acknowledgement.
Definition: stk_peer.hpp:50
@ PDI_KICK_HIGH_PING
Too high ping, kicked by server.
Definition: stk_peer.hpp:52
AlwaysSpectateMode
Definition: stk_peer.hpp:65
@ ASM_COMMAND
Set by player through command.
Definition: stk_peer.hpp:67
@ ASM_FULL
Set by server because too many players joined.
Definition: stk_peer.hpp:68
@ ASM_NONE
Default, not spectating at all.
Definition: stk_peer.hpp:66
Declares the general types that are used by the network.