1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

minimal-ws-server-pmd-bulk: add echo

This commit is contained in:
Andy Green 2018-04-05 07:56:09 +08:00
parent de4c1303f5
commit c8af76c07c
10 changed files with 851 additions and 45 deletions

View file

@ -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);

View file

@ -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:

View file

@ -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

View file

@ -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()

View 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.

View file

@ -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;
}

View file

@ -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

View file

@ -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");

View file

@ -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(){

View file

@ -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;
}