diff --git a/.github/docker-images/Dockerfile b/.github/docker-images/Dockerfile index 754b7d145..bd9a1dce0 100644 --- a/.github/docker-images/Dockerfile +++ b/.github/docker-images/Dockerfile @@ -9,7 +9,7 @@ FROM ${BASE_IMAGE} AS deploy COPY . /root/aws-iot-device-client RUN mkdir -p /root/aws-iot-device-client/build \ && cd /root/aws-iot-device-client/build \ - && cmake .. \ + && cmake -DCMAKE_BUILD_TYPE=Release .. \ && cmake --build . --target aws-iot-device-client ENTRYPOINT ["/root/aws-iot-device-client/build/aws-iot-device-client"] diff --git a/.github/docker-images/base-images/device-client/amazonlinux/Dockerfile b/.github/docker-images/base-images/device-client/amazonlinux/Dockerfile index f2ebc7c54..c674abd1b 100644 --- a/.github/docker-images/base-images/device-client/amazonlinux/Dockerfile +++ b/.github/docker-images/base-images/device-client/amazonlinux/Dockerfile @@ -1,6 +1,6 @@ FROM amazonlinux:2.0.20230307.0 as base -ARG OPENSSL_VERSION=1.1.1n +ARG OPENSSL_VERSION=3.0.8 ############################################################################### # Install prereqs @@ -22,7 +22,7 @@ RUN yum -y update \ && rm -rf /var/cache/yum ############################################################################### -# Install OpenSSL 1.1.1 +# Install OpenSSL 3.0.8 ############################################################################### WORKDIR /tmp RUN wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ @@ -46,9 +46,9 @@ RUN curl -sSL https://github.com/Kitware/CMake/releases/download/v3.24.4/cmake-3 # Clone and build Google Test ############################################################################### WORKDIR /tmp -RUN curl -sSL https://github.com/google/googletest/archive/release-1.11.0.tar.gz -o release-1.11.0.tar.gz \ - && tar xf release-1.11.0.tar.gz \ - && cd googletest-release-1.11.0 \ +RUN curl -sSL https://github.com/google/googletest/archive/release-1.12.0.tar.gz -o release-1.12.0.tar.gz \ + && tar xf release-1.12.0.tar.gz \ + && cd googletest-release-1.12.0 \ && cmake -DBUILD_SHARED_LIBS=ON . \ && make \ && cp -a googletest/include/gtest /usr/include/ \ @@ -87,7 +87,7 @@ RUN mkdir sdk-cpp-workspace \ && cd sdk-cpp-workspace \ && git clone https://github.com/aws/aws-iot-device-sdk-cpp-v2.git \ && cd aws-iot-device-sdk-cpp-v2 \ - && git checkout ac3ba3774b031dde1b988e698880d6064d53b9d9 \ + && git checkout 74c8b683ebe5b1cbf484f6acaa281f56aaa63948 \ && git submodule update --init --recursive \ && cd .. \ && mkdir aws-iot-device-sdk-cpp-v2-build \ @@ -117,4 +117,4 @@ RUN mkdir -p /root/aws-iot-device-client/build \ && cmake .. \ && cmake --build . --target aws-iot-device-client -ENTRYPOINT ["/root/aws-iot-device-client/build/aws-iot-device-client"] \ No newline at end of file +ENTRYPOINT ["/root/aws-iot-device-client/build/aws-iot-device-client"] diff --git a/.github/docker-images/base-images/device-client/ubi8/Dockerfile b/.github/docker-images/base-images/device-client/ubi8/Dockerfile index ea238c10f..a031280bf 100644 --- a/.github/docker-images/base-images/device-client/ubi8/Dockerfile +++ b/.github/docker-images/base-images/device-client/ubi8/Dockerfile @@ -2,7 +2,7 @@ #https://access.redhat.com/RegistryAuthentication FROM registry.access.redhat.com/ubi8/ubi AS base -ARG OPENSSL_VERSION=1.1.1n +ARG OPENSSL_VERSION=3.0.8 ############################################################################### # Install prereqs @@ -33,7 +33,7 @@ RUN curl -sSL https://github.com/Kitware/CMake/releases/download/v3.10.0/cmake-3 && make install ############################################################################### -# Install OpenSSL 1.1.1 +# Install OpenSSL 3.0.8 ############################################################################### WORKDIR /tmp RUN wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ @@ -59,9 +59,9 @@ RUN wget https://dist.opendnssec.org/source/softhsm-2.3.0.tar.gz \ # Clone and build Google Test ############################################################################### WORKDIR /tmp -RUN curl -sSL https://github.com/google/googletest/archive/release-1.11.0.tar.gz -o release-1.11.0.tar.gz \ - && tar xf release-1.11.0.tar.gz \ - && cd googletest-release-1.11.0 \ +RUN curl -sSL https://github.com/google/googletest/archive/release-1.12.0.tar.gz -o release-1.12.0.tar.gz \ + && tar xf release-1.12.0.tar.gz \ + && cd googletest-release-1.12.0 \ && cmake -DBUILD_SHARED_LIBS=ON . \ && make \ && cp -a googletest/include/gtest /usr/include/ \ @@ -100,7 +100,7 @@ RUN mkdir sdk-cpp-workspace \ && cd sdk-cpp-workspace \ && git clone https://github.com/aws/aws-iot-device-sdk-cpp-v2.git \ && cd aws-iot-device-sdk-cpp-v2 \ - && git checkout ac3ba3774b031dde1b988e698880d6064d53b9d9 \ + && git checkout 74c8b683ebe5b1cbf484f6acaa281f56aaa63948 \ && git submodule update --init --recursive \ && cd .. \ && mkdir aws-iot-device-sdk-cpp-v2-build \ @@ -130,4 +130,4 @@ RUN mkdir -p /root/aws-iot-device-client/build \ && cmake .. \ && cmake --build . --target aws-iot-device-client -ENTRYPOINT ["/root/aws-iot-device-client/build/aws-iot-device-client"] \ No newline at end of file +ENTRYPOINT ["/root/aws-iot-device-client/build/aws-iot-device-client"] diff --git a/.github/docker-images/base-images/device-client/ubuntu/Dockerfile b/.github/docker-images/base-images/device-client/ubuntu/Dockerfile index abf3df6a5..b01eb9ca2 100644 --- a/.github/docker-images/base-images/device-client/ubuntu/Dockerfile +++ b/.github/docker-images/base-images/device-client/ubuntu/Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu:18.04 AS base ENV DEBIAN_FRONTEND=noninteractive -ARG OPENSSL_VERSION=1.1.1n +ARG OPENSSL_VERSION=3.0.8 ############################################################################### # Install prereqs @@ -20,7 +20,7 @@ RUN apt-get update -qq \ && apt-get clean ############################################################################### -# Install OpenSSL 1.1.1 +# Install OpenSSL 3.0.8 ############################################################################### WORKDIR /tmp RUN wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ @@ -46,9 +46,9 @@ RUN curl -sSL https://github.com/Kitware/CMake/releases/download/v3.10.0/cmake-3 # Clone and build Google Test ############################################################################### WORKDIR /tmp -RUN wget --ca-certificate=/etc/ssl/certs/ca-certificates.crt https://github.com/google/googletest/archive/release-1.11.0.tar.gz \ - && tar xf release-1.11.0.tar.gz \ - && cd googletest-release-1.11.0 \ +RUN wget --ca-certificate=/etc/ssl/certs/ca-certificates.crt https://github.com/google/googletest/archive/release-1.12.0.tar.gz \ + && tar xf release-1.12.0.tar.gz \ + && cd googletest-release-1.12.0 \ && cmake -DBUILD_SHARED_LIBS=ON . \ && make \ && cp -a googletest/include/gtest /usr/include/ \ @@ -86,7 +86,7 @@ RUN mkdir sdk-cpp-workspace \ && cd sdk-cpp-workspace \ && git clone https://github.com/aws/aws-iot-device-sdk-cpp-v2.git \ && cd aws-iot-device-sdk-cpp-v2 \ - && git checkout ac3ba3774b031dde1b988e698880d6064d53b9d9 \ + && git checkout 74c8b683ebe5b1cbf484f6acaa281f56aaa63948 \ && git submodule update --init --recursive \ && cd .. \ && mkdir aws-iot-device-sdk-cpp-v2-build \ @@ -116,4 +116,4 @@ RUN mkdir -p /root/aws-iot-device-client/build \ && cmake .. \ && cmake --build . --target aws-iot-device-client -ENTRYPOINT ["/root/aws-iot-device-client/build/aws-iot-device-client"] \ No newline at end of file +ENTRYPOINT ["/root/aws-iot-device-client/build/aws-iot-device-client"] diff --git a/.github/docker-images/integration-tests/ubuntu/Dockerfile b/.github/docker-images/integration-tests/ubuntu/Dockerfile index 85c2e789b..b72fb3e40 100644 --- a/.github/docker-images/integration-tests/ubuntu/Dockerfile +++ b/.github/docker-images/integration-tests/ubuntu/Dockerfile @@ -14,17 +14,17 @@ RUN apt update && apt upgrade -y && \ RUN mkdir /home/dependencies WORKDIR /home/dependencies -RUN wget https://www.zlib.net/zlib-1.2.13.tar.gz -O /tmp/zlib-1.2.13.tar.gz && \ - tar xzvf /tmp/zlib-1.2.13.tar.gz && \ - cd zlib-1.2.13 && \ +RUN wget https://www.zlib.net/zlib-1.3.tar.gz -O /tmp/zlib-1.3.tar.gz && \ + tar xzvf /tmp/zlib-1.3.tar.gz && \ + cd zlib-1.3 && \ ./configure && \ make && \ make install && \ cd /home/dependencies -RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.gz -O /tmp/boost.tar.gz && \ +RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.gz -O /tmp/boost.tar.gz && \ tar xzvf /tmp/boost.tar.gz && \ - cd boost_1_79_0 && \ + cd boost_1_81_0 && \ ./bootstrap.sh && \ ./b2 install link=static && \ cd /home/dependencies @@ -39,14 +39,6 @@ RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v3.17.3/p make install && \ cd /home/dependencies -RUN git clone https://github.com/openssl/openssl.git && \ - cd openssl && \ - git checkout OpenSSL_1_1_1-stable && \ - ./config && \ - make depend && \ - make all && \ - cd /home/dependencies - RUN git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git && \ cd Catch2 && \ mkdir build && \ @@ -58,7 +50,7 @@ RUN git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git && \ RUN git clone https://github.com/aws-samples/aws-iot-securetunneling-localproxy && \ cd aws-iot-securetunneling-localproxy && \ - git checkout 851de4cc2b48861b835327d005000c7d0c81d11b && \ + git checkout d3150e0ebc4ef022939deb1ab43de005254f5751 && \ mkdir build && \ cd build && \ cmake ../ && \ diff --git a/.github/docker-images/oss-compliance/build-from-source-packages/build-from-source-package-licenses-ubi8.txt b/.github/docker-images/oss-compliance/build-from-source-packages/build-from-source-package-licenses-ubi8.txt index ed47595f5..0cc64d0b0 100644 --- a/.github/docker-images/oss-compliance/build-from-source-packages/build-from-source-package-licenses-ubi8.txt +++ b/.github/docker-images/oss-compliance/build-from-source-packages/build-from-source-package-licenses-ubi8.txt @@ -377,7 +377,7 @@ Public License instead of this License. ------ -** Google Test 1.10.0; version 1.10.0 -- https://github.com/google/googletest/blob/v1.10.x/LICENSE +** Google Test 1.12.0; version 1.12.0 -- https://github.com/google/googletest/blob/v1.12.x/LICENSE Copyright 2008, Google Inc. All rights reserved. diff --git a/.github/docker-images/oss-compliance/build-from-source-packages/build-from-source-package-licenses.txt b/.github/docker-images/oss-compliance/build-from-source-packages/build-from-source-package-licenses.txt index 750f986c8..d1457f170 100644 --- a/.github/docker-images/oss-compliance/build-from-source-packages/build-from-source-package-licenses.txt +++ b/.github/docker-images/oss-compliance/build-from-source-packages/build-from-source-package-licenses.txt @@ -343,7 +343,7 @@ Public License instead of this License. ------ -** Google Test 1.10.0; version 1.10.0 -- https://github.com/google/googletest/blob/v1.10.x/LICENSE +** Google Test 1.12.0; version 1.12.0 -- https://github.com/google/googletest/blob/v1.12.x/LICENSE Copyright 2008, Google Inc. All rights reserved. diff --git a/.github/workflows/e2e-ci.yml b/.github/workflows/e2e-ci.yml index ad9376558..d7467e9c8 100644 --- a/.github/workflows/e2e-ci.yml +++ b/.github/workflows/e2e-ci.yml @@ -370,7 +370,7 @@ jobs: DEVICE_KEY_SECRET: ${{ secrets.FP_DEVICE_KEY_SECRET }} AMAZON_ROOT_CA: ${{ secrets.AMAZON_ROOT_CA }} run: | - docker run -e AWS_ACCESS_KEY_ID="$(echo ${{ secrets.INTEG_USER_KEY_ID }})" -e AWS_SECRET_ACCESS_KEY="$(echo ${{ secrets.INTEG_USER_KEY_SECRET }})" -e IOT_ENDPOINT="$(echo $IOT_ENDPOINT)" -e CERTIFICATE="$(echo $CERTIFICATE)" -e DEVICE_KEY_SECRET="$(echo $DEVICE_KEY_SECRET)" -e AMAZON_ROOT_CA="$(echo $AMAZON_ROOT_CA)" -e THING_NAME=fleetprovisioning ${{ steps.build-test-runner.outputs.imageid }} --clean-up + docker run -e AWS_ACCESS_KEY_ID="$(echo ${{ secrets.INTEG_USER_KEY_ID }})" -e AWS_SECRET_ACCESS_KEY="$(echo ${{ secrets.INTEG_USER_KEY_SECRET }})" -e IOT_ENDPOINT="$(echo $IOT_ENDPOINT)" -e CERTIFICATE="$(echo $CERTIFICATE)" -e DEVICE_KEY_SECRET="$(echo $DEVICE_KEY_SECRET)" -e AMAZON_ROOT_CA="$(echo $AMAZON_ROOT_CA)" -e THING_NAME=fleetprovisioning ${{ steps.build-test-runner.outputs.imageid }} --skip-st --clean-up e2e-tests-ubuntu-aarch64: runs-on: ubuntu-latest if: ${{ false }} # Disabled for now. aarch64 local proxy build takes too long diff --git a/CMakeLists.txt.awssdk b/CMakeLists.txt.awssdk index c1dbc21be..f5d161d0f 100644 --- a/CMakeLists.txt.awssdk +++ b/CMakeLists.txt.awssdk @@ -5,7 +5,7 @@ project(aws-iot-device-sdk-cpp-v2-download NONE) include(ExternalProject) ExternalProject_Add(aws-iot-device-sdk-cpp-v2 GIT_REPOSITORY https://github.com/aws/aws-iot-device-sdk-cpp-v2.git - GIT_TAG ac3ba3774b031dde1b988e698880d6064d53b9d9 + GIT_TAG 74c8b683ebe5b1cbf484f6acaa281f56aaa63948 SOURCE_DIR "${CMAKE_BINARY_DIR}/aws-iot-device-sdk-cpp-v2-src" BINARY_DIR "${CMAKE_BINARY_DIR}/aws-iot-device-sdk-cpp-v2-build" CONFIGURE_COMMAND "" diff --git a/CMakeLists.txt.gtest b/CMakeLists.txt.gtest index cae958444..341249e80 100644 --- a/CMakeLists.txt.gtest +++ b/CMakeLists.txt.gtest @@ -5,7 +5,7 @@ project(googletest-download NONE) include(ExternalProject) ExternalProject_Add(googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.10.0 + GIT_TAG release-1.12.0 SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" CONFIGURE_COMMAND "" diff --git a/README.md b/README.md index 70e3be68c..dd7ead709 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ The AWS IoT Device Client is currently compatible with x86_64, aarch64, armv7l, * C++ 11 or higher * [CMake](https://cmake.org/) 3.10+ -* OpenSSL 1.1.1 +* OpenSSL 3.0.0+ * [aws-iot-device-sdk-cpp-v2](https://github.com/aws/aws-iot-device-sdk-cpp-v2) commit hash located in `CMakeLists.txt.awssdk` *Note:* The TLS stack, and the version of the SDK mentioned above is what our CI uses. You could potentially use a different TLS stack for example, we just don't actively test or support this. diff --git a/docker-build.sh b/docker-build.sh index 6ebcd55fa..2c8e40edb 100755 --- a/docker-build.sh +++ b/docker-build.sh @@ -2,4 +2,4 @@ # Defaults to ubuntu (18.04). Other options are amazonlinux and ubi8 os=${1:-"ubuntu"} -docker build . --file .github/docker-images/base-images/"$os"/Dockerfile \ No newline at end of file +docker build . --file .github/docker-images/base-images/device-client/"$os"/Dockerfile diff --git a/integration-tests/CMakeLists.txt.gtest b/integration-tests/CMakeLists.txt.gtest index 1e6307831..becd6bd68 100644 --- a/integration-tests/CMakeLists.txt.gtest +++ b/integration-tests/CMakeLists.txt.gtest @@ -5,7 +5,7 @@ project(googletest-download NONE) include(ExternalProject) ExternalProject_Add(googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.11.0 + GIT_TAG release-1.12.0 SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" CMAKE_ARGS -DCMAKE_BUILD_TYPE=Debug diff --git a/integration-tests/source/GTestMain.cpp b/integration-tests/source/GTestMain.cpp index ac4709ab1..a67f6f51f 100644 --- a/integration-tests/source/GTestMain.cpp +++ b/integration-tests/source/GTestMain.cpp @@ -104,7 +104,7 @@ bool parseCliArgs(int argc, char **argv) } else if (currentArg == CLI_CLEAN_UP) { - CLEAN_UP = true; + CLEAN_UP = false; } else { @@ -185,4 +185,4 @@ int main(int argc, char **argv) printf("Tests Complete!\n"); Aws::ShutdownAPI(options); return rc; -} \ No newline at end of file +} diff --git a/source/SharedCrtResourceManager.cpp b/source/SharedCrtResourceManager.cpp index b74e0640d..115a18630 100644 --- a/source/SharedCrtResourceManager.cpp +++ b/source/SharedCrtResourceManager.cpp @@ -39,11 +39,31 @@ bool SharedCrtResourceManager::initialize( std::shared_ptr featureRegistry) { features = featureRegistry; - initializeAllocator(config); initialized = buildClient(config) == SharedCrtResourceManager::SUCCESS; return initialized; } +void SharedCrtResourceManager::loadMemTraceLevelFromEnvironment() +{ + const char *memTraceLevelStr = std::getenv("AWS_CRT_MEMORY_TRACING"); + if (memTraceLevelStr) + { + switch (atoi(memTraceLevelStr)) + { + case AWS_MEMTRACE_BYTES: + LOG_DEBUG(Config::TAG, "Set AWS_CRT_MEMORY_TRACING=AWS_MEMTRACE_BYTES"); + memTraceLevel = AWS_MEMTRACE_BYTES; + break; + case AWS_MEMTRACE_STACKS: + LOG_DEBUG(Config::TAG, "Set AWS_CRT_MEMORY_TRACING=AWS_MEMTRACE_STACKS"); + memTraceLevel = AWS_MEMTRACE_STACKS; + break; + default: + break; + } + } +} + bool SharedCrtResourceManager::locateCredentials(const PlainConfig &config) const { struct stat fileInfo; @@ -174,22 +194,24 @@ bool SharedCrtResourceManager::setupLogging(const PlainConfig &config) const return true; } -void SharedCrtResourceManager::initializeAllocator(const PlainConfig &config) +void SharedCrtResourceManager::initializeAllocator() { + loadMemTraceLevelFromEnvironment(); allocator = aws_default_allocator(); - memTraceLevel = config.memTraceLevel; + if (memTraceLevel != AWS_MEMTRACE_NONE) { // If memTraceLevel == AWS_MEMTRACE_STACKS(2), then by default 8 frames per stack are used. allocator = aws_mem_tracer_new(allocator, nullptr, memTraceLevel, 0); } -} -int SharedCrtResourceManager::buildClient(const PlainConfig &config) -{ // We MUST declare an instance of the ApiHandle to perform global initialization // of the SDK libraries apiHandle = unique_ptr(new ApiHandle()); +} + +int SharedCrtResourceManager::buildClient(const PlainConfig &config) +{ if (config.logConfig.sdkLoggingEnabled) { if (!setupLogging(config)) @@ -318,12 +340,13 @@ int SharedCrtResourceManager::establishConnection(const PlainConfig &config) { proxyOptions.HostName = proxyConfig.proxyHost->c_str(); proxyOptions.Port = proxyConfig.proxyPort.value(); + proxyOptions.ProxyConnectionType = Aws::Crt::Http::AwsHttpProxyConnectionType::Tunneling; LOGM_INFO( TAG, "Attempting to establish MQTT connection with proxy: %s:%u", - proxyConfig.proxyHost->c_str(), - proxyConfig.proxyPort.value()); + proxyOptions.HostName.c_str(), + proxyOptions.Port); if (proxyConfig.httpProxyAuthEnabled) { @@ -516,6 +539,11 @@ Aws::Crt::Io::ClientBootstrap *SharedCrtResourceManager::getClientBootstrap() void SharedCrtResourceManager::disconnect() { LOG_DEBUG(TAG, "Attempting to disconnect MQTT connection"); + if (connection == NULL) + { + return; + } + if (connection->Disconnect()) { if (connectionClosedPromise.get_future().wait_for(std::chrono::seconds(DEFAULT_WAIT_TIME_SECONDS)) == diff --git a/source/SharedCrtResourceManager.h b/source/SharedCrtResourceManager.h index a2ada4025..4b1f1df0b 100644 --- a/source/SharedCrtResourceManager.h +++ b/source/SharedCrtResourceManager.h @@ -49,7 +49,7 @@ namespace Aws int buildClient(const PlainConfig &config); - void initializeAllocator(const PlainConfig &config); + void loadMemTraceLevelFromEnvironment(); protected: /** @@ -58,7 +58,7 @@ namespace Aws bool locateCredentials(const PlainConfig &config) const; public: - SharedCrtResourceManager() = default; + SharedCrtResourceManager() {} virtual ~SharedCrtResourceManager(); @@ -80,6 +80,8 @@ namespace Aws bool initialize(const PlainConfig &config, std::shared_ptr featureRegistry); + void initializeAllocator(); + void initializeAWSHttpLib(); int establishConnection(const PlainConfig &config); diff --git a/source/config/Config.cpp b/source/config/Config.cpp index 4d637720f..279c7b834 100644 --- a/source/config/Config.cpp +++ b/source/config/Config.cpp @@ -17,6 +17,7 @@ #endif +#include "../SharedCrtResourceManager.h" #include "../util/FileUtils.h" #include "../util/MqttUtils.h" #include "../util/ProxyUtils.h" @@ -289,24 +290,6 @@ bool PlainConfig::LoadFromCliArgs(const CliArgs &cliArgs) bool PlainConfig::LoadFromEnvironment() { - const char *memTraceLevelStr = std::getenv("AWS_CRT_MEMORY_TRACING"); - if (memTraceLevelStr) - { - switch (atoi(memTraceLevelStr)) - { - case AWS_MEMTRACE_BYTES: - LOG_DEBUG(Config::TAG, "Set AWS_CRT_MEMORY_TRACING=AWS_MEMTRACE_BYTES"); - memTraceLevel = AWS_MEMTRACE_BYTES; - break; - case AWS_MEMTRACE_STACKS: - LOG_DEBUG(Config::TAG, "Set AWS_CRT_MEMORY_TRACING=AWS_MEMTRACE_STACKS"); - memTraceLevel = AWS_MEMTRACE_STACKS; - break; - default: - break; - } - } - const char *lockFilePathIn = std::getenv("LOCK_FILE_PATH"); if (lockFilePathIn) { @@ -2641,6 +2624,14 @@ bool Config::ParseCliArgs(int argc, char **argv, CliArgs &cliArgs) bool Config::init(const CliArgs &cliArgs) { +#if defined(EXCLUDE_JOBS) + config.jobs.enabled = false; +#endif + +#if defined(EXCLUDE_ST) + config.tunneling.enabled = false; +#endif + try { string filename = Config::DEFAULT_CONFIG_FILE; @@ -3171,4 +3162,4 @@ string Config::ExpandDefaultConfigDir(bool removeTrailingSeparator) return Util::TrimRightCopy(expandedConfigDir, string{Config::PATH_DIRECTORY_SEPARATOR}); } return expandedConfigDir; -} \ No newline at end of file +} diff --git a/source/config/Config.h b/source/config/Config.h index 56dc9beb7..5d13b468e 100644 --- a/source/config/Config.h +++ b/source/config/Config.h @@ -108,7 +108,6 @@ namespace Aws Aws::Crt::Optional rootCa; Aws::Crt::Optional thingName; - aws_mem_trace_level memTraceLevel{AWS_MEMTRACE_NONE}; std::string lockFilePath{DEFAULT_LOCK_FILE_PATH}; struct LogConfig : public LoadableFromJsonAndCliAndEnvironment diff --git a/source/main.cpp b/source/main.cpp index 25b736c6f..eeecf125d 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -145,16 +145,19 @@ void shutdown() LOG_DEBUG(TAG, "Calling stop all"); features->stopAll(); } - resourceManager->dumpMemTrace(); LOG_INFO(TAG, "All features have stopped"); // terminate program #if !defined(DISABLE_MQTT) - resourceManager->disconnect(); + if (resourceManager != NULL) + { + resourceManager->dumpMemTrace(); + resourceManager->disconnect(); + resourceManager.reset(); + } #endif - LoggerFactory::getLoggerInstance().get()->shutdown(); - resourceManager.reset(); - exit(0); + LoggerFactory::getLoggerInstance()->shutdown(); + exit(EXIT_SUCCESS); } /** @@ -162,7 +165,7 @@ void shutdown() * * @param reason the reason why the abort is happening */ -void deviceClientAbort(const string &reason) +void deviceClientAbort(const string &reason, int exitCode) { if (resourceManager != NULL) { @@ -172,7 +175,7 @@ void deviceClientAbort(const string &reason) LoggerFactory::getLoggerInstance()->shutdown(); cout << "AWS IoT Device Client must abort execution, reason: " << reason << endl; cout << "Please check the AWS IoT Device Client logs for more information" << endl; - exit(EXIT_FAILURE); + exit(exitCode); } void attemptConnection() @@ -190,7 +193,8 @@ void attemptConnection() "IoT credentials, " "configuration and/or certificate policy. ***", DC_FATAL_ERROR); - deviceClientAbort("Failed to establish MQTT connection due to credential/configuration error"); + deviceClientAbort( + "Failed to establish MQTT connection due to credential/configuration error", EXIT_FAILURE); return true; } else if (SharedCrtResourceManager::SUCCESS == connectionStatus) @@ -209,7 +213,7 @@ void attemptConnection() catch (const std::exception &e) { LOGM_ERROR(TAG, "Error attempting to connect: %s", e.what()); - deviceClientAbort("Failure from attemptConnection"); + deviceClientAbort("Failure from attemptConnection", EXIT_FAILURE); } } @@ -279,7 +283,7 @@ namespace Aws TAG, "*** %s: Aborting program due to unrecoverable feature error! ***", DeviceClient::DC_FATAL_ERROR); - deviceClientAbort(feature->getName() + " encountered an error"); + deviceClientAbort(feature->getName() + " encountered an error", EXIT_FAILURE); #endif } }; @@ -289,19 +293,24 @@ namespace Aws int main(int argc, char *argv[]) { - CliArgs cliArgs; + if (Config::CheckTerminalArgs(argc, argv)) { LoggerFactory::getLoggerInstance()->shutdown(); return 0; } + + resourceManager = std::make_shared(); + resourceManager->initializeAllocator(); + + CliArgs cliArgs; if (!Config::ParseCliArgs(argc, argv, cliArgs) || !config.init(cliArgs)) { LOGM_ERROR( TAG, "*** %s: AWS IoT Device Client must abort execution, reason: Invalid configuration ***", DC_FATAL_ERROR); - deviceClientAbort("Invalid configuration"); + deviceClientAbort("Invalid configuration", EXIT_FAILURE); } if (!LoggerFactory::reconfigure(config.config) && @@ -330,7 +339,7 @@ int main(int argc, char *argv[]) if (!init(argc, argv)) { LOGM_ERROR(TAG, "*** %s: An instance of Device Client is already running.", DC_FATAL_ERROR); - deviceClientAbort("An instance of Device Client is already running."); + deviceClientAbort("An instance of Device Client is already running.", EXIT_FAILURE); } #endif @@ -344,15 +353,14 @@ int main(int argc, char *argv[]) int received_signal; sigaddset(&sigset, SIGINT); sigaddset(&sigset, SIGHUP); + sigaddset(&sigset, SIGTERM); sigprocmask(SIG_BLOCK, &sigset, nullptr); auto listener = std::make_shared(); - resourceManager = std::make_shared(); - if (!resourceManager.get()->initialize(config.config, features)) { LOGM_ERROR(TAG, "*** %s: Failed to initialize AWS CRT SDK.", DC_FATAL_ERROR); - deviceClientAbort("Failed to initialize AWS CRT SDK"); + deviceClientAbort("Failed to initialize AWS CRT SDK", EXIT_FAILURE); } #if !defined(EXCLUDE_FP) && !defined(DISABLE_MQTT) @@ -380,7 +388,7 @@ int main(int argc, char *argv[]) "Please verify your AWS IoT credentials, " "configuration, Fleet Provisioning Template, claim certificate and policy used. ***", DC_FATAL_ERROR); - deviceClientAbort("Fleet provisioning failed"); + deviceClientAbort("Fleet provisioning failed", EXIT_FAILURE); } resourceManager->disconnect(); } @@ -391,8 +399,10 @@ int main(int argc, char *argv[]) TAG, "*** %s: Fleet Provisioning configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); - deviceClientAbort("Invalid configuration. Fleet Provisioning configuration is enabled but feature is not " - "compiled into binary."); + deviceClientAbort( + "Invalid configuration. Fleet Provisioning configuration is enabled but feature is not " + "compiled into binary.", + EXIT_FAILURE); } #endif @@ -411,7 +421,7 @@ int main(int argc, char *argv[]) TAG, "*** %s: Secure Element configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); - deviceClientAbort("Invalid configuration"); + deviceClientAbort("Invalid configuration", EXIT_FAILURE); } else { @@ -425,7 +435,8 @@ int main(int argc, char *argv[]) "*** %s: Secure Element configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); deviceClientAbort( - "Invalid configuration. Secure Element configuration is enabled but feature is not compiled into binary."); + "Invalid configuration. Secure Element configuration is enabled but feature is not compiled into binary.", + EXIT_FAILURE); } #endif @@ -449,7 +460,7 @@ int main(int argc, char *argv[]) TAG, "*** %s: Config Shadow configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); - deviceClientAbort("Invalid configuration"); + deviceClientAbort("Invalid configuration", EXIT_FAILURE); } #endif @@ -473,7 +484,8 @@ int main(int argc, char *argv[]) LOGM_ERROR( TAG, "*** %s: Jobs configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); deviceClientAbort( - "Invalid configuration. Config Shadow configuration is enabled but feature is not compiled into binary."); + "Invalid configuration. Config Shadow configuration is enabled but feature is not compiled into binary.", + EXIT_FAILURE); } #endif @@ -498,8 +510,10 @@ int main(int argc, char *argv[]) TAG, "*** %s: Secure Tunneling configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); - deviceClientAbort("Invalid configuration. Secure Tunneling configuration is enabled but feature is not " - "compiled into binary."); + deviceClientAbort( + "Invalid configuration. Secure Tunneling configuration is enabled but feature is not " + "compiled into binary.", + EXIT_FAILURE); } #endif @@ -525,7 +539,8 @@ int main(int argc, char *argv[]) "*** %s: Device Defender configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); deviceClientAbort( - "Invalid configuration. Device Defender configuration is enabled but feature is not compiled into binary."); + "Invalid configuration. Device Defender configuration is enabled but feature is not compiled into binary.", + EXIT_FAILURE); } #endif @@ -551,7 +566,8 @@ int main(int argc, char *argv[]) "*** %s: Sample Shadow configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); deviceClientAbort( - "Invalid configuration. Sample Shadow configuration is enabled but feature is not compiled into binary."); + "Invalid configuration. Sample Shadow configuration is enabled but feature is not compiled into binary.", + EXIT_FAILURE); } #endif @@ -577,7 +593,8 @@ int main(int argc, char *argv[]) "*** %s: PubSub sample configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); deviceClientAbort( - "Invalid configuration. PubSub sample configuration is enabled but feature is not compiled into binary."); + "Invalid configuration. PubSub sample configuration is enabled but feature is not compiled into binary.", + EXIT_FAILURE); } #endif @@ -603,7 +620,8 @@ int main(int argc, char *argv[]) "*** %s: Sensor Publish configuration is enabled but feature is not compiled into binary.", DC_FATAL_ERROR); deviceClientAbort( - "Invalid configuration. Sensor Publish configuration is enabled but feature is not compiled into binary."); + "Invalid configuration. Sensor Publish configuration is enabled but feature is not compiled into binary.", + EXIT_FAILURE); } #endif diff --git a/source/tunneling/SecureTunnelWrapper.cpp b/source/tunneling/SecureTunnelWrapper.cpp index a7c8b3bc1..25ec1af23 100644 --- a/source/tunneling/SecureTunnelWrapper.cpp +++ b/source/tunneling/SecureTunnelWrapper.cpp @@ -40,6 +40,43 @@ SecureTunnelWrapper::SecureTunnelWrapper( onSessionReset)) { } + +SecureTunnelWrapper::SecureTunnelWrapper( + Aws::Crt::Allocator *allocator, + Aws::Crt::Io::ClientBootstrap *bootstrap, + const Aws::Crt::Io::SocketOptions &socketOptions, + const Aws::Crt::Http::HttpClientConnectionProxyOptions &proxyOptions, + const std::string &accessToken, + aws_secure_tunneling_local_proxy_mode localProxyMode, + const std::string &endpoint, + const std::string &rootCa, + const Aws::Iotsecuretunneling::OnConnectionComplete &onConnectionComplete, + const Aws::Iotsecuretunneling::OnConnectionShutdown &onConnectionShutdown, + const Aws::Iotsecuretunneling::OnSendDataComplete &onSendDataComplete, + const Aws::Iotsecuretunneling::OnDataReceive &onDataReceive, + const Aws::Iotsecuretunneling::OnStreamStart &onStreamStart, + const Aws::Iotsecuretunneling::OnStreamReset &onStreamReset, + const Aws::Iotsecuretunneling::OnSessionReset &onSessionReset) + : secureTunnel((Aws::Iotsecuretunneling::SecureTunnelBuilder( + allocator, + *bootstrap, + socketOptions, + accessToken, + localProxyMode, + endpoint)) + .WithHttpClientConnectionProxyOptions(proxyOptions) + .WithRootCa(rootCa) + .WithOnConnectionComplete(onConnectionComplete) + .WithOnConnectionShutdown(onConnectionShutdown) + .WithOnSendDataComplete(onSendDataComplete) + .WithOnDataReceive(onDataReceive) + .WithOnStreamStart(onStreamStart) + .WithOnStreamReset(onSessionReset) + .WithOnSessionReset(onSessionReset) + .Build()) +{ +} + int SecureTunnelWrapper::Connect() { return secureTunnel->Connect(); diff --git a/source/tunneling/SecureTunnelWrapper.h b/source/tunneling/SecureTunnelWrapper.h index af07c0714..babf0124b 100644 --- a/source/tunneling/SecureTunnelWrapper.h +++ b/source/tunneling/SecureTunnelWrapper.h @@ -19,10 +19,32 @@ namespace Aws public: SecureTunnelWrapper() = default; virtual ~SecureTunnelWrapper() = default; + + // Without HTTP Proxy + SecureTunnelWrapper( + Aws::Crt::Allocator *allocator, + Aws::Crt::Io::ClientBootstrap *clientBootstrap, + const Aws::Crt::Io::SocketOptions &socketOptions, + + const std::string &accessToken, + aws_secure_tunneling_local_proxy_mode localProxyMode, + const std::string &endpointHost, + const std::string &rootCa, + + const Aws::Iotsecuretunneling::OnConnectionComplete &onConnectionComplete, + const Aws::Iotsecuretunneling::OnConnectionShutdown &onConnectionShutdown, + const Aws::Iotsecuretunneling::OnSendDataComplete &onSendDataComplete, + const Aws::Iotsecuretunneling::OnDataReceive &onDataReceive, + const Aws::Iotsecuretunneling::OnStreamStart &onStreamStart, + const Aws::Iotsecuretunneling::OnStreamReset &onStreamReset, + const Aws::Iotsecuretunneling::OnSessionReset &onSessionReset); + + // With HTTP Proxy SecureTunnelWrapper( Aws::Crt::Allocator *allocator, Aws::Crt::Io::ClientBootstrap *clientBootstrap, const Aws::Crt::Io::SocketOptions &socketOptions, + const Aws::Crt::Http::HttpClientConnectionProxyOptions &proxyOptions, const std::string &accessToken, aws_secure_tunneling_local_proxy_mode localProxyMode, @@ -47,7 +69,7 @@ namespace Aws virtual bool IsValid(); - std::unique_ptr secureTunnel; + std::shared_ptr secureTunnel; private: /** diff --git a/source/tunneling/SecureTunnelingContext.cpp b/source/tunneling/SecureTunnelingContext.cpp index 15f91a83b..234e0f2e1 100644 --- a/source/tunneling/SecureTunnelingContext.cpp +++ b/source/tunneling/SecureTunnelingContext.cpp @@ -33,6 +33,20 @@ namespace Aws { } + SecureTunnelingContext::SecureTunnelingContext( + shared_ptr manager, + const Aws::Crt::Http::HttpClientConnectionProxyOptions &proxyOptions, + const Aws::Crt::Optional &rootCa, + const string &accessToken, + const string &endpoint, + const int port, + const OnConnectionShutdownFn &onConnectionShutdown) + : mSharedCrtResourceManager(manager), mProxyOptions(proxyOptions), + mRootCa(rootCa.has_value() ? rootCa.value() : ""), mAccessToken(accessToken), mEndpoint(endpoint), + mPort(port), mOnConnectionShutdown(onConnectionShutdown) + { + } + SecureTunnelingContext::~SecureTunnelingContext() { if (mSecureTunnel && mSecureTunnel->IsValid()) @@ -191,21 +205,44 @@ namespace Aws const Aws::Iotsecuretunneling::OnStreamReset &onStreamReset, const Aws::Iotsecuretunneling::OnSessionReset &onSessionReset) { - return std::make_shared( - mSharedCrtResourceManager->getAllocator(), - mSharedCrtResourceManager->getClientBootstrap(), - Crt::Io::SocketOptions(), - mAccessToken, - AWS_SECURE_TUNNELING_DESTINATION_MODE, - mEndpoint, - mRootCa, - onConnectionComplete, - onConnectionShutdown, - onSendDataComplete, - onDataReceive, - onStreamStart, - onStreamReset, - onSessionReset); + if (mProxyOptions.HostName.length() > 0) + { + LOGM_INFO(TAG, "Creating Secure Tunneling with proxy to: %s", mProxyOptions.HostName.c_str()); + return std::make_shared( + mSharedCrtResourceManager->getAllocator(), + mSharedCrtResourceManager->getClientBootstrap(), + Crt::Io::SocketOptions(), + mProxyOptions, + mAccessToken, + AWS_SECURE_TUNNELING_DESTINATION_MODE, + mEndpoint, + mRootCa, + onConnectionComplete, + nullptr, // TODO: long term fix needed for onConnectionShutdown callback + onSendDataComplete, + onDataReceive, + onStreamStart, + onStreamReset, + onSessionReset); + } + else + { + return std::make_shared( + mSharedCrtResourceManager->getAllocator(), + mSharedCrtResourceManager->getClientBootstrap(), + Crt::Io::SocketOptions(), + mAccessToken, + AWS_SECURE_TUNNELING_DESTINATION_MODE, + mEndpoint, + mRootCa, + onConnectionComplete, + nullptr, // TODO: long term fix needed for onConnectionShutdown callback + onSendDataComplete, + onDataReceive, + onStreamStart, + onStreamReset, + onSessionReset); + } } std::shared_ptr SecureTunnelingContext::CreateTcpForward() diff --git a/source/tunneling/SecureTunnelingContext.h b/source/tunneling/SecureTunnelingContext.h index d0aed1efa..dab946c01 100644 --- a/source/tunneling/SecureTunnelingContext.h +++ b/source/tunneling/SecureTunnelingContext.h @@ -47,6 +47,15 @@ namespace Aws const int port, const OnConnectionShutdownFn &onConnectionShutdown); + SecureTunnelingContext( + std::shared_ptr manager, + const Aws::Crt::Http::HttpClientConnectionProxyOptions &proxyOptions, + const Aws::Crt::Optional &rootCa, + const std::string &accessToken, + const std::string &endpoint, + const int port, + const OnConnectionShutdownFn &onConnectionShutdown); + /** * \brief Constructor */ @@ -178,6 +187,11 @@ namespace Aws */ std::shared_ptr mSharedCrtResourceManager; + /** + * \brief HTTP proxy strategy and auth config + */ + Aws::Crt::Http::HttpClientConnectionProxyOptions mProxyOptions; + /** * \brief Path to the Amazon root CA */ diff --git a/source/tunneling/SecureTunnelingFeature.cpp b/source/tunneling/SecureTunnelingFeature.cpp index 8aef2341f..6aaf57928 100644 --- a/source/tunneling/SecureTunnelingFeature.cpp +++ b/source/tunneling/SecureTunnelingFeature.cpp @@ -7,6 +7,7 @@ #include "TcpForward.h" #include #include +#include #include #include #include @@ -93,6 +94,38 @@ namespace Aws void SecureTunnelingFeature::LoadFromConfig(const PlainConfig &config) { + PlainConfig::HttpProxyConfig proxyConfig = config.httpProxyConfig; + + if (proxyConfig.httpProxyEnabled) + { + proxyOptions.HostName = proxyConfig.proxyHost->c_str(); + proxyOptions.Port = proxyConfig.proxyPort.value(); + proxyOptions.ProxyConnectionType = Aws::Crt::Http::AwsHttpProxyConnectionType::Tunneling; + + LOGM_INFO( + TAG, + "Attempting to establish tunneling connection with proxy: %s:%u", + proxyOptions.HostName.c_str(), + proxyOptions.Port); + + if (proxyConfig.httpProxyAuthEnabled) + { + LOG_INFO(TAG, "Proxy Authentication is enabled"); + Aws::Crt::Http::HttpProxyStrategyBasicAuthConfig basicAuthConfig; + basicAuthConfig.ConnectionType = Aws::Crt::Http::AwsHttpProxyConnectionType::Tunneling; + proxyOptions.AuthType = Aws::Crt::Http::AwsHttpProxyAuthenticationType::Basic; + basicAuthConfig.Username = proxyConfig.proxyUsername->c_str(); + basicAuthConfig.Password = proxyConfig.proxyPassword->c_str(); + proxyOptions.ProxyStrategy = + Aws::Crt::Http::HttpProxyStrategy::CreateBasicHttpProxyStrategy( + basicAuthConfig, Aws::Crt::g_allocator); + } + else + { + LOG_INFO(TAG, "Proxy Authentication is disabled"); + proxyOptions.AuthType = Aws::Crt::Http::AwsHttpProxyAuthenticationType::None; + } + } mThingName = *config.thingName; mRootCa = config.rootCa; mSubscribeNotification = config.tunneling.subscribeNotification; @@ -100,13 +133,10 @@ namespace Aws if (!config.tunneling.subscribeNotification) { - auto context = unique_ptr(new SecureTunnelingContext( - mSharedCrtResourceManager, - mRootCa, + auto context = createContext( *config.tunneling.destinationAccessToken, - GetEndpoint(*config.tunneling.region), - static_cast(config.tunneling.port.value()), - bind(&SecureTunnelingFeature::OnConnectionShutdown, this, placeholders::_1))); + *config.tunneling.region, + static_cast(config.tunneling.port.value())); mContexts.push_back(std::move(context)); } } @@ -256,6 +286,7 @@ namespace Aws { return std::unique_ptr(new SecureTunnelingContext( mSharedCrtResourceManager, + proxyOptions, mRootCa, accessToken, GetEndpoint(region), @@ -272,12 +303,16 @@ namespace Aws void SecureTunnelingFeature::OnConnectionShutdown(SecureTunnelingContext *contextToRemove) { LOG_DEBUG(TAG, "SecureTunnelingFeature::OnConnectionShutdown"); - auto it = find_if(mContexts.begin(), mContexts.end(), [&](const unique_ptr &c) { return c.get() == contextToRemove; }); mContexts.erase(std::remove(mContexts.begin(), mContexts.end(), *it)); + +#if defined(DISABLE_MQTT) + LOG_INFO(TAG, "Secure Tunnel closed, component cleaning up open thread"); + raise(SIGTERM); +#endif } } // namespace SecureTunneling diff --git a/source/tunneling/SecureTunnelingFeature.h b/source/tunneling/SecureTunnelingFeature.h index e7b855547..f07642c72 100644 --- a/source/tunneling/SecureTunnelingFeature.h +++ b/source/tunneling/SecureTunnelingFeature.h @@ -9,6 +9,7 @@ #include "../SharedCrtResourceManager.h" #include "IotSecureTunnelingClientWrapper.h" #include "SecureTunnelingContext.h" +#include "aws/crt/http/HttpProxyStrategy.h" #include #include @@ -177,6 +178,11 @@ namespace Aws */ std::shared_ptr mClientBaseNotifier; + /** + * \brief HTTP proxy strategy and auth config + */ + Aws::Crt::Http::HttpClientConnectionProxyOptions proxyOptions; + /** * \brief The ThingName to use */ diff --git a/source/util/MqttUtils.cpp b/source/util/MqttUtils.cpp index b1baf6bb4..57d3799de 100644 --- a/source/util/MqttUtils.cpp +++ b/source/util/MqttUtils.cpp @@ -24,17 +24,6 @@ bool MqttUtils::ValidateAwsIotMqttTopicName(std::string topic) topic = reserved_topic.suffix(); } - const std::size_t count_slashes = std::count(topic.cbegin(), topic.cend(), '/'); - if (count_slashes > MAX_NUMBER_OF_FORWARD_SLASHES) - { - LOGM_ERROR( - TAG, - "Number of forward slashes in topic (%lu) exceeds maximum (%lu)", - count_slashes, - MAX_NUMBER_OF_FORWARD_SLASHES); - return false; - } - // Since std::string is based on char, the size of the string and number of UTF8 chars is same. if (topic.size() > MAX_LENGTH_OF_TOPIC) { diff --git a/source/util/MqttUtils.h b/source/util/MqttUtils.h index 9e1e90fda..d1a354a69 100644 --- a/source/util/MqttUtils.h +++ b/source/util/MqttUtils.h @@ -18,15 +18,10 @@ namespace Aws // // https://docs.aws.amazon.com/general/latest/gr/iot-core.html#message-broker-limits // - // A topic in a publish or subscribe request can have no more than 7 forward slashes (/). - // This excludes the first 3 slashes in the mandatory segments for - // Basic Ingest topics ($AWS/rules/rule-name/). - // // The topic passed to AWS IoT Core when sending a publish request can be no larger // than 256 bytes of UTF-8 encoded characters. This excludes the first 3 mandatory // segments for Basic Ingest topics ($AWS/rules/rule-name/). // - static constexpr std::size_t MAX_NUMBER_OF_FORWARD_SLASHES{7}; static constexpr std::size_t MAX_LENGTH_OF_TOPIC{256}; /** diff --git a/test/config/TestConfig.cpp b/test/config/TestConfig.cpp index f9ecbdd1b..fee6b665f 100644 --- a/test/config/TestConfig.cpp +++ b/test/config/TestConfig.cpp @@ -1,6 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "../../source/SharedCrtResourceManager.h" #include "../../source/config/Config.h" #include "../../source/util/FileUtils.h" #include "../../source/util/UniqueString.h" @@ -33,9 +34,13 @@ class ConfigTestFixture : public ::testing::Test public: ConfigTestFixture() = default; string outputPath; + SharedCrtResourceManager resourceManager; void SetUp() override { + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + // Config::Validate will check that cert, key, and root-ca files exist. // Create a temporary file to use as a placeholder for this purpose. ofstream file(filePath, std::fstream::app); @@ -154,6 +159,7 @@ TEST_F(ConfigTestFixture, AllFeaturesEnabled) "secure-element-token-label": "token-label" } })"; + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -1310,41 +1316,6 @@ TEST_F(ConfigTestFixture, SensorPublishInvalidConfigMqttTopicEmpty) ASSERT_FALSE(settings.enabled); } -TEST_F(ConfigTestFixture, SensorPublishInvalidConfigMqttTopic) -{ - constexpr char jsonString[] = R"( -{ - "endpoint": "endpoint value", - "cert": "/tmp/aws-iot-device-client-test-file", - "root-ca": "/tmp/aws-iot-device-client-test/AmazonRootCA1.pem", - "key": "/tmp/aws-iot-device-client-test-file", - "thing-name": "thing-name value", - "sensor-publish": { - "sensors": [ - { - "addr": "/tmp/sensors/my-sensor-server", - "eom_delimiter": "[\r\n]+", - "mqtt_topic": "////////my-sensor-data" - } - ] - } -})"; - JsonObject jsonObject(jsonString); - JsonView jsonView = jsonObject.View(); - - PlainConfig config; - config.LoadFromJson(jsonView); - -#if defined(EXCLUDE_SENSOR_PUBLISH) - GTEST_SKIP(); -#endif - ASSERT_FALSE(config.Validate()); // Invalid mqtt_topic. - ASSERT_TRUE(config.sensorPublish.enabled); - ASSERT_EQ(config.sensorPublish.settings.size(), 1); - const auto &settings = config.sensorPublish.settings[0]; - ASSERT_FALSE(settings.enabled); -} - TEST_F(ConfigTestFixture, SensorPublishInvalidConfigEomDelimiter) { constexpr char jsonString[] = R"( @@ -1713,23 +1684,3 @@ TEST_F(ConfigTestFixture, HTTPProxyConfigNoAuth) ASSERT_FALSE(httpProxyConfig.httpProxyAuthEnabled); ASSERT_STREQ("None", httpProxyConfig.proxyAuthMethod->c_str()); } - -TEST(Config, MemoryTrace) -{ - PlainConfig config; - - // Test all permutations of memory trace set through the environment. - vector levels{ - AWS_MEMTRACE_NONE, - AWS_MEMTRACE_BYTES, - AWS_MEMTRACE_STACKS, - }; - - for (const auto &level : levels) - { - auto levelstr = std::to_string(level); - ::setenv("AWS_CRT_MEMORY_TRACING", levelstr.c_str(), 1); - ASSERT_TRUE(config.LoadFromEnvironment()) << "read AWS_CRT_MEMORY_TRACING=" << level; - ASSERT_EQ(config.memTraceLevel, level); - } -} diff --git a/test/config/TestConfigSerialization.cpp b/test/config/TestConfigSerialization.cpp index 9968d6259..c8e6b4fda 100644 --- a/test/config/TestConfigSerialization.cpp +++ b/test/config/TestConfigSerialization.cpp @@ -1,6 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "../../source/SharedCrtResourceManager.h" #include "../../source/config/Config.h" #include "../../source/util/FileUtils.h" #include "../../source/util/UniqueString.h" @@ -20,32 +21,9 @@ using namespace Aws::Crt; using namespace Aws::Iot::DeviceClient; using namespace Aws::Iot::DeviceClient::Util; -class SerializeConfigTestFixture : public ::testing::TestWithParam +TEST(SerializeConfigTestFixture, SerializeCompleteConfigTest) { - protected: - const char *jsonString; -}; - -TEST_P(SerializeConfigTestFixture, SerializeConfigTest) -{ - const char *jsonString = GetParam(); - PlainConfig config; - JsonObject jsonObject(jsonString); - config.LoadFromJson(jsonObject.View()); - auto inputJsonString = jsonObject.View().WriteCompact(); - - JsonObject serializedConfig; - config.SerializeToObject(serializedConfig); - auto serializedJsonString = serializedConfig.View().WriteCompact(); - - ASSERT_STREQ(inputJsonString.c_str(), serializedJsonString.c_str()); -} - -INSTANTIATE_TEST_CASE_P( - SerializationTests, - SerializeConfigTestFixture, - ::testing::Values( - R"( + constexpr char jsonString[] = R"( { "endpoint": "endpoint value", "cert": "/tmp/aws-iot-device-client-test-file", @@ -61,7 +39,7 @@ INSTANTIATE_TEST_CASE_P( }, "jobs": { "enabled": true, - "handler-directory": "directory" + "handler-directory": "directory" }, "tunneling": { "enabled": true @@ -138,8 +116,27 @@ INSTANTIATE_TEST_CASE_P( } ] } -})", - R"({ +})"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + PlainConfig config; + + JsonObject jsonObject(jsonString); + config.LoadFromJson(jsonObject.View()); + auto inputJsonString = jsonObject.View().WriteCompact(); + + JsonObject serializedConfig; + config.SerializeToObject(serializedConfig); + auto serializedJsonString = serializedConfig.View().WriteCompact(); + + ASSERT_STREQ(inputJsonString.c_str(), serializedJsonString.c_str()); +} + +TEST(SerializeConfigTestFixture, SerializeBasicConfigTest) +{ + constexpr char jsonString[] = R"( +{ "logging": { "level": "DEBUG", "type": "file", @@ -150,7 +147,7 @@ INSTANTIATE_TEST_CASE_P( }, "jobs": { "enabled": true, - "handler-directory": "" + "handler-directory": "" }, "tunneling": { "enabled": true @@ -166,17 +163,32 @@ INSTANTIATE_TEST_CASE_P( "completed-fp": false }, "samples": { - "pub-sub": { - "enabled": true - } - }, + "pub-sub": { + "enabled": true + } + }, "config-shadow": { "enabled": true - }, + }, "sample-shadow": { "enabled": true - }, + }, "secure-element": { "enabled": true - } -})")); + } +})"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + PlainConfig config; + + JsonObject jsonObject(jsonString); + config.LoadFromJson(jsonObject.View()); + auto inputJsonString = jsonObject.View().WriteCompact(); + + JsonObject serializedConfig; + config.SerializeToObject(serializedConfig); + auto serializedJsonString = serializedConfig.View().WriteCompact(); + + ASSERT_STREQ(inputJsonString.c_str(), serializedJsonString.c_str()); +} \ No newline at end of file diff --git a/test/devicedefender/TestDeviceDefender.cpp b/test/devicedefender/TestDeviceDefender.cpp index ab30c3c1d..e81d10867 100644 --- a/test/devicedefender/TestDeviceDefender.cpp +++ b/test/devicedefender/TestDeviceDefender.cpp @@ -85,6 +85,9 @@ class TestDeviceDefender : public testing::Test { deviceDefender = unique_ptr(new MockDDFeature()); manager = shared_ptr(new SharedCrtResourceManager()); + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + manager->initializeAllocator(); + notifier = shared_ptr(new MockNotifier()); task = shared_ptr(new MockReportTask()); config = getSimpleDDConfig(); diff --git a/test/fleetprovisioning/TestFleetProvisioning.cpp b/test/fleetprovisioning/TestFleetProvisioning.cpp index c013dcc20..74f7033cf 100644 --- a/test/fleetprovisioning/TestFleetProvisioning.cpp +++ b/test/fleetprovisioning/TestFleetProvisioning.cpp @@ -11,6 +11,7 @@ using namespace Aws::Iot::DeviceClient::FleetProvisioningNS; TEST(FleetProvisioning, EmptyTemplateParameters) { + Aws::Iot::DeviceClient::SharedCrtResourceManager resourceManager; Aws::Crt::Optional params; // start with empty value FleetProvisioning fp; ASSERT_TRUE(fp.MapParameters(params)); @@ -19,6 +20,10 @@ TEST(FleetProvisioning, EmptyTemplateParameters) TEST(FleetProvisioning, MalformedTemplateParameters) { + Aws::Iot::DeviceClient::SharedCrtResourceManager resourceManager; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + Aws::Crt::Optional params("{\"SerialNumber\" \"Device-SN\"}"); // test missing colon FleetProvisioning fp; ASSERT_FALSE(fp.MapParameters(params)); @@ -30,6 +35,10 @@ TEST(FleetProvisioning, MalformedTemplateParameters) TEST(FleetProvisioning, ValidTemplateParameters) { + Aws::Iot::DeviceClient::SharedCrtResourceManager resourceManager; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + Aws::Crt::Optional params("{\"SerialNumber\": \"Device-SN\"}"); // test single JSON property FleetProvisioning fp; ASSERT_TRUE(fp.MapParameters(params)); diff --git a/test/jobs/TestJobDocument.cpp b/test/jobs/TestJobDocument.cpp index 674fbc203..4f12353d2 100644 --- a/test/jobs/TestJobDocument.cpp +++ b/test/jobs/TestJobDocument.cpp @@ -1,8 +1,10 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "../../source/SharedCrtResourceManager.h" #include "../../source/jobs/JobDocument.h" #include "../../source/util/UniqueString.h" + #include "gtest/gtest.h" #include #include @@ -171,6 +173,10 @@ TEST(JobDocument, SampleJobDocument) } })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -376,6 +382,10 @@ TEST(JobDocument, MissingRequiredFields) } })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -429,6 +439,10 @@ TEST(JobDocument, MinimumJobDocument) ] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -522,6 +536,10 @@ TEST(JobDocument, MissingRequiredFieldsValue) } })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -549,6 +567,10 @@ TEST(JobDocument, CommandFieldsIsEmpty) ] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -576,6 +598,10 @@ TEST(JobDocument, CommandContainsSpaceCharacters) ] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -603,6 +629,10 @@ TEST(JobDocument, SpaceCharactersContainedWithinFirstWordOfCommand) ] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -621,6 +651,10 @@ TEST(JobDocument, oldJobDocumentCompatibility) "path": "default" })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); diff --git a/test/jobs/TestJobsFeature.cpp b/test/jobs/TestJobsFeature.cpp index 1f04cc53f..38bdc95e1 100644 --- a/test/jobs/TestJobsFeature.cpp +++ b/test/jobs/TestJobsFeature.cpp @@ -258,6 +258,9 @@ class TestJobsFeature : public ::testing::Test public: void SetUp() { + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + ThingName = Aws::Crt::String("thing-name value"); notifier = shared_ptr(new MockNotifier()); config = getSimpleConfig(); @@ -269,6 +272,7 @@ class TestJobsFeature : public ::testing::Test } Aws::Crt::String ThingName; shared_ptr notifier; + SharedCrtResourceManager resourceManager; PlainConfig config; unique_ptr startNextJobExecutionResponse; unique_ptr jobsMock; diff --git a/test/shadow/TestConfigShadowFeature.cpp b/test/shadow/TestConfigShadowFeature.cpp index a465ec996..740f05d55 100644 --- a/test/shadow/TestConfigShadowFeature.cpp +++ b/test/shadow/TestConfigShadowFeature.cpp @@ -59,6 +59,10 @@ TEST(ConfigShadowFeature, resetClientConfigWithValidJSON) } })"; + SharedCrtResourceManager resourceManager; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + JsonObject oldJsonObject(oldJsonString); JsonView jsonView = oldJsonObject.View(); PlainConfig config; @@ -149,6 +153,9 @@ TEST(ConfigShadowFeature, resetClientConfigWithInvalidJSON) "shadow-output-file": "" } })"; + SharedCrtResourceManager resourceManager; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); JsonObject oldJsonObject(oldJsonString); JsonView jsonView = oldJsonObject.View(); diff --git a/test/tunneling/TestSecureTunnelingFeature.cpp b/test/tunneling/TestSecureTunnelingFeature.cpp index 6bae9f810..6aeaf880e 100644 --- a/test/tunneling/TestSecureTunnelingFeature.cpp +++ b/test/tunneling/TestSecureTunnelingFeature.cpp @@ -103,9 +103,12 @@ class TestSecureTunnelingFeature : public testing::Test public: void SetUp() override { + manager = shared_ptr(new SharedCrtResourceManager()); + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + manager->initializeAllocator(); + thingName = Aws::Crt::String("thing-name value"); secureTunnelingFeature = shared_ptr(new MockSecureTunnelingFeature()); - manager = shared_ptr(new SharedCrtResourceManager()); mockClient = shared_ptr(new MockIotSecureTunnelingClient()); notifier = shared_ptr(new MockNotifier()); fakeContext = unique_ptr(new FakeSecureTunnelContext()); diff --git a/test/util/TestMqttUtils.cpp b/test/util/TestMqttUtils.cpp index 5b0d6800a..caacf9a7f 100644 --- a/test/util/TestMqttUtils.cpp +++ b/test/util/TestMqttUtils.cpp @@ -27,21 +27,6 @@ TEST(MqttUtils, ReservedTopicValid) ASSERT_TRUE(MqttUtils::ValidateAwsIotMqttTopicName(topic)); } -TEST(MqttUtils, TopicNotValidExceedsMaxSlashes) -{ - std::string topic(MqttUtils::MAX_NUMBER_OF_FORWARD_SLASHES + 1, '/'); - - ASSERT_FALSE(MqttUtils::ValidateAwsIotMqttTopicName(topic)); -} - -TEST(MqttUtils, TopicValidExceedsMaxSlashesWithReservedTopic) -{ - std::string topic(RESERVED_TOPIC); - std::fill_n(std::back_inserter(topic), MqttUtils::MAX_NUMBER_OF_FORWARD_SLASHES, '/'); - - ASSERT_TRUE(MqttUtils::ValidateAwsIotMqttTopicName(topic)); -} - TEST(MqttUtils, TopicNotValidExceedsMaxLength) { std::string topic(MqttUtils::MAX_LENGTH_OF_TOPIC + 1, 'A'); diff --git a/test/util/TestSharedResourceManager.cpp b/test/util/TestSharedResourceManager.cpp index 25d1229c7..a5d3215b0 100644 --- a/test/util/TestSharedResourceManager.cpp +++ b/test/util/TestSharedResourceManager.cpp @@ -57,6 +57,9 @@ class SharedResourceManagerTest : public ::testing::Test void SetUp() override { + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + manager.initializeAllocator(); + // SharedCrtResourceManager::locateCredentials will check that cert, key files // have valid permissions. Create a temporary file to use as a placeholder for this purpose. FileUtils::CreateDirectoryWithPermissions(certDir.c_str(), 0700); @@ -150,4 +153,4 @@ TEST_F(SharedResourceManagerTest, badPermissionsDirectory) chmod(certDir.c_str(), 0777); ASSERT_FALSE(manager.locateCredentialsWrapper(config)); -} +} \ No newline at end of file diff --git a/test/util/TestStringUtils.cpp b/test/util/TestStringUtils.cpp index cc82c3991..ca6a70a87 100644 --- a/test/util/TestStringUtils.cpp +++ b/test/util/TestStringUtils.cpp @@ -1,8 +1,10 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "../../source/SharedCrtResourceManager.h" #include "../../source/config/Config.h" #include "../../source/util/StringUtils.h" + #include "gtest/gtest.h" #include @@ -65,6 +67,10 @@ TEST(StringUtils, leavesNewLineAndTabAlone) TEST(StringUtils, maptoString) { + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + Aws::Crt::Map map; map.insert(std::pair("a", "b")); map.insert(std::pair("c", "d")); @@ -130,6 +136,10 @@ TEST(StringUtils, ParseToStringVector) { "args": ["hello", "world"] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View();