diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 91fef0f06..a0c128c35 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -5159,19 +5159,22 @@ lws_rx_flow_allow_all_protocol(const struct lws_context *context, /** * lws_remaining_packet_payload() - Bytes to come before "overall" - * rx packet is complete + * rx fragment is complete * \param wsi: Websocket instance (available from user callback) * - * This function is intended to be called from the callback if the - * user code is interested in "complete packets" from the client. - * libwebsockets just passes through payload as it comes and issues a buffer - * additionally when it hits a built-in limit. The LWS_CALLBACK_RECEIVE - * callback handler can use this API to find out if the buffer it has just - * been given is the last piece of a "complete packet" from the client -- - * when that is the case lws_remaining_packet_payload() will return - * 0. + * This tracks how many bytes are left in the current ws fragment, according + * to the ws length given in the fragment header. * - * Many protocols won't care becuse their packets are always small. + * If the message was in a single fragment, and there is no compression, this + * is the same as "how much data is left to read for this message". + * + * However, if the message is being sent in multiple fragments, this will + * reflect the unread amount of the current **fragment**, not the message. With + * ws, it is legal to not know the length of the message before it completes. + * + * Additionally if the message is sent via the negotiated permessage-deflate + * extension, this number only tells the amount of **compressed** data left to + * be read, since that is the only information available at the ws layer. */ LWS_VISIBLE LWS_EXTERN size_t lws_remaining_packet_payload(struct lws *wsi); diff --git a/lib/service.c b/lib/service.c index 4fe9b9e75..a82c1cb82 100644 --- a/lib/service.c +++ b/lib/service.c @@ -1749,7 +1749,7 @@ read: eff_buf.token_len); switch (eff_buf.token_len) { case 0: - lwsl_notice("%s: zero length read\n", + lwsl_info("%s: zero length read\n", __func__); goto close_and_handled; case LWS_SSL_CAPABLE_MORE_SERVICE: diff --git a/minimal-examples/ws-client/README.md b/minimal-examples/ws-client/README.md index 34248bc2b..e769c01e6 100644 --- a/minimal-examples/ws-client/README.md +++ b/minimal-examples/ws-client/README.md @@ -1,4 +1,5 @@ |name|demonstrates| ---|--- +minimal-ws-client-pmd-bulk|Client that sends bulk multifragment data to the minimal-ws-server-pmd-bulk example minimal-ws-client-rx|Connects to the dumb-increment-protocol wss server at https://libwebsockets.org and demonstrates receiving ws data minimal-ws-client-tx|Connects to the minimal-ws-broker example as a publisher, demonstrating sending ws data diff --git a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt new file mode 100644 index 000000000..6e0af9cb6 --- /dev/null +++ b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 2.8.9) +include(CheckCSourceCompiles) + +set(SAMP lws-minimal-ws-client-pmd-bulk) +set(SRCS minimal-ws-client-pmd-bulk.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_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-client/minimal-ws-client-pmd-bulk/README.md b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/README.md new file mode 100644 index 000000000..f43a458f6 --- /dev/null +++ b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/README.md @@ -0,0 +1,164 @@ +# lws minimal ws client + permessage-deflate for bulk traffic + +This example opens a client connection to localhost:7681 where it +expects to find minimal-ws-server-pmd-bulk running. + +It sends and receives a large, multifragment message, and then exits. + +## build + +``` + $ cmake . && make +``` + +## usage + +Both the server and client side must use the same options + + - `-n` disable permessage-deflate extension + - `-c` send compressible text instead of uncompressible binary data + +``` + $ ./lws-minimal-ws-client-pmd-bulk +[2018/04/05 12:08:58:9120] USER: LWS minimal ws client + permessage-deflate + multifragment bulk message +[2018/04/05 12:08:58:9120] USER: ./lws-minimal-ws-client-pmd-bulk [-n (no exts)] [-c (compressible)] +[2018/04/05 12:08:58:9120] NOTICE: Creating Vhost 'default' (serving disabled), 2 protocols, IPv6 on +[2018/04/05 12:08:59:9139] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9139] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9139] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9139] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9139] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9140] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9140] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9140] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9140] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9140] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9140] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9141] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9141] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9141] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9142] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9142] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9142] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9142] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9142] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9142] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9143] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9143] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9143] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9143] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9143] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9143] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9144] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9144] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9144] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9144] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9144] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9144] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9145] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9145] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9145] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9145] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9146] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9146] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9146] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9146] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9146] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9146] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9147] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9147] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9147] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9147] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9147] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9148] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9148] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9148] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9148] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9148] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9148] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9149] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9149] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9149] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9149] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9149] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9149] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9150] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9150] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9150] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9150] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9150] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9150] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9151] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9151] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9151] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9151] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9152] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9152] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9152] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9152] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9152] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9152] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9153] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9153] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9153] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9153] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9153] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9153] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9154] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9154] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9154] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9154] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9154] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9154] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9155] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9155] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9155] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9155] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9155] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9155] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9156] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9156] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9156] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9156] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9157] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9157] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9157] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9157] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9157] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9158] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9158] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9158] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9158] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9158] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9158] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9159] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9159] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9159] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9159] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9159] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9159] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9160] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9160] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9160] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9160] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9160] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9160] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9161] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9161] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9161] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9161] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9161] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9161] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9162] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9162] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9162] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9162] USER: LWS_CALLBACK_CLIENT_RECEIVE: 1024 (rpp 0, last 0) +[2018/04/05 12:08:59:9162] USER: LWS_CALLBACK_CLIENT_RECEIVE: 580 (rpp 0, last 1) +[2018/04/05 12:08:59:9180] USER: Completed OK +``` + +Visit http://localhost:7681 in your browser + +One or another kind of bulk ws transfer is made to the browser. + +The ws connection is made via permessage-deflate extension. diff --git a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c new file mode 100644 index 000000000..b5825e3cd --- /dev/null +++ b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/minimal-ws-client-pmd-bulk.c @@ -0,0 +1,128 @@ +/* + * lws-minimal-ws-client-pmd-bulk + * + * Copyright (C) 2018 Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates a ws client that sends bulk data in multiple + * ws fragments, in a way compatible with per-message deflate. + * + * It shows how to send huge messages without needing a lot of memory. + * + * Build and start the minimal-examples/ws-server/minmal-ws-server-pmd-bulk + * example first. Running this sends a large message to the server and + * exits. + * + * If you give both sides the -n commandline option, it disables permessage- + * deflate compression extension. + */ + +#include +#include +#include + +#define LWS_PLUGIN_STATIC +#include "protocol_lws_minimal_pmd_bulk.c" + +static struct lws_protocols protocols[] = { + { "http", lws_callback_http_dummy, 0, 0 }, + LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK, + { NULL, NULL, 0, 0 } /* terminator */ +}; + +static int interrupted, options; + +/* pass pointers to shared vars to the protocol */ + +static const struct lws_protocol_vhost_options pvo_options = { + NULL, + NULL, + "options", /* pvo name */ + (void *)&options /* pvo value */ +}; + +static const struct lws_protocol_vhost_options pvo_interrupted = { + &pvo_options, + NULL, + "interrupted", /* pvo name */ + (void *)&interrupted /* pvo value */ +}; + +static const struct lws_protocol_vhost_options pvo = { + NULL, /* "next" pvo linked-list */ + &pvo_interrupted, /* "child" pvo linked-list */ + "lws-minimal-pmd-bulk", /* protocol name we belong to on this vhost */ + "" /* ignored */ +}; +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; +} + +static int findswitch(int argc, char **argv, const char *val) +{ + while (--argc > 0) { + if (!strcmp(argv[argc], val)) + return 1; + } + + return 0; +} + +int main(int argc, char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = CONTEXT_PORT_NO_LISTEN; + info.protocols = protocols; + info.pvo = &pvo; + if (!findswitch(argc, argv, "-n")) + info.extensions = extensions; + info.pt_serv_buf_size = 32 * 1024; + + if (!findswitch(argc, argv, "-c")) + options |= 1; + + lws_set_log_level(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 */, NULL); + + lwsl_user("LWS minimal ws client + permessage-deflate + multifragment bulk message\n"); + lwsl_user(" %s [-n (no exts)] [-c (compressible)]\n", argv[0]); + 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); + + lwsl_user("Completed %s\n", interrupted == 2 ? "OK" : "failed"); + + return interrupted != 2; +} diff --git a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c new file mode 100644 index 000000000..e4c48c101 --- /dev/null +++ b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c @@ -0,0 +1,319 @@ +/* + * ws protocol handler plugin for "lws-minimal-pmd-bulk" + * + * Copyright (C) 2010-2018 Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * The protocol shows how to send and receive bulk messages over a ws connection + * that optionally may have the permessage-deflate extension negotiated on it. + */ + +#if !defined (LWS_PLUGIN_STATIC) +#define LWS_DLL +#define LWS_INTERNAL +#include +#endif + +#include + +/* + * We will produce a large ws message either from this text repeated many times, + * or from 0x40 + a 6-bit pseudorandom number + */ + +static const char * const redundant_string = + "No one would have believed in the last years of the nineteenth " + "century that this world was being watched keenly and closely by " + "intelligences greater than man's and yet as mortal as his own; that as " + "men busied themselves about their various concerns they were " + "scrutinised and studied, perhaps almost as narrowly as a man with a " + "microscope might scrutinise the transient creatures that swarm and " + "multiply in a drop of water. With infinite complacency men went to " + "and fro over this globe about their little affairs, serene in their " + "assurance of their empire over matter. It is possible that the " + "infusoria under the microscope do the same. No one gave a thought to " + "the older worlds of space as sources of human danger, or thought of " + "them only to dismiss the idea of life upon them as impossible or " + "improbable. It is curious to recall some of the mental habits of " + "those departed days. At most terrestrial men fancied there might be " + "other men upon Mars, perhaps inferior to themselves and ready to " + "welcome a missionary enterprise. Yet across the gulf of space, minds " + "that are to our minds as ours are to those of the beasts that perish, " + "intellects vast and cool and unsympathetic, regarded this earth with " + "envious eyes, and slowly and surely drew their plans against us. And " + "early in the twentieth century came the great disillusionment. " +; + +/* this reflects the length of the string above */ +#define REPEAT_STRING_LEN 1337 +/* this is the total size of the ws message we will send */ +#define MESSAGE_SIZE (100 * REPEAT_STRING_LEN) +/* this is how much we will send each time the connection is writable */ +#define MESSAGE_CHUNK_SIZE (1 * 1024) + +/* one of these is created for each client connecting to us */ + +struct per_session_data__minimal_pmd_bulk { + int position_tx, position_rx; + uint64_t rng_rx, rng_tx; +}; + +struct vhd_minimal_pmd_bulk { + struct lws_context *context; + struct lws_vhost *vhost; + struct lws *client_wsi; + + int *interrupted; + int *options; +}; + +static uint64_t rng(uint64_t *r) +{ + *r ^= *r << 21; + *r ^= *r >> 35; + *r ^= *r << 4; + + return *r; +} + +static int +connect_client(struct vhd_minimal_pmd_bulk *vhd) +{ + struct lws_client_connect_info i; + + memset(&i, 0, sizeof(i)); + + i.context = vhd->context; + i.port = 7681; + i.address = "localhost"; + i.path = "/"; + i.host = i.address; + i.origin = i.address; + i.ssl_connection = 0; + i.vhost = vhd->vhost; + i.protocol = "lws-minimal-pmd-bulk"; + i.pwsi = &vhd->client_wsi; + + return !lws_client_connect_via_info(&i); +} + +static void +schedule_callback(struct lws *wsi, int reason, int secs) +{ + lws_timed_callback_vh_protocol(lws_get_vhost(wsi), + lws_get_protocol(wsi), reason, secs); +} + +static int +callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct per_session_data__minimal_pmd_bulk *pss = + (struct per_session_data__minimal_pmd_bulk *)user; + struct vhd_minimal_pmd_bulk *vhd = (struct vhd_minimal_pmd_bulk *) + lws_protocol_vh_priv_get(lws_get_vhost(wsi), + lws_get_protocol(wsi)); + uint8_t buf[LWS_PRE + MESSAGE_CHUNK_SIZE], *start = &buf[LWS_PRE], *p; + int n, m, flags; + + switch (reason) { + + case LWS_CALLBACK_PROTOCOL_INIT: + vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), + lws_get_protocol(wsi), + sizeof(struct vhd_minimal_pmd_bulk)); + if (!vhd) + return -1; + + vhd->context = lws_get_context(wsi); + vhd->vhost = lws_get_vhost(wsi); + + /* get the pointer to "interrupted" we were passed in pvo */ + vhd->interrupted = (int *)lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "interrupted")->value; + vhd->options = (int *)lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "options")->value; + + if (connect_client(vhd)) + schedule_callback(wsi, LWS_CALLBACK_USER, 1); + break; + + case LWS_CALLBACK_CLIENT_ESTABLISHED: + pss->rng_tx = 4; + pss->rng_rx = 4; + lws_callback_on_writable(wsi); + break; + + case LWS_CALLBACK_CLIENT_WRITEABLE: + + /* + * when we connect, we will send the server a message + */ + + if (pss->position_tx == MESSAGE_SIZE) + break; + + /* fill up one chunk's worth of message content */ + + p = start; + n = MESSAGE_CHUNK_SIZE; + if (n > MESSAGE_SIZE - pss->position_tx) + n = MESSAGE_SIZE - pss->position_tx; + + flags = lws_write_ws_flags(LWS_WRITE_BINARY, !pss->position_tx, + pss->position_tx + n == MESSAGE_SIZE); + + /* + * select between producing compressible repeated text, + * or uncompressible PRNG output + */ + + if (*vhd->options & 1) { + while (n) { + size_t s; + + m = pss->position_tx % REPEAT_STRING_LEN; + s = REPEAT_STRING_LEN - m; + if (s > (size_t)n) + s = n; + memcpy(p, &redundant_string[m], s); + pss->position_tx += s; + p += s; + n -= s; + } + } else { + pss->position_tx += n; + while (n--) + *p++ = rng(&pss->rng_tx); + } + + n = lws_ptr_diff(p, start); + m = lws_write(wsi, start, n, flags); + if (m < n) { + lwsl_err("ERROR %d writing ws\n", m); + return -1; + } + if (pss->position_tx != MESSAGE_SIZE) /* if more to do... */ + lws_callback_on_writable(wsi); + else + /* if we sent and received everything */ + if (pss->position_rx == MESSAGE_SIZE) + *vhd->interrupted = 2; + break; + + case LWS_CALLBACK_CLIENT_RECEIVE: + + /* + * When we connect, the server will send us a message too + */ + + lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE: %4d (rpp %5d, last %d)\n", + (int)len, (int)lws_remaining_packet_payload(wsi), + lws_is_final_fragment(wsi)); + + if (*vhd->options & 1) { + while (len) { + size_t s; + + m = pss->position_rx % REPEAT_STRING_LEN; + s = REPEAT_STRING_LEN - m; + if (s > len) + s = len; + if (memcmp(in, &redundant_string[m], s)) { + lwsl_user("echo'd data doesn't match\n"); + return -1; + } + pss->position_rx += s; + in += s; + len -= s; + } + } else { + p = (uint8_t *)in; + pss->position_rx += len; + while (len--) + if (*p++ != (uint8_t)rng(&pss->rng_rx)) { + lwsl_user("echo'd data doesn't match\n"); + return -1; + } + } + + /* if we sent and received everything */ + + if (pss->position_rx == MESSAGE_SIZE && + pss->position_tx == MESSAGE_SIZE) + *vhd->interrupted = 2; + + break; + + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", + in ? (char *)in : "(null)"); + vhd->client_wsi = NULL; + schedule_callback(wsi, LWS_CALLBACK_USER, 1); + break; + + case LWS_CALLBACK_CLIENT_CLOSED: + vhd->client_wsi = NULL; + schedule_callback(wsi, LWS_CALLBACK_USER, 1); + break; + + /* rate-limited client connect retries */ + + case LWS_CALLBACK_USER: + lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); + if (connect_client(vhd)) + schedule_callback(wsi, LWS_CALLBACK_USER, 1); + break; + + default: + break; + } + + return 0; +} + +#define LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK \ + { \ + "lws-minimal-pmd-bulk", \ + callback_minimal_pmd_bulk, \ + sizeof(struct per_session_data__minimal_pmd_bulk), \ + 4096, \ + 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_PMD_BULK +}; + +LWS_EXTERN LWS_VISIBLE int +init_protocol_minimal_pmd_bulk(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 = ARRAY_SIZE(protocols); + c->extensions = NULL; + c->count_extensions = 0; + + return 0; +} + +LWS_EXTERN LWS_VISIBLE int +destroy_protocol_minimal_pmd_bulk(struct lws_context *context) +{ + return 0; +} +#endif diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c index 29e0d7a2c..301ab8d1c 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/minimal-ws-server-pmd-bulk.c @@ -26,7 +26,30 @@ static struct lws_protocols protocols[] = { { NULL, NULL, 0, 0 } /* terminator */ }; -static int interrupted; +static int interrupted, options; + +/* pass pointers to shared vars to the protocol */ + +static const struct lws_protocol_vhost_options pvo_options = { + NULL, + NULL, + "options", /* pvo name */ + (void *)&options /* pvo value */ +}; + +static const struct lws_protocol_vhost_options pvo_interrupted = { + &pvo_options, + NULL, + "interrupted", /* pvo name */ + (void *)&interrupted /* pvo value */ +}; + +static const struct lws_protocol_vhost_options pvo = { + NULL, /* "next" pvo linked-list */ + &pvo_interrupted, /* "child" pvo linked-list */ + "lws-minimal-pmd-bulk", /* protocol name we belong to on this vhost */ + "" /* ignored */ +}; static const struct lws_http_mount mount = { /* .mount_next */ NULL, /* linked-list "next" */ @@ -64,6 +87,16 @@ void sigint_handler(int sig) interrupted = 1; } +static int findswitch(int argc, char **argv, const char *val) +{ + while (--argc > 0) { + if (!strcmp(argv[argc], val)) + return 1; + } + + return 0; +} + int main(int argc, char **argv) { struct lws_context_creation_info info; @@ -76,7 +109,14 @@ int main(int argc, char **argv) info.port = 7681; info.mounts = &mount; info.protocols = protocols; - info.extensions = extensions; + info.pvo = &pvo; + + if (!findswitch(argc, argv, "-n")) + info.extensions = extensions; + + if (!findswitch(argc, argv, "-c")) + options |= 1; + info.pt_serv_buf_size = 32 * 1024; lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE @@ -88,7 +128,7 @@ int main(int argc, char **argv) /* | LLL_DEBUG */, NULL); lwsl_user("LWS minimal ws server + permessage-deflate | visit http://localhost:7681\n"); - + lwsl_user(" %s [-n (no exts)] [-c (compressible)]\n", argv[0]); context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/index.html b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/index.html index 07cf2b251..29954f44c 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/index.html +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/mount-origin/index.html @@ -61,9 +61,12 @@ try { ws.onmessage =function got_packet(msg) { console.log("Received ws message len " + msg.data.length); document.getElementById("r").value = - document.getElementById("r").value + msg.data + "\n"; + document.getElementById("r").value + "\nReceived: " + msg.data.length + " bytes\n"; document.getElementById("r").scrollTop = document.getElementById("r").scrollHeight; + + /* echo it back */ + ws.send(msg.data); } ws.onclose = function(){ diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c index 7f7499cc6..886cb8806 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c @@ -56,64 +56,96 @@ static const char * const redundant_string = /* one of these is created for each client connecting to us */ struct per_session_data__minimal_pmd_bulk { - int position; /* byte position we got up to sending the message */ - uint64_t rng; + int position_tx, position_rx; + uint64_t rng_rx, rng_tx; }; +struct vhd_minimal_pmd_bulk { + int *interrupted; + int *options; /* b0 = 1: test compressible text, = 0: test uncompressible binary */ +}; + +static uint64_t rng(uint64_t *r) +{ + *r ^= *r << 21; + *r ^= *r >> 35; + *r ^= *r << 4; + + return *r; +} + static int callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { struct per_session_data__minimal_pmd_bulk *pss = (struct per_session_data__minimal_pmd_bulk *)user; + struct vhd_minimal_pmd_bulk *vhd = (struct vhd_minimal_pmd_bulk *) + lws_protocol_vh_priv_get(lws_get_vhost(wsi), + lws_get_protocol(wsi)); uint8_t buf[LWS_PRE + MESSAGE_CHUNK_SIZE], *start = &buf[LWS_PRE], *p; - int n, m, flags; + int n, m, flags, olen; switch (reason) { + case LWS_CALLBACK_PROTOCOL_INIT: + vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), + lws_get_protocol(wsi), + sizeof(struct vhd_minimal_pmd_bulk)); + if (!vhd) + return -1; + + /* get the pointer to "interrupted" we were passed in pvo */ + vhd->interrupted = (int *)lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "interrupted")->value; + vhd->options = (int *)lws_pvo_search( + (const struct lws_protocol_vhost_options *)in, + "options")->value; + break; + case LWS_CALLBACK_ESTABLISHED: - pss->position = 0; - pss->rng = 4; + pss->rng_tx = 4; + pss->rng_rx = 4; lws_callback_on_writable(wsi); break; case LWS_CALLBACK_SERVER_WRITEABLE: - if (pss->position == MESSAGE_SIZE) + if (pss->position_tx == MESSAGE_SIZE) break; /* fill up one chunk's worth of message content */ p = start; n = MESSAGE_CHUNK_SIZE; - if (n > MESSAGE_SIZE - pss->position) - n = MESSAGE_SIZE - pss->position; + if (n > MESSAGE_SIZE - pss->position_tx) + n = MESSAGE_SIZE - pss->position_tx; - flags = lws_write_ws_flags(LWS_WRITE_TEXT, !pss->position, - pss->position + n == MESSAGE_SIZE); + flags = lws_write_ws_flags(LWS_WRITE_BINARY, !pss->position_tx, + pss->position_tx + n == MESSAGE_SIZE); /* * select between producing compressible repeated text, * or uncompressible PRNG output */ -#if 0 - while (n) { - m = pss->position % REPEAT_STRING_LEN; - s = REPEAT_STRING_LEN - m; - if (s > n) - s = n; - memcpy(p, &redundant_string[m], s); - pss->position += s; - p += s; - n -= s; + + if (*vhd->options & 1) { + while (n) { + size_t s; + + m = pss->position_tx % REPEAT_STRING_LEN; + s = REPEAT_STRING_LEN - m; + if (s > (size_t)n) + s = n; + memcpy(p, &redundant_string[m], s); + pss->position_tx += s; + p += s; + n -= s; + } + } else { + pss->position_tx += n; + while (n--) + *p++ = rng(&pss->rng_tx); } -#else - pss->position += n; - while (n--) { - pss->rng ^= pss->rng << 21; - pss->rng ^= pss->rng >> 35; - pss->rng ^= pss->rng << 4; - *p++ = 0x40 + ((pss->rng >> (n & 15)) & 0x3f); - } -#endif n = lws_ptr_diff(p, start); m = lws_write(wsi, start, n, flags); @@ -121,10 +153,48 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, lwsl_err("ERROR %d writing ws\n", n); return -1; } - if (pss->position != MESSAGE_SIZE) /* if more to do... */ + if (pss->position_tx != MESSAGE_SIZE) /* if more to do... */ lws_callback_on_writable(wsi); break; + case LWS_CALLBACK_RECEIVE: + lwsl_user("LWS_CALLBACK_RECEIVE: %4d (pss->pos=%d, rpp %5d, last %d)\n", + (int)len, (int)pss->position_rx, (int)lws_remaining_packet_payload(wsi), + lws_is_final_fragment(wsi)); + olen = len; + + if (*vhd->options & 1) { + while (len) { + size_t s; + m = pss->position_rx % REPEAT_STRING_LEN; + s = REPEAT_STRING_LEN - m; + if (s > len) + s = len; + if (memcmp(in, &redundant_string[m], s)) { + lwsl_user("echo'd data doesn't match\n"); + return -1; + } + pss->position_rx += s; + in += s; + len -= s; + } + } else { + p = (uint8_t *)in; + pss->position_rx += len; + while (len--) { + if (*p++ != (uint8_t)rng(&pss->rng_rx)) { + lwsl_user("echo'd data doesn't match: 0x%02X 0x%02X (%d)\n", + *(p - 1), (int)(0x40 + (pss->rng_rx & 0x3f)), + (int)((pss->position_rx - olen) + olen - len)); + lwsl_hexdump_notice(in, olen); + return -1; + } + } + if (pss->position_rx == MESSAGE_SIZE) + pss->position_rx = 0; + } + break; + default: break; }