The Battle for Wesnoth  1.19.13+dev
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);
68  void cleanup_game(game*); // deleter for shared_ptr
74 
75 public:
76  template<class SocketPtr> void send_server_message(SocketPtr socket, const std::string& message, const std::string& type);
77  void send_server_message(player_iterator player, const std::string& message, const std::string& type) {
78  utils::visit(
79  [this, &message, &type](auto&& socket) { send_server_message(socket, message, type); },
80  player->socket()
81  );
82  }
83  void send_to_lobby(simple_wml::document& data, utils::optional<player_iterator> exclude = {});
85  utils::visit(
86  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
87  player->socket()
88  );
89  }
91  if(player_connections_.get<socket_t>().find(socket) != player_connections_.end())
92  {
93  utils::visit(
94  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
95  socket
96  );
97  }
98  }
99  void send_server_message_to_lobby(const std::string& message, utils::optional<player_iterator> exclude = {});
100  void send_server_message_to_all(const std::string& message, utils::optional<player_iterator> exclude = {});
101 
103  return player->get_game() != nullptr;
104  }
105 
106 private:
108 
110  {
111  std::string nick, ip;
112  std::chrono::system_clock::time_point log_off;
113 
114  bool operator==(const connection_log& c) const
115  {
116  // log off time does not matter to find ip-nick pairs
117  return c.nick == nick && c.ip == ip;
118  }
119  };
120 
121  std::deque<connection_log> ip_log_;
122 
123  struct login_log
124  {
125  std::string ip;
126  int attempts;
127  std::chrono::steady_clock::time_point first_attempt;
128 
129  bool operator==(const login_log& l) const
130  {
131  // only the IP matters
132  return l.ip == ip;
133  }
134  };
135 
136  struct queue_info
137  {
138  queue_info(int id, const std::string& scenario_id, const std::string& name, int required, config game)
139  : id(id)
141  , display_name(name)
142  , players_required(required)
143  , players_in_queue()
144  , settings(game)
145  {
146 
147  }
148 
149  int id;
150  std::string scenario_id;
151  std::string display_name;
152  std::size_t players_required;
153  std::vector<std::string> players_in_queue;
155  };
156 
157  std::deque<login_log> failed_logins_;
158 
159  std::unique_ptr<user_handler> user_handler_;
160 
161  std::mt19937 die_;
162 
163 #ifndef _WIN32
164  /** server socket/fifo. */
165  std::string input_path_;
166 #endif
167 
168  std::string uuid_;
169 
170  const std::string config_file_;
172 
173  /** Read the server config from file 'config_file_'. */
174  config read_config() const;
175 
176  // settings from the server config
177  std::vector<std::string> accepted_versions_;
178  std::string recommended_version_;
179  std::map<std::string,config> redirected_versions_;
180  std::map<std::string,config> proxy_versions_;
181  std::vector<std::string> disallowed_names_;
182  std::map<int, queue_info> queue_info_;
183  std::string admin_passwd_;
184  std::string motd_;
185  std::string announcements_;
186  std::string server_id_;
187  std::string tournaments_;
188  std::string information_;
190  std::chrono::seconds default_time_period_;
193  std::chrono::seconds lan_server_;
194  std::string restart_command;
195  std::size_t max_ip_log_size_;
198  std::string replay_save_path_;
200  std::set<std::string> client_sources_;
201  std::vector<std::string> tor_ip_list_;
203  std::chrono::seconds failed_login_ban_;
204  std::deque<login_log>::size_type failed_login_buffer_size_;
205 
206  /** Parse the server config into local variables. */
207  void load_config(bool reload);
208 
209  bool ip_exceeds_connection_limit(const std::string& ip) const;
210  utils::optional<server_base::login_ban_info> is_ip_banned(const std::string& ip);
211 
215 
217 
219 
220  std::deque<std::shared_ptr<game>> games() const
221  {
222  std::deque<std::shared_ptr<game>> result;
223 
224  for(const auto& iter : player_connections_.get<game_t>()) {
225  if(result.empty() || iter.get_game() != result.back()) {
226  result.push_back(iter.get_game());
227  }
228  }
229 
230  if(!result.empty() && result.front() == nullptr) {
231  result.pop_front();
232  }
233 
234  return result;
235  }
236 
237  boost::asio::steady_timer dump_stats_timer_;
238  void start_dump_stats();
239  void dump_stats(const boost::system::error_code& ec);
240 
241  boost::asio::steady_timer tournaments_timer_;
243  void refresh_tournaments(const boost::system::error_code& ec);
244 
245  /** Process commands from admins and users. */
246  std::string process_command(std::string cmd, std::string issuer_name);
247 
248  void delete_game(int, const std::string& reason="");
249 
250  void update_game_in_lobby(game& g, utils::optional<player_iterator> exclude = {});
251 
252  void start_new_server();
253 
254  void setup_fifo();
255 #ifndef _WIN32
256  void handle_read_from_fifo(const boost::system::error_code& error, std::size_t bytes_transferred);
257 #endif
258  void setup_handlers();
259 
260  typedef std::function<void(const std::string&, const std::string&, std::string&, std::ostringstream *)> cmd_handler;
261  std::map<std::string, cmd_handler> cmd_handlers_;
262 
263  void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
264  void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
265  void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
266  void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
267  void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
268  void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
269  void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
270  void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
271  void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
272  void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
273  void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
274  void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
275  void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
276  void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
277  void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
278  void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
279  void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
280  void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
281  void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
282  void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
283  void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
284  void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
285  void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
286  void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
287  void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
288  void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
289  void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
290  void stopgame_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
291  void reset_queues_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
292 
293 #ifndef _WIN32
294  void handle_sighup(const boost::system::error_code& error, int signal_number);
295 #endif
296 
297  boost::asio::steady_timer timer_;
298  void handle_graceful_timeout(const boost::system::error_code& error);
299 
300  boost::asio::steady_timer lan_server_timer_;
301  void start_lan_server_timer();
302  void abort_lan_server_timer();
303  void handle_lan_server_shutdown(const boost::system::error_code& error);
304 
305  boost::asio::steady_timer dummy_player_timer_;
306  std::chrono::seconds dummy_player_timer_interval_;
308  void dummy_player_updates(const boost::system::error_code& ec);
309 
310  void send_queue_update(const queue_info& queue, utils::optional<player_iterator> exclude = {});
311 };
312 
313 }
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(const 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:90
utils::optional< server_base::login_ban_info > is_ip_banned(const std::string &ip)
Definition: server.cpp:649
void update_game_in_lobby(game &g, utils::optional< player_iterator > exclude={})
Definition: server.cpp:3294
void send_to_lobby(simple_wml::document &data, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2292
int failed_login_limit_
Definition: server.hpp:202
void stopgame_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3207
std::unique_ptr< user_handler > user_handler_
Definition: server.hpp:159
void handle_leave_server_queue(player_iterator p, simple_wml::node &data)
Definition: server.cpp:1712
std::string uuid_
Definition: server.hpp:168
const std::string config_file_
Definition: server.hpp:170
boost::asio::steady_timer dummy_player_timer_
Definition: server.hpp:305
void handle_message(player_iterator player, simple_wml::node &message)
Definition: server.cpp:1440
void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3134
std::string motd_
Definition: server.hpp:184
bool graceful_restart
Definition: server.hpp:192
std::mt19937 die_
Definition: server.hpp:161
std::vector< std::string > disallowed_names_
Definition: server.hpp:181
void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2769
std::string information_
Definition: server.hpp:188
void setup_handlers()
Definition: server.cpp:374
void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2828
void start_dummy_player_updates()
Definition: server.cpp:684
void load_config(bool reload)
Parse the server config into local variables.
Definition: server.cpp:435
std::string input_path_
server socket/fifo.
Definition: server.hpp:165
void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3032
std::map< std::string, config > proxy_versions_
Definition: server.hpp:180
void handle_new_client(tls_socket_ptr socket)
void handle_sighup(const boost::system::error_code &error, int signal_number)
Definition: server.cpp:279
void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2488
std::chrono::seconds dummy_player_timer_interval_
Definition: server.hpp:306
std::string server_id_
Definition: server.hpp:186
void delete_game(int, const std::string &reason="")
Definition: server.cpp:3250
void refresh_tournaments(const boost::system::error_code &ec)
Definition: server.cpp:733
std::string recommended_version_
Definition: server.hpp:178
void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2967
void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2622
std::function< void(const std::string &, const std::string &, std::string &, std::ostringstream *)> cmd_handler
Definition: server.hpp:260
void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2577
bool save_replays_
Definition: server.hpp:197
void start_tournaments_timer()
Definition: server.cpp:727
std::string replay_save_path_
Definition: server.hpp:198
void handle_query(player_iterator player, simple_wml::node &query)
Definition: server.cpp:1319
void handle_player_in_game(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1734
std::string restart_command
Definition: server.hpp:194
void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2686
bool ip_exceeds_connection_limit(const std::string &ip) const
Definition: server.cpp:633
std::chrono::seconds failed_login_ban_
Definition: server.hpp:203
void handle_graceful_timeout(const boost::system::error_code &error)
Definition: server.cpp:292
void cleanup_game(game *)
Definition: server.cpp:1533
void handle_whisper(player_iterator player, simple_wml::node &whisper)
Definition: server.cpp:1279
metrics metrics_
Definition: server.hpp:216
void start_dump_stats()
Definition: server.cpp:666
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:908
void handle_new_client(socket_ptr socket)
Definition: server.cpp:745
void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2727
void send_queue_update(const queue_info &queue, utils::optional< player_iterator > exclude={})
Definition: server.cpp:1467
std::string announcements_
Definition: server.hpp:185
std::deque< connection_log > ip_log_
Definition: server.hpp:121
void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2803
void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3062
void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3187
void handle_join_server_queue(player_iterator p, simple_wml::node &data)
Definition: server.cpp:1654
void handle_join_game(player_iterator player, simple_wml::node &join)
Definition: server.cpp:1567
std::deque< login_log >::size_type failed_login_buffer_size_
Definition: server.hpp:204
void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2568
void send_server_message(SocketPtr socket, const std::string &message, const std::string &type)
Definition: server.cpp:2217
void handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player)
Definition: server.cpp:1156
player_connections player_connections_
Definition: server.hpp:218
simple_wml::document games_and_users_list_
Definition: server.hpp:214
void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2479
void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2507
void dump_stats(const boost::system::error_code &ec)
Definition: server.cpp:672
std::string tournaments_
Definition: server.hpp:187
void start_new_server()
Definition: server.cpp:2321
void remove_player(player_iterator player)
Definition: server.cpp:2241
boost::asio::steady_timer timer_
Definition: server.hpp:297
void handle_read_from_fifo(const boost::system::error_code &error, std::size_t bytes_transferred)
Definition: server.cpp:345
server(int port, bool keep_alive, const std::string &config_file)
Definition: server.cpp:215
simple_wml::document login_response_
Definition: server.hpp:213
boost::asio::steady_timer tournaments_timer_
Definition: server.hpp:241
std::set< std::string > client_sources_
Definition: server.hpp:200
bool player_is_in_game(player_iterator player) const
Definition: server.hpp:102
void abort_lan_server_timer()
Definition: server.cpp:311
void send_server_message(player_iterator player, const std::string &message, const std::string &type)
Definition: server.hpp:77
void handle_lan_server_shutdown(const boost::system::error_code &error)
Definition: server.cpp:316
bool authenticate(SocketPtr socket, const std::string &username, const std::string &password, bool name_taken, bool &registered)
Definition: server.cpp:1032
void reset_queues_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3231
std::string admin_passwd_
Definition: server.hpp:183
void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3113
bool deny_unregistered_login_
Definition: server.hpp:196
std::vector< std::string > accepted_versions_
Definition: server.hpp:177
std::chrono::seconds lan_server_
Definition: server.hpp:193
void dummy_player_updates(const boost::system::error_code &ec)
Definition: server.cpp:690
void handle_create_game(player_iterator player, simple_wml::node &create_game)
Definition: server.cpp:1478
void send_server_message_to_lobby(const std::string &message, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2302
void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2891
void send_server_message_to_all(const std::string &message, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2312
void handle_nickserv(player_iterator player, simple_wml::node &nickserv)
Definition: server.cpp:1397
std::string process_command(std::string cmd, std::string issuer_name)
Process commands from admins and users.
Definition: server.cpp:2337
std::map< int, queue_info > queue_info_
Definition: server.hpp:182
void login_client(boost::asio::yield_context yield, SocketPtr socket)
Definition: server.cpp:764
void handle_ping(player_iterator player, simple_wml::node &nickserv)
Definition: server.cpp:1422
std::deque< login_log > failed_logins_
Definition: server.hpp:157
std::size_t default_max_messages_
Definition: server.hpp:189
std::size_t max_ip_log_size_
Definition: server.hpp:195
void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2423
void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2664
boost::asio::steady_timer lan_server_timer_
Definition: server.hpp:300
void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2392
std::map< std::string, config > redirected_versions_
Definition: server.hpp:179
void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2498
std::map< std::string, cmd_handler > cmd_handlers_
Definition: server.hpp:261
void setup_fifo()
Definition: server.cpp:324
void send_to_player(player_iterator player, simple_wml::document &data)
Definition: server.hpp:84
wesnothd::ban_manager ban_manager_
Definition: server.hpp:107
config read_config() const
Read the server config from file 'config_file_'.
Definition: server.cpp:418
bool accepting_connections() const
Definition: server.hpp:57
boost::asio::steady_timer dump_stats_timer_
Definition: server.hpp:237
void handle_player_in_lobby(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1224
std::vector< std::string > tor_ip_list_
Definition: server.hpp:201
void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2516
void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2559
std::deque< std::shared_ptr< game > > games() const
Definition: server.hpp:220
simple_wml::document version_query_response_
Definition: server.hpp:212
void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2707
std::size_t concurrent_connections_
Definition: server.hpp:191
void send_password_request(SocketPtr socket, const std::string &msg, const char *error_code="", bool force_confirmation=false)
Definition: server.cpp:1138
void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2458
void start_lan_server_timer()
Definition: server.cpp:305
void disconnect_player(player_iterator player)
Definition: server.cpp:2228
bool allow_remote_shutdown_
Definition: server.hpp:199
void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3047
std::chrono::seconds default_time_period_
Definition: server.hpp:190
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:114
std::chrono::system_clock::time_point log_off
Definition: server.hpp:112
bool operator==(const login_log &l) const
Definition: server.hpp:129
std::chrono::steady_clock::time_point first_attempt
Definition: server.hpp:127
std::size_t players_required
Definition: server.hpp:152
queue_info(int id, const std::string &scenario_id, const std::string &name, int required, config game)
Definition: server.hpp:138
std::vector< std::string > players_in_queue
Definition: server.hpp:153
mock_char c
mock_party p