Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"", "gen_ut":1713593881, "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":"2e7fbb279dc731207e63b405fcb77eb3", "commit": {"type":"commit", "time": 1525087052, "time_ofs": 480, "oid_tree": { "oid": "b9d03ddd2c0bcae819b117dc1aca17f0cc72ac90", "alias": []}, "oid":{ "oid": "f497562a622a60abbefee9514dfb726d7d5726e0", "alias": []}, "msg": "refactor: change event lib minimal examples to serve as the test apps", "sig_commit": { "git_time": { "time": 1525087052, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }, "sig_author": { "git_time": { "time": 1525087052, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }}, "body": "refactor: change event lib minimal examples to serve as the test apps" , "diff": "diff --git a/CMakeLists.txt b/CMakeLists.txt\nindex 47eed55..93d7210 100644\n--- a/CMakeLists.txt\n+++ b/CMakeLists.txt\n@@ -1608,7 +1608,10 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)\n \t\tendif()\n \tendif()\n \n-\n+\tif (LWS_WITH_LIBEV)\n+\t\t# libev generates a big mess of warnings with gcc, maintainer claims gcc to blame\n+\t\tset_source_files_properties( lib/event-libs/libev/libev.c PROPERTIES COMPILE_FLAGS \u0022-Wno-error\u0022 )\n+\tendif()\n \n \n \tif (NOT LWS_WITHOUT_SERVER)\n@@ -1651,9 +1654,8 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)\n \t\t\t\t\t\u0022\u0022\n \t\t\t\t\t\u0022\u0022\n \t\t\t\t\t\u0022\u0022)\n-\t\t\t\t# libev generates a big mess of warnings with gcc, maintainers blame gcc\n+\t\t\t\t# libev generates a big mess of warnings with gcc, maintainer claims gcc to blame\n \t\t\t\tset_source_files_properties( test-apps/test-server-libev.c PROPERTIES COMPILE_FLAGS \u0022-Wno-error\u0022 )\n-\t\t\t\tset_source_files_properties( lib/event-libs/libev.c PROPERTIES COMPILE_FLAGS \u0022-Wno-error\u0022 )\n \n \t\t\tendif()\n \t\t\tif (NOT ((CMAKE_C_COMPILER_ID MATCHES \u0022Clang\u0022) OR (CMAKE_CXX_COMPILER_ID MATCHES \u0022Clang\u0022))\n@@ -1671,7 +1673,7 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)\n \t\t#\n \t\t# test-server-extpoll\n \t\t#\n-\t\tif (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL)\n+\t\tif (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL AND NOT WIN32)\n \t\t\tcreate_test_app(test-server-extpoll\n \t\t\t\t\u0022test-apps/test-server.c\u0022\n \t\t\t\t\u0022\u0022\n@@ -1889,7 +1891,7 @@ endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS)\n \t\t\tendforeach()\n \t\tendif()\n \tendif()\n-endif(NOT LWS_WITHOUT_TESTAPPS)\n+endif((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS)\n \n if (LWS_WITH_LWSWS)\n \t\tlist(APPEND LWSWS_SRCS\ndiff --git a/lib/context.c b/lib/context.c\nindex 75bf45a..d42f07c 100644\n--- a/lib/context.c\n+++ b/lib/context.c\n@@ -1794,10 +1794,8 @@ lws_context_destroy(struct lws_context *context)\n \tstruct lws wsi;\n \tint n, m;\n \n-\tif (!context) {\n-\t\tlwsl_notice(\u0022%s: ctx %p\u005cn\u0022, __func__, context);\n+\tif (!context)\n \t\treturn;\n-\t}\n \n \tif (context-\u003efinalize_destroy_after_internal_loops_stopped) {\n \t\tif (context-\u003eevent_loop_ops-\u003edestroy_context2)\n@@ -1809,8 +1807,11 @@ lws_context_destroy(struct lws_context *context)\n \t}\n \n \tif (context-\u003ebeing_destroyed1) {\n-\t\tif (!context-\u003ebeing_destroyed2)\n-\t\t\treturn lws_context_destroy2(context);\n+\t\tif (!context-\u003ebeing_destroyed2) {\n+\t\t\tlws_context_destroy2(context);\n+\n+\t\t\treturn;\n+\t\t}\n \t\tlwsl_info(\u0022%s: ctx %p: already being destroyed\u005cn\u0022,\n \t\t\t __func__, context);\n \t\treturn;\ndiff --git a/lib/event-libs/README.md b/lib/event-libs/README.md\nindex 3a7c377..c4c78a7 100644\n--- a/lib/event-libs/README.md\n+++ b/lib/event-libs/README.md\n@@ -43,8 +43,6 @@ event libs, eg,\n ```\n #if defined(LWS_WITH_LIBUV)\n #include \u0022event-libs/libuv/private.h\u0022\n-#else\n- #define LWS_LIBUV_ENABLED(context) (0)\n #endif\n ```\n \ndiff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c\nindex 06e812b..746d571 100644\n--- a/lib/event-libs/libev/libev.c\n+++ b/lib/event-libs/libev/libev.c\n@@ -177,9 +177,6 @@ elops_init_context_ev(struct lws_context *context,\n static void\n elops_accept_ev(struct lws *wsi)\n {\n-\tstruct lws_context *context \u003d lws_get_context(wsi);\n-\tstruct ev_io *r \u003d \u0026wsi-\u003ew_read.ev.watcher;\n-\tstruct ev_io *w \u003d \u0026wsi-\u003ew_write.ev.watcher;\n \tint fd;\n \n \tif (wsi-\u003erole_ops-\u003efile_handle)\n@@ -187,10 +184,11 @@ elops_accept_ev(struct lws *wsi)\n \telse\n \t\tfd \u003d wsi-\u003edesc.sockfd;\n \n-\twsi-\u003ew_read.context \u003d context;\n-\twsi-\u003ew_write.context \u003d context;\n-\tev_io_init(r, lws_accept_cb, fd, EV_READ);\n-\tev_io_init(w, lws_accept_cb, fd, EV_WRITE);\n+\twsi-\u003ew_read.context \u003d wsi-\u003econtext;\n+\twsi-\u003ew_write.context \u003d wsi-\u003econtext;\n+\n+\tev_io_init(\u0026wsi-\u003ew_read.ev.watcher, lws_accept_cb, fd, EV_READ);\n+\tev_io_init(\u0026wsi-\u003ew_write.ev.watcher, lws_accept_cb, fd, EV_WRITE);\n }\n \n static void\ndiff --git a/lib/event-libs/libev/private.h b/lib/event-libs/libev/private.h\nindex 6ff8ba1..54e1b12 100644\n--- a/lib/event-libs/libev/private.h\n+++ b/lib/event-libs/libev/private.h\n@@ -25,6 +25,7 @@\n \n struct lws_pt_eventlibs_libev {\n \tstruct ev_loop *io_loop;\n+\tstruct ev_timer hrtimer;\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 bd56ea9..43dda05 100644\n--- a/lib/event-libs/libevent/libevent.c\n+++ b/lib/event-libs/libevent/libevent.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\ndiff --git a/lib/event-libs/libevent/private.h b/lib/event-libs/libevent/private.h\nindex 2c4de3e..347c7fe 100644\n--- a/lib/event-libs/libevent/private.h\n+++ b/lib/event-libs/libevent/private.h\n@@ -25,6 +25,7 @@\n \n struct lws_pt_eventlibs_libevent {\n \tstruct event_base *io_loop;\n+\tstruct event *hrtimer;\n };\n \n struct lws_io_watcher_libevent {\ndiff --git a/lib/event-libs/libuv/private.h b/lib/event-libs/libuv/private.h\nindex c7b46bd..173340e 100644\n--- a/lib/event-libs/libuv/private.h\n+++ b/lib/event-libs/libuv/private.h\n@@ -62,3 +62,5 @@ struct lws_signal_watcher_libuv {\n \n extern struct lws_event_loop_ops event_loop_ops_uv;\n \n+LWS_VISIBLE uv_loop_t *\n+lws_uv_getloop(struct lws_context *context, int tsi);\ndiff --git a/lib/event-libs/private.h b/lib/event-libs/private.h\nnew file mode 100644\nindex 0000000..59705c9\n--- /dev/null\n+++ b/lib/event-libs/private.h\n@@ -0,0 +1,74 @@\n+/*\n+ * libwebsockets - small server side websockets and web server implementation\n+ *\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+ * License as published by the Free Software Foundation:\n+ * version 2.1 of the License.\n+ *\n+ * This library is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n+ * Lesser General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU Lesser General Public\n+ * License along with this library; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,\n+ * MA 02110-1301 USA\n+ *\n+ * This is included from private-libwebsockets.h\n+ */\n+\n+struct lws_event_loop_ops {\n+\tconst char *name;\n+\t/* event loop-specific context init during context creation */\n+\tint (*init_context)(struct lws_context *context,\n+\t\t\t const struct lws_context_creation_info *info);\n+\t/* called during lws_destroy_context */\n+\tint (*destroy_context1)(struct lws_context *context);\n+\t/* called during lws_destroy_context2 */\n+\tint (*destroy_context2)(struct lws_context *context);\n+\t/* init vhost listening wsi */\n+\tint (*init_vhost_listen_wsi)(struct lws *wsi);\n+\t/* init the event loop for a pt */\n+\tint (*init_pt)(struct lws_context *context, void *_loop, int tsi);\n+\t/* called at end of first phase of close_free_wsi() */\n+\tint (*wsi_logical_close)(struct lws *wsi);\n+\t/* return nonzero if client connect not allowed */\n+\tint (*check_client_connect_ok)(struct lws *wsi);\n+\t/* close handle manually */\n+\tvoid (*close_handle_manually)(struct lws *wsi);\n+\t/* event loop accept processing */\n+\tvoid (*accept)(struct lws *wsi);\n+\t/* control wsi active events */\n+\tvoid (*io)(struct lws *wsi, int flags);\n+\t/* run the event loop for a pt */\n+\tvoid (*run_pt)(struct lws_context *context, int tsi);\n+\t/* called before pt is destroyed */\n+\tvoid (*destroy_pt)(struct lws_context *context, int tsi);\n+\t/* called just before wsi is freed */\n+\tvoid (*destroy_wsi)(struct lws *wsi);\n+\n+\tunsigned int periodic_events_available:1;\n+};\n+\n+/* bring in event libs private declarations */\n+\n+#if defined(LWS_WITH_POLL)\n+#include \u0022event-libs/poll/private.h\u0022\n+#endif\n+\n+#if defined(LWS_WITH_LIBUV)\n+#include \u0022event-libs/libuv/private.h\u0022\n+#endif\n+\n+#if defined(LWS_WITH_LIBEVENT)\n+#include \u0022event-libs/libevent/private.h\u0022\n+#endif\n+\n+#if defined(LWS_WITH_LIBEV)\n+#include \u0022event-libs/libev/private.h\u0022\n+#endif\n+\ndiff --git a/lib/libwebsockets.c b/lib/libwebsockets.c\nindex 9f7ce8e..af4ca2f 100644\n--- a/lib/libwebsockets.c\n+++ b/lib/libwebsockets.c\n@@ -574,13 +574,14 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *\n \t * must go through and close all those first\n \t */\n \tif (wsi-\u003evhost) {\n-\t\tlws_vhost_lock(wsi-\u003evhost);\n+\t\tif ((int)reason !\u003d -1)\n+\t\t\tlws_vhost_lock(wsi-\u003evhost);\n \t\tlws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,\n \t\t\t\t\twsi-\u003edll_client_transaction_queue_head.next) {\n \t\t\tstruct lws *w \u003d lws_container_of(d, struct lws,\n \t\t\t\t\t\t\t dll_client_transaction_queue);\n \n-\t\t\t__lws_close_free_wsi(w, reason, \u0022trans q leader closing\u0022);\n+\t\t\t__lws_close_free_wsi(w, -1, \u0022trans q leader closing\u0022);\n \t\t} lws_end_foreach_dll_safe(d, d1);\n \n \t\t/*\n@@ -592,7 +593,8 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *\n \t\t * queue leader is closing.\n \t\t */\n \t\tlws_dll_lws_remove(\u0026wsi-\u003edll_client_transaction_queue);\n-\t\tlws_vhost_unlock(wsi-\u003evhost);\n+\t\tif ((int)reason !\u003d-1)\n+\t\t\tlws_vhost_unlock(wsi-\u003evhost);\n \t}\n #endif\n \n@@ -1030,6 +1032,7 @@ lws_buflist_use_segment(struct lws_buflist **head, size_t len)\n void\n lws_buflist_describe(struct lws_buflist **head, void *id)\n {\n+\tstruct lws_buflist *old;\n \tint n \u003d 0;\n \n \tif (*head \u003d\u003d NULL)\n@@ -1040,7 +1043,12 @@ lws_buflist_describe(struct lws_buflist **head, void *id)\n \t\t\t (unsigned long long)(*head)-\u003epos,\n \t\t\t (unsigned long long)(*head)-\u003elen,\n \t\t\t (unsigned long long)(*head)-\u003elen - (*head)-\u003epos);\n+\t\told \u003d *head;\n \t\thead \u003d \u0026((*head)-\u003enext);\n+\t\tif (*head \u003d\u003d old) {\n+\t\t\tlwsl_err(\u0022%s: next points to self\u005cn\u0022, __func__);\n+\t\t\tbreak;\n+\t\t}\n \t\tn++;\n \t}\n }\ndiff --git a/lib/libwebsockets.h b/lib/libwebsockets.h\nindex d97ca4a..3ccb4a7 100644\n--- a/lib/libwebsockets.h\n+++ b/lib/libwebsockets.h\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@@ -4606,7 +4606,7 @@ lws_plat_recommended_rsa_bits(void);\n * cleanly and at the moment all of its libuv objects have completed close.\n */\n \n-LWS_VISIBLE uv_loop_t *\n+LWS_VISIBLE LWS_EXTERN uv_loop_t *\n lws_uv_getloop(struct lws_context *context, int tsi);\n \n LWS_VISIBLE LWS_EXTERN void\ndiff --git a/lib/plat/lws-plat-unix.c b/lib/plat/lws-plat-unix.c\nindex 80b43b1..8ace475 100644\n--- a/lib/plat/lws-plat-unix.c\n+++ b/lib/plat/lws-plat-unix.c\n@@ -57,8 +57,6 @@ lws_plat_pipe_signal(struct lws *wsi)\n \n \tn \u003d write(pt-\u003edummy_pipe_fds[1], \u0026buf, 1);\n \n-\tlwsl_debug(\u0022%s: fd %d %d\u005cn\u0022, __func__, pt-\u003edummy_pipe_fds[1], n);\n-\n \treturn n !\u003d 1;\n }\n \ndiff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h\nindex 2aafdeb..d731c18 100644\n--- a/lib/private-libwebsockets.h\n+++ b/lib/private-libwebsockets.h\n@@ -374,210 +374,11 @@ enum lws_ssl_capable_status {\n \n /*\n *\n- * ------ role ------\n+ * ------ roles ------\n *\n */\n \n-typedef uint32_t lws_wsi_state_t;\n-\n-/*\n- * The wsi-\u003erole_ops pointer decides almost everything about what role the wsi\n- * will play, h2, raw, ws, etc.\n- *\n- * However there are a few additional flags needed that vary, such as if the\n- * role is a client or server side, if it has that concept. And the connection\n- * fulfilling the role, has a separate dynamic state.\n- *\n- * 31 16 15 0\n- * [ role flags ] [ state ]\n- *\n- * The role flags part is generally invariant for the lifetime of the wsi,\n- * although it can change if the connection role itself does, eg, if the\n- * connection upgrades from H1 -\u003e WS1 the role flags may be changed at that\n- * point.\n- *\n- * The state part reflects the dynamic connection state, and the states are\n- * reused between roles.\n- *\n- * None of the internal role or state representations are made available outside\n- * of lws internals. Even for lws internals, if you add stuff here, please keep\n- * the constants inside this header only by adding necessary helpers here and\n- * use the helpers in the actual code. This is to ease any future refactors.\n- *\n- * Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our\n- * data as a stream inside a different protocol.\n- */\n-\n-#define _RS 16\n-\n-#define LWSIFR_CLIENT\t\t(0x1000 \u003c\u003c _RS) /* client side */\n-#define LWSIFR_SERVER\t\t(0x2000 \u003c\u003c _RS) /* server side */\n-\n-#define LWSIFR_P_ENCAP_H2\t(0x0100 \u003c\u003c _RS) /* we are encapsulated by h2 */\n-\n-enum lwsi_role {\n-\tLWSI_ROLE_MASK\t\t\u003d\t\t\t (0xffff \u003c\u003c _RS),\n-\tLWSI_ROLE_ENCAP_MASK\t\u003d\t\t\t (0x0f00 \u003c\u003c _RS),\n-};\n-\n-#define lwsi_role(wsi) (wsi-\u003ewsistate \u0026 LWSI_ROLE_MASK)\n-#if !defined (_DEBUG)\n-#define lwsi_set_role(wsi, role) wsi-\u003ewsistate \u003d \u005c\n-\t\t\t\t(wsi-\u003ewsistate \u0026 (~LWSI_ROLE_MASK)) | role\n-#else\n-void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);\n-#endif\n-\n-#define lwsi_role_client(wsi) (!!(wsi-\u003ewsistate \u0026 LWSIFR_CLIENT))\n-#define lwsi_role_server(wsi) (!!(wsi-\u003ewsistate \u0026 LWSIFR_SERVER))\n-#define lwsi_role_h2_ENCAPSULATION(wsi) \u005c\n-\t\t((wsi-\u003ewsistate \u0026 LWSI_ROLE_ENCAP_MASK) \u003d\u003d LWSIFR_P_ENCAP_H2)\n-\n-/* Pollout wants a callback in this state */\n-#define LWSIFS_POCB\t\t(0x100)\n-/* Before any protocol connection was established */\n-#define LWSIFS_NOT_EST\t\t(0x200)\n-\n-enum lwsi_state {\n-\n-\t/* Phase 1: pre-transport */\n-\n-\tLRS_UNCONNECTED\t\t\t\t\u003d LWSIFS_NOT_EST | 0,\n-\tLRS_WAITING_CONNECT\t\t\t\u003d LWSIFS_NOT_EST | 1,\n-\n-\t/* Phase 2: establishing intermediaries on top of transport */\n-\n-\tLRS_WAITING_PROXY_REPLY\t\t\t\u003d LWSIFS_NOT_EST | 2,\n-\tLRS_WAITING_SSL\t\t\t\t\u003d LWSIFS_NOT_EST | 3,\n-\tLRS_WAITING_SOCKS_GREETING_REPLY\t\u003d LWSIFS_NOT_EST | 4,\n-\tLRS_WAITING_SOCKS_CONNECT_REPLY\t\t\u003d LWSIFS_NOT_EST | 5,\n-\tLRS_WAITING_SOCKS_AUTH_REPLY\t\t\u003d LWSIFS_NOT_EST | 6,\n-\n-\t/* Phase 3: establishing tls tunnel */\n-\n-\tLRS_SSL_INIT\t\t\t\t\u003d LWSIFS_NOT_EST | 7,\n-\tLRS_SSL_ACK_PENDING\t\t\t\u003d LWSIFS_NOT_EST | 8,\n-\tLRS_PRE_WS_SERVING_ACCEPT\t\t\u003d LWSIFS_NOT_EST | 9,\n-\n-\t/* Phase 4: connected */\n-\n-\tLRS_WAITING_SERVER_REPLY\t\t\u003d LWSIFS_NOT_EST | 10,\n-\tLRS_H2_AWAIT_PREFACE\t\t\t\u003d LWSIFS_NOT_EST | 11,\n-\tLRS_H2_AWAIT_SETTINGS\t\t\t\u003d LWSIFS_NOT_EST |\n-\t\t\t\t\t\t LWSIFS_POCB | 12,\n-\n-\t/* Phase 5: protocol logically established */\n-\n-\tLRS_H2_CLIENT_SEND_SETTINGS\t\t\u003d LWSIFS_POCB | 13,\n-\tLRS_H2_WAITING_TO_SEND_HEADERS\t\t\u003d LWSIFS_POCB | 14,\n-\tLRS_DEFERRING_ACTION\t\t\t\u003d LWSIFS_POCB | 15,\n-\tLRS_IDLING\t\t\t\t\u003d 16,\n-\tLRS_H1C_ISSUE_HANDSHAKE\t\t\t\u003d 17,\n-\tLRS_H1C_ISSUE_HANDSHAKE2\t\t\u003d 18,\n-\tLRS_ISSUE_HTTP_BODY\t\t\t\u003d 19,\n-\tLRS_ISSUING_FILE\t\t\t\u003d 20,\n-\tLRS_HEADERS\t\t\t\t\u003d 21,\n-\tLRS_BODY\t\t\t\t\u003d 22,\n-\tLRS_ESTABLISHED\t\t\t\t\u003d LWSIFS_POCB | 23,\n-\n-\t/* Phase 6: finishing */\n-\n-\tLRS_WAITING_TO_SEND_CLOSE\t\t\u003d LWSIFS_POCB | 24,\n-\tLRS_RETURNED_CLOSE\t\t\t\u003d LWSIFS_POCB | 25,\n-\tLRS_AWAITING_CLOSE_ACK\t\t\t\u003d LWSIFS_POCB | 26,\n-\tLRS_FLUSHING_BEFORE_CLOSE\t\t\u003d LWSIFS_POCB | 27,\n-\tLRS_SHUTDOWN\t\t\t\t\u003d 28,\n-\n-\t/* Phase 7: dead */\n-\n-\tLRS_DEAD_SOCKET\t\t\t\t\u003d 29,\n-\n-\tLRS_MASK\t\t\t\t\u003d 0xffff\n-};\n-\n-#define lwsi_state(wsi) ((enum lwsi_state)(wsi-\u003ewsistate \u0026 LRS_MASK))\n-#define lwsi_state_PRE_CLOSE(wsi) ((enum lwsi_state)(wsi-\u003ewsistate_pre_close \u0026 LRS_MASK))\n-#define lwsi_state_est(wsi) (!(wsi-\u003ewsistate \u0026 LWSIFS_NOT_EST))\n-#define lwsi_state_est_PRE_CLOSE(wsi) (!(wsi-\u003ewsistate_pre_close \u0026 LWSIFS_NOT_EST))\n-#define lwsi_state_can_handle_POLLOUT(wsi) (wsi-\u003ewsistate \u0026 LWSIFS_POCB)\n-#if !defined (_DEBUG)\n-#define lwsi_set_state(wsi, lrs) wsi-\u003ewsistate \u003d \u005c\n-\t\t\t (wsi-\u003ewsistate \u0026 (~LRS_MASK)) | lrs\n-#else\n-void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);\n-#endif\n-\n-/*\n- * internal role-specific ops\n- */\n-struct lws_context_per_thread;\n-struct lws_role_ops {\n-\tconst char *name;\n-\tconst char *alpn;\n-\t/*\n-\t * After http headers have parsed, this is the last chance for a role\n-\t * to upgrade the connection to something else using the headers.\n-\t * ws-over-h2 is upgraded from h2 like this.\n-\t */\n-\tint (*check_upgrades)(struct lws *wsi);\n-\t/* role-specific context init during context creation */\n-\tint (*init_context)(struct lws_context *context,\n-\t\t\t const struct lws_context_creation_info *info);\n-\t/* role-specific per-vhost init during vhost creation */\n-\tint (*init_vhost)(struct lws_vhost *vh,\n-\t\t\t const struct lws_context_creation_info *info);\n-\t/* role-specific per-vhost destructor during vhost destroy */\n-\tint (*destroy_vhost)(struct lws_vhost *vh);\n-\t/* generic 1Hz callback for the role itself */\n-\tint (*periodic_checks)(struct lws_context *context, int tsi,\n-\t\t\t time_t now);\n-\t/* chance for the role to force POLLIN without network activity */\n-\tint (*service_flag_pending)(struct lws_context *context, int tsi);\n-\t/* an fd using this role has POLLIN signalled */\n-\tint (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,\n-\t\t\t struct lws_pollfd *pollfd);\n-\t/* an fd using the role wanted a POLLOUT callback and now has it */\n-\tint (*handle_POLLOUT)(struct lws *wsi);\n-\t/* perform user pollout */\n-\tint (*perform_user_POLLOUT)(struct lws *wsi);\n-\t/* do effective callback on writeable */\n-\tint (*callback_on_writable)(struct lws *wsi);\n-\t/* connection-specific tx credit in bytes */\n-\tlws_fileofs_t (*tx_credit)(struct lws *wsi);\n-\t/* role-specific write formatting */\n-\tint (*write_role_protocol)(struct lws *wsi, unsigned char *buf,\n-\t\t\t\t size_t len, enum lws_write_protocol *wp);\n-\n-\t/* get encapsulation parent */\n-\tstruct lws * (*encapsulation_parent)(struct lws *wsi);\n-\n-\t/* role-specific destructor */\n-\tint (*alpn_negotiated)(struct lws *wsi, const char *alpn);\n-\n-\t/* chance for the role to handle close in the protocol */\n-\tint (*close_via_role_protocol)(struct lws *wsi,\n-\t\t\t\t enum lws_close_status reason);\n-\t/* role-specific close processing */\n-\tint (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);\n-\t/* role-specific connection close processing */\n-\tint (*close_kill_connection)(struct lws *wsi,\n-\t\t\t\t enum lws_close_status reason);\n-\t/* role-specific destructor */\n-\tint (*destroy_role)(struct lws *wsi);\n-\n-\t/*\n-\t * the callback reasons for WRITEABLE for client, server\n-\t * (just client applies if no concept of client or server)\n-\t */\n-\tuint16_t writeable_cb[2];\n-\t/*\n-\t * the callback reasons for CLOSE for client, server\n-\t * (just client applies if no concept of client or server)\n-\t */\n-\tuint16_t close_cb[2];\n-\n-\tunsigned int file_handle:1; /* role operates on files not sockets */\n-};\n+#include \u0022roles/private.h\u0022\n \n /* null-terminated array of pointers to roles lws built with */\n extern const struct lws_role_ops *available_roles[];\n@@ -589,113 +390,13 @@ extern const struct lws_role_ops *available_roles[];\n \n #define LWS_FOR_EVERY_AVAILABLE_ROLE_END }}\n \n-/* core roles */\n-extern struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, role_ops_listen,\n-\t\t\t role_ops_pipe;\n-\n-/* bring in role private declarations */\n-\n-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n- #include \u0022roles/http/private.h\u0022\n-#else\n- #define lwsi_role_http(wsi) (0)\n-#endif\n-\n-#if defined(LWS_ROLE_H1)\n- #include \u0022roles/h1/private.h\u0022\n-#else\n- #define lwsi_role_h1(wsi) (0)\n-#endif\n-\n-#if defined(LWS_ROLE_H2)\n- #include \u0022roles/h2/private.h\u0022\n-#else\n- #define lwsi_role_h2(wsi) (0)\n-#endif\n-\n-#if defined(LWS_ROLE_WS)\n- #include \u0022roles/ws/private.h\u0022\n-#else\n- #define lwsi_role_ws(wsi) (0)\n-#endif\n-\n-#if defined(LWS_ROLE_CGI)\n- #include \u0022roles/cgi/private.h\u0022\n-#else\n- #define lwsi_role_cgi(wsi) (0)\n-#endif\n-\n-enum {\n-\tLWS_HP_RET_BAIL_OK,\n-\tLWS_HP_RET_BAIL_DIE,\n-\tLWS_HP_RET_USER_SERVICE,\n-\n-\tLWS_HPI_RET_WSI_ALREADY_DIED,\t/* we closed it */\n-\tLWS_HPI_RET_HANDLED,\t\t/* no probs */\n-\tLWS_HPI_RET_PLEASE_CLOSE_ME,\t/* close it for us */\n-\n-\tLWS_UPG_RET_DONE,\n-\tLWS_UPG_RET_CONTINUE,\n-\tLWS_UPG_RET_BAIL\n-};\n-\n /*\n *\n * ------ event_loop ops ------\n *\n */\n \n-struct lws_event_loop_ops {\n-\tconst char *name;\n-\t/* event loop-specific context init during context creation */\n-\tint (*init_context)(struct lws_context *context,\n-\t\t\t const struct lws_context_creation_info *info);\n-\t/* called during lws_destroy_context */\n-\tint (*destroy_context1)(struct lws_context *context);\n-\t/* called during lws_destroy_context2 */\n-\tint (*destroy_context2)(struct lws_context *context);\n-\t/* init vhost listening wsi */\n-\tint (*init_vhost_listen_wsi)(struct lws *wsi);\n-\t/* init the event loop for a pt */\n-\tint (*init_pt)(struct lws_context *context, void *_loop, int tsi);\n-\t/* called at end of first phase of close_free_wsi() */\n-\tint (*wsi_logical_close)(struct lws *wsi);\n-\t/* return nonzero if client connect not allowed */\n-\tint (*check_client_connect_ok)(struct lws *wsi);\n-\t/* close handle manually */\n-\tvoid (*close_handle_manually)(struct lws *wsi);\n-\t/* event loop accept processing */\n-\tvoid (*accept)(struct lws *wsi);\n-\t/* control wsi active events */\n-\tvoid (*io)(struct lws *wsi, int flags);\n-\t/* run the event loop for a pt */\n-\tvoid (*run_pt)(struct lws_context *context, int tsi);\n-\t/* called before pt is destroyed */\n-\tvoid (*destroy_pt)(struct lws_context *context, int tsi);\n-\t/* called just before wsi is freed */\n-\tvoid (*destroy_wsi)(struct lws *wsi);\n-\n-\tunsigned int periodic_events_available:1;\n-};\n-\n-/* bring in event libs private declarations */\n-\n-#if defined(LWS_WITH_POLL)\n-#include \u0022event-libs/poll/private.h\u0022\n-#endif\n-\n-#if defined(LWS_WITH_LIBUV)\n-#include \u0022event-libs/libuv/private.h\u0022\n-#endif\n-\n-#if defined(LWS_WITH_LIBEVENT)\n-#include \u0022event-libs/libevent/private.h\u0022\n-#endif\n-\n-#if defined(LWS_WITH_LIBEV)\n-#include \u0022event-libs/libev/private.h\u0022\n-#endif\n-\n+#include \u0022event-libs/private.h\u0022\n \n /* enums of socks version */\n enum socks_version {\n@@ -774,8 +475,6 @@ struct lws_ring {\n struct lws_protocols;\n struct lws;\n \n-#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || defined(LWS_WITH_LIBEVENT)\n-\n struct lws_io_watcher {\n #ifdef LWS_WITH_LIBEV\n \tstruct lws_io_watcher_libev ev;\n@@ -803,7 +502,6 @@ struct lws_signal_watcher {\n #endif\n \tstruct lws_context *context;\n };\n-#endif\n \n #ifdef _WIN32\n #define LWS_FD_HASH(fd) ((fd ^ (fd \u003e\u003e 8) ^ (fd \u003e\u003e 16)) % FD_HASHTABLE_MODULUS)\ndiff --git a/lib/roles/README.md b/lib/roles/README.md\nindex 0e3a01c..7e71268 100644\n--- a/lib/roles/README.md\n+++ b/lib/roles/README.md\n@@ -66,7 +66,7 @@ However when the declarations must be accessible to other things in lws build, e\n the role adds members to `struct lws` when enabled, they should be in the role\n directory in a file `private.h`.\n \n-Search for \u0022bring in role private declarations\u0022 in `./lib/private-libwebsockets.h\n+Search for \u0022bring in role private declarations\u0022 in `./lib/roles/private.h\n and add your private role file there following the style used for the other roles,\n eg,\n \ndiff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c\nindex 0cde99d..0f14264 100644\n--- a/lib/roles/h1/ops-h1.c\n+++ b/lib/roles/h1/ops-h1.c\n@@ -314,11 +314,17 @@ lws_h1_server_socket_service(struct lws *wsi, struct lws_pollfd *pollfd)\n \t\t\tgoto try_pollout;\n \t\t}\n \n+\t\t/*\n+\t\t * We got here because there was specifically POLLIN...\n+\t\t * regardless of our buflist state, we need to get it,\n+\t\t * and either use it, or append to the buflist and use\n+\t\t * buflist head material.\n+\t\t */\n+\n \t\tbuffered \u003d lws_buflist_aware_read(pt, wsi, \u0026ebuf);\n \t\tswitch (ebuf.len) {\n \t\tcase 0:\n-\t\t\tlwsl_info(\u0022%s: read 0 len a\u005cn\u0022,\n-\t\t\t\t __func__);\n+\t\t\tlwsl_info(\u0022%s: read 0 len a\u005cn\u0022, __func__);\n \t\t\twsi-\u003eseen_zero_length_recv \u003d 1;\n \t\t\tlws_change_pollfd(wsi, LWS_POLLIN, 0);\n \t\t\tgoto try_pollout;\ndiff --git a/lib/roles/h2/ops-h2.c b/lib/roles/h2/ops-h2.c\nindex f10f7c9..208342f 100644\n--- a/lib/roles/h2/ops-h2.c\n+++ b/lib/roles/h2/ops-h2.c\n@@ -279,11 +279,19 @@ drain:\n \t\t\t\tlws_dll_lws_remove(\u0026wsi-\u003edll_buflist);\n \t\t\t}\n \t\t} else\n-\t\t\tif (n !\u003d ebuf.len \u0026\u0026\n-\t\t\t lws_buflist_append_segment(\u0026wsi-\u003ebuflist,\n+\t\t\tif (n !\u003d ebuf.len) {\n+\t\t\t\tm \u003d lws_buflist_append_segment(\u0026wsi-\u003ebuflist,\n \t\t\t\t\t\t(uint8_t *)ebuf.token + n,\n-\t\t\t\t\t\tebuf.len - n) \u003c 0)\n-\t\t\t\treturn LWS_HPI_RET_PLEASE_CLOSE_ME;\n+\t\t\t\t\t\tebuf.len - n);\n+\t\t\t\tif (m \u003c 0)\n+\t\t\t\t\treturn LWS_HPI_RET_PLEASE_CLOSE_ME;\n+\t\t\t\tif (m) {\n+\t\t\t\t\tlwsl_debug(\u0022%s: added %p to rxflow list\u005cn\u0022,\n+\t\t\t\t\t\t\t__func__, wsi);\n+\t\t\t\t\tlws_dll_lws_add_front(\u0026wsi-\u003edll_buflist,\n+\t\t\t\t\t\t\t\u0026pt-\u003edll_head_buflist);\n+\t\t\t\t}\n+\t\t\t}\n \t}\n \n \t// lws_buflist_describe(\u0026wsi-\u003ebuflist, wsi);\ndiff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c\nindex 6455a1c..c4b61bc 100644\n--- a/lib/roles/http/client/client-handshake.c\n+++ b/lib/roles/http/client/client-handshake.c\n@@ -123,10 +123,11 @@ lws_client_connect_2(struct lws *wsi)\n \t\t\t}\n #endif\n \n-\t\t\tlwsl_info(\u0022applying %p to txn queue on %p (wsistate 0x%x)\u005cn\u0022, wsi, w,\n-\t\t\t\tw-\u003ewsistate);\n+\t\t\tlwsl_info(\u0022applying %p to txn queue on %p (wsistate 0x%x)\u005cn\u0022,\n+\t\t\t\twsi, w, w-\u003ewsistate);\n \t\t\t/*\n \t\t\t * ...let's add ourselves to his transaction queue...\n+\t\t\t * we are adding ourselves at the HEAD\n \t\t\t */\n \t\t\tlws_dll_lws_add_front(\u0026wsi-\u003edll_client_transaction_queue,\n \t\t\t\t\u0026w-\u003edll_client_transaction_queue_head);\n@@ -522,12 +523,15 @@ send_hs:\n \t\t * LRS_H1C_ISSUE_HANDSHAKE2, and let them write.\n \t\t *\n \t\t * If we are trying to do this too early, before the master\n-\t\t * connection has written his own headers,\n+\t\t * connection has written his own headers, then it will just\n+\t\t * wait in the queue until it's possible to send them.\n \t\t */\n \t\tlws_callback_on_writable(wsi_piggyback);\n-\t\tlwsl_info(\u0022wsi %p: waiting to send headers\u005cn\u0022, wsi);\n+\t\tlwsl_info(\u0022%s: wsi %p: waiting to send headers (parent state %x)\u005cn\u0022,\n+\t\t\t __func__, wsi, lwsi_state(wsi_piggyback));\n \t} else {\n-\t\tlwsl_info(\u0022wsi %p: client creating own connection\u005cn\u0022, wsi);\n+\t\tlwsl_info(\u0022%s: wsi %p: client creating own connection\u005cn\u0022,\n+\t\t\t __func__, wsi);\n \n \t\t/* we are making our own connection */\n \t\tlwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE);\ndiff --git a/lib/roles/http/client/client.c b/lib/roles/http/client/client.c\nindex 1a1a27c..1a61e62 100644\n--- a/lib/roles/http/client/client.c\n+++ b/lib/roles/http/client/client.c\n@@ -29,24 +29,26 @@ lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)\n \n /*\n * return self, or queued client wsi we are acting on behalf of\n+ *\n+ * That is the TAIL of the queue (new queue elements are added at the HEAD)\n */\n \n struct lws *\n lws_client_wsi_effective(struct lws *wsi)\n {\n-\tstruct lws *wsi_eff \u003d wsi;\n-\tstruct lws_dll_lws *d;\n+\tstruct lws_dll_lws *tail \u003d NULL;\n \n \tif (!wsi-\u003etransaction_from_pipeline_queue ||\n \t !wsi-\u003edll_client_transaction_queue_head.next)\n \t\treturn wsi;\n \n-\td \u003d wsi-\u003edll_client_transaction_queue_head.next;\n-\tif (d)\n-\t\twsi_eff \u003d lws_container_of(d, struct lws,\n-\t\t\t\t\tdll_client_transaction_queue);\n+\tlws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,\n+\t\t\t\t wsi-\u003edll_client_transaction_queue_head.next) {\n+\t\ttail \u003d d;\n+\t} lws_end_foreach_dll_safe(d, d1);\n \n-\treturn wsi_eff;\n+\treturn lws_container_of(tail, struct lws,\n+\t\t\t\t dll_client_transaction_queue);\n }\n \n /*\n@@ -97,34 +99,40 @@ lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,\n \tif ((pollfd-\u003erevents \u0026 LWS_POLLOUT) \u0026\u0026\n \t wsi-\u003ekeepalive_active \u0026\u0026\n \t wsi-\u003edll_client_transaction_queue_head.next) {\n-\t\tint found \u003d 0;\n+\t\tstruct lws *wfound \u003d NULL;\n \n \t\tlwsl_debug(\u0022%s: pollout HANDSHAKE2\u005cn\u0022, __func__);\n \n-\t\t/* we have a transaction queue that wants to pipeline */\n+\t\t/*\n+\t\t * We have a transaction queued that wants to pipeline.\n+\t\t *\n+\t\t * We have to allow it to send headers strictly in the order\n+\t\t * that it was queued, ie, tail-first.\n+\t\t */\n \t\tlws_vhost_lock(wsi-\u003evhost);\n \t\tlws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,\n \t\t\t\t\t wsi-\u003edll_client_transaction_queue_head.next) {\n \t\t\tstruct lws *w \u003d lws_container_of(d, struct lws,\n \t\t\t\t\t\t dll_client_transaction_queue);\n \n-\t\t\tlwsl_notice(\u0022%s: %p states 0x%x\u005cn\u0022, __func__, w, w-\u003ewsistate);\n-\t\t\tif (lwsi_state(w) \u003d\u003d LRS_H1C_ISSUE_HANDSHAKE2) {\n-\t\t\t\t/*\n-\t\t\t\t * pollfd has the master sockfd in it... we\n-\t\t\t\t * need to use that in HANDSHAKE2 to understand\n-\t\t\t\t * which wsi to actually write on\n-\t\t\t\t */\n-\t\t\t\tlws_client_socket_service(w, pollfd, wsi);\n-\t\t\t\tlws_callback_on_writable(wsi);\n-\t\t\t\tfound \u003d 1;\n-\t\t\t\tbreak;\n-\t\t\t}\n+\t\t\tlwsl_debug(\u0022%s: %p states 0x%x\u005cn\u0022, __func__, w, w-\u003ewsistate);\n+\t\t\tif (lwsi_state(w) \u003d\u003d LRS_H1C_ISSUE_HANDSHAKE2)\n+\t\t\t\twfound \u003d w;\n \t\t} lws_end_foreach_dll_safe(d, d1);\n-\t\tlws_vhost_unlock(wsi-\u003evhost);\n \n-\t\tif (!found)\n-\t\t\tlwsl_err(\u0022%s: didn't find anything in HS2\u005cn\u0022, __func__);\n+\t\tif (wfound) {\n+\t\t\t/*\n+\t\t\t * pollfd has the master sockfd in it... we\n+\t\t\t * need to use that in HANDSHAKE2 to understand\n+\t\t\t * which wsi to actually write on\n+\t\t\t */\n+\t\t\tlws_client_socket_service(wfound, pollfd, wsi);\n+\t\t\tlws_callback_on_writable(wsi);\n+\t\t} else\n+\t\t\tlwsl_debug(\u0022%s: didn't find anything in txn q in HS2\u005cn\u0022,\n+\t\t\t\t\t\t\t __func__);\n+\n+\t\tlws_vhost_unlock(wsi-\u003evhost);\n \n \t\treturn 0;\n \t}\ndiff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c\nindex 2f2224f..8616b23 100644\n--- a/lib/roles/http/server/server.c\n+++ b/lib/roles/http/server/server.c\n@@ -1342,7 +1342,7 @@ deal_body:\n \t\t\t */\n \n \t\t\twhile (1) {\n-\t\t\t\tebuf.len \u003d lws_buflist_next_segment_len(\n+\t\t\t\tebuf.len \u003d (int)lws_buflist_next_segment_len(\n \t\t\t\t\t\t\u0026wsi-\u003ebuflist, (uint8_t **)\u0026ebuf.token);\n \t\t\t\tif (!ebuf.len)\n \t\t\t\t\tbreak;\n@@ -1789,7 +1789,8 @@ lws_http_transaction_completed(struct lws *wsi)\n \t\t\t}\n #endif\n \t\t} else {\n-\t\t\tlwsl_debug(\u0022%s: resetting and keeping ah as more pipeline stuff available\u005cn\u0022, __func__);\n+\t\t\tlwsl_debug(\u0022%s: resetting and keeping ah as pipeline\u005cn\u0022,\n+\t\t\t\t __func__);\n \t\t\tlws_header_table_reset(wsi, 0);\n \t\t\t/*\n \t\t\t * If we kept the ah, we should restrict the amount\n@@ -1804,13 +1805,12 @@ lws_http_transaction_completed(struct lws *wsi)\n \t\tif (wsi-\u003ehttp.ah)\n \t\t\twsi-\u003ehttp.ah-\u003eues \u003d URIES_IDLE;\n \n-\t\tlwsi_set_state(wsi, LRS_ESTABLISHED);\n+\t\t//lwsi_set_state(wsi, LRS_ESTABLISHED);\n \t} else\n \t\tif (lws_buflist_next_segment_len(\u0026wsi-\u003ebuflist, NULL))\n \t\t\tif (lws_header_table_attach(wsi, 0))\n \t\t\t\tlwsl_debug(\u0022acquired ah\u005cn\u0022);\n \n-\n \tlwsl_info(\u0022%s: %p: keep-alive await new transaction\u005cn\u0022, __func__, wsi);\n \tlws_callback_on_writable(wsi);\n \n@@ -2063,6 +2063,7 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)\n {\n \tstruct lws_context_per_thread *pt;\n \tstruct lws_pollfd *pfd;\n+\tint n;\n \n \tif (!wsi)\n \t\treturn NULL;\n@@ -2070,8 +2071,13 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)\n \tif (!readbuf || len \u003d\u003d 0)\n \t\treturn wsi;\n \n-\tif (lws_buflist_append_segment(\u0026wsi-\u003ebuflist, (const uint8_t *)readbuf, len) \u003c 0)\n+\tpt \u003d \u0026wsi-\u003econtext-\u003ept[(int)wsi-\u003etsi];\n+\n+\tn \u003d lws_buflist_append_segment(\u0026wsi-\u003ebuflist, (const uint8_t *)readbuf, len);\n+\tif (n \u003c 0)\n \t\tgoto bail;\n+\tif (n)\n+\t\tlws_dll_lws_add_front(\u0026wsi-\u003edll_buflist, \u0026pt-\u003edll_head_buflist);\n \n \t/*\n \t * we can't process the initial read data until we can attach an ah.\n@@ -2086,7 +2092,6 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)\n \tif (wsi-\u003ehttp.ah || !lws_header_table_attach(wsi, 0)) {\n \n \t\tlwsl_notice(\u0022%s: calling service on readbuf ah\u005cn\u0022, __func__);\n-\t\tpt \u003d \u0026wsi-\u003econtext-\u003ept[(int)wsi-\u003etsi];\n \n \t\t/* unlike a normal connect, we have the headers already\n \t\t * (or the first part of them anyway).\ndiff --git a/lib/roles/private.h b/lib/roles/private.h\nnew file mode 100644\nindex 0000000..f13e14a\n--- /dev/null\n+++ b/lib/roles/private.h\n@@ -0,0 +1,273 @@\n+/*\n+ * libwebsockets - small server side websockets and web server implementation\n+ *\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+ * License as published by the Free Software Foundation:\n+ * version 2.1 of the License.\n+ *\n+ * This library is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n+ * Lesser General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU Lesser General Public\n+ * License along with this library; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,\n+ * MA 02110-1301 USA\n+ *\n+ * This is included from private-libwebsockets.h\n+ */\n+\n+typedef uint32_t lws_wsi_state_t;\n+\n+/*\n+ * The wsi-\u003erole_ops pointer decides almost everything about what role the wsi\n+ * will play, h2, raw, ws, etc.\n+ *\n+ * However there are a few additional flags needed that vary, such as if the\n+ * role is a client or server side, if it has that concept. And the connection\n+ * fulfilling the role, has a separate dynamic state.\n+ *\n+ * 31 16 15 0\n+ * [ role flags ] [ state ]\n+ *\n+ * The role flags part is generally invariant for the lifetime of the wsi,\n+ * although it can change if the connection role itself does, eg, if the\n+ * connection upgrades from H1 -\u003e WS1 the role flags may be changed at that\n+ * point.\n+ *\n+ * The state part reflects the dynamic connection state, and the states are\n+ * reused between roles.\n+ *\n+ * None of the internal role or state representations are made available outside\n+ * of lws internals. Even for lws internals, if you add stuff here, please keep\n+ * the constants inside this header only by adding necessary helpers here and\n+ * use the helpers in the actual code. This is to ease any future refactors.\n+ *\n+ * Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our\n+ * data as a stream inside a different protocol.\n+ */\n+\n+#define _RS 16\n+\n+#define LWSIFR_CLIENT\t\t(0x1000 \u003c\u003c _RS) /* client side */\n+#define LWSIFR_SERVER\t\t(0x2000 \u003c\u003c _RS) /* server side */\n+\n+#define LWSIFR_P_ENCAP_H2\t(0x0100 \u003c\u003c _RS) /* we are encapsulated by h2 */\n+\n+enum lwsi_role {\n+\tLWSI_ROLE_MASK\t\t\u003d\t\t\t (0xffff \u003c\u003c _RS),\n+\tLWSI_ROLE_ENCAP_MASK\t\u003d\t\t\t (0x0f00 \u003c\u003c _RS),\n+};\n+\n+#define lwsi_role(wsi) (wsi-\u003ewsistate \u0026 LWSI_ROLE_MASK)\n+#if !defined (_DEBUG)\n+#define lwsi_set_role(wsi, role) wsi-\u003ewsistate \u003d \u005c\n+\t\t\t\t(wsi-\u003ewsistate \u0026 (~LWSI_ROLE_MASK)) | role\n+#else\n+void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);\n+#endif\n+\n+#define lwsi_role_client(wsi) (!!(wsi-\u003ewsistate \u0026 LWSIFR_CLIENT))\n+#define lwsi_role_server(wsi) (!!(wsi-\u003ewsistate \u0026 LWSIFR_SERVER))\n+#define lwsi_role_h2_ENCAPSULATION(wsi) \u005c\n+\t\t((wsi-\u003ewsistate \u0026 LWSI_ROLE_ENCAP_MASK) \u003d\u003d LWSIFR_P_ENCAP_H2)\n+\n+/* Pollout wants a callback in this state */\n+#define LWSIFS_POCB\t\t(0x100)\n+/* Before any protocol connection was established */\n+#define LWSIFS_NOT_EST\t\t(0x200)\n+\n+enum lwsi_state {\n+\n+\t/* Phase 1: pre-transport */\n+\n+\tLRS_UNCONNECTED\t\t\t\t\u003d LWSIFS_NOT_EST | 0,\n+\tLRS_WAITING_CONNECT\t\t\t\u003d LWSIFS_NOT_EST | 1,\n+\n+\t/* Phase 2: establishing intermediaries on top of transport */\n+\n+\tLRS_WAITING_PROXY_REPLY\t\t\t\u003d LWSIFS_NOT_EST | 2,\n+\tLRS_WAITING_SSL\t\t\t\t\u003d LWSIFS_NOT_EST | 3,\n+\tLRS_WAITING_SOCKS_GREETING_REPLY\t\u003d LWSIFS_NOT_EST | 4,\n+\tLRS_WAITING_SOCKS_CONNECT_REPLY\t\t\u003d LWSIFS_NOT_EST | 5,\n+\tLRS_WAITING_SOCKS_AUTH_REPLY\t\t\u003d LWSIFS_NOT_EST | 6,\n+\n+\t/* Phase 3: establishing tls tunnel */\n+\n+\tLRS_SSL_INIT\t\t\t\t\u003d LWSIFS_NOT_EST | 7,\n+\tLRS_SSL_ACK_PENDING\t\t\t\u003d LWSIFS_NOT_EST | 8,\n+\tLRS_PRE_WS_SERVING_ACCEPT\t\t\u003d LWSIFS_NOT_EST | 9,\n+\n+\t/* Phase 4: connected */\n+\n+\tLRS_WAITING_SERVER_REPLY\t\t\u003d LWSIFS_NOT_EST | 10,\n+\tLRS_H2_AWAIT_PREFACE\t\t\t\u003d LWSIFS_NOT_EST | 11,\n+\tLRS_H2_AWAIT_SETTINGS\t\t\t\u003d LWSIFS_NOT_EST |\n+\t\t\t\t\t\t LWSIFS_POCB | 12,\n+\n+\t/* Phase 5: protocol logically established */\n+\n+\tLRS_H2_CLIENT_SEND_SETTINGS\t\t\u003d LWSIFS_POCB | 13,\n+\tLRS_H2_WAITING_TO_SEND_HEADERS\t\t\u003d LWSIFS_POCB | 14,\n+\tLRS_DEFERRING_ACTION\t\t\t\u003d LWSIFS_POCB | 15,\n+\tLRS_IDLING\t\t\t\t\u003d 16,\n+\tLRS_H1C_ISSUE_HANDSHAKE\t\t\t\u003d 17,\n+\tLRS_H1C_ISSUE_HANDSHAKE2\t\t\u003d 18,\n+\tLRS_ISSUE_HTTP_BODY\t\t\t\u003d 19,\n+\tLRS_ISSUING_FILE\t\t\t\u003d 20,\n+\tLRS_HEADERS\t\t\t\t\u003d 21,\n+\tLRS_BODY\t\t\t\t\u003d 22,\n+\tLRS_ESTABLISHED\t\t\t\t\u003d LWSIFS_POCB | 23,\n+\n+\t/* Phase 6: finishing */\n+\n+\tLRS_WAITING_TO_SEND_CLOSE\t\t\u003d LWSIFS_POCB | 24,\n+\tLRS_RETURNED_CLOSE\t\t\t\u003d LWSIFS_POCB | 25,\n+\tLRS_AWAITING_CLOSE_ACK\t\t\t\u003d LWSIFS_POCB | 26,\n+\tLRS_FLUSHING_BEFORE_CLOSE\t\t\u003d LWSIFS_POCB | 27,\n+\tLRS_SHUTDOWN\t\t\t\t\u003d 28,\n+\n+\t/* Phase 7: dead */\n+\n+\tLRS_DEAD_SOCKET\t\t\t\t\u003d 29,\n+\n+\tLRS_MASK\t\t\t\t\u003d 0xffff\n+};\n+\n+#define lwsi_state(wsi) ((enum lwsi_state)(wsi-\u003ewsistate \u0026 LRS_MASK))\n+#define lwsi_state_PRE_CLOSE(wsi) ((enum lwsi_state)(wsi-\u003ewsistate_pre_close \u0026 LRS_MASK))\n+#define lwsi_state_est(wsi) (!(wsi-\u003ewsistate \u0026 LWSIFS_NOT_EST))\n+#define lwsi_state_est_PRE_CLOSE(wsi) (!(wsi-\u003ewsistate_pre_close \u0026 LWSIFS_NOT_EST))\n+#define lwsi_state_can_handle_POLLOUT(wsi) (wsi-\u003ewsistate \u0026 LWSIFS_POCB)\n+#if !defined (_DEBUG)\n+#define lwsi_set_state(wsi, lrs) wsi-\u003ewsistate \u003d \u005c\n+\t\t\t (wsi-\u003ewsistate \u0026 (~LRS_MASK)) | lrs\n+#else\n+void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);\n+#endif\n+\n+/*\n+ * internal role-specific ops\n+ */\n+struct lws_context_per_thread;\n+struct lws_role_ops {\n+\tconst char *name;\n+\tconst char *alpn;\n+\t/*\n+\t * After http headers have parsed, this is the last chance for a role\n+\t * to upgrade the connection to something else using the headers.\n+\t * ws-over-h2 is upgraded from h2 like this.\n+\t */\n+\tint (*check_upgrades)(struct lws *wsi);\n+\t/* role-specific context init during context creation */\n+\tint (*init_context)(struct lws_context *context,\n+\t\t\t const struct lws_context_creation_info *info);\n+\t/* role-specific per-vhost init during vhost creation */\n+\tint (*init_vhost)(struct lws_vhost *vh,\n+\t\t\t const struct lws_context_creation_info *info);\n+\t/* role-specific per-vhost destructor during vhost destroy */\n+\tint (*destroy_vhost)(struct lws_vhost *vh);\n+\t/* generic 1Hz callback for the role itself */\n+\tint (*periodic_checks)(struct lws_context *context, int tsi,\n+\t\t\t time_t now);\n+\t/* chance for the role to force POLLIN without network activity */\n+\tint (*service_flag_pending)(struct lws_context *context, int tsi);\n+\t/* an fd using this role has POLLIN signalled */\n+\tint (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,\n+\t\t\t struct lws_pollfd *pollfd);\n+\t/* an fd using the role wanted a POLLOUT callback and now has it */\n+\tint (*handle_POLLOUT)(struct lws *wsi);\n+\t/* perform user pollout */\n+\tint (*perform_user_POLLOUT)(struct lws *wsi);\n+\t/* do effective callback on writeable */\n+\tint (*callback_on_writable)(struct lws *wsi);\n+\t/* connection-specific tx credit in bytes */\n+\tlws_fileofs_t (*tx_credit)(struct lws *wsi);\n+\t/* role-specific write formatting */\n+\tint (*write_role_protocol)(struct lws *wsi, unsigned char *buf,\n+\t\t\t\t size_t len, enum lws_write_protocol *wp);\n+\n+\t/* get encapsulation parent */\n+\tstruct lws * (*encapsulation_parent)(struct lws *wsi);\n+\n+\t/* role-specific destructor */\n+\tint (*alpn_negotiated)(struct lws *wsi, const char *alpn);\n+\n+\t/* chance for the role to handle close in the protocol */\n+\tint (*close_via_role_protocol)(struct lws *wsi,\n+\t\t\t\t enum lws_close_status reason);\n+\t/* role-specific close processing */\n+\tint (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);\n+\t/* role-specific connection close processing */\n+\tint (*close_kill_connection)(struct lws *wsi,\n+\t\t\t\t enum lws_close_status reason);\n+\t/* role-specific destructor */\n+\tint (*destroy_role)(struct lws *wsi);\n+\n+\t/*\n+\t * the callback reasons for WRITEABLE for client, server\n+\t * (just client applies if no concept of client or server)\n+\t */\n+\tuint16_t writeable_cb[2];\n+\t/*\n+\t * the callback reasons for CLOSE for client, server\n+\t * (just client applies if no concept of client or server)\n+\t */\n+\tuint16_t close_cb[2];\n+\n+\tunsigned int file_handle:1; /* role operates on files not sockets */\n+};\n+\n+/* core roles */\n+extern struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, role_ops_listen,\n+\t\t\t role_ops_pipe;\n+\n+/* bring in role private declarations */\n+\n+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n+ #include \u0022roles/http/private.h\u0022\n+#else\n+ #define lwsi_role_http(wsi) (0)\n+#endif\n+\n+#if defined(LWS_ROLE_H1)\n+ #include \u0022roles/h1/private.h\u0022\n+#else\n+ #define lwsi_role_h1(wsi) (0)\n+#endif\n+\n+#if defined(LWS_ROLE_H2)\n+ #include \u0022roles/h2/private.h\u0022\n+#else\n+ #define lwsi_role_h2(wsi) (0)\n+#endif\n+\n+#if defined(LWS_ROLE_WS)\n+ #include \u0022roles/ws/private.h\u0022\n+#else\n+ #define lwsi_role_ws(wsi) (0)\n+#endif\n+\n+#if defined(LWS_ROLE_CGI)\n+ #include \u0022roles/cgi/private.h\u0022\n+#else\n+ #define lwsi_role_cgi(wsi) (0)\n+#endif\n+\n+enum {\n+\tLWS_HP_RET_BAIL_OK,\n+\tLWS_HP_RET_BAIL_DIE,\n+\tLWS_HP_RET_USER_SERVICE,\n+\n+\tLWS_HPI_RET_WSI_ALREADY_DIED,\t/* we closed it */\n+\tLWS_HPI_RET_HANDLED,\t\t/* no probs */\n+\tLWS_HPI_RET_PLEASE_CLOSE_ME,\t/* close it for us */\n+\n+\tLWS_UPG_RET_DONE,\n+\tLWS_UPG_RET_CONTINUE,\n+\tLWS_UPG_RET_BAIL\n+};\ndiff --git a/lib/roles/ws/server-ws.c b/lib/roles/ws/server-ws.c\nindex 8327918..0d8a0b9 100644\n--- a/lib/roles/ws/server-ws.c\n+++ b/lib/roles/ws/server-ws.c\n@@ -568,7 +568,7 @@ lws_ws_frame_rest_is_payload(struct lws *wsi, uint8_t **buf, size_t len)\n {\n \tuint8_t *buffer \u003d *buf, mask[4];\n \tstruct lws_tokens ebuf;\n-\tunsigned int avail \u003d len;\n+\tunsigned int avail \u003d (unsigned int)len;\n #if !defined(LWS_WITHOUT_EXTENSIONS)\n \tunsigned int old_packet_length \u003d (int)wsi-\u003ews-\u003erx_packet_length;\n #endif\ndiff --git a/lib/service.c b/lib/service.c\nindex 291995c..0dd4b35 100644\n--- a/lib/service.c\n+++ b/lib/service.c\n@@ -351,33 +351,64 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi)\n \treturn timeout_ms;\n }\n \n-\n+/*\n+ * POLLIN said there is something... we must read it, and either use it; or\n+ * if other material already in the buflist append it and return the buflist\n+ * head material.\n+ */\n int\n lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi,\n \t\t struct lws_tokens *ebuf)\n {\n-\tebuf-\u003elen \u003d (int)lws_buflist_next_segment_len(\u0026wsi-\u003ebuflist,\n-\t\t\t\t\t\t (uint8_t **)\u0026ebuf-\u003etoken);\n-\tif (!ebuf-\u003elen) {\n-\t\tebuf-\u003etoken \u003d (char *)pt-\u003eserv_buf;\n-\t\tebuf-\u003elen \u003d lws_ssl_capable_read(wsi, pt-\u003eserv_buf,\n-\t\t\t\t\twsi-\u003econtext-\u003ept_serv_buf_size);\n+\tint n, prior \u003d (int)lws_buflist_next_segment_len(\u0026wsi-\u003ebuflist, NULL);\n+\n+\tebuf-\u003etoken \u003d (char *)pt-\u003eserv_buf;\n+\tebuf-\u003elen \u003d lws_ssl_capable_read(wsi, pt-\u003eserv_buf,\n+\t\t\t\t\t wsi-\u003econtext-\u003ept_serv_buf_size);\n+\n+\tif (ebuf-\u003elen \u003d\u003d LWS_SSL_CAPABLE_MORE_SERVICE \u0026\u0026 prior)\n+\t\tgoto get_from_buflist;\n \n-\t\t// if (ebuf-\u003elen \u003e 0)\n-\t\t//\tlwsl_hexdump_notice(ebuf-\u003etoken, ebuf-\u003elen);\n+\tif (ebuf-\u003elen \u003c\u003d 0)\n+\t\treturn 0;\n+\n+\t/* nothing in buflist already? Then just use what we read */\n+\n+\tif (!prior)\n+\t\treturn 0;\n+\n+\t/* stash what we read */\n \n-\t\treturn 0; /* fresh */\n+\tn \u003d lws_buflist_append_segment(\u0026wsi-\u003ebuflist, (uint8_t *)ebuf-\u003etoken,\n+\t\t\t\t ebuf-\u003elen);\n+\tif (n \u003c 0)\n+\t\treturn -1;\n+\tif (n) {\n+\t\tlwsl_debug(\u0022%s: added %p to rxflow list\u005cn\u0022, __func__, wsi);\n+\t\tlws_dll_lws_add_front(\u0026wsi-\u003edll_buflist, \u0026pt-\u003edll_head_buflist);\n \t}\n \n-\treturn 1; /* buffered */\n+\t/* get the first buflist guy in line */\n+\n+get_from_buflist:\n+\n+\tebuf-\u003elen \u003d (int)lws_buflist_next_segment_len(\u0026wsi-\u003ebuflist,\n+\t\t\t\t\t\t (uint8_t **)\u0026ebuf-\u003etoken);\n+\n+\treturn 1; /* came from buflist */\n }\n \n int\n lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used,\n \t\t\t int buffered)\n {\n+\tstruct lws_context_per_thread *pt \u003d \u0026wsi-\u003econtext-\u003ept[(int)wsi-\u003etsi];\n \tint m;\n \n+\t/* it's in the buflist; we didn't use any */\n+\n+\tif (!used \u0026\u0026 buffered)\n+\t\treturn 0;\n \n \tif (used \u0026\u0026 buffered) {\n \t\tm \u003d lws_buflist_use_segment(\u0026wsi-\u003ebuflist, used);\n@@ -394,10 +425,17 @@ lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used,\n \n \t/* any remainder goes on the buflist */\n \n-\tif (used !\u003d ebuf-\u003elen \u0026\u0026\n-\t lws_buflist_append_segment(\u0026wsi-\u003ebuflist, (uint8_t *)ebuf-\u003etoken +\n-\t\t\t\t\t used, ebuf-\u003elen - used) \u003c 0)\n-\t\treturn 1; /* OOM */\n+\tif (used !\u003d ebuf-\u003elen) {\n+\t\tm \u003d lws_buflist_append_segment(\u0026wsi-\u003ebuflist,\n+\t\t\t\t\t (uint8_t *)ebuf-\u003etoken + used,\n+\t\t\t\t\t ebuf-\u003elen - used);\n+\t\tif (m \u003c 0)\n+\t\t\treturn 1; /* OOM */\n+\t\tif (m) {\n+\t\t\tlwsl_debug(\u0022%s: added %p to rxflow list\u005cn\u0022, __func__, wsi);\n+\t\t\tlws_dll_lws_add_front(\u0026wsi-\u003edll_buflist, \u0026pt-\u003edll_head_buflist);\n+\t\t}\n+\t}\n \n \treturn 0;\n }\ndiff --git a/lwsws/main.c b/lwsws/main.c\nindex 1a89f85..fba948e 100644\n--- a/lwsws/main.c\n+++ b/lwsws/main.c\n@@ -316,9 +316,11 @@ int main(int argc, char **argv)\n \t}\n \n \tlws_context_destroy(context);\n-\n+\t(void)budget;\n+#if (UV_VERSION_MAJOR \u003e 0) // Travis...\n \twhile ((n \u003d uv_loop_close(\u0026loop)) \u0026\u0026 --budget)\n \t\tuv_run(\u0026loop, UV_RUN_ONCE);\n+#endif\n \n \tfprintf(stderr, \u0022lwsws exited cleanly: %d\u005cn\u0022, n);\n \ndiff --git a/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh b/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh\nindex af8a4bc..2da54b6 100755\n--- a/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh\n+++ b/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh\n@@ -33,9 +33,9 @@ wait $SPID 2\u003e/dev/null\n \n if [ -z \u0022$TRAVIS_OS_NAME\u0022 ] ; then\n \tSPID\u003d\u0022\u0022\n-\tspawn \u0022\u0022 $5/http-server/minimal-http-server-libuv $1/lws-minimal-http-server-libuv -s\n+\tspawn \u0022\u0022 $5/http-server/minimal-http-server-eventlib $1/lws-minimal-http-server-eventlib --uv -s\n \tdotest $1 $2 localhost-suv -l\n-\tspawn $SPID $5/http-server/minimal-http-server-libuv $1/lws-minimal-http-server-libuv -s\n+\tspawn $SPID $5/http-server/minimal-http-server-eventlib $1/lws-minimal-http-server-eventlib --uv -s\n \tdotest $1 $2 localhost-suv-h1 -l --h1\n \n \tkill $SPID 2\u003e/dev/null\ndiff --git a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c\nindex e7c8d07..19940ff 100644\n--- a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c\n+++ b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c\n@@ -94,7 +94,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason,\n \t\treturn 0; /* don't passthru */\n \n \tcase LWS_CALLBACK_COMPLETED_CLIENT_HTTP:\n-\t\tlwsl_user(\u0022LWS_CALLBACK_COMPLETED_CLIENT_HTTP %d\u005cn\u0022, u-\u003eindex);\n+\t\tlwsl_user(\u0022LWS_CALLBACK_COMPLETED_CLIENT_HTTP %p: idx %d\u005cn\u0022,\n+\t\t\t wsi, u-\u003eindex);\n \t\tclient_wsi[u-\u003eindex] \u003d NULL;\n \t\tif (++completed \u003d\u003d COUNT) {\n \t\t\tif (!failed)\n@@ -166,7 +167,7 @@ lws_try_client_connection(struct lws_client_connect_info *i, int m)\n \t\t\tinterrupted \u003d 1;\n \t\t}\n \t} else\n-\t\tlwsl_user(\u0022started connection %d\u005cn\u0022, m);\n+\t\tlwsl_user(\u0022started connection %p: idx %d\u005cn\u0022, client_wsi[m], m);\n }\n \n int main(int argc, const char **argv)\n@@ -201,7 +202,6 @@ int main(int argc, const char **argv)\n \tinfo.options \u003d LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;\n \tinfo.port \u003d CONTEXT_PORT_NO_LISTEN; /* we do not run any server */\n \tinfo.protocols \u003d protocols;\n-\tinfo.max_http_header_pool \u003d 20;\n \n #if defined(LWS_WITH_MBEDTLS)\n \t/*\n@@ -237,6 +237,9 @@ int main(int argc, const char **argv)\n \t\ti.address \u003d \u0022warmcat.com\u0022;\n \t}\n \n+\tif ((p \u003d lws_cmdline_option(argc, argv, \u0022--port\u0022)))\n+\t\ti.port \u003d atoi(p);\n+\n \ti.host \u003d i.address;\n \ti.origin \u003d i.address;\n \ti.method \u003d \u0022GET\u0022;\n@@ -267,7 +270,7 @@ int main(int argc, const char **argv)\n \t\t\t\tif (m \u003d\u003d (int)LWS_ARRAY_SIZE(client_wsi) - 1)\n \t\t\t\t\tnext \u003d us() + 1000000;\n \t\t\t\telse\n-\t\t\t\t\tnext \u003d us() + 100000;\n+\t\t\t\t\tnext \u003d us() + 300000;\n \t\t\t}\n \t\t}\n \ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt\nindex 6ad9493..2d804a7 100644\n--- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt\n@@ -1,8 +1,8 @@\n cmake_minimum_required(VERSION 2.8)\n include(CheckCSourceCompiles)\n \n-set(SAMP lws-minimal-http-server-libuv-foreign)\n-set(SRCS minimal-http-server-libuv-foreign.c)\n+set(SAMP lws-minimal-http-server-eventlib-foreign)\n+set(SRCS minimal-http-server-eventlib-foreign.c)\n \n # If we are being built as part of lws, confirm current build config supports\n # reqconfig, else skip building ourselves.\n@@ -63,16 +63,25 @@ ENDMACRO()\n \n set(requirements 1)\n require_lws_config(LWS_ROLE_H1 1 requirements)\n-require_lws_config(LWS_WITH_LIBUV 1 requirements)\n require_lws_config(LWS_WITHOUT_SERVER 0 requirements)\n \n-CHECK_C_SOURCE_COMPILES(\u0022#include \u003clibwebsockets.h\u003e\u005cn#include \u003cuv.h\u003e\u005cnint main(void) {\u005cn#if (UV_VERSION_MAJOR \u003e 0)\u005cn return 0;\u005cn#else\u005cn fail;\u005cn#endif\u005cn return 0;\u005cn}\u005cn\u0022 HAS_RECENT_LIBUV)\n-if (NOT HAS_RECENT_LIBUV)\n-\tif (LWS_WITH_MINIMAL_EXAMPLES)\n-\t\tmessage(\u0022libuv is too old (pre- 1.0)\u0022)\n-\telse()\n-\t\tmessage(FATAL_ERROR \u0022libuv is too old (pre- 1.0)\u0022)\n-\tendif()\n+CHECK_C_SOURCE_COMPILES(\u0022#include \u003clibwebsockets.h\u003e\u005cnint main(void) {\u005cn#if defined(LWS_WITH_LIBUV)\u005cn return 0;\u005cn#else\u005cn fail;\u005cn#endif\u005cn return 0;\u005cn}\u005cn\u0022 LWS_WITH_LIBUV)\n+CHECK_C_SOURCE_COMPILES(\u0022#include \u003clibwebsockets.h\u003e\u005cnint main(void) {\u005cn#if defined(LWS_WITH_LIBEVENT)\u005cn return 0;\u005cn#else\u005cn fail;\u005cn#endif\u005cn return 0;\u005cn}\u005cn\u0022 LWS_WITH_LIBEVENT)\n+CHECK_C_SOURCE_COMPILES(\u0022#include \u003clibwebsockets.h\u003e\u005cnint main(void) {\u005cn#if defined(LWS_WITH_LIBEV)\u005cn return 0;\u005cn#else\u005cn fail;\u005cn#endif\u005cn return 0;\u005cn}\u005cn\u0022 LWS_WITH_LIBEV)\n+\n+if (LWS_WITH_LIBUV)\n+\tset(extralibs ${extralibs} uv)\n+endif()\n+if (LWS_WITH_LIBEVENT)\n+\tset(extralibs ${extralibs} event)\n+endif()\n+if (LWS_WITH_LIBEV)\n+\tset(extralibs ${extralibs} ev)\n+endif()\n+\n+message(\u0022Extra libs: ${extralibs}\u0022)\n+\n+if (NOT LWS_WITH_LIBUV AND NOT LWS_WITH_LIBEVENT AND NOT LWS_WITH_LIBEV)\n \tset(requirements 0)\n endif()\n \n@@ -80,9 +89,9 @@ if (requirements)\n \tadd_executable(${SAMP} ${SRCS})\n \n \tif (websockets_shared)\n-\t\ttarget_link_libraries(${SAMP} websockets_shared uv)\n+\t\ttarget_link_libraries(${SAMP} websockets_shared ${extralibs})\n \t\tadd_dependencies(${SAMP} websockets_shared)\n \telse()\n-\t\ttarget_link_libraries(${SAMP} websockets uv)\n+\t\ttarget_link_libraries(${SAMP} websockets ${extralibs})\n \tendif()\n endif()\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 41cc9d9..a663d6e 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@@ -1,4 +1,19 @@\n-# lws minimal http server libuv foreign\n+# lws minimal http server eventlib foreign\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+Notice libevent and libev cannot coexist in the one library. But all the other combinations are OK.\n+\n+x|libuv|libevent|libev\n+---|---|---|---\n+libuv|-|OK|OK\n+libevent|OK|-|no\n+libev|OK|no|-\n \n This demonstrates having lws take part in a libuv loop owned by\n something else, with its own objects running in the loop.\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\nnew file mode 100644\nindex 0000000..3e807d9\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c\n@@ -0,0 +1,424 @@\n+/*\n+ * lws-minimal-http-server-eventlib-foreign\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 the most minimal http server you can make with lws that\n+ * uses a libuv event loop created outside lws. It shows how lws can\n+ * participate in someone else's event loop and clean up after itself.\n+ *\n+ * You choose the event loop to work with at runtime, by giving the\n+ * --uv, --event or --ev switch. Lws has to have been configured to build the\n+ * selected event lib support.\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+struct lws_context_creation_info info;\n+static struct lws_context *context;\n+static int lifetime \u003d 5, reported;\n+\n+static void foreign_timer_service(void *foreign_loop);\n+\n+enum {\n+\tTEST_STATE_CREATE_LWS_CONTEXT,\n+\tTEST_STATE_DESTROY_LWS_CONTEXT,\n+\tTEST_STATE_EXIT\n+};\n+\n+static int sequence \u003d TEST_STATE_CREATE_LWS_CONTEXT;\n+\n+static const struct lws_http_mount mount \u003d {\n+\t/* .mount_next */\t\tNULL,\t\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\u0022index.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+static void\n+signal_cb(int signum)\n+{\n+\tlwsl_notice(\u0022Signal %d caught, exiting...\u005cn\u0022, signum);\n+\n+\tswitch (signum) {\n+\tcase SIGTERM:\n+\tcase SIGINT:\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tlws_context_destroy(context);\n+}\n+\n+/*\n+ * The event-loop specific foreign loop code, one set for each event loop lib\n+ *\n+ * Only the code in this section is specific to the event library used.\n+ */\n+\n+#if defined(LWS_WITH_LIBUV)\n+\n+static uv_loop_t loop_uv;\n+static uv_timer_t timer_outer_uv;\n+static uv_signal_t sighandler_uv;\n+\n+static void\n+timer_cb_uv(uv_timer_t *t)\n+{\n+\tforeign_timer_service(\u0026loop_uv);\n+}\n+\n+static void\n+signal_cb_uv(uv_signal_t *watcher, int signum)\n+{\n+\tsignal_cb(signum);\n+}\n+\n+static void\n+foreign_event_loop_init_and_run_libuv(void)\n+{\n+\t/* we create and start our \u0022foreign loop\u0022 */\n+\n+#if (UV_VERSION_MAJOR \u003e 0) // Travis...\n+\tuv_loop_init(\u0026loop_uv);\n+#endif\n+\tuv_signal_init(\u0026loop_uv, \u0026sighandler_uv);\n+\tuv_signal_start(\u0026sighandler_uv, signal_cb_uv, SIGINT);\n+\n+\tuv_timer_init(\u0026loop_uv, \u0026timer_outer_uv);\n+#if (UV_VERSION_MAJOR \u003e 0) // Travis...\n+\tuv_timer_start(\u0026timer_outer_uv, timer_cb_uv, 0, 1000);\n+#else\n+\t(void)timer_cb_uv;\n+#endif\n+\n+\tuv_run(\u0026loop_uv, UV_RUN_DEFAULT);\n+}\n+\n+static void\n+foreign_event_loop_stop_libuv(void)\n+{\n+\tuv_stop(\u0026loop_uv);\n+}\n+\n+static void\n+foreign_event_loop_cleanup_libuv(void)\n+{\n+\t/* cleanup the foreign loop assets */\n+\n+\tuv_timer_stop(\u0026timer_outer_uv);\n+\tuv_close((uv_handle_t*)\u0026timer_outer_uv, NULL);\n+\tuv_signal_stop(\u0026sighandler_uv);\n+\tuv_close((uv_handle_t *)\u0026sighandler_uv, NULL);\n+\n+\tuv_run(\u0026loop_uv, UV_RUN_DEFAULT);\n+#if (UV_VERSION_MAJOR \u003e 0) // Travis...\n+\tuv_loop_close(\u0026loop_uv);\n+#endif\n+}\n+\n+#endif\n+\n+#if defined(LWS_WITH_LIBEVENT)\n+\n+static struct event_base *loop_event;\n+static struct event *timer_outer_event;\n+static struct event *sighandler_event;\n+\n+static void\n+timer_cb_event(int fd, short event, void *arg)\n+{\n+\tforeign_timer_service(loop_event);\n+}\n+\n+static void\n+signal_cb_event(int fd, short event, void *arg)\n+{\n+\tsignal_cb((int)(lws_intptr_t)arg);\n+}\n+\n+static void\n+foreign_event_loop_init_and_run_libevent(void)\n+{\n+\tstruct timeval tv;\n+\n+\t/* we create and start our \u0022foreign loop\u0022 */\n+\n+\ttv.tv_sec \u003d 1;\n+\ttv.tv_usec \u003d 0;\n+\n+\tloop_event \u003d event_base_new();\n+\n+\tsighandler_event \u003d evsignal_new(loop_event, SIGINT, signal_cb_event,\n+\t\t\t\t\t(void*)SIGINT);\n+\n+\ttimer_outer_event \u003d event_new(loop_event, -1, EV_PERSIST,\n+\t\t\t\t timer_cb_event, NULL);\n+\t//evtimer_new(loop_event, timer_cb_event, NULL);\n+\tevtimer_add(timer_outer_event, \u0026tv);\n+\n+\tevent_base_loop(loop_event, 0);\n+}\n+\n+static void\n+foreign_event_loop_stop_libevent(void)\n+{\n+\tevent_base_loopexit(loop_event, NULL);\n+}\n+\n+static void\n+foreign_event_loop_cleanup_libevent(void)\n+{\n+\t/* cleanup the foreign loop assets */\n+\n+\tevtimer_del(timer_outer_event);\n+\tevent_free(timer_outer_event);\n+\tevsignal_del(sighandler_event);\n+\tevent_free(sighandler_event);\n+\n+\tevent_base_loop(loop_event, 0);\n+\tevent_base_free(loop_event);\n+}\n+\n+#endif\n+\n+#if defined(LWS_WITH_LIBEV)\n+\n+static struct ev_loop *loop_ev;\n+static struct ev_timer timer_outer_ev;\n+static struct ev_signal sighandler_ev;\n+\n+static void\n+timer_cb_ev(struct ev_loop *loop, struct ev_timer *watcher, int revents)\n+{\n+\tforeign_timer_service(loop_ev);\n+}\n+\n+static void\n+signal_cb_ev(struct ev_loop *loop, struct ev_signal *watcher, int revents)\n+{\n+\tsignal_cb(watcher-\u003esignum);\n+}\n+\n+static void\n+foreign_event_loop_init_and_run_libev(void)\n+{\n+\t/* we create and start our \u0022foreign loop\u0022 */\n+\n+\tloop_ev \u003d ev_loop_new(0);\n+\n+\tev_signal_init(\u0026sighandler_ev, signal_cb_ev, SIGINT);\n+\tev_signal_start(loop_ev, \u0026sighandler_ev);\n+\n+\tev_timer_init(\u0026timer_outer_ev, timer_cb_ev, 0, 1);\n+\tev_timer_start(loop_ev, \u0026timer_outer_ev);\n+\n+\tev_run(loop_ev, 0);\n+}\n+\n+static void\n+foreign_event_loop_stop_libev(void)\n+{\n+\tev_break(loop_ev, EVBREAK_ALL);\n+}\n+\n+static void\n+foreign_event_loop_cleanup_libev(void)\n+{\n+\t/* cleanup the foreign loop assets */\n+\n+\tev_timer_stop(loop_ev, \u0026timer_outer_ev);\n+\tev_signal_stop(loop_ev, \u0026sighandler_ev);\n+\n+\tev_run(loop_ev, UV_RUN_DEFAULT);\n+\tev_loop_destroy(loop_ev);\n+}\n+\n+#endif\n+\n+/* this is called at 1Hz using a foreign loop timer */\n+\n+static void\n+foreign_timer_service(void *foreign_loop)\n+{\n+\tvoid *foreign_loops[1];\n+\n+\tlwsl_user(\u0022Foreign 1Hz timer\u005cn\u0022);\n+\n+\tif (sequence \u003d\u003d TEST_STATE_EXIT \u0026\u0026 !context \u0026\u0026 !reported) {\n+\t\t/*\n+\t\t * at this point the lws_context_destroy() we did earlier\n+\t\t * has completed and the entire context is wholly destroyed\n+\t\t */\n+\t\tlwsl_user(\u0022lws_destroy_context() done, continuing for 5s\u005cn\u0022);\n+\t\treported \u003d 1;\n+\t}\n+\n+\tif (--lifetime)\n+\t\treturn;\n+\n+\tswitch (sequence++) {\n+\tcase TEST_STATE_CREATE_LWS_CONTEXT:\n+\t\t/* this only has to exist for the duration of create context */\n+\t\tforeign_loops[0] \u003d foreign_loop;\n+\t\tinfo.foreign_loops \u003d foreign_loops;\n+\n+\t\tcontext \u003d lws_create_context(\u0026info);\n+\t\tif (!context) {\n+\t\t\tlwsl_err(\u0022lws init failed\u005cn\u0022);\n+\t\t\treturn;\n+\t\t}\n+\t\tlwsl_user(\u0022LWS Context created and will be active for 10s\u005cn\u0022);\n+\t\tlifetime \u003d 11;\n+\t\tbreak;\n+\n+\tcase TEST_STATE_DESTROY_LWS_CONTEXT:\n+\t\t/* cleanup the lws part */\n+\t\tlwsl_user(\u0022Destroying lws context and continuing loop for 5s\u005cn\u0022);\n+\t\tlws_context_destroy(context);\n+\t\tlifetime \u003d 6;\n+\t\tbreak;\n+\n+\tcase TEST_STATE_EXIT:\n+\t\tlwsl_user(\u0022Deciding to exit foreign loop too\u005cn\u0022);\n+#if defined(LWS_WITH_LIBUV)\n+\t\tif (info.options \u0026 LWS_SERVER_OPTION_LIBUV)\n+\t\t\tforeign_event_loop_stop_libuv();\n+#endif\n+#if defined(LWS_WITH_LIBEVENT)\n+\t\tif (info.options \u0026 LWS_SERVER_OPTION_LIBEVENT)\n+\t\t\tforeign_event_loop_stop_libevent();\n+#endif\n+#if defined(LWS_WITH_LIBEV)\n+\t\tif (info.options \u0026 LWS_SERVER_OPTION_LIBEV)\n+\t\t\tforeign_event_loop_stop_libev();\n+#endif\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+int main(int argc, const char **argv)\n+{\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 libuv + foreign loop |\u0022\n+\t\t \u0022 visit http://localhost:7681\u005cn\u0022);\n+\n+\t/*\n+\t * We prepare the info here, but don't use it until later in the\n+\t * timer callback, to demonstrate the independence of the foreign loop\n+\t * and lws.\n+\t */\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+\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\tlwsl_err(\u0022This app only makes sense when used\u005cn\u0022);\n+\t\t\t\tlwsl_err(\u0022 with a foreign loop, --uv, --event, or --ev\u005cn\u0022);\n+\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\n+\tlwsl_user(\u0022 This app creates a foreign event loop with a timer +\u005cn\u0022);\n+\tlwsl_user(\u0022 signalhandler, and performs a test in three phases:\u005cn\u0022);\n+\tlwsl_user(\u0022\u005cn\u0022);\n+\tlwsl_user(\u0022 1) 5s: Runs the loop with just the timer\u005cn\u0022);\n+\tlwsl_user(\u0022 2) 10s: create an lws context serving on localhost:7681\u005cn\u0022);\n+\tlwsl_user(\u0022 using the same foreign loop. Destroy it after 10s.\u005cn\u0022);\n+\tlwsl_user(\u0022 3) 5s: Run the loop again with just the timer\u005cn\u0022);\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+\n+\t/* foreign loop specific startup and run */\n+\n+#if defined(LWS_WITH_LIBUV)\n+\tif (info.options \u0026 LWS_SERVER_OPTION_LIBUV)\n+\t\tforeign_event_loop_init_and_run_libuv();\n+#endif\n+#if defined(LWS_WITH_LIBEVENT)\n+\tif (info.options \u0026 LWS_SERVER_OPTION_LIBEVENT)\n+\t\tforeign_event_loop_init_and_run_libevent();\n+#endif\n+#if defined(LWS_WITH_LIBEV)\n+\tif (info.options \u0026 LWS_SERVER_OPTION_LIBEV)\n+\t\tforeign_event_loop_init_and_run_libev();\n+#endif\n+\n+\tlws_context_destroy(context);\n+\n+\t/* foreign loop specific cleanup and exit */\n+\n+#if defined(LWS_WITH_LIBUV)\n+\tif (info.options \u0026 LWS_SERVER_OPTION_LIBUV)\n+\t\tforeign_event_loop_cleanup_libuv();\n+#endif\n+#if defined(LWS_WITH_LIBEVENT)\n+\tif (info.options \u0026 LWS_SERVER_OPTION_LIBEVENT)\n+\t\tforeign_event_loop_cleanup_libevent();\n+#endif\n+#if defined(LWS_WITH_LIBEV)\n+\tif (info.options \u0026 LWS_SERVER_OPTION_LIBEV)\n+\t\tforeign_event_loop_cleanup_libev();\n+#endif\n+\n+\tlwsl_user(\u0022%s: exiting...\u005cn\u0022, __func__);\n+\n+\treturn 0;\n+}\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-libuv-foreign.c b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-libuv-foreign.c\ndeleted file mode 100644\nindex 7108133..0000000\n--- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-libuv-foreign.c\n+++ /dev/null\n@@ -1,201 +0,0 @@\n-/*\n- * lws-minimal-http-server-libuv-foreign\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 the most minimal http server you can make with lws that\n- * uses a libuv event loop created outside lws. It shows how lws can\n- * participate in someone else's event loop and clean up after itself.\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-static struct lws_context *context;\n-static uv_loop_t loop;\n-static int lifetime \u003d 5, reported;\n-struct lws_context_creation_info info;\n-\n-enum {\n-\tTEST_STATE_CREATE_LWS_CONTEXT,\n-\tTEST_STATE_DESTROY_LWS_CONTEXT,\n-\tTEST_STATE_EXIT\n-};\n-\n-static int sequence \u003d TEST_STATE_CREATE_LWS_CONTEXT;\n-\n-static const struct lws_http_mount mount \u003d {\n-\t/* .mount_next */\t\tNULL,\t\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\u0022index.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(uv_signal_t *watcher, int signum)\n-{\n-\tlwsl_notice(\u0022Signal %d caught, exiting...\u005cn\u0022, watcher-\u003esignum);\n-\n-\tswitch (watcher-\u003esignum) {\n-\tcase SIGTERM:\n-\tcase SIGINT:\n-\t\tbreak;\n-\tdefault:\n-\t\tsignal(SIGABRT, SIG_DFL);\n-\t\tabort();\n-\t\tbreak;\n-\t}\n-\n-\tif (context)\n-\t\tlws_context_destroy(context);\n-}\n-\n-/* this logs once a second to show that the foreign loop assets are working */\n-\n-static void\n-timer_cb(uv_timer_t *t)\n-{\n-\tvoid *foreign_loops[1];\n-\n-\tforeign_loops[0] \u003d \u0026loop;\n-\tinfo.foreign_loops \u003d foreign_loops;\n-\n-\tlwsl_user(\u0022Foreign 1Hz timer\u005cn\u0022);\n-\n-\tif (sequence \u003d\u003d TEST_STATE_EXIT \u0026\u0026 !context \u0026\u0026 !reported) {\n-\t\t/*\n-\t\t * at this point the lws_context_destroy() we did earlier\n-\t\t * has completed and the entire context is wholly destroyed\n-\t\t */\n-\t\tlwsl_user(\u0022lws_destroy_context() completed, continuing for 5s\u005cn\u0022);\n-\t\treported \u003d 1;\n-\t}\n-\n-\tif (--lifetime)\n-\t\treturn;\n-\n-\tswitch (sequence++) {\n-\tcase TEST_STATE_CREATE_LWS_CONTEXT:\n-\t\tcontext \u003d lws_create_context(\u0026info);\n-\t\tif (!context) {\n-\t\t\tlwsl_err(\u0022lws init failed\u005cn\u0022);\n-\t\t\treturn;\n-\t\t}\n-\t\tlwsl_user(\u0022LWS Context created and active for 10s\u005cn\u0022);\n-\t\tlifetime \u003d 11;\n-\t\tbreak;\n-\tcase TEST_STATE_DESTROY_LWS_CONTEXT:\n-\t\t/* cleanup the lws part */\n-\t\tlwsl_user(\u0022Destroying lws context and continuing loop for 5s\u005cn\u0022);\n-\t\tlws_context_destroy(context);\n-\t\tlifetime \u003d 6;\n-\t\tbreak;\n-\n-\tcase TEST_STATE_EXIT:\n-\t\tlwsl_user(\u0022Deciding to exit foreign loop too\u005cn\u0022);\n-\t\tuv_stop(\u0026loop);\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-}\n-\n-\n-int main(int argc, const char **argv)\n-{\n-\tuv_timer_t timer_outer;\n-\tuv_signal_t sighandler;\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 libuv + foreign loop |\u0022\n-\t\t \u0022 visit http://localhost:7681\u005cn\u0022);\n-\n-\t/*\n-\t * We prepare the info here, but don't use it until later in the\n-\t * timer callback, to demonstrate the independence of the foreign loop\n-\t * and lws.\n-\t */\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.options \u003d LWS_SERVER_OPTION_LIBUV;\n-\tinfo.pcontext \u003d \u0026context;\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-\tinfo.pcontext \u003d \u0026context;\n-\n-\tlwsl_user(\u0022 This app creates a uv loop with a timer + signalhandler, and\u005cn\u0022);\n-\tlwsl_user(\u0022 performs a test in three phases:\u005cn\u0022);\n-\tlwsl_user(\u0022\u005cn\u0022);\n-\tlwsl_user(\u0022 1) 5s: Runs the loop with just the timer\u005cn\u0022);\n-\tlwsl_user(\u0022 2) 10s: create an lws context serving on localhost:7681\u005cn\u0022);\n-\tlwsl_user(\u0022 using the same uv loop. Destroy it after 10s.\u005cn\u0022);\n-\tlwsl_user(\u0022 3) 5s: Run the loop again with just the timer\u005cn\u0022);\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-\t/* we create and start our \u0022foreign loop\u0022 */\n-\n-\tuv_loop_init(\u0026loop);\n-\tuv_signal_init(\u0026loop, \u0026sighandler);\n-\tuv_signal_start(\u0026sighandler, signal_cb, SIGINT);\n-\n-\tuv_timer_init(\u0026loop, \u0026timer_outer);\n-\tuv_timer_start(\u0026timer_outer, timer_cb, 0, 1000);\n-\n-\tuv_run(\u0026loop, UV_RUN_DEFAULT);\n-\n-\t/* in the case we hit ^C while lws still exists */\n-\tlws_context_destroy(context);\n-\n-\t/* cleanup the foreign loop assets */\n-\n-\tuv_timer_stop(\u0026timer_outer);\n-\tuv_close((uv_handle_t*)\u0026timer_outer, NULL);\n-\tuv_signal_stop(\u0026sighandler);\n-\tuv_close((uv_handle_t *)\u0026sighandler, NULL);\n-\n-\tuv_run(\u0026loop, UV_RUN_DEFAULT);\n-\tuv_loop_close(\u0026loop);\n-\n-\tlwsl_user(\u0022%s: exiting...\u005cn\u0022, __func__);\n-\n-\treturn 0;\n-}\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/index.html b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/index.html\nindex 31a6dfa..3ec21df 100644\n--- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/index.html\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/mount-origin/index.html\n@@ -3,10 +3,10 @@\n \t\u003cbody\u003e\n \t\t\u003cimg src\u003d\u0022libwebsockets.org-logo.png\u0022\u003e\u003cbr\u003e\n \n-\t\tHello from the \u003cb\u003eminimal http server libuv foreign loop example\u003c/b\u003e.\n+\t\tHello from the \u003cb\u003eminimal http server eventlib foreign loop example\u003c/b\u003e.\n \t\t\u003cbr\u003e\n \t\tThe timer messages in the console are coming from\u003cbr\u003e\n-\t\ta timer on the libuv loop set up before the lws context\u003cbr\u003e\n+\t\ta timer on the event library lib loop set up before the lws context\u003cbr\u003e\n \t\tstarted using it.\n \t\u003c/body\u003e\n \u003c/html\u003e\ndiff --git a/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c b/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c\nnew file mode 100644\nindex 0000000..4b9d3c9\n--- /dev/null\n+++ b/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c\n@@ -0,0 +1,117 @@\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+static struct lws_context *context;\n+\n+static const struct lws_http_mount mount \u003d {\n+\t/* .mount_next */\t\tNULL,\t\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\u0022index.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+\tswitch (signum) {\n+\tcase SIGTERM:\n+\tcase SIGINT:\n+\t\tbreak;\n+\tdefault:\n+\t\tlwsl_err(\u0022%s: signal %d\u005cn\u0022, __func__, signum);\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.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/minimal-http-server-libuv.c b/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-libuv.c\ndeleted file mode 100644\nindex 9d73be1..0000000\n--- a/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-libuv.c\n+++ /dev/null\n@@ -1,102 +0,0 @@\n-/*\n- * lws-minimal-http-server-libuv\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 the most minimal http server you can make with lws using\n- * the libuv event loop.\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-static struct lws_context *context;\n-\n-static const struct lws_http_mount mount \u003d {\n-\t/* .mount_next */\t\tNULL,\t\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\u0022index.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-\tuv_signal_t *watcher \u003d (uv_signal_t *)handle;\n-\n-\tlwsl_notice(\u0022Signal %d caught, exiting...\u005cn\u0022, watcher-\u003esignum);\n-\n-\tswitch (watcher-\u003esignum) {\n-\tcase SIGTERM:\n-\tcase SIGINT:\n-\t\tbreak;\n-\tdefault:\n-\t\tsignal(SIGABRT, SIG_DFL);\n-\t\tabort();\n-\t\tbreak;\n-\t}\n-\tlws_context_destroy(context);\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 libuv [-s (ssl)] | visit http://localhost:7681\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-\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-\tinfo.options |\u003d LWS_SERVER_OPTION_LIBUV;\n-\tinfo.signal_cb \u003d signal_cb;\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-\tlws_service(context, 0);\n-\n-\tlws_context_destroy(context);\n-\n-\treturn 0;\n-}\ndiff --git a/minimal-examples/selftests-library.sh b/minimal-examples/selftests-library.sh\nindex 13f34dd..feef8f8 100755\n--- a/minimal-examples/selftests-library.sh\n+++ b/minimal-examples/selftests-library.sh\n@@ -79,6 +79,11 @@ dotest() {\n \tif [ -e $2/$MYTEST/$T.result ] ; then\n \t\tR\u003d`cat $2/$MYTEST/$T.result`\n \t\tcat $2/$MYTEST/$T.log | tail -n 3 \u003e $2/$MYTEST/$T.time\n+\t\tif [ $R -ne 0 ] ; then\n+\t\t\techo\n+\t\t\tcat $2/$MYTEST/$T.log\n+\t\t\techo\n+\t\tfi\n \tfi\n \n \tfeedback $MYTEST $R $T\ndiff --git a/plugins/protocol_post_demo.c b/plugins/protocol_post_demo.c\nindex 37cb974..5c76781 100644\n--- a/plugins/protocol_post_demo.c\n+++ b/plugins/protocol_post_demo.c\n@@ -68,6 +68,8 @@ file_upload_cb(void *data, const char *name, const char *filename,\n \t\t\t(struct per_session_data__post_demo *)data;\n #if !defined(LWS_WITH_ESP32)\n \tint n;\n+\n+\t(void)n;\n #endif\n \n \tswitch (state) {\n@@ -92,7 +94,7 @@ file_upload_cb(void *data, const char *name, const char *filename,\n \n #if !defined(LWS_WITH_ESP32)\n \t\t\tn \u003d write((int)(long long)pss-\u003efd, buf, len);\n-\t\t\tlwsl_notice(\u0022%s: write %d says %d\u005cn\u0022, __func__, len, n);\n+\t\t\tlwsl_info(\u0022%s: write %d says %d\u005cn\u0022, __func__, len, n);\n #else\n \t\t\tlwsl_notice(\u0022%s: Received chunk size %d\u005cn\u0022, __func__, len);\n #endif\ndiff --git a/scripts/attack.sh b/scripts/attack.sh\nnew file mode 100755\nindex 0000000..66691fc\n--- /dev/null\n+++ b/scripts/attack.sh\n@@ -0,0 +1,803 @@\n+#!/bin/bash\n+#\n+# attack the test server and try to make it fall over\n+#\n+# Requires the library to have been built with cmake .. -DCMAKE_BUILD_TYPE\u003dDEBUG\n+\n+echo\n+echo \u0022----------------------------------------------\u0022\n+echo \u0022------- tests: lws attack.sh\u0022\n+echo\n+\n+SERVER\u003d127.0.0.1\n+PORT\u003d7681\n+LOG\u003d/tmp/lwslog\n+\n+A\u003d`which libwebsockets-test-server`\n+INSTALLED\u003d`dirname $A`\n+\n+SHAREDIR\u003d$INSTALLED/../share/libwebsockets-test-server\n+CORPUS\u003d$SHAREDIR/test.html\n+\n+\n+CPID\u003d\n+LEN\u003d0\n+\n+function check {\n+\tkill -0 $CPID\n+\tif [ $? -ne 0 ] ; then\n+\t\techo \u0022(killed it) *******\u0022\n+\t\texit 1\n+\tfi\n+\t#dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null\n+\n+\tif [ \u0022$1\u0022 \u003d \u0022default\u0022 ] ; then\n+\t\tdiff /tmp/lwscap $CORPUS \u003e /dev/null\n+\t\tif [ $? -ne 0 ] ; then\n+\t\t\techo \u0022FAIL: got something other than $CORPUS back\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\tif [ \u0022$1\u0022 \u003d \u0022defaultplusforbidden\u0022 ] ; then\n+\tcat $CORPUS \u003e /tmp/plusforb\n+\techo -e -n \u0022HTTP/1.0 403 Forbidden\u005cx0d\u005cx0acontent-type: text/html\u005cx0d\u005cx0acontent-length: 38\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u003chtml\u003e\u003cbody\u003e\u003ch1\u003e403\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e\u0022 \u003e\u003e /tmp/plusforb\n+\t\tdiff /tmp/lwscap /tmp/plusforb \u003e /dev/null\n+\t\tif [ $? -ne 0 ] ; then\n+\t\t\tcat $CORPUS \u003e /tmp/plusforb\n+\n+\t\t\techo -e -n \u0022HTTP/1.1 403 Forbidden\u005cx0d\u005cx0acontent-type: text/html\u005cx0d\u005cx0acontent-length: 38\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u003chtml\u003e\u003cbody\u003e\u003ch1\u003e403\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e\u0022 \u003e\u003e /tmp/plusforb\n+\t\t\tdiff /tmp/lwscap /tmp/plusforb \u003e /dev/null\n+\t\t\tif [ $? -ne 0 ] ; then\n+\n+\t\t\t\techo \u0022FAIL: got something other than $CORPUS + forbidden back\u0022\n+\t\t\t\ttail -n 10 /tmp/lwscap\n+\t\t\t\ttail -n 100 $LOG\n+\t\t\t\texit 1\n+\t\t\tfi\n+\t\tfi\n+\tfi\n+\n+\tif [ \u0022$1\u0022 \u003d \u0022forbidden\u0022 ] ; then\n+\t\tif [ -z \u0022`grep '\u003ch1\u003e403\u003c/h1\u003e' /tmp/lwscap`\u0022 ] ; then\n+\t\t\techo \u0022FAIL: should have told forbidden (test server has no dirs)\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\n+\tif [ \u0022$1\u0022 \u003d \u0022notfound\u0022 ] ; then\n+\t\tif [ -z \u0022`grep '\u003ch1\u003e404\u003c/h1\u003e' /tmp/lwscap`\u0022 ] ; then\n+\t\t\techo \u0022FAIL: should have told not found\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\n+\n+\tif [ \u0022$1\u0022 \u003d \u0022rejected\u0022 ] ; then\n+\t\tif [ -z \u0022`grep '\u003ch1\u003e404\u003c/h1\u003e' /tmp/lwscap`\u0022 ] ; then\n+\t\t\techo \u0022FAIL: should have told forbidden (test server has no dirs)\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\n+\n+\tif [ \u0022$1\u0022 \u003d \u0022media\u0022 ] ; then\n+\t\tif [ -z \u0022`grep '\u003ch1\u003e404\u003c/h1\u003e' /tmp/lwscap`\u0022 ] ; then\n+\t\t\techo \u0022FAIL: should have told unknown media type\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\n+\tif [ \u0022$1\u0022 \u003d\u003d \u00220\u0022 ] ; then\n+\t\ta\u003d\u0022`dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null |grep \u0022get\u005c \u005c \u003d\u0022 | tr -s ' ' | cut -d' ' -f4-`\u0022\n+\t\tif [ \u0022$a\u0022 !\u003d \u0022$2\u0022 ] ; then\n+\t\t\techo \u0022URL path '$a' not $2\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\n+\tif [ \u0022$1\u0022 \u003d\u003d \u00221\u0022 ] ; then\n+\t\ta\u003d\u0022`dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null |grep URI\u005c Arg\u005c 1\u005c: | tr -s ' ' | cut -d' ' -f7-`\u0022\n+\t\tif [ \u0022$a\u0022 !\u003d \u0022$2\u0022 ] ; then\n+\t\t\techo \u0022Arg 1 '$a' not $2\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\n+\tif [ \u0022$1\u0022 \u003d\u003d \u00222\u0022 ] ; then\n+\t\ta\u003d\u0022`dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null |grep URI\u005c Arg\u005c 2\u005c: | tr -s ' ' | cut -d' ' -f7-`\u0022\n+\t\tif [ \u0022$a\u0022 !\u003d \u0022$2\u0022 ] ; then\n+\t\t\techo \u0022Arg 2 '$a' not $2\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\tif [ \u0022$1\u0022 \u003d\u003d \u00223\u0022 ] ; then\n+\t\ta\u003d\u0022`dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null |grep URI\u005c Arg\u005c 3\u005c: | tr -s ' ' | cut -d' ' -f7-`\u0022\n+\t\tif [ \u0022$a\u0022 !\u003d \u0022$2\u0022 ] ; then\n+\t\t\techo \u0022Arg 3 '$a' not $2\u0022\n+\t\t\texit 1\n+\t\tfi\n+\tfi\n+\n+\tif [ -z \u0022$1\u0022 ] ; then\n+\t\tLEN\u003d`stat $LOG -c %s`\n+\tfi\n+}\n+\n+\n+rm -rf $LOG\n+killall libwebsockets-test-server 2\u003e/dev/null\n+libwebsockets-test-server -d15 2\u003e\u003e $LOG \u003e/dev/null \u0026\n+CPID\u003d$!\n+\n+echo \u0022Started server on PID $CPID\u0022\n+\n+while [ -z \u0022`grep ort\u005c 7681 $LOG`\u0022 ] ; do\n+\tsleep 0.5s\n+done\n+check\n+\n+echo\n+echo \u0022---- /cgi-bin/settingsjs?UPDATE_SETTINGS\u003d1\u0026Root_Channels_1_Channel_name_http_post\u003d%3F\u0026Root_Channels_1_Channel_location_http_post\u003d%3F\u0022\n+rm -f /tmp/lwscap\n+echo -n -e \u0022GET /cgi-bin/settingsjs?UPDATE_SETTINGS\u003d1\u0026Root_Channels_1_Channel_name_http_post\u003d%3F\u0026Root_Channels_1_Channel_location_http_post\u003d%3F HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+cat /tmp/lwscap\n+check 1 \u0022UPDATE_SETTINGS\u003d1\u0022\n+check 2 \u0022Root_Channels_1_Channel_name_http_post\u003d?\u0022\n+check 3 \u0022Root_Channels_1_Channel_location_http_post\u003d?\u0022\n+check\n+\n+echo\n+echo \u0022---- ? processing (/cgi-bin/settings.js?key1\u003dvalue1)\u0022\n+rm -f /tmp/lwscap\n+echo -n -e \u0022GET /cgi-bin/settings.js?key1\u003dvalue1 HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check 1 \u0022key1\u003dvalue1\u0022\n+check\n+\n+echo\n+echo \u0022---- ? processing (/t%3dest?key1%3d2\u003dvalue1)\u0022\n+rm -f /tmp/lwscap\n+echo -n -e \u0022GET /t%3dest?key1%3d2\u003dvalue1 HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check 0 \u0022/t\u003dest\u0022\n+check 1 \u0022key1_2\u003dvalue1\u0022\n+check\n+\n+echo\n+echo \u0022---- ? processing (%2f%2e%2e%2f%2e./xxtest.html?arg\u003d1)\u0022\n+rm -f /tmp/lwscap\n+echo -n -e \u0022GET %2f%2e%2e%2f%2e./xxtest.html?arg\u003d1 HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check 1 \u0022arg\u003d1\u0022\n+check\n+\n+echo\n+echo \u0022---- ? processing (%2f%2e%2e%2f%2e./xxtest.html?arg\u003d/../.)\u0022\n+rm -f /tmp/lwscap\n+echo -n -e \u0022GET %2f%2e%2e%2f%2e./xxtest.html?arg\u003d/../. HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check 1 \u0022arg\u003d/../.\u0022\n+check\n+\n+echo\n+echo \u0022---- spam enough crap to not be GET\u0022\n+echo \u0022not GET\u0022 | nc $SERVER $PORT\n+check\n+\n+echo\n+echo \u0022---- spam more than the name buffer of crap\u0022\n+dd if\u003d/dev/urandom bs\u003d1 count\u003d80 2\u003e/dev/null | nc -i1 $SERVER $PORT\n+check\n+\n+echo\n+echo \u0022---- spam 10MB of crap\u0022\n+dd if\u003d/dev/urandom bs\u003d1 count\u003d655360 | nc -i1 $SERVER $PORT\n+check\n+\n+echo\n+echo \u0022---- malformed URI\u0022\n+echo \u0022GET nonsense................................................................................................................\u0022 \u005c\n+\t| nc -i1 $SERVER $PORT\n+check\n+\n+echo\n+echo \u0022---- missing URI\u0022\n+echo -n -e \u0022GET HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc -i1 $SERVER $PORT \u003e/tmp/lwscap\n+check\n+\n+echo\n+echo \u0022---- repeated method\u0022\n+echo -n -e \u0022GET blah HTTP/1.0\u005cx0d\u005cx0aGET blah HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT \u003e/tmp/lwscap \n+check\n+\n+echo\n+echo \u0022---- crazy header name part\u0022\n+echo -n -e \u0022GET blah HTTP/1.0\u005cx0d\u005cx0a................................................................................................................\u0022 \u005c\n+\t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+\t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ | nc -i1 $SERVER $PORT\n+check\n+\n+echo\n+echo \u0022---- excessive uri content\u0022\n+echo -n -e \u0022GET ................................................................................................................\u0022 \u005c\n+\t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+\t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ \t\u0022.......................................................................................................................\u0022 \u005c\n+ | nc -i1 $SERVER $PORT\n+check\n+\n+echo\n+echo \u0022---- good request but http payload coming too (test.html served then forbidden)\u0022\n+echo -n -e \u0022GET /test.html HTTP/1.1\u005cx0d\u005cx0a\u005cx0d\u005cx0aILLEGAL-PAYLOAD........................................\u0022 \u005c\n+\t| cat - /dev/zero | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check defaultplusforbidden\n+check\n+\n+echo\n+echo \u0022---- nonexistent file\u0022\n+rm -f /tmp/lwscap\n+echo -n -e \u0022GET /nope HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+cat /tmp/lwscap\n+check notfound\n+check\n+\n+echo\n+echo \u0022---- relative uri path\u0022\n+rm -f /tmp/lwscap\n+echo -n -e \u0022GET nope HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check forbidden\n+check\n+\n+echo\n+echo \u0022---- directory attack 1 (/../../../../etc/passwd should be /etc/passswd)\u0022\n+rm -f /tmp/lwscap\n+echo -n -e \u0022GET /../../../../etc/passwd HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check notfound\n+check\n+\n+echo\n+echo \u0022---- directory attack 2 (/../ should be /)\u0022\n+rm -f /tmp/lwscap\n+echo -e -n \u0022GET /../ HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check default\n+check\n+\n+echo\n+echo \u0022---- directory attack 3 (/./ should be /)\u0022\n+rm -f /tmp/lwscap\n+echo -e -n \u0022GET /./ HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check default\n+check\n+\n+echo\n+echo \u0022---- directory attack 4 (/blah/.. should be /)\u0022\n+rm -f /tmp/lwscap\n+echo -e -n \u0022GET /blah/.. HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check default\n+check\n+\n+echo\n+echo \u0022---- directory attack 5 (/blah/../ should be /)\u0022\n+rm -f /tmp/lwscap\n+echo -e -n \u0022GET /blah/../ HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check default\n+check\n+\n+echo\n+echo \u0022---- directory attack 6 (/blah/../. should be /)\u0022\n+rm -f /tmp/lwscap\n+echo -e -n \u0022GET /blah/../. HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check default\n+check\n+\n+echo\n+echo \u0022---- directory attack 7 (/%2e%2e%2f../../../etc/passwd should be /etc/passswd)\u0022\n+rm -f /tmp/lwscap\n+echo -e -n \u0022GET /%2e%2e%2f../../../etc/passwd HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check notfound\n+check\n+\n+echo\n+echo \u0022---- directory attack 8 (%2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd should be /etc/passswd)\u0022\n+rm -f /tmp/lwscap\n+echo -e -n \u0022GET %2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n+check notfound\n+check\n+\n+echo\n+echo \u0022---- http/1.1 pipelining\u0022\n+rm -f /tmp/lwscap\n+wget -O/tmp/lwsdump http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html 2\u003e\u00261 | grep \u0022Downloaded: 8 files\u0022 \u003e /tmp/lwscap\n+good\u003d`cat $CORPUS $CORPUS $CORPUS $CORPUS $CORPUS $CORPUS $CORPUS $CORPUS | md5sum | cut -d' ' -f1`\n+if [ \u0022$good\u0022 !\u003d \u0022`md5sum /tmp/lwsdump | cut -d' ' -f 1`\u0022 ] ; then\n+\techo \u0022FAIL: mismatched content good\u003d$good received\u003d`md5sum /tmp/lwsdump`\u0022\n+\texit 1\n+fi\n+\n+echo\n+echo \u0022---- mass testing uri variations\u0022\n+\n+rm -f /tmp/results\n+\n+for i in \u005c\n+/..../ \u005c\n+/.../. \u005c\n+/...// \u005c\n+/.../a \u005c\n+/.../w \u005c\n+\u0022/.../?\u0022 \u005c\n+/.../% \u005c\n+/../.. \u005c\n+/.././ \u005c\n+/../.a \u005c\n+/../.w \u005c\n+/../.. \u005c\n+/../.% \u005c\n+/..//. \u005c\n+/../// \u005c\n+/..//a \u005c\n+/..//w \u005c\n+\u0022/..//?\u0022 \u005c\n+/..//% \u005c\n+/../a. \u005c\n+/../a/ \u005c\n+/../aa \u005c\n+/../aw \u005c\n+/../a? \u005c\n+/../a% \u005c\n+/../w. \u005c\n+/../w/ \u005c\n+/../wa \u005c\n+/../ww \u005c\n+/../w? \u005c\n+/../w% \u005c\n+/../?. \u005c\n+/../?/ \u005c\n+/../?a \u005c\n+/../?w \u005c\n+/../?? \u005c\n+/../?% \u005c\n+/../%. \u005c\n+/../%/ \u005c\n+/../%a \u005c\n+/../%w \u005c\n+/../%? \u005c\n+/../%% \u005c\n+/./... \u005c\n+/./../ \u005c\n+/./..a \u005c\n+/./..w \u005c\n+/./..? \u005c\n+/./..% \u005c\n+/.//.. \u005c\n+/.a../ \u005c\n+/.a/.. \u005c\n+/.w../ \u005c\n+/.w/.. \u005c\n+/.?../ \u005c\n+/../.. \u005c\n+/.%../ \u005c\n+/.%/.. \u005c\n+//.... \u005c\n+//.../ \u005c\n+//...a \u005c\n+//...w \u005c\n+//...? \u005c\n+//...% \u005c\n+//../. \u005c\n+//..// \u005c\n+//../a \u005c\n+//../w \u005c\n+//../? \u005c\n+//../% \u005c\n+//..a. \u005c\n+//..a/ \u005c\n+//..aa \u005c\n+//..aw \u005c\n+//..a? \u005c\n+//..a% \u005c\n+//..w. \u005c\n+//..w/ \u005c\n+//..wa \u005c\n+//..ww \u005c\n+//..w? \u005c\n+//..w% \u005c\n+//..?. \u005c\n+//..?/ \u005c\n+//..?a \u005c\n+//..?w \u005c\n+//..?? \u005c\n+//..?% \u005c\n+//..%. \u005c\n+//..%/ \u005c\n+//..%a \u005c\n+//..%w \u005c\n+//..%? \u005c\n+//..%% \u005c\n+//./.. \u005c\n+///... \u005c\n+///../ \u005c\n+///..a \u005c\n+///..w \u005c\n+///..? \u005c\n+///..% \u005c\n+////.. \u005c\n+//a../ \u005c\n+//a/.. \u005c\n+//w../ \u005c\n+//w/.. \u005c\n+//?../ \u005c\n+//?/.. \u005c\n+//%../ \u005c\n+//%/.. \u005c\n+/a.../ \u005c\n+/a../. \u005c\n+/a..// \u005c\n+/a../a \u005c\n+/a../w \u005c\n+/a../? \u005c\n+/a../% \u005c\n+/a./.. \u005c\n+/a/... \u005c\n+/a/../ \u005c\n+/a/..a \u005c\n+/a/..w \u005c\n+/a/..? \u005c\n+/a/..% \u005c\n+/a//.. \u005c\n+/aa../ \u005c\n+/aa/.. \u005c\n+/aw../ \u005c\n+/aw/.. \u005c\n+/a?../ \u005c\n+/a?/.. \u005c\n+/a%../ \u005c\n+/a%/.. \u005c\n+/w.../ \u005c\n+/w../. \u005c\n+/w..// \u005c\n+/w../a \u005c\n+/w../w \u005c\n+/w../? \u005c\n+/w../% \u005c\n+/w./.. \u005c\n+/w/... \u005c\n+/w/../ \u005c\n+/w/..a \u005c\n+/w/..w \u005c\n+/w/..? \u005c\n+/w/..% \u005c\n+/w//.. \u005c\n+/wa../ \u005c\n+/wa/.. \u005c\n+/ww../ \u005c\n+/ww/.. \u005c\n+/w?../ \u005c\n+/w?/.. \u005c\n+/w%../ \u005c\n+/w%/.. \u005c\n+/?.../ \u005c\n+/?../. \u005c\n+/?..// \u005c\n+/?../a \u005c\n+/?../w \u005c\n+/?../? \u005c\n+/?../% \u005c\n+/?./.. \u005c\n+/?/... \u005c\n+/?/../ \u005c\n+/?/..a \u005c\n+/?/..w \u005c\n+/?/..? \u005c\n+/?/..% \u005c\n+/?//.. \u005c\n+/?a../ \u005c\n+/?a/.. \u005c\n+/?w../ \u005c\n+/?w/.. \u005c\n+/??../ \u005c\n+/??/.. \u005c\n+/?%../ \u005c\n+/?%/.. \u005c\n+/%.../ \u005c\n+/%../. \u005c\n+/%..// \u005c\n+/%../a \u005c\n+/%../w \u005c\n+/%../? \u005c\n+/%../% \u005c\n+/%./.. \u005c\n+/%/... \u005c\n+/%/../ \u005c\n+/%/..a \u005c\n+/%/..w \u005c\n+/%/..? \u005c\n+/%/..% \u005c\n+/%//.. \u005c\n+/%a../ \u005c\n+/%a/.. \u005c\n+/%w../ \u005c\n+/%w/.. \u005c\n+/%?../ \u005c\n+/%?/.. \u005c\n+/%%../ \u005c\n+/%%/.. \u005c\n+/a/w/../a \u005c\n+/path/to/dir/../other/dir \u005c\n+; do\n+\n+R\u003d`rm -f /tmp/lwscap ; echo -n -e \u0022GET $i HTTP/1.0\u005cr\u005cn\u005cr\u005cn\u0022 | nc localhost 7681 2\u003e/dev/null \u003e/tmp/lwscap; head -n1 /tmp/lwscap| cut -d' ' -f2`\n+\n+#echo \u003d\u003d\u003d\u003d $R\n+\n+\n+if [ \u0022$R\u0022 !\u003d \u0022403\u0022 ]; then\n+\tU\u003d`cat $LOG | grep Method: | tail -n 1 | cut -d\u0022'\u0022 -f4 | sed \u0022s|\u005c\u005c'||g\u0022`\n+\techo \u0022- \u005c\u0022$i\u005c\u0022 -\u003e $R \u005c\u0022$U\u005c\u0022\u0022 \u003e\u003e/tmp/results\n+else\n+\techo \u0022- \u005c\u0022$i\u005c\u0022 -\u003e $R\u0022 \u003e\u003e/tmp/results\n+fi\n+done\n+\n+cat \u003c\u003cEOF \u003e/tmp/lwsresult1\n+- \u0022/..../\u0022 -\u003e 404 \u0022/..../\u0022\n+- \u0022/.../.\u0022 -\u003e 404 \u0022/.../\u0022\n+- \u0022/...//\u0022 -\u003e 404 \u0022/.../\u0022\n+- \u0022/.../a\u0022 -\u003e 404 \u0022/.../a\u0022\n+- \u0022/.../w\u0022 -\u003e 404 \u0022/.../w\u0022\n+- \u0022/.../?\u0022 -\u003e 404 \u0022/.../\u0022\n+- \u0022/.../%\u0022 -\u003e 403\n+- \u0022/../..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/.././\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/../.a\u0022 -\u003e 404 \u0022/.a\u0022\n+- \u0022/../.w\u0022 -\u003e 404 \u0022/.w\u0022\n+- \u0022/../..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/../.%\u0022 -\u003e 403\n+- \u0022/..//.\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/..///\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/..//a\u0022 -\u003e 404 \u0022/a\u0022\n+- \u0022/..//w\u0022 -\u003e 404 \u0022/w\u0022\n+- \u0022/..//?\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/..//%\u0022 -\u003e 403\n+- \u0022/../a.\u0022 -\u003e 404 \u0022/a.\u0022\n+- \u0022/../a/\u0022 -\u003e 404 \u0022/a/\u0022\n+- \u0022/../aa\u0022 -\u003e 404 \u0022/aa\u0022\n+- \u0022/../aw\u0022 -\u003e 404 \u0022/aw\u0022\n+- \u0022/../a?\u0022 -\u003e 404 \u0022/a\u0022\n+- \u0022/../a%\u0022 -\u003e 403\n+- \u0022/../w.\u0022 -\u003e 404 \u0022/w.\u0022\n+- \u0022/../w/\u0022 -\u003e 404 \u0022/w/\u0022\n+- \u0022/../wa\u0022 -\u003e 404 \u0022/wa\u0022\n+- \u0022/../ww\u0022 -\u003e 404 \u0022/ww\u0022\n+- \u0022/../w?\u0022 -\u003e 404 \u0022/w\u0022\n+- \u0022/../w%\u0022 -\u003e 403\n+- \u0022/../?.\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/../?/\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/../?a\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/../?w\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/../??\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/../?%\u0022 -\u003e 403\n+- \u0022/../%.\u0022 -\u003e 403\n+- \u0022/../%/\u0022 -\u003e 403\n+- \u0022/../%a\u0022 -\u003e 403\n+- \u0022/../%w\u0022 -\u003e 403\n+- \u0022/../%?\u0022 -\u003e 403\n+- \u0022/../%%\u0022 -\u003e 403\n+- \u0022/./...\u0022 -\u003e 404 \u0022/...\u0022\n+- \u0022/./../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/./..a\u0022 -\u003e 404 \u0022/..a\u0022\n+- \u0022/./..w\u0022 -\u003e 404 \u0022/..w\u0022\n+- \u0022/./..?\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/./..%\u0022 -\u003e 403\n+- \u0022/.//..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/.a../\u0022 -\u003e 404 \u0022/.a../\u0022\n+- \u0022/.a/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/.w../\u0022 -\u003e 404 \u0022/.w../\u0022\n+- \u0022/.w/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/.?../\u0022 -\u003e 404 \u0022/.\u0022\n+- \u0022/../..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/.%../\u0022 -\u003e 403\n+- \u0022/.%/..\u0022 -\u003e 403\n+- \u0022//....\u0022 -\u003e 404 \u0022/....\u0022\n+- \u0022//.../\u0022 -\u003e 404 \u0022/.../\u0022\n+- \u0022//...a\u0022 -\u003e 404 \u0022/...a\u0022\n+- \u0022//...w\u0022 -\u003e 404 \u0022/...w\u0022\n+- \u0022//...?\u0022 -\u003e 404 \u0022/...\u0022\n+- \u0022//...%\u0022 -\u003e 403\n+- \u0022//../.\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//..//\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//../a\u0022 -\u003e 404 \u0022/a\u0022\n+- \u0022//../w\u0022 -\u003e 404 \u0022/w\u0022\n+- \u0022//../?\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//../%\u0022 -\u003e 403\n+- \u0022//..a.\u0022 -\u003e 404 \u0022/..a.\u0022\n+- \u0022//..a/\u0022 -\u003e 404 \u0022/..a/\u0022\n+- \u0022//..aa\u0022 -\u003e 404 \u0022/..aa\u0022\n+- \u0022//..aw\u0022 -\u003e 404 \u0022/..aw\u0022\n+- \u0022//..a?\u0022 -\u003e 404 \u0022/..a\u0022\n+- \u0022//..a%\u0022 -\u003e 403\n+- \u0022//..w.\u0022 -\u003e 404 \u0022/..w.\u0022\n+- \u0022//..w/\u0022 -\u003e 404 \u0022/..w/\u0022\n+- \u0022//..wa\u0022 -\u003e 404 \u0022/..wa\u0022\n+- \u0022//..ww\u0022 -\u003e 404 \u0022/..ww\u0022\n+- \u0022//..w?\u0022 -\u003e 404 \u0022/..w\u0022\n+- \u0022//..w%\u0022 -\u003e 403\n+- \u0022//..?.\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//..?/\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//..?a\u0022 -\u003e 404 \u0022/a\u0022\n+- \u0022//..?w\u0022 -\u003e 404 \u0022/w\u0022\n+- \u0022//..??\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//..?%\u0022 -\u003e 403\n+- \u0022//..%.\u0022 -\u003e 403\n+- \u0022//..%/\u0022 -\u003e 403\n+- \u0022//..%a\u0022 -\u003e 403\n+- \u0022//..%w\u0022 -\u003e 403\n+- \u0022//..%?\u0022 -\u003e 403\n+- \u0022//..%%\u0022 -\u003e 403\n+- \u0022//./..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022///...\u0022 -\u003e 404 \u0022/...\u0022\n+- \u0022///../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022///..a\u0022 -\u003e 404 \u0022/..a\u0022\n+- \u0022///..w\u0022 -\u003e 404 \u0022/..w\u0022\n+- \u0022///..?\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022///..%\u0022 -\u003e 403\n+- \u0022////..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//a../\u0022 -\u003e 404 \u0022/a../\u0022\n+- \u0022//a/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//w../\u0022 -\u003e 404 \u0022/w../\u0022\n+- \u0022//w/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//?../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//?/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022//%../\u0022 -\u003e 403\n+- \u0022//%/..\u0022 -\u003e 403\n+- \u0022/a.../\u0022 -\u003e 404 \u0022/a.../\u0022\n+- \u0022/a../.\u0022 -\u003e 404 \u0022/a../\u0022\n+- \u0022/a..//\u0022 -\u003e 404 \u0022/a../\u0022\n+- \u0022/a../a\u0022 -\u003e 404 \u0022/a../a\u0022\n+- \u0022/a../w\u0022 -\u003e 404 \u0022/a../w\u0022\n+- \u0022/a../?\u0022 -\u003e 404 \u0022/a../\u0022\n+- \u0022/a../%\u0022 -\u003e 403\n+- \u0022/a./..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/a/...\u0022 -\u003e 404 \u0022/a/...\u0022\n+- \u0022/a/../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/a/..a\u0022 -\u003e 404 \u0022/a/..a\u0022\n+- \u0022/a/..w\u0022 -\u003e 404 \u0022/a/..w\u0022\n+- \u0022/a/..?\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/a/..%\u0022 -\u003e 403\n+- \u0022/a//..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/aa../\u0022 -\u003e 404 \u0022/aa../\u0022\n+- \u0022/aa/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/aw../\u0022 -\u003e 404 \u0022/aw../\u0022\n+- \u0022/aw/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/a?../\u0022 -\u003e 404 \u0022/a\u0022\n+- \u0022/a?/..\u0022 -\u003e 404 \u0022/a\u0022\n+- \u0022/a%../\u0022 -\u003e 403\n+- \u0022/a%/..\u0022 -\u003e 403\n+- \u0022/w.../\u0022 -\u003e 404 \u0022/w.../\u0022\n+- \u0022/w../.\u0022 -\u003e 404 \u0022/w../\u0022\n+- \u0022/w..//\u0022 -\u003e 404 \u0022/w../\u0022\n+- \u0022/w../a\u0022 -\u003e 404 \u0022/w../a\u0022\n+- \u0022/w../w\u0022 -\u003e 404 \u0022/w../w\u0022\n+- \u0022/w../?\u0022 -\u003e 404 \u0022/w../\u0022\n+- \u0022/w../%\u0022 -\u003e 403\n+- \u0022/w./..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/w/...\u0022 -\u003e 404 \u0022/w/...\u0022\n+- \u0022/w/../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/w/..a\u0022 -\u003e 404 \u0022/w/..a\u0022\n+- \u0022/w/..w\u0022 -\u003e 404 \u0022/w/..w\u0022\n+- \u0022/w/..?\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/w/..%\u0022 -\u003e 403\n+- \u0022/w//..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/wa../\u0022 -\u003e 404 \u0022/wa../\u0022\n+- \u0022/wa/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/ww../\u0022 -\u003e 404 \u0022/ww../\u0022\n+- \u0022/ww/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/w?../\u0022 -\u003e 404 \u0022/w\u0022\n+- \u0022/w?/..\u0022 -\u003e 404 \u0022/w\u0022\n+- \u0022/w%../\u0022 -\u003e 403\n+- \u0022/w%/..\u0022 -\u003e 403\n+- \u0022/?.../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?../.\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?..//\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?../a\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?../w\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?../?\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?../%\u0022 -\u003e 403\n+- \u0022/?./..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?/...\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?/../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?/..a\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?/..w\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?/..?\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?/..%\u0022 -\u003e 403\n+- \u0022/?//..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?a../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?a/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?w../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?w/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/??../\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/??/..\u0022 -\u003e 200 \u0022/\u0022\n+- \u0022/?%../\u0022 -\u003e 403\n+- \u0022/?%/..\u0022 -\u003e 403\n+- \u0022/%.../\u0022 -\u003e 403\n+- \u0022/%../.\u0022 -\u003e 403\n+- \u0022/%..//\u0022 -\u003e 403\n+- \u0022/%../a\u0022 -\u003e 403\n+- \u0022/%../w\u0022 -\u003e 403\n+- \u0022/%../?\u0022 -\u003e 403\n+- \u0022/%../%\u0022 -\u003e 403\n+- \u0022/%./..\u0022 -\u003e 403\n+- \u0022/%/...\u0022 -\u003e 403\n+- \u0022/%/../\u0022 -\u003e 403\n+- \u0022/%/..a\u0022 -\u003e 403\n+- \u0022/%/..w\u0022 -\u003e 403\n+- \u0022/%/..?\u0022 -\u003e 403\n+- \u0022/%/..%\u0022 -\u003e 403\n+- \u0022/%//..\u0022 -\u003e 403\n+- \u0022/%a../\u0022 -\u003e 403\n+- \u0022/%a/..\u0022 -\u003e 403\n+- \u0022/%w../\u0022 -\u003e 403\n+- \u0022/%w/..\u0022 -\u003e 403\n+- \u0022/%?../\u0022 -\u003e 403\n+- \u0022/%?/..\u0022 -\u003e 403\n+- \u0022/%%../\u0022 -\u003e 403\n+- \u0022/%%/..\u0022 -\u003e 403\n+- \u0022/a/w/../a\u0022 -\u003e 404 \u0022/a/a\u0022\n+- \u0022/path/to/dir/../other/dir\u0022 -\u003e 404 \u0022/path/to/other/dir\u0022\n+EOF\n+\n+if [ \u0022`md5sum /tmp/results | cut -d' ' -f 1`\u0022 !\u003d \u0022`md5sum /tmp/lwsresult1 | cut -d' ' -f1`\u0022 ] ; then\n+\techo \u0022Differences...\u0022\n+\tdiff -urN /tmp/lwsresult1 /tmp/results\n+\texit 1\n+else\n+\techo \u0022OK\u0022\n+fi\n+\n+\n+echo\n+echo \u0022--- survived OK ---\u0022\n+kill -2 $CPID\n+\n+exit 0\n+\n+# coverage...\n+# run the test client against mirror for one period and exit\n+killall libwebsockets-test-server 2\u003e/dev/null\n+libwebsockets-test-server -s 2\u003e\u003e $LOG \u0026\n+CPID\u003d$!\n+sleep 1s\n+libwebsockets-test-client 127.0.0.1 -s -O\n+\n+# https://github.com/curl/curl/issues/1587\n+curl -v -F text\u003dhello -F send\u003dSEND -F upload\u003d@../README.md https://127.0.0.1:7681/formtest -k\n+\n+kill -2 $CPID\n+\n+exit 0\n+\n+\ndiff --git a/scripts/travis_control.sh b/scripts/travis_control.sh\nindex 2eef3cf..a5fe7e6 100755\n--- a/scripts/travis_control.sh\n+++ b/scripts/travis_control.sh\n@@ -14,7 +14,7 @@ else\n \t\t\tsudo make install \u0026\u0026\n \t\t\t../minimal-examples/selftests.sh \u0026\u0026\n \t\t\t../scripts/h2spec.sh \u0026\u0026\n-\t\t\t../test-apps/attack.sh \u0026\u0026\n+\t\t\t../scripts/attack.sh \u0026\u0026\n \t\t\t../scripts/h2load.sh \u0026\u0026\n \t\t\t../scripts/autobahn-test.sh\n \t\telse\ndiff --git a/test-apps/attack.sh b/test-apps/attack.sh\ndeleted file mode 100755\nindex 38c6cd5..0000000\n--- a/test-apps/attack.sh\n+++ /dev/null\n@@ -1,804 +0,0 @@\n-#!/bin/bash\n-#\n-# attack the test server and try to make it fall over\n-#\n-# Requires the library to have been built with cmake .. -DCMAKE_BUILD_TYPE\u003dDEBUG\n-\n-echo\n-echo \u0022----------------------------------------------\u0022\n-echo \u0022------- tests: lws attack.sh\u0022\n-echo\n-\n-SERVER\u003d127.0.0.1\n-PORT\u003d7681\n-LOG\u003d/tmp/lwslog\n-\n-A\u003d`which libwebsockets-test-server`\n-INSTALLED\u003d`dirname $A`\n-\n-CPID\u003d\n-LEN\u003d0\n-\n-function check {\n-\tkill -0 $CPID\n-\tif [ $? -ne 0 ] ; then\n-\t\techo \u0022(killed it) *******\u0022\n-\t\texit 1\n-\tfi\n-\t#dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null\n-\n-\tif [ \u0022$1\u0022 \u003d \u0022default\u0022 ] ; then\n-\t\tdiff /tmp/lwscap $INSTALLED/../share/libwebsockets-test-server/test.html \u003e /dev/null\n-\t\tif [ $? -ne 0 ] ; then\n-\t\t\techo \u0022FAIL: got something other than test.html back\u0022\n-\t\t\texit 1\n-\t\tfi\n-\tfi\n-\tif [ \u0022$1\u0022 \u003d \u0022defaultplusforbidden\u0022 ] ; then\n-\tcat $INSTALLED/../share/libwebsockets-test-server/test.html \u003e /tmp/plusforb\n-\techo -e -n \u0022HTTP/1.0 403 Forbidden\u005cx0d\u005cx0acontent-type: text/html\u005cx0d\u005cx0acontent-length: 38\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u003chtml\u003e\u003cbody\u003e\u003ch1\u003e403\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e\u0022 \u003e\u003e /tmp/plusforb\n-\t\tdiff /tmp/lwscap /tmp/plusforb \u003e /dev/null\n-\t\tif [ $? -ne 0 ] ; then\n-\t\t\tcat $INSTALLED/../share/libwebsockets-test-server/test.html \u003e /tmp/plusforb\n-\n-\t\t\techo -e -n \u0022HTTP/1.1 403 Forbidden\u005cx0d\u005cx0acontent-type: text/html\u005cx0d\u005cx0acontent-length: 38\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u003chtml\u003e\u003cbody\u003e\u003ch1\u003e403\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e\u0022 \u003e\u003e /tmp/plusforb\n-\t\t\tdiff /tmp/lwscap /tmp/plusforb \u003e /dev/null\n-\t\t\tif [ $? -ne 0 ] ; then\n-\n-\t\t\t\techo \u0022FAIL: got something other than test.html + forbidden back\u0022\n-\t\t\t\texit 1\n-\t\t\tfi\n-\t\tfi\n-\tfi\n-\n-\tif [ \u0022$1\u0022 \u003d \u0022forbidden\u0022 ] ; then\n-\t\tif [ -z \u0022`grep '\u003ch1\u003e403\u003c/h1\u003e' /tmp/lwscap`\u0022 ] ; then\n-\t\t\techo \u0022FAIL: should have told forbidden (test server has no dirs)\u0022\n-\t\t\texit 1\n-\t\tfi\n-\tfi\n-\n-\tif [ \u0022$1\u0022 \u003d \u0022rejected\u0022 ] ; then\n-\t\tif [ -z \u0022`grep '\u003ch1\u003e406\u003c/h1\u003e' /tmp/lwscap`\u0022 ] ; then\n-\t\t\techo \u0022FAIL: should have told forbidden (test server has no dirs)\u0022\n-\t\t\texit 1\n-\t\tfi\n-\tfi\n-\n-\n-\tif [ \u0022$1\u0022 \u003d \u0022media\u0022 ] ; then\n-\t\tif [ -z \u0022`grep '\u003ch1\u003e415\u003c/h1\u003e' /tmp/lwscap`\u0022 ] ; then\n-\t\t\techo \u0022FAIL: should have told unknown media type\u0022\n-\t\t\texit 1\n-\t\tfi\n-\tfi\n-\n-\tif [ \u0022$1\u0022 \u003d\u003d \u00220\u0022 ] ; then\n-\t\ta\u003d\u0022`dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null |grep \u0022get\u005c \u005c \u003d\u0022 | tr -s ' ' | cut -d' ' -f4-`\u0022\n-\t\tif [ \u0022$a\u0022 !\u003d \u0022$2\u0022 ] ; then\n-\t\t\techo \u0022URL path '$a' not $2\u0022\n-\t\t\texit 1\n-\t\tfi\n-\tfi\n-\n-\tif [ \u0022$1\u0022 \u003d\u003d \u00221\u0022 ] ; then\n-\t\ta\u003d\u0022`dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null |grep URI\u005c Arg\u005c 1\u005c: | tr -s ' ' | cut -d' ' -f7-`\u0022\n-\t\tif [ \u0022$a\u0022 !\u003d \u0022$2\u0022 ] ; then\n-\t\t\techo \u0022Arg 1 '$a' not $2\u0022\n-\t\t\texit 1\n-\t\tfi\n-\tfi\n-\n-\tif [ \u0022$1\u0022 \u003d\u003d \u00222\u0022 ] ; then\n-\t\ta\u003d\u0022`dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null |grep URI\u005c Arg\u005c 2\u005c: | tr -s ' ' | cut -d' ' -f7-`\u0022\n-\t\tif [ \u0022$a\u0022 !\u003d \u0022$2\u0022 ] ; then\n-\t\t\techo \u0022Arg 2 '$a' not $2\u0022\n-\t\t\texit 1\n-\t\tfi\n-\tfi\n-\tif [ \u0022$1\u0022 \u003d\u003d \u00223\u0022 ] ; then\n-\t\ta\u003d\u0022`dd if\u003d$LOG bs\u003d1 skip\u003d$LEN 2\u003e/dev/null |grep URI\u005c Arg\u005c 3\u005c: | tr -s ' ' | cut -d' ' -f7-`\u0022\n-\t\tif [ \u0022$a\u0022 !\u003d \u0022$2\u0022 ] ; then\n-\t\t\techo \u0022Arg 3 '$a' not $2\u0022\n-\t\t\texit 1\n-\t\tfi\n-\tfi\n-\n-\tif [ -z \u0022$1\u0022 ] ; then\n-\t\tLEN\u003d`stat $LOG -c %s`\n-\tfi\n-}\n-\n-\n-rm -rf $LOG\n-killall libwebsockets-test-server 2\u003e/dev/null\n-libwebsockets-test-server -d15 2\u003e\u003e $LOG \u003e/dev/null \u0026\n-CPID\u003d$!\n-\n-echo \u0022Started server on PID $CPID\u0022\n-\n-while [ -z \u0022`grep ort\u005c 7681 $LOG`\u0022 ] ; do\n-\tsleep 0.5s\n-done\n-check\n-\n-echo\n-echo \u0022---- /cgi-bin/settingsjs?UPDATE_SETTINGS\u003d1\u0026Root_Channels_1_Channel_name_http_post\u003d%3F\u0026Root_Channels_1_Channel_location_http_post\u003d%3F\u0022\n-rm -f /tmp/lwscap\n-echo -n -e \u0022GET /cgi-bin/settingsjs?UPDATE_SETTINGS\u003d1\u0026Root_Channels_1_Channel_name_http_post\u003d%3F\u0026Root_Channels_1_Channel_location_http_post\u003d%3F HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check 1 \u0022UPDATE_SETTINGS\u003d1\u0022\n-check 2 \u0022Root_Channels_1_Channel_name_http_post\u003d?\u0022\n-check 3 \u0022Root_Channels_1_Channel_location_http_post\u003d?\u0022\n-check\n-\n-echo\n-echo \u0022---- ? processing (/cgi-bin/settings.js?key1\u003dvalue1)\u0022\n-rm -f /tmp/lwscap\n-echo -n -e \u0022GET /cgi-bin/settings.js?key1\u003dvalue1 HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check 1 \u0022key1\u003dvalue1\u0022\n-check\n-\n-echo\n-echo \u0022---- ? processing (/t%3dest?key1%3d2\u003dvalue1)\u0022\n-rm -f /tmp/lwscap\n-echo -n -e \u0022GET /t%3dest?key1%3d2\u003dvalue1 HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check 0 \u0022/t\u003dest\u0022\n-check 1 \u0022key1_2\u003dvalue1\u0022\n-check\n-\n-echo\n-echo \u0022---- ? processing (%2f%2e%2e%2f%2e./test.html?arg\u003d1)\u0022\n-rm -f /tmp/lwscap\n-echo -n -e \u0022GET %2f%2e%2e%2f%2e./test.html?arg\u003d1 HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check 1 \u0022arg\u003d1\u0022\n-check\n-\n-echo\n-echo \u0022---- ? processing (%2f%2e%2e%2f%2e./test.html?arg\u003d/../.)\u0022\n-rm -f /tmp/lwscap\n-echo -n -e \u0022GET %2f%2e%2e%2f%2e./test.html?arg\u003d/../. HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check 1 \u0022arg\u003d/../.\u0022\n-check\n-\n-echo\n-echo \u0022---- spam enough crap to not be GET\u0022\n-echo \u0022not GET\u0022 | nc $SERVER $PORT\n-check\n-\n-echo\n-echo \u0022---- spam more than the name buffer of crap\u0022\n-dd if\u003d/dev/urandom bs\u003d1 count\u003d80 2\u003e/dev/null | nc -i1s $SERVER $PORT\n-check\n-\n-echo\n-echo \u0022---- spam 10MB of crap\u0022\n-dd if\u003d/dev/urandom bs\u003d1 count\u003d655360 | nc -i1s $SERVER $PORT\n-check\n-\n-echo\n-echo \u0022---- malformed URI\u0022\n-echo \u0022GET nonsense................................................................................................................\u0022 \u005c\n-\t| nc -i1s $SERVER $PORT\n-check\n-\n-echo\n-echo \u0022---- missing URI\u0022\n-echo -n -e \u0022GET HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc -i1s $SERVER $PORT \u003e/tmp/lwscap\n-check\n-\n-echo\n-echo \u0022---- repeated method\u0022\n-echo -n -e \u0022GET blah HTTP/1.0\u005cx0d\u005cx0aGET blah HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT \u003e/tmp/lwscap \n-check\n-\n-echo\n-echo \u0022---- crazy header name part\u0022\n-echo -n -e \u0022GET blah HTTP/1.0\u005cx0d\u005cx0a................................................................................................................\u0022 \u005c\n-\t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n-\t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- | nc -i1s $SERVER $PORT\n-check\n-\n-echo\n-echo \u0022---- excessive uri content\u0022\n-echo -n -e \u0022GET ................................................................................................................\u0022 \u005c\n-\t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n-\t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- | nc -i1s $SERVER $PORT\n-check\n-\n-echo\n-echo \u0022---- good request but http payload coming too (test.html served then forbidden)\u0022\n-echo -n -e \u0022GET /test.html HTTP/1.1\u005cx0d\u005cx0a\u005cx0d\u005cx0aILLEGAL-PAYLOAD........................................\u0022 \u005c\n-\t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n-\t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n- \t\u0022.......................................................................................................................\u0022 \u005c\n-\t | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check defaultplusforbidden\n-check\n-\n-echo\n-echo \u0022---- nonexistent file\u0022\n-rm -f /tmp/lwscap\n-echo -n -e \u0022GET /nope HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check media\n-check\n-\n-echo\n-echo \u0022---- relative uri path\u0022\n-rm -f /tmp/lwscap\n-echo -n -e \u0022GET nope HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check forbidden\n-check\n-\n-echo\n-echo \u0022---- directory attack 1 (/../../../../etc/passwd should be /etc/passswd)\u0022\n-rm -f /tmp/lwscap\n-echo -n -e \u0022GET /../../../../etc/passwd HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check rejected\n-check\n-\n-echo\n-echo \u0022---- directory attack 2 (/../ should be /)\u0022\n-rm -f /tmp/lwscap\n-echo -e -n \u0022GET /../ HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check default\n-check\n-\n-echo\n-echo \u0022---- directory attack 3 (/./ should be /)\u0022\n-rm -f /tmp/lwscap\n-echo -e -n \u0022GET /./ HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check default\n-check\n-\n-echo\n-echo \u0022---- directory attack 4 (/blah/.. should be /)\u0022\n-rm -f /tmp/lwscap\n-echo -e -n \u0022GET /blah/.. HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check default\n-check\n-\n-echo\n-echo \u0022---- directory attack 5 (/blah/../ should be /)\u0022\n-rm -f /tmp/lwscap\n-echo -e -n \u0022GET /blah/../ HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check default\n-check\n-\n-echo\n-echo \u0022---- directory attack 6 (/blah/../. should be /)\u0022\n-rm -f /tmp/lwscap\n-echo -e -n \u0022GET /blah/../. HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check default\n-check\n-\n-echo\n-echo \u0022---- directory attack 7 (/%2e%2e%2f../../../etc/passwd should be /etc/passswd)\u0022\n-rm -f /tmp/lwscap\n-echo -e -n \u0022GET /%2e%2e%2f../../../etc/passwd HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check rejected\n-check\n-\n-echo\n-echo \u0022---- directory attack 8 (%2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd should be /etc/passswd)\u0022\n-rm -f /tmp/lwscap\n-echo -e -n \u0022GET %2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd HTTP/1.0\u005cx0d\u005cx0a\u005cx0d\u005cx0a\u0022 | nc $SERVER $PORT | sed '1,/^\u005cr$/d'\u003e /tmp/lwscap\n-check rejected\n-check\n-\n-echo\n-echo \u0022---- http/1.1 pipelining\u0022\n-rm -f /tmp/lwscap\n-wget -O/tmp/lwsdump http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html http://localhost:7681/test.html 2\u003e\u00261 | grep \u0022Downloaded: 8 files\u0022 \u003e /tmp/lwscap\n-good\u003d`cat $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html $INSTALLED/../share/libwebsockets-test-server/test.html | md5sum | cut -d' ' -f1`\n-if [ \u0022$good\u0022 !\u003d \u0022`md5sum /tmp/lwsdump | cut -d' ' -f 1`\u0022 ] ; then\n-\techo \u0022FAIL: mismatched content good\u003d$good received\u003d`md5sum /tmp/lwsdump`\u0022\n-\texit 1\n-fi\n-\n-echo\n-echo \u0022---- mass testing uri variations\u0022\n-\n-rm -f /tmp/results\n-\n-for i in \u005c\n-/..../ \u005c\n-/.../. \u005c\n-/...// \u005c\n-/.../a \u005c\n-/.../w \u005c\n-\u0022/.../?\u0022 \u005c\n-/.../% \u005c\n-/../.. \u005c\n-/.././ \u005c\n-/../.a \u005c\n-/../.w \u005c\n-/../.. \u005c\n-/../.% \u005c\n-/..//. \u005c\n-/../// \u005c\n-/..//a \u005c\n-/..//w \u005c\n-\u0022/..//?\u0022 \u005c\n-/..//% \u005c\n-/../a. \u005c\n-/../a/ \u005c\n-/../aa \u005c\n-/../aw \u005c\n-/../a? \u005c\n-/../a% \u005c\n-/../w. \u005c\n-/../w/ \u005c\n-/../wa \u005c\n-/../ww \u005c\n-/../w? \u005c\n-/../w% \u005c\n-/../?. \u005c\n-/../?/ \u005c\n-/../?a \u005c\n-/../?w \u005c\n-/../?? \u005c\n-/../?% \u005c\n-/../%. \u005c\n-/../%/ \u005c\n-/../%a \u005c\n-/../%w \u005c\n-/../%? \u005c\n-/../%% \u005c\n-/./... \u005c\n-/./../ \u005c\n-/./..a \u005c\n-/./..w \u005c\n-/./..? \u005c\n-/./..% \u005c\n-/.//.. \u005c\n-/.a../ \u005c\n-/.a/.. \u005c\n-/.w../ \u005c\n-/.w/.. \u005c\n-/.?../ \u005c\n-/../.. \u005c\n-/.%../ \u005c\n-/.%/.. \u005c\n-//.... \u005c\n-//.../ \u005c\n-//...a \u005c\n-//...w \u005c\n-//...? \u005c\n-//...% \u005c\n-//../. \u005c\n-//..// \u005c\n-//../a \u005c\n-//../w \u005c\n-//../? \u005c\n-//../% \u005c\n-//..a. \u005c\n-//..a/ \u005c\n-//..aa \u005c\n-//..aw \u005c\n-//..a? \u005c\n-//..a% \u005c\n-//..w. \u005c\n-//..w/ \u005c\n-//..wa \u005c\n-//..ww \u005c\n-//..w? \u005c\n-//..w% \u005c\n-//..?. \u005c\n-//..?/ \u005c\n-//..?a \u005c\n-//..?w \u005c\n-//..?? \u005c\n-//..?% \u005c\n-//..%. \u005c\n-//..%/ \u005c\n-//..%a \u005c\n-//..%w \u005c\n-//..%? \u005c\n-//..%% \u005c\n-//./.. \u005c\n-///... \u005c\n-///../ \u005c\n-///..a \u005c\n-///..w \u005c\n-///..? \u005c\n-///..% \u005c\n-////.. \u005c\n-//a../ \u005c\n-//a/.. \u005c\n-//w../ \u005c\n-//w/.. \u005c\n-//?../ \u005c\n-//?/.. \u005c\n-//%../ \u005c\n-//%/.. \u005c\n-/a.../ \u005c\n-/a../. \u005c\n-/a..// \u005c\n-/a../a \u005c\n-/a../w \u005c\n-/a../? \u005c\n-/a../% \u005c\n-/a./.. \u005c\n-/a/... \u005c\n-/a/../ \u005c\n-/a/..a \u005c\n-/a/..w \u005c\n-/a/..? \u005c\n-/a/..% \u005c\n-/a//.. \u005c\n-/aa../ \u005c\n-/aa/.. \u005c\n-/aw../ \u005c\n-/aw/.. \u005c\n-/a?../ \u005c\n-/a?/.. \u005c\n-/a%../ \u005c\n-/a%/.. \u005c\n-/w.../ \u005c\n-/w../. \u005c\n-/w..// \u005c\n-/w../a \u005c\n-/w../w \u005c\n-/w../? \u005c\n-/w../% \u005c\n-/w./.. \u005c\n-/w/... \u005c\n-/w/../ \u005c\n-/w/..a \u005c\n-/w/..w \u005c\n-/w/..? \u005c\n-/w/..% \u005c\n-/w//.. \u005c\n-/wa../ \u005c\n-/wa/.. \u005c\n-/ww../ \u005c\n-/ww/.. \u005c\n-/w?../ \u005c\n-/w?/.. \u005c\n-/w%../ \u005c\n-/w%/.. \u005c\n-/?.../ \u005c\n-/?../. \u005c\n-/?..// \u005c\n-/?../a \u005c\n-/?../w \u005c\n-/?../? \u005c\n-/?../% \u005c\n-/?./.. \u005c\n-/?/... \u005c\n-/?/../ \u005c\n-/?/..a \u005c\n-/?/..w \u005c\n-/?/..? \u005c\n-/?/..% \u005c\n-/?//.. \u005c\n-/?a../ \u005c\n-/?a/.. \u005c\n-/?w../ \u005c\n-/?w/.. \u005c\n-/??../ \u005c\n-/??/.. \u005c\n-/?%../ \u005c\n-/?%/.. \u005c\n-/%.../ \u005c\n-/%../. \u005c\n-/%..// \u005c\n-/%../a \u005c\n-/%../w \u005c\n-/%../? \u005c\n-/%../% \u005c\n-/%./.. \u005c\n-/%/... \u005c\n-/%/../ \u005c\n-/%/..a \u005c\n-/%/..w \u005c\n-/%/..? \u005c\n-/%/..% \u005c\n-/%//.. \u005c\n-/%a../ \u005c\n-/%a/.. \u005c\n-/%w../ \u005c\n-/%w/.. \u005c\n-/%?../ \u005c\n-/%?/.. \u005c\n-/%%../ \u005c\n-/%%/.. \u005c\n-/a/w/../a \u005c\n-/path/to/dir/../other/dir \u005c\n-; do\n-\n-R\u003d`rm -f /tmp/lwscap ; echo -n -e \u0022GET $i HTTP/1.0\u005cr\u005cn\u005cr\u005cn\u0022 | nc localhost 7681 2\u003e/dev/null \u003e/tmp/lwscap; head -n1 /tmp/lwscap| cut -d' ' -f2`\n-\n-#cat /tmp/lwscap | head -n1\n-#echo \u003d\u003d\u003d\u003d $R\n-\n-\n-if [ \u0022$R\u0022 !\u003d \u0022403\u0022 ]; then\n-\tU\u003d`cat $LOG | grep lws_http_serve | tail -n 1 | cut -d':' -f6 | cut -d' ' -f2`\n-#\techo $U\n-\techo \u0022- \u005c\u0022$i\u005c\u0022 -\u003e $R \u005c\u0022$U\u005c\u0022\u0022 \u003e\u003e/tmp/results\n-else\n-\techo \u0022- \u005c\u0022$i\u005c\u0022 -\u003e $R\u0022 \u003e\u003e/tmp/results\n-fi\n-done\n-\n-cat \u003c\u003cEOF \u003e/tmp/lwsresult1\n-- \u0022/..../\u0022 -\u003e 406 \u0022/..../\u0022\n-- \u0022/.../.\u0022 -\u003e 406 \u0022/.../\u0022\n-- \u0022/...//\u0022 -\u003e 406 \u0022/.../\u0022\n-- \u0022/.../a\u0022 -\u003e 406 \u0022/.../a\u0022\n-- \u0022/.../w\u0022 -\u003e 406 \u0022/.../w\u0022\n-- \u0022/.../?\u0022 -\u003e 406 \u0022/.../\u0022\n-- \u0022/.../%\u0022 -\u003e 403\n-- \u0022/../..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/.././\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/../.a\u0022 -\u003e 415 \u0022/.a\u0022\n-- \u0022/../.w\u0022 -\u003e 415 \u0022/.w\u0022\n-- \u0022/../..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/../.%\u0022 -\u003e 403\n-- \u0022/..//.\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/..///\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/..//a\u0022 -\u003e 415 \u0022/a\u0022\n-- \u0022/..//w\u0022 -\u003e 415 \u0022/w\u0022\n-- \u0022/..//?\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/..//%\u0022 -\u003e 403\n-- \u0022/../a.\u0022 -\u003e 415 \u0022/a.\u0022\n-- \u0022/../a/\u0022 -\u003e 406 \u0022/a/\u0022\n-- \u0022/../aa\u0022 -\u003e 415 \u0022/aa\u0022\n-- \u0022/../aw\u0022 -\u003e 415 \u0022/aw\u0022\n-- \u0022/../a?\u0022 -\u003e 415 \u0022/a\u0022\n-- \u0022/../a%\u0022 -\u003e 403\n-- \u0022/../w.\u0022 -\u003e 415 \u0022/w.\u0022\n-- \u0022/../w/\u0022 -\u003e 406 \u0022/w/\u0022\n-- \u0022/../wa\u0022 -\u003e 415 \u0022/wa\u0022\n-- \u0022/../ww\u0022 -\u003e 415 \u0022/ww\u0022\n-- \u0022/../w?\u0022 -\u003e 415 \u0022/w\u0022\n-- \u0022/../w%\u0022 -\u003e 403\n-- \u0022/../?.\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/../?/\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/../?a\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/../?w\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/../??\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/../?%\u0022 -\u003e 403\n-- \u0022/../%.\u0022 -\u003e 403\n-- \u0022/../%/\u0022 -\u003e 403\n-- \u0022/../%a\u0022 -\u003e 403\n-- \u0022/../%w\u0022 -\u003e 403\n-- \u0022/../%?\u0022 -\u003e 403\n-- \u0022/../%%\u0022 -\u003e 403\n-- \u0022/./...\u0022 -\u003e 415 \u0022/...\u0022\n-- \u0022/./../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/./..a\u0022 -\u003e 415 \u0022/..a\u0022\n-- \u0022/./..w\u0022 -\u003e 415 \u0022/..w\u0022\n-- \u0022/./..?\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/./..%\u0022 -\u003e 403\n-- \u0022/.//..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/.a../\u0022 -\u003e 406 \u0022/.a../\u0022\n-- \u0022/.a/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/.w../\u0022 -\u003e 406 \u0022/.w../\u0022\n-- \u0022/.w/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/.?../\u0022 -\u003e 415 \u0022/.\u0022\n-- \u0022/../..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/.%../\u0022 -\u003e 403\n-- \u0022/.%/..\u0022 -\u003e 403\n-- \u0022//....\u0022 -\u003e 415 \u0022/....\u0022\n-- \u0022//.../\u0022 -\u003e 406 \u0022/.../\u0022\n-- \u0022//...a\u0022 -\u003e 415 \u0022/...a\u0022\n-- \u0022//...w\u0022 -\u003e 415 \u0022/...w\u0022\n-- \u0022//...?\u0022 -\u003e 415 \u0022/...\u0022\n-- \u0022//...%\u0022 -\u003e 403\n-- \u0022//../.\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//..//\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//../a\u0022 -\u003e 415 \u0022/a\u0022\n-- \u0022//../w\u0022 -\u003e 415 \u0022/w\u0022\n-- \u0022//../?\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//../%\u0022 -\u003e 403\n-- \u0022//..a.\u0022 -\u003e 415 \u0022/..a.\u0022\n-- \u0022//..a/\u0022 -\u003e 406 \u0022/..a/\u0022\n-- \u0022//..aa\u0022 -\u003e 415 \u0022/..aa\u0022\n-- \u0022//..aw\u0022 -\u003e 415 \u0022/..aw\u0022\n-- \u0022//..a?\u0022 -\u003e 415 \u0022/..a\u0022\n-- \u0022//..a%\u0022 -\u003e 403\n-- \u0022//..w.\u0022 -\u003e 415 \u0022/..w.\u0022\n-- \u0022//..w/\u0022 -\u003e 406 \u0022/..w/\u0022\n-- \u0022//..wa\u0022 -\u003e 415 \u0022/..wa\u0022\n-- \u0022//..ww\u0022 -\u003e 415 \u0022/..ww\u0022\n-- \u0022//..w?\u0022 -\u003e 415 \u0022/..w\u0022\n-- \u0022//..w%\u0022 -\u003e 403\n-- \u0022//..?.\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//..?/\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//..?a\u0022 -\u003e 415 \u0022/a\u0022\n-- \u0022//..?w\u0022 -\u003e 415 \u0022/w\u0022\n-- \u0022//..??\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//..?%\u0022 -\u003e 403\n-- \u0022//..%.\u0022 -\u003e 403\n-- \u0022//..%/\u0022 -\u003e 403\n-- \u0022//..%a\u0022 -\u003e 403\n-- \u0022//..%w\u0022 -\u003e 403\n-- \u0022//..%?\u0022 -\u003e 403\n-- \u0022//..%%\u0022 -\u003e 403\n-- \u0022//./..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022///...\u0022 -\u003e 415 \u0022/...\u0022\n-- \u0022///../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022///..a\u0022 -\u003e 415 \u0022/..a\u0022\n-- \u0022///..w\u0022 -\u003e 415 \u0022/..w\u0022\n-- \u0022///..?\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022///..%\u0022 -\u003e 403\n-- \u0022////..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//a../\u0022 -\u003e 406 \u0022/a../\u0022\n-- \u0022//a/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//w../\u0022 -\u003e 406 \u0022/w../\u0022\n-- \u0022//w/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//?../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//?/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022//%../\u0022 -\u003e 403\n-- \u0022//%/..\u0022 -\u003e 403\n-- \u0022/a.../\u0022 -\u003e 406 \u0022/a.../\u0022\n-- \u0022/a../.\u0022 -\u003e 406 \u0022/a../\u0022\n-- \u0022/a..//\u0022 -\u003e 406 \u0022/a../\u0022\n-- \u0022/a../a\u0022 -\u003e 406 \u0022/a../a\u0022\n-- \u0022/a../w\u0022 -\u003e 406 \u0022/a../w\u0022\n-- \u0022/a../?\u0022 -\u003e 406 \u0022/a../\u0022\n-- \u0022/a../%\u0022 -\u003e 403\n-- \u0022/a./..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/a/...\u0022 -\u003e 406 \u0022/a/...\u0022\n-- \u0022/a/../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/a/..a\u0022 -\u003e 406 \u0022/a/..a\u0022\n-- \u0022/a/..w\u0022 -\u003e 406 \u0022/a/..w\u0022\n-- \u0022/a/..?\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/a/..%\u0022 -\u003e 403\n-- \u0022/a//..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/aa../\u0022 -\u003e 406 \u0022/aa../\u0022\n-- \u0022/aa/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/aw../\u0022 -\u003e 406 \u0022/aw../\u0022\n-- \u0022/aw/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/a?../\u0022 -\u003e 415 \u0022/a\u0022\n-- \u0022/a?/..\u0022 -\u003e 415 \u0022/a\u0022\n-- \u0022/a%../\u0022 -\u003e 403\n-- \u0022/a%/..\u0022 -\u003e 403\n-- \u0022/w.../\u0022 -\u003e 406 \u0022/w.../\u0022\n-- \u0022/w../.\u0022 -\u003e 406 \u0022/w../\u0022\n-- \u0022/w..//\u0022 -\u003e 406 \u0022/w../\u0022\n-- \u0022/w../a\u0022 -\u003e 406 \u0022/w../a\u0022\n-- \u0022/w../w\u0022 -\u003e 406 \u0022/w../w\u0022\n-- \u0022/w../?\u0022 -\u003e 406 \u0022/w../\u0022\n-- \u0022/w../%\u0022 -\u003e 403\n-- \u0022/w./..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/w/...\u0022 -\u003e 406 \u0022/w/...\u0022\n-- \u0022/w/../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/w/..a\u0022 -\u003e 406 \u0022/w/..a\u0022\n-- \u0022/w/..w\u0022 -\u003e 406 \u0022/w/..w\u0022\n-- \u0022/w/..?\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/w/..%\u0022 -\u003e 403\n-- \u0022/w//..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/wa../\u0022 -\u003e 406 \u0022/wa../\u0022\n-- \u0022/wa/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/ww../\u0022 -\u003e 406 \u0022/ww../\u0022\n-- \u0022/ww/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/w?../\u0022 -\u003e 415 \u0022/w\u0022\n-- \u0022/w?/..\u0022 -\u003e 415 \u0022/w\u0022\n-- \u0022/w%../\u0022 -\u003e 403\n-- \u0022/w%/..\u0022 -\u003e 403\n-- \u0022/?.../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?../.\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?..//\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?../a\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?../w\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?../?\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?../%\u0022 -\u003e 403\n-- \u0022/?./..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?/...\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?/../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?/..a\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?/..w\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?/..?\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?/..%\u0022 -\u003e 403\n-- \u0022/?//..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?a../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?a/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?w../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?w/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/??../\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/??/..\u0022 -\u003e 200 \u0022/\u0022\n-- \u0022/?%../\u0022 -\u003e 403\n-- \u0022/?%/..\u0022 -\u003e 403\n-- \u0022/%.../\u0022 -\u003e 403\n-- \u0022/%../.\u0022 -\u003e 403\n-- \u0022/%..//\u0022 -\u003e 403\n-- \u0022/%../a\u0022 -\u003e 403\n-- \u0022/%../w\u0022 -\u003e 403\n-- \u0022/%../?\u0022 -\u003e 403\n-- \u0022/%../%\u0022 -\u003e 403\n-- \u0022/%./..\u0022 -\u003e 403\n-- \u0022/%/...\u0022 -\u003e 403\n-- \u0022/%/../\u0022 -\u003e 403\n-- \u0022/%/..a\u0022 -\u003e 403\n-- \u0022/%/..w\u0022 -\u003e 403\n-- \u0022/%/..?\u0022 -\u003e 403\n-- \u0022/%/..%\u0022 -\u003e 403\n-- \u0022/%//..\u0022 -\u003e 403\n-- \u0022/%a../\u0022 -\u003e 403\n-- \u0022/%a/..\u0022 -\u003e 403\n-- \u0022/%w../\u0022 -\u003e 403\n-- \u0022/%w/..\u0022 -\u003e 403\n-- \u0022/%?../\u0022 -\u003e 403\n-- \u0022/%?/..\u0022 -\u003e 403\n-- \u0022/%%../\u0022 -\u003e 403\n-- \u0022/%%/..\u0022 -\u003e 403\n-- \u0022/a/w/../a\u0022 -\u003e 406 \u0022/a/a\u0022\n-- \u0022/path/to/dir/../other/dir\u0022 -\u003e 406 \u0022/path/to/other/dir\u0022\n-EOF\n-\n-if [ \u0022`md5sum /tmp/results | cut -d' ' -f 1`\u0022 !\u003d \u0022`md5sum /tmp/lwsresult1 | cut -d' ' -f1`\u0022 ] ; then\n-\techo \u0022Differences...\u0022\n-\tdiff -urN /tmp/results /tmp/lwsresult1\n-\texit 1\n-else\n-\techo \u0022OK\u0022\n-fi\n-\n-\n-echo\n-echo \u0022--- survived OK ---\u0022\n-kill -2 $CPID\n-\n-exit 0\n-\n-# coverage...\n-# run the test client against mirror for one period and exit\n-killall libwebsockets-test-server 2\u003e/dev/null\n-libwebsockets-test-server -s 2\u003e\u003e $LOG \u0026\n-CPID\u003d$!\n-sleep 1s\n-libwebsockets-test-client 127.0.0.1 -s -O\n-\n-# https://github.com/curl/curl/issues/1587\n-curl -v -F text\u003dhello -F send\u003dSEND -F upload\u003d@../README.md https://127.0.0.1:7681/formtest -k\n-\n-kill -2 $CPID\n-\n-exit 0\n-\n-\ndiff --git a/test-apps/test-server.c b/test-apps/test-server.c\nindex f2cfc0d..3ad1c63 100644\n--- a/test-apps/test-server.c\n+++ b/test-apps/test-server.c\n@@ -22,6 +22,7 @@\n #include \u003cstdio.h\u003e\n #include \u003cstdlib.h\u003e\n #include \u003cgetopt.h\u003e\n+#include \u003csignal.h\u003e\n \n int close_testing;\n int max_poll_elements;\n@@ -77,12 +78,69 @@ char crl_path[1024] \u003d \u0022\u0022;\n #include \u0022../plugins/protocol_post_demo.c\u0022\n #endif\n \n+static int\n+lws_callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,\n+\t\t void *in, size_t len)\n+{\n+\tconst unsigned char *c;\n+\tchar buf[1024];\n+\tint n \u003d 0, hlen;\n+\n+\tswitch (reason) {\n+\tcase LWS_CALLBACK_HTTP:\n+\n+\t\t/* non-mount-handled accesses will turn up here */\n+\n+\t\t/* dump the headers */\n+\n+\t\tdo {\n+\t\t\tc \u003d lws_token_to_string(n);\n+\t\t\tif (!c) {\n+\t\t\t\tn++;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\thlen \u003d lws_hdr_total_length(wsi, n);\n+\t\t\tif (!hlen || hlen \u003e (int)sizeof(buf) - 1) {\n+\t\t\t\tn++;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tlws_hdr_copy(wsi, buf, sizeof buf, n);\n+\t\t\tbuf[sizeof(buf) - 1] \u003d '\u005c0';\n+\n+\t\t\tfprintf(stderr, \u0022 %s \u003d %s\u005cn\u0022, (char *)c, buf);\n+\t\t\tn++;\n+\t\t} while (c);\n+\n+\t\t/* dump the individual URI Arg parameters */\n+\n+\t\tn \u003d 0;\n+\t\twhile (lws_hdr_copy_fragment(wsi, buf, sizeof(buf),\n+\t\t\t\t\t WSI_TOKEN_HTTP_URI_ARGS, n) \u003e 0) {\n+\t\t\tlwsl_notice(\u0022URI Arg %d: %s\u005cn\u0022, ++n, buf);\n+\t\t}\n+\n+\t\tif (lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL))\n+\t\t\treturn -1;\n+\n+\t\tif (lws_http_transaction_completed(wsi))\n+\t\t\treturn -1;\n+\n+\t\treturn 0;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn lws_callback_http_dummy(wsi, reason, user, in, len);\n+}\n+\n /* list of supported protocols and callbacks */\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+\t{ \u0022http-only\u0022, lws_callback_http, 0, 0, },\n #if defined(LWS_ROLE_WS)\n \tLWS_PLUGIN_PROTOCOL_DUMB_INCREMENT,\n \tLWS_PLUGIN_PROTOCOL_MIRROR,\n","s":{"c":1713593881,"u": 27308}} ],"g": 176711,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}