The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
campaign_server.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2017 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
18 #include "server/server_base.hpp"
19 #include "server/simple_wml.hpp"
20 
21 #include "utils/functional.hpp"
22 #include <boost/unordered_map.hpp>
23 #include <boost/asio/steady_timer.hpp>
24 
25 #include <chrono>
26 
27 namespace campaignd {
28 
29 /**
30  * Legacy add-ons server.
31  */
32 class server : public server_base
33 {
34 public:
35  explicit server(const std::string& cfg_file);
36  server(const config& server) = delete;
37  ~server();
38 
39  server& operator=(const config& server) = delete;
40 
41 private:
42  /**
43  * Client request information object.
44  *
45  * Contains data and metadata associated with a single request from a
46  * remote add-ons client, in a light-weight format for passing to request
47  * handlers.
48  */
49  struct request
50  {
51  const std::string& cmd;
52  const config& cfg;
53 
56 
57  /**
58  * Constructor.
59  *
60  * @param reqcmd Request command.
61  * @param reqcfg Request WML body.
62  * @param reqsock Client socket that initiated the request.
63  *
64  * @note Neither @a reqcmd nor @a reqcfg are copied into instances, so
65  * they are required to exist for as long as every @a request
66  * instance that uses them.
67  */
68  request(const std::string& reqcmd,
69  const config& reqcfg,
70  socket_ptr reqsock)
71  : cmd(reqcmd)
72  , cfg(reqcfg)
73  , sock(reqsock)
74  , addr(client_address(sock))
75  {}
76  };
77 
78  typedef std::function<void (server*, const request& req)> request_handler;
79  typedef std::map<std::string, request_handler> request_handlers_table;
80 
83 
84  bool read_only_;
85  int compress_level_; /**< Used for add-on archives. */
86 
87  /** Default upload size limit in bytes. */
88  static const size_t default_document_size_limit = 100 * 1024 * 1024;
89 
90  std::map<std::string, std::string> hooks_;
91  request_handlers_table handlers_;
92 
94 
97 
98  boost::asio::basic_waitable_timer<std::chrono::steady_clock> flush_timer_;
99 
100  void handle_new_client(socket_ptr socket);
101  void handle_request(socket_ptr socket, std::shared_ptr<simple_wml::document> doc);
102 
103 #ifndef _WIN32
104  void handle_read_from_fifo(const boost::system::error_code& error, std::size_t bytes_transferred);
105 
106  void handle_sighup(const boost::system::error_code& error, int signal_number);
107 #endif
108 
109  /**
110  * Starts timer to write config to disk every ten minutes.
111  */
112  void flush_cfg();
113  void handle_flush(const boost::system::error_code& error);
114 
115  /**
116  * Reads the server configuration from WML.
117  */
118  void load_config();
119 
120  /**
121  * Writes the server configuration WML back to disk.
122  */
123  void write_config();
124 
125  /**
126  * Reads the add-ons upload blacklist from WML.
127  */
128  void load_blacklist();
129 
130  /**
131  * Fires a hook script.
132  */
133  void fire(const std::string& hook, const std::string& addon);
134 
135  /** Retrieves the contents of the [campaigns] WML node. */
136  const config& campaigns() const { return cfg_.child("campaigns"); }
137 
138  /** Retrieves the contents of the [campaigns] WML node. */
139  config& campaigns() { return cfg_.child("campaigns"); }
140 
141  /** Retrieves a campaign by id if found, or a null config otherwise. */
142  config& get_campaign(const std::string& id) { return campaigns().find_child("campaign", "name", id); }
143 
144  /** Retrieves the contents of the [server_info] WML node. */
145  const config& server_info() const { return cfg_.child("server_info"); }
146 
147  /** Retrieves the contents of the [server_info] WML node. */
148  config& server_info() { return cfg_.child("server_info"); }
149 
150  //
151  // Request handling.
152  //
153 
154  /**
155  * Registers client request handlers.
156  *
157  * This is called by the class constructor. Individual handlers must be
158  * methods of this class that take a single parameter of type @a request
159  * and they are registered using the @a register_handler method.
160  *
161  * When adding new handlers, make sure to update the implementation of
162  * this method accordingly so they are recognized and invoked at runtime.
163  */
164  void register_handlers();
165 
166  void handle_request_campaign_list(const request&);
167  void handle_request_campaign(const request&);
168  void handle_request_terms(const request&);
169  void handle_upload(const request&);
170  void handle_delete(const request&);
171  void handle_change_passphrase(const request&);
172 
173  /**
174  * Send a client an informational message.
175  *
176  * The WML sent consists of a document containing a single @p [message]
177  * child with a @a message attribute holding the value of @a msg.
178  */
179  void send_message(const std::string& msg, socket_ptr sock);
180 
181  /**
182  * Send a client an error message.
183  *
184  * The WML sent consists of a document containing a single @p [error] child
185  * with a @a message attribute holding the value of @a msg. In addition to
186  * sending the error to the client, a line with the client IP and message
187  * is recorded to the server log.
188  */
189  void send_error(const std::string& msg, socket_ptr sock);
190 
191  /**
192  * Send a client an error message.
193  *
194  * The WML sent consists of a document containing a single @p [error] child
195  * with a @a message attribute holding the value of @a msg, and an
196  * @a extra_data attribute holding the value of @a extra_data. In addition
197  * to sending the error to the client, a line with the client IP and
198  * message is recorded to the server log.
199  */
200  void send_error(const std::string& msg, const std::string& extra_data, socket_ptr sock);
201 };
202 
203 } // end namespace campaignd
std::string feedback_url_format_
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:352
std::vector< char_t > string
Legacy add-ons server.
void handle_request_terms(const request &)
void handle_flush(const boost::system::error_code &error)
config & find_child(config_key_type key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Definition: config.cpp:715
void handle_request(socket_ptr socket, std::shared_ptr< simple_wml::document > doc)
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:39
void handle_delete(const request &)
Client request information object.
void load_config()
Reads the server configuration from WML.
request(const std::string &reqcmd, const config &reqcfg, socket_ptr reqsock)
Constructor.
config & campaigns()
Retrieves the contents of the [campaigns] WML node.
const config & server_info() const
Retrieves the contents of the [server_info] WML node.
server & operator=(const config &server)=delete
void fire(const std::string &hook, const std::string &addon)
Fires a hook script.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
request_handlers_table handlers_
std::map< std::string, std::string > hooks_
void load_blacklist()
Reads the add-ons upload blacklist from WML.
void register_handlers()
Registers client request handlers.
const std::string cfg_file_
std::string client_address(socket_ptr socket)
std::map< std::string, request_handler > request_handlers_table
void handle_sighup(const boost::system::error_code &error, int signal_number)
boost::asio::basic_waitable_timer< std::chrono::steady_clock > flush_timer_
const config & campaigns() const
Retrieves the contents of the [campaigns] WML node.
std::string blacklist_file_
Add-on blacklist table.
Definition: blacklist.hpp:41
void handle_read_from_fifo(const boost::system::error_code &error, std::size_t bytes_transferred)
void handle_change_passphrase(const request &)
void write_config()
Writes the server configuration WML back to disk.
config & server_info()
Retrieves the contents of the [server_info] WML node.
void handle_new_client(socket_ptr socket)
void handle_request_campaign(const request &)
void handle_request_campaign_list(const request &)
std::function< void(server *, const request &req)> request_handler
void flush_cfg()
Starts timer to write config to disk every ten minutes.
std::shared_ptr< boost::asio::ip::tcp::socket > socket_ptr
Definition: server_base.hpp:33
static const size_t default_document_size_limit
Default upload size limit in bytes.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
void send_message(const std::string &msg, socket_ptr sock)
Send a client an informational message.
void send_error(const std::string &msg, socket_ptr sock)
Send a client an error message.
void handle_upload(const request &)
server(const std::string &cfg_file)
config & get_campaign(const std::string &id)
Retrieves a campaign by id if found, or a null config otherwise.
Base class for servers using Wesnoth's WML over TCP protocol.
int compress_level_
Used for add-on archives.