Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"", "gen_ut":1711642003, "reponame":"libwebsockets", "desc":"libwebsockets lightweight C networking library", "owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets", "f":3, "items": [ {"schema":"libjg2-1", "cid":"5d9fd48a3f5d5f61ffd682cd2960b178", "commit": {"type":"commit", "time": 1525260453, "time_ofs": 480, "oid_tree": { "oid": "a38a861b57c62ac90b0bb8aee24f9d6d5ffb8155", "alias": []}, "oid":{ "oid": "a01ad0dd2076cf597c58cbb945ba6dbae3c9878c", "alias": []}, "msg": "hrtimer: add support for libevent and libev", "sig_commit": { "git_time": { "time": 1525260453, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }, "sig_author": { "git_time": { "time": 1525257358, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }}, "body": "hrtimer: add support for libevent and libev" , "diff": "diff --git a/.gitignore b/.gitignore\nindex d2b3e44..74c0e3c 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -47,3 +47,5 @@ libwebsockets.pc\n build/\n *.swp\n doc\n+/build2/\n+/build3/\ndiff --git a/lib/context.c b/lib/context.c\nindex c85a481..2ccfbe9 100644\n--- a/lib/context.c\n+++ b/lib/context.c\n@@ -1163,6 +1163,7 @@ lws_create_context(const struct lws_context_creation_info *info)\n \tlwsl_info(\u0022Using event loop: %s\u005cn\u0022, context-\u003eevent_loop_ops-\u003ename);\n \n #if defined(LWS_WITH_TLS)\n+\ttime(\u0026context-\u003etls.last_cert_check_s);\n \tif (info-\u003ealpn)\n \t\tcontext-\u003etls.alpn_default \u003d info-\u003ealpn;\n \telse {\n@@ -1365,8 +1366,6 @@ lws_create_context(const struct lws_context_creation_info *info)\n \tif (!lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))\n \t\tlws_plat_drop_app_privileges(info);\n \n-\ttime(\u0026context-\u003elast_cert_check_s);\n-\n \t/* expedite post-context init (eg, protocols) */\n \tlws_cancel_service(context);\n \n@@ -1729,6 +1728,22 @@ static void\n lws_context_destroy3(struct lws_context *context)\n {\n \tstruct lws_context **pcontext_finalize \u003d context-\u003epcontext_finalize;\n+\tstruct lws_context_per_thread *pt;\n+\tint n;\n+\n+\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n+\t\tpt \u003d \u0026context-\u003ept[n];\n+\n+\t\tif (context-\u003eevent_loop_ops-\u003edestroy_pt)\n+\t\t\tcontext-\u003eevent_loop_ops-\u003edestroy_pt(context, n);\n+\n+\t\tlws_free_set_NULL(context-\u003ept[n].serv_buf);\n+\n+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n+\t\twhile (pt-\u003ehttp.ah_list)\n+\t\t\t_lws_destroy_ah(pt, pt-\u003ehttp.ah_list);\n+#endif\n+\t}\n \n \tlws_free(context);\n \tlwsl_info(\u0022%s: ctx %p freed\u005cn\u0022, __func__, context);\n@@ -1746,8 +1761,9 @@ lws_context_destroy2(struct lws_context *context)\n {\n \tstruct lws_vhost *vh \u003d NULL, *vh1;\n #if defined(LWS_WITH_PEER_LIMITS)\n-\tuint32_t n;\n+\tuint32_t nu;\n #endif\n+\tint n;\n \n \tlwsl_info(\u0022%s: ctx %p\u005cn\u0022, __func__, context);\n \n@@ -1780,9 +1796,9 @@ lws_context_destroy2(struct lws_context *context)\n \tlws_plat_context_late_destroy(context);\n \n #if defined(LWS_WITH_PEER_LIMITS)\n-\tfor (n \u003d 0; n \u003c context-\u003epl_hash_elements; n++)\t{\n+\tfor (nu \u003d 0; nu \u003c context-\u003epl_hash_elements; nu++)\t{\n \t\tlws_start_foreach_llp(struct lws_peer **, peer,\n-\t\t\t\t context-\u003epl_hash_table[n]) {\n+\t\t\t\t context-\u003epl_hash_table[nu]) {\n \t\t\tstruct lws_peer *df \u003d *peer;\n \t\t\t*peer \u003d df-\u003enext;\n \t\t\tlws_free(df);\n@@ -1807,6 +1823,11 @@ lws_context_destroy2(struct lws_context *context)\n \t\t\treturn;\n \t\t}\n \n+\tif (!context-\u003ept[0].event_loop_foreign)\n+\t\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++)\n+\t\t\tif (context-\u003ept[n].inside_service)\n+\t\t\t\treturn;\n+\n \tlws_context_destroy3(context);\n }\n \n@@ -1844,6 +1865,8 @@ lws_context_destroy(struct lws_context *context)\n \t\t}\n \t\tlwsl_info(\u0022%s: ctx %p: already being destroyed\u005cn\u0022,\n \t\t\t __func__, context);\n+\n+\t\tlws_context_destroy3(context);\n \t\treturn;\n \t}\n \n@@ -1891,20 +1914,6 @@ lws_context_destroy(struct lws_context *context)\n \t\tlws_pt_mutex_destroy(pt);\n \t}\n \n-\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n-\t\tpt \u003d \u0026context-\u003ept[n];\n-\n-\t\tif (context-\u003eevent_loop_ops-\u003edestroy_pt)\n-\t\t\tcontext-\u003eevent_loop_ops-\u003edestroy_pt(context, n);\n-\n-\t\tlws_free_set_NULL(context-\u003ept[n].serv_buf);\n-\n-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n-\t\twhile (pt-\u003ehttp.ah_list)\n-\t\t\t_lws_destroy_ah(pt, pt-\u003ehttp.ah_list);\n-#endif\n-\t}\n-\n \t/*\n \t * inform all the protocols that they are done and will have no more\n \t * callbacks.\n@@ -1944,10 +1953,5 @@ lws_context_destroy(struct lws_context *context)\n \t\treturn;\n \t}\n \n-\tif (!context-\u003ept[0].event_loop_foreign)\n-\t\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++)\n-\t\t\tif (context-\u003ept[n].inside_service)\n-\t\t\t\treturn;\n-\n \tlws_context_destroy2(context);\n }\ndiff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c\nindex 746d571..d60072c 100644\n--- a/lib/event-libs/libev/libev.c\n+++ b/lib/event-libs/libev/libev.c\n@@ -1,7 +1,7 @@\n /*\n * libwebsockets - small server side websockets and web server implementation\n *\n- * Copyright (C) 2010-2017 Andy Green \u003candy@warmcat.com\u003e\n+ * Copyright (C) 2010-2018 Andy Green \u003candy@warmcat.com\u003e\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n@@ -22,12 +22,65 @@\n #include \u0022private-libwebsockets.h\u0022\n \n static void\n+lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)\n+{\n+\tstruct lws_context_per_thread *pt \u003d\n+\t\t\t(struct lws_context_per_thread *)watcher-\u003edata;\n+\tlws_usec_t us;\n+\n+\tlws_pt_lock(pt, __func__);\n+\tus \u003d __lws_hrtimer_service(pt);\n+\tif (us !\u003d LWS_HRTIMER_NOWAIT) {\n+\t\tev_timer_set(\u0026pt-\u003eev.hrtimer, ((float)us) / 1000000.0, 0);\n+\t\tev_timer_start(pt-\u003eev.io_loop, \u0026pt-\u003eev.hrtimer);\n+\t}\n+\tlws_pt_unlock(pt);\n+}\n+\n+static void\n+lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents)\n+{\n+\tstruct lws_context_per_thread *pt \u003d lws_container_of(handle,\n+\t\t\t\t\tstruct lws_context_per_thread, ev.idle);\n+\tlws_usec_t us;\n+\n+\tlws_service_do_ripe_rxflow(pt);\n+\n+\t/*\n+\t * is there anybody with pending stuff that needs service forcing?\n+\t */\n+\tif (!lws_service_adjust_timeout(pt-\u003econtext, 1, pt-\u003etid)) {\n+\t\t/* -1 timeout means just do forced service */\n+\t\t_lws_plat_service_tsi(pt-\u003econtext, -1, pt-\u003etid);\n+\t\t/* still somebody left who wants forced service? */\n+\t\tif (!lws_service_adjust_timeout(pt-\u003econtext, 1, pt-\u003etid))\n+\t\t\t/* yes... come back again later */\n+\t\treturn;\n+\t}\n+\n+\t/* account for hrtimer */\n+\n+\tlws_pt_lock(pt, __func__);\n+\tus \u003d __lws_hrtimer_service(pt);\n+\tif (us !\u003d LWS_HRTIMER_NOWAIT) {\n+\t\tev_timer_set(\u0026pt-\u003eev.hrtimer, ((float)us) / 1000000.0, 0);\n+\t\tev_timer_start(pt-\u003eev.io_loop, \u0026pt-\u003eev.hrtimer);\n+\t}\n+\tlws_pt_unlock(pt);\n+\n+\t/* there is nobody who needs service forcing, shut down idle */\n+\tev_idle_stop(loop, handle);\n+}\n+\n+static void\n lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)\n {\n+\tstruct lws_context_per_thread *pt;\n \tstruct lws_io_watcher *lws_io \u003d lws_container_of(watcher,\n \t\t\t\t\tstruct lws_io_watcher, ev.watcher);\n \tstruct lws_context *context \u003d lws_io-\u003econtext;\n \tstruct lws_pollfd eventfd;\n+\tstruct lws *wsi;\n \n \tif (revents \u0026 EV_ERROR)\n \t\treturn;\n@@ -45,7 +98,12 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)\n \t\teventfd.revents |\u003d LWS_POLLOUT;\n \t}\n \n-\tlws_service_fd(context, \u0026eventfd);\n+\twsi \u003d wsi_from_fd(context, watcher-\u003efd);\n+\tpt \u003d \u0026context-\u003ept[(int)wsi-\u003etsi];\n+\n+\tlws_service_fd_tsi(context, \u0026eventfd, (int)wsi-\u003etsi);\n+\n+\tev_idle_start(pt-\u003eev.io_loop, \u0026pt-\u003eev.idle);\n }\n \n LWS_VISIBLE void\n@@ -64,6 +122,7 @@ lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)\n static int\n elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)\n {\n+\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[tsi];\n \tstruct ev_signal *w_sigint \u003d \u0026context-\u003ept[tsi].w_sigint.ev.watcher;\n \tstruct lws_vhost *vh \u003d context-\u003evhost_list;\n \tconst char *backend_name;\n@@ -84,7 +143,7 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)\n \t\treturn -1;\n \t}\n \n-\tcontext-\u003ept[tsi].ev.io_loop \u003d loop;\n+\tpt-\u003eev.io_loop \u003d loop;\n \n \t/*\n \t * Initialize the accept w_accept with all the listening sockets\n@@ -138,6 +197,11 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)\n \tlwsl_info(\u0022 libev backend: %s\u005cn\u0022, backend_name);\n \t(void)backend_name;\n \n+\tev_timer_init(\u0026pt-\u003eev.hrtimer, lws_ev_hrtimer_cb, 0, 0);\n+\tpt-\u003eev.hrtimer.data \u003d pt;\n+\n+\tev_idle_init(\u0026pt-\u003eev.idle, lws_ev_idle_cb);\n+\n \treturn status;\n }\n \n@@ -147,17 +211,22 @@ elops_destroy_pt_ev(struct lws_context *context, int tsi)\n \tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[tsi];\n \tstruct lws_vhost *vh \u003d context-\u003evhost_list;\n \n-\tif (!pt-\u003eev.io_loop)\n-\t\treturn;\n-\n \twhile (vh) {\n \t\tif (vh-\u003elserv_wsi)\n \t\t\tev_io_stop(pt-\u003eev.io_loop, \u0026vh-\u003ew_accept.ev.watcher);\n \t\tvh \u003d vh-\u003evhost_next;\n \t}\n-\tif (!pt-\u003eevent_loop_foreign)\n+\n+\t/* static assets */\n+\n+\tev_timer_stop(pt-\u003eev.io_loop, \u0026pt-\u003eev.hrtimer);\n+\tev_idle_stop(pt-\u003eev.io_loop, \u0026pt-\u003eev.idle);\n+\n+\tif (!pt-\u003eevent_loop_foreign) {\n \t\tev_signal_stop(pt-\u003eev.io_loop, \u0026pt-\u003ew_sigint.ev.watcher);\n \n+\t\tev_loop_destroy(pt-\u003eev.io_loop);\n+\t}\n }\n \n static int\n@@ -226,7 +295,7 @@ static int\n elops_destroy_context2_ev(struct lws_context *context)\n {\n \tstruct lws_context_per_thread *pt;\n-\tint n, m, internal \u003d 0;\n+\tint n, m;\n \n \tlwsl_debug(\u0022%s\u005cn\u0022, __func__);\n \n@@ -240,7 +309,6 @@ elops_destroy_context2_ev(struct lws_context *context)\n \t\tif (pt-\u003eevent_loop_foreign || !pt-\u003eev.io_loop)\n \t\t\tcontinue;\n \n-\t\tinternal \u003d 1;\n \t\tif (!context-\u003efinalize_destroy_after_internal_loops_stopped) {\n \t\t\tev_break(pt-\u003eev.io_loop, EVBREAK_ONE);\n \t\t\tcontinue;\n@@ -252,7 +320,7 @@ elops_destroy_context2_ev(struct lws_context *context)\n \t\tev_loop_destroy(pt-\u003eev.io_loop);\n \t}\n \n-\treturn internal;\n+\treturn 0;\n }\n \n static int\n@@ -281,6 +349,15 @@ elops_init_vhost_listen_wsi_ev(struct lws *wsi)\n \treturn 0;\n }\n \n+static void\n+elops_destroy_wsi_ev(struct lws *wsi)\n+{\n+\tstruct lws_context_per_thread *pt \u003d \u0026wsi-\u003econtext-\u003ept[(int)wsi-\u003etsi];\n+\n+\tev_io_stop(pt-\u003eev.io_loop, \u0026wsi-\u003ew_read.ev.watcher);\n+\tev_io_stop(pt-\u003eev.io_loop, \u0026wsi-\u003ew_write.ev.watcher);\n+}\n+\n struct lws_event_loop_ops event_loop_ops_ev \u003d {\n \t/* name */\t\t\t\u0022libev\u0022,\n \t/* init_context */\t\telops_init_context_ev,\n@@ -295,7 +372,7 @@ struct lws_event_loop_ops event_loop_ops_ev \u003d {\n \t/* io */\t\t\telops_io_ev,\n \t/* run_pt */\t\t\telops_run_pt_ev,\n \t/* destroy_pt */\t\telops_destroy_pt_ev,\n-\t/* destroy wsi */\t\tNULL,\n+\t/* destroy wsi */\t\telops_destroy_wsi_ev,\n \n \t/* periodic_events_available */\t0,\n };\ndiff --git a/lib/event-libs/libev/private.h b/lib/event-libs/libev/private.h\nindex 54e1b12..52de727 100644\n--- a/lib/event-libs/libev/private.h\n+++ b/lib/event-libs/libev/private.h\n@@ -23,9 +23,19 @@\n \n #include \u003cev.h\u003e\n \n+#define LWS_EV_REFCOUNT_STATIC_HANDLE_NEW(_x, _ctx) \u005c\n+\t\t{ (_x)-\u003edata \u003d _ctx; \u005c\n+\t\t_ctx-\u003ecount_event_loop_static_asset_handles++; }\n+#define LWS_EV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x) \u005c\n+\t\t\t((struct lws_context *)(_x)-\u003edata)))\n+#define LWS_EV_REFCOUNT_STATIC_HANDLE_DESTROYED(_x) \u005c\n+\t\t(--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-\u003e \u005c\n+\t\t\t\tcount_event_loop_static_asset_handles))\n+\n struct lws_pt_eventlibs_libev {\n \tstruct ev_loop *io_loop;\n \tstruct ev_timer hrtimer;\n+\tstruct ev_idle idle;\n };\n \n struct lws_io_watcher_libev {\ndiff --git a/lib/event-libs/libevent/libevent.c b/lib/event-libs/libevent/libevent.c\nindex 43dda05..5cb4726 100644\n--- a/lib/event-libs/libevent/libevent.c\n+++ b/lib/event-libs/libevent/libevent.c\n@@ -22,23 +22,82 @@\n #include \u0022private-libwebsockets.h\u0022\n \n static void\n+lws_event_hrtimer_cb(int fd, short event, void *p)\n+{\n+\tstruct lws_context_per_thread *pt \u003d (struct lws_context_per_thread *)p;\n+\tstruct timeval tv;\n+\tlws_usec_t us;\n+\n+\tlws_pt_lock(pt, __func__);\n+\tus \u003d __lws_hrtimer_service(pt);\n+\tif (us !\u003d LWS_HRTIMER_NOWAIT) {\n+\t\ttv.tv_sec \u003d us / 1000000;\n+\t\ttv.tv_usec \u003d us - (tv.tv_sec * 1000000);\n+\t\tevtimer_add(pt-\u003eevent.hrtimer, \u0026tv);\n+\t}\n+\tlws_pt_unlock(pt);\n+}\n+\n+static void\n+lws_event_idle_timer_cb(int fd, short event, void *p)\n+{\n+\tstruct lws_context_per_thread *pt \u003d (struct lws_context_per_thread *)p;\n+\tstruct timeval tv;\n+\tlws_usec_t us;\n+\n+\tlws_service_do_ripe_rxflow(pt);\n+\n+\t/*\n+\t * is there anybody with pending stuff that needs service forcing?\n+\t */\n+\tif (!lws_service_adjust_timeout(pt-\u003econtext, 1, pt-\u003etid)) {\n+\t\t/* -1 timeout means just do forced service */\n+\t\t_lws_plat_service_tsi(pt-\u003econtext, -1, pt-\u003etid);\n+\t\t/* still somebody left who wants forced service? */\n+\t\tif (!lws_service_adjust_timeout(pt-\u003econtext, 1, pt-\u003etid)) {\n+\t\t\t/* yes... come back again later */\n+\n+\t\t\ttv.tv_sec \u003d 0;\n+\t\t\ttv.tv_usec \u003d 1000;\n+\t\t\tevtimer_add(pt-\u003eevent.idle_timer, \u0026tv);\n+\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\n+\t/* account for hrtimer */\n+\n+\tlws_pt_lock(pt, __func__);\n+\tus \u003d __lws_hrtimer_service(pt);\n+\tif (us !\u003d LWS_HRTIMER_NOWAIT) {\n+\t\ttv.tv_sec \u003d us / 1000000;\n+\t\ttv.tv_usec \u003d us - (tv.tv_sec * 1000000);\n+\t\tevtimer_add(pt-\u003eevent.hrtimer, \u0026tv);\n+\t}\n+\tlws_pt_unlock(pt);\n+}\n+\n+static void\n lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)\n {\n \tstruct lws_io_watcher *lws_io \u003d (struct lws_io_watcher *)ctx;\n \tstruct lws_context *context \u003d lws_io-\u003econtext;\n+\tstruct lws_context_per_thread *pt;\n \tstruct lws_pollfd eventfd;\n+\tstruct timeval tv;\n+\tstruct lws *wsi;\n \n \tif (revents \u0026 EV_TIMEOUT)\n \t\treturn;\n \n \t/* !!! EV_CLOSED doesn't exist in libevent2 */\n-\t#if LIBEVENT_VERSION_NUMBER \u003c 0x02000000\n+#if LIBEVENT_VERSION_NUMBER \u003c 0x02000000\n \tif (revents \u0026 EV_CLOSED) {\n \t\tevent_del(lws_io-\u003eevent.watcher);\n \t\tevent_free(lws_io-\u003eevent.watcher);\n \t\treturn;\n \t}\n-\t#endif\n+#endif\n \n \teventfd.fd \u003d sock_fd;\n \teventfd.events \u003d 0;\n@@ -52,7 +111,16 @@ lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)\n \t\teventfd.revents |\u003d LWS_POLLOUT;\n \t}\n \n-\tlws_service_fd(context, \u0026eventfd);\n+\twsi \u003d wsi_from_fd(context, sock_fd);\n+\tpt \u003d \u0026context-\u003ept[(int)wsi-\u003etsi];\n+\n+\tlws_service_fd_tsi(context, \u0026eventfd, wsi-\u003etsi);\n+\n+\t/* set the idle timer for 1ms ahead */\n+\n+\ttv.tv_sec \u003d 0;\n+\ttv.tv_usec \u003d 1000;\n+\tevtimer_add(pt-\u003eevent.idle_timer, \u0026tv);\n }\n \n LWS_VISIBLE void\n@@ -77,6 +145,7 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)\n {\n \tstruct lws_vhost *vh \u003d context-\u003evhost_list;\n \tstruct event_base *loop \u003d (struct event_base *)_loop;\n+\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[tsi];\n \n \tlwsl_info(\u0022%s: loop %p\u005cn\u0022, __func__, _loop);\n \n@@ -91,7 +160,7 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)\n \t\treturn -1;\n \t}\n \n-\tcontext-\u003ept[tsi].event.io_loop \u003d loop;\n+\tpt-\u003eevent.io_loop \u003d loop;\n \n \t/*\n \t* Initialize all events with the listening sockets\n@@ -110,13 +179,22 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)\n \t\tvh \u003d vh-\u003evhost_next;\n \t}\n \n+\t/* static event loop objects */\n+\n+\tpt-\u003eevent.hrtimer \u003d event_new(loop, -1, EV_PERSIST,\n+\t\t\t\t lws_event_hrtimer_cb, pt);\n+\n+\tpt-\u003eevent.idle_timer \u003d event_new(loop, -1, EV_PERSIST,\n+\t\t\t\t lws_event_idle_timer_cb, pt);\n+\n \t/* Register the signal watcher unless it's a foreign loop */\n-\tif (context-\u003ept[tsi].event_loop_foreign)\n+\n+\tif (pt-\u003eevent_loop_foreign)\n \t\treturn 0;\n \n-\tcontext-\u003ept[tsi].w_sigint.event.watcher \u003d evsignal_new(loop, SIGINT,\n-\t\t\tlws_event_sigint_cb, \u0026context-\u003ept[tsi]);\n-\tevent_add(context-\u003ept[tsi].w_sigint.event.watcher, NULL);\n+\tpt-\u003ew_sigint.event.watcher \u003d evsignal_new(loop, SIGINT,\n+\t\t\t\t\t\t lws_event_sigint_cb, pt);\n+\tevent_add(pt-\u003ew_sigint.event.watcher, NULL);\n \n \treturn 0;\n }\n@@ -217,8 +295,15 @@ elops_destroy_pt_event(struct lws_context *context, int tsi)\n \t\tvh \u003d vh-\u003evhost_next;\n \t}\n \n-\tif (!pt-\u003eevent_loop_foreign)\n+\tevent_free(pt-\u003eevent.hrtimer);\n+\tevent_free(pt-\u003eevent.idle_timer);\n+\n+\tif (!pt-\u003eevent_loop_foreign) {\n+\t\tevent_del(pt-\u003ew_sigint.event.watcher);\n \t\tevent_free(pt-\u003ew_sigint.event.watcher);\n+\n+\t\tevent_base_free(pt-\u003eevent.io_loop);\n+\t}\n }\n \n static void\n@@ -227,10 +312,10 @@ elops_destroy_wsi_event(struct lws *wsi)\n \tif (!wsi)\n \t\treturn;\n \n-\tif(wsi-\u003ew_read.event.watcher)\n+\tif (wsi-\u003ew_read.event.watcher)\n \t\tevent_free(wsi-\u003ew_read.event.watcher);\n \n-\tif(wsi-\u003ew_write.event.watcher)\n+\tif (wsi-\u003ew_write.event.watcher)\n \t\tevent_free(wsi-\u003ew_write.event.watcher);\n }\n \n@@ -271,7 +356,7 @@ static int\n elops_destroy_context2_event(struct lws_context *context)\n {\n \tstruct lws_context_per_thread *pt;\n-\tint n, m, internal \u003d 0;\n+\tint n, m;\n \n \tlwsl_debug(\u0022%s\u005cn\u0022, __func__);\n \n@@ -285,7 +370,6 @@ elops_destroy_context2_event(struct lws_context *context)\n \t\tif (pt-\u003eevent_loop_foreign || !pt-\u003eevent.io_loop)\n \t\t\tcontinue;\n \n-\t\tinternal \u003d 1;\n \t\tif (!context-\u003efinalize_destroy_after_internal_loops_stopped) {\n \t\t\tevent_base_loopexit(pt-\u003eevent.io_loop, NULL);\n \t\t\tcontinue;\n@@ -305,7 +389,7 @@ elops_destroy_context2_event(struct lws_context *context)\n \n \t}\n \n-\treturn internal;\n+\treturn 0;\n }\n \n struct lws_event_loop_ops event_loop_ops_event \u003d {\ndiff --git a/lib/event-libs/libevent/private.h b/lib/event-libs/libevent/private.h\nindex 347c7fe..1c2d360 100644\n--- a/lib/event-libs/libevent/private.h\n+++ b/lib/event-libs/libevent/private.h\n@@ -26,6 +26,7 @@\n struct lws_pt_eventlibs_libevent {\n \tstruct event_base *io_loop;\n \tstruct event *hrtimer;\n+\tstruct event *idle_timer;\n };\n \n struct lws_io_watcher_libevent {\ndiff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c\nindex ecc7e2d..ee948b6 100644\n--- a/lib/event-libs/libuv/libuv.c\n+++ b/lib/event-libs/libuv/libuv.c\n@@ -1,7 +1,7 @@\n /*\n * libwebsockets - small server side websockets and web server implementation\n *\n- * Copyright (C) 2010-2017 Andy Green \u003candy@warmcat.com\u003e\n+ * Copyright (C) 2010-2018 Andy Green \u003candy@warmcat.com\u003e\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n@@ -116,11 +116,7 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents)\n \t\t\teventfd.revents |\u003d LWS_POLLOUT;\n \t\t}\n \t}\n-\tlws_service_fd(context, \u0026eventfd);\n-\n-\tlws_pt_lock(pt, __func__);\n-\t__lws_hrtimer_service(pt);\n-\tlws_pt_unlock(pt);\n+\tlws_service_fd_tsi(context, \u0026eventfd, wsi-\u003etsi);\n \n \tuv_idle_start(\u0026pt-\u003euv.idle, lws_uv_idle);\n }\n@@ -526,7 +522,8 @@ elops_destroy_context1_uv(struct lws_context *context)\n \t\t\t\t\t\t UV_RUN_NOWAIT)))\n \t\t\t\t\t;\n \t\t\tif (m)\n-\t\t\t\tlwsl_err(\u0022%s: tsi %d: failed to close everything\u005cn\u0022, __func__, n);\n+\t\t\t\tlwsl_err(\u0022%s: tsi %d: not all closed\u005cn\u0022,\n+\t\t\t\t\t __func__, n);\n \n \t\t}\n \t}\n@@ -891,8 +888,9 @@ lws_libuv_closewsi(uv_handle_t* handle)\n \t\t\tvh \u003d vh-\u003evhost_next;\n \t\t}\n \n-\t\tif (context-\u003ept[0].event_loop_foreign) {\n-\t\t\tlwsl_info(\u0022%s: calling lws_context_destroy2\u005cn\u0022, __func__);\n+\t\tif (!context-\u003ecount_event_loop_static_asset_handles \u0026\u0026\n+\t\t context-\u003ept[0].event_loop_foreign) {\n+\t\t\tlwsl_info(\u0022%s: call lws_context_destroy2\u005cn\u0022, __func__);\n \t\t\tlws_context_destroy2(context);\n \t\t}\n \t}\ndiff --git a/lib/event-libs/libuv/private.h b/lib/event-libs/libuv/private.h\nindex 173340e..cf8f710 100644\n--- a/lib/event-libs/libuv/private.h\n+++ b/lib/event-libs/libuv/private.h\n@@ -24,6 +24,11 @@\n #include \u003cuv.h\u003e\n \n /*\n+ * libuv's async destroy cb means that asking to close something doesn't mean\n+ * you can destroy it or parent things until after the close completes.\n+ *\n+ * So we must reference-count creation and close completions with libuv.\n+ *\n * All \u0022static\u0022 (per-pt or per-context) uv handles must\n *\n * - have their .data set to point to the context\ndiff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h\nindex 4ff5878..9f60bd6 100644\n--- a/lib/private-libwebsockets.h\n+++ b/lib/private-libwebsockets.h\n@@ -757,7 +757,6 @@ struct lws_peer {\n struct lws_context {\n \ttime_t last_timeout_check_s;\n \ttime_t last_ws_ping_pong_check_s;\n-\ttime_t last_cert_check_s;\n \ttime_t time_up;\n \ttime_t time_discontiguity;\n \ttime_t time_fixup;\ndiff --git a/lib/service.c b/lib/service.c\nindex 8cf8c93..a08506f 100644\n--- a/lib/service.c\n+++ b/lib/service.c\n@@ -554,9 +554,6 @@ lws_service_periodic_checks(struct lws_context *context,\n \tstruct lws *wsi;\n \tint timed_out \u003d 0;\n \ttime_t now;\n-#if defined(LWS_WITH_TLS)\n-\tint n \u003d 0;\n-#endif\n #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n \tstruct allocated_headers *ah;\n \tint m;\n@@ -810,12 +807,10 @@ lws_service_periodic_checks(struct lws_context *context,\n \t/*\n \t * Phase 6: check the remaining cert lifetime daily\n \t */\n-#if defined(LWS_WITH_TLS)\n-\tn \u003d lws_compare_time_t(context, now, context-\u003elast_cert_check_s);\n-\tif ((!context-\u003elast_cert_check_s || n \u003e (24 * 60 * 60)) \u0026\u0026\n-\t !lws_tls_check_all_cert_lifetimes(context))\n-\t\tcontext-\u003elast_cert_check_s \u003d now;\n-#endif\n+\n+\tif (context-\u003etls_ops \u0026\u0026\n+\t context-\u003etls_ops-\u003eperiodic_housekeeping)\n+\t\tcontext-\u003etls_ops-\u003eperiodic_housekeeping(context, now);\n \n \treturn timed_out;\n }\n@@ -869,7 +864,8 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd,\n \t}\n \n #if defined(LWS_WITH_TLS)\n-\tif (lwsi_state(wsi) \u003d\u003d LRS_SHUTDOWN \u0026\u0026 lws_is_ssl(wsi) \u0026\u0026 wsi-\u003etls.ssl) {\n+\tif (lwsi_state(wsi) \u003d\u003d LRS_SHUTDOWN \u0026\u0026\n+\t lws_is_ssl(wsi) \u0026\u0026 wsi-\u003etls.ssl) {\n \t\tswitch (__lws_tls_shutdown(wsi)) {\n \t\tcase LWS_SSL_CAPABLE_DONE:\n \t\tcase LWS_SSL_CAPABLE_ERROR:\n@@ -927,6 +923,10 @@ handled:\n #endif\n \tpollfd-\u003erevents \u003d 0;\n \n+\tlws_pt_lock(pt, __func__);\n+\t__lws_hrtimer_service(pt);\n+\tlws_pt_unlock(pt);\n+\n \treturn 0;\n }\n \ndiff --git a/lib/tls/mbedtls/ssl.c b/lib/tls/mbedtls/ssl.c\nindex 44eb061..b024dfa 100644\n--- a/lib/tls/mbedtls/ssl.c\n+++ b/lib/tls/mbedtls/ssl.c\n@@ -501,7 +501,20 @@ tops_fake_POLLIN_for_buffered_mbedtls(struct lws_context_per_thread *pt)\n \treturn lws_tls_fake_POLLIN_for_buffered(pt);\n }\n \n+static int\n+tops_periodic_housekeeping_mbedtls(struct lws_context *context, time_t now)\n+{\n+\tint n;\n+\n+\tn \u003d lws_compare_time_t(context, now, context-\u003etls.last_cert_check_s);\n+\tif ((!context-\u003etls.last_cert_check_s || n \u003e (24 * 60 * 60)) \u0026\u0026\n+\t !lws_tls_check_all_cert_lifetimes(context))\n+\t\tcontext-\u003etls.last_cert_check_s \u003d now;\n+\n+\treturn 0;\n+}\n+\n const struct lws_tls_ops tls_ops_mbedtls \u003d {\n \t/* fake_POLLIN_for_buffered */\ttops_fake_POLLIN_for_buffered_mbedtls,\n-\n+\t/* periodic_housekeeping */\ttops_periodic_housekeeping_mbedtls,\n };\ndiff --git a/lib/tls/openssl/ssl.c b/lib/tls/openssl/ssl.c\nindex d92ea78..ec43770 100644\n--- a/lib/tls/openssl/ssl.c\n+++ b/lib/tls/openssl/ssl.c\n@@ -689,7 +689,21 @@ tops_fake_POLLIN_for_buffered_openssl(struct lws_context_per_thread *pt)\n \treturn lws_tls_fake_POLLIN_for_buffered(pt);\n }\n \n+static int\n+tops_periodic_housekeeping_openssl(struct lws_context *context, time_t now)\n+{\n+\tint n;\n+\n+\tn \u003d lws_compare_time_t(context, now, context-\u003etls.last_cert_check_s);\n+\tif ((!context-\u003etls.last_cert_check_s || n \u003e (24 * 60 * 60)) \u0026\u0026\n+\t !lws_tls_check_all_cert_lifetimes(context))\n+\t\tcontext-\u003etls.last_cert_check_s \u003d now;\n+\n+\treturn 0;\n+}\n+\n const struct lws_tls_ops tls_ops_openssl \u003d {\n \t/* fake_POLLIN_for_buffered */\ttops_fake_POLLIN_for_buffered_openssl,\n+\t/* periodic_housekeeping */\ttops_periodic_housekeeping_openssl,\n \n };\ndiff --git a/lib/tls/private.h b/lib/tls/private.h\nindex 20f9bd3..5c6beeb 100644\n--- a/lib/tls/private.h\n+++ b/lib/tls/private.h\n@@ -93,6 +93,7 @@ struct lws_context_per_thread;\n \n struct lws_tls_ops {\n \tint (*fake_POLLIN_for_buffered)(struct lws_context_per_thread *pt);\n+\tint (*periodic_housekeeping)(struct lws_context *context, time_t now);\n };\n \n #if defined(LWS_WITH_TLS)\n@@ -110,6 +111,7 @@ extern const struct lws_tls_ops tls_ops_openssl, tls_ops_mbedtls;\n struct lws_context_tls {\n \tchar alpn_discovered[32];\n \tconst char *alpn_default;\n+\ttime_t last_cert_check_s;\n };\n \n struct lws_pt_tls {\ndiff --git a/lib/tls/tls-server.c b/lib/tls/tls-server.c\nindex 01e4ca6..19549a5 100644\n--- a/lib/tls/tls-server.c\n+++ b/lib/tls/tls-server.c\n@@ -214,7 +214,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)\n \t\t\tlws_gate_accepts(context, 0);\n \n #if defined(LWS_WITH_STATS)\n-\tcontext-\u003eupdated \u003d 1;\n+\t\tcontext-\u003eupdated \u003d 1;\n #endif\n \t\t/*\n \t\t * we are not accepted yet, but we need to enter ourselves\ndiff --git a/minimal-examples/http-server/README.md b/minimal-examples/http-server/README.md\nindex d9ea25f..1adb694 100644\n--- a/minimal-examples/http-server/README.md\n+++ b/minimal-examples/http-server/README.md\n@@ -3,6 +3,7 @@\n minimal-http-server-basicauth|Shows how to protect a mount using a password file and basic auth\n minimal-http-server-dynamic|Serves both static and dynamically generated http content\n minimal-http-server-eventlib-foreign|Demonstrates integrating lws with a foreign event library\n+minimal-http-server-eventlib-demos|Using the demo plugins with event libraries\n minimal-http-server-eventlib|Same as minimal-http-server but works with a supported event library\n minimal-http-server-form-get|Process a GET form\n minimal-http-server-form-post-file|Process a multipart POST form with file transfer\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt\nnew file mode 100644\nindex 0000000..593d687\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt\n@@ -0,0 +1,79 @@\n+cmake_minimum_required(VERSION 2.8)\n+include(CheckCSourceCompiles)\n+\n+set(SAMP lws-minimal-http-server-eventlib-demos)\n+set(SRCS minimal-http-server-eventlib-demos.c)\n+\n+# If we are being built as part of lws, confirm current build config supports\n+# reqconfig, else skip building ourselves.\n+#\n+# If we are being built externally, confirm installed lws was configured to\n+# support reqconfig, else error out with a helpful message about the problem.\n+#\n+MACRO(require_lws_config reqconfig _val result)\n+\n+\tif (DEFINED ${reqconfig})\n+\tif (${reqconfig})\n+\t\tset (rq 1)\n+\telse()\n+\t\tset (rq 0)\n+\tendif()\n+\telse()\n+\t\tset(rq 0)\n+\tendif()\n+\n+\tif (${_val} EQUAL ${rq})\n+\t\tset(SAME 1)\n+\telse()\n+\t\tset(SAME 0)\n+\tendif()\n+\n+\tif (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})\n+\t\tif (${_val})\n+\t\t\tmessage(\u0022${SAMP}: skipping as lws being built without ${reqconfig}\u0022)\n+\t\telse()\n+\t\t\tmessage(\u0022${SAMP}: skipping as lws built with ${reqconfig}\u0022)\n+\t\tendif()\n+\t\tset(${result} 0)\n+\telse()\n+\t\tif (LWS_WITH_MINIMAL_EXAMPLES)\n+\t\t\tset(MET ${SAME})\n+\t\telse()\n+\t\t\tCHECK_C_SOURCE_COMPILES(\u0022#include \u003clibwebsockets.h\u003e\u005cnint main(void) {\u005cn#if defined(${reqconfig})\u005cn return 0;\u005cn#else\u005cn fail;\u005cn#endif\u005cn return 0;\u005cn}\u005cn\u0022 HAS_${reqconfig})\n+\t\t\tif (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})\n+\t\t\t\tset(HAS_${reqconfig} 0)\n+\t\t\telse()\n+\t\t\t\tset(HAS_${reqconfig} 1)\n+\t\t\tendif()\n+\t\t\tif ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))\n+\t\t\t\tset(MET 1)\n+\t\t\telse()\n+\t\t\t\tset(MET 0)\n+\t\t\tendif()\n+\t\tendif()\n+\t\tif (NOT MET)\n+\t\t\tif (${_val})\n+\t\t\t\tmessage(FATAL_ERROR \u0022This project requires lws must have been configured with ${reqconfig}\u0022)\n+\t\t\telse()\n+\t\t\t\tmessage(FATAL_ERROR \u0022Lws configuration of ${reqconfig} is incompatible with this project\u0022)\n+\t\t\tendif()\n+\t\tendif()\n+\t\n+\tendif()\n+ENDMACRO()\n+\n+set(requirements 1)\n+require_lws_config(LWS_ROLE_H1 1 requirements)\n+require_lws_config(LWS_ROLE_WS 1 requirements)\n+require_lws_config(LWS_WITHOUT_SERVER 0 requirements)\n+\n+if (requirements)\n+\tadd_executable(${SAMP} ${SRCS})\n+\n+\tif (websockets_shared)\n+\t\ttarget_link_libraries(${SAMP} websockets_shared)\n+\t\tadd_dependencies(${SAMP} websockets_shared)\n+\telse()\n+\t\ttarget_link_libraries(${SAMP} websockets)\n+\tendif()\n+endif()\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/README.md b/minimal-examples/http-server/minimal-http-server-eventlib-demos/README.md\nnew file mode 100644\nindex 0000000..90720e4\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/README.md\n@@ -0,0 +1,30 @@\n+# lws minimal http server eventlib demos\n+\n+This demonstrates a slightly more complex demo that can use\n+any of the event loops (it defaults to poll)\n+\n+It uses statically included plugins to provide the lws test server functions\n+\n+Commandline option|Meaning\n+---|---\n+-d \u003cloglevel\u003e|Debug verbosity in decimal, eg, -d15\n+--uv|Use the libuv event library (lws must have been configured with `-DLWS_WITH_LIBUV\u003d1`)\n+--event|Use the libevent library (lws must have been configured with `-DLWS_WITH_LIBEVENT\u003d1`)\n+--ev|Use the libev event library (lws must have been configured with `-DLWS_WITH_LIBEV\u003d1`)\n+\n+## build\n+\n+```\n+ $ cmake . \u0026\u0026 make\n+```\n+\n+## usage\n+\n+```\n+ $ ./lws-minimal-http-server-eventlib-demos\n+[2018/03/04 09:30:02:7986] USER: LWS minimal http server-eventlib-demos | visit http://localhost:7681\n+[2018/03/04 09:30:02:7986] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 on\n+```\n+\n+Visit http://localhost:7681\n+\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/localhost-100y.cert b/minimal-examples/http-server/minimal-http-server-eventlib-demos/localhost-100y.cert\nnew file mode 100644\nindex 0000000..6f372db\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/localhost-100y.cert\n@@ -0,0 +1,34 @@\n+-----BEGIN CERTIFICATE-----\n+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\n+e2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE\u003d\n+-----END CERTIFICATE-----\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/localhost-100y.key b/minimal-examples/http-server/minimal-http-server-eventlib-demos/localhost-100y.key\nnew file mode 100644\nindex 0000000..148f859\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/localhost-100y.key\n@@ -0,0 +1,52 @@\n+-----BEGIN PRIVATE KEY-----\n+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\n+fBrpEY1IATtPq1taBZZogRqI3rOkkPk\u003d\n+-----END PRIVATE KEY-----\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c b/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c\nnew file mode 100644\nindex 0000000..f624fa5\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c\n@@ -0,0 +1,186 @@\n+/*\n+ * lws-minimal-http-server-eventlib\n+ *\n+ * Copyright (C) 2018 Andy Green \u003candy@warmcat.com\u003e\n+ *\n+ * This file is made available under the Creative Commons CC0 1.0\n+ * Universal Public Domain Dedication.\n+ *\n+ * This demonstrates a minimal http[s] server that can work with any of the\n+ * supported event loop backends, or the default poll() one.\n+ *\n+ * To keep it simple, it serves stuff from the subdirectory \n+ * \u0022./mount-origin\u0022 of the directory it was started in.\n+ * You can change that by changing mount.origin below.\n+ */\n+\n+#include \u003clibwebsockets.h\u003e\n+#include \u003cstring.h\u003e\n+#include \u003csignal.h\u003e\n+\n+#define LWS_PLUGIN_STATIC\n+#include \u0022../../../plugins/protocol_lws_mirror.c\u0022\n+#include \u0022../../../plugins/protocol_lws_status.c\u0022\n+#include \u0022../../../plugins/protocol_dumb_increment.c\u0022\n+#include \u0022../../../plugins/protocol_post_demo.c\u0022\n+\n+static struct lws_context *context;\n+\n+static struct lws_protocols protocols[] \u003d {\n+\t/* first protocol must always be HTTP handler */\n+\n+\t{ \u0022http-only\u0022, lws_callback_http_dummy, 0, 0, },\n+\tLWS_PLUGIN_PROTOCOL_DUMB_INCREMENT,\n+\tLWS_PLUGIN_PROTOCOL_MIRROR,\n+\tLWS_PLUGIN_PROTOCOL_LWS_STATUS,\n+\tLWS_PLUGIN_PROTOCOL_POST_DEMO,\n+\t{ NULL, NULL, 0, 0 } /* terminator */\n+};\n+\n+/*\n+ * mount handlers for sections of the URL space\n+ */\n+\n+static const struct lws_http_mount mount_ziptest \u003d {\n+\tNULL,\t\t\t/* linked-list pointer to next*/\n+\t\u0022/ziptest\u0022,\t\t/* mountpoint in URL namespace on this vhost */\n+\t\u0022candide.zip\u0022,\t/* handler */\n+\tNULL,\t/* default filename if none given */\n+\tNULL,\n+\tNULL,\n+\tNULL,\n+\tNULL,\n+\t0,\n+\t0,\n+\t0,\n+\t0,\n+\t0,\n+\t0,\n+\tLWSMPRO_FILE,\t/* origin points to a callback */\n+\t8,\t\t\t/* strlen(\u0022/ziptest\u0022), ie length of the mountpoint */\n+\tNULL,\n+\n+\t{ NULL, NULL } // sentinel\n+};\n+\n+static const struct lws_http_mount mount_post \u003d {\n+\t(struct lws_http_mount *)\u0026mount_ziptest, /* linked-list pointer to next*/\n+\t\u0022/formtest\u0022,\t\t/* mountpoint in URL namespace on this vhost */\n+\t\u0022protocol-post-demo\u0022,\t/* handler */\n+\tNULL,\t/* default filename if none given */\n+\tNULL,\n+\tNULL,\n+\tNULL,\n+\tNULL,\n+\t0,\n+\t0,\n+\t0,\n+\t0,\n+\t0,\n+\t0,\n+\tLWSMPRO_CALLBACK,\t/* origin points to a callback */\n+\t9,\t\t\t/* strlen(\u0022/formtest\u0022), ie length of the mountpoint */\n+\tNULL,\n+\n+\t{ NULL, NULL } // sentinel\n+};\n+\n+\n+static const struct lws_http_mount mount \u003d {\n+\t/* .mount_next */\t\t\u0026mount_post,\t/* linked-list \u0022next\u0022 */\n+\t/* .mountpoint */\t\t\u0022/\u0022,\t\t/* mountpoint URL */\n+\t/* .origin */\t\t\t\u0022./mount-origin\u0022, /* serve from dir */\n+\t/* .def */\t\t\t\u0022test.html\u0022,\t/* default filename */\n+\t/* .protocol */\t\t\tNULL,\n+\t/* .cgienv */\t\t\tNULL,\n+\t/* .extra_mimetypes */\t\tNULL,\n+\t/* .interpret */\t\tNULL,\n+\t/* .cgi_timeout */\t\t0,\n+\t/* .cache_max_age */\t\t0,\n+\t/* .auth_mask */\t\t0,\n+\t/* .cache_reusable */\t\t0,\n+\t/* .cache_revalidate */\t\t0,\n+\t/* .cache_intermediaries */\t0,\n+\t/* .origin_protocol */\t\tLWSMPRO_FILE,\t/* files in a dir */\n+\t/* .mountpoint_len */\t\t1,\t\t/* char count */\n+\t/* .basic_auth_login_file */\tNULL,\n+};\n+\n+void signal_cb(void *handle, int signum)\n+{\n+\tlwsl_err(\u0022%s: signal %d\u005cn\u0022, __func__, signum);\n+\n+\tswitch (signum) {\n+\tcase SIGTERM:\n+\tcase SIGINT:\n+\t\tbreak;\n+\tdefault:\n+\n+\t\tbreak;\n+\t}\n+\tlws_context_destroy(context);\n+}\n+\n+void sigint_handler(int sig)\n+{\n+\tsignal_cb(NULL, sig);\n+}\n+\n+int main(int argc, const char **argv)\n+{\n+\tstruct lws_context_creation_info info;\n+\tconst char *p;\n+\tint logs \u003d LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE\n+\t\t\t/* for LLL_ verbosity above NOTICE to be built into lws,\n+\t\t\t * lws must have been configured and built with\n+\t\t\t * -DCMAKE_BUILD_TYPE\u003dDEBUG instead of \u003dRELEASE */\n+\t\t\t/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */\n+\t\t\t/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */\n+\t\t\t/* | LLL_DEBUG */;\n+\n+\tif ((p \u003d lws_cmdline_option(argc, argv, \u0022-d\u0022)))\n+\t\tlogs \u003d atoi(p);\n+\n+\tlws_set_log_level(logs, NULL);\n+\tlwsl_user(\u0022LWS minimal http server eventlib | visit http://localhost:7681\u005cn\u0022);\n+\tlwsl_user(\u0022 [-s (ssl)] [--uv (libuv)] [--ev (libev)] [--event (libevent)]\u005cn\u0022);\n+\n+\tmemset(\u0026info, 0, sizeof info); /* otherwise uninitialized garbage */\n+\tinfo.port \u003d 7681;\n+\tinfo.mounts \u003d \u0026mount;\n+\tinfo.error_document_404 \u003d \u0022/404.html\u0022;\n+\tinfo.pcontext \u003d \u0026context;\n+\tinfo.protocols \u003d protocols;\n+\tinfo.signal_cb \u003d signal_cb;\n+\n+\tif (lws_cmdline_option(argc, argv, \u0022-s\u0022)) {\n+\t\tinfo.options |\u003d LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;\n+\t\tinfo.ssl_cert_filepath \u003d \u0022localhost-100y.cert\u0022;\n+\t\tinfo.ssl_private_key_filepath \u003d \u0022localhost-100y.key\u0022;\n+\t}\n+\n+\tif (lws_cmdline_option(argc, argv, \u0022--uv\u0022))\n+\t\tinfo.options |\u003d LWS_SERVER_OPTION_LIBUV;\n+\telse\n+\t\tif (lws_cmdline_option(argc, argv, \u0022--event\u0022))\n+\t\t\tinfo.options |\u003d LWS_SERVER_OPTION_LIBEVENT;\n+\t\telse\n+\t\t\tif (lws_cmdline_option(argc, argv, \u0022--ev\u0022))\n+\t\t\t\tinfo.options |\u003d LWS_SERVER_OPTION_LIBEV;\n+\t\t\telse\n+\t\t\t\tsignal(SIGINT, sigint_handler);\n+\n+\tcontext \u003d lws_create_context(\u0026info);\n+\tif (!context) {\n+\t\tlwsl_err(\u0022lws init failed\u005cn\u0022);\n+\t\treturn 1;\n+\t}\n+\n+\twhile (!lws_service(context, 0))\n+\t\t;\n+\n+\tlwsl_info(\u0022calling external context destroy\u005cn\u0022);\n+\tlws_context_destroy(context);\n+\n+\treturn 0;\n+}\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/404.html b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/404.html\nnew file mode 100644\nindex 0000000..1f7ae66\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/404.html\n@@ -0,0 +1,9 @@\n+\u003cmeta charset\u003d\u0022UTF-8\u0022\u003e \n+\u003chtml\u003e\n+\t\u003cbody\u003e\n+\t\t\u003cimg src\u003d\u0022libwebsockets.org-logo.png\u0022\u003e\u003cbr\u003e\n+\t\t\u003ch1\u003e404\u003c/h1\u003e\n+\t\tSorry, that file doesn't exist.\n+\t\u003c/body\u003e\n+\u003c/html\u003e\n+\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/candide.zip b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/candide.zip\nnew file mode 100644\nindex 0000000..82a6619\nBinary files /dev/null and b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/candide.zip differ\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/favicon.ico b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/favicon.ico\nnew file mode 100644\nindex 0000000..c0cc2e3\nBinary files /dev/null and b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/favicon.ico differ\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/http2.png b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/http2.png\nnew file mode 100644\nindex 0000000..b4129e7\nBinary files /dev/null and b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/http2.png differ\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/leaf.jpg b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/leaf.jpg\nnew file mode 100644\nindex 0000000..1a3f46b\nBinary files /dev/null and b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/leaf.jpg differ\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/libwebsockets.org-logo.png b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/libwebsockets.org-logo.png\nnew file mode 100644\nindex 0000000..2060a10\nBinary files /dev/null and b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/libwebsockets.org-logo.png differ\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/lws-common.js b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/lws-common.js\nnew file mode 100644\nindex 0000000..f0c5b92\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/lws-common.js\n@@ -0,0 +1,398 @@\n+/*\n+ * This section around grayOut came from here:\n+ * http://www.codingforums.com/archive/index.php/t-151720.html\n+ * Assumed public domain\n+ *\n+ * Init like this in your main html script, this also reapplies the gray\n+ *\n+ * lws_gray_out(true,{'zindex':'499'});\n+ *\n+ * To remove the gray\n+ *\n+ * lws_gray_out(false);\n+ *\n+ */\n+\n+function lws_gray_out(vis, options) {\n+\n+\tvar options \u003d options || {};\n+\tvar zindex \u003d options.zindex || 50;\n+\tvar opacity \u003d options.opacity || 70;\n+\tvar opaque \u003d (opacity / 100);\n+\tvar bgcolor \u003d options.bgcolor || '#000000';\n+\tvar dark \u003d document.getElementById('darkenScreenObject');\n+\n+\tif (!dark) {\n+\t\tvar tbody \u003d document.getElementsByTagName(\u0022body\u0022)[0];\n+\t\tvar tnode \u003d document.createElement('div');\n+\t\ttnode.style.position \u003d 'absolute';\n+\t\ttnode.style.top \u003d '0px';\n+\t\ttnode.style.left \u003d '0px';\n+\t\ttnode.style.overflow \u003d 'hidden';\n+\t\ttnode.style.display \u003d'none';\n+\t\ttnode.id \u003d 'darkenScreenObject';\n+\t\ttbody.appendChild(tnode);\n+\t\tdark \u003d document.getElementById('darkenScreenObject');\n+\t}\n+\tif (vis) {\n+\t\tdark.style.opacity \u003d opaque;\n+\t\tdark.style.MozOpacity \u003d opaque;\n+\t\t// dark.style.filter \u003d'alpha(opacity\u003d'+opacity+')';\n+\t\tdark.style.zIndex \u003d zindex;\n+\t\tdark.style.backgroundColor \u003d bgcolor;\n+\t\tdark.style.width \u003d gsize(1);\n+\t\tdark.style.height \u003d gsize(0);\n+\t\tdark.style.display \u003d'block';\n+\t\taddEvent(window, \u0022resize\u0022,\n+\t\t\tfunction() {\n+\t\t\t\tdark.style.height \u003d gsize(0);\n+\t\t\t\tdark.style.width \u003d gsize(1);\n+\t\t\t}\n+\t\t);\n+\t} else {\n+\t\tdark.style.display \u003d 'none';\n+\t\tremoveEvent(window, \u0022resize\u0022,\n+\t\t\tfunction() {\n+\t\t\t\tdark.style.height \u003d gsize(0);\n+\t\t\t\tdark.style.width \u003d gsize(1);\n+\t\t\t}\n+\t\t);\n+\t}\n+}\n+\n+function gsize(ptype)\n+{\n+\tvar h \u003d document.compatMode \u003d\u003d 'CSS1Compat' \u0026\u0026\n+\t\t!window.opera ?\n+\t\t\tdocument.documentElement.clientHeight :\n+\t\t\t\t\t\tdocument.body.clientHeight;\n+\tvar w \u003d document.compatMode \u003d\u003d 'CSS1Compat' \u0026\u0026\n+\t\t!window.opera ? \n+\t\t\tdocument.documentElement.clientWidth :\n+\t\t\t\t\t\tdocument.body.clientWidth;\n+\tif (document.body \u0026\u0026 \n+\t\t (document.body.scrollWidth || document.body.scrollHeight)) {\n+\t\tvar pageWidth \u003d (w \u003e (t \u003d document.body.scrollWidth)) ?\n+\t\t\t\t\t(\u0022\u0022 + w + \u0022px\u0022) : (\u0022\u0022 + (t) + \u0022px\u0022);\n+\t\tvar pageHeight \u003d (h \u003e (t \u003d document.body.scrollHeight)) ?\n+\t\t\t\t\t(\u0022\u0022 + h + \u0022px\u0022) : (\u0022\u0022 + (t) + \u0022px\u0022);\n+\t} else if (document.body.offsetWidth) {\n+\t\tvar pageWidth \u003d (w \u003e (t \u003d document.body.offsetWidth)) ?\n+\t\t\t\t\t(\u0022\u0022 + w + \u0022px\u0022) : (\u0022\u0022 + (t) + \u0022px\u0022);\n+\t\tvar pageHeight \u003d(h \u003e (t \u003d document.body.offsetHeight)) ?\n+\t\t\t\t\t(\u0022\u0022 + h + \u0022px\u0022) : (\u0022\u0022 + (t) + \u0022px\u0022);\n+\t} else {\n+\t\tvar pageWidth \u003d '100%';\n+\t\tvar pageHeight \u003d '100%';\n+\t}\n+\treturn (ptype \u003d\u003d 1) ? pageWidth : pageHeight;\n+}\n+\n+function addEvent( obj, type, fn ) {\n+\tif ( obj.attachEvent ) {\n+\t\tobj['e' + type + fn] \u003d fn;\n+\t\tobj[type+fn] \u003d function() { obj['e' + type+fn]( window.event );}\n+\t\tobj.attachEvent('on' + type, obj[type + fn]);\n+\t} else\n+\t\tobj.addEventListener(type, fn, false);\n+}\n+\n+function removeEvent( obj, type, fn ) {\n+\tif ( obj.detachEvent ) {\n+\t\tobj.detachEvent('on' + type, obj[type + fn]);\n+\t\tobj[type + fn] \u003d null;\n+\t} else\n+\t\tobj.removeEventListener(type, fn, false);\n+}\n+\n+/*\n+ * end of grayOut related stuff\n+ */\n+ \n+/*\n+ * lws-meta helpers\n+ */\n+\n+var lws_meta_cmd \u003d {\n+\tOPEN_SUBCHANNEL: 0x41,\n+\t/**\u003c Client requests to open new subchannel\n+\t */\n+\tOPEN_RESULT: 0x42,\n+\t/**\u003c Result of client request to open new subchannel */\n+\tCLOSE_NOT: 0x43,\n+\tCLOSE_RQ: 0x44,\n+\t/**\u003c client requests to close a subchannel */\n+\tWRITE: 0x45,\n+\t/**\u003c connection writes something to specific channel index */\n+\tRX: 0x46,\n+};\n+\n+function new_ws(urlpath, protocol)\n+{\n+\tif (typeof MozWebSocket !\u003d \u0022undefined\u0022)\n+\t\treturn new MozWebSocket(urlpath, protocol);\n+\n+\treturn new WebSocket(urlpath, protocol);\n+}\n+\n+function lws_meta_ws() {\n+\tvar real;\n+\t\n+\tvar channel_id_to_child;\n+\tvar pending_children;\n+\tvar active_children;\n+}\n+\n+function lws_meta_ws_child() {\n+\tvar onopen;\n+\tvar onmessage;\n+\tvar onclose;\n+\t\n+\tvar channel_id;\n+\t\n+\tvar subprotocol;\n+\tvar suburl;\n+\tvar cookie;\n+\t\n+\tvar extensions;\n+\t\n+\tvar parent;\n+}\n+\n+lws_meta_ws_child.prototype.send \u003d function(data)\n+{\n+\n+\tif (typeof data \u003d\u003d \u0022string\u0022) {\n+\t\tdata \u003d String.fromCharCode(lws_meta_cmd.WRITE) +\n+\t\t\tString.fromCharCode(this.channel_id) +\n+\t\t\tdata;\n+\t\t\n+\t\treturn this.parent.real.send(data);\n+\t}\n+\t\n+\t{\n+\n+\t\tvar ab \u003d new Uint8Array(data.length + 2);\n+\n+\t\tab[0] \u003d lws_meta_cmd.WRITE;\n+\t\tab[1] \u003d this.channel_id;\n+\t\tab.set(data, 2);\n+\t\n+\t\treturn this.parent.real.send(ab);\n+\t}\n+}\n+\n+lws_meta_ws_child.prototype.close \u003d function(close_code, close_string)\n+{\n+\tvar pkt \u003d new Uint8Array(129), m \u003d 0, pkt1;\n+\t\n+\tpkt[m++] \u003d lws_meta_cmd.CLOSE_RQ;\n+\tpkt[m++] \u003d this.channel_id;\n+\t\n+\tpkt[m++] \u003d close_string.length + 0x20;\n+\t\n+\tpkt[m++] \u003d close_code / 256;\n+\tpkt[m++] \u003d close_code % 256;\n+\t\n+\tfor (i \u003d 0; i \u003c close_string.length; i++)\n+\t\tpkt[m++] \u003d close_string.charCodeAt(i);\n+\t\n+\tpkt1 \u003d new Uint8Array(m);\n+\tfor (n \u003d 0; n \u003c m; n++)\n+\t\tpkt1[n] \u003d pkt[n];\n+\t\t\n+\tthis.parent.real.send(pkt1.buffer);\n+}\n+\n+/* make a real ws connection using lws_meta*/\n+lws_meta_ws.prototype.new_parent \u003d function(urlpath)\n+{\n+\tvar n, i, m \u003d 0, pkt1;\n+\t\n+\tthis.ordinal \u003d 1;\n+\tthis.pending_children \u003d [];\n+\tthis.active_children \u003d [];\n+\tthis.real \u003d new_ws(urlpath, \u0022lws-meta\u0022);\n+\t\n+\tthis.real.binaryType \u003d 'arraybuffer';\n+\tthis.real.myparent \u003d this;\n+\n+\tthis.real.onopen \u003d function() {\n+\t\tpkt \u003d new Uint8Array(1024);\n+\t\t\tvar n, i, m \u003d 0, pkt1;\n+\t\tconsole.log(\u0022real open - pending children \u0022 + this.myparent.pending_children.length);\n+\t\tfor (n \u003d 0; n \u003c this.myparent.pending_children.length; n++) {\n+\t\t\n+\t\t\tvar p \u003d this.myparent.pending_children[n];\n+\t\t\n+\t\t\tpkt[m++] \u003d lws_meta_cmd.OPEN_SUBCHANNEL;\n+\t\t\tfor (i \u003d 0; i \u003c p.subprotocol.length; i++)\n+\t\t\t\tpkt[m++] \u003d p.subprotocol.charCodeAt(i);\n+\t\t\tpkt[m++] \u003d 0;\n+\t\t\tfor (i \u003d 0; i \u003c p.suburl.length; i++)\n+\t\t\t\tpkt[m++] \u003d p.suburl.charCodeAt(i);\n+\t\t\tpkt[m++] \u003d 0;\n+\t\t\tfor (i \u003d 0; i \u003c p.cookie.length; i++)\n+\t\t\t\tpkt[m++] \u003d p.cookie.charCodeAt(i);\n+\t\t\tpkt[m++] \u003d 0;\n+\t\t}\n+\t\t\n+\t\tpkt1 \u003d new Uint8Array(m);\n+\t\tfor (n \u003d 0; n \u003c m; n++)\n+\t\t\tpkt1[n] \u003d pkt[n];\n+\t\t\n+\t\tconsole.log(this.myparent.pending_children[0].subprotocol);\n+\t\tconsole.log(pkt1);\n+\t\t\n+\t\tthis.send(pkt1.buffer);\n+\t}\n+\n+\n+\tthis.real.onmessage \u003d function(msg) {\n+\t\n+\t\tif (typeof msg.data !\u003d \u0022string\u0022) {\n+\t\t\tvar ba \u003d new Uint8Array(msg.data), n \u003d 0;\n+\t\t\t\n+\t\t\twhile (n \u003c ba.length) {\n+\n+\t\t\t\tswitch (ba[n++]) {\n+\t\t\t\tcase lws_meta_cmd.OPEN_RESULT:\n+\t\t\t\t{\n+\t\t\t\t\tvar m \u003d 0, cookie \u003d \u0022\u0022, protocol \u003d \u0022\u0022, ch \u003d 0;\n+\t\t\t\t\tvar ws \u003d this.myparent;\n+\t\t\t\t\t/* cookie NUL\n+\t\t\t\t\t * channel index + 0x20\n+\t\t\t\t\t * protocol NUL\n+\t\t\t\t\t */\n+\t\t\t\t\t while (ba[n])\n+\t\t\t\t\t \tcookie \u003d cookie + String.fromCharCode(ba[n++]);\n+\t\t\t\t\t n++;\n+\t\t\t\t\t ch \u003d ba[n++];\n+\t\t\t\t\t \n+\t\t\t\t\t while (ba[n])\n+\t\t\t\t\t \tprotocol \u003d protocol + String.fromCharCode(ba[n++]);\n+\t\t\t\t\t \t\n+\t\t\t\t\tconsole.log(\u0022open result \u0022 + cookie + \u0022 \u0022 + protocol + \u0022 \u0022 + ch + \u0022 pending len \u0022 + ws.pending_children.length);\n+\t\t\t\t\t\n+\t\t\t\t\tfor (m \u003d 0; m \u003c ws.pending_children.length; m++) {\n+\t\t\t\t\t\tif (ws.pending_children[m].cookie \u003d\u003d cookie) {\n+\t\t\t\t\t\t\tvar newchild \u003d ws.pending_children[m];\n+\t\t\t\n+\t\t\t\t\t\t\t/* found it */\n+\t\t\t\t\t\t\tws.pending_children[m].channel_id \u003d ch;\n+\t\t\t\t\t\t\t/* add to active children array */\n+\t\t\t\t\t\t\tws.active_children.push(ws.pending_children[m]);\n+\t\t\t\t\t\t\t/* remove from pending children array */\n+\t\t\t\t\t\t\tws.pending_children.splice(m, 1);\n+\t\t\t\t\t\t\t\n+\t\t\t\t\t\t\tnewchild.parent \u003d ws;\n+\t\t\t\t\t\t\tnewchild.extensions \u003d this.extensions;\n+\t\t\t\t\t\t\t\n+\t\t\t\t\t\t\tnewchild.onopen();\n+\t\t\t\t\t\t\t\n+\t\t\t\t\t\t\tconsole.log(\u0022made active \u0022 + cookie);\n+\t\t\t\t\t\t\tbreak;\n+\t\t\t\t\t\t}\n+\t\t\t\t\t}\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\n+\t\t\t\tcase lws_meta_cmd.CLOSE_NOT:\n+\t\t\t\t{\n+\t\t\t\t\tvar code \u003d 0, str \u003d \u0022\u0022, ch \u003d 0, m, le;\n+\t\t\t\t\tvar ba \u003d new Uint8Array(msg.data);\n+\t\t\t\t\t/*\n+\t\t\t\t\t * BYTE: channel\n+\t\t\t\t\t * BYTE: MSB status code\n+\t\t\t\t\t * BYTE: LSB status code\n+\t\t\t\t\t * BYTES: rest of message is close status string\n+\t\t\t\t\t */\n+\t\t\t\t\t \n+\t\t\t\t\t ch \u003d ba[n++];\n+\t\t\t\t\t le \u003d ba[n++] - 0x20;\n+\t\t\t\t\t code \u003d ba[n++] * 256;\n+\t\t\t\t\t code +\u003d ba[n++];\n+\t\t\t\t\t \n+\t\t\t\t\t while (le--)\n+\t\t\t\t\t \tstr +\u003d String.fromCharCode(ba[n++]);\n+\t\t\t\t\t \t\n+\t\t\t\t\tconsole.log(\u0022channel id \u0022 + ch + \u0022 code \u0022 + code + \u0022 str \u0022 + str + \u0022 len \u0022 + str.length);\n+\t\t\t\t\t \t\n+\t\t\t\t\tfor (m \u003d 0; m \u003c this.myparent.active_children.length; m++)\n+\t\t\t\t\t\tif (this.myparent.active_children[m].channel_id \u003d\u003d ch) {\n+\t\t\t\t\t\t\tvar child \u003d this.myparent.active_children[m];\n+\t\t\t\t\t\t\tvar ms \u003d new CloseEvent(\u0022close\u0022, { code:code, reason:str } );\n+\t\t\t\t\t\t\t\n+\t\t\t\t\t\t\t/* reply with close ack */\n+\t\t\t\t\t\t\tthis.send(msg.data);\n+\t\t\t\t\t\t\t\n+\t\t\t\t\t\t\tif (child.onclose)\n+\t\t\t\t\t\t\t\tchild.onclose(ms);\n+\t\t\t\t\t\t\t\n+\t\t\t\t\t\t\tthis.myparent.active_children.splice(m, 1);\n+\t\t\t\t\t\t\tbreak;\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t}\n+\t\t\t\t} // switch\n+\t\t\t}\n+\t\t} else {\n+\t\t\tif (msg.data.charCodeAt(0) \u003d\u003d lws_meta_cmd.WRITE ) {\n+\t\t\t\tvar ch \u003d msg.data.charCodeAt(1), m, ms;\n+\t\t\t\tvar ws \u003d this.myparent, ms;\n+\t\t\t\t\t\t\t\t\n+\t\t\t\tfor (m \u003d 0; m \u003c ws.active_children.length; m++) {\n+\t\t\t\t\tif (ws.active_children[m].channel_id \u003d\u003d ch) {\n+\t\t\t\t\t\tms \u003d new MessageEvent(\u0022WebSocket\u0022, { data: msg.data.substr(2, msg.data.length - 2) } );\n+\t\t\t\t\t\tif (ws.active_children[m].onmessage)\n+\t\t\t\t\t\t\tws.active_children[m].onmessage(ms);\n+\t\t\t\t\t\tbreak;\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\tthis.real.onclose \u003d function() {\n+\t\tvar ws \u003d this.myparent, m;\n+\t\tfor (m \u003d 0; m \u003c ws.active_children.length; m++) {\n+\t\t\tvar child \u003d ws.active_children[m];\n+\t\t\tvar ms \u003d new CloseEvent(\u0022close\u0022, { code:1000, reason:\u0022parent closed\u0022 } );\n+\t\t\t\n+\t\t\tif (child.onclose)\n+\t\t\t\tchild.onclose(ms);\n+\t\t}\n+\t}\n+\n+}\n+\n+\n+\n+/* make a child connection using existing lws_meta real ws connection */\n+lws_meta_ws.prototype.new_ws \u003d function(suburl, protocol)\n+{\n+\tvar ch \u003d new lws_meta_ws_child();\n+\t\n+\tch.suburl \u003d suburl;\n+\tch.subprotocol \u003d protocol;\n+\tch.cookie \u003d \u0022C\u0022 + this.ordinal++;\n+\t\n+\tthis.pending_children.push(ch);\n+\t\n+\tif (this.real.readyState \u003d\u003d 1)\n+\t\tthis.real.onopen();\n+\t\n+\treturn ch;\n+}\n+\n+\n+/*\n+ * end of lws-meta helpers\n+ */\n+ \n+function lws_san(s)\n+{\n+\tif (s.search(\u0022\u003c\u0022) !\u003d -1)\n+\t\treturn \u0022invalid string\u0022;\n+\t\n+\treturn s;\n+}\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/test.html b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/test.html\nnew file mode 100644\nindex 0000000..91c6dc2\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/test.html\n@@ -0,0 +1,858 @@\n+\u003c!DOCTYPE html\u003e\n+\u003chtml lang\u003d\u0022en\u0022\u003e\n+\u003chead\u003e\n+ \u003cmeta charset\u003dutf-8 http-equiv\u003d\u0022Content-Language\u0022 content\u003d\u0022en\u0022/\u003e\n+ \u003cscript src\u003d\u0022/lws-common.js\u0022\u003e\u003c/script\u003e\n+ \u003ctitle\u003eMinimal Websocket test app\u003c/title\u003e\n+\u003cstyle type\u003d\u0022text/css\u0022\u003e\n+\tspan.title { font-size:18pt; font-family: Arial; font-weight:normal; text-align:center; color:#000000; }\n+\t.browser { font-size:12pt; font-family: Arial; font-weight:normal; text-align:center; color:#ffff00; vertical-align:middle; text-align:center; background:#d0b070; padding:12px; -webkit-border-radius:10px; border-radius:10px;}\n+\t.group2 { vertical-align:middle;\n+\t\ttext-align:center;\n+\t\tbackground:#f0f0e0; \n+\t\tpadding:12px; \n+\t\t-webkit-border-radius:10px; \n+\t\tborder-radius:10px; }\n+\t.explain { vertical-align:middle;\n+\t\ttext-align:center;\n+\t\tbackground:#f0f0c0; padding:12px;\n+\t\t-webkit-border-radius:10px;\n+\t\tborder-radius:10px;\n+\t\tcolor:#404000; }\n+\ttd.wsstatus { vertical-align:middle; width:200px; height:50px;\n+\t\ttext-align:center;\n+\t\tbackground:#f0f0c0; padding:6px;\n+\t\t-webkit-border-radius:8px;\n+\t\tborder-radius:8px;\n+\t\tcolor:#404000; }\n+\t.tdform { vertical-align:middle; width:200px; height:50px;\n+\t\ttext-align:center;\n+\t\tbackground:#f0f0d0; padding:6px;\n+\t\t-webkit-border-radius:8px;\n+\t\tmargin:10px;\n+\t\tborder-radius:8px;\n+\t\tborder: 1px solid black;\n+\t\tborder-collapse: collapse;font-size:18pt; font-family: Arial; font-weight:normal; text-align:center; color:#000000; \n+\t\tcolor:#404000; }\n+\t\t\n+\ttd.l { vertical-align:middle;\n+\t\ttext-align:center;\n+\t\tbackground:#d0d0b0; \n+\t\tpadding:3px; \n+\t\t-webkit-border-radius:3px;\n+\t\tborder-radius:3px; }\n+\t.content { vertical-align:top; text-align:center; background:#fffff0; padding:12px; -webkit-border-radius:10px; border-radius:10px; }\n+\t.canvas { vertical-align:top; text-align:center; background:#efefd0; padding:12px; -webkit-border-radius:10px; border-radius:10px; }\n+.tabs {\n+ position: relative; \n+ min-height: 750px; /* This part sucks */\n+ clear: both;\n+ margin: 25px 0;\n+}\n+.tab {\n+ float: left;\n+}\n+.tab label {\n+ background: #eee; \n+ padding: 10px; \n+ border: 1px solid #ccc; \n+ margin-left: -1px; \n+ position: relative;\n+ left: 1px; \n+}\n+.tab [type\u003dradio] {\n+ display: none; \n+}\n+.content {\n+ position: absolute;\n+ top: 28px;\n+ left: 0;\n+ background: white;\n+ right: 0;\n+ bottom: 0;\n+ padding: 20px;\n+ border: 1px solid #ccc; \n+}\n+[type\u003dradio]:checked ~ label {\n+ background: white;\n+ border-bottom: 1px solid white;\n+ z-index: 2;\n+}\n+[type\u003dradio]:checked ~ label ~ .content {\n+ z-index: 1;\n+}\n+\u003c/style\u003e\n+\u003c/head\u003e\n+\n+\u003cbody\u003e\n+\u003cheader\u003e\u003c/header\u003e\n+\u003carticle\u003e\n+\n+\u003ctable\u003e\u003ctr\u003e\u003ctd\u003e\n+\n+\u003ctable width\u003d600px\u003e\n+ \u003ctr\u003e\n+ \u003ctd valign\u003dmiddle align\u003dcenter\u003e\n+ \u003ca href\u003d\u0022https://libwebsockets.org\u0022\u003e\n+ \u003cimg src\u003d\u0022libwebsockets.org-logo.png\u0022\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e\n+\t\u003csection class\u003d\u0022browser\u0022\u003e\n+\t\u003cdiv id\u003dbrow\u003e...\u003c/div\u003e\u003c/section\u003e\n+ \u003c/td\u003e\n+ \u003ctd width\u003d\u002264\u0022 height\u003d\u002264\u0022 id\u003d\u0022wstransport\u0022\u003e\u003c/td\u003e\n+ \u003ctd width\u003d\u002264\u0022 height\u003d\u002264\u0022 id\u003d\u0022transport\u0022\u003e\u003c/td\u003e\n+ \u003c/tr\u003e\n+\n+\u003c/table\u003e\n+\u003c/td\u003e\u003c/tr\u003e\n+\u003ctr\u003e\u003ctd colspan\u003d2 align\u003dcenter\u003e\n+Click \u003ca href\u003d\u0022leaf.jpg\u0022 target\u003d\u0022_blank\u0022\u003eHere\u003c/a\u003e to\n+have the test server send a big picture by http.\n+\u003c/td\u003e\u003c/tr\u003e\n+\u003ctr\u003e\u003ctd colspan\u003d2\u003e\n+\u003cdiv class\u003d\u0022tabs\u0022\u003e\n+\n+ \u003cdiv class\u003d\u0022tab\u0022\u003e\n+ \u003cinput type\u003d\u0022radio\u0022 id\u003d\u0022tab-1\u0022 name\u003d\u0022tab-group-1\u0022 checked\u003e\n+ \u003clabel for\u003d\u0022tab-1\u0022\u003eDumb Increment Demo\u003c/label\u003e\n+ \n+ \u003cdiv class\u003d\u0022content\u0022\u003e\n+ \u003cdiv id\u003d\u0022dumb\u0022 class\u003d\u0022group2\u0022\u003e\n+ \u003ctable\u003e\n+ \u003ctr\u003e\n+\t \u003ctd id\u003dwsdi_statustd align\u003dcenter class\u003d\u0022wsstatus\u0022\u003e\n+\t \u003cspan id\u003dwsdi_status\u003eWebsocket connection not initialized\u003c/span\u003e\u003c/td\u003e\n+ \u003ctd\u003e\u003cspan class\u003d\u0022title\u0022\u003edumb increment-protocol\u003c/span\u003e\u003c/td\u003e\n+\t \u003c/tr\u003e\n+\t \u003ctr\u003e\n+\t \u003ctd class\u003d\u0022explain\u0022 colspan\u003d2\u003e\n+The incrementing number is coming from the server at 20Hz and is individual for\n+each connection to the server... try opening a second browser window.\n+\u003cbr/\u003e\u003cbr/\u003e\n+The button sends a message over the websocket link to ask the server\n+to zero just this connection's number.\n+\t \u003c/td\u003e\n+\t \u003c/tr\u003e\n+\t \u003ctr\u003e\n+\t \u003ctd align\u003dcenter\u003e\u003cdiv id\u003dnumber style\u003d\u0022font-size:120%;\u0022\u003e \u003c/div\u003e\u003c/td\u003e\n+\t \u003ctd align\u003dcenter\u003e\n+\t \u003cinput type\u003dbutton id\u003doffset value\u003d\u0022Reset counter\u0022\u003e\n+\t \u003cinput type\u003dbutton id\u003djunk value\u003d\u0022Send junk\u0022\u003e\n+\t \u003c/td\u003e\n+\t \u003c/tr\u003e\n+\t \u003c/table\u003e\n+\t\u003c/div\u003e\n+ \u003c/div\u003e \n+ \u003c/div\u003e\n+\n+ \u003cdiv class\u003d\u0022tab\u0022\u003e\n+ \u003cinput type\u003d\u0022radio\u0022 id\u003d\u0022tab-2\u0022 name\u003d\u0022tab-group-1\u0022\u003e\n+ \u003clabel for\u003d\u0022tab-2\u0022\u003eMirror Demo\u003c/label\u003e\n+ \n+ \u003cdiv class\u003d\u0022content\u0022\u003e\n+ \u003cdiv id\u003d\u0022mirror\u0022 class\u003d\u0022group2\u0022\u003e\n+ \u003ctable\u003e\n+ \u003ctr\u003e\n+\t \u003ctd colspan\u003d1 id\u003dwslm_statustd align\u003dcenter class\u003d\u0022wsstatus\u0022\u003e\n+\t \u003cspan id\u003dwslm_status\u003eWebsocket connection not initialized\u003c/span\u003e\n+\t\u003c/td\u003e\n+ \u003ctd\u003e\n+ \u003cspan class\u003d\u0022title\u0022\u003elws-mirror-protocol\u003c/span\u003e\n+ \u003c/td\u003e\n+ \u003c/tr\u003e\n+ \u003ctr\u003e\n+ \u003ctd colspan\u003d2\u003e\n+ \u003cdiv class\u003d\u0022explain\u0022\u003e\n+Use the mouse to draw on the canvas below -- all other browser windows open\n+on this page see your drawing in realtime and you can see any of theirs as\n+well.\n+\u003cbr/\u003e\u003cbr/\u003e\n+The lws-mirror protocol doesn't interpret what is being sent to it, it just\n+re-sends it to every other websocket it has a connection with using that\n+protocol, including the guy who sent the packet.\n+\u003cbr/\u003e\u003cbr/\u003e\n+\u003cb\u003elibwebsockets-test-client\u003c/b\u003e joins in by spamming circles on to this shared canvas when\n+run.\n+ \u003c/div\u003e\n+ \u003c/td\u003e\n+ \u003c/tr\u003e\n+ \u003ctr\u003e\n+\t\u003ctd colspan\u003d2\u003eDrawing color:\n+\t \u003cselect id\u003d\u0022color\u0022\u003e\n+\t\t\u003coption value\u003d#000000\u003eBlack\u003c/option\u003e\n+\t\t\u003coption value\u003d#0000ff\u003eBlue\u003c/option\u003e\n+\t\t\u003coption value\u003d#20ff20\u003eGreen\u003c/option\u003e\n+\t\t\u003coption value\u003d#802020\u003eDark Red\u003c/option\u003e\n+\t \u003c/select\u003e\n+ \u003c/tr\u003e\n+ \u003ctr\u003e\n+\t \u003ctd colspan\u003d2 width\u003d500 height\u003d320\u003e\n+\t\t\u003cdiv id\u003d\u0022wslm_drawing\u0022 style\u003d\u0022background:white\u0022\u003e\u003c/div\u003e\n+\t\u003c/td\u003e\n+ \u003c/tr\u003e\n+ \u003c/table\u003e\n+ \u003c/div\u003e\n+ \u003c/div\u003e \n+ \u003c/div\u003e\n+ \n+ \u003cdiv class\u003d\u0022tab\u0022\u003e\n+ \u003cinput type\u003d\u0022radio\u0022 id\u003d\u0022tab-3\u0022 name\u003d\u0022tab-group-1\u0022\u003e\n+ \u003clabel for\u003d\u0022tab-3\u0022\u003eClose Testing\u003c/label\u003e\n+ \n+ \u003cdiv class\u003d\u0022content\u0022\u003e\n+\u003cdiv id\u003d\u0022ot\u0022 class\u003d\u0022group2\u0022\u003e\n+ \u003ctable\u003e\n+ \u003ctr\u003e\n+ \u003ctd\u003e\n+\n+\t\t\u003c/td\u003e\u003c/tr\u003e\n+\t\t\u003ctr\u003e\u003ctd id\u003dot_statustd align\u003dcenter class\u003d\u0022wsstatus\u0022\u003e\n+\t\t \u003cspan id\u003dot_status\u003eWebsocket connection not initialized\u003c/span\u003e\n+\t\t\u003c/td\u003e\n+\t\t\u003ctd colspan\u003d2\u003e\u003cspan class\u003d\u0022title\u0022\u003eOpen and close testing\u003c/span\u003e\u003c/td\u003e\n+\t\t\u003c/tr\u003e\n+\t\t\u003ctr\u003e\t\n+\u003ctd class\u003d\u0022explain\u0022 colspan\u003d3 style\u003d\u0022padding:3px\u0022\u003e\n+To help with open and close testing, you can open and close a connection by hand using\n+ the buttons.\u003cbr\u003e\n+ \u0022\u003cb\u003eClose\u003c/b\u003e\u0022 closes the connection from the browser with code 3000\n+ and reason 'Bye!\u0022.\u003cbr\u003e\n+ \u0022\u003cb\u003eRequest Server Close\u003c/b\u003e\u0022 sends a message asking the server to\n+initiate the close, which it does with code 1001 and reason \u0022Seeya\u0022.\n+\u003c/td\u003e\u003c/tr\u003e\n+\t\t\u003ctr\u003e\n+\t\t\u003ctd align\u003dcenter\u003e\u003cinput type\u003dbutton id\u003dot_open_btn value\u003d\u0022Open\u0022\u003e\u003c/td\u003e\n+\t\t\u003ctd align\u003dcenter\u003e\u003cinput type\u003dbutton id\u003dot_close_btn disabled value\u003d\u0022Close\u0022 \u003e\u003c/td\u003e\n+\t\t\u003ctd align\u003dcenter\u003e\u003cinput type\u003dbutton id\u003dot_req_close_btn disabled value\u003d\u0022Request Server Close\u0022 \u003e\u003c/td\u003e\n+\t\t\u003c/tr\u003e\n+\n+\u003c/table\u003e\n+\n+\u003c/div\u003e\n+ \u003c/div\u003e \n+ \u003c/div\u003e\n+ \n+ \u003cdiv class\u003d\u0022tab\u0022\u003e\n+ \u003cinput type\u003d\u0022radio\u0022 id\u003d\u0022tab-4\u0022 name\u003d\u0022tab-group-1\u0022\u003e\n+ \u003clabel for\u003d\u0022tab-4\u0022\u003eServer info\u003c/label\u003e\n+\n+ \u003cdiv class\u003d\u0022content\u0022\u003e\n+\u003cdiv id\u003d\u0022ot\u0022 class\u003d\u0022group2\u0022\u003e\n+ \u003ctable\u003e\n+ \u003ctr\u003e\n+\t\u003ctd id\u003ds_statustd align\u003dcenter class\u003d\u0022wsstatus\u0022\u003e\n+\t \u003cdiv id\u003ds_status\u003eWebsocket connection not initialized\u003c/div\u003e\n+\t\u003c/td\u003e\n+\t \u003ctd colspan\u003d1\u003e\n+\u003cspan class\u003d\u0022title\u0022\u003eServer Info\u003c/span\u003e\t \u003cinput type\u003dbutton id\u003dpmd value\u003d\u0022Test pmd\u0022\u003e\n+\n+\t\u003c/td\u003e\n+\t\u003c/tr\u003e\u003ctr\u003e\n+\u003ctd class\u003d\u0022explain\u0022 colspan\u003d2\u003e\n+This information is sent by the server over a ws[s] link and updated live\n+whenever the information changes server-side.\n+\u003c/td\u003e\u003c/tr\u003e\n+\t\u003ctr\u003e\n+\t\u003ctd align\u003dcenter colspan\u003d2\u003e\u003cdiv id\u003dservinfo\u003e\u003c/div\u003e\u003c/td\u003e\n+\t\u003c/tr\u003e\n+\t\u003ctr\u003e\n+\t\u003ctd align\u003dcenter colspan\u003d2\u003e\u003cdiv id\u003dconninfo style\u003d\u0022border: solid 2px #e0d040; padding: 4px; width: 500px; height:350px; overflow: auto;\u0022\u003e\u003c/div\u003e\u003c/td\u003e\n+\t\u003c/tr\u003e\n+\u003c/table\u003e\n+\u003c/div\u003e\n+ \u003c/div\u003e \n+ \u003c/div\u003e\n+\n+ \u003cdiv class\u003d\u0022tab\u0022\u003e\n+ \u003cinput type\u003d\u0022radio\u0022 id\u003d\u0022tab-5\u0022 name\u003d\u0022tab-group-1\u0022\u003e\n+ \u003clabel for\u003d\u0022tab-5\u0022\u003ePOST\u003c/label\u003e\n+\n+ \u003cdiv class\u003d\u0022content\u0022\u003e\n+\u003cdiv id\u003d\u0022ot\u0022 class\u003d\u0022group2\u0022\u003e\n+ \u003ctable width\u003d100%\u003e\n+ \u003ctr\u003e\n+\t \u003ctd colspan\u003d1\u003e\n+\u003cspan class\u003d\u0022title\u0022\u003ePOST Form testing\u003c/span\u003e\n+\t\u003c/td\u003e\n+\t\u003c/tr\u003e\u003ctr\u003e\n+\u003ctd class\u003d\u0022explain\u0022 colspan\u003d2\u003e\n+This tests POST handling in lws.\n+\u003c/td\u003e\u003c/tr\u003e\n+\t\u003ctr\u003e\n+\t\u003ctd align\u003dcenter colspan\u003d2 class\u003dtdform\u003e\u003cdiv id\u003dpostinfo style\u003dform\u003e\n+\tFORM 1: send with urlencoded POST body args\u003cbr\u003e\n+\t\u003cform action\u003d\u0022formtest\u0022 method\u003d\u0022post\u0022\u003e\n+ \u003cspan style\u003d\u0022font-size:12pt;\u0022\u003eSome text: \u003c/span\u003e\n+ \u003cinput type\u003d\u0022text\u0022 name\u003d\u0022text\u0022 value\u003d\u0022Give me some text\u0022\u003e\u003cbr\u003e\n+ \u003cinput type\u003d\u0022submit\u0022 name\u003d\u0022send\u0022 value\u003d\u0022Send the form\u0022\u003e\n+\t\u003c/form\u003e\n+\t\u003c/div\u003e\u003c/td\u003e\n+\t\u003c/tr\u003e\n+\n+\u003cscript nonce\u003d\u0022lwscaro\u0022\u003e\n+function check_file()\n+{\n+\tvar f \u003d document.getElementById('file').files[0];\n+\tvar max_len \u003d 100000;\n+\tvar dis \u003d 0;\n+\t\n+\tif (f) {\n+\t\tif (f.size \u003e\u003d max_len) {\n+\t\t\tdis \u003d 1;\n+\t\t\tdocument.getElementById('file_info').innerHTML \u003d\n+\t\t\t\t\u0022\u003cspan style\u003d\u005c\u0022color:red;font-weight:bold\u005c\u0022\u003eFile larger than \u0022+max_len+\u0022\u003c/span\u003e\u0022;\n+\t\t} else\n+\t\t\tdocument.getElementById('file_info').innerHTML \u003d\n+\t\t\t\t\u0022File length \u0022+f.size;\n+\t} else\n+\t\tdis \u003d 1;\n+\t\n+\tdocument.getElementById('upload').disabled \u003d dis;\n+}\n+\u003c/script\u003e\n+\n+\t\u003ctr\u003e\n+\t\u003ctd align\u003dcenter colspan\u003d2 class\u003dtdform\u003e\u003cdiv id\u003dpostinfo style\u003dform\u003e\n+\tFORM 2: send with multipart/form-data\u003cbr\u003e\n+\t(can handle file upload, test limited to 100KB)\u003cbr\u003e\n+\t\u003cform name\u003dmultipart action\u003d\u0022formtest\u0022 method\u003d\u0022post\u0022 enctype\u003d\u0022multipart/form-data\u0022\u003e\n+ \u003cspan style\u003d\u0022font-size:12pt;\u0022\u003eSome text: \u003c/span\u003e\n+ \u003cinput type\u003d\u0022text\u0022 name\u003d\u0022text\u0022 value\u003d\u0022Give me some text\u0022\u003e\n+\u003cbr\u003e\n+ \u003cinput type\u003d\u0022file\u0022 name\u003d\u0022file\u0022 id\u003d\u0022file\u0022 size\u003d\u002220\u0022\u003e\u0026nbsp;\u003cspan id\u003dfile_info style\u003d\u0022font-size:12pt;\u0022\u003e\u003c/span\u003e\u003cbr\u003e\n+ \u003cinput type\u003d\u0022submit\u0022 id\u003d\u0022upload\u0022 name\u003d\u0022upload\u0022 disabled\u003d1 value\u003d\u0022Upload\u0022\u003e\n+\t\u003c/form\u003e\n+\t\u003c/div\u003e\u003c/td\u003e\n+\t\u003c/tr\u003e\n+\t\n+\u003c/table\u003e\n+\u003c/div\u003e\n+ \u003c/div\u003e \n+ \u003c/div\u003e\n+\n+\u003c/div\u003e\n+\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n+\n+Looking for support? \u003ca href\u003d\u0022https://libwebsockets.org\u0022\u003ehttps://libwebsockets.org\u003c/a\u003e, \u003ca href\u003d\u0022https://github.com/warmcat/libwebsockets\u0022\u003ehttps://github.com/warmcat/libwebsockets\u003c/a\u003e\u003c/a\u003e\u003cbr/\u003e\n+Join the mailing list: \u003ca href\u003d\u0022https://libwebsockets.org/mailman/listinfo/libwebsockets\u0022\u003ehttps://libwebsockets.org/mailman/listinfo/libwebsockets\u003c/a\u003e\n+\n+\u003c/article\u003e\n+\n+\u003cscript nonce\u003d\u0022lwscaro\u0022\u003e\n+\n+document.getElementById('file').onchange \u003d check_file;\n+document.getElementById('offset').onclick \u003d reset;\n+document.getElementById('junk').onclick \u003d junk;\n+document.getElementById('color').onclick \u003d update_color;\n+document.getElementById('ot_open_btn').onclick \u003d ot_open;\n+document.getElementById('ot_close_btn').onclick \u003d ot_close;\n+document.getElementById('ot_req_close_btn').onclick \u003d ot_req_close;\n+document.getElementById('pmd').onclick \u003d on_pmd;\n+\n+/*\n+ * We display untrusted stuff in html context... reject anything\n+ * that has HTML stuff in it\n+ */\n+\n+function san(s)\n+{\n+\tif (s.search(\u0022\u003c\u0022) !\u003d -1)\n+\t\treturn \u0022invalid string\u0022;\n+\t\n+\treturn s;\n+}\n+\n+lws_gray_out(true,{'zindex':'499'});\n+\n+/* BrowserDetect came from http://www.quirksmode.org/js/detect.html */\n+\n+var BrowserDetect \u003d {\n+\tinit: function () {\n+\t\tthis.browser \u003d this.searchString(this.dataBrowser) || \u0022An unknown browser\u0022;\n+\t\tthis.version \u003d this.searchVersion(navigator.userAgent)\n+\t\t\t|| this.searchVersion(navigator.appVersion)\n+\t\t\t|| \u0022an unknown version\u0022;\n+\t\tthis.OS \u003d this.searchString(this.dataOS) || \u0022an unknown OS\u0022;\n+\t},\n+\tsearchString: function (data) {\n+\t\tfor (var i\u003d0;i\u003cdata.length;i++)\t{\n+\t\t\tvar dataString \u003d data[i].string;\n+\t\t\tvar dataProp \u003d data[i].prop;\n+\t\t\tthis.versionSearchString \u003d data[i].versionSearch || data[i].identity;\n+\t\t\tif (dataString) {\n+\t\t\t\tif (dataString.indexOf(data[i].subString) !\u003d -1)\n+\t\t\t\t\treturn data[i].identity;\n+\t\t\t}\n+\t\t\telse if (dataProp)\n+\t\t\t\treturn data[i].identity;\n+\t\t}\n+\t},\n+\tsearchVersion: function (dataString) {\n+\t\tvar index \u003d dataString.indexOf(this.versionSearchString);\n+\t\tif (index \u003d\u003d -1) return;\n+\t\treturn parseFloat(dataString.substring(index+this.versionSearchString.length+1));\n+\t},\n+\tdataBrowser: [\n+\t\t{\n+\t\t\tstring: navigator.userAgent,\n+\t\t\tsubString: \u0022Chrome\u0022,\n+\t\t\tidentity: \u0022Chrome\u0022\n+\t\t},\n+\t\t{ \tstring: navigator.userAgent,\n+\t\t\tsubString: \u0022OmniWeb\u0022,\n+\t\t\tversionSearch: \u0022OmniWeb/\u0022,\n+\t\t\tidentity: \u0022OmniWeb\u0022\n+\t\t},\n+\t\t{\n+\t\t\tstring: navigator.vendor,\n+\t\t\tsubString: \u0022Apple\u0022,\n+\t\t\tidentity: \u0022Safari\u0022,\n+\t\t\tversionSearch: \u0022Version\u0022\n+\t\t},\n+\t\t{\n+\t\t\tprop: window.opera,\n+\t\t\tidentity: \u0022Opera\u0022,\n+\t\t\tversionSearch: \u0022Version\u0022\n+\t\t},\n+\t\t{\n+\t\t\tstring: navigator.vendor,\n+\t\t\tsubString: \u0022iCab\u0022,\n+\t\t\tidentity: \u0022iCab\u0022\n+\t\t},\n+\t\t{\n+\t\t\tstring: navigator.vendor,\n+\t\t\tsubString: \u0022KDE\u0022,\n+\t\t\tidentity: \u0022Konqueror\u0022\n+\t\t},\n+\t\t{\n+\t\t\tstring: navigator.userAgent,\n+\t\t\tsubString: \u0022Firefox\u0022,\n+\t\t\tidentity: \u0022Firefox\u0022\n+\t\t},\n+\t\t{\n+\t\t\tstring: navigator.vendor,\n+\t\t\tsubString: \u0022Camino\u0022,\n+\t\t\tidentity: \u0022Camino\u0022\n+\t\t},\n+\t\t{\t\t// for newer Netscapes (6+)\n+\t\t\tstring: navigator.userAgent,\n+\t\t\tsubString: \u0022Netscape\u0022,\n+\t\t\tidentity: \u0022Netscape\u0022\n+\t\t},\n+\t\t{\n+\t\t\tstring: navigator.userAgent,\n+\t\t\tsubString: \u0022MSIE\u0022,\n+\t\t\tidentity: \u0022Explorer\u0022,\n+\t\t\tversionSearch: \u0022MSIE\u0022\n+\t\t},\n+\t\t{\n+\t\t\tstring: navigator.userAgent,\n+\t\t\tsubString: \u0022Gecko\u0022,\n+\t\t\tidentity: \u0022Mozilla\u0022,\n+\t\t\tversionSearch: \u0022rv\u0022\n+\t\t},\n+\t\t{ \t\t// for older Netscapes (4-)\n+\t\t\tstring: navigator.userAgent,\n+\t\t\tsubString: \u0022Mozilla\u0022,\n+\t\t\tidentity: \u0022Netscape\u0022,\n+\t\t\tversionSearch: \u0022Mozilla\u0022\n+\t\t}\n+\t],\n+\tdataOS : [\n+\t\t{\n+\t\t\tstring: navigator.platform,\n+\t\t\tsubString: \u0022Win\u0022,\n+\t\t\tidentity: \u0022Windows\u0022\n+\t\t},\n+\t\t{\n+\t\t\tstring: navigator.platform,\n+\t\t\tsubString: \u0022Mac\u0022,\n+\t\t\tidentity: \u0022Mac\u0022\n+\t\t},\n+\t\t{\n+\t\t\t string: navigator.userAgent,\n+\t\t\t subString: \u0022iPhone\u0022,\n+\t\t\t identity: \u0022iPhone/iPod\u0022\n+\t },\n+\t\t{\n+\t\t\tstring: navigator.platform,\n+\t\t\tsubString: \u0022Linux\u0022,\n+\t\t\tidentity: \u0022Linux\u0022\n+\t\t}\n+\t]\n+\n+};\n+BrowserDetect.init();\n+\n+document.getElementById(\u0022brow\u0022).textContent \u003d \u0022 \u0022 + BrowserDetect.browser + \u0022 \u0022\n+\t+ BrowserDetect.version +\u0022 \u0022 + BrowserDetect.OS +\u0022 \u0022;\n+\n+\tvar pos \u003d 0;\n+\n+function get_appropriate_ws_url(extra_url)\n+{\n+\tvar pcol;\n+\tvar u \u003d document.URL;\n+\n+\t/*\n+\t * We open the websocket encrypted if this page came on an\n+\t * https:// url itself, otherwise unencrypted\n+\t */\n+\n+\tif (u.substring(0, 5) \u003d\u003d \u0022https\u0022) {\n+\t\tpcol \u003d \u0022wss://\u0022;\n+\t\tu \u003d u.substr(8);\n+\t} else {\n+\t\tpcol \u003d \u0022ws://\u0022;\n+\t\tif (u.substring(0, 4) \u003d\u003d \u0022http\u0022)\n+\t\t\tu \u003d u.substr(7);\n+\t}\n+\n+\tu \u003d u.split('/');\n+\n+\t/* + \u0022/xxx\u0022 bit is for IE10 workaround */\n+\n+\treturn pcol + u[0] + \u0022/\u0022 + extra_url;\n+}\n+\n+var params \u003d {};\n+\n+if (location.search) {\n+ var parts \u003d location.search.substring(1).split('\u0026');\n+\n+ for (var i \u003d 0; i \u003c parts.length; i++) {\n+ var nv \u003d parts[i].split('\u003d');\n+ if (!nv[0]) continue;\n+ params[nv[0]] \u003d nv[1] || true;\n+ }\n+}\n+window.onload \u003d function() {\n+var transport_protocol \u003d \u0022\u0022;\n+\n+if ( performance \u0026\u0026 performance.timing.nextHopProtocol ) {\n+ transport_protocol \u003d performance.timing.nextHopProtocol;\n+} else if ( window.chrome \u0026\u0026 window.chrome.loadTimes ) {\n+ transport_protocol \u003d window.chrome.loadTimes().connectionInfo;\n+} else {\n+\n+ var p \u003d performance.getEntriesByType(\u0022resource\u0022);\n+ for (var i\u003d0; i \u003c p.length; i++) {\n+var value \u003d \u0022nextHopProtocol\u0022 in p[i];\n+ if (value)\n+ transport_protocol \u003d p[i].nextHopProtocol;\n+ }\n+ }\n+ \n+ console.log(\u0022transport protocol \u0022 + transport_protocol);\n+ \n+ if (transport_protocol \u003d\u003d \u0022h2\u0022)\n+ \tdocument.getElementById(\u0022transport\u0022).innerHTML \u003d \u0022\u003cimg src\u003d\u005c\u0022./http2.png\u005c\u0022\u003e\u0022;\n+}\n+\n+var mirror_name \u003d \u0022\u0022;\n+if (params.mirror)\n+\tmirror_name \u003d params.mirror;\n+\n+\tconsole.log(mirror_name);\n+\t\n+\n+/*\n+ * if using lws-meta to carry the other ws connections, declare the\n+ * parent connection object and start its connection to the server.\n+ *\n+ * These helpers are defined in lws-common.js\n+ */\n+\n+var use_lws_meta \u003d 0, lws_meta;\n+\n+if (use_lws_meta) {\n+\tlws_meta \u003d new lws_meta_ws();\n+\tlws_meta.new_parent(get_appropriate_ws_url(\u0022?mirror\u003d\u0022 + mirror_name));\n+}\n+\n+\n+document.getElementById(\u0022number\u0022).textContent \u003d get_appropriate_ws_url(mirror_name);\n+\n+/* dumb increment protocol */\n+\n+\t/*\n+\t * to connect via an lws-meta connection, start the connection using\n+\t * lws_meta.new_ws(). To connect by independent connection, start\n+\t * the connection using just new_ws()\n+\t */\n+\t\n+\tvar socket_di;\n+\t\n+\tif (use_lws_meta)\n+\t\tsocket_di \u003d lws_meta.new_ws(\u0022\u0022, \u0022dumb-increment-protocol\u0022);\n+\telse\n+\t\tsocket_di \u003d new_ws(get_appropriate_ws_url(\u0022\u0022), \u0022dumb-increment-protocol\u0022);\n+\n+\ttry {\n+\t\tsocket_di.onopen \u003d function() {\n+\t\t\tdocument.getElementById(\u0022wsdi_statustd\u0022).style.backgroundColor \u003d \u0022#40ff40\u0022;\n+\t\t\tdocument.getElementById(\u0022wsdi_status\u0022).innerHTML \u003d\n+\t\t\t\t\u0022 \u003cb\u003ewebsocket connection opened\u003c/b\u003e\u003cbr\u003e\u0022 +\n+\t\t\t\tsan(socket_di.extensions);\n+\t\t} \n+\n+\t\tsocket_di.onmessage \u003dfunction got_packet(msg) {\n+\t\t\tdocument.getElementById(\u0022number\u0022).textContent \u003d msg.data + \u0022\u005cn\u0022;\n+\t\t} \n+\n+\t\tsocket_di.onclose \u003d function(){\n+\t\t\tdocument.getElementById(\u0022wsdi_statustd\u0022).style.backgroundColor \u003d \u0022#ff4040\u0022;\n+\t\t\tdocument.getElementById(\u0022wsdi_status\u0022).textContent \u003d \u0022 websocket connection CLOSED \u0022;\n+\t\t}\n+\t} catch(exception) {\n+\t\talert('\u003cp\u003eError' + exception); \n+\t}\n+\t\n+\tvar socket_status, jso, s;\n+\n+\tif (use_lws_meta)\n+\t\tsocket_status \u003d lws_meta.new_ws(\u0022\u0022, \u0022lws-status\u0022);\n+\telse\n+\t\tsocket_status \u003d new_ws(get_appropriate_ws_url(\u0022\u0022), \u0022lws-status\u0022);\n+\n+\ttry {\n+\t\tsocket_status.onopen \u003d function() {\n+\t\t\tdocument.getElementById(\u0022s_statustd\u0022).style.backgroundColor \u003d \u0022#40ff40\u0022;\n+\t\t\tdocument.getElementById(\u0022s_status\u0022).innerHTML \u003d\n+\t\t\t\t\u0022 \u003cb\u003ewebsocket connection opened\u003c/b\u003e\u003cbr\u003e\u0022 +\n+\t\t\t\tsan(socket_status.extensions);\n+\t\t} \n+\n+\t\tsocket_status.onmessage \u003dfunction got_packet(msg) {\n+\t\t\tvar s;\n+\t\t\t\n+\t\t\tconsole.log(msg.data);\n+\t\t\t\n+\t\t\tjso \u003d JSON.parse(msg.data);\n+\t\t\t\n+\t\t\tif (jso.wss_over_h2 \u003d\u003d \u00221\u0022)\n+\t\t\t\tdocument.getElementById(\u0022wstransport\u0022).innerHTML \u003d \u0022\u003cimg src\u003d\u005c\u0022./wss-over-h2.png\u005c\u0022\u003e\u0022;\n+\t\t\t\n+\t\t\tdocument.getElementById(\u0022servinfo\u0022).innerHTML \u003d \n+\t\t\t\t\u0022\u003ctable\u003e\u003ctr\u003e\u003ctd class\u003dl\u003eBuild info\u003c/td\u003e\u003ctd\u003e\u0022+\n+\t\t\t\t\tsan(jso.version) + \u0022\u003c/td\u003e\u003c/tr\u003e\u0022 +\n+\t\t\t\t\t\u0022\u003ctr\u003e\u003ctd class\u003dl\u003eServer info\u003c/td\u003e\u003ctd\u003e\u0022 +\n+\t\t\t\t\tsan(jso.hostname) + \u0022\u003c/td\u003e\u003c/tr\u003e\u0022 +\n+\t\t\t\t\t\u0022\u003c/table\u003e\u0022;\n+\t\t\ts\u003d\u0022\u003ctable\u003e\u0022;\n+\t\t\tvar n;\n+\t\t\tfor (n \u003d 0; n \u003c jso.conns.length; n++) {\n+\t\t\t\tvar d \u003d new Date(parseInt(jso.conns[n].time) * 1000);\n+\t\t\t\t\n+\t\t\t\ts \u003d s + \u0022\u003ctr\u003e\u003ctd class\u003dl\u003eclient \u0022 + (n + 1) +\n+\t\t\t\t\u0022\u003c/td\u003e\u003ctd\u003e\u003cb\u003e\u0022 + san(jso.conns[n].peer) +\n+\t\t\t\t\u0022\u003c/b\u003e\u003cbr\u003e\u0022 + san(d.toString()) +\n+\t\t\t\t\u0022\u003cbr\u003e\u0022 + san(jso.conns[n].ua) +\n+\t\t\t\t\u0022\u003c/td\u003e\u003c/tr\u003e\u0022;\n+\t\t\t}\n+\t\t\ts \u003d s + \u0022\u003c/table\u003e\u0022;\n+\t\t\t\n+\t\t\tdocument.getElementById(\u0022conninfo\u0022).innerHTML \u003d s;\n+\t\t} \n+\n+\t\tsocket_status.onclose \u003d function(){\n+\t\t\tdocument.getElementById(\u0022s_statustd\u0022).style.backgroundColor \u003d \u0022#ff4040\u0022;\n+\t\t\tdocument.getElementById(\u0022s_status\u0022).textContent \u003d \u0022 websocket connection CLOSED \u0022;\n+\t\t}\n+\t} catch(exception) {\n+\t\talert('\u003cp\u003eError' + exception); \n+\t}\n+\n+function reset() {\n+\tsocket_di.send(\u0022reset\u005cn\u0022);\n+}\n+\n+\n+function junk() {\n+\tfor(var word \u003d ''; word.length \u003c 9000; word +\u003d 'a'){}\n+\tsocket_di.send(word);\n+}\n+\n+function on_pmd() {\n+\tsocket_status.send(\u0022{ \u005c\u0022RequestType\u005c\u0022:\u005c\u0022DDoS\u005c\u0022, \u005c\u0022blob\u005c\u0022:\u005c\u0022data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAJbElEQVR4Xu2af4xUVxXHv+e9O0OhIEibgrRlF8rOG6CWKiumrUlTo6byj6mmNFta2DdQsRJJrP5j+0cnjSVp1BoSU1yzO28LEeL6h7GJNhpJNa2CBQ1gd9k3QPlRBU2LLV0W2p173zFvZvbtzOybmbd7J9DEd/+befece97nfe+95/4gxEWLAGlZx8aIAWqKIAYYA9QkoGkeKzAGqElA0zxWYAxQk4CmeazAGKAmAU3zWIExQE0CmuaxAmOAmgQ0zWMFxgA1CWiaxwqMAWoS0DRvrQJ3ujeb17Hrx6SuzLwV32x7VzO+1pj3HJprJue8BcBQCSONRzr+2RrHaO2OtHDc1wDcUwqOj0s7nWpVoDp+hOMeA5Au+zggbesuHX+Vti1VoOh3j4BxRxEf8xmVSbe3KlAdP2bOPUmEpaXviiGZsVbq+IsBxgCnpp9YgVPjNan2RwagmXMfUpnUAEAc9k6Rx8AHB0zzy3euU5nUXk02RXMzl+9Ssw8PYN06FeYvOkAmM5dfpzLWL6LGFXkSMR13jIAEmKXMpBM6AIXjeih+BVLqTEcSWfJ/T71ks4bZ9vAYgU1/epC2ZegAFLnhAogEM0tV5x1r/UcGKBw3UJ1sTyVwH8laZ5EU2DO4WCTFmXFbOTbnemxZdHnq9AAMvDVTjF4ObKVS7di8IvA97jOSArNsiLZ8oGBpW5HYRKrkB1IFcGwkiS2dhWkB7B1qE6Z5uiUAew7NEsk5o4EveEtgLw98TwngwIApRlcFoogBVnzdSArUAWg6+T4QS3U69Xi98eiqK7A4vnX1+YsldWbPJmSzk8fJa6FAP67FXTv9sVLZqU1k9rvHibGsmKQzBlTGeih0gqgcA69CFxaO+zKA+4uxEF6W3dbaSXFdA4Bmzt1DhK5SLHycTMd9n4A5pT9oSNqp0GXO1VagcFx/cphZhnZF2tasjwJAkRs+CqJPFvEBIzHA8a8ScQyMAdbbTGgJwAY7FS3LA3edXCyUbJoHitzwKIhK3Zb5ssykr5/Uha9BHigc9whQ3nHyu7DIDe8A0TY/OI/xtJexngnP5ocLRCRAkLLbas1KhOGps6lE2MxvOO6TBvBsMS7Pe8rbtHz7pLhavRLpdwtgCDCkzIS/o9Gff8pg/n55EtlRSqT7h+8B0xhs62AYvHJlf524QZ3duzs0pfCT7aj7gQNsmqPHH1V2qr9+ewBePHYXIICNHfsb1TNzw7Y6e343svdNWh35dpHyQL9iKUV5VGVSu+qt94tx7DrZCa8wA93pP0deiTR80fLDyACjOGthncgAp9FmqwG+CsbnynHkpW1Z04ip5Sai3x0CY3kpU+P9sjt9d6saaSlA9JybJWaMXARDyRFjLrZ1fNiqQLX8DAwmxai4CCAhzblzsWFhsH7W8lvM8eOiRSAGqIUvVqAmvhhgDFCbgKaDqY+B2ayBBV2fQJJnwzQlSL6HjcsvhMaRHUwG/2dXjjWMtXdwPjBjPryCARKXIcQ7sJd8EOn9fFuTbkCBCDOMUZw69596SXWVv4HB2bicXAClBARdwqm95+stEurFER1gz6GESM45DGBFmLNJW+C5E7cKUmfH68pkoh3rl046r8CL7s3CQ+hdFQY2KNvaXS94o8/\u005c\u0022 }\u0022);\n+\tsocket_status.send(\u0022{ \u005c\u0022RequestType\u005c\u0022:\u005c\u0022SendImage\u005c\u0022, \u005c\u0022RequestID\u005c\u0022:\u005c\u0022283463389\u005c\u0022, \u005c\u0022toType\u005c\u0022:\u005c\u0022toUser\u005c\u0022, \u005c\u0022toID\u005c\u0022:\u005c\u00221036\u005c\u0022, \u005c\u0022fileType\u005c\u0022:\u005c\u0022image/jpeg\u005c\u0022, \u005c\u0022blob\u005c\u0022:\u005c\u0022data:image/jpeg;base64,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oooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACioZry0t/8AX3Mcf+8wFUZvEekxcfaN5/2VJosBqUVz03jC3GRBau3+8QKozeLb9/8AVRRxj86fKwOvorg5tc1Sb7124HoOKjtdUvba4WcXDtgjILZBFPlA9AoooqQCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACori5gtYzLcSqijualrkPFsztfpAWO1EBA9zTSuBqzeK9NjyIxJIfYYFUpvGMh/497NR/vtn+Vc3RV8qA1pvE+rS/dlWMf7Kj+tUZtRv7j/XXcrD0LnFV6KdkAUUUUAFFFFABQOtFA60AelDpS0g6UtZAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFcb4r/5Cv/bJf612Vcb4r/5Cv/bJf61UdwMaiiirAKKKVVZztVSSewFACUVch0fU5/8AV2UuD3K4H61eh8KanJ/rDFF/vNn+VF0Bi0V08Pg5BzPeE+yrV2HwxpUX3o3kP+01LmQHF0DrXb3ui6b9ilCWqIVQkEdQRXEDrQncD0odKWkHSlrMAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArjfFf8AyFf+2S/1rsq43xX/AMhX/tkv9aqO4FfSNGl1UuVkEaJwWIzzW7D4RsU5lmlkPpnApvg//jzn/wCuv9BW/Q27gZ8Og6TD92zRv9/5v51djhihG2KJUHooxT6KkAooooAKKKKAIbz/AI9Jv+ubfyrzoda9FvP+PSb/AK5t/KvOh1q4gelDpS0g6UtQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVxviv8A5Cv/AGyX+tdlXG+K/wDkK/8AbJf61UdwNPwf/wAec3/XX+grfrA8H/8AHnN/11/oK36T3AKKKKQBRRRQAUUUUAQ3n/HpN/1zb+VedDrXot5/x6Tf9c2/lXnQ61cQPSh0paQdKWoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK43xX/yFf+2S/wBa7KuN8V/8hX/tkv8AWqjuBp+D/wDjzm/66/0Fb9YHg/8A485v+uv9BW/Se4BRRRSAKKKKACiiigCG8/49Jv8Arm38q86HWvRbz/j0m/65t/KvOh1q4gelDpS0g6UtQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVxviv/AJCv/bJf612Vcb4r/wCQr/2yX+tVHcDT8H/8ec3/AF1/oK36wPB//HnN/wBdf6Ct+k9wCiiikAUUVDc3dtZp5lzMsY7ZPX6UATUViy+K9MQ4QSye4XH86j/4S+w/59p/yH+NOzA2Lw4tJs/882/lXnQ610GqeKBdW7W9pCyBxhmbGce1c+OtXFWA9KHSlpB0pazAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiioLy9t7GEz3MgVR09SfQUAT0Vy9z4vkJItLYAdi55/Kqh8Vaqe8Q+iVXKwOzri/FDq+qttOdqKp+vNNfxNqrqV81Fz3C81mO7yOXdizMcknvTirAdV4P/AOPOb/rr/QVv1geD/wDjzm/66/0Fb9S9wCiiikBXv7tLG1kuX/gHA9TXBXd3PeztPO5Zj09h6Cuq8WFhpqgdDIM/rXH1cUAUUUVQBQOtFS2sTT3MUKjJdwv5mgD0UdKWkpayAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACuH8QX73l+67j5cR2qP5mu4rzzUI2ivZ43HIc/zqo7gV6KKKsAooooA6zweP8AQpj/ANNf6Ct+snwzbNb6WjMMGUl/w7fpWtWb3AKKKKQFXU7IX9lJbHgsMqfQ1wU8EttK0MyFWU4INej1UvtLstQXFzECezDgiqTsB5/RXUyeDoScxXjKPQrmmr4OT+K+P4J/9eq5kBzFdH4Y0h/MGo3CFQv+rB7n1rSs/DWnWrB2VpWHQv0/KtUAAYAwBUuXYBaKKKkAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKK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RGJ2jIDLzkMM9wQCPpXM6V8IfDuk614c1uC7vGm8N2ktrAjsu2YuCDJIMcuNzYIx9413VFAHBn4VfY2a48PeMNY0m6a+vr1pYhFIr/apmldGjkRkIDMdpIyB3qfwl8K9E8IajZ6rY3t3LPa2dzaMZSuJTPKkjyMABhtyDgYGCeK7WigDC8N+EbHwzoM3h+0uZ5YZp7qcvJjcDPK8jDgAYBcgewFc6vwc0NbW1tU1fVI/sel3WlRSRSiOQJPKspkDKAQ6soxjj1Brv6KAPPf+FQwX76jdeJvFWp6xe39gNNW5ljgiaGAMWG0RIqk7jnLA10Wg+F73RZ7SWfxVqmoJa2IsvJn8tY5CGBEpVFA3gDbxgYzxmugooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD//Z\u005c\u0022}\u0022)\n+\tsocket_status.send(\u0022{ \u005c\u0022RequestType\u005c\u0022:\u005c\u0022SendImage\u005c\u0022, \u005c\u0022RequestID\u005c\u0022:\u005c\u0022788346414\u005c\u0022, \u005c\u0022toType\u005c\u0022:\u005c\u0022toUser\u005c\u0022, \u005c\u0022toID\u005c\u0022:\u005c\u00221036\u005c\u0022, \u005c\u0022fileType\u005c\u0022:\u005c\u0022image/jpeg\u005c\u0022, \u005c\u0022blob\u005c\u0022:\u005c\u0022data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAHgAoADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9U6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAopNy/wB4fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/AHh+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv8AeH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/wB4fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/AHh+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv8AeH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/wB4fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/AHh+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv8AeH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv94fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/wB4fnRuX+8PzoAWik3L/eH50bl/vD86AFopNy/3h+dG5f7w/OgBaKTcv94fnRuX+8PzoAxst6mky3940UmRQA7J9TRk+ppKKAAFh/EaCWP8RoooAXJ9TRk+ppKKADL/AN40Zf8AvGkwKMCgA3N/eNG5v7xoI70Ad6AF3Mf4iPxpMsP4j+dHSlxmgBCWH8R/OlBb+8fzpCM96OgoAVWb+8fzoLN6n86OBTSc0AOy3940Zb+8aTg0YFACkv8A3jRlv7xpNvvSYx3oAXLn+I0Ev/eNAwOc0YBNABubHU/nSbm/vH86VaMc5oATc394/nTt3+0aTb70baAAl8/eP50uW/vGk20baADc3940B27k0babQA/Lf3jRlv7xpMAdTRgH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iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/9k\u003d\u005c\u0022}\u0022)\n+}\n+\n+var socket_ot;\n+\n+function ot_open() {\n+\tif (use_lws_meta)\n+\t\tsocket_ot \u003d lws_meta.new_ws(get_appropriate_ws_url(\u0022\u0022), \u0022dumb-increment-protocol\u0022);\n+\telse\n+\t\tsocket_ot \u003d new_ws(get_appropriate_ws_url(\u0022\u0022), \u0022dumb-increment-protocol\u0022);\n+\n+\tconsole.log(\u0022ot_open\u0022);\n+\n+\ttry {\n+\t\tsocket_ot.onopen \u003d function() {\n+\t\t\tdocument.getElementById(\u0022ot_statustd\u0022).style.backgroundColor \u003d \u0022#40ff40\u0022;\n+\t\t\tdocument.getElementById(\u0022ot_status\u0022).innerHTML \u003d \u0022 \u003cb\u003ewebsocket connection opened\u003c/b\u003e\u003cbr\u003e\u0022 + san(socket_di.extensions);\n+\t\t\tdocument.getElementById(\u0022ot_open_btn\u0022).disabled \u003d true;\n+\t\t\tdocument.getElementById(\u0022ot_close_btn\u0022).disabled \u003d false;\n+\t\t\tdocument.getElementById(\u0022ot_req_close_btn\u0022).disabled \u003d false;\n+\t\t\tconsole.log(\u0022ot_open.onopen\u0022);\n+\t\t} \n+\n+\t\tsocket_ot.onclose \u003d function(e){\n+\t\t\tdocument.getElementById(\u0022ot_statustd\u0022).style.backgroundColor \u003d \u0022#ff4040\u0022;\n+\t\t\tdocument.getElementById(\u0022ot_status\u0022).textContent \u003d \u0022 websocket connection CLOSED, code: \u0022 + e.code +\n+\t\t\t\u0022, reason: \u0022 + e.reason;\n+\t\t\tdocument.getElementById(\u0022ot_open_btn\u0022).disabled \u003d false;\n+\t\t\tdocument.getElementById(\u0022ot_close_btn\u0022).disabled \u003d true;\n+\t\t\tdocument.getElementById(\u0022ot_req_close_btn\u0022).disabled \u003d true;\n+\t\t}\n+\t} catch(exception) {\n+\t\talert('\u003cp\u003eError' + exception); \n+\t}\n+}\n+\n+/* browser will close the ws in a controlled way */\n+function ot_close() {\n+\tsocket_ot.close(3000, \u0022Bye!\u0022);\n+}\n+\n+/* we ask the server to close the ws in a controlled way */\n+function ot_req_close() {\n+\tsocket_ot.send(\u0022closeme\u005cn\u0022);\n+}\n+\n+/* lws-mirror protocol */\n+\n+\tvar down \u003d 0;\n+\tvar no_last \u003d 1;\n+\tvar last_x \u003d 0, last_y \u003d 0;\n+\tvar ctx;\n+\tvar socket_lm;\n+\tvar color \u003d \u0022#000000\u0022;\n+\tvar pending \u003d \u0022\u0022;\n+\tvar lm_timer;\n+\n+\tif (use_lws_meta)\n+\t\tsocket_lm \u003d lws_meta.new_ws(get_appropriate_ws_url(\u0022?mirror\u003d\u0022 + mirror_name),\n+\t\t\t\u0022lws-mirror-protocol\u0022);\n+\telse\n+\t\tsocket_lm \u003d new_ws(get_appropriate_ws_url(\u0022?mirror\u003d\u0022 + mirror_name),\n+\t\t\t\u0022lws-mirror-protocol\u0022);\n+\ttry {\n+\t\tsocket_lm.onopen \u003d function() {\n+\t\t\tdocument.getElementById(\u0022wslm_statustd\u0022).style.backgroundColor \u003d \u0022#40ff40\u0022;\n+\t\t\tdocument.getElementById(\u0022wslm_status\u0022).innerHTML \u003d\n+\t\t\t\t\u0022 \u003cb\u003ewebsocket connection opened\u003c/b\u003e\u003cbr\u003e\u0022 +\n+\t\t\t\tsan(socket_lm.extensions);\n+\t\t\tlws_gray_out(false);\n+\t\t} \n+\n+\t\tsocket_lm.onmessage \u003dfunction got_packet(msg) {\n+\t\t\tj \u003d msg.data.split(';');\n+\t\t\tf \u003d 0;\n+\t\t\twhile (f \u003c j.length - 1) {\n+\t\t\t\ti \u003d j[f].split(' ');\n+\t\t\t\tif (i[0] \u003d\u003d 'd') {\n+\t\t\t\t\tctx.strokeStyle \u003d i[1];\n+\t\t\t\t\tctx.beginPath();\n+\t\t\t\t\tctx.moveTo(+(i[2]), +(i[3]));\n+\t\t\t\t\tctx.lineTo(+(i[4]), +(i[5]));\n+\t\t\t\t\tctx.stroke();\n+\t\t\t\t}\n+\t\t\t\tif (i[0] \u003d\u003d 'c') {\n+\t\t\t\t\tctx.strokeStyle \u003d i[1];\n+\t\t\t\t\tctx.beginPath();\n+\t\t\t\t\tctx.arc(+(i[2]), +(i[3]), +(i[4]), 0, Math.PI*2, true); \n+\t\t\t\t\tctx.stroke();\n+\t\t\t\t}\n+\n+\t\t\t\tf++;\n+\t\t\t}\n+\t\t}\n+\n+\t\tsocket_lm.onclose \u003d function(){\n+\t\t\tdocument.getElementById(\u0022wslm_statustd\u0022).style.backgroundColor \u003d \u0022#ff4040\u0022;\n+\t\t\tdocument.getElementById(\u0022wslm_status\u0022).textContent \u003d \u0022 websocket connection CLOSED \u0022;\n+\t\t\tlws_gray_out(true,{'zindex':'499'});\n+\t\t}\n+\t} catch(exception) {\n+\t\talert('\u003cp\u003eError' + exception); \n+\t}\n+\n+\tvar canvas \u003d document.createElement('canvas');\n+\tcanvas.height \u003d 300;\n+\tcanvas.width \u003d 480;\n+\tctx \u003d canvas.getContext(\u00222d\u0022);\n+\n+\tdocument.getElementById('wslm_drawing').appendChild(canvas);\n+\n+\tcanvas.addEventListener('mousemove', ev_mousemove, false);\n+\tcanvas.addEventListener('mousedown', ev_mousedown, false);\n+\tcanvas.addEventListener('mouseup', ev_mouseup, false);\n+\n+\toffsetX \u003d offsetY \u003d 0;\n+\telement \u003d canvas;\n+ if (element.offsetParent) {\n+ do {\n+ offsetX +\u003d element.offsetLeft;\n+ offsetY +\u003d element.offsetTop;\n+ } while ((element \u003d element.offsetParent));\n+ }\n+ \n+function update_color() {\n+\tcolor \u003d document.getElementById(\u0022color\u0022).value;\n+}\n+\n+function ev_mousedown (ev) {\n+\tdown \u003d 1;\n+}\n+\n+function ev_mouseup(ev) {\n+\tdown \u003d 0;\n+\tno_last \u003d 1;\n+}\n+\n+function lm_timer_handler(ev) {\n+\tsocket_lm.send(pending);\n+\tpending\u003d\u0022\u0022;\n+}\n+\n+function ev_mousemove (ev) {\n+\tvar x, y;\n+\n+\tif (ev.offsetX) {\n+\t\tx \u003d ev.offsetX;\n+\t\ty \u003d ev.offsetY;\n+\t} else {\n+\t\tx \u003d ev.layerX - offsetX;\n+\t\ty \u003d ev.layerY - offsetY;\n+\n+\t}\n+\n+\tif (!down)\n+\t\treturn;\n+\tif (no_last) {\n+\t\tno_last \u003d 0;\n+\t\tlast_x \u003d x;\n+\t\tlast_y \u003d y;\n+\t\treturn;\n+\t}\n+\tpending \u003d pending + \u0022d \u0022 + color + \u0022 \u0022 + last_x + \u0022 \u0022 + last_y +\n+\t\t\t\u0022 \u0022 + x + ' ' + y + ';';\n+\t\t\t\n+\tif (pending.length \u003e 400) {\n+\t\tsocket_lm.send(pending);\n+\t\tclearTimeout(lm_timer);\n+\t\tpending \u003d \u0022\u0022;\n+\t} else\n+\t\tlm_timer \u003d setTimeout(lm_timer_handler, 1);\n+\n+\tlast_x \u003d x;\n+\tlast_y \u003d y;\n+}\n+\n+\n+\u003c/script\u003e\n+\n+\u003c/body\u003e\n+\u003c/html\u003e\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/wss-over-h2.png b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/wss-over-h2.png\nnew file mode 100644\nindex 0000000..1a62d83\nBinary files /dev/null and b/minimal-examples/http-server/minimal-http-server-eventlib-demos/mount-origin/wss-over-h2.png differ\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/README.md b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/README.md\nindex a663d6e..4c21fa1 100644\n--- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/README.md\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/README.md\n@@ -41,8 +41,8 @@ exits itself.\n ## usage\n \n ```\n- $ ./lws-minimal-http-server-libuv-foreign\n-[2018/03/29 12:19:31:3480] USER: LWS minimal http server libuv + foreign loop | visit http://localhost:7681\n+ $ ./lws-minimal-http-server-eventlib-foreign\n+[2018/03/29 12:19:31:3480] USER: LWS minimal http server eventlib + foreign loop | visit http://localhost:7681\n [2018/03/29 12:19:31:3724] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 off\n [2018/03/29 12:19:31:3804] NOTICE: Using foreign event loop...\n [2018/03/29 12:19:31:3938] USER: Foreign 1Hz timer\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c\nindex 3e807d9..f31b7bd 100644\n--- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c\n@@ -337,7 +337,7 @@ int main(int argc, const char **argv)\n \t\tlogs \u003d atoi(p);\n \n \tlws_set_log_level(logs, NULL);\n-\tlwsl_user(\u0022LWS minimal http server libuv + foreign loop |\u0022\n+\tlwsl_user(\u0022LWS minimal http server eventlib + foreign loop |\u0022\n \t\t \u0022 visit http://localhost:7681\u005cn\u0022);\n \n \t/*\n@@ -383,8 +383,7 @@ int main(int argc, const char **argv)\n \tlwsl_user(\u0022\u005cn\u0022);\n \tlwsl_user(\u0022 Finally close only the timer and signalhandler and\u005cn\u0022);\n \tlwsl_user(\u0022 exit the loop cleanly\u005cn\u0022);\n-\n-\tlwsl_notice(\u0022%s\u005cn\u0022, info.ssl_cert_filepath);\n+\tlwsl_user(\u0022\u005cn\u0022);\n \n \t/* foreign loop specific startup and run */\n \ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib/README.md b/minimal-examples/http-server/minimal-http-server-eventlib/README.md\nindex 873e250..ecfb733 100644\n--- a/minimal-examples/http-server/minimal-http-server-eventlib/README.md\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib/README.md\n@@ -1,4 +1,13 @@\n-# lws minimal http server libuv\n+# lws minimal http server eventlib\n+\n+This demonstrates a minimal http server that can use any of the event libraries\n+\n+Commandline option|Meaning\n+---|---\n+-d \u003cloglevel\u003e|Debug verbosity in decimal, eg, -d15\n+--uv|Use the libuv event library (lws must have been configured with `-DLWS_WITH_LIBUV\u003d1`)\n+--event|Use the libevent library (lws must have been configured with `-DLWS_WITH_LIBEVENT\u003d1`)\n+--ev|Use the libev event library (lws must have been configured with `-DLWS_WITH_LIBEV\u003d1`)\n \n ## build\n \n@@ -9,8 +18,8 @@\n ## usage\n \n ```\n- $ ./lws-minimal-http-server-libuv\n-[2018/03/04 09:30:02:7986] USER: LWS minimal http server-libuv | visit http://localhost:7681\n+ $ ./lws-minimal-http-server-eventlib\n+[2018/03/04 09:30:02:7986] USER: LWS minimal http server-eventlib | visit http://localhost:7681\n [2018/03/04 09:30:02:7986] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 on\n ```\n \n","s":{"c":1711642003,"u": 19872}} ],"g": 157919,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}