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