The Battle for Wesnoth  1.19.27+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"
19 #include "mt_rng.hpp"
22 #include "server/wesnothd/ban.hpp"
27 
28 #include "utils/optional_fwd.hpp"
29 
30 #include <boost/asio/steady_timer.hpp>
31 
32 #include <chrono>
33 #include <random>
34 
35 namespace wesnothd
36 {
37 
38 class server : public server_base
39 {
40 public:
41  server(int port, bool keep_alive, const std::string& config_file);
42 
43  // We keep this flag for coroutines. Since they get their stack unwinding done after player_connections_
44  // is already destroyed they need to know to avoid calling remove_player() on invalid iterators.
45  bool destructed = false;
46  ~server() {
47  destructed = true;
48  }
49 
50 private:
51  void handle_new_client(socket_ptr socket);
53 
54  template<class SocketPtr> void login_client(boost::asio::yield_context yield, SocketPtr socket);
55  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);
56  template<class SocketPtr> bool authenticate(SocketPtr socket, const std::string& username, const std::string& password, bool name_taken, bool& registered);
57  template<class SocketPtr> void send_password_request(SocketPtr socket, const std::string& msg, const char* error_code = "", bool force_confirmation = false);
58  bool accepting_connections() const { return !graceful_restart; }
59 
60  template<class SocketPtr> void handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player);
69  void cleanup_game(game*); // deleter for shared_ptr
75 
76 public:
77  template<class SocketPtr> void send_server_message(SocketPtr socket, const std::string& message, const std::string& type);
78  void send_server_message(player_iterator player, const std::string& message, const std::string& type) {
79  utils::visit(
80  [this, &message, &type](auto&& socket) { send_server_message(socket, message, type); },
81  player->socket()
82  );
83  }
84  void send_to_lobby(simple_wml::document& data, utils::optional<player_iterator> exclude = {});
86  utils::visit(
87  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
88  player->socket()
89  );
90  }
92  if(player_connections_.get<socket_t>().find(socket) != player_connections_.end())
93  {
94  utils::visit(
95  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
96  socket
97  );
98  }
99  }
100  void send_server_message_to_lobby(const std::string& message, utils::optional<player_iterator> exclude = {});
101  void send_server_message_to_all(const std::string& message, utils::optional<player_iterator> exclude = {});
102 
104  return player->get_game() != nullptr;
105  }
106 
107 private:
110 
112  {
113  std::string nick, ip;
114  std::chrono::system_clock::time_point log_off;
115 
116  bool operator==(const connection_log& c) const
117  {
118  // log off time does not matter to find ip-nick pairs
119  return c.nick == nick && c.ip == ip;
120  }
121  };
122 
123  std::deque<connection_log> ip_log_;
124 
125  struct login_log
126  {
127  std::string ip;
128  int attempts;
129  std::chrono::steady_clock::time_point first_attempt;
130 
131  bool operator==(const login_log& l) const
132  {
133  // only the IP matters
134  return l.ip == ip;
135  }
136  };
137 
138  struct queue_info
139  {
140  queue_info(int id, const std::string& name, int required, std::string addons, config game)
141  : id(id)
142  , display_name(name)
143  , players_required(required)
144  , players_in_queue()
145  , required_addons(addons)
146  , settings(game)
147  {
148 
149  }
150 
151  int id;
152  std::string display_name;
153  std::size_t players_required;
154  std::vector<std::string> players_in_queue;
155  std::string required_addons;
157  };
158 
159  std::deque<login_log> failed_logins_;
160 
161  std::unique_ptr<user_handler> user_handler_;
162 
163  std::mt19937 die_;
164 
165 #ifndef _WIN32
166  /** server socket/fifo. */
167  std::string input_path_;
168 #endif
169 
170  std::string uuid_;
171 
172  const std::string config_file_;
174 
175  /** Read the server config from file 'config_file_'. */
176  config read_config() const;
177 
178  // settings from the server config
179  std::vector<std::string> accepted_versions_;
180  std::string recommended_version_;
181  std::map<std::string,config> redirected_versions_;
182  std::map<std::string,config> proxy_versions_;
183  std::vector<std::string> disallowed_names_;
184  std::map<int, queue_info> queue_info_;
185  std::string admin_passwd_;
186  std::string motd_;
187  std::string announcements_;
188  std::string server_id_;
189  std::string tournaments_;
190  std::string information_;
192  std::chrono::seconds default_time_period_;
195  std::chrono::seconds lan_server_;
196  std::string restart_command;
197  std::size_t max_ip_log_size_;
200  std::string replay_save_path_;
202  std::set<std::string> client_sources_;
203  std::vector<std::string> tor_ip_list_;
205  std::chrono::seconds failed_login_ban_;
206  std::deque<login_log>::size_type failed_login_buffer_size_;
207 
208  /** Parse the server config into local variables. */
209  void load_config(bool reload);
210 
211  bool ip_exceeds_connection_limit(const std::string& ip) const;
212  utils::optional<server_base::login_ban_info> is_ip_banned(const std::string& ip);
213 
217 
219 
221 
222  std::deque<std::shared_ptr<game>> games() const
223  {
224  std::deque<std::shared_ptr<game>> result;
225 
226  for(const auto& iter : player_connections_.get<game_t>()) {
227  if(result.empty() || iter.get_game() != result.back()) {
228  result.push_back(iter.get_game());
229  }
230  }
231 
232  if(!result.empty() && result.front() == nullptr) {
233  result.pop_front();
234  }
235 
236  return result;
237  }
238 
239  boost::asio::steady_timer dump_stats_timer_;
240  void start_dump_stats();
241  void dump_stats(const boost::system::error_code& ec);
242 
243  boost::asio::steady_timer tournaments_timer_;
245  void refresh_tournaments(const boost::system::error_code& ec);
246 
247  /** Process commands from admins and users. */
248  std::string process_command(std::string cmd, std::string issuer_name);
249 
250  void delete_game(int, const std::string& reason="");
251 
252  void update_game_in_lobby(game& g, utils::optional<player_iterator> exclude = {});
253 
254  void start_new_server();
255 
256  void setup_fifo();
257 #ifndef _WIN32
258  void handle_read_from_fifo(const boost::system::error_code& error, std::size_t bytes_transferred);
259 #endif
260  void setup_handlers();
261 
262  typedef std::function<void(const std::string&, const std::string&, std::string&, std::ostringstream *)> cmd_handler;
263  std::map<std::string, cmd_handler> cmd_handlers_;
264 
265  void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
266  void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
267  void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
268  void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
269  void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
270  void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
271  void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
272  void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
273  void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
274  void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
275  void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
276  void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
277  void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
278  void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
279  void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
280  void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
281  void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
282  void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
283  void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
284  void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
285  void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
286  void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
287  void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
288  void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
289  void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
290  void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
291  void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
292  void stopgame_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
293  void reset_queues_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
294 
295 #ifndef _WIN32
296  void handle_sighup(const boost::system::error_code& error, int signal_number);
297 #endif
298 
299  boost::asio::steady_timer timer_;
300  void handle_graceful_timeout(const boost::system::error_code& error);
301 
302  boost::asio::steady_timer lan_server_timer_;
303  void start_lan_server_timer();
304  void abort_lan_server_timer();
305  void handle_lan_server_shutdown(const boost::system::error_code& error);
306 
307  boost::asio::steady_timer dummy_player_timer_;
308  std::chrono::seconds dummy_player_timer_interval_;
310  void dummy_player_updates(const boost::system::error_code& ec);
311 
312  void send_queue_update(const queue_info& queue, utils::optional<player_iterator> exclude = {});
313 };
314 
315 }
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:157
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:91
utils::optional< server_base::login_ban_info > is_ip_banned(const std::string &ip)
Definition: server.cpp:658
void update_game_in_lobby(game &g, utils::optional< player_iterator > exclude={})
Definition: server.cpp:3347
void send_to_lobby(simple_wml::document &data, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2343
int failed_login_limit_
Definition: server.hpp:204
void stopgame_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3260
std::unique_ptr< user_handler > user_handler_
Definition: server.hpp:161
void handle_leave_server_queue(player_iterator p, simple_wml::node &data)
Definition: server.cpp:1766
std::string uuid_
Definition: server.hpp:170
const std::string config_file_
Definition: server.hpp:172
boost::asio::steady_timer dummy_player_timer_
Definition: server.hpp:307
void handle_message(player_iterator player, simple_wml::node &message)
Definition: server.cpp:1452
void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3185
std::string motd_
Definition: server.hpp:186
bool graceful_restart
Definition: server.hpp:194
std::mt19937 die_
Definition: server.hpp:163
std::vector< std::string > disallowed_names_
Definition: server.hpp:183
void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2820
std::string information_
Definition: server.hpp:190
void setup_handlers()
Definition: server.cpp:384
void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2879
void start_dummy_player_updates()
Definition: server.cpp:693
void load_config(bool reload)
Parse the server config into local variables.
Definition: server.cpp:445
std::string input_path_
server socket/fifo.
Definition: server.hpp:167
void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3083
std::map< std::string, config > proxy_versions_
Definition: server.hpp:182
void handle_new_client(tls_socket_ptr socket)
void handle_sighup(const boost::system::error_code &error, int signal_number)
Definition: server.cpp:289
void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2539
std::chrono::seconds dummy_player_timer_interval_
Definition: server.hpp:308
std::string server_id_
Definition: server.hpp:188
void delete_game(int, const std::string &reason="")
Definition: server.cpp:3303
void refresh_tournaments(const boost::system::error_code &ec)
Definition: server.cpp:742
std::string recommended_version_
Definition: server.hpp:180
void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3018
void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2673
std::function< void(const std::string &, const std::string &, std::string &, std::ostringstream *)> cmd_handler
Definition: server.hpp:262
void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2628
bool save_replays_
Definition: server.hpp:199
void start_tournaments_timer()
Definition: server.cpp:736
std::string replay_save_path_
Definition: server.hpp:200
void handle_query(player_iterator player, simple_wml::node &query)
Definition: server.cpp:1331
void handle_player_in_game(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1788
std::string restart_command
Definition: server.hpp:196
void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2737
bool ip_exceeds_connection_limit(const std::string &ip) const
Definition: server.cpp:642
std::chrono::seconds failed_login_ban_
Definition: server.hpp:205
void handle_graceful_timeout(const boost::system::error_code &error)
Definition: server.cpp:302
void cleanup_game(game *)
Definition: server.cpp:1549
void handle_whisper(player_iterator player, simple_wml::node &whisper)
Definition: server.cpp:1291
metrics metrics_
Definition: server.hpp:218
void start_dump_stats()
Definition: server.cpp:675
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:920
void handle_new_client(socket_ptr socket)
Definition: server.cpp:754
void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2778
void send_queue_update(const queue_info &queue, utils::optional< player_iterator > exclude={})
Definition: server.cpp:1479
std::string announcements_
Definition: server.hpp:187
std::deque< connection_log > ip_log_
Definition: server.hpp:123
void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2854
void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3113
void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3240
void handle_join_server_queue(player_iterator p, simple_wml::node &data)
Definition: server.cpp:1690
void handle_join_game(player_iterator player, simple_wml::node &join)
Definition: server.cpp:1583
std::deque< login_log >::size_type failed_login_buffer_size_
Definition: server.hpp:206
void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2619
void send_server_message(SocketPtr socket, const std::string &message, const std::string &type)
Definition: server.cpp:2267
void handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player)
Definition: server.cpp:1168
player_connections player_connections_
Definition: server.hpp:220
simple_wml::document games_and_users_list_
Definition: server.hpp:216
void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2530
void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2558
void dump_stats(const boost::system::error_code &ec)
Definition: server.cpp:681
std::string tournaments_
Definition: server.hpp:189
void start_new_server()
Definition: server.cpp:2372
void remove_player(player_iterator player)
Definition: server.cpp:2291
boost::asio::steady_timer timer_
Definition: server.hpp:299
randomness::mt_rng rng_
Definition: server.hpp:109
void handle_read_from_fifo(const boost::system::error_code &error, std::size_t bytes_transferred)
Definition: server.cpp:355
server(int port, bool keep_alive, const std::string &config_file)
Definition: server.cpp:216
simple_wml::document login_response_
Definition: server.hpp:215
boost::asio::steady_timer tournaments_timer_
Definition: server.hpp:243
std::set< std::string > client_sources_
Definition: server.hpp:202
bool player_is_in_game(player_iterator player) const
Definition: server.hpp:103
void abort_lan_server_timer()
Definition: server.cpp:321
void send_server_message(player_iterator player, const std::string &message, const std::string &type)
Definition: server.hpp:78
void handle_lan_server_shutdown(const boost::system::error_code &error)
Definition: server.cpp:326
bool authenticate(SocketPtr socket, const std::string &username, const std::string &password, bool name_taken, bool &registered)
Definition: server.cpp:1044
void reset_queues_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3284
std::string admin_passwd_
Definition: server.hpp:185
void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3164
bool deny_unregistered_login_
Definition: server.hpp:198
std::vector< std::string > accepted_versions_
Definition: server.hpp:179
std::chrono::seconds lan_server_
Definition: server.hpp:195
void dummy_player_updates(const boost::system::error_code &ec)
Definition: server.cpp:699
void handle_create_game(player_iterator player, simple_wml::node &create_game)
Definition: server.cpp:1490
void send_server_message_to_lobby(const std::string &message, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2353
void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2942
void send_server_message_to_all(const std::string &message, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2363
void handle_nickserv(player_iterator player, simple_wml::node &nickserv)
Definition: server.cpp:1409
std::string process_command(std::string cmd, std::string issuer_name)
Process commands from admins and users.
Definition: server.cpp:2388
std::map< int, queue_info > queue_info_
Definition: server.hpp:184
void login_client(boost::asio::yield_context yield, SocketPtr socket)
Definition: server.cpp:773
void handle_ping(player_iterator player, simple_wml::node &nickserv)
Definition: server.cpp:1434
std::deque< login_log > failed_logins_
Definition: server.hpp:159
std::size_t default_max_messages_
Definition: server.hpp:191
std::size_t max_ip_log_size_
Definition: server.hpp:197
void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2474
void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2715
boost::asio::steady_timer lan_server_timer_
Definition: server.hpp:302
void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2443
std::map< std::string, config > redirected_versions_
Definition: server.hpp:181
void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2549
std::map< std::string, cmd_handler > cmd_handlers_
Definition: server.hpp:263
void setup_fifo()
Definition: server.cpp:334
void send_to_player(player_iterator player, simple_wml::document &data)
Definition: server.hpp:85
wesnothd::ban_manager ban_manager_
Definition: server.hpp:108
config read_config() const
Read the server config from file 'config_file_'.
Definition: server.cpp:428
bool accepting_connections() const
Definition: server.hpp:58
boost::asio::steady_timer dump_stats_timer_
Definition: server.hpp:239
void handle_player_in_lobby(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1236
std::vector< std::string > tor_ip_list_
Definition: server.hpp:203
void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2567
void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2610
std::deque< std::shared_ptr< game > > games() const
Definition: server.hpp:222
simple_wml::document version_query_response_
Definition: server.hpp:214
void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2758
std::size_t concurrent_connections_
Definition: server.hpp:193
void send_password_request(SocketPtr socket, const std::string &msg, const char *error_code="", bool force_confirmation=false)
Definition: server.cpp:1150
void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2509
void start_lan_server_timer()
Definition: server.cpp:315
void disconnect_player(player_iterator player)
Definition: server.cpp:2278
bool allow_remote_shutdown_
Definition: server.hpp:201
void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:3098
std::chrono::seconds default_time_period_
Definition: server.hpp:192
Definitions for the interface to Wesnoth Markup Language (WML).
Contains the general settings which have a default.
std::string join(const Range &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:116
std::chrono::system_clock::time_point log_off
Definition: server.hpp:114
bool operator==(const login_log &l) const
Definition: server.hpp:131
std::chrono::steady_clock::time_point first_attempt
Definition: server.hpp:129
queue_info(int id, const std::string &name, int required, std::string addons, config game)
Definition: server.hpp:140
std::size_t players_required
Definition: server.hpp:153
std::vector< std::string > players_in_queue
Definition: server.hpp:154
mock_char c
mock_party p