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