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);
File could not be opened.
Base class for exceptions in Fawkes.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
@ CANCEL_DISABLED
thread cannot be cancelled
static void set_cancel_state(CancelState new_state, CancelState *old_state=0)
Set the cancel state of the current thread.
A class for handling time.
unsigned int active_requests() const
Get number of active requests.
void setup_cors(bool allow_all, std::vector< std::string > &&origins, unsigned int max_age)
Setup cross-origin resource sharing.
void setup_basic_auth(const char *realm, WebUserVerifier *verifier)
Setup basic authentication.
static void * uri_log_cb(void *cls, const char *uri)
Callback for new requests.
static void request_completed_cb(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Process request completion.
static MHD_RESULT process_request_cb(void *callback_data, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **session_data)
Process request callback for libmicrohttpd.
void setup_access_log(const char *filename)
Setup access log.
Time last_request_completion_time() const
Get time when last request was completed.
Probides information about ongoing requests.
Encapsulation of the libmicrohttpd webserver.
WebServer & setup_access_log(const char *filename)
Setup access log.
void process()
Process requests.
WebServer(unsigned short int port, WebRequestDispatcher *dispatcher, fawkes::Logger *logger=0)
Constructor.
WebServer & setup_ipv(bool enable_ipv4, bool enable_ipv6)
Setup protocols, i.e., IPv4 and/or IPv6.
WebServer & setup_cors(bool allow_all, std::vector< std::string > &&origins, unsigned int max_age)
Setup cross-origin resource sharing.
Time last_request_completion_time() const
Get time when last request was completed.
WebServer & setup_tls(const char *key_pem_filepath, const char *cert_pem_filepath, const char *cipher_suite=WEBVIEW_DEFAULT_CIPHERS)
Setup Transport Layer Security (encryption),.
unsigned int active_requests() const
Get number of active requests.
WebServer & setup_thread_pool(unsigned int num_threads)
Setup thread pool.
WebServer & setup_basic_auth(const char *realm, WebUserVerifier *verifier)
Setup basic authentication.
void start()
Start daemon and enable processing requests.
WebServer & setup_request_manager(WebRequestManager *request_manager)
Setup this server as request manager.
Interface for user verification.
Fawkes library namespace.