diff --git a/README.md b/README.md index aa476a84..2305fbb6 100644 --- a/README.md +++ b/README.md @@ -13,16 +13,16 @@ The Travis build of lws done on every commit now runs Tests|Count|Explanation ---|---|--- -Build / Linux / gcc|13|-Wall -Werror -Build / Mac / Clang|13|-Wall -Werror +Build / Linux / gcc|13|-Wall -Werror cmake config variants +Build / Mac / Clang|13|-Wall -Werror cmake config variants Build / Windows / MSVC|7|default -Selftests|29|minimal examples built and run against each other and remote server +Selftests|33|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 nearly 1,400 tests run on every commit take most of an hour to complete. +The over 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/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 197b28b5..ab940a3f 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -59,7 +59,7 @@ lws_client_connect_2(struct lws *wsi) /* we can only piggyback GET */ meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD); - if (meth && strcmp(meth, "GET")) + if (meth && strcmp(meth, "GET") && strcmp(meth, "POST")) goto create_new_conn; /* we only pipeline connections that said it was okay */ @@ -79,7 +79,8 @@ lws_client_connect_2(struct lws *wsi) struct lws *w = lws_container_of(d, struct lws, dll_active_client_conns); - lwsl_debug("%s: check %s %s %d %d\n", __func__, adsin, w->client_hostname_copy, wsi->c_port, w->c_port); + lwsl_debug("%s: check %s %s %d %d\n", __func__, adsin, + w->client_hostname_copy, wsi->c_port, w->c_port); if (w != wsi && w->client_hostname_copy && !strcmp(adsin, w->client_hostname_copy) && @@ -161,7 +162,7 @@ create_new_conn: * piggyback on our transaction queue */ - if (meth && !strcmp(meth, "GET") && + if (meth && (!strcmp(meth, "GET") || !strcmp(meth, "POST")) && lws_dll_is_null(&wsi->dll_client_transaction_queue) && lws_dll_is_null(&wsi->dll_active_client_conns)) { lws_vhost_lock(wsi->vhost); diff --git a/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c b/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c index 0d7aedfa..a5f3ed2b 100644 --- a/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c +++ b/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c @@ -17,8 +17,8 @@ #include #include -static int interrupted, bad = 1, status; -static struct lws *client_wsi; +static int interrupted, bad = 0, status, count_clients = 1, completed; +static struct lws *client_wsi[4]; struct pss { char boundary[32]; @@ -42,13 +42,20 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); - client_wsi = NULL; + bad = 1; + if (++completed == count_clients) + lws_cancel_service(lws_get_context(wsi)); break; case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - client_wsi = NULL; - bad = status != 200; - lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + for (n = 0; n < count_clients; n++) + if (client_wsi[n] == wsi) { + client_wsi[n] = NULL; + bad |= status != 200; + if (++completed == count_clients) + /* abort poll wait */ + lws_cancel_service(lws_get_context(wsi)); + } break; /* ...callbacks related to receiving the result... */ @@ -72,8 +79,18 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n"); - client_wsi = NULL; - bad = status != 200; + bad |= status != 200; + /* + * Do this to mark us as having processed the completion + * so close doesn't duplicate (with pipelining, completion != + * connection close + */ + for (n = 0; n < count_clients; n++) + if (client_wsi[n] == wsi) + client_wsi[n] = NULL; + if (++completed == count_clients) + /* abort poll wait */ + lws_cancel_service(lws_get_context(wsi)); break; /* ...callbacks related to generating the POST... */ @@ -232,6 +249,9 @@ int main(int argc, const char **argv) return 1; } + if (lws_cmdline_option(argc, argv, "-m")) + count_clients = LWS_ARRAY_SIZE(client_wsi); + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ i.context = context; i.ssl_connection = LCCSCF_USE_SSL; @@ -256,10 +276,14 @@ int main(int argc, const char **argv) i.alpn = "http/1.1"; i.protocol = protocols[0].name; - i.pwsi = &client_wsi; - lws_client_connect_via_info(&i); - while (n >= 0 && client_wsi && !interrupted) + for (n = 0; n < count_clients; n++) { + i.pwsi = &client_wsi[n]; + if (!lws_client_connect_via_info(&i)) + completed++; + } + + while (n >= 0 && completed != count_clients && !interrupted) n = lws_service(context, 1000); lws_context_destroy(context); diff --git a/minimal-examples/http-client/minimal-http-client-post/selftest.sh b/minimal-examples/http-client/minimal-http-client-post/selftest.sh index eeabeea1..2f887f2a 100755 --- a/minimal-examples/http-client/minimal-http-client-post/selftest.sh +++ b/minimal-examples/http-client/minimal-http-client-post/selftest.sh @@ -18,15 +18,21 @@ . $5/selftests-library.sh -COUNT_TESTS=4 +COUNT_TESTS=8 dotest $1 $2 warmcat dotest $1 $2 warmcat-h1 --h1 +dotest $1 $2 warmcat-m -m +dotest $1 $2 warmcat-m-h1 -m --h1 spawn "" $5 $1/libwebsockets-test-server -s dotest $1 $2 localhost -l spawn $SPID $5 $1/libwebsockets-test-server -s dotest $1 $2 localhost-h1 -l --h1 +spawn $SPID $5 $1/libwebsockets-test-server -s +dotest $1 $2 localhost-m -l -m +spawn $SPID $5 $1/libwebsockets-test-server -s +dotest $1 $2 localhost-m-h1 -l -m --h1 kill $SPID 2>/dev/null wait $SPID 2>/dev/null