SuperTuxKart
database_connector.hpp
1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2024 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 #ifdef ENABLE_SQLITE3
20 
21 #ifndef DATABASE_CONNECTOR_HPP
22 #define DATABASE_CONNECTOR_HPP
23 
24 #include "utils/string_utils.hpp"
25 #include "utils/time.hpp"
26 
27 #include <functional>
28 #include <iostream>
29 #include <memory>
30 #include <sqlite3.h>
31 #include <string>
32 #include <vector>
33 
34 class SocketAddress;
35 class STKPeer;
37 
56 struct Binder;
57 
63 struct BinderCollection
64 {
65  std::vector<std::shared_ptr<Binder>> m_binders;
66 
67  std::function<void(sqlite3_stmt* stmt)> getBindFunction() const;
68 };
69 
87 struct Binder
88 {
89  std::weak_ptr<BinderCollection> m_collection;
90  std::string m_value;
91  std::string m_name;
92  bool m_use_null_if_empty;
93 
94  Binder(std::shared_ptr<BinderCollection> collection, std::string value,
95  std::string name = "", bool use_null_if_empty = false):
96  m_collection(collection), m_value(value),
97  m_name(name), m_use_null_if_empty(use_null_if_empty) {}
98 };
99 
100 std::ostream& operator << (std::ostream& os, const Binder& binder);
101 
107 class DatabaseConnector
108 {
109 private:
110  sqlite3* m_db;
111  std::string m_server_stats_table;
112  bool m_ip_ban_table_exists;
113  bool m_ipv6_ban_table_exists;
114  bool m_online_id_ban_table_exists;
115  bool m_ip_geolocation_table_exists;
116  bool m_ipv6_geolocation_table_exists;
117  bool m_player_reports_table_exists;
118  uint64_t m_last_poll_db_time;
119 
120 public:
122  struct IpBanTableData
123  {
124  int row_id;
125  uint32_t ip_start;
126  uint32_t ip_end;
127  std::string reason;
128  std::string description;
129  };
131  struct Ipv6BanTableData
132  {
133  int row_id;
134  std::string ipv6_cidr;
135  std::string reason;
136  std::string description;
137  };
139  struct OnlineIdBanTableData
140  {
141  int row_id;
142  uint32_t online_id;
143  std::string reason;
144  std::string description;
145  };
146  void initDatabase();
147  void destroyDatabase();
148 
149  bool easySQLQuery(const std::string& query,
150  std::vector<std::vector<std::string>>* output = nullptr,
151  std::function<void(sqlite3_stmt* stmt)> bind_function = nullptr,
152  std::string null_value = "") const;
153 
154  void checkTableExists(const std::string& table, bool& result);
155 
156  std::string ip2Country(const SocketAddress& addr) const;
157 
158  std::string ipv62Country(const SocketAddress& addr) const;
159 
160  static void upperIPv6SQL(sqlite3_context* context, int argc,
161  sqlite3_value** argv);
162  static void insideIPv6CIDRSQL(sqlite3_context* context, int argc,
163  sqlite3_value** argv);
164  void writeDisconnectInfoTable(STKPeer* peer);
165  void initServerStatsTable();
166  bool writeReport(
167  STKPeer* reporter, std::shared_ptr<NetworkPlayerProfile> reporter_npp,
168  STKPeer* reporting, std::shared_ptr<NetworkPlayerProfile> reporting_npp,
169  irr::core::stringw& info);
170  bool hasDatabase() const { return m_db != nullptr; }
171  bool hasServerStatsTable() const { return !m_server_stats_table.empty(); }
172  bool hasPlayerReportsTable() const
173  { return m_player_reports_table_exists; }
174  bool hasIpBanTable() const { return m_ip_ban_table_exists; }
175  bool hasIpv6BanTable() const { return m_ipv6_ban_table_exists; }
176  bool hasOnlineIdBanTable() const { return m_online_id_ban_table_exists; }
177  bool isTimeToPoll() const
178  { return StkTime::getMonoTimeMs() >= m_last_poll_db_time + 60000; }
179  void updatePollTime() { m_last_poll_db_time = StkTime::getMonoTimeMs(); }
180  std::vector<IpBanTableData> getIpBanTableData(uint32_t ip = 0) const;
181  std::vector<Ipv6BanTableData> getIpv6BanTableData(std::string ipv6 = "") const;
182  std::vector<OnlineIdBanTableData> getOnlineIdBanTableData(uint32_t online_id = 0) const;
183  void increaseIpBanTriggerCount(uint32_t ip_start, uint32_t ip_end) const;
184  void increaseIpv6BanTriggerCount(const std::string& ipv6_cidr) const;
185  void increaseOnlineIdBanTriggerCount(uint32_t online_id) const;
186  void clearOldReports();
187  void setDisconnectionTimes(std::vector<uint32_t>& present_hosts);
188  void saveAddressToIpBanTable(const SocketAddress& addr);
189  void onPlayerJoinQueries(std::shared_ptr<STKPeer> peer, uint32_t online_id,
190  unsigned player_count, const std::string& country_code);
191  void listBanTable();
192 };
193 
194 #endif // ifndef DATABASE_CONNECTOR_HPP
195 #endif // ifdef ENABLE_SQLITE3
Contains the profile of a player.
Definition: network_player_profile.hpp:42
Represents a peer. This class is used to interface the ENetPeer structure.
Definition: stk_peer.hpp:76
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