diff --git a/.travis.yml b/.travis.yml
index 77bad91c..17262e70 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -30,7 +30,7 @@ install:
# - Rscript -e 'covr::coveralls()'
script:
- - if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "osx" ]; then mkdir build && cd build && cmake -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" $CMAKE_ARGS .. && cmake --build .; else if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "linux" ]; then mkdir build && cd build && cmake $CMAKE_ARGS .. && cmake --build . && if [ "$LWS_METHOD" = "lwsws" ] ; then sudo make install && ../minimal-examples/selftests.sh && ../test-apps/attack.sh && ../scripts/autobahn-test.sh ; fi ; fi ; fi
+ - if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "osx" ]; then mkdir build && cd build && cmake -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" $CMAKE_ARGS .. && cmake --build .; else if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "linux" ]; then mkdir build && cd build && if [ "$LWS_METHOD" = "lwsws" ] ; then cmake -DLWS_OPENSSL_LIBRARIES="/usr/local/lib/libssl.so;/usr/local/lib/libcrypto.so" -DLWS_OPENSSL_INCLUDE_DIRS="/usr/local/include/openssl" $CMAKE_ARGS .. && cmake --build . && sudo make install && ../minimal-examples/selftests.sh && ../scripts/h2spec.sh && ../test-apps/attack.sh && ../scripts/autobahn-test.sh ; else cmake $CMAKE_ARGS .. && cmake --build . ; fi ; fi ; fi
sudo: required
dist: trusty
addons:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index df320e43..f2ce419e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -952,8 +952,8 @@ endif()
if (LWS_WITH_JWS)
list(APPEND SOURCES
- lib/jws/jwk.c
- lib/jws/jws.c)
+ lib/misc/jws/jwk.c
+ lib/misc/jws/jws.c)
endif()
# Add helper files for Windows.
diff --git a/README.md b/README.md
index 23555496..aa476a84 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,9 @@ Selftests|29|minimal examples built and run against each other and remote server
attack.sh|225|Correctness, robustness and security tests for http parser
Autobahn Server|480|Testing lws ws client, including permessage-deflate
Autobahn Client|480|Testing lws ws server, including permaessage-deflate
+h2spec|146|Http/2 server compliance suite (in strict mode)
-The over 1,200 tests run on every commit take 40 minutes to complete.
+The nearly 1,400 tests run on every commit take most of an hour to complete.
If any problems are found, it breaks the travis build, generating an email.
Current master passes all the tests and these new CI arrangements will help
diff --git a/READMEs/release-checklist b/READMEs/release-checklist
index 9f0e6d88..5db79e9e 100644
--- a/READMEs/release-checklist
+++ b/READMEs/release-checklist
@@ -18,20 +18,6 @@ Release Checklist
d) valgrind test servers + client + browser
- e) attack.sh
-
- $ ./test-apps/attack.sh
-
- f) Autobahn
-
- $ wstest -m fuzzingserver &
- $ ./scripts/autobahn-test.sh
-
- Force update by browser using agent "libwebsockets"
- http://localhost:8080/test_browser.html
-
- rsync -av ./reports/* root@warmcat.com:/var/www/libwebsockets.org
-
2) soname bump?
a) We need one if we added / changed / removed apis
diff --git a/contrib/abi/README.md b/contrib/abi/README.md
index 1b09a1a0..e0d8769e 100644
--- a/contrib/abi/README.md
+++ b/contrib/abi/README.md
@@ -20,7 +20,13 @@ LGPL2 / GPL2 at your choice.
Installation
------------
-The author provides an easy way to install the various tools he provides:
+The abi monitoring stuff is now packaged in, eg, fedora, which is a lot
+easier than using the helper script.
+
+```
+# dnf install abi-tracker vtable-dumper
+
+Otherwise, the author provides an "easy way" to install the various tools he provides:
git clone https://github.com/lvc/installer
cd installer
diff --git a/lib/context.c b/lib/context.c
index 770edac2..37f10505 100644
--- a/lib/context.c
+++ b/lib/context.c
@@ -807,11 +807,15 @@ lws_create_vhost(struct lws_context *context,
lwsl_err("%s: lws_context_init_client_ssl failed\n", __func__);
goto bail1;
}
- if (lws_context_init_server(info, vh) < 0) {
+ lws_context_lock(context);
+ n = _lws_context_init_server(info, vh);
+ lws_context_unlock(context);
+ if (n < 0) {
lwsl_err("init server failed\n");
goto bail1;
}
+
while (1) {
if (!(*vh1)) {
*vh1 = vh;
@@ -1120,7 +1124,7 @@ lws_create_context(struct lws_context_creation_info *info)
if (info->max_http_header_pool)
context->max_http_header_pool = info->max_http_header_pool;
else
- context->max_http_header_pool = LWS_DEF_HEADER_POOL;
+ context->max_http_header_pool = context->max_fds;
/*
* Allocate the per-thread storage for scratchpad buffers,
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index f452e3d4..e8bb5d60 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -2785,7 +2785,8 @@ struct lws_context_creation_info {
* can be processed simultaneously (the corresponding memory is
* allocated and deallocated dynamically as needed). If the pool is
* fully busy new incoming connections must wait for accept until one
- * becomes free. */
+ * becomes free. 0 = allow as many ah as number of availble fds for
+ * the process */
unsigned int count_threads;
/**< CONTEXT: how many contexts to create in an array, 0 = 1 */
diff --git a/lib/jws/jwk.c b/lib/misc/jws/jwk.c
similarity index 100%
rename from lib/jws/jwk.c
rename to lib/misc/jws/jwk.c
diff --git a/lib/jws/jws.c b/lib/misc/jws/jws.c
similarity index 100%
rename from lib/jws/jws.c
rename to lib/misc/jws/jws.c
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 54700b7c..5a337d13 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -1759,7 +1759,7 @@ LWS_EXTERN int
lws_change_pollfd(struct lws *wsi, int _and, int _or);
#ifndef LWS_NO_SERVER
- int lws_context_init_server(struct lws_context_creation_info *info,
+ int _lws_context_init_server(struct lws_context_creation_info *info,
struct lws_vhost *vhost);
LWS_EXTERN struct lws_vhost *
lws_select_vhost(struct lws_context *context, int port, const char *servername);
@@ -1769,7 +1769,7 @@ lws_change_pollfd(struct lws *wsi, int _and, int _or);
lws_server_get_canonical_hostname(struct lws_context *context,
struct lws_context_creation_info *info);
#else
- #define lws_context_init_server(_a, _b) (0)
+ #define _lws_context_init_server(_a, _b) (0)
#define lws_parse_ws(_a, _b, _c) (0)
#define lws_server_get_canonical_hostname(_a, _b)
#endif
diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c
index 00485faa..c80b61d6 100644
--- a/lib/roles/h1/ops-h1.c
+++ b/lib/roles/h1/ops-h1.c
@@ -228,7 +228,8 @@ ws_mode:
case LRS_DEAD_SOCKET:
lwsl_err("%s: Unhandled state LRS_DEAD_SOCKET\n", __func__);
- assert(0);
+ goto bail;
+ // assert(0);
/* fallthru */
default:
diff --git a/lib/roles/h2/hpack.c b/lib/roles/h2/hpack.c
index f5451382..2147c653 100644
--- a/lib/roles/h2/hpack.c
+++ b/lib/roles/h2/hpack.c
@@ -393,7 +393,7 @@ lws_token_from_index(struct lws *wsi, int index, const char **arg, int *len,
if (index < (int)ARRAY_SIZE(static_token) ||
index >= (int)ARRAY_SIZE(static_token) + dyn->used_entries) {
- lwsl_err(" %s: adjusted index %d >= %d\n", __func__, index,
+ lwsl_info(" %s: adjusted index %d >= %d\n", __func__, index,
dyn->used_entries);
lws_h2_goaway(wsi, H2_ERR_COMPRESSION_ERROR,
"index out of range");
@@ -597,14 +597,19 @@ lws_hpack_dynamic_size(struct lws *wsi, int size)
nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]);
if (size > (int)nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]) {
- lwsl_notice("rejecting hpack dyn size %u\n", size);
-//#if defined(LWS_WITH_ESP32)
+ lwsl_info("rejecting hpack dyn size %u vs %u\n", size,
+ nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE]);
+
+ // this seems necessary to work with some browsers
+
+ if (nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE] == 65536 &&
+ size == 65537) { /* h2spec */
+ lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR,
+ "Asked for header table bigger than we told");
+ goto bail;
+ }
+
size = nwsi->vhost->h2.set.s[H2SET_HEADER_TABLE_SIZE];
-//#else
-// lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR,
-// "Asked for header table bigger than we told");
-// goto bail;
-//#endif
}
dyn->virtual_payload_max = size;
@@ -754,7 +759,7 @@ lws_hpack_handle_pseudo_rules(struct lws *nwsi, struct lws *wsi, int m)
if (wsi->seen_nonpseudoheader &&
(lws_header_implies_psuedoheader_map[m >> 3] & (1 << (m & 7)))) {
- lwsl_notice("lws tok %d seems to be a pseudoheader\n", m);
+ lwsl_info("lws tok %d seems to be a pseudoheader\n", m);
/*
* it's not legal to see a
@@ -1157,7 +1162,7 @@ swallow:
if (h2n->huff && (h2n->huff_pad > 7 ||
(h2n->zero_huff_padding && h2n->huff_pad))) {
- lwsl_notice("zero_huff_padding: %d huff_pad: %d\n",
+ lwsl_info("zero_huff_padding: %d huff_pad: %d\n",
h2n->zero_huff_padding, h2n->huff_pad);
lws_h2_goaway(nwsi, H2_ERR_COMPRESSION_ERROR,
"Huffman padding excessive or wrong");
diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c
index 41bc7d23..69e248b8 100644
--- a/lib/roles/h2/http2.c
+++ b/lib/roles/h2/http2.c
@@ -829,7 +829,7 @@ lws_h2_parse_frame_header(struct lws *wsi)
* peer sent us something bigger than we told
* it we would allow
*/
- lwsl_notice("received oversize frame %d\n", h2n->length);
+ lwsl_info("received oversize frame %d\n", h2n->length);
lws_h2_goaway(wsi, H2_ERR_FRAME_SIZE_ERROR,
"Peer ignored our frame size setting");
return 1;
@@ -842,7 +842,7 @@ lws_h2_parse_frame_header(struct lws *wsi)
else {
/* if it's data, either way no swsi means CLOSED state */
if (h2n->type == LWS_H2_FRAME_TYPE_DATA) {
- if (h2n->sid <= h2n->highest_sid_opened) {
+ if (h2n->sid <= h2n->highest_sid_opened && wsi->client_h2_alpn) {
lwsl_notice("ignoring straggling data\n");
h2n->type = LWS_H2_FRAME_TYPE_COUNT; /* ie, IGNORE */
} else {
@@ -899,7 +899,7 @@ lws_h2_parse_frame_header(struct lws *wsi)
case LWS_H2_FRAME_TYPE_DATA:
lwsl_info("seen incoming LWS_H2_FRAME_TYPE_DATA start\n");
if (!h2n->sid) {
- lwsl_notice("DATA: 0 sid\n");
+ lwsl_info("DATA: 0 sid\n");
lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "DATA 0 sid");
break;
}
@@ -910,6 +910,8 @@ lws_h2_parse_frame_header(struct lws *wsi)
break;
}
+ lwsl_info("DATA rx on state %d\n", h2n->swsi->h2.h2_state);
+
if (
h2n->swsi->h2.h2_state == LWS_H2_STATE_HALF_CLOSED_REMOTE ||
h2n->swsi->h2.h2_state == LWS_H2_STATE_CLOSED) {
@@ -975,6 +977,13 @@ lws_h2_parse_frame_header(struct lws *wsi)
if (h2n->type == LWS_H2_FRAME_TYPE_COUNT)
return 0;
+
+ if (wsi->upgraded_to_http2) {
+ pps = lws_h2_new_pps(LWS_H2_PPS_ACK_SETTINGS);
+ if (!pps)
+ return 1;
+ lws_pps_schedule(wsi, pps);
+ }
break;
}
/* came to us with ACK set... not allowed to have payload */
@@ -1024,6 +1033,12 @@ lws_h2_parse_frame_header(struct lws *wsi)
return 1;
}
+ if (h2n->swsi && !h2n->swsi->h2.END_STREAM && h2n->swsi->h2.END_HEADERS &&
+ !(h2n->flags & LWS_H2_FLAG_END_STREAM)) {
+ lws_h2_goaway(wsi, H2_ERR_PROTOCOL_ERROR, "extra HEADERS together");
+ return 1;
+ }
+
#if !defined(LWS_NO_CLIENT)
if (wsi->client_h2_alpn) {
if (h2n->sid) {
@@ -1108,7 +1123,7 @@ lws_h2_parse_frame_header(struct lws *wsi)
h2n->cont_exp = !(h2n->flags & LWS_H2_FLAG_END_HEADERS);
h2n->cont_exp_sid = h2n->sid;
h2n->cont_exp_headers = 1;
- lws_header_table_reset(h2n->swsi, 0);
+ // lws_header_table_reset(h2n->swsi, 0);
update_end_headers:
/* no END_HEADERS means CONTINUATION must come */
@@ -1391,6 +1406,7 @@ lws_h2_parse_end_of_frame(struct lws *wsi)
break;
}
+
if (lws_hdr_extant(h2n->swsi, WSI_TOKEN_TE)) {
n = lws_hdr_total_length(h2n->swsi, WSI_TOKEN_TE);
@@ -1726,7 +1742,7 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
break;
if (lws_buflist_next_segment_len(&h2n->swsi->buflist, NULL))
- lwsl_err("%s: substream has pending !!!\n", __func__);
+ lwsl_info("%s: substream has pending\n", __func__);
if (lwsi_role_http(h2n->swsi) &&
lwsi_state(h2n->swsi) == LRS_ESTABLISHED) {
@@ -1777,7 +1793,7 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
} else {
if (lwsi_state(h2n->swsi) == LRS_DEFERRING_ACTION) {
- lwsl_notice("appending because we are in LRS_DEFERRING_ACTION\n");
+ // lwsl_notice("appending because we are in LRS_DEFERRING_ACTION\n");
m = lws_buflist_append_segment(
&h2n->swsi->buflist,
in - 1, n);
diff --git a/lib/roles/h2/ops-h2.c b/lib/roles/h2/ops-h2.c
index 51ac1428..01461e1b 100644
--- a/lib/roles/h2/ops-h2.c
+++ b/lib/roles/h2/ops-h2.c
@@ -297,7 +297,7 @@ drain:
pending = lws_ssl_pending(wsi);
if (pending) {
- lwsl_err("going around\n");
+ // lwsl_info("going around\n");
goto read;
}
@@ -684,7 +684,7 @@ lws_h2_bind_for_post_before_action(struct lws *wsi)
const char *p;
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD);
- if (!strcmp(p, "POST")) {
+ if (p && !strcmp(p, "POST")) {
const struct lws_protocols *pp;
const char *name;
const struct lws_http_mount *hit =
@@ -704,7 +704,7 @@ lws_h2_bind_for_post_before_action(struct lws *wsi)
pp = lws_vhost_name_to_protocol(wsi->vhost, name);
if (!pp) {
- lwsl_err("Unable to find plugin '%s'\n", name);
+ lwsl_info("Unable to find protocol '%s'\n", name);
return 1;
}
@@ -712,7 +712,7 @@ lws_h2_bind_for_post_before_action(struct lws *wsi)
return 1;
}
- lwsl_notice("%s: setting LRS_BODY from 0x%x (%s)\n", __func__,
+ lwsl_info("%s: setting LRS_BODY from 0x%x (%s)\n", __func__,
wsi->wsistate, wsi->protocol->name);
lwsi_set_state(wsi, LRS_BODY);
}
diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c
index 666f061d..4846db9a 100644
--- a/lib/roles/http/server/server.c
+++ b/lib/roles/http/server/server.c
@@ -32,10 +32,12 @@ const char * const method_names[] = {
* return 0: all done
* 1: nonfatal error
* <0: fatal error
+ *
+ * REQUIRES CONTEXT LOCK HELD
*/
int
-lws_context_init_server(struct lws_context_creation_info *info,
+_lws_context_init_server(struct lws_context_creation_info *info,
struct lws_vhost *vhost)
{
int n, opt = 1, limit = 1;
@@ -82,7 +84,7 @@ lws_context_init_server(struct lws_context_creation_info *info,
is = lws_socket_bind(vhost, LWS_SOCK_INVALID, vhost->listen_port, vhost->iface);
lwsl_debug("initial if check says %d\n", is);
deal:
- lws_context_lock(vhost->context);
+
lws_start_foreach_llp(struct lws_vhost **, pv,
vhost->context->no_listener_vhost_list) {
if (is >= LWS_ITOSA_USABLE && *pv == vhost) {
@@ -108,7 +110,6 @@ deal:
}
done_list:
- lws_context_unlock(vhost->context);
switch (is) {
default:
diff --git a/lib/roles/ws/client-parser-ws.c b/lib/roles/ws/client-parser-ws.c
index e15025c8..0f63c344 100644
--- a/lib/roles/ws/client-parser-ws.c
+++ b/lib/roles/ws/client-parser-ws.c
@@ -398,7 +398,7 @@ spill:
wsi->ws->rx_ubuf_head);
wsi->ws->close_in_ping_buffer_len = wsi->ws->rx_ubuf_head;
- lwsl_notice("%s: scheduling return close as ack\n", __func__);
+ lwsl_info("%s: scheduling return close as ack\n", __func__);
__lws_change_pollfd(wsi, LWS_POLLIN, 0);
lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 3);
wsi->waiting_to_send_close_frame = 1;
diff --git a/lib/service.c b/lib/service.c
index 2ead7ffd..226bf96b 100644
--- a/lib/service.c
+++ b/lib/service.c
@@ -742,7 +742,7 @@ lws_service_periodic_checks(struct lws_context *context,
context->no_listener_vhost_list) {
struct lws_vhost *v = *pv;
lwsl_debug("deferred iface: checking if on vh %s\n", (*pv)->name);
- if (lws_context_init_server(NULL, *pv) == 0) {
+ if (_lws_context_init_server(NULL, *pv) == 0) {
/* became happy */
lwsl_notice("vh %s: became connected\n", v->name);
*pv = v->no_listener_vhost_list;
diff --git a/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.cert b/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.cert
new file mode 100644
index 00000000..6f372db4
--- /dev/null
+++ b/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.cert
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+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
+e2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE=
+-----END CERTIFICATE-----
diff --git a/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.key b/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.key
new file mode 100644
index 00000000..148f8598
--- /dev/null
+++ b/minimal-examples/http-server/minimal-http-server-smp/localhost-100y.key
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+fBrpEY1IATtPq1taBZZogRqI3rOkkPk=
+-----END PRIVATE KEY-----
diff --git a/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c b/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c
index fcd008b5..6df28f9c 100644
--- a/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c
+++ b/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c
@@ -89,8 +89,16 @@ int main(int argc, const char **argv)
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
info.port = 7681;
info.mounts = &mount;
- // info.max_http_header_pool = 10;
- info.count_threads = COUNT_THREADS;
+ if ((p = lws_cmdline_option(argc, argv, "-t")))
+ info.count_threads = atoi(p);
+ else
+ info.count_threads = COUNT_THREADS;
+
+ if (lws_cmdline_option(argc, argv, "-s")) {
+ info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
+ info.ssl_cert_filepath = "localhost-100y.cert";
+ info.ssl_private_key_filepath = "localhost-100y.key";
+ }
context = lws_create_context(&info);
if (!context) {
diff --git a/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c b/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c
index 7af4db8c..a209bdee 100644
--- a/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c
+++ b/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c
@@ -72,7 +72,6 @@ int main(int argc, const char **argv)
info.port = 7681;
info.mounts = &mount;
info.error_document_404 = "/404.html";
- info.max_http_header_pool = 32;
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
info.ssl_cert_filepath = "localhost-100y.cert";
info.ssl_private_key_filepath = "localhost-100y.key";
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
index fd49dc62..5bca4381 100644
--- 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
@@ -103,7 +103,7 @@ int main(int argc, const char **argv)
info.extensions = extensions;
info.pt_serv_buf_size = 32 * 1024;
- if (!lws_cmdline_option(argc, argv, "-c"))
+ if (lws_cmdline_option(argc, argv, "-c"))
options |= 1;
context = lws_create_context(&info);
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 daa6fc7e..f74309c3 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
@@ -107,7 +107,7 @@ int main(int argc, const char **argv)
lws_set_log_level(logs, 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]);
+ lwsl_user(" %s [-n (no exts)] [-c (compressible)] [-b (blob)]\n", argv[0]);
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
info.port = 7681;
@@ -118,8 +118,11 @@ int main(int argc, const char **argv)
if (!lws_cmdline_option(argc, argv, "-n"))
info.extensions = extensions;
- if (!lws_cmdline_option(argc, argv, "-c"))
- options |= 1;
+ if (lws_cmdline_option(argc, argv, "-c"))
+ options |= 1; /* send compressible text */
+
+ if (lws_cmdline_option(argc, argv, "-b"))
+ options |= 2; /* send in one giant blob */
info.pt_serv_buf_size = 32 * 1024;
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 f6a22f8d..c123699f 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
@@ -6,6 +6,7 @@
LWS bulk transfer example.
A large ws message is sent to all browsers open on this page.
+ The browser js echoes the large ws message back to the server.
Ws closed
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 886cb880..58fe1604 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
@@ -62,7 +62,11 @@ struct per_session_data__minimal_pmd_bulk {
struct vhd_minimal_pmd_bulk {
int *interrupted;
- int *options; /* b0 = 1: test compressible text, = 0: test uncompressible binary */
+ /*
+ * b0 = 1: test compressible text, = 0: test uncompressible binary
+ * b1 = 1: send as a single blob, = 0: send as fragments
+ */
+ int *options;
};
static uint64_t rng(uint64_t *r)
@@ -83,8 +87,8 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
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, olen;
+ uint8_t buf[LWS_PRE + MESSAGE_SIZE], *start = &buf[LWS_PRE], *p;
+ int n, m, flags, olen, amount;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT:
@@ -113,10 +117,16 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
if (pss->position_tx == MESSAGE_SIZE)
break;
+ amount = MESSAGE_CHUNK_SIZE;
+ if ((*vhd->options) & 2) {
+ amount = MESSAGE_SIZE;
+ lwsl_user("(writing as one blob of %d)\n", amount);
+ }
+
/* fill up one chunk's worth of message content */
p = start;
- n = MESSAGE_CHUNK_SIZE;
+ n = amount;
if (n > MESSAGE_SIZE - pss->position_tx)
n = MESSAGE_SIZE - pss->position_tx;
@@ -149,6 +159,7 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
n = lws_ptr_diff(p, start);
m = lws_write(wsi, start, n, flags);
+ lwsl_user("LWS_CALLBACK_SERVER_WRITEABLE: wrote %d\n", n);
if (m < n) {
lwsl_err("ERROR %d writing ws\n", n);
return -1;
diff --git a/scripts/h2spec.sh b/scripts/h2spec.sh
new file mode 100755
index 00000000..518cdc66
--- /dev/null
+++ b/scripts/h2spec.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# run from the build subdir
+
+if [ ! -e h2spec ] ; then
+ wget https://github.com/summerwind/h2spec/releases/download/v2.1.0/h2spec_linux_amd64.tar.gz &&\
+ tar xf h2spec_linux_amd64.tar.gz
+ if [ ! -e h2spec ] ; then
+ echo "Couldn't get h2spec"
+ exit 1
+ fi
+fi
+
+cd ../minimal-examples/http-server/minimal-http-server-tls
+../../../build/bin/lws-minimal-http-server-tls&
+
+sleep 1s
+
+P=$!
+../../../build/h2spec -h 127.0.0.1 -p 7681 -t -k -S > /tmp/hlog
+kill $P 2>/dev/null
+wait $P 2>/dev/null
+
+if [ ! -z "`cat /tmp/hlog | grep "Failures:"`" ] ; then
+ cat /tmp/hlog | sed '/Failures:/,$!d'
+
+ exit 1
+fi
+
+cat /tmp/hlog | sed '/Finished\ in/,$!d'
+
+
+exit 0
+
diff --git a/scripts/travis_install.sh b/scripts/travis_install.sh
index 90f38802..299041cb 100755
--- a/scripts/travis_install.sh
+++ b/scripts/travis_install.sh
@@ -14,6 +14,11 @@ then
sudo pip install Twisted==16.0.0
sudo pip install pyopenssl>=0.14
sudo pip install autobahntestsuite
+ wget https://libwebsockets.org/openssl-1.1.0-trusty.tar.bz2 -O/tmp/openssl.tar.bz2
+ cd /
+ sudo tar xf /tmp/openssl.tar.bz2
+ sudo ldconfig
+ sudo update-ca-certificates
fi
if [ "$LWS_METHOD" == "libev" ];