The Battle for Wesnoth  1.19.11+dev
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
server.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2025
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"
26 
27 #include "utils/optional_fwd.hpp"
28 
29 #include <boost/asio/steady_timer.hpp>
30 
31 #include <chrono>
32 #include <random>
33 
34 namespace wesnothd
35 {
36 
37 class server : public server_base
38 {
39 public:
40  server(int port, bool keep_alive, const std::string& config_file);
41 
42  // We keep this flag for coroutines. Since they get their stack unwinding done after player_connections_
43  // is already destroyed they need to know to avoid calling remove_player() on invalid iterators.
44  bool destructed = false;
45  ~server() {
46  destructed = true;
47  }
48 
49 private:
50  void handle_new_client(socket_ptr socket);
52 
53  template<class SocketPtr> void login_client(boost::asio::yield_context yield, SocketPtr socket);
54  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);
55  template<class SocketPtr> bool authenticate(SocketPtr socket, const std::string& username, const std::string& password, bool name_taken, bool& registered);
56  template<class SocketPtr> void send_password_request(SocketPtr socket, const std::string& msg, const char* error_code = "", bool force_confirmation = false);
57  bool accepting_connections() const { return !graceful_restart; }
58 
59  template<class SocketPtr> void handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player);
67  void cleanup_game(game*); // deleter for shared_ptr
73 
74 public:
75  template<class SocketPtr> void send_server_message(SocketPtr socket, const std::string& message, const std::string& type);
76  void send_server_message(player_iterator player, const std::string& message, const std::string& type) {
77  utils::visit(
78  [this, &message, &type](auto&& socket) { send_server_message(socket, message, type); },
79  player->socket()
80  );
81  }
82  void send_to_lobby(simple_wml::document& data, utils::optional<player_iterator> exclude = {});
84  utils::visit(
85  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
86  player->socket()
87  );
88  }
90  if(player_connections_.get<socket_t>().find(socket) != player_connections_.end())
91  {
92  utils::visit(
93  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
94  socket
95  );
96  }
97  }
98  void send_server_message_to_lobby(const std::string& message, utils::optional<player_iterator> exclude = {});
99  void send_server_message_to_all(const std::string& message, utils::optional<player_iterator> exclude = {});
100 
102  return player->get_game() != nullptr;
103  }
104 
105 private:
107 
109  {
110  std::string nick, ip;
111  std::chrono::system_clock::time_point log_off;
112 
113  bool operator==(const connection_log& c) const
114  {
115  // log off time does not matter to find ip-nick pairs
116  return c.nick == nick && c.ip == ip;
117  }
118  };
119 
120  std::deque<connection_log> ip_log_;
121 
122  struct login_log
123  {
124  std::string ip;
125  int attempts;
126  std::chrono::steady_clock::time_point first_attempt;
127 
128  bool operator==(const login_log& l) const
129  {
130  // only the IP matters
131  return l.ip == ip;
132  }
133  };
134 
135  struct queue_info
136  {
137  queue_info(int id, const std::string& scenario_id, const std::string& name, int required, config game)
138  : id(id)
140  , display_name(name)
141  , players_required(required)
142  , players_in_queue()
143  , settings(game)
144  {
145 
146  }
147 
148  int id;
149  std::string scenario_id;
150  std::string display_name;
151  std::size_t players_required;
152  std::vector<std::string> players_in_queue;
154  };
155 
156  std::deque<login_log> failed_logins_;
157 
158  std::unique_ptr<user_handler> user_handler_;
159 
160  std::mt19937 die_;
161 
162 #ifndef _WIN32
163  /** server socket/fifo. */
164  std::string input_path_;
165 #endif
166 
167  std::string uuid_;
168 
169  const std::string config_file_;
171 
172  /** Read the server config from file 'config_file_'. */
173  config read_config() const;
174 
175  // settings from the server config
176  std::vector<std::string> accepted_versions_;
177  std::string recommended_version_;
178  std::map<std::string,config> redirected_versions_;
179  std::map<std::string,config> proxy_versions_;
180  std::vector<std::string> disallowed_names_;
181  std::map<int, queue_info> queue_info_;
182  std::string admin_passwd_;
183  std::string motd_;
184  std::string announcements_;
185  std::string server_id_;
186  std::string tournaments_;
187  std::string information_;
189  std::chrono::seconds default_time_period_;
192  std::chrono::seconds lan_server_;
193  std::string restart_command;
194  std::size_t max_ip_log_size_;
197  std::string replay_save_path_;
199  std::set<std::string> client_sources_;
200  std::vector<std::string> tor_ip_list_;
202  std::chrono::seconds failed_login_ban_;
203  std::deque<login_log>::size_type failed_login_buffer_size_;
204 
205  /** Parse the server config into local variables. */
206  void load_config(bool reload);
207 
208  bool ip_exceeds_connection_limit(const std::string& ip) const;
209  utils::optional<server_base::login_ban_info> is_ip_banned(const std::string& ip);
210 
214 
216 
218 
219  std::deque<std::shared_ptr<game>> games() const
220  {
221  std::deque<std::shared_ptr<game>> result;
222 
223  for(const auto& iter : player_connections_.get<game_t>()) {
224  if(result.empty() || iter.get_game() != result.back()) {
225  result.push_back(iter.get_game());
226  }
227  }
228 
229  if(!result.empty() && result.front() == nullptr) {
230  result.pop_front();
231  }
232 
233  return result;
234  }
235 
236  boost::asio::steady_timer dump_stats_timer_;
237  void start_dump_stats();
238  void dump_stats(const boost::system::error_code& ec);
239 
240  boost::asio::steady_timer tournaments_timer_;
242  void refresh_tournaments(const boost::system::error_code& ec);
243 
244  /** Process commands from admins and users. */
245  std::string process_command(std::string cmd, std::string issuer_name);
246 
247  void delete_game(int, const std::string& reason="");
248 
249  void update_game_in_lobby(game& g, utils::optional<player_iterator> exclude = {});
250 
251  void start_new_server();
252 
253  void setup_fifo();
254 #ifndef _WIN32
255  void handle_read_from_fifo(const boost::system::error_code& error, std::size_t bytes_transferred);
256 #endif
257  void setup_handlers();
258 
259  typedef std::function<void(const std::string&, const std::string&, std::string&, std::ostringstream *)> cmd_handler;
260  std::map<std::string, cmd_handler> cmd_handlers_;
261 
262  void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
263  void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
264  void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
265  void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
266  void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
267  void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
268  void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
269  void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
270  void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
271  void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
272  void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
273  void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
274  void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
275  void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
276  void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
277  void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
278  void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
279  void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
280  void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
281  void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
282  void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
283  void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
284  void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
285  void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
286  void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
287  void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
288  void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
289  void stopgame_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
290  void reset_queues_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
291 
292 #ifndef _WIN32
293  void handle_sighup(const boost::system::error_code& error, int signal_number);
294 #endif
295 
296  boost::asio::steady_timer timer_;
297  void handle_graceful_timeout(const boost::system::error_code& error);
298 
299  boost::asio::steady_timer lan_server_timer_;
300  void start_lan_server_timer();
301  void abort_lan_server_timer();
302  void handle_lan_server_shutdown(const boost::system::error_code& error);
303 
304  boost::asio::steady_timer dummy_player_timer_;
305  std::chrono::seconds dummy_player_timer_interval_;
307  void dummy_player_updates(const boost::system::error_code& ec);
308 
309  void send_queue_update(const queue_info& queue, utils::optional<player_iterator> exclude = {});
310 };
311 
312 }
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:158
Base class for implementing servers that use gzipped-WML network protocol.
Definition: server_base.hpp:81
void async_send_doc_queued(SocketPtr socket, simple_wml::document &doc)
High level wrapper for sending a WML document.
void send_to_player(any_socket_ptr socket, simple_wml::document &data)
Definition: server.hpp:89
utils::optional< server_base::login_ban_info > is_ip_banned(const std::string &ip)
Definition: server.cpp:650
void update_game_in_lobby(game &g, utils::optional< player_iterator > exclude={})
Definition: server.cpp:3307
void send_to_lobby(simple_wml::document &data, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2305
int failed_login_limit_
Definition: server.hpp:201
void stopgame_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3220
std::unique_ptr< user_handler > user_handler_
Definition: server.hpp:158
void handle_leave_server_queue(player_iterator p, simple_wml::node &data)
Definition: server.cpp:1725
std::string uuid_
Definition: server.hpp:167
const std::string config_file_
Definition: server.hpp:169
boost::asio::steady_timer dummy_player_timer_
Definition: server.hpp:304
void handle_message(player_iterator player, simple_wml::node &message)
Definition: server.cpp:1419
void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3147
std::string motd_
Definition: server.hpp:183
bool graceful_restart
Definition: server.hpp:191
std::mt19937 die_
Definition: server.hpp:160
std::vector< std::string > disallowed_names_
Definition: server.hpp:180
void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2782
std::string information_
Definition: server.hpp:187
void setup_handlers()
Definition: server.cpp:375
void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2841
void start_dummy_player_updates()
Definition: server.cpp:685
void load_config(bool reload)
Parse the server config into local variables.
Definition: server.cpp:436
std::string input_path_
server socket/fifo.
Definition: server.hpp:164
void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3045
std::map< std::string, config > proxy_versions_
Definition: server.hpp:179
void handle_new_client(tls_socket_ptr socket)
void handle_sighup(const boost::system::error_code &error, int signal_number)
Definition: server.cpp:280
void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2501
std::chrono::seconds dummy_player_timer_interval_
Definition: server.hpp:305
std::string server_id_
Definition: server.hpp:185
void delete_game(int, const std::string &reason="")
Definition: server.cpp:3263
void refresh_tournaments(const boost::system::error_code &ec)
Definition: server.cpp:734
std::string recommended_version_
Definition: server.hpp:177
void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2980
void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2635
std::function< void(const std::string &, const std::string &, std::string &, std::ostringstream *)> cmd_handler
Definition: server.hpp:259
void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2590
bool save_replays_
Definition: server.hpp:196
void start_tournaments_timer()
Definition: server.cpp:728
std::string replay_save_path_
Definition: server.hpp:197
void handle_query(player_iterator player, simple_wml::node &query)
Definition: server.cpp:1316
void handle_player_in_game(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1747
std::string restart_command
Definition: server.hpp:193
void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2699
bool ip_exceeds_connection_limit(const std::string &ip) const
Definition: server.cpp:634
std::chrono::seconds failed_login_ban_
Definition: server.hpp:202
void handle_graceful_timeout(const boost::system::error_code &error)
Definition: server.cpp:293
void cleanup_game(game *)
Definition: server.cpp:1512
void handle_whisper(player_iterator player, simple_wml::node &whisper)
Definition: server.cpp:1276
metrics metrics_
Definition: server.hpp:215
void start_dump_stats()
Definition: server.cpp:667
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:910
void handle_new_client(socket_ptr socket)
Definition: server.cpp:746
void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2740
void send_queue_update(const queue_info &queue, utils::optional< player_iterator > exclude={})
Definition: server.cpp:1446
std::string announcements_
Definition: server.hpp:184
std::deque< connection_log > ip_log_
Definition: server.hpp:120
void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2816
void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3075
void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3200
void handle_join_server_queue(player_iterator p, simple_wml::node &data)
Definition: server.cpp:1667
void handle_join_game(player_iterator player, simple_wml::node &join)
Definition: server.cpp:1546
std::deque< login_log >::size_type failed_login_buffer_size_
Definition: server.hpp:203
void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2581
void send_server_message(SocketPtr socket, const std::string &message, const std::string &type)
Definition: server.cpp:2230
void handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player)
Definition: server.cpp:1158
player_connections player_connections_
Definition: server.hpp:217
simple_wml::document games_and_users_list_
Definition: server.hpp:213
void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2492
void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2520
void dump_stats(const boost::system::error_code &ec)
Definition: server.cpp:673
std::string tournaments_
Definition: server.hpp:186
void start_new_server()
Definition: server.cpp:2334
void remove_player(player_iterator player)
Definition: server.cpp:2254
boost::asio::steady_timer timer_
Definition: server.hpp:296
void handle_read_from_fifo(const boost::system::error_code &error, std::size_t bytes_transferred)
Definition: server.cpp:346
server(int port, bool keep_alive, const std::string &config_file)
Definition: server.cpp:216
simple_wml::document login_response_
Definition: server.hpp:212
boost::asio::steady_timer tournaments_timer_
Definition: server.hpp:240
std::set< std::string > client_sources_
Definition: server.hpp:199
bool player_is_in_game(player_iterator player) const
Definition: server.hpp:101
void abort_lan_server_timer()
Definition: server.cpp:312
void send_server_message(player_iterator player, const std::string &message, const std::string &type)
Definition: server.hpp:76
void handle_lan_server_shutdown(const boost::system::error_code &error)
Definition: server.cpp:317
bool authenticate(SocketPtr socket, const std::string &username, const std::string &password, bool name_taken, bool &registered)
Definition: server.cpp:1034
void reset_queues_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3244
std::string admin_passwd_
Definition: server.hpp:182
void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3126
bool deny_unregistered_login_
Definition: server.hpp:195
std::vector< std::string > accepted_versions_
Definition: server.hpp:176
std::chrono::seconds lan_server_
Definition: server.hpp:192
void dummy_player_updates(const boost::system::error_code &ec)
Definition: server.cpp:691
void handle_create_game(player_iterator player, simple_wml::node &create_game)
Definition: server.cpp:1457
void send_server_message_to_lobby(const std::string &message, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2315
void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2904
void send_server_message_to_all(const std::string &message, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2325
void handle_nickserv(player_iterator player, simple_wml::node &nickserv)
Definition: server.cpp:1394
std::string process_command(std::string cmd, std::string issuer_name)
Process commands from admins and users.
Definition: server.cpp:2350
std::map< int, queue_info > queue_info_
Definition: server.hpp:181
void login_client(boost::asio::yield_context yield, SocketPtr socket)
Definition: server.cpp:765
std::deque< login_log > failed_logins_
Definition: server.hpp:156
std::size_t default_max_messages_
Definition: server.hpp:188
std::size_t max_ip_log_size_
Definition: server.hpp:194
void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2436
void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2677
boost::asio::steady_timer lan_server_timer_
Definition: server.hpp:299
void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2405
std::map< std::string, config > redirected_versions_
Definition: server.hpp:178
void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2511
std::map< std::string, cmd_handler > cmd_handlers_
Definition: server.hpp:260
void setup_fifo()
Definition: server.cpp:325
void send_to_player(player_iterator player, simple_wml::document &data)
Definition: server.hpp:83
wesnothd::ban_manager ban_manager_
Definition: server.hpp:106
config read_config() const
Read the server config from file 'config_file_'.
Definition: server.cpp:419
bool accepting_connections() const
Definition: server.hpp:57
boost::asio::steady_timer dump_stats_timer_
Definition: server.hpp:236
void handle_player_in_lobby(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1221
std::vector< std::string > tor_ip_list_
Definition: server.hpp:200
void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2529
void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2572
std::deque< std::shared_ptr< game > > games() const
Definition: server.hpp:219
simple_wml::document version_query_response_
Definition: server.hpp:211
void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2720
std::size_t concurrent_connections_
Definition: server.hpp:190
void send_password_request(SocketPtr socket, const std::string &msg, const char *error_code="", bool force_confirmation=false)
Definition: server.cpp:1140
void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2471
void start_lan_server_timer()
Definition: server.cpp:306
void disconnect_player(player_iterator player)
Definition: server.cpp:2241
bool allow_remote_shutdown_
Definition: server.hpp:198
void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3060
std::chrono::seconds default_time_period_
Definition: server.hpp:189
Definitions for the interface to Wesnoth Markup Language (WML).
Contains the general settings which have a default.
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:188
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:52
utils::variant< socket_ptr, tls_socket_ptr > any_socket_ptr
Definition: server_base.hpp:53
std::shared_ptr< boost::asio::ip::tcp::socket > socket_ptr
Definition: server_base.hpp:49
bool operator==(const connection_log &c) const
Definition: server.hpp:113
std::chrono::system_clock::time_point log_off
Definition: server.hpp:111
bool operator==(const login_log &l) const
Definition: server.hpp:128
std::chrono::steady_clock::time_point first_attempt
Definition: server.hpp:126
std::size_t players_required
Definition: server.hpp:151
queue_info(int id, const std::string &scenario_id, const std::string &name, int required, config game)
Definition: server.hpp:137
std::vector< std::string > players_in_queue
Definition: server.hpp:152
mock_char c
mock_party p