22 #include <core/exception.h>
23 #include <core/exceptions/system.h>
24 #include <core/threading/thread.h>
25 #include <logging/logger.h>
26 #include <sys/socket.h>
27 #include <webview/access_log.h>
28 #include <webview/request.h>
29 #include <webview/request_dispatcher.h>
30 #include <webview/request_manager.h>
31 #include <webview/server.h>
36 #include <microhttpd.h>
53 WebRequestDispatcher *dispatcher,
57 dispatcher_ = dispatcher;
59 request_manager_ = NULL;
76 const char *cert_pem_filepath,
77 const char *cipher_suite)
80 tls_key_mem_ = read_file(key_pem_filepath);
81 tls_cert_mem_ = read_file(cert_pem_filepath);
82 if (cipher_suite == NULL) {
83 tls_cipher_suite_ = WEBVIEW_DEFAULT_CIPHERS;
85 tls_cipher_suite_ = cipher_suite;
99 enable_ipv4_ = enable_ipv4;
100 enable_ipv6_ = enable_ipv6;
114 cors_allow_all_ = allow_all;
115 cors_origins_ = std::move(origins);
116 cors_max_age_ = max_age;
131 num_threads_ = num_threads;
141 unsigned int flags = MHD_NO_FLAG;
142 #if MHD_VERSION >= 0x00090280
143 if (enable_ipv4_ && enable_ipv6_) {
144 flags |= MHD_USE_DUAL_STACK;
145 }
else if (enable_ipv6_) {
146 flags |= MHD_USE_IPv6;
147 }
else if (!enable_ipv4_ && !enable_ipv6_) {
153 flags |= MHD_USE_SSL;
156 dispatcher_->
setup_cors(cors_allow_all_, std::move(cors_origins_), cors_max_age_);
158 if (num_threads_ > 1) {
160 flags |= MHD_USE_EPOLL_LINUX_ONLY;
162 flags |= MHD_USE_SELECT_INTERNALLY;
165 size_t num_options = 3 + (num_threads_ > 1 ? 1 : 0) + (tls_enabled_ ? 3 : 0);
168 struct MHD_OptionItem ops[num_options];
169 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_NOTIFY_COMPLETED,
171 (
void *)dispatcher_};
172 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_URI_LOG_CALLBACK,
174 (
void *)dispatcher_};
176 if (num_threads_ > 1) {
177 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_THREAD_POOL_SIZE, num_threads_, NULL};
181 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_HTTPS_MEM_KEY, (intptr_t)tls_key_mem_.c_str(), NULL};
183 MHD_OptionItem{MHD_OPTION_HTTPS_MEM_CERT, (intptr_t)tls_cert_mem_.c_str(), NULL};
185 MHD_OptionItem{MHD_OPTION_HTTPS_PRIORITIES, (intptr_t)tls_cipher_suite_.c_str(), NULL};
188 ops[cur_op++] = MHD_OptionItem{MHD_OPTION_END, 0, NULL};
190 daemon_ = MHD_start_daemon(flags,
200 if (daemon_ == NULL) {
208 if (request_manager_) {
209 request_manager_->set_server(NULL);
212 MHD_stop_daemon(daemon_);
224 WebServer::read_file(
const char *filename)
226 FILE *f = fopen(filename,
"rb");
232 if ((fseek(f, 0, SEEK_END) != 0) || ((size = ftell(f)) == 1)) {
234 throw Exception(
"Cannot determine file size of %s", filename);
236 fseek(f, 0, SEEK_SET);
240 throw Exception(
"File %s has zero length", filename);
241 }
else if (size > 1024 * 1024) {
244 throw Exception(
"File %s is unexpectedly large", filename);
247 std::string rv(size + 1, 0);
248 if (fread(&rv[0], size, 1, f) != 1) {
251 throw FileReadException(filename, terrno);
289 request_manager->set_server(
this);
290 request_manager_ = request_manager;
323 if (num_threads_ > 1) {
328 fd_set read_fd, write_fd, except_fd;
333 if (MHD_get_fdset(daemon_, &read_fd, &write_fd, &except_fd, &max_fd) != MHD_YES) {
335 logger_->
log_warn(
"WebviewThread",
"Could not get microhttpd fdsets");
338 select(max_fd + 1, &read_fd, &write_fd, &except_fd, NULL);