22 #include "microhttpd_compat.h"
24 #include <core/exception.h>
25 #include <core/exceptions/system.h>
26 #include <core/threading/thread.h>
27 #include <logging/logger.h>
28 #include <sys/socket.h>
29 #include <webview/access_log.h>
30 #include <webview/request.h>
31 #include <webview/request_dispatcher.h>
32 #include <webview/request_manager.h>
33 #include <webview/server.h>
58 dispatcher_ = dispatcher;
60 request_manager_ = NULL;
77 const char *cert_pem_filepath,
78 const char *cipher_suite)
81 tls_key_mem_ = read_file(key_pem_filepath);
82 tls_cert_mem_ = read_file(cert_pem_filepath);
83 if (cipher_suite == NULL) {
84 tls_cipher_suite_ = WEBVIEW_DEFAULT_CIPHERS;
86 tls_cipher_suite_ = cipher_suite;
100 enable_ipv4_ = enable_ipv4;
101 enable_ipv6_ = enable_ipv6;
115 cors_allow_all_ = allow_all;
116 cors_origins_ = std::move(origins);
117 cors_max_age_ = max_age;
132 num_threads_ = num_threads;
142 unsigned int flags = MHD_NO_FLAG;
143 #if MHD_VERSION >= 0x00090280
144 if (enable_ipv4_ && enable_ipv6_) {
145 flags |= MHD_USE_DUAL_STACK;
146 }
else if (enable_ipv6_) {
147 flags |= MHD_USE_IPv6;
148 }
else if (!enable_ipv4_ && !enable_ipv6_) {
154 flags |= MHD_USE_SSL;
157 dispatcher_->
setup_cors(cors_allow_all_, std::move(cors_origins_), cors_max_age_);
159 if (num_threads_ > 1) {
161 flags |= MHD_USE_EPOLL_LINUX_ONLY;
163 flags |= MHD_USE_SELECT_INTERNALLY;
166 size_t num_options = 3 + (num_threads_ > 1 ? 1 : 0) + (tls_enabled_ ? 3 : 0);
169 struct MHD_OptionItem ops[num_options];
170 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_NOTIFY_COMPLETED,
172 (
void *)dispatcher_};
173 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_URI_LOG_CALLBACK,
175 (
void *)dispatcher_};
177 if (num_threads_ > 1) {
178 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_THREAD_POOL_SIZE, num_threads_, NULL};
182 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_HTTPS_MEM_KEY, (intptr_t)tls_key_mem_.c_str(), NULL};
184 MHD_OptionItem{MHD_OPTION_HTTPS_MEM_CERT, (intptr_t)tls_cert_mem_.c_str(), NULL};
186 MHD_OptionItem{MHD_OPTION_HTTPS_PRIORITIES, (intptr_t)tls_cipher_suite_.c_str(), NULL};
189 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_END, 0, NULL};
191 daemon_ = MHD_start_daemon(flags,
201 if (daemon_ == NULL) {
209 if (request_manager_) {
210 request_manager_->set_server(NULL);
213 MHD_stop_daemon(daemon_);
225 WebServer::read_file(
const char *filename)
227 FILE *f = fopen(filename,
"rb");
233 if ((fseek(f, 0, SEEK_END) != 0) || ((size = ftell(f)) == 1)) {
235 throw Exception(
"Cannot determine file size of %s", filename);
237 fseek(f, 0, SEEK_SET);
241 throw Exception(
"File %s has zero length", filename);
242 }
else if (size > 1024 * 1024) {
245 throw Exception(
"File %s is unexpectedly large", filename);
248 std::string rv(size + 1, 0);
249 if (fread(&rv[0], size, 1, f) != 1) {
252 throw FileReadException(filename, terrno);
290 request_manager->set_server(
this);
291 request_manager_ = request_manager;
324 if (num_threads_ > 1) {
329 fd_set read_fd, write_fd, except_fd;
334 if (MHD_get_fdset(daemon_, &read_fd, &write_fd, &except_fd, &max_fd) != MHD_YES) {
336 logger_->
log_warn(
"WebviewThread",
"Could not get microhttpd fdsets");
339 select(max_fd + 1, &read_fd, &write_fd, &except_fd, NULL);