From 5b74d7108b5cfcc3a6ee3dcad521e0f0c3a18d0c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 14 Nov 2017 11:25:54 +0800 Subject: [PATCH] gcov: add in cmake and adapt defaults 1) Introduce LWS_WITH_GCOV to build with gcc / clang coverage instrumentation. $ cd build $ make clean && rm -f `find . -name "*.gcno" -o -name "*.gcda"` && make -j16 && sudo make install && sudo /usr/local/bin/libwebsockets-test-server -s ... $ gcov `find . -name *.c.gcno | grep -v test-apps` -b | sed "/\.h.\$/,/^$/d" The above are available in two helper scripts - scripts/build-gcov.sh - scripts/gcov.sh 2) CMake defaults changed: - LWS_WITH_ZIP_FOPS: OFF - LWS_WITH_RANGES: OFF - LWS_WITHOUT_EXTENSIONS: ON - LWS_WITH_ZLIB: OFF New CMake controls that default-OFF: - LWS_WITH_GENHASH - LWS_WITH_GENRSA these are implied by LWS_WITH_JWS (which is implied by LWS_WITH_ACME) 3) rename ./lib/tls/XXX/server.c and client.c to XXX-server.c / XXX-client.c. This is because gcov dumps its results using the .c filename part only, the copies overwrite each other if there are different .c files in the tree with the same filename part. 4) Add onetime test-client mode and test to ./test-apps/attack.sh 5) Add gcov howto in READMEs/README.build.md using attack.sh --- .travis.yml | 5 ++ CMakeLists.txt | 64 +++++++++++++------ READMEs/README.build.md | 19 ++++-- cmake/lws_config.h.in | 1 + component.mk | 3 + .../mbedtls/{client.c => mbedtls-client.c} | 0 .../mbedtls/{server.c => mbedtls-server.c} | 3 +- lib/tls/mbedtls/ssl.c | 3 +- .../openssl/{client.c => openssl-client.c} | 0 .../openssl/{server.c => openssl-server.c} | 2 + lib/tls/openssl/ssl.c | 3 +- lib/tls/tls.c | 29 --------- scripts/build-gcov.sh | 6 ++ scripts/gcov.sh | 3 + test-apps/attack.sh | 12 ++++ test-apps/test-client.c | 10 ++- 16 files changed, 106 insertions(+), 57 deletions(-) rename lib/tls/mbedtls/{client.c => mbedtls-client.c} (100%) rename lib/tls/mbedtls/{server.c => mbedtls-server.c} (99%) rename lib/tls/openssl/{client.c => openssl-client.c} (100%) rename lib/tls/openssl/{server.c => openssl-server.c} (99%) create mode 100755 scripts/build-gcov.sh create mode 100755 scripts/gcov.sh diff --git a/.travis.yml b/.travis.yml index b331ca15..f34ea2a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,11 @@ os: language: generic install: - ./scripts/travis_install.sh +# - ./travis-tool.sh github_package jimhester/covr + +#after_success: +# - 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 .; fi ; fi sudo: required diff --git a/CMakeLists.txt b/CMakeLists.txt index 433c315a..b84c9a7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,12 +20,12 @@ option(LWS_IPV6 "Compile with support for ipv6" OFF) option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF) option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF) option(LWS_WITH_HTTP_PROXY "Support for rewriting HTTP proxying (requires libhubbub)" OFF) -option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" ON) +option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" OFF) option(LWS_WITH_SOCKS5 "Allow use of SOCKS5 proxy on client connections" OFF) option(LWS_WITH_GENERIC_SESSIONS "With the Generic Sessions plugin" OFF) option(LWS_WITH_PEER_LIMITS "Track peers and restrict resources a single peer can allocate" OFF) option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF) -option(LWS_WITH_RANGES "Support http ranges (RFC7233)" ON) +option(LWS_WITH_RANGES "Support http ranges (RFC7233)" OFF) option(LWS_WITH_SERVER_STATUS "Support json + jscript server monitoring" OFF) option(LWS_WITH_ACME "Enable support for ACME automatic cert acquisition + maintenance (letsencrypt etc)" OFF) # @@ -71,8 +71,8 @@ option(LWS_WITHOUT_TEST_FRAGGLE "Don't build the ping test application" OFF) # # Extensions (permessage-deflate) # -option(LWS_WITHOUT_EXTENSIONS "Don't compile with extensions" OFF) -option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" ON) +option(LWS_WITHOUT_EXTENSIONS "Don't compile with extensions" ON) +option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" OFF) option(LWS_WITH_BUNDLED_ZLIB "Use bundled zlib version (Windows only)" ${LWS_WITH_BUNDLED_ZLIB_DEFAULT}) # # Helpers + misc @@ -91,7 +91,10 @@ option(LWS_WITH_NO_LOGS "Disable all logging from being compiled in" OFF) option(LWS_AVOID_SIGPIPE_IGN "Android 7+ reportedly needs this" OFF) option(LWS_WITH_STATS "Keep statistics of lws internal operations" OFF) option(LWS_WITH_JWS "JSON Web Signature (RFC7515) API" OFF) +option(LWS_WITH_GENHASH "Enable support for Generic Hash (SHA1 + SHA2 with api independent of TLS backend)" OFF) +option(LWS_WITH_GENRSA "Enable support for Generic RSA (RSA with api independent of TLS backend)" OFF) option(LWS_WITH_SELFTESTS "Selftests run at context creation" OFF) +option(LWS_WITH_GCOV "Build with gcc gcov coverage instrumentation" OFF) # # End of user settings # @@ -176,6 +179,8 @@ endif() if (LWS_WITH_JWS) set(LWS_WITH_LEJP 1) + set(LWS_WITH_GENHASH 1) + set(LWS_WITH_GENRSA 1) endif() if (LWS_WITH_PLUGINS AND NOT LWS_WITH_LIBUV) @@ -188,6 +193,12 @@ message(STATUS "LWS_WITH_SMTP --> Enabling LWS_WITH_LIBUV") set(LWS_WITH_LIBUV 1) endif() +if (LWS_WITH_PLUGINS OR LWS_WITH_CGI) + # sshd plugin + set(LWS_WITH_GENHASH 1) + set(LWS_WITH_GENRSA 1) +endif() + if (LWS_WITH_GENERIC_SESSIONS) set(LWS_WITH_SQLITE3 1) set(LWS_WITH_SMTP 1) @@ -271,10 +282,8 @@ if (NOT (LWS_WITH_STATIC OR LWS_WITH_SHARED)) message(FATAL_ERROR "Makes no sense to compile with neither static nor shared libraries.") endif() -if (NOT LWS_WITHOUT_EXTENSIONS) - if (NOT LWS_WITH_ZLIB) - message(FATAL_ERROR "zlib is required for extensions.") - endif() +if (NOT LWS_WITHOUT_EXTENSIONS OR LWS_WITH_ZIP_FOPS) + set(LWS_WITH_ZLIB 1) endif() set(LWS_ZLIB_LIBRARIES CACHE PATH "Path to the zlib library") @@ -728,15 +737,31 @@ if (LWS_WITH_SSL) if (LWS_WITH_MBEDTLS) list(APPEND SOURCES lib/tls/mbedtls/ssl.c - lib/tls/mbedtls/lws-genhash.c - lib/tls/mbedtls/lws-genrsa.c ) + if (LWS_WITH_GENHASH) + list(APPEND SOURCES + lib/tls/mbedtls/lws-genhash.c + ) + endif() + if (LWS_WITH_GENRSA) + list(APPEND SOURCES + lib/tls/mbedtls/lws-genrsa.c + ) + endif() else() list(APPEND SOURCES lib/tls/openssl/ssl.c - lib/tls/openssl/lws-genhash.c - lib/tls/openssl/lws-genrsa.c ) + if (LWS_WITH_GENHASH) + list(APPEND SOURCES + lib/tls/openssl/lws-genhash.c + ) + endif() + if (LWS_WITH_GENRSA) + list(APPEND SOURCES + lib/tls/openssl/lws-genrsa.c + ) + endif() endif() if (NOT LWS_WITHOUT_SERVER) @@ -744,10 +769,10 @@ if (LWS_WITH_SSL) lib/server/ssl-server.c) if (LWS_WITH_MBEDTLS) list(APPEND SOURCES - lib/tls/mbedtls/server.c) + lib/tls/mbedtls/mbedtls-server.c) else() list(APPEND SOURCES - lib/tls/openssl/server.c) + lib/tls/openssl/openssl-server.c) endif() endif() if (NOT LWS_WITHOUT_CLIENT) @@ -755,10 +780,10 @@ if (LWS_WITH_SSL) lib/client/ssl-client.c) if (LWS_WITH_MBEDTLS) list(APPEND SOURCES - lib/tls/mbedtls/client.c) + lib/tls/mbedtls/mbedtls-client.c) else() list(APPEND SOURCES - lib/tls/openssl/client.c) + lib/tls/openssl/openssl-client.c) endif() endif() @@ -908,10 +933,13 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_C_COMPILER_ID if (LWS_HAVE_VISIBILITY) set(VISIBILITY_FLAG -fvisibility=hidden) endif() + if (LWS_WITH_GCOV) + set (GCOV_FLAGS "-fprofile-arcs -ftest-coverage -O0") + endif() if ((UNIX OR LWS_WITH_ESP8266) AND NOT LWS_WITH_ESP32) - set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${CMAKE_C_FLAGS}" ) + set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) else() - set(CMAKE_C_FLAGS "-Wall ${VISIBILITY_FLAG} ${CMAKE_C_FLAGS}" ) + set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) endif() endif () diff --git a/READMEs/README.build.md b/READMEs/README.build.md index b92c557f..f97317aa 100644 --- a/READMEs/README.build.md +++ b/READMEs/README.build.md @@ -431,14 +431,25 @@ Testing with h2spec (https://github.com/summerwind/h2spec) $ h2spec -h 127.0.0.1 -p 7681 -t -k -v -o 1 ``` -At the time of writing, http/2 support is not fully complete; however all the -h2spec tests pass. - ``` -145 tests, 144 passed, 1 skipped, 0 failed +145 tests, 145 passed, 0 skipped, 0 failed ``` +@section coverage Automated Coverage Testing + +./test-apps/attack.sh contains scripted tests that are the basis +of the automated test coverage assessment available for gcc and clang. + +To reproduce + + $ cd build + $ cmake .. -DLWS_WITH_GCOV=1 -DCMAKE_BUILD_TYPE=DEBUG + $ ../scripts/build-gcov.sh + $ ../test-apps/attack.sh + $ ../scripts/gcov.sh +... +Lines executed:51.24% of 8279 @section windowsprebuilt Using Windows binary builds on Appveyor diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index e47b5674..d6ddd3c5 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -148,6 +148,7 @@ #cmakedefine LWS_HAVE__STAT32I64 #cmakedefine LWS_WITH_JWS +#cmakedefine LWS_WITH_ACME #cmakedefine LWS_WITH_SELFTESTS /* OpenSSL various APIs */ diff --git a/component.mk b/component.mk index 7cc5d7b1..9afdeb6f 100644 --- a/component.mk +++ b/component.mk @@ -28,7 +28,10 @@ build: -DLWS_MBEDTLS_INCLUDE_DIRS="${IDF_PATH}/components/openssl/include;${IDF_PATH}/components/mbedtls/include;${IDF_PATH}/components/mbedtls/port/include" \ -DLWS_WITH_STATS=0 \ -DLWS_WITH_HTTP2=1 \ + -DLWS_WITH_RANGES=1 \ -DLWS_WITH_ACME=1 \ + -DLWS_WITH_ZLIB=1 \ + -DLWS_WITH_ZIP_FOPS=1 \ -DZLIB_LIBRARY=$(BUILD_DIR_BASE)/zlib/libzlib.a \ -DZLIB_INCLUDE_DIR=$(COMPONENT_PATH)/../zlib \ -DLWS_WITH_ESP32=1 \ diff --git a/lib/tls/mbedtls/client.c b/lib/tls/mbedtls/mbedtls-client.c similarity index 100% rename from lib/tls/mbedtls/client.c rename to lib/tls/mbedtls/mbedtls-client.c diff --git a/lib/tls/mbedtls/server.c b/lib/tls/mbedtls/mbedtls-server.c similarity index 99% rename from lib/tls/mbedtls/server.c rename to lib/tls/mbedtls/mbedtls-server.c index 88970890..fb74d71c 100644 --- a/lib/tls/mbedtls/server.c +++ b/lib/tls/mbedtls/mbedtls-server.c @@ -328,6 +328,7 @@ lws_tls_server_accept(struct lws *wsi) return LWS_SSL_CAPABLE_ERROR; } +#if defined(LWS_WITH_ACME) /* * mbedtls doesn't support SAN for cert creation. So we use a known-good * tls-sni-01 cert from OpenSSL that worked on Let's Encrypt, and just replace @@ -620,4 +621,4 @@ fail: return -1; } #endif - +#endif diff --git a/lib/tls/mbedtls/ssl.c b/lib/tls/mbedtls/ssl.c index 391b01aa..f46eabaa 100644 --- a/lib/tls/mbedtls/ssl.c +++ b/lib/tls/mbedtls/ssl.c @@ -278,8 +278,9 @@ lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost) if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx) SSL_CTX_free(vhost->ssl_client_ctx); - +#if defined(LWS_WITH_ACME) lws_tls_acme_sni_cert_destroy(vhost); +#endif } void diff --git a/lib/tls/openssl/client.c b/lib/tls/openssl/openssl-client.c similarity index 100% rename from lib/tls/openssl/client.c rename to lib/tls/openssl/openssl-client.c diff --git a/lib/tls/openssl/server.c b/lib/tls/openssl/openssl-server.c similarity index 99% rename from lib/tls/openssl/server.c rename to lib/tls/openssl/openssl-server.c index f4a62b47..a3cf45ac 100644 --- a/lib/tls/openssl/server.c +++ b/lib/tls/openssl/openssl-server.c @@ -493,6 +493,7 @@ lws_tls_server_accept(struct lws *wsi) return LWS_SSL_CAPABLE_ERROR; } +#if defined(LWS_WITH_ACME) static int lws_tls_openssl_rsa_new_key(RSA **rsa, int bits) { @@ -818,3 +819,4 @@ bail0: return ret; } +#endif diff --git a/lib/tls/openssl/ssl.c b/lib/tls/openssl/ssl.c index 7dbd3efa..249a1db2 100644 --- a/lib/tls/openssl/ssl.c +++ b/lib/tls/openssl/ssl.c @@ -416,8 +416,9 @@ lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost) if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx) SSL_CTX_free(vhost->ssl_client_ctx); - +#if defined(LWS_WITH_ACME) lws_tls_acme_sni_cert_destroy(vhost); +#endif } void diff --git a/lib/tls/tls.c b/lib/tls/tls.c index fcc829d0..2572434b 100644 --- a/lib/tls/tls.c +++ b/lib/tls/tls.c @@ -21,35 +21,6 @@ #include "private-libwebsockets.h" -int -lws_alloc_vfs_file(struct lws_context *context, const char *filename, - uint8_t **buf, lws_filepos_t *amount) -{ - lws_filepos_t len; - lws_fop_flags_t flags = LWS_O_RDONLY; - lws_fop_fd_t fops_fd = lws_vfs_file_open( - lws_get_fops(context), filename, &flags); - int ret = 1; - - if (!fops_fd) - return 1; - - len = lws_vfs_get_length(fops_fd); - - *buf = lws_malloc((size_t)len, "lws_alloc_vfs_file"); - if (!*buf) - goto bail; - - if (lws_vfs_file_read(fops_fd, amount, *buf, len)) - goto bail; - - ret = 0; -bail: - lws_vfs_file_close(&fops_fd); - - return ret; -} - int lws_ssl_anybody_has_buffered_read_tsi(struct lws_context *context, int tsi) { diff --git a/scripts/build-gcov.sh b/scripts/build-gcov.sh new file mode 100755 index 00000000..1db1d6c5 --- /dev/null +++ b/scripts/build-gcov.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +cmake .. -DLWS_WITH_GCOV=1 && \ +make clean && \ +rm -f `find . -name "*.gcno" -o -name "*.gcda"` && \ +make -j16 && sudo make install diff --git a/scripts/gcov.sh b/scripts/gcov.sh new file mode 100755 index 00000000..ee71cc0f --- /dev/null +++ b/scripts/gcov.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +gcov `find . -name *.c.gcno | grep -v test-apps` -b | sed "/\.h.\$/,/^$/d" diff --git a/test-apps/attack.sh b/test-apps/attack.sh index 4314579a..0ce1004b 100755 --- a/test-apps/attack.sh +++ b/test-apps/attack.sh @@ -2,6 +2,8 @@ # # attack the test server and try to make it fall over # +# Requires the library to have been built with cmake .. -DCMAKE_BUILD_TYPE=DEBUG + SERVER=127.0.0.1 PORT=7681 LOG=/tmp/lwslog @@ -777,6 +779,16 @@ echo echo "--- survived OK ---" kill -2 $CPID +# coverage... +# run the test client against mirror for one period and exit +libwebsockets-test-server -s 2>> $LOG & +CPID=$! + +libwebsockets-test-client 127.0.0.1 -s -O +curl -v -F text=hello -F send=SEND -F upload=@../README.md https://127.0.0.1:7681/formtest -k + +kill -2 $CPID + exit 0 diff --git a/test-apps/test-client.c b/test-apps/test-client.c index db02f47c..872c3996 100644 --- a/test-apps/test-client.c +++ b/test-apps/test-client.c @@ -43,7 +43,7 @@ struct lws_poly_gen { #define block_size (3 * 4096) -static int deny_deflate, longlived, mirror_lifetime, test_post; +static int deny_deflate, longlived, mirror_lifetime, test_post, once; static struct lws *wsi_dumb, *wsi_mirror; static struct lws *wsi_multi[3]; static volatile int force_exit; @@ -360,7 +360,7 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason, "rxb %d, rx_count %d\n", mirror_lifetime, rxb, rx_count); wsi_mirror = NULL; - if (flag_echo) + if (flag_echo || once) force_exit = 1; break; @@ -536,6 +536,7 @@ static struct option options[] = { { "justmirror", no_argument, NULL, 'j' }, { "longlived", no_argument, NULL, 'l' }, { "post", no_argument, NULL, 'o' }, + { "once", no_argument, NULL, 'O' }, { "pingpong-secs", required_argument, NULL, 'P' }, { "ssl-cert", required_argument, NULL, 'C' }, { "ssl-key", required_argument, NULL, 'K' }, @@ -584,7 +585,7 @@ int main(int argc, char **argv) goto usage; while (n >= 0) { - n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moe", options, + n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moeO", options, NULL); if (n < 0) continue; @@ -628,6 +629,9 @@ int main(int argc, char **argv) case 'o': test_post = 1; break; + case 'O': + once = 1; + break; case 'n': flag_no_mirror_traffic = 1; lwsl_notice("Disabled sending mirror data (for pingpong testing)\n");