diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 18003a0..0b94345 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -81,7 +81,7 @@ jobs: timeout-minutes: 10 - name: Install dependencies run: | - sudo apt-get update && sudo apt-get install pbuilder debhelper -y + sudo apt-get update && sudo apt-get install git pbuilder debhelper -y - name: Setup pdebuilderrc for cross-compiling env: PBUILDER_RC: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 2598b6f..706333b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,11 +26,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 your system's [jsmn](https://github.com/zserge/jsmn) lib, instead of downloading it automatically. -### Changed +### Changes -#### voucher +#### Build -**The voucher ABI has breaking changes**. +* C++17 is now required to build the `brski` CLI tool. ## [0.2.0] - 2023-03-27 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 7310abf..afd5b7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,9 +155,9 @@ add_compile_options( $<$:-Wextra> ) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# use -std=c++11 rather than -std=gnu++11 +# use -std=c++17 rather than -std=gnu++17 set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -166,6 +166,7 @@ set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};${CMAKE_CURRENT_BINARY_DIR}/lib") # Include the libraries include(cmocka) +include(cpr) # need to call `FetchContent_MakeAvailable(cpr)` later include(openssl3) include(httplib) include(minIni) diff --git a/debian/control b/debian/control index 0a1f333..51059fd 100644 --- a/debian/control +++ b/debian/control @@ -5,8 +5,8 @@ Maintainer: Alexandru Mereacre Build-Depends: debhelper-compat (= 12), ca-certificates, cmake (>=3.15.0), libssl-dev (>=3.0.0), - libminini-dev (>=1.2), - libjsmn-dev (>=1.1.0) + libminini-dev (>=1.2), zlib1g-dev, + libjsmn-dev (>=1.1.0), git (>=2.30.0) Standards-Version: 4.5.0 Homepage: https://github.com/nqminds/brski Vcs-Browser: https://github.com/nqminds/brski diff --git a/lib/cpr.cmake b/lib/cpr.cmake new file mode 100644 index 0000000..9ef7f04 --- /dev/null +++ b/lib/cpr.cmake @@ -0,0 +1,11 @@ +if (BUILD_ONLY_DOCS) +else() + include(FetchContent) + SET(CURL_ZLIB OFF CACHE STRING "" FORCE) + FetchContent_Declare(cpr + URL https://github.com/libcpr/cpr/archive/refs/tags/1.9.5.tar.gz + URL_HASH SHA3_256=bea98952db1fe1f45f8d7cf88af98ac67178072722fef33c677f6956690fb489 + DOWNLOAD_NAME "cpr-1.9.5.tar.gz" + DOWNLOAD_DIR "${EP_DOWNLOAD_DIR}" # if empty string, uses default dir + ) +endif() diff --git a/src/brski/http/CMakeLists.txt b/src/brski/http/CMakeLists.txt index efd67c8..ba9d262 100644 --- a/src/brski/http/CMakeLists.txt +++ b/src/brski/http/CMakeLists.txt @@ -1,12 +1,23 @@ +set(CMAKE_C_EXTENSIONS ON) # needed to compile cpr +set(BRSKI_BUILD_TESTING "${BUILD_TESTING}") + +FetchContent_GetProperties(cpr) +if(NOT cpr_POPULATED) + FetchContent_Populate(cpr) + # zlib-ng causes issues with `make install`, at least until v2.1.2 + add_subdirectory(${cpr_SOURCE_DIR} ${cpr_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() +# cpr overwrites the BUILD_TESTING var, so we need to reset it +set(BUILD_TESTING "${BRSKI_BUILD_TESTING}" CACHE BOOL "Build the testing tree." FORCE) + add_library(https_server https_server.cpp) add_library(https_client https_client.cpp) +target_link_libraries(https_client PRIVATE os log cpr::cpr) + if (USE_CPPHTTPLIB_LIB) add_library(httplib_wrapper httplib_wrapper.cpp) target_link_libraries(httplib_wrapper PRIVATE os log httplib::httplib OpenSSL3::Crypto) target_compile_definitions(https_server PUBLIC WITH_CPPHTTPLIB_LIB) target_link_libraries(https_server PRIVATE os log httplib_wrapper) - - target_compile_definitions(https_client PUBLIC WITH_CPPHTTPLIB_LIB) - target_link_libraries(https_client PRIVATE os log httplib_wrapper) endif() diff --git a/src/brski/http/httplib_wrapper.cpp b/src/brski/http/httplib_wrapper.cpp index 017e643..28a6812 100644 --- a/src/brski/http/httplib_wrapper.cpp +++ b/src/brski/http/httplib_wrapper.cpp @@ -231,27 +231,3 @@ int httplib_start(struct http_config *config, return 0; } - -int httplib_post_request(const std::string &client_key_path, - const std::string &client_cert_path, - const std::string &host, int port, - const std::string &path, bool verify, - const std::string &body, - const std::string &content_type, - std::string &response) { - - httplib::SSLClient cli(host, port, client_cert_path, client_key_path); - - cli.enable_server_certificate_verification(verify); - - log_info("Post request to %s:%d%s", host.c_str(), port, path.c_str()); - if (httplib::Result res = cli.Post(path, body, content_type)) { - response = res->body; - return res->status; - } else { - std::string err = to_string(res.error()); - log_error("httplib::Client fail with \"%s\"", err.c_str()); - - return -1; - } -} diff --git a/src/brski/http/httplib_wrapper.hpp b/src/brski/http/httplib_wrapper.hpp index b139ad8..8e392d1 100644 --- a/src/brski/http/httplib_wrapper.hpp +++ b/src/brski/http/httplib_wrapper.hpp @@ -34,25 +34,4 @@ int httplib_start(struct http_config *config, */ void httplib_stop(void *srv_ctx); -/** - * @brief Sends a POST request to an endpoint - * - * @param[in] client_key_path The https client key path - * @param[in] client_cert_path The https client cert path - * @param[in] host The https server host name - * @param[in] port The https server port name - * @param[in] path The endpoint route path string - * @param[in] verify Enable server certificate verification - * @param[in] body The request body string - * @param[in] content_type The content typ string - * @param[out] response The output response string - * @return int the status code on success, -1 on failure - */ -int httplib_post_request(const std::string &client_key_path, - const std::string &client_cert_path, - const std::string &host, int port, - const std::string &path, bool verify, - const std::string &body, - const std::string &content_type, - std::string &response); #endif diff --git a/src/brski/http/https_client.cpp b/src/brski/http/https_client.cpp index 4c9b166..3c5e87b 100644 --- a/src/brski/http/https_client.cpp +++ b/src/brski/http/https_client.cpp @@ -8,30 +8,47 @@ * @brief File containing the implementation of the https client functions. */ +#include #include +#include "./https_client.hpp" + extern "C" { #include "../../utils/log.h" #include "../../utils/os.h" } -#ifdef WITH_CPPHTTPLIB_LIB -#include "httplib_wrapper.hpp" -#endif - int https_post_request(const std::string &client_key_path, const std::string &client_cert_path, const std::string &host, int port, const std::string &path, bool verify, const std::string &body, const std::string &content_type, std::string &response) { -#ifdef WITH_CPPHTTPLIB_LIB - return httplib_post_request(client_key_path, client_cert_path, host, port, - path, verify, body, content_type, response); -#else - log_error("No https client defined"); - return -1; -#endif + auto key = cpr::ssl::PemKey(std::string{client_key_path}); + auto cert = cpr::ssl::PemCert(std::string{client_cert_path}); + + cpr::SslOptions sslOpts = cpr::Ssl(cert, key, cpr::ssl::VerifyHost{verify}, + cpr::ssl::VerifyPeer{verify}); + auto url = cpr::Url{get_https_address(host.c_str(), port) + path}; + log_info("Post request to %s", url.c_str()); + cpr::Response res = cpr::Post( + cpr::Url{get_https_address(host.c_str(), port) + path}, sslOpts, + cpr::Body{body}, cpr::Header{{"Content-Type", content_type}}, + cpr::DebugCallback([&](cpr::DebugCallback::InfoType type, + std::string data, intptr_t userdata) -> void { + if (type == cpr::DebugCallback::InfoType::TEXT) { + log_trace("%s", data.c_str()); + } + })); + + if (res.status_code == 0) { + log_error("Post request to %s returned error %s", url.c_str(), + res.error.message.c_str()); + return -1; + } + + response = res.text; + return res.status_code; } std::string get_https_address(const char *bind_address, int port) {