minimal-ws-server-pmd-bulk: add echo
This commit is contained in:
parent
de4c1303f5
commit
c8af76c07c
10 changed files with 851 additions and 45 deletions
|
@ -5159,19 +5159,22 @@ lws_rx_flow_allow_all_protocol(const struct lws_context *context,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lws_remaining_packet_payload() - Bytes to come before "overall"
|
* 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)
|
* \param wsi: Websocket instance (available from user callback)
|
||||||
*
|
*
|
||||||
* This function is intended to be called from the callback if the
|
* This tracks how many bytes are left in the current ws fragment, according
|
||||||
* user code is interested in "complete packets" from the client.
|
* to the ws length given in the fragment header.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* 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_VISIBLE LWS_EXTERN size_t
|
||||||
lws_remaining_packet_payload(struct lws *wsi);
|
lws_remaining_packet_payload(struct lws *wsi);
|
||||||
|
|
|
@ -1749,7 +1749,7 @@ read:
|
||||||
eff_buf.token_len);
|
eff_buf.token_len);
|
||||||
switch (eff_buf.token_len) {
|
switch (eff_buf.token_len) {
|
||||||
case 0:
|
case 0:
|
||||||
lwsl_notice("%s: zero length read\n",
|
lwsl_info("%s: zero length read\n",
|
||||||
__func__);
|
__func__);
|
||||||
goto close_and_handled;
|
goto close_and_handled;
|
||||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|name|demonstrates|
|
|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-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
|
minimal-ws-client-tx|Connects to the minimal-ws-broker example as a publisher, demonstrating sending ws data
|
||||||
|
|
|
@ -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 <libwebsockets.h>\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()
|
164
minimal-examples/ws-client/minimal-ws-client-pmd-bulk/README.md
Normal file
164
minimal-examples/ws-client/minimal-ws-client-pmd-bulk/README.md
Normal file
|
@ -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.
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* lws-minimal-ws-client-pmd-bulk
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
|
||||||
|
*
|
||||||
|
* 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 <libwebsockets.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1,319 @@
|
||||||
|
/*
|
||||||
|
* ws protocol handler plugin for "lws-minimal-pmd-bulk"
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
|
||||||
|
*
|
||||||
|
* 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 <libwebsockets.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
|
@ -26,7 +26,30 @@ static struct lws_protocols protocols[] = {
|
||||||
{ NULL, NULL, 0, 0 } /* terminator */
|
{ 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 = {
|
static const struct lws_http_mount mount = {
|
||||||
/* .mount_next */ NULL, /* linked-list "next" */
|
/* .mount_next */ NULL, /* linked-list "next" */
|
||||||
|
@ -64,6 +87,16 @@ void sigint_handler(int sig)
|
||||||
interrupted = 1;
|
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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct lws_context_creation_info info;
|
struct lws_context_creation_info info;
|
||||||
|
@ -76,7 +109,14 @@ int main(int argc, char **argv)
|
||||||
info.port = 7681;
|
info.port = 7681;
|
||||||
info.mounts = &mount;
|
info.mounts = &mount;
|
||||||
info.protocols = protocols;
|
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;
|
info.pt_serv_buf_size = 32 * 1024;
|
||||||
|
|
||||||
lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
|
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);
|
/* | LLL_DEBUG */, NULL);
|
||||||
|
|
||||||
lwsl_user("LWS minimal ws server + permessage-deflate | visit http://localhost:7681\n");
|
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);
|
context = lws_create_context(&info);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
lwsl_err("lws init failed\n");
|
lwsl_err("lws init failed\n");
|
||||||
|
|
|
@ -61,9 +61,12 @@ try {
|
||||||
ws.onmessage =function got_packet(msg) {
|
ws.onmessage =function got_packet(msg) {
|
||||||
console.log("Received ws message len " + msg.data.length);
|
console.log("Received ws message len " + msg.data.length);
|
||||||
document.getElementById("r").value =
|
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").scrollTop =
|
||||||
document.getElementById("r").scrollHeight;
|
document.getElementById("r").scrollHeight;
|
||||||
|
|
||||||
|
/* echo it back */
|
||||||
|
ws.send(msg.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.onclose = function(){
|
ws.onclose = function(){
|
||||||
|
|
|
@ -56,64 +56,96 @@ static const char * const redundant_string =
|
||||||
/* one of these is created for each client connecting to us */
|
/* one of these is created for each client connecting to us */
|
||||||
|
|
||||||
struct per_session_data__minimal_pmd_bulk {
|
struct per_session_data__minimal_pmd_bulk {
|
||||||
int position; /* byte position we got up to sending the message */
|
int position_tx, position_rx;
|
||||||
uint64_t rng;
|
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
|
static int
|
||||||
callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
|
callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
|
||||||
void *user, void *in, size_t len)
|
void *user, void *in, size_t len)
|
||||||
{
|
{
|
||||||
struct per_session_data__minimal_pmd_bulk *pss =
|
struct per_session_data__minimal_pmd_bulk *pss =
|
||||||
(struct per_session_data__minimal_pmd_bulk *)user;
|
(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;
|
uint8_t buf[LWS_PRE + MESSAGE_CHUNK_SIZE], *start = &buf[LWS_PRE], *p;
|
||||||
int n, m, flags;
|
int n, m, flags, olen;
|
||||||
|
|
||||||
switch (reason) {
|
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:
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
pss->position = 0;
|
pss->rng_tx = 4;
|
||||||
pss->rng = 4;
|
pss->rng_rx = 4;
|
||||||
lws_callback_on_writable(wsi);
|
lws_callback_on_writable(wsi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||||
if (pss->position == MESSAGE_SIZE)
|
if (pss->position_tx == MESSAGE_SIZE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* fill up one chunk's worth of message content */
|
/* fill up one chunk's worth of message content */
|
||||||
|
|
||||||
p = start;
|
p = start;
|
||||||
n = MESSAGE_CHUNK_SIZE;
|
n = MESSAGE_CHUNK_SIZE;
|
||||||
if (n > MESSAGE_SIZE - pss->position)
|
if (n > MESSAGE_SIZE - pss->position_tx)
|
||||||
n = MESSAGE_SIZE - pss->position;
|
n = MESSAGE_SIZE - pss->position_tx;
|
||||||
|
|
||||||
flags = lws_write_ws_flags(LWS_WRITE_TEXT, !pss->position,
|
flags = lws_write_ws_flags(LWS_WRITE_BINARY, !pss->position_tx,
|
||||||
pss->position + n == MESSAGE_SIZE);
|
pss->position_tx + n == MESSAGE_SIZE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* select between producing compressible repeated text,
|
* select between producing compressible repeated text,
|
||||||
* or uncompressible PRNG output
|
* or uncompressible PRNG output
|
||||||
*/
|
*/
|
||||||
#if 0
|
|
||||||
while (n) {
|
if (*vhd->options & 1) {
|
||||||
m = pss->position % REPEAT_STRING_LEN;
|
while (n) {
|
||||||
s = REPEAT_STRING_LEN - m;
|
size_t s;
|
||||||
if (s > n)
|
|
||||||
s = n;
|
m = pss->position_tx % REPEAT_STRING_LEN;
|
||||||
memcpy(p, &redundant_string[m], s);
|
s = REPEAT_STRING_LEN - m;
|
||||||
pss->position += s;
|
if (s > (size_t)n)
|
||||||
p += s;
|
s = n;
|
||||||
n -= s;
|
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);
|
n = lws_ptr_diff(p, start);
|
||||||
m = lws_write(wsi, start, n, flags);
|
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);
|
lwsl_err("ERROR %d writing ws\n", n);
|
||||||
return -1;
|
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);
|
lws_callback_on_writable(wsi);
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue