diff --git a/.clang-tidy-limits.yml b/.clang-tidy-limits.yml deleted file mode 100644 index f0b5377..0000000 --- a/.clang-tidy-limits.yml +++ /dev/null @@ -1,32 +0,0 @@ -limits: - "google-readability-braces-around-statements" : 30 - "readability-braces-around-statements" : 30 - "clang-diagnostic-error" : 10 - "readability-non-const-parameter" : 10 - "misc-misplaced-const" : 10 - "clang-diagnostic-typedef-redefinition" : 10 - "hicpp-braces-around-statements" : 10 - "clang-diagnostic-int-to-pointer-cast" : 10 - "hicpp-no-assembler" : 10 - "readability-else-after-return" : 10 - "readability-redundant-declaration" : 10 - "clang-diagnostic-unknown-attributes" : 10 - "misc-unused-parameters" : 10 - "readability-inconsistent-declaration-parameter-name" : 10 - "google-readability-todo" : 10 - "clang-diagnostic-macro-redefined" : 10 - "google-readability-casting" : 10 - "readability-inconsistent-declaration-parameter-name": 10 - "readability-named-parameter": 10 - "readability-container-size-empty": 10 - "modernize-use-using": 10 - "modernize-use-override": 10 - "readability-implicit-bool-cast": 10 - "modernize-use-default-member-init": 10 - "performance-unnecessary-value-param": 10 - "modernize-use-equals-default": 10 - "modernize-use-nullptr": 10 - -ignore: - - diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3461a4c..aa87863 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,8 @@ stages: variables: IDF_REPO: ${GITLAB_SSH_SERVER}/idf/esp-idf.git + OLDER_IDF: release/v3.1 + RECENT_IDF: release/v3.3 .add_gh_key_remote: &add_gh_key_remote | cit_add_ssh_key "${GH_PUSH_KEY}" @@ -19,6 +21,23 @@ before_script: - source citools/import_functions - PATH=$CI_PROJECT_DIR/esp-idf/tools:$PATH +build_with_older_idf: + stage: build + image: ${CI_DOCKER_REGISTRY}/esp32-ci-env + tags: + - build + dependencies: [] + script: + - cit_add_ssh_key "${GITLAB_KEY}" + - git clone "${IDF_REPO}" && cd esp-idf && git checkout ${OLDER_IDF} + - ./tools/ci/mirror-submodule-update.sh + - export IDF_PATH=$(pwd) + - cd $CI_PROJECT_DIR + - ./modify_for_legacy_idf.sh ${RECENT_IDF} || true + - cd $CI_PROJECT_DIR/examples/tcp + - make defconfig + - make + build_with_idf: stage: build image: ${CI_DOCKER_REGISTRY}/esp32-ci-env @@ -40,17 +59,16 @@ build_with_idf: - rm -rf .git - cp -r $CI_PROJECT_DIR/.git . - git reset --hard $CI_COMMIT_SHA - # build one example and capture compile commands/flags for static analysis + # capture compile commands/flags for static analysis - cd $IDF_PATH/examples/protocols/mqtt/tcp + - mkdir -p tidybuild && cd tidybuild + - cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. + - mv $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild $CI_PROJECT_DIR/tidybuild + # enable pedantic flags for compilation - export PEDANTIC_CFLAGS="-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function" - export EXTRA_CFLAGS=${PEDANTIC_CFLAGS} && export EXTRA_CXXFLAGS=${EXTRA_CFLAGS} - - idf.py build - - mkdir -p tidybuild - - cd tidybuild - - cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. - - cd $CI_PROJECT_DIR - - mv $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild $CI_PROJECT_DIR/tidybuild # build other examples + - cd $IDF_PATH/examples/protocols/mqtt/tcp && idf.py build - cd $IDF_PATH/examples/protocols/mqtt/ssl && idf.py build - cd $IDF_PATH/examples/protocols/mqtt/ssl_mutual_auth && idf.py build - cd $IDF_PATH/examples/protocols/mqtt/ws && idf.py build @@ -82,9 +100,8 @@ clang_tidy_check: - git reset --hard $CI_COMMIT_SHA - mv $CI_PROJECT_DIR/tidybuild $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild - cd $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild - - git clone "${CI_REPORT_TOOLS}" - - cd static-analysis-utils - - ./generate_report.sh $CI_PROJECT_DIR/.clang-tidy-limits.yml $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild/report $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild/output.xml + - git clone $IDF_ANALYSIS_UTILS static_analysis_utils && cd static_analysis_utils + - ./generate_report.sh $CI_PROJECT_DIR/static-analysis-rules.yml $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild/report $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild/output.xml deploy_report: stage: deploy_report @@ -105,6 +122,7 @@ deploy_report: - ssh $DOCS_SERVER -x "cd $DOCS_PATH/clang-tidy && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest" # add link to view the report - echo "[static analysis][clang tidy] $CI_DOCKER_REGISTRY/static_analysis/esp-idf/clang-tidy/${GIT_VER}/index.html" + - test ! -e ${GIT_VER}/FAILED_RULES || { echo 'Failed static analysis rules!'; cat ${GIT_VER}/FAILED_RULES; exit 1; } push_master_to_github: stage: deploy diff --git a/include/mqtt_client.h b/include/mqtt_client.h index 8b05d0b..a347f08 100644 --- a/include/mqtt_client.h +++ b/include/mqtt_client.h @@ -19,6 +19,12 @@ extern "C" { #endif +#ifndef ESP_EVENT_DECLARE_BASE +// Define event loop types if macros not available +typedef void * esp_event_loop_handle_t; +typedef void * esp_event_handler_t; +#endif + typedef struct esp_mqtt_client *esp_mqtt_client_handle_t; /** diff --git a/include/mqtt_supported_features.h b/include/mqtt_supported_features.h index 9a3ab04..3e9fac0 100644 --- a/include/mqtt_supported_features.h +++ b/include/mqtt_supported_features.h @@ -27,10 +27,15 @@ */ #ifdef ESP_IDF_VERSION + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(3, 3, 0) +// Features supported from 3.3 +#define MQTT_SUPPORTED_FEATURE_EVENT_LOOP +#endif + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) - +// Features supported in 4.0 #define MQTT_SUPPORTED_FEATURE_WS_SUBPROTOCOL - #endif #endif diff --git a/lib/mqtt_outbox.c b/lib/mqtt_outbox.c index d92bfb6..8b1ff8d 100644 --- a/lib/mqtt_outbox.c +++ b/lib/mqtt_outbox.c @@ -152,7 +152,6 @@ int outbox_delete_expired(outbox_handle_t outbox, int current_tick, int timeout) STAILQ_FOREACH_SAFE(item, outbox, next, tmp) { if (current_tick - item->tick > timeout) { STAILQ_REMOVE(outbox, item, outbox_item, next); - printf("free message\n"); free(item->buffer); free(item); deleted_items ++; @@ -167,7 +166,9 @@ int outbox_get_size(outbox_handle_t outbox) int siz = 0; outbox_item_handle_t item; STAILQ_FOREACH(item, outbox, next) { - siz += item->len; + // Suppressing "use after free" warning as this could happen only if queue is in inconsistent state + // which never happens if STAILQ interface used + siz += item->len; // NOLINT(clang-analyzer-unix.Malloc) } return siz; } diff --git a/mqtt_client.c b/mqtt_client.c index a3e2fce..a95f4b3 100644 --- a/mqtt_client.c +++ b/mqtt_client.c @@ -30,11 +30,13 @@ static const char *TAG = "MQTT_CLIENT"; +#ifdef MQTT_SUPPORTED_FEATURE_EVENT_LOOP /** * @brief Define of MQTT Event base * */ ESP_EVENT_DEFINE_BASE(MQTT_EVENTS); +#endif typedef struct mqtt_state { @@ -55,7 +57,9 @@ typedef struct mqtt_state typedef struct { mqtt_event_callback_t event_handle; +#ifdef MQTT_SUPPORTED_FEATURE_EVENT_LOOP esp_event_loop_handle_t event_loop_handle; +#endif int task_stack; int task_prio; char *uri; @@ -226,11 +230,13 @@ esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_cl if (config->event_handle) { cfg->event_handle = config->event_handle; } else { +#ifdef MQTT_SUPPORTED_FEATURE_EVENT_LOOP esp_event_loop_args_t no_task_loop = { .queue_size = 1, .task_name = NULL, }; esp_event_loop_create(&no_task_loop, &cfg->event_loop_handle); +#endif } if (config->refresh_connection_after_ms) { @@ -564,8 +570,12 @@ static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client) if (client->config->event_handle) { return client->config->event_handle(&client->event); } else { +#ifdef MQTT_SUPPORTED_FEATURE_EVENT_LOOP esp_event_post_to(client->config->event_loop_handle, MQTT_EVENTS, client->event.event_id, &client->event, sizeof(client->event), portMAX_DELAY); return esp_event_loop_run(client->config->event_loop_handle, 0); +#else + return ESP_FAIL; +#endif } } @@ -1319,10 +1329,15 @@ esp_err_t esp_mqtt_client_register_event(esp_mqtt_client_handle_t client, esp_mq if (client == NULL) { return ESP_ERR_INVALID_ARG; } +#ifdef MQTT_SUPPORTED_FEATURE_EVENT_LOOP if (client->config->event_handle) { ESP_LOGW(TAG, "Registering event loop while event callback is not null, clearing callback"); client->config->event_handle = NULL; } return esp_event_handler_register_with(client->config->event_loop_handle, MQTT_EVENTS, event, event_handler, event_handler_arg); +#else + ESP_LOGE(TAG, "Registering event handler while event loop not available in IDF version %s", IDF_VER); + return ESP_FAIL; +#endif } diff --git a/static-analysis-rules.yml b/static-analysis-rules.yml new file mode 100644 index 0000000..bd36de8 --- /dev/null +++ b/static-analysis-rules.yml @@ -0,0 +1,9 @@ +limits: + "clang-analyzer-core.NullDereference" : 0 + "clang-analyzer-unix.Malloc" : 0 + +ignore: + - "llvm-header-guard" + - "llvm-include-order" + +skip: