The Battle for Wesnoth  1.19.7+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"
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
71 
72 public:
73  template<class SocketPtr> void send_server_message(SocketPtr socket, const std::string& message, const std::string& type);
74  void send_server_message(player_iterator player, const std::string& message, const std::string& type) {
75  utils::visit(
76  [this, &message, &type](auto&& socket) { send_server_message(socket, message, type); },
77  player->socket()
78  );
79  }
80  void send_to_lobby(simple_wml::document& data, utils::optional<player_iterator> exclude = {});
82  utils::visit(
83  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
84  player->socket()
85  );
86  }
88  if(player_connections_.get<socket_t>().find(socket) != player_connections_.end())
89  {
90  utils::visit(
91  [this, &data](auto&& socket) { async_send_doc_queued(socket, data); },
92  socket
93  );
94  }
95  }
96  void send_server_message_to_lobby(const std::string& message, utils::optional<player_iterator> exclude = {});
97  void send_server_message_to_all(const std::string& message, utils::optional<player_iterator> exclude = {});
98 
100  return player->get_game() != nullptr;
101  }
102 
103 private:
105 
107  {
108  std::string nick, ip;
109  std::chrono::system_clock::time_point log_off;
110 
111  bool operator==(const connection_log& c) const
112  {
113  // log off time does not matter to find ip-nick pairs
114  return c.nick == nick && c.ip == ip;
115  }
116  };
117 
118  std::deque<connection_log> ip_log_;
119 
120  struct login_log
121  {
122  std::string ip;
123  int attempts;
124  std::chrono::steady_clock::time_point first_attempt;
125 
126  bool operator==(const login_log& l) const
127  {
128  // only the IP matters
129  return l.ip == ip;
130  }
131  };
132 
133  std::deque<login_log> failed_logins_;
134 
135  std::unique_ptr<user_handler> user_handler_;
136 
137  std::mt19937 die_;
138 
139 #ifndef _WIN32
140  /** server socket/fifo. */
141  std::string input_path_;
142 #endif
143 
144  std::string uuid_;
145 
146  const std::string config_file_;
148 
149  /** Read the server config from file 'config_file_'. */
150  config read_config() const;
151 
152  // settings from the server config
153  std::vector<std::string> accepted_versions_;
154  std::string recommended_version_;
155  std::map<std::string,config> redirected_versions_;
156  std::map<std::string,config> proxy_versions_;
157  std::vector<std::string> disallowed_names_;
158  std::string admin_passwd_;
159  std::string motd_;
160  std::string announcements_;
161  std::string server_id_;
162  std::string tournaments_;
163  std::string information_;
165  std::chrono::seconds default_time_period_;
168  std::chrono::seconds lan_server_;
169  std::string restart_command;
170  std::size_t max_ip_log_size_;
173  std::string replay_save_path_;
175  std::set<std::string> client_sources_;
176  std::vector<std::string> tor_ip_list_;
178  std::chrono::seconds failed_login_ban_;
179  std::deque<login_log>::size_type failed_login_buffer_size_;
180 
181  /** Parse the server config into local variables. */
182  void load_config();
183 
184  bool ip_exceeds_connection_limit(const std::string& ip) const;
185  utils::optional<server_base::login_ban_info> is_ip_banned(const std::string& ip);
186 
190 
192 
194 
195  std::deque<std::shared_ptr<game>> games() const
196  {
197  std::deque<std::shared_ptr<game>> result;
198 
199  for(const auto& iter : player_connections_.get<game_t>()) {
200  if(result.empty() || iter.get_game() != result.back()) {
201  result.push_back(iter.get_game());
202  }
203  }
204 
205  if(!result.empty() && result.front() == nullptr) {
206  result.pop_front();
207  }
208 
209  return result;
210  }
211 
212  boost::asio::steady_timer dump_stats_timer_;
213  void start_dump_stats();
214  void dump_stats(const boost::system::error_code& ec);
215 
216  boost::asio::steady_timer tournaments_timer_;
218  void refresh_tournaments(const boost::system::error_code& ec);
219 
220  /** Process commands from admins and users. */
221  std::string process_command(std::string cmd, std::string issuer_name);
222 
223  void delete_game(int, const std::string& reason="");
224 
225  void update_game_in_lobby(game& g, utils::optional<player_iterator> exclude = {});
226 
227  void start_new_server();
228 
229  void setup_fifo();
230 #ifndef _WIN32
231  void handle_read_from_fifo(const boost::system::error_code& error, std::size_t bytes_transferred);
232 #endif
233  void setup_handlers();
234 
235  typedef std::function<void(const std::string&, const std::string&, std::string&, std::ostringstream *)> cmd_handler;
236  std::map<std::string, cmd_handler> cmd_handlers_;
237 
238  void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
239  void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
240  void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
241  void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
242  void stats_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
243  void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
244  void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
245  void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
246  void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
247  void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
248  void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
249  void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
250  void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
251  void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
252  void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
253  void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
254  void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
255  void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
256  void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
257  void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
258  void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
259  void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
260  void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
261  void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
262  void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
263  void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
264  void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *);
265  void stopgame(const std::string &, const std::string &, std::string &, std::ostringstream *);
266 
267 #ifndef _WIN32
268  void handle_sighup(const boost::system::error_code& error, int signal_number);
269 #endif
270 
271  boost::asio::steady_timer timer_;
272  void handle_graceful_timeout(const boost::system::error_code& error);
273 
274  boost::asio::steady_timer lan_server_timer_;
275  void start_lan_server_timer();
276  void abort_lan_server_timer();
277  void handle_lan_server_shutdown(const boost::system::error_code& error);
278 
279  boost::asio::steady_timer dummy_player_timer_;
280  std::chrono::seconds dummy_player_timer_interval_;
282  void dummy_player_updates(const boost::system::error_code& ec);
283 };
284 
285 }
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:172
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:87
utils::optional< server_base::login_ban_info > is_ip_banned(const std::string &ip)
Definition: server.cpp:586
void update_game_in_lobby(game &g, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2997
void send_to_lobby(simple_wml::document &data, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2016
int failed_login_limit_
Definition: server.hpp:177
std::unique_ptr< user_handler > user_handler_
Definition: server.hpp:135
std::string uuid_
Definition: server.hpp:144
const std::string config_file_
Definition: server.hpp:146
boost::asio::steady_timer dummy_player_timer_
Definition: server.hpp:279
void handle_message(player_iterator player, simple_wml::node &message)
Definition: server.cpp:1335
void searchlog_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2858
std::string motd_
Definition: server.hpp:159
bool graceful_restart
Definition: server.hpp:167
std::mt19937 die_
Definition: server.hpp:137
std::vector< std::string > disallowed_names_
Definition: server.hpp:157
void clones_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2493
std::string information_
Definition: server.hpp:163
void setup_handlers()
Definition: server.cpp:371
void ban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2552
void start_dummy_player_updates()
Definition: server.cpp:621
std::string input_path_
server socket/fifo.
Definition: server.hpp:141
void unban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2756
std::map< std::string, config > proxy_versions_
Definition: server.hpp:156
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:2212
std::chrono::seconds dummy_player_timer_interval_
Definition: server.hpp:280
std::string server_id_
Definition: server.hpp:161
void delete_game(int, const std::string &reason="")
Definition: server.cpp:2953
void refresh_tournaments(const boost::system::error_code &ec)
Definition: server.cpp:670
std::string recommended_version_
Definition: server.hpp:154
void gban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2691
void pm_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2346
std::function< void(const std::string &, const std::string &, std::string &, std::ostringstream *)> cmd_handler
Definition: server.hpp:235
void adminmsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2301
bool save_replays_
Definition: server.hpp:172
void start_tournaments_timer()
Definition: server.cpp:664
std::string replay_save_path_
Definition: server.hpp:173
void handle_query(player_iterator player, simple_wml::node &query)
Definition: server.cpp:1232
void handle_player_in_game(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1518
std::string restart_command
Definition: server.hpp:169
void lobbymsg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2410
bool ip_exceeds_connection_limit(const std::string &ip) const
Definition: server.cpp:570
std::chrono::seconds failed_login_ban_
Definition: server.hpp:178
void handle_graceful_timeout(const boost::system::error_code &error)
Definition: server.cpp:293
void cleanup_game(game *)
Definition: server.cpp:1406
void handle_whisper(player_iterator player, simple_wml::node &whisper)
Definition: server.cpp:1192
metrics metrics_
Definition: server.hpp:191
void start_dump_stats()
Definition: server.cpp:603
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:836
void handle_new_client(socket_ptr socket)
Definition: server.cpp:682
void status_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2451
std::string announcements_
Definition: server.hpp:160
std::deque< connection_log > ip_log_
Definition: server.hpp:118
void bans_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2527
void kick_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2786
void dul_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2911
void handle_join_game(player_iterator player, simple_wml::node &join)
Definition: server.cpp:1440
std::deque< login_log >::size_type failed_login_buffer_size_
Definition: server.hpp:179
void wml_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2292
void send_server_message(SocketPtr socket, const std::string &message, const std::string &type)
Definition: server.cpp:1948
void handle_player(boost::asio::yield_context yield, SocketPtr socket, player_iterator player)
Definition: server.cpp:1084
player_connections player_connections_
Definition: server.hpp:193
simple_wml::document games_and_users_list_
Definition: server.hpp:189
void help_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2203
void requests_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2231
void dump_stats(const boost::system::error_code &ec)
Definition: server.cpp:609
std::string tournaments_
Definition: server.hpp:162
void start_new_server()
Definition: server.cpp:2045
void remove_player(player_iterator player)
Definition: server.cpp:1972
boost::asio::steady_timer timer_
Definition: server.hpp:271
void handle_read_from_fifo(const boost::system::error_code &error, std::size_t bytes_transferred)
Definition: server.cpp:342
server(int port, bool keep_alive, const std::string &config_file)
Definition: server.cpp:216
simple_wml::document login_response_
Definition: server.hpp:188
boost::asio::steady_timer tournaments_timer_
Definition: server.hpp:216
std::set< std::string > client_sources_
Definition: server.hpp:175
bool player_is_in_game(player_iterator player) const
Definition: server.hpp:99
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:74
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:960
std::string admin_passwd_
Definition: server.hpp:158
void motd_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2837
void load_config()
Parse the server config into local variables.
Definition: server.cpp:435
bool deny_unregistered_login_
Definition: server.hpp:171
std::vector< std::string > accepted_versions_
Definition: server.hpp:153
std::chrono::seconds lan_server_
Definition: server.hpp:168
void dummy_player_updates(const boost::system::error_code &ec)
Definition: server.cpp:627
void handle_create_game(player_iterator player, simple_wml::node &create_game)
Definition: server.cpp:1362
void send_server_message_to_lobby(const std::string &message, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2026
void kickban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2615
void send_server_message_to_all(const std::string &message, utils::optional< player_iterator > exclude={})
Definition: server.cpp:2036
void handle_nickserv(player_iterator player, simple_wml::node &nickserv)
Definition: server.cpp:1310
std::string process_command(std::string cmd, std::string issuer_name)
Process commands from admins and users.
Definition: server.cpp:2061
void login_client(boost::asio::yield_context yield, SocketPtr socket)
Definition: server.cpp:701
void stopgame(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2931
std::deque< login_log > failed_logins_
Definition: server.hpp:133
std::size_t default_max_messages_
Definition: server.hpp:164
std::size_t max_ip_log_size_
Definition: server.hpp:170
void restart_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2147
void msg_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2388
boost::asio::steady_timer lan_server_timer_
Definition: server.hpp:274
void shut_down_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2116
std::map< std::string, config > redirected_versions_
Definition: server.hpp:155
void metrics_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2222
std::map< std::string, cmd_handler > cmd_handlers_
Definition: server.hpp:236
void setup_fifo()
Definition: server.cpp:325
void send_to_player(player_iterator player, simple_wml::document &data)
Definition: server.hpp:81
wesnothd::ban_manager ban_manager_
Definition: server.hpp:104
config read_config() const
Read the server config from file 'config_file_'.
Definition: server.cpp:414
bool accepting_connections() const
Definition: server.hpp:57
boost::asio::steady_timer dump_stats_timer_
Definition: server.hpp:212
void handle_player_in_lobby(player_iterator player, simple_wml::document &doc)
Definition: server.cpp:1147
std::vector< std::string > tor_ip_list_
Definition: server.hpp:176
void roll_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2240
void games_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2283
std::deque< std::shared_ptr< game > > games() const
Definition: server.hpp:195
simple_wml::document version_query_response_
Definition: server.hpp:187
void version_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2431
std::size_t concurrent_connections_
Definition: server.hpp:166
void send_password_request(SocketPtr socket, const std::string &msg, const char *error_code="", bool force_confirmation=false)
Definition: server.cpp:1066
void sample_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2182
void start_lan_server_timer()
Definition: server.cpp:306
void disconnect_player(player_iterator player)
Definition: server.cpp:1959
bool allow_remote_shutdown_
Definition: server.hpp:174
void ungban_handler(const std::string &, const std::string &, std::string &, std::ostringstream *)
Definition: server.cpp:2771
std::chrono::seconds default_time_period_
Definition: server.hpp:165
Definitions for the interface to Wesnoth Markup Language (WML).
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:178
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:111
std::chrono::system_clock::time_point log_off
Definition: server.hpp:109
bool operator==(const login_log &l) const
Definition: server.hpp:126
std::chrono::steady_clock::time_point first_attempt
Definition: server.hpp:124
mock_char c