diff --git a/lib/core/output.c b/lib/core/output.c index 2f3dd60e0..6c8b9b91d 100644 --- a/lib/core/output.c +++ b/lib/core/output.c @@ -32,6 +32,7 @@ int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) unsigned int n, m; // lwsl_notice("%s: len %d\n", __func__, (int)len); + // lwsl_hexdump_level(LLL_NOTICE, buf, len); /* * Detect if we got called twice without going through the diff --git a/lib/roles/ws/ext/extension-permessage-deflate.c b/lib/roles/ws/ext/extension-permessage-deflate.c index 405c23298..fba11a0b0 100644 --- a/lib/roles/ws/ext/extension-permessage-deflate.c +++ b/lib/roles/ws/ext/extension-permessage-deflate.c @@ -302,8 +302,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, priv->rx_held_valid = 1; } - ebuf->len = lws_ptr_diff(priv->rx.next_out, - ebuf->token); + ebuf->len = lws_ptr_diff(priv->rx.next_out, ebuf->token); priv->count_rx_between_fin += ebuf->len; lwsl_ext(" %s: RX leaving with new effbuff len %d, " diff --git a/minimal-examples/ws-server/README.md b/minimal-examples/ws-server/README.md index b69c1d896..9d52d6d85 100644 --- a/minimal-examples/ws-server/README.md +++ b/minimal-examples/ws-server/README.md @@ -3,6 +3,7 @@ minimal-ws-broker|Simple ws server with a publish / broker / subscribe architecture minimal-ws-server-echo|Simple ws server that listens and echos back anything clients send minimal-ws-server-pmd-bulk|Simple ws server showing how to pass bulk data with permessage-deflate +minimal-ws-server-pmd-corner|Corner-case tests for permessage-deflate minimal-ws-server-pmd|Simple ws server with permessage-deflate support minimal-ws-server-ring|Like minimal-ws-server but holds the chat in a multi-tail ringbuffer minimal-ws-server-threadpool|Demonstrates how to use a worker thread pool with lws diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt new file mode 100644 index 000000000..1098d50e6 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 2.8.9) +include(CheckCSourceCompiles) + +set(SAMP lws-minimal-ws-server-pmd-corner) +set(SRCS minimal-ws-server-pmd-corner.c) + +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + + endif() +ENDMACRO() + +set(requirements 1) +require_lws_config(LWS_ROLE_WS 1 requirements) +require_lws_config(LWS_WITHOUT_SERVER 0 requirements) +require_lws_config(LWS_WITHOUT_EXTENSIONS 0 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets) + endif() +endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/README.md b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/README.md new file mode 100644 index 000000000..eb5a73859 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/README.md @@ -0,0 +1,24 @@ +# lws minimal ws server + permessage-deflate corner case tests + +## build + +``` + $ cmake . && make +``` + +## usage + +``` + $ ./lws-minimal-ws-server-pmd-corner +[2018/11/21 16:47:49:0171] USER: LWS minimal ws server + permessage-deflate Corner Cases | visit http://localhost:7681 +[2018/11/21 16:47:49:0172] NOTICE: Creating Vhost 'default' port 7681, 2 protocols, IPv6 off + +``` + +Visit http://localhost:7681 + +5 ws connections are made via permessage-deflate extension. + +When the ws connection is established, various amounts of data are sent +resulting in ciphertext packets of a known size. + diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/minimal-ws-server-pmd-corner.c b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/minimal-ws-server-pmd-corner.c new file mode 100644 index 000000000..68f11806f --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/minimal-ws-server-pmd-corner.c @@ -0,0 +1,108 @@ +/* + * lws-minimal-ws-server + * + * Copyright (C) 2018 Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates the most minimal http server you can make with lws. + * + * To keep it simple, it serves stuff in the subdirectory "./mount-origin" of + * the directory it was started in. + * You can change that by changing mount.origin. + */ + +#include +#include +#include + +#define LWS_PLUGIN_STATIC +#include "protocol_lws_minimal.c" + +static struct lws_protocols protocols[] = { + { "http", lws_callback_http_dummy, 0, 0 }, + LWS_PLUGIN_PROTOCOL_MINIMAL, + { NULL, NULL, 0, 0 } /* terminator */ +}; + +static int interrupted; + +static const struct lws_http_mount mount = { + /* .mount_next */ NULL, /* linked-list "next" */ + /* .mountpoint */ "/", /* mountpoint URL */ + /* .origin */ "./mount-origin", /* serve from dir */ + /* .def */ "index.html", /* default filename */ + /* .protocol */ NULL, + /* .cgienv */ NULL, + /* .extra_mimetypes */ NULL, + /* .interpret */ NULL, + /* .cgi_timeout */ 0, + /* .cache_max_age */ 0, + /* .auth_mask */ 0, + /* .cache_reusable */ 0, + /* .cache_revalidate */ 0, + /* .cache_intermediaries */ 0, + /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ + /* .mountpoint_len */ 1, /* char count */ + /* .basic_auth_login_file */ NULL, +}; + +static const struct lws_extension extensions[] = { + { + "permessage-deflate", + lws_extension_callback_pm_deflate, + "permessage-deflate" + "; client_no_context_takeover" + "; client_max_window_bits" + }, + { NULL, NULL, NULL /* terminator */ } +}; + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + const char *p; + int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE + /* for LLL_ verbosity above NOTICE to be built into lws, + * lws must have been configured and built with + * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ + /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ + /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ + /* | LLL_DEBUG */; + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS minimal ws server + permessage-deflate Corner Cases | visit http://localhost:7681\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = 7681; + info.mounts = &mount; + info.protocols = protocols; + info.extensions = extensions; + info.options = + LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + while (n >= 0 && !interrupted) + n = lws_service(context, 1000); + + lws_context_destroy(context); + + return 0; +} diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/example.js b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/example.js new file mode 100644 index 000000000..ec3a99c31 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/example.js @@ -0,0 +1,88 @@ + +function get_appropriate_ws_url(extra_url) +{ + var pcol; + var u = document.URL; + + /* + * We open the websocket encrypted if this page came on an + * https:// url itself, otherwise unencrypted + */ + + if (u.substring(0, 5) === "https") { + pcol = "wss://"; + u = u.substr(8); + } else { + pcol = "ws://"; + if (u.substring(0, 4) === "http") + u = u.substr(7); + } + + u = u.split("/"); + + /* + "/xxx" bit is for IE10 workaround */ + + return pcol + u[0] + "/" + extra_url; +} + +function new_ws(urlpath, protocol) +{ + if (typeof MozWebSocket != "undefined") + return new MozWebSocket(urlpath, protocol); + + return new WebSocket(urlpath, protocol); +} + +var ws = new Array(); + +function conn(n) +{ + ws[n] = new_ws(get_appropriate_ws_url("/" + (n + 1)), "lws-minimal"); + ws[n].n = n; + try { + ws[n].onopen = function() { + document.getElementById("r").disabled = 0; + document.getElementById("status").textContent = + document.getElementById("status").textContent + " " + + "ws open "+ ws[n].extensions; + }; + + ws[n].onmessage = function got_packet(msg) { + if (typeof msg.data !== "string") { + //console.log(msg.data); + document.getElementById("r").value = + document.getElementById("r").value + + ws[n].n + " " + "blob uncompressed length " + + msg.data.size + "\n"; + } else + document.getElementById("r").value = + document.getElementById("r").value + msg.data + "\n"; + document.getElementById("r").scrollTop = + document.getElementById("r").scrollHeight; + }; + + ws[n].onclose = function(){ + document.getElementById("r").disabled = 1; + document.getElementById("status").textContent = "ws closed"; + }; + } catch(exception) { + alert("

Error " + exception); + } +} + +window.addEventListener("load", function() { + + var n; + + /* + * we make 5 individual connections. Because if we don't, by default pmd + * will reuse its dictionary to make subsequent tests very short. + */ + + for (n = 0; n < 5; n++) + conn(n); + + console.log("load"); + +}, false); + diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/favicon.ico b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/favicon.ico new file mode 100644 index 000000000..c0cc2e3df Binary files /dev/null and b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/favicon.ico differ diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/index.html b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/index.html new file mode 100644 index 000000000..45b0d8166 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/index.html @@ -0,0 +1,21 @@ + + + + + + + + +
+ + LWS pmd corner case test.
+ A ws link is made back to the server and results shown here.
+ It should show four binary blobs of increasing size. +
+
+ Ws closed
+
+ + + + diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/libwebsockets.org-logo.svg b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/libwebsockets.org-logo.svg new file mode 100644 index 000000000..7baea649f --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/libwebsockets.org-logo.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/strict-csp.svg b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/strict-csp.svg new file mode 100644 index 000000000..cd128f1d2 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/mount-origin/strict-csp.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/protocol_lws_minimal.c b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/protocol_lws_minimal.c new file mode 100644 index 000000000..79152a6a4 --- /dev/null +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/protocol_lws_minimal.c @@ -0,0 +1,303 @@ +/* + * ws protocol handler plugin for "lws-minimal" + * + * Copyright (C) 2010-2018 Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This version holds a single message at a time, which may be lost if a new + * message comes. See the minimal-ws-server-ring sample for the same thing + * but using an lws_ring ringbuffer to hold up to 8 messages at a time. + */ + +#if !defined (LWS_PLUGIN_STATIC) +#define LWS_DLL +#define LWS_INTERNAL +#include +#endif + +#include + +/* + * This came from... + * + * cat /dev/urandom | hexdump -C -n 1024 | tr -s ' ' | cut -d' ' -f 2-17 | head -n-1 | sed "s/\ /, 0x/g" | sed "s/^/0x/g" | sed "s/\$/,/g" + * + * ...then the length tuned by hand to get the ciphertext sizes that we want to + * confirm are OK. + * + * We can only pass in a maximum of one compression buffer of input at a time, + * which is 1024 by default. + */ + +unsigned char uncompressible[] = { + 0xfe, 0xcc, 0x47, 0xcb, 0x10, 0xf4, 0x3c, 0x85, + 0x8e, 0xd4, 0xe2, 0xf6, 0xd1, 0xd1, 0xdb, 0x64, + 0x94, 0x50, 0xf6, 0x14, 0x25, 0x03, 0x09, 0x3a, + 0xb1, 0x47, 0x86, 0xa8, 0x3c, 0x4f, 0x3b, 0x98, + 0x7b, 0x3e, 0x67, 0x3e, 0x22, 0xc5, 0x4c, 0x45, + 0xf4, 0xf7, 0xb5, 0x79, 0xc0, 0x26, 0x6e, 0x5c, + 0xf4, 0x10, 0x04, 0xa9, 0x3c, 0x4f, 0xed, 0xc5, + 0x3d, 0xd4, 0x9f, 0x9f, 0xa3, 0xdb, 0x29, 0xeb, + 0x1e, 0xe1, 0x52, 0xab, 0xb5, 0x75, 0x25, 0x86, + 0x86, 0x02, 0x2c, 0x9d, 0x9c, 0x86, 0x46, 0x92, + 0xe9, 0x04, 0xd8, 0x2c, 0x7d, 0x8a, 0x56, 0xe1, + 0xe1, 0xb6, 0x84, 0x4d, 0x17, 0x30, 0x01, 0x60, + 0xa6, 0xf4, 0xba, 0xc9, 0x5a, 0x29, 0xe3, 0x05, + 0xe1, 0xb4, 0x0b, 0x23, 0x74, 0x93, 0x25, 0x76, + 0xce, 0x15, 0xe4, 0x82, 0x9f, 0xbf, 0xe8, 0x6a, + 0x4a, 0xc5, 0xc2, 0x22, 0x91, 0x80, 0xb5, 0xd7, + 0xb3, 0xce, 0x70, 0x0e, 0xf7, 0xbb, 0x2f, 0xc5, + 0x83, 0x39, 0x86, 0xe5, 0x3e, 0xb7, 0x83, 0x87, + 0xc2, 0xeb, 0xc8, 0xed, 0x59, 0x26, 0xc1, 0xe6, + 0x80, 0x17, 0x3c, 0x29, 0x53, 0x4c, 0x1c, 0x3f, + 0x54, 0xbe, 0x34, 0x26, 0x72, 0xed, 0x38, 0x10, + 0xd1, 0x37, 0x07, 0x2d, 0x12, 0x31, 0x9b, 0xc5, + 0x92, 0x09, 0x13, 0x5d, 0x8e, 0xef, 0xdb, 0x52, + 0x7f, 0x7d, 0x6f, 0x62, 0x1e, 0x17, 0xd2, 0xf9, + 0x72, 0x74, 0xc7, 0xd6, 0x1f, 0x8b, 0x9c, 0x4c, + 0x26, 0xd2, 0x6f, 0x7c, 0x33, 0x06, 0xee, 0xc2, + 0xa3, 0x41, 0x43, 0x4f, 0x40, 0x2a, 0x9c, 0xb3, + 0x4a, 0xb1, 0x88, 0x4e, 0x6f, 0xf2, 0xb7, 0x38, + 0xde, 0x87, 0x0d, 0xdc, 0x15, 0x6a, 0x36, 0x6b, + 0xf3, 0x6c, 0x61, 0xf5, 0x24, 0x8e, 0xb6, 0xcc, + 0x8a, 0x3a, 0xa0, 0xb4, 0x9b, 0xae, 0x85, 0x87, + 0x75, 0xf5, 0xbd, 0x50, 0x1f, 0xb5, 0x0c, 0xdb, + 0x6c, 0x68, 0x59, 0xef, 0x37, 0x5a, 0x2a, 0x85, + 0xf0, 0xce, 0x4d, 0x58, 0xa1, 0xa5, 0xde, 0x73, + 0x9b, 0x1a, 0x3d, 0x8a, 0x00, 0xba, 0x2f, 0xe2, + 0xda, 0xad, 0x3c, 0x63, 0x8a, 0x33, 0x39, 0xc4, + 0x07, 0x29, 0x1d, 0xa7, 0x40, 0x3b, 0xa4, 0xa6, + 0xae, 0xee, 0x37, 0x08, 0x83, 0xd1, 0x72, 0x66, + 0x3d, 0x43, 0xe3, 0x7a, 0x48, 0xfc, 0xf8, 0xd4, + 0xe3, 0xab, 0xd0, 0xe9, 0xb1, 0xf4, 0x4d, 0x3c, + 0x6b, 0x58, 0xde, 0x3c, 0x91, 0x0d, 0x3e, 0xec, + 0x35, 0x6d, 0x53, 0xe6, 0xb6, 0x4b, 0xc0, 0x80, + 0x18, 0xab, 0x96, 0x7f, 0x05, 0xd7, 0xd4, 0x81, + 0x0f, 0x92, 0x2b, 0xaf, 0x72, 0x59, 0xc2, 0x14, + 0xca, 0x62, 0x82, 0xac, 0xe3, 0x17, 0x43, 0x61, + 0x4d, 0x1e, 0xfc, 0x72, 0xaf, 0xfc, 0x55, 0x2a, + 0x2b, 0xb6, 0x8e, 0x6e, 0xe6, 0x86, 0xeb, 0xcc, + 0x26, 0x6c, 0xdf, 0xac, 0x02, 0x58, 0xa1, 0x5d, + 0x1b, 0x07, 0xe2, 0x5d, 0x50, 0xb9, 0xbf, 0x2e, + 0x1f, 0x49, 0x39, 0xe6, 0x7f, 0x2f, 0x0e, 0x9d, + 0x09, 0x42, 0xc7, 0xa1, 0xcc, 0xeb, 0x5b, 0x06, + 0x1c, 0x11, 0x9f, 0xea, 0xc1, 0x96, 0x82, 0xa9, + 0x30, 0x6a, 0xda, 0x98, 0x87, 0x43, 0xfd, 0x25, + 0xe7, 0x27, 0x53, 0x9a, 0xb3, 0x2f, 0x19, 0xa9, + 0x1a, 0xf4, 0xd6, 0xf3, 0x9e, 0xba, 0x9a, 0x91, + 0x52, 0x8f, 0x20, 0x6b, 0x4c, 0x3a, 0x2a, 0x3d, + 0xa0, 0xff, 0x8d, 0x61, 0x04, 0xee, 0x26, 0x55, + 0xdd, 0xd7, 0x67, 0xe4, 0x84, 0x0d, 0xf1, 0x5d, + 0xc7, 0xeb, 0xb3, 0x8c, 0x67, 0xa2, 0xc8, 0x1f, + 0x53, 0x02, 0xc4, 0x8c, 0x89, 0xd5, 0x51, 0xc8, + 0x8b, 0xb7, 0xc8, 0x11, 0xbe, 0x0e, 0xc2, 0xb1, + 0x00, 0x35, 0x81, 0x96, 0xac, 0x90, 0x9c, 0xbc, + 0x09, 0x82, 0x75, 0xc3, 0xe7, 0x66, 0x4e, 0x68, + 0xdc, 0xa1, 0xf0, 0xd0, 0x2d, 0x49, 0x3b, 0x47, + 0xba, 0x19, 0xc8, 0x9b, 0x90, 0x12, 0xc0, 0xdf, + 0xda, 0x32, 0x0f, 0x79, 0x6d, 0x1a, 0x5f, 0x92, + 0x51, 0x70, 0xfc, 0xca, 0x08, 0xd4, 0x7f, 0x1a, + 0x56, 0x04, 0x99, 0x33, 0x89, 0x3d, 0x6f, 0x89, + 0x10, 0x25, 0x81, 0xe2, 0xbd, 0x06, 0xd6, 0xaa, + 0x02, 0x8e, 0x4c, 0xa3, 0x60, 0xfd, 0xaf, 0x9c, + 0x81, 0x75, 0xaf, 0x2f, 0xe1, 0x72, 0xe0, 0x6e, + 0x15, 0xdd, 0xbb, 0x92, 0xd1, 0xbe, 0x8e, 0x9b, + 0xfb, 0x82, 0xb9, 0x47, 0x6f, 0x02, 0x28, 0x2a, + 0x67, 0x50, 0xed, 0x24, 0x9b, 0x4d, 0x69, 0xd7, + 0xa9, 0x66, 0x3e, 0x14, 0x4b, 0x00, 0x2a, 0xe4, + 0x3d, 0x63, 0xb2, 0x10, 0xd4, 0x05, 0x9d, 0xe3, + 0xde, 0xce, 0xd8, 0x04, 0x41, 0x03, 0xb5, 0xda, + 0xb0, 0x6f, 0xca, 0x63, 0x64, 0x04, 0xff, 0x07, + 0x58, 0x5f, 0x96, 0xf7, 0x6c, 0xb7, 0x67, 0x05, + 0xd6, 0x85, 0xf2, 0x1e, 0xc1, 0xdc, 0x76, 0x12, + 0x50, 0x83, 0x78, 0xa2, 0x51, 0x94, 0xe1, 0x2e, + 0xb8, 0x97, 0x5b, 0x08, 0x81, 0xac, 0x59, 0x43, + 0xe9, 0x01, 0x09, 0xa2, 0xed, 0x10, 0x4f, 0xb1, + 0x5b, 0xb8, 0x67, 0xe8, 0x61, 0x8d, 0xc8, 0xd9, + 0xc3, 0x5f, 0x65, 0xd7, 0xaa, 0x30, 0x0e, 0xc9, + 0x43, 0x98, 0x1d, 0xf1, 0xa5, 0x28, 0xd5, 0xa1, + 0x6b, 0x8f, 0x89, 0x76, 0x97, 0xa1, 0x3e, 0x6f, + 0x39, 0xf4, 0xb9, 0x6b, 0xa7, 0xfe, 0x58, 0x24, + 0xcd, 0x75, 0xa8, 0xec, 0x9e, 0x1c, 0x8e, 0x02, + 0x2a, 0xce, 0xe9, 0x0a, 0x24, 0x31, 0x89, 0x5a, + 0xd5, 0xdd, 0x70, 0x8e, 0x5f, 0xee, 0xc1, 0x34, + 0xf8, 0xe2, 0x8a, 0xca, 0xf1, 0xf2, 0x71, 0x4c, + 0x31, 0x56, 0xeb, 0x03, 0xf9, 0x6c, 0x0d, 0xa9, + 0x65, 0x6e, 0x88, 0x4f, 0x8e, 0x80, 0x69, 0xd7, + 0xd4, 0x63, 0x45, 0x9c, 0xab, 0x8c, 0x3d, 0x08, + 0x8b, 0xd9, 0x97, 0xdc, 0x88, 0x59, 0x19, 0x2d, + 0xb2, 0x84, 0xf4, 0x78, 0x3e, 0xce, 0x80, 0xba, + 0xeb, 0x34, 0x5a, 0x9e, 0x8e, 0x98, 0xc4, 0x45, + 0x9d, 0x59, 0xb2, 0x7e, 0xc1, 0x7e, 0x5b, 0x89, + 0xd0, 0x02, 0xcb, 0xa4, 0xf1, 0xf2, 0xa7, 0x3a, + 0x05, 0xc3, 0x7d, 0x43, 0x64, 0x7f, 0xf0, 0xc1, + 0xf8, 0x71, 0x3b, 0x38, 0x39, 0xc7, 0x1b, 0xf4, + 0x2f, 0x5a, 0x5c, 0x43, 0x1b, 0xe3, 0x93, 0xe8, + 0x79, 0xe8, 0x35, 0x63, 0x34, 0x7e, 0x25, 0x41, + 0x6f, 0x08, 0xce, 0x6f, 0x95, 0x2a, 0xc2, 0xdc, + 0x65, 0xe2, 0xa5, 0xc0, 0xfd, 0xf1, 0x78, 0x32, + 0x23, 0x09, 0x75, 0x99, 0x12, 0x7a, 0x83, 0xfd, + 0xae, 0x1e, 0xb2, 0xe9, 0x12, 0x5c, 0x3d, 0x03, + 0x68, 0x12, 0x1e, 0xe3, 0x8f, 0xff, 0x47, 0xe3, + 0xb4, 0x7e, 0x9b, 0x7e, 0x60, 0x2e, 0xf4, 0x06, + 0xba, 0x10, 0x08, 0x6b, 0xf9, 0x25, 0x59, 0xf3, + 0x61, 0x13, 0x2b, 0xd1, 0x2f, 0x04, 0x5f, 0xd6, + 0xd3, 0x42, 0xf6, 0x21, 0x57, 0xf6, 0xd3, 0xb3, + 0xec, 0xec, 0x07, 0x33, 0xbf, 0x69, 0x04, 0xec, + 0x88, 0x8d, 0x06, 0x2b, 0xfa, 0xee, 0xb2, 0x7b, + 0x41, 0x2a, 0x49, 0x0f, 0x30, 0x52, 0x41, 0x29, + 0x70, 0xd0, 0xf6, 0xb6, 0xbf, 0x27, 0x1a, 0x56, + 0x9a, 0x4b, 0x2a, 0x67, 0xfb, 0xc8, 0x16, 0x46, + 0x59, 0xc7, 0xf5, 0x5f, 0x20, 0x10, 0x25, 0x6c, + 0x1e, 0x36, 0x20, 0x0c, 0x3e, 0x7e, 0x15, 0x6c, + 0xa2, 0xbd, 0x22, 0xc4, 0x3d, 0xc9, 0x74, 0x56, + 0xab, 0x31, 0x92, 0xb8, 0x9f, 0xa1, 0x05, 0x2e, + 0xc4, 0xdb, 0x32, 0x91, 0xcb, 0x0f, 0x4a, 0x73, + 0x7f, 0xe1, 0xe6, 0x65, 0x2e, 0x5e, 0xa6, 0xaf, + 0xae, 0xa9, 0x04, 0x14, 0x83, 0xef, 0x19, 0x70, + 0x5e, 0xcb, 0xf5, 0x87, 0xcc, 0x45, 0xf7, 0x60, + 0xd7, 0x9d, 0x1e, 0x2e, /* 1012 */ + + /* up to here, this generates a 1022-byte single packet of compressed + * data that is well-formed and produces 1012 bytes of plaintext. + * + * The compressed packet ends + * + * 03F0: 70 5E CB F5 87 CC 45 F7 60 D7 9D 1E 2E 00 + */ + + 0x54, /* 1013 */ + + /* up to here, this generates a 1023-byte single packet of compressed + * data that is well-formed and produces 1013 bytes of plaintext. + * + * The compressed packet ends + * + * 03F0: 70 5E CB F5 87 CC 45 F7 60 D7 9D 1E 2E 54 00 + */ + + 0x83, /* 1014 */ + + /* up to here, a 1023-byte + 3-byte (1 byte payload) packet + * of uncompressed length 1014 */ + + 0x09, 0x99, 0xf9, 0x71, 0x9f, 0x15, 0x49, 0xda, 0xa8, 0x99, /* 1024 */ + + /* up to here, a 1023-byte (1020 payload) + 3-byte (1 payload) packet + * of uncompressed length 1019 */ + + 0xf5, 0xe6, 0xa1, 0x71, 0x64, 0x9a, 0x95, 0xed, + + +}; + +/* generates ciphertext: 1022 1023 1023 + 3 1023 + 3 */ +static int corner_lengths[] = { +/* bytes plaintext, ciphertext */ + 1012, /* 1019 */ + 1013, /* 1020 */ + 1014, /* 1021 */ + 1019, /* 1021 */ + 1024, /* 1021*/ +}; + + +/* one of these is created for each client connecting to us */ + +struct per_session_data__minimal { + int which; + int last; /* 0 no test, else test number in corner_lengths[] + 1 */ +}; + +static int +callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct per_session_data__minimal *pss = + (struct per_session_data__minimal *)user; + unsigned char buf[LWS_PRE + 2048]; + int m; + + switch (reason) { + case LWS_CALLBACK_ESTABLISHED: + if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI) < 0) + return -1; + + pss->last = atoi(buf + 1); + + if (pss->last > LWS_ARRAY_SIZE(corner_lengths)) + pss->last = 0; + lws_callback_on_writable(wsi); + break; + + case LWS_CALLBACK_SERVER_WRITEABLE: + if (!pss->last) + break; + + lwsl_err("%s: writable %d, %d\n", __func__, pss->last, + corner_lengths[pss->last - 1]); + + memcpy(buf + LWS_PRE, uncompressible, + corner_lengths[pss->last - 1]); + + /* notice we allowed for LWS_PRE in the payload already */ + m = lws_write(wsi, buf + LWS_PRE, corner_lengths[pss->last - 1], + LWS_WRITE_BINARY); + if (m < corner_lengths[pss->last - 1]) { + lwsl_err("ERROR %d writing to ws socket\n", m); + return -1; + } + + pss->last = 0; + break; + + default: + break; + } + + return 0; +} + +#define LWS_PLUGIN_PROTOCOL_MINIMAL \ + { \ + "lws-minimal", \ + callback_minimal, \ + sizeof(struct per_session_data__minimal), \ + 2048, \ + 0, NULL, 0 \ + } + +#if !defined (LWS_PLUGIN_STATIC) + +/* boilerplate needed if we are built as a dynamic plugin */ + +static const struct lws_protocols protocols[] = { + LWS_PLUGIN_PROTOCOL_MINIMAL +}; + +LWS_EXTERN LWS_VISIBLE int +init_protocol_minimal(struct lws_context *context, + struct lws_plugin_capability *c) +{ + if (c->api_magic != LWS_PLUGIN_API_MAGIC) { + lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, + c->api_magic); + return 1; + } + + c->protocols = protocols; + c->count_protocols = LWS_ARRAY_SIZE(protocols); + c->extensions = NULL; + c->count_extensions = 0; + + return 0; +} + +LWS_EXTERN LWS_VISIBLE int +destroy_protocol_minimal(struct lws_context *context) +{ + return 0; +} +#endif