From d05b408cde66a3ed8917d99f5f1bc6b634269217 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 28 Apr 2018 14:11:39 +0800 Subject: [PATCH] refactor: clean out test-apps --- CMakeLists.txt | 28 +- lib/roles/ws/client-parser-ws.c | 2 +- plugins/protocol_dumb_increment.c | 85 +-- plugins/protocol_lws_status.c | 1 - test-apps/test-ping.c | 570 ----------------- test-apps/test-server-dumb-increment.c | 106 ---- test-apps/test-server-http.c | 822 ------------------------- test-apps/test-server-libev.c | 171 ++--- test-apps/test-server-libevent.c | 190 +++--- test-apps/test-server-libuv.c | 124 ++-- test-apps/test-server-v2.0.c | 5 - test-apps/test-server.c | 204 +++--- test-apps/test-server.h | 124 ---- 13 files changed, 422 insertions(+), 2010 deletions(-) delete mode 100644 test-apps/test-ping.c delete mode 100644 test-apps/test-server-dumb-increment.c delete mode 100644 test-apps/test-server-http.c delete mode 100644 test-apps/test-server.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 964c3692..3c6cd9fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1611,8 +1611,8 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) # if (NOT LWS_WITHOUT_TEST_SERVER) create_test_app(test-server "test-apps/test-server.c" - "test-apps/test-server-http.c" - "test-apps/test-server-dumb-increment.c" + "" + "" "" "" "") @@ -1640,8 +1640,8 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) AND LWS_WITH_LIBEV) create_test_app(test-server-libev "test-apps/test-server-libev.c" - "test-apps/test-server-http.c" - "test-apps/test-server-dumb-increment.c" + "" + "" "" "" "") @@ -1654,7 +1654,7 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) AND LWS_WITH_LIBUV) create_test_app(test-server-libuv "test-apps/test-server-libuv.c" - "test-apps/test-server-http.c" + "" "" "" "" @@ -1664,8 +1664,8 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) AND LWS_WITH_LIBEVENT) create_test_app(test-server-libevent "test-apps/test-server-libevent.c" - "test-apps/test-server-http.c" - "test-apps/test-server-dumb-increment.c" + "" + "" "" "" "") @@ -1676,9 +1676,10 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) # test-server-extpoll # if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL) - create_test_app(test-server-extpoll "test-apps/test-server.c" - "test-apps/test-server-http.c" - "test-apps/test-server-dumb-increment.c" + create_test_app(test-server-extpoll + "test-apps/test-server.c" + "" + "" "" "" "") @@ -1755,13 +1756,6 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) create_test_app(test-client "test-apps/test-client.c" "" "" "" "" "") endif() - # - # test-ping - # - if (NOT LWS_WITHOUT_TEST_PING AND NOT LWS_WITHOUT_SERVER AND NOT LWS_WITHOUT_CLIENT) - create_test_app(test-ping "test-apps/test-ping.c" "" "" "" "" "") - endif() - endif(NOT LWS_WITHOUT_CLIENT) diff --git a/lib/roles/ws/client-parser-ws.c b/lib/roles/ws/client-parser-ws.c index 0f63c344..8e74a6dd 100644 --- a/lib/roles/ws/client-parser-ws.c +++ b/lib/roles/ws/client-parser-ws.c @@ -501,7 +501,7 @@ drain_extension: #else n = 0; #endif - lwsl_notice("post inflate ebuf len %d\n", ebuf.len); + lwsl_debug("post inflate ebuf len %d\n", ebuf.len); if (rx_draining_ext && !ebuf.len) { lwsl_debug(" --- ending drain on 0 read result\n"); diff --git a/plugins/protocol_dumb_increment.c b/plugins/protocol_dumb_increment.c index 43e707d6..47b293c0 100644 --- a/plugins/protocol_dumb_increment.c +++ b/plugins/protocol_dumb_increment.c @@ -1,7 +1,7 @@ /* * ws protocol handler plugin for "dumb increment" * - * Copyright (C) 2010-2016 Andy Green + * Copyright (C) 2010-2018 Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -26,79 +26,51 @@ #include -#define DUMB_PERIOD 50 +#define DUMB_PERIOD_US 50000 -struct per_vhost_data__dumb_increment { - uv_timer_t timeout_watcher; - struct lws_context *context; - struct lws_vhost *vhost; - const struct lws_protocols *protocol; -}; - -struct per_session_data__dumb_increment { +struct pss__dumb_increment { int number; }; -static void -uv_timeout_cb_dumb_increment(uv_timer_t *w -#if UV_VERSION_MAJOR == 0 - , int status -#endif -) -{ - struct per_vhost_data__dumb_increment *vhd = lws_container_of(w, - struct per_vhost_data__dumb_increment, timeout_watcher); - lws_callback_on_writable_all_protocol_vhost(vhd->vhost, vhd->protocol); -} +struct vhd__dumb_increment { + const unsigned int *options; +}; static int callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { - struct per_session_data__dumb_increment *pss = - (struct per_session_data__dumb_increment *)user; - struct per_vhost_data__dumb_increment *vhd = - (struct per_vhost_data__dumb_increment *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), - lws_get_protocol(wsi)); - unsigned char buf[LWS_PRE + 20]; - unsigned char *p = &buf[LWS_PRE]; + struct pss__dumb_increment *pss = (struct pss__dumb_increment *)user; + struct vhd__dumb_increment *vhd = + (struct vhd__dumb_increment *) + lws_protocol_vh_priv_get(lws_get_vhost(wsi), + lws_get_protocol(wsi)); + uint8_t buf[LWS_PRE + 20], *p = &buf[LWS_PRE]; + const struct lws_protocol_vhost_options *opt; int n, m; switch (reason) { case LWS_CALLBACK_PROTOCOL_INIT: vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), - sizeof(struct per_vhost_data__dumb_increment)); - vhd->context = lws_get_context(wsi); - vhd->protocol = lws_get_protocol(wsi); - vhd->vhost = lws_get_vhost(wsi); - - uv_timer_init(lws_uv_getloop(vhd->context, 0), - &vhd->timeout_watcher); - lws_libuv_static_refcount_add((uv_handle_t *)&vhd->timeout_watcher, - vhd->context); - uv_timer_start(&vhd->timeout_watcher, - uv_timeout_cb_dumb_increment, DUMB_PERIOD, DUMB_PERIOD); - - break; - - case LWS_CALLBACK_PROTOCOL_DESTROY: + lws_get_protocol(wsi), + sizeof(struct vhd__dumb_increment)); if (!vhd) - break; - lwsl_notice("di: LWS_CALLBACK_PROTOCOL_DESTROY: v=%p, ctx=%p\n", vhd, vhd->context); - uv_timer_stop(&vhd->timeout_watcher); - uv_close((uv_handle_t *)&vhd->timeout_watcher, - lws_libuv_static_refcount_del); + return -1; + if ((opt = lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "options"))) + vhd->options = (unsigned int *)opt->value; break; case LWS_CALLBACK_ESTABLISHED: pss->number = 0; - lws_set_timer_usecs(wsi, 3 * LWS_USEC_PER_SEC); + if (!vhd->options || !((*vhd->options) & 1)) + lws_set_timer_usecs(wsi, DUMB_PERIOD_US); break; case LWS_CALLBACK_SERVER_WRITEABLE: - n = lws_snprintf((char *)p, sizeof(buf) - LWS_PRE, "%d", pss->number++); + n = lws_snprintf((char *)p, sizeof(buf) - LWS_PRE, "%d", + pss->number++); m = lws_write(wsi, p, n, LWS_WRITE_TEXT); if (m < n) { lwsl_err("ERROR %d writing to di socket\n", n); @@ -120,8 +92,11 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_TIMER: - lwsl_info("%s: LWS_CALLBACK_TIMER: %p\n", __func__, wsi); - lws_set_timer_usecs(wsi, 3 * LWS_USEC_PER_SEC); + if (!vhd->options || !((*vhd->options) & 1)) { + lws_callback_on_writable_all_protocol_vhost( + lws_get_vhost(wsi), lws_get_protocol(wsi)); + lws_set_timer_usecs(wsi, DUMB_PERIOD_US); + } break; default: @@ -135,7 +110,7 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, { \ "dumb-increment-protocol", \ callback_dumb_increment, \ - sizeof(struct per_session_data__dumb_increment), \ + sizeof(struct pss__dumb_increment), \ 10, /* rx buf size must be >= permessage-deflate rx size */ \ 0, NULL, 0 \ } diff --git a/plugins/protocol_lws_status.c b/plugins/protocol_lws_status.c index 1475e2c5..ab91b606 100644 --- a/plugins/protocol_lws_status.c +++ b/plugins/protocol_lws_status.c @@ -206,7 +206,6 @@ walk_final: case LWS_CALLBACK_RECEIVE: lwsl_notice("pmd test: RX len %d\n", (int)len); - puts(in); break; case LWS_CALLBACK_CLOSED: diff --git a/test-apps/test-ping.c b/test-apps/test-ping.c deleted file mode 100644 index e9f8f18a..00000000 --- a/test-apps/test-ping.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * libwebsockets-test-ping - libwebsockets test floodping - * - * Copyright (C) 2011-2016 Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - * - * The person who associated a work with this deed has dedicated - * the work to the public domain by waiving all of his or her rights - * to the work worldwide under copyright law, including all related - * and neighboring rights, to the extent allowed by law. You can copy, - * modify, distribute and perform the work, even for commercial purposes, - * all without asking permission. - * - * The test apps are intended to be adapted for use in your code, which - * may be proprietary. So unlike the library itself, they are licensed - * Public Domain. - */ - -#include -#include -#include -#include -#include -#include - -#include "../lib/libwebsockets.h" - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#else -#include "gettimeofday.h" -#endif - -#ifdef __ANDROID__ -#include -#endif - -#ifdef __sun -#include -#endif - -/* - * this is specified in the 04 standard, control frames can only have small - * payload length styles - */ -#define MAX_PING_PAYLOAD 125 -#define MAX_MIRROR_PAYLOAD 4096 -#define MAX_PING_CLIENTS 256 -#define PING_RINGBUFFER_SIZE 256 - -static struct lws *ping_wsi[MAX_PING_CLIENTS]; -static unsigned int interval_us = 1000000; -static unsigned int size = 64; -static int flood; -static const char *address; -static unsigned char pingbuf[LWS_PRE + MAX_MIRROR_PAYLOAD]; -static char peer_name[128]; -static unsigned long started; -static int screen_width = 80; -static int use_mirror; -static unsigned int write_options; - -static unsigned long rtt_min = 100000000; -static unsigned long rtt_max; -static unsigned long rtt_avg; -static unsigned long global_rx_count; -static unsigned long global_tx_count; -static int clients = 1; -static unsigned long interrupted_time; - -struct ping { - unsigned long issue_timestamp; - unsigned long index; - unsigned int seen; -}; - -struct per_session_data__ping { - unsigned long long ping_index; - - struct ping ringbuffer[PING_RINGBUFFER_SIZE]; - int ringbuffer_head; - int ringbuffer_tail; - - unsigned long rx_count; -}; - -/* - * uses the ping pong protocol features to provide an equivalent for the - * ping utility for 04+ websockets - */ - -enum demo_protocols { - - PROTOCOL_LWS_MIRROR, - - /* always last */ - DEMO_PROTOCOL_COUNT -}; - - -static int -callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__ping *psd = user; - struct timeval tv; - unsigned char *p; - unsigned long iv; - int match = 0; - unsigned long long l; - int shift; - int n; - - switch (reason) { - case LWS_CALLBACK_CLOSED: - fprintf(stderr, "LWS_CALLBACK_CLOSED on %p\n", (void *)wsi); - - /* remove closed guy */ - - for (n = 0; n < clients; n++) - if (ping_wsi[n] == wsi) { - clients--; - while (n < clients) { - ping_wsi[n] = ping_wsi[n + 1]; - n++; - } - } - - break; - - case LWS_CALLBACK_CLIENT_ESTABLISHED: - - psd->rx_count = 0; - psd->ping_index = 1; - psd->ringbuffer_head = 0; - psd->ringbuffer_tail = 0; - - /* - * start the ball rolling, - * LWS_CALLBACK_CLIENT_WRITEABLE will come next service - */ - - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_CLIENT_RECEIVE: - case LWS_CALLBACK_CLIENT_RECEIVE_PONG: - gettimeofday(&tv, NULL); - iv = (tv.tv_sec * 1000000) + tv.tv_usec; - - psd->rx_count++; - - shift = 56; - p = in; - l = 0; - - while (shift >= 0) { - l |= ((lws_intptr_t)*p++) << shift; - shift -= 8; - } - - /* find it in the ringbuffer, look backwards from head */ - n = psd->ringbuffer_head; - while (!match) { - - if (psd->ringbuffer[n].index == l) { - psd->ringbuffer[n].seen++; - match = 1; - continue; - } - - if (n == psd->ringbuffer_tail) { - match = -1; - continue; - } - - if (n == 0) - n = PING_RINGBUFFER_SIZE - 1; - else - n--; - } - - if (match < 1) { - - if (!flood) - fprintf(stderr, "%d bytes from %s: req=%ld " - "time=(unknown)\n", (int)len, address, - (long)l); - else - fprintf(stderr, "\b \b"); - - break; - } - - if (psd->ringbuffer[n].seen > 1) - fprintf(stderr, "DUP! "); - - if ((iv - psd->ringbuffer[n].issue_timestamp) < rtt_min) - rtt_min = iv - psd->ringbuffer[n].issue_timestamp; - - if ((iv - psd->ringbuffer[n].issue_timestamp) > rtt_max) - rtt_max = iv - psd->ringbuffer[n].issue_timestamp; - - rtt_avg += iv - psd->ringbuffer[n].issue_timestamp; - global_rx_count++; - - if (!flood) - fprintf(stderr, "%d bytes from %s: req=%ld " - "time=%lu.%lums\n", (int)len, address, (long)l, - (iv - psd->ringbuffer[n].issue_timestamp) / 1000, - ((iv - psd->ringbuffer[n].issue_timestamp) / 100) % 10); - else - fprintf(stderr, "\b \b"); - break; - - case LWS_CALLBACK_CLIENT_WRITEABLE: - - shift = 56; - p = &pingbuf[LWS_PRE]; - - /* 64-bit ping index in network byte order */ - - while (shift >= 0) { - *p++ = (unsigned char)(psd->ping_index >> shift); - shift -= 8; - } - - while ((unsigned int)(p - &pingbuf[LWS_PRE]) < size) - *p++ = 0; - - gettimeofday(&tv, NULL); - - psd->ringbuffer[psd->ringbuffer_head].issue_timestamp = - (tv.tv_sec * 1000000) + tv.tv_usec; - psd->ringbuffer[psd->ringbuffer_head].index = (unsigned long)psd->ping_index++; - psd->ringbuffer[psd->ringbuffer_head].seen = 0; - - if (psd->ringbuffer_head == PING_RINGBUFFER_SIZE - 1) - psd->ringbuffer_head = 0; - else - psd->ringbuffer_head++; - - /* snip any re-used tail so we keep to the ring length */ - - if (psd->ringbuffer_tail == psd->ringbuffer_head) { - if (psd->ringbuffer_tail == PING_RINGBUFFER_SIZE - 1) - psd->ringbuffer_tail = 0; - else - psd->ringbuffer_tail++; - } - - global_tx_count++; - - if (use_mirror) - n = lws_write(wsi, - &pingbuf[LWS_PRE], - size, write_options | LWS_WRITE_BINARY); - else - n = lws_write(wsi, - &pingbuf[LWS_PRE], - size, write_options | LWS_WRITE_PING); - - if (n < 0) - return -1; - if (n < (int)size) { - lwsl_err("Partial write\n"); - return -1; - } - - if (flood && - (int)(psd->ping_index - psd->rx_count) < (screen_width - 1)) - fprintf(stderr, "."); - break; - - default: - break; - } - - return 0; -} - - -/* list of supported protocols and callbacks */ - -static struct lws_protocols protocols[] = { - - { - "lws-mirror-protocol", - callback_lws_mirror, - sizeof (struct per_session_data__ping), - }, - { - NULL, NULL, 0/* end of list */ - } -}; - -static const struct lws_extension exts[] = { - { - "permessage-deflate", - lws_extension_callback_pm_deflate, - "permessage-deflate; client_no_context_takeover; client_max_window_bits" - }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, - { NULL, NULL, NULL /* terminator */ } -}; - -static struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "debug", required_argument, NULL, 'd' }, - { "port", required_argument, NULL, 'p' }, - { "ssl", no_argument, NULL, 't' }, - { "interval", required_argument, NULL, 'i' }, - { "size", required_argument, NULL, 's' }, - { "protocol", required_argument, NULL, 'n' }, - { "flood", no_argument, NULL, 'f' }, - { "mirror", no_argument, NULL, 'm' }, - { "replicate", required_argument, NULL, 'r' }, - { "killmask", no_argument, NULL, 'k' }, - { "version", required_argument, NULL, 'v' }, - { NULL, 0, 0, 0 } -}; - -#ifndef _WIN32 -static void -signal_handler(int sig, siginfo_t *si, void *v) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - interrupted_time = (tv.tv_sec * 1000000) + tv.tv_usec; -} -#endif - -int main(int argc, char **argv) -{ - int n = 0; - int port = 7681; - int use_ssl = 0; - struct lws_context *context; - char protocol_name[256], ads_port[300]; - char ip[30]; -#ifndef _WIN32 - struct sigaction sa; - struct winsize w; -#endif - struct timeval tv; - unsigned long oldus = 0; - unsigned long l; - int ietf_version = -1; - struct lws_context_creation_info info; - struct lws_client_connect_info i; - - memset(&info, 0, sizeof info); - - if (argc < 2) - goto usage; - - while (n >= 0) { - n = getopt_long(argc, argv, "v:kr:hmfts:n:i:p:d:", options, NULL); - if (n < 0) - continue; - switch (n) { - case 'd': - lws_set_log_level(atoi(optarg), NULL); - break; - case 'm': - use_mirror = 1; - break; - case 't': - use_ssl = 2; /* 2 = allow selfsigned */ - break; - case 'p': - port = atoi(optarg); - break; - case 'n': - lws_strncpy(protocol_name, optarg, sizeof protocol_name); - protocols[PROTOCOL_LWS_MIRROR].name = protocol_name; - break; - case 'i': - interval_us = (unsigned int)(1000000.0 * atof(optarg)); - break; - case 's': - size = atoi(optarg); - break; - case 'f': - flood = 1; - break; - case 'r': - clients = atoi(optarg); - if (clients > MAX_PING_CLIENTS || clients < 1) { - fprintf(stderr, "Max clients supported = %d\n", - MAX_PING_CLIENTS); - return 1; - } - break; - case 'k': - write_options = LWS_WRITE_CLIENT_IGNORE_XOR_MASK; - break; - case 'v': - ietf_version = atoi(optarg); - break; - - case 'h': - goto usage; - } - } - - if (!use_mirror) { - if (size > MAX_PING_PAYLOAD) { - fprintf(stderr, "Max ping opcode payload size %d\n", - MAX_PING_PAYLOAD); - return 1; - } - } else { - if (size > MAX_MIRROR_PAYLOAD) { - fprintf(stderr, "Max mirror payload size %d\n", - MAX_MIRROR_PAYLOAD); - return 1; - } - } - -#ifndef _WIN32 - if (isatty(STDOUT_FILENO)) - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) - if (w.ws_col > 0) - screen_width = w.ws_col; -#endif - - info.port = CONTEXT_PORT_NO_LISTEN; - info.protocols = protocols; - info.extensions = exts; - - info.gid = -1; - info.uid = -1; - - if (use_ssl) - info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - - context = lws_create_context(&info); - if (context == NULL) { - fprintf(stderr, "Creating libwebsocket context failed\n"); - return 1; - } - - /* create client websockets using dumb increment protocol */ - - address = argv[optind]; - lws_snprintf(ads_port, sizeof(ads_port), "%s:%u", - address, port & 65535); - lwsl_notice("Connecting to %s...\n", ads_port); - memset(&i, 0, sizeof(i)); - i.context = context; - i.address = address; - i.port = port; - i.ssl_connection = use_ssl; - i.path = "/"; - i.host = ads_port; - i.origin = ads_port; - i.protocol = protocols[PROTOCOL_LWS_MIRROR].name; - i.ietf_version_or_minus_one = ietf_version; - - for (n = 0; n < clients; n++) { - ping_wsi[n] = lws_client_connect_via_info(&i); - if (ping_wsi[n] == NULL) { - lwsl_err("client %d failed to connect\n", n); - return 1; - } - } - - lws_get_peer_addresses(ping_wsi[0], lws_get_socket_fd(ping_wsi[0]), - peer_name, sizeof peer_name, ip, sizeof ip); - - lwsl_notice("libwebsockets test server ping - license LGPL2.1+SLE\n"); - lwsl_notice("(C) Copyright 2010-2016 Andy Green \n"); - fprintf(stderr, "Websocket PING %s (%s) %d bytes of data.\n", - peer_name, ip, size); - -#ifndef _WIN32 - /* set the ^C handler */ - sa.sa_sigaction = signal_handler; - sa.sa_flags = SA_SIGINFO; - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); -#endif - - gettimeofday(&tv, NULL); - started = (tv.tv_sec * 1000000) + tv.tv_usec; - - /* service loop */ - - n = 0; - while (n >= 0) { - - gettimeofday(&tv, NULL); - l = (tv.tv_sec * 1000000) + tv.tv_usec; - - /* servers can hang up on us */ - - if (clients == 0) { - n = -1; - continue; - } - - if (!interrupted_time) { - if ((l - oldus) > interval_us) { - for (n = 0; n < clients; n++) - lws_callback_on_writable(ping_wsi[n]); - oldus = l; - } - } else - - /* allow time for in-flight pongs to come */ - - if ((l - interrupted_time) > 250000) { - n = -1; - continue; - } - - if (!interval_us) - n = lws_service(context, 0); - else - n = lws_service(context, 1); - } - - /* stats */ - - if (global_rx_count && global_tx_count) - fprintf(stderr, "\n--- %s websocket ping statistics " - "using %d connections ---\n" - "%lu packets transmitted, %lu received, " - "%lu%% packet loss, time %ldms\n" - "rtt min/avg/max = %0.3f/%0.3f/%0.3f ms\n" - "payload bandwidth average %0.3f KiBytes/sec\n", - peer_name, clients, global_tx_count, global_rx_count, - ((global_tx_count - global_rx_count) * 100) / global_tx_count, - (l - started) / 1000, - ((double)rtt_min) / 1000.0, - ((double)rtt_avg / global_rx_count) / 1000.0, - ((double)rtt_max) / 1000.0, - ((double)global_rx_count * (double)size) / - ((double)(l - started) / 1000000.0) / 1024.0); - - lws_context_destroy(context); - - return 0; - -usage: - fprintf(stderr, "Usage: libwebsockets-test-ping " - " [--port=

] " - "[--ssl] [--interval=] " - "[--size=] " - "[--protocol=] " - "[--mirror] " - "[--replicate=clients>] " - "[--version ] " - "[-d ]" - "\n"); - return 1; -} diff --git a/test-apps/test-server-dumb-increment.c b/test-apps/test-server-dumb-increment.c deleted file mode 100644 index 0e30f027..00000000 --- a/test-apps/test-server-dumb-increment.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * libwebsockets-test-server - libwebsockets test implementation - * - * Copyright (C) 2010-2016 Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - * - * The person who associated a work with this deed has dedicated - * the work to the public domain by waiving all of his or her rights - * to the work worldwide under copyright law, including all related - * and neighboring rights, to the extent allowed by law. You can copy, - * modify, distribute and perform the work, even for commercial purposes, - * all without asking permission. - * - * The test apps are intended to be adapted for use in your code, which - * may be proprietary. So unlike the library itself, they are licensed - * Public Domain. - */ -#include "test-server.h" - -#if defined(LWS_ROLE_WS) - -/* dumb_increment protocol */ - -int -callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - unsigned char buf[LWS_PRE + 512]; - struct per_session_data__dumb_increment *pss = - (struct per_session_data__dumb_increment *)user; - unsigned char *p = &buf[LWS_PRE]; - int n, m; - - switch (reason) { - - case LWS_CALLBACK_ESTABLISHED: - pss->number = 0; - /* just to test the timer api */ - lws_set_timer_usecs(wsi, 3 * LWS_USEC_PER_SEC); - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - n = sprintf((char *)p, "%d", pss->number++); - m = lws_write(wsi, p, n, LWS_WRITE_TEXT); - if (m < n) { - lwsl_err("ERROR %d writing to di socket\n", n); - return -1; - } - if (close_testing && pss->number == 50) { - lwsl_info("close tesing limit, closing\n"); - return -1; - } - break; - - case LWS_CALLBACK_RECEIVE: -// if (len < 6) -// break; - lwsl_hexdump_notice(in, len); - if (strncmp((const char *)in, "reset\n", 6) == 0) - pss->number = 0; - if (strncmp((const char *)in, "closeme\n", 8) == 0) { - lwsl_notice("dumb_inc: closing as requested\n"); - lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, - (unsigned char *)"seeya", 5); - return -1; - } - break; - - case LWS_CALLBACK_TIMER: - lwsl_notice("%s: LWS_CALLBACK_TIMER: %p\n", __func__, wsi); - lws_set_timer_usecs(wsi, 3 * LWS_USEC_PER_SEC); - break; - - /* - * this just demonstrates how to use the protocol filter. If you won't - * study and reject connections based on header content, you don't need - * to handle this callback - */ - case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: - dump_handshake_info(wsi); - /* you could return non-zero here and kill the connection */ - break; - - /* - * this just demonstrates how to handle - * LWS_CALLBACK_WS_PEER_INITIATED_CLOSE and extract the peer's close - * code and auxiliary data. You can just not handle it if you don't - * have a use for this. - */ - case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: - lwsl_notice("LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: len %lu\n", - (unsigned long)len); - for (n = 0; n < (int)len; n++) - lwsl_notice(" %d: 0x%02X\n", n, - ((unsigned char *)in)[n]); - break; - - default: - break; - } - - return 0; -} -#endif \ No newline at end of file diff --git a/test-apps/test-server-http.c b/test-apps/test-server-http.c deleted file mode 100644 index 905a0a83..00000000 --- a/test-apps/test-server-http.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * libwebsockets-test-server - libwebsockets test implementation - * - * Copyright (C) 2010-2016 Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - * - * The person who associated a work with this deed has dedicated - * the work to the public domain by waiving all of his or her rights - * to the work worldwide under copyright law, including all related - * and neighboring rights, to the extent allowed by law. You can copy, - * modify, distribute and perform the work, even for commercial purposes, - * all without asking permission. - * - * The test apps are intended to be adapted for use in your code, which - * may be proprietary. So unlike the library itself, they are licensed - * Public Domain. - */ -#include "test-server.h" - -/* - * This demo server shows how to use libwebsockets for one or more - * websocket protocols in the same server - * - * It defines the following websocket protocols: - * - * dumb-increment-protocol: once the socket is opened, an incrementing - * ascii string is sent down it every 50ms. - * If you send "reset\n" on the websocket, then - * the incrementing number is reset to 0. - * - * lws-mirror-protocol: copies any received packet to every connection also - * using this protocol, including the sender - */ - -#if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param) -/* location of the certificate revocation list */ -extern char crl_path[1024]; -#endif - -extern int debug_level; - -enum demo_protocols { - /* always first */ - PROTOCOL_HTTP = 0, - - PROTOCOL_DUMB_INCREMENT, - PROTOCOL_LWS_MIRROR, - - /* always last */ - DEMO_PROTOCOL_COUNT -}; - -/* - * We take a strict whitelist approach to stop ../ attacks - */ -struct serveable { - const char *urlpath; - const char *mimetype; -}; - -/* - * this is just an example of parsing handshake headers, you don't need this - * in your code unless you will filter allowing connections by the header - * content - */ -void -dump_handshake_info(struct lws *wsi) -{ - int n = 0, len; - char buf[256]; - const unsigned char *c; - - do { - c = lws_token_to_string(n); - if (!c) { - n++; - continue; - } - - len = lws_hdr_total_length(wsi, n); - if (!len || len > (int)sizeof(buf) - 1) { - n++; - continue; - } - - lws_hdr_copy(wsi, buf, sizeof buf, n); - buf[sizeof(buf) - 1] = '\0'; - - fprintf(stderr, " %s = %s\n", (char *)c, buf); - n++; - } while (c); -} - -const char * get_mimetype(const char *file) -{ - int n = (int)strlen(file); - - if (n < 5) - return NULL; - - if (!strcmp(&file[n - 4], ".ico")) - return "image/x-icon"; - - if (!strcmp(&file[n - 4], ".png")) - return "image/png"; - - if (!strcmp(&file[n - 5], ".html")) - return "text/html"; - - if (!strcmp(&file[n - 4], ".css")) - return "text/css"; - - if (!strcmp(&file[n - 3], ".js")) - return "text/javascript"; - - return NULL; -} - - -static const char * const param_names[] = { - "text", - "send", - "file", - "upload", -}; - -enum enum_param_names { - EPN_TEXT, - EPN_SEND, - EPN_FILE, - EPN_UPLOAD, -}; - -static int -file_upload_cb(void *data, const char *name, const char *filename, - char *buf, int len, enum lws_spa_fileupload_states state) -{ - struct per_session_data__http *pss = - (struct per_session_data__http *)data; - int n; - - (void)n; - - switch (state) { - case LWS_UFS_OPEN: - lws_strncpy(pss->filename, filename, sizeof(pss->filename)); - /* we get the original filename in @filename arg, but for - * simple demo use a fixed name so we don't have to deal with - * attacks */ - pss->post_fd = (lws_filefd_type)(long long)open("/tmp/post-file", - O_CREAT | O_TRUNC | O_RDWR, 0600); - break; - case LWS_UFS_FINAL_CONTENT: - case LWS_UFS_CONTENT: - if (len) { - pss->file_length += len; - - /* if the file length is too big, drop it */ - if (pss->file_length > 100000) - return 1; - - n = write((int)(long long)pss->post_fd, buf, len); - lwsl_info("%s: write %d says %d\n", __func__, len, n); - } - if (state == LWS_UFS_CONTENT) - break; - close((int)(long long)pss->post_fd); - pss->post_fd = LWS_INVALID_FILE; - break; - } - - return 0; -} - -/* this protocol server (always the first one) handles HTTP, - * - * Some misc callbacks that aren't associated with a protocol also turn up only - * here on the first protocol server. - */ - -int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, - void *in, size_t len) -{ - struct per_session_data__http *pss = - (struct per_session_data__http *)user; - unsigned char buffer[4096 + LWS_PRE]; - lws_filepos_t amount, file_len, sent; - char leaf_path[1024]; - const char *mimetype; - char *other_headers; - unsigned char *end, *start; - struct timeval tv; - unsigned char *p; -#ifndef LWS_NO_CLIENT - struct per_session_data__http *pss1; - struct lws *wsi1; -#endif - char buf[256]; - char b64[64]; - int n, m; -#ifdef EXTERNAL_POLL - struct lws_pollargs *pa = (struct lws_pollargs *)in; -#endif - - - switch (reason) { - case LWS_CALLBACK_HTTP: - - lwsl_info("lws_http_serve: %s\n", (const char *)in); - - if (debug_level & LLL_INFO) { - dump_handshake_info(wsi); - - /* dump the individual URI Arg parameters */ - n = 0; - while (lws_hdr_copy_fragment(wsi, buf, sizeof(buf), - WSI_TOKEN_HTTP_URI_ARGS, n) > 0) { - lwsl_notice("URI Arg %d: %s\n", ++n, buf); - } - - if (lws_get_peer_simple(wsi, buf, sizeof(buf))) - lwsl_info("HTTP connect from %s\n", buf); - } - - if (len < 1) { - lws_return_http_status(wsi, - HTTP_STATUS_BAD_REQUEST, NULL); - goto try_to_reuse; - } - -#if !defined(LWS_NO_CLIENT) && defined(LWS_WITH_TLS) - if (!strncmp(in, "/proxytest", 10)) { - struct lws_client_connect_info i; - char *rootpath = "/git/"; - const char *p = (const char *)in; - - if (lws_get_child(wsi)) - break; - - pss->client_finished = 0; - memset(&i, 0, sizeof(i)); - i.context = lws_get_context(wsi); - i.address = "libwebsockets.org"; - i.port = 443; - i.ssl_connection = 1; - if (p[10]) - i.path = (char *)in + 10; - else - i.path = rootpath; - i.host = i.address; - i.origin = NULL; - i.method = "GET"; - i.parent_wsi = wsi; - i.uri_replace_from = "libwebsockets.org/git/"; - i.uri_replace_to = "/proxytest/"; - - if (!lws_client_connect_via_info(&i)) { - lwsl_err("proxy connect fail\n"); - break; - } - - break; - } -#endif - -#if 1 - /* this example server has no concept of directories */ - if (strchr((const char *)in + 1, '/')) { - lws_return_http_status(wsi, HTTP_STATUS_NOT_ACCEPTABLE, NULL); - goto try_to_reuse; - } -#endif - - /* if a legal POST URL, let it continue and accept data */ - if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) { - n = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_POST_URI); - if (n < 0) - return -1; - if (strcmp(buf, "/formtest")) { - lws_return_http_status(wsi, HTTP_STATUS_NOT_ACCEPTABLE, NULL); - return -1; - } - return 0; - } - - /* check for the "send a big file by hand" example case */ - - if (!strcmp((const char *)in, "/leaf.jpg")) { - lws_fop_flags_t flags = LWS_O_RDONLY; - - if (strlen(resource_path) > sizeof(leaf_path) - 10) - return -1; - sprintf(leaf_path, "%s/leaf.jpg", resource_path); - - /* well, let's demonstrate how to send the hard way */ - - p = buffer + LWS_PRE; - end = p + sizeof(buffer) - LWS_PRE; - - pss->fop_fd = lws_vfs_file_open( - lws_get_fops(lws_get_context(wsi)), - leaf_path, &flags); - if (!pss->fop_fd) { - lwsl_err("failed to open file %s\n", leaf_path); - return -1; - } - file_len = lws_vfs_get_length(pss->fop_fd); - - /* - * we will send a big jpeg file, but it could be - * anything. Set the Content-Type: appropriately - * so the browser knows what to do with it. - * - * Notice we use the APIs to build the header, which - * will do the right thing for HTTP 1/1.1 and HTTP2 - * depending on what connection it happens to be working - * on - */ - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - return 1; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER, - (unsigned char *)"libwebsockets", - 13, &p, end)) - return 1; - if (lws_add_http_header_by_token(wsi, - WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"image/jpeg", - 10, &p, end)) - return 1; - if (lws_add_http_header_content_length(wsi, - file_len, &p, - end)) - return 1; - if (lws_finalize_http_header(wsi, &p, end)) - return 1; - - /* - * send the http headers... - * this won't block since it's the first payload sent - * on the connection since it was established - * (too small for partial) - * - * Notice they are sent using LWS_WRITE_HTTP_HEADERS - * which also means you can't send body too in one step, - * this is mandated by changes in HTTP2 - */ - - *p = '\0'; - lwsl_info("%s\n", buffer + LWS_PRE); - - n = lws_write(wsi, buffer + LWS_PRE, - p - (buffer + LWS_PRE), - LWS_WRITE_HTTP_HEADERS); - if (n < 0) { - lws_vfs_file_close(&pss->fop_fd); - return -1; - } - /* - * book us a LWS_CALLBACK_HTTP_WRITEABLE callback - */ - lws_callback_on_writable(wsi); - break; - } - - /* if not, send a file the easy way */ - if (!strncmp(in, "/cgit-data/", 11)) { - in = (char *)in + 11; - strcpy(buf, "/usr/share/cgit"); - } else - strcpy(buf, resource_path); - - if (strcmp(in, "/")) { - if (*((const char *)in) != '/') - strcat(buf, "/"); - strncat(buf, in, sizeof(buf) - strlen(buf) - 1); - } else /* default file to serve */ - strcat(buf, "/test.html"); - buf[sizeof(buf) - 1] = '\0'; - - /* refuse to serve files we don't understand */ - mimetype = get_mimetype(buf); - if (!mimetype) { - lwsl_err("Unknown mimetype for %s\n", buf); - lws_return_http_status(wsi, - HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, "Unknown Mimetype"); - return -1; - } - - /* demonstrates how to set a cookie on / */ - - other_headers = leaf_path; - p = (unsigned char *)leaf_path; - if (!strcmp((const char *)in, "/") && - !lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) { - /* this isn't very unguessable but it'll do for us */ - gettimeofday(&tv, NULL); - n = sprintf(b64, "test=LWS_%u_%u_COOKIE;Max-Age=360000", - (unsigned int)tv.tv_sec, - (unsigned int)tv.tv_usec); - - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)b64, n, &p, - (unsigned char *)leaf_path + sizeof(leaf_path))) - return 1; - } -#if !defined(LWS_WITH_HTTP2) - if (lws_is_ssl(wsi) && lws_add_http_header_by_name(wsi, - (unsigned char *) - "Strict-Transport-Security:", - (unsigned char *) - "max-age=15768000 ; " - "includeSubDomains", 36, &p, - (unsigned char *)leaf_path + - sizeof(leaf_path))) - return 1; -#endif - n = lws_ptr_diff(p, leaf_path); - - n = lws_serve_http_file(wsi, buf, mimetype, other_headers, n); - if (n < 0) - return -1; /* error*/ - - /* - * notice that the sending of the file completes asynchronously, - * we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when - * it's done. That's the case even if we just completed the - * send, so wait for that. - */ - break; - - case LWS_CALLBACK_CLIENT_RECEIVE: - ((char *)in)[len] = '\0'; - lwsl_info("rx %d '%s'\n", (int)len, (char *)in); - break; - - case LWS_CALLBACK_HTTP_BODY: - lwsl_info("LWS_CALLBACK_HTTP_BODY: len %d\n", (int)len); - /* create the POST argument parser if not already existing */ - if (!pss->spa) { - pss->spa = lws_spa_create(wsi, param_names, - ARRAY_SIZE(param_names), 1024, - file_upload_cb, pss); - if (!pss->spa) - return -1; - - pss->filename[0] = '\0'; - pss->file_length = 0; - } - - /* let it parse the POST data */ - if (lws_spa_process(pss->spa, in, (int)len)) - return -1; - break; - - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - lwsl_debug("LWS_CALLBACK_HTTP_BODY_COMPLETION\n"); - /* - * the whole of the sent body arrived, - * respond to the client with a redirect to show the - * results - */ - - /* call to inform no more payload data coming */ - lws_spa_finalize(pss->spa); - - p = (unsigned char *)pss->result + LWS_PRE; - end = p + sizeof(pss->result) - LWS_PRE - 1; - p += sprintf((char *)p, - "

Form results (after urldecoding)

" - ""); - - for (n = 0; n < (int)ARRAY_SIZE(param_names); n++) - p += lws_snprintf((char *)p, end - p, - "", - param_names[n], - lws_spa_get_length(pss->spa, n), - lws_spa_get_string(pss->spa, n)); - - p += lws_snprintf((char *)p, end - p, "
NameLengthValue
%s%d%s

filename: %s, length %ld", - pss->filename, pss->file_length); - - p += lws_snprintf((char *)p, end - p, ""); - pss->result_len = lws_ptr_diff(p, pss->result + LWS_PRE); - - p = buffer + LWS_PRE; - start = p; - end = p + sizeof(buffer) - LWS_PRE; - - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - return 1; - - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/html", 9, &p, end)) - return 1; - if (lws_add_http_header_content_length(wsi, pss->result_len, &p, end)) - return 1; - if (lws_finalize_http_header(wsi, &p, end)) - return 1; - - n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); - if (n < 0) - return 1; - - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - lwsl_debug("LWS_CALLBACK_HTTP_DROP_PROTOCOL\n"); - - /* called when our wsi user_space is going to be destroyed */ - if (pss->spa) { - lws_spa_destroy(pss->spa); - pss->spa = NULL; - } - break; - case LWS_CALLBACK_HTTP_FILE_COMPLETION: - goto try_to_reuse; - - case LWS_CALLBACK_HTTP_WRITEABLE: - lwsl_info("LWS_CALLBACK_HTTP_WRITEABLE: %p\n", wsi); - - if (pss->client_finished) - return -1; - - if (!lws_get_child(wsi) && !pss->fop_fd && !pss->result_len) - goto try_to_reuse; - -#ifndef LWS_NO_CLIENT - if (pss->reason_bf & LWS_CB_REASON_AUX_BF__PROXY) { - char *px = buf + LWS_PRE; - int lenx = sizeof(buf) - LWS_PRE; - /* - * our sink is writeable and our source has something - * to read. So read a lump of source material of - * suitable size to send or what's available, whichever - * is the smaller. - */ - - - pss->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY; - wsi1 = lws_get_child(wsi); - if (!wsi1) - break; - if (lws_http_client_read(wsi1, &px, &lenx) < 0) - return -1; - - if (pss->client_finished) - return -1; - - break; - } - - if (lws_get_child(wsi)) - break; - -#endif - /* - * we can send more of whatever it is we were sending - */ - - if (pss->result_len) { - /* the result from the form */ - n = lws_write(wsi, (unsigned char *)pss->result + LWS_PRE, - pss->result_len, LWS_WRITE_HTTP); - pss->result_len = 0; - if (n < 0) - return 1; - goto try_to_reuse; - } - - sent = 0; - do { - /* we'd like the send this much */ - n = sizeof(buffer) - LWS_PRE; - - /* but if the peer told us he wants less, we can adapt */ - m = (int)lws_get_peer_write_allowance(wsi); - - /* -1 means not using a protocol that has this info */ - if (m == 0) - /* right now, peer can't handle anything */ - goto later; - - if (m != -1 && m < n) - /* he couldn't handle that much */ - n = m; - - n = lws_vfs_file_read(pss->fop_fd, - &amount, buffer + LWS_PRE, n); - /* problem reading, close conn */ - if (n < 0) { - lwsl_err("problem reading file\n"); - goto bail; - } - n = (int)amount; - /* sent it all, close conn */ - if (n == 0) - goto penultimate; - /* - * To support HTTP2, must take care about preamble space - * - * identification of when we send the last payload frame - * is handled by the library itself if you sent a - * content-length header - */ - m = lws_write(wsi, buffer + LWS_PRE, n, LWS_WRITE_HTTP); - if (m < 0) { - lwsl_err("write failed\n"); - /* write failed, close conn */ - goto bail; - } - if (m) /* while still active, extend timeout */ - lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, 30); - sent += m; - - } while (!lws_send_pipe_choked(wsi) && (sent < 1024 * 1024)); -later: - lws_callback_on_writable(wsi); - break; -penultimate: - lws_vfs_file_close(&pss->fop_fd); - pss->fop_fd = NULL; - goto try_to_reuse; - -bail: - lws_vfs_file_close(&pss->fop_fd); - - return -1; - - /* - * callback for confirming to continue with client IP appear in - * protocol 0 callback since no websocket protocol has been agreed - * yet. You can just ignore this if you won't filter on client IP - * since the default unhandled callback return is 0 meaning let the - * connection continue. - */ - case LWS_CALLBACK_FILTER_NETWORK_CONNECTION: - /* if we returned non-zero from here, we kill the connection */ - break; - -#ifndef LWS_NO_CLIENT - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: { - char ctype[64], ctlen = 0; - lwsl_err("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP\n"); - p = buffer + LWS_PRE; - end = p + sizeof(buffer) - LWS_PRE; - if (lws_add_http_header_status(lws_get_parent(wsi), HTTP_STATUS_OK, &p, end)) - return 1; - if (lws_add_http_header_by_token(lws_get_parent(wsi), - WSI_TOKEN_HTTP_SERVER, - (unsigned char *)"libwebsockets", - 13, &p, end)) - return 1; - - ctlen = lws_hdr_copy(wsi, ctype, sizeof(ctype), WSI_TOKEN_HTTP_CONTENT_TYPE); - if (ctlen > 0) { - if (lws_add_http_header_by_token(lws_get_parent(wsi), - WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)ctype, ctlen, &p, end)) - return 1; - } -#if 0 - if (lws_add_http_header_content_length(lws_get_parent(wsi), - file_len, &p, end)) - return 1; -#endif - if (lws_finalize_http_header(lws_get_parent(wsi), &p, end)) - return 1; - - *p = '\0'; - lwsl_info("%s\n", buffer + LWS_PRE); - - n = lws_write(lws_get_parent(wsi), buffer + LWS_PRE, - p - (buffer + LWS_PRE), - LWS_WRITE_HTTP_HEADERS); - if (n < 0) - return -1; - - break; } - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - //lwsl_err("LWS_CALLBACK_CLOSED_CLIENT_HTTP\n"); - return -1; - break; - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP: wsi %p\n", wsi); - assert(lws_get_parent(wsi)); - if (!lws_get_parent(wsi)) - break; - pss1 = lws_wsi_user(lws_get_parent(wsi)); - pss1->reason_bf |= LWS_CB_REASON_AUX_BF__PROXY; - lws_callback_on_writable(lws_get_parent(wsi)); - break; - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ len %d\n", (int)len); - assert(lws_get_parent(wsi)); - m = lws_write(lws_get_parent(wsi), (unsigned char *)in, - len, LWS_WRITE_HTTP); - if (m < 0) - return -1; - break; - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - //lwsl_err("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n"); - assert(lws_get_parent(wsi)); - if (!lws_get_parent(wsi)) - break; - pss1 = lws_wsi_user(lws_get_parent(wsi)); - pss1->client_finished = 1; - break; -#endif - - /* - * callbacks for managing the external poll() array appear in - * protocol 0 callback - */ - - case LWS_CALLBACK_LOCK_POLL: - /* - * lock mutex to protect pollfd state - * called before any other POLL related callback - * if protecting wsi lifecycle change, len == 1 - */ - test_server_lock((int)len); - break; - - case LWS_CALLBACK_UNLOCK_POLL: - /* - * unlock mutex to protect pollfd state when - * called after any other POLL related callback - * if protecting wsi lifecycle change, len == 1 - */ - test_server_unlock((int)len); - break; - -#ifdef EXTERNAL_POLL - case LWS_CALLBACK_ADD_POLL_FD: - - if (count_pollfds >= max_poll_elements) { - lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n"); - return 1; - } - - fd_lookup[pa->fd] = count_pollfds; - pollfds[count_pollfds].fd = pa->fd; - pollfds[count_pollfds].events = pa->events; - pollfds[count_pollfds++].revents = 0; - break; - - case LWS_CALLBACK_DEL_POLL_FD: - if (!--count_pollfds) - break; - m = fd_lookup[pa->fd]; - /* have the last guy take up the vacant slot */ - pollfds[m] = pollfds[count_pollfds]; - fd_lookup[pollfds[count_pollfds].fd] = m; - break; - - case LWS_CALLBACK_CHANGE_MODE_POLL_FD: - pollfds[fd_lookup[pa->fd]].events = pa->events; - break; -#endif - - case LWS_CALLBACK_GET_THREAD_ID: - /* - * if you will call "lws_callback_on_writable" - * from a different thread, return the caller thread ID - * here so lws can use this information to work out if it - * should signal the poll() loop to exit and restart early - */ - - /* return pthread_getthreadid_np(); */ - - break; - -#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) - case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: - /* Verify the client certificate */ - if (!len || (SSL_get_verify_result((SSL*)in) != X509_V_OK)) { - int err = X509_STORE_CTX_get_error((X509_STORE_CTX*)user); - int depth = X509_STORE_CTX_get_error_depth((X509_STORE_CTX*)user); - const char* msg = X509_verify_cert_error_string(err); - lwsl_err("LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: SSL error: %s (%d), depth: %d\n", msg, err, depth); - return 1; - } - break; -#if defined(LWS_HAVE_SSL_CTX_set1_param) && !defined(LWS_WITH_MBEDTLS) - case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: - if (crl_path[0]) { - /* Enable CRL checking */ - X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); - X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); - SSL_CTX_set1_param((SSL_CTX*)user, param); - X509_STORE *store = SSL_CTX_get_cert_store((SSL_CTX*)user); - X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); - n = X509_load_cert_crl_file(lookup, crl_path, X509_FILETYPE_PEM); - X509_VERIFY_PARAM_free(param); - if (n != 1) { - char errbuf[256]; - n = ERR_get_error(); - lwsl_err("LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: SSL error: %s (%d)\n", ERR_error_string(n, errbuf), n); - return 1; - } - } - break; -#endif -#endif - - default: - break; - } - - return 0; - - /* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */ -try_to_reuse: - if (lws_http_transaction_completed(wsi)) - return -1; - - return 0; -} diff --git a/test-apps/test-server-libev.c b/test-apps/test-server-libev.c index b2679e95..debbf0f1 100644 --- a/test-apps/test-server-libev.c +++ b/test-apps/test-server-libev.c @@ -1,7 +1,7 @@ /* * libwebsockets-test-server - libwebsockets test implementation * - * Copyright (C) 2011-2016 Andy Green + * Copyright (C) 2011-2018 Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -17,7 +17,10 @@ * may be proprietary. So unlike the library itself, they are licensed * Public Domain. */ -#include "test-server.h" +#include +#include +#include +#include int close_testing; int max_poll_elements; @@ -35,67 +38,20 @@ char crl_path[1024] = ""; #endif #define LWS_PLUGIN_STATIC +#include "../plugins/protocol_dumb_increment.c" #include "../plugins/protocol_lws_mirror.c" #include "../plugins/protocol_lws_status.c" - -/* singlethreaded version --> no locks */ - -void test_server_lock(int care) -{ -} -void test_server_unlock(int care) -{ -} - -/* - * This demo server shows how to use libwebsockets for one or more - * websocket protocols in the same server - * - * It defines the following websocket protocols: - * - * dumb-increment-protocol: once the socket is opened, an incrementing - * ascii string is sent down it every 50ms. - * If you send "reset\n" on the websocket, then - * the incrementing number is reset to 0. - * - * lws-mirror-protocol: copies any received packet to every connection also - * using this protocol, including the sender - */ - -enum demo_protocols { - /* always first */ - PROTOCOL_HTTP = 0, - - PROTOCOL_DUMB_INCREMENT, - PROTOCOL_LWS_MIRROR, - PROTOCOL_LWS_STATUS, - - /* always last */ - DEMO_PROTOCOL_COUNT -}; +#include "../plugins/protocol_post_demo.c" /* list of supported protocols and callbacks */ static struct lws_protocols protocols[] = { /* first protocol must always be HTTP handler */ - - { - "http-only", /* name */ - callback_http, /* callback */ - sizeof (struct per_session_data__http), /* per_session_data_size */ - 0, /* max frame size / rx buffer */ - }, - { - "dumb-increment-protocol", - callback_dumb_increment, - sizeof(struct per_session_data__dumb_increment), - 10, /* rx buf size must be >= permessage-deflate rx size - * dumb-increment only sends very small packets, so we set - * this accordingly. If your protocol will send bigger - * things, adjust this to match */ - }, + { "http-only", lws_callback_http_dummy, 0, 0, }, + LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, LWS_PLUGIN_PROTOCOL_MIRROR, LWS_PLUGIN_PROTOCOL_LWS_STATUS, + LWS_PLUGIN_PROTOCOL_POST_DEMO, { NULL, NULL, 0, 0 } /* terminator */ }; @@ -105,14 +61,85 @@ static const struct lws_extension exts[] = { lws_extension_callback_pm_deflate, "permessage-deflate; client_no_context_takeover; client_max_window_bits" }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, { NULL, NULL, NULL /* terminator */ } }; +/* + * mount handlers for sections of the URL space + */ + +static const struct lws_http_mount mount_ziptest = { + NULL, /* linked-list pointer to next*/ + "/ziptest", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH"/candide.zip", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* origin points to a callback */ + 8, /* strlen("/ziptest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +static const struct lws_http_mount mount_post = { + (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ + "/formtest", /* mountpoint in URL namespace on this vhost */ + "protocol-post-demo", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_CALLBACK, /* origin points to a callback */ + 9, /* strlen("/formtest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +/* + * mount a filesystem directory into the URL space at / + * point it to our /usr/share directory with our assets in + * stuff from here is autoserved by the library + */ + +static const struct lws_http_mount mount = { + (struct lws_http_mount *)&mount_post, /* linked-list pointer to next*/ + "/", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH, /* where to go on the filesystem for that */ + "test.html", /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* mount type is a directory in a filesystem */ + 1, /* strlen("/"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + /* this shows how to override the lws file operations. You don't need * to do any of this unless you have a reason (eg, want to serve * compressed files without decompressing the whole archive) @@ -148,13 +175,6 @@ void signal_cb(struct ev_loop *loop, struct ev_signal* watcher, int revents) } } -static void -ev_timeout_cb (EV_P_ ev_timer *w, int revents) -{ - lws_callback_on_writable_all_protocol(context, - &protocols[PROTOCOL_DUMB_INCREMENT]); -} - static struct option options[] = { { "help", no_argument, NULL, 'h' }, { "debug", required_argument, NULL, 'd' }, @@ -178,15 +198,11 @@ int main(int argc, char **argv) struct lws_context_creation_info info; char interface_name[128] = ""; const char *iface = NULL; - ev_timer timeout_watcher; char cert_path[1024]; char key_path[1024]; int use_ssl = 0; int opts = 0; int n = 0; -#ifndef _WIN32 - int syslog_options = LOG_PID | LOG_PERROR; -#endif #ifndef LWS_NO_DAEMONIZE int daemonize = 0; #endif @@ -264,12 +280,6 @@ int main(int argc, char **argv) ev_signal_start(loop, &signals[n]); } -#ifndef _WIN32 - /* we will only try to log things according to our debug_level */ - setlogmask(LOG_UPTO (LOG_DEBUG)); - openlog("lwsts", syslog_options, LOG_DAEMON); -#endif - /* tell the library what debug level to emit and to send it to stderr */ lws_set_log_level(debug_level, NULL); @@ -281,6 +291,7 @@ int main(int argc, char **argv) info.iface = iface; info.protocols = protocols; info.extensions = exts; + info.mounts = &mount; info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; @@ -325,17 +336,11 @@ int main(int argc, char **argv) lws_get_fops(context)->open = test_server_fops_open; lws_ev_initloop(context, loop, 0); - - ev_timer_init(&timeout_watcher, ev_timeout_cb, 0.05, 0.05); - ev_timer_start(loop, &timeout_watcher); ev_run(loop, 0); lws_context_destroy(context); - lwsl_notice("libwebsockets-test-server exited cleanly\n"); -#ifndef _WIN32 - closelog(); -#endif + lwsl_notice("libwebsockets-test-server exited cleanly\n"); return 0; } diff --git a/test-apps/test-server-libevent.c b/test-apps/test-server-libevent.c index 61558389..2766c9f7 100644 --- a/test-apps/test-server-libevent.c +++ b/test-apps/test-server-libevent.c @@ -17,7 +17,10 @@ * may be proprietary. So unlike the library itself, they are licensed * Public Domain. */ -#include "test-server.h" +#include +#include +#include +#include int close_testing; int max_poll_elements; @@ -35,79 +38,30 @@ char crl_path[1024] = ""; #endif #define LWS_PLUGIN_STATIC +#include "../plugins/protocol_dumb_increment.c" #include "../plugins/protocol_lws_mirror.c" #include "../plugins/protocol_lws_status.c" - -/* singlethreaded version --> no locks */ - -void test_server_lock(int care) -{ -} -void test_server_unlock(int care) -{ -} - -/* - * This demo server shows how to use libwebsockets for one or more - * websocket protocols in the same server - * - * It defines the following websocket protocols: - * - * dumb-increment-protocol: once the socket is opened, an incrementing - * ascii string is sent down it every 50ms. - * If you send "reset\n" on the websocket, then - * the incrementing number is reset to 0. - * - * lws-mirror-protocol: copies any received packet to every connection also - * using this protocol, including the sender - */ - -enum demo_protocols { - /* always first */ - PROTOCOL_HTTP = 0, - - PROTOCOL_DUMB_INCREMENT, - PROTOCOL_LWS_MIRROR, - - /* always last */ - DEMO_PROTOCOL_COUNT -}; +#include "../plugins/protocol_post_demo.c" /* list of supported protocols and callbacks */ static struct lws_protocols protocols[] = { - /* first protocol must always be HTTP handler */ - - { - "http-only", /* name */ - callback_http, /* callback */ - sizeof (struct per_session_data__http), /* per_session_data_size */ - 0, /* max frame size / rx buffer */ - }, - { - "dumb-increment-protocol", - callback_dumb_increment, - sizeof(struct per_session_data__dumb_increment), - 10, - }, - - LWS_PLUGIN_PROTOCOL_MIRROR, - LWS_PLUGIN_PROTOCOL_LWS_STATUS, - { NULL, NULL, 0, 0 } /* terminator */ + /* first protocol must always be HTTP handler */ + { "http-only", lws_callback_http_dummy, 0, 0, }, + LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, + LWS_PLUGIN_PROTOCOL_MIRROR, + LWS_PLUGIN_PROTOCOL_LWS_STATUS, + LWS_PLUGIN_PROTOCOL_POST_DEMO, + { NULL, NULL, 0, 0 } /* terminator */ }; static const struct lws_extension exts[] = { - { - "permessage-deflate", - lws_extension_callback_pm_deflate, - "permessage-deflate; client_no_context_takeover; client_max_window_bits" - }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, - { NULL, NULL, NULL /* terminator */ } + { + "permessage-deflate", + lws_extension_callback_pm_deflate, + "permessage-deflate; client_no_context_takeover; client_max_window_bits" + }, + { NULL, NULL, NULL /* terminator */ } }; /* this shows how to override the lws file operations. You don't need @@ -139,12 +93,81 @@ void signal_cb(evutil_socket_t sock_fd, short events, void *ctx) event_base_loopbreak(event_base_loop); } -static void -ev_timeout_cb (evutil_socket_t sock_fd, short events, void *ctx) -{ - lws_callback_on_writable_all_protocol(context, - &protocols[PROTOCOL_DUMB_INCREMENT]); -} +/* + * mount handlers for sections of the URL space + */ + +static const struct lws_http_mount mount_ziptest = { + NULL, /* linked-list pointer to next*/ + "/ziptest", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH"/candide.zip", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* origin points to a callback */ + 8, /* strlen("/ziptest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +static const struct lws_http_mount mount_post = { + (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ + "/formtest", /* mountpoint in URL namespace on this vhost */ + "protocol-post-demo", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_CALLBACK, /* origin points to a callback */ + 9, /* strlen("/formtest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +/* + * mount a filesystem directory into the URL space at / + * point it to our /usr/share directory with our assets in + * stuff from here is autoserved by the library + */ + +static const struct lws_http_mount mount = { + (struct lws_http_mount *)&mount_post, /* linked-list pointer to next*/ + "/", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH, /* where to go on the filesystem for that */ + "test.html", /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* mount type is a directory in a filesystem */ + 1, /* strlen("/"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; static struct option options[] = { { "help", no_argument, NULL, 'h' }, @@ -170,15 +193,11 @@ int main(int argc, char **argv) struct lws_context_creation_info info; char interface_name[128] = ""; const char *iface = NULL; - struct event *timeout_watcher; char cert_path[1024]; char key_path[1024]; int use_ssl = 0; int opts = 0; int n = 0; -#ifndef _WIN32 - int syslog_options = LOG_PID | LOG_PERROR; -#endif #ifndef LWS_NO_DAEMONIZE int daemonize = 0; #endif @@ -259,23 +278,18 @@ int main(int argc, char **argv) evsignal_add(signals[n], NULL); } -#ifndef _WIN32 - /* we will only try to log things according to our debug_level */ - setlogmask(LOG_UPTO (LOG_DEBUG)); - openlog("lwsts", syslog_options, LOG_DAEMON); -#endif - - /* tell the library what debug level to emit and to send it to syslog */ - lws_set_log_level(debug_level, lwsl_emit_syslog); + /* tell the library what debug level to emit and to send it to stderr */ + lws_set_log_level(debug_level, NULL); lwsl_notice("libwebsockets test server libevent - license LGPL2.1+SLE\n"); - lwsl_notice("(C) Copyright 2010-2016 Andy Green \n"); + lwsl_notice("(C) Copyright 2010-2018 Andy Green \n"); printf("Using resource path \"%s\"\n", resource_path); info.iface = iface; info.protocols = protocols; info.extensions = exts; + info.mounts = &mount; info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; @@ -325,17 +339,11 @@ int main(int argc, char **argv) // Initialize the LWS with libevent loop lws_event_initloop(context, event_base_loop, 0); - timeout_watcher = event_new(event_base_loop, -1, EV_PERSIST, ev_timeout_cb, NULL); - struct timeval tv = {0, 50000}; - evtimer_add(timeout_watcher, &tv); event_base_dispatch(event_base_loop); lws_context_destroy(context); - lwsl_notice("libwebsockets-test-server exited cleanly\n"); -#ifndef _WIN32 - closelog(); -#endif + lwsl_notice("libwebsockets-test-server exited cleanly\n"); return 0; } diff --git a/test-apps/test-server-libuv.c b/test-apps/test-server-libuv.c index 4374e78c..6d28add4 100644 --- a/test-apps/test-server-libuv.c +++ b/test-apps/test-server-libuv.c @@ -19,8 +19,10 @@ * MA 02110-1301 USA */ -#define DI_HANDLED_BY_PLUGIN -#include "test-server.h" +#include +#include +#include +#include #include int close_testing; @@ -51,50 +53,21 @@ void test_server_unlock(int care) #include "../plugins/protocol_dumb_increment.c" #include "../plugins/protocol_lws_mirror.c" #include "../plugins/protocol_lws_status.c" +#include "../plugins/protocol_post_demo.c" #endif -/* - * This demo server shows how to use libwebsockets for one or more - * websocket protocols in the same server - * - * It defines the following websocket protocols: - * - * dumb-increment-protocol: once the socket is opened, an incrementing - * ascii string is sent down it every 50ms. - * If you send "reset\n" on the websocket, then - * the incrementing number is reset to 0. - * - * lws-mirror-protocol: copies any received packet to every connection also - * using this protocol, including the sender - */ - -enum demo_protocols { - /* always first */ - PROTOCOL_HTTP = 0, - - PROTOCOL_DUMB_INCREMENT, - PROTOCOL_LWS_MIRROR, - PROTOCOL_LWS_STATUS, - - /* always last */ - DEMO_PROTOCOL_COUNT -}; /* list of supported protocols and callbacks */ static struct lws_protocols protocols[] = { /* first protocol must always be HTTP handler */ - { - "http-only", /* name */ - callback_http, /* callback */ - sizeof (struct per_session_data__http), /* per_session_data_size */ - 0, /* max frame size / rx buffer */ - }, + { "http-only", lws_callback_http_dummy, 0, 0, }, #if defined(LWS_ROLE_WS) LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, LWS_PLUGIN_PROTOCOL_MIRROR, LWS_PLUGIN_PROTOCOL_LWS_STATUS, + LWS_PLUGIN_PROTOCOL_POST_DEMO, #endif { NULL, NULL, 0, 0 } /* terminator */ }; @@ -106,11 +79,6 @@ static const struct lws_extension exts[] = { lws_extension_callback_pm_deflate, "permessage-deflate; client_no_context_takeover; client_max_window_bits" }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, { NULL, NULL, NULL /* terminator */ } }; @@ -129,6 +97,81 @@ void signal_cb(uv_signal_t *watcher, int signum) lws_libuv_stop(context); } +/* + * mount handlers for sections of the URL space + */ + +static const struct lws_http_mount mount_ziptest = { + NULL, /* linked-list pointer to next*/ + "/ziptest", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH"/candide.zip", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* origin points to a callback */ + 8, /* strlen("/ziptest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +static const struct lws_http_mount mount_post = { + (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ + "/formtest", /* mountpoint in URL namespace on this vhost */ + "protocol-post-demo", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_CALLBACK, /* origin points to a callback */ + 9, /* strlen("/formtest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +/* + * mount a filesystem directory into the URL space at / + * point it to our /usr/share directory with our assets in + * stuff from here is autoserved by the library + */ + +static const struct lws_http_mount mount = { + (struct lws_http_mount *)&mount_post, /* linked-list pointer to next*/ + "/", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH, /* where to go on the filesystem for that */ + "test.html", /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* mount type is a directory in a filesystem */ + 1, /* strlen("/"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; static struct option options[] = { { "help", no_argument, NULL, 'h' }, @@ -300,13 +343,14 @@ int main(int argc, char **argv) lws_set_log_level(debug_level, NULL); lwsl_notice("libwebsockets test server libuv - license LGPL2.1+SLE\n"); - lwsl_notice("(C) Copyright 2010-2016 Andy Green \n"); + lwsl_notice("(C) Copyright 2010-2018 Andy Green \n"); lwsl_info("Using resource path \"%s\"\n", resource_path); info.iface = iface; info.protocols = protocols; info.extensions = exts; + info.mounts = &mount; info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; diff --git a/test-apps/test-server-v2.0.c b/test-apps/test-server-v2.0.c index 5e1fda7c..94cddce5 100644 --- a/test-apps/test-server-v2.0.c +++ b/test-apps/test-server-v2.0.c @@ -111,11 +111,6 @@ static const struct lws_extension exts[] = { lws_extension_callback_pm_deflate, "permessage-deflate" }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, { NULL, NULL, NULL /* terminator */ } }; diff --git a/test-apps/test-server.c b/test-apps/test-server.c index edbd5b99..f2cfc0d1 100644 --- a/test-apps/test-server.c +++ b/test-apps/test-server.c @@ -18,7 +18,10 @@ * Public Domain. */ -#include "test-server.h" +#include +#include +#include +#include int close_testing; int max_poll_elements; @@ -33,6 +36,7 @@ volatile int force_exit = 0, dynamic_vhost_enable = 0; struct lws_vhost *dynamic_vhost; struct lws_context *context; struct lws_plat_file_ops fops_plat; +static int test_options; /* http server gets files from this path */ #define LOCAL_RESOURCE_PATH INSTALL_DATADIR"/libwebsockets-test-server" @@ -69,72 +73,21 @@ char crl_path[1024] = ""; #if defined(LWS_ROLE_WS) #include "../plugins/protocol_lws_mirror.c" #include "../plugins/protocol_lws_status.c" +#include "../plugins/protocol_dumb_increment.c" +#include "../plugins/protocol_post_demo.c" #endif -/* singlethreaded version --> no locks */ - -void test_server_lock(int care) -{ -} -void test_server_unlock(int care) -{ -} - -/* - * This demo server shows how to use libwebsockets for one or more - * websocket protocols in the same server - * - * It defines the following websocket protocols: - * - * dumb-increment-protocol: once the socket is opened, an incrementing - * ascii string is sent down it every 50ms. - * If you send "reset\n" on the websocket, then - * the incrementing number is reset to 0. - * - * lws-mirror-protocol: copies any received packet to every connection also - * using this protocol, including the sender - * - * lws-status: informs connected browsers of who else is - * connected. - */ - -enum demo_protocols { - /* always first */ - PROTOCOL_HTTP = 0, - - PROTOCOL_DUMB_INCREMENT, - PROTOCOL_LWS_MIRROR, - PROTOCOL_LWS_STATUS, - - PROTOCOL_LWS_META, - - /* always last */ - DEMO_PROTOCOL_COUNT -}; - /* list of supported protocols and callbacks */ static struct lws_protocols protocols[] = { /* first protocol must always be HTTP handler */ - { - "http-only", /* name */ - callback_http, /* callback */ - sizeof (struct per_session_data__http), /* per_session_data_size */ - 0, /* max frame size / rx buffer */ - }, + { "http-only", lws_callback_http_dummy, 0, 0, }, #if defined(LWS_ROLE_WS) - { - "dumb-increment-protocol", - callback_dumb_increment, - sizeof(struct per_session_data__dumb_increment), - 10, /* rx buf size must be >= permessage-deflate rx size - * dumb-increment only sends very small packets, so we set - * this accordingly. If your protocol will send bigger - * things, adjust this to match */ - }, + LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, LWS_PLUGIN_PROTOCOL_MIRROR, LWS_PLUGIN_PROTOCOL_LWS_STATUS, + LWS_PLUGIN_PROTOCOL_POST_DEMO, #endif { NULL, NULL, 0, 0 } /* terminator */ }; @@ -191,15 +144,98 @@ static const struct lws_extension exts[] = { lws_extension_callback_pm_deflate, "permessage-deflate" }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, { NULL, NULL, NULL /* terminator */ } }; +/* + * mount handlers for sections of the URL space + */ +static const struct lws_http_mount mount_ziptest = { + NULL, /* linked-list pointer to next*/ + "/ziptest", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH"/candide.zip", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* origin points to a callback */ + 8, /* strlen("/ziptest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +static const struct lws_http_mount mount_post = { + (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/ + "/formtest", /* mountpoint in URL namespace on this vhost */ + "protocol-post-demo", /* handler */ + NULL, /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_CALLBACK, /* origin points to a callback */ + 9, /* strlen("/formtest"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +/* + * mount a filesystem directory into the URL space at / + * point it to our /usr/share directory with our assets in + * stuff from here is autoserved by the library + */ + +static const struct lws_http_mount mount = { + (struct lws_http_mount *)&mount_post, /* linked-list pointer to next*/ + "/", /* mountpoint in URL namespace on this vhost */ + LOCAL_RESOURCE_PATH, /* where to go on the filesystem for that */ + "test.html", /* default filename if none given */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + LWSMPRO_FILE, /* mount type is a directory in a filesystem */ + 1, /* strlen("/"), ie length of the mountpoint */ + NULL, + + { NULL, NULL } // sentinel +}; + +static const struct lws_protocol_vhost_options pvo_options = { + NULL, + NULL, + "options", /* pvo name */ + (void *)&test_options /* pvo value */ +}; + +static const struct lws_protocol_vhost_options pvo = { + NULL, /* "next" pvo linked-list */ + &pvo_options, /* "child" pvo linked-list */ + "dumb-increment-protocol", /* protocol name we belong to on this vhost */ + "" /* ignored */ +}; static struct option options[] = { { "help", no_argument, NULL, 'h' }, @@ -233,7 +269,9 @@ int main(int argc, char **argv) struct lws_context_creation_info info; struct lws_vhost *vhost; char interface_name[128] = ""; - unsigned int ms, oldms = 0; +#ifdef EXTERNAL_POLL + unsigned int ms; +#endif const char *iface = NULL; char cert_path[1024] = ""; char key_path[1024] = ""; @@ -243,18 +281,9 @@ int main(int argc, char **argv) int pp_secs = 0; int opts = 0; int n = 0; -#ifndef _WIN32 -/* LOG_PERROR is not POSIX standard, and may not be portable */ -#ifdef __sun - int syslog_options = LOG_PID; -#else - int syslog_options = LOG_PID | LOG_PERROR; -#endif -#endif #ifndef LWS_NO_DAEMONIZE int daemonize = 0; #endif - char no_dumb_send = 0; /* * take care to zero down the info struct, he contains random garbaage @@ -289,7 +318,8 @@ int main(int argc, char **argv) debug_level = atoi(optarg); break; case 'n': - no_dumb_send = 1; + /* no dumb increment send */ + test_options |= 1; break; case 's': use_ssl = 1; @@ -380,17 +410,11 @@ int main(int argc, char **argv) signal(SIGUSR1, sighandler); #endif -#ifndef _WIN32 - /* we will only try to log things according to our debug_level */ - setlogmask(LOG_UPTO (LOG_DEBUG)); - openlog("lwsts", syslog_options, LOG_DAEMON); -#endif - - /* tell the library what debug level to emit and to send it to syslog */ + /* tell the library what debug level to emit and to send it to stderr */ lws_set_log_level(debug_level, NULL); lwsl_notice("libwebsockets test server - license LGPL2.1+SLE\n"); - lwsl_notice("(C) Copyright 2010-2017 Andy Green \n"); + lwsl_notice("(C) Copyright 2010-2018 Andy Green \n"); printf("Using resource path \"%s\"\n", resource_path); #ifdef EXTERNAL_POLL @@ -432,7 +456,6 @@ int main(int argc, char **argv) } info.gid = gid; info.uid = uid; - info.max_http_header_pool = 256; info.options = opts | LWS_SERVER_OPTION_VALIDATE_UTF8 | LWS_SERVER_OPTION_EXPLICIT_VHOSTS; info.extensions = exts; info.timeout_secs = 5; @@ -449,6 +472,7 @@ int main(int argc, char **argv) "!DHE-RSA-AES256-SHA256:" "!AES256-GCM-SHA384:" "!AES256-SHA256"; + info.mounts = &mount; info.ip_limit_ah = 24; /* for testing */ info.ip_limit_wsi = 105; /* for testing */ @@ -462,6 +486,8 @@ int main(int argc, char **argv) return -1; } + info.pvo = &pvo; + vhost = lws_create_vhost(context, &info); if (!vhost) { lwsl_err("vhost creation failed\n"); @@ -504,20 +530,12 @@ int main(int argc, char **argv) * as soon as it can take more packets (usually immediately) */ - ms = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - if ((ms - oldms) > 50) { - if (!no_dumb_send) - lws_callback_on_writable_all_protocol(context, - &protocols[PROTOCOL_DUMB_INCREMENT]); - oldms = ms; - } - #ifdef EXTERNAL_POLL /* * this represents an existing server's single poll action * which also includes libwebsocket sockets */ - + ms = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); n = poll(pollfds, count_pollfds, 50); if (n < 0) continue; @@ -580,9 +598,5 @@ done: lwsl_notice("libwebsockets-test-server exited cleanly\n"); -#ifndef _WIN32 - closelog(); -#endif - return 0; } diff --git a/test-apps/test-server.h b/test-apps/test-server.h deleted file mode 100644 index c8775042..00000000 --- a/test-apps/test-server.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * libwebsockets-test-server - libwebsockets test implementation - * - * Copyright (C) 2010-2016 Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - * - * The person who associated a work with this deed has dedicated - * the work to the public domain by waiving all of his or her rights - * to the work worldwide under copyright law, including all related - * and neighboring rights, to the extent allowed by law. You can copy, - * modify, distribute and perform the work, even for commercial purposes, - * all without asking permission. - * - * The test apps are intended to be adapted for use in your code, which - * may be proprietary. So unlike the library itself, they are licensed - * Public Domain. - */ - -#if defined(_WIN32) && defined(EXTERNAL_POLL) - -#if (WINVER < 0x0600) -#undef WINVER -#undef _WIN32_WINNT -#define WINVER 0x0600 -#define _WIN32_WINNT WINVER -#endif - -#define poll(fdArray, fds, timeout) WSAPoll((LPWSAPOLLFD)(fdArray), (ULONG)(fds), (INT)(timeout)) -#endif - -#include "lws_config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../lib/libwebsockets.h" - -#ifdef _WIN32 -#include -#include "gettimeofday.h" -#else -#include -#include -#include -#endif - -extern int close_testing; -extern int max_poll_elements; - -#ifdef EXTERNAL_POLL -extern struct lws_pollfd *pollfds; -extern int *fd_lookup; -extern int count_pollfds; -#endif -extern volatile int force_exit; -extern struct lws_context *context; -extern char *resource_path; -#if defined(LWS_WITH_TLS) && defined(LWS_HAVE_SSL_CTX_set1_param) -extern char crl_path[1024]; -#endif - -extern void test_server_lock(int care); -extern void test_server_unlock(int care); - -#ifndef __func__ -#define __func__ __FUNCTION__ -#endif - -struct per_session_data__http { - lws_fop_fd_t fop_fd; -#ifdef LWS_WITH_CGI - struct lws_cgi_args args; -#endif -#if defined(LWS_WITH_CGI) || !defined(LWS_NO_CLIENT) - int reason_bf; -#endif - unsigned int client_finished:1; - - - struct lws_spa *spa; - char result[500 + LWS_PRE]; - int result_len; - - char filename[256]; - long file_length; - lws_filefd_type post_fd; -}; - -/* - * one of these is auto-created for each connection and a pointer to the - * appropriate instance is passed to the callback in the user parameter - * - * for this example protocol we use it to individualize the count for each - * connection. - */ - -#if !defined(DI_HANDLED_BY_PLUGIN) -struct per_session_data__dumb_increment { - int number; -}; -#endif - - -extern int -callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, - void *in, size_t len); - -#if !defined(DI_HANDLED_BY_PLUGIN) -extern int -callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len); -#endif - - -extern void -dump_handshake_info(struct lws *wsi);