hrtimer: add support for libevent and libev
This commit is contained in:
parent
9cce1874b0
commit
a01ad0dd20
32 changed files with 1943 additions and 79 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -47,3 +47,5 @@ libwebsockets.pc
|
|||
build/
|
||||
*.swp
|
||||
doc
|
||||
/build2/
|
||||
/build3/
|
||||
|
|
|
@ -1163,6 +1163,7 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
lwsl_info("Using event loop: %s\n", context->event_loop_ops->name);
|
||||
|
||||
#if defined(LWS_WITH_TLS)
|
||||
time(&context->tls.last_cert_check_s);
|
||||
if (info->alpn)
|
||||
context->tls.alpn_default = info->alpn;
|
||||
else {
|
||||
|
@ -1365,8 +1366,6 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
|
||||
lws_plat_drop_app_privileges(info);
|
||||
|
||||
time(&context->last_cert_check_s);
|
||||
|
||||
/* expedite post-context init (eg, protocols) */
|
||||
lws_cancel_service(context);
|
||||
|
||||
|
@ -1729,6 +1728,22 @@ static void
|
|||
lws_context_destroy3(struct lws_context *context)
|
||||
{
|
||||
struct lws_context **pcontext_finalize = context->pcontext_finalize;
|
||||
struct lws_context_per_thread *pt;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < context->count_threads; n++) {
|
||||
pt = &context->pt[n];
|
||||
|
||||
if (context->event_loop_ops->destroy_pt)
|
||||
context->event_loop_ops->destroy_pt(context, n);
|
||||
|
||||
lws_free_set_NULL(context->pt[n].serv_buf);
|
||||
|
||||
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
||||
while (pt->http.ah_list)
|
||||
_lws_destroy_ah(pt, pt->http.ah_list);
|
||||
#endif
|
||||
}
|
||||
|
||||
lws_free(context);
|
||||
lwsl_info("%s: ctx %p freed\n", __func__, context);
|
||||
|
@ -1746,8 +1761,9 @@ lws_context_destroy2(struct lws_context *context)
|
|||
{
|
||||
struct lws_vhost *vh = NULL, *vh1;
|
||||
#if defined(LWS_WITH_PEER_LIMITS)
|
||||
uint32_t n;
|
||||
uint32_t nu;
|
||||
#endif
|
||||
int n;
|
||||
|
||||
lwsl_info("%s: ctx %p\n", __func__, context);
|
||||
|
||||
|
@ -1780,9 +1796,9 @@ lws_context_destroy2(struct lws_context *context)
|
|||
lws_plat_context_late_destroy(context);
|
||||
|
||||
#if defined(LWS_WITH_PEER_LIMITS)
|
||||
for (n = 0; n < context->pl_hash_elements; n++) {
|
||||
for (nu = 0; nu < context->pl_hash_elements; nu++) {
|
||||
lws_start_foreach_llp(struct lws_peer **, peer,
|
||||
context->pl_hash_table[n]) {
|
||||
context->pl_hash_table[nu]) {
|
||||
struct lws_peer *df = *peer;
|
||||
*peer = df->next;
|
||||
lws_free(df);
|
||||
|
@ -1807,6 +1823,11 @@ lws_context_destroy2(struct lws_context *context)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!context->pt[0].event_loop_foreign)
|
||||
for (n = 0; n < context->count_threads; n++)
|
||||
if (context->pt[n].inside_service)
|
||||
return;
|
||||
|
||||
lws_context_destroy3(context);
|
||||
}
|
||||
|
||||
|
@ -1844,6 +1865,8 @@ lws_context_destroy(struct lws_context *context)
|
|||
}
|
||||
lwsl_info("%s: ctx %p: already being destroyed\n",
|
||||
__func__, context);
|
||||
|
||||
lws_context_destroy3(context);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1891,20 +1914,6 @@ lws_context_destroy(struct lws_context *context)
|
|||
lws_pt_mutex_destroy(pt);
|
||||
}
|
||||
|
||||
for (n = 0; n < context->count_threads; n++) {
|
||||
pt = &context->pt[n];
|
||||
|
||||
if (context->event_loop_ops->destroy_pt)
|
||||
context->event_loop_ops->destroy_pt(context, n);
|
||||
|
||||
lws_free_set_NULL(context->pt[n].serv_buf);
|
||||
|
||||
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
||||
while (pt->http.ah_list)
|
||||
_lws_destroy_ah(pt, pt->http.ah_list);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* inform all the protocols that they are done and will have no more
|
||||
* callbacks.
|
||||
|
@ -1944,10 +1953,5 @@ lws_context_destroy(struct lws_context *context)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!context->pt[0].event_loop_foreign)
|
||||
for (n = 0; n < context->count_threads; n++)
|
||||
if (context->pt[n].inside_service)
|
||||
return;
|
||||
|
||||
lws_context_destroy2(context);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
|
||||
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -21,13 +21,66 @@
|
|||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
static void
|
||||
lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
|
||||
{
|
||||
struct lws_context_per_thread *pt =
|
||||
(struct lws_context_per_thread *)watcher->data;
|
||||
lws_usec_t us;
|
||||
|
||||
lws_pt_lock(pt, __func__);
|
||||
us = __lws_hrtimer_service(pt);
|
||||
if (us != LWS_HRTIMER_NOWAIT) {
|
||||
ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0);
|
||||
ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer);
|
||||
}
|
||||
lws_pt_unlock(pt);
|
||||
}
|
||||
|
||||
static void
|
||||
lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents)
|
||||
{
|
||||
struct lws_context_per_thread *pt = lws_container_of(handle,
|
||||
struct lws_context_per_thread, ev.idle);
|
||||
lws_usec_t us;
|
||||
|
||||
lws_service_do_ripe_rxflow(pt);
|
||||
|
||||
/*
|
||||
* is there anybody with pending stuff that needs service forcing?
|
||||
*/
|
||||
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) {
|
||||
/* -1 timeout means just do forced service */
|
||||
_lws_plat_service_tsi(pt->context, -1, pt->tid);
|
||||
/* still somebody left who wants forced service? */
|
||||
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
|
||||
/* yes... come back again later */
|
||||
return;
|
||||
}
|
||||
|
||||
/* account for hrtimer */
|
||||
|
||||
lws_pt_lock(pt, __func__);
|
||||
us = __lws_hrtimer_service(pt);
|
||||
if (us != LWS_HRTIMER_NOWAIT) {
|
||||
ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0);
|
||||
ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer);
|
||||
}
|
||||
lws_pt_unlock(pt);
|
||||
|
||||
/* there is nobody who needs service forcing, shut down idle */
|
||||
ev_idle_stop(loop, handle);
|
||||
}
|
||||
|
||||
static void
|
||||
lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
|
||||
{
|
||||
struct lws_context_per_thread *pt;
|
||||
struct lws_io_watcher *lws_io = lws_container_of(watcher,
|
||||
struct lws_io_watcher, ev.watcher);
|
||||
struct lws_context *context = lws_io->context;
|
||||
struct lws_pollfd eventfd;
|
||||
struct lws *wsi;
|
||||
|
||||
if (revents & EV_ERROR)
|
||||
return;
|
||||
|
@ -45,7 +98,12 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
|
|||
eventfd.revents |= LWS_POLLOUT;
|
||||
}
|
||||
|
||||
lws_service_fd(context, &eventfd);
|
||||
wsi = wsi_from_fd(context, watcher->fd);
|
||||
pt = &context->pt[(int)wsi->tsi];
|
||||
|
||||
lws_service_fd_tsi(context, &eventfd, (int)wsi->tsi);
|
||||
|
||||
ev_idle_start(pt->ev.io_loop, &pt->ev.idle);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
|
@ -64,6 +122,7 @@ lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)
|
|||
static int
|
||||
elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||||
struct ev_signal *w_sigint = &context->pt[tsi].w_sigint.ev.watcher;
|
||||
struct lws_vhost *vh = context->vhost_list;
|
||||
const char *backend_name;
|
||||
|
@ -84,7 +143,7 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
|
|||
return -1;
|
||||
}
|
||||
|
||||
context->pt[tsi].ev.io_loop = loop;
|
||||
pt->ev.io_loop = loop;
|
||||
|
||||
/*
|
||||
* Initialize the accept w_accept with all the listening sockets
|
||||
|
@ -138,6 +197,11 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
|
|||
lwsl_info(" libev backend: %s\n", backend_name);
|
||||
(void)backend_name;
|
||||
|
||||
ev_timer_init(&pt->ev.hrtimer, lws_ev_hrtimer_cb, 0, 0);
|
||||
pt->ev.hrtimer.data = pt;
|
||||
|
||||
ev_idle_init(&pt->ev.idle, lws_ev_idle_cb);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -147,17 +211,22 @@ elops_destroy_pt_ev(struct lws_context *context, int tsi)
|
|||
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||||
struct lws_vhost *vh = context->vhost_list;
|
||||
|
||||
if (!pt->ev.io_loop)
|
||||
return;
|
||||
|
||||
while (vh) {
|
||||
if (vh->lserv_wsi)
|
||||
ev_io_stop(pt->ev.io_loop, &vh->w_accept.ev.watcher);
|
||||
vh = vh->vhost_next;
|
||||
}
|
||||
if (!pt->event_loop_foreign)
|
||||
|
||||
/* static assets */
|
||||
|
||||
ev_timer_stop(pt->ev.io_loop, &pt->ev.hrtimer);
|
||||
ev_idle_stop(pt->ev.io_loop, &pt->ev.idle);
|
||||
|
||||
if (!pt->event_loop_foreign) {
|
||||
ev_signal_stop(pt->ev.io_loop, &pt->w_sigint.ev.watcher);
|
||||
|
||||
ev_loop_destroy(pt->ev.io_loop);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -226,7 +295,7 @@ static int
|
|||
elops_destroy_context2_ev(struct lws_context *context)
|
||||
{
|
||||
struct lws_context_per_thread *pt;
|
||||
int n, m, internal = 0;
|
||||
int n, m;
|
||||
|
||||
lwsl_debug("%s\n", __func__);
|
||||
|
||||
|
@ -240,7 +309,6 @@ elops_destroy_context2_ev(struct lws_context *context)
|
|||
if (pt->event_loop_foreign || !pt->ev.io_loop)
|
||||
continue;
|
||||
|
||||
internal = 1;
|
||||
if (!context->finalize_destroy_after_internal_loops_stopped) {
|
||||
ev_break(pt->ev.io_loop, EVBREAK_ONE);
|
||||
continue;
|
||||
|
@ -252,7 +320,7 @@ elops_destroy_context2_ev(struct lws_context *context)
|
|||
ev_loop_destroy(pt->ev.io_loop);
|
||||
}
|
||||
|
||||
return internal;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -281,6 +349,15 @@ elops_init_vhost_listen_wsi_ev(struct lws *wsi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
elops_destroy_wsi_ev(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
|
||||
ev_io_stop(pt->ev.io_loop, &wsi->w_read.ev.watcher);
|
||||
ev_io_stop(pt->ev.io_loop, &wsi->w_write.ev.watcher);
|
||||
}
|
||||
|
||||
struct lws_event_loop_ops event_loop_ops_ev = {
|
||||
/* name */ "libev",
|
||||
/* init_context */ elops_init_context_ev,
|
||||
|
@ -295,7 +372,7 @@ struct lws_event_loop_ops event_loop_ops_ev = {
|
|||
/* io */ elops_io_ev,
|
||||
/* run_pt */ elops_run_pt_ev,
|
||||
/* destroy_pt */ elops_destroy_pt_ev,
|
||||
/* destroy wsi */ NULL,
|
||||
/* destroy wsi */ elops_destroy_wsi_ev,
|
||||
|
||||
/* periodic_events_available */ 0,
|
||||
};
|
||||
|
|
|
@ -23,9 +23,19 @@
|
|||
|
||||
#include <ev.h>
|
||||
|
||||
#define LWS_EV_REFCOUNT_STATIC_HANDLE_NEW(_x, _ctx) \
|
||||
{ (_x)->data = _ctx; \
|
||||
_ctx->count_event_loop_static_asset_handles++; }
|
||||
#define LWS_EV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x) \
|
||||
((struct lws_context *)(_x)->data)))
|
||||
#define LWS_EV_REFCOUNT_STATIC_HANDLE_DESTROYED(_x) \
|
||||
(--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \
|
||||
count_event_loop_static_asset_handles))
|
||||
|
||||
struct lws_pt_eventlibs_libev {
|
||||
struct ev_loop *io_loop;
|
||||
struct ev_timer hrtimer;
|
||||
struct ev_idle idle;
|
||||
};
|
||||
|
||||
struct lws_io_watcher_libev {
|
||||
|
|
|
@ -21,24 +21,83 @@
|
|||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
static void
|
||||
lws_event_hrtimer_cb(int fd, short event, void *p)
|
||||
{
|
||||
struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
|
||||
struct timeval tv;
|
||||
lws_usec_t us;
|
||||
|
||||
lws_pt_lock(pt, __func__);
|
||||
us = __lws_hrtimer_service(pt);
|
||||
if (us != LWS_HRTIMER_NOWAIT) {
|
||||
tv.tv_sec = us / 1000000;
|
||||
tv.tv_usec = us - (tv.tv_sec * 1000000);
|
||||
evtimer_add(pt->event.hrtimer, &tv);
|
||||
}
|
||||
lws_pt_unlock(pt);
|
||||
}
|
||||
|
||||
static void
|
||||
lws_event_idle_timer_cb(int fd, short event, void *p)
|
||||
{
|
||||
struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
|
||||
struct timeval tv;
|
||||
lws_usec_t us;
|
||||
|
||||
lws_service_do_ripe_rxflow(pt);
|
||||
|
||||
/*
|
||||
* is there anybody with pending stuff that needs service forcing?
|
||||
*/
|
||||
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) {
|
||||
/* -1 timeout means just do forced service */
|
||||
_lws_plat_service_tsi(pt->context, -1, pt->tid);
|
||||
/* still somebody left who wants forced service? */
|
||||
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) {
|
||||
/* yes... come back again later */
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1000;
|
||||
evtimer_add(pt->event.idle_timer, &tv);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* account for hrtimer */
|
||||
|
||||
lws_pt_lock(pt, __func__);
|
||||
us = __lws_hrtimer_service(pt);
|
||||
if (us != LWS_HRTIMER_NOWAIT) {
|
||||
tv.tv_sec = us / 1000000;
|
||||
tv.tv_usec = us - (tv.tv_sec * 1000000);
|
||||
evtimer_add(pt->event.hrtimer, &tv);
|
||||
}
|
||||
lws_pt_unlock(pt);
|
||||
}
|
||||
|
||||
static void
|
||||
lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
|
||||
{
|
||||
struct lws_io_watcher *lws_io = (struct lws_io_watcher *)ctx;
|
||||
struct lws_context *context = lws_io->context;
|
||||
struct lws_context_per_thread *pt;
|
||||
struct lws_pollfd eventfd;
|
||||
struct timeval tv;
|
||||
struct lws *wsi;
|
||||
|
||||
if (revents & EV_TIMEOUT)
|
||||
return;
|
||||
|
||||
/* !!! EV_CLOSED doesn't exist in libevent2 */
|
||||
#if LIBEVENT_VERSION_NUMBER < 0x02000000
|
||||
#if LIBEVENT_VERSION_NUMBER < 0x02000000
|
||||
if (revents & EV_CLOSED) {
|
||||
event_del(lws_io->event.watcher);
|
||||
event_free(lws_io->event.watcher);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
eventfd.fd = sock_fd;
|
||||
eventfd.events = 0;
|
||||
|
@ -52,7 +111,16 @@ lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
|
|||
eventfd.revents |= LWS_POLLOUT;
|
||||
}
|
||||
|
||||
lws_service_fd(context, &eventfd);
|
||||
wsi = wsi_from_fd(context, sock_fd);
|
||||
pt = &context->pt[(int)wsi->tsi];
|
||||
|
||||
lws_service_fd_tsi(context, &eventfd, wsi->tsi);
|
||||
|
||||
/* set the idle timer for 1ms ahead */
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1000;
|
||||
evtimer_add(pt->event.idle_timer, &tv);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
|
@ -77,6 +145,7 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
|
|||
{
|
||||
struct lws_vhost *vh = context->vhost_list;
|
||||
struct event_base *loop = (struct event_base *)_loop;
|
||||
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||||
|
||||
lwsl_info("%s: loop %p\n", __func__, _loop);
|
||||
|
||||
|
@ -91,7 +160,7 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
|
|||
return -1;
|
||||
}
|
||||
|
||||
context->pt[tsi].event.io_loop = loop;
|
||||
pt->event.io_loop = loop;
|
||||
|
||||
/*
|
||||
* Initialize all events with the listening sockets
|
||||
|
@ -110,13 +179,22 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
|
|||
vh = vh->vhost_next;
|
||||
}
|
||||
|
||||
/* static event loop objects */
|
||||
|
||||
pt->event.hrtimer = event_new(loop, -1, EV_PERSIST,
|
||||
lws_event_hrtimer_cb, pt);
|
||||
|
||||
pt->event.idle_timer = event_new(loop, -1, EV_PERSIST,
|
||||
lws_event_idle_timer_cb, pt);
|
||||
|
||||
/* Register the signal watcher unless it's a foreign loop */
|
||||
if (context->pt[tsi].event_loop_foreign)
|
||||
|
||||
if (pt->event_loop_foreign)
|
||||
return 0;
|
||||
|
||||
context->pt[tsi].w_sigint.event.watcher = evsignal_new(loop, SIGINT,
|
||||
lws_event_sigint_cb, &context->pt[tsi]);
|
||||
event_add(context->pt[tsi].w_sigint.event.watcher, NULL);
|
||||
pt->w_sigint.event.watcher = evsignal_new(loop, SIGINT,
|
||||
lws_event_sigint_cb, pt);
|
||||
event_add(pt->w_sigint.event.watcher, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -217,8 +295,15 @@ elops_destroy_pt_event(struct lws_context *context, int tsi)
|
|||
vh = vh->vhost_next;
|
||||
}
|
||||
|
||||
if (!pt->event_loop_foreign)
|
||||
event_free(pt->event.hrtimer);
|
||||
event_free(pt->event.idle_timer);
|
||||
|
||||
if (!pt->event_loop_foreign) {
|
||||
event_del(pt->w_sigint.event.watcher);
|
||||
event_free(pt->w_sigint.event.watcher);
|
||||
|
||||
event_base_free(pt->event.io_loop);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -227,10 +312,10 @@ elops_destroy_wsi_event(struct lws *wsi)
|
|||
if (!wsi)
|
||||
return;
|
||||
|
||||
if(wsi->w_read.event.watcher)
|
||||
if (wsi->w_read.event.watcher)
|
||||
event_free(wsi->w_read.event.watcher);
|
||||
|
||||
if(wsi->w_write.event.watcher)
|
||||
if (wsi->w_write.event.watcher)
|
||||
event_free(wsi->w_write.event.watcher);
|
||||
}
|
||||
|
||||
|
@ -271,7 +356,7 @@ static int
|
|||
elops_destroy_context2_event(struct lws_context *context)
|
||||
{
|
||||
struct lws_context_per_thread *pt;
|
||||
int n, m, internal = 0;
|
||||
int n, m;
|
||||
|
||||
lwsl_debug("%s\n", __func__);
|
||||
|
||||
|
@ -285,7 +370,6 @@ elops_destroy_context2_event(struct lws_context *context)
|
|||
if (pt->event_loop_foreign || !pt->event.io_loop)
|
||||
continue;
|
||||
|
||||
internal = 1;
|
||||
if (!context->finalize_destroy_after_internal_loops_stopped) {
|
||||
event_base_loopexit(pt->event.io_loop, NULL);
|
||||
continue;
|
||||
|
@ -305,7 +389,7 @@ elops_destroy_context2_event(struct lws_context *context)
|
|||
|
||||
}
|
||||
|
||||
return internal;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct lws_event_loop_ops event_loop_ops_event = {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
struct lws_pt_eventlibs_libevent {
|
||||
struct event_base *io_loop;
|
||||
struct event *hrtimer;
|
||||
struct event *idle_timer;
|
||||
};
|
||||
|
||||
struct lws_io_watcher_libevent {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
|
||||
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -116,11 +116,7 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents)
|
|||
eventfd.revents |= LWS_POLLOUT;
|
||||
}
|
||||
}
|
||||
lws_service_fd(context, &eventfd);
|
||||
|
||||
lws_pt_lock(pt, __func__);
|
||||
__lws_hrtimer_service(pt);
|
||||
lws_pt_unlock(pt);
|
||||
lws_service_fd_tsi(context, &eventfd, wsi->tsi);
|
||||
|
||||
uv_idle_start(&pt->uv.idle, lws_uv_idle);
|
||||
}
|
||||
|
@ -526,7 +522,8 @@ elops_destroy_context1_uv(struct lws_context *context)
|
|||
UV_RUN_NOWAIT)))
|
||||
;
|
||||
if (m)
|
||||
lwsl_err("%s: tsi %d: failed to close everything\n", __func__, n);
|
||||
lwsl_err("%s: tsi %d: not all closed\n",
|
||||
__func__, n);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -891,8 +888,9 @@ lws_libuv_closewsi(uv_handle_t* handle)
|
|||
vh = vh->vhost_next;
|
||||
}
|
||||
|
||||
if (context->pt[0].event_loop_foreign) {
|
||||
lwsl_info("%s: calling lws_context_destroy2\n", __func__);
|
||||
if (!context->count_event_loop_static_asset_handles &&
|
||||
context->pt[0].event_loop_foreign) {
|
||||
lwsl_info("%s: call lws_context_destroy2\n", __func__);
|
||||
lws_context_destroy2(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
#include <uv.h>
|
||||
|
||||
/*
|
||||
* libuv's async destroy cb means that asking to close something doesn't mean
|
||||
* you can destroy it or parent things until after the close completes.
|
||||
*
|
||||
* So we must reference-count creation and close completions with libuv.
|
||||
*
|
||||
* All "static" (per-pt or per-context) uv handles must
|
||||
*
|
||||
* - have their .data set to point to the context
|
||||
|
|
|
@ -757,7 +757,6 @@ struct lws_peer {
|
|||
struct lws_context {
|
||||
time_t last_timeout_check_s;
|
||||
time_t last_ws_ping_pong_check_s;
|
||||
time_t last_cert_check_s;
|
||||
time_t time_up;
|
||||
time_t time_discontiguity;
|
||||
time_t time_fixup;
|
||||
|
|
|
@ -554,9 +554,6 @@ lws_service_periodic_checks(struct lws_context *context,
|
|||
struct lws *wsi;
|
||||
int timed_out = 0;
|
||||
time_t now;
|
||||
#if defined(LWS_WITH_TLS)
|
||||
int n = 0;
|
||||
#endif
|
||||
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
||||
struct allocated_headers *ah;
|
||||
int m;
|
||||
|
@ -810,12 +807,10 @@ lws_service_periodic_checks(struct lws_context *context,
|
|||
/*
|
||||
* Phase 6: check the remaining cert lifetime daily
|
||||
*/
|
||||
#if defined(LWS_WITH_TLS)
|
||||
n = lws_compare_time_t(context, now, context->last_cert_check_s);
|
||||
if ((!context->last_cert_check_s || n > (24 * 60 * 60)) &&
|
||||
!lws_tls_check_all_cert_lifetimes(context))
|
||||
context->last_cert_check_s = now;
|
||||
#endif
|
||||
|
||||
if (context->tls_ops &&
|
||||
context->tls_ops->periodic_housekeeping)
|
||||
context->tls_ops->periodic_housekeeping(context, now);
|
||||
|
||||
return timed_out;
|
||||
}
|
||||
|
@ -869,7 +864,8 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd,
|
|||
}
|
||||
|
||||
#if defined(LWS_WITH_TLS)
|
||||
if (lwsi_state(wsi) == LRS_SHUTDOWN && lws_is_ssl(wsi) && wsi->tls.ssl) {
|
||||
if (lwsi_state(wsi) == LRS_SHUTDOWN &&
|
||||
lws_is_ssl(wsi) && wsi->tls.ssl) {
|
||||
switch (__lws_tls_shutdown(wsi)) {
|
||||
case LWS_SSL_CAPABLE_DONE:
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
|
@ -927,6 +923,10 @@ handled:
|
|||
#endif
|
||||
pollfd->revents = 0;
|
||||
|
||||
lws_pt_lock(pt, __func__);
|
||||
__lws_hrtimer_service(pt);
|
||||
lws_pt_unlock(pt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -501,7 +501,20 @@ tops_fake_POLLIN_for_buffered_mbedtls(struct lws_context_per_thread *pt)
|
|||
return lws_tls_fake_POLLIN_for_buffered(pt);
|
||||
}
|
||||
|
||||
static int
|
||||
tops_periodic_housekeeping_mbedtls(struct lws_context *context, time_t now)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = lws_compare_time_t(context, now, context->tls.last_cert_check_s);
|
||||
if ((!context->tls.last_cert_check_s || n > (24 * 60 * 60)) &&
|
||||
!lws_tls_check_all_cert_lifetimes(context))
|
||||
context->tls.last_cert_check_s = now;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct lws_tls_ops tls_ops_mbedtls = {
|
||||
/* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_mbedtls,
|
||||
|
||||
/* periodic_housekeeping */ tops_periodic_housekeeping_mbedtls,
|
||||
};
|
||||
|
|
|
@ -689,7 +689,21 @@ tops_fake_POLLIN_for_buffered_openssl(struct lws_context_per_thread *pt)
|
|||
return lws_tls_fake_POLLIN_for_buffered(pt);
|
||||
}
|
||||
|
||||
static int
|
||||
tops_periodic_housekeeping_openssl(struct lws_context *context, time_t now)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = lws_compare_time_t(context, now, context->tls.last_cert_check_s);
|
||||
if ((!context->tls.last_cert_check_s || n > (24 * 60 * 60)) &&
|
||||
!lws_tls_check_all_cert_lifetimes(context))
|
||||
context->tls.last_cert_check_s = now;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct lws_tls_ops tls_ops_openssl = {
|
||||
/* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_openssl,
|
||||
/* periodic_housekeeping */ tops_periodic_housekeeping_openssl,
|
||||
|
||||
};
|
||||
|
|
|
@ -93,6 +93,7 @@ struct lws_context_per_thread;
|
|||
|
||||
struct lws_tls_ops {
|
||||
int (*fake_POLLIN_for_buffered)(struct lws_context_per_thread *pt);
|
||||
int (*periodic_housekeeping)(struct lws_context *context, time_t now);
|
||||
};
|
||||
|
||||
#if defined(LWS_WITH_TLS)
|
||||
|
@ -110,6 +111,7 @@ extern const struct lws_tls_ops tls_ops_openssl, tls_ops_mbedtls;
|
|||
struct lws_context_tls {
|
||||
char alpn_discovered[32];
|
||||
const char *alpn_default;
|
||||
time_t last_cert_check_s;
|
||||
};
|
||||
|
||||
struct lws_pt_tls {
|
||||
|
|
|
@ -214,7 +214,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)
|
|||
lws_gate_accepts(context, 0);
|
||||
|
||||
#if defined(LWS_WITH_STATS)
|
||||
context->updated = 1;
|
||||
context->updated = 1;
|
||||
#endif
|
||||
/*
|
||||
* we are not accepted yet, but we need to enter ourselves
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
minimal-http-server-basicauth|Shows how to protect a mount using a password file and basic auth
|
||||
minimal-http-server-dynamic|Serves both static and dynamically generated http content
|
||||
minimal-http-server-eventlib-foreign|Demonstrates integrating lws with a foreign event library
|
||||
minimal-http-server-eventlib-demos|Using the demo plugins with event libraries
|
||||
minimal-http-server-eventlib|Same as minimal-http-server but works with a supported event library
|
||||
minimal-http-server-form-get|Process a GET form
|
||||
minimal-http-server-form-post-file|Process a multipart POST form with file transfer
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
set(SAMP lws-minimal-http-server-eventlib-demos)
|
||||
set(SRCS minimal-http-server-eventlib-demos.c)
|
||||
|
||||
# If we are being built as part of lws, confirm current build config supports
|
||||
# reqconfig, else skip building ourselves.
|
||||
#
|
||||
# If we are being built externally, confirm installed lws was configured to
|
||||
# support reqconfig, else error out with a helpful message about the problem.
|
||||
#
|
||||
MACRO(require_lws_config reqconfig _val result)
|
||||
|
||||
if (DEFINED ${reqconfig})
|
||||
if (${reqconfig})
|
||||
set (rq 1)
|
||||
else()
|
||||
set (rq 0)
|
||||
endif()
|
||||
else()
|
||||
set(rq 0)
|
||||
endif()
|
||||
|
||||
if (${_val} EQUAL ${rq})
|
||||
set(SAME 1)
|
||||
else()
|
||||
set(SAME 0)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})
|
||||
if (${_val})
|
||||
message("${SAMP}: skipping as lws being built without ${reqconfig}")
|
||||
else()
|
||||
message("${SAMP}: skipping as lws built with ${reqconfig}")
|
||||
endif()
|
||||
set(${result} 0)
|
||||
else()
|
||||
if (LWS_WITH_MINIMAL_EXAMPLES)
|
||||
set(MET ${SAME})
|
||||
else()
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig})
|
||||
if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})
|
||||
set(HAS_${reqconfig} 0)
|
||||
else()
|
||||
set(HAS_${reqconfig} 1)
|
||||
endif()
|
||||
if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))
|
||||
set(MET 1)
|
||||
else()
|
||||
set(MET 0)
|
||||
endif()
|
||||
endif()
|
||||
if (NOT MET)
|
||||
if (${_val})
|
||||
message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}")
|
||||
else()
|
||||
message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif()
|
||||
ENDMACRO()
|
||||
|
||||
set(requirements 1)
|
||||
require_lws_config(LWS_ROLE_H1 1 requirements)
|
||||
require_lws_config(LWS_ROLE_WS 1 requirements)
|
||||
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
|
||||
|
||||
if (requirements)
|
||||
add_executable(${SAMP} ${SRCS})
|
||||
|
||||
if (websockets_shared)
|
||||
target_link_libraries(${SAMP} websockets_shared)
|
||||
add_dependencies(${SAMP} websockets_shared)
|
||||
else()
|
||||
target_link_libraries(${SAMP} websockets)
|
||||
endif()
|
||||
endif()
|
|
@ -0,0 +1,30 @@
|
|||
# lws minimal http server eventlib demos
|
||||
|
||||
This demonstrates a slightly more complex demo that can use
|
||||
any of the event loops (it defaults to poll)
|
||||
|
||||
It uses statically included plugins to provide the lws test server functions
|
||||
|
||||
Commandline option|Meaning
|
||||
---|---
|
||||
-d <loglevel>|Debug verbosity in decimal, eg, -d15
|
||||
--uv|Use the libuv event library (lws must have been configured with `-DLWS_WITH_LIBUV=1`)
|
||||
--event|Use the libevent library (lws must have been configured with `-DLWS_WITH_LIBEVENT=1`)
|
||||
--ev|Use the libev event library (lws must have been configured with `-DLWS_WITH_LIBEV=1`)
|
||||
|
||||
## build
|
||||
|
||||
```
|
||||
$ cmake . && make
|
||||
```
|
||||
|
||||
## usage
|
||||
|
||||
```
|
||||
$ ./lws-minimal-http-server-eventlib-demos
|
||||
[2018/03/04 09:30:02:7986] USER: LWS minimal http server-eventlib-demos | visit http://localhost:7681
|
||||
[2018/03/04 09:30:02:7986] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 on
|
||||
```
|
||||
|
||||
Visit http://localhost:7681
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
e2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,52 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
fBrpEY1IATtPq1taBZZogRqI3rOkkPk=
|
||||
-----END PRIVATE KEY-----
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* lws-minimal-http-server-eventlib
|
||||
*
|
||||
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates a minimal http[s] server that can work with any of the
|
||||
* supported event loop backends, or the default poll() one.
|
||||
*
|
||||
* To keep it simple, it serves stuff from the subdirectory
|
||||
* "./mount-origin" of the directory it was started in.
|
||||
* You can change that by changing mount.origin below.
|
||||
*/
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "../../../plugins/protocol_lws_mirror.c"
|
||||
#include "../../../plugins/protocol_lws_status.c"
|
||||
#include "../../../plugins/protocol_dumb_increment.c"
|
||||
#include "../../../plugins/protocol_post_demo.c"
|
||||
|
||||
static struct lws_context *context;
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
/* first protocol must always be HTTP handler */
|
||||
|
||||
{ "http-only", lws_callback_http_dummy, 0, 0, },
|
||||
LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT,
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_STATUS,
|
||||
LWS_PLUGIN_PROTOCOL_POST_DEMO,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
/*
|
||||
* mount handlers for sections of the URL space
|
||||
*/
|
||||
|
||||
static const struct lws_http_mount mount_ziptest = {
|
||||
NULL, /* linked-list pointer to next*/
|
||||
"/ziptest", /* mountpoint in URL namespace on this vhost */
|
||||
"candide.zip", /* handler */
|
||||
NULL, /* default filename if none given */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
LWSMPRO_FILE, /* origin points to a callback */
|
||||
8, /* strlen("/ziptest"), ie length of the mountpoint */
|
||||
NULL,
|
||||
|
||||
{ NULL, NULL } // sentinel
|
||||
};
|
||||
|
||||
static const struct lws_http_mount mount_post = {
|
||||
(struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/
|
||||
"/formtest", /* mountpoint in URL namespace on this vhost */
|
||||
"protocol-post-demo", /* handler */
|
||||
NULL, /* default filename if none given */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
LWSMPRO_CALLBACK, /* origin points to a callback */
|
||||
9, /* strlen("/formtest"), ie length of the mountpoint */
|
||||
NULL,
|
||||
|
||||
{ NULL, NULL } // sentinel
|
||||
};
|
||||
|
||||
|
||||
static const struct lws_http_mount mount = {
|
||||
/* .mount_next */ &mount_post, /* linked-list "next" */
|
||||
/* .mountpoint */ "/", /* mountpoint URL */
|
||||
/* .origin */ "./mount-origin", /* serve from dir */
|
||||
/* .def */ "test.html", /* default filename */
|
||||
/* .protocol */ NULL,
|
||||
/* .cgienv */ NULL,
|
||||
/* .extra_mimetypes */ NULL,
|
||||
/* .interpret */ NULL,
|
||||
/* .cgi_timeout */ 0,
|
||||
/* .cache_max_age */ 0,
|
||||
/* .auth_mask */ 0,
|
||||
/* .cache_reusable */ 0,
|
||||
/* .cache_revalidate */ 0,
|
||||
/* .cache_intermediaries */ 0,
|
||||
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
|
||||
/* .mountpoint_len */ 1, /* char count */
|
||||
/* .basic_auth_login_file */ NULL,
|
||||
};
|
||||
|
||||
void signal_cb(void *handle, int signum)
|
||||
{
|
||||
lwsl_err("%s: signal %d\n", __func__, signum);
|
||||
|
||||
switch (signum) {
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
lws_context_destroy(context);
|
||||
}
|
||||
|
||||
void sigint_handler(int sig)
|
||||
{
|
||||
signal_cb(NULL, sig);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
const char *p;
|
||||
int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
|
||||
/* for LLL_ verbosity above NOTICE to be built into lws,
|
||||
* lws must have been configured and built with
|
||||
* -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
|
||||
/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
|
||||
/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
|
||||
/* | LLL_DEBUG */;
|
||||
|
||||
if ((p = lws_cmdline_option(argc, argv, "-d")))
|
||||
logs = atoi(p);
|
||||
|
||||
lws_set_log_level(logs, NULL);
|
||||
lwsl_user("LWS minimal http server eventlib | visit http://localhost:7681\n");
|
||||
lwsl_user(" [-s (ssl)] [--uv (libuv)] [--ev (libev)] [--event (libevent)]\n");
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
info.error_document_404 = "/404.html";
|
||||
info.pcontext = &context;
|
||||
info.protocols = protocols;
|
||||
info.signal_cb = signal_cb;
|
||||
|
||||
if (lws_cmdline_option(argc, argv, "-s")) {
|
||||
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
info.ssl_cert_filepath = "localhost-100y.cert";
|
||||
info.ssl_private_key_filepath = "localhost-100y.key";
|
||||
}
|
||||
|
||||
if (lws_cmdline_option(argc, argv, "--uv"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBUV;
|
||||
else
|
||||
if (lws_cmdline_option(argc, argv, "--event"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEVENT;
|
||||
else
|
||||
if (lws_cmdline_option(argc, argv, "--ev"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEV;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
lwsl_err("lws init failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (!lws_service(context, 0))
|
||||
;
|
||||
|
||||
lwsl_info("calling external context destroy\n");
|
||||
lws_context_destroy(context);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<meta charset="UTF-8">
|
||||
<html>
|
||||
<body>
|
||||
<img src="libwebsockets.org-logo.png"><br>
|
||||
<h1>404</h1>
|
||||
Sorry, that file doesn't exist.
|
||||
</body>
|
||||
</html>
|
||||
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.4 MiB |
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* This section around grayOut came from here:
|
||||
* http://www.codingforums.com/archive/index.php/t-151720.html
|
||||
* Assumed public domain
|
||||
*
|
||||
* Init like this in your main html script, this also reapplies the gray
|
||||
*
|
||||
* lws_gray_out(true,{'zindex':'499'});
|
||||
*
|
||||
* To remove the gray
|
||||
*
|
||||
* lws_gray_out(false);
|
||||
*
|
||||
*/
|
||||
|
||||
function lws_gray_out(vis, options) {
|
||||
|
||||
var options = options || {};
|
||||
var zindex = options.zindex || 50;
|
||||
var opacity = options.opacity || 70;
|
||||
var opaque = (opacity / 100);
|
||||
var bgcolor = options.bgcolor || '#000000';
|
||||
var dark = document.getElementById('darkenScreenObject');
|
||||
|
||||
if (!dark) {
|
||||
var tbody = document.getElementsByTagName("body")[0];
|
||||
var tnode = document.createElement('div');
|
||||
tnode.style.position = 'absolute';
|
||||
tnode.style.top = '0px';
|
||||
tnode.style.left = '0px';
|
||||
tnode.style.overflow = 'hidden';
|
||||
tnode.style.display ='none';
|
||||
tnode.id = 'darkenScreenObject';
|
||||
tbody.appendChild(tnode);
|
||||
dark = document.getElementById('darkenScreenObject');
|
||||
}
|
||||
if (vis) {
|
||||
dark.style.opacity = opaque;
|
||||
dark.style.MozOpacity = opaque;
|
||||
// dark.style.filter ='alpha(opacity='+opacity+')';
|
||||
dark.style.zIndex = zindex;
|
||||
dark.style.backgroundColor = bgcolor;
|
||||
dark.style.width = gsize(1);
|
||||
dark.style.height = gsize(0);
|
||||
dark.style.display ='block';
|
||||
addEvent(window, "resize",
|
||||
function() {
|
||||
dark.style.height = gsize(0);
|
||||
dark.style.width = gsize(1);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
dark.style.display = 'none';
|
||||
removeEvent(window, "resize",
|
||||
function() {
|
||||
dark.style.height = gsize(0);
|
||||
dark.style.width = gsize(1);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function gsize(ptype)
|
||||
{
|
||||
var h = document.compatMode == 'CSS1Compat' &&
|
||||
!window.opera ?
|
||||
document.documentElement.clientHeight :
|
||||
document.body.clientHeight;
|
||||
var w = document.compatMode == 'CSS1Compat' &&
|
||||
!window.opera ?
|
||||
document.documentElement.clientWidth :
|
||||
document.body.clientWidth;
|
||||
if (document.body &&
|
||||
(document.body.scrollWidth || document.body.scrollHeight)) {
|
||||
var pageWidth = (w > (t = document.body.scrollWidth)) ?
|
||||
("" + w + "px") : ("" + (t) + "px");
|
||||
var pageHeight = (h > (t = document.body.scrollHeight)) ?
|
||||
("" + h + "px") : ("" + (t) + "px");
|
||||
} else if (document.body.offsetWidth) {
|
||||
var pageWidth = (w > (t = document.body.offsetWidth)) ?
|
||||
("" + w + "px") : ("" + (t) + "px");
|
||||
var pageHeight =(h > (t = document.body.offsetHeight)) ?
|
||||
("" + h + "px") : ("" + (t) + "px");
|
||||
} else {
|
||||
var pageWidth = '100%';
|
||||
var pageHeight = '100%';
|
||||
}
|
||||
return (ptype == 1) ? pageWidth : pageHeight;
|
||||
}
|
||||
|
||||
function addEvent( obj, type, fn ) {
|
||||
if ( obj.attachEvent ) {
|
||||
obj['e' + type + fn] = fn;
|
||||
obj[type+fn] = function() { obj['e' + type+fn]( window.event );}
|
||||
obj.attachEvent('on' + type, obj[type + fn]);
|
||||
} else
|
||||
obj.addEventListener(type, fn, false);
|
||||
}
|
||||
|
||||
function removeEvent( obj, type, fn ) {
|
||||
if ( obj.detachEvent ) {
|
||||
obj.detachEvent('on' + type, obj[type + fn]);
|
||||
obj[type + fn] = null;
|
||||
} else
|
||||
obj.removeEventListener(type, fn, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* end of grayOut related stuff
|
||||
*/
|
||||
|
||||
/*
|
||||
* lws-meta helpers
|
||||
*/
|
||||
|
||||
var lws_meta_cmd = {
|
||||
OPEN_SUBCHANNEL: 0x41,
|
||||
/**< Client requests to open new subchannel
|
||||
*/
|
||||
OPEN_RESULT: 0x42,
|
||||
/**< Result of client request to open new subchannel */
|
||||
CLOSE_NOT: 0x43,
|
||||
CLOSE_RQ: 0x44,
|
||||
/**< client requests to close a subchannel */
|
||||
WRITE: 0x45,
|
||||
/**< connection writes something to specific channel index */
|
||||
RX: 0x46,
|
||||
};
|
||||
|
||||
function new_ws(urlpath, protocol)
|
||||
{
|
||||
if (typeof MozWebSocket != "undefined")
|
||||
return new MozWebSocket(urlpath, protocol);
|
||||
|
||||
return new WebSocket(urlpath, protocol);
|
||||
}
|
||||
|
||||
function lws_meta_ws() {
|
||||
var real;
|
||||
|
||||
var channel_id_to_child;
|
||||
var pending_children;
|
||||
var active_children;
|
||||
}
|
||||
|
||||
function lws_meta_ws_child() {
|
||||
var onopen;
|
||||
var onmessage;
|
||||
var onclose;
|
||||
|
||||
var channel_id;
|
||||
|
||||
var subprotocol;
|
||||
var suburl;
|
||||
var cookie;
|
||||
|
||||
var extensions;
|
||||
|
||||
var parent;
|
||||
}
|
||||
|
||||
lws_meta_ws_child.prototype.send = function(data)
|
||||
{
|
||||
|
||||
if (typeof data == "string") {
|
||||
data = String.fromCharCode(lws_meta_cmd.WRITE) +
|
||||
String.fromCharCode(this.channel_id) +
|
||||
data;
|
||||
|
||||
return this.parent.real.send(data);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
var ab = new Uint8Array(data.length + 2);
|
||||
|
||||
ab[0] = lws_meta_cmd.WRITE;
|
||||
ab[1] = this.channel_id;
|
||||
ab.set(data, 2);
|
||||
|
||||
return this.parent.real.send(ab);
|
||||
}
|
||||
}
|
||||
|
||||
lws_meta_ws_child.prototype.close = function(close_code, close_string)
|
||||
{
|
||||
var pkt = new Uint8Array(129), m = 0, pkt1;
|
||||
|
||||
pkt[m++] = lws_meta_cmd.CLOSE_RQ;
|
||||
pkt[m++] = this.channel_id;
|
||||
|
||||
pkt[m++] = close_string.length + 0x20;
|
||||
|
||||
pkt[m++] = close_code / 256;
|
||||
pkt[m++] = close_code % 256;
|
||||
|
||||
for (i = 0; i < close_string.length; i++)
|
||||
pkt[m++] = close_string.charCodeAt(i);
|
||||
|
||||
pkt1 = new Uint8Array(m);
|
||||
for (n = 0; n < m; n++)
|
||||
pkt1[n] = pkt[n];
|
||||
|
||||
this.parent.real.send(pkt1.buffer);
|
||||
}
|
||||
|
||||
/* make a real ws connection using lws_meta*/
|
||||
lws_meta_ws.prototype.new_parent = function(urlpath)
|
||||
{
|
||||
var n, i, m = 0, pkt1;
|
||||
|
||||
this.ordinal = 1;
|
||||
this.pending_children = [];
|
||||
this.active_children = [];
|
||||
this.real = new_ws(urlpath, "lws-meta");
|
||||
|
||||
this.real.binaryType = 'arraybuffer';
|
||||
this.real.myparent = this;
|
||||
|
||||
this.real.onopen = function() {
|
||||
pkt = new Uint8Array(1024);
|
||||
var n, i, m = 0, pkt1;
|
||||
console.log("real open - pending children " + this.myparent.pending_children.length);
|
||||
for (n = 0; n < this.myparent.pending_children.length; n++) {
|
||||
|
||||
var p = this.myparent.pending_children[n];
|
||||
|
||||
pkt[m++] = lws_meta_cmd.OPEN_SUBCHANNEL;
|
||||
for (i = 0; i < p.subprotocol.length; i++)
|
||||
pkt[m++] = p.subprotocol.charCodeAt(i);
|
||||
pkt[m++] = 0;
|
||||
for (i = 0; i < p.suburl.length; i++)
|
||||
pkt[m++] = p.suburl.charCodeAt(i);
|
||||
pkt[m++] = 0;
|
||||
for (i = 0; i < p.cookie.length; i++)
|
||||
pkt[m++] = p.cookie.charCodeAt(i);
|
||||
pkt[m++] = 0;
|
||||
}
|
||||
|
||||
pkt1 = new Uint8Array(m);
|
||||
for (n = 0; n < m; n++)
|
||||
pkt1[n] = pkt[n];
|
||||
|
||||
console.log(this.myparent.pending_children[0].subprotocol);
|
||||
console.log(pkt1);
|
||||
|
||||
this.send(pkt1.buffer);
|
||||
}
|
||||
|
||||
|
||||
this.real.onmessage = function(msg) {
|
||||
|
||||
if (typeof msg.data != "string") {
|
||||
var ba = new Uint8Array(msg.data), n = 0;
|
||||
|
||||
while (n < ba.length) {
|
||||
|
||||
switch (ba[n++]) {
|
||||
case lws_meta_cmd.OPEN_RESULT:
|
||||
{
|
||||
var m = 0, cookie = "", protocol = "", ch = 0;
|
||||
var ws = this.myparent;
|
||||
/* cookie NUL
|
||||
* channel index + 0x20
|
||||
* protocol NUL
|
||||
*/
|
||||
while (ba[n])
|
||||
cookie = cookie + String.fromCharCode(ba[n++]);
|
||||
n++;
|
||||
ch = ba[n++];
|
||||
|
||||
while (ba[n])
|
||||
protocol = protocol + String.fromCharCode(ba[n++]);
|
||||
|
||||
console.log("open result " + cookie + " " + protocol + " " + ch + " pending len " + ws.pending_children.length);
|
||||
|
||||
for (m = 0; m < ws.pending_children.length; m++) {
|
||||
if (ws.pending_children[m].cookie == cookie) {
|
||||
var newchild = ws.pending_children[m];
|
||||
|
||||
/* found it */
|
||||
ws.pending_children[m].channel_id = ch;
|
||||
/* add to active children array */
|
||||
ws.active_children.push(ws.pending_children[m]);
|
||||
/* remove from pending children array */
|
||||
ws.pending_children.splice(m, 1);
|
||||
|
||||
newchild.parent = ws;
|
||||
newchild.extensions = this.extensions;
|
||||
|
||||
newchild.onopen();
|
||||
|
||||
console.log("made active " + cookie);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case lws_meta_cmd.CLOSE_NOT:
|
||||
{
|
||||
var code = 0, str = "", ch = 0, m, le;
|
||||
var ba = new Uint8Array(msg.data);
|
||||
/*
|
||||
* BYTE: channel
|
||||
* BYTE: MSB status code
|
||||
* BYTE: LSB status code
|
||||
* BYTES: rest of message is close status string
|
||||
*/
|
||||
|
||||
ch = ba[n++];
|
||||
le = ba[n++] - 0x20;
|
||||
code = ba[n++] * 256;
|
||||
code += ba[n++];
|
||||
|
||||
while (le--)
|
||||
str += String.fromCharCode(ba[n++]);
|
||||
|
||||
console.log("channel id " + ch + " code " + code + " str " + str + " len " + str.length);
|
||||
|
||||
for (m = 0; m < this.myparent.active_children.length; m++)
|
||||
if (this.myparent.active_children[m].channel_id == ch) {
|
||||
var child = this.myparent.active_children[m];
|
||||
var ms = new CloseEvent("close", { code:code, reason:str } );
|
||||
|
||||
/* reply with close ack */
|
||||
this.send(msg.data);
|
||||
|
||||
if (child.onclose)
|
||||
child.onclose(ms);
|
||||
|
||||
this.myparent.active_children.splice(m, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} // switch
|
||||
}
|
||||
} else {
|
||||
if (msg.data.charCodeAt(0) == lws_meta_cmd.WRITE ) {
|
||||
var ch = msg.data.charCodeAt(1), m, ms;
|
||||
var ws = this.myparent, ms;
|
||||
|
||||
for (m = 0; m < ws.active_children.length; m++) {
|
||||
if (ws.active_children[m].channel_id == ch) {
|
||||
ms = new MessageEvent("WebSocket", { data: msg.data.substr(2, msg.data.length - 2) } );
|
||||
if (ws.active_children[m].onmessage)
|
||||
ws.active_children[m].onmessage(ms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.real.onclose = function() {
|
||||
var ws = this.myparent, m;
|
||||
for (m = 0; m < ws.active_children.length; m++) {
|
||||
var child = ws.active_children[m];
|
||||
var ms = new CloseEvent("close", { code:1000, reason:"parent closed" } );
|
||||
|
||||
if (child.onclose)
|
||||
child.onclose(ms);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* make a child connection using existing lws_meta real ws connection */
|
||||
lws_meta_ws.prototype.new_ws = function(suburl, protocol)
|
||||
{
|
||||
var ch = new lws_meta_ws_child();
|
||||
|
||||
ch.suburl = suburl;
|
||||
ch.subprotocol = protocol;
|
||||
ch.cookie = "C" + this.ordinal++;
|
||||
|
||||
this.pending_children.push(ch);
|
||||
|
||||
if (this.real.readyState == 1)
|
||||
this.real.onopen();
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* end of lws-meta helpers
|
||||
*/
|
||||
|
||||
function lws_san(s)
|
||||
{
|
||||
if (s.search("<") != -1)
|
||||
return "invalid string";
|
||||
|
||||
return s;
|
||||
}
|
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -41,8 +41,8 @@ exits itself.
|
|||
## usage
|
||||
|
||||
```
|
||||
$ ./lws-minimal-http-server-libuv-foreign
|
||||
[2018/03/29 12:19:31:3480] USER: LWS minimal http server libuv + foreign loop | visit http://localhost:7681
|
||||
$ ./lws-minimal-http-server-eventlib-foreign
|
||||
[2018/03/29 12:19:31:3480] USER: LWS minimal http server eventlib + foreign loop | visit http://localhost:7681
|
||||
[2018/03/29 12:19:31:3724] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 off
|
||||
[2018/03/29 12:19:31:3804] NOTICE: Using foreign event loop...
|
||||
[2018/03/29 12:19:31:3938] USER: Foreign 1Hz timer
|
||||
|
|
|
@ -337,7 +337,7 @@ int main(int argc, const char **argv)
|
|||
logs = atoi(p);
|
||||
|
||||
lws_set_log_level(logs, NULL);
|
||||
lwsl_user("LWS minimal http server libuv + foreign loop |"
|
||||
lwsl_user("LWS minimal http server eventlib + foreign loop |"
|
||||
" visit http://localhost:7681\n");
|
||||
|
||||
/*
|
||||
|
@ -383,8 +383,7 @@ int main(int argc, const char **argv)
|
|||
lwsl_user("\n");
|
||||
lwsl_user(" Finally close only the timer and signalhandler and\n");
|
||||
lwsl_user(" exit the loop cleanly\n");
|
||||
|
||||
lwsl_notice("%s\n", info.ssl_cert_filepath);
|
||||
lwsl_user("\n");
|
||||
|
||||
/* foreign loop specific startup and run */
|
||||
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
# lws minimal http server libuv
|
||||
# lws minimal http server eventlib
|
||||
|
||||
This demonstrates a minimal http server that can use any of the event libraries
|
||||
|
||||
Commandline option|Meaning
|
||||
---|---
|
||||
-d <loglevel>|Debug verbosity in decimal, eg, -d15
|
||||
--uv|Use the libuv event library (lws must have been configured with `-DLWS_WITH_LIBUV=1`)
|
||||
--event|Use the libevent library (lws must have been configured with `-DLWS_WITH_LIBEVENT=1`)
|
||||
--ev|Use the libev event library (lws must have been configured with `-DLWS_WITH_LIBEV=1`)
|
||||
|
||||
## build
|
||||
|
||||
|
@ -9,8 +18,8 @@
|
|||
## usage
|
||||
|
||||
```
|
||||
$ ./lws-minimal-http-server-libuv
|
||||
[2018/03/04 09:30:02:7986] USER: LWS minimal http server-libuv | visit http://localhost:7681
|
||||
$ ./lws-minimal-http-server-eventlib
|
||||
[2018/03/04 09:30:02:7986] USER: LWS minimal http server-eventlib | visit http://localhost:7681
|
||||
[2018/03/04 09:30:02:7986] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 on
|
||||
```
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue