diff --git a/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/CMakeLists.txt new file mode 100644 index 000000000..281d65baa --- /dev/null +++ b/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/CMakeLists.txt @@ -0,0 +1,25 @@ +project(lws-minimal-ws-client-spam-tx-rx C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-ws-client-spam-tx-rx) +set(SRCS minimal-ws-client.c) + +set(requirements 1) +require_lws_config(LWS_ROLE_WS 1 requirements) +require_lws_config(LWS_WITH_CLIENT 1 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/libwebsockets.org.cer b/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/libwebsockets.org.cer new file mode 100644 index 000000000..b9bdb987a --- /dev/null +++ b/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/libwebsockets.org.cer @@ -0,0 +1,79 @@ +-----BEGIN CERTIFICATE----- +MIIFWjCCBEKgAwIBAgISA9x0/oj5PLdW46hsmR82/7ytMA0GCSqGSIb3DQEBCwUA +MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD +ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTA5MDcwNzA5NDBaFw0x +OTEyMDYwNzA5NDBaMBwxGjAYBgNVBAMTEWxpYndlYnNvY2tldHMub3JnMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxPinIkleLmvEcA/YuBss6ASXVi7g +yr6Sss7cB3vTy7Fp8OB2c1N25prHZxVpORAUo0UreiaY2Ws4NFvDaYp08ZffevuC +UhThsEJlbkD0uvt7dPapJt9PNJtlxjNFWyvHEy6PijzIaMYDROiStcCJQn7kAew/ +Za2+5kNVgKqT+7OXukJEFdSdVZI6QC/npeQlkIrFSq1WVthCGBNJehxxES0hSWzk +0gNVKlkD3/SbkupsfUpe73XiawMtrtsSE7cdnul7VZmiP8I/3sJr1+4/3xZ+DEYg +mVB82B0vd08VJYzU7Nf0pz0PWusAmzRoRn81IXkOfBg9ohlSSEoZhHYS7QIDAQAB +o4ICZjCCAmIwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr +BgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRmKKyGjufWgp7pR2x0tWxG +D9G+WTAfBgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcB +AQRjMGEwLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlw +dC5vcmcwLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlw +dC5vcmcvMBwGA1UdEQQVMBOCEWxpYndlYnNvY2tldHMub3JnMEwGA1UdIARFMEMw +CAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9j +cHMubGV0c2VuY3J5cHQub3JnMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHcAdH7a +gzGtMxCRIZzOJU9CcMK//V5CIAjGNzV55hB7zFYAAAFtCsWIfgAABAMASDBGAiEA +0H55VqSKV3otHK7uHNbcR0QwoUYtCmeObhsqxzCnmDwCIQD3mtuSKrxTD3oA+Yde +nmTgWfFyS4TNgLNEPCJYo2s75gB1ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM +9OVFR/R4AAABbQrFil4AAAQDAEYwRAIgNSpvz/1JA2aP6fh6ujGNuYfrAvWjlxXo +CJtVGe4XaDYCIGmK1/9tl1uQbVD46P5NswnULq06KQmuOrlI3HO4r86HMA0GCSqG +SIb3DQEBCwUAA4IBAQBiAlV7wkCsWE99VmZHBmcbZChWyWUHG3LM1hnaQRQjTSYk +CIlauCpWzlUd6weuvra85KqBbCYo+1hxbwITI796uAdgtHmBE8nj0VltHwKeSq2s +KKiGXBRT7Z7t0VHYSLOlGOVn1auuQFaWBArc0cQ/m1ZsoHvOiHTlKQvVsA4HnIxA +CjGY9OOQoh0c36ecbJZ44XKnU9J/OXtDx00aW6QodaZmgMp/OOCghFQUvufkgTUL +LZid873/8dJVWjAaj1VdadO1nSbdAfBbeWXy93+vg1aAoig80RoscrzYCaNlwmR7 +EO5zWxL3l+xUZogQSJuICgUgNzVB3wjn8HeHGsqt +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow +SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT +GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF +q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 +SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 +Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA +a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj +/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG +CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv +bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k +c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw +VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC +ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz +MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu +Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF +AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo +uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ +wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu +X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG +PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 +KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== +-----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + diff --git a/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c b/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c new file mode 100644 index 000000000..f611e4661 --- /dev/null +++ b/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c @@ -0,0 +1,221 @@ +#include +#include +#include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif + +static int nclients = 11; +unsigned char msg[LWS_PRE+128]; +static int message_delay = 500000; // microseconds +static int connection_delay = 100000; // microseconds +static struct lws_context *context; +static const char *server_address = "localhost", *pro = "lws-minimal"; +static int interrupted = 0, port = 7681, ssl_connection = 0; + +static int connect_client() +{ + struct lws_client_connect_info i; + + memset(&i, 0, sizeof(i)); + + i.context = context; + i.port = port; + i.address = server_address; + i.path = "/"; + i.host = i.address; + i.origin = i.address; + i.ssl_connection = ssl_connection; + i.protocol = pro; + i.local_protocol_name = pro; + + //usleep(connection_delay); + lwsl_notice("%s: connection %s:%d\n", __func__, i.address, i.port); + if (!lws_client_connect_via_info(&i)) return 1; + + return 0; +} + +static int +callback(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + int m= 0, n = 0; + short r; +#if defined(_DEBUG) + size_t remain; + int first = 0, final = 0; +#endif + + //lwsl_notice("callback called with reason %d\n", reason); + switch (reason) { + + case LWS_CALLBACK_PROTOCOL_INIT: + for (n = 0; n < nclients; n++) + connect_client(); + break; + + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : + "(null)"); + if(--nclients == 0) interrupted = 1; + break; + + /* --- client callbacks --- */ + + case LWS_CALLBACK_CLIENT_ESTABLISHED: + lws_callback_on_writable(wsi); + lwsl_user("%s: established connection, wsi = %p\n", + __func__, wsi); + break; + + case LWS_CALLBACK_CLIENT_CLOSED: + lwsl_user("%s: CLOSED\n", __func__); + if(--nclients == 0) interrupted = 1; + break; + + case LWS_CALLBACK_CLIENT_WRITEABLE: + + m = lws_write(wsi, msg + LWS_PRE, 128, LWS_WRITE_TEXT); + if (m < 128) { + lwsl_err("sending message failed: %d < %d\n", m, n); + return -1; + } + + /* + * Schedule the timer after minimum message delay plus the + * random number of centiseconds. + */ + if (lws_get_random(lws_get_context(wsi), &r, 2) == 2) { + n = message_delay + 10000*(r % 100); + lwsl_debug("set timer on %d usecs\n", n); + lws_set_timer_usecs(wsi, n); + } + break; + + case LWS_CALLBACK_TIMER: + // Let the main loop know we want to send another message to the + // server + lws_callback_on_writable(wsi); + break; + + case LWS_CALLBACK_CLIENT_RECEIVE: +#if defined(_DEBUG) + first = lws_is_first_fragment(wsi); + final = lws_is_final_fragment(wsi); + remain = lws_remaining_packet_payload(wsi); + lwsl_debug("LWS_CALLBACK_RECEIVE: len = %lu, first = %d, " + "final = %d, remains = %lu\n", + (unsigned long)len, first, final, + (unsigned long)remain); +#endif + break; + + case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: + lwsl_notice("server initiated connection close: len = %lu, " + "in = %s\n", (unsigned long)len, (char*)in); + return 0; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { "spam-rx-tx", callback, 4096, 4096, 0, NULL, 0 }, + { NULL, NULL, 0, 0 } +}; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + const char *p; + int n = 0, logs = + LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; +#ifndef WIN32 + srandom(time(0)); +#endif + + memset(msg, 'x', sizeof(msg)); + + signal(SIGINT, sigint_handler); + + if (lws_cmdline_option(argc, argv, "-d")) + logs |= LLL_INFO | LLL_DEBUG; + + lws_set_log_level(logs, NULL); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ + info.protocols = protocols; +#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) + /* + * OpenSSL uses the system trust store. mbedTLS has to be told which + * CA to trust explicitly. + */ + info.client_ssl_ca_filepath = "./libwebsockets.org.cer"; +#endif + + if ((p = lws_cmdline_option(argc, argv, "-h"))) { + server_address = p; + } + + if ((p = lws_cmdline_option(argc, argv, "-s"))) { + ssl_connection |= + LCCSCF_USE_SSL | + LCCSCF_ALLOW_SELFSIGNED | + LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; + } + + if ((p = lws_cmdline_option(argc, argv, "-p"))) + port = atoi(p); + + if ((p = lws_cmdline_option(argc, argv, "-n"))) { + n = atoi(p); + if (n < 1) + n = 1; + if (n < nclients) + nclients = n; + lwsl_notice("Start test clients: %d\n", nclients); + } + + if ((p = lws_cmdline_option(argc, argv, "-c"))) { + connection_delay = atoi(p); + lwsl_notice("Connection delay: %d\n", connection_delay); + } + + if ((p = lws_cmdline_option(argc, argv, "-m"))) { + message_delay = atoi(p); + lwsl_notice("Message delay: %d\n", connection_delay); + } + + info.fd_limit_per_thread = 1 + nclients + 1; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lwsl_notice("%s: exiting service loop. n = %d, interrupted = %d\n", + __func__, n, interrupted); + + lws_context_destroy(context); + + return 0; +} diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/CMakeLists.txt similarity index 96% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/CMakeLists.txt rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/CMakeLists.txt index 4596046e9..22fa30c8b 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/CMakeLists.txt @@ -1,4 +1,4 @@ -project(lws-minimal-ws-server-threads-foreign-smp C) +project(lws-minimal-ws-server-threads-foreign-libuv-smp C) cmake_minimum_required(VERSION 2.8) find_package(libwebsockets CONFIG REQUIRED) list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/README.md b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/README.md similarity index 100% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/README.md rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/README.md diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/minimal-ws-server.c similarity index 75% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/minimal-ws-server.c rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/minimal-ws-server.c index 4a4e40a4a..b9b7d35d8 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/minimal-ws-server.c +++ b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/minimal-ws-server.c @@ -1,5 +1,5 @@ /* - * lws-minimal-ws-server + * lws-minimal-ws-server-threads-foreign-smp * * Written in 2010-2020 by Andy Green * @@ -44,6 +44,7 @@ static struct lws_protocols protocols[] = { static struct lws_context *context; static int interrupted; static uv_loop_t loop[COUNT_THREADS]; +static uv_signal_t *s, signal_outer[COUNT_THREADS]; static const struct lws_http_mount mount = { /* .mount_next */ NULL, /* linked-list "next" */ @@ -90,38 +91,54 @@ static const struct lws_protocol_vhost_options pvo = { void *thread_service(void *threadid) { + /* + * This is a foreign thread context for each event loop... lws doesn't + * know about it, except that it's getting called into from the event + * lib bound to each of these. + * + * When closing, at the point we have detached everything related to + * lws from the loop and destroyed the context we can as the "foreign + * app" take care of stopping the foreign loop and cloing this thread. + * + * The call to lws_service_tsi just starts the related event loop + */ while (lws_service_tsi(context, 0, (int)(lws_intptr_t)threadid) >= 0 && !interrupted) lwsl_notice("%s\n", __func__); + lwsl_info("%s: thr %d: exiting\n", __func__, (int)(lws_intptr_t)threadid); + pthread_exit(NULL); return NULL; } -void signal_cb(uv_signal_t *watcher, int signum) +static void +signal_cb(uv_signal_t *watcher, int signum) { int n; - if (interrupted) - return; + n = (int)(watcher - signal_outer); + + lwsl_notice("%s: thr %d: signal %d caught\n", __func__, n, + watcher->signum); - lwsl_notice("signal_cb: signal %d caught\n", watcher->signum); - interrupted = 1; uv_signal_stop(watcher); - lws_context_destroy(context); - for (n = 0; n < COUNT_THREADS; n++) - uv_stop(&loop[n]); + uv_close((uv_handle_t *)&signal_outer[n], NULL); + if (!interrupted) { + interrupted = 1; + lws_context_destroy(context); + } } int main(int argc, const char **argv) { int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; - uv_signal_t *s, signal_outer[3 * COUNT_THREADS]; pthread_t pthread_service[COUNT_THREADS]; struct lws_context_creation_info info; void *foreign_loops[COUNT_THREADS]; + int actual_threads; const char *p; void *retval; @@ -132,15 +149,11 @@ int main(int argc, const char **argv) lwsl_user("LWS minimal ws server + threads + smp | visit http://localhost:7681\n"); for (n = 0; n < COUNT_THREADS; n++) { - int m; - uv_loop_init(&loop[n]); - for (m = 0; m < 3; m++) { - s = &signal_outer[n * 3 + m]; - uv_signal_init(&loop[n], s); - uv_signal_start(s, signal_cb, SIGINT); - } + s = &signal_outer[n]; + uv_signal_init(&loop[n], s); + uv_signal_start(s, signal_cb, SIGINT); foreign_loops[n] = &loop[n]; } @@ -162,11 +175,12 @@ int main(int argc, const char **argv) return 1; } - lwsl_notice(" Service threads: %d\n", lws_get_count_threads(context)); + actual_threads = lws_get_count_threads(context); + lwsl_notice(" Service threads: %d\n", actual_threads); /* start all the service threads */ - for (n = 0; n < lws_get_count_threads(context); n++) + for (n = 0; n < actual_threads; n++) if (pthread_create(&pthread_service[n], NULL, thread_service, (void *)(lws_intptr_t)n)) lwsl_err("Failed to start service thread\n"); @@ -178,5 +192,13 @@ int main(int argc, const char **argv) lws_context_destroy(context); + for (n = 0; n < COUNT_THREADS; n++) { + int m; + + m = uv_loop_close(&loop[n]); + if (m) + lwsl_notice("%s: uv_close_loop %d: %d\n", __func__, n, m); + } + return 0; } diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/example.js b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/example.js similarity index 100% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/example.js rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/example.js diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/favicon.ico b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/favicon.ico similarity index 100% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/favicon.ico rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/favicon.ico diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/index.html b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/index.html similarity index 100% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/index.html rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/index.html diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/libwebsockets.org-logo.svg b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/libwebsockets.org-logo.svg similarity index 100% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/libwebsockets.org-logo.svg rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/libwebsockets.org-logo.svg diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/strict-csp.svg b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/strict-csp.svg similarity index 100% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/mount-origin/strict-csp.svg rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/mount-origin/strict-csp.svg diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/protocol_lws_minimal.c b/minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/protocol_lws_minimal.c similarity index 100% rename from minimal-examples/ws-server/minimal-ws-server-threads-foreign-smp/protocol_lws_minimal.c rename to minimal-examples/ws-server/minimal-ws-server-threads-foreign-libuv-smp/protocol_lws_minimal.c