The Battle for Wesnoth  1.19.0-dev
server.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2024
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 #include "config.hpp"
21 #include "server/wesnothd/ban.hpp"
25 
26 #include <boost/asio/steady_timer.hpp>
27 
28 #include <optional>
29 #include <random>
30 
31 namespace wesnothd
32 {
33 
34 class server : public server_base
35 {
36 public:
37  server(int port, bool keep_alive, const std::string& config_file);
38 
39  // We keep this flag for coroutines. Since they get their stack unwinding done after player_connections_
40  // is already destroyed they need to know to avoid calling remove_player() on invalid iterators.
41  bool destructed = false;
42  ~server() {
43  destructed = true;
44  }
45 
46 private:
47  void handle_new_client(socket_ptr socket);
49 
50  template<class SocketPtr> void login_client(boost::asio::yield_context yield, SocketPtr socket);
51  template<class SocketPtr> bool is_login_allowed(boost::asio::yield_context yield, SocketPtr socket, const simple_wml::node* const login, const std::string& username, bool& registered, bool& is_moderator);
52  template<class SocketPtr> bool authenticate(SocketPtr socket, const std::string& username, const std::string& password, bool name_taken, bool& registered);
53  template<class SocketPtr> void send_password_request(SocketPtr socket, const std::string& msg, const char* error_code = "", bool force_confirmation = false);
54  bool accepting_connections() const { return !graceful_restart; }
55 
56  template<class SocketPtr> void handle_player(boost::asio::yield_context yield, SocketPtr socket, const player& player);
64  void cleanup_game(game*); // deleter for shared_ptr
68 
69 public:
70  template<class SocketPtr> void send_server_message(SocketPtr socket, const std::string& message, const std::string& type);
71  void send_server_message(player_iterator player, const std::string& message, const std::string& type) {
72  utils::visit(
73  [this, &message, &type](auto&& socket) { send_server_message(socket, message, type); },
74  player->socket()
75  );
76  }
77  void send_to_lobby(simple_wml::document& data, std::optional<player_iterator> exclude = {});
79  utils::visit(
80  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
81  player->socket()
82  );
83  }
84  void send_server_message_to_lobby(const std::string& message, std::optional<player_iterator> exclude = {});
85  void send_server_message_to_all(const std::string& message, std::optional<player_iterator> exclude = {});
86 
88  return player->get_game() != nullptr;
89  }
90 
91 private:
93 
95  {
96  std::string nick, ip;
97  std::time_t log_off;
98 
99  bool operator==(const connection_log& c) const
100  {
101  // log off time does not matter to find ip-nick pairs
102  return c.nick == nick && c.ip == ip;
103  }
104  };
105 
106  std::deque<connection_log> ip_log_;
107 
108  struct login_log
109  {
110  std::string ip;
111  int attempts;
112  std::time_t first_attempt;
113 
114  bool operator==(const login_log& l) const
115  {
116  // only the IP matters
117  return l.ip == ip;
118  }
119  };
120 
121  std::deque<login_log> failed_logins_;
122 
123  std::unique_ptr<user_handler> user_handler_;
124 
125  std::mt19937 die_;
126 
127 #ifndef _WIN32
128  /** server socket/fifo. */
129  std::string input_path_;
130 #endif
131 
132  std::string uuid_;
133 
134  const std::string config_file_;
136 
137  /** Read the server config from file 'config_file_'. */
138  config read_config() const;
139 
140  // settings from the server config
141  std::vector<std::string> accepted_versions_;
142  std::string recommended_version_;
143  std::map<std::string,config> redirected_versions_;
144  std::map<std::string,config> proxy_versions_;
145  std::vector<std::string> disallowed_names_;
146  std::string admin_passwd_;
147  std::string motd_;
148  std::string announcements_;
149  std::string server_id_;
150  std::string tournaments_;
151  std::string information_;
153  std::size_t default_time_period_;
156  std::time_t lan_server_;
157  std::time_t last_user_seen_time_;
158  std::string restart_command;
159  std::size_t max_ip_log_size_;
162  std::string replay_save_path_;
164  std::set<std::string> client_sources_;
165  std::vector<std::string> tor_ip_list_;
167  std::time_t failed_login_ban_;
168  std::deque<login_log>::size_type failed_login_buffer_size_;
169 
170  /** Parse the server config into local variables. */
171  void load_config();
172 
173  bool ip_exceeds_connection_limit(const std::string& ip) const;
174  std::string is_ip_banned(const std::string& ip);
175 
179 
181 
183 
184  std::deque<std::shared_ptr<game>> games() const
185  {
186  std::deque<std::shared_ptr<game>> result;
187 
188  for(const auto& iter : player_connections_.get<game_t>()) {
189  if(result.empty() || iter.get_game() != result.back()) {
190  result.push_back(iter.get_game());
191  }
192  }
193 
194  if(!result.empty() && result.front() == nullptr) {
195  result.pop_front();
196  }
197 
198  return result;
199  }
200 
201  boost::asio::steady_timer dump_stats_timer_;
202  void start_dump_stats();
203  void dump_stats(const boost::system::error_code& ec);
204 
205  boost::asio::steady_timer tournaments_timer_;
207  void refresh_tournaments(const boost::system::error_code& ec);
208 
209  /** Process commands from admins and users. */
210  std::string process_command(std::string cmd, std::string issuer_name);
211 
212  void delete_game(int, const std::string& reason="");
213 
214  void update_game_in_lobby(const game& g, std::optional<player_iterator> exclude = {});
215 
216  void start_new_server();
217 
218  void setup_fifo();
219 #ifndef _WIN32
220  void handle_read_from_fifo(const boost::system::error_code& error, std::size_t bytes_transferred);
221 #endif
222  void setup_handlers();
223 
224  typedef std::function<void(const std::string&, const std::string&, std::string&, std::ostringstream *)> cmd_handler;
225  std::map<std::string, cmd_handler> cmd_handlers_;
226 
227  void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
228  void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
229  void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
230  void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
231  void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
232  void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
233  void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
234  void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
235  void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
236  void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
237  void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
238  void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
239  void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
240  void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
241  void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
242  void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
243  void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
244  void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
245  void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
246  void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
247  void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
248  void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
249  void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
250  void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
251  void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
252  void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
253  void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
254  void stopgame(const std::string &, const std::string &, std::string &, std::ostringstream *);
255 
256 #ifndef _WIN32
257  void handle_sighup(const boost::system::error_code& error, int signal_number);
258 #endif
259 
260  boost::asio::steady_timer timer_;
261  void handle_graceful_timeout(const boost::system::error_code& error);
262 
263  boost::asio::steady_timer lan_server_timer_;
264  void start_lan_server_timer();
265  void abort_lan_server_timer();
266  void handle_lan_server_shutdown(const boost::system::error_code& error);
267 
268  boost::asio::steady_timer dummy_player_timer_;
271  void dummy_player_updates(const boost::system::error_code& ec);
272 };
273 
274 }
double g
Definition: astarsearch.cpp:63
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
Base class for implementing servers that use gzipped-WML network protocol.
Definition: server_base.hpp:80
void async_send_doc_queued(SocketPtr socket, simple_wml::document &doc)
High level wrapper for sending a WML document.
void send_server_message_to_all(const std::string &message, std::optional< player_iterator > exclude={})
Definition: server.cpp:2013
int failed_login_limit_
Definition: server.hpp:166
void handle_player(boost::asio::yield_context yield, SocketPtr socket, const player &player)
Definition: server.cpp:1051
std::time_t failed_login_ban_
Definition: server.hpp:167
std::unique_ptr< user_handler > user_handler_
Definition: server.hpp:123
std::string uuid_
Definition: server.hpp:132
const std::string config_file_
Definition: server.hpp:134
boost::asio::steady_timer dummy_player_timer_
Definition: server.hpp:268
void handle_message(player_iterator player, simple_wml::node &message)
Definition: server.cpp:1307
void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2835
std::string motd_
Definition: server.hpp:147
bool graceful_restart
Definition: server.hpp:155
std::mt19937 die_
Definition: server.hpp:125
std::vector< std::string > disallowed_names_
Definition: server.hpp:145
void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2470
std::string information_
Definition: server.hpp:151
void setup_handlers()
Definition: server.cpp:362
void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2529
void start_dummy_player_updates()
Definition: server.cpp:604
std::string input_path_
server socket/fifo.
Definition: server.hpp:129
void update_game_in_lobby(const game &g, std::optional< player_iterator > exclude={})
Definition: server.cpp:2974
void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2733
std::map< std::string, config > proxy_versions_
Definition: server.hpp:144
void handle_new_client(tls_socket_ptr socket)
void handle_sighup(const boost::system::error_code &error, int signal_number)
Definition: server.cpp:271
int dummy_player_timer_interval_
Definition: server.hpp:269
void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2189
std::string server_id_
Definition: server.hpp:149
void delete_game(int, const std::string &reason="")
Definition: server.cpp:2930
void refresh_tournaments(const boost::system::error_code &ec)
Definition: server.cpp:653
std::string recommended_version_
Definition: server.hpp:142
void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2668
void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2323
std::function< void(const std::string &, const std::string &, std::string &, std::ostringstream *)> cmd_handler
Definition: server.hpp:224
void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2278
bool save_replays_
Definition: server.hpp:161
void start_tournaments_timer()
Definition: server.cpp:647
std::string replay_save_path_
Definition: server.hpp:162
void handle_query(player_iterator player, simple_wml::node &query)
Definition: server.cpp:1204
std::size_t default_time_period_
Definition: server.hpp:153
void handle_player_in_game(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1490
std::string restart_command
Definition: server.hpp:158
void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2387
bool ip_exceeds_connection_limit(const std::string &ip) const
Definition: server.cpp:559
void handle_graceful_timeout(const boost::system::error_code &error)
Definition: server.cpp:284
void cleanup_game(game *)
Definition: server.cpp:1378
void handle_whisper(player_iterator player, simple_wml::node &whisper)
Definition: server.cpp:1164
metrics metrics_
Definition: server.hpp:180
void start_dump_stats()
Definition: server.cpp:586
bool is_login_allowed(boost::asio::yield_context yield, SocketPtr socket, const simple_wml::node *const login, const std::string &username, bool &registered, bool &is_moderator)
Definition: server.cpp:803
void handle_new_client(socket_ptr socket)
Definition: server.cpp:665
void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2428
std::string announcements_
Definition: server.hpp:148
std::deque< connection_log > ip_log_
Definition: server.hpp:106
void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2504
void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2763
void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2888
void handle_join_game(player_iterator player, simple_wml::node &join)
Definition: server.cpp:1412
std::deque< login_log >::size_type failed_login_buffer_size_
Definition: server.hpp:168
void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2269
void send_server_message(SocketPtr socket, const std::string &message, const std::string &type)
Definition: server.cpp:1925
void send_server_message_to_lobby(const std::string &message, std::optional< player_iterator > exclude={})
Definition: server.cpp:2003
player_connections player_connections_
Definition: server.hpp:182
simple_wml::document games_and_users_list_
Definition: server.hpp:178
void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2180
void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2208
void dump_stats(const boost::system::error_code &ec)
Definition: server.cpp:592
std::string tournaments_
Definition: server.hpp:150
void start_new_server()
Definition: server.cpp:2022
void remove_player(player_iterator player)
Definition: server.cpp:1949
boost::asio::steady_timer timer_
Definition: server.hpp:260
void handle_read_from_fifo(const boost::system::error_code &error, std::size_t bytes_transferred)
Definition: server.cpp:333
server(int port, bool keep_alive, const std::string &config_file)
Definition: server.cpp:206
simple_wml::document login_response_
Definition: server.hpp:177
boost::asio::steady_timer tournaments_timer_
Definition: server.hpp:205
std::string is_ip_banned(const std::string &ip)
Definition: server.cpp:575
std::set< std::string > client_sources_
Definition: server.hpp:164
bool player_is_in_game(player_iterator player) const
Definition: server.hpp:87
void abort_lan_server_timer()
Definition: server.cpp:303
void send_server_message(player_iterator player, const std::string &message, const std::string &type)
Definition: server.hpp:71
void handle_lan_server_shutdown(const boost::system::error_code &error)
Definition: server.cpp:308
bool authenticate(SocketPtr socket, const std::string &username, const std::string &password, bool name_taken, bool &registered)
Definition: server.cpp:927
std::string admin_passwd_
Definition: server.hpp:146
void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2814
void load_config()
Parse the server config into local variables.
Definition: server.cpp:424
bool deny_unregistered_login_
Definition: server.hpp:160
std::vector< std::string > accepted_versions_
Definition: server.hpp:141
void dummy_player_updates(const boost::system::error_code &ec)
Definition: server.cpp:610
void handle_create_game(player_iterator player, simple_wml::node &create_game)
Definition: server.cpp:1334
void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2592
void handle_nickserv(player_iterator player, simple_wml::node &nickserv)
Definition: server.cpp:1282
std::string process_command(std::string cmd, std::string issuer_name)
Process commands from admins and users.
Definition: server.cpp:2038
void login_client(boost::asio::yield_context yield, SocketPtr socket)
Definition: server.cpp:676
void stopgame(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2908
std::deque< login_log > failed_logins_
Definition: server.hpp:121
std::size_t default_max_messages_
Definition: server.hpp:152
std::size_t max_ip_log_size_
Definition: server.hpp:159
void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2124
void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2365
boost::asio::steady_timer lan_server_timer_
Definition: server.hpp:263
void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2093
std::map< std::string, config > redirected_versions_
Definition: server.hpp:143
void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2199
std::map< std::string, cmd_handler > cmd_handlers_
Definition: server.hpp:225
void setup_fifo()
Definition: server.cpp:316
void send_to_player(player_iterator player, simple_wml::document &data)
Definition: server.hpp:78
wesnothd::ban_manager ban_manager_
Definition: server.hpp:92
config read_config() const
Read the server config from file 'config_file_'.
Definition: server.cpp:405
bool accepting_connections() const
Definition: server.hpp:54
boost::asio::steady_timer dump_stats_timer_
Definition: server.hpp:201
void handle_player_in_lobby(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1119
std::vector< std::string > tor_ip_list_
Definition: server.hpp:165
void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2217
void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2260
std::time_t last_user_seen_time_
Definition: server.hpp:157
std::deque< std::shared_ptr< game > > games() const
Definition: server.hpp:184
simple_wml::document version_query_response_
Definition: server.hpp:176
void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2408
std::size_t concurrent_connections_
Definition: server.hpp:154
void send_password_request(SocketPtr socket, const std::string &msg, const char *error_code="", bool force_confirmation=false)
Definition: server.cpp:1033
void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2159
void start_lan_server_timer()
Definition: server.cpp:297
void send_to_lobby(simple_wml::document &data, std::optional< player_iterator > exclude={})
Definition: server.cpp:1993
void disconnect_player(player_iterator player)
Definition: server.cpp:1936
bool allow_remote_shutdown_
Definition: server.hpp:163
void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2748
std::time_t lan_server_
Definition: server.hpp:156
std::string password(const std::string &server, const std::string &login)
std::string login()
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
player_connections::const_iterator player_iterator
bmi::multi_index_container< player_record, bmi::indexed_by< bmi::ordered_unique< bmi::tag< socket_t >, bmi::const_mem_fun< player_record, const any_socket_ptr, &player_record::socket > >, bmi::hashed_unique< bmi::tag< name_t >, bmi::const_mem_fun< player_record, const std::string &, &player_record::name > >, bmi::ordered_non_unique< bmi::tag< game_t >, bmi::const_mem_fun< player_record, int, &player_record::game_id > > > > player_connections
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::string_view data
Definition: picture.cpp:194
Base class for servers using Wesnoth's WML over TCP protocol.
std::shared_ptr< boost::asio::ssl::stream< socket_ptr::element_type > > tls_socket_ptr
Definition: server_base.hpp:51
std::shared_ptr< boost::asio::ip::tcp::socket > socket_ptr
Definition: server_base.hpp:48
bool operator==(const connection_log &c) const
Definition: server.hpp:99
bool operator==(const login_log &l) const
Definition: server.hpp:114
mock_char c