-
Notifications
You must be signed in to change notification settings - Fork 192
Expand file tree
/
Copy pathwebserver.hpp
More file actions
277 lines (235 loc) · 10.3 KB
/
webserver.hpp
File metadata and controls
277 lines (235 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
This file is part of libhttpserver
Copyright (C) 2011-2019 Sebastiano Merlino
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
*/
#if !defined (_HTTPSERVER_HPP_INSIDE_) && !defined (HTTPSERVER_COMPILATION)
#error "Only <httpserver.hpp> or <httpserverpp> can be included directly."
#endif
#ifndef SRC_HTTPSERVER_WEBSERVER_HPP_
#define SRC_HTTPSERVER_WEBSERVER_HPP_
#define NOT_FOUND_ERROR "Not Found"
#define METHOD_ERROR "Method not Allowed"
#define NOT_METHOD_ERROR "Method not Acceptable"
#define GENERIC_ERROR "Internal Error"
#include <microhttpd.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#if !defined(__MINGW32__)
#include <sys/socket.h>
#endif
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <shared_mutex>
#include <string>
#include <unordered_map>
#include <vector>
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#endif // HAVE_GNUTLS
#include "httpserver/http_utils.hpp"
#include "httpserver/create_webserver.hpp"
#include "httpserver/details/http_endpoint.hpp"
namespace httpserver { class http_resource; }
namespace httpserver { class http_response; }
namespace httpserver { namespace details { struct modded_request; } }
struct MHD_Connection;
namespace httpserver {
/**
* Class representing the webserver. Main class of the apis.
**/
class webserver {
public:
// Keeping this non explicit on purpose to easy construction through builder class.
webserver(const create_webserver& params); // NOLINT(runtime/explicit)
/**
* Destructor of the class
**/
~webserver();
/**
* Method used to start the webserver.
* This method can be blocking or not.
* @param blocking param indicating if the method is blocking or not
* @return a boolean indicating if the webserver is running or not.
**/
bool start(bool blocking = false);
/**
* Method used to stop the webserver.
* @return true if the webserver is stopped.
**/
bool stop();
/**
* Method used to evaluate if the server is running or not.
* @return true if the webserver is running
**/
bool is_running();
/**
* Method used to register a resource with the webserver.
* @param resource The url pointing to the resource. This url could be also parametrized in the form /path/to/url/{par1}/and/{par2}
* or a regular expression.
* @param http_resource http_resource pointer to register.
* @param family boolean indicating whether the resource is registered for the endpoint and its child or not.
* @return true if the resource was registered
**/
bool register_resource(const std::string& resource, http_resource* res, bool family = false);
void unregister_resource(const std::string& resource);
void ban_ip(const std::string& ip);
void allow_ip(const std::string& ip);
void unban_ip(const std::string& ip);
void disallow_ip(const std::string& ip);
log_access_ptr get_access_logger() const {
return log_access;
}
log_error_ptr get_error_logger() const {
return log_error;
}
validator_ptr get_request_validator() const {
return validator;
}
unescaper_ptr get_unescaper() const {
return unescaper;
}
/**
* Method used to kill the webserver waiting for it to terminate
**/
void sweet_kill();
protected:
webserver& operator=(const webserver& other);
private:
const uint16_t port;
http::http_utils::start_method_T start_method;
const int max_threads;
const int max_connections;
const int memory_limit;
const size_t content_size_limit;
const int connection_timeout;
const int per_IP_connection_limit;
log_access_ptr log_access;
log_error_ptr log_error;
validator_ptr validator;
unescaper_ptr unescaper;
const struct sockaddr* bind_address;
std::shared_ptr<struct sockaddr_storage> bind_address_storage;
/* Changed type to MHD_socket because this type will always reflect the
platform's actual socket type (e.g. SOCKET on windows, int on unixes)*/
MHD_socket bind_socket;
const int max_thread_stack_size;
const bool use_ssl;
const bool use_ipv6;
const bool use_dual_stack;
const bool debug;
const bool pedantic;
const std::string https_mem_key;
const std::string https_mem_cert;
const std::string https_mem_trust;
const std::string https_priorities;
const http::http_utils::cred_type_T cred_type;
const psk_cred_handler_callback psk_cred_handler;
const std::string digest_auth_random;
const int nonce_nc_size;
bool running;
const http::http_utils::policy_T default_policy;
#ifdef HAVE_BAUTH
const bool basic_auth_enabled;
#endif // HAVE_BAUTH
const bool digest_auth_enabled;
const bool regex_checking;
const bool ban_system_enabled;
const bool post_process_enabled;
const bool put_processed_data_to_content;
const file_upload_target_T file_upload_target;
const std::string file_upload_dir;
const bool generate_random_filename_on_upload;
const bool deferred_enabled;
const bool single_resource;
const bool tcp_nodelay;
pthread_mutex_t mutexwait;
pthread_cond_t mutexcond;
const render_ptr not_found_resource;
const render_ptr method_not_allowed_resource;
const render_ptr internal_error_resource;
const file_cleanup_callback_ptr file_cleanup_callback;
const auth_handler_ptr auth_handler;
const std::vector<std::string> auth_skip_paths;
const sni_callback_t sni_callback;
std::shared_mutex registered_resources_mutex;
std::map<details::http_endpoint, http_resource*> registered_resources;
std::map<std::string, http_resource*> registered_resources_str;
std::map<details::http_endpoint, http_resource*> registered_resources_regex;
struct route_cache_entry {
details::http_endpoint matched_endpoint;
http_resource* resource;
};
static constexpr size_t ROUTE_CACHE_MAX_SIZE = 256;
std::mutex route_cache_mutex;
std::list<std::pair<std::string, route_cache_entry>> route_cache_list;
std::unordered_map<std::string, std::list<std::pair<std::string, route_cache_entry>>::iterator> route_cache_map;
std::shared_mutex bans_mutex;
std::set<http::ip_representation> bans;
std::shared_mutex allowances_mutex;
std::set<http::ip_representation> allowances;
struct MHD_Daemon* daemon;
std::shared_ptr<http_response> method_not_allowed_page(details::modded_request* mr) const;
std::shared_ptr<http_response> internal_error_page(details::modded_request* mr, bool force_our = false) const;
std::shared_ptr<http_response> not_found_page(details::modded_request* mr) const;
bool should_skip_auth(const std::string& path) const;
static void request_completed(void *cls,
struct MHD_Connection *connection, void **con_cls,
enum MHD_RequestTerminationCode toe);
static MHD_Result answer_to_connection(void* cls, MHD_Connection* connection, const char* url,
const char* method, const char* version, const char* upload_data,
size_t* upload_data_size, void** con_cls);
static MHD_Result post_iterator(void *cls, enum MHD_ValueKind kind, const char *key,
const char *filename, const char *content_type, const char *transfer_encoding,
const char *data, uint64_t off, size_t size);
static void upgrade_handler(void *cls, struct MHD_Connection* connection, void **con_cls, int upgrade_socket);
MHD_Result requests_answer_first_step(MHD_Connection* connection, struct details::modded_request* mr);
MHD_Result requests_answer_second_step(MHD_Connection* connection,
const char* method, const char* version, const char* upload_data,
size_t* upload_data_size, struct details::modded_request* mr);
MHD_Result finalize_answer(MHD_Connection* connection, struct details::modded_request* mr, const char* method);
MHD_Result complete_request(MHD_Connection* connection, struct details::modded_request* mr, const char* version, const char* method);
void invalidate_route_cache();
#ifdef HAVE_GNUTLS
// MHD_PskServerCredentialsCallback signature
static int psk_cred_handler_func(void* cls,
struct MHD_Connection* connection,
const char* username,
void** psk,
size_t* psk_size);
#ifdef MHD_OPTION_HTTPS_CERT_CALLBACK
// SNI certificate callback function (libmicrohttpd 0.9.71+)
static int sni_cert_callback_func(void* cls,
struct MHD_Connection* connection,
const char* server_name,
gnutls_certificate_credentials_t* creds);
// Cache for loaded credentials per server name
mutable std::map<std::string, gnutls_certificate_credentials_t> sni_credentials_cache;
mutable std::shared_mutex sni_credentials_mutex;
#endif // MHD_OPTION_HTTPS_CERT_CALLBACK
#endif // HAVE_GNUTLS
friend MHD_Result policy_callback(void *cls, const struct sockaddr* addr, socklen_t addrlen);
friend void error_log(void* cls, const char* fmt, va_list ap);
friend void access_log(webserver* cls, std::string uri);
friend void* uri_log(void* cls, const char* uri);
friend size_t unescaper_func(void * cls, struct MHD_Connection *c, char *s);
friend class http_response;
};
} // namespace httpserver
#endif // SRC_HTTPSERVER_WEBSERVER_HPP_