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 19 /*! \file stk_peer.hpp 20 * \brief Defines functions to easily manipulate 8-bit network destinated strings. 21 */ 22 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; 42 class NetworkPlayerProfile; 43 class NetworkString; 44 class STKHost; 45 class SocketAddress; 46 47 enum PeerDisconnectInfo : unsigned int 48 { 49 PDI_TIMEOUT = 0, //!< Timeout disconnected (default in enet). 50 PDI_NORMAL = 1, //!< Normal disconnction with acknowledgement 51 PDI_KICK = 2, //!< Kick disconnection 52 PDI_KICK_HIGH_PING = 3, //!< Too high ping, kicked by server 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, //!< Default, not spectating at all 67 ASM_COMMAND = 1, //!< Set by player through command 68 ASM_FULL = 2, //!< Set by server because too many players joined 69 }; // AlwaysSpectateMode 70 71 /*! \class STKPeer 72 * \brief Represents a peer. 73 * This class is used to interface the ENetPeer structure. 74 */ 75 class STKPeer : public NoCopy 76 { 77 protected: 78 /** Pointer to the corresponding ENet peer data structure. */ 79 ENetPeer* m_enet_peer; 80 81 ENetAddress m_address; 82 83 /** True if this peer is validated by server. */ 84 std::atomic_bool m_validated; 85 86 /** True if this peer is waiting for game. */ 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 97 /** Host id of this peer. */ 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 114 /** Available karts and tracks from this peer */ 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 129 /** List of client capabilities set when connecting it, to determine 130 * features available in same version. */ 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 // ------------------------------------------------------------------------ getPlayerProfiles()153 std::vector<std::shared_ptr<NetworkPlayerProfile> >& getPlayerProfiles() 154 { return m_players; } 155 // ------------------------------------------------------------------------ hasPlayerProfiles() const156 bool hasPlayerProfiles() const { return !m_players.empty(); } 157 // ------------------------------------------------------------------------ cleanPlayerProfiles()158 void cleanPlayerProfiles() { m_players.clear(); } 159 // ------------------------------------------------------------------------ addPlayer(std::shared_ptr<NetworkPlayerProfile> p)160 void addPlayer(std::shared_ptr<NetworkPlayerProfile> p) 161 { m_players.push_back(p); } 162 // ------------------------------------------------------------------------ setValidated(bool val)163 void setValidated(bool val) { m_validated.store(val); } 164 // ------------------------------------------------------------------------ 165 /** Returns if the client is validated by server. */ isValidated() const166 bool isValidated() const { return m_validated.load(); } 167 // ------------------------------------------------------------------------ 168 /** Returns the host id of this peer. */ getHostId() const169 uint32_t getHostId() const { return m_host_id; } 170 // ------------------------------------------------------------------------ getConnectedTime() const171 float getConnectedTime() const 172 { return float(StkTime::getMonoTimeMs() - m_connected_time) / 1000.0f; } 173 // ------------------------------------------------------------------------ setAvailableKartsTracks(std::set<std::string> & k,std::set<std::string> & t)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 // ------------------------------------------------------------------------ eraseServerKarts(const std::set<std::string> & server_karts,std::set<std::string> & karts_erase) const178 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 // ------------------------------------------------------------------------ eraseServerTracks(const std::set<std::string> & server_tracks,std::set<std::string> & tracks_erase) const193 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> > getClientAssets() const209 getClientAssets() const { return m_available_kts; } 210 // ------------------------------------------------------------------------ setPingInterval(uint32_t interval)211 void setPingInterval(uint32_t interval) 212 { enet_peer_ping_interval(m_enet_peer, interval); } 213 // ------------------------------------------------------------------------ 214 uint32_t getPing(); 215 // ------------------------------------------------------------------------ getCrypto() const216 Crypto* getCrypto() const { return m_crypto.get(); } 217 // ------------------------------------------------------------------------ 218 void setCrypto(std::unique_ptr<Crypto>&& c); 219 // ------------------------------------------------------------------------ getAveragePing() const220 uint32_t getAveragePing() const { return m_average_ping.load(); } 221 // ------------------------------------------------------------------------ getENetPeer() const222 ENetPeer* getENetPeer() const { return m_enet_peer; } 223 // ------------------------------------------------------------------------ setWaitingForGame(bool val)224 void setWaitingForGame(bool val) { m_waiting_for_game.store(val); } 225 // ------------------------------------------------------------------------ isWaitingForGame() const226 bool isWaitingForGame() const { return m_waiting_for_game.load(); } 227 // ------------------------------------------------------------------------ setSpectator(bool val)228 void setSpectator(bool val) { m_spectator.store(val); } 229 // ------------------------------------------------------------------------ isSpectator() const230 bool isSpectator() const { return m_spectator.load(); } 231 // ------------------------------------------------------------------------ isDisconnected() const232 bool isDisconnected() const { return m_disconnected.load(); } 233 // ------------------------------------------------------------------------ setDisconnected(bool val)234 void setDisconnected(bool val) { return m_disconnected.store(val); } 235 // ------------------------------------------------------------------------ hasWarnedForHighPing() const236 bool hasWarnedForHighPing() const { return m_warned_for_high_ping.load(); } 237 // ------------------------------------------------------------------------ setWarnedForHighPing(bool val)238 void setWarnedForHighPing(bool val) { m_warned_for_high_ping.store(val); } 239 // ------------------------------------------------------------------------ clearAvailableKartIDs()240 void clearAvailableKartIDs() { m_available_kart_ids.clear(); } 241 // ------------------------------------------------------------------------ addAvailableKartID(unsigned id)242 void addAvailableKartID(unsigned id) { m_available_kart_ids.insert(id); } 243 // ------------------------------------------------------------------------ availableKartID(unsigned id)244 bool availableKartID(unsigned id) 245 { return m_available_kart_ids.find(id) != m_available_kart_ids.end(); } 246 // ------------------------------------------------------------------------ getAvailableKartIDs() const247 const std::set<unsigned>& getAvailableKartIDs() const 248 { return m_available_kart_ids; } 249 // ------------------------------------------------------------------------ setUserVersion(const std::string & uv)250 void setUserVersion(const std::string& uv) { m_user_version = uv; } 251 // ------------------------------------------------------------------------ getUserVersion() const252 const std::string& getUserVersion() const { return m_user_version; } 253 // ------------------------------------------------------------------------ updateLastActivity()254 void updateLastActivity() 255 { m_last_activity.store((int64_t)StkTime::getMonoTimeMs()); } 256 // ------------------------------------------------------------------------ idleForSeconds() const257 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 // ------------------------------------------------------------------------ setClientCapabilities(std::set<std::string> & caps)266 void setClientCapabilities(std::set<std::string>& caps) 267 { m_client_capabilities = std::move(caps); } 268 // ------------------------------------------------------------------------ getClientCapabilities() const269 const std::set<std::string>& getClientCapabilities() const 270 { return m_client_capabilities; } 271 // ------------------------------------------------------------------------ isAIPeer() const272 bool isAIPeer() const { return m_user_version == "AI"; } 273 // ------------------------------------------------------------------------ setPacketLoss(int loss)274 void setPacketLoss(int loss) { m_packet_loss.store(loss); } 275 // ------------------------------------------------------------------------ getPacketLoss() const276 int getPacketLoss() const { return m_packet_loss.load(); } 277 // ------------------------------------------------------------------------ getAddonsScores() const278 const std::array<int, AS_TOTAL>& getAddonsScores() const 279 { return m_addons_scores; } 280 // ------------------------------------------------------------------------ setAddonsScores(const std::array<int,AS_TOTAL> & scores)281 void setAddonsScores(const std::array<int, AS_TOTAL>& scores) 282 { m_addons_scores = scores; } 283 // ------------------------------------------------------------------------ updateLastMessage()284 void updateLastMessage() 285 { m_last_message.store((int64_t)StkTime::getMonoTimeMs()); } 286 // ------------------------------------------------------------------------ getLastMessage() const287 int64_t getLastMessage() const 288 { return m_last_message; } 289 // ------------------------------------------------------------------------ updateConsecutiveMessages(bool too_fast)290 void updateConsecutiveMessages(bool too_fast) 291 { 292 if (too_fast) 293 m_consecutive_messages++; 294 else 295 m_consecutive_messages = 0; 296 } 297 // ------------------------------------------------------------------------ getConsecutiveMessages() const298 int getConsecutiveMessages() const { return m_consecutive_messages; } 299 // ------------------------------------------------------------------------ getAddress() const300 const SocketAddress& getAddress() const { return *m_socket_address.get(); } 301 // ------------------------------------------------------------------------ setAlwaysSpectate(AlwaysSpectateMode mode)302 void setAlwaysSpectate(AlwaysSpectateMode mode) 303 { m_always_spectate.store(mode); } 304 // ------------------------------------------------------------------------ alwaysSpectate() const305 bool alwaysSpectate() const 306 { return m_always_spectate.load() != ASM_NONE; } 307 // ------------------------------------------------------------------------ resetAlwaysSpectateFull()308 void resetAlwaysSpectateFull() 309 { 310 if (m_always_spectate.load() == ASM_FULL) 311 m_always_spectate.store(ASM_NONE); 312 } 313 }; // STKPeer 314 315 #endif // STK_PEER_HPP 316