From 9fbdb9c50e5bffe0e6d459dcfd299fe62fc154d0 Mon Sep 17 00:00:00 2001 From: Amit Sheth Date: Thu, 18 Jul 2024 17:16:24 +0530 Subject: [PATCH] examples: Removed OTA examples Older AWS OTA has now been replaced with newer, modular approach --- examples/ota/README.md | 5 + examples/ota/SecurityGuide.md | 170 -- examples/ota/ota_http/CMakeLists.txt | 22 - examples/ota/ota_http/README.md | 28 - examples/ota/ota_http/main/CMakeLists.txt | 16 - examples/ota/ota_http/main/FreeRTOSIPConfig.h | 318 --- examples/ota/ota_http/main/Kconfig.projbuild | 69 - examples/ota/ota_http/main/app_main.c | 54 - .../ota/ota_http/main/certs/aws_codesign.crt | 10 - examples/ota/ota_http/main/certs/client.crt | 1 - examples/ota/ota_http/main/certs/client.key | 1 - .../main/certs/http_root_cert_auth.crt | 20 - .../ota_http/main/certs/root_cert_auth.crt | 21 - examples/ota/ota_http/main/demo_config.h | 126 - .../ota/ota_http/main/http_demo_url_utils.c | 202 -- .../ota/ota_http/main/http_demo_url_utils.h | 105 - examples/ota/ota_http/main/idf_component.yml | 7 - .../ota_http/main/mqtt_subscription_manager.c | 218 -- .../ota_http/main/mqtt_subscription_manager.h | 143 - .../ota/ota_http/main/ota_demo_core_http.c | 2390 ----------------- examples/ota/ota_http/ota_http_demo.csv | 3 - examples/ota/ota_http/partitions_ota_http.csv | 9 - examples/ota/ota_http/sdkconfig.defaults | 21 - .../ota/ota_http/sdkconfig.defaults.esp32c2 | 21 - .../ota/ota_http/sdkconfig.defaults.esp32s2 | 21 - examples/ota/ota_mqtt/CMakeLists.txt | 20 - examples/ota/ota_mqtt/README.md | 28 - examples/ota/ota_mqtt/main/CMakeLists.txt | 15 - examples/ota/ota_mqtt/main/FreeRTOSIPConfig.h | 318 --- examples/ota/ota_mqtt/main/Kconfig.projbuild | 70 - examples/ota/ota_mqtt/main/app_main.c | 54 - .../ota/ota_mqtt/main/certs/aws_codesign.crt | 10 - examples/ota/ota_mqtt/main/certs/client.crt | 1 - examples/ota/ota_mqtt/main/certs/client.key | 1 - .../ota_mqtt/main/certs/root_cert_auth.crt | 21 - examples/ota/ota_mqtt/main/demo_config.h | 114 - examples/ota/ota_mqtt/main/idf_component.yml | 7 - .../ota_mqtt/main/mqtt_subscription_manager.c | 218 -- .../ota_mqtt/main/mqtt_subscription_manager.h | 143 - .../ota/ota_mqtt/main/ota_demo_core_mqtt.c | 1908 ------------- examples/ota/ota_mqtt/ota_mqtt_demo.csv | 3 - examples/ota/ota_mqtt/partitions_ota_mqtt.csv | 9 - examples/ota/ota_mqtt/sdkconfig.defaults | 21 - .../ota/ota_mqtt/sdkconfig.defaults.esp32c2 | 17 - .../ota/ota_mqtt/sdkconfig.defaults.esp32s2 | 17 - 45 files changed, 5 insertions(+), 6991 deletions(-) create mode 100644 examples/ota/README.md delete mode 100644 examples/ota/SecurityGuide.md delete mode 100644 examples/ota/ota_http/CMakeLists.txt delete mode 100644 examples/ota/ota_http/README.md delete mode 100644 examples/ota/ota_http/main/CMakeLists.txt delete mode 100644 examples/ota/ota_http/main/FreeRTOSIPConfig.h delete mode 100644 examples/ota/ota_http/main/Kconfig.projbuild delete mode 100644 examples/ota/ota_http/main/app_main.c delete mode 100644 examples/ota/ota_http/main/certs/aws_codesign.crt delete mode 100644 examples/ota/ota_http/main/certs/client.crt delete mode 100644 examples/ota/ota_http/main/certs/client.key delete mode 100644 examples/ota/ota_http/main/certs/http_root_cert_auth.crt delete mode 100644 examples/ota/ota_http/main/certs/root_cert_auth.crt delete mode 100644 examples/ota/ota_http/main/demo_config.h delete mode 100644 examples/ota/ota_http/main/http_demo_url_utils.c delete mode 100644 examples/ota/ota_http/main/http_demo_url_utils.h delete mode 100644 examples/ota/ota_http/main/idf_component.yml delete mode 100644 examples/ota/ota_http/main/mqtt_subscription_manager.c delete mode 100644 examples/ota/ota_http/main/mqtt_subscription_manager.h delete mode 100644 examples/ota/ota_http/main/ota_demo_core_http.c delete mode 100644 examples/ota/ota_http/ota_http_demo.csv delete mode 100644 examples/ota/ota_http/partitions_ota_http.csv delete mode 100644 examples/ota/ota_http/sdkconfig.defaults delete mode 100644 examples/ota/ota_http/sdkconfig.defaults.esp32c2 delete mode 100644 examples/ota/ota_http/sdkconfig.defaults.esp32s2 delete mode 100644 examples/ota/ota_mqtt/CMakeLists.txt delete mode 100644 examples/ota/ota_mqtt/README.md delete mode 100644 examples/ota/ota_mqtt/main/CMakeLists.txt delete mode 100644 examples/ota/ota_mqtt/main/FreeRTOSIPConfig.h delete mode 100644 examples/ota/ota_mqtt/main/Kconfig.projbuild delete mode 100644 examples/ota/ota_mqtt/main/app_main.c delete mode 100644 examples/ota/ota_mqtt/main/certs/aws_codesign.crt delete mode 100644 examples/ota/ota_mqtt/main/certs/client.crt delete mode 100644 examples/ota/ota_mqtt/main/certs/client.key delete mode 100644 examples/ota/ota_mqtt/main/certs/root_cert_auth.crt delete mode 100644 examples/ota/ota_mqtt/main/demo_config.h delete mode 100644 examples/ota/ota_mqtt/main/idf_component.yml delete mode 100644 examples/ota/ota_mqtt/main/mqtt_subscription_manager.c delete mode 100644 examples/ota/ota_mqtt/main/mqtt_subscription_manager.h delete mode 100644 examples/ota/ota_mqtt/main/ota_demo_core_mqtt.c delete mode 100644 examples/ota/ota_mqtt/ota_mqtt_demo.csv delete mode 100644 examples/ota/ota_mqtt/partitions_ota_mqtt.csv delete mode 100644 examples/ota/ota_mqtt/sdkconfig.defaults delete mode 100644 examples/ota/ota_mqtt/sdkconfig.defaults.esp32c2 delete mode 100644 examples/ota/ota_mqtt/sdkconfig.defaults.esp32s2 diff --git a/examples/ota/README.md b/examples/ota/README.md new file mode 100644 index 000000000..64b072087 --- /dev/null +++ b/examples/ota/README.md @@ -0,0 +1,5 @@ +The FreeRTOS 202406.01-LTS release uses the new and completely refactored 'Modular OTA' approach for Over the Air updates. +It makes use of the new [AWS IoT MQTT File Streams Library](https://github.com/espressif/esp-aws-iot/tree/master/libraries/aws-iot-core-mqtt-file-streams-embedded-c) for OTA application design. +More information about the approach can be found [here](https://www.freertos.org/freertos-core/over-the-air-updates/index.html#:~:text=OTA%20update%20provider.-,Modular%20OTA%20approach,-Modular%20OTA%20consists). + +Please refer to the [iot-reference example](https://github.com/FreeRTOS/iot-reference-esp32c3) for a production-ready starting point that uses this new approach. diff --git a/examples/ota/SecurityGuide.md b/examples/ota/SecurityGuide.md deleted file mode 100644 index 640c448f6..000000000 --- a/examples/ota/SecurityGuide.md +++ /dev/null @@ -1,170 +0,0 @@ -# Getting Started with Security Features - -## 1 Pre-requisites - -Once you have set up and run the OTA update examples successfully, you can follow the steps given in this guide to make use of the Security Features available on the Espressif chips for development and production scenarios. - -> **Note**: The guide and linked references are specific to the ESP32-C3. Please change the SoC in the documentation pointer to the one that you are using. - -## 2 Securing Device Identity - -Espressif provides `esp_secure_cert_mgr`, a simplified interface to access the PKI credentials of a device pre-provisioned with the Espressif Provisioning Service or provisioned by the user. -It provides the set of APIs that are required to access the contents of the `esp_secure_cert` partition. - -SoCs that are equipped with the Digital Signature Peripheral produce hardware accelerated digital signatures (with assistance of HMAC), without the private key being accessible by software. -This allows the private key to be kept securely on the device without anyone other than the device hardware being able to access it. -More details about the Digital Signature Peripheral can be found [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/ds.html). - -On SoCs without the digital signature peripheral (ESP32 and ESP32-C2), the private key must be protected by enabling secure boot and flash encryption after the `esp_secure_cert` partition is created and written. - -More information on the `esp_secure_cert_mgr` and the corresponding example application can be found [here](https://github.com/espressif/esp_secure_cert_mgr/). - -The tool to generate the `esp_secure_cert` partition and configure the digital signature peripheral on supported SoCs can be installed using: -```sh -pip install esp-secure-cert-tool -``` - -### Configuring esp-secure-cert-tool - -1) Generate Root CA and key pair: -```sh -openssl req -newkey rsa:2048 -nodes -keyout prvtkey.pem \ --x509 -days 3650 -out cacert.pem -subj "/CN=Test CA" -``` - -2) Generate client private key: -```sh -openssl genrsa -out client.key -``` - -3) Generate device cert: -```sh -openssl req -out client.csr -key client.key -new - -openssl x509 -req -days 365 -in client.csr -CA cacert.pem \ --CAkey prvtkey.pem -sha256 -CAcreateserial -out client.crt -``` - -In the next section, the script will generate a partition named `esp_secure_cert` on host machine, that contains the parameters required by the DS peripheral. -It automatically flashes the partition to the ESP platform which has been connected and specified by the port. - -The examples in this repository already include the APIs required to utilise the `esp_secure_cert` partition and fetch the `esp_secure_cert_mgr` component using [IDF Component Registry](https://components.espressif.com/components/espressif/esp_secure_cert_mgr) at build-time. -It can be enabled for any example for SoCs that have the digital signature peripheral by following the following steps, after the `esp_secure_cert` partition has been flashed: - 1. Enter the menuconfig - ```sh - idf.py menuconfig - ``` - 2. Go into the `Example Configuration` section. - 3. Go into `Choose PKI credentials access method` - 4. Choose `Use ESP Secure Certificate Manager` - 5. Go into `(Top)` -> `Component config` -> `ESP Secure Cert Manager` - 6. Choose `Enable DS peripheral support` - -### Securing Device Identity Workflows -
- Expand Development Workflow - - ### - In the development workflow, read protection for the eFuse key block in which the DS key is programmed is not enabled when configuring the DS peripheral. - This is done to allow flexibility during development. - - The following command shall generate a binary partition containing the PKI credentials stored in the TLV format: - ```sh - configure_esp_secure_cert.py -p (PORT) --keep_ds_data_on_host --efuse_key_id 1 \ - --ca-cert cacert.pem --device-cert client.crt --private-key client.key \ - --target_chip (TARGET_CHIP) --secure_cert_type cust_flash_tlv --configure_ds - ``` - If the DS Peripheral is disabled in the menuconfig, or if you are using this command for a non-DS SoC, please remove the `--configure_ds` argument from the command. -
- -
- Expand Production Workflow - - ### - It is recommended to use modules pre-provisioned with the Espressif Provisioning Service for production scenario, because use of the following workflow for production can still lead to security compromised devices, if the private key (which is available in plaintext on the host) gets compromised. - In the production workflow, the read protection for the eFuse key block in which the DS key is programmed is enabled. - ```sh - configure_esp_secure_cert.py -p (PORT) --keep_ds_data_on_host --efuse_key_id 1 \ - --ca-cert cacert.pem --device-cert client.crt --private-key client.key \ - --target_chip (TARGET_CHIP) --secure_cert_type cust_flash_tlv --configure_ds --production - ``` - If the DS Peripheral is disabled in the menuconfig, or if you are using this command for a non-DS SoC, please remove the `--configure_ds` argument from the command. - > **IMPORTANT**: For non-DS SoCs, you will need to enable flash encryption and secure boot, to protect the private key. - > The subsequent sections describe how this can be accomplished. -
- - -## 3 Enabling Flash Encryption - -Flash encryption is intended for encrypting the contents of the device's off-chip flash memory and thus provides the "confidentiality" aspect to the software or data stored in the flash memory. -Once this feature is enabled, firmware is flashed as plaintext, and then the data is encrypted in place on the first boot. -As a result, physical readout of flash will not be sufficient to recover most flash contents. - -More details on Flash Encryption for your SoC can be found [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/security/flash-encryption.html). - -### Flash Encryption Workflows -
- Expand Development Workflow - - ### - 1. Enter the menuconfig - ```sh - idf.py menuconfig - ``` - 2. Go into the `Security features` section and select `Enable flash encryption on boot`. - 3. Ensure that the usage mode is set to `Development (NOT SECURE)` (it will be selected by default) - > In the next step upon resetting, the partitions marked `encrypted`, partitions of "app" type, the firmware bootloader and the partition table will be encrypted. - 4. Rebuild, re-flash and reset the board (Can be accomplished in one go by doing `idf.py build flash monitor`) - 5. Watch the serial console output to verify that Flash Encryption is enabled, and no errors have occurred. - -
- -
- Expand Production Workflow - - ### - 1. Enter the menuconfig - ```sh - idf.py menuconfig - ``` - 2. Go into the `Security features` section and select `Enable flash encryption on boot`. - 3. Change usage mode to `Release`. - Setting the usage mode to `Release` ensures that all the eFuse bits that are recommended for production are set correctly. - > In the next step upon resetting, the partitions marked `encrypted`, partitions of "app" type, the firmware bootloader and the partition table will be encrypted. - 4. Rebuild, re-flash and reset the board (Can be accomplished in one go by doing `idf.py build flash monitor`) - 5. Watch the serial console output to verify that Flash Encryption is enabled, and no errors have occurred. - - More details on `Release mode` for your SoC can be found [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/security/flash-encryption.html#release-mode). -
- - -## 4 Enabling Secure Boot - -The Secure Boot feature ensures that only authenticated software can execute on the device. The secure boot process forms chain of trust by verifying all mutable software entities involved in the ESP-IDF boot process. Signature verification happens during both boot-up as well as OTA updates. - -There is no separate `Development Workflow` for Secure Boot. - -More details on Secure Boot can be found [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/security/secure-boot-v2.html). - -### Secure Boot Production Workflow -
- Expand Production Workflow - - ### - 1. Open the Project Configuration Menu, in "Security features" set "Enable hardware Secure Boot in bootloader" to enable Secure Boot. - 2. The "Secure Boot V2" option will be selected, and the "App Signing Scheme" would be set to RSA by default. - 3. Specify the path to Secure Boot signing key, relative to the project directory. - 4. The first time you run `idf.py build`, if the signing key is not found then an error message will be printed with a command to generate a signing key via `espsecure.py generate_signing_key`. - For production environments, it is recommended to generate the key pair using OpenSSL or another industry standard encryption program. - See the [Generating Secure Boot Signing Key](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/security/secure-boot-v2.html#secure-boot-v2-generate-key) page for your SoC for more details. - 5. Run `idf.py bootloader` to build a Secure Boot enabled bootloader. - The build output will include a prompt for a flashing command, using `esptool.py write_flash`. - 6. When you are ready to flash the bootloader, run the specified command (you must enter it yourself, this step is not performed by the build system) and then wait for flashing to complete. - 7. Run `idf.py flash` to build and flash the partition table and the just-built app image. - The app image will be signed using the signing key you generated in step 4. - 8. Reset the device, and it will boot the software bootloader you flashed which will enable Secure Boot on the chip, and then it verifies the app image signature and boots the app. - 9. Watch the serial console output to verify that Secure Boot is enabled, and no errors have occurred due to the build configuration. -
- -> **Note**: Since the AWS OTA library implements its own signature verification of the OTA payload (based on ECDSA), there is a double signature verification for the application that takes place during OTA update. -> After the OTA payload has been successfully downloaded, first the ECDSA signature (supplied by the `certs/aws_codesign.crt` file) is verified and then the Secure Boot V2 RSA signature gets verified. diff --git a/examples/ota/ota_http/CMakeLists.txt b/examples/ota/ota_http/CMakeLists.txt deleted file mode 100644 index 03e6e049e..000000000 --- a/examples/ota/ota_http/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/common_components/protocol_examples_common" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/aws-iot-core-mqtt-file-streams-embedded-c" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/coreHTTP" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/coreMQTT" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/coreJSON" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/corePKCS11" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/backoffAlgorithm" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/common/posix_compat" - ) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(ota_http) - -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/root_cert_auth.crt" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/client.crt" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/client.key" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/http_root_cert_auth.crt" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/aws_codesign.crt" TEXT) diff --git a/examples/ota/ota_http/README.md b/examples/ota/ota_http/README.md deleted file mode 100644 index 152efdf0c..000000000 --- a/examples/ota/ota_http/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Steps to run OTA over HTTP Demo - -1. Ensure that you have followed all the prerequisites for OTA Update from the [Amazon FreeRTOS Docs](https://docs.aws.amazon.com/freertos/latest/userguide/ota-prereqs.html). - -2. Create a code signing certificate for ESP32, as shown [here](https://docs.aws.amazon.com/freertos/latest/userguide/ota-code-sign-cert-esp.html). -Ensure that keep the `ecdsasigner.crt` file handy, it will be needed in subsequent steps. - -3. Grant access to code signing, for AWS IoT, as shown [here](https://docs.aws.amazon.com/freertos/latest/userguide/code-sign-policy.html). - -4. Now, to create an OTA update job, using the AWS IoT console, follow the steps mentioned [here](https://docs.aws.amazon.com/freertos/latest/userguide/ota-console-workflow.html). -For **"Path name of code signing certificate on device"**, put the following value: -``` -Code Verify Key -``` -This corresponds to `pkcs11configLABEL_CODE_VERIFICATION_KEY` in the `core_pkcs11_config.h` file. - -For **"Path name of file on device"**, put an arbitrary value such as: -``` -/ -``` - -5. Replace the contents of the file `main/certs/aws_codesign.crt` with the content from the file `ecdsasigner.crt` - -> The code-signing public key certificate will be used by the application binary i.e. the demo, to authenticate a binary that was downloaded for an update (this downloaded firmware would have been signed by the certificate's corresponding private key i.e. `ecdsasigner.key`). - -6. `idf.py menuconfig` and set MQTT endpoint. - -7. `idf.py build flash monitor` \ No newline at end of file diff --git a/examples/ota/ota_http/main/CMakeLists.txt b/examples/ota/ota_http/main/CMakeLists.txt deleted file mode 100644 index 0b9b533a2..000000000 --- a/examples/ota/ota_http/main/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(COMPONENT_SRCS - "app_main.c" - "ota_demo_core_http.c" - "http_demo_url_utils.c" - "mqtt_subscription_manager.c" - ) - -set(COMPONENT_ADD_INCLUDEDIRS - "." - "${PROJECT_DIR}/../../../libraries/common/logging/" - "${PROJECT_DIR}/../../../libraries/common/posix_compat/" - ) - -idf_component_register(SRCS "${COMPONENT_SRCS}" - INCLUDE_DIRS ${COMPONENT_ADD_INCLUDEDIRS} - ) \ No newline at end of file diff --git a/examples/ota/ota_http/main/FreeRTOSIPConfig.h b/examples/ota/ota_http/main/FreeRTOSIPConfig.h deleted file mode 100644 index 6eee3aff7..000000000 --- a/examples/ota/ota_http/main/FreeRTOSIPConfig.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * FreeRTOS Kernel V10.2.0 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://aws.amazon.com/freertos - * http://www.FreeRTOS.org - */ - - -/***************************************************************************** -* -* See the following URL for configuration information. -* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html -* -*****************************************************************************/ - -#ifndef FREERTOS_IP_CONFIG_H -#define FREERTOS_IP_CONFIG_H - -/* Prototype for the function used to print out. In this case it prints to the - * console before the network is connected then a UDP port after the network has - * connected. */ -extern void vLoggingPrintf( const char * pcFormatString, - ... ); - -/* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to - * 1 then FreeRTOS_debug_printf should be defined to the function used to print - * out the debugging messages. */ -#define ipconfigHAS_DEBUG_PRINTF 0 -#if ( ipconfigHAS_DEBUG_PRINTF == 1 ) - #define FreeRTOS_debug_printf( X ) configPRINTF( X ) -#endif - -/* Set to 1 to print out non debugging messages, for example the output of the - * FreeRTOS_netstat() command, and ping replies. If ipconfigHAS_PRINTF is set to 1 - * then FreeRTOS_printf should be set to the function used to print out the - * messages. */ -#define ipconfigHAS_PRINTF 1 -#if ( ipconfigHAS_PRINTF == 1 ) - #define FreeRTOS_printf( X ) configPRINTF( X ) - /* Allow monitoring the message queue of the IP-task. */ - #define ipconfigCHECK_IP_QUEUE_SPACE 1 -#endif - -/* Define the byte order of the target MCU (the MCU FreeRTOS+TCP is executing - * on). Valid options are pdFREERTOS_BIG_ENDIAN and pdFREERTOS_LITTLE_ENDIAN. */ -#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN - -/* If the network card/driver includes checksum offloading (IP/TCP/UDP checksums) - * then set ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to 1 to prevent the software - * stack repeating the checksum calculations. */ -#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 - -/* TX checksum offloading has NOT been implemented in the Wi-Fi of ESP32. */ -#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 0 - -/* Several API's will block until the result is known, or the action has been - * performed, for example FreeRTOS_send() and FreeRTOS_recv(). The timeouts can be - * set per socket, using setsockopt(). If not set, the times below will be - * used as defaults. */ -#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME ( 500 ) -#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME ( 500 ) - -/* Include support for DNS caching. For TCP, having a small DNS cache is very - * useful. When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low - * and also DNS may use small timeouts. If a DNS reply comes in after the DNS - * socket has been destroyed, the result will be stored into the cache. The next - * call to FreeRTOS_gethostbyname() will return immediately, without even creating - * a socket. - */ -#define ipconfigUSE_DNS_CACHE ( 1 ) -#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ( 6 ) -#define ipconfigDNS_REQUEST_ATTEMPTS ( 2 ) - -/* The IP stack executes it its own task (although any application task can make - * use of its services through the published sockets API). ipconfigUDP_TASK_PRIORITY - * sets the priority of the task that executes the IP stack. The priority is a - * standard FreeRTOS task priority so can take any value from 0 (the lowest - * priority) to (configMAX_PRIORITIES - 1) (the highest priority). - * configMAX_PRIORITIES is a standard FreeRTOS configuration parameter defined in - * FreeRTOSConfig.h, not FreeRTOSIPConfig.h. Consideration needs to be given as to - * the priority assigned to the task executing the IP stack relative to the - * priority assigned to tasks that use the IP stack. */ -#define ipconfigIP_TASK_PRIORITY ( configMAX_PRIORITIES - 7U ) - -/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP - * task. This setting is less important when the FreeRTOS Win32 simulator is used - * as the Win32 simulator only stores a fixed amount of information on the task - * stack. FreeRTOS includes optional stack overflow detection, see: - * http://www.freertos.org/Stacks-and-stack-overflow-checking.html. */ -#define ipconfigIP_TASK_STACK_SIZE_WORDS ( configMINIMAL_STACK_SIZE * 5U ) - -/* ipconfigRAND32() is called by the IP stack to generate random numbers for - * things such as a DHCP transaction number or initial sequence number. Random - * number generation is performed via this macro to allow applications to use their - * own random number generation method. For example, it might be possible to - * generate a random number by sampling noise on an analogue input. */ -extern uint32_t ulRand(); -#define ipconfigRAND32() ulRand() - -/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the - * network event hook at the appropriate times. If ipconfigUSE_NETWORK_EVENT_HOOK - * is not set to 1 then the network event hook will never be called. See: - * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml. - */ -#define ipconfigUSE_NETWORK_EVENT_HOOK 1 - -/* Sockets have a send block time attribute. If FreeRTOS_sendto() is called but - * a network buffer cannot be obtained then the calling task is held in the Blocked - * state (so other tasks can continue to executed) until either a network buffer - * becomes available or the send block time expires. If the send block time expires - * then the send operation is aborted. The maximum allowable send block time is - * capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS. Capping the - * maximum allowable send block time prevents prevents a deadlock occurring when - * all the network buffers are in use and the tasks that process (and subsequently - * free) the network buffers are themselves blocked waiting for a network buffer. - * ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks. A time in - * milliseconds can be converted to a time in ticks by dividing the time in - * milliseconds by portTICK_PERIOD_MS. */ -#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000U / portTICK_PERIOD_MS ) - -/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP - * address, netmask, DNS server address and gateway address from a DHCP server. If - * ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address. The - * stack will revert to using the static IP address even when ipconfigUSE_DHCP is - * set to 1 if a valid configuration cannot be obtained from a DHCP server for any - * reason. The static configuration used is that passed into the stack by the - * FreeRTOS_IPInit() function call. */ -#define ipconfigUSE_DHCP 1 -#define ipconfigDHCP_REGISTER_HOSTNAME 1 -#define ipconfigDHCP_USES_UNICAST 1 - -/* If ipconfigDHCP_USES_USER_HOOK is set to 1 then the application writer must - * provide an implementation of the DHCP callback function, - * xApplicationDHCPUserHook(). */ -#define ipconfigUSE_DHCP_HOOK 0 - -/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at - * increasing time intervals until either a reply is received from a DHCP server - * and accepted, or the interval between transmissions reaches - * ipconfigMAXIMUM_DISCOVER_TX_PERIOD. The IP stack will revert to using the - * static IP address passed as a parameter to FreeRTOS_IPInit() if the - * re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without - * a DHCP reply being received. */ -#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD \ - ( 120000U / portTICK_PERIOD_MS ) - -/* The ARP cache is a table that maps IP addresses to MAC addresses. The IP - * stack can only send a UDP message to a remove IP address if it knowns the MAC - * address associated with the IP address, or the MAC address of the router used to - * contact the remote IP address. When a UDP message is received from a remote IP - * address the MAC address and IP address are added to the ARP cache. When a UDP - * message is sent to a remote IP address that does not already appear in the ARP - * cache then the UDP message is replaced by a ARP message that solicits the - * required MAC address information. ipconfigARP_CACHE_ENTRIES defines the maximum - * number of entries that can exist in the ARP table at any one time. */ -#define ipconfigARP_CACHE_ENTRIES 6 - -/* ARP requests that do not result in an ARP response will be re-transmitted a - * maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is - * aborted. */ -#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 ) - -/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP - * table being created or refreshed and the entry being removed because it is stale. - * New ARP requests are sent for ARP cache entries that are nearing their maximum - * age. ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is - * equal to 1500 seconds (or 25 minutes). */ -#define ipconfigMAX_ARP_AGE 150 - -/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling - * routines, which are relatively large. To save code space the full - * FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster - * alternative called FreeRTOS_inet_addr_quick() is provided. FreeRTOS_inet_addr() - * takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter. - * FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets - * (for example, 192, 168, 0, 1) as its parameters. If - * ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and - * FreeRTOS_indet_addr_quick() are available. If ipconfigINCLUDE_FULL_INET_ADDR is - * not set to 1 then only FreeRTOS_indet_addr_quick() is available. */ -#define ipconfigINCLUDE_FULL_INET_ADDR 1 - -/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that - * are available to the IP stack. The total number of network buffers is limited - * to ensure the total amount of RAM that can be consumed by the IP stack is capped - * to a pre-determinable value. */ -#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 60U - -/* A FreeRTOS queue is used to send events from application tasks to the IP - * stack. ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can - * be queued for processing at any one time. The event queue must be a minimum of - * 5 greater than the total number of network buffers. */ -#define ipconfigEVENT_QUEUE_LENGTH \ - ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5U ) - -/* The address of a socket is the combination of its IP address and its port - * number. FreeRTOS_bind() is used to manually allocate a port number to a socket - * (to 'bind' the socket to a port), but manual binding is not normally necessary - * for client sockets (those sockets that initiate outgoing connections rather than - * wait for incoming connections on a known port number). If - * ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling - * FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP - * stack automatically binding the socket to a port number from the range - * socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff. If - * ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto() - * on a socket that has not yet been bound will result in the send operation being - * aborted. */ -#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1 - -/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */ -#define ipconfigUDP_TIME_TO_LIVE 128 -/* Also defined in FreeRTOSIPConfigDefaults.h. */ -#define ipconfigTCP_TIME_TO_LIVE 128 - -/* USE_TCP: Use TCP and all its features. */ -#define ipconfigUSE_TCP ( 1 ) - -/* USE_WIN: Let TCP use windowing mechanism. */ -#define ipconfigUSE_TCP_WIN ( 1 ) - -/* The MTU is the maximum number of bytes the payload of a network frame can - * contain. For normal Ethernet V2 frames the maximum MTU is 1500. Setting a - * lower value can save RAM. */ -#define ipconfigNETWORK_MTU 1460U - -/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver. DNS is used - * through the FreeRTOS_gethostbyname() API function. */ -#define ipconfigUSE_DNS 1 - -/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will - * generate replies to incoming ICMP echo (ping) requests. */ -#define ipconfigREPLY_TO_INCOMING_PINGS 1 - -/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the - * FreeRTOS_SendPingRequest() API function is available. */ -#define ipconfigSUPPORT_OUTGOING_PINGS 0 - -/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select() - * (and associated) API function is available. */ -#define ipconfigSUPPORT_SELECT_FUNCTION 0 - -/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames - * that are not in Ethernet II format will be dropped. This option is included for - * potential future IP stack developments. */ -#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1 - -/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the - * responsibility of the Ethernet interface to filter out packets that are of no - * interest. If the Ethernet interface does not implement this functionality, then - * set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack - * perform the filtering instead (it is much less efficient for the stack to do it - * because the packet will already have been passed into the stack). If the - * Ethernet driver does all the necessary filtering in hardware then software - * filtering can be removed by using a value other than 1 or 0. */ -#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 - -/* The windows simulator cannot really simulate MAC interrupts, and needs to - * block occasionally to allow other tasks to run. */ -#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 20 / portTICK_PERIOD_MS ) - -/* Advanced only: in order to access 32-bit fields in the IP packets with - * 32-bit memory instructions, all packets will be stored 32-bit-aligned, - * plus 16-bits. This has to do with the contents of the IP-packets: all - * 32-bit fields are 32-bit-aligned, plus 16-bit. */ -#define ipconfigPACKET_FILLER_SIZE 2U - -/* Define the size of the pool of TCP window descriptors. On the average, each - * TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6 - * outstanding packets (for Rx and Tx). When using up to 10 TP sockets - * simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */ -#define ipconfigTCP_WIN_SEG_COUNT 240 - -/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed - * maximum size. Define the size of Rx buffer for TCP sockets. */ -#define ipconfigTCP_RX_BUFFER_LENGTH ( 3000 ) - -/* Define the size of Tx buffer for TCP sockets. */ -#define ipconfigTCP_TX_BUFFER_LENGTH ( 3000 ) - -/* When using call-back handlers, the driver may check if the handler points to - * real program memory (RAM or flash) or just has a random non-zero value. */ -#define ipconfigIS_VALID_PROG_ADDRESS( x ) ( ( x ) != NULL ) - -/* Include support for TCP keep-alive messages. */ -#define ipconfigTCP_KEEP_ALIVE ( 1 ) -#define ipconfigTCP_KEEP_ALIVE_INTERVAL ( 20 ) /* Seconds. */ - -/* The socket semaphore is used to unblock the MQTT task. */ -#define ipconfigSOCKET_HAS_USER_SEMAPHORE ( 0 ) - -#define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK ( 1 ) -#define ipconfigUSE_CALLBACKS ( 0 ) - - -#define portINLINE __inline - -void vApplicationMQTTGetKeys( const char ** ppcRootCA, - const char ** ppcClientCert, - const char ** ppcClientPrivateKey ); - -#endif /* FREERTOS_IP_CONFIG_H */ diff --git a/examples/ota/ota_http/main/Kconfig.projbuild b/examples/ota/ota_http/main/Kconfig.projbuild deleted file mode 100644 index 53d44e88f..000000000 --- a/examples/ota/ota_http/main/Kconfig.projbuild +++ /dev/null @@ -1,69 +0,0 @@ -menu "Example Configuration" - - config MQTT_CLIENT_IDENTIFIER - string "The MQTT client identifier used in this example" - default "testClient" - help - The MQTT client identifier used in this example. Each client identifier must be unique. - so edit as required to ensure that no two clients connecting to the same broker use the same client identifier. - - config MQTT_BROKER_ENDPOINT - string "Endpoint of the MQTT broker to connect to" - default "test.mosquitto.org" - help - This example can be run with any MQTT broker, that supports server authentication. - - config MQTT_BROKER_PORT - int "Port of the MQTT broker use" - default 8883 - help - In general, port 8883 is for secured MQTT connections. - Port 443 requires use of the ALPN TLS extension with the ALPN protocol name. - When using port 8883, ALPN is not required. - - config HARDWARE_PLATFORM_NAME - string "The hardware platform" - default "ESP32" - help - The name of the hardware platform the application is running on. - - config MQTT_NETWORK_BUFFER_SIZE - int "Size of the network buffer for MQTT packets" - range 1024 2048 - default 1024 - help - Size of the network buffer for MQTT packets. - - choice EXAMPLE_CHOOSE_PKI_ACCESS_METHOD - prompt "Choose PKI credentials access method" - default EXAMPLE_USE_PLAIN_FLASH_STORAGE - help - ESP devices support multiple ways to secure store the PKI credentials. - Currently Secure Element (ATECC608A) and DS peripheral - (using ESP Secure Cert Manager) are supported. - The default behaviour is to access the PKI credentials which are embedded in the binary. - Consult the ESP-TLS documentation in ESP-IDF Programming guide for more details. - - - config EXAMPLE_USE_SECURE_ELEMENT - bool "Use secure element (ATECC608A)" - depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32C2) && ESP_TLS_USING_MBEDTLS - # To confirm that we are satisfying the dependencies of secure element - help - Enable the use of secure element for the example. - The esp-cryptoauthlib component is required for enabling - this option. - - config EXAMPLE_USE_ESP_SECURE_CERT_MGR - bool "Use ESP Secure Certificate Manager" - help - Enable the use of ESP Secure Certificate Manager APIs for the example. - Please refer to ESP Secure Certificate Manager documentation for more details. - - config EXAMPLE_USE_PLAIN_FLASH_STORAGE - bool "Use flash storage (default)" - help - This option expects the Private key and Device certificate to be embedded in the binary. - This is the default behaviour. - endchoice -endmenu diff --git a/examples/ota/ota_http/main/app_main.c b/examples/ota/ota_http/main/app_main.c deleted file mode 100644 index 93fc7ca4a..000000000 --- a/examples/ota/ota_http/main/app_main.c +++ /dev/null @@ -1,54 +0,0 @@ -/* ota_http example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -int aws_iot_demo_main( int argc, char ** argv ); - -#include "esp_log.h" - -static const char *TAG = "OTA_MQTT"; - -void app_main() -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %"PRIu32" bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - - /* Initialize NVS partition */ - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - /* NVS partition was truncated - * and needs to be erased */ - ESP_ERROR_CHECK(nvs_flash_erase()); - - /* Retry nvs_flash_init */ - ESP_ERROR_CHECK(nvs_flash_init()); - } - - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - aws_iot_demo_main(0,NULL); -} diff --git a/examples/ota/ota_http/main/certs/aws_codesign.crt b/examples/ota/ota_http/main/certs/aws_codesign.crt deleted file mode 100644 index fc9db06fb..000000000 --- a/examples/ota/ota_http/main/certs/aws_codesign.crt +++ /dev/null @@ -1,10 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBcDCCARagAwIBAgIUYNy4lAy9AREPtp+bBG0chiEDUQMwCgYIKoZIzj0EAwIw -JTEjMCEGA1UEAwwaZGhhdmFsLmd1amFyQGVzcHJlc3NpZi5jb20wHhcNMjEwNzA2 -MTI0MTA5WhcNMjIwNzA2MTI0MTA5WjAlMSMwIQYDVQQDDBpkaGF2YWwuZ3VqYXJA -ZXNwcmVzc2lmLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI/b7P+Y2c6f -PAD0fC2DCwaAUT/cplFr4AwyYjYk4qlAnBaEbltmukvZKIjkIct7sNEK0rbXSNf1 -/QHDWu2hqkmjJDAiMAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAK -BggqhkjOPQQDAgNIADBFAiEA6kjPuxXvyKEnavPC0R2B+uR3nTntrkiszXPuwbMA -CxICIGUnuxeOEx7SAT1O9G6b/k3oNxDf4xjzgHs7dcaSxwAo ------END CERTIFICATE----- diff --git a/examples/ota/ota_http/main/certs/client.crt b/examples/ota/ota_http/main/certs/client.crt deleted file mode 100644 index 6459f31e3..000000000 --- a/examples/ota/ota_http/main/certs/client.crt +++ /dev/null @@ -1 +0,0 @@ -Certificate goes here. \ No newline at end of file diff --git a/examples/ota/ota_http/main/certs/client.key b/examples/ota/ota_http/main/certs/client.key deleted file mode 100644 index f6ef61476..000000000 --- a/examples/ota/ota_http/main/certs/client.key +++ /dev/null @@ -1 +0,0 @@ -Key goes here. \ No newline at end of file diff --git a/examples/ota/ota_http/main/certs/http_root_cert_auth.crt b/examples/ota/ota_http/main/certs/http_root_cert_auth.crt deleted file mode 100644 index a6f3e92af..000000000 --- a/examples/ota/ota_http/main/certs/http_root_cert_auth.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/examples/ota/ota_http/main/certs/root_cert_auth.crt b/examples/ota/ota_http/main/certs/root_cert_auth.crt deleted file mode 100644 index 350356673..000000000 --- a/examples/ota/ota_http/main/certs/root_cert_auth.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- - diff --git a/examples/ota/ota_http/main/demo_config.h b/examples/ota/ota_http/main/demo_config.h deleted file mode 100644 index d139cb862..000000000 --- a/examples/ota/ota_http/main/demo_config.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202103.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef DEMO_CONFIG_H_ -#define DEMO_CONFIG_H_ - -/**************************************************/ -/******* DO NOT CHANGE the following order ********/ -/**************************************************/ - -/* Logging related header files are required to be included in the following order: - * 1. Include the header file "logging_levels.h". - * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. - * 3. Include the header file "logging_stack.h". - */ - -/* Include header that defines log levels. */ -#include "logging_levels.h" - -/* Logging configuration for the Demo. */ -#ifndef LIBRARY_LOG_NAME - #define LIBRARY_LOG_NAME "OTA_HTTP_DEMO" -#endif -#ifndef LIBRARY_LOG_LEVEL - #define LIBRARY_LOG_LEVEL LOG_INFO -#endif - -#include "logging_stack.h" - -/************ End of logging configuration ****************/ - -/** - * @brief Details of the MQTT broker to connect to. - * - * @note Your AWS IoT Core endpoint can be found in the AWS IoT console under - * Settings/Custom Endpoint, or using the describe-endpoint API. - * - */ -#define AWS_IOT_ENDPOINT CONFIG_MQTT_BROKER_ENDPOINT - -/** - * @brief AWS IoT MQTT broker port number. - * - * In general, port 8883 is for secured MQTT connections. - * - * @note Port 443 requires use of the ALPN TLS extension with the ALPN protocol - * name. When using port 8883, ALPN is not required. - */ -#define AWS_MQTT_PORT ( CONFIG_MQTT_BROKER_PORT ) - -/** - * @brief AWS IoT Core server port number for HTTPS connections. - * - * For this demo, an X.509 certificate is used to verify the client. - * - * @note Port 443 requires use of the ALPN TLS extension with the ALPN protocol - * name being x-amzn-http-ca. When using port 8443, ALPN is not required. - */ -#ifndef AWS_HTTPS_PORT - #define AWS_HTTPS_PORT 443 -#endif - -/** - * @brief MQTT client identifier. - * - * No two clients may use the same client identifier simultaneously. - */ -#ifndef CLIENT_IDENTIFIER - #define CLIENT_IDENTIFIER CONFIG_MQTT_CLIENT_IDENTIFIER -#endif - -/** - * @brief Configure application version. - */ - -#define APP_VERSION_MAJOR 0 -#define APP_VERSION_MINOR 9 -#define APP_VERSION_BUILD 2 - -/** - * @brief The name of the operating system that the application is running on. - * The current value is given as an example. Please update for your specific - * operating system. - */ -#define OS_NAME "FreeRTOS" - -/** - * @brief The version of the operating system that the application is running - * on. The current value is given as an example. Please update for your specific - * operating system version. - */ -#define OS_VERSION tskKERNEL_VERSION_NUMBER - -/** - * @brief The name of the hardware platform the application is running on. The - * current value is given as an example. Please update for your specific - * hardware platform. - */ -#define HARDWARE_PLATFORM_NAME CONFIG_HARDWARE_PLATFORM_NAME - -/** - * @brief The name of the library used and its version, following an "@" - * symbol. - */ -#define OTA_LIB "otalib@1.0.0" - -#endif /* ifndef DEMO_CONFIG_H */ diff --git a/examples/ota/ota_http/main/http_demo_url_utils.c b/examples/ota/ota_http/main/http_demo_url_utils.c deleted file mode 100644 index ca34d0c42..000000000 --- a/examples/ota/ota_http/main/http_demo_url_utils.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202108.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* Standard includes. */ -#include -#include -#include - -/* Include Demo Config as the first non-system header. */ -#include "demo_config.h" - -/* Demo utils header. */ -#include "http_demo_url_utils.h" - -/*-----------------------------------------------------------*/ - -/** - * @brief The separator between the "https" scheme and the host in a URL. - */ -#define SCHEME_SEPARATOR "://" - -/** - * @brief The length of the "://" separator. - */ -#define SCHEME_SEPARATOR_LEN ( sizeof( SCHEME_SEPARATOR ) - 1 ) - -/*-----------------------------------------------------------*/ - -HTTPStatus_t getUrlPath( const char * pUrl, - size_t urlLen, - const char ** pPath, - size_t * pPathLen ) -{ - HTTPStatus_t httpStatus = HTTPSuccess; - const char * pHostStart = NULL; - const char * pPathStart = NULL; - size_t hostLen = 0, i = 0, pathStartIndex = 0, pathLen = 0; - - if( ( pUrl == NULL ) || ( pPath == NULL ) || ( pPathLen == NULL ) ) - { - LogError( ( "NULL parameter passed to getUrlPath()." ) ); - httpStatus = HTTPInvalidParameter; - } - - if( httpStatus == HTTPSuccess ) - { - httpStatus = getUrlAddress( pUrl, urlLen, &pHostStart, &hostLen ); - } - - if( httpStatus == HTTPSuccess ) - { - /* Search for the start of the path. */ - for( i = ( pHostStart - pUrl ) + hostLen; i < urlLen; i++ ) - { - if( pUrl[ i ] == '/' ) - { - pPathStart = &pUrl[ i ]; - pathStartIndex = i; - break; - } - } - - if( pPathStart != NULL ) - { - /* The end of the path will be either the start of the query, - * start of the fragment, or end of the URL. If this is an S3 - * presigned URL, then there must be a query. */ - for( i = pathStartIndex; i < urlLen; i++ ) - { - if( pUrl[ i ] == '?' ) - { - break; - } - } - - pathLen = i - pathStartIndex; - } - - if( pathLen == 0 ) - { - LogError( ( "Could not parse path from input URL %.*s", - ( int ) urlLen, - pUrl ) ); - httpStatus = HTTPNoResponse; - } - } - - if( httpStatus == HTTPSuccess ) - { - *pPathLen = pathLen; - *pPath = pPathStart; - } - - if( httpStatus != HTTPSuccess ) - { - LogError( ( "Error parsing the path from URL %s. Error code: %d", - pUrl, - httpStatus ) ); - } - - return httpStatus; -} - -/*-----------------------------------------------------------*/ - -HTTPStatus_t getUrlAddress( const char * pUrl, - size_t urlLen, - const char ** pAddress, - size_t * pAddressLen ) -{ - HTTPStatus_t httpStatus = HTTPSuccess; - const char * pHostStart = NULL; - const char * pHostEnd = NULL; - size_t i = 0, hostLen = 0; - - if( ( pUrl == NULL ) || ( pAddress == NULL ) || ( pAddressLen == NULL ) ) - { - LogError( ( "NULL parameter passed to getUrlAddress()." ) ); - httpStatus = HTTPInvalidParameter; - } - - if( httpStatus == HTTPSuccess ) - { - /* Search for the start of the hostname using the "://" separator. */ - for( i = 0; i < ( urlLen - SCHEME_SEPARATOR_LEN ); i++ ) - { - if( strncmp( &( pUrl[ i ] ), SCHEME_SEPARATOR, SCHEME_SEPARATOR_LEN ) == 0 ) - { - pHostStart = pUrl + i + SCHEME_SEPARATOR_LEN; - break; - } - } - - if( pHostStart == NULL ) - { - LogError( ( "Could not find \"://\" scheme separator in input URL %.*s", - ( int ) urlLen, - pUrl ) ); - httpStatus = HTTPParserInternalError; - } - else - { - /* Search for the end of the hostname assuming that the object path - * is next. Assume that there is no port number as this is used for - * S3 presigned URLs. */ - for( pHostEnd = pHostStart; pHostEnd < ( pUrl + urlLen ); pHostEnd++ ) - { - if( *pHostEnd == '/' ) - { - hostLen = ( size_t ) ( pHostEnd - pHostStart ); - break; - } - } - } - } - - if( httpStatus == HTTPSuccess ) - { - *pAddressLen = hostLen; - - if( hostLen == 0 ) - { - LogError( ( "Could not find end of host in input URL %.*s", - ( int ) urlLen, - pUrl ) ); - httpStatus = HTTPNoResponse; - *pAddress = NULL; - } - else - { - *pAddress = pHostStart; - } - } - - if( httpStatus != HTTPSuccess ) - { - LogError( ( "Error parsing the address from URL %s. Error code %d", - pUrl, - httpStatus ) ); - } - - return httpStatus; -} \ No newline at end of file diff --git a/examples/ota/ota_http/main/http_demo_url_utils.h b/examples/ota/ota_http/main/http_demo_url_utils.h deleted file mode 100644 index b0f98fbdb..000000000 --- a/examples/ota/ota_http/main/http_demo_url_utils.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202108.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef HTTP_DEMO_URL_UTILS_H_ -#define HTTP_DEMO_URL_UTILS_H_ - -/* Standard includes. */ -#include -#include - -/* *INDENT-OFF* */ -#ifdef __cplusplus - extern "C" { -#endif -/* *INDENT-ON* */ - -/* HTTP API header. */ -#include "core_http_client.h" - -/** - * @brief Retrieve the path from the input URL. - * - * This function retrieves the location and length of the path from within the - * input the URL. The query is not included in the length returned. - * - * The URL MUST start with "http://" or "https://" to find the path. - * - * For example, if pUrl is: - * "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff" - * - * Then pPath and pPathLen will be the following: - * *pPath = "/path/to/item.txt?optionalquery=stuff" - * *pPathLen = 17 - * - * @param[in] pUrl URL string to parse. - * @param[in] urlLen The length of the URL string input. - * @param[out] pPath pointer within input url that the path starts at. - * @param[out] pPathLen Length of the path. - * - * @return The status of the parsing attempt: - * HTTPSuccess if the path was successfully parsed, - * HTTPParserInternalError if there was an error parsing the URL, - * or HTTPNoResponse if the path was not found. - */ -HTTPStatus_t getUrlPath( const char * pUrl, - size_t urlLen, - const char ** pPath, - size_t * pPathLen ); - -/** - * @brief Retrieve the Address from the input URL. - * - * This function retrieves the location and length of the address from within - * the input URL. The path and query are not included in the length returned. - * - * The URL MUST start with "http://" or "https://" to find the address. - * - * For example, if pUrl is: - * "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff" - * - * Then pAddress and pAddressLen will be the following: - * *pAddress = "www.somewebsite.com/path/to/item.txt?optionalquery=stuff" - * *pAddressLen = 19 - * - * @param[in] pUrl URL string to parse. - * @param[in] urlLen The length of the URL string input. - * @param[out] pAddress pointer within input url that the address starts at. - * @param[out] pAddressLen Length of the address. - * - * @return The status of the parsing attempt: - * HTTPSuccess if the path was successfully parsed, - * HTTPParserInternalError if there was an error parsing the URL, - * or HTTPNoResponse if the path was not found. - */ -HTTPStatus_t getUrlAddress( const char * pUrl, - size_t urlLen, - const char ** pAddress, - size_t * pAddressLen ); - -/* *INDENT-OFF* */ -#ifdef __cplusplus - } -#endif -/* *INDENT-ON* */ - -#endif /* ifndef HTTP_DEMO_URL_UTILS_H_ */ \ No newline at end of file diff --git a/examples/ota/ota_http/main/idf_component.yml b/examples/ota/ota_http/main/idf_component.yml deleted file mode 100644 index 6c511a925..000000000 --- a/examples/ota/ota_http/main/idf_component.yml +++ /dev/null @@ -1,7 +0,0 @@ -## IDF Component Manager Manifest File -dependencies: - espressif/esp_secure_cert_mgr: "^2.0.5" - espressif/cbor: - version: ">=0.5.4,<1.0.0" - rules: - - if: "idf_version >=5.0" diff --git a/examples/ota/ota_http/main/mqtt_subscription_manager.c b/examples/ota/ota_http/main/mqtt_subscription_manager.c deleted file mode 100644 index 8535f109f..000000000 --- a/examples/ota/ota_http/main/mqtt_subscription_manager.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202103.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @file mqtt_subscription_manager.c - * @brief Implementation of the API of a subscription manager for handling subscription callbacks - * to topic filters in MQTT operations. - */ - -/* Standard includes. */ -#include -#include - -/* Include demo config. */ -#include "demo_config.h" - -/* Include header for the subscription manager. */ -#include "mqtt_subscription_manager.h" - - -/** - * @brief Represents a registered record of the topic filter and its associated callback - * in the subscription manager registry. - */ -typedef struct SubscriptionManagerRecord -{ - const char * pTopicFilter; - uint16_t topicFilterLength; - SubscriptionManagerCallback_t callback; -} SubscriptionManagerRecord_t; - -/** - * @brief The default value for the maximum size of the callback registry in the - * subscription manager. - */ -#ifndef MAX_SUBSCRIPTION_CALLBACK_RECORDS - #define MAX_SUBSCRIPTION_CALLBACK_RECORDS 5 -#endif - -/** - * @brief The registry to store records of topic filters and their subscription callbacks. - */ -static SubscriptionManagerRecord_t callbackRecordList[ MAX_SUBSCRIPTION_CALLBACK_RECORDS ] = { 0 }; - -/*-----------------------------------------------------------*/ - -void SubscriptionManager_DispatchHandler( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ) -{ - bool matchStatus = false; - size_t listIndex = 0u; - - assert( pPublishInfo != NULL ); - assert( pContext != NULL ); - - /* Iterate through record list to find matching topics, and invoke their callbacks. */ - for( listIndex = 0; listIndex < MAX_SUBSCRIPTION_CALLBACK_RECORDS; listIndex++ ) - { - if( ( callbackRecordList[ listIndex ].pTopicFilter != NULL ) && - ( MQTT_MatchTopic( pPublishInfo->pTopicName, - pPublishInfo->topicNameLength, - callbackRecordList[ listIndex ].pTopicFilter, - callbackRecordList[ listIndex ].topicFilterLength, - &matchStatus ) == MQTTSuccess ) && - ( matchStatus == true ) ) - { - LogInfo( ( "Invoking subscription callback of matching topic filter: " - "TopicFilter=%.*s, TopicName=%.*s", - callbackRecordList[ listIndex ].topicFilterLength, - callbackRecordList[ listIndex ].pTopicFilter, - pPublishInfo->topicNameLength, - pPublishInfo->pTopicName ) ); - - /* Invoke the callback associated with the record as the topics match. */ - callbackRecordList[ listIndex ].callback( pContext, pPublishInfo ); - } - } -} - -/*-----------------------------------------------------------*/ - -SubscriptionManagerStatus_t SubscriptionManager_RegisterCallback( const char * pTopicFilter, - uint16_t topicFilterLength, - SubscriptionManagerCallback_t callback ) -{ - assert( pTopicFilter != NULL ); - assert( topicFilterLength != 0 ); - assert( callback != NULL ); - - SubscriptionManagerStatus_t returnStatus; - size_t availableIndex = MAX_SUBSCRIPTION_CALLBACK_RECORDS; - bool recordExists = false; - size_t index = 0u; - - /* Search for the first available spot in the list to store the record, and also check if - * a record for the topic filter already exists. */ - while( ( recordExists == false ) && ( index < MAX_SUBSCRIPTION_CALLBACK_RECORDS ) ) - { - /* Check if the index represents an empty spot in the registry. If we had already - * found an empty spot in the list, we will not update it. */ - if( ( availableIndex == MAX_SUBSCRIPTION_CALLBACK_RECORDS ) && - ( callbackRecordList[ index ].pTopicFilter == NULL ) ) - { - availableIndex = index; - } - - /* Check if the current record's topic filter in the registry matches the topic filter - * we are trying to register. */ - else if( ( callbackRecordList[ index ].topicFilterLength == topicFilterLength ) && - ( strncmp( pTopicFilter, callbackRecordList[ index ].pTopicFilter, topicFilterLength ) - == 0 ) ) - { - recordExists = true; - } - - index++; - } - - if( recordExists == true ) - { - /* The record for the topic filter already exists. */ - LogError( ( "Failed to register callback: Record for topic filter already exists: TopicFilter=%.*s", - topicFilterLength, - pTopicFilter ) ); - - returnStatus = SUBSCRIPTION_MANAGER_RECORD_EXISTS; - } - else if( availableIndex == MAX_SUBSCRIPTION_CALLBACK_RECORDS ) - { - /* The registry is full. */ - LogError( ( "Unable to register callback: Registry list is full: TopicFilter=%.*s, MaxRegistrySize=%u", - topicFilterLength, - pTopicFilter, - MAX_SUBSCRIPTION_CALLBACK_RECORDS ) ); - - returnStatus = SUBSCRIPTION_MANAGER_REGISTRY_FULL; - } - else - { - callbackRecordList[ availableIndex ].pTopicFilter = pTopicFilter; - callbackRecordList[ availableIndex ].topicFilterLength = topicFilterLength; - callbackRecordList[ availableIndex ].callback = callback; - - returnStatus = SUBSCRIPTION_MANAGER_SUCCESS; - - LogDebug( ( "Added callback to registry: TopicFilter=%.*s", - topicFilterLength, - pTopicFilter ) ); - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -void SubscriptionManager_RemoveCallback( const char * pTopicFilter, - uint16_t topicFilterLength ) -{ - assert( pTopicFilter != NULL ); - assert( topicFilterLength != 0 ); - - size_t index; - SubscriptionManagerRecord_t * pRecord = NULL; - - /* Iterate through the records list to find the matching record. */ - for( index = 0; index < MAX_SUBSCRIPTION_CALLBACK_RECORDS; index++ ) - { - pRecord = &callbackRecordList[ index ]; - - /* Only match the non-empty records. */ - if( pRecord->pTopicFilter != NULL ) - { - if( ( topicFilterLength == pRecord->topicFilterLength ) && - ( strncmp( pTopicFilter, pRecord->pTopicFilter, topicFilterLength ) == 0 ) ) - { - break; - } - } - } - - /* Delete the record by clearing the found entry in the records list. */ - if( index < MAX_SUBSCRIPTION_CALLBACK_RECORDS ) - { - pRecord->pTopicFilter = NULL; - pRecord->topicFilterLength = 0u; - pRecord->callback = NULL; - - LogDebug( ( "Deleted callback record for topic filter: TopicFilter=%.*s", - topicFilterLength, - pTopicFilter ) ); - } - else - { - LogWarn( ( "Attempted to remove callback for un-registered topic filter: TopicFilter=%.*s", - topicFilterLength, - pTopicFilter ) ); - } -} -/*-----------------------------------------------------------*/ diff --git a/examples/ota/ota_http/main/mqtt_subscription_manager.h b/examples/ota/ota_http/main/mqtt_subscription_manager.h deleted file mode 100644 index 03ca72b77..000000000 --- a/examples/ota/ota_http/main/mqtt_subscription_manager.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202108.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @file mqtt_subscription_manager.h - * @brief The API of a subscription manager for handling subscription callbacks - * to topic filters in MQTT operations. - */ - -#ifndef MQTT_SUBSCRIPTION_MANAGER_H_ -#define MQTT_SUBSCRIPTION_MANAGER_H_ - -/**************************************************/ -/******* DO NOT CHANGE the following order ********/ -/**************************************************/ - -/* Logging related header files are required to be included in the following order: - * 1. Include the header file "logging_levels.h". - * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. - * 3. Include the header file "logging_stack.h". - */ - -/* Include header that defines log levels. */ -#include "logging_levels.h" - -/* Logging configuration for the Subscription Manager module. */ -#ifndef LIBRARY_LOG_NAME - #define LIBRARY_LOG_NAME "Subscription Manager" -#endif -#ifndef LIBRARY_LOG_LEVEL - #define LIBRARY_LOG_LEVEL LOG_DEBUG -#endif - -#include "logging_stack.h" - -/************ End of logging configuration ****************/ - -/* Include MQTT library. */ -#include "core_mqtt.h" - -/* Enumeration type for return status value from Subscription Manager API. */ -typedef enum SubscriptionManagerStatus -{ - /** - * @brief Success return value from Subscription Manager API. - */ - SUBSCRIPTION_MANAGER_SUCCESS = 1, - - /** - * @brief Failure return value due to registry being full. - */ - SUBSCRIPTION_MANAGER_REGISTRY_FULL = 2, - - /** - * @brief Failure return value due to an already existing record in the - * registry for a new callback registration's requested topic filter. - */ - SUBSCRIPTION_MANAGER_RECORD_EXISTS = 3 -} SubscriptionManagerStatus_t; - - -/** - * @brief Callback type to be registered for a topic filter with the subscription manager. - * - * For incoming PUBLISH messages received on topics that match the registered topic filter, - * the callback would be invoked by the subscription manager. - * - * @param[in] pContext The context associated with the MQTT connection. - * @param[in] pPublishInfo The incoming PUBLISH message information. - */ -typedef void (* SubscriptionManagerCallback_t )( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ); - -/** - * @brief Dispatches the incoming PUBLISH message to the callbacks that have their - * registered topic filters matching the incoming PUBLISH topic name. The dispatch - * handler will invoke all these callbacks with matching topic filters. - * - * @param[in] pContext The context associated with the MQTT connection. - * @param[in] pPublishInfo The incoming PUBLISH message information. - */ -void SubscriptionManager_DispatchHandler( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ); - -/** - * @brief Utility to register a callback for a topic filter in the subscription manager. - * - * The callback will be invoked when an incoming PUBLISH message is received on - * a topic that matches the topic filter, @a pTopicFilter. The subscription manager - * accepts wildcard topic filters. - * - * @param[in] pTopicFilter The topic filter to register the callback for. - * @param[in] topicFilterLength The length of the topic filter string. - * @param[in] callback The callback to be registered for the topic filter. - * - * @note The subscription manager does not allow more than one callback to be registered - * for the same topic filter. - * @note The passed topic filter, @a pTopicFilter, is saved in the registry. - * The application must not free or alter the content of the topic filter memory - * until the callback for the topic filter is removed from the subscription manager. - * - * @return Returns one of the following: - * - #SUBSCRIPTION_MANAGER_SUCCESS if registration of the callback is successful. - * - #SUBSCRIPTION_MANAGER_REGISTRY_FULL if the registration failed due to registry - * being already full. - * - #SUBSCRIPTION_MANAGER_RECORD_EXISTS, if a registered callback already exists for - * the requested topic filter in the subscription manager. - */ -SubscriptionManagerStatus_t SubscriptionManager_RegisterCallback( const char * pTopicFilter, - uint16_t topicFilterLength, - SubscriptionManagerCallback_t pCallback ); - -/** - * @brief Utility to remove the callback registered for a topic filter from the - * subscription manager. - * - * @param[in] pTopicFilter The topic filter to remove from the subscription manager. - * @param[in] topicFilterLength The length of the topic filter string. - */ -void SubscriptionManager_RemoveCallback( const char * pTopicFilter, - uint16_t topicFilterLength ); - - -#endif /* ifndef MQTT_SUBSCRIPTION_MANAGER_H_ */ diff --git a/examples/ota/ota_http/main/ota_demo_core_http.c b/examples/ota/ota_http/main/ota_demo_core_http.c deleted file mode 100644 index 7bd9ae8a1..000000000 --- a/examples/ota/ota_http/main/ota_demo_core_http.c +++ /dev/null @@ -1,2390 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202108.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @file ota_demo_core_http.c - * @brief OTA update example using coreMQTT and coreHTTP. - */ - -/* Standard includes. */ -#include -#include -#include -#include - -/* Include Demo Config as the first non-system header. */ -#include "demo_config.h" - -/* OpenSSL sockets transport implementation. */ -#include "network_transport.h" - -/* Clock for timer. */ -#include "clock.h" - -/* pthread include. */ -#include -#include "semaphore.h" -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_pthread.h" - -/* MQTT include. */ -#include "core_mqtt.h" -#include "mqtt_subscription_manager.h" - -/* HTTP include. */ -#include "core_http_client.h" - -/* Common HTTP demo utilities. */ -#include "http_demo_url_utils.h" - -/*Include backoff algorithm header for retry logic.*/ -#include "backoff_algorithm.h" - -/* OTA Library include. */ -#include "ota.h" -#include "ota_config.h" - -/* OTA Library Interface include. */ -#include "ota_os_freertos.h" -#include "ota_mqtt_interface.h" -#include "ota_pal.h" - -/* Include firmware version struct definition. */ -#include "ota_appversion32.h" - -#ifdef CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR - #include "esp_secure_cert_read.h" -#endif - -extern const char root_cert_auth_start[] asm("_binary_root_cert_auth_crt_start"); -extern const char root_cert_auth_end[] asm("_binary_root_cert_auth_crt_end"); - -extern const char http_root_cert_auth_start[] asm("_binary_http_root_cert_auth_crt_start"); -extern const char http_root_cert_auth_end[] asm("_binary_http_root_cert_auth_crt_end"); - -#ifndef CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR - extern const char client_cert_start[] asm("_binary_client_crt_start"); - extern const char client_cert_end[] asm("_binary_client_crt_end"); - extern const char client_key_start[] asm("_binary_client_key_start"); - extern const char client_key_end[] asm("_binary_client_key_end"); -#endif - -extern const char pcAwsCodeSigningCertPem[] asm("_binary_aws_codesign_crt_start"); - -/** - * @brief ALPN (Application-Layer Protocol Negotiation) protocol name for AWS IoT MQTT. - * - * This will be used if the AWS_MQTT_PORT is configured as 443 for AWS IoT MQTT broker. - * Please see more details about the ALPN protocol for AWS IoT MQTT endpoint - * in the link below. - * https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/ - */ -#define AWS_IOT_MQTT_ALPN "x-amzn-mqtt-ca" - -/** - * @brief ALPN protocol name to be sent as part of the ClientHello message. - * - * @note When using ALPN, port 443 must be used to connect to AWS IoT Core. - */ -#define IOT_CORE_ALPN_PROTOCOL_NAME "x-amzn-http-ca" - -/** - * @brief Length of ALPN protocol name. - */ -#define AWS_IOT_MQTT_ALPN_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_MQTT_ALPN ) - 1 ) ) - -/** - * @brief Length of MQTT server host name. - */ -#define AWS_IOT_ENDPOINT_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_ENDPOINT ) - 1 ) ) - -/** - * @brief Length of client identifier. - */ -#define CLIENT_IDENTIFIER_LENGTH ( ( uint16_t ) ( sizeof( CLIENT_IDENTIFIER ) - 1 ) ) - -/** - * @brief Transport timeout in milliseconds for transport send and receive. - */ -#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 1500U ) - -/** - * @brief Timeout for receiving CONNACK packet in milli seconds. - */ -#define CONNACK_RECV_TIMEOUT_MS ( 2000U ) - -/** - * @brief The maximum time interval in seconds which is allowed to elapse - * between two Control Packets. - * - * It is the responsibility of the Client to ensure that the interval between - * Control Packets being sent does not exceed the this Keep Alive value. In the - * absence of sending any other Control Packets, the Client MUST send a - * PINGREQ Packet. - */ -#define MQTT_KEEP_ALIVE_INTERVAL_SECONDS ( 60U ) - -/** - * @brief Maximum number or retries to publish a message in case of failures. - */ -#define MQTT_PUBLISH_RETRY_MAX_ATTEMPS ( 3U ) - -/** - * @brief Period for demo loop sleep in milliseconds. - */ -#define OTA_EXAMPLE_LOOP_SLEEP_PERIOD_MS ( 5U ) - -/** - * @brief The delay used in the main OTA Demo task loop to periodically output the OTA - * statistics like number of packets received, dropped, processed and queued per connection. - */ -#define OTA_EXAMPLE_TASK_DELAY_MS ( 1000U ) - -/** - * @brief The timeout for waiting for the agent to get suspended after closing the - * connection. - */ -#define OTA_SUSPEND_TIMEOUT_MS ( 5000U ) - -/** - * @brief Period for waiting on ack. - */ -#define MQTT_ACK_TIMEOUT_MS ( 5000U ) - -/** - * @brief The timeout for waiting before exiting the OTA demo. - */ -#define OTA_DEMO_EXIT_TIMEOUT_MS ( 3000U ) - -/** - * @brief The maximum size of the file paths used in the demo. - */ -#define OTA_MAX_FILE_PATH_SIZE ( 260U ) - -/** - * @brief The maximum size of the stream name required for downloading update file - * from streaming service. - */ -#define OTA_MAX_STREAM_NAME_SIZE ( 128U ) - -/** - * @brief The maximum back-off delay (in milliseconds) for retrying connection to server. - */ -#define CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS ( 5000U ) - -/** - * @brief The base back-off delay (in milliseconds) to use for connection retry attempts. - */ -#define CONNECTION_RETRY_BACKOFF_BASE_MS ( 500U ) - -/** - * @brief Number of milliseconds in a second. - */ -#define NUM_MILLISECONDS_IN_SECOND ( 1000U ) - -/** - * @brief Maximum size of the url. - */ -#define OTA_MAX_URL_SIZE ( 2048U ) - -/** - * @brief Maximum size of the auth scheme. - */ -#define OTA_MAX_AUTH_SCHEME_SIZE ( 2048U ) - -/** - * @brief Size of the network buffer to receive the MQTT message. - * - * The largest message size is data size from the AWS IoT streaming service, - * otaconfigFILE_BLOCK_SIZE + extra for headers. - */ - -#define OTA_NETWORK_BUFFER_SIZE ( otaconfigFILE_BLOCK_SIZE + OTA_MAX_URL_SIZE + 128 ) - -/** - * @brief The maximum number of retries for connecting to server. - */ -#define CONNECTION_RETRY_MAX_ATTEMPTS ( 5U ) - -/** - * @brief The maximum size of the HTTP header. - */ -#define HTTP_HEADER_SIZE_MAX ( 1024U ) - -/* HTTP buffers used for http request and response. */ -#define HTTP_USER_BUFFER_LENGTH ( otaconfigFILE_BLOCK_SIZE + HTTP_HEADER_SIZE_MAX ) - -/** - * @brief The MQTT metrics string expected by AWS IoT. - */ -#define METRICS_STRING "?SDK=" OS_NAME "&Version=" OS_VERSION "&Platform=" HARDWARE_PLATFORM_NAME "&OTALib=" OTA_LIB - -/** - * @brief The length of the MQTT metrics string expected by AWS IoT. - */ -#define METRICS_STRING_LENGTH ( ( uint16_t ) ( sizeof( METRICS_STRING ) - 1 ) ) - - -#ifdef CLIENT_USERNAME - -/** - * @brief Append the username with the metrics string if #CLIENT_USERNAME is defined. - * - * This is to support both metrics reporting and username/password based client - * authentication by AWS IoT. - */ - #define CLIENT_USERNAME_WITH_METRICS CLIENT_USERNAME METRICS_STRING -#endif - -/** - * @brief The common prefix for all OTA topics. - */ -#define OTA_TOPIC_PREFIX "$aws/things/+/" - -/** - * @brief The string used for jobs topics. - */ -#define OTA_TOPIC_JOBS "jobs" - -/** - * @brief The string used for streaming service topics. - */ -#define OTA_TOPIC_STREAM "streams" - -/** - * @brief HTTP response codes used in this demo. - */ -#define HTTP_RESPONSE_PARTIAL_CONTENT ( 206 ) -#define HTTP_RESPONSE_BAD_REQUEST ( 400 ) -#define HTTP_RESPONSE_FORBIDDEN ( 403 ) -#define HTTP_RESPONSE_NOT_FOUND ( 404 ) - -/** - * @brief The length of the outgoing publish records array used by the coreMQTT - * library to track QoS > 0 packet ACKS for outgoing publishes. - */ -#define OUTGOING_PUBLISH_RECORD_LEN ( 10U ) - -/** - * @brief The length of the incoming publish records array used by the coreMQTT - * library to track QoS > 0 packet ACKS for incoming publishes. - */ -#define INCOMING_PUBLISH_RECORD_LEN ( 10U ) - -/*-----------------------------------------------------------*/ - -/* Linkage for error reporting. */ -extern int errno; - -/** - * @brief Struct for firmware version. - */ -const AppVersion32_t appFirmwareVersion = -{ - .u.x.major = APP_VERSION_MAJOR, - .u.x.minor = APP_VERSION_MINOR, - .u.x.build = APP_VERSION_BUILD, -}; - -/** - * @brief Static buffer for TLS Context Semaphore. - */ -static StaticSemaphore_t xTlsContextSemaphoreBuffer; - -/** - * @brief Static buffer for TLS Context Semaphore (For HTTP). - */ -static StaticSemaphore_t xTlsContextSemaphoreBufferHTTP; - -/** - * @brief Network connection context used in this demo for MQTT connection. - */ -static NetworkContext_t networkContextMqtt; - -/** - * @brief Network connection context used for HTTP connection. - */ -static NetworkContext_t networkContextHttp; - - -/** - * @brief The host address string extracted from the pre-signed URL. - * - * @note S3_PRESIGNED_GET_URL_LENGTH is set as the array length here as the - * length of the host name string cannot exceed this value. - */ -static char serverHost[ 256 ]; - -/** - * @brief A buffer used in the demo for storing HTTP request headers and - * HTTP response headers and body. - * - * @note This demo shows how the same buffer can be re-used for storing the HTTP - * response after the HTTP request is sent out. However, the user can also - * decide to use separate buffers for storing the HTTP request and response. - */ -static uint8_t httpUserBuffer[ HTTP_USER_BUFFER_LENGTH ]; - -/* The transport layer interface used by the HTTP Client library. */ -TransportInterface_t transportInterfaceHttp; - -/** - * @brief MQTT connection context used in this demo. - */ -static MQTTContext_t mqttContext; - -/** - * @brief Keep a flag for indicating if the MQTT connection is alive. - */ -static bool mqttSessionEstablished = false; - -/** - * @brief Mutex for synchronizing coreMQTT API calls. - */ -static pthread_mutex_t mqttMutex; - -/** - * @brief The host address string extracted from the pre-signed URL. - * - * @note S3_PRESIGNED_GET_URL_LENGTH is set as the array length here as the - * length of the host name string cannot exceed this value. - */ -static char serverHost[ 256 ]; - -/** - * @brief The length of the host address found in the pre-signed URL. - */ -static size_t serverHostLength; - -/** - * @brief Semaphore for synchronizing buffer operations. - */ -static osi_sem_t bufferSemaphore; - -/** - * @brief Semaphore for synchronizing wait for ack. - */ -static osi_sem_t ackSemaphore; - -/** - * @brief Enum for type of OTA job messages received. - */ -typedef enum jobMessageType -{ - jobMessageTypeNextGetAccepted = 0, - jobMessageTypeNextNotify, - jobMessageTypeMax -} jobMessageType_t; - -/** - * @brief The network buffer must remain valid when OTA library task is running. - */ -static uint8_t otaNetworkBuffer[ OTA_NETWORK_BUFFER_SIZE ]; - -/** - * @brief The location of the path within the pre-signed URL. - */ -static const char * pPath; - -/** - * @brief Update File path buffer. - */ -uint8_t updateFilePath[ OTA_MAX_FILE_PATH_SIZE ]; - -/** - * @brief Certificate File path buffer. - */ -uint8_t certFilePath[ OTA_MAX_FILE_PATH_SIZE ]; - -/** - * @brief Stream name buffer. - */ -uint8_t streamName[ OTA_MAX_STREAM_NAME_SIZE ]; - -/** - * @brief Decode memory. - */ -uint8_t decodeMem[ otaconfigFILE_BLOCK_SIZE ]; - -/** - * @brief Bitmap memory. - */ -uint8_t bitmap[ OTA_MAX_BLOCK_BITMAP_SIZE ]; - -/** - * @brief Certificate File path buffer. - */ -uint8_t updateUrl[ OTA_MAX_URL_SIZE ]; - -/** - * @brief Auth scheme buffer. - */ -uint8_t authScheme[ OTA_MAX_URL_SIZE ]; - -/** - * @brief Event buffer. - */ -static OtaEventData_t eventBuffer[ otaconfigMAX_NUM_OTA_DATA_BUFFERS ]; - -/** - * @brief The buffer passed to the OTA Agent from application while initializing. - */ -static OtaAppBuffer_t otaBuffer = -{ - .pUpdateFilePath = updateFilePath, - .updateFilePathsize = OTA_MAX_FILE_PATH_SIZE, - .pCertFilePath = certFilePath, - .certFilePathSize = OTA_MAX_FILE_PATH_SIZE, - .pDecodeMemory = decodeMem, - .decodeMemorySize = otaconfigFILE_BLOCK_SIZE, - .pFileBitmap = bitmap, - .fileBitmapSize = OTA_MAX_BLOCK_BITMAP_SIZE, - .pUrl = updateUrl, - .urlSize = OTA_MAX_URL_SIZE, - .pAuthScheme = authScheme, - .authSchemeSize = OTA_MAX_AUTH_SCHEME_SIZE -}; - -/** - * @brief Array to track the outgoing publish records for outgoing publishes - * with QoS > 0. - * - * This is passed into #MQTT_InitStatefulQoS to allow for QoS > 0. - * - */ -static MQTTPubAckInfo_t pOutgoingPublishRecords[ OUTGOING_PUBLISH_RECORD_LEN ]; - -/** - * @brief Array to track the incoming publish records for incoming publishes - * with QoS > 0. - * - * This is passed into #MQTT_InitStatefulQoS to allow for QoS > 0. - * - */ -static MQTTPubAckInfo_t pIncomingPublishRecords[ INCOMING_PUBLISH_RECORD_LEN ]; - -/*-----------------------------------------------------------*/ - -int aws_iot_demo_main( int argc, char ** argv ); - -/** - * @brief Retry logic to establish a connection to the server. - * - * If the connection fails, keep retrying with exponentially increasing - * timeout value, until max retries, max timeout or successful connect. - * - * @param[in] pNetworkContext Network context to connect on. - * @return int EXIT_FAILURE if connection failed after retries. - */ -static int connectToServerWithBackoffRetries( NetworkContext_t * pNetworkContext ); - -/** - * @brief Sends an MQTT CONNECT packet over the already connected TCP socket. - * - * @param[in] pMqttContext MQTT context pointer. - * @param[in] createCleanSession Creates a new MQTT session if true. - * If false, tries to establish the existing session if there was session - * already present in broker. - * @param[out] pSessionPresent Session was already present in the broker or not. - * Session present response is obtained from the CONNACK from broker. - * - * @return EXIT_SUCCESS if an MQTT session is established; - * EXIT_FAILURE otherwise. - */ -static int establishMqttSession( MQTTContext_t * pMqttContext ); - -/** - * @brief Publish message to a topic. - * - * This function publishes a message to a given topic & QoS. - * - * @param[in] pTopic Mqtt topic filter. - * - * @param[in] topicLen Length of the topic filter. - * - * @param[in] pMsg Message to publish. - * - * @param[in] msgSize Message size. - * - * @param[in] qos Quality of Service - * - * @return OtaMqttSuccess if success , other error code on failure. - */ -static OtaMqttStatus_t mqttPublish( const char * const pTopic, - uint16_t topicLen, - const char * pMsg, - uint32_t msgSize, - uint8_t qos ); - -/** - * @brief Subscribe to the Mqtt topics. - * - * This function subscribes to the Mqtt topics with the Quality of service - * received as parameter. This function also registers a callback for the - * topicfilter. - * - * @param[in] pTopicFilter Mqtt topic filter. - * - * @param[in] topicFilterLength Length of the topic filter. - * - * @param[in] qos Quality of Service - * - * @return OtaMqttSuccess if success , other error code on failure. - */ -static OtaMqttStatus_t mqttSubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t qos ); - -/** - * @brief Unsubscribe to the Mqtt topics. - * - * This function unsubscribes to the Mqtt topics with the Quality of service - * received as parameter. - * - * @param[in] pTopicFilter Mqtt topic filter. - * - * @param[in] topicFilterLength Length of the topic filter. - * - * @param[qos] qos Quality of Service - * - * @return OtaMqttSuccess if success , other error code on failure. - */ -static OtaMqttStatus_t mqttUnsubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t qos ); - -/** - * @brief Handle HTTP response. - * - * @param[in] pResponse Pointer to http response buffer. - * @return OtaHttpStatus_t OtaHttpSuccess if success or failure code otherwise. - */ -static OtaHttpStatus_t handleHttpResponse( const HTTPResponse_t * pResponse ); - -/** - * @brief Initialize OTA Http interface. - * - * @param[in] pUrl Pointer to the pre-signed url for downloading update file. - * @return OtaHttpStatus_t OtaHttpSuccess if success , - * OtaHttpInitFailed on failure. - */ -static OtaHttpStatus_t httpInit( char * pUrl ); - -/** - * @brief Request file block over HTTP. - * - * @param[in] rangeStart Starting index of the file data - * @param[in] rangeEnd Last index of the file data - * @return OtaHttpStatus_t OtaHttpSuccess if success , - * other errors on failure. - */ -static OtaHttpStatus_t httpRequest( uint32_t rangeStart, - uint32_t rangeEnd ); - -/** - * @brief Deinitialize and cleanup of the HTTP connection. - * - * @return OtaHttpStatus_t OtaHttpSuccess if success , - * OtaHttpRequestFailed on failure. - */ -static OtaHttpStatus_t httpDeinit( void ); - -/** - * @brief Initialize MQTT by setting up transport interface and network. - * - * @param[in] pMqttContext Structure representing MQTT connection. - * @param[in] pNetworkContext Network context to connect on. - * @return int EXIT_SUCCESS if MQTT component is initialized - */ -static int initializeMqtt( MQTTContext_t * pMqttContext, - NetworkContext_t * pNetworkContext ); - -/** - * @brief Attempt to connect to the MQTT broker. - * - * @return int EXIT_SUCCESS if a connection is established. - */ -static int establishConnection( void ); - -/** - * @brief Disconnect from the MQTT broker. - * - */ -static void disconnect( void ); - -/** - * @brief Thread to call the OTA agent task. - * - * @param[in] pParam Can be used to pass down functionality to the agent task - * @return void* returning null. - */ -static void * otaThread( void * pParam ); - -/** - * @brief Start OTA demo. - * - * @return EXIT_SUCCESS or EXIT_FAILURE. - */ -static int startOTADemo( void ); - -/** - * @brief Set OTA interfaces. - * - * @param[in] pOtaInterfaces pointer to OTA interface structure. - * - * @return None. - */ -static void setOtaInterfaces( OtaInterfaces_t * pOtaInterfaces ); - -/** - * @brief Random number to be used as a back-off value for retrying connection. - * - * @return uint32_t The generated random number. - */ -static uint32_t generateRandomNumber(); - -/* Callbacks used to handle different events. */ - -/** - * @brief The OTA agent has completed the update job or it is in - * self test mode. If it was accepted, we want to activate the new image. - * This typically means we should reset the device to run the new firmware. - * If now is not a good time to reset the device, it may be activated later - * by your user code. If the update was rejected, just return without doing - * anything and we'll wait for another job. If it reported that we should - * start test mode, normally we would perform some kind of system checks to - * make sure our new firmware does the basic things we think it should do - * but we'll just go ahead and set the image as accepted for demo purposes. - * The accept function varies depending on your platform. Refer to the OTA - * PAL implementation for your platform in aws_ota_pal.c to see what it - * does for you. - * - * @param[in] event Event from OTA lib of type OtaJobEvent_t. - * @return None. - */ -static void otaAppCallback( OtaJobEvent_t event, - void * pData ); - -/** - * @brief callback to use with the MQTT context to notify incoming packet events. - * - * @param[in] pMqttContext MQTT context which stores the connection. - * @param[in] pPacketInfo Parameters of the incoming packet. - * @param[in] pDeserializedInfo Deserialized packet information to be dispatched by - * the subscription manager to event callbacks. - */ -static void mqttEventCallback( MQTTContext_t * pMqttContext, - MQTTPacketInfo_t * pPacketInfo, - MQTTDeserializedInfo_t * pDeserializedInfo ); - -/** - * @brief Callback registered with the OTA library that notifies the OTA agent - * of an incoming PUBLISH containing a job document. - * - * @param[in] pContext MQTT context which stores the connection. - * @param[in] pPublishInfo MQTT packet information which stores details of the - * job document. - */ -static void mqttJobCallback( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ); - -/** - * @brief Callback that notifies the OTA library when a data block is received. - * - * @param[in] pContext MQTT context which stores the connection. - * @param[in] pPublishInfo MQTT packet that stores the information of the file block. - */ -static void mqttDataCallback( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ); - -static SubscriptionManagerCallback_t otaMessageCallback[] = { mqttJobCallback, mqttDataCallback }; - -/*-----------------------------------------------------------*/ - -void otaEventBufferFree( OtaEventData_t * const pxBuffer ) -{ - if( osi_sem_take( &bufferSemaphore, 0 ) == 0 ) - { - pxBuffer->bufferUsed = false; - ( void ) osi_sem_give( &bufferSemaphore ); - } - else - { - LogError( ( "Failed to get buffer semaphore: " - ",errno=%s", - strerror( errno ) ) ); - } -} - -/*-----------------------------------------------------------*/ - -OtaEventData_t * otaEventBufferGet( void ) -{ - uint32_t ulIndex = 0; - OtaEventData_t * pFreeBuffer = NULL; - - if( osi_sem_take( &bufferSemaphore, 0 ) == 0 ) - { - for( ulIndex = 0; ulIndex < otaconfigMAX_NUM_OTA_DATA_BUFFERS; ulIndex++ ) - { - if( eventBuffer[ ulIndex ].bufferUsed == false ) - { - eventBuffer[ ulIndex ].bufferUsed = true; - pFreeBuffer = &eventBuffer[ ulIndex ]; - break; - } - } - - ( void ) osi_sem_give( &bufferSemaphore ); - } - else - { - LogError( ( "Failed to get buffer semaphore: " - ",errno=%s", - strerror( errno ) ) ); - } - - return pFreeBuffer; -} - -/*-----------------------------------------------------------*/ - -static void otaAppCallback( OtaJobEvent_t event, - void * pData ) -{ - OtaErr_t err = OtaErrUninitialized; - int ret; - - switch( event ) - { - case OtaJobEventActivate: - LogInfo( ( "Received OtaJobEventActivate callback from OTA Agent." ) ); - - /* Activate the new firmware image. */ - OTA_ActivateNewImage(); - - /* Shutdown OTA Agent, if it is required that the unsubscribe operations are not - * performed while shutting down please set the second parameter to 0 instead of 1. */ - OTA_Shutdown( 0, 1 ); - - /* Requires manual activation of new image.*/ - LogError( ( "New image activation failed." ) ); - - break; - - case OtaJobEventFail: - LogInfo( ( "Received OtaJobEventFail callback from OTA Agent." ) ); - - /* Nothing special to do. The OTA agent handles it. */ - break; - - case OtaJobEventStartTest: - - /* This demo just accepts the image since it was a good OTA update and networking - * and services are all working (or we would not have made it this far). If this - * were some custom device that wants to test other things before validating new - * image, this would be the place to kick off those tests before calling - * OTA_SetImageState() with the final result of either accepted or rejected. */ - - LogInfo( ( "Received OtaJobEventStartTest callback from OTA Agent." ) ); - err = OTA_SetImageState( OtaImageStateAccepted ); - - if( err == OtaErrNone ) { - /* Erasing passive partition */ - ret = otaPal_EraseLastBootPartition(); - if (ret != ESP_OK) { - ESP_LOGE("otaAppCallback", "Failed to erase last boot partition! (%d)", ret); - } - } else { - LogError( ( " Failed to set image state as accepted." ) ); - } - - break; - - case OtaJobEventProcessed: - LogDebug( ( "Received OtaJobEventProcessed callback from OTA Agent." ) ); - - if( pData != NULL ) - { - otaEventBufferFree( ( OtaEventData_t * ) pData ); - } - - break; - - case OtaJobEventSelfTestFailed: - LogDebug( ( "Received OtaJobEventSelfTestFailed callback from OTA Agent." ) ); - - /* Requires manual activation of previous image as self-test for - * new image downloaded failed.*/ - LogError( ( "Self-test failed, shutting down OTA Agent." ) ); - - /* Shutdown OTA Agent, if it is required that the unsubscribe operations are not - * performed while shutting down please set the second parameter to 0 instead of 1. */ - OTA_Shutdown( 0, 1 ); - - - break; - - default: - LogDebug( ( "Received invalid callback event from OTA Agent." ) ); - } -} - -jobMessageType_t getJobMessageType( const char * pTopicName, - uint16_t topicNameLength ) -{ - uint16_t index = 0U; - MQTTStatus_t mqttStatus = MQTTSuccess; - bool isMatch = false; - jobMessageType_t jobMessageIndex = jobMessageTypeMax; - - /* For suppressing compiler-warning: unused variable. */ - ( void ) mqttStatus; - - /* Lookup table for OTA job message string. */ - static const char * const pJobTopicFilters[ jobMessageTypeMax ] = - { - OTA_TOPIC_PREFIX OTA_TOPIC_JOBS "/$next/get/accepted", - OTA_TOPIC_PREFIX OTA_TOPIC_JOBS "/notify-next", - }; - - /* Match the input topic filter against the wild-card pattern of topics filters - * relevant for the OTA Update service to determine the type of topic filter. */ - for( ; index < jobMessageTypeMax; index++ ) - { - mqttStatus = MQTT_MatchTopic( pTopicName, - topicNameLength, - pJobTopicFilters[ index ], - strlen( pJobTopicFilters[ index ] ), - &isMatch ); - assert( mqttStatus == MQTTSuccess ); - - if( isMatch ) - { - jobMessageIndex = index; - break; - } - } - - return jobMessageIndex; -} - -/*-----------------------------------------------------------*/ - -static void mqttJobCallback( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ) -{ - OtaEventData_t * pData; - OtaEventMsg_t eventMsg = { 0 }; - jobMessageType_t jobMessageType = 0; - - assert( pPublishInfo != NULL ); - assert( pContext != NULL ); - - ( void ) pContext; - - jobMessageType = getJobMessageType( pPublishInfo->pTopicName, pPublishInfo->topicNameLength ); - - switch( jobMessageType ) - { - case jobMessageTypeNextGetAccepted: - case jobMessageTypeNextNotify: - - pData = otaEventBufferGet(); - - if( pData != NULL ) - { - memcpy( pData->data, pPublishInfo->pPayload, pPublishInfo->payloadLength ); - pData->dataLength = pPublishInfo->payloadLength; - eventMsg.eventId = OtaAgentEventReceivedJobDocument; - eventMsg.pEventData = pData; - - /* Send job document received event. */ - OTA_SignalEvent( &eventMsg ); - } - else - { - LogError( ( "No OTA data buffers available." ) ); - } - - break; - - default: - LogInfo( ( "Received job message %s size %zu.\n\n", - pPublishInfo->pTopicName, - pPublishInfo->payloadLength ) ); - } -} - -/*-----------------------------------------------------------*/ - -static void mqttDataCallback( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ) -{ - OtaEventData_t * pData; - OtaEventMsg_t eventMsg = { 0 }; - - assert( pPublishInfo != NULL ); - assert( pContext != NULL ); - - ( void ) pContext; - - LogInfo( ( "Received data message callback, size %zu.\n\n", pPublishInfo->payloadLength ) ); - - pData = otaEventBufferGet(); - - if( pData != NULL ) - { - memcpy( pData->data, pPublishInfo->pPayload, pPublishInfo->payloadLength ); - pData->dataLength = pPublishInfo->payloadLength; - eventMsg.eventId = OtaAgentEventReceivedFileBlock; - eventMsg.pEventData = pData; - - /* Send job document received event. */ - OTA_SignalEvent( &eventMsg ); - } - else - { - LogError( ( "No OTA data buffers available." ) ); - } -} - -/*-----------------------------------------------------------*/ - -static void mqttEventCallback( MQTTContext_t * pMqttContext, - MQTTPacketInfo_t * pPacketInfo, - MQTTDeserializedInfo_t * pDeserializedInfo ) -{ - assert( pMqttContext != NULL ); - assert( pPacketInfo != NULL ); - assert( pDeserializedInfo != NULL ); - - /* Handle incoming publish. The lower 4 bits of the publish packet - * type is used for the dup, QoS, and retain flags. Hence masking - * out the lower bits to check if the packet is publish. */ - if( ( pPacketInfo->type & 0xF0U ) == MQTT_PACKET_TYPE_PUBLISH ) - { - assert( pDeserializedInfo->pPublishInfo != NULL ); - /* Handle incoming publish. */ - SubscriptionManager_DispatchHandler( pMqttContext, pDeserializedInfo->pPublishInfo ); - } - else - { - /* Handle other packets. */ - switch( pPacketInfo->type ) - { - case MQTT_PACKET_TYPE_SUBACK: - LogInfo( ( "Received SUBACK.\n\n" ) ); - break; - - case MQTT_PACKET_TYPE_UNSUBACK: - LogInfo( ( "Received UNSUBACK.\n\n" ) ); - break; - - case MQTT_PACKET_TYPE_PINGRESP: - - /* Nothing to be done from application as library handles - * PINGRESP. */ - LogWarn( ( "PINGRESP should not be handled by the application " - "callback when using MQTT_ProcessLoop.\n\n" ) ); - break; - - case MQTT_PACKET_TYPE_PUBACK: - LogInfo( ( "PUBACK received for packet id %u.\n\n", - pDeserializedInfo->packetIdentifier ) ); - osi_sem_give( &ackSemaphore ); - break; - - /* Any other packet type is invalid. */ - default: - LogError( ( "Unknown packet type received:(%02x).\n\n", - pPacketInfo->type ) ); - } - } -} - -/*-----------------------------------------------------------*/ - -static uint32_t generateRandomNumber() -{ - return( rand() ); -} - -/*-----------------------------------------------------------*/ - -static int initializeMqtt( MQTTContext_t * pMqttContext, - NetworkContext_t * pNetworkContext ) -{ - int returnStatus = EXIT_SUCCESS; - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTFixedBuffer_t networkBuffer; - TransportInterface_t transport = { 0 }; - - assert( pMqttContext != NULL ); - assert( pNetworkContext != NULL ); - - /* Fill in TransportInterface send and receive function pointers. - * For this demo, TCP sockets are used to send and receive data - * from network. Network context is SSL context for OpenSSL.*/ - transport.pNetworkContext = pNetworkContext; - transport.send = espTlsTransportSend; - transport.recv = espTlsTransportRecv; - transport.writev = NULL; - - /* Fill the values for network buffer. */ - networkBuffer.pBuffer = otaNetworkBuffer; - networkBuffer.size = OTA_NETWORK_BUFFER_SIZE; - - /* Initialize MQTT library. */ - mqttStatus = MQTT_Init( pMqttContext, - &transport, - Clock_GetTimeMs, - mqttEventCallback, - &networkBuffer ); - - if( mqttStatus != MQTTSuccess ) - { - returnStatus = EXIT_FAILURE; - LogError( ( "MQTT_Init failed: Status = %s.", MQTT_Status_strerror( mqttStatus ) ) ); - } - else - { - mqttStatus = MQTT_InitStatefulQoS( pMqttContext, - pOutgoingPublishRecords, - OUTGOING_PUBLISH_RECORD_LEN, - pIncomingPublishRecords, - INCOMING_PUBLISH_RECORD_LEN ); - - if( mqttStatus != MQTTSuccess ) - { - returnStatus = EXIT_FAILURE; - LogError( ( "MQTT_InitStatefulQoS failed: Status = %s.", MQTT_Status_strerror( mqttStatus ) ) ); - } - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static int connectToServerWithBackoffRetries( NetworkContext_t * pNetworkContext ) -{ - int returnStatus = EXIT_SUCCESS; - BackoffAlgorithmStatus_t backoffAlgStatus = BackoffAlgorithmSuccess; - TlsTransportStatus_t tlsStatus = TLS_TRANSPORT_SUCCESS; - BackoffAlgorithmContext_t reconnectParams; - pNetworkContext->pcHostname = AWS_IOT_ENDPOINT; - pNetworkContext->xPort = AWS_MQTT_PORT; - pNetworkContext->pxTls = NULL; - pNetworkContext->xTlsContextSemaphore = xSemaphoreCreateMutexStatic(&xTlsContextSemaphoreBuffer); - - pNetworkContext->disableSni = 0; - uint16_t nextRetryBackOff; - - /* Initialize credentials for establishing TLS session. */ - pNetworkContext->pcServerRootCA = root_cert_auth_start; - pNetworkContext->pcServerRootCASize = root_cert_auth_end - root_cert_auth_start; - - - /* If #CLIENT_USERNAME is defined, username/password is used for authenticating - * the client. */ - -#ifdef CONFIG_EXAMPLE_USE_SECURE_ELEMENT - pNetworkContext->use_secure_element = true; - -#elif defined(CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR) - if (esp_secure_cert_get_device_cert(&pNetworkContext->pcClientCert, &pNetworkContext->pcClientCertSize) != ESP_OK) { - LogError( ( "Failed to obtain flash address of device cert") ); - return EXIT_FAILURE; - } -#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL - pNetworkContext->ds_data = esp_secure_cert_get_ds_ctx(); - if (pNetworkContext->ds_data == NULL) { - LogError( ( "Failed to obtain the ds context") ); - return EXIT_FAILURE; - } -#else /* !CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - if (esp_secure_cert_get_priv_key(&pNetworkContext->pcClientKey, &pNetworkContext->pcClientKeySize) != ESP_OK) { - LogError( ( "Failed to obtain flash address of private_key") ); - return EXIT_FAILURE; - } -#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - -#else /* !CONFIG_EXAMPLE_USE_SECURE_ELEMENT && !CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR */ - #ifndef CLIENT_USERNAME - pNetworkContext->pcClientCert = client_cert_start; - pNetworkContext->pcClientCertSize = client_cert_end - client_cert_start; - pNetworkContext->pcClientKey = client_key_start; - pNetworkContext->pcClientKeySize = client_key_end - client_key_start; - #endif -#endif - - if( AWS_MQTT_PORT == 443 ) - { - /* Pass the ALPN protocol name depending on the port being used. - * Please see more details about the ALPN protocol for the AWS IoT MQTT - * endpoint in the link below. - * https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/ - * - * For username and password based authentication in AWS IoT, - * #AWS_IOT_PASSWORD_ALPN is used. More details can be found in the - * link below. - * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html - */ - - static const char * pcAlpnProtocols[] = { NULL, NULL }; - - #ifdef CLIENT_USERNAME - pcAlpnProtocols[0] = AWS_IOT_PASSWORD_ALPN; - #else - pcAlpnProtocols[0] = AWS_IOT_MQTT_ALPN; - #endif - - pNetworkContext->pAlpnProtos = pcAlpnProtocols; - } else { - pNetworkContext->pAlpnProtos = NULL; - } - - /* Initialize reconnect attempts and interval */ - BackoffAlgorithm_InitializeParams( &reconnectParams, - CONNECTION_RETRY_BACKOFF_BASE_MS, - CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS, - CONNECTION_RETRY_MAX_ATTEMPTS ); - - /* Attempt to connect to MQTT broker. If connection fails, retry after - * a timeout. Timeout value will exponentially increase until maximum - * attempts are reached. - */ - do - { - /* Establish a TLS session with the MQTT broker. This example connects - * to the MQTT broker as specified in AWS_IOT_ENDPOINT and AWS_MQTT_PORT - * at the demo config header. */ - LogInfo( ( "Establishing a TLS session to %.*s:%d.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT, - AWS_MQTT_PORT ) ); - tlsStatus = xTlsConnect ( pNetworkContext ); - - if( tlsStatus != TLS_TRANSPORT_SUCCESS ) - { - /* Generate a random number and get back-off value (in milliseconds) for the next connection retry. */ - backoffAlgStatus = BackoffAlgorithm_GetNextBackoff( &reconnectParams, generateRandomNumber(), &nextRetryBackOff ); - - if( backoffAlgStatus == BackoffAlgorithmRetriesExhausted ) - { - LogError( ( "Connection to the broker failed, all attempts exhausted." ) ); - returnStatus = EXIT_FAILURE; - } - else if( backoffAlgStatus == BackoffAlgorithmSuccess ) - { - LogWarn( ( "Connection to the broker failed. Retrying connection " - "after %hu ms backoff.", - ( unsigned short ) nextRetryBackOff ) ); - Clock_SleepMs( nextRetryBackOff ); - } - } - } while( ( tlsStatus != TLS_TRANSPORT_SUCCESS ) && ( backoffAlgStatus == BackoffAlgorithmSuccess ) ); - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static int establishMqttSession( MQTTContext_t * pMqttContext ) -{ - int returnStatus = EXIT_SUCCESS; - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTConnectInfo_t connectInfo = { 0 }; - - bool sessionPresent = false; - - assert( pMqttContext != NULL ); - - /* Establish MQTT session by sending a CONNECT packet. */ - - /* If #createCleanSession is true, start with a clean session - * i.e. direct the MQTT broker to discard any previous session data. - * If #createCleanSession is false, directs the broker to attempt to - * reestablish a session which was already present. */ - connectInfo.cleanSession = true; - - /* The client identifier is used to uniquely identify this MQTT client to - * the MQTT broker. In a production device the identifier can be something - * unique, such as a device serial number. */ - connectInfo.pClientIdentifier = CLIENT_IDENTIFIER; - connectInfo.clientIdentifierLength = CLIENT_IDENTIFIER_LENGTH; - - /* The maximum time interval in seconds which is allowed to elapse - * between two Control Packets. - * It is the responsibility of the Client to ensure that the interval between - * Control Packets being sent does not exceed the this Keep Alive value. In the - * absence of sending any other Control Packets, the Client MUST send a - * PINGREQ Packet. */ - connectInfo.keepAliveSeconds = MQTT_KEEP_ALIVE_INTERVAL_SECONDS; - - /* Use the username and password for authentication, if they are defined. - * Refer to the AWS IoT documentation below for details regarding client - * authentication with a username and password. - * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html - * An authorizer setup needs to be done, as mentioned in the above link, to use - * username/password based client authentication. - * - * The username field is populated with voluntary metrics to AWS IoT. - * The metrics collected by AWS IoT are the operating system, the operating - * system's version, the hardware platform, and the MQTT Client library - * information. These metrics help AWS IoT improve security and provide - * better technical support. - * - * If client authentication is based on username/password in AWS IoT, - * the metrics string is appended to the username to support both client - * authentication and metrics collection. */ - #ifdef CLIENT_USERNAME - connectInfo.pUserName = CLIENT_USERNAME_WITH_METRICS; - connectInfo.userNameLength = strlen( CLIENT_USERNAME_WITH_METRICS ); - connectInfo.pPassword = CLIENT_PASSWORD; - connectInfo.passwordLength = strlen( CLIENT_PASSWORD ); - #else - connectInfo.pUserName = METRICS_STRING; - connectInfo.userNameLength = METRICS_STRING_LENGTH; - /* Password for authentication is not used. */ - connectInfo.pPassword = NULL; - connectInfo.passwordLength = 0U; - #endif /* ifdef CLIENT_USERNAME */ - - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Send MQTT CONNECT packet to broker. */ - mqttStatus = MQTT_Connect( pMqttContext, &connectInfo, NULL, CONNACK_RECV_TIMEOUT_MS, &sessionPresent ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mutex for executing MQTT_Connect" - ",errno=%s", - strerror( errno ) ) ); - } - - if( mqttStatus != MQTTSuccess ) - { - returnStatus = EXIT_FAILURE; - LogError( ( "Connection with MQTT broker failed with status %s.", - MQTT_Status_strerror( mqttStatus ) ) ); - } - else - { - LogInfo( ( "MQTT connection successfully established with broker.\n\n" ) ); - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static int establishConnection( void ) -{ - int returnStatus = EXIT_FAILURE; - - /* Attempt to connect to the MQTT broker. If connection fails, retry after - * a timeout. Timeout value will be exponentially increased till the maximum - * attempts are reached or maximum timeout value is reached. The function - * returns EXIT_FAILURE if the TCP connection cannot be established to - * broker after configured number of attempts. */ - returnStatus = connectToServerWithBackoffRetries( &networkContextMqtt ); - - if( returnStatus != EXIT_SUCCESS ) - { - /* Log error to indicate connection failure. */ - LogError( ( "Failed to connect to MQTT broker %.*s.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT ) ); - } - else - { - /* Establish MQTT session on top of TCP+TLS connection. */ - LogInfo( ( "Creating an MQTT connection to %.*s.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT ) ); - - /* Sends an MQTT Connect packet using the established TLS session, - * then waits for connection acknowledgment (CONNACK) packet. */ - returnStatus = establishMqttSession( &mqttContext ); - - if( returnStatus != EXIT_SUCCESS ) - { - LogError( ( "Failed creating an MQTT connection to %.*s.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT ) ); - xTlsDisconnect( &networkContextMqtt ); - } - else - { - LogDebug( ( "Success creating MQTT connection to %.*s.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT ) ); - - mqttSessionEstablished = true; - } - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static void cleanupESPSecureMgrCerts( NetworkContext_t * pNetworkContext ) -{ -#ifdef CONFIG_EXAMPLE_USE_SECURE_ELEMENT - /* Nothing to be freed */ -#elif defined(CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR) - esp_secure_cert_free_device_cert(&pNetworkContext->pcClientCert); -#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL - esp_secure_cert_free_ds_ctx(pNetworkContext->ds_data); -#else /* !CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - esp_secure_cert_free_priv_key(&pNetworkContext->pcClientKey); -#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - -#else /* !CONFIG_EXAMPLE_USE_SECURE_ELEMENT && !CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR */ - /* Nothing to be freed */ -#endif - return; -} - -/*-----------------------------------------------------------*/ - -static void disconnect( void ) -{ - /* Disconnect from broker. */ - LogInfo( ( "Disconnecting the MQTT connection with %s.", AWS_IOT_ENDPOINT ) ); - - if( mqttSessionEstablished == true ) - { - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Disconnect MQTT session. */ - MQTT_Disconnect( &mqttContext ); - - /* Clear the mqtt session flag. */ - mqttSessionEstablished = false; - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mutex to execute MQTT_Disconnect" - ",errno=%s", - strerror( errno ) ) ); - } - } - else - { - LogError( ( "MQTT already disconnected." ) ); - } - - /* End TLS session, then close TCP connection. */ - cleanupESPSecureMgrCerts( &networkContextMqtt ); - ( void ) xTlsDisconnect( &networkContextMqtt ); -} - -static int32_t connectToS3Server( NetworkContext_t * pNetworkContext, - const char * pUrl ) -{ - int32_t returnStatus = EXIT_SUCCESS; - HTTPStatus_t httpStatus = HTTPSuccess; - - /* The location of the host address within the pre-signed URL. */ - const char * pAddress = NULL; - - /* Status returned by OpenSSL transport implementation. */ - TlsTransportStatus_t tlsStatus = TLS_TRANSPORT_SUCCESS; - pNetworkContext->xTlsContextSemaphore = xSemaphoreCreateMutexStatic(&xTlsContextSemaphoreBufferHTTP); - pNetworkContext->disableSni = 0; - - /* Initialize TLS credentials. */ - pNetworkContext->pcServerRootCA = http_root_cert_auth_start; - pNetworkContext->pcServerRootCASize = http_root_cert_auth_end - http_root_cert_auth_start; - -#ifdef CONFIG_EXAMPLE_USE_SECURE_ELEMENT - pNetworkContext->use_secure_element = true; - -#elif defined(CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR) - if (esp_secure_cert_get_device_cert(&pNetworkContext->pcClientCert, &pNetworkContext->pcClientCertSize) != ESP_OK) { - LogError( ( "Failed to obtain flash address of device cert") ); - return EXIT_FAILURE; - } -#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL - pNetworkContext->ds_data = esp_secure_cert_get_ds_ctx(); - if (pNetworkContext->ds_data == NULL) { - LogError( ( "Failed to obtain the ds context") ); - return EXIT_FAILURE; - } -#else /* !CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - if (esp_secure_cert_get_priv_key(&pNetworkContext->pcClientKey, &pNetworkContext->pcClientKeySize) != ESP_OK) { - LogError( ( "Failed to obtain flash address of private_key") ); - return EXIT_FAILURE; - } -#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ -#else /* !CONFIG_EXAMPLE_USE_SECURE_ELEMENT && !CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR */ - pNetworkContext->pcClientCert = client_cert_start; - pNetworkContext->pcClientCertSize = client_cert_end - client_cert_start; - pNetworkContext->pcClientKey = client_key_start; - pNetworkContext->pcClientKeySize = client_key_end - client_key_start; -#endif /* CONFIG_EXAMPLE_USE_SECURE_ELEMENT */ - - /* Retrieve the address location and length from S3_PRESIGNED_GET_URL. */ - if( pUrl != NULL ) - { - /* Retrieve the address location and length from S3_PRESIGNED_GET_URL. */ - httpStatus = getUrlAddress( pUrl, - strlen( pUrl ), - &pAddress, - &serverHostLength ); - - if( httpStatus != HTTPSuccess ) - { - LogError( ( "URL %s parsing failed. Error code: %d", - pUrl, - httpStatus ) ); - } - - /* serverHost should consist only of the host address. */ - memcpy( serverHost, pAddress, serverHostLength ); - serverHost[ serverHostLength ] = '\0'; - } - - if( returnStatus != EXIT_FAILURE ) - { - /* Initialize server information. */ - pNetworkContext->pcHostname = serverHost; - pNetworkContext->xPort = AWS_HTTPS_PORT; - - /* ALPN is required when communicating to AWS IoT Core over port 443 through HTTP. */ - if( AWS_HTTPS_PORT == 443 ) - { - static const char * pcAlpnProtocols[] = { NULL, NULL }; - pcAlpnProtocols[0] = IOT_CORE_ALPN_PROTOCOL_NAME; - pNetworkContext->pAlpnProtos = pcAlpnProtocols; - - } else { - pNetworkContext->pAlpnProtos = NULL; - } - - /* Establish a TLS session with the HTTP server. This example connects - * to the HTTP server as specified in SERVER_HOST and HTTPS_PORT in - * demo_config.h. */ - LogInfo( ( "Establishing a TLS session with %s:%d.", - serverHost, - AWS_HTTPS_PORT ) ); - - tlsStatus = xTlsConnect ( pNetworkContext ); - - returnStatus = ( tlsStatus == TLS_TRANSPORT_SUCCESS ) ? EXIT_SUCCESS : EXIT_FAILURE; - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static OtaHttpStatus_t handleHttpResponse( const HTTPResponse_t * pResponse ) -{ - /* Return error code. */ - OtaHttpStatus_t ret = OtaHttpRequestFailed; - - OtaEventData_t * pData; - OtaEventMsg_t eventMsg = { 0 }; - - switch( pResponse->statusCode ) - { - case HTTP_RESPONSE_PARTIAL_CONTENT: - /* Get buffer to send event & data. */ - pData = otaEventBufferGet(); - - if( pData != NULL ) - { - /* Get the data from response buffer. */ - memcpy( pData->data, pResponse->pBody, pResponse->bodyLen ); - pData->dataLength = pResponse->bodyLen; - - /* Send job document received event. */ - eventMsg.eventId = OtaAgentEventReceivedFileBlock; - eventMsg.pEventData = pData; - OTA_SignalEvent( &eventMsg ); - - ret = OtaHttpSuccess; - } - else - { - LogError( ( "Error: No OTA data buffers available." ) ); - - ret = OtaHttpRequestFailed; - } - - break; - - case HTTP_RESPONSE_BAD_REQUEST: - case HTTP_RESPONSE_FORBIDDEN: - case HTTP_RESPONSE_NOT_FOUND: - /* Request the job document to get new url. */ - eventMsg.eventId = OtaAgentEventRequestJobDocument; - eventMsg.pEventData = NULL; - OTA_SignalEvent( &eventMsg ); - - ret = OtaHttpSuccess; - break; - - default: - LogError( ( "Unhandled http response code: =%d.", - pResponse->statusCode ) ); - - ret = OtaHttpRequestFailed; - } - - return ret; -} - -static OtaHttpStatus_t httpInit( char * pUrl ) -{ - /* OTA lib return error code. */ - OtaHttpStatus_t ret = OtaHttpSuccess; - - /* HTTPS Client library return status. */ - HTTPStatus_t httpStatus = HTTPSuccess; - - /* Return value from libraries. */ - int32_t returnStatus = EXIT_SUCCESS; - - /* The length of the path within the pre-signed URL. This variable is - * defined in order to store the length returned from parsing the URL, but - * it is unused. The path used for the requests in this demo needs all the - * query information following the location of the object, to the end of the - * S3 presigned URL. */ - size_t pathLen = 0; - - /* Establish HTTPs connection */ - LogInfo( ( "Performing TLS handshake on top of the TCP connection." ) ); - - /* Attempt to connect to the HTTPs server. If connection fails, retry after - * a timeout. Timeout value will be exponentially increased till the maximum - * attempts are reached or maximum timeout value is reached. The function - * returns EXIT_FAILURE if the TCP connection cannot be established to - * broker after configured number of attempts. */ - returnStatus = connectToS3Server( &networkContextHttp, pUrl ); - - if( returnStatus == EXIT_SUCCESS ) - { - /* Define the transport interface. */ - ( void ) memset( &transportInterfaceHttp, 0, sizeof( transportInterfaceHttp ) ); - transportInterfaceHttp.recv = espTlsTransportRecv; - transportInterfaceHttp.send = espTlsTransportSend; - transportInterfaceHttp.pNetworkContext = &networkContextHttp; - transportInterfaceHttp.writev = NULL; - - /* Retrieve the path location from url. This - * function returns the length of the path without the query into - * pathLen, which is left unused in this demo. */ - httpStatus = getUrlPath( pUrl, - strlen( pUrl ), - &pPath, - &pathLen ); - - ret = ( httpStatus == HTTPSuccess ) ? OtaHttpSuccess : OtaHttpInitFailed; - } - else - { - /* Log an error to indicate connection failure after all - * reconnect attempts are over. */ - LogError( ( "Failed to connect to HTTP server %s.", - serverHost ) ); - - ret = OtaHttpInitFailed; - } - - return ret; -} - -static OtaHttpStatus_t httpRequest( uint32_t rangeStart, - uint32_t rangeEnd ) -{ - /* OTA lib return error code. */ - OtaHttpStatus_t ret = OtaHttpSuccess; - - /* Configurations of the initial request headers that are passed to - * #HTTPClient_InitializeRequestHeaders. */ - HTTPRequestInfo_t requestInfo; - /* Represents a response returned from an HTTP server. */ - HTTPResponse_t response; - /* Represents header data that will be sent in an HTTP request. */ - HTTPRequestHeaders_t requestHeaders; - - /* Return value of all methods from the HTTP Client library API. */ - HTTPStatus_t httpStatus = HTTPSuccess; - - /* Reconnection required flag. */ - bool reconnectRequired = false; - - /* Initialize all HTTP Client library API structs to 0. */ - ( void ) memset( &requestInfo, 0, sizeof( requestInfo ) ); - ( void ) memset( &response, 0, sizeof( response ) ); - ( void ) memset( &requestHeaders, 0, sizeof( requestHeaders ) ); - - /* Initialize the request object. */ - requestInfo.pHost = serverHost; - requestInfo.hostLen = serverHostLength; - requestInfo.pMethod = HTTP_METHOD_GET; - requestInfo.methodLen = sizeof( HTTP_METHOD_GET ) - 1; - requestInfo.pPath = pPath; - requestInfo.pathLen = strlen( pPath ); - - /* Set "Connection" HTTP header to "keep-alive" so that multiple requests - * can be sent over the same established TCP connection. */ - requestInfo.reqFlags = HTTP_REQUEST_KEEP_ALIVE_FLAG; - - /* Set the buffer used for storing request headers. */ - requestHeaders.pBuffer = httpUserBuffer; - requestHeaders.bufferLen = HTTP_USER_BUFFER_LENGTH; - - httpStatus = HTTPClient_InitializeRequestHeaders( &requestHeaders, - &requestInfo ); - - HTTPClient_AddRangeHeader( &requestHeaders, rangeStart, rangeEnd ); - - if( httpStatus == HTTPSuccess ) - { - /* Initialize the response object. The same buffer used for storing - * request headers is reused here. */ - response.pBuffer = httpUserBuffer; - response.bufferLen = HTTP_USER_BUFFER_LENGTH; - - /* Send the request and receive the response. */ - httpStatus = HTTPClient_Send( &transportInterfaceHttp, - &requestHeaders, - NULL, - 0, - &response, - 0 ); - } - else - { - LogError( ( "Failed to initialize HTTP request headers: Error=%s.", - HTTPClient_strerror( httpStatus ) ) ); - } - - if( httpStatus != HTTPSuccess ) - { - if( ( httpStatus == HTTPNoResponse ) || ( httpStatus == HTTPNetworkError ) ) - { - reconnectRequired = true; - } - else - { - LogError( ( "HTTPClient_Send failed: Error=%s.", - HTTPClient_strerror( httpStatus ) ) ); - - ret = OtaHttpRequestFailed; - } - } - else - { - /* Check if reconnection required. */ - if( response.respFlags & HTTP_RESPONSE_CONNECTION_CLOSE_FLAG ) - { - reconnectRequired = true; - } - - /* Handle the http response received. */ - ret = handleHttpResponse( &response ); - } - - if( reconnectRequired == true ) - { - /* End TLS session, then close TCP connection. */ - cleanupESPSecureMgrCerts( &networkContextHttp ); - ( void ) xTlsDisconnect( &networkContextHttp ); - - /* Try establishing connection to S3 server again. */ - if( connectToS3Server( &networkContextHttp, NULL ) == EXIT_SUCCESS ) - { - ret = OtaHttpSuccess; - } - else - { - /* Log an error to indicate connection failure after all - * reconnect attempts are over. */ - LogError( ( "Failed to connect to HTTP server %s.", - serverHost ) ); - - ret = OtaHttpRequestFailed; - } - } - - return ret; -} - -static OtaHttpStatus_t httpDeinit( void ) -{ - OtaHttpStatus_t ret = OtaHttpSuccess; - - /* Nothing special to do here .*/ - - return ret; -} - - -/*-----------------------------------------------------------*/ - -static void registerSubscriptionManagerCallback( const char * pTopicFilter, - uint16_t topicFilterLength ) -{ - bool isMatch = false; - MQTTStatus_t mqttStatus = MQTTSuccess; - SubscriptionManagerStatus_t subscriptionStatus = SUBSCRIPTION_MANAGER_SUCCESS; - - uint16_t index = 0U; - - /* For suppressing compiler-warning: unused variable. */ - ( void ) mqttStatus; - - /* Lookup table for OTA message string. */ - static const char * const pWildCardTopicFilters[] = - { - OTA_TOPIC_PREFIX OTA_TOPIC_JOBS "/#", - OTA_TOPIC_PREFIX OTA_TOPIC_STREAM "/#" - }; - - /* Match the input topic filter against the wild-card pattern of topics filters - * relevant for the OTA Update service to determine the type of topic filter. */ - for( ; index < 2; index++ ) - { - mqttStatus = MQTT_MatchTopic( pTopicFilter, - topicFilterLength, - pWildCardTopicFilters[ index ], - strlen( pWildCardTopicFilters[ index ] ), - &isMatch ); - assert( mqttStatus == MQTTSuccess ); - - if( isMatch ) - { - /* Register callback to subscription manager. */ - subscriptionStatus = SubscriptionManager_RegisterCallback( pWildCardTopicFilters[ index ], - strlen( pWildCardTopicFilters[ index ] ), - otaMessageCallback[ index ] ); - - if( subscriptionStatus != SUBSCRIPTION_MANAGER_SUCCESS ) - { - LogWarn( ( "Failed to register a callback to subscription manager with error = %d.", - subscriptionStatus ) ); - } - - break; - } - } -} - - - -/*-----------------------------------------------------------*/ - -static OtaMqttStatus_t mqttSubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t qos ) -{ - OtaMqttStatus_t otaRet = OtaMqttSuccess; - - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTContext_t * pMqttContext = &mqttContext; - MQTTSubscribeInfo_t pSubscriptionList[ 1 ]; - - assert( pMqttContext != NULL ); - assert( pTopicFilter != NULL ); - assert( topicFilterLength > 0 ); - - ( void ) qos; - - /* Start with everything at 0. */ - ( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) ); - - /* Set the topic and topic length. */ - pSubscriptionList[ 0 ].pTopicFilter = pTopicFilter; - pSubscriptionList[ 0 ].topicFilterLength = topicFilterLength; - - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Send SUBSCRIBE packet. */ - mqttStatus = MQTT_Subscribe( pMqttContext, - pSubscriptionList, - sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ), - MQTT_GetPacketId( pMqttContext ) ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mqtt mutex for executing MQTT_Subscribe" - ",errno=%s", - strerror( errno ) ) ); - } - - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to send SUBSCRIBE packet to broker with error = %u.", - mqttStatus ) ); - - otaRet = OtaMqttSubscribeFailed; - } - else - { - LogInfo( ( "SUBSCRIBE topic %.*s to broker.\n\n", - topicFilterLength, - pTopicFilter ) ); - - registerSubscriptionManagerCallback( pTopicFilter, topicFilterLength ); - } - - return otaRet; -} - -static OtaMqttStatus_t mqttPublish( const char * const pTopic, - uint16_t topicLen, - const char * pMsg, - uint32_t msgSize, - uint8_t qos ) -{ - OtaMqttStatus_t otaRet = OtaMqttSuccess; - - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTPublishInfo_t publishInfo = { 0 }; - MQTTContext_t * pMqttContext = &mqttContext; - BackoffAlgorithmStatus_t backoffAlgStatus = BackoffAlgorithmSuccess; - BackoffAlgorithmContext_t reconnectParams; - uint16_t nextRetryBackOff; - - - /* Initialize reconnect attempts and interval */ - BackoffAlgorithm_InitializeParams( &reconnectParams, - CONNECTION_RETRY_BACKOFF_BASE_MS, - CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS, - MQTT_PUBLISH_RETRY_MAX_ATTEMPS ); - - /* Set the required publish parameters. */ - publishInfo.pTopicName = pTopic; - publishInfo.topicNameLength = topicLen; - publishInfo.qos = qos; - publishInfo.pPayload = pMsg; - publishInfo.payloadLength = msgSize; - - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - do - { - mqttStatus = MQTT_Publish( pMqttContext, - &publishInfo, - MQTT_GetPacketId( pMqttContext ) ); - - if( qos == 1 ) - { - /* Loop to receive packet from transport interface. */ - mqttStatus = MQTT_ReceiveLoop( &mqttContext ); - } - - if( mqttStatus != MQTTSuccess && mqttStatus != MQTTNeedMoreBytes ) - { - /* Generate a random number and get back-off value (in milliseconds) for the next connection retry. */ - backoffAlgStatus = BackoffAlgorithm_GetNextBackoff( &reconnectParams, generateRandomNumber(), &nextRetryBackOff ); - - if( backoffAlgStatus == BackoffAlgorithmRetriesExhausted ) - { - LogError( ( "Publish failed, all attempts exhausted." ) ); - } - else if( backoffAlgStatus == BackoffAlgorithmSuccess ) - { - LogWarn( ( "Publish failed. Retrying connection " - "after %hu ms backoff.", - ( unsigned short ) nextRetryBackOff ) ); - Clock_SleepMs( nextRetryBackOff ); - } - } - } while( ( mqttStatus != MQTTSuccess ) && ( backoffAlgStatus == BackoffAlgorithmSuccess ) ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mqtt mutex for executing MQTT_Publish" - ",errno=%s", - strerror( errno ) ) ); - } - - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to send PUBLISH packet to broker with error = %u.", mqttStatus ) ); - - otaRet = OtaMqttPublishFailed; - } - else - { - LogInfo( ( "Sent PUBLISH packet to broker %.*s to broker.\n\n", - topicLen, - pTopic ) ); - } - - return otaRet; -} - -/*-----------------------------------------------------------*/ - -static OtaMqttStatus_t mqttUnsubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t qos ) -{ - OtaMqttStatus_t otaRet = OtaMqttSuccess; - MQTTStatus_t mqttStatus = MQTTBadParameter; - - MQTTSubscribeInfo_t pSubscriptionList[ 1 ]; - MQTTContext_t * pMqttContext = &mqttContext; - - ( void ) qos; - - /* Start with everything at 0. */ - ( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) ); - - /* Set the QoS , topic and topic length. */ - pSubscriptionList[ 0 ].qos = qos; - pSubscriptionList[ 0 ].pTopicFilter = pTopicFilter; - pSubscriptionList[ 0 ].topicFilterLength = topicFilterLength; - - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Send UNSUBSCRIBE packet. */ - mqttStatus = MQTT_Unsubscribe( pMqttContext, - pSubscriptionList, - sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ), - MQTT_GetPacketId( pMqttContext ) ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mutex for executing MQTT_Unsubscribe" - ",errno=%s", - strerror( errno ) ) ); - } - - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to send UNSUBSCRIBE packet to broker with error = %u.", - mqttStatus ) ); - - otaRet = OtaMqttUnsubscribeFailed; - } - else - { - LogInfo( ( "UNSUBSCRIBE topic %.*s to broker.\n\n", - topicFilterLength, - pTopicFilter ) ); - } - - return otaRet; -} - -/*-----------------------------------------------------------*/ - -static void setOtaInterfaces( OtaInterfaces_t * pOtaInterfaces ) -{ - /* Initialize OTA library OS Interface. */ - pOtaInterfaces->os.event.init = OtaInitEvent_FreeRTOS; - pOtaInterfaces->os.event.send = OtaSendEvent_FreeRTOS; - pOtaInterfaces->os.event.recv = OtaReceiveEvent_FreeRTOS; - pOtaInterfaces->os.event.deinit = OtaDeinitEvent_FreeRTOS; - pOtaInterfaces->os.timer.start = OtaStartTimer_FreeRTOS; - pOtaInterfaces->os.timer.stop = OtaStopTimer_FreeRTOS; - pOtaInterfaces->os.timer.delete = OtaDeleteTimer_FreeRTOS; - pOtaInterfaces->os.mem.malloc = Malloc_FreeRTOS; - pOtaInterfaces->os.mem.free = Free_FreeRTOS; - - /* Initialize the OTA library MQTT Interface.*/ - pOtaInterfaces->mqtt.subscribe = mqttSubscribe; - pOtaInterfaces->mqtt.publish = mqttPublish; - pOtaInterfaces->mqtt.unsubscribe = mqttUnsubscribe; - - /* Initialize the OTA library HTTP Interface.*/ - pOtaInterfaces->http.init = httpInit; - pOtaInterfaces->http.request = httpRequest; - pOtaInterfaces->http.deinit = httpDeinit; - - /* Initialize the OTA library PAL Interface.*/ - pOtaInterfaces->pal.getPlatformImageState = otaPal_GetPlatformImageState; - pOtaInterfaces->pal.setPlatformImageState = otaPal_SetPlatformImageState; - pOtaInterfaces->pal.writeBlock = otaPal_WriteBlock; - pOtaInterfaces->pal.activate = otaPal_ActivateNewImage; - pOtaInterfaces->pal.closeFile = otaPal_CloseFile; - pOtaInterfaces->pal.reset = otaPal_ResetDevice; - pOtaInterfaces->pal.abort = otaPal_Abort; - pOtaInterfaces->pal.createFile = otaPal_CreateFileForRx; -} - -/*-----------------------------------------------------------*/ - -static void * otaThread( void * pParam ) -{ - /* Calling OTA agent task. */ - OTA_EventProcessingTask( pParam ); - LogInfo( ( "OTA Agent stopped." ) ); - return NULL; -} - -/*-----------------------------------------------------------*/ -static int startOTADemo( void ) -{ - /* Status indicating a successful demo or not. */ - int returnStatus = EXIT_SUCCESS; - - /* coreMQTT library return status. */ - MQTTStatus_t mqttStatus = MQTTBadParameter; - - /* OTA library return status. */ - OtaErr_t otaRet = OtaErrNone; - - /* OTA Agent state returned from calling OTA_GetState.*/ - OtaState_t state = OtaAgentStateStopped; - - /* OTA event message used for sending event to OTA Agent.*/ - OtaEventMsg_t eventMsg = { 0 }; - - /* OTA library packet statistics per job.*/ - OtaAgentStatistics_t otaStatistics = { 0 }; - - /* OTA Agent thread handle.*/ - pthread_t threadHandle; - - /* Status return from call to pthread_join. */ - int returnJoin = 0; - - /* OTA interface context required for library interface functions.*/ - OtaInterfaces_t otaInterfaces; - - /* Maximum time to wait for the OTA agent to get suspended. */ - int16_t suspendTimeout; - - /* Set OTA Library interfaces.*/ - setOtaInterfaces( &otaInterfaces ); - - /* Set OTA Code Signing Certificate */ - if( !otaPal_SetCodeSigningCertificate( pcAwsCodeSigningCertPem ) ) - { - LogError( ( "Failed to allocate memory for Code Signing Certificate" ) ); - returnStatus = EXIT_FAILURE; - } - - /****************************** Init OTA Library. ******************************/ - - if( returnStatus == EXIT_SUCCESS ) - { - if( ( otaRet = OTA_Init( &otaBuffer, - &otaInterfaces, - ( const uint8_t * ) ( CLIENT_IDENTIFIER ), - otaAppCallback ) ) != OtaErrNone ) - { - LogError( ( "Failed to initialize OTA Agent, exiting = %u.", - otaRet ) ); - - returnStatus = EXIT_FAILURE; - } - } - - /****************************** Create OTA Task. ******************************/ - - if( returnStatus == EXIT_SUCCESS ) - { - if( pthread_create( &threadHandle, NULL, otaThread, NULL ) != 0 ) - { - LogError( ( "Failed to create OTA thread: " - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - } - - /****************************** OTA Demo loop. ******************************/ - - if( returnStatus == EXIT_SUCCESS ) - { - /* Wait till OTA library is stopped, output statistics for currently running - * OTA job */ - while( ( ( state = OTA_GetState() ) != OtaAgentStateStopped ) ) - { - if( mqttSessionEstablished != true ) - { - /* Connect to MQTT broker and create MQTT connection. */ - if( EXIT_SUCCESS == establishConnection() ) - { - mqttSessionEstablished = true; - - /* Check if OTA process was suspended and resume if required. */ - if( state == OtaAgentStateSuspended ) - { - /* Resume OTA operations. */ - OTA_Resume(); - } - else - { - /* Send start event to OTA Agent.*/ - eventMsg.eventId = OtaAgentEventStart; - OTA_SignalEvent( &eventMsg ); - } - } - } - - if( mqttSessionEstablished == true ) - { - /* Acquire the mqtt mutex lock. */ - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Loop to receive packet from transport interface. */ - mqttStatus = MQTT_ProcessLoop( &mqttContext ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mutex to execute process loop" - ",errno=%s", - strerror( errno ) ) ); - } - - if( ( mqttStatus == MQTTSuccess ) || ( mqttStatus == MQTTNeedMoreBytes ) ) - { - /* Get OTA statistics for currently executing job. */ - OTA_GetStatistics( &otaStatistics ); - - LogInfo( ( " Received: %"PRIu32" Queued: %"PRIu32" Processed: %"PRIu32" Dropped: %"PRIu32"", - otaStatistics.otaPacketsReceived, - otaStatistics.otaPacketsQueued, - otaStatistics.otaPacketsProcessed, - otaStatistics.otaPacketsDropped ) ); - - Clock_SleepMs( OTA_EXAMPLE_LOOP_SLEEP_PERIOD_MS ); - } - else - { - LogError( ( "MQTT_ProcessLoop returned with status = %s.", - MQTT_Status_strerror( mqttStatus ) ) ); - - /* Disconnect from broker and close connection. */ - disconnect(); - - /* Set connection flag to false. */ - mqttSessionEstablished = false; - - /* Suspend OTA operations. */ - otaRet = OTA_Suspend(); - - if( otaRet != OtaErrNone ) - { - LogError( ( "OTA failed to suspend. " - "StatusCode=%d.", otaRet ) ); - } - else - { - suspendTimeout = OTA_SUSPEND_TIMEOUT_MS; - - while( ( ( state = OTA_GetState() ) != OtaAgentStateSuspended ) && ( suspendTimeout > 0 ) ) - { - /* Wait for OTA Library state to suspend */ - Clock_SleepMs( OTA_EXAMPLE_TASK_DELAY_MS ); - suspendTimeout -= OTA_EXAMPLE_TASK_DELAY_MS; - } - } - } - } - } - } - - /****************************** Wait for OTA Thread. ******************************/ - - if( returnStatus == EXIT_SUCCESS ) - { - returnJoin = pthread_join( threadHandle, NULL ); - - if( returnJoin != 0 ) - { - LogError( ( "Failed to join thread" - ",error code = %d", - returnJoin ) ); - - returnStatus = EXIT_FAILURE; - } - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -/** - * @brief Entry point of demo. - * - * This example initializes the OTA library to enable OTA updates via the - * MQTT broker. It simply connects to the MQTT broker with the users - * credentials and spins in an indefinite loop to allow MQTT messages to be - * forwarded to the OTA agent for possible processing. The OTA agent does all - * of the real work; checking to see if the message topic is one destined for - * the OTA agent. If not, it is simply ignored. - */ -int aws_iot_demo_main( int argc, - char ** argv ) -{ - ( void ) argc; - ( void ) argv; - - /* Return error status. */ - int returnStatus = EXIT_SUCCESS; - - /* Semaphore initialization flag. */ - bool bufferSemInitialized = false; - bool ackSemInitialized = false; - bool mqttMutexInitialized = false; - - /* Maximum time in milliseconds to wait before exiting demo . */ - int16_t waitTimeoutMs = OTA_DEMO_EXIT_TIMEOUT_MS; - - LogInfo( ( "OTA over HTTP demo, Application version %u.%u.%u", - appFirmwareVersion.u.x.major, - appFirmwareVersion.u.x.minor, - appFirmwareVersion.u.x.build ) ); - - /* Initialize semaphore for buffer operations. */ - if( osi_sem_new( &bufferSemaphore, 0x7FFFU, 1 ) != 0 ) - { - LogError( ( "Failed to initialize buffer semaphore" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - else - { - bufferSemInitialized = true; - } - - /* Initialize semaphore for ack. */ - if( osi_sem_new( &ackSemaphore, 0x7FFFU, 0 ) != 0 ) - { - LogError( ( "Failed to initialize ack semaphore" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - else - { - ackSemInitialized = true; - } - - /* Initialize mutex for coreMQTT APIs. */ - if( pthread_mutex_init( &mqttMutex, NULL ) != 0 ) - { - LogError( ( "Failed to initialize mutex for mqtt apis" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - else - { - mqttMutexInitialized = true; - } - - if( returnStatus == EXIT_SUCCESS ) - { - /* Initialize MQTT library. Initialization of the MQTT library needs to be - * done only once in this demo. */ - returnStatus = initializeMqtt( &mqttContext, &networkContextMqtt ); - } - - if( returnStatus == EXIT_SUCCESS ) - { - /* Start OTA demo. */ - returnStatus = startOTADemo(); - } - - /* Disconnect from broker and close connection. */ - disconnect(); - - /* Disconnect from S3 and close connection. */ - cleanupESPSecureMgrCerts( &networkContextHttp ); - xTlsDisconnect( &networkContextHttp ); - - if( bufferSemInitialized == true ) - { - /* Cleanup semaphore created for buffer operations. */ - if( osi_sem_free( &bufferSemaphore ) != 0 ) - { - LogError( ( "Failed to destroy buffer semaphore" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - } - - if( ackSemInitialized == true ) - { - /* Cleanup semaphore created for ack. */ - if( osi_sem_free( &ackSemaphore ) != 0 ) - { - LogError( ( "Failed to destroy ack semaphore" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - } - - if( mqttMutexInitialized == true ) - { - /* Cleanup mutex created for buffer operations. */ - if( pthread_mutex_destroy( &mqttMutex ) != 0 ) - { - LogError( ( "Failed to destroy mutex for mqtt apis" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - } - - /* Wait and log message before exiting demo. */ - while( waitTimeoutMs > 0 ) - { - Clock_SleepMs( OTA_EXAMPLE_TASK_DELAY_MS ); - waitTimeoutMs -= OTA_EXAMPLE_TASK_DELAY_MS; - - LogError( ( "Exiting demo in %d sec", waitTimeoutMs / 1000 ) ); - } - - return returnStatus; -} diff --git a/examples/ota/ota_http/ota_http_demo.csv b/examples/ota/ota_http/ota_http_demo.csv deleted file mode 100644 index bd0d168af..000000000 --- a/examples/ota/ota_http/ota_http_demo.csv +++ /dev/null @@ -1,3 +0,0 @@ -key,type,encoding,value -creds,namespace,, -P11_CSK,file,string,./main/certs/P11_CSK.crt diff --git a/examples/ota/ota_http/partitions_ota_http.csv b/examples/ota/ota_http/partitions_ota_http.csv deleted file mode 100644 index b7bfb33f6..000000000 --- a/examples/ota/ota_http/partitions_ota_http.csv +++ /dev/null @@ -1,9 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap -pre_prov, 0x3F, , 0xD000, 0x6000, encrypted -nvs, data, nvs, , 0x4000, -otadata, data, ota, , 0x2000, -phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, , 1200K, -ota_1, app, ota_1, , 1200K, -storage, data, nvs, , 0x4000, \ No newline at end of file diff --git a/examples/ota/ota_http/sdkconfig.defaults b/examples/ota/ota_http/sdkconfig.defaults deleted file mode 100644 index 98521f42e..000000000 --- a/examples/ota/ota_http/sdkconfig.defaults +++ /dev/null @@ -1,21 +0,0 @@ -# newlib for ESP32 and ESP8266 platform - -CONFIG_NEWLIB_ENABLE=y -CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y -CONFIG_NEWLIB_NANO_FORMAT= -CONFIG_SSL_USING_MBEDTLS=y -CONFIG_LWIP_IPV6=y -CONFIG_MBEDTLS_THREADING_C=y -# CONFIG_MBEDTLS_THREADING_ALT is not set -CONFIG_MBEDTLS_THREADING_PTHREAD=y -CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192 -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_ota_http.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions_ota_http.csv" -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y -CONFIG_MBEDTLS_CMAC_C=y -CONFIG_OTA_DATA_OVER_HTTP=y -CONFIG_OTA_DATA_OVER_MQTT=n -CONFIG_OTA_DATA_OVER_HTTP_PRIMARY=y -CONFIG_OTA_DATA_OVER_MQTT_PRIMARY=n diff --git a/examples/ota/ota_http/sdkconfig.defaults.esp32c2 b/examples/ota/ota_http/sdkconfig.defaults.esp32c2 deleted file mode 100644 index d3966e587..000000000 --- a/examples/ota/ota_http/sdkconfig.defaults.esp32c2 +++ /dev/null @@ -1,21 +0,0 @@ -CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y -CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y -CONFIG_SPI_FLASH_ROM_IMPL=y - -# Wi-Fi -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=4 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=n -CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=n -CONFIG_ESP32_WIFI_IRAM_OPT=n -CONFIG_ESP32_WIFI_RX_IRAM_OPT=n - -# LWIP -CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=16 - -# mbedTLS -CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2048 -CONFIG_MBEDTLS_DYNAMIC_BUFFER=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y diff --git a/examples/ota/ota_http/sdkconfig.defaults.esp32s2 b/examples/ota/ota_http/sdkconfig.defaults.esp32s2 deleted file mode 100644 index d3966e587..000000000 --- a/examples/ota/ota_http/sdkconfig.defaults.esp32s2 +++ /dev/null @@ -1,21 +0,0 @@ -CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y -CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y -CONFIG_SPI_FLASH_ROM_IMPL=y - -# Wi-Fi -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=4 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=n -CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=n -CONFIG_ESP32_WIFI_IRAM_OPT=n -CONFIG_ESP32_WIFI_RX_IRAM_OPT=n - -# LWIP -CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=16 - -# mbedTLS -CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2048 -CONFIG_MBEDTLS_DYNAMIC_BUFFER=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y diff --git a/examples/ota/ota_mqtt/CMakeLists.txt b/examples/ota/ota_mqtt/CMakeLists.txt deleted file mode 100644 index d8745e3c0..000000000 --- a/examples/ota/ota_mqtt/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/aws-iot-core-mqtt-file-streams-embedded-c" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/coreMQTT" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/corePKCS11" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/coreJSON" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/backoffAlgorithm" - "${CMAKE_CURRENT_LIST_DIR}/../../../libraries/common/posix_compat" - ) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(ota_mqtt) - -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/root_cert_auth.crt" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/client.crt" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/client.key" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/certs/aws_codesign.crt" TEXT) \ No newline at end of file diff --git a/examples/ota/ota_mqtt/README.md b/examples/ota/ota_mqtt/README.md deleted file mode 100644 index d363fe337..000000000 --- a/examples/ota/ota_mqtt/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Steps to run OTA over MQTT Demo - -1. Ensure that you have followed all the prerequisites for OTA Update from the [Amazon FreeRTOS Docs](https://docs.aws.amazon.com/freertos/latest/userguide/ota-prereqs.html). - -2. Create a code signing certificate for ESP32, as shown [here](https://docs.aws.amazon.com/freertos/latest/userguide/ota-code-sign-cert-esp.html). -Ensure that keep the `ecdsasigner.crt` file handy, it will be needed in subsequent steps. - -3. Grant access to code signing, for AWS IoT, as shown [here](https://docs.aws.amazon.com/freertos/latest/userguide/code-sign-policy.html). - -4. Now, to create an OTA update job, using the AWS IoT console, follow the steps mentioned [here](https://docs.aws.amazon.com/freertos/latest/userguide/ota-console-workflow.html). -For **"Path name of code signing certificate on device"**, put the following value: -``` -Code Verify Key -``` -This corresponds to `pkcs11configLABEL_CODE_VERIFICATION_KEY` in the `core_pkcs11_config.h` file. - -For **"Path name of file on device"**, put an arbitrary value such as: -``` -/ -``` - -5. Replace the contents of the file `main/certs/aws_codesign.crt` with the content from the file `ecdsasigner.crt` - -> The code-signing public key certificate will be used by the application binary i.e. the demo, to authenticate a binary that was downloaded for an update (this downloaded firmware would have been signed by the certificate's corresponding private key i.e. `ecdsasigner.key`). - -6. `idf.py menuconfig` and set MQTT endpoint. - -7. `idf.py build flash monitor` \ No newline at end of file diff --git a/examples/ota/ota_mqtt/main/CMakeLists.txt b/examples/ota/ota_mqtt/main/CMakeLists.txt deleted file mode 100644 index e0411b34c..000000000 --- a/examples/ota/ota_mqtt/main/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -set(COMPONENT_SRCS - "app_main.c" - "ota_demo_core_mqtt.c" - "mqtt_subscription_manager.c" - ) - -set(COMPONENT_ADD_INCLUDEDIRS - "." - "${PROJECT_DIR}/../../../libraries/common/logging/" - "${PROJECT_DIR}/../../../libraries/common/posix_compat/" - ) - -idf_component_register(SRCS "${COMPONENT_SRCS}" - INCLUDE_DIRS ${COMPONENT_ADD_INCLUDEDIRS} - ) \ No newline at end of file diff --git a/examples/ota/ota_mqtt/main/FreeRTOSIPConfig.h b/examples/ota/ota_mqtt/main/FreeRTOSIPConfig.h deleted file mode 100644 index 6eee3aff7..000000000 --- a/examples/ota/ota_mqtt/main/FreeRTOSIPConfig.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * FreeRTOS Kernel V10.2.0 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://aws.amazon.com/freertos - * http://www.FreeRTOS.org - */ - - -/***************************************************************************** -* -* See the following URL for configuration information. -* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html -* -*****************************************************************************/ - -#ifndef FREERTOS_IP_CONFIG_H -#define FREERTOS_IP_CONFIG_H - -/* Prototype for the function used to print out. In this case it prints to the - * console before the network is connected then a UDP port after the network has - * connected. */ -extern void vLoggingPrintf( const char * pcFormatString, - ... ); - -/* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to - * 1 then FreeRTOS_debug_printf should be defined to the function used to print - * out the debugging messages. */ -#define ipconfigHAS_DEBUG_PRINTF 0 -#if ( ipconfigHAS_DEBUG_PRINTF == 1 ) - #define FreeRTOS_debug_printf( X ) configPRINTF( X ) -#endif - -/* Set to 1 to print out non debugging messages, for example the output of the - * FreeRTOS_netstat() command, and ping replies. If ipconfigHAS_PRINTF is set to 1 - * then FreeRTOS_printf should be set to the function used to print out the - * messages. */ -#define ipconfigHAS_PRINTF 1 -#if ( ipconfigHAS_PRINTF == 1 ) - #define FreeRTOS_printf( X ) configPRINTF( X ) - /* Allow monitoring the message queue of the IP-task. */ - #define ipconfigCHECK_IP_QUEUE_SPACE 1 -#endif - -/* Define the byte order of the target MCU (the MCU FreeRTOS+TCP is executing - * on). Valid options are pdFREERTOS_BIG_ENDIAN and pdFREERTOS_LITTLE_ENDIAN. */ -#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN - -/* If the network card/driver includes checksum offloading (IP/TCP/UDP checksums) - * then set ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to 1 to prevent the software - * stack repeating the checksum calculations. */ -#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 - -/* TX checksum offloading has NOT been implemented in the Wi-Fi of ESP32. */ -#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 0 - -/* Several API's will block until the result is known, or the action has been - * performed, for example FreeRTOS_send() and FreeRTOS_recv(). The timeouts can be - * set per socket, using setsockopt(). If not set, the times below will be - * used as defaults. */ -#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME ( 500 ) -#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME ( 500 ) - -/* Include support for DNS caching. For TCP, having a small DNS cache is very - * useful. When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low - * and also DNS may use small timeouts. If a DNS reply comes in after the DNS - * socket has been destroyed, the result will be stored into the cache. The next - * call to FreeRTOS_gethostbyname() will return immediately, without even creating - * a socket. - */ -#define ipconfigUSE_DNS_CACHE ( 1 ) -#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ( 6 ) -#define ipconfigDNS_REQUEST_ATTEMPTS ( 2 ) - -/* The IP stack executes it its own task (although any application task can make - * use of its services through the published sockets API). ipconfigUDP_TASK_PRIORITY - * sets the priority of the task that executes the IP stack. The priority is a - * standard FreeRTOS task priority so can take any value from 0 (the lowest - * priority) to (configMAX_PRIORITIES - 1) (the highest priority). - * configMAX_PRIORITIES is a standard FreeRTOS configuration parameter defined in - * FreeRTOSConfig.h, not FreeRTOSIPConfig.h. Consideration needs to be given as to - * the priority assigned to the task executing the IP stack relative to the - * priority assigned to tasks that use the IP stack. */ -#define ipconfigIP_TASK_PRIORITY ( configMAX_PRIORITIES - 7U ) - -/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP - * task. This setting is less important when the FreeRTOS Win32 simulator is used - * as the Win32 simulator only stores a fixed amount of information on the task - * stack. FreeRTOS includes optional stack overflow detection, see: - * http://www.freertos.org/Stacks-and-stack-overflow-checking.html. */ -#define ipconfigIP_TASK_STACK_SIZE_WORDS ( configMINIMAL_STACK_SIZE * 5U ) - -/* ipconfigRAND32() is called by the IP stack to generate random numbers for - * things such as a DHCP transaction number or initial sequence number. Random - * number generation is performed via this macro to allow applications to use their - * own random number generation method. For example, it might be possible to - * generate a random number by sampling noise on an analogue input. */ -extern uint32_t ulRand(); -#define ipconfigRAND32() ulRand() - -/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the - * network event hook at the appropriate times. If ipconfigUSE_NETWORK_EVENT_HOOK - * is not set to 1 then the network event hook will never be called. See: - * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml. - */ -#define ipconfigUSE_NETWORK_EVENT_HOOK 1 - -/* Sockets have a send block time attribute. If FreeRTOS_sendto() is called but - * a network buffer cannot be obtained then the calling task is held in the Blocked - * state (so other tasks can continue to executed) until either a network buffer - * becomes available or the send block time expires. If the send block time expires - * then the send operation is aborted. The maximum allowable send block time is - * capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS. Capping the - * maximum allowable send block time prevents prevents a deadlock occurring when - * all the network buffers are in use and the tasks that process (and subsequently - * free) the network buffers are themselves blocked waiting for a network buffer. - * ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks. A time in - * milliseconds can be converted to a time in ticks by dividing the time in - * milliseconds by portTICK_PERIOD_MS. */ -#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000U / portTICK_PERIOD_MS ) - -/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP - * address, netmask, DNS server address and gateway address from a DHCP server. If - * ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address. The - * stack will revert to using the static IP address even when ipconfigUSE_DHCP is - * set to 1 if a valid configuration cannot be obtained from a DHCP server for any - * reason. The static configuration used is that passed into the stack by the - * FreeRTOS_IPInit() function call. */ -#define ipconfigUSE_DHCP 1 -#define ipconfigDHCP_REGISTER_HOSTNAME 1 -#define ipconfigDHCP_USES_UNICAST 1 - -/* If ipconfigDHCP_USES_USER_HOOK is set to 1 then the application writer must - * provide an implementation of the DHCP callback function, - * xApplicationDHCPUserHook(). */ -#define ipconfigUSE_DHCP_HOOK 0 - -/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at - * increasing time intervals until either a reply is received from a DHCP server - * and accepted, or the interval between transmissions reaches - * ipconfigMAXIMUM_DISCOVER_TX_PERIOD. The IP stack will revert to using the - * static IP address passed as a parameter to FreeRTOS_IPInit() if the - * re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without - * a DHCP reply being received. */ -#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD \ - ( 120000U / portTICK_PERIOD_MS ) - -/* The ARP cache is a table that maps IP addresses to MAC addresses. The IP - * stack can only send a UDP message to a remove IP address if it knowns the MAC - * address associated with the IP address, or the MAC address of the router used to - * contact the remote IP address. When a UDP message is received from a remote IP - * address the MAC address and IP address are added to the ARP cache. When a UDP - * message is sent to a remote IP address that does not already appear in the ARP - * cache then the UDP message is replaced by a ARP message that solicits the - * required MAC address information. ipconfigARP_CACHE_ENTRIES defines the maximum - * number of entries that can exist in the ARP table at any one time. */ -#define ipconfigARP_CACHE_ENTRIES 6 - -/* ARP requests that do not result in an ARP response will be re-transmitted a - * maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is - * aborted. */ -#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 ) - -/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP - * table being created or refreshed and the entry being removed because it is stale. - * New ARP requests are sent for ARP cache entries that are nearing their maximum - * age. ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is - * equal to 1500 seconds (or 25 minutes). */ -#define ipconfigMAX_ARP_AGE 150 - -/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling - * routines, which are relatively large. To save code space the full - * FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster - * alternative called FreeRTOS_inet_addr_quick() is provided. FreeRTOS_inet_addr() - * takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter. - * FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets - * (for example, 192, 168, 0, 1) as its parameters. If - * ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and - * FreeRTOS_indet_addr_quick() are available. If ipconfigINCLUDE_FULL_INET_ADDR is - * not set to 1 then only FreeRTOS_indet_addr_quick() is available. */ -#define ipconfigINCLUDE_FULL_INET_ADDR 1 - -/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that - * are available to the IP stack. The total number of network buffers is limited - * to ensure the total amount of RAM that can be consumed by the IP stack is capped - * to a pre-determinable value. */ -#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 60U - -/* A FreeRTOS queue is used to send events from application tasks to the IP - * stack. ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can - * be queued for processing at any one time. The event queue must be a minimum of - * 5 greater than the total number of network buffers. */ -#define ipconfigEVENT_QUEUE_LENGTH \ - ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5U ) - -/* The address of a socket is the combination of its IP address and its port - * number. FreeRTOS_bind() is used to manually allocate a port number to a socket - * (to 'bind' the socket to a port), but manual binding is not normally necessary - * for client sockets (those sockets that initiate outgoing connections rather than - * wait for incoming connections on a known port number). If - * ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling - * FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP - * stack automatically binding the socket to a port number from the range - * socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff. If - * ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto() - * on a socket that has not yet been bound will result in the send operation being - * aborted. */ -#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1 - -/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */ -#define ipconfigUDP_TIME_TO_LIVE 128 -/* Also defined in FreeRTOSIPConfigDefaults.h. */ -#define ipconfigTCP_TIME_TO_LIVE 128 - -/* USE_TCP: Use TCP and all its features. */ -#define ipconfigUSE_TCP ( 1 ) - -/* USE_WIN: Let TCP use windowing mechanism. */ -#define ipconfigUSE_TCP_WIN ( 1 ) - -/* The MTU is the maximum number of bytes the payload of a network frame can - * contain. For normal Ethernet V2 frames the maximum MTU is 1500. Setting a - * lower value can save RAM. */ -#define ipconfigNETWORK_MTU 1460U - -/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver. DNS is used - * through the FreeRTOS_gethostbyname() API function. */ -#define ipconfigUSE_DNS 1 - -/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will - * generate replies to incoming ICMP echo (ping) requests. */ -#define ipconfigREPLY_TO_INCOMING_PINGS 1 - -/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the - * FreeRTOS_SendPingRequest() API function is available. */ -#define ipconfigSUPPORT_OUTGOING_PINGS 0 - -/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select() - * (and associated) API function is available. */ -#define ipconfigSUPPORT_SELECT_FUNCTION 0 - -/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames - * that are not in Ethernet II format will be dropped. This option is included for - * potential future IP stack developments. */ -#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1 - -/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the - * responsibility of the Ethernet interface to filter out packets that are of no - * interest. If the Ethernet interface does not implement this functionality, then - * set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack - * perform the filtering instead (it is much less efficient for the stack to do it - * because the packet will already have been passed into the stack). If the - * Ethernet driver does all the necessary filtering in hardware then software - * filtering can be removed by using a value other than 1 or 0. */ -#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 - -/* The windows simulator cannot really simulate MAC interrupts, and needs to - * block occasionally to allow other tasks to run. */ -#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 20 / portTICK_PERIOD_MS ) - -/* Advanced only: in order to access 32-bit fields in the IP packets with - * 32-bit memory instructions, all packets will be stored 32-bit-aligned, - * plus 16-bits. This has to do with the contents of the IP-packets: all - * 32-bit fields are 32-bit-aligned, plus 16-bit. */ -#define ipconfigPACKET_FILLER_SIZE 2U - -/* Define the size of the pool of TCP window descriptors. On the average, each - * TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6 - * outstanding packets (for Rx and Tx). When using up to 10 TP sockets - * simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */ -#define ipconfigTCP_WIN_SEG_COUNT 240 - -/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed - * maximum size. Define the size of Rx buffer for TCP sockets. */ -#define ipconfigTCP_RX_BUFFER_LENGTH ( 3000 ) - -/* Define the size of Tx buffer for TCP sockets. */ -#define ipconfigTCP_TX_BUFFER_LENGTH ( 3000 ) - -/* When using call-back handlers, the driver may check if the handler points to - * real program memory (RAM or flash) or just has a random non-zero value. */ -#define ipconfigIS_VALID_PROG_ADDRESS( x ) ( ( x ) != NULL ) - -/* Include support for TCP keep-alive messages. */ -#define ipconfigTCP_KEEP_ALIVE ( 1 ) -#define ipconfigTCP_KEEP_ALIVE_INTERVAL ( 20 ) /* Seconds. */ - -/* The socket semaphore is used to unblock the MQTT task. */ -#define ipconfigSOCKET_HAS_USER_SEMAPHORE ( 0 ) - -#define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK ( 1 ) -#define ipconfigUSE_CALLBACKS ( 0 ) - - -#define portINLINE __inline - -void vApplicationMQTTGetKeys( const char ** ppcRootCA, - const char ** ppcClientCert, - const char ** ppcClientPrivateKey ); - -#endif /* FREERTOS_IP_CONFIG_H */ diff --git a/examples/ota/ota_mqtt/main/Kconfig.projbuild b/examples/ota/ota_mqtt/main/Kconfig.projbuild deleted file mode 100644 index 338954d36..000000000 --- a/examples/ota/ota_mqtt/main/Kconfig.projbuild +++ /dev/null @@ -1,70 +0,0 @@ -menu "Example Configuration" - - config MQTT_CLIENT_IDENTIFIER - string "The MQTT client identifier used in this example" - default "testClient" - help - The MQTT client identifier used in this example. Each client identifier must be unique. - so edit as required to ensure that no two clients connecting to the same broker use the same client identifier. - - config MQTT_BROKER_ENDPOINT - string "Endpoint of the MQTT broker to connect to" - default "test.mosquitto.org" - help - This example can be run with any MQTT broker, that supports server authentication. - - config MQTT_BROKER_PORT - int "Port of the MQTT broker use" - default 8883 - help - In general, port 8883 is for secured MQTT connections. - Port 443 requires use of the ALPN TLS extension with the ALPN protocol name. - When using port 8883, ALPN is not required. - - config HARDWARE_PLATFORM_NAME - string "The hardware platform" - default "ESP32" - help - The name of the hardware platform the application is running on. - - config MQTT_NETWORK_BUFFER_SIZE - int "Size of the network buffer for MQTT packets" - range 1024 2048 - default 1024 - help - Size of the network buffer for MQTT packets. - - choice EXAMPLE_CHOOSE_PKI_ACCESS_METHOD - prompt "Choose PKI credentials access method" - default EXAMPLE_USE_PLAIN_FLASH_STORAGE - help - ESP devices support multiple ways to secure store the PKI credentials. - Currently Secure Element (ATECC608A) and DS peripheral - (using ESP Secure Cert Manager) are supported. - The default behaviour is to access the PKI credentials which are embedded in the binary. - Consult the ESP-TLS documentation in ESP-IDF Programming guide for more details. - - config EXAMPLE_USE_SECURE_ELEMENT - bool "Use secure element (ATECC608A)" - depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32C2) && ESP_TLS_USING_MBEDTLS - # To confirm that we are satisfying the dependencies of secure element - select ESP_TLS_USE_SECURE_ELEMENT - help - Enable the use of secure element for the example. - The esp-cryptoauthlib component is required for enabling - this option. - - config EXAMPLE_USE_ESP_SECURE_CERT_MGR - bool "Use ESP Secure Certificate Manager" - help - Enable the use of ESP Secure Certificate Manager APIs for the example. - Please refer to ESP Secure Certificate Manager documentation for more details. - - config EXAMPLE_USE_PLAIN_FLASH_STORAGE - bool "Use flash storage (default)" - help - This option expects the Private key and Device certificate to be embedded in the binary. - This is the default behaviour. - endchoice - -endmenu diff --git a/examples/ota/ota_mqtt/main/app_main.c b/examples/ota/ota_mqtt/main/app_main.c deleted file mode 100644 index 7e26a0b6c..000000000 --- a/examples/ota/ota_mqtt/main/app_main.c +++ /dev/null @@ -1,54 +0,0 @@ -/* ota_mqtt example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -int aws_iot_demo_main( int argc, char ** argv ); - -#include "esp_log.h" - -static const char *TAG = "OTA_MQTT"; - -void app_main() -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %"PRIu32" bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - - /* Initialize NVS partition */ - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - /* NVS partition was truncated - * and needs to be erased */ - ESP_ERROR_CHECK(nvs_flash_erase()); - - /* Retry nvs_flash_init */ - ESP_ERROR_CHECK(nvs_flash_init()); - } - - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - aws_iot_demo_main(0,NULL); -} diff --git a/examples/ota/ota_mqtt/main/certs/aws_codesign.crt b/examples/ota/ota_mqtt/main/certs/aws_codesign.crt deleted file mode 100644 index fc9db06fb..000000000 --- a/examples/ota/ota_mqtt/main/certs/aws_codesign.crt +++ /dev/null @@ -1,10 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBcDCCARagAwIBAgIUYNy4lAy9AREPtp+bBG0chiEDUQMwCgYIKoZIzj0EAwIw -JTEjMCEGA1UEAwwaZGhhdmFsLmd1amFyQGVzcHJlc3NpZi5jb20wHhcNMjEwNzA2 -MTI0MTA5WhcNMjIwNzA2MTI0MTA5WjAlMSMwIQYDVQQDDBpkaGF2YWwuZ3VqYXJA -ZXNwcmVzc2lmLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI/b7P+Y2c6f -PAD0fC2DCwaAUT/cplFr4AwyYjYk4qlAnBaEbltmukvZKIjkIct7sNEK0rbXSNf1 -/QHDWu2hqkmjJDAiMAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAK -BggqhkjOPQQDAgNIADBFAiEA6kjPuxXvyKEnavPC0R2B+uR3nTntrkiszXPuwbMA -CxICIGUnuxeOEx7SAT1O9G6b/k3oNxDf4xjzgHs7dcaSxwAo ------END CERTIFICATE----- diff --git a/examples/ota/ota_mqtt/main/certs/client.crt b/examples/ota/ota_mqtt/main/certs/client.crt deleted file mode 100644 index 6459f31e3..000000000 --- a/examples/ota/ota_mqtt/main/certs/client.crt +++ /dev/null @@ -1 +0,0 @@ -Certificate goes here. \ No newline at end of file diff --git a/examples/ota/ota_mqtt/main/certs/client.key b/examples/ota/ota_mqtt/main/certs/client.key deleted file mode 100644 index f6ef61476..000000000 --- a/examples/ota/ota_mqtt/main/certs/client.key +++ /dev/null @@ -1 +0,0 @@ -Key goes here. \ No newline at end of file diff --git a/examples/ota/ota_mqtt/main/certs/root_cert_auth.crt b/examples/ota/ota_mqtt/main/certs/root_cert_auth.crt deleted file mode 100644 index 350356673..000000000 --- a/examples/ota/ota_mqtt/main/certs/root_cert_auth.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- - diff --git a/examples/ota/ota_mqtt/main/demo_config.h b/examples/ota/ota_mqtt/main/demo_config.h deleted file mode 100644 index b93f4655e..000000000 --- a/examples/ota/ota_mqtt/main/demo_config.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202103.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef DEMO_CONFIG_H_ -#define DEMO_CONFIG_H_ - -/**************************************************/ -/******* DO NOT CHANGE the following order ********/ -/**************************************************/ - -/* Logging related header files are required to be included in the following order: - * 1. Include the header file "logging_levels.h". - * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. - * 3. Include the header file "logging_stack.h". - */ - -/* Include header that defines log levels. */ -#include "logging_levels.h" - -/* Logging configuration for the Demo. */ -#ifndef LIBRARY_LOG_NAME - #define LIBRARY_LOG_NAME "OTA_MQTT_DEMO" -#endif -#ifndef LIBRARY_LOG_LEVEL - #define LIBRARY_LOG_LEVEL LOG_INFO -#endif - -#include "logging_stack.h" - -/************ End of logging configuration ****************/ - -/** - * @brief Details of the MQTT broker to connect to. - * - * @note Your AWS IoT Core endpoint can be found in the AWS IoT console under - * Settings/Custom Endpoint, or using the describe-endpoint API. - * - */ -#define AWS_IOT_ENDPOINT CONFIG_MQTT_BROKER_ENDPOINT - -/** - * @brief AWS IoT MQTT broker port number. - * - * In general, port 8883 is for secured MQTT connections. - * - * @note Port 443 requires use of the ALPN TLS extension with the ALPN protocol - * name. When using port 8883, ALPN is not required. - */ -#define AWS_MQTT_PORT ( CONFIG_MQTT_BROKER_PORT ) - -/** - * @brief MQTT client identifier. - * - * No two clients may use the same client identifier simultaneously. - */ -#ifndef CLIENT_IDENTIFIER - #define CLIENT_IDENTIFIER CONFIG_MQTT_CLIENT_IDENTIFIER -#endif - -/** - * @brief Configure application version. - */ - -#define APP_VERSION_MAJOR 0 -#define APP_VERSION_MINOR 9 -#define APP_VERSION_BUILD 2 - -/** - * @brief The name of the operating system that the application is running on. - * The current value is given as an example. Please update for your specific - * operating system. - */ -#define OS_NAME "FreeRTOS" - -/** - * @brief The version of the operating system that the application is running - * on. The current value is given as an example. Please update for your specific - * operating system version. - */ -#define OS_VERSION tskKERNEL_VERSION_NUMBER - -/** - * @brief The name of the hardware platform the application is running on. The - * current value is given as an example. Please update for your specific - * hardware platform. - */ -#define HARDWARE_PLATFORM_NAME CONFIG_HARDWARE_PLATFORM_NAME - -/** - * @brief The name of the library used and its version, following an "@" - * symbol. - */ -#define OTA_LIB "otalib@1.0.0" - -#endif /* ifndef DEMO_CONFIG_H */ diff --git a/examples/ota/ota_mqtt/main/idf_component.yml b/examples/ota/ota_mqtt/main/idf_component.yml deleted file mode 100644 index 473313cbc..000000000 --- a/examples/ota/ota_mqtt/main/idf_component.yml +++ /dev/null @@ -1,7 +0,0 @@ -## IDF Component Manager Manifest File -dependencies: - espressif/esp_secure_cert_mgr: "^2.0.5" - espressif/cbor: - version: ">=0.5.4,<1.0.0" - rules: - - if: "idf_version >=5.0" \ No newline at end of file diff --git a/examples/ota/ota_mqtt/main/mqtt_subscription_manager.c b/examples/ota/ota_mqtt/main/mqtt_subscription_manager.c deleted file mode 100644 index 8535f109f..000000000 --- a/examples/ota/ota_mqtt/main/mqtt_subscription_manager.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202103.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @file mqtt_subscription_manager.c - * @brief Implementation of the API of a subscription manager for handling subscription callbacks - * to topic filters in MQTT operations. - */ - -/* Standard includes. */ -#include -#include - -/* Include demo config. */ -#include "demo_config.h" - -/* Include header for the subscription manager. */ -#include "mqtt_subscription_manager.h" - - -/** - * @brief Represents a registered record of the topic filter and its associated callback - * in the subscription manager registry. - */ -typedef struct SubscriptionManagerRecord -{ - const char * pTopicFilter; - uint16_t topicFilterLength; - SubscriptionManagerCallback_t callback; -} SubscriptionManagerRecord_t; - -/** - * @brief The default value for the maximum size of the callback registry in the - * subscription manager. - */ -#ifndef MAX_SUBSCRIPTION_CALLBACK_RECORDS - #define MAX_SUBSCRIPTION_CALLBACK_RECORDS 5 -#endif - -/** - * @brief The registry to store records of topic filters and their subscription callbacks. - */ -static SubscriptionManagerRecord_t callbackRecordList[ MAX_SUBSCRIPTION_CALLBACK_RECORDS ] = { 0 }; - -/*-----------------------------------------------------------*/ - -void SubscriptionManager_DispatchHandler( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ) -{ - bool matchStatus = false; - size_t listIndex = 0u; - - assert( pPublishInfo != NULL ); - assert( pContext != NULL ); - - /* Iterate through record list to find matching topics, and invoke their callbacks. */ - for( listIndex = 0; listIndex < MAX_SUBSCRIPTION_CALLBACK_RECORDS; listIndex++ ) - { - if( ( callbackRecordList[ listIndex ].pTopicFilter != NULL ) && - ( MQTT_MatchTopic( pPublishInfo->pTopicName, - pPublishInfo->topicNameLength, - callbackRecordList[ listIndex ].pTopicFilter, - callbackRecordList[ listIndex ].topicFilterLength, - &matchStatus ) == MQTTSuccess ) && - ( matchStatus == true ) ) - { - LogInfo( ( "Invoking subscription callback of matching topic filter: " - "TopicFilter=%.*s, TopicName=%.*s", - callbackRecordList[ listIndex ].topicFilterLength, - callbackRecordList[ listIndex ].pTopicFilter, - pPublishInfo->topicNameLength, - pPublishInfo->pTopicName ) ); - - /* Invoke the callback associated with the record as the topics match. */ - callbackRecordList[ listIndex ].callback( pContext, pPublishInfo ); - } - } -} - -/*-----------------------------------------------------------*/ - -SubscriptionManagerStatus_t SubscriptionManager_RegisterCallback( const char * pTopicFilter, - uint16_t topicFilterLength, - SubscriptionManagerCallback_t callback ) -{ - assert( pTopicFilter != NULL ); - assert( topicFilterLength != 0 ); - assert( callback != NULL ); - - SubscriptionManagerStatus_t returnStatus; - size_t availableIndex = MAX_SUBSCRIPTION_CALLBACK_RECORDS; - bool recordExists = false; - size_t index = 0u; - - /* Search for the first available spot in the list to store the record, and also check if - * a record for the topic filter already exists. */ - while( ( recordExists == false ) && ( index < MAX_SUBSCRIPTION_CALLBACK_RECORDS ) ) - { - /* Check if the index represents an empty spot in the registry. If we had already - * found an empty spot in the list, we will not update it. */ - if( ( availableIndex == MAX_SUBSCRIPTION_CALLBACK_RECORDS ) && - ( callbackRecordList[ index ].pTopicFilter == NULL ) ) - { - availableIndex = index; - } - - /* Check if the current record's topic filter in the registry matches the topic filter - * we are trying to register. */ - else if( ( callbackRecordList[ index ].topicFilterLength == topicFilterLength ) && - ( strncmp( pTopicFilter, callbackRecordList[ index ].pTopicFilter, topicFilterLength ) - == 0 ) ) - { - recordExists = true; - } - - index++; - } - - if( recordExists == true ) - { - /* The record for the topic filter already exists. */ - LogError( ( "Failed to register callback: Record for topic filter already exists: TopicFilter=%.*s", - topicFilterLength, - pTopicFilter ) ); - - returnStatus = SUBSCRIPTION_MANAGER_RECORD_EXISTS; - } - else if( availableIndex == MAX_SUBSCRIPTION_CALLBACK_RECORDS ) - { - /* The registry is full. */ - LogError( ( "Unable to register callback: Registry list is full: TopicFilter=%.*s, MaxRegistrySize=%u", - topicFilterLength, - pTopicFilter, - MAX_SUBSCRIPTION_CALLBACK_RECORDS ) ); - - returnStatus = SUBSCRIPTION_MANAGER_REGISTRY_FULL; - } - else - { - callbackRecordList[ availableIndex ].pTopicFilter = pTopicFilter; - callbackRecordList[ availableIndex ].topicFilterLength = topicFilterLength; - callbackRecordList[ availableIndex ].callback = callback; - - returnStatus = SUBSCRIPTION_MANAGER_SUCCESS; - - LogDebug( ( "Added callback to registry: TopicFilter=%.*s", - topicFilterLength, - pTopicFilter ) ); - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -void SubscriptionManager_RemoveCallback( const char * pTopicFilter, - uint16_t topicFilterLength ) -{ - assert( pTopicFilter != NULL ); - assert( topicFilterLength != 0 ); - - size_t index; - SubscriptionManagerRecord_t * pRecord = NULL; - - /* Iterate through the records list to find the matching record. */ - for( index = 0; index < MAX_SUBSCRIPTION_CALLBACK_RECORDS; index++ ) - { - pRecord = &callbackRecordList[ index ]; - - /* Only match the non-empty records. */ - if( pRecord->pTopicFilter != NULL ) - { - if( ( topicFilterLength == pRecord->topicFilterLength ) && - ( strncmp( pTopicFilter, pRecord->pTopicFilter, topicFilterLength ) == 0 ) ) - { - break; - } - } - } - - /* Delete the record by clearing the found entry in the records list. */ - if( index < MAX_SUBSCRIPTION_CALLBACK_RECORDS ) - { - pRecord->pTopicFilter = NULL; - pRecord->topicFilterLength = 0u; - pRecord->callback = NULL; - - LogDebug( ( "Deleted callback record for topic filter: TopicFilter=%.*s", - topicFilterLength, - pTopicFilter ) ); - } - else - { - LogWarn( ( "Attempted to remove callback for un-registered topic filter: TopicFilter=%.*s", - topicFilterLength, - pTopicFilter ) ); - } -} -/*-----------------------------------------------------------*/ diff --git a/examples/ota/ota_mqtt/main/mqtt_subscription_manager.h b/examples/ota/ota_mqtt/main/mqtt_subscription_manager.h deleted file mode 100644 index 03ca72b77..000000000 --- a/examples/ota/ota_mqtt/main/mqtt_subscription_manager.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202108.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @file mqtt_subscription_manager.h - * @brief The API of a subscription manager for handling subscription callbacks - * to topic filters in MQTT operations. - */ - -#ifndef MQTT_SUBSCRIPTION_MANAGER_H_ -#define MQTT_SUBSCRIPTION_MANAGER_H_ - -/**************************************************/ -/******* DO NOT CHANGE the following order ********/ -/**************************************************/ - -/* Logging related header files are required to be included in the following order: - * 1. Include the header file "logging_levels.h". - * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. - * 3. Include the header file "logging_stack.h". - */ - -/* Include header that defines log levels. */ -#include "logging_levels.h" - -/* Logging configuration for the Subscription Manager module. */ -#ifndef LIBRARY_LOG_NAME - #define LIBRARY_LOG_NAME "Subscription Manager" -#endif -#ifndef LIBRARY_LOG_LEVEL - #define LIBRARY_LOG_LEVEL LOG_DEBUG -#endif - -#include "logging_stack.h" - -/************ End of logging configuration ****************/ - -/* Include MQTT library. */ -#include "core_mqtt.h" - -/* Enumeration type for return status value from Subscription Manager API. */ -typedef enum SubscriptionManagerStatus -{ - /** - * @brief Success return value from Subscription Manager API. - */ - SUBSCRIPTION_MANAGER_SUCCESS = 1, - - /** - * @brief Failure return value due to registry being full. - */ - SUBSCRIPTION_MANAGER_REGISTRY_FULL = 2, - - /** - * @brief Failure return value due to an already existing record in the - * registry for a new callback registration's requested topic filter. - */ - SUBSCRIPTION_MANAGER_RECORD_EXISTS = 3 -} SubscriptionManagerStatus_t; - - -/** - * @brief Callback type to be registered for a topic filter with the subscription manager. - * - * For incoming PUBLISH messages received on topics that match the registered topic filter, - * the callback would be invoked by the subscription manager. - * - * @param[in] pContext The context associated with the MQTT connection. - * @param[in] pPublishInfo The incoming PUBLISH message information. - */ -typedef void (* SubscriptionManagerCallback_t )( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ); - -/** - * @brief Dispatches the incoming PUBLISH message to the callbacks that have their - * registered topic filters matching the incoming PUBLISH topic name. The dispatch - * handler will invoke all these callbacks with matching topic filters. - * - * @param[in] pContext The context associated with the MQTT connection. - * @param[in] pPublishInfo The incoming PUBLISH message information. - */ -void SubscriptionManager_DispatchHandler( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ); - -/** - * @brief Utility to register a callback for a topic filter in the subscription manager. - * - * The callback will be invoked when an incoming PUBLISH message is received on - * a topic that matches the topic filter, @a pTopicFilter. The subscription manager - * accepts wildcard topic filters. - * - * @param[in] pTopicFilter The topic filter to register the callback for. - * @param[in] topicFilterLength The length of the topic filter string. - * @param[in] callback The callback to be registered for the topic filter. - * - * @note The subscription manager does not allow more than one callback to be registered - * for the same topic filter. - * @note The passed topic filter, @a pTopicFilter, is saved in the registry. - * The application must not free or alter the content of the topic filter memory - * until the callback for the topic filter is removed from the subscription manager. - * - * @return Returns one of the following: - * - #SUBSCRIPTION_MANAGER_SUCCESS if registration of the callback is successful. - * - #SUBSCRIPTION_MANAGER_REGISTRY_FULL if the registration failed due to registry - * being already full. - * - #SUBSCRIPTION_MANAGER_RECORD_EXISTS, if a registered callback already exists for - * the requested topic filter in the subscription manager. - */ -SubscriptionManagerStatus_t SubscriptionManager_RegisterCallback( const char * pTopicFilter, - uint16_t topicFilterLength, - SubscriptionManagerCallback_t pCallback ); - -/** - * @brief Utility to remove the callback registered for a topic filter from the - * subscription manager. - * - * @param[in] pTopicFilter The topic filter to remove from the subscription manager. - * @param[in] topicFilterLength The length of the topic filter string. - */ -void SubscriptionManager_RemoveCallback( const char * pTopicFilter, - uint16_t topicFilterLength ); - - -#endif /* ifndef MQTT_SUBSCRIPTION_MANAGER_H_ */ diff --git a/examples/ota/ota_mqtt/main/ota_demo_core_mqtt.c b/examples/ota/ota_mqtt/main/ota_demo_core_mqtt.c deleted file mode 100644 index 793739a17..000000000 --- a/examples/ota/ota_mqtt/main/ota_demo_core_mqtt.c +++ /dev/null @@ -1,1908 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C 202108.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * @file ota_demo_core_mqtt.c - * @brief OTA update example using coreMQTT. - */ - -/* Standard includes. */ -#include -#include -#include -#include - -/* Include Demo Config as the first non-system header. */ -#include "demo_config.h" - -/* OpenSSL sockets transport implementation. */ -#include "network_transport.h" - -/* Clock for timer. */ -#include "clock.h" - -/* pthread include. */ -#include -#include "semaphore.h" -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_pthread.h" - -/* MQTT include. */ -#include "core_mqtt.h" -#include "mqtt_subscription_manager.h" - -/*Include backoff algorithm header for retry logic.*/ -#include "backoff_algorithm.h" - -/* OTA Library include. */ -#include "ota.h" -#include "ota_config.h" - -/* OTA Library Interface include. */ -#include "ota_os_freertos.h" -#include "ota_mqtt_interface.h" -#include "ota_pal.h" - -/* Include firmware version struct definition. */ -#include "ota_appversion32.h" - -#ifdef CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR - #include "esp_secure_cert_read.h" -#endif - -extern const char root_cert_auth_start[] asm("_binary_root_cert_auth_crt_start"); -extern const char root_cert_auth_end[] asm("_binary_root_cert_auth_crt_end"); - -#ifndef CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR - extern const char client_cert_start[] asm("_binary_client_crt_start"); - extern const char client_cert_end[] asm("_binary_client_crt_end"); - extern const char client_key_start[] asm("_binary_client_key_start"); - extern const char client_key_end[] asm("_binary_client_key_end"); -#endif - -extern const char pcAwsCodeSigningCertPem[] asm("_binary_aws_codesign_crt_start"); - -/** - * @brief ALPN (Application-Layer Protocol Negotiation) protocol name for AWS IoT MQTT. - * - * This will be used if the AWS_MQTT_PORT is configured as 443 for AWS IoT MQTT broker. - * Please see more details about the ALPN protocol for AWS IoT MQTT endpoint - * in the link below. - * https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/ - */ -#define AWS_IOT_MQTT_ALPN "x-amzn-mqtt-ca" - -/** - * @brief Length of ALPN protocol name. - */ -#define AWS_IOT_MQTT_ALPN_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_MQTT_ALPN ) - 1 ) ) - -/** - * @brief Length of MQTT server host name. - */ -#define AWS_IOT_ENDPOINT_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_ENDPOINT ) - 1 ) ) - -/** - * @brief Length of client identifier. - */ -#define CLIENT_IDENTIFIER_LENGTH ( ( uint16_t ) ( sizeof( CLIENT_IDENTIFIER ) - 1 ) ) - -/** - * @brief Transport timeout in milliseconds for transport send and receive. - */ -#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 1500U ) - -/** - * @brief Timeout for receiving CONNACK packet in milli seconds. - */ -#define CONNACK_RECV_TIMEOUT_MS ( 2000U ) - -/** - * @brief The maximum time interval in seconds which is allowed to elapse - * between two Control Packets. - * - * It is the responsibility of the Client to ensure that the interval between - * Control Packets being sent does not exceed the this Keep Alive value. In the - * absence of sending any other Control Packets, the Client MUST send a - * PINGREQ Packet. - */ -#define MQTT_KEEP_ALIVE_INTERVAL_SECONDS ( 60U ) - -/** - * @brief Maximum number or retries to publish a message in case of failures. - */ -#define MQTT_PUBLISH_RETRY_MAX_ATTEMPS ( 3U ) - -/** - * @brief Period for waiting on ack. - */ -#define MQTT_ACK_TIMEOUT_MS ( 5000U ) - -/** - * @brief Period for demo loop sleep in milliseconds. - */ -#define OTA_EXAMPLE_LOOP_SLEEP_PERIOD_MS ( 20U ) - -/** - * @brief Size of the network buffer to receive the MQTT message. - * - * The largest message size is data size from the AWS IoT streaming service, - * otaconfigFILE_BLOCK_SIZE + extra for headers. - */ - -#define OTA_NETWORK_BUFFER_SIZE ( otaconfigFILE_BLOCK_SIZE + 128 ) - -/** - * @brief The delay used in the main OTA Demo task loop to periodically output the OTA - * statistics like number of packets received, dropped, processed and queued per connection. - */ -#define OTA_EXAMPLE_TASK_DELAY_MS ( 1000U ) - -/** - * @brief The timeout for waiting for the agent to get suspended after closing the - * connection. - */ -#define OTA_SUSPEND_TIMEOUT_MS ( 5000U ) - -/** - * @brief The timeout for waiting before exiting the OTA demo. - */ -#define OTA_DEMO_EXIT_TIMEOUT_MS ( 3000U ) - -/** - * @brief The maximum size of the file paths used in the demo. - */ -#define OTA_MAX_FILE_PATH_SIZE ( 260U ) - -/** - * @brief The maximum size of the stream name required for downloading update file - * from streaming service. - */ -#define OTA_MAX_STREAM_NAME_SIZE ( 128U ) - -/** - * @brief The maximum back-off delay (in milliseconds) for retrying connection to server. - */ -#define CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS ( 5000U ) - -/** - * @brief The base back-off delay (in milliseconds) to use for connection retry attempts. - */ -#define CONNECTION_RETRY_BACKOFF_BASE_MS ( 500U ) - -/** - * @brief Number of milliseconds in a second. - */ -#define NUM_MILLISECONDS_IN_SECOND ( 1000U ) - -/** - * @brief The maximum number of retries for connecting to server. - */ -#define CONNECTION_RETRY_MAX_ATTEMPTS ( 5U ) - -/** - * @brief The MQTT metrics string expected by AWS IoT. - */ -#define METRICS_STRING "?SDK=" OS_NAME "&Version=" OS_VERSION "&Platform=" HARDWARE_PLATFORM_NAME "&OTALib=" OTA_LIB - -/** - * @brief The length of the MQTT metrics string expected by AWS IoT. - */ -#define METRICS_STRING_LENGTH ( ( uint16_t ) ( sizeof( METRICS_STRING ) - 1 ) ) - - -#ifdef CLIENT_USERNAME - -/** - * @brief Append the username with the metrics string if #CLIENT_USERNAME is defined. - * - * This is to support both metrics reporting and username/password based client - * authentication by AWS IoT. - */ - #define CLIENT_USERNAME_WITH_METRICS CLIENT_USERNAME METRICS_STRING -#endif - -/** - * @brief The common prefix for all OTA topics. - */ -#define OTA_TOPIC_PREFIX "$aws/things/+/" - -/** - * @brief The string used for jobs topics. - */ -#define OTA_TOPIC_JOBS "jobs" - -/** - * @brief The string used for streaming service topics. - */ -#define OTA_TOPIC_STREAM "streams" - -/** - * @brief The length of the outgoing publish records array used by the coreMQTT - * library to track QoS > 0 packet ACKS for outgoing publishes. - */ -#define OUTGOING_PUBLISH_RECORD_LEN ( 10U ) - -/** - * @brief The length of the incoming publish records array used by the coreMQTT - * library to track QoS > 0 packet ACKS for incoming publishes. - */ -#define INCOMING_PUBLISH_RECORD_LEN ( 10U ) - -/*-----------------------------------------------------------*/ - -/* Linkage for error reporting. */ -extern int errno; - -/** - * @brief Struct for firmware version. - */ -const AppVersion32_t appFirmwareVersion = -{ - .u.x.major = APP_VERSION_MAJOR, - .u.x.minor = APP_VERSION_MINOR, - .u.x.build = APP_VERSION_BUILD, -}; - -/** - * @brief Static buffer for TLS Context Semaphore. - */ -static StaticSemaphore_t xTlsContextSemaphoreBuffer; - -/** - * @brief Network connection context used in this demo. - */ -static NetworkContext_t networkContext; - -/** - * @brief MQTT connection context used in this demo. - */ -static MQTTContext_t mqttContext; - -/** - * @brief Keep a flag for indicating if the MQTT connection is alive. - */ -static bool mqttSessionEstablished = false; - -/** - * @brief Mutex for synchronizing coreMQTT API calls. - */ -static pthread_mutex_t mqttMutex; - -/** - * @brief Semaphore for synchronizing buffer operations. - */ -// static osi_sem_t bufferSemaphore; -static osi_sem_t bufferSemaphore; - -/** - * @brief Semaphore for synchronizing wait for ack. - */ -static osi_sem_t ackSemaphore; - -/** - * @brief Enum for type of OTA job messages received. - */ -typedef enum jobMessageType -{ - jobMessageTypeNextGetAccepted = 0, - jobMessageTypeNextNotify, - jobMessageTypeMax -} jobMessageType_t; - -/** - * @brief The network buffer must remain valid when OTA library task is running. - */ -static uint8_t otaNetworkBuffer[ OTA_NETWORK_BUFFER_SIZE ]; - -/** - * @brief Update File path buffer. - */ -uint8_t updateFilePath[ OTA_MAX_FILE_PATH_SIZE ]; - -/** - * @brief Certificate File path buffer. - */ -uint8_t certFilePath[ OTA_MAX_FILE_PATH_SIZE ]; - -/** - * @brief Stream name buffer. - */ -uint8_t streamName[ OTA_MAX_STREAM_NAME_SIZE ]; - -/** - * @brief Decode memory. - */ -uint8_t decodeMem[ otaconfigFILE_BLOCK_SIZE ]; - -/** - * @brief Bitmap memory. - */ -uint8_t bitmap[ OTA_MAX_BLOCK_BITMAP_SIZE ]; - -/** - * @brief Event buffer. - */ -static OtaEventData_t eventBuffer[ otaconfigMAX_NUM_OTA_DATA_BUFFERS ]; - -/** - * @brief The buffer passed to the OTA Agent from application while initializing. - */ -static OtaAppBuffer_t otaBuffer = -{ - .pUpdateFilePath = updateFilePath, - .updateFilePathsize = OTA_MAX_FILE_PATH_SIZE, - .pCertFilePath = certFilePath, - .certFilePathSize = OTA_MAX_FILE_PATH_SIZE, - .pStreamName = streamName, - .streamNameSize = OTA_MAX_STREAM_NAME_SIZE, - .pDecodeMemory = decodeMem, - .decodeMemorySize = otaconfigFILE_BLOCK_SIZE, - .pFileBitmap = bitmap, - .fileBitmapSize = OTA_MAX_BLOCK_BITMAP_SIZE -}; - -/** - * @brief Array to track the outgoing publish records for outgoing publishes - * with QoS > 0. - * - * This is passed into #MQTT_InitStatefulQoS to allow for QoS > 0. - * - */ -static MQTTPubAckInfo_t pOutgoingPublishRecords[ OUTGOING_PUBLISH_RECORD_LEN ]; - -/** - * @brief Array to track the incoming publish records for incoming publishes - * with QoS > 0. - * - * This is passed into #MQTT_InitStatefulQoS to allow for QoS > 0. - * - */ -static MQTTPubAckInfo_t pIncomingPublishRecords[ INCOMING_PUBLISH_RECORD_LEN ]; - -/*-----------------------------------------------------------*/ - -int aws_iot_demo_main( int argc, char ** argv ); - -/** - * @brief Sends an MQTT CONNECT packet over the already connected TCP socket. - * - * @param[in] pMqttContext MQTT context pointer. - * @param[in] createCleanSession Creates a new MQTT session if true. - * If false, tries to establish the existing session if there was session - * already present in broker. - * @param[out] pSessionPresent Session was already present in the broker or not. - * Session present response is obtained from the CONNACK from broker. - * - * @return EXIT_SUCCESS if an MQTT session is established; - * EXIT_FAILURE otherwise. - */ -static int establishMqttSession( MQTTContext_t * pMqttContext ); - - -/** - * @brief Publish message to a topic. - * - * This function publishes a message to a given topic & QoS. - * - * @param[in] pacTopic Mqtt topic filter. - * - * @param[in] topicLen Length of the topic filter. - * - * @param[in] pMsg Message to publish. - * - * @param[in] msgSize Message size. - * - * @param[in] qos Quality of Service - * - * @return OtaMqttSuccess if success , other error code on failure. - */ -static OtaMqttStatus_t mqttPublish( const char * const pacTopic, - uint16_t topicLen, - const char * pMsg, - uint32_t msgSize, - uint8_t qos ); - -/** - * @brief Subscribe to the MQTT topic filter, and registers the handler for the topic filter with the subscription manager. - * - * This function subscribes to the Mqtt topics with the Quality of service - * received as parameter. This function also registers a callback for the - * topicfilter. - * - * @param[in] pTopicFilter Mqtt topic filter. - * - * @param[in] topicFilterLength Length of the topic filter. - * - * @param[in] qos Quality of Service - * - * @return OtaMqttSuccess if success , other error code on failure. - */ -static OtaMqttStatus_t mqttSubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t qos ); - -/** - * @brief Unsubscribe to the Mqtt topics. - * - * This function unsubscribes to the Mqtt topics with the Quality of service - * received as parameter. - * - * @param[in] pTopicFilter Mqtt topic filter. - * - * @param[in] topicFilterLength Length of the topic filter. - * - * @param[qos] qos Quality of Service - * - * @return OtaMqttSuccess if success , other error code on failure. - */ -static OtaMqttStatus_t mqttUnsubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t qos ); - -/** - * @brief Thread to call the OTA agent task. - * - * @param[in] pParam Can be used to pass down functionality to the agent task - * @return void* returning null. - */ -static void * otaThread( void * pParam ); - -/** - * @brief Start OTA demo. - * - * The OTA task is created with initializing the OTA agent and - * setting the required interfaces. The demo loop then starts, - * establishing an MQTT connection with the broker and waiting - * for an update. After a successful update the OTA agent requests - * a manual reset to the downloaded executable. - * - * @return EXIT_SUCCESS or EXIT_FAILURE. - */ -static int startOTADemo( void ); - -/** - * @brief Set OTA interfaces. - * - * @param[in] pOtaInterfaces pointer to OTA interface structure. - */ -static void setOtaInterfaces( OtaInterfaces_t * pOtaInterfaces ); - -/** - * @brief Disconnect from the MQTT broker and close connection. - * - */ -static void disconnect( void ); - -/** - * @brief Attempt to connect to the MQTT broker. - * - * @return int EXIT_SUCCESS if a connection is established. - */ -static int establishConnection( void ); - -/** - * @brief Initialize MQTT by setting up transport interface and network. - * - * @param[in] pMqttContext Structure representing MQTT connection. - * @param[in] pNetworkContext Network context to connect on. - * @return int EXIT_SUCCESS if MQTT component is initialized - */ -static int initializeMqtt( MQTTContext_t * pMqttContext, - NetworkContext_t * pNetworkContext ); - -/** - * @brief Retry logic to establish a connection to the server. - * - * If the connection fails, keep retrying with exponentially increasing - * timeout value, until max retries, max timeout or successful connect. - * - * @param[in] pNetworkContext Network context to connect on. - * @return int EXIT_FAILURE if connection failed after retries. - */ -static int connectToServerWithBackoffRetries( NetworkContext_t * pNetworkContext ); - -/** - * @brief Random number to be used as a back-off value for retrying connection. - * - * @return uint32_t The generated random number. - */ -static uint32_t generateRandomNumber(); - -/* Callbacks used to handle different events. */ - -/** - * @brief The OTA agent has completed the update job or it is in - * self test mode. If it was accepted, we want to activate the new image. - * This typically means we should reset the device to run the new firmware. - * If now is not a good time to reset the device, it may be activated later - * by your user code. If the update was rejected, just return without doing - * anything and we'll wait for another job. If it reported that we should - * start test mode, normally we would perform some kind of system checks to - * make sure our new firmware does the basic things we think it should do - * but we'll just go ahead and set the image as accepted for demo purposes. - * The accept function varies depending on your platform. Refer to the OTA - * PAL implementation for your platform in aws_ota_pal.c to see what it - * does for you. - * - * @param[in] event Event from OTA lib of type OtaJobEvent_t. - * @return None. - */ -static void otaAppCallback( OtaJobEvent_t event, - void * pData ); - -/** - * @brief callback to use with the MQTT context to notify incoming packet events. - * - * @param[in] pMqttContext MQTT context which stores the connection. - * @param[in] pPacketInfo Parameters of the incoming packet. - * @param[in] pDeserializedInfo Deserialized packet information to be dispatched by - * the subscription manager to event callbacks. - */ -static void mqttEventCallback( MQTTContext_t * pMqttContext, - MQTTPacketInfo_t * pPacketInfo, - MQTTDeserializedInfo_t * pDeserializedInfo ); - -/** - * @brief Callback registered with the OTA library that notifies the OTA agent - * of an incoming PUBLISH containing a job document. - * - * @param[in] pContext MQTT context which stores the connection. - * @param[in] pPublishInfo MQTT packet information which stores details of the - * job document. - */ -static void mqttJobCallback( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ); - -/** - * @brief Callback that notifies the OTA library when a data block is received. - * - * @param[in] pContext MQTT context which stores the connection. - * @param[in] pPublishInfo MQTT packet that stores the information of the file block. - */ -static void mqttDataCallback( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ); - -static SubscriptionManagerCallback_t otaMessageCallback[] = { mqttJobCallback, mqttDataCallback }; - -/*-----------------------------------------------------------*/ - -void otaEventBufferFree( OtaEventData_t * const pxBuffer ) -{ - if( osi_sem_take( &bufferSemaphore, 0 ) == 0 ) - { - pxBuffer->bufferUsed = false; - ( void ) osi_sem_give( &bufferSemaphore ); - } - else - { - LogError( ( "Failed to get buffer semaphore: " - ",errno=%s", - strerror( errno ) ) ); - } -} - -/*-----------------------------------------------------------*/ - -OtaEventData_t * otaEventBufferGet( void ) -{ - uint32_t ulIndex = 0; - OtaEventData_t * pFreeBuffer = NULL; - - if( osi_sem_take( &bufferSemaphore, 0 ) == 0 ) - { - for( ulIndex = 0; ulIndex < otaconfigMAX_NUM_OTA_DATA_BUFFERS; ulIndex++ ) - { - if( eventBuffer[ ulIndex ].bufferUsed == false ) - { - eventBuffer[ ulIndex ].bufferUsed = true; - pFreeBuffer = &eventBuffer[ ulIndex ]; - break; - } - } - - ( void ) osi_sem_give( &bufferSemaphore ); - } - else - { - LogError( ( "Failed to get buffer semaphore: " - ",errno=%s", - strerror( errno ) ) ); - } - - return pFreeBuffer; -} - -/*-----------------------------------------------------------*/ - -static void otaAppCallback( OtaJobEvent_t event, - void * pData ) -{ - OtaErr_t err = OtaErrUninitialized; - int ret; - - switch( event ) - { - case OtaJobEventActivate: - LogInfo( ( "Received OtaJobEventActivate callback from OTA Agent." ) ); - - /* Activate the new firmware image. */ - OTA_ActivateNewImage(); - - /* Shutdown OTA Agent, if it is required that the unsubscribe operations are not - * performed while shutting down please set the second parameter to 0 instead of 1. */ - OTA_Shutdown( 0, 1 ); - - /* Requires manual activation of new image.*/ - LogError( ( "New image activation failed." ) ); - - break; - - case OtaJobEventFail: - LogInfo( ( "Received OtaJobEventFail callback from OTA Agent." ) ); - - /* Nothing special to do. The OTA agent handles it. */ - break; - - case OtaJobEventStartTest: - - /* This demo just accepts the image since it was a good OTA update and networking - * and services are all working (or we would not have made it this far). If this - * were some custom device that wants to test other things before validating new - * image, this would be the place to kick off those tests before calling - * OTA_SetImageState() with the final result of either accepted or rejected. */ - - LogInfo( ( "Received OtaJobEventStartTest callback from OTA Agent." ) ); - err = OTA_SetImageState( OtaImageStateAccepted ); - - if( err == OtaErrNone ) { - /* Erasing passive partition */ - ret = otaPal_EraseLastBootPartition(); - if (ret != ESP_OK) { - ESP_LOGE("otaAppCallback", "Failed to erase last boot partition! (%d)", ret); - } - } else { - LogError( ( " Failed to set image state as accepted." ) ); - } - - break; - - case OtaJobEventProcessed: - LogDebug( ( "Received OtaJobEventProcessed callback from OTA Agent." ) ); - - if( pData != NULL ) - { - otaEventBufferFree( ( OtaEventData_t * ) pData ); - } - - break; - - case OtaJobEventSelfTestFailed: - LogDebug( ( "Received OtaJobEventSelfTestFailed callback from OTA Agent." ) ); - - /* Requires manual activation of previous image as self-test for - * new image downloaded failed.*/ - LogError( ( "Self-test failed, shutting down OTA Agent." ) ); - - /* Shutdown OTA Agent, if it is required that the unsubscribe operations are not - * performed while shutting down please set the second parameter to 0 instead of 1. */ - OTA_Shutdown( 0, 1 ); - - break; - - default: - LogDebug( ( "Received invalid callback event from OTA Agent." ) ); - } -} - -jobMessageType_t getJobMessageType( const char * pTopicName, - uint16_t topicNameLength ) -{ - uint16_t index = 0U; - MQTTStatus_t mqttStatus = MQTTSuccess; - bool isMatch = false; - jobMessageType_t jobMessageIndex = jobMessageTypeMax; - - /* For suppressing compiler-warning: unused variable. */ - ( void ) mqttStatus; - - /* Lookup table for OTA job message string. */ - static const char * const pJobTopicFilters[ jobMessageTypeMax ] = - { - OTA_TOPIC_PREFIX OTA_TOPIC_JOBS "/$next/get/accepted", - OTA_TOPIC_PREFIX OTA_TOPIC_JOBS "/notify-next", - }; - - /* Match the input topic filter against the wild-card pattern of topics filters - * relevant for the OTA Update service to determine the type of topic filter. */ - for( ; index < jobMessageTypeMax; index++ ) - { - mqttStatus = MQTT_MatchTopic( pTopicName, - topicNameLength, - pJobTopicFilters[ index ], - strlen( pJobTopicFilters[ index ] ), - &isMatch ); - assert( mqttStatus == MQTTSuccess ); - - if( isMatch ) - { - jobMessageIndex = index; - break; - } - } - - return jobMessageIndex; -} - -/*-----------------------------------------------------------*/ - -static void mqttJobCallback( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ) -{ - OtaEventData_t * pData; - OtaEventMsg_t eventMsg = { 0 }; - jobMessageType_t jobMessageType = 0; - - assert( pPublishInfo != NULL ); - assert( pContext != NULL ); - - ( void ) pContext; - - jobMessageType = getJobMessageType( pPublishInfo->pTopicName, pPublishInfo->topicNameLength ); - - switch( jobMessageType ) - { - case jobMessageTypeNextGetAccepted: - case jobMessageTypeNextNotify: - - pData = otaEventBufferGet(); - - if( pData != NULL ) - { - memcpy( pData->data, pPublishInfo->pPayload, pPublishInfo->payloadLength ); - pData->dataLength = pPublishInfo->payloadLength; - eventMsg.eventId = OtaAgentEventReceivedJobDocument; - eventMsg.pEventData = pData; - - /* Send job document received event. */ - OTA_SignalEvent( &eventMsg ); - } - else - { - LogError( ( "No OTA data buffers available." ) ); - } - - break; - - default: -// %zu - LogInfo( ( "Received job message %s size %zu.\n\n", - pPublishInfo->pTopicName, - pPublishInfo->payloadLength ) ); - } -} - -/*-----------------------------------------------------------*/ - -static void mqttDataCallback( MQTTContext_t * pContext, - MQTTPublishInfo_t * pPublishInfo ) -{ - OtaEventData_t * pData; - OtaEventMsg_t eventMsg = { 0 }; - - assert( pPublishInfo != NULL ); - assert( pContext != NULL ); - - ( void ) pContext; - - LogInfo( ( "Received data message callback, size %zu.\n\n", pPublishInfo->payloadLength ) ); - - pData = otaEventBufferGet(); - - if( pData != NULL ) - { - memcpy( pData->data, pPublishInfo->pPayload, pPublishInfo->payloadLength ); - pData->dataLength = pPublishInfo->payloadLength; - eventMsg.eventId = OtaAgentEventReceivedFileBlock; - eventMsg.pEventData = pData; - - /* Send job document received event. */ - OTA_SignalEvent( &eventMsg ); - } - else - { - LogError( ( "No OTA data buffers available." ) ); - } -} - -/*-----------------------------------------------------------*/ - -static void mqttEventCallback( MQTTContext_t * pMqttContext, - MQTTPacketInfo_t * pPacketInfo, - MQTTDeserializedInfo_t * pDeserializedInfo ) -{ - assert( pMqttContext != NULL ); - assert( pPacketInfo != NULL ); - assert( pDeserializedInfo != NULL ); - - /* Handle incoming publish. The lower 4 bits of the publish packet - * type is used for the dup, QoS, and retain flags. Hence masking - * out the lower bits to check if the packet is publish. */ - if( ( pPacketInfo->type & 0xF0U ) == MQTT_PACKET_TYPE_PUBLISH ) - { - assert( pDeserializedInfo->pPublishInfo != NULL ); - /* Handle incoming publish. */ - SubscriptionManager_DispatchHandler( pMqttContext, pDeserializedInfo->pPublishInfo ); - } - else - { - /* Handle other packets. */ - switch( pPacketInfo->type ) - { - case MQTT_PACKET_TYPE_SUBACK: - LogInfo( ( "Received SUBACK.\n\n" ) ); - break; - - case MQTT_PACKET_TYPE_UNSUBACK: - LogInfo( ( "Received UNSUBACK.\n\n" ) ); - break; - - case MQTT_PACKET_TYPE_PINGRESP: - - /* Nothing to be done from application as library handles - * PINGRESP. */ - LogWarn( ( "PINGRESP should not be handled by the application " - "callback when using MQTT_ProcessLoop.\n\n" ) ); - break; - - case MQTT_PACKET_TYPE_PUBACK: - LogInfo( ( "PUBACK received for packet id %u.\n\n", - pDeserializedInfo->packetIdentifier ) ); -// sem_post( &ackSemaphore ); - break; - - /* Any other packet type is invalid. */ - default: - LogError( ( "Unknown packet type received:(%02x).\n\n", - pPacketInfo->type ) ); - } - } -} - -/*-----------------------------------------------------------*/ - -static uint32_t generateRandomNumber() -{ - return( rand() ); -} - -/*-----------------------------------------------------------*/ - -static int initializeMqtt( MQTTContext_t * pMqttContext, - NetworkContext_t * pNetworkContext ) -{ - int returnStatus = EXIT_SUCCESS; - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTFixedBuffer_t networkBuffer; - TransportInterface_t transport = { 0 }; - - assert( pMqttContext != NULL ); - assert( pNetworkContext != NULL ); - - /* Fill in TransportInterface send and receive function pointers. - * For this demo, TCP sockets are used to send and receive data - * from network. TLS over TCP channel is used as the transport - * layer for the MQTT connection. Network context is SSL context - * for OpenSSL.*/ - transport.pNetworkContext = pNetworkContext; - transport.send = espTlsTransportSend; - transport.recv = espTlsTransportRecv; - transport.writev = NULL; - - /* Fill the values for network buffer. */ - networkBuffer.pBuffer = otaNetworkBuffer; - networkBuffer.size = OTA_NETWORK_BUFFER_SIZE; - - /* Initialize MQTT library. */ - mqttStatus = MQTT_Init( pMqttContext, - &transport, - Clock_GetTimeMs, - mqttEventCallback, - &networkBuffer ); - - if( mqttStatus != MQTTSuccess ) - { - returnStatus = EXIT_FAILURE; - LogError( ( "MQTT_Init failed: Status = %s.", MQTT_Status_strerror( mqttStatus ) ) ); - } - else - { - mqttStatus = MQTT_InitStatefulQoS( pMqttContext, - pOutgoingPublishRecords, - OUTGOING_PUBLISH_RECORD_LEN, - pIncomingPublishRecords, - INCOMING_PUBLISH_RECORD_LEN ); - - if( mqttStatus != MQTTSuccess ) - { - returnStatus = EXIT_FAILURE; - LogError( ( "MQTT_InitStatefulQoS failed: Status = %s.", MQTT_Status_strerror( mqttStatus ) ) ); - } - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static int connectToServerWithBackoffRetries( NetworkContext_t * pNetworkContext ) -{ - int returnStatus = EXIT_SUCCESS; - BackoffAlgorithmStatus_t backoffAlgStatus = BackoffAlgorithmSuccess; - TlsTransportStatus_t tlsStatus = TLS_TRANSPORT_SUCCESS; - BackoffAlgorithmContext_t reconnectParams; - pNetworkContext->pcHostname = AWS_IOT_ENDPOINT; - pNetworkContext->xPort = AWS_MQTT_PORT; - pNetworkContext->pxTls = NULL; - pNetworkContext->xTlsContextSemaphore = xSemaphoreCreateMutexStatic(&xTlsContextSemaphoreBuffer); - - pNetworkContext->disableSni = 0; - uint16_t nextRetryBackOff; - - /* Initialize credentials for establishing TLS session. */ - pNetworkContext->pcServerRootCA = root_cert_auth_start; - pNetworkContext->pcServerRootCASize = root_cert_auth_end - root_cert_auth_start; - -#ifdef CONFIG_EXAMPLE_USE_SECURE_ELEMENT - pNetworkContext->use_secure_element = true; - -#elif defined(CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR) - if (esp_secure_cert_get_device_cert(&pNetworkContext->pcClientCert, &pNetworkContext->pcClientCertSize) != ESP_OK) { - LogError( ( "Failed to obtain flash address of device cert") ); - return EXIT_FAILURE; - } -#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL - pNetworkContext->ds_data = esp_secure_cert_get_ds_ctx(); - if (pNetworkContext->ds_data == NULL) { - LogError( ( "Failed to obtain the ds context") ); - return EXIT_FAILURE; - } -#else /* !CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - if (esp_secure_cert_get_priv_key(&pNetworkContext->pcClientKey, &pNetworkContext->pcClientKeySize) != ESP_OK) { - LogError( ( "Failed to obtain flash address of private_key") ); - return EXIT_FAILURE; - } -#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - -#else /* !CONFIG_EXAMPLE_USE_SECURE_ELEMENT && !CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR */ - #ifndef CLIENT_USERNAME - pNetworkContext->pcClientCert = client_cert_start; - pNetworkContext->pcClientCertSize = client_cert_end - client_cert_start; - pNetworkContext->pcClientKey = client_key_start; - pNetworkContext->pcClientKeySize = client_key_end - client_key_start; - #endif -#endif - - /* AWS IoT requires devices to send the Server Name Indication (SNI) - * extension to the Transport Layer Security (TLS) protocol and provide - * the complete endpoint address in the host_name field. Details about - * SNI for AWS IoT can be found in the link below. - * https://docs.aws.amazon.com/iot/latest/developerguide/transport-security.html */ - - if( AWS_MQTT_PORT == 443 ) - { - /* Pass the ALPN protocol name depending on the port being used. - * Please see more details about the ALPN protocol for the AWS IoT MQTT - * endpoint in the link below. - * https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/ - * - * For username and password based authentication in AWS IoT, - * #AWS_IOT_PASSWORD_ALPN is used. More details can be found in the - * link below. - * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html - */ - - static const char * pcAlpnProtocols[] = { NULL, NULL }; - - #ifdef CLIENT_USERNAME - pcAlpnProtocols[0] = AWS_IOT_PASSWORD_ALPN; - #else - pcAlpnProtocols[0] = AWS_IOT_MQTT_ALPN; - #endif - - pNetworkContext->pAlpnProtos = pcAlpnProtocols; - } else { - pNetworkContext->pAlpnProtos = NULL; - } - - /* Initialize reconnect attempts and interval */ - BackoffAlgorithm_InitializeParams( &reconnectParams, - CONNECTION_RETRY_BACKOFF_BASE_MS, - CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS, - CONNECTION_RETRY_MAX_ATTEMPTS ); - - /* Attempt to connect to MQTT broker. If connection fails, retry after - * a timeout. Timeout value will exponentially increase until maximum - * attempts are reached. - */ - do - { - /* Establish a TLS session with the MQTT broker. This example connects - * to the MQTT broker as specified in AWS_IOT_ENDPOINT and AWS_MQTT_PORT - * at the demo config header. */ - LogInfo( ( "Establishing a TLS session to %.*s:%d.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT, - AWS_MQTT_PORT ) ); - tlsStatus = xTlsConnect ( pNetworkContext ); - if( tlsStatus != TLS_TRANSPORT_SUCCESS ) - { - /* Generate a random number and get back-off value (in milliseconds) for the next connection retry. */ - backoffAlgStatus = BackoffAlgorithm_GetNextBackoff( &reconnectParams, generateRandomNumber(), &nextRetryBackOff ); - - if( backoffAlgStatus == BackoffAlgorithmRetriesExhausted ) - { - LogError( ( "Connection to the broker failed, all attempts exhausted." ) ); - returnStatus = EXIT_FAILURE; - } - else if( backoffAlgStatus == BackoffAlgorithmSuccess ) - { - LogWarn( ( "Connection to the broker failed. Retrying connection " - "after %hu ms backoff.", - ( unsigned short ) nextRetryBackOff ) ); - Clock_SleepMs( nextRetryBackOff ); -// vTaskDelay( nextRetryBackOff/portTICK_PERIOD_MS ); - } - } - } while( ( tlsStatus != TLS_TRANSPORT_SUCCESS ) && ( backoffAlgStatus == BackoffAlgorithmSuccess ) ); - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static int establishMqttSession( MQTTContext_t * pMqttContext ) -{ - int returnStatus = EXIT_SUCCESS; - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTConnectInfo_t connectInfo = { 0 }; - - bool sessionPresent = false; - - assert( pMqttContext != NULL ); - - /* Establish MQTT session by sending a CONNECT packet. */ - - /* If #createCleanSession is true, start with a clean session - * i.e. direct the MQTT broker to discard any previous session data. - * If #createCleanSession is false, directs the broker to attempt to - * reestablish a session which was already present. */ - connectInfo.cleanSession = true; - - /* The client identifier is used to uniquely identify this MQTT client to - * the MQTT broker. In a production device the identifier can be something - * unique, such as a device serial number. */ - connectInfo.pClientIdentifier = CLIENT_IDENTIFIER; - connectInfo.clientIdentifierLength = CLIENT_IDENTIFIER_LENGTH; - - /* The maximum time interval in seconds which is allowed to elapse - * between two Control Packets. - * It is the responsibility of the Client to ensure that the interval between - * Control Packets being sent does not exceed the this Keep Alive value. In the - * absence of sending any other Control Packets, the Client MUST send a - * PINGREQ Packet. */ - connectInfo.keepAliveSeconds = MQTT_KEEP_ALIVE_INTERVAL_SECONDS; - - /* Use the username and password for authentication, if they are defined. - * Refer to the AWS IoT documentation below for details regarding client - * authentication with a username and password. - * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html - * An authorizer setup needs to be done, as mentioned in the above link, to use - * username/password based client authentication. - * - * The username field is populated with voluntary metrics to AWS IoT. - * The metrics collected by AWS IoT are the operating system, the operating - * system's version, the hardware platform, and the MQTT Client library - * information. These metrics help AWS IoT improve security and provide - * better technical support. - * - * If client authentication is based on username/password in AWS IoT, - * the metrics string is appended to the username to support both client - * authentication and metrics collection. */ - #ifdef CLIENT_USERNAME - connectInfo.pUserName = CLIENT_USERNAME_WITH_METRICS; - connectInfo.userNameLength = strlen( CLIENT_USERNAME_WITH_METRICS ); - connectInfo.pPassword = CLIENT_PASSWORD; - connectInfo.passwordLength = strlen( CLIENT_PASSWORD ); - #else - connectInfo.pUserName = METRICS_STRING; - connectInfo.userNameLength = METRICS_STRING_LENGTH; - /* Password for authentication is not used. */ - connectInfo.pPassword = NULL; - connectInfo.passwordLength = 0U; - #endif /* ifdef CLIENT_USERNAME */ - - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Send MQTT CONNECT packet to broker. */ - mqttStatus = MQTT_Connect( pMqttContext, &connectInfo, NULL, CONNACK_RECV_TIMEOUT_MS, &sessionPresent ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mutex for executing MQTT_Connect" - ",errno=%s", - strerror( errno ) ) ); - } - - if( mqttStatus != MQTTSuccess ) - { - returnStatus = EXIT_FAILURE; - LogError( ( "Connection with MQTT broker failed with status %s.", - MQTT_Status_strerror( mqttStatus ) ) ); - } - else - { - LogInfo( ( "MQTT connection successfully established with broker.\n\n" ) ); - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static int establishConnection( void ) -{ - int returnStatus = EXIT_FAILURE; - - /* Attempt to connect to the MQTT broker. If connection fails, retry after - * a timeout. Timeout value will be exponentially increased till the maximum - * attempts are reached or maximum timeout value is reached. The function - * returns EXIT_FAILURE if the TCP connection cannot be established to - * broker after configured number of attempts. */ - returnStatus = connectToServerWithBackoffRetries( &networkContext ); - - if( returnStatus != EXIT_SUCCESS ) - { - /* Log error to indicate connection failure. */ - LogError( ( "Failed to connect to MQTT broker %.*s.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT ) ); - } - else - { - /* Establish MQTT session on top of TCP+TLS connection. */ - LogInfo( ( "Creating an MQTT connection to %.*s.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT ) ); - - /* Sends an MQTT Connect packet using the established TLS session, - * then waits for connection acknowledgment (CONNACK) packet. */ - returnStatus = establishMqttSession( &mqttContext ); - - if( returnStatus != EXIT_SUCCESS ) - { - LogError( ( "Failed creating an MQTT connection to %.*s.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT ) ); - xTlsDisconnect(&networkContext); - } - else - { - LogDebug( ( "Success creating MQTT connection to %.*s.", - AWS_IOT_ENDPOINT_LENGTH, - AWS_IOT_ENDPOINT ) ); - - mqttSessionEstablished = true; - } - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -static void cleanupESPSecureMgrCerts( NetworkContext_t * pNetworkContext ) -{ -#ifdef CONFIG_EXAMPLE_USE_SECURE_ELEMENT - /* Nothing to be freed */ -#elif defined(CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR) - esp_secure_cert_free_device_cert(&pNetworkContext->pcClientCert); -#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL - esp_secure_cert_free_ds_ctx(pNetworkContext->ds_data); -#else /* !CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - esp_secure_cert_free_priv_key(&pNetworkContext->pcClientKey); -#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ - -#else /* !CONFIG_EXAMPLE_USE_SECURE_ELEMENT && !CONFIG_EXAMPLE_USE_ESP_SECURE_CERT_MGR */ - /* Nothing to be freed */ -#endif - return; -} - -/*-----------------------------------------------------------*/ - -static void disconnect( void ) -{ - /* Disconnect from broker. */ - LogInfo( ( "Disconnecting the MQTT connection with %s.", AWS_IOT_ENDPOINT ) ); - - if( mqttSessionEstablished == true ) - { - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Disconnect MQTT session. */ - MQTT_Disconnect( &mqttContext ); - - /* Clear the mqtt session flag. */ - mqttSessionEstablished = false; - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mutex to execute MQTT_Disconnect" - ",errno=%s", - strerror( errno ) ) ); - } - } - else - { - LogError( ( "MQTT already disconnected." ) ); - } - - /* End TLS session, then close TCP connection. */ - cleanupESPSecureMgrCerts( &networkContext ); - ( void ) xTlsDisconnect( &networkContext ); -} - -/*-----------------------------------------------------------*/ - -static void registerSubscriptionManagerCallback( const char * pTopicFilter, - uint16_t topicFilterLength ) -{ - bool isMatch = false; - MQTTStatus_t mqttStatus = MQTTSuccess; - SubscriptionManagerStatus_t subscriptionStatus = SUBSCRIPTION_MANAGER_SUCCESS; - - uint16_t index = 0U; - - /* For suppressing compiler-warning: unused variable. */ - ( void ) mqttStatus; - - /* Lookup table for OTA message string. */ - static const char * const pWildCardTopicFilters[] = - { - OTA_TOPIC_PREFIX OTA_TOPIC_JOBS "/#", - OTA_TOPIC_PREFIX OTA_TOPIC_STREAM "/#" - }; - - /* Match the input topic filter against the wild-card pattern of topics filters - * relevant for the OTA Update service to determine the type of topic filter. */ - for( ; index < 2; index++ ) - { - mqttStatus = MQTT_MatchTopic( pTopicFilter, - topicFilterLength, - pWildCardTopicFilters[ index ], - strlen( pWildCardTopicFilters[ index ] ), - &isMatch ); - assert( mqttStatus == MQTTSuccess ); - - if( isMatch ) - { - /* Register callback to subscription manager. */ - subscriptionStatus = SubscriptionManager_RegisterCallback( pWildCardTopicFilters[ index ], - strlen( pWildCardTopicFilters[ index ] ), - otaMessageCallback[ index ] ); - - if( subscriptionStatus != SUBSCRIPTION_MANAGER_SUCCESS ) - { - LogWarn( ( "Failed to register a callback to subscription manager with error = %d.", - subscriptionStatus ) ); - } - - break; - } - } -} - -/*-----------------------------------------------------------*/ - -static OtaMqttStatus_t mqttSubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t qos ) -{ - OtaMqttStatus_t otaRet = OtaMqttSuccess; - - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTContext_t * pMqttContext = &mqttContext; - MQTTSubscribeInfo_t pSubscriptionList[ 1 ]; - - assert( pMqttContext != NULL ); - assert( pTopicFilter != NULL ); - assert( topicFilterLength > 0 ); - - ( void ) qos; - - /* Start with everything at 0. */ - ( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) ); - - /* Set the topic and topic length. */ - pSubscriptionList[ 0 ].pTopicFilter = pTopicFilter; - pSubscriptionList[ 0 ].topicFilterLength = topicFilterLength; - - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Send SUBSCRIBE packet. */ - mqttStatus = MQTT_Subscribe( pMqttContext, - pSubscriptionList, - sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ), - MQTT_GetPacketId( pMqttContext ) ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mqtt mutex for executing MQTT_Subscribe" - ",errno=%s", - strerror( errno ) ) ); - } - - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to send SUBSCRIBE packet to broker with error = %u.", - mqttStatus ) ); - - otaRet = OtaMqttSubscribeFailed; - } - else - { - LogInfo( ( "SUBSCRIBE topic %.*s to broker.\n\n", - topicFilterLength, - pTopicFilter ) ); - - registerSubscriptionManagerCallback( pTopicFilter, topicFilterLength ); - } - - return otaRet; -} - -/*-----------------------------------------------------------*/ - -static OtaMqttStatus_t mqttPublish( const char * const pacTopic, - uint16_t topicLen, - const char * pMsg, - uint32_t msgSize, - uint8_t qos ) -{ - OtaMqttStatus_t otaRet = OtaMqttSuccess; - - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTPublishInfo_t publishInfo = { 0 }; - MQTTContext_t * pMqttContext = &mqttContext; - BackoffAlgorithmStatus_t backoffAlgStatus = BackoffAlgorithmSuccess; - BackoffAlgorithmContext_t reconnectParams; - uint16_t nextRetryBackOff; - - - /* Initialize reconnect attempts and interval */ - BackoffAlgorithm_InitializeParams( &reconnectParams, - CONNECTION_RETRY_BACKOFF_BASE_MS, - CONNECTION_RETRY_MAX_BACKOFF_DELAY_MS, - MQTT_PUBLISH_RETRY_MAX_ATTEMPS ); - - /* Set the required publish parameters. */ - publishInfo.pTopicName = pacTopic; - publishInfo.topicNameLength = topicLen; - publishInfo.qos = qos; - publishInfo.pPayload = pMsg; - publishInfo.payloadLength = msgSize; - - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - do - { - mqttStatus = MQTT_Publish( pMqttContext, - &publishInfo, - MQTT_GetPacketId( pMqttContext ) ); - - if( qos == 1 ) - { - /* Loop to receive packet from transport interface. */ - mqttStatus = MQTT_ReceiveLoop( &mqttContext ); - } - - if( mqttStatus != MQTTSuccess ) - { - /* Generate a random number and get back-off value (in milliseconds) for the next connection retry. */ - backoffAlgStatus = BackoffAlgorithm_GetNextBackoff( &reconnectParams, generateRandomNumber(), &nextRetryBackOff ); - - if( backoffAlgStatus == BackoffAlgorithmRetriesExhausted ) - { - LogError( ( "Publish failed, all attempts exhausted." ) ); - } - else if( backoffAlgStatus == BackoffAlgorithmSuccess ) - { - LogWarn( ( "Publish failed. Retrying connection " - "after %hu ms backoff.", - ( unsigned short ) nextRetryBackOff ) ); - vTaskDelay( nextRetryBackOff/portTICK_PERIOD_MS ); - } - } - } while( ( mqttStatus != MQTTSuccess ) && ( backoffAlgStatus == BackoffAlgorithmSuccess ) ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mqtt mutex for executing MQTT_Publish" - ",errno=%s", - strerror( errno ) ) ); - } - - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to send PUBLISH packet to broker with error = %u.", mqttStatus ) ); - - otaRet = OtaMqttPublishFailed; - } - else - { - LogInfo( ( "Sent PUBLISH packet to broker %.*s to broker.\n\n", - topicLen, - pacTopic ) ); - } - - return otaRet; -} - -/*-----------------------------------------------------------*/ - -static OtaMqttStatus_t mqttUnsubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t qos ) -{ - OtaMqttStatus_t otaRet = OtaMqttSuccess; - MQTTStatus_t mqttStatus = MQTTBadParameter; - - MQTTSubscribeInfo_t pSubscriptionList[ 1 ]; - MQTTContext_t * pMqttContext = &mqttContext; - - ( void ) qos; - - /* Start with everything at 0. */ - ( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) ); - - /* Set the topic and topic length. */ - pSubscriptionList[ 0 ].pTopicFilter = pTopicFilter; - pSubscriptionList[ 0 ].topicFilterLength = topicFilterLength; - - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Send UNSUBSCRIBE packet. */ - mqttStatus = MQTT_Unsubscribe( pMqttContext, - pSubscriptionList, - sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ), - MQTT_GetPacketId( pMqttContext ) ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mutex for executing MQTT_Unsubscribe" - ",errno=%s", - strerror( errno ) ) ); - } - - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to send UNSUBSCRIBE packet to broker with error = %u.", - mqttStatus ) ); - - otaRet = OtaMqttUnsubscribeFailed; - } - else - { - LogInfo( ( "UNSUBSCRIBE topic %.*s to broker.\n\n", - topicFilterLength, - pTopicFilter ) ); - } - - return otaRet; -} - -/*-----------------------------------------------------------*/ - -static void setOtaInterfaces( OtaInterfaces_t * pOtaInterfaces ) -{ - /* Initialize OTA library OS Interface. */ - pOtaInterfaces->os.event.init = OtaInitEvent_FreeRTOS; - pOtaInterfaces->os.event.send = OtaSendEvent_FreeRTOS; - pOtaInterfaces->os.event.recv = OtaReceiveEvent_FreeRTOS; - pOtaInterfaces->os.event.deinit = OtaDeinitEvent_FreeRTOS; - pOtaInterfaces->os.timer.start = OtaStartTimer_FreeRTOS; - pOtaInterfaces->os.timer.stop = OtaStopTimer_FreeRTOS; - pOtaInterfaces->os.timer.delete = OtaDeleteTimer_FreeRTOS; - pOtaInterfaces->os.mem.malloc = Malloc_FreeRTOS; - pOtaInterfaces->os.mem.free = Free_FreeRTOS; - - /* Initialize the OTA library MQTT Interface.*/ - pOtaInterfaces->mqtt.subscribe = mqttSubscribe; - pOtaInterfaces->mqtt.publish = mqttPublish; - pOtaInterfaces->mqtt.unsubscribe = mqttUnsubscribe; - - /* Initialize the OTA library PAL Interface.*/ - pOtaInterfaces->pal.getPlatformImageState = otaPal_GetPlatformImageState; - pOtaInterfaces->pal.setPlatformImageState = otaPal_SetPlatformImageState; - pOtaInterfaces->pal.writeBlock = otaPal_WriteBlock; - pOtaInterfaces->pal.activate = otaPal_ActivateNewImage; - pOtaInterfaces->pal.closeFile = otaPal_CloseFile; - pOtaInterfaces->pal.reset = otaPal_ResetDevice; - pOtaInterfaces->pal.abort = otaPal_Abort; - pOtaInterfaces->pal.createFile = otaPal_CreateFileForRx; -} - -/*-----------------------------------------------------------*/ - -static void * otaThread( void * pParam ) -{ - /* Calling OTA agent task. */ - OTA_EventProcessingTask( pParam ); - LogInfo( ( "OTA Agent stopped." ) ); - return NULL; -} -/*-----------------------------------------------------------*/ -uint32_t otaPacketsReceived_prev = 0; - -static int startOTADemo( void ) -{ - /* Status indicating a successful demo or not. */ - int returnStatus = EXIT_SUCCESS; - - /* coreMQTT library return status. */ - MQTTStatus_t mqttStatus = MQTTBadParameter; - - /* OTA library return status. */ - OtaErr_t otaRet = OtaErrNone; - - /* OTA Agent state returned from calling OTA_GetAgentState.*/ - OtaState_t state = OtaAgentStateStopped; - - /* OTA event message used for sending event to OTA Agent.*/ - OtaEventMsg_t eventMsg = { 0 }; - - /* OTA library packet statistics per job.*/ - OtaAgentStatistics_t otaStatistics = { 0 }; - - /* OTA Agent thread handle.*/ - pthread_t threadHandle; - - /* Status return from call to pthread_join. */ - int returnJoin = 0; - - /* OTA interface context required for library interface functions.*/ - OtaInterfaces_t otaInterfaces; - - /* Maximum time to wait for the OTA agent to get suspended. */ - int16_t suspendTimeout; - - /* Set OTA Library interfaces.*/ - setOtaInterfaces( &otaInterfaces ); - - /* Set OTA Code Signing Certificate */ - if( !otaPal_SetCodeSigningCertificate( pcAwsCodeSigningCertPem ) ) - { - LogError( ( "Failed to allocate memory for Code Signing Certificate" ) ); - returnStatus = EXIT_FAILURE; - } - - LogInfo( ( "OTA over MQTT demo, Application version %u.%u.%u", - appFirmwareVersion.u.x.major, - appFirmwareVersion.u.x.minor, - appFirmwareVersion.u.x.build ) ); - - /****************************** Init OTA Library. ******************************/ - - if( returnStatus == EXIT_SUCCESS ) - { - if( ( otaRet = OTA_Init( &otaBuffer, - &otaInterfaces, - ( const uint8_t * ) ( CLIENT_IDENTIFIER ), - otaAppCallback ) ) != OtaErrNone ) - { - LogError( ( "Failed to initialize OTA Agent, exiting = %u.", - otaRet ) ); - - returnStatus = EXIT_FAILURE; - } - } - - /****************************** Create OTA Task. ******************************/ - - if( returnStatus == EXIT_SUCCESS ) - { - if( pthread_create( &threadHandle, NULL, otaThread, NULL ) != 0 ) - { - LogError( ( "Failed to create OTA thread: " - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - } - - /****************************** OTA Demo loop. ******************************/ - - if( returnStatus == EXIT_SUCCESS ) - { - /* Wait till OTA library is stopped, output statistics for currently running - * OTA job */ - while( ( ( state = OTA_GetState() ) != OtaAgentStateStopped ) ) - { - if( mqttSessionEstablished != true ) - { - /* Connect to MQTT broker and create MQTT connection. */ - if( EXIT_SUCCESS == establishConnection() ) - { - /* Check if OTA process was suspended and resume if required. */ - if( state == OtaAgentStateSuspended ) - { - /* Resume OTA operations. */ - OTA_Resume(); - } - else - { - /* Send start event to OTA Agent.*/ - eventMsg.eventId = OtaAgentEventStart; - OTA_SignalEvent( &eventMsg ); - } - } - } - - if( mqttSessionEstablished == true ) - { - /* Acquire the mqtt mutex lock. */ - if( pthread_mutex_lock( &mqttMutex ) == 0 ) - { - /* Loop to receive packet from transport interface. */ - mqttStatus = MQTT_ProcessLoop( &mqttContext ); - - pthread_mutex_unlock( &mqttMutex ); - } - else - { - LogError( ( "Failed to acquire mutex to execute process loop" - ",errno=%s", - strerror( errno ) ) ); - } - - if( ( mqttStatus == MQTTSuccess ) || ( mqttStatus == MQTTNeedMoreBytes ) ) - { - /* Get OTA statistics for currently executing job. */ - OTA_GetStatistics( &otaStatistics ); - - LogInfo( ( " Received: %"PRIu32" Queued: %"PRIu32" Processed: %"PRIu32" Dropped: %"PRIu32"", - otaStatistics.otaPacketsReceived, - otaStatistics.otaPacketsQueued, - otaStatistics.otaPacketsProcessed, - otaStatistics.otaPacketsDropped ) ); - - /* Delay to allow data to buffer for MQTT_ProcessLoop. */ - - if (otaStatistics.otaPacketsReceived == otaPacketsReceived_prev) { - Clock_SleepMs( OTA_EXAMPLE_LOOP_SLEEP_PERIOD_MS ); - } - - otaPacketsReceived_prev = otaStatistics.otaPacketsReceived; - - } - else - { - LogError( ( "MQTT_ProcessLoop returned with status = %s.", - MQTT_Status_strerror( mqttStatus ) ) ); - - /* Disconnect from broker and close connection. */ - disconnect(); - - /* Suspend OTA operations. */ - otaRet = OTA_Suspend(); - - if( otaRet == OtaErrNone ) - { - suspendTimeout = OTA_SUSPEND_TIMEOUT_MS; - - while( ( ( state = OTA_GetState() ) != OtaAgentStateSuspended ) && ( suspendTimeout > 0 ) ) - { - /* Wait for OTA Library state to suspend */ - Clock_SleepMs( OTA_EXAMPLE_TASK_DELAY_MS ); - suspendTimeout -= OTA_EXAMPLE_TASK_DELAY_MS; - } - } - else - { - LogError( ( "OTA failed to suspend. " - "StatusCode=%d.", otaRet ) ); - } - } - } - } - } - - /****************************** Wait for OTA Thread. ******************************/ - - if( returnStatus == EXIT_SUCCESS ) - { - returnJoin = pthread_join( threadHandle, NULL ); - - if( returnJoin != 0 ) - { - LogError( ( "Failed to join thread" - ",error code = %d", - returnJoin ) ); - - returnStatus = EXIT_FAILURE; - } - } - - return returnStatus; -} - -/*-----------------------------------------------------------*/ - -/** - * @brief Entry point of demo. - * - * This example initializes the OTA library to enable OTA updates via the - * MQTT broker. It simply connects to the MQTT broker with the users - * credentials and spins in an indefinite loop to allow MQTT messages to be - * forwarded to the OTA agent for possible processing. The OTA agent does all - * of the real work; checking to see if the message topic is one destined for - * the OTA agent. If not, it is simply ignored. - */ -int aws_iot_demo_main( int argc, - char ** argv ) -{ - ( void ) argc; - ( void ) argv; - - /* Return error status. */ - int returnStatus = EXIT_SUCCESS; - - /* Semaphore initialization flag. */ - bool bufferSemInitialized = false; - bool ackSemInitialized = false; - bool mqttMutexInitialized = false; - - /* Maximum time in milliseconds to wait before exiting demo . */ - int16_t waitTimeoutMs = OTA_DEMO_EXIT_TIMEOUT_MS; - - /* Initialize semaphore for buffer operations. */ - if( osi_sem_new( &bufferSemaphore, 0x7FFFU, 1 ) != 0 ) - { - LogError( ( "Failed to initialize buffer semaphore" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - else - { - bufferSemInitialized = true; - } - - /* Initialize semaphore for ack. */ - if( osi_sem_new( &ackSemaphore, 0x7FFFU, 0 ) != 0 ) - { - LogError( ( "Failed to initialize ack semaphore" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - else - { - ackSemInitialized = true; - } - - /* Initialize mutex for coreMQTT APIs. */ - if( pthread_mutex_init( &mqttMutex, NULL ) != 0 ) - { - LogError( ( "Failed to initialize mutex for mqtt apis" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - else - { - mqttMutexInitialized = true; - } - - if( returnStatus == EXIT_SUCCESS ) - { - /* Initialize MQTT library. Initialization of the MQTT library needs to be - * done only once in this demo. */ - returnStatus = initializeMqtt( &mqttContext, &networkContext ); - } - - if( returnStatus == EXIT_SUCCESS ) - { - /* Start OTA demo. */ - returnStatus = startOTADemo(); - } - - /* Disconnect from broker and close connection. */ - disconnect(); - - if( bufferSemInitialized == true ) - { - /* Cleanup semaphore created for buffer operations. */ - if( osi_sem_free( &bufferSemaphore ) != 0 ) - { - LogError( ( "Failed to destroy buffer semaphore" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - } - - if( ackSemInitialized == true ) - { - /* Cleanup semaphore created for ack. */ - if( osi_sem_free( &ackSemaphore ) != 0 ) - { - LogError( ( "Failed to destroy ack semaphore" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - } - - if( mqttMutexInitialized == true ) - { - /* Cleanup mutex created for MQTT operations. */ - if( pthread_mutex_destroy( &mqttMutex ) != 0 ) - { - LogError( ( "Failed to destroy mutex for mqtt apis" - ",errno=%s", - strerror( errno ) ) ); - - returnStatus = EXIT_FAILURE; - } - } - - /* Wait and log message before exiting demo. */ - while( waitTimeoutMs > 0 ) - { - Clock_SleepMs( OTA_EXAMPLE_TASK_DELAY_MS ); - waitTimeoutMs -= OTA_EXAMPLE_TASK_DELAY_MS; - - LogError( ( "Exiting demo in %d sec", waitTimeoutMs / 1000 ) ); - } - - return returnStatus; -} diff --git a/examples/ota/ota_mqtt/ota_mqtt_demo.csv b/examples/ota/ota_mqtt/ota_mqtt_demo.csv deleted file mode 100644 index bd0d168af..000000000 --- a/examples/ota/ota_mqtt/ota_mqtt_demo.csv +++ /dev/null @@ -1,3 +0,0 @@ -key,type,encoding,value -creds,namespace,, -P11_CSK,file,string,./main/certs/P11_CSK.crt diff --git a/examples/ota/ota_mqtt/partitions_ota_mqtt.csv b/examples/ota/ota_mqtt/partitions_ota_mqtt.csv deleted file mode 100644 index 619afc19b..000000000 --- a/examples/ota/ota_mqtt/partitions_ota_mqtt.csv +++ /dev/null @@ -1,9 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap -pre_prov, 0x3F, , 0xD000, 0x6000, encrypted -nvs, data, nvs, , 0x4000, -otadata, data, ota, , 0x2000, -phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, , 1M, -ota_1, app, ota_1, , 1M, -storage, data, nvs, , 0x4000, \ No newline at end of file diff --git a/examples/ota/ota_mqtt/sdkconfig.defaults b/examples/ota/ota_mqtt/sdkconfig.defaults deleted file mode 100644 index e3e30bf0d..000000000 --- a/examples/ota/ota_mqtt/sdkconfig.defaults +++ /dev/null @@ -1,21 +0,0 @@ -# newlib for ESP32 and ESP8266 platform - -CONFIG_NEWLIB_ENABLE=y -CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL=y -CONFIG_NEWLIB_NANO_FORMAT= -CONFIG_SSL_USING_MBEDTLS=y -CONFIG_LWIP_IPV6=y -CONFIG_MBEDTLS_THREADING_C=y -# CONFIG_MBEDTLS_THREADING_ALT is not set -CONFIG_MBEDTLS_THREADING_PTHREAD=y -CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192 -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_ota_mqtt.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions_ota_mqtt.csv" -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y -CONFIG_MBEDTLS_CMAC_C=y -CONFIG_OTA_DATA_OVER_MQTT=y -CONFIG_OTA_DATA_OVER_HTTP=n -CONFIG_OTA_DATA_OVER_MQTT_PRIMARY=y -CONFIG_OTA_DATA_OVER_HTTP_PRIMARY=n diff --git a/examples/ota/ota_mqtt/sdkconfig.defaults.esp32c2 b/examples/ota/ota_mqtt/sdkconfig.defaults.esp32c2 deleted file mode 100644 index 98a10ccba..000000000 --- a/examples/ota/ota_mqtt/sdkconfig.defaults.esp32c2 +++ /dev/null @@ -1,17 +0,0 @@ -# Wi-Fi -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=4 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=n -CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=n -CONFIG_ESP32_WIFI_IRAM_OPT=n -CONFIG_ESP32_WIFI_RX_IRAM_OPT=n - -# LWIP -CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=16 - -# mbedTLS -CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2048 -CONFIG_MBEDTLS_DYNAMIC_BUFFER=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y diff --git a/examples/ota/ota_mqtt/sdkconfig.defaults.esp32s2 b/examples/ota/ota_mqtt/sdkconfig.defaults.esp32s2 deleted file mode 100644 index ef650a86c..000000000 --- a/examples/ota/ota_mqtt/sdkconfig.defaults.esp32s2 +++ /dev/null @@ -1,17 +0,0 @@ -# Wi-Fi -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=4 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=8 -CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=n -CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=n -CONFIG_ESP32_WIFI_IRAM_OPT=n -CONFIG_ESP32_WIFI_RX_IRAM_OPT=n - -# LWIP -CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=16 - -# mbedTLS -CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2048 -CONFIG_MBEDTLS_DYNAMIC_BUFFER=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y -CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y \ No newline at end of file