diff --git a/include/villas/web.h b/include/villas/web.h index fb0645b87..06aa0c12d 100644 --- a/include/villas/web.h +++ b/include/villas/web.h @@ -26,6 +26,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -42,6 +43,8 @@ struct web { struct lws_context *context; /**< The libwebsockets server context. */ struct lws_vhost *vhost; /**< The libwebsockets vhost. */ + struct queue writables; /**< Queue of WSIs for which we will call lws_callback_on_writable() */ + int port; /**< Port of the build in HTTP / WebSocket server. */ char *htdocs; /**< The root directory for files served via HTTP. */ char *ssl_cert; /**< Path to the SSL certitifcate for HTTPS / WSS. */ @@ -65,6 +68,8 @@ int web_stop(struct web *w); /** Parse HTTPd and WebSocket related options */ int web_parse(struct web *w, json_t *cfg); +void web_callback_on_writable(struct lws *wsi); + #ifdef __cplusplus } #endif diff --git a/lib/api.c b/lib/api.c index 8f836dc17..04c6da9b9 100644 --- a/lib/api.c +++ b/lib/api.c @@ -326,7 +326,7 @@ int api_stop(struct api *a) s->state = API_SESSION_STATE_SHUTDOWN; - lws_callback_on_writable(s->wsi); + web_callback_on_writable(s->wsi); } for (int i = 0; i < 10 && list_length(&a->sessions) > 0; i++) { @@ -373,7 +373,7 @@ static void * api_worker(void *ctx) queue_push(&s->response.queue, resp); - lws_callback_on_writable(s->wsi); + web_callback_on_writable(s->wsi); } return NULL; diff --git a/lib/nodes/websocket.c b/lib/nodes/websocket.c index 788218c6d..8c3034ecc 100644 --- a/lib/nodes/websocket.c +++ b/lib/nodes/websocket.c @@ -164,7 +164,7 @@ static int websocket_connection_write(struct websocket_connection *c, struct sam /* Client connections which are currently conecting don't have an associate c->wsi yet */ if (c->wsi) - lws_callback_on_writable(c->wsi); + web_callback_on_writable(c->wsi); return 0; } diff --git a/lib/web.c b/lib/web.c index 4194537ef..13e321da1 100644 --- a/lib/web.c +++ b/lib/web.c @@ -165,19 +165,34 @@ static void logger(int level, const char *msg) { } } +void web_callback_on_writable(struct lws *wsi) +{ + struct lws_context *ctx = lws_get_context(wsi); + struct web *w = lws_context_user(ctx); + + queue_push(&w->writables, (void *) wsi); +} + static void * web_worker(void *ctx) { + struct lws *wsi; struct web *w = ctx; - for (;;) + for (;;) { lws_service(w->context, 100); + while (queue_available(&w->writables)) { + queue_pull(&w->writables, (void **) &wsi); + lws_callback_on_writable(wsi); + } + } + return NULL; } int web_init(struct web *w, struct api *a) { - int lvl = LLL_ERR | LLL_WARN | LLL_NOTICE; + int ret, lvl = LLL_ERR | LLL_WARN | LLL_NOTICE; if (global_log->level >=10 && global_log->facilities & LOG_WEB) lvl |= (1 << LLL_COUNT) - 1; @@ -190,6 +205,10 @@ int web_init(struct web *w, struct api *a) w->port = getuid() > 0 ? 8080 : 80; /**< @todo Use libcap to check if user can bind to ports < 1024 */ w->htdocs = strdup(WEB_PATH); + ret = queue_init(&w->writables, 128, &memory_heap); + if (ret) + return ret; + w->state = STATE_INITIALIZED; return 0; @@ -312,6 +331,8 @@ int web_stop(struct web *w) int web_destroy(struct web *w) { + int ret; + if (w->state == STATE_DESTROYED) return 0; @@ -328,6 +349,10 @@ int web_destroy(struct web *w) if (w->htdocs) free(w->htdocs); + ret = queue_destroy(&w->writables); + if (ret) + return ret; + w->state = STATE_DESTROYED; return 0;