From 49335410859a39bd7b87832ca242729cb5dd387f Mon Sep 17 00:00:00 2001 From: Simone Basso Date: Fri, 2 Aug 2019 09:36:51 +0200 Subject: [PATCH] Start converting libndt to use mkbuild This is yak shaving for releasing. There will be some pain but overall we're gonna be fine because the maintenance toil is going to be lower than it used to be. --- .appveyor.yml | 5 +- .ci/common | 1 - .gitignore | 45 +----- .gitmodules | 6 - .travis.yml | 2 +- CMakeLists.txt | 432 ++++++++++++++++++++++++++++++++++++++----------- MKBuild.yaml | 51 ++++++ README.md | 16 +- cmake/Modules | 1 - docker.sh | 95 +++++++++++ libndt.hpp | 48 ------ 11 files changed, 496 insertions(+), 206 deletions(-) delete mode 160000 .ci/common delete mode 100644 .gitmodules create mode 100644 MKBuild.yaml delete mode 160000 cmake/Modules create mode 100755 docker.sh diff --git a/.appveyor.yml b/.appveyor.yml index d3cfb07..7be5f9a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -4,5 +4,6 @@ environment: - CMAKE_GENERATOR: "Visual Studio 15 2017 Win64" - CMAKE_GENERATOR: "Visual Studio 15 2017" build_script: - - cmd: git submodule update --init --recursive - - cmd: .\.ci\common\script\appveyor.bat + - cmd: cmake -G "%CMAKE_GENERATOR%" . + - cmd: cmake --build . -- /nologo /property:Configuration=Release + - cmd: ctest --output-on-failure -C Release -a diff --git a/.ci/common b/.ci/common deleted file mode 160000 index 46845c7..0000000 --- a/.ci/common +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 46845c708c5ba015eb17ff2c5d24ac8f960887ac diff --git a/.gitignore b/.gitignore index a24f0d4..796b96d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,44 +1 @@ -/.ninja_deps -/.ninja_log -/.vs -/ALL_BUILD.vcxproj -/ALL_BUILD.vcxproj.filters -/argh.h -/build.ninja -/catch.hpp -/cmake_install.cmake -/CMakeCache.txt -/CMakeFiles/ -/CTestTestfile.cmake -/html -/INSTALL.vcxproj -/INSTALL.vcxproj.filters -/install_manifest.txt -/json.hpp -/latex -/libndt.a -/libndt.dylib -/libndt.sln -/libndt-client -/libndt-client.dir/ -/libndt-client.vcxproj -/libndt-client.vcxproj.filters -/Makefile -/MK_DIST/ -/Release/ -/rules.ninja -/RUN_TESTS.vcxproj -/RUN_TESTS.vcxproj.filters -/Testing/ -/tests-curl -/tests-curl.dir/ -/tests-curl.vcxproj -/tests-curl.vcxproj.filters -/tests-libndt -/tests-libndt.dir/ -/tests-libndt.vcxproj -/tests-libndt.vcxproj.filters -/windows-curl-7.61.0-1.tar.gz -/x64/ -/ZERO_CHECK.vcxproj -/ZERO_CHECK.vcxproj.filters +/build diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5ef9023..0000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule ".ci/common"] - path = .ci/common - url = https://github.com/measurement-kit/ci-common -[submodule "cmake/Modules"] - path = cmake/Modules - url = https://github.com/measurement-kit/cmake-modules diff --git a/.travis.yml b/.travis.yml index 35c49ee..dac4367 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,4 @@ matrix: - env: BUILD_TYPE="ubsan" - env: BUILD_TYPE="vanilla" script: - - ./.ci/common/script/travis $BUILD_TYPE + - ./docker.sh $BUILD_TYPE diff --git a/CMakeLists.txt b/CMakeLists.txt index 9187e14..2a13e1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,46 +1,52 @@ -cmake_minimum_required(VERSION 3.1.0) -project(libndt LANGUAGES C CXX) +# Autogenerated by `mkbuild`; DO NOT EDIT! -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules") -include(MkUtils) +cmake_minimum_required(VERSION 3.12.0) +project("libndt") -# Settings +include(CheckIncludeFileCXX) +include(CheckLibraryExists) +include(CheckCXXCompilerFlag) -set(LIBNDT_OPENSSL "${LIBNDT_OPENSSL}" CACHE PATH - "Path where OpenSSL is installed") -if(NOT ("${LIBNDT_OPENSSL}" STREQUAL "")) - list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBNDT_OPENSSL}/include") - list(APPEND CMAKE_LIBRARY_PATH "${LIBNDT_OPENSSL}/lib") -endif() +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) -# Download dependencies -# --------------------- +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) -MkDownloadAdishavitArgh() -MkDownloadNlohmannJson() -MkDownloadCatchorgCatch2() +list(APPEND CMAKE_REQUIRED_LIBRARIES Threads::Threads) -set(LIBNDT_ENABLE_CURL "TRUE" CACHE BOOL "Whether to enable cURL") -if("${MSVC}" AND "${LIBNDT_ENABLE_CURL}") - MkDownloadMeasurementKitPrebuiltWindowsCurl() - list(APPEND CMAKE_INCLUDE_PATH "${MK_WINDOWS_CURL_INCLUDE_PATH}") - list(APPEND CMAKE_LIBRARY_PATH "${MK_WINDOWS_CURL_LIBRARY_PATH}") - add_definitions(${MK_WINDOWS_CURL_DEFINITIONS}) - list(APPEND LIBNDT_LIBS ${MK_WINDOWS_CURL_EXTRA_LINK_LIBS}) +if(("${WIN32}")) + list(APPEND CMAKE_REQUIRED_LIBRARIES ws2_32 crypt32) endif() -# Checks -# ------ +enable_testing() + +if(("${WIN32}")) + if(("${CMAKE_SIZEOF_VOID_P}" EQUAL 4)) + SET(MK_WIN32_ARCH "x86") + elseif(("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)) + SET(MK_WIN32_ARCH "x64") + else() + message(FATAL_ERROR "Neither 32 not 64 bit") + endif() +endif() +if((${APPLE})) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/local/include") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L/usr/local/lib") +endif() include(CheckFunctionExists) -include(CheckIncludeFiles) include(CheckSymbolExists) - check_function_exists(strtonum LIBNDT_HAVE_STRTONUM) if(${LIBNDT_HAVE_STRTONUM}) add_definitions(-DLIBNDT_HAVE_STRTONUM) endif() - check_symbol_exists(SO_NOSIGPIPE sys/socket.h LIBNDT_HAVE_SO_NOSIGPIPE) if(${LIBNDT_HAVE_SO_NOSIGPIPE}) add_definitions(-DLIBNDT_HAVE_SO_NOSIGPIPE) @@ -50,81 +56,325 @@ if(${LIBNDT_HAVE_MSG_NOSIGNAL}) add_definitions(-DLIBNDT_HAVE_MSG_NOSIGNAL) endif() -check_include_files(openssl/ssl.h LIBNDT_HAVE_OPENSSL_SSL_H) -find_library(CRYPTO_LIBRARY crypto) -find_library(SSL_LIBRARY ssl) -if (NOT ("${LIBNDT_HAVE_OPENSSL_SSL_H}" STREQUAL "") AND NOT - ("${CRYPTO_LIBRARY}" STREQUAL "CRYPTO_LIBRARY-NOTFOUND") AND NOT - ("${SSL_LIBRARY}" STREQUAL "SSL_LIBRARY-NOTFOUND")) - message(STATUS "crypto library: ${CRYPTO_LIBRARY}") - list(APPEND LIBNDT_LIBS "${CRYPTO_LIBRARY}") - message(STATUS "ssl library: ${SSL_LIBRARY}") - list(APPEND LIBNDT_LIBS "${SSL_LIBRARY}") - add_definitions(-DLIBNDT_HAVE_OPENSSL) -else() - message(WARNING "OpenSSL not found; will disable TLS support") +# +# argh.h +# + +message(STATUS "mkdirAll: ${CMAKE_BINARY_DIR}/.mkbuild/include") +execute_process(COMMAND + ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/.mkbuild/include" + RESULT_VARIABLE FAILURE_1799) +if("${FAILURE_1799}") + message(FATAL_ERROR "${FAILURE_1799}") +endif() +message(STATUS "download: https://raw.githubusercontent.com/adishavit/argh/v1.3.1/argh.h") +file(DOWNLOAD https://raw.githubusercontent.com/adishavit/argh/v1.3.1/argh.h + "${CMAKE_BINARY_DIR}/.mkbuild/include/argh.h" + EXPECTED_HASH SHA256=ddb7dfc18dcf90149735b76fb2cff101067453a1df1943a6911233cb7085980c + TLS_VERIFY ON) +LIST(APPEND CMAKE_REQUIRED_INCLUDES "${CMAKE_BINARY_DIR}/.mkbuild/include") +CHECK_INCLUDE_FILE_CXX("argh.h" MK_HAVE_HEADER_2299) +if(NOT ("${MK_HAVE_HEADER_2299}")) + message(FATAL_ERROR "cannot find: argh.h") +endif() + +# +# catch.hpp +# + +message(STATUS "mkdirAll: ${CMAKE_BINARY_DIR}/.mkbuild/include") +execute_process(COMMAND + ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/.mkbuild/include" + RESULT_VARIABLE FAILURE_2623) +if("${FAILURE_2623}") + message(FATAL_ERROR "${FAILURE_2623}") +endif() +message(STATUS "download: https://github.com/catchorg/Catch2/releases/download/v2.8.0/catch.hpp") +file(DOWNLOAD https://github.com/catchorg/Catch2/releases/download/v2.8.0/catch.hpp + "${CMAKE_BINARY_DIR}/.mkbuild/include/catch.hpp" + EXPECTED_HASH SHA256=2791047e459b981a1035f4ee16a2ad031f5bfb4ba66487ad4d3fc816c8946f61 + TLS_VERIFY ON) +LIST(APPEND CMAKE_REQUIRED_INCLUDES "${CMAKE_BINARY_DIR}/.mkbuild/include") +CHECK_INCLUDE_FILE_CXX("catch.hpp" MK_HAVE_HEADER_3140) +if(NOT ("${MK_HAVE_HEADER_3140}")) + message(FATAL_ERROR "cannot find: catch.hpp") endif() -if(${LIBNDT_ENABLE_CURL}) - find_package(CURL) - if(${CURL_FOUND}) - add_definitions(-DLIBNDT_HAVE_CURL) +if(("${WIN32}")) + + # + # windows-curl-7.61.1-1.tar.gz + # + + message(STATUS "mkdirAll: ${CMAKE_BINARY_DIR}/.mkbuild/download") + execute_process(COMMAND + ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/.mkbuild/download" + RESULT_VARIABLE FAILURE_3521) + if("${FAILURE_3521}") + message(FATAL_ERROR "${FAILURE_3521}") + endif() + message(STATUS "download: https://github.com/measurement-kit/prebuilt/releases/download//testing/windows-curl-7.61.1-1.tar.gz") + file(DOWNLOAD https://github.com/measurement-kit/prebuilt/releases/download//testing/windows-curl-7.61.1-1.tar.gz + "${CMAKE_BINARY_DIR}/.mkbuild/download/windows-curl-7.61.1-1.tar.gz" + EXPECTED_HASH SHA256=424d2f18f0f74dd6a0128f0f4e59860b7d2f00c80bbf24b2702e9cac661357cf + TLS_VERIFY ON) + message(STATUS "Extract: ${CMAKE_BINARY_DIR}/.mkbuild/download/windows-curl-7.61.1-1.tar.gz") + execute_process(COMMAND + ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/.mkbuild/download/windows-curl-7.61.1-1.tar.gz" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/.mkbuild/download" + RESULT_VARIABLE FAILURE_4344) + if("${FAILURE_4344}") + message(FATAL_ERROR "${FAILURE_4344}") + endif() + LIST(APPEND CMAKE_REQUIRED_INCLUDES "${CMAKE_BINARY_DIR}/.mkbuild/download/MK_DIST/windows/curl/7.61.1-1/${MK_WIN32_ARCH}/include") + CHECK_INCLUDE_FILE_CXX("curl/curl.h" MK_HAVE_HEADER_4589) + if(NOT ("${MK_HAVE_HEADER_4589}")) + message(FATAL_ERROR "cannot find: curl/curl.h") + endif() + CHECK_LIBRARY_EXISTS("${CMAKE_BINARY_DIR}/.mkbuild/download/MK_DIST/windows/curl/7.61.1-1/${MK_WIN32_ARCH}/lib/libcurl.lib" "curl_easy_init" "" MK_HAVE_LIB_4748) + if(NOT ("${MK_HAVE_LIB_4748}")) + message(FATAL_ERROR "cannot find: ${CMAKE_BINARY_DIR}/.mkbuild/download/MK_DIST/windows/curl/7.61.1-1/${MK_WIN32_ARCH}/lib/libcurl.lib") + endif() + LIST(APPEND CMAKE_REQUIRED_LIBRARIES "${CMAKE_BINARY_DIR}/.mkbuild/download/MK_DIST/windows/curl/7.61.1-1/${MK_WIN32_ARCH}/lib/libcurl.lib") + LIST(APPEND CMAKE_REQUIRED_DEFINITIONS -DCURL_STATICLIB) +else() + CHECK_INCLUDE_FILE_CXX("curl/curl.h" MK_HAVE_HEADER_5306) + if(NOT ("${MK_HAVE_HEADER_5306}")) + message(FATAL_ERROR "cannot find: curl/curl.h") endif() + CHECK_LIBRARY_EXISTS("curl" "curl_easy_init" "" MK_HAVE_LIB_5465) + if(NOT ("${MK_HAVE_LIB_5465}")) + message(FATAL_ERROR "cannot find: curl") + endif() + LIST(APPEND CMAKE_REQUIRED_LIBRARIES "curl") endif() -# Compiler flags +# +# generic-assets-20190520205742.tar.gz +# -MkSetCompilerFlags() +message(STATUS "mkdirAll: ${CMAKE_BINARY_DIR}/.mkbuild/download") +execute_process(COMMAND + ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/.mkbuild/download" + RESULT_VARIABLE FAILURE_5889) +if("${FAILURE_5889}") + message(FATAL_ERROR "${FAILURE_5889}") +endif() +message(STATUS "download: https://github.com/measurement-kit/generic-assets/releases/download/20190520205742/generic-assets-20190520205742.tar.gz") +file(DOWNLOAD https://github.com/measurement-kit/generic-assets/releases/download/20190520205742/generic-assets-20190520205742.tar.gz + "${CMAKE_BINARY_DIR}/.mkbuild/download/generic-assets-20190520205742.tar.gz" + EXPECTED_HASH SHA256=70d590c20b2ed31fd43cc63709b267672fecfeac7e908d11e845664ddd43b04f + TLS_VERIFY ON) +message(STATUS "Extract: ${CMAKE_BINARY_DIR}/.mkbuild/download/generic-assets-20190520205742.tar.gz") +execute_process(COMMAND + ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/.mkbuild/download/generic-assets-20190520205742.tar.gz" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/.mkbuild/download" + RESULT_VARIABLE FAILURE_6750) +if("${FAILURE_6750}") + message(FATAL_ERROR "${FAILURE_6750}") +endif() -# Library and binary -# ------------------ +# +# json.hpp +# -set(LIBNDT_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} - ${CURL_INCLUDE_DIRS} ${CMAKE_REQUIRED_INCLUDES}) +message(STATUS "mkdirAll: ${CMAKE_BINARY_DIR}/.mkbuild/include") +execute_process(COMMAND + ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/.mkbuild/include" + RESULT_VARIABLE FAILURE_7035) +if("${FAILURE_7035}") + message(FATAL_ERROR "${FAILURE_7035}") +endif() +message(STATUS "download: https://raw.githubusercontent.com/nlohmann/json/v3.6.1/single_include/nlohmann/json.hpp") +file(DOWNLOAD https://raw.githubusercontent.com/nlohmann/json/v3.6.1/single_include/nlohmann/json.hpp + "${CMAKE_BINARY_DIR}/.mkbuild/include/json.hpp" + EXPECTED_HASH SHA256=d2eeb25d2e95bffeb08ebb7704cdffd2e8fca7113eba9a0b38d60a5c391ea09a + TLS_VERIFY ON) +LIST(APPEND CMAKE_REQUIRED_INCLUDES "${CMAKE_BINARY_DIR}/.mkbuild/include") +CHECK_INCLUDE_FILE_CXX("json.hpp" MK_HAVE_HEADER_7587) +if(NOT ("${MK_HAVE_HEADER_7587}")) + message(FATAL_ERROR "cannot find: json.hpp") +endif() -add_executable(libndt-client libndt-client.cpp) -target_include_directories(libndt-client PUBLIC ${LIBNDT_INCLUDES}) -list (APPEND LIBNDT_LIBS ${CURL_LIBRARIES}) -install(FILES libndt.hpp DESTINATION include/measurement-kit/libndt) -install(TARGETS libndt-client DESTINATION bin) -if("${WIN32}" OR "${MINGW}") - list(APPEND LIBNDT_LIBS "ws2_32") - if ("${MINGW}") - list(APPEND LIBNDT_LIBS -static-libgcc -static-libstdc++) +if(("${APPLE}")) + if(EXISTS "/usr/local/opt/openssl@1.1") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/opt/openssl@1.1/include") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/local/opt/openssl@1.1/include") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/opt/openssl@1.1/lib") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L/usr/local/opt/openssl@1.1/lib") endif() endif() -list(APPEND LIBNDT_LIBS Threads::Threads) -target_link_libraries(libndt-client "${LIBNDT_LIBS}") +CHECK_INCLUDE_FILE_CXX("openssl/rsa.h" MK_HAVE_HEADER_8172) +if(NOT ("${MK_HAVE_HEADER_8172}")) + message(FATAL_ERROR "cannot find: openssl/rsa.h") +endif() +CHECK_LIBRARY_EXISTS("crypto" "RSA_new" "" MK_HAVE_LIB_8327) +if(NOT ("${MK_HAVE_LIB_8327}")) + message(FATAL_ERROR "cannot find: crypto") +endif() +LIST(APPEND CMAKE_REQUIRED_LIBRARIES "crypto") +CHECK_INCLUDE_FILE_CXX("openssl/ssl.h" MK_HAVE_HEADER_8520) +if(NOT ("${MK_HAVE_HEADER_8520}")) + message(FATAL_ERROR "cannot find: openssl/ssl.h") +endif() +CHECK_LIBRARY_EXISTS("ssl" "SSL_read" "" MK_HAVE_LIB_8675) +if(NOT ("${MK_HAVE_LIB_8675}")) + message(FATAL_ERROR "cannot find: ssl") +endif() +LIST(APPEND CMAKE_REQUIRED_LIBRARIES "ssl") -# Testing -# ------- +# +# Set restrictive compiler flags +# -set(BUILD_TESTING "ON" CACHE BOOL "Whether to build tests") -if(${BUILD_TESTING}) - enable_testing() - if(${CURL_FOUND}) - add_executable(tests-curl curlx_test.cpp) - target_link_libraries(tests-curl "${LIBNDT_LIBS}") - target_include_directories(tests-curl PUBLIC ${LIBNDT_INCLUDES}) - add_test(NAME curl_unit_tests COMMAND tests-curl) - endif() - add_executable(tests-libndt libndt_test.cpp strtonum_test.cpp) - target_link_libraries(tests-libndt "${LIBNDT_LIBS}") - target_include_directories(tests-libndt PUBLIC ${LIBNDT_INCLUDES}) - add_test(NAME other_unit_tests COMMAND tests-libndt) - if(${CURL_FOUND}) # Some tests require cURL for mlab-ns - add_test(NAME simple_test COMMAND libndt-client --verbose - --download --upload) - add_test(NAME json_test COMMAND libndt-client --verbose --json - --download --upload) - add_test(NAME websocket_test COMMAND libndt-client --verbose --websocket - --download --upload) - if(${UNIX}) # On UNIX We auto-discover the CA bundle path - add_test(NAME tls_test COMMAND libndt-client --verbose --download - --upload --tls --json) - # This is how NDT should run - add_test(NAME modern_test COMMAND libndt-client --verbose --download - --upload --tls --json --websocket) +macro(MKSetRestrictiveCompilerFlags) + if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") OR + ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Werror") + # https://www.owasp.org/index.php/C-Based_Toolchain_Hardening_Cheat_Sheet + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wall") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wextra") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wconversion") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wcast-align") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wformat=2") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wformat-security") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -fno-common") + # Some options are only supported by GCC when we're compiling C code: + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wmissing-prototypes") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wstrict-prototypes") + else() + set(MK_C_FLAGS "${MK_C_FLAGS} -Wmissing-prototypes") + set(MK_C_FLAGS "${MK_C_FLAGS} -Wstrict-prototypes") + endif() + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wmissing-declarations") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wstrict-overflow") + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -Wtrampolines") endif() + set(MK_CXX_FLAGS "${MK_CXX_FLAGS} -Woverloaded-virtual") + set(MK_CXX_FLAGS "${MK_CXX_FLAGS} -Wreorder") + set(MK_CXX_FLAGS "${MK_CXX_FLAGS} -Wsign-promo") + set(MK_CXX_FLAGS "${MK_CXX_FLAGS} -Wnon-virtual-dtor") + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} -fstack-protector-all") + if(NOT "${APPLE}" AND NOT "${MINGW}") + set(MK_LD_FLAGS "${MK_LD_FLAGS} -Wl,-z,noexecstack") + set(MK_LD_FLAGS "${MK_LD_FLAGS} -Wl,-z,now") + set(MK_LD_FLAGS "${MK_LD_FLAGS} -Wl,-z,relro") + set(MK_LD_FLAGS "${MK_LD_FLAGS} -Wl,-z,nodlopen") + set(MK_LD_FLAGS "${MK_LD_FLAGS} -Wl,-z,nodump") + elseif(("${MINGW}")) + set(MK_LD_FLAGS "${MK_LD_FLAGS} -static") + endif() + add_definitions(-D_FORTIFY_SOURCES=2) + elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # TODO(bassosimone): add support for /Wall and /analyze + set(MK_COMMON_FLAGS "${MK_COMMON_FLAGS} /WX /W4 /EHs") + set(MK_LD_FLAGS "${MK_LD_FLAGS} /WX") + else() + message(FATAL_ERROR "Compiler not supported: ${CMAKE_CXX_COMPILER_ID}") endif() -endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MK_COMMON_FLAGS} ${MK_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MK_COMMON_FLAGS} ${MK_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MK_LD_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MK_LD_FLAGS}") + if("${WIN32}") + add_definitions(-D_WIN32_WINNT=0x0600) # for NI_NUMERICSERV and WSAPoll + endif() +endmacro() + +MKSetRestrictiveCompilerFlags() + +# +# Prepare for compiling targets +# + +add_definitions(${CMAKE_REQUIRED_DEFINITIONS}) +include_directories(${CMAKE_REQUIRED_INCLUDES}) + +# +# libndt-client +# + +add_executable( + libndt-client + libndt-client.cpp +) +target_link_libraries( + libndt-client + ${CMAKE_REQUIRED_LIBRARIES} +) + +# +# tests-curl +# + +add_executable( + tests-curl + curlx_test.cpp +) +target_link_libraries( + tests-curl + ${CMAKE_REQUIRED_LIBRARIES} +) + +# +# tests-libndt +# + +add_executable( + tests-libndt + libndt_test.cpp strtonum_test.cpp +) +target_link_libraries( + tests-libndt + ${CMAKE_REQUIRED_LIBRARIES} +) + +# +# test: curl_unit_tests +# + +add_test( + NAME curl_unit_tests COMMAND tests-curl +) + +# +# test: ndt3_test +# + +add_test( + NAME ndt3_test COMMAND libndt-client -verbose -download -upload ndt-iupui-mlab3-lga0t.measurement-lab.org +) + +# +# test: ndt4_test +# + +add_test( + NAME ndt4_test COMMAND libndt-client -verbose -json -websocket -download -upload ndt-iupui-mlab3-lga0t.measurement-lab.org +) + +# +# test: ndt5_test +# + +add_test( + NAME ndt5_test COMMAND libndt-client -verbose -download -upload -tls -json -websocket ndt-iupui-mlab3-lga0t.measurement-lab.org +) + +# +# test: ndt7_test +# + +add_test( + NAME ndt7_test COMMAND libndt-client -verbose -download -upload -ndt7 ndt-iupui-mlab3-lga0t.measurement-lab.org +) + +# +# test: other_unit_tests +# + +add_test( + NAME other_unit_tests COMMAND tests-libndt +) diff --git a/MKBuild.yaml b/MKBuild.yaml new file mode 100644 index 0000000..fd9baf7 --- /dev/null +++ b/MKBuild.yaml @@ -0,0 +1,51 @@ +name: libndt + +docker: bassosimone/mk-debian +docker_tc_disabled: false + +function_checks: +- name: strtonum + define: LIBNDT_HAVE_STRTONUM + +symbol_checks: +- name: SO_NOSIGPIPE + header: sys/socket.h + define: LIBNDT_HAVE_SO_NOSIGPIPE +- name: MSG_NOSIGNAL + header: sys/socket.h + define: LIBNDT_HAVE_MSG_NOSIGNAL + +dependencies: +- github.com/adishavit/argh +- github.com/catchorg/catch2 +- github.com/curl/curl +- github.com/measurement-kit/generic-assets +- github.com/nlohmann/json +- github.com/openssl/openssl + +targets: + executables: + libndt-client: + compile: [libndt-client.cpp] + tests-curl: + compile: [curlx_test.cpp] + tests-libndt: + compile: [libndt_test.cpp strtonum_test.cpp] + +tests: + curl_unit_tests: + command: tests-curl + other_unit_tests: + command: tests-libndt + ndt3_test: + command: libndt-client -verbose -download -upload + ndt-iupui-mlab3-lga0t.measurement-lab.org + ndt4_test: + command: libndt-client -verbose -json -websocket -download -upload + ndt-iupui-mlab3-lga0t.measurement-lab.org + ndt5_test: + command: libndt-client -verbose -download -upload -tls -json -websocket + ndt-iupui-mlab3-lga0t.measurement-lab.org + ndt7_test: + command: libndt-client -verbose -download -upload -ndt7 + ndt-iupui-mlab3-lga0t.measurement-lab.org diff --git a/README.md b/README.md index d948595..3233b7f 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,10 @@ https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) before proceeding. The minimum supported version is v3.0.0. Put `json.hpp` in the current working directory. +Libndt depends on OpenSSL (for TLS support and in the future for +WebSocket support) and cURL (to autodiscover servers). CMake will +fail if such dependencies are not installed. + Then, download [libndt.hpp]( https://github.com/measurement-kit/libndt/blob/master/libndt.hpp) and put it in the current working directory. @@ -37,18 +41,6 @@ int main() { Compile with `g++ -std=c++11 -Wall -Wextra -I. -o main main.cpp`. -Libndt optionally depends on OpenSSL (for TLS support and in the future for -WebSocket support) and cURL (to autodiscover servers). You can use the following -preprocessor macros to tell libndt that such dependencies are available: - -- `LIBNDT_HAVE_OPENSSL`: just define this macro to use OpenSSL (it does not - matter whether the macro is defined to a true or false value); - -- `LIBNDT_HAVE_CURL`: just define to use cURL (likewise). - -If these dependencies are not installed in canonical locations, make sure you -add the pass the compiler the proper flags. - See [codedocs.xyz/measurement-kit/libndt]( https://codedocs.xyz/measurement-kit/libndt/) for API documentation; [libndt.hpp](libndt.hpp) for the full API. diff --git a/cmake/Modules b/cmake/Modules deleted file mode 160000 index 3c70b2f..0000000 --- a/cmake/Modules +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3c70b2f60d313ee5a58a97d8c4e94c6e38f64360 diff --git a/docker.sh b/docker.sh new file mode 100755 index 0000000..9e2c06e --- /dev/null +++ b/docker.sh @@ -0,0 +1,95 @@ +#!/bin/sh -e +# Autogenerated by 'mkbuild'; DO NOT EDIT! + +USAGE="Usage: $0 asan|clang|coverage|ubsan|vanilla" + +if [ $# -eq 1 ]; then + INTERNAL=0 + BUILD_TYPE="$1" +elif [ $# -eq 2 -a "$1" = "-internal" ]; then + INTERNAL=1 + BUILD_TYPE="$2" +else + echo "$USAGE" 1>&2 + exit 1 +fi + +if [ "$CODECOV_TOKEN" = "" ]; then + echo "WARNING: CODECOV_TOKEN is not set" 1>&2 +fi +if [ "$TRAVIS_BRANCH" = "" ]; then + echo "WARNING: TRAVIS_BRANCH is not set" 1>&2 +fi + +set -x + +if [ $INTERNAL -eq 0 ]; then + exec docker run --cap-add=NET_ADMIN \ + --cap-add=SYS_PTRACE \ + -e CODECOV_TOKEN=$CODECOV_TOKEN \ + -e TRAVIS_BRANCH=$TRAVIS_BRANCH \ + -v "$(pwd):/mk" \ + --workdir /mk \ + -t bassosimone/mk-debian \ + ./docker.sh -internal "$1" +fi + +env | grep -v TOKEN | sort + +# Select the proper build flags depending on the build type +if [ "$BUILD_TYPE" = "asan" ]; then + export CFLAGS="-fsanitize=address -O1 -fno-omit-frame-pointer" + export CXXFLAGS="-fsanitize=address -O1 -fno-omit-frame-pointer" + export LDFLAGS="-fsanitize=address -fno-omit-frame-pointer" + export CMAKE_BUILD_TYPE="Debug" + +elif [ "$BUILD_TYPE" = "clang" ]; then + export CMAKE_BUILD_TYPE="Release" + export CXXFLAGS="-stdlib=libc++" + export CC=clang + export CXX=clang++ + +elif [ "$BUILD_TYPE" = "coverage" ]; then + export CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + export CMAKE_BUILD_TYPE="Debug" + export CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + export LDFLAGS="-lgcov" + +elif [ "$BUILD_TYPE" = "ubsan" ]; then + export CFLAGS="-fsanitize=undefined -fno-sanitize-recover" + export CXXFLAGS="-fsanitize=undefined -fno-sanitize-recover" + export LDFLAGS="-fsanitize=undefined" + export CMAKE_BUILD_TYPE="Debug" + +elif [ "$BUILD_TYPE" = "vanilla" ]; then + export CMAKE_BUILD_TYPE="Release" + +else + echo "$0: BUILD_TYPE not in: asan, clang, coverage, ubsan, vanilla" 1>&2 + exit 1 +fi + +# Configure and make equivalent +mkdir -p build/$BUILD_TYPE +cd build/$BUILD_TYPE +cmake -GNinja -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE ../../ +cmake --build . -- -v + +# Make sure we don't consume too much resources by bumping latency. Not all +# repositories need this feature. For them the code is commented out. +tc qdisc add dev eth0 root netem delay 200ms 10ms + +# Make check equivalent +ctest --output-on-failure -a -j1 + +# Stop adding latency. Commented out if we don't need it. +tc qdisc del dev eth0 root + +# Measure and possibly report the test coverage +if [ "$BUILD_TYPE" = "coverage" ]; then + lcov --directory . --capture -o lcov.info + if [ "$CODECOV_TOKEN" != "" ]; then + curl -fsSL -o codecov.sh https://codecov.io/bash + bash codecov.sh -X gcov -Z -f lcov.info + fi +fi diff --git a/libndt.hpp b/libndt.hpp index baa203a..63f1743 100644 --- a/libndt.hpp +++ b/libndt.hpp @@ -91,16 +91,12 @@ #include #include -#ifdef LIBNDT_HAVE_OPENSSL // Define this macro to enable OpenSSL support #include #include #include #include -#endif -#ifdef LIBNDT_HAVE_CURL // Likewise but to enable cURL support #include -#endif namespace measurement_kit { namespace libndt { @@ -511,7 +507,6 @@ class Client { // // Note that we cannot have ndt7 without OpenSSL. -#ifdef LIBNDT_HAVE_OPENSSL // ndt7_download performs a ndt7 download. Returns true if the download // succeeds and false in case of failure. bool ndt7_download() noexcept; @@ -521,7 +516,6 @@ class Client { // ndt7_connect connects to @p url_path. bool ndt7_connect(std::string url_path) noexcept; -#endif // LIBNDT_HAVE_OPENSSL // NDT protocol API // ```````````````` @@ -703,7 +697,6 @@ class Client { // ``````````````````` // // This section contains functionality used by cURL. -#ifdef LIBNDT_HAVE_CURL class CurlDeleter { public: void operator()(CURL *handle) noexcept; @@ -738,7 +731,6 @@ class Client { virtual CURLcode curlx_getinfo_response_code( UniqueCurl &handle, long *response_code) noexcept; -#endif // LIBNDT_HAVE_CURL virtual bool query_mlabns_curl(const std::string &url, long timeout, std::string *body) noexcept; @@ -832,9 +824,7 @@ class Client { Socket sock_ = (Socket)-1; std::vector granted_suite_; Settings settings_; -#ifdef LIBNDT_HAVE_OPENSSL std::map fd_to_ssl_; -#endif #ifdef _WIN32 Winsock winsock_; #endif @@ -964,7 +954,6 @@ constexpr size_t msg_kickoff_size = sizeof(msg_kickoff) - 1; // Private utils // ````````````` -#ifdef LIBNDT_HAVE_OPENSSL // Format OpenSSL error as a C++ string. static std::string ssl_format_error() noexcept { std::stringstream ss; @@ -977,7 +966,6 @@ static std::string ssl_format_error() noexcept { } return ss.str(); } -#endif // LIBNDT_HAVE_OPENSSL // Map an error code to the corresponding string value. static std::string libndt_perror(Err err) noexcept { @@ -1021,12 +1009,10 @@ static std::string libndt_perror(Err err) noexcept { } #undef LIBNDT_PERROR // Tidy // -#ifdef LIBNDT_HAVE_OPENSSL if (err == Err::ssl_generic) { rv += ": "; rv += ssl_format_error(); } -#endif // LIBNDT_HAVE_OPENSSL // return rv; } @@ -1235,7 +1221,6 @@ bool Client::run() noexcept { // TODO(bassosimone): we will eventually want to refactor the code to // make ndt7 the default and ndt5 the optional case. if ((settings_.protocol_flags & protocol_flag_ndt7) != 0) { -#ifdef LIBNDT_HAVE_OPENSSL LIBNDT_EMIT_INFO("using the ndt7 protocol"); if ((settings_.nettest_flags & nettest_flag_download) != 0) { // TODO(bassosimone): for now we do not try with more than one host @@ -1256,10 +1241,6 @@ bool Client::run() noexcept { // TODO(bassosimone): here we may want to warn if the user selects // subtests that we actually do not implement. return true; -#else - LIBNDT_EMIT_WARNING("ndt7: OpenSSL support not compiled in"); - return false; -#endif } if (!connect()) { LIBNDT_EMIT_WARNING("cannot connect to remote host; trying another one"); @@ -1902,7 +1883,6 @@ bool Client::run_upload() noexcept { // ndt7 protocol API // ````````````````` -#ifdef LIBNDT_HAVE_OPENSSL bool Client::ndt7_download() noexcept { if (!ndt7_connect("/ndt/v7/download")) { @@ -2013,8 +1993,6 @@ bool Client::ndt7_connect(std::string url_path) noexcept { return true; } -#endif // LIBNDT_HAVE_OPENSSL - // NDT protocol API // ```````````````` @@ -2841,8 +2819,6 @@ Err Client::ws_recvmsg( // #define OS_EINVAL EINVAL #endif -#ifdef LIBNDT_HAVE_OPENSSL - // - - - BEGIN BIO IMPLEMENTATION - - - { // // This BIO implementation is based on the implementation of rabbitmq-c @@ -3041,8 +3017,6 @@ static Err ssl_retry_unary_op(std::string opname, Client *client, SSL *ssl, return err; } -#endif // LIBNDT_HAVE_OPENSSL - Err Client::netx_maybews_dial(const std::string &hostname, const std::string &port, uint64_t ws_flags, std::string ws_protocol, std::string url_path, @@ -3085,7 +3059,6 @@ Err Client::netx_maybessl_dial(const std::string &hostname, LIBNDT_EMIT_DEBUG("netx_maybessl_dial: TLS not enabled"); return Err::none; } -#ifdef LIBNDT_HAVE_OPENSSL LIBNDT_EMIT_DEBUG("netx_maybetls_dial: about to start TLS handshake"); if (settings_.ca_bundle_path.empty() && settings_.tls_verify_peer) { #ifndef _WIN32 @@ -3192,10 +3165,6 @@ Err Client::netx_maybessl_dial(const std::string &hostname, } LIBNDT_EMIT_DEBUG("SSL handshake complete"); return Err::none; -#else - LIBNDT_EMIT_WARNING("SSL support not compiled in"); - return Err::function_not_supported; -#endif } Err Client::netx_maybesocks5h_dial(const std::string &hostname, @@ -3615,7 +3584,6 @@ Err Client::netx_recv_nonblocking(Socket fd, void *base, Size count, return Err::invalid_argument; } sys_set_last_error(0); -#ifdef LIBNDT_HAVE_OPENSSL if ((settings_.protocol_flags & protocol_flag_tls) != 0) { if (count > INT_MAX) { return Err::invalid_argument; @@ -3633,7 +3601,6 @@ Err Client::netx_recv_nonblocking(Socket fd, void *base, Size count, *actual = (Size)ret; return Err::none; } -#endif auto rv = sys_recv(fd, base, count); if (rv < 0) { assert(rv == -1); @@ -3698,7 +3665,6 @@ Err Client::netx_send_nonblocking(Socket fd, const void *base, Size count, return Err::invalid_argument; } sys_set_last_error(0); -#ifdef LIBNDT_HAVE_OPENSSL if ((settings_.protocol_flags & protocol_flag_tls) != 0) { if (count > INT_MAX) { return Err::invalid_argument; @@ -3716,7 +3682,6 @@ Err Client::netx_send_nonblocking(Socket fd, const void *base, Size count, *actual = (Size)ret; return Err::none; } -#endif auto rv = sys_send(fd, base, count); if (rv < 0) { assert(rv == -1); @@ -3909,7 +3874,6 @@ Err Client::netx_poll( } Err Client::netx_shutdown_both(Socket fd) noexcept { -#ifdef LIBNDT_HAVE_OPENSSL if ((settings_.protocol_flags & protocol_flag_tls) != 0) { if (fd_to_ssl_.count(fd) != 1) { return Err::invalid_argument; @@ -3925,7 +3889,6 @@ Err Client::netx_shutdown_both(Socket fd) noexcept { return err; } } -#endif if (sys_shutdown(fd, LIBNDT_OS_SHUT_RDWR) != 0) { return netx_map_errno(sys_get_last_error()); } @@ -3933,7 +3896,6 @@ Err Client::netx_shutdown_both(Socket fd) noexcept { } Err Client::netx_closesocket(Socket fd) noexcept { -#if LIBNDT_HAVE_OPENSSL if ((settings_.protocol_flags & protocol_flag_tls) != 0) { if (fd_to_ssl_.count(fd) != 1) { return Err::invalid_argument; @@ -3941,7 +3903,6 @@ Err Client::netx_closesocket(Socket fd) noexcept { ::SSL_free(fd_to_ssl_.at(fd)); fd_to_ssl_.erase(fd); } -#endif if (sys_closesocket(fd) != 0) { return netx_map_errno(sys_get_last_error()); } @@ -3950,7 +3911,6 @@ Err Client::netx_closesocket(Socket fd) noexcept { // Dependencies (cURL) // ``````````````````` -#ifdef LIBNDT_HAVE_CURL } // namespace libndt } // namespace measurement_kit extern "C" { @@ -4107,17 +4067,9 @@ CURLcode Client::curlx_getinfo_response_code( handle.get(), CURLINFO_RESPONSE_CODE, response_code); } -#endif // LIBNDT_HAVE_CURL - bool Client::query_mlabns_curl(const std::string &url, long timeout, std::string *body) noexcept { -#ifdef LIBNDT_HAVE_CURL return curlx_get_maybe_socks5(settings_.socks5h_port, url, timeout, body); -#else - (void)url, (void)timeout, (void)body; - LIBNDT_EMIT_WARNING("cURL not compiled in; don't know how to get server"); - return false; -#endif } // Other helpers