From 2f4316527b39148aa4c6bea8a5439fc4da7f790a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 27 Oct 2019 06:17:35 +0000 Subject: [PATCH] sul: more paranoid casting vs libc header types As it is, if time_t is 32-bit on the platform it might lead to arithmetic overflow, so force it to lws_usec_t (uint64_t) even though it works OK here on x86_64. Add a minimal example aimed at testing the wsi hrtimer stability consistently across platforms. Add and disable by default hrtimer dump code (this is too expensive and specific to internal testing to leave in for debug mode even if it's not printed). If you hack it enabled, it will dump the sul list for the pt and assert if the list is disordered. --- include/libwebsockets.h | 8 +- include/libwebsockets/lws-timeout-timer.h | 2 +- lib/core-net/sorted-usec-list.c | 31 +++- lib/core-net/wsi-timeout.c | 2 +- lib/plat/unix/unix-misc.c | 6 +- lib/plat/unix/unix-service.c | 12 +- .../minimal-ws-server-timer/CMakeLists.txt | 78 ++++++++++ .../minimal-ws-server-timer/README.md | 34 +++++ .../localhost-100y.cert | 34 +++++ .../localhost-100y.key | 52 +++++++ .../minimal-ws-server.c | 143 ++++++++++++++++++ .../mount-origin/example.js | 69 +++++++++ .../mount-origin/favicon.ico | Bin 0 -> 1406 bytes .../mount-origin/index.html | 16 ++ .../mount-origin/libwebsockets.org-logo.svg | 120 +++++++++++++++ .../mount-origin/strict-csp.svg | 53 +++++++ 16 files changed, 648 insertions(+), 12 deletions(-) create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/README.md create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/localhost-100y.cert create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/localhost-100y.key create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/example.js create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/favicon.ico create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/index.html create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/libwebsockets.org-logo.svg create mode 100644 minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/strict-csp.svg diff --git a/include/libwebsockets.h b/include/libwebsockets.h index d900a44e0..6052d24a0 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -50,10 +50,10 @@ struct lws_dsh; * CARE: everything using cmake defines needs to be below here */ -#define LWS_US_PER_SEC 1000000 -#define LWS_MS_PER_SEC 1000 -#define LWS_US_PER_MS 1000 -#define LWS_NS_PER_US 1000 +#define LWS_US_PER_SEC ((lws_usec_t)1000000) +#define LWS_MS_PER_SEC ((lws_usec_t)1000) +#define LWS_US_PER_MS ((lws_usec_t)1000) +#define LWS_NS_PER_US ((lws_usec_t)1000) #define LWS_KI (1024) #define LWS_MI (LWS_KI * 1024) diff --git a/include/libwebsockets/lws-timeout-timer.h b/include/libwebsockets/lws-timeout-timer.h index f6b15dc43..9a0f2959f 100644 --- a/include/libwebsockets/lws-timeout-timer.h +++ b/include/libwebsockets/lws-timeout-timer.h @@ -114,7 +114,7 @@ void lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us); #define LWS_SET_TIMER_USEC_CANCEL ((lws_usec_t)-1ll) -#define LWS_USEC_PER_SEC (1000000ll) +#define LWS_USEC_PER_SEC ((lws_usec_t)1000000) /** * lws_set_timer_usecs() - schedules a callback on the wsi in the future diff --git a/lib/core-net/sorted-usec-list.c b/lib/core-net/sorted-usec-list.c index e54a4061f..72bd8a243 100644 --- a/lib/core-net/sorted-usec-list.c +++ b/lib/core-net/sorted-usec-list.c @@ -47,6 +47,7 @@ int __lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, lws_usec_t us) { + lws_usec_t now = lws_now_usecs(); lws_dll2_remove(&sul->list); if (us == LWS_SET_TIMER_USEC_CANCEL) { @@ -56,7 +57,7 @@ __lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, return 0; } - sul->us = lws_now_usecs() + us; + sul->us = now + us; assert(sul->cb); /* @@ -66,7 +67,28 @@ __lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, lws_dll2_add_sorted(&sul->list, own, sul_compare); - // lws_dll2_describe(own, "post-tail-insert"); +#if 0 // defined(_DEBUG) + { + lws_usec_t worst = 0; + int n = 1; + + lwsl_info("%s: own %p: count %d\n", __func__, own, own->count); + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, + lws_dll2_get_head(own)) { + lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *)p; + lwsl_info("%s: %d: %llu (+%lld)\n", __func__, n++, + (unsigned long long)sul->us, + (long long)(sul->us - now)); + if (sul->us < worst) { + lwsl_err("%s: wrongly sorted sul entry!\n", + __func__); + assert(0); + } + worst = sul->us; + } lws_end_foreach_dll_safe(p, tp); + } +#endif return 0; } @@ -109,5 +131,10 @@ __lws_sul_check(lws_dll2_owner_t *own, lws_usec_t usnow) */ } + /* + * Nothing left to take care of in the list (cannot return 0 otherwise + * because we will service anything equal to usnow rather than return) + */ + return 0; } diff --git a/lib/core-net/wsi-timeout.c b/lib/core-net/wsi-timeout.c index 594800be5..2d74df347 100644 --- a/lib/core-net/wsi-timeout.c +++ b/lib/core-net/wsi-timeout.c @@ -178,7 +178,7 @@ lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us) lws_pt_lock(pt, __func__); __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_timeout, us); - lwsl_debug("%s: %p: %llu us, reason %d\n", __func__, wsi, + lwsl_notice("%s: %p: %llu us, reason %d\n", __func__, wsi, (unsigned long long)us, reason); wsi->pending_timeout = reason; diff --git a/lib/plat/unix/unix-misc.c b/lib/plat/unix/unix-misc.c index 8667746c8..07ca41982 100644 --- a/lib/plat/unix/unix-misc.c +++ b/lib/plat/unix/unix-misc.c @@ -34,12 +34,14 @@ lws_now_usecs(void) if (clock_gettime(CLOCK_MONOTONIC, &ts)) return 0; - return (ts.tv_sec * LWS_US_PER_SEC) + (ts.tv_nsec / LWS_NS_PER_US); + return (((lws_usec_t)ts.tv_sec) * LWS_US_PER_SEC) + + ((lws_usec_t)ts.tv_nsec / LWS_NS_PER_US); #else struct timeval now; gettimeofday(&now, NULL); - return (now.tv_sec * 1000000ll) + now.tv_usec; + return (((lws_usec_t)now.tv_sec) * LWS_US_PER_SEC) + + (lws_usec_t)now.tv_usec; #endif } diff --git a/lib/plat/unix/unix-service.c b/lib/plat/unix/unix-service.c index 21c586ee6..61ea1e087 100644 --- a/lib/plat/unix/unix-service.c +++ b/lib/plat/unix/unix-service.c @@ -60,6 +60,8 @@ _lws_plat_service_forced_tsi(struct lws_context *context, int tsi) return 0; } +#define LWS_POLL_WAIT_LIMIT 2000000000 + int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) { @@ -86,7 +88,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) timeout_ms = 0; else /* force a default timeout of 23 days */ - timeout_ms = 2000000000; + timeout_ms = LWS_POLL_WAIT_LIMIT; timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS; if (context->event_loop_ops->run_pt) @@ -123,9 +125,15 @@ again: lws_pt_unlock(pt); } + /* ensure we don't wrap at 2^31 with poll()'s signed int ms */ + + timeout_us /= LWS_US_PER_MS; /* ms now */ + if (timeout_us > LWS_POLL_WAIT_LIMIT) + timeout_us = LWS_POLL_WAIT_LIMIT; + vpt->inside_poll = 1; lws_memory_barrier(); - n = poll(pt->fds, pt->fds_count, timeout_us / LWS_US_PER_MS); + n = poll(pt->fds, pt->fds_count, timeout_us /* ms now */ ); vpt->inside_poll = 0; lws_memory_barrier(); diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt new file mode 100644 index 000000000..acf34686d --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 2.8) +include(CheckCSourceCompiles) + +set(SAMP lws-minimal-ws-server-timer) +set(SRCS minimal-ws-server.c) + +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + + endif() +ENDMACRO() + +set(requirements 1) +require_lws_config(LWS_ROLE_WS 1 requirements) +require_lws_config(LWS_WITH_SERVER 1 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets) + endif() +endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/README.md b/minimal-examples/ws-server/minimal-ws-server-timer/README.md new file mode 100644 index 000000000..2f90df590 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/README.md @@ -0,0 +1,34 @@ +# lws minimal ws server timer + +This is designed to confirm long term stability of ws timers on a +particular platform. + +## build + +``` + $ cmake . && make +``` + +## Commandline Options + +Option|Meaning +---|--- +-d|Set logging verbosity +-s|Serve using TLS selfsigned cert (ie, connect to it with https://...) +-h|Strict Host: header checking against vhost name (localhost) and port +-v|Connection validity use 3s / 10s instead of default 5m / 5m10s + +## usage + +``` + $ ./lws-minimal-ws-server-timer +[2018/03/04 09:30:02:7986] USER: LWS minimal ws server | visit http://localhost:7681 +[2018/03/04 09:30:02:7986] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 on +``` + +Visit http://localhost:7681 and the browser will connect back to the test +server, you'll see ESTABLISHED logged. That triggers a TIMER event at 20s +intervals which sets the wsi timeout to 60s. It should just stay like +that forever doing the TIMER events at 20s intervals and not sending any +traffic either way. + diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/localhost-100y.cert b/minimal-examples/ws-server/minimal-ws-server-timer/localhost-100y.cert new file mode 100644 index 000000000..6f372db40 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/localhost-100y.cert @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +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 +e2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE= +-----END CERTIFICATE----- diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/localhost-100y.key b/minimal-examples/ws-server/minimal-ws-server-timer/localhost-100y.key new file mode 100644 index 000000000..148f8598e --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/localhost-100y.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +fBrpEY1IATtPq1taBZZogRqI3rOkkPk= +-----END PRIVATE KEY----- diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c new file mode 100644 index 000000000..4288767e3 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c @@ -0,0 +1,143 @@ +/* + * lws-minimal-ws-server-timer + * + * Written in 2010-2019 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates the most minimal http server you can make with lws, + * with an added websocket chat server. + * + * To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + * the directory it was started in. + * You can change that by changing mount.origin. + */ + +#include +#include +#include + +static int +callback_protocol(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + switch (reason) { + + case LWS_CALLBACK_ESTABLISHED: + lwsl_user("LWS_CALLBACK_ESTABLISHED\n"); + lws_set_timer_usecs(wsi, 20 * LWS_USEC_PER_SEC); + lws_set_timeout(wsi, 1, 60); + break; + + case LWS_CALLBACK_TIMER: + lwsl_user("LWS_CALLBACK_TIMER\n"); + lws_set_timer_usecs(wsi, 20 * LWS_USEC_PER_SEC); + lws_set_timeout(wsi, 1, 60); + break; + + case LWS_CALLBACK_CLOSED: + lwsl_user("LWS_CALLBACK_CLOSED\n"); + break; + + default: + break; + } + + return 0; +} + +static struct lws_protocols protocols[] = { + { "http", lws_callback_http_dummy, 0, 0 }, + { "timer", callback_protocol, 0, 0 }, + { NULL, NULL, 0, 0 } /* terminator */ +}; + +static const lws_retry_bo_t retry = { + .secs_since_valid_ping = 3, + .secs_since_valid_hangup = 10, +}; + +static int interrupted; + +static const struct lws_http_mount mount = { + /* .mount_next */ NULL, /* linked-list "next" */ + /* .mountpoint */ "/", /* mountpoint URL */ + /* .origin */ "./mount-origin", /* serve from dir */ + /* .def */ "index.html", /* default filename */ + /* .protocol */ NULL, + /* .cgienv */ NULL, + /* .extra_mimetypes */ NULL, + /* .interpret */ NULL, + /* .cgi_timeout */ 0, + /* .cache_max_age */ 0, + /* .auth_mask */ 0, + /* .cache_reusable */ 0, + /* .cache_revalidate */ 0, + /* .cache_intermediaries */ 0, + /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ + /* .mountpoint_len */ 1, /* char count */ + /* .basic_auth_login_file */ NULL, +}; + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + const char *p; + int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE + /* for LLL_ verbosity above NOTICE to be built into lws, + * lws must have been configured and built with + * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ + /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ + /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ + /* | LLL_DEBUG */; + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS minimal ws server | visit http://localhost:7681 (-s = use TLS / https)\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = 7681; + info.mounts = &mount; + info.protocols = protocols; + info.vhost_name = "localhost"; + info.ws_ping_pong_interval = 10; + info.options = + LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; + + if (lws_cmdline_option(argc, argv, "-s")) { + lwsl_user("Server using TLS\n"); + info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.ssl_cert_filepath = "localhost-100y.cert"; + info.ssl_private_key_filepath = "localhost-100y.key"; + } + + if (lws_cmdline_option(argc, argv, "-h")) + info.options |= LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK; + + if (lws_cmdline_option(argc, argv, "-v")) + info.retry_and_idle_policy = &retry; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_context_destroy(context); + + return 0; +} diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/example.js b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/example.js new file mode 100644 index 000000000..3a638d0ab --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/example.js @@ -0,0 +1,69 @@ + +function get_appropriate_ws_url(extra_url) +{ + var pcol; + var u = document.URL; + + /* + * We open the websocket encrypted if this page came on an + * https:// url itself, otherwise unencrypted + */ + + if (u.substring(0, 5) === "https") { + pcol = "wss://"; + u = u.substr(8); + } else { + pcol = "ws://"; + if (u.substring(0, 4) === "http") + u = u.substr(7); + } + + u = u.split("/"); + + /* + "/xxx" bit is for IE10 workaround */ + + return pcol + u[0] + "/" + extra_url; +} + +function new_ws(urlpath, protocol) +{ + if (typeof MozWebSocket != "undefined") + return new MozWebSocket(urlpath, protocol); + + return new WebSocket(urlpath, protocol); +} + +document.addEventListener("DOMContentLoaded", function() { + + var ws = new_ws(get_appropriate_ws_url(""), "timer"); + try { + ws.onopen = function() { + document.getElementById("m").disabled = 0; + document.getElementById("b").disabled = 0; + }; + + ws.onmessage =function got_packet(msg) { + document.getElementById("r").value = + document.getElementById("r").value + msg.data + "\n"; + document.getElementById("r").scrollTop = + document.getElementById("r").scrollHeight; + }; + + ws.onclose = function(){ + document.getElementById("m").disabled = 1; + document.getElementById("b").disabled = 1; + }; + } catch(exception) { + alert("

Error " + exception); + } + + function sendmsg() + { + ws.send(document.getElementById("m").value); + document.getElementById("m").value = ""; + } + + document.getElementById("b").addEventListener("click", sendmsg); + +}, false); + diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/favicon.ico b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c0cc2e3dff34012ba3d4a7848a7ed17579788ec5 GIT binary patch literal 1406 zcmZQzU<5(|0R}M0U}azs1F|%L7$l?s#Ec9aKoZP=&`9i!<^REA8>%80(yxAC$j<-A zkb5S8;qL6446ipNFl>5#fuVR6L=8goC~GtXMnhmYga9MSfQgBTk&TUw5$JocUP63y z3phA97+G0a8QIy{!BT|y==xb$SQt4uIT@LmnZZ(o_~`mk`Tv1M8w?+DXJCL~kQj^& JqOtKoVgQl$ETjMc literal 0 HcmV?d00001 diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/index.html b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/index.html new file mode 100644 index 000000000..5b597867f --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/index.html @@ -0,0 +1,16 @@ + + + + + + + +
+ + LWS wsi timer minimal ws server timer example.
+ This opens a ws connection back to the server and just sits there + setting the timer to fire every 20s, which resets the wsi timeout + for 60s each timer. It should just stay like that forever. + + + diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/libwebsockets.org-logo.svg b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/libwebsockets.org-logo.svg new file mode 100644 index 000000000..7baea649f --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/libwebsockets.org-logo.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/strict-csp.svg b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/strict-csp.svg new file mode 100644 index 000000000..cd128f1d2 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-timer/mount-origin/strict-csp.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +