Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"", "gen_ut":1715142554, "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":"8d23176b71e0eb92722cd0700b67e31e", "commit": {"type":"commit", "time": 1525563391, "time_ofs": 480, "oid_tree": { "oid": "13c7ec250b02e1d9cebf9d92346e1831f416c12d", "alias": []}, "oid":{ "oid": "412ff64be96dc5dc3114c5ac606cf88d701acde1", "alias": []}, "msg": "lws_ring: implement lagging client culling", "sig_commit": { "git_time": { "time": 1525563391, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }, "sig_author": { "git_time": { "time": 1525486614, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }}, "body": "lws_ring: implement lagging client culling" , "diff": "diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c\nindex 8eedbf8..0da02b1 100644\n--- a/lib/core/libwebsockets.c\n+++ b/lib/core/libwebsockets.c\n@@ -390,6 +390,9 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)\n \t\treturn;\n \t}\n \n+\tif (secs \u003d\u003d LWS_TO_KILL_ASYNC)\n+\t\tsecs \u003d 0;\n+\n \tlws_pt_lock(pt, __func__);\n \t__lws_set_timeout(wsi, reason, secs);\n \tlws_pt_unlock(pt);\n@@ -2932,12 +2935,14 @@ lws_cmdline_option(int argc, const char **argv, const char *val)\n \tint n \u003d (int)strlen(val), c \u003d argc;\n \n \twhile (--c \u003e 0) {\n-\t\t/* coverity treats unchecked argv as \u0022tainted\u0022 */\n-\t\tif (!argv[c] || strlen(argv[c]) \u003e 1024)\n-\t\t\treturn NULL;\n+\n \t\tif (!strncmp(argv[c], val, n)) {\n-\t\t\tif (!*(argv[c] + n) \u0026\u0026 c \u003c argc - 1)\n+\t\t\tif (!*(argv[c] + n) \u0026\u0026 c \u003c argc - 1) {\n+\t\t\t\t/* coverity treats unchecked argv as \u0022tainted\u0022 */\n+\t\t\t\tif (!argv[c + 1] || strlen(argv[c + 1]) \u003e 1024)\n+\t\t\t\t\treturn NULL;\n \t\t\t\treturn argv[c + 1];\n+\t\t\t}\n \n \t\t\treturn argv[c] + n;\n \t\t}\ndiff --git a/lib/libwebsockets.h b/lib/libwebsockets.h\nindex cf4cb51..bac430d 100644\n--- a/lib/libwebsockets.h\n+++ b/lib/libwebsockets.h\n@@ -4668,6 +4668,7 @@ enum pending_timeout {\n \tPENDING_TIMEOUT_HOLDING_AH\t\t\t\t\u003d 25,\n \tPENDING_TIMEOUT_UDP_IDLE\t\t\t\t\u003d 26,\n \tPENDING_TIMEOUT_CLIENT_CONN_IDLE\t\t\t\u003d 27,\n+\tPENDING_TIMEOUT_LAGGING\t\t\t\t\t\u003d 28,\n \n \t/****** add new things just above ---^ ******/\n \n@@ -5542,6 +5543,13 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,\n \ttype it \u003d \u0026(start); \u005c\n \twhile (*(it)) {\n \n+#define lws_start_foreach_llp_safe(type, it, start, nxt)\u005c\n+{ \u005c\n+\ttype it \u003d \u0026(start); \u005c\n+\ttype next; \u005c\n+\twhile (*(it)) { \u005c\n+\t\tnext \u003d \u0026((*(it))-\u003enxt); \u005c\n+\n /**\n * lws_end_foreach_llp(): linkedlist pointer iterator helper end\n *\n@@ -5557,6 +5565,11 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,\n \t} \u005c\n }\n \n+#define lws_end_foreach_llp_safe(it) \u005c\n+\t\tit \u003d next; \u005c\n+\t} \u005c\n+}\n+\n #define lws_ll_fwd_insert(\u005c\n \t___new_object,\t/* pointer to new object */ \u005c\n \t___m_list,\t/* member for next list object ptr */ \u005c\ndiff --git a/lib/tls/mbedtls/mbedtls-server.c b/lib/tls/mbedtls/mbedtls-server.c\nindex 12829a3..2de6d42 100644\n--- a/lib/tls/mbedtls/mbedtls-server.c\n+++ b/lib/tls/mbedtls/mbedtls-server.c\n@@ -111,8 +111,8 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,\n \tlws_filepos_t flen;\n \tlong err;\n \n-\tif (!cert || !private_key) {\n-\t\tlwsl_notice(\u0022%s: no paths\u005cn\u0022, __func__);\n+\tif ((!cert || !private_key) \u0026\u0026 (!mem_cert || !mem_privkey)) {\n+\t\tlwsl_notice(\u0022%s: no usable input\u005cn\u0022, __func__);\n \t\treturn 0;\n \t}\n \ndiff --git a/lib/tls/tls.c b/lib/tls/tls.c\nindex 640a283..92b7c55 100644\n--- a/lib/tls/tls.c\n+++ b/lib/tls/tls.c\n@@ -405,6 +405,9 @@ lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert,\n \t * parameter.\n \t */\n \n+\tif (!cert || !private_key)\n+\t\treturn LWS_TLS_EXTANT_NO;\n+\n \tn \u003d lws_tls_use_any_upgrade_check_extant(cert);\n \tif (n \u003d\u003d LWS_TLS_EXTANT_ALTERNATIVE)\n \t\treturn LWS_TLS_EXTANT_ALTERNATIVE;\ndiff --git a/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt\nindex 28018e4..e199801 100644\n--- a/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt\n+++ b/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt\n@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8)\n include(CheckCSourceCompiles)\n \n set(SAMP lws-minimal-ws-server-ring)\n-set(SRCS minimal-ws-server.c)\n+set(SRCS minimal-ws-server-ring.c)\n \n # If we are being built as part of lws, confirm current build config supports\n # reqconfig, else skip building ourselves.\n@@ -75,4 +75,4 @@ if (requirements)\n \telse()\n \t\ttarget_link_libraries(${SAMP} websockets)\n \tendif()\n-endif()\n\u005c No newline at end of file\n+endif()\ndiff --git a/minimal-examples/ws-server/minimal-ws-server-ring/README.md b/minimal-examples/ws-server/minimal-ws-server-ring/README.md\nindex fb03885..25eb0ae 100644\n--- a/minimal-examples/ws-server/minimal-ws-server-ring/README.md\n+++ b/minimal-examples/ws-server/minimal-ws-server-ring/README.md\n@@ -19,3 +19,6 @@ Visit http://localhost:7681 on multiple browser windows\n Text you type in any browser window is sent to all of them.\n \n A ringbuffer holds up to 8 lines of text.\n+\n+This also demonstrates how the ringbuffer can take action against lagging or\n+disconnected clients that cause the ringbuffer to fill.\ndiff --git a/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server-ring.c b/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server-ring.c\nnew file mode 100644\nindex 0000000..1da7538\n--- /dev/null\n+++ b/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server-ring.c\n@@ -0,0 +1,95 @@\n+/*\n+ * lws-minimal-ws-server\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,\n+ * with an added websocket chat server using a ringbuffer.\n+ *\n+ * To keep it simple, it serves stuff in the subdirectory \u0022./mount-origin\u0022 of\n+ * the directory it was started in.\n+ * You can change that by changing mount.origin.\n+ */\n+\n+#include \u003clibwebsockets.h\u003e\n+#include \u003cstring.h\u003e\n+#include \u003csignal.h\u003e\n+\n+#define LWS_PLUGIN_STATIC\n+#include \u0022protocol_lws_minimal.c\u0022\n+\n+static struct lws_protocols protocols[] \u003d {\n+\t{ \u0022http\u0022, lws_callback_http_dummy, 0, 0 },\n+\tLWS_PLUGIN_PROTOCOL_MINIMAL,\n+\t{ NULL, NULL, 0, 0 } /* terminator */\n+};\n+\n+static int interrupted;\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 sigint_handler(int sig)\n+{\n+\tinterrupted \u003d 1;\n+}\n+\n+int main(int argc, const char **argv)\n+{\n+\tstruct lws_context_creation_info info;\n+\tstruct lws_context *context;\n+\tconst char *p;\n+\tint n \u003d 0, 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+\tsignal(SIGINT, sigint_handler);\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 ws server (lws_ring) | 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.protocols \u003d protocols;\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 (n \u003e\u003d 0 \u0026\u0026 !interrupted)\n+\t\tn \u003d lws_service(context, 1000);\n+\n+\tlws_context_destroy(context);\n+\n+\treturn 0;\n+}\ndiff --git a/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server.c\ndeleted file mode 100644\nindex 1da7538..0000000\n--- a/minimal-examples/ws-server/minimal-ws-server-ring/minimal-ws-server.c\n+++ /dev/null\n@@ -1,95 +0,0 @@\n-/*\n- * lws-minimal-ws-server\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,\n- * with an added websocket chat server using a ringbuffer.\n- *\n- * To keep it simple, it serves stuff in the subdirectory \u0022./mount-origin\u0022 of\n- * the directory it was started in.\n- * You can change that by changing mount.origin.\n- */\n-\n-#include \u003clibwebsockets.h\u003e\n-#include \u003cstring.h\u003e\n-#include \u003csignal.h\u003e\n-\n-#define LWS_PLUGIN_STATIC\n-#include \u0022protocol_lws_minimal.c\u0022\n-\n-static struct lws_protocols protocols[] \u003d {\n-\t{ \u0022http\u0022, lws_callback_http_dummy, 0, 0 },\n-\tLWS_PLUGIN_PROTOCOL_MINIMAL,\n-\t{ NULL, NULL, 0, 0 } /* terminator */\n-};\n-\n-static int interrupted;\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 sigint_handler(int sig)\n-{\n-\tinterrupted \u003d 1;\n-}\n-\n-int main(int argc, const char **argv)\n-{\n-\tstruct lws_context_creation_info info;\n-\tstruct lws_context *context;\n-\tconst char *p;\n-\tint n \u003d 0, 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-\tsignal(SIGINT, sigint_handler);\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 ws server (lws_ring) | 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.protocols \u003d protocols;\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 (n \u003e\u003d 0 \u0026\u0026 !interrupted)\n-\t\tn \u003d lws_service(context, 1000);\n-\n-\tlws_context_destroy(context);\n-\n-\treturn 0;\n-}\ndiff --git a/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c b/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c\nindex cdf1216..725cdf7 100644\n--- a/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c\n+++ b/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c\n@@ -8,6 +8,9 @@\n *\n * This version uses an lws_ring ringbuffer to cache up to 8 messages at a time,\n * so it's not so easy to lose messages.\n+ *\n+ * This also demonstrates how to \u0022cull\u0022, ie, kill, connections that can't\n+ * keep up for some reason.\n */\n \n #if !defined (LWS_PLUGIN_STATIC)\n@@ -31,6 +34,8 @@ struct per_session_data__minimal {\n \tstruct per_session_data__minimal *pss_list;\n \tstruct lws *wsi;\n \tuint32_t tail;\n+\n+\tunsigned int culled:1;\n };\n \n /* one of these is created for each vhost our protocol is used with */\n@@ -45,6 +50,87 @@ struct per_vhost_data__minimal {\n \tstruct lws_ring *ring; /* ringbuffer holding unsent messages */\n };\n \n+static void\n+cull_lagging_clients(struct per_vhost_data__minimal *vhd)\n+{\n+\tuint32_t oldest_tail \u003d lws_ring_get_oldest_tail(vhd-\u003ering);\n+\tstruct per_session_data__minimal *old_pss \u003d NULL;\n+\tint most \u003d 0, before \u003d lws_ring_get_count_waiting_elements(vhd-\u003ering,\n+\t\t\t\t\t\u0026oldest_tail), m;\n+\n+\t/*\n+\t * At least one guy with the oldest tail has lagged too far, filling\n+\t * the ringbuffer with stuff waiting for them, while new stuff is\n+\t * coming in, and they must close, freeing up ringbuffer entries.\n+\t */\n+\n+\tlws_start_foreach_llp_safe(struct per_session_data__minimal **,\n+\t\t\t ppss, vhd-\u003epss_list, pss_list) {\n+\n+\t\tif ((*ppss)-\u003etail \u003d\u003d oldest_tail) {\n+\t\t\told_pss \u003d *ppss;\n+\n+\t\t\tlwsl_user(\u0022Killing lagging client %p\u005cn\u0022, (*ppss)-\u003ewsi);\n+\n+\t\t\tlws_set_timeout((*ppss)-\u003ewsi, PENDING_TIMEOUT_LAGGING,\n+\t\t\t\t\t/*\n+\t\t\t\t\t * we may kill the wsi we came in on,\n+\t\t\t\t\t * so the actual close is deferred\n+\t\t\t\t\t */\n+\t\t\t\t\tLWS_TO_KILL_ASYNC);\n+\n+\t\t\t/*\n+\t\t\t * We might try to write something before we get a\n+\t\t\t * chance to close. But this pss is now detached\n+\t\t\t * from the ring buffer. Mark this pss as culled so we\n+\t\t\t * don't try to do anything more with it.\n+\t\t\t */\n+\n+\t\t\t(*ppss)-\u003eculled \u003d 1;\n+\n+\t\t\t/*\n+\t\t\t * Because we can't kill it synchronously, but we\n+\t\t\t * know it's closing momentarily and don't want its\n+\t\t\t * participation any more, remove its pss from the\n+\t\t\t * vhd pss list early. (This is safe to repeat\n+\t\t\t * uselessly later in the close flow).\n+\t\t\t *\n+\t\t\t * Notice this changes *ppss!\n+\t\t\t */\n+\n+\t\t\tlws_ll_fwd_remove(struct per_session_data__minimal,\n+\t\t\t\t\t pss_list, (*ppss), vhd-\u003epss_list);\n+\n+\t\t\t/* use the changed *ppss so we won't skip anything */\n+\n+\t\t\tcontinue;\n+\n+\t\t} else {\n+\t\t\t/*\n+\t\t\t * so this guy is a survivor of the cull. Let's track\n+\t\t\t * what is the largest number of pending ring elements\n+\t\t\t * for any survivor.\n+\t\t\t */\n+\t\t\tm \u003d lws_ring_get_count_waiting_elements(vhd-\u003ering,\n+\t\t\t\t\t\t\t\u0026((*ppss)-\u003etail));\n+\t\t\tif (m \u003e most)\n+\t\t\t\tmost \u003d m;\n+\t\t}\n+\n+\t} lws_end_foreach_llp_safe(ppss);\n+\n+\t/*\n+\t * Let's recover (ie, free up) all the ring slots between the\n+\t * original oldest's last one and the \u0022worst\u0022 survivor.\n+\t */\n+\n+\tlws_ring_consume_and_update_oldest_tail(vhd-\u003ering,\n+\t\tstruct per_session_data__minimal, \u0026old_pss-\u003etail, before - most,\n+\t\tvhd-\u003epss_list, tail, pss_list);\n+\n+\tlwsl_user(\u0022%s: shrunk ring from %d to %d\u005cn\u0022, __func__, before, most);\n+}\n+\n /* destroys the message when everyone has had a copy of it */\n \n static void\n@@ -92,18 +178,22 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,\n \n \tcase LWS_CALLBACK_ESTABLISHED:\n \t\t/* add ourselves to the list of live pss held in the vhd */\n+\t\tlwsl_user(\u0022LWS_CALLBACK_ESTABLISHED: wsi %p\u005cn\u0022, wsi);\n \t\tlws_ll_fwd_insert(pss, pss_list, vhd-\u003epss_list);\n \t\tpss-\u003etail \u003d lws_ring_get_oldest_tail(vhd-\u003ering);\n \t\tpss-\u003ewsi \u003d wsi;\n \t\tbreak;\n \n \tcase LWS_CALLBACK_CLOSED:\n+\t\tlwsl_user(\u0022LWS_CALLBACK_CLOSED: wsi %p\u005cn\u0022, wsi);\n \t\t/* remove our closing pss from the list of live pss */\n \t\tlws_ll_fwd_remove(struct per_session_data__minimal, pss_list,\n \t\t\t\t pss, vhd-\u003epss_list);\n \t\tbreak;\n \n \tcase LWS_CALLBACK_SERVER_WRITEABLE:\n+\t\tif (pss-\u003eculled)\n+\t\t\tbreak;\n \t\tpmsg \u003d lws_ring_get_element(vhd-\u003ering, \u0026pss-\u003etail);\n \t\tif (!pmsg)\n \t\t\tbreak;\n@@ -135,18 +225,24 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,\n \tcase LWS_CALLBACK_RECEIVE:\n \t\tn \u003d (int)lws_ring_get_count_free_elements(vhd-\u003ering);\n \t\tif (!n) {\n-\t\t\tlwsl_user(\u0022dropping!\u005cn\u0022);\n-\t\t\tbreak;\n+\t\t\t/* forcibly make space */\n+\t\t\tcull_lagging_clients(vhd);\n+\t\t\tn \u003d (int)lws_ring_get_count_free_elements(vhd-\u003ering);\n \t\t}\n+\t\tif (!n)\n+\t\t\tbreak;\n+\n+\t\tlwsl_user(\u0022LWS_CALLBACK_RECEIVE: free space %d\u005cn\u0022, n);\n \n \t\tamsg.len \u003d len;\n-\t\t/* notice we over-allocate by LWS_PRE */\n+\t\t/* notice we over-allocate by LWS_PRE... */\n \t\tamsg.payload \u003d malloc(LWS_PRE + len);\n \t\tif (!amsg.payload) {\n \t\t\tlwsl_user(\u0022OOM: dropping\u005cn\u0022);\n \t\t\tbreak;\n \t\t}\n \n+\t\t/* ...and we copy the payload in at +LWS_PRE */\n \t\tmemcpy((char *)amsg.payload + LWS_PRE, in, len);\n \t\tif (!lws_ring_insert(vhd-\u003ering, \u0026amsg, 1)) {\n \t\t\t__minimal_destroy_message(\u0026amsg);\n@@ -176,7 +272,7 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,\n \t\t\u0022lws-minimal\u0022, \u005c\n \t\tcallback_minimal, \u005c\n \t\tsizeof(struct per_session_data__minimal), \u005c\n-\t\t128, \u005c\n+\t\t0, \u005c\n \t\t0, NULL, 0 \u005c\n \t}\n \n","s":{"c":1715142554,"u": 10248}} ],"g": 11394,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}