From 9fd739bc73809d19227e8e6c34cc5293e4298c5a Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Fri, 15 Sep 2023 16:28:39 +0000 Subject: [PATCH 01/11] Establish separate cloud connections for each device Also, handle ownership transfer for the second device when the first device is already connected to the hub. Extend the cloud server to accommodate multiple servers and enhance the check for empty endpoints. --- api/cloud/oc_cloud_apis.c | 4 ++ apps/cloud_server.c | 138 +++++++++++++++++++++++++++----------- security/oc_tls.c | 2 +- 3 files changed, 102 insertions(+), 42 deletions(-) diff --git a/api/cloud/oc_cloud_apis.c b/api/cloud/oc_cloud_apis.c index f92daf4a9b..962504870b 100644 --- a/api/cloud/oc_cloud_apis.c +++ b/api/cloud/oc_cloud_apis.c @@ -63,6 +63,10 @@ conv_cloud_endpoint(oc_cloud_context_t *ctx) int ret = 0; if (ctx->cloud_ep != NULL && oc_endpoint_is_empty(ctx->cloud_ep)) { ret = oc_string_to_endpoint(&ctx->store.ci_server, ctx->cloud_ep, NULL); + if (ret == 0) { + // set device id to cloud endpoint for multiple servers + ctx->cloud_ep->device = ctx->device; + } #ifdef OC_DNS_CACHE oc_dns_clear_cache(); #endif /* OC_DNS_CACHE */ diff --git a/apps/cloud_server.c b/apps/cloud_server.c index 0809cde3eb..21e91af230 100644 --- a/apps/cloud_server.c +++ b/apps/cloud_server.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include #ifndef _MSC_VER #include @@ -245,6 +247,7 @@ static const char *device_name = "CloudServer"; static const char *manufacturer = "ocfcloud.com"; static oc_connectivity_ports_t g_ports; +static size_t g_num_devices = 1; #ifdef OC_SECURITY static const char *cis; @@ -302,6 +305,18 @@ cloud_status_handler(oc_cloud_context_t *ctx, oc_cloud_status_t status, } } +static bool +factory_device_name(size_t device, char *buf, size_t buf_len) +{ + int written = 0; + if (device == 0) { + written = snprintf(buf, buf_len, "%s", device_name); + } else { + written = snprintf(buf, buf_len, "%s-%d", device_name, (int)device); + } + return (written < 0 || written >= (int)buf_len) ? false : true; +} + #ifdef OC_HAS_FEATURE_PLGD_TIME static int print_time(oc_clock_time_t time, void *data) @@ -343,19 +358,29 @@ app_init(void) #ifdef OC_HAS_FEATURE_PLGD_TIME plgd_time_init(); #endif /* OC_HAS_FEATURE_PLGD_TIME */ - oc_add_new_device_t new_device = { - .uri = "oic/d", - .rt = device_rt, - .name = device_name, - .spec_version = spec_version, - .data_model_version = data_model_version, - .add_device_cb = NULL, - .add_device_cb_data = NULL, - .ports = g_ports, - }; - if (oc_add_device_v1(new_device) != 0) { - OC_PRINTF("ERROR: failed to register new device\n"); - return -1; + for (size_t i = 0; i < g_num_devices; ++i) { + char dev_name[128]; + const char *dev_name_ptr = device_name; + if (factory_device_name(i, dev_name, sizeof(dev_name))) { + dev_name_ptr = dev_name; + } + + oc_add_new_device_t new_device = { + .uri = "oic/d", + .rt = device_rt, + .name = dev_name_ptr, + .spec_version = spec_version, + .data_model_version = data_model_version, + .add_device_cb = NULL, + .add_device_cb_data = NULL, + }; + if (i == 0) { + new_device.ports = g_ports; + } + if (oc_add_device_v1(new_device) != 0) { + OC_PRINTF("ERROR: failed to register new device\n"); + return -1; + } } return 0; } @@ -730,26 +755,26 @@ register_collection(void) #endif /* OC_COLLECTIONS */ static bool -register_con(void) +register_con(size_t device) { - oc_resource_t *con_res = oc_core_get_resource_by_index(OCF_CON, 0); + oc_resource_t *con_res = oc_core_get_resource_by_index(OCF_CON, device); return oc_cloud_add_resource(con_res) == 0; } #ifdef OC_MNT static bool -register_mnt(void) +register_mnt(size_t device) { - oc_resource_t *mnt_res = oc_core_get_resource_by_index(OCF_MNT, 0); + oc_resource_t *mnt_res = oc_core_get_resource_by_index(OCF_MNT, device); return oc_cloud_add_resource(mnt_res) == 0; } #endif /* OC_MNT */ #ifdef OC_HAS_FEATURE_PLGD_TIME static bool -register_plgd_time(void) +register_plgd_time(size_t device) { - oc_resource_t *ptime_res = oc_core_get_resource_by_index(PLGD_TIME, 0); + oc_resource_t *ptime_res = oc_core_get_resource_by_index(PLGD_TIME, device); return oc_cloud_add_resource(ptime_res) == 0; } #endif /* OC_HAS_FEATURE_PLGD_TIME */ @@ -765,19 +790,21 @@ register_resources(void) oc_abort("ERROR: could not register collection\n"); } #endif /* OC_COLLECTIONS */ - if (!register_con()) { - oc_abort("ERROR: could not register con resource\n"); - } + for (size_t i = 0; i < g_num_devices; ++i) { + if (!register_con(i)) { + oc_abort("ERROR: could not register con resource\n"); + } #ifdef OC_MNT - if (!register_mnt()) { - oc_abort("ERROR: could not register mnt resource\n"); - } + if (!register_mnt(i)) { + oc_abort("ERROR: could not register mnt resource\n"); + } #endif /* OC_MNT */ #ifdef OC_HAS_FEATURE_PLGD_TIME - if (!register_plgd_time()) { - oc_abort("ERROR: could not register plgd time resource\n"); - } + if (!register_plgd_time(i)) { + oc_abort("ERROR: could not register plgd time resource\n"); + } #endif /* OC_HAS_FEATURE_PLGD_TIME */ + } } #if defined(OC_SECURITY) && defined(OC_PKI) @@ -830,8 +857,13 @@ factory_presets_cb(size_t device, void *data) #if defined(OC_SECURITY) && defined(OC_PKI) // preserve name after factory reset oc_device_info_t *dev = oc_core_get_device_info(device); + char dev_name[128]; + const char *dev_name_ptr = device_name; + if (factory_device_name(device, dev_name, sizeof(dev_name))) { + dev_name_ptr = dev_name; + } oc_free_string(&dev->name); - oc_new_string(&dev->name, device_name, strlen(device_name)); + oc_new_string(&dev->name, dev_name_ptr, strlen(dev_name_ptr)); unsigned char cloud_ca[4096]; size_t cert_len = 4096; @@ -882,12 +914,12 @@ factory_presets_cb(size_t device, void *data) } static void -display_device_uuid(void) +display_device_uuid(size_t device) { char buffer[OC_UUID_LEN]; - oc_uuid_to_str(oc_core_get_device_id(0), buffer, sizeof(buffer)); + oc_uuid_to_str(oc_core_get_device_id(device), buffer, sizeof(buffer)); - OC_PRINTF("Started device with ID: %s\n", buffer); + OC_PRINTF("Started device %d with ID: %s\n", (int)device, buffer); } #if defined(OC_SECURITY) && defined(OC_PKI) @@ -1062,6 +1094,7 @@ simulate_tpm_pk_free_key(size_t device, const unsigned char *key, size_t keylen) #define OPT_DISABLE_TLS_VERIFY_TIME "disable-tls-verify-time" #define OPT_HELP "help" #define OPT_NUM_RESOURCES "num-resources" +#define OPT_NUM_DEVICES "num-devices" #define OPT_DEVICE_NAME "device-name" #define OPT_CLOUD_AUTH_CODE "cloud-auth-code" #define OPT_CLOUD_CIS "cloud-endpoint" @@ -1106,6 +1139,7 @@ printhelp(const char *exec_path) OC_PRINTF(" -p | --%-26s cloud authorization provider name\n", OPT_CLOUD_APN); OC_PRINTF(" -r | --%-26s number of resources\n", OPT_NUM_RESOURCES); + OC_PRINTF(" -c | --%-26s number of devices\n", OPT_NUM_DEVICES); #if defined(OC_SECURITY) && defined(OC_PKI) OC_PRINTF(" -d | --%-26s disable time verification during TLS handshake\n", OPT_DISABLE_TLS_VERIFY_TIME); @@ -1221,6 +1255,7 @@ parse_options(int argc, char *argv[], parse_options_result_t *parsed_options) { OPT_CLOUD_APN, required_argument, NULL, 'p' }, { OPT_NUM_RESOURCES, required_argument, NULL, 'r' }, { OPT_LOG_LEVEL, required_argument, NULL, 'l' }, + { OPT_NUM_DEVICES, required_argument, NULL, 'c' }, #if defined(OC_SECURITY) && defined(OC_PKI) { OPT_DISABLE_TLS_VERIFY_TIME, no_argument, NULL, 'd' }, { OPT_SIMULATE_TPM, no_argument, NULL, 'm' }, @@ -1300,6 +1335,18 @@ parse_options(int argc, char *argv[], parse_options_result_t *parsed_options) num_resources = (int)val; break; } + case 'c': { + char *eptr = NULL; + errno = 0; + long val = strtol(optarg, &eptr, 10); // NOLINT(readability-magic-numbers) + if (errno != 0 || eptr == optarg || (*eptr) != '\0' || val < 0 || + val > INT32_MAX) { + OC_PRINTF("invalid number of resources argument value(%s)\n", optarg); + return false; + } + g_num_devices = (size_t)val; + break; + } case 'l': { oc_log_level_t level; if (!parse_log_level(optarg, &level)) { @@ -1553,8 +1600,10 @@ main(int argc, char *argv[]) OC_PRINTF("Using parameters: device_name: %s, auth_code: %s, cis: %s, " "sid: %s, " "apn: %s, " - "num_resources: %d, ", - device_name, auth_code, cis, sid, apn, num_resources); + "num_resources: %d, " + "num_devices: %d, ", + device_name, auth_code, cis, sid, apn, num_resources, + (int)g_num_devices); #if defined(OC_SECURITY) && defined(OC_PKI) OC_PRINTF("disable_tls_time_verification: %s, ", parsed_options.disable_tls_verify_time ? "true" : "false"); @@ -1655,14 +1704,16 @@ main(int argc, char *argv[]) return ret; } - oc_cloud_context_t *ctx = oc_cloud_get_context(0); - if (ctx) { - oc_cloud_manager_start(ctx, cloud_status_handler, NULL); - if (cis) { - oc_cloud_provision_conf_resource(ctx, cis, auth_code, sid, apn); + for (size_t i = 0; i < g_num_devices; ++i) { + oc_cloud_context_t *ctx = oc_cloud_get_context(0); + if (ctx) { + oc_cloud_manager_start(ctx, cloud_status_handler, NULL); + if (cis) { + oc_cloud_provision_conf_resource(ctx, cis, auth_code, sid, apn); + } } + display_device_uuid(i); } - display_device_uuid(); #ifdef OC_HAS_FEATURE_PLGD_TIME if (g_time != (oc_clock_time_t)-1) { plgd_time_set_time(g_time); @@ -1671,7 +1722,12 @@ main(int argc, char *argv[]) run_loop(); - oc_cloud_manager_stop(ctx); + for (size_t i = 0; i < g_num_devices; ++i) { + oc_cloud_context_t *ctx = oc_cloud_get_context(0); + if (ctx) { + oc_cloud_manager_stop(ctx); + } + } oc_main_shutdown(); deinit(); return 0; diff --git a/security/oc_tls.c b/security/oc_tls.c index 491390d465..6619328bf7 100644 --- a/security/oc_tls.c +++ b/security/oc_tls.c @@ -2038,7 +2038,7 @@ tls_is_valid_doc(size_t device) OC_ERR("oc_tls: DOC not valid: oxmsel not set"); return false; } - if (oc_list_length(g_tls_peers) != 0) { + if (oc_tls_num_peers(device) != 0) { OC_ERR("oc_tls: DOC not valid: multiple DOC peers not allowed"); /* Allow only a single DOC */ return false; From 44d8643e89db093d6c518cb00fb806fdc1a2a13f Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Tue, 19 Sep 2023 16:14:50 +0200 Subject: [PATCH 02/11] Check iotivity-lite stack init before processing requests Check if the iotivity-lite stack is initialized before processing new requests during shutdown. --------- Co-authored-by: Daniel Adam --- api/oc_main.c | 6 ++---- messaging/coap/engine.c | 29 +++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/api/oc_main.c b/api/oc_main.c index 3a65e795be..0d936444ba 100644 --- a/api/oc_main.c +++ b/api/oc_main.c @@ -313,7 +313,7 @@ main_load_resources(void) int oc_main_init(const oc_handler_t *handler) { - if (g_initialized == true) { + if (g_initialized) { return 0; } @@ -367,7 +367,6 @@ oc_main_init(const oc_handler_t *handler) #endif /* OC_SERVER */ OC_DBG("oc_main: stack initialized"); - g_initialized = true; #ifdef OC_CLIENT @@ -420,10 +419,9 @@ oc_main_needs_poll(void) void oc_main_shutdown(void) { - if (g_initialized == false) { + if (!g_initialized) { return; } - g_initialized = false; #if defined(OC_CLIENT) && defined(OC_SERVER) && defined(OC_CLOUD) diff --git a/messaging/coap/engine.c b/messaging/coap/engine.c index 4fdd13badc..a76ec1cb7a 100644 --- a/messaging/coap/engine.c +++ b/messaging/coap/engine.c @@ -488,11 +488,9 @@ coap_receive_blockwise_block2(coap_receive_ctx_t *ctx, const char *href, } static coap_receive_status_t -coap_receive_method_payload(coap_receive_ctx_t *ctx, const char *href, - size_t href_len, const oc_endpoint_t *endpoint) +coap_receive_blockwise(coap_receive_ctx_t *ctx, const char *href, + size_t href_len, const oc_endpoint_t *endpoint) { - assert(ctx->request->code >= COAP_GET && ctx->request->code <= COAP_DELETE); - // block1 and block2 options are expected to be used with UDP protocol if (ctx->block1.enabled && // block1 is expected only for POST/PUT requests @@ -504,14 +502,27 @@ coap_receive_method_payload(coap_receive_ctx_t *ctx, const char *href, ctx->request->code == COAP_GET) { return coap_receive_blockwise_block2(ctx, href, href_len, endpoint); } + + COAP_ERR("unexpected block1 or block2 option(s)"); + return COAP_RECEIVE_ERROR; +} + +static coap_receive_status_t +coap_receive_method_payload(coap_receive_ctx_t *ctx, const char *href, + size_t href_len, const oc_endpoint_t *endpoint) +{ + assert(ctx->request->code >= COAP_GET && ctx->request->code <= COAP_DELETE); + if (ctx->block1.enabled || ctx->block2.enabled) { - COAP_ERR("unexpected block1 and block2 options"); + return coap_receive_blockwise(ctx, href, href_len, endpoint); + } + COAP_DBG("no block options; processing regular request"); + + if (!oc_main_initialized()) { + COAP_DBG("cannot process new requests during shutdown iotivity-lite stack"); return COAP_RECEIVE_ERROR; } - COAP_DBG("no block options; processing regular request"); - const uint8_t *incoming_block; - uint32_t incoming_block_len = coap_get_payload(ctx->request, &incoming_block); #ifdef OC_SECURITY // Drop unsecured (unicast/multicast) requests during reset the device. if (oc_reset_in_progress(endpoint->device) && @@ -521,6 +532,8 @@ coap_receive_method_payload(coap_receive_ctx_t *ctx, const char *href, } #endif /* OC_SECURITY */ + const uint8_t *incoming_block; + uint32_t incoming_block_len = coap_get_payload(ctx->request, &incoming_block); #ifdef OC_TCP bool is_valid_size = ((endpoint->flags & TCP) != 0 && From 7b99f87ef4d1ac381f5937b5b33c2f86b5b4932a Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Wed, 13 Sep 2023 12:00:28 +0000 Subject: [PATCH 03/11] Run tests with release images --- .github/workflows/cmake-linux.yml | 10 +++-- .../workflows/plgd-device-test-with-cfg.yml | 14 +++---- .github/workflows/plgd-device-tests.yml | 27 ++++++++----- .github/workflows/plgd-hub-test-with-cfg.yml | 17 ++++---- .github/workflows/plgd-hub-tests.yml | 39 ++++++++++++------- 5 files changed, 64 insertions(+), 43 deletions(-) diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index c88501a23e..9e7250c46b 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -16,6 +16,10 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: inputs: + build_type: + description: "Type of the build" + type: string + default: "Debug" clang: description: "Compile using clang" required: false @@ -71,7 +75,7 @@ jobs: uses: ./.github/workflows/unit-test-with-cfg.yml with: build_args: -DOC_LOG_MAXIMUM_LOG_LEVEL=INFO -DOC_WKCORE_ENABLED=ON -DOC_SOFTWARE_UPDATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_PUSH_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON ${{ matrix.args }} - build_type: Debug + build_type: ${{ (github.event_name == 'workflow_dispatch' && inputs.build_type) || 'Debug' }} clang: ${{ github.event_name == 'workflow_dispatch' && inputs.clang }} coverage: false install_mbedtls: ${{ github.event_name == 'workflow_dispatch' && inputs.install_mbedtls }} @@ -82,7 +86,7 @@ jobs: with: # cloud on (ipv4+tcp on), collections create on, maintenance resource on, well-known core resource on, software update on, /oic/res observable on, push notification on, plgd-time on, etag on build_args: -DOC_LOG_MAXIMUM_LOG_LEVEL=INFO -DOC_CLOUD_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_WKCORE_ENABLED=ON -DOC_SOFTWARE_UPDATE_ENABLED=ON -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_PUSH_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON - build_type: Debug + build_type: ${{ (github.event_name == 'workflow_dispatch' && inputs.build_type) || 'Debug' }} clang: ${{ github.event_name == 'workflow_dispatch' && inputs.clang }} coverage: false install_mbedtls: ${{ github.event_name != 'workflow_dispatch' }} @@ -114,7 +118,7 @@ jobs: uses: ./.github/workflows/unit-test-with-cfg.yml with: build_args: -DOC_LOG_MAXIMUM_LOG_LEVEL=INFO -DOC_CLOUD_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_WKCORE_ENABLED=ON -DOC_SOFTWARE_UPDATE_ENABLED=ON -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_PUSH_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON ${{ matrix.args }} - build_type: Debug + build_type: ${{ (github.event_name == 'workflow_dispatch' && inputs.build_type) || 'Debug' }} clang: ${{ github.event_name == 'workflow_dispatch' && inputs.clang }} coverage: false install_mbedtls: ${{ github.event_name == 'workflow_dispatch' && inputs.install_mbedtls }} diff --git a/.github/workflows/plgd-device-test-with-cfg.yml b/.github/workflows/plgd-device-test-with-cfg.yml index b104be8667..dafb64ac8a 100644 --- a/.github/workflows/plgd-device-test-with-cfg.yml +++ b/.github/workflows/plgd-device-test-with-cfg.yml @@ -25,11 +25,6 @@ on: type: string required: false default: P256 - clang: - description: Use clang instead of gcc - type: boolean - required: false - default: false coverage: type: boolean required: false @@ -42,12 +37,15 @@ on: type: boolean required: false default: false + docker_file: + description: Dockerfile used to build the cloud server image + type: string + required: false + default: docker/apps/Dockerfile.cloud-server-debug env: TEST_CLOUD_SERVER_IMAGE: ghcr.io/plgd-dev/device/test-cloud-server:latest CERT_TOOL_IMAGE: ghcr.io/plgd-dev/hub/cert-tool:vnext CERT_PATH: .tmp/pki_certs - CLOUD_SERVER_DOCKER_FILE: docker/apps/Dockerfile.cloud-server-debug - CLOUD_SERVER_CLANG_DOCKER_FILE: docker/apps/Dockerfile.cloud-server-debug-clang CLOUD_SERVER_DOCKER_TAG: dbg jobs: @@ -66,7 +64,7 @@ jobs: with: context: . push: false - file: ${{ (inputs.clang && env.CLOUD_SERVER_CLANG_DOCKER_FILE) || env.CLOUD_SERVER_DOCKER_FILE }} + file: ${{ inputs.docker_file }} tags: ${{ env.CLOUD_SERVER_DOCKER_TAG }} build-args: | BUILD_ARGS=${{ inputs.build_args }} diff --git a/.github/workflows/plgd-device-tests.yml b/.github/workflows/plgd-device-tests.yml index 667f58131c..959dcf2622 100644 --- a/.github/workflows/plgd-device-tests.yml +++ b/.github/workflows/plgd-device-tests.yml @@ -19,6 +19,10 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: inputs: + build_type: + description: "Type of the build" + type: string + default: "Debug" cert_signature_algorithm: type: choice description: Signature algorithm used in generated certificates @@ -50,7 +54,7 @@ jobs: - name: cloud-server-tsan args: "-DOC_TSAN_ENABLED=ON" # GCC thread-sanitizer keeps reporting false positives, so we use clang instead for tests with thread-sanitizer - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-access-in-RFOTM args: "-DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" @@ -58,7 +62,7 @@ jobs: args: "-DOC_ASAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" - name: cloud-server-tsan-access-in-RFOTM args: "-DOC_TSAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-discovery-resource-observable args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON" @@ -66,7 +70,7 @@ jobs: args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_ASAN_ENABLED=ON" - name: cloud-server-discovery-resource-observable-tsan args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-discovery-resource-observable-access-in-RFOTM args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" @@ -74,7 +78,7 @@ jobs: args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_ASAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" - name: cloud-server-discovery-resource-observable-tsan-access-in-RFOTM args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_TSAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-rep-realloc args: "-DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON" @@ -82,24 +86,29 @@ jobs: args: "-DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_ASAN_ENABLED=ON" - name: cloud-server-rep-realloc-tsan args: "-DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc # same configuration as "cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc" in the SonarCloud scan job, skip for events that trigger both jobs skip: ${{ github.event_name != 'workflow_dispatch' }} args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON" - name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc-asan - args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON-DOC_ASAN_ENABLED=ON" + args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_ASAN_ENABLED=ON" - name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc-tsan args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang + + - name: cloud-server-release-discovery-resource-observable-access-in-RFOTM-rep-realloc + args: "-DOC_DEBUG_ENABLED=OFF -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON" + build_type: Release + docker_file: docker/apps/Dockerfile.cloud-server uses: ./.github/workflows/plgd-device-test-with-cfg.yml with: name: ${{ matrix.name }} build_args: -DOC_DEBUG_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_OSCORE_ENABLED=OFF -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON ${{ matrix.args }} - build_type: Debug + build_type: ${{ (github.event_name == 'workflow_dispatch' && inputs.build_type) || (matrix.build_type || 'Debug') }} cert_signature_algorithm: ${{ (github.event_name == 'workflow_dispatch' && inputs.cert_signature_algorithm) || 'ECDSA-SHA256' }} cert_elliptic_curve: ${{ (github.event_name == 'workflow_dispatch' && inputs.cert_elliptic_curve) || 'P256' }} - clang: ${{ matrix.clang || false }} + docker_file: ${{ matrix.docker_file || 'docker/apps/Dockerfile.cloud-server-debug' }} skip: ${{ matrix.skip || false }} diff --git a/.github/workflows/plgd-hub-test-with-cfg.yml b/.github/workflows/plgd-hub-test-with-cfg.yml index f2ed47c7c1..10aec64354 100644 --- a/.github/workflows/plgd-hub-test-with-cfg.yml +++ b/.github/workflows/plgd-hub-test-with-cfg.yml @@ -19,7 +19,8 @@ on: required: true build_type: type: string - required: true + required: false + default: Debug cert_signature_algorithm: description: Signature algorithm used in generated certificates type: string @@ -30,11 +31,6 @@ on: type: string required: false default: P256 - clang: - description: Use clang instead of gcc - type: boolean - required: false - default: false coverage: description: gather and upload coverage data type: boolean @@ -45,6 +41,11 @@ on: type: string required: false default: "" + docker_file: + description: Dockerfile used to build the cloud_server container + type: string + required: false + default: docker/apps/Dockerfile.cloud-server-debug hub_args: description: arguments forwarded to the docker run command of the plgd-dev/hub/test-cloud-server container type: string @@ -62,8 +63,6 @@ on: env: TEST_CLOUD_SERVER_IMAGE: ghcr.io/plgd-dev/hub/test-cloud-server:latest - CLOUD_SERVER_DOCKER_FILE: docker/apps/Dockerfile.cloud-server-debug - CLOUD_SERVER_CLANG_DOCKER_FILE: docker/apps/Dockerfile.cloud-server-debug-clang CLOUD_SERVER_DOCKER_TAG: dbg jobs: @@ -84,7 +83,7 @@ jobs: build-args: | BUILD_ARGS=${{ inputs.build_args }} BUILD_TYPE=${{ inputs.build_type }} - file: ${{ (inputs.clang && env.CLOUD_SERVER_CLANG_DOCKER_FILE) || env.CLOUD_SERVER_DOCKER_FILE }} + file: ${{ inputs.docker_file }} tags: ${{ env.CLOUD_SERVER_DOCKER_TAG }} - name: Pull plgd hub tests image diff --git a/.github/workflows/plgd-hub-tests.yml b/.github/workflows/plgd-hub-tests.yml index 8b43f86e4d..209cfff9d3 100644 --- a/.github/workflows/plgd-hub-tests.yml +++ b/.github/workflows/plgd-hub-tests.yml @@ -19,6 +19,10 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: inputs: + build_type: + description: "Type of the build" + type: string + default: "Debug" cert_signature_algorithm: type: choice description: Signature algorithm used in generated certificates @@ -48,7 +52,7 @@ jobs: - name: cloud-server-tsan build_args: "-DOC_TSAN_ENABLED=ON" # GCC thread-sanitizer keeps reporting false positives, so we use clang instead for tests with thread-sanitizer - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-simulate-tpm-asan build_args: "-DOC_ASAN_ENABLED=ON" @@ -66,7 +70,7 @@ jobs: build_args: "-DOC_TSAN_ENABLED=ON" docker_args: '-e FAKETIME="@2000-01-01 11:12:13"' args: "--disable-tls-verify-time" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-time-2100-01-01 build_args: "" @@ -80,7 +84,7 @@ jobs: build_args: "-DOC_TSAN_ENABLED=ON" docker_args: '-e FAKETIME="@2100-01-01 11:12:13"' args: "--disable-tls-verify-time" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-set-mbedtls-time-2000-01-01 build_args: "" @@ -97,7 +101,7 @@ jobs: build_args: "-DOC_ASAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" - name: cloud-server-tsan-access-in-RFOTM build_args: "-DOC_TSAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-discovery-resource-observable build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON" @@ -105,7 +109,7 @@ jobs: build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_ASAN_ENABLED=ON" - name: cloud-server-discovery-resource-observable-tsan build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-discovery-resource-observable-access-in-RFOTM # same configuration as "cloud-server-discovery-resource-observable-access-in-RFOTM" in the SonarCloud scan job, skip for events that trigger both jobs @@ -115,7 +119,7 @@ jobs: build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_ASAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" - name: cloud-server-discovery-resource-observable-tsan-access-in-RFOTM build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_TSAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-rep-realloc build_args: "-DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON" @@ -123,7 +127,7 @@ jobs: build_args: "-DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_ASAN_ENABLED=ON" - name: cloud-server-rep-realloc-tsan build_args: "-DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang - name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON" @@ -131,13 +135,15 @@ jobs: build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_ASAN_ENABLED=ON" - name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc-tsan build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang # ports - name: cloud-server-tcp-disabled args: "--udp-port 61234 --udp-port4 61234 --dtls-port 61235 --dtls-port4 61235 --tcp-port -1 --tcp-port4 -1 --tls-port -1 --tls-port4 -1" + build_args: "" - name: cloud-server-ipv6-disabled args: "--udp-port -1 --udp-port4 61234 --dtls-port -1 --dtls-port4 61235 --tcp-port -1 --tcp-port4 61234 --tls-port -1 --tls-port4 61235" + build_args: "" - name: dtls-cloud-server build_args: "" @@ -147,7 +153,7 @@ jobs: hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true" - name: dtls-cloud-server-tsan build_args: "-DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true" - name: dtls-cloud-server-discovery-resource-observable @@ -158,7 +164,7 @@ jobs: hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true" - name: dtls-cloud-server-discovery-resource-observable-tsan build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true" - name: dtls-cloud-server-rep-realloc @@ -171,7 +177,7 @@ jobs: hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true" - name: dtls-cloud-server-rep-realloc-tsan build_args: "-DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true" - name: dtls-cloud-server-discovery-resource-observable-rep-realloc @@ -182,18 +188,23 @@ jobs: hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true" - name: dtls-cloud-server-discovery-resource-observable-rep-realloc-tsan build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_TSAN_ENABLED=ON" - clang: true + docker_file: docker/apps/Dockerfile.cloud-server-debug-clang hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true" + - name: cloud-server-release-discovery-resource-observable-access-in-RFOTM-rep-realloc + build_args: "-DOC_DEBUG_ENABLED=OFF -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON" + build_type: Release + docker_file: docker/apps/Dockerfile.cloud-server + uses: ./.github/workflows/plgd-hub-test-with-cfg.yml with: name: ${{ matrix.name }} build_args: -DOC_DEBUG_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_OSCORE_ENABLED=OFF -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON ${{ matrix.build_args }} - build_type: Debug + build_type: ${{ (github.event_name == 'workflow_dispatch' && inputs.build_type) || (matrix.build_type || 'Debug') }} hub_args: ${{ matrix.hub_args }} args: ${{ matrix.args }} docker_args: ${{ matrix.docker_args }} cert_signature_algorithm: ${{ (github.event_name == 'workflow_dispatch' && inputs.cert_signature_algorithm) || 'ECDSA-SHA256' }} cert_elliptic_curve: ${{ (github.event_name == 'workflow_dispatch' && inputs.cert_elliptic_curve) || 'P256' }} - clang: ${{ matrix.clang || false }} skip: ${{ matrix.skip || false }} + docker_file: ${{ matrix.docker_file || 'docker/apps/Dockerfile.cloud-server-debug' }} From 35f679bf15e94f3a3bb50eb481780c730641abb5 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Wed, 20 Sep 2023 12:43:26 +0200 Subject: [PATCH 04/11] Add oc_endpoint_to_string64 Create an oc_string64_t struct with statically allocated buffer that fits an endpoint address to avoid the use of the heap. The new function oc_endpoint_to_string64 converts an oc_endpoint_t to a string address using the oc_string64_t. Currently used internally. --------- Co-authored-by: Daniel Adam --- api/oc_collection.c | 11 +- api/oc_discovery.c | 23 ++-- api/oc_endpoint.c | 111 ++++++++++++-------- api/oc_endpoint_internal.h | 53 ++++++++-- api/oc_introspection.c | 6 +- api/oc_push.c | 13 ++- api/unittest/eptest.cpp | 191 ++++++++++++++++++++++++++++++---- api/unittest/plgdtimetest.cpp | 7 +- include/oc_endpoint.h | 40 +++++-- include/oc_helpers.h | 2 +- messaging/coap/observe.c | 7 +- messaging/coap/transactions.c | 6 +- port/common/oc_ip.c | 32 +++--- port/common/oc_ip.h | 8 +- port/linux/tcpsession.c | 6 +- security/oc_tls.c | 21 ++-- tests/gtest/Device.cpp | 17 ++- tests/gtest/Device.h | 9 ++ tests/gtest/Endpoint.cpp | 5 +- 19 files changed, 410 insertions(+), 158 deletions(-) diff --git a/api/oc_collection.c b/api/oc_collection.c index fcd922a9ec..afd255b33b 100644 --- a/api/oc_collection.c +++ b/api/oc_collection.c @@ -20,6 +20,7 @@ #if defined(OC_COLLECTIONS) && defined(OC_SERVER) #include "api/oc_collection_internal.h" +#include "api/oc_endpoint_internal.h" #include "api/oc_helpers_internal.h" #include "api/oc_link_internal.h" #include "api/oc_ri_internal.h" @@ -715,10 +716,9 @@ collection_encode_links(const oc_collection_t *collection, continue; } oc_rep_object_array_start_item(eps); - oc_string_t ep; - if (oc_endpoint_to_string(eps, &ep) == 0) { + oc_string64_t ep; + if (oc_endpoint_to_string64(eps, &ep)) { oc_rep_set_text_string_v1(eps, ep, oc_string(ep), oc_string_len(ep)); - oc_free_string(&ep); } oc_rep_object_array_end_item(eps); } @@ -856,10 +856,9 @@ oc_handle_collection_linked_list_request(oc_request_t *request) continue; } oc_rep_object_array_start_item(eps); - oc_string_t ep; - if (oc_endpoint_to_string(eps, &ep) == 0) { + oc_string64_t ep; + if (oc_endpoint_to_string64(eps, &ep)) { oc_rep_set_text_string_v1(eps, ep, oc_string(ep), oc_string_len(ep)); - oc_free_string(&ep); } oc_rep_object_array_end_item(eps); } diff --git a/api/oc_discovery.c b/api/oc_discovery.c index 66fdd4b443..55d80cf125 100644 --- a/api/oc_discovery.c +++ b/api/oc_discovery.c @@ -18,6 +18,7 @@ #include "api/oc_core_res_internal.h" #include "api/oc_discovery_internal.h" +#include "api/oc_endpoint_internal.h" #include "api/oc_resource_internal.h" #include "api/oc_ri_internal.h" #include "api/oc_server_api_internal.h" @@ -122,12 +123,11 @@ discovery_encode_endpoint(CborEncoder *eps, const oc_endpoint_t *ep, int latency) { oc_rep_begin_object(eps, ep); - oc_string_t ep_str; - if (oc_endpoint_to_string(ep, &ep_str) == 0) { + oc_string64_t ep_str; + if (oc_endpoint_to_string64(ep, &ep_str)) { g_err |= oc_rep_encode_text_string(&ep_map, "ep", OC_CHAR_ARRAY_LEN("ep")); g_err |= oc_rep_encode_text_string(&ep_map, oc_string(ep_str), oc_string_len(ep_str)); - oc_free_string(&ep_str); } if (latency > 0) { g_err |= @@ -1058,14 +1058,15 @@ oc_wkcore_discovery_handler(oc_request_t *request, oc_string_t uri; memset(&uri, 0, sizeof(oc_string_t)); while (eps != NULL) { - if (eps->flags & SECURED) { - oc_string_t ep; - if (oc_endpoint_to_string(eps, &ep) == 0) { - length = clf_add_str_to_buffer(oc_string(ep), oc_string_len(ep)); - response_length += length; - oc_free_string(&ep); - break; - } + if ((eps->flags & SECURED) == 0) { + eps = eps->next; + continue; + } + oc_string64_t ep; + if (oc_endpoint_to_string64(eps, &ep)) { + length = clf_add_str_to_buffer(oc_string(ep), oc_string_len(ep)); + response_length += length; + break; } eps = eps->next; } diff --git a/api/oc_endpoint.c b/api/oc_endpoint.c index d58ebd53d1..7dedf2cf5e 100644 --- a/api/oc_endpoint.c +++ b/api/oc_endpoint.c @@ -16,8 +16,9 @@ * ****************************************************************************/ +#include "api/oc_endpoint_internal.h" +#include "api/oc_helpers_internal.h" #include "oc_endpoint.h" -#include "oc_endpoint_internal.h" #include "oc_core_res.h" #include "port/common/oc_ip.h" #include "port/oc_connectivity.h" @@ -66,26 +67,41 @@ oc_endpoint_set_di(oc_endpoint_t *endpoint, const oc_uuid_t *di) memcpy(endpoint->di.id, di->id, sizeof(di->id)); } -const char * -oc_endpoint_flags_to_scheme(unsigned flags) +static oc_string_view_t +endpoint_flags_to_scheme(unsigned flags) { #ifdef OC_TCP if ((flags & TCP) != 0) { if ((flags & SECURED) != 0) { - return OC_SCHEME_COAPS_TCP; + return OC_STRING_VIEW(OC_SCHEME_COAPS_TCP); } - return OC_SCHEME_COAP_TCP; + return OC_STRING_VIEW(OC_SCHEME_COAP_TCP); } -#endif +#endif /* OC_TCP */ if ((flags & SECURED) != 0) { - return OC_SCHEME_COAPS; + return OC_STRING_VIEW(OC_SCHEME_COAPS); } - return OC_SCHEME_COAP; + return OC_STRING_VIEW(OC_SCHEME_COAP); +} + +int +oc_endpoint_flags_to_scheme(unsigned flags, char *buffer, size_t buffer_size) +{ + oc_string_view_t scheme = endpoint_flags_to_scheme(flags); + if (buffer == NULL) { + return (int)scheme.length; + } + if (scheme.length < buffer_size) { + memcpy(buffer, scheme.data, scheme.length); + buffer[scheme.length] = '\0'; + return (int)scheme.length; + } + return -1; } int oc_endpoint_host(const oc_endpoint_t *endpoint, char *buffer, - uint32_t buffer_size) + size_t buffer_size) { #ifdef OC_IPV4 if ((endpoint->flags & IPV4) != 0) { @@ -99,8 +115,8 @@ oc_endpoint_host(const oc_endpoint_t *endpoint, char *buffer, } int -oc_endpoint_to_cstring(const oc_endpoint_t *endpoint, char *buffer, - uint32_t buffer_size) +oc_endpoint_address_and_port_to_cstring(const oc_endpoint_t *endpoint, + char *buffer, size_t buffer_size) { #ifdef OC_IPV4 if ((endpoint->flags & IPV4) != 0) { @@ -115,6 +131,26 @@ oc_endpoint_to_cstring(const oc_endpoint_t *endpoint, char *buffer, return -1; } +int +oc_endpoint_to_cstring(const oc_endpoint_t *endpoint, char *buffer, + size_t buffer_size) +{ + int written = + oc_endpoint_flags_to_scheme(endpoint->flags, buffer, buffer_size); + if (written < 0) { + return -1; + } + int len = written; + buffer += written; + buffer_size -= (size_t)written; + written = + oc_endpoint_address_and_port_to_cstring(endpoint, buffer, buffer_size); + if (written < 0) { + return -1; + } + return len + written; +} + int oc_endpoint_to_string(const oc_endpoint_t *endpoint, oc_string_t *endpoint_str) { @@ -122,15 +158,31 @@ oc_endpoint_to_string(const oc_endpoint_t *endpoint, oc_string_t *endpoint_str) return -1; } - char ip[OC_IPV6_MAXSTRLEN] = { 0 }; - if (oc_endpoint_to_cstring(endpoint, ip, OC_ARRAY_SIZE(ip)) != 0) { + oc_string64_t ep_str; + if (!oc_endpoint_to_string64(endpoint, &ep_str)) { return -1; } - oc_concat_strings(endpoint_str, oc_endpoint_flags_to_scheme(endpoint->flags), - ip); + oc_new_string(endpoint_str, oc_string(ep_str), oc_string_len(ep_str)); return 0; } +bool +oc_endpoint_to_string64(const oc_endpoint_t *endpoint, + oc_string64_t *endpoint_str) +{ + if (!endpoint || !endpoint_str) { + return false; + } + memset(endpoint_str, 0, sizeof(oc_string64_t)); + int written = oc_endpoint_to_cstring(endpoint, oc_string(*endpoint_str), + OC_ARRAY_SIZE(endpoint_str->ptr)); + if (written < 0) { + return false; + } + endpoint_str->size = (size_t)written + 1; + return true; +} + int oc_endpoint_port(const oc_endpoint_t *endpoint) { @@ -353,26 +405,8 @@ parse_endpoint_uri(const oc_string_t *endpoint_str, return false; } - const char *address = NULL; - switch (flags) { -#ifdef OC_TCP - case TCP | SECURED: - address = ep + OC_CHAR_ARRAY_LEN(OC_SCHEME_COAPS_TCP); - break; - case TCP: - address = ep + OC_CHAR_ARRAY_LEN(OC_SCHEME_COAP_TCP); - break; -#endif /* OC_TCP */ - case SECURED: - address = ep + OC_CHAR_ARRAY_LEN(OC_SCHEME_COAPS); - break; - case 0: - address = ep + OC_CHAR_ARRAY_LEN(OC_SCHEME_COAP); - break; - default: - OC_ERR("invalid endpoint(%s) uri scheme: %d", ep != NULL ? ep : "", flags); - return false; - } + oc_string_view_t scheme = endpoint_flags_to_scheme(flags); + const char *address = ep + scheme.length; size_t ep_len = oc_string_len(*endpoint_str); size_t address_len = ep_len - (address - ep); @@ -701,12 +735,7 @@ oc_endpoint_list_copy(oc_endpoint_t **dst, const oc_endpoint_t *src) return count; oc_endpoint_list_copy_err: - ep = head; - while (ep != NULL) { - oc_endpoint_t *next = ep->next; - oc_free_endpoint(ep); - ep = next; - } + oc_endpoint_list_free(head); return -1; } diff --git a/api/oc_endpoint_internal.h b/api/oc_endpoint_internal.h index 18c3624e68..a9f74e4a38 100644 --- a/api/oc_endpoint_internal.h +++ b/api/oc_endpoint_internal.h @@ -21,8 +21,11 @@ #include "oc_endpoint.h" #include "util/oc_compiler.h" +#include "util/oc_macros_internal.h" #include +#include +#include #ifdef __cplusplus extern "C" { @@ -40,28 +43,60 @@ extern "C" { #define OC_SCHEME_OCF "ocf://" -/** @brief Get scheme string for transport flags */ -const char *oc_endpoint_flags_to_scheme(unsigned flags) OC_RETURNS_NONNULL; +/** + * @brief Write the scheme string (including NUL terminator) for given transport + * flags to buffer + * + * @param flags transport flags of an endpoint + * @param buffer output buffer (if NULL the function returns the number of bytes + * that would have been written, excluding the NUL terminator) + * @param buffer_size size of output buffer + * @return return number of written bytes (excluding the NUL terminator) + * @return -1 for error + */ +int oc_endpoint_flags_to_scheme(unsigned flags, char *buffer, + size_t buffer_size); /** * @brief Convert the endpoint to a human readable string (e.g. - * "coaps://[fe::22]:/") + * "[fe::22]:1234") * - * @param endpoint the endpoint - * @param buffer output buffer + * @param endpoint the endpoint (cannot be NULL) + * @param buffer output buffer (cannot be NULL) * @param buffer_size size of output buffer - * @return int 0 success + * @return number of written bytes, -1 for error */ -int oc_endpoint_to_cstring(const oc_endpoint_t *endpoint, char *buffer, - uint32_t buffer_size) OC_NONNULL(); +int oc_endpoint_address_and_port_to_cstring(const oc_endpoint_t *endpoint, + char *buffer, size_t buffer_size) + OC_NONNULL(); /** @brief Get host of the endpoint as string */ int oc_endpoint_host(const oc_endpoint_t *endpoint, char *buffer, - uint32_t buffer_size) OC_NONNULL(); + size_t buffer_size) OC_NONNULL(); /** @brief Get port of the endpoint */ int oc_endpoint_port(const oc_endpoint_t *endpoint) OC_NONNULL(); +typedef struct oc_string64_s +{ + size_t size; + char ptr[64]; +} oc_string64_t; + +#define oc_string64_cap(ocstring) \ + (OC_ARRAY_SIZE((ocstring).ptr) - (ocstring).size) + +/** + * @brief convert the endpoint to a human readable string (e.g. + * "coaps://[fe::22]:1234"). + * + * @param endpoint the endpoint + * @param endpoint_str endpoint as human readable string + * @return true for success + */ +bool oc_endpoint_to_string64(const oc_endpoint_t *endpoint, + oc_string64_t *endpoint_str); + #ifdef __cplusplus } #endif diff --git a/api/oc_introspection.c b/api/oc_introspection.c index 06e3e814e5..89b69aeef5 100644 --- a/api/oc_introspection.c +++ b/api/oc_introspection.c @@ -21,6 +21,7 @@ #ifdef OC_INTROSPECTION #include "api/oc_core_res_internal.h" +#include "api/oc_endpoint_internal.h" #include "api/oc_introspection_internal.h" #include "api/oc_ri_internal.h" #include "api/oc_server_api_internal.h" @@ -126,10 +127,9 @@ oc_introspection_wk_get_uri(size_t device, int interface_index, if ((interface_index == -1 || eps->interface_index == (unsigned)interface_index) && (eps->flags == flags)) { - oc_string_t ep; - if (oc_endpoint_to_string(eps, &ep) == 0) { + oc_string64_t ep; + if (oc_endpoint_to_string64(eps, &ep)) { oc_concat_strings(uri, oc_string(ep), OC_INTROSPECTION_DATA_URI); - oc_free_string(&ep); return true; } } diff --git a/api/oc_push.c b/api/oc_push.c index d6d37446df..1ac8e2383a 100644 --- a/api/oc_push.c +++ b/api/oc_push.c @@ -28,6 +28,7 @@ #include "api/oc_helpers_internal.h" #include "api/oc_rep_internal.h" +#include "api/oc_endpoint_internal.h" #include "oc_api.h" #include "oc_core_res.h" #include "oc_core_res_internal.h" @@ -572,9 +573,9 @@ get_ns_properties(const oc_resource_t *resource, oc_interface_mask_t iface_mask, /* * pushtarget */ - oc_string_t ep; + oc_string64_t ep; oc_string_t full_uri; - if (oc_endpoint_to_string(&ns_instance->pushtarget_ep, &ep) < 0) { + if (!oc_endpoint_to_string64(&ns_instance->pushtarget_ep, &ep)) { /* handle NULL pushtarget... */ #if 0 char ipv6addrstr[50], ipv4addrstr[50]; @@ -594,8 +595,6 @@ get_ns_properties(const oc_resource_t *resource, oc_interface_mask_t iface_mask, oc_string(ns_instance->targetpath)); else oc_new_string(&full_uri, oc_string(ep), oc_string_len(ep)); - - oc_free_string(&ep); } oc_rep_set_text_string(root, pushtarget, oc_string(full_uri)); @@ -2428,9 +2427,10 @@ push_update(oc_ns_t *ns_instance) return false; } #ifdef OC_PUSHDEBUG - oc_string_t ep, full_uri; + oc_string64_t ep; + oc_string_t full_uri; - oc_endpoint_to_string(&ns_instance->pushtarget_ep, &ep); + oc_endpoint_to_string64(&ns_instance->pushtarget_ep, &ep); if (oc_string_len(ns_instance->targetpath)) { oc_concat_strings(&full_uri, oc_string(ep), oc_string(ns_instance->targetpath)); @@ -2440,7 +2440,6 @@ push_update(oc_ns_t *ns_instance) OC_PUSH_DBG("push \"%s\" ====> \"%s\"", oc_string(src_rsc->uri), oc_string(full_uri)); - oc_free_string(&ep); oc_free_string(&full_uri); #endif OC_PUSH_DBG("state of Push Proxy (\"%s\") is changed (%s => %s)", diff --git a/api/unittest/eptest.cpp b/api/unittest/eptest.cpp index a985a8b2b9..8415888136 100644 --- a/api/unittest/eptest.cpp +++ b/api/unittest/eptest.cpp @@ -22,13 +22,16 @@ #include "oc_helpers.h" #include "oc_uuid.h" #include "port/common/oc_ip.h" +#include "port/oc_connectivity.h" #include "port/oc_random.h" +#include "tests/gtest/Device.h" #include "tests/gtest/Endpoint.h" #include #include #include #include +#include #include #ifdef _WIN32 @@ -94,6 +97,56 @@ TEST_F(TestEndpoint, SetDeviceID) oc_random_destroy(); } +TEST_F(TestEndpoint, EndpointFlagsToScheme) +{ + std::array buf; + buf.fill(0); + EXPECT_EQ(OC_CHAR_ARRAY_LEN(OC_SCHEME_COAP), + oc_endpoint_flags_to_scheme(0, buf.data(), buf.size())); + EXPECT_STREQ(OC_SCHEME_COAP, buf.data()); + EXPECT_EQ(OC_CHAR_ARRAY_LEN(OC_SCHEME_COAP), + oc_endpoint_flags_to_scheme(0, nullptr, 0)); + EXPECT_EQ(-1, oc_endpoint_flags_to_scheme(0, buf.data(), 0)); + + buf.fill(0); + EXPECT_EQ(OC_CHAR_ARRAY_LEN(OC_SCHEME_COAPS), + oc_endpoint_flags_to_scheme(SECURED, buf.data(), buf.size())); + EXPECT_STREQ(OC_SCHEME_COAPS, buf.data()); + EXPECT_EQ(OC_CHAR_ARRAY_LEN(OC_SCHEME_COAPS), + oc_endpoint_flags_to_scheme(SECURED, nullptr, 0)); + EXPECT_EQ(-1, oc_endpoint_flags_to_scheme(SECURED, buf.data(), 0)); + +#ifdef OC_TCP + buf.fill(0); + EXPECT_EQ(OC_CHAR_ARRAY_LEN(OC_SCHEME_COAP_TCP), + oc_endpoint_flags_to_scheme(TCP, buf.data(), buf.size())); + EXPECT_STREQ(OC_SCHEME_COAP_TCP, buf.data()); + EXPECT_EQ(OC_CHAR_ARRAY_LEN(OC_SCHEME_COAP_TCP), + oc_endpoint_flags_to_scheme(TCP, nullptr, 0)); + EXPECT_EQ(-1, oc_endpoint_flags_to_scheme(TCP, buf.data(), 0)); + + buf.fill(0); + EXPECT_EQ(OC_CHAR_ARRAY_LEN(OC_SCHEME_COAPS_TCP), + oc_endpoint_flags_to_scheme(SECURED | TCP, buf.data(), buf.size())); + EXPECT_STREQ(OC_SCHEME_COAPS_TCP, buf.data()); + EXPECT_EQ(OC_CHAR_ARRAY_LEN(OC_SCHEME_COAPS_TCP), + oc_endpoint_flags_to_scheme(SECURED | TCP, nullptr, 0)); + EXPECT_EQ(-1, oc_endpoint_flags_to_scheme(SECURED | TCP, buf.data(), 0)); +#endif /* OC_TCP */ +} + +TEST_F(TestEndpoint, EndpointToCStringInvalid) +{ + oc_endpoint_t ep = oc::endpoint::FromString("coap://[::1]:42"); + // cannot fit scheme + std::array too_small{}; + EXPECT_EQ(-1, oc_endpoint_to_cstring(&ep, &too_small[0], too_small.size())); + + // can fit scheme but not address + std::array too_small2{}; + EXPECT_EQ(-1, oc_endpoint_to_cstring(&ep, &too_small2[0], too_small2.size())); +} + TEST_F(TestEndpoint, EndpointToStringInvalid) { EXPECT_EQ(-1, oc_endpoint_to_string(nullptr, nullptr)); @@ -102,6 +155,8 @@ TEST_F(TestEndpoint, EndpointToStringInvalid) EXPECT_EQ(-1, oc_endpoint_to_string(nullptr, &ep_str)); oc_endpoint_t ep{}; + EXPECT_EQ(-1, oc_endpoint_to_string(&ep, nullptr)); + EXPECT_EQ(-1, oc_endpoint_to_string(&ep, &ep_str)); } @@ -137,9 +192,9 @@ TEST_F(TestEndpoint, StringToEndpointInvalid) TEST_F(TestEndpoint, IPv6AddressToStringFail) { -#define ENDPOINT_ADDR "[fe80:123::1]:42" + constexpr std::string_view ENDPOINT_ADDR = "[fe80:123::1]:42"; + std::string ep_str = "coap://" + std::string(ENDPOINT_ADDR); - std::string ep_str = "coap://" ENDPOINT_ADDR; oc_endpoint_t ep = oc::endpoint::FromString(ep_str); std::array too_small{}; EXPECT_EQ(-1, oc_ipv6_address_and_port_to_string( @@ -152,33 +207,57 @@ TEST_F(TestEndpoint, IPv6AddressToStringFail) std::array too_small3{}; EXPECT_EQ(-1, oc_ipv6_address_and_port_to_string( &ep.addr.ipv6, too_small3.data(), too_small3.size())); -#undef ENDPOINT_ADDR } TEST_F(TestEndpoint, IPv6AddressToString) { -#define ENDPOINT_ADDR "[::1]:42" - std::string ep_str = "coap://" ENDPOINT_ADDR; + constexpr std::string_view ENDPOINT_ADDR = "[::1]:42"; + std::string ep_str = "coap://" + std::string(ENDPOINT_ADDR); oc_endpoint_t ep = oc::endpoint::FromString(ep_str); std::array exact{}; - EXPECT_EQ(0, oc_ipv6_address_and_port_to_string(&ep.addr.ipv6, exact.data(), + EXPECT_EQ(8, oc_ipv6_address_and_port_to_string(&ep.addr.ipv6, exact.data(), exact.size())); - EXPECT_STREQ(ENDPOINT_ADDR, exact.data()); + EXPECT_STREQ(ENDPOINT_ADDR.data(), exact.data()); std::array larger{}; - EXPECT_EQ(0, oc_ipv6_address_and_port_to_string(&ep.addr.ipv6, larger.data(), + EXPECT_EQ(8, oc_ipv6_address_and_port_to_string(&ep.addr.ipv6, larger.data(), larger.size())); - EXPECT_STREQ(ENDPOINT_ADDR, larger.data()); -#undef ENDPOINT_ADDR + EXPECT_STREQ(ENDPOINT_ADDR.data(), larger.data()); +} + +TEST_F(TestEndpoint, EndpointToString64Invalid) +{ + EXPECT_FALSE(oc_endpoint_to_string64(nullptr, nullptr)); + + oc_string64_t ep_str{}; + EXPECT_FALSE(oc_endpoint_to_string64(nullptr, &ep_str)); + + oc_endpoint_t ep{}; + EXPECT_FALSE(oc_endpoint_to_string64(&ep, nullptr)); + + EXPECT_FALSE(oc_endpoint_to_string64(&ep, &ep_str)); +} + +TEST_F(TestEndpoint, IPv6EndpointToString64) +{ + constexpr std::string_view ENDPOINT_ADDR = "[::1]:42"; + std::string ep_str = "coap://" + std::string(ENDPOINT_ADDR); + oc_endpoint_t ep = oc::endpoint::FromString(ep_str); + + oc_string64_t ep_str64{}; + oc_endpoint_to_string64(&ep, &ep_str64); + EXPECT_EQ(15, oc_string_len(ep_str64)); + EXPECT_EQ(15, strlen(oc_string(ep_str64))); + EXPECT_STREQ(ep_str.c_str(), oc_string(ep_str64)); } #ifdef OC_IPV4 TEST_F(TestEndpoint, IPv4AddressToStringFail) { -#define ENDPOINT_ADDR "127.0.0.1:80" - std::string ep_str = "coap://" ENDPOINT_ADDR; + constexpr std::string_view ENDPOINT_ADDR = "127.0.0.1:80"; + std::string ep_str = "coap://" + std::string(ENDPOINT_ADDR); oc_endpoint_t ep = oc::endpoint::FromString(ep_str); std::array too_small{}; EXPECT_EQ(-1, oc_ipv4_address_and_port_to_string( @@ -187,24 +266,37 @@ TEST_F(TestEndpoint, IPv4AddressToStringFail) std::array too_small2{}; EXPECT_EQ(-1, oc_ipv4_address_and_port_to_string( &ep.addr.ipv4, too_small2.data(), too_small2.size())); -#undef ENDPOINT_ADDR } TEST_F(TestEndpoint, IPv4AddressToString) { -#define ENDPOINT_ADDR "127.0.0.1:80" - std::string ep_str = "coap://" ENDPOINT_ADDR; + constexpr std::string_view ENDPOINT_ADDR = "127.0.0.1:80"; + std::string ep_str = "coap://" + std::string(ENDPOINT_ADDR); oc_endpoint_t ep = oc::endpoint::FromString(ep_str); std::array exact{}; - EXPECT_EQ(0, oc_ipv4_address_and_port_to_string(&ep.addr.ipv4, exact.data(), - exact.size())); - EXPECT_STREQ(ENDPOINT_ADDR, exact.data()); + EXPECT_EQ(12, oc_ipv4_address_and_port_to_string(&ep.addr.ipv4, exact.data(), + exact.size())); + EXPECT_STREQ(ENDPOINT_ADDR.data(), exact.data()); std::array larger{}; - EXPECT_EQ(0, oc_ipv4_address_and_port_to_string(&ep.addr.ipv4, larger.data(), - larger.size())); - EXPECT_STREQ(ENDPOINT_ADDR, larger.data()); -#undef ENDPOINT_ADDR + EXPECT_EQ(12, oc_ipv4_address_and_port_to_string(&ep.addr.ipv4, larger.data(), + larger.size())); + EXPECT_STREQ(ENDPOINT_ADDR.data(), larger.data()); +} + +TEST_F(TestEndpoint, IPv4EndpointToString64) +{ + constexpr std::string_view ENDPOINT_ADDR = "127.0.0.1:80"; + std::string ep_str = "coap://" + std::string(ENDPOINT_ADDR); + oc_endpoint_t ep = oc::endpoint::FromString(ep_str); + + EXPECT_FALSE(oc_endpoint_to_string64(&ep, nullptr)); + + oc_string64_t ep_str64{}; + EXPECT_TRUE(oc_endpoint_to_string64(&ep, &ep_str64)); + EXPECT_EQ(19, oc_string_len(ep_str64)); + EXPECT_EQ(19, strlen(oc_string(ep_str64))); + EXPECT_STREQ(ep_str.c_str(), oc_string(ep_str64)); } #endif /* OC_IPV4 */ @@ -226,10 +318,20 @@ TEST_F(TestEndpoint, StringToEndpoint) for (size_t i = 0; i < spu0.size(); ++i) { oc_endpoint_t ep = oc::endpoint::FromString(spu0[i]); + oc_string_t ep_str{}; EXPECT_EQ(0, oc_endpoint_to_string(&ep, &ep_str)); EXPECT_STREQ(exp[i].c_str(), oc_string(ep_str)); oc_free_string(&ep_str); + + oc_string64_t ep_str64{}; + EXPECT_TRUE(oc_endpoint_to_string64(&ep, &ep_str64)); + EXPECT_STREQ(exp[i].c_str(), oc_string(ep_str64)); + + std::array ep_buf{}; + EXPECT_EQ(exp[i].length(), + oc_endpoint_to_cstring(&ep, &ep_buf[0], ep_buf.size())); + EXPECT_STREQ(exp[i].c_str(), ep_buf.data()); } } @@ -806,3 +908,48 @@ TEST_F(TestEndpoint, EndpointHost) } #endif /* OC_IPV4 */ } + +#ifdef OC_CLIENT + +static constexpr size_t kDeviceID{ 0 }; + +class TestEndpointWithServer : public testing::Test { +public: + static void SetUpTestCase() { ASSERT_TRUE(oc::TestDevice::StartServer()); } + + static void TearDownTestCase() { oc::TestDevice::StopServer(); } +}; + +TEST_F(TestEndpointWithServer, SetLocalAddressFail) +{ + oc_endpoint_t ep{}; + oc_endpoint_set_local_address(&ep, UINT32_MAX); + EXPECT_TRUE(oc_endpoint_is_empty(&ep)); +} + +TEST_F(TestEndpointWithServer, SetLocalAddress) +{ + auto epOpt = oc::TestDevice::GetEndpoint(kDeviceID); + ASSERT_TRUE(epOpt.has_value()); + auto ep = std::move(*epOpt); + + std::array addr_empty{}; + ASSERT_EQ(0, memcmp(&ep.addr_local, &addr_empty[0], sizeof(ep.addr_local))); + + // oc_endpoint_set_local_address should modify only the output parameter, + // which is a local copy in this test case, so the global endpoints shouldn't + // be modified + auto checkEndpoints = [](size_t device) { + oc_endpoint_t *eps = oc_connectivity_get_endpoints(device); + while (eps != nullptr) { + EXPECT_NE(0, memcmp(&eps->addr, &eps->addr_local, sizeof(eps->addr))); + eps = eps->next; + } + }; + + oc_endpoint_set_local_address(&ep, ep.interface_index); + EXPECT_NE(0, memcmp(&ep.addr_local, &addr_empty[0], sizeof(ep.addr_local))); + checkEndpoints(kDeviceID); +} + +#endif /* OC_CLIENT */ diff --git a/api/unittest/plgdtimetest.cpp b/api/unittest/plgdtimetest.cpp index d3c5335437..f2d2e5fea1 100644 --- a/api/unittest/plgdtimetest.cpp +++ b/api/unittest/plgdtimetest.cpp @@ -594,8 +594,11 @@ TEST_F(TestPlgdTimeWithServer, FetchTimeFail) ep_flags |= TCP; #endif /* OC_TCP */ - std::string ep_str = - std::string(oc_endpoint_flags_to_scheme(ep_flags)) + "[ff02::158]:12345"; + std::array scheme{}; + ASSERT_NE(-1, + oc_endpoint_flags_to_scheme(ep_flags, &scheme[0], scheme.size())); + + std::string ep_str = std::string(scheme.data()) + "[ff02::158]:12345"; oc_endpoint_t ep = oc::endpoint::FromString(ep_str); auto fetch_handler = [](oc_status_t code, oc_clock_time_t, void *data) { diff --git a/include/oc_endpoint.h b/include/oc_endpoint.h index 7b84df403a..d60dcbd07b 100644 --- a/include/oc_endpoint.h +++ b/include/oc_endpoint.h @@ -27,6 +27,7 @@ #ifdef OC_OSCORE #include "messaging/coap/oscore_constants.h" #endif /* OC_OSCORE */ +#include "util/oc_compiler.h" #include @@ -139,11 +140,12 @@ void oc_free_endpoint(oc_endpoint_t *endpoint); * @param di device identifier (cannot be NULL) */ OC_API -void oc_endpoint_set_di(oc_endpoint_t *endpoint, const oc_uuid_t *di); +void oc_endpoint_set_di(oc_endpoint_t *endpoint, const oc_uuid_t *di) + OC_NONNULL(); /** * @brief convert the endpoint to a human readable string (e.g. - * "coaps://[fe::22]:/") + * "coaps://[fe::22]:1234") * * @param endpoint the endpoint * @param endpoint_str endpoint as human readable string @@ -153,6 +155,19 @@ OC_API int oc_endpoint_to_string(const oc_endpoint_t *endpoint, oc_string_t *endpoint_str); +/** + * @brief convert the endpoint to a human readable string (e.g. + * "coaps://[fe::22]:1234") + * + * @param endpoint the endpoint (cannot be NULL) + * @param buffer output buffer (cannot be NULL) + * @param buffer_size size of output buffer + * @return number of written bytes, -1 for error + */ +OC_API +int oc_endpoint_to_cstring(const oc_endpoint_t *endpoint, char *buffer, + size_t buffer_size) OC_NONNULL(); + /** * @brief string to endpoint * @@ -168,7 +183,7 @@ int oc_string_to_endpoint(const oc_string_t *endpoint_str, /** * @brief parse path component (ie. the part after the first '/') of a uri * - * @param[in] endpoint_str uri to parse + * @param endpoint_str uri to parse * @param[out] path output variable * @return 0 on success * @return -1 on failure @@ -215,16 +230,18 @@ int oc_endpoint_compare_address(const oc_endpoint_t *ep1, * @return false otherwise */ OC_API -bool oc_endpoint_is_empty(const oc_endpoint_t *endpoint); +bool oc_endpoint_is_empty(const oc_endpoint_t *endpoint) OC_NONNULL(); /** - * @brief set interface index on the endpoint + * @brief set local address on endpoint from the first device endpoint with + * matching flags and interface index * - * @param ep the endpoint (cannot be NULL) + * @param[in,out] ep the endpoint (cannot be NULL) * @param interface_index the interface index */ OC_API -void oc_endpoint_set_local_address(oc_endpoint_t *ep, unsigned interface_index); +void oc_endpoint_set_local_address(oc_endpoint_t *ep, unsigned interface_index) + OC_NONNULL(); /** * @brief copy endpoint @@ -233,16 +250,21 @@ void oc_endpoint_set_local_address(oc_endpoint_t *ep, unsigned interface_index); * @param src source endpoint (cannot be NULL) */ OC_API -void oc_endpoint_copy(oc_endpoint_t *dst, const oc_endpoint_t *src); +void oc_endpoint_copy(oc_endpoint_t *dst, const oc_endpoint_t *src) + OC_NONNULL(); /** * @brief copy list of endpoints * * @param dst destination list of endpoints (cannot be NULL) * @param src source list of endpoints + * + * @return 0 on success + * @return -1 on failure */ OC_API -int oc_endpoint_list_copy(oc_endpoint_t **dst, const oc_endpoint_t *src); +int oc_endpoint_list_copy(oc_endpoint_t **dst, const oc_endpoint_t *src) + OC_NONNULL(1); /** * @brief deallocate a linked list of endpoints diff --git a/include/oc_helpers.h b/include/oc_helpers.h index 2b38a3879c..ce054d0c2e 100644 --- a/include/oc_helpers.h +++ b/include/oc_helpers.h @@ -45,7 +45,7 @@ typedef struct oc_mmem oc_handle_t, oc_string_t, oc_array_t, oc_string_array_t, * @brief cast oc_string to string * */ -#define oc_string(ocstring) (oc_cast(ocstring, char)) +#define oc_string(ocstring) ((char *)(ocstring).ptr) #ifdef OC_MEMORY_TRACE #define oc_alloc_string(ocstring, size) \ diff --git a/messaging/coap/observe.c b/messaging/coap/observe.c index 22ff1cde2d..82472821c6 100644 --- a/messaging/coap/observe.c +++ b/messaging/coap/observe.c @@ -52,6 +52,7 @@ #ifdef OC_SERVER #include "api/oc_buffer_internal.h" +#include "api/oc_endpoint_internal.h" #include "api/oc_helpers_internal.h" #include "api/oc_query_internal.h" #include "api/oc_ri_internal.h" @@ -1064,15 +1065,13 @@ coap_iterate_observers(oc_resource_t *resource, oc_response_t *response, } if (prepare_response) { #if OC_DBG_IS_ENABLED - oc_string_t ep_str; - memset(&ep_str, 0, sizeof(oc_string_t)); + oc_string64_t ep_str; const char *ep_cstr = ""; - if (oc_endpoint_to_string(&obs->endpoint, &ep_str) == 0) { + if (oc_endpoint_to_string64(&obs->endpoint, &ep_str)) { ep_cstr = oc_string(ep_str); } COAP_DBG("prepare GET request to resource(%s) for endpoint %s", oc_string(resource->uri), ep_cstr); - oc_free_string(&ep_str); #endif /* OC_DBG_IS_ENABLED */ if (!coap_fill_response(response, resource, &obs->endpoint, iface_mask, true)) { diff --git a/messaging/coap/transactions.c b/messaging/coap/transactions.c index c7dcfd49aa..a00e58dc61 100644 --- a/messaging/coap/transactions.c +++ b/messaging/coap/transactions.c @@ -276,9 +276,9 @@ coap_free_transactions_by_endpoint(const oc_endpoint_t *endpoint, oc_status_t code) { #if OC_DBG_IS_ENABLED - char ep_addr[64] = { 0 }; - oc_endpoint_to_cstring(endpoint, ep_addr, OC_ARRAY_SIZE(ep_addr)); - COAP_DBG("free transactions for endpoint(%s)", ep_addr); + oc_string64_t ep_str; + oc_endpoint_to_string64(endpoint, &ep_str); + COAP_DBG("free transactions for endpoint(%s)", oc_string(ep_str)); #endif /* OC_DBG_IS_ENABLED */ #ifndef OC_CLIENT (void)code; diff --git a/port/common/oc_ip.c b/port/common/oc_ip.c index 088495b3f0..d47a0ad714 100644 --- a/port/common/oc_ip.c +++ b/port/common/oc_ip.c @@ -41,12 +41,13 @@ int oc_ipv6_address_to_string(const oc_ipv6_addr_t *ipv6, char *buffer, - uint32_t buffer_size) + size_t buffer_size) { assert(ipv6 != NULL); assert(buffer != NULL); - if (inet_ntop(AF_INET6, ipv6->address, buffer, buffer_size) == NULL) { + if (inet_ntop(AF_INET6, ipv6->address, buffer, (socklen_t)buffer_size) == + NULL) { return -1; } // safe: maximal IPv6 length is 45 @@ -55,42 +56,42 @@ oc_ipv6_address_to_string(const oc_ipv6_addr_t *ipv6, char *buffer, int oc_ipv6_address_and_port_to_string(const oc_ipv6_addr_t *ipv6, char *buffer, - uint32_t buffer_size) + size_t buffer_size) { assert(ipv6 != NULL); assert(buffer != NULL); - // shortest valid ipv6 address with a port + // shortest valid IPv6 address with a port if (buffer_size < sizeof("[::1]:X")) { return -1; } - uint32_t start = 0; + size_t start = 0; buffer[start++] = '['; int written = oc_ipv6_address_to_string(ipv6, &buffer[start], buffer_size - start); if (written < 0) { return -1; } - start += (uint32_t)written; - - written = snprintf(&buffer[start], buffer_size - start, "]:%u", ipv6->port); - if ((written < 0) || start + (uint32_t)written >= buffer_size) { + start += (size_t)written; + size_t remaining_space = buffer_size - start; + written = snprintf(&buffer[start], remaining_space, "]:%u", ipv6->port); + if (written < 0 || (size_t)written >= remaining_space) { return -1; } - return 0; + return (int)(start + written); } #ifdef OC_IPV4 int oc_ipv4_address_to_string(const oc_ipv4_addr_t *ipv4, char *buffer, - uint32_t buffer_size) + size_t buffer_size) { assert(buffer != NULL); const uint8_t *addr = ipv4->address; int written = snprintf(buffer, buffer_size, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]); - if ((written < 0) || (uint32_t)written >= buffer_size) { + if ((written < 0) || (size_t)written >= buffer_size) { return -1; } return written; @@ -98,7 +99,7 @@ oc_ipv4_address_to_string(const oc_ipv4_addr_t *ipv4, char *buffer, int oc_ipv4_address_and_port_to_string(const oc_ipv4_addr_t *ipv4, char *buffer, - uint32_t buffer_size) + size_t buffer_size) { assert(ipv4 != NULL); assert(buffer != NULL); @@ -107,13 +108,14 @@ oc_ipv4_address_and_port_to_string(const oc_ipv4_addr_t *ipv4, char *buffer, if (written < 0) { return -1; } + int ret = written; buffer_size -= written; written = snprintf(&buffer[written], buffer_size, ":%u", ipv4->port); - if ((written < 0) || (uint32_t)written >= buffer_size) { + if ((written < 0) || (size_t)written >= buffer_size) { return -1; } - return 0; + return ret + written; } #endif /* OC_IPV4 */ diff --git a/port/common/oc_ip.h b/port/common/oc_ip.h index c1419361bb..7b8dfbc2e1 100644 --- a/port/common/oc_ip.h +++ b/port/common/oc_ip.h @@ -31,21 +31,21 @@ extern "C" { /** @brief Convert an IPv6 address to a human readable string */ int oc_ipv6_address_to_string(const oc_ipv6_addr_t *ipv6, char *buffer, - uint32_t buffer_size) OC_NONNULL(); + size_t buffer_size) OC_NONNULL(); /** Convert an IPv6 address with port to a human readable string */ int oc_ipv6_address_and_port_to_string(const oc_ipv6_addr_t *ipv6, char *buffer, - uint32_t buffer_size) OC_NONNULL(); + size_t buffer_size) OC_NONNULL(); #ifdef OC_IPV4 /** @brief Convert an IPv4 address to a human readable string */ int oc_ipv4_address_to_string(const oc_ipv4_addr_t *ipv4, char *buffer, - uint32_t buffer_size) OC_NONNULL(); + size_t buffer_size) OC_NONNULL(); /** Convert an IPv4 address with port to a human readable string */ int oc_ipv4_address_and_port_to_string(const oc_ipv4_addr_t *ipv4, char *buffer, - uint32_t buffer_size) OC_NONNULL(); + size_t buffer_size) OC_NONNULL(); #endif /* OC_IPV4 */ diff --git a/port/linux/tcpsession.c b/port/linux/tcpsession.c index f27b427899..9a76c4366d 100644 --- a/port/linux/tcpsession.c +++ b/port/linux/tcpsession.c @@ -19,6 +19,7 @@ #define __USE_GNU #include "api/oc_buffer_internal.h" +#include "api/oc_endpoint_internal.h" #include "api/oc_network_events_internal.h" #include "api/oc_session_events_internal.h" #include "api/oc_tcp_internal.h" @@ -199,15 +200,14 @@ get_interface_index(int sock) static void log_new_session(oc_endpoint_t *endpoint, int sock, bool is_connected) { - oc_string_t ep; + oc_string64_t ep; const char *addr = ""; - if (oc_endpoint_to_string(endpoint, &ep) == 0) { + if (oc_endpoint_to_string64(endpoint, &ep)) { addr = oc_string(ep); } OC_DBG("new TCP session endpoint: %s, endpoint interface: %d, sock: %d, " "connected: %d", addr, endpoint->interface_index, sock, (int)is_connected); - oc_free_string(&ep); } #endif /* OC_DBG_IS_ENABLED */ diff --git a/security/oc_tls.c b/security/oc_tls.c index 6619328bf7..e5c1c83e05 100644 --- a/security/oc_tls.c +++ b/security/oc_tls.c @@ -20,6 +20,7 @@ #include "oc_tls_internal.h" #include "api/oc_buffer_internal.h" +#include "api/oc_endpoint_internal.h" #include "api/oc_events_internal.h" #include "api/oc_network_events_internal.h" #include "api/oc_session_events_internal.h" @@ -398,13 +399,12 @@ process_drop_event_for_removed_endpoint(oc_process_event_t ev, oc_message_t *message = (oc_message_t *)data; if (oc_endpoint_compare(&message->endpoint, endpoint) == 0) { #if OC_DBG_IS_ENABLED - oc_string_t endpoint_str; - oc_endpoint_to_string(&message->endpoint, &endpoint_str); + oc_string64_t endpoint_str; + oc_endpoint_to_string64(&message->endpoint, &endpoint_str); OC_DBG("oc_tls: dropping %s message for removed endpoint(%s)", (ev == oc_event_to_oc_process_event(RI_TO_TLS_EVENT)) ? "sent" : "received", oc_string(endpoint_str)); - oc_free_string(&endpoint_str); #endif /* OC_DBG_IS_ENABLED */ oc_message_unref(message); return true; @@ -416,12 +416,11 @@ static void oc_tls_free_peer(oc_tls_peer_t *peer, bool inactivity_cb, bool from_reset) { #if OC_DBG_IS_ENABLED - oc_string_t endpoint_str; - oc_endpoint_to_string(&peer->endpoint, &endpoint_str); + oc_string64_t endpoint_str; + oc_endpoint_to_string64(&peer->endpoint, &endpoint_str); OC_DBG("oc_tls: freeing peer(%p): endpoint(%s), role(%s)", (void *)peer, oc_string(endpoint_str), peer->role == MBEDTLS_SSL_IS_SERVER ? "server" : "client"); - oc_free_string(&endpoint_str); #endif /* OC_DBG_IS_ENABLED */ #ifdef OC_PKI if (peer->user_data.free != NULL) { @@ -2110,12 +2109,11 @@ oc_tls_add_new_peer(oc_tls_new_peer_params_t params) oc_list_add(g_tls_peers, peer); #if OC_DBG_IS_ENABLED - oc_string_t endpoint_str; - oc_endpoint_to_string(&peer->endpoint, &endpoint_str); + oc_string64_t endpoint_str; + oc_endpoint_to_string64(&peer->endpoint, &endpoint_str); OC_DBG("oc_tls: new peer(%p) added: endpoint(%s), role(%s)", (void *)peer, oc_string(endpoint_str), peer->role == MBEDTLS_SSL_IS_SERVER ? "server" : "client"); - oc_free_string(&endpoint_str); #endif /* OC_DBG_IS_ENABLED */ return peer; @@ -2939,13 +2937,12 @@ oc_tls_recv_message(oc_message_t *message) peer = oc_tls_get_peer(&message->endpoint); if (peer != NULL && peer->role != MBEDTLS_SSL_IS_CLIENT) { #if OC_ERR_IS_ENABLED - oc_string_t endpoint_str; - oc_endpoint_to_string(&message->endpoint, &endpoint_str); + oc_string64_t endpoint_str; + oc_endpoint_to_string64(&message->endpoint, &endpoint_str); // The peer is not a client, so it is not possible to receive a message. OC_ERR("oc_tls: TCP-TLS peer %p with endpoint(%s) is not in role as " "client but as server", (void *)peer, oc_string(endpoint_str)); - oc_free_string(&endpoint_str); #endif /* OC_ERR_IS_ENABLED */ peer = NULL; } diff --git a/tests/gtest/Device.cpp b/tests/gtest/Device.cpp index 9b6016d07a..7f07746ace 100644 --- a/tests/gtest/Device.cpp +++ b/tests/gtest/Device.cpp @@ -422,8 +422,9 @@ TestDevice::ClearDynamicResources() #endif /* OC_SERVER */ -std::optional -TestDevice::GetEndpoint(size_t device, unsigned flags, unsigned exclude_flags) +oc_endpoint_t * +TestDevice::GetEndpointPtr(size_t device, unsigned flags, + unsigned exclude_flags) { oc_endpoint_t *ep = oc_connectivity_get_endpoints(device); auto has_matching_flags = [](const oc_endpoint_t *ep, unsigned flags, @@ -446,10 +447,20 @@ TestDevice::GetEndpoint(size_t device, unsigned flags, unsigned exclude_flags) while (ep != nullptr) { if (has_matching_flags(ep, flags, exclude_flags) && has_matching_device(ep, device)) { - return *ep; + return ep; } ep = ep->next; } + return nullptr; +} + +std::optional +TestDevice::GetEndpoint(size_t device, unsigned flags, unsigned exclude_flags) +{ + oc_endpoint_t *ep = GetEndpointPtr(device, flags, exclude_flags); + if (ep != nullptr) { + return *ep; + } return std::nullopt; } diff --git a/tests/gtest/Device.h b/tests/gtest/Device.h index 2333d33dd5..abd3c1ab67 100644 --- a/tests/gtest/Device.h +++ b/tests/gtest/Device.h @@ -223,6 +223,15 @@ class TestDevice { size_t device, unsigned flags = defaultEndpointIncludeFlags(), unsigned exclude_flags = kDefaultEndpointExcludeFlags); + /** @brief Get pointer to a matching endpoint of a device + * + * @warning list of endpoints might get refreshed by each call of the method, + * so you should not store the pointer for later use + */ + static oc_endpoint_t *GetEndpointPtr( + size_t device, unsigned flags = defaultEndpointIncludeFlags(), + unsigned exclude_flags = kDefaultEndpointExcludeFlags); + private: static int SetSystemTime(oc_clock_time_t time, void *user_data); diff --git a/tests/gtest/Endpoint.cpp b/tests/gtest/Endpoint.cpp index 04cc8fb061..eae276db60 100644 --- a/tests/gtest/Endpoint.cpp +++ b/tests/gtest/Endpoint.cpp @@ -51,10 +51,9 @@ FromString(const std::string &addr, oc_endpoint_t *ep, oc_string_t *uri) std::string ToAddress(const oc_endpoint_t &ep) { - oc_string_t ep_str{}; - oc_endpoint_to_string(&ep, &ep_str); + oc_string64_t ep_str{}; + oc_endpoint_to_string64(&ep, &ep_str); std::string s(oc_string(ep_str)); - oc_free_string(&ep_str); return s; } From 92a18114623d8ad3f170b9d8f58f256b73aa0b8a Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Fri, 22 Sep 2023 15:33:39 +0200 Subject: [PATCH 05/11] Update query public API Extend the function signature to include the include the length of the key. If the length of the key is known then a call to strlen can be avoided. Added: - oc_iterate_query_get_values_v1 - oc_get_query_value_v1 - oc_query_value_exists_v1 - oc_ri_get_query_value_v1 - oc_ri_query_exists_v1 Deprecated: - oc_iterate_query_get_values - oc_get_query_value - oc_query_value_exists - oc_ri_get_query_value - oc_ri_query_exists --- .github/workflows/cmake-linux.yml | 2 +- CMakeLists.txt | 2 +- api/oc_core_res.c | 4 +- api/oc_discovery.c | 3 +- api/oc_discovery_internal.h | 2 +- api/oc_push.c | 39 ++- api/oc_query.c | 127 ++++++-- api/oc_ri.c | 8 +- api/unittest/querytest.cpp | 482 ++++++++++++++++++++++++++++- apps/cloud_proxy.c | 20 +- apps/server_certification_tests.c | 11 +- apps/simpleserver-TVAppAndAction.c | 8 +- apps/smart_home_server_linux.c | 5 +- include/oc_api.h | 74 +++-- include/oc_ri.h | 53 +++- messaging/coap/coap_options.h | 2 + security/oc_acl.c | 3 +- security/oc_cred.c | 3 +- security/oc_doxm.c | 6 +- security/oc_roles.c | 3 +- swig/swig_interfaces/oc_api.i | 2 + swig/swig_interfaces/oc_ri.i | 1 + 22 files changed, 735 insertions(+), 125 deletions(-) diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index 9e7250c46b..53bd8b743b 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -119,7 +119,7 @@ jobs: with: build_args: -DOC_LOG_MAXIMUM_LOG_LEVEL=INFO -DOC_CLOUD_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_WKCORE_ENABLED=ON -DOC_SOFTWARE_UPDATE_ENABLED=ON -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_PUSH_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON ${{ matrix.args }} build_type: ${{ (github.event_name == 'workflow_dispatch' && inputs.build_type) || 'Debug' }} - clang: ${{ github.event_name == 'workflow_dispatch' && inputs.clang }} + clang: ${{ ((github.event_name == 'workflow_dispatch' && inputs.clang) || matrix.clang) || false }} coverage: false install_mbedtls: ${{ github.event_name == 'workflow_dispatch' && inputs.install_mbedtls }} install_tinycbor: ${{ github.event_name == 'workflow_dispatch' && inputs.install_tinycbor }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eb860a4f2..cb0492197d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -988,7 +988,7 @@ if(BUILD_TESTING AND(UNIX OR MINGW)) oc_package_add_test(TARGET cloudtest SOURCES ${COMMONTEST_SRC} ${CLOUDTEST_SRC}) endif() - if(UNIX) + if(UNIX AND NOT OC_TSAN_ENABLED) # install https://github.com/wolfcw/libfaketime for this test suit to run find_library(FAKETIME_LIBRARY NAMES libfaketimeMT.so.1 diff --git a/api/oc_core_res.c b/api/oc_core_res.c index 2edfd74e9b..f5d3bf865e 100644 --- a/api/oc_core_res.c +++ b/api/oc_core_res.c @@ -833,8 +833,8 @@ oc_filter_resource_by_rt(const oc_resource_t *resource, do { const char *rt = NULL; int rt_len = -1; - more_query_params = - oc_iterate_query_get_values(request, "rt", &rt, &rt_len); + more_query_params = oc_iterate_query_get_values_v1( + request, "rt", OC_CHAR_ARRAY_LEN("rt"), &rt, &rt_len); if (rt_len <= 0) { continue; } diff --git a/api/oc_discovery.c b/api/oc_discovery.c index 55d80cf125..8760384ee5 100644 --- a/api/oc_discovery.c +++ b/api/oc_discovery.c @@ -919,7 +919,8 @@ discovery_resource_get(oc_request_t *request, oc_interface_mask_t iface_mask, // for dev without SVRs, ignore queries for backward compatibility #ifdef OC_SECURITY const char *q; - int ql = oc_get_query_value(request, OCF_RES_QUERY_SDUUID, &q); + int ql = oc_get_query_value_v1(request, OCF_RES_QUERY_SDUUID, + OC_CHAR_ARRAY_LEN(OCF_RES_QUERY_SDUUID), &q); if (ql > 0 && !discovery_check_sduuid(request, q, (size_t)ql)) { return; } diff --git a/api/oc_discovery_internal.h b/api/oc_discovery_internal.h index 85a48f8e38..e511009c7a 100644 --- a/api/oc_discovery_internal.h +++ b/api/oc_discovery_internal.h @@ -73,7 +73,7 @@ void oc_create_discovery_resource(size_t device); * the callbacks) * * @param payload the recieved discovery response - * @param len lenght of the payload + * @param len length of the payload * @param handler handler of the discovery * @param endpoint endpoint * @param user_data the user data to be supplied to the handler diff --git a/api/oc_push.c b/api/oc_push.c index 1ac8e2383a..0f4340e5f3 100644 --- a/api/oc_push.c +++ b/api/oc_push.c @@ -243,6 +243,10 @@ static void (*oc_push_arrived)(oc_pushd_resource_rep_t *) = NULL; #define OC_PUSH_PROP_PRT "prt" #define OC_PUSH_PROP_PIF "pif" #define OC_PUSH_PROP_SOURCERT "sourcert" +#define OC_PUSH_PROP_RECEIVEURI "receiveruri" +#define OC_PUSH_PROP_RTS "rts" + +#define OC_PUSH_QUERY_RECEIVERURI "receiveruri" void oc_set_on_push_arrived(oc_on_push_arrived_t func) @@ -1853,7 +1857,8 @@ _update_recv_obj(oc_recv_t *recv_obj, const oc_recvs_t *recvs_instance, while (rep) { switch (rep->type) { case OC_REP_STRING: - if (strcmp(oc_string(rep->name), "receiveruri") == 0) { + if (oc_rep_is_property(rep, OC_PUSH_PROP_RECEIVEURI, + OC_CHAR_ARRAY_LEN(OC_PUSH_PROP_RECEIVEURI))) { OC_PUSH_DBG("target receiveruri: \"%s\", new receiveruri: \"%s\"", oc_string(recv_obj->receiveruri), oc_string(rep->value.string)); @@ -1880,7 +1885,8 @@ _update_recv_obj(oc_recv_t *recv_obj, const oc_recvs_t *recvs_instance, break; case OC_REP_STRING_ARRAY: - if (strcmp(oc_string(rep->name), "rts") == 0) { + if (oc_rep_is_property(rep, OC_PUSH_PROP_RTS, + OC_CHAR_ARRAY_LEN(OC_PUSH_PROP_RTS))) { oc_free_string_array(&recv_obj->rts); size_t len = oc_string_array_get_allocated_size(rep->value.array); oc_new_string_array(&recv_obj->rts, len); @@ -1922,7 +1928,8 @@ _create_recv_obj(oc_recvs_t *recvs_instance, oc_rep_t *rep) while (rep) { switch (rep->type) { case OC_REP_STRING: - if (strcmp(oc_string(rep->name), "receiveruri") == 0) { + if (oc_rep_is_property(rep, OC_PUSH_PROP_RECEIVEURI, + OC_CHAR_ARRAY_LEN(OC_PUSH_PROP_RECEIVEURI))) { oc_new_string(&recv_obj->receiveruri, oc_string(rep->value.string), oc_string_len(rep->value.string)); mandatory_property_check |= 0x1; @@ -1930,7 +1937,8 @@ _create_recv_obj(oc_recvs_t *recvs_instance, oc_rep_t *rep) break; case OC_REP_STRING_ARRAY: - if (strcmp(oc_string(rep->name), "rts") == 0) { + if (oc_rep_is_property(rep, OC_PUSH_PROP_RTS, + OC_CHAR_ARRAY_LEN(OC_PUSH_PROP_RTS))) { size_t len = oc_string_array_get_allocated_size(rep->value.array); oc_new_string_array(&recv_obj->rts, len); @@ -1993,13 +2001,15 @@ _validate_recv_obj_list(oc_rep_t *obj_list) for (; rep != NULL; rep = rep->next) { switch (rep->type) { case OC_REP_STRING: - if (strcmp(oc_string(rep->name), "receiveruri") == 0) { + if (oc_rep_is_property(rep, OC_PUSH_PROP_RECEIVEURI, + OC_CHAR_ARRAY_LEN(OC_PUSH_PROP_RECEIVEURI))) { mandatory_property_check |= 0x1; } break; case OC_REP_STRING_ARRAY: - if (strcmp(oc_string(rep->name), "rts") == 0) { + if (oc_rep_is_property(rep, OC_PUSH_PROP_RTS, + OC_CHAR_ARRAY_LEN(OC_PUSH_PROP_RTS))) { mandatory_property_check |= 0x2; } break; @@ -2077,8 +2087,9 @@ post_pushrecv(oc_request_t *request, oc_interface_mask_t iface_mask, /* try to get "receiveruri" parameter */ if (request->query) { - uri_param_len = oc_ri_get_query_value(request->query, request->query_len, - "receiveruri", &uri_param); + uri_param_len = oc_ri_get_query_value_v1( + request->query, request->query_len, OC_PUSH_QUERY_RECEIVERURI, + OC_CHAR_ARRAY_LEN(OC_PUSH_QUERY_RECEIVERURI), &uri_param); if (uri_param_len != -1) { OC_PUSH_DBG( "received query string: \"%.*s\", found \"receiveruri\": \"%.*s\" ", @@ -2113,7 +2124,7 @@ post_pushrecv(oc_request_t *request, oc_interface_mask_t iface_mask, uri_param_len, uri_param); /* - * if there is already NORMAL resource whose path is same as requested + * if there is already NORMAL resource whose path is same as equested * target uri, just ignore this request and return error! */ if (oc_ri_get_app_resource_by_uri(uri_param, uri_param_len, @@ -2173,8 +2184,9 @@ delete_pushrecv(oc_request_t *request, oc_interface_mask_t iface_mask, /* try to get "receiveruri" parameter */ if (request->query) { - uri_param_len = oc_ri_get_query_value(request->query, request->query_len, - "receiveruri", &uri_param); + uri_param_len = oc_ri_get_query_value_v1( + request->query, request->query_len, OC_PUSH_QUERY_RECEIVERURI, + OC_CHAR_ARRAY_LEN(OC_PUSH_QUERY_RECEIVERURI), &uri_param); if (uri_param_len != -1) { OC_PUSH_DBG( "received query string: \"%.*s\", found \"receiveruri\": \"%.*s\" ", @@ -2214,13 +2226,10 @@ delete_pushrecv(oc_request_t *request, oc_interface_mask_t iface_mask, /* if the given `receiveruri` parameter is not in existing receivers * array, add new receiver object to the receivers array */ #ifdef OC_PUSHDEBUG - // oc_string_t uri; - // oc_new_string(&uri, uri_param, uri_param_len); OC_PUSH_DBG( "can't find receiver object which has uri(\"%.*s\"), ignore it...", uri_param_len, uri_param); -// oc_free_string(&uri); -#endif +#endif /* OC_PUSHDEBUG */ result = OC_STATUS_NOT_FOUND; } } else { diff --git a/api/oc_query.c b/api/oc_query.c index d1431f78ef..1916dc74f7 100644 --- a/api/oc_query.c +++ b/api/oc_query.c @@ -19,8 +19,10 @@ #include "api/oc_query_internal.h" #include "api/oc_helpers_internal.h" #include "api/oc_ri_internal.h" +#include "messaging/coap/coap_options.h" #include "oc_api.h" #include "oc_ri.h" +#include "util/oc_secure_string_internal.h" #include #include @@ -78,8 +80,9 @@ static key_value_pair_t oc_ri_find_query_nth_key_value_pair(const char *query, size_t query_len, size_t n) { + assert(n > 0); key_value_pair_t res = { NULL, 0, NULL, 0 }; - if (query == NULL) { + if (query == NULL || query_len == 0) { return res; } const char *start = query; @@ -122,6 +125,7 @@ oc_ri_get_query_nth_key_value(const char *query, size_t query_len, { assert(key != NULL); assert(key_len != NULL); + assert(n > 0); key_value_pair_t kv = oc_ri_find_query_nth_key_value_pair(query, query_len, n); if (kv.key == NULL) { @@ -146,23 +150,31 @@ oc_ri_get_query_nth_key_value(const char *query, size_t query_len, } int -oc_ri_get_query_value(const char *query, size_t query_len, const char *key, - const char **value) +oc_ri_get_query_value_v1(const char *query, size_t query_len, const char *key, + size_t key_len, const char **value) { assert(key != NULL); + // we can limit the key length by the maximal allowed query option size + if (key_len > COAP_OPTION_QUERY_MAX_SIZE) { + return -1; + } + int found = -1; size_t pos = 0; while (pos < query_len) { const char *k; size_t kl; + const char *v; size_t vl; int next_pos = oc_ri_get_query_nth_key_value(query + pos, query_len - pos, - &k, &kl, value, &vl, 1u); + &k, &kl, &v, &vl, 1u); if (next_pos == -1) { return -1; } - if (kl == strlen(key) && strncasecmp(key, k, kl) == 0) { + if (kl == key_len && strncasecmp(key, k, kl) == 0) { + assert(vl <= INT_MAX); + *value = v; found = (int)vl; break; } @@ -172,12 +184,22 @@ oc_ri_get_query_value(const char *query, size_t query_len, const char *key, return found; } +int +oc_ri_get_query_value(const char *query, size_t query_len, const char *key, + const char **value) +{ + assert(key != NULL); + size_t key_len = oc_strnlen(key, COAP_OPTION_QUERY_MAX_SIZE + 1); + return oc_ri_get_query_value_v1(query, query_len, key, key_len, value); +} + int oc_ri_query_nth_key_exists(const char *query, size_t query_len, const char **key, size_t *key_len, size_t n) { assert(key != NULL); assert(key_len != NULL); + assert(n > 0); key_value_pair_t kv = oc_ri_find_query_nth_key_value_pair(query, query_len, n); if (kv.key == NULL) { @@ -189,17 +211,23 @@ oc_ri_query_nth_key_exists(const char *query, size_t query_len, size_t next_pos = kv.value != NULL ? (size_t)((kv.value + kv.value_len) - query) : kv.key_len; - ++next_pos; // +1 for '&' + if (next_pos < query_len) { + ++next_pos; // +1 for '&' + } assert(next_pos <= INT_MAX); return (int)next_pos; } -int -oc_ri_query_exists(const char *query, size_t query_len, const char *key) +bool +oc_ri_query_exists_v1(const char *query, size_t query_len, const char *key, + size_t key_len) { assert(key != NULL); - int found = -1; + if (key_len > COAP_OPTION_QUERY_MAX_SIZE) { + return false; + } + size_t pos = 0; while (pos < query_len) { const char *k; @@ -208,20 +236,23 @@ oc_ri_query_exists(const char *query, size_t query_len, const char *key) oc_ri_query_nth_key_exists(query + pos, query_len - pos, &k, &kl, 1u); if (next_pos == -1) { - return -1; + return false; } - - if (kl == strlen(key) && strncasecmp(key, k, kl) == 0) { - found = 1; - break; - } - if (next_pos == 0) { - return -1; + if (kl == key_len && strncasecmp(key, k, kl) == 0) { + return true; } - - pos += next_pos; + assert(next_pos != 0); + pos += (size_t)next_pos; } - return found; + return false; +} + +int +oc_ri_query_exists(const char *query, size_t query_len, const char *key) +{ + assert(key != NULL); + size_t key_len = oc_strnlen(key, COAP_OPTION_QUERY_MAX_SIZE + 1); + return oc_ri_query_exists_v1(query, query_len, key, key_len) ? 1 : -1; } void @@ -241,10 +272,18 @@ oc_iterate_query(const oc_request_t *request, const char **key, size_t *key_len, } bool -oc_iterate_query_get_values(const oc_request_t *request, const char *key, - const char **value, int *value_len) +oc_iterate_query_get_values_v1(const oc_request_t *request, const char *key, + size_t key_len, const char **value, + int *value_len) { - size_t key_len = strlen(key); + assert(request != NULL); + assert(key != NULL); + assert(value != NULL); + assert(value_len != NULL); + if (key_len > COAP_OPTION_QUERY_MAX_SIZE) { + return false; + } + int pos = 0; do { const char *k = NULL; @@ -254,6 +293,7 @@ oc_iterate_query_get_values(const oc_request_t *request, const char *key, pos = oc_iterate_query(request, &k, &k_len, &v, &v_len); if (pos != -1 && key_len == k_len && memcmp(key, k, k_len) == 0) { *value = v; + assert(v_len <= INT_MAX); *value_len = (int)v_len; goto more_or_done; } @@ -263,21 +303,48 @@ oc_iterate_query_get_values(const oc_request_t *request, const char *key, return pos != -1 && (size_t)pos < request->query_len; } +bool +oc_iterate_query_get_values(const oc_request_t *request, const char *key, + const char **value, int *value_len) +{ + size_t key_len = oc_strnlen(key, COAP_OPTION_QUERY_MAX_SIZE + 1); + return oc_iterate_query_get_values_v1(request, key, key_len, value, + value_len); +} + +int +oc_get_query_value_v1(const oc_request_t *request, const char *key, + size_t key_len, const char **value) +{ + if (request == NULL) { + return -1; + } + return oc_ri_get_query_value_v1(request->query, request->query_len, key, + key_len, value); +} + int oc_get_query_value(const oc_request_t *request, const char *key, const char **value) { - if (!request) { - return -1; + size_t key_len = oc_strnlen(key, COAP_OPTION_QUERY_MAX_SIZE + 1); + return oc_get_query_value_v1(request, key, key_len, value); +} + +bool +oc_query_value_exists_v1(const oc_request_t *request, const char *key, + size_t key_len) +{ + if (request == NULL) { + return false; } - return oc_ri_get_query_value(request->query, request->query_len, key, value); + return oc_ri_query_exists_v1(request->query, request->query_len, key, + key_len); } int oc_query_value_exists(const oc_request_t *request, const char *key) { - if (!request) { - return -1; - } - return oc_ri_query_exists(request->query, request->query_len, key); + size_t key_len = oc_strnlen(key, COAP_OPTION_QUERY_MAX_SIZE + 1); + return oc_query_value_exists_v1(request, key, key_len) ? 1 : -1; } diff --git a/api/oc_ri.c b/api/oc_ri.c index 64b05ad835..43437994e2 100644 --- a/api/oc_ri.c +++ b/api/oc_ri.c @@ -345,8 +345,8 @@ oc_ri_filter_request_by_device_id(size_t device, const char *query, oc_uuid_to_str(device_id, di, OC_UUID_LEN); for (size_t pos = 0; pos < query_len;) { const char *value = NULL; - int value_len = - oc_ri_get_query_value(query + pos, query_len - pos, "di", &value); + int value_len = oc_ri_get_query_value_v1(query + pos, query_len - pos, "di", + OC_CHAR_ARRAY_LEN("di"), &value); if (value_len == -1) { // pos == 0 key not found, otherwise device id not match the device. return pos == 0; @@ -1256,8 +1256,8 @@ oc_ri_invoke_coap_entity_handler(coap_make_response_ctx_t *ctx, request_obj.query_len = uri_query_len; /* Check if query string includes interface selection. */ const char *iface = NULL; - int iface_len = - oc_ri_get_query_value(uri_query, uri_query_len, "if", &iface); + int iface_len = oc_ri_get_query_value_v1(uri_query, uri_query_len, "if", + OC_CHAR_ARRAY_LEN("if"), &iface); if (iface_len != -1 && iface != NULL) { iface_query |= oc_ri_get_interface_mask(iface, (size_t)iface_len); } diff --git a/api/unittest/querytest.cpp b/api/unittest/querytest.cpp index d65b4b8412..a388a44c15 100644 --- a/api/unittest/querytest.cpp +++ b/api/unittest/querytest.cpp @@ -18,6 +18,7 @@ #include "api/oc_query_internal.h" #include "api/oc_ri_internal.h" +#include "messaging/coap/coap_options.h" #include "oc_api.h" #include "oc_ri.h" @@ -28,16 +29,113 @@ class TestQuery : public testing::Test {}; -TEST_F(TestQuery, RIGetQueryValueEmpty_N) +TEST_F(TestQuery, RIGetQueryNthKeyValue_F) { - const char *value; + const char *k = nullptr; + size_t klen = 0; + EXPECT_EQ(-1, oc_ri_get_query_nth_key_value(nullptr, 0, &k, &klen, nullptr, + nullptr, 1)); + EXPECT_EQ(nullptr, k); + EXPECT_EQ(0, klen); + + EXPECT_EQ( + -1, oc_ri_get_query_nth_key_value("", 0, &k, &klen, nullptr, nullptr, 1)); + EXPECT_EQ(nullptr, k); + EXPECT_EQ(0, klen); + + std::string key = "key="; + EXPECT_EQ(-1, oc_ri_get_query_nth_key_value(key.c_str(), key.length(), &k, + &klen, nullptr, nullptr, 2)); + EXPECT_EQ(nullptr, k); + EXPECT_EQ(0, klen); +} + +TEST_F(TestQuery, RIGetQueryNthKeyValue_P) +{ + std::string key1 = "key1"; + std::string value1 = "value1"; + std::string query = key1 + "=" + value1; + const char *k = nullptr; + size_t klen = 0; + EXPECT_EQ(query.length() + 1, + oc_ri_get_query_nth_key_value(query.c_str(), query.length(), &k, + &klen, nullptr, nullptr, 1)); + EXPECT_EQ(key1.length(), klen); + EXPECT_EQ(0, memcmp(key1.c_str(), k, klen)); + + for (int i = 1; i <= 3; ++i) { + query = ""; + std::vector keys{}; + std::vector values{}; + for (int j = 0; j < i; ++j) { + std::string key = "key" + std::to_string(j); + std::string value = "value" + std::to_string(j); + query += key + "=" + value; + keys.emplace_back(key); + values.emplace_back(value); + if (j < i - 1) { + query += "&"; + } + } + for (int j = 0; j < i; ++j) { + k = nullptr; + klen = 0; + const char *v = nullptr; + size_t vlen = 0; + EXPECT_NE(-1, oc_ri_get_query_nth_key_value(query.c_str(), query.length(), + &k, &klen, &v, &vlen, j + 1)); + EXPECT_EQ(keys[j].length(), klen); + EXPECT_EQ(0, memcmp(keys[j].c_str(), k, klen)); + EXPECT_EQ(values[j].length(), vlen); + EXPECT_EQ(0, memcmp(values[j].c_str(), v, vlen)); + } + } +} + +TEST_F(TestQuery, RIGetQueryValue_F) +{ + const char *value = nullptr; int ret = oc_ri_get_query_value(nullptr, 0, "key", &value); - EXPECT_EQ(-1, ret) << "N input NULL " - << "key"; + EXPECT_EQ(-1, ret) << "N input NULL"; + EXPECT_EQ(nullptr, value); ret = oc_ri_get_query_value("", 0, "key", &value); - EXPECT_EQ(-1, ret) << "N input \"\" " - << "key"; + EXPECT_EQ(-1, ret) << "N input \"\""; + EXPECT_EQ(nullptr, value); + + std::string query = "key1=1"; + auto key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + ret = + oc_ri_get_query_value(query.c_str(), query.length(), key.c_str(), &value); + EXPECT_EQ(-1, ret) << "N input " << query << " " << key; + EXPECT_EQ(nullptr, value); +} + +TEST_F(TestQuery, RIGetQueryValueV1_F) +{ + std::string key1 = "key1"; + const char *value = nullptr; + int ret = + oc_ri_get_query_value_v1(nullptr, 0, key1.c_str(), key1.length(), &value); + EXPECT_EQ(-1, ret) << "N input NULL " << key1; + EXPECT_EQ(nullptr, value); + + ret = oc_ri_get_query_value_v1("", 0, key1.c_str(), key1.length(), &value); + EXPECT_EQ(-1, ret) << "N input \"\" " << key1; + EXPECT_EQ(nullptr, value); + + std::string query = "key1=1"; + std::string key2 = "key2"; + ret = oc_ri_get_query_value_v1(query.c_str(), query.length(), key2.c_str(), + key2.length(), &value); + EXPECT_EQ(-1, ret) << "N input " << query << " " << key2; + EXPECT_EQ(nullptr, value); + + auto key3 = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + ret = oc_ri_get_query_value_v1(query.c_str(), query.length(), key3.c_str(), + key3.length(), &value); + EXPECT_EQ(-1, ret) << "N input " << query << " " << key3; + EXPECT_EQ(nullptr, value); } TEST_F(TestQuery, RIGetQueryValue_P) @@ -75,6 +173,120 @@ TEST_F(TestQuery, RIGetQueryValue_P) } } +TEST_F(TestQuery, RIGetQueryValueV1_P) +{ + using string_pair = std::pair; + std::vector inputs = { + { "key", "" }, + { "key=1337", "1337" }, + { "data=1&key=22", "22" }, + { "key=333&data=3", "333" }, + { "x&key=42&data=3", "42" }, + { "y&x&key=5225&data=3", "5225" }, + { "y&x&key=6", "6" }, + { "y&x&key=777&y", "777" }, + }; + std::string key = "key"; + const char *v; + for (const auto &[query, exp] : inputs) { + int ret = oc_ri_get_query_value_v1(query.c_str(), query.length(), + key.c_str(), key.length(), &v); + EXPECT_EQ(exp.length(), ret) << "P input " << query << " " << key; + if (ret > 0) { + std::string value(v, ret); + EXPECT_STREQ(exp.c_str(), value.c_str()) + << "P input " << query << " " + << "value " << exp << " vs " << value; + } + } + + std::string key2 = "key2"; + for (const auto &[query, _] : inputs) { + int ret = oc_ri_get_query_value_v1(query.c_str(), query.length(), + key2.c_str(), key2.length(), nullptr); + EXPECT_EQ(-1, ret) << "N input " << query << " " << key2; + } +} + +TEST_F(TestQuery, RIQueryNthKeyExists_F) +{ + const char *k = nullptr; + size_t klen = 0; + EXPECT_EQ(-1, oc_ri_query_nth_key_exists(nullptr, 0, &k, &klen, 1)); + EXPECT_EQ(nullptr, k); + EXPECT_EQ(0, klen); + + EXPECT_EQ(-1, oc_ri_query_nth_key_exists("", 0, &k, &klen, 1)); + EXPECT_EQ(nullptr, k); + EXPECT_EQ(0, klen); + + EXPECT_EQ(-1, oc_ri_query_nth_key_exists("&&&", 0, &k, &klen, 1)); + EXPECT_EQ(nullptr, k); + EXPECT_EQ(0, klen); +} + +TEST_F(TestQuery, RIQueryNthKeyExists_P) +{ + for (int i = 1; i <= 3; ++i) { + std::string query = ""; + std::vector keys{}; + for (int j = 0; j < i; ++j) { + std::string key = "key" + std::to_string(j); + query += key + "=" + std::to_string(j); + keys.emplace_back(key); + if (j < i - 1) { + query += "&"; + } + } + for (int j = 0; j < i; ++j) { + const char *k = nullptr; + size_t klen = 0; + int vlen = oc_ri_query_nth_key_exists(query.c_str(), query.length(), &k, + &klen, j + 1); + EXPECT_NE(-1, vlen); + if (j == i - 1) { + EXPECT_EQ(query.length(), vlen); + } + EXPECT_EQ(keys[j].length(), klen); + EXPECT_EQ(0, memcmp(keys[j].c_str(), k, klen)); + } + } +} + +TEST_F(TestQuery, RIQueryExists_F) +{ + EXPECT_EQ(-1, oc_ri_query_exists(nullptr, 0, "")); + + std::string query = "key1=1"; + std::string key = "key"; + EXPECT_EQ(-1, oc_ri_query_exists(query.c_str(), query.length(), key.c_str())); + key = "key11"; + EXPECT_EQ(-1, oc_ri_query_exists(query.c_str(), query.length(), key.c_str())); + key = "1"; + EXPECT_EQ(-1, oc_ri_query_exists(query.c_str(), query.length(), key.c_str())); + key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + EXPECT_EQ(-1, oc_ri_query_exists(query.c_str(), query.length(), key.c_str())); +} + +TEST_F(TestQuery, RIQueryExistsV1_F) +{ + EXPECT_FALSE(oc_ri_query_exists_v1(nullptr, 0, "", 0)); + + std::string query = "key1=1"; + std::string key = "key"; + EXPECT_FALSE(oc_ri_query_exists_v1(query.c_str(), query.length(), key.c_str(), + key.length())); + key = "key11"; + EXPECT_FALSE(oc_ri_query_exists_v1(query.c_str(), query.length(), key.c_str(), + key.length())); + key = "1"; + EXPECT_FALSE(oc_ri_query_exists_v1(query.c_str(), query.length(), key.c_str(), + key.length())); + key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + EXPECT_FALSE(oc_ri_query_exists_v1(query.c_str(), query.length(), key.c_str(), + key.length())); +} + TEST_F(TestQuery, RIQueryExists_P) { std::vector inputs = { "key=1", @@ -87,30 +299,83 @@ TEST_F(TestQuery, RIQueryExists_P) "y=&key=2&data=3", "y=1&x&key=2&data=3", "y=1&x&key" }; - int ret; for (const auto &input : inputs) { - ret = oc_ri_query_exists(input.c_str(), input.length(), "key"); + int ret = oc_ri_query_exists(input.c_str(), input.length(), "key"); EXPECT_EQ(1, ret) << "P input " << input << " " << "key"; } inputs.emplace_back(""); for (const auto &input : inputs) { - ret = oc_ri_query_exists(input.c_str(), input.length(), "key2"); + int ret = oc_ri_query_exists(input.c_str(), input.length(), "key2"); EXPECT_EQ(-1, ret) << "N input " << input << " " << "key2"; } } +TEST_F(TestQuery, RIQueryExistsV1_P) +{ + std::vector inputs = { "key=1", + "key", + "data=1&key=2", + "data=2&key", + "key&data=3", + "key=2&data=3", + "x=1&key=2&data=3", + "y=&key=2&data=3", + "y=1&x&key=2&data=3", + "y=1&x&key" }; + std::string key = "key"; + for (const auto &input : inputs) { + bool ret = oc_ri_query_exists_v1(input.c_str(), input.length(), key.c_str(), + key.length()); + EXPECT_TRUE(ret) << "P input " << input << " " << key; + } + + inputs.emplace_back(""); + std::string key2 = "key2"; + for (const auto &input : inputs) { + bool ret = oc_ri_query_exists_v1(input.c_str(), input.length(), + key2.c_str(), key2.length()); + EXPECT_FALSE(ret) << "N input " << input << " " << key2; + } +} + TEST_F(TestQuery, GetValue_F) { EXPECT_EQ(-1, oc_get_query_value(nullptr, "", nullptr)); + + oc_request_t request{}; + std::string query = "key1=1&key2=2"; + request.query = query.c_str(); + request.query_len = query.length(); + oc_init_query_iterator(); + auto key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + const char *value = nullptr; + EXPECT_EQ(-1, oc_get_query_value(&request, key.c_str(), &value)); + EXPECT_EQ(nullptr, value); +} + +TEST_F(TestQuery, GetValueV1_F) +{ + EXPECT_EQ(-1, oc_get_query_value_v1(nullptr, "", 0, nullptr)); + + oc_request_t request{}; + std::string query = "key1=1&key2=2"; + request.query = query.c_str(); + request.query_len = query.length(); + oc_init_query_iterator(); + auto key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + const char *value = nullptr; + EXPECT_EQ(-1, + oc_get_query_value_v1(&request, key.c_str(), key.length(), &value)); + EXPECT_EQ(nullptr, value); } TEST_F(TestQuery, GetValueEmpty_N) { - const char *value; - oc_request_t request; + const char *value = nullptr; + oc_request_t request{}; request.query = nullptr; request.query_len = 0; int ret = oc_get_query_value(&request, "key", &value); @@ -123,9 +388,163 @@ TEST_F(TestQuery, GetValueEmpty_N) << "key"; } +TEST_F(TestQuery, GetValueV1Empty_N) +{ + const char *value = nullptr; + oc_request_t request{}; + request.query = nullptr; + request.query_len = 0; + std::string key = "key"; + int ret = oc_get_query_value_v1(&request, key.c_str(), key.length(), &value); + EXPECT_EQ(-1, ret) << "N input NULL " << key; + + request.query = ""; + ret = oc_get_query_value_v1(&request, key.c_str(), key.length(), &value); + EXPECT_EQ(-1, ret) << "N input \"\" " << key; +} + +TEST_F(TestQuery, IterateValues_F) +{ + oc_init_query_iterator(); + oc_request_t request{}; + const char *v = nullptr; + int vlen = 0; + EXPECT_FALSE(oc_iterate_query_get_values(&request, "", &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + + oc_init_query_iterator(); + std::string query = "key1=1&key2=2"; + request.query = query.c_str(); + request.query_len = query.length(); + EXPECT_FALSE(oc_iterate_query_get_values(&request, "", &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + EXPECT_FALSE(oc_iterate_query_get_values(&request, "key", &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + EXPECT_FALSE(oc_iterate_query_get_values(&request, "key12", &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + EXPECT_FALSE(oc_iterate_query_get_values(&request, "keyF", &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + auto key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + EXPECT_FALSE(oc_iterate_query_get_values(&request, key.c_str(), &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); +} + +TEST_F(TestQuery, IterateValuesV1_F) +{ + oc_init_query_iterator(); + oc_request_t request{}; + const char *v = nullptr; + int vlen = 0; + EXPECT_FALSE(oc_iterate_query_get_values_v1(&request, "", 0, &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + + oc_init_query_iterator(); + std::string query = "key1=1&key2=2"; + request.query = query.c_str(); + request.query_len = query.length(); + EXPECT_FALSE(oc_iterate_query_get_values_v1(&request, "", 0, &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + std::string key = "key"; + EXPECT_FALSE(oc_iterate_query_get_values_v1(&request, key.c_str(), + key.length(), &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + key = "key12"; + EXPECT_FALSE(oc_iterate_query_get_values_v1(&request, key.c_str(), + key.length(), &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + key = "keyF"; + EXPECT_FALSE(oc_iterate_query_get_values_v1(&request, key.c_str(), + key.length(), &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); + key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + EXPECT_FALSE(oc_iterate_query_get_values_v1(&request, key.c_str(), + key.length(), &v, &vlen)); + EXPECT_EQ(nullptr, v); + EXPECT_EQ(0, vlen); +} + +TEST_F(TestQuery, IterateValuesV1_P) +{ + std::string query = "key1=1&key2=2&key3=3"; + oc_request_t request{}; + request.query = query.c_str(); + request.query_len = query.length(); + const char *v = nullptr; + int vlen = 0; + + std::string key = "key1"; + oc_init_query_iterator(); + EXPECT_TRUE(oc_iterate_query_get_values_v1(&request, key.c_str(), + key.length(), &v, &vlen)); + EXPECT_EQ(1, vlen); + EXPECT_EQ(0, memcmp("1", v, static_cast(vlen))); + + key = "key2"; + oc_init_query_iterator(); + EXPECT_TRUE(oc_iterate_query_get_values_v1(&request, key.c_str(), + key.length(), &v, &vlen)); + EXPECT_EQ(1, vlen); + EXPECT_EQ(0, memcmp("2", v, static_cast(vlen))); + + key = "key3"; + oc_init_query_iterator(); + EXPECT_FALSE(oc_iterate_query_get_values_v1(&request, key.c_str(), + key.length(), &v, &vlen)); + EXPECT_EQ(1, vlen); + EXPECT_EQ(0, memcmp("3", v, static_cast(vlen))); + + query = "key=1&key=2&key=3"; + request.query = query.c_str(); + request.query_len = query.length(); + oc_init_query_iterator(); + key = "key"; + bool more = true; + int i = 1; + do { + more = oc_iterate_query_get_values_v1(&request, key.c_str(), key.length(), + &v, &vlen); + EXPECT_EQ(1, vlen); + EXPECT_EQ(0, + memcmp(std::to_string(i).c_str(), v, static_cast(vlen))); + ++i; + } while (more); +} + TEST_F(TestQuery, Exists_F) { EXPECT_EQ(-1, oc_query_value_exists(nullptr, "")); + + oc_request_t request{}; + std::string query = "key1=1&key2=2"; + request.query = query.c_str(); + request.query_len = query.length(); + oc_init_query_iterator(); + auto key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + EXPECT_EQ(-1, oc_query_value_exists(&request, key.c_str())); +} + +TEST_F(TestQuery, ExistsV1_F) +{ + EXPECT_FALSE(oc_query_value_exists_v1(nullptr, "", 0)); + + oc_request_t request{}; + std::string query = "key1=1&key2=2"; + request.query = query.c_str(); + request.query_len = query.length(); + oc_init_query_iterator(); + auto key = std::string(COAP_OPTION_QUERY_MAX_SIZE + 1, 'a'); + EXPECT_FALSE(oc_query_value_exists_v1(&request, key.c_str(), key.length())); } TEST_F(TestQuery, Exists_P) @@ -140,27 +559,58 @@ TEST_F(TestQuery, Exists_P) "y=&key=2&data=3", "y=1&x&key=2&data=3", "y=1&x&key" }; - int ret; for (const auto &input : inputs) { - oc_request_t request; + oc_request_t request{}; request.query = input.c_str(); request.query_len = input.length(); - ret = oc_query_value_exists(&request, "key"); + int ret = oc_query_value_exists(&request, "key"); EXPECT_EQ(1, ret) << "P input " << input << " " << "key"; } inputs.emplace_back(""); for (const auto &input : inputs) { - oc_request_t request; + oc_request_t request{}; request.query = input.c_str(); request.query_len = input.length(); - ret = oc_query_value_exists(&request, "key2"); + int ret = oc_query_value_exists(&request, "key2"); EXPECT_EQ(-1, ret) << "N input " << input << " " << "key2"; } } +TEST_F(TestQuery, ExistsV1_P) +{ + std::vector inputs = { "key=1", + "key", + "data=1&key=2", + "data=2&key", + "key&data=3", + "key=2&data=3", + "x=1&key=2&data=3", + "y=&key=2&data=3", + "y=1&x&key=2&data=3", + "y=1&x&key" }; + std::string key = "key"; + for (const auto &input : inputs) { + oc_request_t request{}; + request.query = input.c_str(); + request.query_len = input.length(); + bool ret = oc_query_value_exists_v1(&request, key.c_str(), key.length()); + EXPECT_TRUE(ret) << "P input " << input << " " << key; + } + + inputs.emplace_back(""); + std::string key2 = "key2"; + for (const auto &input : inputs) { + oc_request_t request{}; + request.query = input.c_str(); + request.query_len = input.length(); + bool ret = oc_query_value_exists_v1(&request, key2.c_str(), key2.length()); + EXPECT_FALSE(ret) << "N input " << input << " " << key2; + } +} + #ifdef OC_SERVER TEST_F(TestQuery, EncodeInterface_F) diff --git a/apps/cloud_proxy.c b/apps/cloud_proxy.c index 3c8ad4b393..3666a5bc77 100644 --- a/apps/cloud_proxy.c +++ b/apps/cloud_proxy.c @@ -197,6 +197,7 @@ static CRITICAL_SECTION cs; /**< event loop variable */ #endif #define btoa(x) ((x) ? "true" : "false") +#define CHAR_ARRAY_LEN(x) (sizeof(x) - 1) #define MAX_STRING 30 /**< max size of the strings. */ #define MAX_PAYLOAD_STRING 65 /**< max size strings in the payload */ @@ -682,7 +683,8 @@ post_d2dserverlist(oc_request_t *request, oc_interface_mask_t interfaces, const char *_scan = NULL; /* not null terminated */ /* do a scan to all devices */ - int _scan_len = oc_get_query_value(request, "scan", &_scan); + int _scan_len = + oc_get_query_value_v1(request, "scan", CHAR_ARRAY_LEN("scan"), &_scan); if (_scan_len > 0) { OC_PRINTF(" Send multicast discovery\n"); issue_requests_all(); @@ -690,7 +692,8 @@ post_d2dserverlist(oc_request_t *request, oc_interface_mask_t interfaces, return; } - int _di_len = oc_get_query_value(request, "di", &_di); + int _di_len = + oc_get_query_value_v1(request, "di", CHAR_ARRAY_LEN("di"), &_di); if (_di_len != -1) { /* input check * ^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$ @@ -770,7 +773,6 @@ STATIC void delete_d2dserverlist(oc_request_t *request, oc_interface_mask_t interfaces, void *user_data) { - (void)request; (void)interfaces; (void)user_data; bool error_state = true; @@ -780,7 +782,8 @@ delete_d2dserverlist(oc_request_t *request, oc_interface_mask_t interfaces, /* query name 'di' type: 'string'*/ const char *_di = NULL; /* not null terminated */ - int _di_len = oc_get_query_value(request, "di", &_di); + int _di_len = + oc_get_query_value_v1(request, "di", CHAR_ARRAY_LEN("di"), &_di); if (_di_len != -1) { /* input check * ^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$ @@ -1124,7 +1127,6 @@ STATIC void post_resource(oc_request_t *request, oc_interface_mask_t interfaces, void *user_data) { - (void)request; (void)interfaces; (void)user_data; @@ -1227,9 +1229,6 @@ STATIC void delete_resource(oc_request_t *request, oc_interface_mask_t interfaces, void *user_data) { - (void)request; - (void)interfaces; - (void)user_data; (void)interfaces; (void)user_data; char query_as_string[MAX_URI_LENGTH * 2] = ""; @@ -1277,11 +1276,10 @@ delete_resource(oc_request_t *request, oc_interface_mask_t interfaces, STATIC oc_discovery_flags_t discovery(const char *anchor, const char *uri, oc_string_array_t types, oc_interface_mask_t iface_mask, const oc_endpoint_t *endpoint, - oc_resource_properties_t bm, bool x, void *user_data) + oc_resource_properties_t bm, bool more, void *user_data) { - (void)user_data; (void)bm; - (void)x; + (void)more; int i; char url[MAX_URI_LENGTH]; char this_udn[200]; diff --git a/apps/server_certification_tests.c b/apps/server_certification_tests.c index 30df80ae71..84472be2d9 100644 --- a/apps/server_certification_tests.c +++ b/apps/server_certification_tests.c @@ -58,6 +58,8 @@ static const char *manufacturer = "OCF"; #define btoa(x) ((x) ? "true" : "false") #define MAX_ARRAY 10 /* max size of the array */ +#define CHAR_ARRAY_LEN(x) (sizeof(x) - 1) + /* global property variables for path: "/dali" */ static const char *g_dali_RESOURCE_PROPERTY_NAME_pld = "pld"; /* the name for the attribute */ @@ -606,7 +608,8 @@ get_temp(oc_request_t *request, oc_interface_mask_t iface_mask, void *user_data) bool invalid_query = false; const char *units; units_t u = temp_units; - int units_len = oc_get_query_value(request, "units", &units); + int units_len = + oc_get_query_value_v1(request, "units", CHAR_ARRAY_LEN("units"), &units); if (units_len != -1) { if (units[0] == 'K') { u = K; @@ -1633,7 +1636,8 @@ get_remotecontrol(oc_request_t *request, oc_interface_mask_t iface_mask, const char *action = NULL; int action_len = -1; oc_init_query_iterator(); - oc_iterate_query_get_values(request, "action", &action, &action_len); + oc_iterate_query_get_values_v1(request, "action", CHAR_ARRAY_LEN("action"), + &action, &action_len); if (action_len > 0) { // An action parm was received @@ -1678,7 +1682,8 @@ post_remotecontrol(oc_request_t *request, oc_interface_mask_t iface_mask, const char *action = NULL; int action_len = -1; oc_init_query_iterator(); - oc_iterate_query_get_values(request, "action", &action, &action_len); + oc_iterate_query_get_values_v1(request, "action", CHAR_ARRAY_LEN("action"), + &action, &action_len); if (action_len > 0) { OC_PRINTF("POST action length = %d \n", action_len); diff --git a/apps/simpleserver-TVAppAndAction.c b/apps/simpleserver-TVAppAndAction.c index da445f4cb7..b152779530 100644 --- a/apps/simpleserver-TVAppAndAction.c +++ b/apps/simpleserver-TVAppAndAction.c @@ -32,6 +32,8 @@ #include #include +#define CHAR_ARRAY_LEN(x) (sizeof(x) - 1) + #ifdef __linux__ #include static pthread_mutex_t mutex; @@ -228,7 +230,8 @@ get_remotecontrol(oc_request_t *request, oc_interface_mask_t iface_mask, const char *action = NULL; int action_len = -1; oc_init_query_iterator(); - oc_iterate_query_get_values(request, "action", &action, &action_len); + oc_iterate_query_get_values_v1(request, "action", CHAR_ARRAY_LEN("action"), + &action, &action_len); if (action_len > 0) { // An action parm was received @@ -273,7 +276,8 @@ post_remotecontrol(oc_request_t *request, oc_interface_mask_t iface_mask, const char *action = NULL; int action_len = -1; oc_init_query_iterator(); - oc_iterate_query_get_values(request, "action", &action, &action_len); + oc_iterate_query_get_values_v1(request, "action", CHAR_ARRAY_LEN("action"), + &action, &action_len); if (action_len > 0) { printf("POST action length = %d \n", action_len); diff --git a/apps/smart_home_server_linux.c b/apps/smart_home_server_linux.c index 5f3a3fa687..e025792425 100644 --- a/apps/smart_home_server_linux.c +++ b/apps/smart_home_server_linux.c @@ -32,6 +32,8 @@ #include #include +#define CHAR_ARRAY_LEN(x) (sizeof(x) - 1) + static pthread_mutex_t mutex; static pthread_cond_t cv; @@ -134,7 +136,8 @@ get_temp(oc_request_t *request, oc_interface_mask_t iface_mask, void *user_data) bool invalid_query = false; const char *units; units_t u = temp_units; - int units_len = oc_get_query_value(request, "units", &units); + int units_len = + oc_get_query_value_v1(request, "units", CHAR_ARRAY_LEN("units"), &units); if (units_len != -1) { if (units[0] == 'K') { u = K; diff --git a/include/oc_api.h b/include/oc_api.h index f5491e351e..138e8e1bb3 100644 --- a/include/oc_api.h +++ b/include/oc_api.h @@ -1383,9 +1383,9 @@ int oc_iterate_query(const oc_request_t *request, const char **key, OC_NONNULL(1, 2, 3); /** - * Iterate though the URI query parameters for a specific key. + * @brief Iterate though the URI query parameters for a specific key. * - * Before calling oc_iterate_query_get_values() the first time + * Before calling oc_iterate_query_get_values_v1() the first time * oc_init_query_iterator() must be called to reset the query iterator to the * first query parameter. * @@ -1396,13 +1396,13 @@ int oc_iterate_query(const oc_request_t *request, const char **key, * Example: * ``` * bool more_query_params = false; - * const char* expected_value = "world" - * char *value = NULL; + * const char* expected_value = "world"; + * const char *value = NULL; * int value_len = -1; * oc_init_query_iterator(); * do { - * more_query_params = oc_iterate_query_get_values(request, "hello", - * &value, &value_len); + * more_query_params = oc_iterate_query_get_values_v1(request, "hello", + * strlen("hello"), &value, &value_len); * if (rt_len > 0) { * printf("Found %s = %.*s\n", "hello", value_len, value); * } @@ -1412,6 +1412,7 @@ int oc_iterate_query(const oc_request_t *request, const char **key, * @param[in] request the oc_request_t that contains the query parameters * (cannot be NULL) * @param[in] key the key being searched for (cannot be NULL) + * @param[in] key_len the length of the key * @param[out] value pointer to the value string for to the key=value pair * (cannot be NULL) * @param[out] value_len the length of the value string (cannot be NULL) @@ -1419,13 +1420,25 @@ int oc_iterate_query(const oc_request_t *request, const char **key, * @return True if there are more query parameters to iterate through */ OC_API +bool oc_iterate_query_get_values_v1(const oc_request_t *request, + const char *key, size_t key_len, + const char **value, int *value_len) + OC_NONNULL(); + +/** + * @brief Iterate though the URI query parameters for a specific key. + * + * @deprecated replaced by oc_iterate_query_get_values_v1 in v2.2.5.9 + */ +OC_API bool oc_iterate_query_get_values(const oc_request_t *request, const char *key, const char **value, int *value_len) - OC_NONNULL(); + OC_NONNULL() + OC_DEPRECATED("replaced by oc_iterate_query_get_values_v1 in v2.2.5.9"); /** - * Get a pointer to the start of the value in a URL query parameter key=value - * pair. + * @brief Get a pointer to the start of the value in a URL query parameter + * key=value pair. * * @note The char pointer returned is pointing to the string location in the * query string. Do not rely on a nul terminator to find the end of the @@ -1433,6 +1446,7 @@ bool oc_iterate_query_get_values(const oc_request_t *request, const char *key, * * @param[in] request the oc_request_t that contains the query parameters * @param[in] key the key being searched for (cannot be NULL) + * @param[in] key_len the length of the key * @param[out] value pointer to the value string assigned to the key * * @return @@ -1440,22 +1454,46 @@ bool oc_iterate_query_get_values(const oc_request_t *request, const char *key, * - `-1` if there are no additional query parameters */ OC_API +int oc_get_query_value_v1(const oc_request_t *request, const char *key, + size_t key_len, const char **value) OC_NONNULL(2); + +/** + * @brief Get a pointer to the start of the value in a URL query parameter + * key=value pair. + * + * @deprecated replaced by oc_get_query_value_v1 in v2.2.5.9 + */ +OC_API int oc_get_query_value(const oc_request_t *request, const char *key, - const char **value) OC_NONNULL(2); + const char **value) OC_NONNULL(2) + OC_DEPRECATED("replaced by oc_get_query_value_v1 in v2.2.5.9"); /** - * Checks if a query parameter 'key' exist in the URL query parameter + * @brief Checks if a query parameter 'key' exist in the URL query parameter * - * @param[in] request the oc_request_t that contains the query parameters - * @param[in] key the key being searched for (cannot be NULL) + * @param request the oc_request_t that contains the query parameters + * @param key the key being searched for (cannot be NULL) + * @param key_len the length of the key * - * @return - * - 1 exist - * - -1 does not exist + * @return true if the key exist in the query parameter + * @return false if the key does not exist in the query parameter + */ +OC_API +bool oc_query_value_exists_v1(const oc_request_t *request, const char *key, + size_t key_len) OC_NONNULL(2); + +/** + * @brief Checks if a query parameter 'key' exist in the URL query parameter + * + * @return 1 if the key exist in the query parameter + * @return -1 if the key does not exist in the query parameter + * + * @deprecated replaced by oc_query_value_exists_v1 in v2.2.5.9 */ OC_API int oc_query_value_exists(const oc_request_t *request, const char *key) - OC_NONNULL(2); + OC_NONNULL(2) + OC_DEPRECATED("replaced by oc_query_value_exists_v1 in v2.2.5.9"); /** * Called after the response to a GET, PUT, POST or DELETE call has been @@ -1597,7 +1635,7 @@ bool oc_get_response_payload_raw(const oc_client_response_t *response, * * @param request the request * @param msg the message in ascii - * @param msg_len the lenght of the message + * @param msg_len the length of the message * @param response_code the coap response code */ OC_API diff --git a/include/oc_ri.h b/include/oc_ri.h index 77dddb6290..3b57aab05b 100644 --- a/include/oc_ri.h +++ b/include/oc_ri.h @@ -525,7 +525,7 @@ oc_interface_mask_t oc_ri_get_interface_mask(const char *iface, * @brief retrieve the resource by uri and device index * * @param uri the uri of the resource - * @param uri_len the lenght of the uri + * @param uri_len the length of the uri * @param device the device index * @return oc_resource_t* the resource structure */ @@ -626,7 +626,7 @@ bool oc_ri_on_delete_resource_remove_callback(oc_ri_delete_resource_cb_t cb) * @param[out] key_len the length of the key (cannot be NULL) * @param[out] value the value belonging to the key * @param[out] value_len the length of the value - * @param n the position to query + * @param n the position to query (must be > 0) * @return int the position of the next key value pair in the query * @return int -1 on failure */ @@ -639,36 +639,61 @@ int oc_ri_get_query_nth_key_value(const char *query, size_t query_len, * @brief retrieve the value of the query parameter "key" * * @param query the input query - * @param query_len the query lenght + * @param query_len the query length * @param key the wanted key (cannot be NULL) + * @param key_len the length of the wanted key * @param value the returned value - * @return int the lenght of the value + * @return -1 if the key is not found + * @return the length of the value + */ +int oc_ri_get_query_value_v1(const char *query, size_t query_len, + const char *key, size_t key_len, + const char **value) OC_NONNULL(3); + +/** + * @brief retrieve the value of the query parameter "key" + * + * @deprecated replaced by oc_ri_get_query_value_v1 in v2.2.5.9 */ int oc_ri_get_query_value(const char *query, size_t query_len, const char *key, - const char **value) OC_NONNULL(3); + const char **value) OC_NONNULL(3) + OC_DEPRECATED("replaced by oc_ri_get_query_value_v1 in v2.2.5.9"); /** - * @brief checks if key exist in query + * @brief Checks if key exist in query * - * @param[in] query the query to inspect - * @param[in] query_len the lenght of the query - * @param[in] key the key to be checked if exist, key is null terminated (cannot + * @param query the query to inspect + * @param query_len the length of the query + * @param key the key to be checked if exist, key is null terminated (cannot * be NULL) - * @return int -1 = not exists + * @param key_len the key length + * @return true if key exists + */ +bool oc_ri_query_exists_v1(const char *query, size_t query_len, const char *key, + size_t key_len) OC_NONNULL(3); + +/** + * @brief Checks if key exist in query + * + * @return -1 if key does not exist + * + * @deprecated replaced by oc_ri_query_exists_v1 in v2.2.5.9 */ int oc_ri_query_exists(const char *query, size_t query_len, const char *key) - OC_NONNULL(3); + OC_NONNULL(3) OC_DEPRECATED("replaced by oc_ri_query_exists_v1 in v2.2.5.9"); /** * @brief check if the nth key exists * * @param query the query to inspect - * @param query_len the lenght of the query + * @param query_len the length of the query * @param key the key to be checked if exist, key is not null terminated (cannot * be NULL) * @param key_len the key length (cannot be NULL) - * @param n index of the key - * @return int -1 = not exists + * @param n index of the key (must be > 0) + * @return -1 if key does not exist + * @return >= 0 if key exists and the value is the position of the next key in + * the query or query_len if it is the last key */ int oc_ri_query_nth_key_exists(const char *query, size_t query_len, const char **key, size_t *key_len, size_t n) diff --git a/messaging/coap/coap_options.h b/messaging/coap/coap_options.h index 08925577df..4f506a012b 100644 --- a/messaging/coap/coap_options.h +++ b/messaging/coap/coap_options.h @@ -87,6 +87,8 @@ extern "C" { +-----+---+---+---+---+----------------+--------+--------+----------+ */ +#define COAP_OPTION_QUERY_MAX_SIZE (255) + /** * @brief Get the Content-Format option value. * diff --git a/security/oc_acl.c b/security/oc_acl.c index 75dc540dd2..d5f5c03eac 100644 --- a/security/oc_acl.c +++ b/security/oc_acl.c @@ -1364,7 +1364,8 @@ delete_acl(oc_request_t *request, oc_interface_mask_t iface_mask, void *data) bool success = false; const char *query_param = 0; - int ret = oc_get_query_value(request, "aceid", &query_param); + int ret = oc_get_query_value_v1(request, "aceid", OC_CHAR_ARRAY_LEN("aceid"), + &query_param); int aceid = 0; if (ret != -1) { aceid = (int)strtoul(query_param, NULL, 10); diff --git a/security/oc_cred.c b/security/oc_cred.c index ee00c39653..239595a6ad 100644 --- a/security/oc_cred.c +++ b/security/oc_cred.c @@ -1832,7 +1832,8 @@ cred_resource_delete(oc_request_t *request, oc_interface_mask_t iface_mask, } const char *query_param = NULL; - int ret = oc_get_query_value(request, "credid", &query_param); + int ret = oc_get_query_value_v1(request, "credid", + OC_CHAR_ARRAY_LEN("credid"), &query_param); if (ret != -1) { errno = 0; long credid = diff --git a/security/oc_doxm.c b/security/oc_doxm.c index 684550d2c9..c9d3281167 100644 --- a/security/oc_doxm.c +++ b/security/oc_doxm.c @@ -289,7 +289,8 @@ get_doxm(oc_request_t *request, oc_interface_mask_t iface_mask, void *data) case OC_IF_RW: case OC_IF_BASELINE: { const char *q; - int ql = oc_get_query_value(request, OC_DOXM_OWNED, &q); + int ql = oc_get_query_value_v1(request, OC_DOXM_OWNED, + OC_CHAR_ARRAY_LEN(OC_DOXM_OWNED), &q); size_t device = request->resource->device; if (ql > 0 && @@ -313,7 +314,8 @@ get_doxm(oc_request_t *request, oc_interface_mask_t iface_mask, void *data) // FOR DEVELOPMENT USE ONLY #ifdef OC_DOXM_UUID_FILTER const char *q2; - int ql2 = oc_get_query_value(request, OC_DOXM_DEVICEUUID, &q2); + int ql2 = oc_get_query_value_v1(request, OC_DOXM_DEVICEUUID, + OC_CHAR_ARRAY_LEN(OC_DOXM_DEVICEUUID), &q2); // q2 is not null terminated, so we subtract 1 from the comparison length if (ql2 > 0) { diff --git a/security/oc_roles.c b/security/oc_roles.c index e3076b126d..5ffd291c8c 100644 --- a/security/oc_roles.c +++ b/security/oc_roles.c @@ -371,7 +371,8 @@ roles_resource_delete(oc_request_t *request, oc_interface_mask_t iface_mask, (void)data; const oc_tls_peer_t *client = oc_tls_get_peer(request->origin); const char *query_param = NULL; - int ret = oc_get_query_value(request, "credid", &query_param); + int ret = oc_get_query_value_v1(request, "credid", + OC_CHAR_ARRAY_LEN("credid"), &query_param); if (ret == -1) { // no query param, delete all roles oc_sec_free_roles(client); diff --git a/swig/swig_interfaces/oc_api.i b/swig/swig_interfaces/oc_api.i index 0dd10a2a8d..489134f3ab 100644 --- a/swig/swig_interfaces/oc_api.i +++ b/swig/swig_interfaces/oc_api.i @@ -901,7 +901,9 @@ void jni_oc_con_callback(size_t device_index, const oc_rep_t *rep) %ignore oc_init_query_iterator; %ignore oc_iterate_query; %ignore oc_get_query_value; +%ignore oc_get_query_value_v1; %ignore oc_iterate_query_get_values; +%ignore oc_iterate_query_get_values_v1; %typemap(jni) jobject getQueryValues "jobject"; %typemap(jtype) jobject getQueryValues "java.util.List"; diff --git a/swig/swig_interfaces/oc_ri.i b/swig/swig_interfaces/oc_ri.i index 6a47c711db..45ab06e1a9 100644 --- a/swig/swig_interfaces/oc_ri.i +++ b/swig/swig_interfaces/oc_ri.i @@ -167,6 +167,7 @@ struct oc_response_s %ignore oc_ri_free_resource_properties; %ignore oc_ri_get_query_nth_key_value; %ignore oc_ri_get_query_value; +%ignore oc_ri_get_query_value_v1; %ignore oc_ri_get_interface_mask; #define OC_API From 40eb6bc7d262581b719e06b58633a14e62c4ed00 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Fri, 22 Sep 2023 07:35:32 +0000 Subject: [PATCH 06/11] TLS: Drop messages associated with a closed endpoint in the processes When a session has been closed, we also need to clean up the process events associated with the endpoint. --- CMakeLists.txt | 20 +++--- api/oc_events.c | 82 +++++++++++++++++++++++ api/oc_events_internal.h | 14 ++++ api/oc_network_events.c | 69 ++++++++++++++++---- api/oc_network_events_internal.h | 21 ++++-- api/oc_resource_factory_internal.h | 4 ++ api/unittest/eventstest.cpp | 39 +++++++++++ security/oc_oscore_engine.c | 2 +- security/oc_pstat.c | 6 +- security/oc_tls.c | 84 ++++++++++++++++++++---- security/oc_tls_internal.h | 10 +++ security/unittest/tlstest.cpp | 101 ++++++++++++++++++++++++++++- util/oc_list.h | 5 ++ util/unittest/etimertest.cpp | 4 +- 14 files changed, 410 insertions(+), 51 deletions(-) create mode 100644 api/unittest/eventstest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index cb0492197d..37950fc783 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -599,11 +599,11 @@ endif() # enable clang-tidy for iotivity targets oc_enable_clang_tidy() -add_library(common-obj OBJECT ${COMMON_SRC}) -target_compile_definitions(common-obj PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} PUBLIC ${PUBLIC_COMPILE_DEFINITIONS}) -target_compile_options(common-obj PRIVATE ${PRIVATE_COMPILE_OPTIONS}) -target_include_directories(common-obj PRIVATE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/port ${PORT_INCLUDE_DIR}) -target_link_libraries(common-obj PRIVATE ${TINYCBOR_DEP}) +add_library(client-common-obj OBJECT ${COMMON_SRC}) +target_compile_definitions(client-common-obj PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} PUBLIC ${PUBLIC_COMPILE_DEFINITIONS} "OC_CLIENT") +target_compile_options(client-common-obj PRIVATE ${PRIVATE_COMPILE_OPTIONS}) +target_include_directories(client-common-obj PRIVATE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/port ${PORT_INCLUDE_DIR}) +target_link_libraries(client-common-obj PRIVATE ${TINYCBOR_DEP}) add_library(client-obj OBJECT ${CLIENT_SRC}) target_compile_definitions(client-obj PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} PUBLIC ${PUBLIC_COMPILE_DEFINITIONS} "OC_CLIENT") @@ -614,7 +614,7 @@ if(OC_SECURITY_ENABLED) target_link_libraries(client-obj PRIVATE ${MBEDTLS_DEP}) endif() -add_library(server-obj OBJECT ${SERVER_SRC}) +add_library(server-obj OBJECT ${COMMON_SRC} ${SERVER_SRC}) target_compile_definitions(server-obj PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} PUBLIC ${PUBLIC_COMPILE_DEFINITIONS} "OC_SERVER") target_compile_options(server-obj PRIVATE ${PRIVATE_COMPILE_OPTIONS}) target_include_directories(server-obj PRIVATE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/port ${PORT_INCLUDE_DIR}) @@ -623,7 +623,7 @@ if(OC_SECURITY_ENABLED) target_link_libraries(server-obj PRIVATE ${MBEDTLS_DEP}) endif() -add_library(client-server-obj OBJECT ${CLIENT_SRC}) +add_library(client-server-obj OBJECT ${COMMON_SRC} ${CLIENT_SRC}) target_compile_definitions(client-server-obj PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} PUBLIC ${PUBLIC_COMPILE_DEFINITIONS} "OC_CLIENT" "OC_SERVER") target_compile_options(client-server-obj PRIVATE ${PRIVATE_COMPILE_OPTIONS}) target_include_directories(client-server-obj PRIVATE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/port ${PORT_INCLUDE_DIR}) @@ -657,7 +657,7 @@ endif() # ####### Compose static and shared libraries ######## # Client set(client-lib-obj - $ + $ $ ) @@ -713,7 +713,6 @@ endif() # Server set(server-lib-obj - $ $ ) @@ -769,7 +768,6 @@ endif() # Client-Server set(client-server-lib-obj - $ $ ) @@ -842,7 +840,7 @@ endif() if(OC_SECURITY_ENABLED) # Python client set(client-python-lib-obj - $ + $ $ $ ) diff --git a/api/oc_events.c b/api/oc_events.c index 49e85bac8d..3f95d4f458 100644 --- a/api/oc_events.c +++ b/api/oc_events.c @@ -18,6 +18,7 @@ ***************************************************************************/ #include "oc_events_internal.h" +#include "util/oc_features.h" #include @@ -38,3 +39,84 @@ oc_event_to_oc_process_event(oc_events_t event) assert(event < __NUM_OC_EVENT_TYPES__); return oc_events[event]; } + +#if OC_DBG_IS_ENABLED + +oc_string_view_t +oc_process_event_name(oc_process_event_t event) +{ + if (event == oc_event_to_oc_process_event(INBOUND_NETWORK_EVENT)) { + return OC_STRING_VIEW("inbound-message"); + } + if (event == oc_event_to_oc_process_event(OUTBOUND_NETWORK_EVENT)) { + return OC_STRING_VIEW("outbound-message"); + } + if (event == oc_event_to_oc_process_event(UDP_TO_TLS_EVENT)) { + return OC_STRING_VIEW("inbound-tls-message"); + } + if (event == oc_event_to_oc_process_event(RI_TO_TLS_EVENT)) { + return OC_STRING_VIEW("outbound-tls-message"); + } + if (event == oc_event_to_oc_process_event(INBOUND_RI_EVENT)) { + return OC_STRING_VIEW("inbound-coap-message"); + } + if (event == oc_event_to_oc_process_event(TLS_READ_DECRYPTED_DATA)) { + return OC_STRING_VIEW("inbound-application-data"); + } +#ifdef OC_CLIENT + if (event == oc_event_to_oc_process_event(TLS_WRITE_APPLICATION_DATA)) { + return OC_STRING_VIEW("outbound-application-data"); + } +#endif /* OC_CLIENT */ +#ifdef OC_OSCORE + if (event == oc_event_to_oc_process_event(INBOUND_OSCORE_EVENT)) { + return OC_STRING_VIEW("inbound-oscore-message"); + } + if (event == oc_event_to_oc_process_event(OUTBOUND_OSCORE_EVENT)) { + return OC_STRING_VIEW("outbound-oscore-message"); + } + if (event == oc_event_to_oc_process_event(OUTBOUND_GROUP_OSCORE_EVENT)) { + return OC_STRING_VIEW("outbound-oscore-multicast-message"); + } +#endif /* OC_OSCORE */ + if (event == oc_event_to_oc_process_event(TLS_CLOSE_ALL_SESSIONS)) { + return OC_STRING_VIEW("close-all-tls-sessions"); + } +#ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT + if (event == oc_event_to_oc_process_event(TCP_CONNECT_SESSION)) { + return OC_STRING_VIEW("connect-tcp-session"); + } +#endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ + +#ifdef OC_NETWORK_MONITOR + if (event == oc_event_to_oc_process_event(INTERFACE_DOWN)) { + return OC_STRING_VIEW("network-down"); + } + if (event == oc_event_to_oc_process_event(INTERFACE_UP)) { + return OC_STRING_VIEW("network-up"); + } +#endif /* OC_NETWORK_MONITOR */ + +#ifdef OC_SOFTWARE_UPDATE + if (event == oc_event_to_oc_process_event(SW_UPDATE_NSA)) { + return OC_STRING_VIEW("software-update-available"); + } + if (event == oc_event_to_oc_process_event(SW_UPDATE_DOWNLOADED)) { + return OC_STRING_VIEW("software-update-downloaded"); + } + if (event == oc_event_to_oc_process_event(SW_UPDATE_UPGRADING)) { + return OC_STRING_VIEW("software-update-upgrading"); + } + if (event == oc_event_to_oc_process_event(SW_UPDATE_DONE)) { + return OC_STRING_VIEW("software-update-done"); + } +#endif /* OC_SOFTWARE_UPDATE */ +#ifdef OC_HAS_FEATURE_PUSH + if (event == oc_event_to_oc_process_event(PUSH_RSC_STATE_CHANGED)) { + return OC_STRING_VIEW("push-resource-state-changed"); + } +#endif /* OC_HAS_FEATURE_PUSH */ + return OC_STRING_VIEW(""); +} + +#endif /* OC_DBG_IS_ENABLED */ diff --git a/api/oc_events_internal.h b/api/oc_events_internal.h index 936a025998..bacaac0c38 100644 --- a/api/oc_events_internal.h +++ b/api/oc_events_internal.h @@ -19,6 +19,9 @@ #ifndef OC_EVENTS_H #define OC_EVENTS_H +#include "api/oc_helpers_internal.h" +#include "oc_config.h" +#include "port/oc_log_internal.h" #include "util/oc_features.h" #include "util/oc_process.h" @@ -33,9 +36,13 @@ typedef enum { INBOUND_RI_EVENT, OUTBOUND_NETWORK_EVENT, TLS_READ_DECRYPTED_DATA, +#ifdef OC_CLIENT TLS_WRITE_APPLICATION_DATA, +#endif /* OC_CLIENT */ +#ifdef OC_NETWORK_MONITOR INTERFACE_DOWN, INTERFACE_UP, +#endif /* OC_NETWORK_MONITOR */ TLS_CLOSE_ALL_SESSIONS, /* close all TLS sessions for reset reason*/ #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT TCP_CONNECT_SESSION, @@ -69,6 +76,13 @@ void oc_event_assign_oc_process_events(void); */ oc_process_event_t oc_event_to_oc_process_event(oc_events_t event); +#if OC_DBG_IS_ENABLED + +/** @brief Get human-readable name for event */ +oc_string_view_t oc_process_event_name(oc_process_event_t event); + +#endif /* OC_DBG_IS_ENABLED */ + #ifdef __cplusplus } #endif diff --git a/api/oc_network_events.c b/api/oc_network_events.c index 0033f3f826..ea6707a9db 100644 --- a/api/oc_network_events.c +++ b/api/oc_network_events.c @@ -16,8 +16,10 @@ * ****************************************************************************/ -#include "oc_network_events_internal.h" #include "api/oc_buffer_internal.h" +#include "api/oc_endpoint_internal.h" +#include "api/oc_events_internal.h" +#include "api/oc_network_events_internal.h" #include "messaging/coap/coap.h" #include "oc_buffer.h" #include "oc_config.h" @@ -31,6 +33,8 @@ #include "util/oc_features.h" #include "util/oc_list.h" +#include + OC_LIST(g_network_events); #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT OC_LIST(g_network_tcp_connect_events); @@ -44,33 +48,46 @@ static void oc_process_network_event(void) { oc_network_event_handler_mutex_lock(); +#ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT + OC_LIST_LOCAL(network_tcp_connect_events); + oc_list_copy(network_tcp_connect_events, g_network_tcp_connect_events); + oc_list_init(g_network_tcp_connect_events); +#endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ + OC_LIST_LOCAL(network_events); + oc_list_copy(network_events, g_network_events); + oc_list_init(g_network_events); +#ifdef OC_NETWORK_MONITOR + bool interface_up = g_interface_up; + g_interface_up = false; + bool interface_down = g_interface_down; + g_interface_down = false; +#endif /* OC_NETWORK_MONITOR */ + oc_network_event_handler_mutex_unlock(); + #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT oc_tcp_on_connect_event_t *event = - (oc_tcp_on_connect_event_t *)oc_list_pop(g_network_tcp_connect_events); + (oc_tcp_on_connect_event_t *)oc_list_pop(network_tcp_connect_events); while (event != NULL) { oc_tcp_connect_session(event); event = - (oc_tcp_on_connect_event_t *)oc_list_pop(g_network_tcp_connect_events); + (oc_tcp_on_connect_event_t *)oc_list_pop(network_tcp_connect_events); } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ - oc_message_t *message = (oc_message_t *)oc_list_pop(g_network_events); + oc_message_t *message = (oc_message_t *)oc_list_pop(network_events); while (message != NULL) { oc_recv_message(message); - message = (oc_message_t *)oc_list_pop(g_network_events); + message = (oc_message_t *)oc_list_pop(network_events); } #ifdef OC_NETWORK_MONITOR - if (g_interface_up) { + if (interface_up) { oc_process_post(&oc_network_events, oc_event_to_oc_process_event(INTERFACE_UP), NULL); - g_interface_up = false; } - if (g_interface_down) { + if (interface_down) { oc_process_post(&oc_network_events, oc_event_to_oc_process_event(INTERFACE_DOWN), NULL); - g_interface_down = false; } #endif /* OC_NETWORK_MONITOR */ - oc_network_event_handler_mutex_unlock(); } OC_PROCESS(oc_network_events, ""); @@ -95,9 +112,6 @@ OC_PROCESS_THREAD(oc_network_events, ev, data) void oc_network_receive_event(oc_message_t *message) { - if (!message) { - return; - } if (!oc_process_is_running(&oc_network_events)) { oc_message_unref(message); return; @@ -135,6 +149,35 @@ oc_network_tcp_connect_event(oc_tcp_on_connect_event_t *event) } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ +int +oc_network_drop_receive_events(const oc_endpoint_t *endpoint) +{ + int dropped = 0; + oc_network_event_handler_mutex_lock(); + for (oc_message_t *message = (oc_message_t *)oc_list_head(g_network_events); + message != NULL;) { + oc_message_t *next = message->next; + if (oc_endpoint_compare(&message->endpoint, endpoint) == 0) { + oc_list_remove(g_network_events, message); +#if OC_DBG_IS_ENABLED + // GCOVR_EXCL_START + oc_process_event_t ev = + oc_event_to_oc_process_event(INBOUND_NETWORK_EVENT); + oc_string_view_t ev_name = oc_process_event_name(ev); + oc_string64_t endpoint_str; + OC_DBG("oc_network_events: dropping %s for endpoint(%s)", ev_name.data, + oc_string(endpoint_str)); + // GCOVR_EXCL_STOP +#endif /* OC_DBG_IS_ENABLED */ + oc_message_unref(message); + ++dropped; + } + message = next; + } + oc_network_event_handler_mutex_unlock(); + return dropped; +} + #ifdef OC_NETWORK_MONITOR void oc_network_interface_event(oc_interface_event_t event) diff --git a/api/oc_network_events_internal.h b/api/oc_network_events_internal.h index 7d14f03d9d..9f5eef3b4f 100644 --- a/api/oc_network_events_internal.h +++ b/api/oc_network_events_internal.h @@ -20,11 +20,11 @@ #define OC_NETWORK_EVENTS_INTERNAL_H #include "port/oc_connectivity.h" -#include "util/oc_process.h" -#include "util/oc_features.h" #include "oc_config.h" #include "oc_network_events.h" #include "oc_tcp_internal.h" +#include "util/oc_features.h" +#include "util/oc_process.h" #ifdef __cplusplus extern "C" { @@ -38,19 +38,28 @@ OC_PROCESS_NAME(oc_network_events); /** * @brief network receive event * - * @param message the network message + * @param message the network message (cannot be NULL) */ -void oc_network_receive_event(oc_message_t *message); +void oc_network_receive_event(oc_message_t *message) OC_NONNULL(); #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT /** * @brief network TCP connect event * - * @param event the TCP on connect event + * @param event the TCP on connect event (cannot be NULL) */ -void oc_network_tcp_connect_event(oc_tcp_on_connect_event_t *event); +void oc_network_tcp_connect_event(oc_tcp_on_connect_event_t *event) + OC_NONNULL(); #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ +/** + * @brief Drop received events for endpoint + * + * @param endpoint the endpoint (cannot be NULL) + * @return number of events dropped + */ +int oc_network_drop_receive_events(const oc_endpoint_t *endpoint) OC_NONNULL(); + #ifdef OC_NETWORK_MONITOR /** * Structure to manage network interface handler list. diff --git a/api/oc_resource_factory_internal.h b/api/oc_resource_factory_internal.h index da52ad97c5..8e587ead2b 100644 --- a/api/oc_resource_factory_internal.h +++ b/api/oc_resource_factory_internal.h @@ -19,6 +19,8 @@ #ifndef OC_RESOURCE_FACTORY_INTERNAL_H #define OC_RESOURCE_FACTORY_INTERNAL_H +#if defined(OC_COLLECTIONS) && defined(OC_COLLECTIONS_IF_CREATE) + #include "oc_api.h" #ifdef __cplusplus @@ -62,4 +64,6 @@ void oc_fi_factory_free_all_created_resources(void); } #endif +#endif /* OC_COLLECTIONS && OC_COLLECTIONS_IF_CREATE */ + #endif /* OC_RESOURCE_FACTORY_INTERNAL_H */ diff --git a/api/unittest/eventstest.cpp b/api/unittest/eventstest.cpp new file mode 100644 index 0000000000..aff15bb955 --- /dev/null +++ b/api/unittest/eventstest.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** + * + * Copyright (c) 2023 plgd.dev s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include "api/oc_events_internal.h" +#include "port/oc_log_internal.h" + +#include + +class TestEvents : public testing::Test { +public: + static void SetUpTestCase() { oc_event_assign_oc_process_events(); } +}; + +#if OC_DBG_IS_ENABLED + +TEST_F(TestEvents, ProcessEventName) +{ + for (int ev = 0; ev < __NUM_OC_EVENT_TYPES__; ++ev) { + auto name = oc_process_event_name(static_cast(ev)); + EXPECT_NE(name.data, nullptr); + } +} + +#endif /* OC_DBG_IS_ENABLED */ diff --git a/security/oc_oscore_engine.c b/security/oc_oscore_engine.c index ae9e47e8c7..3b0c72f73a 100644 --- a/security/oc_oscore_engine.c +++ b/security/oc_oscore_engine.c @@ -822,7 +822,7 @@ oc_oscore_send_message(oc_message_t *msg) OC_PROCESS_THREAD(oc_oscore_handler, ev, data) { OC_PROCESS_BEGIN(); - while (1) { + while (oc_process_is_running(&oc_oscore_handler)) { OC_PROCESS_YIELD(); if (ev == oc_event_to_oc_process_event(INBOUND_OSCORE_EVENT)) { diff --git a/security/oc_pstat.c b/security/oc_pstat.c index d2a83c4cc8..86cc717304 100644 --- a/security/oc_pstat.c +++ b/security/oc_pstat.c @@ -43,9 +43,9 @@ #include "api/cloud/oc_cloud_internal.h" #endif /* OC_CLOUD */ -#ifdef OC_COLLECTIONS_IF_CREATE +#if defined(OC_COLLECTIONS) && defined(OC_COLLECTIONS_IF_CREATE) #include "api/oc_resource_factory_internal.h" -#endif /* OC_COLLECTIONS_IF_CREATE */ +#endif /* OC_COLLECTIONS && OC_COLLECTIONS_IF_CREATE */ #ifdef OC_SOFTWARE_UPDATE #include "api/oc_swupdate_internal.h" @@ -698,7 +698,7 @@ oc_pstat_set_reset_delay_ms(uint64_t delay_ms) } uint64_t -oc_pstat_get_reset_delay_ms() +oc_pstat_get_reset_delay_ms(void) { return g_reset_delay_ms; } diff --git a/security/oc_tls.c b/security/oc_tls.c index e5c1c83e05..486fc71baa 100644 --- a/security/oc_tls.c +++ b/security/oc_tls.c @@ -352,6 +352,7 @@ is_peer_active(const oc_tls_peer_t *peer) static oc_event_callback_retval_t oc_dtls_inactive(void *data); #ifdef OC_CLIENT + static void oc_tls_free_invalid_peer(oc_tls_peer_t *peer) { @@ -386,25 +387,65 @@ oc_tls_free_invalid_peer(oc_tls_peer_t *peer) } #endif /* OC_CLIENT */ +bool +oc_tls_event_is_inbound_or_outbound(oc_process_event_t event) +{ + return (event == oc_event_to_oc_process_event(RI_TO_TLS_EVENT) || + event == oc_event_to_oc_process_event(UDP_TO_TLS_EVENT) || +#ifdef OC_OSCORE + event == oc_event_to_oc_process_event(INBOUND_OSCORE_EVENT) || + event == oc_event_to_oc_process_event(OUTBOUND_OSCORE_EVENT) || +#endif /* OC_OSCORE */ + event == oc_event_to_oc_process_event(INBOUND_RI_EVENT) || + event == oc_event_to_oc_process_event(OUTBOUND_NETWORK_EVENT) || + event == oc_event_to_oc_process_event(INBOUND_NETWORK_EVENT) || +#ifdef OC_CLIENT + event == oc_event_to_oc_process_event(TLS_WRITE_APPLICATION_DATA) || +#endif /* OC_CLIENT */ + event == oc_event_to_oc_process_event(TLS_READ_DECRYPTED_DATA)); +} + static bool -process_drop_event_for_removed_endpoint(oc_process_event_t ev, - oc_process_data_t data, - const void *user_data) +tls_process_drop_event_for_removed_endpoint(oc_process_event_t ev, + oc_process_data_t data, + const void *user_data) { + if (!oc_tls_event_is_inbound_or_outbound(ev)) { + return false; + } const oc_endpoint_t *endpoint = (const oc_endpoint_t *)user_data; - if (ev != oc_event_to_oc_process_event(RI_TO_TLS_EVENT) && - ev != oc_event_to_oc_process_event(UDP_TO_TLS_EVENT)) { + if ( +#ifdef OC_CLIENT + ev == oc_event_to_oc_process_event(TLS_WRITE_APPLICATION_DATA) || +#endif /* OC_CLIENT */ + ev == oc_event_to_oc_process_event(TLS_READ_DECRYPTED_DATA)) { + const oc_tls_peer_t *peer = (const oc_tls_peer_t *)data; + if (oc_endpoint_compare(&peer->endpoint, endpoint) == 0) { + // the peer will be removed, just drop the event +#if OC_DBG_IS_ENABLED + // GCOVR_EXCL_START + oc_string64_t endpoint_str; + oc_endpoint_to_string64(&peer->endpoint, &endpoint_str); + oc_string_view_t ev_name = oc_process_event_name(ev); + OC_DBG("oc_tls: dropping %s for removed endpoint(%s)", ev_name.data, + oc_string(endpoint_str)); + // GCOVR_EXCL_STOP +#endif /* OC_DBG_IS_ENABLED */ + return true; + } return false; } + oc_message_t *message = (oc_message_t *)data; if (oc_endpoint_compare(&message->endpoint, endpoint) == 0) { #if OC_DBG_IS_ENABLED + // GCOVR_EXCL_START oc_string64_t endpoint_str; oc_endpoint_to_string64(&message->endpoint, &endpoint_str); - OC_DBG("oc_tls: dropping %s message for removed endpoint(%s)", - (ev == oc_event_to_oc_process_event(RI_TO_TLS_EVENT)) ? "sent" - : "received", + oc_string_view_t ev_name = oc_process_event_name(ev); + OC_DBG("oc_tls: dropping %s for removed endpoint(%s)", ev_name.data, oc_string(endpoint_str)); + // GCOVR_EXCL_STOP #endif /* OC_DBG_IS_ENABLED */ oc_message_unref(message); return true; @@ -412,6 +453,25 @@ process_drop_event_for_removed_endpoint(oc_process_event_t ev, return false; } +static void +tls_drop_endpoint_events(const oc_endpoint_t *endpoint) +{ + oc_network_drop_receive_events(endpoint); + + oc_process_drop(&oc_tls_handler, tls_process_drop_event_for_removed_endpoint, + endpoint); + OC_PROCESS_NAME(oc_message_buffer_handler); + oc_process_drop(&oc_message_buffer_handler, + tls_process_drop_event_for_removed_endpoint, endpoint); + OC_PROCESS_NAME(g_coap_engine); + oc_process_drop(&g_coap_engine, tls_process_drop_event_for_removed_endpoint, + endpoint); +#ifdef OC_OSCORE + oc_process_drop(&oc_oscore_handler, + tls_process_drop_event_for_removed_endpoint, endpoint); +#endif /* OC_OSCORE */ +} + static void oc_tls_free_peer(oc_tls_peer_t *peer, bool inactivity_cb, bool from_reset) { @@ -462,8 +522,7 @@ oc_tls_free_peer(oc_tls_peer_t *peer, bool inactivity_cb, bool from_reset) oc_message_unref(message); message = (oc_message_t *)oc_list_pop(peer->recv_q); } - oc_process_drop(&oc_tls_handler, process_drop_event_for_removed_endpoint, - &peer->endpoint); + tls_drop_endpoint_events(&peer->endpoint); #ifdef OC_PKI oc_free_string(&peer->public_key); #endif /* OC_PKI */ @@ -518,8 +577,7 @@ oc_tls_remove_peer(const oc_endpoint_t *endpoint) if (peer != NULL) { oc_tls_free_peer(peer, false, false); } else { - oc_process_drop(&oc_tls_handler, process_drop_event_for_removed_endpoint, - endpoint); + tls_drop_endpoint_events(endpoint); } } @@ -3000,7 +3058,7 @@ OC_PROCESS_THREAD(oc_tls_handler, ev, data) { OC_PROCESS_POLLHANDLER(close_all_tls_sessions()); OC_PROCESS_BEGIN(); - while (true) { + while (oc_process_is_running(&oc_tls_handler)) { OC_PROCESS_YIELD(); if (ev == oc_event_to_oc_process_event(UDP_TO_TLS_EVENT)) { diff --git a/security/oc_tls_internal.h b/security/oc_tls_internal.h index 1794d04145..7ae08261d2 100644 --- a/security/oc_tls_internal.h +++ b/security/oc_tls_internal.h @@ -279,6 +279,16 @@ int oc_tls_pbkdf2(const unsigned char *pin, size_t pin_len, const oc_uuid_t *uuid, unsigned int c, uint8_t *key, uint32_t key_len); +/** + * @brief Check if event is inbound or outbound (i.e. processing this event will + * create a (D)TLS session) + * + * @param event event to check + * @return true if event is inbound or outbound + * @return false otherwise + */ +bool oc_tls_event_is_inbound_or_outbound(oc_process_event_t event); + #ifdef OC_TEST void oc_dtls_set_inactivity_timeout(oc_clock_time_t timeout); oc_clock_time_t oc_dtls_inactivity_timeout(void); diff --git a/security/unittest/tlstest.cpp b/security/unittest/tlstest.cpp index c1c3d2e5c3..83f1b017e1 100644 --- a/security/unittest/tlstest.cpp +++ b/security/unittest/tlstest.cpp @@ -16,25 +16,33 @@ * ******************************************************************/ -#if defined(OC_TCP) && defined(OC_SECURITY) +#ifdef OC_SECURITY +#include "api/oc_buffer_internal.h" #include "api/oc_core_res_internal.h" +#include "api/oc_events_internal.h" #include "api/oc_ri_internal.h" #include "api/oc_runtime_internal.h" +#include "messaging/coap/coap_signal.h" #include "oc_api.h" #include "oc_endpoint.h" #include "oc_signal_event_loop.h" #include "oc_core_res.h" #include "port/oc_network_event_handler_internal.h" #include "security/oc_tls_internal.h" +#include "tests/gtest/Device.h" +#include "tests/gtest/Endpoint.h" +#include "util/oc_process_internal.h" #ifdef OC_HAS_FEATURE_PUSH #include "api/oc_push_internal.h" #endif /* OC_HAS_FEATURE_PUSH */ +#include #include #include +static constexpr size_t kDeviceID{ 0 }; static const std::string kDeviceURI{ "/oic/d" }; static const std::string kDeviceType{ "oic.d.light" }; static const std::string kDeviceName{ "Table Lamp" }; @@ -95,4 +103,93 @@ TEST_F(TestTlsConnection, TlsConnectionTest_N) oc_free_endpoint(endpoint); } -#endif /* OC_TCP && OC_SECURITY */ +class TestEventsWithServer : public testing::Test { +public: + static void SetUpTestCase() { ASSERT_TRUE(oc::TestDevice::StartServer()); } + + static void TearDownTestCase() { oc::TestDevice::StopServer(); } +}; + +static size_t +countInboundOrOutboundEvents() +{ + size_t count = 0; + oc_process_iterate_events( + [](const struct oc_process *, oc_process_event_t ev, oc_process_data_t, + void *user_data) { + if (oc_tls_event_is_inbound_or_outbound(ev)) { + ++(*static_cast(user_data)); + } + return true; + }, + &count); + return count; +} + +TEST_F(TestEventsWithServer, DropOutputMessages) +{ + unsigned includeFlags = 0; +#ifdef OC_IPV4 + includeFlags |= IPV4; + includeFlags |= SECURED; +#endif /* OC_IPV4 */ + + auto epOpt = oc::TestDevice::GetEndpoint(kDeviceID, includeFlags, TCP); + ASSERT_TRUE(epOpt.has_value()); + auto ep = std::move(*epOpt); + + ASSERT_EQ(0, countInboundOrOutboundEvents()); + oc_message_t *msg = oc_allocate_message(); + memcpy(&msg->endpoint, &ep, sizeof(oc_endpoint_t)); + coap_packet_t packet = {}; + coap_udp_init_message(&packet, COAP_TYPE_RST, 0, 0); + std::array payload{ "connect" }; + packet.payload = payload.data(); + packet.payload_len = payload.size(); + msg->length = + coap_serialize_message(&packet, msg->data, oc_message_buffer_size()); + + oc_send_message(msg); + EXPECT_LT(0, countInboundOrOutboundEvents()); + + oc_tls_remove_peer(&ep); + ASSERT_EQ(0, countInboundOrOutboundEvents()); +} + +#ifdef OC_TCP + +TEST_F(TestEventsWithServer, DropOutputMessagesTCP) +{ + unsigned includeFlags = TCP; +#ifdef OC_IPV4 + includeFlags |= IPV4; + includeFlags |= SECURED; +#endif /* OC_IPV4 */ + + auto epOpt = oc::TestDevice::GetEndpoint(kDeviceID, includeFlags, 0); + ASSERT_TRUE(epOpt.has_value()); + auto ep = std::move(*epOpt); + + ASSERT_EQ(0, countInboundOrOutboundEvents()); + oc_message_t *msg = oc_allocate_message(); + memcpy(&msg->endpoint, &ep, sizeof(oc_endpoint_t)); + coap_packet_t packet = {}; + coap_tcp_init_message(&packet, CSM_7_01); + std::array payload{ "connect" }; + packet.payload = payload.data(); + packet.payload_len = payload.size(); + msg->length = + coap_serialize_message(&packet, msg->data, oc_message_buffer_size()); + + oc_send_message(msg); + EXPECT_LT(0, countInboundOrOutboundEvents()); + + oc_tls_remove_peer(&ep); + ASSERT_EQ(0, countInboundOrOutboundEvents()); +} +#endif /* OC_TCP */ + +// TODO: tests for oscore +// TODO: tests for inbound data + +#endif /* OC_SECURITY */ diff --git a/util/oc_list.h b/util/oc_list.h index d06216c1c9..c376678a96 100644 --- a/util/oc_list.h +++ b/util/oc_list.h @@ -82,6 +82,11 @@ extern "C" { static void *OC_LIST_CONCAT(name, _list) = NULL; \ static oc_list_t name = &OC_LIST_CONCAT(name, _list) +/** Non-static version of OC_LIST */ +#define OC_LIST_LOCAL(name) \ + void *OC_LIST_CONCAT(name, _list) = NULL; \ + oc_list_t name = &OC_LIST_CONCAT(name, _list) + /** * Declare a linked list inside a structure declaraction. * diff --git a/util/unittest/etimertest.cpp b/util/unittest/etimertest.cpp index 5d95ad2bf3..b10d4076c7 100644 --- a/util/unittest/etimertest.cpp +++ b/util/unittest/etimertest.cpp @@ -78,7 +78,7 @@ std::function TestEventTimer::onEventTimer_{}; OC_PROCESS_THREAD(oc_test_process_1, ev, data) { OC_PROCESS_BEGIN(); - while (true) { + while (oc_process_is_running(&oc_test_process_1)) { OC_PROCESS_YIELD(); OC_INFO("received event 0x%x", (int)ev); @@ -95,7 +95,7 @@ OC_PROCESS_THREAD(oc_test_process_1, ev, data) OC_PROCESS_THREAD(oc_test_process_2, ev, data) { OC_PROCESS_BEGIN(); - while (true) { + while (oc_process_is_running(&oc_test_process_2)) { OC_PROCESS_YIELD(); OC_INFO("received event 0x%x", (int)ev); From f8fac5e9822a7c35fe6c69c435cb002e467c8cb7 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Tue, 26 Sep 2023 10:26:18 +0200 Subject: [PATCH 07/11] Add allocator mutex When OC_DYNAMIC_ALLOCATION is disabled then memory allocation by oc_memb pool from multiple threads needs to be synchronized. For this purpose oc_allocator_mutex should be used to avoid misusing other mutexes for this purpose. --- .github/workflows/cmake-linux.yml | 7 +- CMakeLists.txt | 61 ++++++++-- api/oc_buffer.c | 18 ++- api/oc_endpoint.c | 17 ++- api/oc_helpers.c | 17 ++- api/oc_helpers_internal.h | 29 ++++- api/oc_main.c | 2 +- api/oc_push.c | 37 ++---- api/oc_query.c | 2 +- api/oc_runtime.c | 10 ++ api/oc_tcp.c | 18 ++- api/unittest/buffertest.cpp | 15 ++- api/unittest/collectiontest.cpp | 16 +-- api/unittest/eptest.cpp | 8 ++ api/unittest/tcptest.cpp | 10 +- api/unittest/udptest.cpp | 10 +- apps/cloud_server.c | 1 + docker/run.sh | 5 +- include/oc_helpers.h | 4 +- messaging/coap/unittest/observetest.cpp | 43 ++++--- port/android/Makefile | 4 +- port/common/posix/oc_allocator.c | 60 +++++++++ port/esp32/main/CMakeLists.txt | 1 + port/linux/Makefile | 4 +- port/oc_allocator_internal.h | 68 +++++++++++ port/windows/ipadapter.c | 10 +- port/windows/oc_allocator.c | 50 ++++++++ port/windows/vs2015/IoTivity-lite.vcxproj | 6 +- .../vs2015/IoTivity-lite.vcxproj.filters | 16 ++- tests/libfaketime/unittest/etimertest.cpp | 2 +- util/oc_mem_trace.c | 10 +- ...oc_mem_trace.h => oc_mem_trace_internal.h} | 6 +- util/oc_memb.c | 18 ++- util/oc_memb.h | 39 +++++- util/oc_mmem.c | 108 +++++++++-------- util/oc_mmem.h | 49 +++----- util/oc_mmem_internal.h | 114 ++++++++++++++++++ util/oc_process.c | 12 ++ util/oc_process_internal.h | 36 ++++++ 39 files changed, 722 insertions(+), 221 deletions(-) create mode 100644 port/common/posix/oc_allocator.c create mode 100644 port/oc_allocator_internal.h create mode 100644 port/windows/oc_allocator.c rename util/{oc_mem_trace.h => oc_mem_trace_internal.h} (91%) create mode 100644 util/oc_mmem_internal.h diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index 53bd8b743b..dd37353028 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -108,7 +108,12 @@ jobs: - args: -DOC_TSAN_ENABLED=ON # GCC thread-sanitizer keeps reporting false positives, so we use clang instead for tests with thread-sanitizer clang: true - install_faketime: true + install_faketime: false + # static allocation requires additional thread synchronization + - args: -DOC_TSAN_ENABLED=ON -DOC_DYNAMIC_ALLOCATION_ENABLED=OFF + # GCC thread-sanitizer keeps reporting false positives, so we use clang instead for tests with thread-sanitizer + clang: true + install_faketime: false # undefined behaviour sanitizer - args: -DOC_UBSAN_ENABLED=ON install_faketime: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 37950fc783..3f5853f636 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ if(UNIX) message(STATUS "Address sanitizer enabled") add_compile_options(${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer) add_link_options(-fsanitize=address) + set(OC_ASAN_OPTIONS "debug=true:atexit=true:check_initialization_order=true:detect_stack_use_after_return=true:alloc_dealloc_mismatch=true:detect_invalid_pointer_pairs=2:strict_string_checks=true") endif() if(OC_LSAN_ENABLED) @@ -93,6 +94,7 @@ if(UNIX) message(STATUS "Thread sanitizer enabled") add_compile_options(${CMAKE_C_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer) add_link_options(-fsanitize=thread) + set(OC_TSAN_OPTIONS "halt_on_error=1:abort_on_error=true") endif() if(OC_UBSAN_ENABLED) @@ -453,6 +455,13 @@ file(GLOB COMMON_SRC ${PROJECT_SOURCE_DIR}/util/*.c ) +if(UNIX) + file(GLOB COMMON_POSIX_SRC + ${PROJECT_SOURCE_DIR}/port/common/posix/*.c + ) + list(APPEND COMMON_SRC ${COMMON_POSIX_SRC}) +endif() + if(NOT OC_MEMORY_TRACE_ENABLED) list(REMOVE_ITEM COMMON_SRC ${PROJECT_SOURCE_DIR}/util/oc_mem_trace.c @@ -956,21 +965,47 @@ if(BUILD_TESTING AND(UNIX OR MINGW)) if (OC_INTROSPECTION_ENABLED AND OC_IDD_API_ENABLED) set(apitest_files ${PROJECT_SOURCE_DIR}/api/unittest/introspectiontest_IDD.cbor) endif() - oc_package_add_test(TARGET apitest SOURCES ${COMMONTEST_SRC} ${APITEST_SRC} FILES ${apitest_files}) + oc_package_add_test( + TARGET apitest + SOURCES ${COMMONTEST_SRC} ${APITEST_SRC} + FILES ${apitest_files} + ENVIRONMENT "ASAN_OPTIONS=${OC_ASAN_OPTIONS}" + "TSAN_OPTIONS=${OC_TSAN_OPTIONS}" + ) file(GLOB TIMESTAMPTEST_SRC api/c-timestamp/unittest/*.cpp) - oc_package_add_test(TARGET timestamptest SOURCES ${TIMESTAMPTEST_SRC}) + oc_package_add_test( + TARGET timestamptest + SOURCES ${TIMESTAMPTEST_SRC} + ENVIRONMENT "ASAN_OPTIONS=${OC_ASAN_OPTIONS}" + "TSAN_OPTIONS=${OC_TSAN_OPTIONS}" + ) file(GLOB PLATFORMTEST_SRC port/unittest/*.cpp) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/storage_test) - oc_package_add_test(TARGET platformtest SOURCES ${COMMONTEST_SRC} ${PLATFORMTEST_SRC}) + oc_package_add_test( + TARGET platformtest + SOURCES ${COMMONTEST_SRC} ${PLATFORMTEST_SRC} + ENVIRONMENT "ASAN_OPTIONS=${OC_ASAN_OPTIONS}" + "TSAN_OPTIONS=${OC_TSAN_OPTIONS}" + ) file(GLOB MESSAGINGTEST_SRC messaging/coap/unittest/*.cpp) - oc_package_add_test(TARGET messagingtest SOURCES ${COMMONTEST_SRC} ${MESSAGINGTEST_SRC}) + oc_package_add_test( + TARGET messagingtest + SOURCES ${COMMONTEST_SRC} ${MESSAGINGTEST_SRC} + ENVIRONMENT "ASAN_OPTIONS=${OC_ASAN_OPTIONS}" + "TSAN_OPTIONS=${OC_TSAN_OPTIONS}" + ) if(OC_SECURITY_ENABLED) file(GLOB SECURITYTEST_SRC security/unittest/*.cpp) - oc_package_add_test(TARGET securitytest SOURCES ${COMMONTEST_SRC} ${SECURITYTEST_SRC}) + oc_package_add_test( + TARGET securitytest + SOURCES ${COMMONTEST_SRC} ${SECURITYTEST_SRC} + ENVIRONMENT "ASAN_OPTIONS=${OC_ASAN_OPTIONS}" + "TSAN_OPTIONS=${OC_TSAN_OPTIONS}" + ) file(COPY ${PROJECT_SOURCE_DIR}/apps/pki_certs DESTINATION ${CMAKE_CURRENT_BINARY_DIR} @@ -978,12 +1013,22 @@ if(BUILD_TESTING AND(UNIX OR MINGW)) endif() file(GLOB UTILTEST_SRC util/unittest/*.cpp) - oc_package_add_test(TARGET utiltest SOURCES ${COMMONTEST_SRC} ${UTILTEST_SRC}) + oc_package_add_test( + TARGET utiltest + SOURCES ${COMMONTEST_SRC} ${UTILTEST_SRC} + ENVIRONMENT "ASAN_OPTIONS=${OC_ASAN_OPTIONS}" + "TSAN_OPTIONS=${OC_TSAN_OPTIONS}" + ) if(OC_CLOUD_ENABLED) file(GLOB CLOUDTEST_SRC api/cloud/unittest/*.cpp) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/storage_cloud) - oc_package_add_test(TARGET cloudtest SOURCES ${COMMONTEST_SRC} ${CLOUDTEST_SRC}) + oc_package_add_test( + TARGET cloudtest + SOURCES ${COMMONTEST_SRC} ${CLOUDTEST_SRC} + ENVIRONMENT "ASAN_OPTIONS=${OC_ASAN_OPTIONS}" + "TSAN_OPTIONS=${OC_TSAN_OPTIONS}" + ) endif() if(UNIX AND NOT OC_TSAN_ENABLED) @@ -997,7 +1042,7 @@ if(BUILD_TESTING AND(UNIX OR MINGW)) oc_package_add_test( TARGET faketimetest SOURCES ${COMMONTEST_SRC} ${FAKETIMETEST_SRC} - ENVIRONMENT "ASAN_OPTIONS=verify_asan_link_order=0" + ENVIRONMENT "ASAN_OPTIONS=${OC_ASAN_OPTIONS}:verify_asan_link_order=0" "LD_PRELOAD=/usr/local/lib/faketime/libfaketimeMT.so.1" "FAKETIME_DONT_FAKE_MONOTONIC=1" "FAKETIME_TIMESTAMP_FILE=" diff --git a/api/oc_buffer.c b/api/oc_buffer.c index 1af4b0889f..948d96d612 100644 --- a/api/oc_buffer.c +++ b/api/oc_buffer.c @@ -23,7 +23,7 @@ #include "oc_events_internal.h" #include "oc_signal_event_loop.h" #include "port/oc_log_internal.h" -#include "port/oc_network_event_handler_internal.h" +#include "port/oc_allocator_internal.h" #include "util/oc_features.h" #include "util/oc_macros_internal.h" #include "util/oc_memb.h" @@ -57,17 +57,25 @@ message_deallocate(oc_message_t *message, struct oc_memb *pool) #if defined(OC_DYNAMIC_ALLOCATION) && !defined(OC_INOUT_BUFFER_SIZE) free(message->data); #endif /* OC_DYNAMIC_ALLOCATION && !OC_INOUT_BUFFER_SIZE */ - oc_network_event_handler_mutex_lock(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_lock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ oc_memb_free(pool, message); - oc_network_event_handler_mutex_unlock(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_unlock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ } static oc_message_t * message_allocate_with_size(struct oc_memb *pool, size_t size) { - oc_network_event_handler_mutex_lock(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_lock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ oc_message_t *message = (oc_message_t *)oc_memb_alloc(pool); - oc_network_event_handler_mutex_unlock(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_unlock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ if (message == NULL) { #if !defined(OC_DYNAMIC_ALLOCATION) || defined(OC_INOUT_BUFFER_SIZE) OC_WRN("buffer: No free TX/RX buffers!"); diff --git a/api/oc_endpoint.c b/api/oc_endpoint.c index 7dedf2cf5e..7571af63f4 100644 --- a/api/oc_endpoint.c +++ b/api/oc_endpoint.c @@ -21,9 +21,9 @@ #include "oc_endpoint.h" #include "oc_core_res.h" #include "port/common/oc_ip.h" +#include "port/oc_allocator_internal.h" #include "port/oc_connectivity.h" #include "port/oc_log_internal.h" -#include "port/oc_network_event_handler_internal.h" #include "util/oc_macros_internal.h" #include "util/oc_memb.h" @@ -44,11 +44,11 @@ oc_endpoint_t * oc_new_endpoint(void) { #ifndef OC_DYNAMIC_ALLOCATION - oc_network_event_handler_mutex_lock(); + oc_allocator_mutex_lock(); #endif /* !OC_DYNAMIC_ALLOCATION */ oc_endpoint_t *endpoint = (oc_endpoint_t *)oc_memb_alloc(&oc_endpoints_s); #ifndef OC_DYNAMIC_ALLOCATION - oc_network_event_handler_mutex_unlock(); + oc_allocator_mutex_unlock(); #endif /* !OC_DYNAMIC_ALLOCATION */ return endpoint; } @@ -56,9 +56,16 @@ oc_new_endpoint(void) void oc_free_endpoint(oc_endpoint_t *endpoint) { - if (endpoint) { - oc_memb_free(&oc_endpoints_s, endpoint); + if (endpoint == NULL) { + return; } +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_lock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ + oc_memb_free(&oc_endpoints_s, endpoint); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_unlock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ } void diff --git a/api/oc_helpers.c b/api/oc_helpers.c index 04d374a1be..be65735543 100644 --- a/api/oc_helpers.c +++ b/api/oc_helpers.c @@ -23,6 +23,7 @@ #include "port/oc_log_internal.h" #include "port/oc_random.h" #include "util/oc_macros_internal.h" +#include "util/oc_mmem_internal.h" #include #include #include @@ -35,7 +36,7 @@ oc_malloc( #ifdef OC_MEMORY_TRACE const char *func, #endif - oc_handle_t *block, size_t num_items, pool pool_type) + oc_handle_t *block, size_t num_items, oc_mmem_pool_t pool_type) { if (!g_mmem_initialized) { oc_mmem_init(); @@ -54,7 +55,7 @@ oc_free( #ifdef OC_MEMORY_TRACE const char *func, #endif - oc_handle_t *block, pool pool_type) + oc_handle_t *block, oc_mmem_pool_t pool_type) { _oc_mmem_free( #ifdef OC_MEMORY_TRACE @@ -62,7 +63,9 @@ oc_free( #endif block, pool_type); +#ifndef OC_DYNAMIC_ALLOCATION block->next = NULL; +#endif /* !OC_DYNAMIC_ALLOCATION */ block->ptr = NULL; block->size = 0; } @@ -156,12 +159,6 @@ oc_string_view2(const oc_string_t *str) return oc_string_view(oc_string(*str), oc_string_len(*str)); } -oc_string_view_t -oc_string_view_null(void) -{ - return oc_string_view(NULL, 0); -} - bool oc_string_view_is_equal(oc_string_view_t str1, oc_string_view_t str2) { @@ -215,7 +212,7 @@ _oc_new_array( #ifdef OC_MEMORY_TRACE const char *func, #endif - oc_array_t *ocarray, size_t size, pool type) + oc_array_t *ocarray, size_t size, oc_mmem_pool_t type) { switch (type) { case INT_POOL: @@ -237,7 +234,7 @@ _oc_free_array( #ifdef OC_MEMORY_TRACE const char *func, #endif - oc_array_t *ocarray, pool type) + oc_array_t *ocarray, oc_mmem_pool_t type) { oc_free( #ifdef OC_MEMORY_TRACE diff --git a/api/oc_helpers_internal.h b/api/oc_helpers_internal.h index fca6fa573f..5aab0087f6 100644 --- a/api/oc_helpers_internal.h +++ b/api/oc_helpers_internal.h @@ -48,21 +48,44 @@ typedef struct oc_string_view_t size_t length; } oc_string_view_t; +#ifdef __cplusplus + +#define OC_STRING_VIEW(str) \ + oc_string_view_t \ + { \ + (str), OC_CHAR_ARRAY_LEN(str), \ + } + +/** Create empty oc_string_view_t. */ +#define OC_STRING_VIEW_NULL() \ + oc_string_view_t \ + { \ + NULL, 0, \ + } + +#else /* !__cplusplus */ + #define OC_STRING_VIEW(str) \ (oc_string_view_t) \ { \ .data = (str), .length = OC_CHAR_ARRAY_LEN(str), \ } +/** Create empty oc_string_view_t. */ +#define OC_STRING_VIEW_NULL() \ + (oc_string_view_t) \ + { \ + .data = NULL, .length = 0, \ + } + +#endif /* __cplusplus */ + /** Create an oc_string_view_t from a C-string. */ oc_string_view_t oc_string_view(const char *data, size_t length); /** Create an oc_string_view_t from an oc_string_t. */ oc_string_view_t oc_string_view2(const oc_string_t *str); -/** Create empty oc_string_view_t. */ -oc_string_view_t oc_string_view_null(void); - /** * @brief Compare two oc_string_view_t values. * diff --git a/api/oc_main.c b/api/oc_main.c index 0d936444ba..ad7cb09514 100644 --- a/api/oc_main.c +++ b/api/oc_main.c @@ -64,7 +64,7 @@ #endif /* OC_SOFTWARE_UPDATE */ #ifdef OC_MEMORY_TRACE -#include "util/oc_mem_trace.h" +#include "util/oc_mem_trace_internal.h" #endif /* OC_MEMORY_TRACE */ #ifdef OC_HAS_FEATURE_PUSH diff --git a/api/oc_push.c b/api/oc_push.c index 0f4340e5f3..0b0f590789 100644 --- a/api/oc_push.c +++ b/api/oc_push.c @@ -43,6 +43,7 @@ #include "util/oc_list.h" #include "util/oc_macros_internal.h" #include "util/oc_mmem.h" +#include "util/oc_mmem_internal.h" #include "util/oc_process.h" #include @@ -221,21 +222,6 @@ static void (*oc_push_arrived)(oc_pushd_resource_rep_t *) = NULL; #define pp_update_state(state, new_state) \ (oc_set_string(&(state), (new_state), strlen((new_state)))) -/** - * @brief initialize oc_string_t object - */ -#define oc_init_string(str) \ - do { \ - (str).size = 0; \ - (str).ptr = NULL; \ - (str).next = NULL; \ - } while (0) - -/** - * @brief initialize oc_string_array_t object - */ -#define oc_init_string_array(str_array) oc_init_string((str_array)) - #define OC_PUSH_PROP_PHREF "phref" #define OC_PUSH_PROP_PUSHTARGET "pushtarget" #define OC_PUSH_PROP_PUSHQIF "pushqif" @@ -317,11 +303,8 @@ set_ns_properties(const oc_resource_t *resource, const oc_rep_t *rep, } else { /* if non-NULL pushtarget.. */ - oc_endpoint_t *new_ep; - oc_string_t new_targetpath; - - new_ep = oc_new_endpoint(); - oc_init_string(new_targetpath); + oc_endpoint_t *new_ep = oc_new_endpoint(); + oc_string_t new_targetpath = OC_MMEM_NULL(); OC_PUSH_DBG("oic.r.pushproxy:pushtarget (%s)", oc_string(rep->value.string)); @@ -751,12 +734,12 @@ get_ns_instance(const char *href, const oc_string_array_t *types, oc_string(ns_instance->resource->uri), PUSHCONFIG_RESOURCE_PATH); /* initialize properties */ - oc_init_string(ns_instance->phref); - oc_init_string_array(ns_instance->prt); - oc_init_string_array(ns_instance->pif); - oc_init_string(ns_instance->pushtarget_di); - oc_init_string(ns_instance->targetpath); - oc_init_string_array(ns_instance->sourcert); + ns_instance->phref = OC_MMEM_NULL(); + ns_instance->prt = OC_MMEM_NULL(); + ns_instance->pif = OC_MMEM_NULL(); + ns_instance->pushtarget_di = OC_MMEM_NULL(); + ns_instance->targetpath = OC_MMEM_NULL(); + ns_instance->sourcert = OC_MMEM_NULL(); oc_new_string(&ns_instance->state, pp_statestr(OC_PP_WFP), strlen(pp_statestr(OC_PP_WFP))); ns_instance->user_data = NULL; @@ -2467,7 +2450,7 @@ OC_PROCESS_THREAD(oc_push_process, ev, data) OC_PROCESS_BEGIN(); - while (1) { + while (oc_process_is_running(&oc_push_process)) { #if 0 int device_count = oc_core_get_num_devices(); diff --git a/api/oc_query.c b/api/oc_query.c index 1916dc74f7..43daaac219 100644 --- a/api/oc_query.c +++ b/api/oc_query.c @@ -62,7 +62,7 @@ oc_query_encode_interface(oc_interface_mask_t iface_mask) default: break; } - return oc_string_view_null(); + return OC_STRING_VIEW_NULL(); } #endif /* OC_SERVER */ diff --git a/api/oc_runtime.c b/api/oc_runtime.c index 7c25079b9f..2bac5363d7 100644 --- a/api/oc_runtime.c +++ b/api/oc_runtime.c @@ -20,15 +20,25 @@ #include "port/oc_random.h" #include "port/oc_clock.h" +#ifndef OC_DYNAMIC_ALLOCATION +#include "port/oc_allocator_internal.h" +#endif /* !OC_DYNAMIC_ALLOCATION */ + void oc_runtime_init(void) { oc_random_init(); oc_clock_init(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_init(); +#endif /* !OC_DYNAMIC_ALLOCATION */ } void oc_runtime_shutdown(void) { +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_destroy(); +#endif /* !OC_DYNAMIC_ALLOCATION */ oc_random_destroy(); } diff --git a/api/oc_tcp.c b/api/oc_tcp.c index 221d6581b0..bb9f9c23ab 100644 --- a/api/oc_tcp.c +++ b/api/oc_tcp.c @@ -33,7 +33,7 @@ #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT -#include "port/oc_network_event_handler_internal.h" +#include "port/oc_allocator_internal.h" #include "util/oc_memb.h" OC_MEMB(g_oc_tcp_on_connect_event_s, oc_tcp_on_connect_event_t, @@ -42,10 +42,14 @@ OC_MEMB(g_oc_tcp_on_connect_event_s, oc_tcp_on_connect_event_t, static oc_tcp_on_connect_event_t * oc_tcp_on_connect_event_allocate(void) { - oc_network_event_handler_mutex_lock(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_lock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ oc_tcp_on_connect_event_t *event = (oc_tcp_on_connect_event_t *)oc_memb_alloc(&g_oc_tcp_on_connect_event_s); - oc_network_event_handler_mutex_unlock(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_unlock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ return event; } @@ -71,9 +75,13 @@ oc_tcp_on_connect_event_free(oc_tcp_on_connect_event_t *event) if (event == NULL) { return; } - oc_network_event_handler_mutex_lock(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_lock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ oc_memb_free(&g_oc_tcp_on_connect_event_s, event); - oc_network_event_handler_mutex_unlock(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_unlock(); +#endif /* !OC_DYNAMIC_ALLOCATION */ } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ diff --git a/api/unittest/buffertest.cpp b/api/unittest/buffertest.cpp index c0af245f3c..77a86ff4be 100644 --- a/api/unittest/buffertest.cpp +++ b/api/unittest/buffertest.cpp @@ -21,6 +21,7 @@ #include "api/oc_runtime_internal.h" #include "oc_buffer.h" #include "oc_config.h" +#include "port/oc_allocator_internal.h" #include "port/oc_network_event_handler_internal.h" #include "util/oc_features.h" #include "util/oc_memb.h" @@ -40,13 +41,21 @@ class TestMessage : public testing::Test { static void SetUpTestCase() { (void)kTestMessagesPoolSize; +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_init(); +#endif /* OC_DYNAMIC_ALLOCATION */ oc_memb_init(&oc_test_messages); oc_set_buffers_avail_cb(onIncomingBufferAvailable); oc_memb_set_buffers_avail_cb(&oc_test_messages, onTestBufferAvailable); - oc_network_event_handler_mutex_init(); } - static void TearDownTestCase() { oc_network_event_handler_mutex_destroy(); } + static void TearDownTestCase() + { + oc_set_buffers_avail_cb(nullptr); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_destroy(); +#endif /* OC_DYNAMIC_ALLOCATION */ + } void SetUp() override { @@ -232,6 +241,7 @@ template void testProcessMessagesByProcess() { + oc_network_event_handler_mutex_init(); oc_runtime_init(); oc_ri_init(); @@ -263,6 +273,7 @@ testProcessMessagesByProcess() oc_message_buffer_handler_stop(); oc_ri_shutdown(); oc_runtime_shutdown(); + oc_network_event_handler_mutex_destroy(); } TEST_F(TestMessage, RecvMessageByProcess) diff --git a/api/unittest/collectiontest.cpp b/api/unittest/collectiontest.cpp index c950703d4e..76c18b68dc 100644 --- a/api/unittest/collectiontest.cpp +++ b/api/unittest/collectiontest.cpp @@ -22,6 +22,7 @@ #include "api/oc_collection_internal.h" #include "api/oc_event_callback_internal.h" +#include "api/oc_helpers_internal.h" #include "api/oc_link_internal.h" #include "api/oc_ri_internal.h" #include "messaging/coap/oc_coap.h" @@ -32,6 +33,7 @@ #include "tests/gtest/RepPool.h" #include "tests/gtest/Resource.h" #include "util/oc_features.h" +#include "util/oc_mmem_internal.h" #ifdef OC_HAS_FEATURE_ETAG #include "oc_etag.h" @@ -234,7 +236,7 @@ TEST_F(TestCollections, AddLink) std::string uri_1 = "/a"; oc_resource_t resource_1{}; - resource_1.uri = { nullptr, uri_1.length() + 1, &uri_1[0] }; + resource_1.uri = OC_MMEM(&uri_1[0], uri_1.length() + 1, nullptr); oc_link_t *link_1 = oc_new_link(&resource_1); ASSERT_NE(link_1, nullptr); oc_collection_add_link(&collection->res, link_1); @@ -242,7 +244,7 @@ TEST_F(TestCollections, AddLink) std::string uri_2 = "/b"; oc_resource_t resource_2{}; - resource_2.uri = { nullptr, uri_2.length() + 1, &uri_2[0] }; + resource_2.uri = OC_MMEM(&uri_2[0], uri_2.length() + 1, nullptr); oc_link_t *link_2 = oc_new_link(&resource_2); ASSERT_NE(link_2, nullptr); oc_collection_add_link(&collection->res, link_2); @@ -272,21 +274,21 @@ TEST_F(TestCollections, RemoveLink) std::string uri_1 = "/ccc"; oc_resource_t resource_1{}; - resource_1.uri = { nullptr, uri_1.length() + 1, &uri_1[0] }; + resource_1.uri = OC_MMEM(&uri_1[0], uri_1.length() + 1, nullptr); oc_link_t *link_1 = oc_new_link(&resource_1); ASSERT_NE(link_1, nullptr); oc_collection_add_link(&collection->res, link_1); std::string uri_2 = "/bb"; oc_resource_t resource_2{}; - resource_2.uri = { nullptr, uri_2.length() + 1, &uri_2[0] }; + resource_2.uri = OC_MMEM(&uri_2[0], uri_2.length() + 1, nullptr); oc_link_t *link_2 = oc_new_link(&resource_2); ASSERT_NE(link_2, nullptr); oc_collection_add_link(&collection->res, link_2); std::string uri_3 = "/a"; oc_resource_t resource_3{}; - resource_3.uri = { nullptr, uri_3.length() + 1, &uri_3[0] }; + resource_3.uri = OC_MMEM(&uri_3[0], uri_3.length() + 1, nullptr); oc_link_t *link_3 = oc_new_link(&resource_3); ASSERT_NE(link_3, nullptr); oc_collection_add_link(&collection->res, link_3); @@ -319,14 +321,14 @@ TEST_F(TestCollections, GetLinkByURI) std::string uri_1 = "/aaa"; oc_resource_t resource_1{}; - resource_1.uri = { nullptr, uri_1.length() + 1, &uri_1[0] }; + resource_1.uri = OC_MMEM(&uri_1[0], uri_1.length() + 1, nullptr); oc_link_t *link_1 = oc_new_link(&resource_1); ASSERT_NE(link_1, nullptr); oc_collection_add_link(&collection->res, link_1); std::string uri_2 = "/bbb"; oc_resource_t resource_2{}; - resource_2.uri = { nullptr, uri_2.length() + 1, &uri_2[0] }; + resource_2.uri = OC_MMEM(&uri_2[0], uri_2.length() + 1, nullptr); oc_link_t *link_2 = oc_new_link(&resource_2); ASSERT_NE(link_2, nullptr); oc_collection_add_link(&collection->res, link_2); diff --git a/api/unittest/eptest.cpp b/api/unittest/eptest.cpp index 8415888136..7ee773edf5 100644 --- a/api/unittest/eptest.cpp +++ b/api/unittest/eptest.cpp @@ -22,6 +22,7 @@ #include "oc_helpers.h" #include "oc_uuid.h" #include "port/common/oc_ip.h" +#include "port/oc_allocator_internal.h" #include "port/oc_connectivity.h" #include "port/oc_random.h" #include "tests/gtest/Device.h" @@ -49,10 +50,17 @@ class TestEndpoint : public testing::Test { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); #endif /* _WIN32 */ +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_init(); +#endif /* !OC_DYNAMIC_ALLOCATION */ } void TearDown() override { +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_destroy(); +#endif /* !OC_DYNAMIC_ALLOCATION */ + #ifdef _WIN32 WSACleanup(); #endif /* _WIN32 */ diff --git a/api/unittest/tcptest.cpp b/api/unittest/tcptest.cpp index 4b14dea45f..cdeb3b7ad2 100644 --- a/api/unittest/tcptest.cpp +++ b/api/unittest/tcptest.cpp @@ -22,7 +22,7 @@ #include "oc_endpoint.h" #include "oc_buffer.h" #include "api/oc_tcp_internal.h" -#include "port/oc_network_event_handler_internal.h" +#include "port/oc_allocator_internal.h" #ifdef _WIN32 #include @@ -40,19 +40,23 @@ class TCPMessage : public testing::Test { public: void SetUp() override { - oc_network_event_handler_mutex_init(); #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); #endif /* _WIN32 */ +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_init(); +#endif /* !OC_DYNAMIC_ALLOCATION */ } void TearDown() override { +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_destroy(); +#endif /* !OC_DYNAMIC_ALLOCATION */ #ifdef _WIN32 WSACleanup(); #endif /* _WIN32 */ - oc_network_event_handler_mutex_destroy(); } static void ValidateMessage(bool exp, bool secure, diff --git a/api/unittest/udptest.cpp b/api/unittest/udptest.cpp index a15ac586e0..c1e5876c9d 100644 --- a/api/unittest/udptest.cpp +++ b/api/unittest/udptest.cpp @@ -20,8 +20,8 @@ #include "oc_endpoint.h" #include "oc_buffer.h" #include "api/oc_udp_internal.h" +#include "port/oc_allocator_internal.h" #include "port/oc_log_internal.h" -#include "port/oc_network_event_handler_internal.h" #include #include @@ -39,19 +39,23 @@ class UDPMessage : public testing::Test { public: void SetUp() override { - oc_network_event_handler_mutex_init(); #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); #endif /* _WIN32 */ +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_init(); +#endif /* !OC_DYNAMIC_ALLOCATION */ } void TearDown() override { +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_destroy(); +#endif /* !OC_DYNAMIC_ALLOCATION */ #ifdef _WIN32 WSACleanup(); #endif /* _WIN32 */ - oc_network_event_handler_mutex_destroy(); } static void ValidateMessage(bool exp, bool secure, diff --git a/apps/cloud_server.c b/apps/cloud_server.c index 21e91af230..84dbb29171 100644 --- a/apps/cloud_server.c +++ b/apps/cloud_server.c @@ -40,6 +40,7 @@ #include #include #include +#include #ifndef _MSC_VER #include diff --git a/docker/run.sh b/docker/run.sh index c0e7a6dff8..ec829b28e8 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -14,9 +14,10 @@ mkdir -p /tmp/logbt-coredumps pids=() echo "called_from_lib:libfaketimeMT.so.1" > /tmp/tsan.suppressions for ((i=0;i<$NUM_DEVICES;i++)); do - export ASAN_OPTIONS="atexit=1:log_path=/tmp/${i}.asan.log:verify_asan_link_order=0" + # verify_asan_link_order=0 is needed when using libfaketimeMT.so.1 + export ASAN_OPTIONS="debug=true:atexit=true:check_initialization_order=true:detect_stack_use_after_return=true:alloc_dealloc_mismatch=true:detect_invalid_pointer_pairs=2:strict_string_checks=true:log_path=/tmp/${i}.asan.log:verify_asan_link_order=0" # abort on first tsan problem found - export TSAN_OPTIONS="halt_on_error=1:abort_on_error=1:log_path=/tmp/${i}.tsan.log:suppressions=/tmp/tsan.suppressions" + export TSAN_OPTIONS="halt_on_error=1:abort_on_error=true:log_path=/tmp/${i}.tsan.log:suppressions=/tmp/tsan.suppressions" export LD_PRELOAD=/usr/local/lib/faketime/libfaketimeMT.so.1 ${PREFIX_EXEC} /iotivity-lite/port/linux/service $@ > /tmp/$i.log 2>&1 & pids+=($!) diff --git a/include/oc_helpers.h b/include/oc_helpers.h index ce054d0c2e..ea90b69ef5 100644 --- a/include/oc_helpers.h +++ b/include/oc_helpers.h @@ -273,7 +273,7 @@ void _oc_free_array( #ifdef OC_MEMORY_TRACE const char *func, #endif - oc_array_t *ocarray, pool type); + oc_array_t *ocarray, oc_mmem_pool_t type); /** * @brief reset ocstring contents @@ -308,7 +308,7 @@ void _oc_new_array( #ifdef OC_MEMORY_TRACE const char *func, #endif - oc_array_t *ocarray, size_t size, pool type); + oc_array_t *ocarray, size_t size, oc_mmem_pool_t type); /** * @brief allocate string array diff --git a/messaging/coap/unittest/observetest.cpp b/messaging/coap/unittest/observetest.cpp index 44170873e9..852e7cc390 100644 --- a/messaging/coap/unittest/observetest.cpp +++ b/messaging/coap/unittest/observetest.cpp @@ -21,11 +21,12 @@ #include "messaging/coap/transactions.h" #include "oc_core_res.h" #include "oc_ri.h" -#include "port/oc_network_event_handler_internal.h" +#include "port/oc_allocator_internal.h" #include "port/oc_random.h" #include "tests/gtest/Device.h" #include "tests/gtest/Endpoint.h" #include "util/oc_list.h" +#include "util/oc_mmem_internal.h" #include #include @@ -36,7 +37,9 @@ class TestObserver : public testing::Test { public: static void SetUpTestCase() { - oc_network_event_handler_mutex_init(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_init(); +#endif /* !OC_DYNAMIC_ALLOCATION */ oc_random_init(); } @@ -45,7 +48,9 @@ class TestObserver : public testing::Test { coap_free_all_transactions(); // remove transactions generated by // coap_remove_observers_by_resource oc_random_destroy(); - oc_network_event_handler_mutex_destroy(); +#ifndef OC_DYNAMIC_ALLOCATION + oc_allocator_mutex_destroy(); +#endif /* !OC_DYNAMIC_ALLOCATION */ } }; @@ -53,7 +58,7 @@ TEST_F(TestObserver, AddObserver) { std::string uri = "/res1"; oc_resource_t res{}; - res.uri = oc_string_t{ nullptr, uri.length() + 1, &uri[0] }; + res.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); oc_endpoint_t ep = oc::endpoint::FromString("coap://[0:85a3::1319:8a2e:0:0]:1337"); std::array token; @@ -81,7 +86,7 @@ TEST_F(TestObserver, AddObserver_RemoveDuplicates) { std::string uri = "/res1"; oc_resource_t res{}; - res.uri = oc_string_t{ nullptr, uri.length() + 1, &uri[0] }; + res.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); constexpr uint16_t block_size = 1024; oc_endpoint_t ep = oc::endpoint::FromString("coap://[0:85a3::1319:8a2e:0:0]:1337"); @@ -98,7 +103,7 @@ TEST_F(TestObserver, AddObserver_RemoveDuplicates) // - different resource doesn't matter std::string uri2 = "/res2"; oc_resource_t res2{}; - res2.uri = oc_string_t{ nullptr, uri2.length() + 1, &uri2[0] }; + res2.uri = OC_MMEM(&uri2[0], uri2.length() + 1, nullptr); EXPECT_NE(nullptr, coap_add_observer(&res, block_size, &ep, token.data(), token.size(), uri.c_str(), uri.length(), iface_mask)); @@ -127,7 +132,7 @@ TEST_F(TestObserver, AddObserver_Multiples) { std::string uri = "/res1"; oc_resource_t res{}; - res.uri = oc_string_t{ nullptr, uri.length() + 1, &uri[0] }; + res.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); oc_endpoint_t ep = oc::endpoint::FromString("coap://[0:85a3::1319:8a2e:0:0]:1337"); std::array token; @@ -169,7 +174,7 @@ TEST_F(TestObserver, AddObserver_Fail) { std::string res_uri = "/res"; oc_resource_t res{}; - res.uri = oc_string_t{ nullptr, res_uri.length() + 1, &res_uri[0] }; + res.uri = OC_MMEM(&res_uri[0], res_uri.length() + 1, nullptr); oc_endpoint_t ep = oc::endpoint::FromString("coap://[0:85a3::1319:8a2e:0:0]:1337"); std::array token; @@ -204,7 +209,7 @@ TEST_F(TestObserver, RemoveAllByClient) { std::string uri = "/res1"; oc_resource_t res{}; - res.uri = oc_string_t{ nullptr, uri.length() + 1, &uri[0] }; + res.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); oc_endpoint_t ep = oc::endpoint::FromString("coap://[0:85a3::1319:8a2e:0:0]:1337"); std::array token; @@ -248,7 +253,7 @@ TEST_F(TestObserver, RemoveByToken) { std::string uri = "/res"; oc_resource_t res{}; - res.uri = oc_string_t{ nullptr, uri.length() + 1, &uri[0] }; + res.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); oc_endpoint_t ep1 = oc::endpoint::FromString("coap://[0:85a3::1319:8a2e:0:0]:1337"); std::array token1; @@ -314,7 +319,7 @@ TEST_F(TestObserver, RemoveByMID) { std::string uri = "/res"; oc_resource_t res{}; - res.uri = oc_string_t{ nullptr, uri.length() + 1, &uri[0] }; + res.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); oc_endpoint_t ep1 = oc::endpoint::FromString("coap://[0:85a3::1319:8a2e:0:0]:1337"); std::array token; @@ -379,7 +384,7 @@ TEST_F(TestObserver, RemoveAllObserversByResource) { std::string uri1 = "/res/1"; oc_resource_t res1{}; - res1.uri = oc_string_t{ nullptr, uri1.length() + 1, &uri1[0] }; + res1.uri = OC_MMEM(&uri1[0], uri1.length() + 1, nullptr); oc_endpoint_t ep1 = oc::endpoint::FromString("coap://[0:85a3::1319:8a2e:0:0]:1337"); std::array token; @@ -408,7 +413,7 @@ TEST_F(TestObserver, RemoveAllObserversByResource) // 4: res2 + uri1 + ep1 oc_resource_t res2{}; - res2.uri = oc_string_t{ nullptr, uri2.length() + 1, &uri2[0] }; + res2.uri = OC_MMEM(&uri2[0], uri2.length() + 1, nullptr); EXPECT_NE(nullptr, coap_add_observer(&res2, 0, &ep1, token.data(), token.size(), uri1.c_str(), uri1.length(), iface_mask2)); @@ -426,7 +431,7 @@ TEST_F(TestObserver, RemoveAllObserversByResource) ASSERT_EQ(6, oc_list_length(coap_get_observers())); oc_resource_t res3{}; - res3.uri = oc_string_t{ nullptr, uri1.length() + 1, &uri1[0] }; + res3.uri = OC_MMEM(&uri1[0], uri1.length() + 1, nullptr); // remove all observers for res3 EXPECT_EQ(0, coap_remove_observers_by_resource(&res3)); @@ -519,7 +524,7 @@ TEST_F(TestObserverWithServer, { std::string uri = "/a"; oc_resource_t resource{}; - resource.uri = { nullptr, uri.length() + 1, &uri[0] }; + resource.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); EXPECT_FALSE(coap_add_discovery_batch_observer(&resource, /*removed*/ false, /*dispatch*/ false)); @@ -534,7 +539,7 @@ TEST_F(TestObserverWithServer, AddDiscoveryBatchObserver_FailInvalidResource) EXPECT_FALSE(coap_add_discovery_batch_observer(&resource, /*removed*/ true, /*dispatch*/ false)); std::string uri = ""; - resource.uri = { nullptr, uri.length() + 1, &uri[0] }; + resource.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); EXPECT_FALSE(coap_add_discovery_batch_observer(&resource, /*removed*/ true, /*dispatch*/ false)); } @@ -562,7 +567,7 @@ TEST_F(TestObserverWithServer, AddDiscoveryBatchObserver_FailDuplicate) std::string uri = "/a"; oc_resource_t resource{}; - resource.uri = { nullptr, uri.length() + 1, &uri[0] }; + resource.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); EXPECT_TRUE(coap_add_discovery_batch_observer(&resource, /*removed*/ false, /*dispatch*/ false)); EXPECT_FALSE(coap_add_discovery_batch_observer(&resource, /*removed*/ false, @@ -579,7 +584,7 @@ TEST_F(TestObserverWithServer, AddDiscoveryBatchObserver_FailAllocation) std::vector resources{}; for (int i = 0; i < COAP_MAX_OBSERVERS; ++i) { oc_resource_t resource{}; - resource.uri = { nullptr, uri.length() + 1, &uri[0] }; + resource.uri = OC_MMEM(&uri[0], uri.length() + 1, nullptr); resources.emplace_back(std::move(resource)); } for (auto &resource : resources) { @@ -591,7 +596,7 @@ TEST_F(TestObserverWithServer, AddDiscoveryBatchObserver_FailAllocation) // out of static memory std::string failUri = "/fail"; oc_resource_t resource{}; - resource.uri = { nullptr, failUri.length() + 1, &failUri[0] }; + resource.uri = OC_MMEM(&failUri[0], failUri.length() + 1, nullptr); EXPECT_FALSE(coap_add_discovery_batch_observer(&resource, /*removed*/ false, /*dispatch*/ false)); diff --git a/port/android/Makefile b/port/android/Makefile index 0abb4de33f..2a44db684b 100644 --- a/port/android/Makefile +++ b/port/android/Makefile @@ -143,7 +143,7 @@ endif CTIMESTAMP+=../../api/c-timestamp/timestamp_compare.c ../../api/c-timestamp/timestamp_format.c ../../api/c-timestamp/timestamp_valid.c ../../api/c-timestamp/timestamp_parse.c -SRC_PORT_COMMON:=$(wildcard ../../port/common/*.c) +SRC_PORT_COMMON:=$(wildcard ../../port/common/*.c) $(wildcard ../../port/common/posix/*.c) ifneq ($(MEMORY_TRACE),1) SRC_UTIL:=$(filter-out %_mem_trace.c,$(wildcard ../../util/*.c)) else @@ -197,7 +197,7 @@ else OBJ_CLOUD = endif OBJ_CLIENT_SERVER=$(addprefix ${OBJDIR}/client_server/,$(notdir $(SRC:.c=.o) $(SRC_CLIENT:.c=.o))) -VPATH=../../api/:../../api/client/:../../api/cloud/:../../api/c-timestamp:../../messaging/coap/:../../port/common/:../../util/: +VPATH=../../api/:../../api/client/:../../api/cloud/:../../api/c-timestamp:../../messaging/coap/:../../port/common/:../../port/common/posix/:../../util/: VPATH+=../../deps/tinycbor/src/:../../deps/mbedtls/library: LIBS?= -lm -llog diff --git a/port/common/posix/oc_allocator.c b/port/common/posix/oc_allocator.c new file mode 100644 index 0000000000..f68c585212 --- /dev/null +++ b/port/common/posix/oc_allocator.c @@ -0,0 +1,60 @@ +/**************************************************************************** + * + * Copyright (c) 2023 plgd.dev s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include "port/oc_allocator_internal.h" +#include "port/oc_assert.h" + +#ifndef OC_DYNAMIC_ALLOCATION + +#include + +static pthread_mutex_t g_allocator_mutex; + +void +oc_allocator_mutex_init(void) +{ + if (pthread_mutex_init(&g_allocator_mutex, NULL) != 0) { + oc_abort("error initializing allocator mutex"); + } +} + +void +oc_allocator_mutex_lock(void) +{ + if (pthread_mutex_lock(&g_allocator_mutex) != 0) { + oc_abort("error locking allocator mutex"); + } +} + +void +oc_allocator_mutex_unlock(void) +{ + if (pthread_mutex_unlock(&g_allocator_mutex) != 0) { + oc_abort("error unlocking allocator mutex"); + } +} + +void +oc_allocator_mutex_destroy(void) +{ + if (pthread_mutex_destroy(&g_allocator_mutex) != 0) { + oc_abort("error destroying allocator mutex"); + } +} + +#endif /* !OC_DYNAMIC_ALLOCATION */ diff --git a/port/esp32/main/CMakeLists.txt b/port/esp32/main/CMakeLists.txt index f4e173f2ef..55cd03ef49 100644 --- a/port/esp32/main/CMakeLists.txt +++ b/port/esp32/main/CMakeLists.txt @@ -66,6 +66,7 @@ set(sources ${CMAKE_CURRENT_SOURCE_DIR}/../../../messaging/coap/separate.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../messaging/coap/transactions.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../port/common/oc_ip.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../port/common/posix/oc_allocator.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../util/oc_etimer.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../util/oc_list.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../util/oc_memb.c diff --git a/port/linux/Makefile b/port/linux/Makefile index 6604c598bc..5db60e42a1 100644 --- a/port/linux/Makefile +++ b/port/linux/Makefile @@ -115,7 +115,7 @@ endif CTIMESTAMP+=../../api/c-timestamp/timestamp_compare.c ../../api/c-timestamp/timestamp_format.c ../../api/c-timestamp/timestamp_valid.c ../../api/c-timestamp/timestamp_parse.c -SRC_PORT_COMMON:=$(wildcard ../../port/common/*.c) +SRC_PORT_COMMON:=$(wildcard ../../port/common/*.c) $(wildcard ../../port/common/posix/*.c) ifneq ($(MEMORY_TRACE),1) SRC_UTIL:=$(filter-out %_mem_trace.c,$(wildcard ../../util/*.c)) else @@ -167,7 +167,7 @@ OBJ_PYTHON=$(addprefix obj/python/,$(notdir $(SRC_PYTHON:.c=.o))) # $(info OBJ_PYTHON is $(OBJ_PYTHON)) # $(info SRC_PYTHON is $(SRC_PYTHON)) -VPATH=../../api/:../../api/client/:../../api/cloud/:../../api/c-timestamp:../../messaging/coap/:../../port/common/:../../python/:../../util/: +VPATH=../../api/:../../api/client/:../../api/cloud/:../../api/c-timestamp:../../messaging/coap/:../../port/common/:../../port/common/posix/:../../python/:../../util/: VPATH+=../../deps/tinycbor/src/:../../deps/mbedtls/library: LIBS?= -lm -pthread -lrt diff --git a/port/oc_allocator_internal.h b/port/oc_allocator_internal.h new file mode 100644 index 0000000000..ee882d20ad --- /dev/null +++ b/port/oc_allocator_internal.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * + * Copyright (c) 2023 plgd.dev s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#ifndef OC_PORT_ALLOCATOR_INTERNAL_H +#define OC_PORT_ALLOCATOR_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup allocator Allocation synchronization + * + * If a struct is allocated and deallocated in multiple threads, it must be + * protected by a mutex. + * + * Known cases of multithreaded allocation: + * + * - oc_message_t when allocated by oc_memb pool (oc_allocate_message) + * - oc_endpoint_t when allocated by oc_memb pool (oc_new_endpoint) + * - oc_tcp_on_connect_event_t when allocated by oc_memb pool + * (oc_tcp_on_connect_event_create + * + * Struct oc_memb pool needs synchronization when dynamic allocation is + * disabled. Since all known cases are allocated by oc_memb pool with static + * allocation, we ifdef out the mutexes when dynamic allocation is disabled. + * + * @{ + */ + +#ifndef OC_DYNAMIC_ALLOCATION + +/** @brief initialize the allocator mutex */ +void oc_allocator_mutex_init(void); + +/** @brief lock the allocator mutex */ +void oc_allocator_mutex_lock(void); + +/** @brief unlock the allocator mutex */ +void oc_allocator_mutex_unlock(void); + +/** @brief destroy the network event handler mutex */ +void oc_allocator_mutex_destroy(void); + +#endif /* !OC_DYNAMIC_ALLOCATION */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* OC_PORT_ALLOCATOR_INTERNAL_H */ diff --git a/port/windows/ipadapter.c b/port/windows/ipadapter.c index 8e8436f526..8d30b7339e 100644 --- a/port/windows/ipadapter.c +++ b/port/windows/ipadapter.c @@ -72,7 +72,7 @@ static const uint8_t ALL_COAP_NODES_SL[] = { 0xff, 0x05, 0, 0, 0, 0, 0, 0, #define ALL_COAP_NODES_V4 0xe00001bb -static HANDLE mutex; +static HANDLE g_network_mutex; SOCKET ifchange_sock; BOOL ifchange_initialized; OVERLAPPED ifchange_event; @@ -168,7 +168,7 @@ remove_all_network_interface_cbs(void) void oc_network_event_handler_mutex_init(void) { - mutex = mutex_new(); + g_network_mutex = mutex_new(); #ifdef OC_NETWORK_MONITOR oc_network_interface_cb_mutex = mutex_new(); #endif /* OC_NETWORK_MONITOR */ @@ -180,13 +180,13 @@ oc_network_event_handler_mutex_init(void) void oc_network_event_handler_mutex_lock(void) { - mutex_lock(mutex); + mutex_lock(g_network_mutex); } void oc_network_event_handler_mutex_unlock(void) { - mutex_unlock(mutex); + mutex_unlock(g_network_mutex); } void @@ -196,7 +196,7 @@ oc_network_event_handler_mutex_destroy(void) oc_tcp_adapter_mutex_destroy(); #endif /* OC_TCP */ ifchange_initialized = false; - mutex_free(mutex); + mutex_free(g_network_mutex); closesocket(ifchange_sock); #ifdef OC_NETWORK_MONITOR mutex_free(oc_network_interface_cb_mutex); diff --git a/port/windows/oc_allocator.c b/port/windows/oc_allocator.c new file mode 100644 index 0000000000..6f0d1dbff5 --- /dev/null +++ b/port/windows/oc_allocator.c @@ -0,0 +1,50 @@ +/**************************************************************************** + * + * Copyright (c) 2023 plgd.dev s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"), + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include "mutex.h" +#include "port/oc_allocator_internal.h" + +#ifndef OC_DYNAMIC_ALLOCATION + +static mutex_t g_allocator_mutex; + +void +oc_allocator_mutex_init(void) +{ + mutex_init(&g_allocator_mutex); +} + +void +oc_allocator_mutex_lock(void) +{ + mutex_lock(&g_allocator_mutex); +} + +void +oc_allocator_mutex_unlock(void) +{ + mutex_unlock(&g_allocator_mutex); +} + +void +oc_allocator_mutex_destroy(void) +{ + mutex_destroy(&g_allocator_mutex); +} + +#endif /* !OC_DYNAMIC_ALLOCATION */ diff --git a/port/windows/vs2015/IoTivity-lite.vcxproj b/port/windows/vs2015/IoTivity-lite.vcxproj index 3399fe15c3..b7e71f4fa6 100644 --- a/port/windows/vs2015/IoTivity-lite.vcxproj +++ b/port/windows/vs2015/IoTivity-lite.vcxproj @@ -296,12 +296,15 @@ + + - + + @@ -459,6 +462,7 @@ + diff --git a/port/windows/vs2015/IoTivity-lite.vcxproj.filters b/port/windows/vs2015/IoTivity-lite.vcxproj.filters index 2f006cc1f3..62a588cc07 100644 --- a/port/windows/vs2015/IoTivity-lite.vcxproj.filters +++ b/port/windows/vs2015/IoTivity-lite.vcxproj.filters @@ -287,6 +287,9 @@ Core + + Port + Port @@ -523,6 +526,9 @@ Headers + + Port + Port @@ -547,6 +553,9 @@ Headers + + Port + Port @@ -613,7 +622,7 @@ Headers - + Port @@ -622,6 +631,9 @@ Port + + Port + Port @@ -672,7 +684,7 @@ Security - + Security diff --git a/tests/libfaketime/unittest/etimertest.cpp b/tests/libfaketime/unittest/etimertest.cpp index c0e9680ce7..f3b512d795 100644 --- a/tests/libfaketime/unittest/etimertest.cpp +++ b/tests/libfaketime/unittest/etimertest.cpp @@ -72,7 +72,7 @@ std::function TestEventTimer::onEventTimer_{}; OC_PROCESS_THREAD(oc_test_process, ev, data) { OC_PROCESS_BEGIN(); - while (true) { + while (oc_process_is_running(&oc_test_process)) { OC_PROCESS_YIELD(); OC_INFO("received event 0x%x", (int)ev); diff --git a/util/oc_mem_trace.c b/util/oc_mem_trace.c index fe4c2d5cdd..8ab7f06bf1 100644 --- a/util/oc_mem_trace.c +++ b/util/oc_mem_trace.c @@ -18,15 +18,15 @@ #ifdef OC_MEMORY_TRACE +#include "oc_list.h" +#include "port/oc_log_internal.h" +#include "util/oc_mem_trace_internal.h" + #include #include #include -#include "oc_list.h" -#include "oc_mem_trace.h" -#include "port/oc_log_internal.h" - -#define FUNC_NAME_LEN 30 +#define FUNC_NAME_LEN (30) typedef struct _mem_info { diff --git a/util/oc_mem_trace.h b/util/oc_mem_trace_internal.h similarity index 91% rename from util/oc_mem_trace.h rename to util/oc_mem_trace_internal.h index 1cf3860ca5..49a0523bfe 100644 --- a/util/oc_mem_trace.h +++ b/util/oc_mem_trace_internal.h @@ -16,8 +16,8 @@ * ****************************************************************************/ -#ifndef OC_MEM_TRACE_H -#define OC_MEM_TRACE_H +#ifndef OC_MEM_TRACE_INTERNAL_H +#define OC_MEM_TRACE_INTERNAL_H #ifdef __cplusplus extern "C" { @@ -34,4 +34,4 @@ void oc_mem_trace_shutdown(void); } #endif -#endif /* OC_MEM_TRACE_H */ +#endif /* OC_MEM_TRACE_INTERNAL_H */ diff --git a/util/oc_memb.c b/util/oc_memb.c index 230d837b6a..1fbb66680e 100644 --- a/util/oc_memb.c +++ b/util/oc_memb.c @@ -38,10 +38,9 @@ #include #ifdef OC_MEMORY_TRACE -#include "oc_mem_trace.h" +#include "util/oc_mem_trace_internal.h" #endif -/*---------------------------------------------------------------------------*/ void oc_memb_init(struct oc_memb *m) { @@ -50,7 +49,7 @@ oc_memb_init(struct oc_memb *m) memset(m->mem, 0, (unsigned)m->num * sizeof(char *)); } } -/*---------------------------------------------------------------------------*/ + void * _oc_memb_alloc( #ifdef OC_MEMORY_TRACE @@ -99,7 +98,7 @@ _oc_memb_alloc( return ptr; } -/*---------------------------------------------------------------------------*/ + char _oc_memb_free( #ifdef OC_MEMORY_TRACE @@ -138,19 +137,19 @@ _oc_memb_free( free(ptr); } #endif /* OC_DYNAMIC_ALLOCATION */ - if (m->buffers_avail_cb) { + if (m->buffers_avail_cb != NULL) { m->buffers_avail_cb(oc_memb_numfree(m)); } return 0; } -/*---------------------------------------------------------------------------*/ -int + +bool oc_memb_inmemb(const struct oc_memb *m, const void *ptr) { return ((const char *)ptr >= (char *)m->mem) && ((const char *)ptr < ((char *)m->mem + (ptrdiff_t)(m->num * m->size))); } -/*---------------------------------------------------------------------------*/ + int oc_memb_numfree(const struct oc_memb *m) { @@ -162,11 +161,10 @@ oc_memb_numfree(const struct oc_memb *m) } return num_free; } -/*---------------------------------------------------------------------------*/ + void oc_memb_set_buffers_avail_cb(struct oc_memb *m, oc_memb_buffers_avail_callback_t cb) { m->buffers_avail_cb = cb; } -/*---------------------------------------------------------------------------*/ diff --git a/util/oc_memb.h b/util/oc_memb.h index 163939ea37..860299cba7 100644 --- a/util/oc_memb.h +++ b/util/oc_memb.h @@ -48,6 +48,10 @@ #define OC_MEMB_H #include "oc_config.h" +#include "oc_export.h" +#include "util/oc_compiler.h" + +#include #ifdef __cplusplus extern "C" { @@ -143,13 +147,15 @@ struct oc_memb * * \param m A memory block previously declared with MEMB(). */ -void oc_memb_init(struct oc_memb *m); +OC_API +void oc_memb_init(struct oc_memb *m) OC_NONNULL(); /** * Allocate a memory block from a block of memory declared with MEMB(). * * \param m A memory block previously declared with MEMB(). */ +OC_API void *_oc_memb_alloc( #ifdef OC_MEMORY_TRACE const char *func, @@ -160,7 +166,7 @@ void *_oc_memb_alloc( * Deallocate a memory block from a memory block previously declared * with MEMB(). * - * \param m m A memory block previously declared with MEMB(). + * \param m A memory block previously declared with MEMB(). * * \param ptr A pointer to the memory block that is to be deallocated. * @@ -168,6 +174,7 @@ void *_oc_memb_alloc( * if successfully deallocated) or -1 if the pointer "ptr" did not * point to a legal memory block. */ +OC_API char _oc_memb_free( #ifdef OC_MEMORY_TRACE const char *func, @@ -182,11 +189,35 @@ char _oc_memb_free( #define oc_memb_free(m, ptr) _oc_memb_free(m, ptr) #endif +/** + * @brief Set callback invoked when memory for given block becomes available. + * + * @param m A memory block previously declared with MEMB(). + * @param cb Callback invoked when memory for given block becomes available. + */ +OC_API void oc_memb_set_buffers_avail_cb(struct oc_memb *m, - oc_memb_buffers_avail_callback_t cb); + oc_memb_buffers_avail_callback_t cb) + OC_NONNULL(1); -int oc_memb_inmemb(const struct oc_memb *m, const void *ptr); +/** + * @brief Check if given pointer is in given memory block. + * + * @param m A memory block previously declared with MEMB(). + * @param ptr A pointer to be checked. + * @return true If the pointer is in given memory block. + * @return false Otherwise. + */ +OC_API +bool oc_memb_inmemb(const struct oc_memb *m, const void *ptr); +/** + * @brief Get the number of free memory blocks in given memory block. + * + * @param m A memory block previously declared with MEMB(). + * @return number of free memory blocks in given memory block. + */ +OC_API int oc_memb_numfree(const struct oc_memb *m); #ifdef __cplusplus diff --git a/util/oc_mmem.c b/util/oc_mmem.c index 1f4af7dee3..e71a284edf 100644 --- a/util/oc_mmem.c +++ b/util/oc_mmem.c @@ -32,42 +32,50 @@ * */ -#include "oc_mmem.h" #include "oc_config.h" #include "oc_list.h" +#include "oc_mmem.h" +#include "oc_mmem_internal.h" #include "port/oc_log_internal.h" -#include -#include + #ifdef OC_MEMORY_TRACE -#include "oc_mem_trace.h" +#include "util/oc_mem_trace_internal.h" +#endif /* OC_MEMORY_TRACE */ + #include -#endif +#include +#include + +#ifdef OC_DYNAMIC_ALLOCATION +#include +#endif /* OC_DYNAMIC_ALLOCATION */ #ifndef OC_DYNAMIC_ALLOCATION #if !defined(OC_BYTES_POOL_SIZE) || !defined(OC_INTS_POOL_SIZE) || \ !defined(OC_DOUBLES_POOL_SIZE) #error "Please define byte, int, double pool sizes in oc_config.h" -#endif /* ...POOL_SIZE */ +#endif /* !OC_BYTES_POOL_SIZE || !OC_INTS_POOL_SIZE || !OC_DOUBLES_POOL_SIZE \ + */ -static double doubles[OC_DOUBLES_POOL_SIZE]; -static int64_t ints[OC_INTS_POOL_SIZE]; -static unsigned char bytes[OC_BYTES_POOL_SIZE]; -static unsigned int avail_bytes, avail_ints, avail_doubles; +static unsigned char g_mmem_bytes[OC_BYTES_POOL_SIZE] = { 0 }; +static unsigned int g_mmem_avail_bytes = OC_BYTES_POOL_SIZE; +OC_LIST(g_mmem_bytes_list); -OC_LIST(bytes_list); -OC_LIST(ints_list); -OC_LIST(doubles_list); -#else /* !OC_DYNAMIC_ALLOCATION */ -#include -#endif /* OC_DYNAMIC_ALLOCATION */ -/*---------------------------------------------------------------------------*/ +static int64_t g_mmem_ints[OC_INTS_POOL_SIZE] = { 0 }; +static unsigned int g_mmem_avail_ints = OC_INTS_POOL_SIZE; +OC_LIST(g_mmem_ints_list); + +static double g_mmem_doubles[OC_DOUBLES_POOL_SIZE] = { 0.0 }; +static unsigned int g_mmem_avail_doubles = OC_DOUBLES_POOL_SIZE; +OC_LIST(g_mmem_doubles_list); +#endif /* !OC_DYNAMIC_ALLOCATION */ size_t _oc_mmem_alloc( #ifdef OC_MEMORY_TRACE const char *func, #endif - struct oc_mmem *m, size_t size, pool pool_type) + struct oc_mmem *m, size_t size, oc_mmem_pool_t pool_type) { if (!m) { OC_ERR("oc_mmem is NULL"); @@ -83,14 +91,14 @@ _oc_mmem_alloc( m->ptr = malloc(size); m->size = size; #else /* !OC_DYNAMIC_ALLOCATION */ - if (avail_bytes < size) { + if (g_mmem_avail_bytes < size) { OC_WRN("byte pool exhausted"); return 0; } - oc_list_add(bytes_list, m); - m->ptr = &bytes[OC_BYTES_POOL_SIZE - avail_bytes]; + oc_list_add(g_mmem_bytes_list, m); + m->ptr = &g_mmem_bytes[OC_BYTES_POOL_SIZE - g_mmem_avail_bytes]; m->size = size; - avail_bytes -= size; + g_mmem_avail_bytes -= size; #endif /* OC_DYNAMIC_ALLOCATION */ break; case INT_POOL: @@ -99,14 +107,14 @@ _oc_mmem_alloc( m->ptr = malloc(size * sizeof(int64_t)); m->size = size; #else /* OC_DYNAMIC_ALLOCATION */ - if (avail_ints < size) { + if (g_mmem_avail_ints < size) { OC_WRN("int pool exhausted"); return 0; } - oc_list_add(ints_list, m); - m->ptr = &ints[OC_INTS_POOL_SIZE - avail_ints]; + oc_list_add(g_mmem_ints_list, m); + m->ptr = &g_mmem_ints[OC_INTS_POOL_SIZE - g_mmem_avail_ints]; m->size = size; - avail_ints -= size; + g_mmem_avail_ints -= size; #endif /* !OC_DYNAMIC_ALLOCATION */ break; case DOUBLE_POOL: @@ -115,14 +123,14 @@ _oc_mmem_alloc( m->ptr = malloc(size * sizeof(double)); m->size = size; #else /* OC_DYNAMIC_ALLOCATION */ - if (avail_doubles < size) { + if (g_mmem_avail_doubles < size) { OC_WRN("double pool exhausted"); return 0; } - oc_list_add(doubles_list, m); - m->ptr = &doubles[OC_DOUBLES_POOL_SIZE - avail_doubles]; + oc_list_add(g_mmem_doubles_list, m); + m->ptr = &g_mmem_doubles[OC_DOUBLES_POOL_SIZE - g_mmem_avail_doubles]; m->size = size; - avail_doubles -= size; + g_mmem_avail_doubles -= size; #endif /* !OC_DYNAMIC_ALLOCATION */ break; default: @@ -141,7 +149,7 @@ _oc_mmem_free( #ifdef OC_MEMORY_TRACE const char *func, #endif - struct oc_mmem *m, pool pool_type) + struct oc_mmem *m, oc_mmem_pool_t pool_type) { if (!m) { OC_ERR("oc_mmem is NULL"); @@ -170,17 +178,18 @@ _oc_mmem_free( switch (pool_type) { case BYTE_POOL: memmove(m->ptr, m->next->ptr, - &bytes[OC_BYTES_POOL_SIZE - avail_bytes] - + &g_mmem_bytes[OC_BYTES_POOL_SIZE - g_mmem_avail_bytes] - (unsigned char *)m->next->ptr); break; case INT_POOL: memmove(m->ptr, m->next->ptr, - &ints[OC_INTS_POOL_SIZE - avail_ints] - (int64_t *)m->next->ptr); + &g_mmem_ints[OC_INTS_POOL_SIZE - g_mmem_avail_ints] - + (int64_t *)m->next->ptr); break; case DOUBLE_POOL: memmove(m->ptr, m->next->ptr, - &doubles[OC_DOUBLES_POOL_SIZE - avail_doubles] - + &g_mmem_doubles[OC_DOUBLES_POOL_SIZE - g_mmem_avail_doubles] - (double *)m->next->ptr); break; default: @@ -194,16 +203,16 @@ _oc_mmem_free( switch (pool_type) { case BYTE_POOL: - avail_bytes += m->size; - oc_list_remove(bytes_list, m); + g_mmem_avail_bytes += m->size; + oc_list_remove(g_mmem_bytes_list, m); break; case INT_POOL: - avail_ints += m->size; - oc_list_remove(ints_list, m); + g_mmem_avail_ints += m->size; + oc_list_remove(g_mmem_ints_list, m); break; case DOUBLE_POOL: - avail_doubles += m->size; - oc_list_remove(doubles_list, m); + g_mmem_avail_doubles += m->size; + oc_list_remove(g_mmem_doubles_list, m); break; } #else /* !OC_DYNAMIC_ALLOCATION */ @@ -217,17 +226,16 @@ void oc_mmem_init(void) { #ifndef OC_DYNAMIC_ALLOCATION - static int inited = 0; - if (inited) { + static bool initialized = false; + if (initialized) { return; } - oc_list_init(bytes_list); - oc_list_init(ints_list); - oc_list_init(doubles_list); - avail_bytes = OC_BYTES_POOL_SIZE; - avail_ints = OC_INTS_POOL_SIZE; - avail_doubles = OC_DOUBLES_POOL_SIZE; - inited = 1; + oc_list_init(g_mmem_bytes_list); + oc_list_init(g_mmem_ints_list); + oc_list_init(g_mmem_doubles_list); + g_mmem_avail_bytes = OC_BYTES_POOL_SIZE; + g_mmem_avail_ints = OC_INTS_POOL_SIZE; + g_mmem_avail_doubles = OC_DOUBLES_POOL_SIZE; + initialized = true; #endif /* OC_DYNAMIC_ALLOCATION */ } -/*---------------------------------------------------------------------------*/ diff --git a/util/oc_mmem.h b/util/oc_mmem.h index 492f6719be..72c546f043 100644 --- a/util/oc_mmem.h +++ b/util/oc_mmem.h @@ -41,44 +41,29 @@ extern "C" { #endif +typedef enum { + BYTE_POOL, + INT_POOL, + DOUBLE_POOL, +} oc_mmem_pool_t; + #define OC_MMEM_PTR(m) (struct oc_mmem *)(m)->ptr +/** + * @brief An allocation block. + * + * @warning With OC_DYNAMIC_ALLOCATION not defined, the allocation and + * deallocation of structs typedef-ed from oc_mmem_t is not thread-safe. + */ struct oc_mmem { - struct oc_mmem *next; - size_t size; - void *ptr; +#ifndef OC_DYNAMIC_ALLOCATION + struct oc_mmem *next; ///< Pointer to next block in memory pool. +#endif /* !OC_DYNAMIC_ALLOCATION */ + size_t size; ///< Size of this block. + void *ptr; ///< Pointer to the memory. }; -typedef enum { BYTE_POOL, INT_POOL, DOUBLE_POOL } pool; - -void oc_mmem_init(void); - -#ifdef OC_MEMORY_TRACE - -#define oc_mmem_alloc(m, size, pool_type) \ - _oc_mmem_alloc(__func__, m, size, pool_type) -#define oc_mmem_free(m, pool_type) _oc_mmem_free(__func__, m, pool_type) - -#else /* OC_MEMORY_TRACE */ - -#define oc_mmem_alloc(m, size, pool_type) _oc_mmem_alloc(m, size, pool_type) -#define oc_mmem_free(m, pool_type) _oc_mmem_free(m, pool_type) - -#endif /* !OC_MEMORY_TRACE */ - -size_t _oc_mmem_alloc( -#ifdef OC_MEMORY_TRACE - const char *func, -#endif - struct oc_mmem *m, size_t size, pool pool_type); - -void _oc_mmem_free( -#ifdef OC_MEMORY_TRACE - const char *func, -#endif - struct oc_mmem *m, pool pool_type); - #ifdef __cplusplus } #endif diff --git a/util/oc_mmem_internal.h b/util/oc_mmem_internal.h new file mode 100644 index 0000000000..bcede71545 --- /dev/null +++ b/util/oc_mmem_internal.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#ifndef OC_MMEM_INTERNAL_H +#define OC_MMEM_INTERNAL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus + +#ifdef OC_DYNAMIC_ALLOCATION +#define OC_MMEM(ptr, size, next) \ + oc_mmem \ + { \ + (size), (ptr), \ + } + +#else /* !OC_DYNAMIC_ALLOCATION */ +#define OC_MMEM(ptr, size, next) \ + oc_mmem \ + { \ + (next), (size), (ptr), \ + } +#endif /* OC_DYNAMIC_ALLOCATION */ + +#else /* !__cplusplus */ + +#ifdef OC_DYNAMIC_ALLOCATION +#define OC_MMEM(ptr, size, next) \ + (struct oc_mmem) \ + { \ + (size), (ptr), \ + } + +#else /* !OC_DYNAMIC_ALLOCATION */ +#define OC_MMEM(ptr, size, next) \ + (struct oc_mmem) \ + { \ + (next), (size), (ptr), \ + } +#endif /* OC_DYNAMIC_ALLOCATION */ + +#endif /* __cplusplus */ + +#define OC_MMEM_NULL() OC_MMEM(NULL, 0, NULL) + +void oc_mmem_init(void); + +#ifdef OC_MEMORY_TRACE + +#define oc_mmem_alloc(m, size, pool_type) \ + _oc_mmem_alloc(__func__, m, size, pool_type) +#define oc_mmem_free(m, pool_type) _oc_mmem_free(__func__, m, pool_type) + +#else /* OC_MEMORY_TRACE */ + +#define oc_mmem_alloc(m, size, pool_type) _oc_mmem_alloc(m, size, pool_type) +#define oc_mmem_free(m, pool_type) _oc_mmem_free(m, pool_type) + +#endif /* !OC_MEMORY_TRACE */ + +size_t _oc_mmem_alloc( +#ifdef OC_MEMORY_TRACE + const char *func, +#endif + struct oc_mmem *m, size_t size, oc_mmem_pool_t pool_type); + +void _oc_mmem_free( +#ifdef OC_MEMORY_TRACE + const char *func, +#endif + struct oc_mmem *m, oc_mmem_pool_t pool_type); + +#ifdef __cplusplus +} +#endif + +#endif /* OC_MMEM_INTERNAL_H */ diff --git a/util/oc_process.c b/util/oc_process.c index 0834cf7315..2a30cef19d 100644 --- a/util/oc_process.c +++ b/util/oc_process.c @@ -384,6 +384,18 @@ oc_process_is_closing_all_tls_sessions(void) } #endif /* OC_SECURITY */ +void +oc_process_iterate_events(oc_process_iterate_event_fn_t fn, void *fn_data) +{ + for (oc_process_num_events_t i = 0; i < g_nevents; ++i) { + oc_process_num_events_t index = (g_fevent + i) % OC_PROCESS_NUMEVENTS; + struct event_data *event = &g_events[index]; + if (!fn(event->p, event->ev, event->data, fn_data)) { + return; + } + } +} + int oc_process_drop(const struct oc_process *p, oc_process_drop_event_t drop_event, const void *user_data) diff --git a/util/oc_process_internal.h b/util/oc_process_internal.h index b6e8dc15f9..d4edae56fe 100644 --- a/util/oc_process_internal.h +++ b/util/oc_process_internal.h @@ -41,6 +41,42 @@ void oc_process_init(void); */ void oc_process_shutdown(void); +/** + * @brief This function is responsible for determining whether an event should + * be removed from the event queue of a given process. + * + * @param ev The event to be dropped. + * @param data The auxiliary data to be sent with the event + * @param user_data Data to be passed to the drop_event function. + * @return true Drop the event. + */ + +/** + * @brief Callback invoked for each event iterated by + * oc_process_iterate_events. + * + * @param p process of the event + * @param ev the event + * @param data data of the event + * @return true to continue iteration + * @return false to stop iteration + */ +typedef bool (*oc_process_iterate_event_fn_t)(const struct oc_process *p, + oc_process_event_t ev, + oc_process_data_t data, + void *user_data); +/** + * @brief Iterate over all events and invoke given callback. + * + * @param fn callback invoked for each resource (cannot be NULL) + * @param fn_data custom user data passed to \p fn + * + * @note if \p fn returns false then iteration is stopped immediately and the + * remaining events are not iterated + */ +void oc_process_iterate_events(oc_process_iterate_event_fn_t fn, void *fn_data) + OC_NONNULL(1); + #ifdef OC_TEST /** @brief Get the maximal number of events */ From 3ff55e761501948d0234315673663e410017ca27 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Tue, 19 Sep 2023 09:48:58 +0200 Subject: [PATCH 08/11] Update Android compilation Fix compilation on supported Android environments. --- .github/workflows/android.yml | 15 +- api/cloud/unittest/cloud_manager_test.cpp | 2 +- api/oc_collection.c | 7 +- api/oc_core_res.c | 15 +- api/oc_discovery.c | 7 +- api/oc_endpoint.c | 3 +- api/oc_swupdate.c | 9 +- api/plgd/plgd_time.c | 14 +- apps/cloud_certification_tests.c | 4 +- messaging/coap/observe.c | 3 +- port/android/Makefile | 2 +- port/android/ifaddrs-android.c | 18 +-- port/esp32/adapter/src/ipadapter.c | 12 +- port/linux/Makefile | 2 +- port/windows/ipadapter.c | 3 +- security/oc_doxm.c | 2 +- security/oc_obt.c | 3 +- security/oc_sdi.c | 3 +- security/unittest/oscore_test.cpp | 160 +++++++++++----------- swig/java_lang/oc_iotivity_lite_jni.c | 6 +- swig/java_lang/oc_iotivity_lite_jni.h | 6 +- swig/swig_interfaces/oc_api.i | 2 +- swig/swig_interfaces/oc_collection.i | 2 +- swig/swig_interfaces/oc_rep.i | 18 +-- swig/swig_interfaces/oc_uuid.i | 4 +- tests/gtest/Device.cpp | 2 +- util/oc_compiler.h | 43 +++++- 27 files changed, 223 insertions(+), 144 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 7553253cf7..48f7129dfd 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -16,6 +16,19 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: + inputs: + ndk-version: + description: NDK version + required: false + type: choice + default: r26 + options: + - r21 + - r22 + - r23 + - r24 + - r25 + - r26 # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -57,7 +70,7 @@ jobs: - uses: nttld/setup-ndk@v1 id: setup-ndk with: - ndk-version: r25 + ndk-version: ${{ (github.event_name == 'workflow_dispatch' && inputs.ndk-version) || 'r26' }} # Runs a set of commands using the runners shell - name: build diff --git a/api/cloud/unittest/cloud_manager_test.cpp b/api/cloud/unittest/cloud_manager_test.cpp index fa1b401ee8..a608826af5 100644 --- a/api/cloud/unittest/cloud_manager_test.cpp +++ b/api/cloud/unittest/cloud_manager_test.cpp @@ -67,7 +67,7 @@ class TestCloudManager : public testing::Test { TEST_F(TestCloudManager, cloud_manager_start_initialized_without_retry_f) { - uint8_t retry_original[6] = { 0 }; + uint8_t retry_original[6]{}; size_t retry_original_size = cloud_manager_get_retry( retry_original, sizeof(retry_original) / sizeof(retry_original[0])); EXPECT_NE((size_t)-1, retry_original_size); diff --git a/api/oc_collection.c b/api/oc_collection.c index afd255b33b..81b217fdaf 100644 --- a/api/oc_collection.c +++ b/api/oc_collection.c @@ -881,9 +881,12 @@ oc_handle_collection_batch_request(oc_method_t method, oc_request_t *request, int pcode = oc_status_code(OC_STATUS_BAD_REQUEST); CborEncoder encoder; CborEncoder prev_link; - oc_request_t rest_request = { 0 }; - oc_response_t response = { 0 }; + oc_request_t rest_request; + memset(&rest_request, 0, sizeof(oc_request_t)); + oc_response_t response; + memset(&response, 0, sizeof(oc_response_t)); oc_response_buffer_t response_buffer; + memset(&response_buffer, 0, sizeof(oc_response_buffer_t)); bool method_not_found = false; bool get_delete = false; const oc_rep_t *rep = request->request_payload; diff --git a/api/oc_core_res.c b/api/oc_core_res.c index f5d3bf865e..ac94957b7a 100644 --- a/api/oc_core_res.c +++ b/api/oc_core_res.c @@ -76,12 +76,17 @@ static oc_resource_t *g_core_resources = NULL; static oc_device_info_t *g_oc_device_info = NULL; #else /* OC_DYNAMIC_ALLOCATION */ -static oc_resource_t - g_core_resources[OC_NUM_CORE_PLATFORM_RESOURCES + - (OC_NUM_CORE_LOGICAL_DEVICE_RESOURCES * OC_MAX_NUM_DEVICES)]; -static oc_device_info_t g_oc_device_info[OC_MAX_NUM_DEVICES]; +static oc_resource_t g_core_resources[OC_NUM_CORE_PLATFORM_RESOURCES + + (OC_NUM_CORE_LOGICAL_DEVICE_RESOURCES * + OC_MAX_NUM_DEVICES)] = { 0 }; +static oc_device_info_t g_oc_device_info[OC_MAX_NUM_DEVICES] = { 0 }; #endif /* !OC_DYNAMIC_ALLOCATION */ -static oc_platform_info_t g_oc_platform_info = { 0 }; +static oc_platform_info_t g_oc_platform_info = { + .pi = { { 0 } }, + .mfg_name = { 0 }, + .init_platform_cb = NULL, + .data = NULL, +}; static int g_res_latency = 0; static OC_ATOMIC_UINT32_T g_device_count = 0; diff --git a/api/oc_discovery.c b/api/oc_discovery.c index 8760384ee5..039e2300c6 100644 --- a/api/oc_discovery.c +++ b/api/oc_discovery.c @@ -748,9 +748,12 @@ process_batch_response(CborEncoder *links_array, oc_resource_t *resource, !oc_discovery_resource_is_in_batch_response(resource, endpoint, true)) { return; } - oc_request_t rest_request = { 0 }; - oc_response_t response = { 0 }; + oc_request_t rest_request; + memset(&rest_request, 0, sizeof(oc_request_t)); + oc_response_t response; + memset(&response, 0, sizeof(oc_response_t)); oc_response_buffer_t response_buffer; + memset(&response_buffer, 0, sizeof(oc_response_buffer_t)); response.response_buffer = &response_buffer; rest_request.response = &response; rest_request.origin = endpoint; diff --git a/api/oc_endpoint.c b/api/oc_endpoint.c index 7571af63f4..ea8efcc39e 100644 --- a/api/oc_endpoint.c +++ b/api/oc_endpoint.c @@ -503,7 +503,8 @@ static int oc_parse_endpoint_string(const oc_string_t *endpoint_str, oc_endpoint_t *endpoint, oc_string_t *uri) { - endpoint_uri_t ep_uri = { 0 }; + endpoint_uri_t ep_uri; + memset(&ep_uri, 0, sizeof(endpoint_uri_t)); if (!parse_endpoint_uri(endpoint_str, &ep_uri, uri != NULL)) { return -1; } diff --git a/api/oc_swupdate.c b/api/oc_swupdate.c index 0dc4ddffc2..0b9948895a 100644 --- a/api/oc_swupdate.c +++ b/api/oc_swupdate.c @@ -757,8 +757,10 @@ swupdate_decode(const oc_rep_t *rep, int flags, bool has_purl, bool oc_swupdate_decode(const oc_rep_t *rep, int flags, oc_swupdate_t *dst) { - oc_swupdate_on_error_t on_error = { NULL, NULL }; - oc_swupdate_decode_t swudecode = { 0 }; + oc_swupdate_on_error_t on_error; + memset(&on_error, 0, sizeof(on_error)); + oc_swupdate_decode_t swudecode; + memset(&swudecode, 0, sizeof(swudecode)); if (!swupdate_decode(rep, flags, oc_string(dst->purl) != NULL, on_error, &swudecode)) { return false; @@ -782,7 +784,8 @@ oc_swupdate_validate_update(size_t device, const oc_rep_t *rep, .fn = on_error, .data = on_error_data, }; - oc_swupdate_decode_t swudecode = { 0 }; + oc_swupdate_decode_t swudecode; + memset(&swudecode, 0, sizeof(swudecode)); return swupdate_decode(rep, OC_SWUPDATE_DECODE_FLAG_VALIDATE_DECODED_DATA, oc_string(g_sw[device].purl) != NULL, on_error_impl, &swudecode); diff --git a/api/plgd/plgd_time.c b/api/plgd/plgd_time.c index c2acfc353f..571f355ea4 100644 --- a/api/plgd/plgd_time.c +++ b/api/plgd/plgd_time.c @@ -83,7 +83,13 @@ OC_MEMB(g_time_verify_certificate_params_s, time_verify_certificate_params_t, #endif /* OC_CLIENT */ -static plgd_time_t g_oc_plgd_time = { 0 }; +static plgd_time_t g_oc_plgd_time = { + .store = { 0 }, + .status = 0, + .update_time = 0, + .set_system_time = NULL, + .set_system_time_data = NULL, +}; plgd_time_t * plgd_time_get(void) @@ -511,7 +517,8 @@ store_decode_plgd_time(const oc_rep_t *rep, size_t device, void *data) bool plgd_time_load(void) { - plgd_time_t pt = { 0 }; + plgd_time_t pt; + memset(&pt, 0, sizeof(pt)); if (oc_storage_data_load(PLGD_TIME_STORE_NAME, 0, store_decode_plgd_time, &pt) <= 0) { OC_DBG("failed to load plgd-time from storage"); @@ -532,7 +539,8 @@ plgd_time_resource_post(oc_request_t *request, oc_interface_mask_t iface_mask, { (void)iface_mask; (void)data; - plgd_time_t pt = { 0 }; + plgd_time_t pt; + memset(&pt, 0, sizeof(pt)); if (!plgd_time_decode(request->request_payload, &pt)) { OC_ERR("cannot decode data for plgd-time resource"); oc_send_response_with_callback(request, OC_STATUS_BAD_REQUEST, true); diff --git a/apps/cloud_certification_tests.c b/apps/cloud_certification_tests.c index 561848d4e9..d2a809727b 100644 --- a/apps/cloud_certification_tests.c +++ b/apps/cloud_certification_tests.c @@ -388,7 +388,7 @@ struct switch_t bool state; }; -static struct switch_t bswitch = { 0 }; +static struct switch_t bswitch = { false }; static void get_switch(oc_request_t *request, oc_interface_mask_t iface_mask, @@ -469,7 +469,7 @@ register_resources(void) } static oc_resource_t *reg_resource = NULL; -static struct switch_t reg_bswitch = { 0 }; +static struct switch_t reg_bswitch = { false }; static void add_resource(void) diff --git a/messaging/coap/observe.c b/messaging/coap/observe.c index 82472821c6..b97b9b8226 100644 --- a/messaging/coap/observe.c +++ b/messaging/coap/observe.c @@ -1370,7 +1370,8 @@ coap_process_discovery_batch_observers(void) oc_rep_new_v1(response_buffer.buffer, response_buffer.buffer_size); #endif /* !OC_DYNAMIC_ALLOCATION */ if (observe_batch_set_response_buffer(batch_obs, &response_buffer)) { - oc_response_t response = { 0 }; + oc_response_t response; + memset(&response, 0, sizeof(response)); response.response_buffer = &response_buffer; if (notify_batch_observer(obs, &response) < 0) { goto leave_notify_observers; diff --git a/port/android/Makefile b/port/android/Makefile index 2a44db684b..0f83d56d0f 100644 --- a/port/android/Makefile +++ b/port/android/Makefile @@ -133,7 +133,7 @@ DTLS= \ x509_csr.c platform_util.c ssl_msg.c constant_time.c \ nist_kw.c aria.c rsa_alt_helpers.c -DTLSFLAGS=-I../../deps/mbedtls/include +DTLSFLAGS=-I../../deps/mbedtls/include -Wno-error=unused CBOR=../../deps/tinycbor/src/cborencoder.c ../../deps/tinycbor/src/cborencoder_close_container_checked.c ../../deps/tinycbor/src/cborencoder_float.c ../../deps/tinycbor/src/cborparser.c ../../deps/tinycbor/src/cborparser_float.c# ../../deps/tinycbor/src/cbortojson.c ../../deps/tinycbor/src/cborpretty.c ../../deps/tinycbor/src/cborparser_dup_string.c diff --git a/port/android/ifaddrs-android.c b/port/android/ifaddrs-android.c index 569538bfd8..198608b99d 100644 --- a/port/android/ifaddrs-android.c +++ b/port/android/ifaddrs-android.c @@ -51,8 +51,6 @@ struct netlinkrequest struct ifaddrmsg msg; }; -static const int kMaxReadSize = 4096; - static int set_ifname(struct ifaddrs *ifaddr, int interface) { @@ -111,7 +109,7 @@ set_addresses(struct ifaddrs *ifaddr, struct ifaddrmsg *msg, void *data, static int make_prefixes(struct ifaddrs *ifaddr, int family, int prefixlen) { - char *prefix = NULL; + unsigned char *prefix = NULL; if (family == AF_INET) { struct sockaddr_in *mask = malloc(sizeof(struct sockaddr_in)); memset(mask, 0, sizeof(struct sockaddr_in)); @@ -121,7 +119,7 @@ make_prefixes(struct ifaddrs *ifaddr, int family, int prefixlen) if (prefixlen > 32) { prefixlen = 32; } - prefix = (char *)&mask->sin_addr; + prefix = (unsigned char *)&mask->sin_addr; } else if (family == AF_INET6) { struct sockaddr_in6 *mask = malloc(sizeof(struct sockaddr_in6)); memset(mask, 0, sizeof(struct sockaddr_in6)); @@ -131,14 +129,14 @@ make_prefixes(struct ifaddrs *ifaddr, int family, int prefixlen) if (prefixlen > 128) { prefixlen = 128; } - prefix = (char *)&mask->sin6_addr; + prefix = (unsigned char *)&mask->sin6_addr; } else { return -1; } for (int i = 0; i < (prefixlen / 8); i++) { *prefix++ = 0xFF; } - char remainder = 0xff; + unsigned char remainder = 0xFF; remainder <<= (8 - prefixlen % 8); *prefix = remainder; return 0; @@ -184,8 +182,10 @@ android_getifaddrs(struct ifaddrs **result) } struct ifaddrs *start = NULL; struct ifaddrs *current = NULL; - char buf[kMaxReadSize]; - ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0); +#define MAX_READ_SIZE (4096) + char buf[MAX_READ_SIZE] = { 0 }; +#undef MAX_READ_SIZE + ssize_t amount_read = recv(fd, &buf, OC_ARRAY_SIZE(buf), 0); while (amount_read > 0) { struct nlmsghdr *header = (struct nlmsghdr *)&buf[0]; size_t header_size = (size_t)amount_read; @@ -234,7 +234,7 @@ android_getifaddrs(struct ifaddrs **result) } } } - amount_read = recv(fd, &buf, kMaxReadSize, 0); + amount_read = recv(fd, &buf, OC_ARRAY_SIZE(buf), 0); } close(fd); android_freeifaddrs(start); diff --git a/port/esp32/adapter/src/ipadapter.c b/port/esp32/adapter/src/ipadapter.c index 60e6701813..8016bc05e0 100644 --- a/port/esp32/adapter/src/ipadapter.c +++ b/port/esp32/adapter/src/ipadapter.c @@ -239,10 +239,9 @@ get_ip_context_for_device(size_t device) static int add_mcast_sock_to_ipv4_mcast_group(int mcast_sock, const esp_ip4_addr_t *local) { - struct ip_mreq imreq = { 0 }; - int err = 0; - // Configure source interface + struct ip_mreq imreq; memset(&imreq, 0, sizeof(struct ip_mreq)); + // Configure source interface inet_addr_from_ip4addr(&imreq.imr_interface, local); imreq.imr_multiaddr.s_addr = htonl(ALL_COAP_NODES_V4); OC_DBG("Configured IPV4 Multicast address %s", @@ -253,8 +252,8 @@ add_mcast_sock_to_ipv4_mcast_group(int mcast_sock, const esp_ip4_addr_t *local) return -1; } - err = setsockopt(mcast_sock, IPPROTO_IP, IP_MULTICAST_IF, - &imreq.imr_interface, sizeof(struct in_addr)); + int err = setsockopt(mcast_sock, IPPROTO_IP, IP_MULTICAST_IF, + &imreq.imr_interface, sizeof(struct in_addr)); if (err < 0) { OC_ERR("setsockopt IP_MULTICAST_IF ret:%d", err); return -1; @@ -421,7 +420,8 @@ get_interface_addresses(ip_context_t *dev, unsigned char family, uint16_t port, { for (esp_netif_t *esp_netif = esp_netif_next(NULL); esp_netif; esp_netif = esp_netif_next(esp_netif)) { - oc_endpoint_t ep = { 0 }; + oc_endpoint_t ep; + memset(&ep, 0, sizeof(oc_endpoint_t)); int if_index = esp_netif_get_netif_impl_index(esp_netif); if (if_index < 0) { OC_ERR("esp_netif_get_netif_impl_index returns error"); diff --git a/port/linux/Makefile b/port/linux/Makefile index 5db60e42a1..24838669b2 100644 --- a/port/linux/Makefile +++ b/port/linux/Makefile @@ -96,7 +96,7 @@ DTLS= aes.c aesni.c asn1parse.c asn1write.c base64.c \ ssl_srv.c ssl_ticket.c ssl_tls.c x509write_csr.c\ x509write_crt.c x509_create.c x509_csr.c ssl_msg.c constant_time.c \ nist_kw.c aria.c rsa_alt_helpers.c -DTLSFLAGS=-I../../deps/mbedtls/include +DTLSFLAGS=-I../../deps/mbedtls/include -Wno-error=unused CBOR_DIR=../../deps/tinycbor/src CBOR=$(CBOR_DIR)/cborencoder.c $(CBOR_DIR)/cborencoder_close_container_checked.c \ diff --git a/port/windows/ipadapter.c b/port/windows/ipadapter.c index 8d30b7339e..d6a4e4f334 100644 --- a/port/windows/ipadapter.c +++ b/port/windows/ipadapter.c @@ -399,7 +399,8 @@ get_interface_addresses(ifaddr_t *ifaddr_list, ip_context_t *dev, { ifaddr_t *ifaddr; - oc_endpoint_t ep = { 0 }; + oc_endpoint_t ep; + memset(&ep, 0, sizeof(oc_endpoint_t)); if (secure) { ep.flags = SECURED; diff --git a/security/oc_doxm.c b/security/oc_doxm.c index c9d3281167..883eab4e49 100644 --- a/security/oc_doxm.c +++ b/security/oc_doxm.c @@ -57,7 +57,7 @@ #ifdef OC_DYNAMIC_ALLOCATION #include -static oc_sec_doxm_t *g_doxm; +static oc_sec_doxm_t *g_doxm = NULL; #else /* OC_DYNAMIC_ALLOCATION */ static oc_sec_doxm_t g_doxm[OC_MAX_NUM_DEVICES] = { 0 }; #endif /* !OC_DYNAMIC_ALLOCATION */ diff --git a/security/oc_obt.c b/security/oc_obt.c index 305f2c6e95..e014a501fa 100644 --- a/security/oc_obt.c +++ b/security/oc_obt.c @@ -565,7 +565,8 @@ get_endpoints(oc_client_response_t *data) return; } - oc_uuid_t di = { 0 }; + oc_uuid_t di; + memset(&di, 0, sizeof(oc_uuid_t)); // skip "ocf://" prefix oc_str_to_uuid(oc_string(*anchor) + 6, &di); const oc_uuid_t *my_uuid = oc_core_get_device_id(0); diff --git a/security/oc_sdi.c b/security/oc_sdi.c index 94ba2c9887..8898daa089 100644 --- a/security/oc_sdi.c +++ b/security/oc_sdi.c @@ -181,7 +181,8 @@ oc_sec_sdi_decode_with_state(const oc_rep_t *rep, oc_dostype_t state, { assert(sdi != NULL); - sdi_decode_data_t sdi_data = { 0 }; + sdi_decode_data_t sdi_data; + memset(&sdi_data, 0, sizeof(sdi_data)); for (; rep != NULL; rep = rep->next) { switch (rep->type) { case OC_REP_STRING: diff --git a/security/unittest/oscore_test.cpp b/security/unittest/oscore_test.cpp index 19d062e7f3..177d8f4117 100644 --- a/security/unittest/oscore_test.cpp +++ b/security/unittest/oscore_test.cpp @@ -73,7 +73,7 @@ TEST_F(TestOSCORE, ClientKDFWithSalt_P) recipient nonce: 0x4722d4dd6d944169eefb54987c (13 bytes) */ - std::array secret; + std::array secret{}; size_t secret_len = secret.size(); std::string secret_str = "0102030405060708090a0b0c0d0e0f10"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(secret_str.c_str(), @@ -82,7 +82,7 @@ TEST_F(TestOSCORE, ClientKDFWithSalt_P) 0); EXPECT_EQ(secret_len, 16); - std::array salt; + std::array salt{}; size_t salt_len = salt.size(); std::string salt_str = "9e7ca92223786340"; EXPECT_EQ(oc_conv_hex_string_to_byte_array( @@ -90,9 +90,9 @@ TEST_F(TestOSCORE, ClientKDFWithSalt_P) 0); EXPECT_EQ(salt_len, 8); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); - std::array key; + std::array key{}; EXPECT_EQ(oc_oscore_context_derive_param( nullptr, 0, nullptr, 0, "Key", secret.data(), secret_len, salt.data(), salt_len, key.data(), key.size()), @@ -113,7 +113,7 @@ TEST_F(TestOSCORE, ClientKDFWithSalt_P) 0); EXPECT_STREQ(testvec.data(), "ffb14e093c94c9cac9471648b4f98710"); - std::array iv; + std::array iv{}; EXPECT_EQ(oc_oscore_context_derive_param( nullptr, 0, nullptr, 0, "IV", secret.data(), secret_len, salt.data(), salt_len, iv.data(), iv.size()), @@ -124,8 +124,8 @@ TEST_F(TestOSCORE, ClientKDFWithSalt_P) 0); EXPECT_STREQ(testvec.data(), "4622d4dd6d944168eefb54987c"); - std::array piv = { 0 }; - std::array nonce; + std::array piv{}; + std::array nonce{}; oc_oscore_AEAD_nonce(nullptr, 0, piv.data(), piv.size(), iv.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -161,7 +161,7 @@ TEST_F(TestOSCORE, ServerKDFWithSalt_P) recipient nonce: 0x4722d4dd6d944169eefb54987c (13 bytes) */ - std::array secret; + std::array secret{}; size_t secret_len = secret.size(); std::string secret_str = "0102030405060708090a0b0c0d0e0f10"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(secret_str.c_str(), @@ -170,7 +170,7 @@ TEST_F(TestOSCORE, ServerKDFWithSalt_P) 0); EXPECT_EQ(secret_len, 16); - std::array salt; + std::array salt{}; size_t salt_len = secret.size(); std::string salt_str = "9e7ca92223786340"; EXPECT_EQ(oc_conv_hex_string_to_byte_array( @@ -178,11 +178,11 @@ TEST_F(TestOSCORE, ServerKDFWithSalt_P) 0); EXPECT_EQ(salt_len, 8); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); std::array sid = { 0x01 }; - std::array key; - std::array iv; + std::array key{}; + std::array iv{}; EXPECT_EQ(oc_oscore_context_derive_param( sid.data(), sid.size(), nullptr, 0, "Key", secret.data(), secret_len, salt.data(), salt_len, key.data(), key.size()), @@ -212,8 +212,8 @@ TEST_F(TestOSCORE, ServerKDFWithSalt_P) 0); EXPECT_STREQ(testvec.data(), "4622d4dd6d944168eefb54987c"); - std::array piv = { 0 }; - std::array nonce; + std::array piv{}; + std::array nonce{}; oc_oscore_AEAD_nonce(sid.data(), sid.size(), piv.data(), piv.size(), iv.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -249,7 +249,7 @@ TEST_F(TestOSCORE, ClientKDFWithoutSalt_P) recipient nonce: 0xbf35ae297d2dace810c52e99f9 (13 bytes) */ - std::array secret; + std::array secret{}; size_t secret_len = secret.size(); std::string secret_str = "0102030405060708090a0b0c0d0e0f10"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(secret_str.c_str(), @@ -258,10 +258,10 @@ TEST_F(TestOSCORE, ClientKDFWithoutSalt_P) 0); EXPECT_EQ(secret_len, 16); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); - std::array sid = { 0 }; - std::array key; + std::array sid{}; + std::array key{}; EXPECT_EQ(oc_oscore_context_derive_param(sid.data(), sid.size(), nullptr, 0, "Key", secret.data(), secret_len, nullptr, 0, key.data(), key.size()), @@ -282,7 +282,7 @@ TEST_F(TestOSCORE, ClientKDFWithoutSalt_P) 0); EXPECT_STREQ(testvec.data(), "e57b5635815177cd679ab4bcec9d7dda"); - std::array iv; + std::array iv{}; EXPECT_EQ(oc_oscore_context_derive_param(nullptr, 0, nullptr, 0, "IV", secret.data(), secret_len, nullptr, 0, iv.data(), iv.size()), @@ -293,8 +293,8 @@ TEST_F(TestOSCORE, ClientKDFWithoutSalt_P) 0); EXPECT_STREQ(testvec.data(), "be35ae297d2dace910c52e99f9"); - std::array piv = { 0 }; - std::array nonce; + std::array piv{}; + std::array nonce{}; oc_oscore_AEAD_nonce(sid.data(), sid.size(), piv.data(), piv.size(), iv.data(), nonce.data(), nonce.size()); @@ -330,7 +330,7 @@ TEST_F(TestOSCORE, ServerKDFWithoutSalt_P) recipient nonce: 0xbf35ae297d2dace910c52e99f9 (13 bytes) */ - std::array secret; + std::array secret{}; size_t secret_len = secret.size(); std::string secret_str = "0102030405060708090a0b0c0d0e0f10"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(secret_str.c_str(), @@ -339,10 +339,10 @@ TEST_F(TestOSCORE, ServerKDFWithoutSalt_P) 0); EXPECT_EQ(secret_len, 16); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); std::array sid = { 0x01 }; - std::array key; + std::array key{}; EXPECT_EQ(oc_oscore_context_derive_param(sid.data(), sid.size(), nullptr, 0, "Key", secret.data(), secret_len, nullptr, 0, key.data(), key.size()), @@ -352,7 +352,7 @@ TEST_F(TestOSCORE, ServerKDFWithoutSalt_P) 0); EXPECT_STREQ(testvec.data(), "e57b5635815177cd679ab4bcec9d7dda"); - std::array rid = { 0 }; + std::array rid{}; EXPECT_EQ(oc_oscore_context_derive_param(rid.data(), rid.size(), nullptr, 0, "Key", secret.data(), secret_len, nullptr, 0, key.data(), key.size()), @@ -363,7 +363,7 @@ TEST_F(TestOSCORE, ServerKDFWithoutSalt_P) 0); EXPECT_STREQ(testvec.data(), "321b26943253c7ffb6003b0b64d74041"); - std::array iv; + std::array iv{}; EXPECT_EQ(oc_oscore_context_derive_param(nullptr, 0, nullptr, 0, "IV", secret.data(), secret_len, nullptr, 0, iv.data(), iv.size()), @@ -374,8 +374,8 @@ TEST_F(TestOSCORE, ServerKDFWithoutSalt_P) 0); EXPECT_STREQ(testvec.data(), "be35ae297d2dace910c52e99f9"); - std::array piv = { 0 }; - std::array nonce; + std::array piv{}; + std::array nonce{}; oc_oscore_AEAD_nonce(sid.data(), sid.size(), piv.data(), piv.size(), iv.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -413,7 +413,7 @@ TEST_F(TestOSCORE, ClientKDFWithIDContext_P) recipient nonce: 0x2da58fb85ff1b81d0b7181b85e (13 bytes) */ - std::array secret; + std::array secret{}; size_t secret_len = secret.size(); std::string secret_str = "0102030405060708090a0b0c0d0e0f10"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(secret_str.c_str(), @@ -422,7 +422,7 @@ TEST_F(TestOSCORE, ClientKDFWithIDContext_P) 0); EXPECT_EQ(secret_len, 16); - std::array salt; + std::array salt{}; size_t salt_len = salt.size(); std::string salt_str = "9e7ca92223786340"; EXPECT_EQ(oc_conv_hex_string_to_byte_array( @@ -430,7 +430,7 @@ TEST_F(TestOSCORE, ClientKDFWithIDContext_P) 0); EXPECT_EQ(salt_len, 8); - std::array idctx; + std::array idctx{}; size_t idctx_len = idctx.size(); std::string idctx_str = "37cbf3210017a2d3"; EXPECT_EQ(oc_conv_hex_string_to_byte_array( @@ -438,12 +438,12 @@ TEST_F(TestOSCORE, ClientKDFWithIDContext_P) 0); EXPECT_EQ(idctx_len, 8); - std::array key; + std::array key{}; EXPECT_EQ(oc_oscore_context_derive_param( nullptr, 0, idctx.data(), idctx_len, "Key", secret.data(), secret_len, salt.data(), salt_len, key.data(), key.size()), 0); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); EXPECT_EQ(oc_conv_byte_array_to_hex_string(key.data(), key.size(), testvec.data(), &testvec_len), @@ -462,7 +462,7 @@ TEST_F(TestOSCORE, ClientKDFWithIDContext_P) 0); EXPECT_STREQ(testvec.data(), "e39a0c7c77b43f03b4b39ab9a268699f"); - std::array iv; + std::array iv{}; EXPECT_EQ(oc_oscore_context_derive_param( nullptr, 0, idctx.data(), idctx_len, "IV", secret.data(), secret_len, salt.data(), salt_len, iv.data(), iv.size()), @@ -473,8 +473,8 @@ TEST_F(TestOSCORE, ClientKDFWithIDContext_P) 0); EXPECT_STREQ(testvec.data(), "2ca58fb85ff1b81c0b7181b85e"); - std::array piv = { 0 }; - std::array nonce; + std::array piv{}; + std::array nonce{}; oc_oscore_AEAD_nonce(nullptr, 0, piv.data(), piv.size(), iv.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -511,7 +511,7 @@ TEST_F(TestOSCORE, ServerKDFWithIDContext_P) recipient nonce: 0x2ca58fb85ff1b81c0b7181b85e (13 bytes) */ - std::array secret; + std::array secret{}; size_t secret_len = secret.size(); std::string secret_str = "0102030405060708090a0b0c0d0e0f10"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(secret_str.c_str(), @@ -520,7 +520,7 @@ TEST_F(TestOSCORE, ServerKDFWithIDContext_P) 0); EXPECT_EQ(secret_len, 16); - std::array salt; + std::array salt{}; size_t salt_len = salt.size(); std::string salt_str = "9e7ca92223786340"; EXPECT_EQ(oc_conv_hex_string_to_byte_array( @@ -528,7 +528,7 @@ TEST_F(TestOSCORE, ServerKDFWithIDContext_P) 0); EXPECT_EQ(salt_len, 8); - std::array idctx; + std::array idctx{}; size_t idctx_len = idctx.size(); std::string idctx_str = "37cbf3210017a2d3"; EXPECT_EQ(oc_conv_hex_string_to_byte_array( @@ -536,10 +536,10 @@ TEST_F(TestOSCORE, ServerKDFWithIDContext_P) 0); EXPECT_EQ(idctx_len, 8); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); std::array sid = { 0x01 }; - std::array key; + std::array key{}; EXPECT_EQ(oc_oscore_context_derive_param(sid.data(), sid.size(), idctx.data(), idctx_len, "Key", secret.data(), secret_len, salt.data(), salt_len, @@ -560,7 +560,7 @@ TEST_F(TestOSCORE, ServerKDFWithIDContext_P) 0); EXPECT_STREQ(testvec.data(), "af2a1300a5e95788b356336eeecd2b92"); - std::array iv; + std::array iv{}; EXPECT_EQ(oc_oscore_context_derive_param( nullptr, 0, idctx.data(), idctx_len, "IV", secret.data(), secret_len, salt.data(), salt_len, iv.data(), iv.size()), @@ -571,8 +571,8 @@ TEST_F(TestOSCORE, ServerKDFWithIDContext_P) 0); EXPECT_STREQ(testvec.data(), "2ca58fb85ff1b81c0b7181b85e"); - std::array piv = { 0 }; - std::array nonce; + std::array piv{}; + std::array nonce{}; oc_oscore_AEAD_nonce(sid.data(), sid.size(), piv.data(), piv.size(), iv.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -598,7 +598,7 @@ TEST_F(TestOSCORE, ClientRequest1_P) 0x44015d1f00003974396c6f63616c686f737483747631 (22 bytes) */ - std::array buffer; + std::array buffer{}; size_t buffer_len = buffer.size(); std::string request_str = "44015d1f00003974396c6f63616c686f737483747631"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(request_str.c_str(), @@ -614,7 +614,7 @@ TEST_F(TestOSCORE, ClientRequest1_P) /* Common IV: 0x4622d4dd6d944168eefb54987c (13 bytes) */ std::string civ_str = "4622d4dd6d944168eefb54987c"; - std::array civ; + std::array civ{}; size_t civ_len = civ.size(); EXPECT_EQ(oc_conv_hex_string_to_byte_array(civ_str.c_str(), civ_str.length(), civ.data(), &civ_len), @@ -626,26 +626,26 @@ TEST_F(TestOSCORE, ClientRequest1_P) Sender Sequence Number: 20 */ std::string key_str = "f0910ed7295e6ad4b54fc793154302ff"; - std::array skey; + std::array skey{}; size_t skey_len = skey.size(); EXPECT_EQ(oc_conv_hex_string_to_byte_array(key_str.c_str(), key_str.length(), skey.data(), &skey_len), 0); uint64_t ssn = 20; - std::array piv; + std::array piv{}; uint8_t piv_len = piv.size(); oscore_store_piv(ssn, piv.data(), &piv_len); /* Verify AAD: 0x8368456e63727970743040488501810a40411440 (20 bytes) */ - std::array AAD; + std::array AAD{}; uint8_t AAD_len = AAD.size(); EXPECT_EQ(oc_oscore_compose_AAD(nullptr, 0, piv.data(), piv_len, AAD.data(), &AAD_len), 0); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); EXPECT_EQ(oc_conv_byte_array_to_hex_string(AAD.data(), AAD_len, testvec.data(), &testvec_len), @@ -665,7 +665,7 @@ TEST_F(TestOSCORE, ClientRequest1_P) EXPECT_STREQ(testvec.data(), "01b3747631"); /* Verify nonce: 0x4622d4dd6d944168eefb549868 (13 bytes) */ - std::array nonce; + std::array nonce{}; oc_oscore_AEAD_nonce(nullptr, 0, piv.data(), piv_len, civ.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -721,7 +721,7 @@ TEST_F(TestOSCORE, ClientRequest2_P) 0x440171c30000b932396c6f63616c686f737483747631 (22 bytes) */ - std::array buffer; + std::array buffer{}; size_t buffer_len = buffer.size(); std::string request_str = "440171c30000b932396c6f63616c686f737483747631"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(request_str.c_str(), @@ -736,7 +736,7 @@ TEST_F(TestOSCORE, ClientRequest2_P) /* Common IV: 0xbe35ae297d2dace910c52e99f9 (13 bytes) */ - std::array civ; + std::array civ{}; size_t civ_len = civ.size(); std::string civ_str = "be35ae297d2dace910c52e99f9"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(civ_str.c_str(), civ_str.length(), @@ -748,8 +748,8 @@ TEST_F(TestOSCORE, ClientRequest2_P) Sender Key: 0x321b26943253c7ffb6003b0b64d74041 (16 bytes) Sender Sequence Number: 20 */ - std::array sid = { 0 }; - std::array skey; + std::array sid{}; + std::array skey{}; size_t skey_len = skey.size(); std::string key_str = "321b26943253c7ffb6003b0b64d74041"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(key_str.c_str(), key_str.length(), @@ -757,19 +757,19 @@ TEST_F(TestOSCORE, ClientRequest2_P) 0); uint64_t ssn = 20; - std::array piv; + std::array piv{}; uint8_t piv_len = piv.size(); oscore_store_piv(ssn, piv.data(), &piv_len); /* Verify AAD: 0x8368456e63727970743040498501810a4100411440 (20 bytes) */ - std::array AAD; + std::array AAD{}; uint8_t AAD_len = AAD.size(); EXPECT_EQ(oc_oscore_compose_AAD(sid.data(), sid.size(), piv.data(), piv_len, AAD.data(), &AAD_len), 0); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); EXPECT_EQ(oc_conv_byte_array_to_hex_string(AAD.data(), AAD_len, testvec.data(), &testvec_len), @@ -789,7 +789,7 @@ TEST_F(TestOSCORE, ClientRequest2_P) EXPECT_STREQ(testvec.data(), "01b3747631"); /* Verify nonce: 0xbf35ae297d2dace910c52e99ed (13 bytes) */ - std::array nonce; + std::array nonce{}; oc_oscore_AEAD_nonce(sid.data(), sid.size(), piv.data(), piv_len, civ.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -845,7 +845,7 @@ TEST_F(TestOSCORE, ClientRequest3_P) 0x44012f8eef9bbf7a396c6f63616c686f737483747631 (22 bytes) */ - std::array buffer; + std::array buffer{}; size_t buffer_len = buffer.size(); std::string request_str = "44012f8eef9bbf7a396c6f63616c686f737483747631"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(request_str.c_str(), @@ -860,7 +860,7 @@ TEST_F(TestOSCORE, ClientRequest3_P) /* Common IV: 0x2ca58fb85ff1b81c0b7181b85e (13 bytes) */ - std::array civ; + std::array civ{}; size_t civ_len = civ.size(); std::string civ_str = "2ca58fb85ff1b81c0b7181b85e"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(civ_str.c_str(), civ_str.length(), @@ -873,14 +873,14 @@ TEST_F(TestOSCORE, ClientRequest3_P) Sender Key: 0xaf2a1300a5e95788b356336eeecd2b92 (16 bytes) Sender Sequence Number: 20 */ - std::array idctx; + std::array idctx{}; size_t idctx_len = idctx.size(); std::string idctx_str = "37cbf3210017a2d3"; EXPECT_EQ(oc_conv_hex_string_to_byte_array( idctx_str.c_str(), idctx_str.length(), idctx.data(), &idctx_len), 0); - std::array skey; + std::array skey{}; size_t skey_len = skey.size(); std::string key_str = "af2a1300a5e95788b356336eeecd2b92"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(key_str.c_str(), key_str.length(), @@ -888,19 +888,19 @@ TEST_F(TestOSCORE, ClientRequest3_P) 0); uint64_t ssn = 20; - std::array piv; + std::array piv{}; uint8_t piv_len = piv.size(); oscore_store_piv(ssn, piv.data(), &piv_len); /* Verify AAD: 0x8368456e63727970743040488501810a40411440 (20 bytes) */ - std::array AAD; + std::array AAD{}; uint8_t AAD_len = AAD.size(); EXPECT_EQ(oc_oscore_compose_AAD(nullptr, 0, piv.data(), piv_len, AAD.data(), &AAD_len), 0); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); EXPECT_EQ(oc_conv_byte_array_to_hex_string(AAD.data(), AAD_len, testvec.data(), &testvec_len), @@ -920,7 +920,7 @@ TEST_F(TestOSCORE, ClientRequest3_P) EXPECT_STREQ(testvec.data(), "01b3747631"); /* Verify nonce: 0x2ca58fb85ff1b81c0b7181b84a (13 bytes) */ - std::array nonce; + std::array nonce{}; oc_oscore_AEAD_nonce(nullptr, 0, piv.data(), piv_len, civ.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -977,7 +977,7 @@ TEST_F(TestOSCORE, ServerResponse1_P) 0x64455d1f00003974ff48656c6c6f20576f726c6421 (21 bytes) */ - std::array buffer; + std::array buffer{}; size_t buffer_len = buffer.size(); std::string response_str = "64455d1f00003974ff48656c6c6f20576f726c6421"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(response_str.c_str(), @@ -992,7 +992,7 @@ TEST_F(TestOSCORE, ServerResponse1_P) /* Common IV: 0x4622d4dd6d944168eefb54987c (13 bytes) */ - std::array civ; + std::array civ{}; size_t civ_len = civ.size(); std::string civ_str = "4622d4dd6d944168eefb54987c"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(civ_str.c_str(), civ_str.length(), @@ -1004,7 +1004,7 @@ TEST_F(TestOSCORE, ServerResponse1_P) Sender Key: 0xffb14e093c94c9cac9471648b4f98710 (16 bytes) Sender Sequence Number: 0 */ - std::array skey; + std::array skey{}; size_t skey_len = skey.size(); std::string key_str = "ffb14e093c94c9cac9471648b4f98710"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(key_str.c_str(), key_str.length(), @@ -1015,13 +1015,13 @@ TEST_F(TestOSCORE, ServerResponse1_P) std::array request_piv = { 0x14 }; /* Verify AAD: 0x8368456e63727970743040488501810a40411440 (20 bytes) */ - std::array AAD; + std::array AAD{}; uint8_t AAD_len = AAD.size(); EXPECT_EQ(oc_oscore_compose_AAD(nullptr, 0, request_piv.data(), request_piv.size(), AAD.data(), &AAD_len), 0); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); EXPECT_EQ(oc_conv_byte_array_to_hex_string(AAD.data(), AAD_len, testvec.data(), &testvec_len), @@ -1042,7 +1042,7 @@ TEST_F(TestOSCORE, ServerResponse1_P) /* Verify nonce: 0x4622d4dd6d944168eefb549868 (13 bytes) */ /* Using nonce from request in test vector C.4 */ - std::array nonce; + std::array nonce{}; oc_oscore_AEAD_nonce(nullptr, 0, request_piv.data(), request_piv.size(), civ.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); @@ -1100,7 +1100,7 @@ TEST_F(TestOSCORE, ServerResponse2_P) 0x64455d1f00003974ff48656c6c6f20576f726c6421 (21 bytes) */ - std::array buffer; + std::array buffer{}; size_t buffer_len = buffer.size(); std::string response_str = "64455d1f00003974ff48656c6c6f20576f726c6421"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(response_str.c_str(), @@ -1115,7 +1115,7 @@ TEST_F(TestOSCORE, ServerResponse2_P) /* Common IV: 0x4622d4dd6d944168eefb54987c (13 bytes) */ - std::array civ; + std::array civ{}; size_t civ_len = civ.size(); std::string civ_str = "4622d4dd6d944168eefb54987c"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(civ_str.c_str(), civ_str.length(), @@ -1125,7 +1125,7 @@ TEST_F(TestOSCORE, ServerResponse2_P) /* Sender Key: 0xffb14e093c94c9cac9471648b4f98710 (16 bytes) */ - std::array skey; + std::array skey{}; size_t skey_len = skey.size(); std::string key_str = "ffb14e093c94c9cac9471648b4f98710"; EXPECT_EQ(oc_conv_hex_string_to_byte_array(key_str.c_str(), key_str.length(), @@ -1135,13 +1135,13 @@ TEST_F(TestOSCORE, ServerResponse2_P) /* Using request_piv & request_kid from test vetor in C.4 */ std::array request_piv = { 0x14 }; /* Verify AAD: 0x8368456e63727970743040488501810a40411440 (20 bytes) */ - std::array AAD; + std::array AAD{}; uint8_t AAD_len = AAD.size(); EXPECT_EQ(oc_oscore_compose_AAD(nullptr, 0, request_piv.data(), request_piv.size(), AAD.data(), &AAD_len), 0); - std::array testvec; + std::array testvec{}; size_t testvec_len = testvec.size(); EXPECT_EQ(oc_conv_byte_array_to_hex_string(AAD.data(), AAD_len, testvec.data(), &testvec_len), @@ -1165,9 +1165,9 @@ TEST_F(TestOSCORE, ServerResponse2_P) Sender Sequence Number: 0 */ std::array sid = { 0x01 }; - std::array piv = { 0 }; + std::array piv{}; /* Verify nonce: 0x4722d4dd6d944169eefb54987c (13 bytes) */ - std::array nonce; + std::array nonce{}; oc_oscore_AEAD_nonce(sid.data(), sid.size(), piv.data(), piv.size(), civ.data(), nonce.data(), nonce.size()); testvec_len = testvec.size(); diff --git a/swig/java_lang/oc_iotivity_lite_jni.c b/swig/java_lang/oc_iotivity_lite_jni.c index 0ab9b0ddc0..ab072ce542 100644 --- a/swig/java_lang/oc_iotivity_lite_jni.c +++ b/swig/java_lang/oc_iotivity_lite_jni.c @@ -413,7 +413,7 @@ JNI_OnLoad(JavaVM *vm, void *reserved) } JavaVM * -get_jvm() +get_jvm(void) { return jvm; } @@ -428,7 +428,7 @@ get_jvm() OC_LIST(jni_callbacks); jni_callback_data * -jni_list_get_head() +jni_list_get_head(void) { return (jni_callback_data *)oc_list_head(jni_callbacks); } @@ -459,7 +459,7 @@ jni_list_remove(jni_callback_data *item) } void -jni_list_clear() +jni_list_clear(void) { OC_DBG("JNI: - lock %s\n", __func__); jni_mutex_lock(jni_sync_lock); diff --git a/swig/java_lang/oc_iotivity_lite_jni.h b/swig/java_lang/oc_iotivity_lite_jni.h index 66dc089823..06deb85b86 100644 --- a/swig/java_lang/oc_iotivity_lite_jni.h +++ b/swig/java_lang/oc_iotivity_lite_jni.h @@ -182,15 +182,15 @@ typedef struct jni_callback_data_s jni_callback_valid_t cb_valid; } jni_callback_data; -jni_callback_data *jni_list_get_head(); +jni_callback_data *jni_list_get_head(void); void jni_list_add(jni_callback_data *item); void jni_list_remove(jni_callback_data *item); -void jni_list_clear(); +void jni_list_clear(void); jni_callback_data *jni_list_get_item_by_java_callback(jobject callback); jni_callback_data *jni_list_get_item_by_callback_valid( jni_callback_valid_t cb_valid); -JavaVM *get_jvm(); +JavaVM *get_jvm(void); JNIEnv *get_jni_env(jint *getEnvResult); diff --git a/swig/swig_interfaces/oc_api.i b/swig/swig_interfaces/oc_api.i index 489134f3ab..a0de7a9946 100644 --- a/swig/swig_interfaces/oc_api.i +++ b/swig/swig_interfaces/oc_api.i @@ -531,7 +531,7 @@ void jni_set_random_pin_callback(oc_random_pin_cb_t cb, jni_callback_data *jcb) %ignore oc_reset; %rename(reset) jni_reset; %inline %{ -void jni_reset() { +void jni_reset(void) { OC_DBG("JNI: %s\n", __func__); #ifdef OC_SECURITY oc_reset(); diff --git a/swig/swig_interfaces/oc_collection.i b/swig/swig_interfaces/oc_collection.i index 784e963ff7..a267b7aab5 100644 --- a/swig/swig_interfaces/oc_collection.i +++ b/swig/swig_interfaces/oc_collection.i @@ -238,7 +238,7 @@ typedef struct oc_collection_s oc_collection_t; %rename(addCollection) oc_add_collection; // DOCUMENTATION workaround -%javamethodmodifiers oc_add_collection "/** +%javamethodmodifiers oc_add_collection_v1 "/** * Adds a collection to the list of collections. *

* If the caller makes the collection discoverable, then it will diff --git a/swig/swig_interfaces/oc_rep.i b/swig/swig_interfaces/oc_rep.i index 1b0b3fee0c..9747418bcc 100644 --- a/swig/swig_interfaces/oc_rep.i +++ b/swig/swig_interfaces/oc_rep.i @@ -93,7 +93,7 @@ uint8_t *g_new_rep_buffer = NULL; struct oc_memb g_rep_objects; %} %inline %{ -void deleteBuffer() { +void deleteBuffer(void) { free(g_new_rep_buffer); g_new_rep_buffer = NULL; } @@ -345,7 +345,7 @@ void jni_rep_end_array(CborEncoder *parent, CborEncoder *arrayObject) { %rename (beginLinksArray) jni_rep_start_links_array; %inline %{ /* Alt implementation of oc_rep_start_links_array macro */ -CborEncoder * jni_rep_start_links_array() { +CborEncoder * jni_rep_start_links_array(void) { OC_DBG("JNI: %s\n", __func__); oc_rep_encoder_create_array(oc_rep_get_encoder(), &links_array, CborIndefiniteLength); return &links_array; @@ -355,7 +355,7 @@ CborEncoder * jni_rep_start_links_array() { %rename (endLinksArray) jni_rep_end_links_array; %inline %{ /* Alt implementation of oc_rep_end_links_array macro */ -void jni_rep_end_links_array() { +void jni_rep_end_links_array(void) { OC_DBG("JNI: %s\n", __func__); oc_rep_end_links_array(); } @@ -373,7 +373,7 @@ void jni_rep_end_links_array() { %rename(beginRootObject) jni_begin_root_object; %inline %{ /* Alt implementation of oc_rep_start_root_object macro */ -CborEncoder * jni_begin_root_object() { +CborEncoder * jni_begin_root_object(void) { OC_DBG("JNI: %s\n", __func__); g_err |= oc_rep_encoder_create_map(oc_rep_get_encoder(), &root_map, CborIndefiniteLength); return &root_map; @@ -390,7 +390,7 @@ CborEncoder * jni_begin_root_object() { public"; %rename(endRootObject) jni_rep_end_root_object; %inline %{ -void jni_rep_end_root_object() { +void jni_rep_end_root_object(void) { OC_DBG("JNI: %s\n", __func__); oc_rep_end_root_object(); } @@ -1083,7 +1083,7 @@ void jni_rep_rep_set_string_array(CborEncoder *object, const char* key, oc_strin * to enable encode/decode unit testing. This function is not expected to be used in typical * use case. It should only be called after calling oc_rep_end_root_object. */ -oc_rep_t * jni_rep_get_rep_from_root_object() { +oc_rep_t * jni_rep_get_rep_from_root_object(void) { oc_rep_t * rep = (oc_rep_t *)malloc(sizeof(oc_rep_t)); const uint8_t *payload = oc_rep_get_encoder_buf(); int payload_len = oc_rep_get_encoded_payload_size(); @@ -1112,7 +1112,7 @@ oc_rep_t * jni_rep_get_rep_from_root_object() { %ignore oc_rep_get_cbor_errno; %rename(getCborErrno) jni_rep_get_cbor_errno; %inline %{ -int jni_rep_get_cbor_errno() { +int jni_rep_get_cbor_errno(void) { return (int)oc_rep_get_cbor_errno(); } %} @@ -1126,7 +1126,7 @@ int jni_rep_get_cbor_errno() { */ public"; %inline %{ -void clearCborErrno() { +void clearCborErrno(void) { g_err = CborNoError; } %} @@ -1872,4 +1872,4 @@ char *jni_rep_to_json(oc_rep_t *rep, bool prettyPrint) #define OC_NONNULL(...) #define OC_RETURNS_NONNULL %include "oc_rep.h" -/*******************End oc_rep.h****************************/ \ No newline at end of file +/*******************End oc_rep.h****************************/ diff --git a/swig/swig_interfaces/oc_uuid.i b/swig/swig_interfaces/oc_uuid.i index b3d9006e0c..7aff761c2f 100644 --- a/swig/swig_interfaces/oc_uuid.i +++ b/swig/swig_interfaces/oc_uuid.i @@ -92,7 +92,7 @@ char * jni_uuid_to_str(const oc_uuid_t *uuid) %rename(generateUuid) jni_gen_uuid; %newobject jni_gen_uuid; %inline %{ -oc_uuid_t * jni_gen_uuid() +oc_uuid_t * jni_gen_uuid(void) { oc_uuid_t *value = (oc_uuid_t *)malloc(sizeof(oc_uuid_t)); oc_gen_uuid(value); @@ -102,4 +102,4 @@ oc_uuid_t * jni_gen_uuid() #define OC_API #define OC_NONNULL(...) -%include oc_uuid.h \ No newline at end of file +%include oc_uuid.h diff --git a/tests/gtest/Device.cpp b/tests/gtest/Device.cpp index 7f07746ace..c4607884d9 100644 --- a/tests/gtest/Device.cpp +++ b/tests/gtest/Device.cpp @@ -470,7 +470,7 @@ TestDevice::SetSystemTime(oc_clock_time_t time, void *user_data) auto *v = static_cast(user_data); *v = time; - std::array ts = { 0 }; + std::array ts{}; oc_clock_encode_time_rfc3339(time, ts.data(), ts.size()); OC_DBG("set system_time: %s", ts.data()); return 0; diff --git a/util/oc_compiler.h b/util/oc_compiler.h index c8c7ed6bac..ab72312f5d 100644 --- a/util/oc_compiler.h +++ b/util/oc_compiler.h @@ -31,6 +31,26 @@ #error "Unsupported compiler on MinGW platform" #endif /* __MINGW32__ && (!__GNUC__ || __GNUC__ < 9) */ +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif /* !__has_attribute */ + +#ifndef __has_c_attribute +#define __has_c_attribute(x) 0 +#endif /* !__has_c_attribute */ + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif /* !__has_feature */ + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 6)) +#define OC_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg) +#elif __has_feature(c_static_assert) +#define OC_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg) +#else +#define OC_STATIC_ASSERT(...) +#endif + #if defined(__clang__) || defined(__GNUC__) #define OC_NO_DISCARD_RETURN __attribute__((warn_unused_result)) #else @@ -43,10 +63,13 @@ #define OC_NO_RETURN #endif -#if defined(__clang__) || defined(__GNUC__) +#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 7) || \ + (defined(__clang__) && __clang_major__ >= 10) #define OC_FALLTHROUGH __attribute__((fallthrough)) +#elif __has_c_attribute(fallthrough) +#define OC_FALLTHROUGH [[fallthrough]] #else -#define OC_FALLTHROUGH +#define OC_FALLTHROUGH /* FALLTHROUGH */ #endif #if defined(__clang__) || defined(__GNUC__) @@ -84,4 +107,20 @@ #define OC_PRINTF_FORMAT(...) #endif +#if defined(__GNUC__) && __GNUC__ >= 8 && !defined(__clang__) +#define OC_NONSTRING __attribute__((nonstring)) +#else +#define OC_NONSTRING +#endif + +/* GCC: check for __SANITIZE_ADDRESS__; clang: use __has_feature */ +#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) +#define OC_SANITIZE_ADDRESS +#endif + +/* GCC: check for __SANITIZE_THREAD__; clang: use __has_feature */ +#if defined(__SANITIZE_THREAD__) || __has_feature(thread_sanitizer) +#define OC_SANITIZE_THREAD +#endif + #endif // OC_COMPILER_H From 43443b64ca6faebaeaa7609674665dcec102fb6a Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Mon, 24 Jul 2023 10:58:24 +0200 Subject: [PATCH 09/11] obt: handle possible GET/POST/DELETE request failures --- security/oc_obt.c | 819 +++++++++++++++++++++++++--------------------- 1 file changed, 438 insertions(+), 381 deletions(-) diff --git a/security/oc_obt.c b/security/oc_obt.c index e014a501fa..e09d10c49c 100644 --- a/security/oc_obt.c +++ b/security/oc_obt.c @@ -45,6 +45,7 @@ check oc_config.h and make sure OC_STORAGE is defined if OC_SECURITY is defined. #include "security/oc_sdi_internal.h" #include "security/oc_tls_internal.h" #include "util/oc_macros_internal.h" +#include "util/oc_secure_string_internal.h" #include #include @@ -651,7 +652,7 @@ obt_check_owned(oc_client_response_t *data) device->ctx = data->user_data; if (!oc_do_get("/oic/res", device->endpoint, "rt=oic.r.doxm", &get_endpoints, HIGH_QOS, device)) { - OC_ERR("Could not send GET request to retrieve endpoints"); + OC_ERR("Could not send GET request to /oic/res"); } } @@ -860,19 +861,25 @@ switch_dos(oc_device_t *device, oc_dostype_t dos, oc_obt_status_cb_t cb, d->cb.cb = cb; d->cb.data = data; - if (oc_init_post("/oic/sec/pstat", ep, NULL, &pstat_POST_dos1_to_dos2, - HIGH_QOS, d)) { - oc_rep_start_root_object(); - oc_rep_set_object(root, dos); - oc_rep_set_int(dos, s, dos); - oc_rep_close_object(root, dos); - oc_rep_end_root_object(); - if (oc_do_post()) { - oc_list_add(oc_switch_dos_ctx_l, d); - return d; - } + if (!oc_init_post("/oic/sec/pstat", ep, NULL, &pstat_POST_dos1_to_dos2, + HIGH_QOS, d)) { + OC_ERR("Could not init POST request to /oic/sec/pstat"); + goto err_switch_dos; + } + oc_rep_start_root_object(); + oc_rep_set_object(root, dos); + oc_rep_set_int(dos, s, dos); + oc_rep_close_object(root, dos); + oc_rep_end_root_object(); + if (!oc_do_post()) { + OC_ERR("Could not do POST request to /oic/sec/pstat"); + goto err_switch_dos; } + oc_list_add(oc_switch_dos_ctx_l, d); + return d; + +err_switch_dos: oc_memb_free(&oc_switch_dos_ctx_m, d); return NULL; } @@ -1046,7 +1053,7 @@ device1oscore_cred(oc_client_response_t *data) oc_oscoreprov_ctx_t *p = (oc_oscoreprov_ctx_t *)data->user_data; if (data->code >= OC_STATUS_BAD_REQUEST) { - goto error; + goto err_device1oscore_cred; } char d1uuid[OC_UUID_LEN]; oc_uuid_to_str(&p->device1->uuid, d1uuid, OC_UUID_LEN); @@ -1054,7 +1061,8 @@ device1oscore_cred(oc_client_response_t *data) const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device2->endpoint); if (!oc_init_post("/oic/sec/cred", ep, NULL, &device2oscore_cred, HIGH_QOS, p)) { - goto error; + OC_ERR("Could not init POST request to /oic/sec/cred"); + goto err_device1oscore_cred; } oc_rep_start_root_object(); @@ -1091,12 +1099,13 @@ device1oscore_cred(oc_client_response_t *data) oc_rep_end_root_object(); if (!oc_do_post()) { - goto error; + OC_ERR("Could not do POST request to /oic/sec/cred"); + goto err_device1oscore_cred; } return; -error: +err_device1oscore_cred: free_oscoreprov_ctx(p, -1); } @@ -1111,7 +1120,7 @@ device2oscore_RFPRO(int status, void *data) p->switch_dos = NULL; if (status < 0) { - goto error; + goto err_device2oscore_RFPRO; } gen_oscore_ctxid(p->sendid, false); @@ -1123,7 +1132,8 @@ device2oscore_RFPRO(int status, void *data) const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); if (!oc_init_post("/oic/sec/cred", ep, NULL, &device1oscore_cred, HIGH_QOS, p)) { - goto error; + OC_ERR("Could not init POST request to /oic/sec/cred"); + goto err_device2oscore_RFPRO; } oc_rep_start_root_object(); @@ -1160,12 +1170,13 @@ device2oscore_RFPRO(int status, void *data) oc_rep_end_root_object(); if (!oc_do_post()) { - goto error; + OC_ERR("Could not do POST request to /oic/sec/cred"); + goto err_device2oscore_RFPRO; } return; -error: +err_device2oscore_RFPRO: free_oscoreprov_state(p, -1); } @@ -1298,7 +1309,7 @@ deviceoscoregroup_RFPRO(int status, void *data) p->switch_dos = NULL; if (status < 0) { - goto error; + goto err_deviceoscoregroup_RFPRO; } char groupsub[OC_UUID_LEN]; @@ -1306,7 +1317,8 @@ deviceoscoregroup_RFPRO(int status, void *data) const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device->endpoint); if (!oc_init_post("/oic/sec/cred", ep, NULL, &deviceoscoregroup_cred, HIGH_QOS, p)) { - goto error; + OC_ERR("Could not init POST request to /oic/sec/cred"); + goto err_deviceoscoregroup_RFPRO; } oc_rep_start_root_object(); oc_rep_set_array(root, creds); @@ -1341,12 +1353,13 @@ deviceoscoregroup_RFPRO(int status, void *data) oc_rep_end_root_object(); if (!oc_do_post()) { - goto error; + OC_ERR("Could not do POST request to /oic/sec/cred"); + goto err_deviceoscoregroup_RFPRO; } return; -error: +err_deviceoscoregroup_RFPRO: free_oscoregroupprov_state(p, -1); } @@ -1499,16 +1512,19 @@ device2_cred(oc_client_response_t *data) } oc_credprov_ctx_t *p = (oc_credprov_ctx_t *)data->user_data; - if (data->code >= OC_STATUS_BAD_REQUEST) { - free_credprov_ctx(p, -1); - return; + goto err_device2_cred; } p->switch_dos = switch_dos(p->device1, OC_DOS_RFNOP, device1_RFNOP, p); if (!p->switch_dos) { - free_credprov_ctx(p, -1); + goto err_device2_cred; } + + return; + +err_device2_cred: + free_credprov_ctx(p, -1); } static void @@ -1521,8 +1537,7 @@ device1_cred(oc_client_response_t *data) oc_credprov_ctx_t *p = (oc_credprov_ctx_t *)data->user_data; if (data->code >= OC_STATUS_BAD_REQUEST) { - free_credprov_ctx(p, -1); - return; + goto err_device1_cred; } char d1uuid[OC_UUID_LEN]; @@ -1530,28 +1545,34 @@ device1_cred(oc_client_response_t *data) const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device2->endpoint); - if (oc_init_post("/oic/sec/cred", ep, NULL, &device2_cred, HIGH_QOS, p)) { - oc_rep_start_root_object(); - oc_rep_set_array(root, creds); - oc_rep_object_array_start_item(creds); + if (!oc_init_post("/oic/sec/cred", ep, NULL, &device2_cred, HIGH_QOS, p)) { + OC_ERR("Could not init POST request to /oic/sec/cred"); + goto err_device1_cred; + } + oc_rep_start_root_object(); + oc_rep_set_array(root, creds); + oc_rep_object_array_start_item(creds); - oc_rep_set_int(creds, credtype, 1); - oc_rep_set_text_string(creds, subjectuuid, d1uuid); + oc_rep_set_int(creds, credtype, 1); + oc_rep_set_text_string(creds, subjectuuid, d1uuid); - oc_rep_set_object(creds, privatedata); - oc_rep_set_byte_string(privatedata, data, p->key, OC_ARRAY_SIZE(p->key)); - oc_rep_set_text_string_v1(privatedata, encoding, OC_ENCODING_RAW_STR, - OC_CHAR_ARRAY_LEN(OC_ENCODING_RAW_STR)); - oc_rep_close_object(creds, privatedata); + oc_rep_set_object(creds, privatedata); + oc_rep_set_byte_string(privatedata, data, p->key, OC_ARRAY_SIZE(p->key)); + oc_rep_set_text_string_v1(privatedata, encoding, OC_ENCODING_RAW_STR, + OC_CHAR_ARRAY_LEN(OC_ENCODING_RAW_STR)); + oc_rep_close_object(creds, privatedata); - oc_rep_object_array_end_item(creds); - oc_rep_close_array(root, creds); - oc_rep_end_root_object(); - if (oc_do_post()) { - return; - } + oc_rep_object_array_end_item(creds); + oc_rep_close_array(root, creds); + oc_rep_end_root_object(); + if (!oc_do_post()) { + OC_ERR("Could not do POST request to /oic/sec/cred"); + goto err_device1_cred; } + return; + +err_device1_cred: free_credprov_ctx(p, -1); } @@ -1565,37 +1586,46 @@ device2_RFPRO(int status, void *data) oc_credprov_ctx_t *p = (oc_credprov_ctx_t *)data; p->switch_dos = NULL; - if (status >= 0) { - oc_random_buffer(p->key, OC_ARRAY_SIZE(p->key)); + if (status < 0) { + OC_DBG("Could not switch device2 to RFPRO"); + goto err_device2_RFPRO; + } + oc_random_buffer(p->key, OC_ARRAY_SIZE(p->key)); - char d2uuid[OC_UUID_LEN]; - oc_uuid_to_str(&p->device2->uuid, d2uuid, OC_UUID_LEN); + char d2uuid[OC_UUID_LEN]; + oc_uuid_to_str(&p->device2->uuid, d2uuid, OC_UUID_LEN); - const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); + const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); - if (oc_init_post("/oic/sec/cred", ep, NULL, &device1_cred, HIGH_QOS, p)) { - oc_rep_start_root_object(); - oc_rep_set_array(root, creds); - oc_rep_object_array_start_item(creds); + if (!oc_init_post("/oic/sec/cred", ep, NULL, &device1_cred, HIGH_QOS, p)) { + OC_ERR("Could not init POST request to /oic/sec/cred"); + goto err_device2_RFPRO; + } + oc_rep_start_root_object(); + oc_rep_set_array(root, creds); + oc_rep_object_array_start_item(creds); - oc_rep_set_int(creds, credtype, 1); - oc_rep_set_text_string(creds, subjectuuid, d2uuid); + oc_rep_set_int(creds, credtype, 1); + oc_rep_set_text_string_v1(creds, subjectuuid, d2uuid, + oc_strnlen(d2uuid, OC_UUID_LEN)); - oc_rep_set_object(creds, privatedata); - oc_rep_set_byte_string(privatedata, data, p->key, OC_ARRAY_SIZE(p->key)); - oc_rep_set_text_string_v1(privatedata, encoding, OC_ENCODING_RAW_STR, - OC_CHAR_ARRAY_LEN(OC_ENCODING_RAW_STR)); - oc_rep_close_object(creds, privatedata); + oc_rep_set_object(creds, privatedata); + oc_rep_set_byte_string(privatedata, data, p->key, OC_ARRAY_SIZE(p->key)); + oc_rep_set_text_string_v1(privatedata, encoding, OC_ENCODING_RAW_STR, + OC_CHAR_ARRAY_LEN(OC_ENCODING_RAW_STR)); + oc_rep_close_object(creds, privatedata); - oc_rep_object_array_end_item(creds); - oc_rep_close_array(root, creds); - oc_rep_end_root_object(); - if (oc_do_post()) { - return; - } - } + oc_rep_object_array_end_item(creds); + oc_rep_close_array(root, creds); + oc_rep_end_root_object(); + if (!oc_do_post()) { + OC_ERR("Could not do POST request to /oic/sec/cred"); + goto err_device2_RFPRO; } + return; + +err_device2_RFPRO: free_credprov_state(p, -1); } @@ -1770,37 +1800,42 @@ device_cred(oc_client_response_t *data) /** 6) post acl2 with auth-crypt RW ACE for /oic/sec/roles */ const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); - if (oc_init_post("/oic/sec/acl2", ep, NULL, &device_authcrypt_roles, HIGH_QOS, - p)) { - oc_rep_start_root_object(); + if (!oc_init_post("/oic/sec/acl2", ep, NULL, &device_authcrypt_roles, + HIGH_QOS, p)) { + OC_ERR("Could not init POST request to /oic/sec/acl2"); + goto err_device_cred; + } + oc_rep_start_root_object(); - oc_rep_set_array(root, aclist2); - oc_rep_object_array_start_item(aclist2); + oc_rep_set_array(root, aclist2); + oc_rep_object_array_start_item(aclist2); - oc_rep_set_object(aclist2, subject); - oc_rep_set_text_string_v1(subject, conntype, "auth-crypt", - OC_CHAR_ARRAY_LEN("auth-crypt")); - oc_rep_close_object(aclist2, subject); + oc_rep_set_object(aclist2, subject); + oc_rep_set_text_string_v1(subject, conntype, "auth-crypt", + OC_CHAR_ARRAY_LEN("auth-crypt")); + oc_rep_close_object(aclist2, subject); - oc_rep_set_array(aclist2, resources); - oc_rep_object_array_start_item(resources); - oc_rep_set_text_string_v1(resources, href, OCF_SEC_ROLES_URI, - OC_CHAR_ARRAY_LEN(OCF_SEC_ROLES_URI)); - oc_rep_object_array_end_item(resources); - oc_rep_close_array(aclist2, resources); + oc_rep_set_array(aclist2, resources); + oc_rep_object_array_start_item(resources); + oc_rep_set_text_string_v1(resources, href, OCF_SEC_ROLES_URI, + OC_CHAR_ARRAY_LEN(OCF_SEC_ROLES_URI)); + oc_rep_object_array_end_item(resources); + oc_rep_close_array(aclist2, resources); - oc_rep_set_uint(aclist2, permission, OC_PERM_RETRIEVE | OC_PERM_UPDATE); + oc_rep_set_uint(aclist2, permission, OC_PERM_RETRIEVE | OC_PERM_UPDATE); - oc_rep_object_array_end_item(aclist2); - oc_rep_close_array(root, aclist2); + oc_rep_object_array_end_item(aclist2); + oc_rep_close_array(root, aclist2); - oc_rep_end_root_object(); + oc_rep_end_root_object(); - if (oc_do_post()) { - return; - } + if (!oc_do_post()) { + OC_ERR("Could not do POST request to /oic/sec/acl2"); + goto err_device_cred; } + return; + err_device_cred: free_credprov_ctx(p, -1); } @@ -1922,6 +1957,7 @@ device_CSR(oc_client_response_t *data) const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); if (!oc_init_post("/oic/sec/cred", ep, NULL, &device_cred, HIGH_QOS, p)) { + OC_ERR("Could not init POST request to /oic/sec/cred"); goto err_device_CSR; } oc_rep_start_root_object(); @@ -1947,10 +1983,13 @@ device_CSR(oc_client_response_t *data) oc_rep_object_array_end_item(creds); oc_rep_close_array(root, creds); oc_rep_end_root_object(); - if (oc_do_post()) { - return; + if (!oc_do_post()) { + OC_ERR("Could not do POST request to /oic/sec/cred"); + goto err_device_CSR; } + return; + err_device_CSR: free_credprov_state(p, -1); } @@ -1971,10 +2010,13 @@ device_root(oc_client_response_t *data) /** 4) get csr */ const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); - if (oc_do_get(OCF_SEC_CSR_URI, ep, NULL, &device_CSR, HIGH_QOS, p)) { - return; + if (!oc_do_get(OCF_SEC_CSR_URI, ep, NULL, &device_CSR, HIGH_QOS, p)) { + OC_ERR("Could not issue GET request to /oic/sec/csr"); + goto err_device_root; } + return; + err_device_root: free_credprov_ctx(p, -1); } @@ -1989,45 +2031,50 @@ device_RFPRO(int status, void *data) oc_credprov_ctx_t *p = (oc_credprov_ctx_t *)data; p->switch_dos = NULL; - if (status >= 0) { - const oc_sec_cred_t *root = - oc_sec_get_cred_by_credid(g_root_cert_credid, 0); - if (!root) { - goto err_device_RFPRO; - } + if (status < 0) { + OC_DBG("Could not switch device to RFPRO"); + goto err_device_RFPRO; + } + const oc_sec_cred_t *root = oc_sec_get_cred_by_credid(g_root_cert_credid, 0); + if (!root) { + OC_ERR("Could not get root cert"); + goto err_device_RFPRO; + } - /** 3) post cred with trustca - */ - const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); - if (oc_init_post("/oic/sec/cred", ep, NULL, &device_root, HIGH_QOS, p)) { - oc_rep_start_root_object(); - oc_rep_set_array(root, creds); - oc_rep_object_array_start_item(creds); - - oc_rep_set_int(creds, credtype, OC_CREDTYPE_CERT); - oc_rep_set_text_string_v1(creds, subjectuuid, "*", - OC_CHAR_ARRAY_LEN("*")); - - oc_rep_set_object(creds, publicdata); - oc_rep_set_text_string_v1(publicdata, data, - oc_string(root->publicdata.data), - oc_string_len(root->publicdata.data)); - oc_rep_set_text_string_v1(publicdata, encoding, OC_ENCODING_PEM_STR, - OC_CHAR_ARRAY_LEN(OC_ENCODING_PEM_STR)); - oc_rep_close_object(creds, publicdata); - - oc_rep_set_text_string_v1(creds, credusage, OC_CREDUSAGE_TRUSTCA_STR, - OC_CHAR_ARRAY_LEN(OC_CREDUSAGE_TRUSTCA_STR)); - - oc_rep_object_array_end_item(creds); - oc_rep_close_array(root, creds); - oc_rep_end_root_object(); - if (oc_do_post()) { - return; - } - } + /** 3) post cred with trustca + */ + const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); + if (!oc_init_post("/oic/sec/cred", ep, NULL, &device_root, HIGH_QOS, p)) { + OC_ERR("Could not init POST request to /oic/sec/cred"); + goto err_device_RFPRO; + } + oc_rep_start_root_object(); + oc_rep_set_array(root, creds); + oc_rep_object_array_start_item(creds); + + oc_rep_set_int(creds, credtype, OC_CREDTYPE_CERT); + oc_rep_set_text_string_v1(creds, subjectuuid, "*", OC_CHAR_ARRAY_LEN("*")); + + oc_rep_set_object(creds, publicdata); + oc_rep_set_text_string_v1(publicdata, data, oc_string(root->publicdata.data), + oc_string_len(root->publicdata.data)); + oc_rep_set_text_string_v1(publicdata, encoding, OC_ENCODING_PEM_STR, + OC_CHAR_ARRAY_LEN(OC_ENCODING_PEM_STR)); + oc_rep_close_object(creds, publicdata); + + oc_rep_set_text_string_v1(creds, credusage, OC_CREDUSAGE_TRUSTCA_STR, + OC_CHAR_ARRAY_LEN(OC_CREDUSAGE_TRUSTCA_STR)); + + oc_rep_object_array_end_item(creds); + oc_rep_close_array(root, creds); + oc_rep_end_root_object(); + if (!oc_do_post()) { + OC_ERR("Could not do POST request to /oic/sec/cred"); + goto err_device_RFPRO; } + return; + err_device_RFPRO: free_credprov_state(p, -1); } @@ -2105,6 +2152,7 @@ oc_obt_provision_role_certificate(oc_role_t *roles, const oc_uuid_t *uuid, const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(device->endpoint); if (!oc_do_get("/oic/sec/doxm", ep, NULL, &supports_cert_creds, HIGH_QOS, p)) { + OC_ERR("Could not issue GET request to /oic/sec/doxm"); oc_memb_free(&oc_credprov_ctx_m, p); return -1; } @@ -2152,9 +2200,11 @@ oc_obt_provision_identity_certificate(const oc_uuid_t *uuid, const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(device->endpoint); if (!oc_do_get("/oic/sec/doxm", ep, NULL, &supports_cert_creds, HIGH_QOS, p)) { + OC_ERR("Could not issue GET request to /oic/sec/doxm"); oc_memb_free(&oc_credprov_ctx_m, p); return -1; } + oc_list_add(oc_credprov_ctx_l, p); return 0; } @@ -2206,42 +2256,47 @@ trustanchor_device_RFPRO(int status, void *response_data) } oc_trustanchor_ctx_t *p = (oc_trustanchor_ctx_t *)response_data; - if (status >= 0) { - const oc_sec_cred_t *root = - oc_sec_get_cred_by_credid(g_root_cert_credid, 0); - if (!root) { - goto err_trustanchor_device_RFPRO; - } + if (status < 0) { + goto err_trustanchor_device_RFPRO; + } + const oc_sec_cred_t *root = oc_sec_get_cred_by_credid(g_root_cert_credid, 0); + if (!root) { + goto err_trustanchor_device_RFPRO; + } - /** 3) post cred with trustca - */ - const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); - if (oc_init_post("/oic/sec/cred", ep, NULL, &trustanchor_device_RFNOP, - HIGH_QOS, p)) { - oc_rep_start_root_object(); - oc_rep_set_array(root, creds); - oc_rep_object_array_start_item(creds); - - oc_rep_set_int(creds, credtype, OC_CREDTYPE_CERT); - oc_rep_set_text_string(creds, subjectuuid, p->trustanchor_subject); - - oc_rep_set_object(creds, publicdata); - oc_rep_set_text_string(publicdata, data, p->trustanchor); - oc_rep_set_text_string_v1(publicdata, encoding, OC_ENCODING_PEM_STR, - OC_CHAR_ARRAY_LEN(OC_ENCODING_PEM_STR)); - oc_rep_close_object(creds, publicdata); - - oc_rep_set_text_string_v1(creds, credusage, OC_CREDUSAGE_TRUSTCA_STR, - OC_CHAR_ARRAY_LEN(OC_CREDUSAGE_TRUSTCA_STR)); - - oc_rep_object_array_end_item(creds); - oc_rep_close_array(root, creds); - oc_rep_end_root_object(); - if (oc_do_post()) { - return; - } - } + /** 3) post cred with trustca + */ + const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device1->endpoint); + if (!oc_init_post("/oic/sec/cred", ep, NULL, &trustanchor_device_RFNOP, + HIGH_QOS, p)) { + OC_ERR("Could not init POST request to /oic/sec/cred"); + goto err_trustanchor_device_RFPRO; } + oc_rep_start_root_object(); + oc_rep_set_array(root, creds); + oc_rep_object_array_start_item(creds); + + oc_rep_set_int(creds, credtype, OC_CREDTYPE_CERT); + oc_rep_set_text_string(creds, subjectuuid, p->trustanchor_subject); + + oc_rep_set_object(creds, publicdata); + oc_rep_set_text_string(publicdata, data, p->trustanchor); + oc_rep_set_text_string_v1(publicdata, encoding, OC_ENCODING_PEM_STR, + OC_CHAR_ARRAY_LEN(OC_ENCODING_PEM_STR)); + oc_rep_close_object(creds, publicdata); + + oc_rep_set_text_string_v1(creds, credusage, OC_CREDUSAGE_TRUSTCA_STR, + OC_CHAR_ARRAY_LEN(OC_CREDUSAGE_TRUSTCA_STR)); + + oc_rep_object_array_end_item(creds); + oc_rep_close_array(root, creds); + oc_rep_end_root_object(); + if (!oc_do_post()) { + OC_ERR("Could not do POST request to /oic/sec/cred"); + goto err_trustanchor_device_RFPRO; + } + + return; err_trustanchor_device_RFPRO: free_trustanchor_state(p, -1); @@ -2319,6 +2374,7 @@ oc_obt_provision_trust_anchor(const char *certificate, size_t certificate_size, const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(device->endpoint); if (!oc_do_get("/oic/sec/doxm", ep, NULL, &trustanchor_supports_cert_creds, HIGH_QOS, p)) { + OC_ERR("Could not issue GET request to /oic/sec/doxm"); oc_memb_free(&oc_installtrust_ctx_m, p); return -1; } @@ -2568,92 +2624,96 @@ provision_ace(int status, void *data) r->switch_dos = NULL; if (status < 0) { - free_acl2prov_ctx(r, -1); - return; + goto err_provision_ace; } const oc_device_t *device = r->device; oc_sec_ace_t *ace = r->ace; const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(device->endpoint); - if (oc_init_post("/oic/sec/acl2", ep, NULL, &acl2_response, HIGH_QOS, r)) { - oc_rep_start_root_object(); - - oc_rep_set_array(root, aclist2); - oc_rep_object_array_start_item(aclist2); - - oc_rep_set_object(aclist2, subject); - switch (ace->subject_type) { - case OC_SUBJECT_UUID: { - char uuid[OC_UUID_LEN]; - oc_uuid_to_str(&ace->subject.uuid, uuid, OC_UUID_LEN); - oc_rep_set_text_string(subject, uuid, uuid); - } break; - case OC_SUBJECT_CONN: { - switch (ace->subject.conn) { - case OC_CONN_AUTH_CRYPT: - oc_rep_set_text_string_v1(subject, conntype, "auth-crypt", - OC_CHAR_ARRAY_LEN("auth-crypt")); - break; - case OC_CONN_ANON_CLEAR: - oc_rep_set_text_string_v1(subject, conntype, "anon-clear", - OC_CHAR_ARRAY_LEN("anon-clear")); - break; - } - } break; - case OC_SUBJECT_ROLE: { - oc_rep_set_text_string_v1(subject, role, - oc_string(ace->subject.role.role), - oc_string_len(ace->subject.role.role)); - if (oc_string_len(ace->subject.role.authority) > 0) { - oc_rep_set_text_string_v1(subject, authority, - oc_string(ace->subject.role.authority), - oc_string_len(ace->subject.role.authority)); - } - } break; - default: + if (!oc_init_post("/oic/sec/acl2", ep, NULL, &acl2_response, HIGH_QOS, r)) { + OC_ERR("Could not init POST request to /oic/sec/acl2"); + goto err_provision_ace; + } + + oc_rep_start_root_object(); + oc_rep_set_array(root, aclist2); + oc_rep_object_array_start_item(aclist2); + + oc_rep_set_object(aclist2, subject); + switch (ace->subject_type) { + case OC_SUBJECT_UUID: { + char uuid[OC_UUID_LEN]; + oc_uuid_to_str(&ace->subject.uuid, uuid, OC_UUID_LEN); + oc_rep_set_text_string_v1(subject, uuid, uuid, OC_UUID_LEN); + } break; + case OC_SUBJECT_CONN: { + switch (ace->subject.conn) { + case OC_CONN_AUTH_CRYPT: + oc_rep_set_text_string_v1(subject, conntype, "auth-crypt", + OC_CHAR_ARRAY_LEN("auth-crypt")); break; + case OC_CONN_ANON_CLEAR: + oc_rep_set_text_string_v1(subject, conntype, "anon-clear", + OC_CHAR_ARRAY_LEN("anon-clear")); + break; + } + } break; + case OC_SUBJECT_ROLE: { + oc_rep_set_text_string_v1(subject, role, oc_string(ace->subject.role.role), + oc_string_len(ace->subject.role.role)); + if (oc_string_len(ace->subject.role.authority) > 0) { + oc_rep_set_text_string_v1(subject, authority, + oc_string(ace->subject.role.authority), + oc_string_len(ace->subject.role.authority)); } - oc_rep_close_object(aclist2, subject); + } break; + default: + break; + } + oc_rep_close_object(aclist2, subject); - oc_ace_res_t *res = (oc_ace_res_t *)oc_list_head(ace->resources); - oc_rep_set_array(aclist2, resources); - while (res != NULL) { - oc_rep_object_array_start_item(resources); - if (oc_string_len(res->href) > 0) { - oc_rep_set_text_string_v1(resources, href, oc_string(res->href), - oc_string_len(res->href)); - } else { - switch (res->wildcard) { - case OC_ACE_WC_ALL_SECURED: - oc_rep_set_text_string_v1(resources, wc, "+", OC_CHAR_ARRAY_LEN("+")); - break; - case OC_ACE_WC_ALL_PUBLIC: - oc_rep_set_text_string_v1(resources, wc, "-", OC_CHAR_ARRAY_LEN("-")); - break; - case OC_ACE_WC_ALL: - oc_rep_set_text_string_v1(resources, wc, "*", OC_CHAR_ARRAY_LEN("*")); - break; - default: - break; - } + oc_ace_res_t *res = (oc_ace_res_t *)oc_list_head(ace->resources); + oc_rep_set_array(aclist2, resources); + while (res != NULL) { + oc_rep_object_array_start_item(resources); + if (oc_string_len(res->href) > 0) { + oc_rep_set_text_string_v1(resources, href, oc_string(res->href), + oc_string_len(res->href)); + } else { + switch (res->wildcard) { + case OC_ACE_WC_ALL_SECURED: + oc_rep_set_text_string_v1(resources, wc, "+", OC_CHAR_ARRAY_LEN("+")); + break; + case OC_ACE_WC_ALL_PUBLIC: + oc_rep_set_text_string_v1(resources, wc, "-", OC_CHAR_ARRAY_LEN("-")); + break; + case OC_ACE_WC_ALL: + oc_rep_set_text_string_v1(resources, wc, "*", OC_CHAR_ARRAY_LEN("*")); + break; + default: + break; } - oc_rep_object_array_end_item(resources); - res = res->next; } - oc_rep_close_array(aclist2, resources); + oc_rep_object_array_end_item(resources); + res = res->next; + } + oc_rep_close_array(aclist2, resources); - oc_rep_set_uint(aclist2, permission, ace->permission); + oc_rep_set_uint(aclist2, permission, ace->permission); - oc_rep_object_array_end_item(aclist2); - oc_rep_close_array(root, aclist2); + oc_rep_object_array_end_item(aclist2); + oc_rep_close_array(root, aclist2); - oc_rep_end_root_object(); + oc_rep_end_root_object(); - if (oc_do_post()) { - return; - } + if (!oc_do_post()) { + OC_ERR("Could not do POST request to /oic/sec/acl2"); + goto err_provision_ace; } + return; + +err_provision_ace: free_acl2prov_ctx(r, -1); } @@ -2932,12 +2992,13 @@ oc_obt_retrieve_creds(const oc_uuid_t *uuid, oc_obt_creds_cb_t cb, void *data) oc_tls_select_psk_ciphersuite(); const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(device->endpoint); - if (oc_do_get("/oic/sec/cred", ep, NULL, &cred_rsrc, HIGH_QOS, r)) { - oc_list_add(oc_credret_ctx_l, r); - return 0; + if (!oc_do_get("/oic/sec/cred", ep, NULL, &cred_rsrc, HIGH_QOS, r)) { + OC_ERR("could not issue GET request to /oic/sec/cred"); + oc_memb_free(&oc_credret_ctx_m, r); + return -1; } - oc_memb_free(&oc_credret_ctx_m, r); + oc_list_add(oc_credret_ctx_l, r); return 0; } @@ -3013,15 +3074,21 @@ creddel_RFPRO(int status, void *data) oc_creddel_ctx_t *p = (oc_creddel_ctx_t *)data; p->switch_dos = NULL; - if (status >= 0) { - char query[64]; - snprintf(query, 64, "credid=%d", p->credid); - const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device->endpoint); - if (oc_do_delete("/oic/sec/cred", ep, query, &cred_del, HIGH_QOS, p)) { - return; - } + if (status < 0) { + OC_DBG("oc_obt: could not switch to RFPRO"); + goto err_creddel_RFPRO; + } + char query[64]; + snprintf(query, 64, "credid=%d", p->credid); + const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device->endpoint); + if (!oc_do_delete("/oic/sec/cred", ep, query, &cred_del, HIGH_QOS, p)) { + OC_ERR("could not issue DELETE request to /oic/sec/cred"); + goto err_creddel_RFPRO; } + return; + +err_creddel_RFPRO: free_creddel_ctx(p, -1); } @@ -3258,13 +3325,13 @@ oc_obt_retrieve_acl(const oc_uuid_t *uuid, oc_obt_acl_cb_t cb, void *data) oc_tls_select_psk_ciphersuite(); const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(device->endpoint); - if (oc_do_get("/oic/sec/acl2", ep, NULL, &acl2_rsrc, HIGH_QOS, r)) { - oc_list_add(oc_aclret_ctx_l, r); - return 0; + if (!oc_do_get("/oic/sec/acl2", ep, NULL, &acl2_rsrc, HIGH_QOS, r)) { + OC_ERR("could not issue GET request to /oic/sec/acl2"); + oc_memb_free(&oc_aclret_ctx_m, r); + return -1; } - oc_memb_free(&oc_aclret_ctx_m, r); - + oc_list_add(oc_aclret_ctx_l, r); return 0; } @@ -3338,17 +3405,22 @@ acedel_RFPRO(int status, void *data) } oc_acedel_ctx_t *p = (oc_acedel_ctx_t *)data; - p->switch_dos = NULL; - if (status >= 0) { - char query[64]; - snprintf(query, 64, "aceid=%d", p->aceid); - const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device->endpoint); - if (oc_do_delete("/oic/sec/acl2", ep, query, &ace_del, HIGH_QOS, p)) { - return; - } + if (status < 0) { + OC_DBG("oc_obt: could not switch to RFPRO"); + goto err_acedel_RFPRO; } + char query[64]; + snprintf(query, 64, "aceid=%d", p->aceid); + const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(p->device->endpoint); + if (!oc_do_delete("/oic/sec/acl2", ep, query, &ace_del, HIGH_QOS, p)) { + OC_ERR("could not issue DELETE request to /oic/sec/acl2"); + goto err_acedel_RFPRO; + } + + return; +err_acedel_RFPRO: free_acedel_ctx(p, -1); } @@ -3431,24 +3503,22 @@ oc_obt_update_cloud_conf_device(const oc_uuid_t *uuid, const char *url, OC_DBG("apn %s", apn); OC_DBG("cis %s", cis); OC_DBG("sid %s", sid); - if (oc_init_post(url, ep, NULL, cb, LOW_QOS, user_data)) { - oc_rep_start_root_object(); - oc_rep_set_text_string(root, at, at); - oc_rep_set_text_string(root, apn, apn); - oc_rep_set_text_string(root, cis, cis); - oc_rep_set_text_string(root, sid, sid); - oc_rep_end_root_object(); - if (oc_do_post()) - OC_DBG("Sent POST request"); - else { - OC_ERR("Could not send POST request"); - return -1; - } - } else { + if (!oc_init_post(url, ep, NULL, cb, LOW_QOS, user_data)) { OC_ERR("Could not init POST request"); return -1; } + oc_rep_start_root_object(); + oc_rep_set_text_string(root, at, at); + oc_rep_set_text_string(root, apn, apn); + oc_rep_set_text_string(root, cis, cis); + oc_rep_set_text_string(root, sid, sid); + oc_rep_end_root_object(); + if (!oc_do_post()) { + OC_ERR("Could not send POST request"); + return -1; + } + OC_DBG("Sent POST request"); return 0; } @@ -3458,7 +3528,6 @@ oc_obt_retrieve_cloud_conf_device(const oc_uuid_t *uuid, const char *url, { // TODO get the URL from the device // char url[200] = "/CoapCloudConfResURI"; - int err = 0; // oc_device_t* device = oc_obt_get_cached_device_handle(uuid); const oc_device_t *device = oc_obt_get_owned_device_handle(uuid); @@ -3477,11 +3546,12 @@ oc_obt_retrieve_cloud_conf_device(const oc_uuid_t *uuid, const char *url, return -1; } - if (oc_do_get(url, ep, NULL, cb, LOW_QOS, user_data)) { - err = -1; + if (!oc_do_get(url, ep, NULL, cb, LOW_QOS, user_data)) { + OC_ERR("Could not send GET request"); + return -1; } - return err; + return 0; } int @@ -3499,8 +3569,9 @@ oc_obt_retrieve_d2dserverlist(const oc_uuid_t *uuid, oc_response_handler_t cb, oc_tls_select_psk_ciphersuite(); const oc_endpoint_t *ep = oc_obt_get_secure_endpoint(device->endpoint); - if (oc_do_get("/d2dserverlist", ep, NULL, cb, LOW_QOS, data)) { - return 0; + if (!oc_do_get("/d2dserverlist", ep, NULL, cb, LOW_QOS, data)) { + OC_ERR("Could not send GET request to /d2dserverlist"); + return -1; } return 0; @@ -3527,25 +3598,21 @@ oc_obt_post_d2dserverlist(const oc_uuid_t *uuid, const char *query, return -1; } - if (oc_init_post(url, ep, query, cb, LOW_QOS, user_data)) { - if (oc_do_post()) - OC_DBG("Sent POST request %s?%s", url, query); - else { - OC_ERR("Could not send POST request"); - return -1; - } - } else { + if (!oc_init_post(url, ep, query, cb, LOW_QOS, user_data)) { OC_ERR("Could not init POST request"); return -1; } + if (!oc_do_post()) { + OC_ERR("Could not send POST request"); + return -1; + } + OC_DBG("Sent POST request %s?%s", url, query); return 0; } -/* General GET, POST and DELETE */ -int -oc_obt_general_get(const oc_uuid_t *uuid, const char *url, - oc_response_handler_t cb, void *data) +static const oc_endpoint_t * +obt_get_endpoint(const oc_uuid_t *uuid) { const oc_device_t *device; if (!oc_obt_is_owned_device(uuid)) { @@ -3553,26 +3620,35 @@ oc_obt_general_get(const oc_uuid_t *uuid, const char *url, } else { device = oc_obt_get_owned_device_handle(uuid); } - if (!device) { - return -1; + if (device == NULL) { + return NULL; } char di[OC_UUID_LEN]; oc_uuid_to_str(&(device->uuid), di, OC_ARRAY_SIZE(di)); OC_DBG("[C] Target uuid = %s", di); - oc_tls_select_psk_ciphersuite(); - - const oc_endpoint_t *ep; if (!oc_obt_is_owned_device(uuid)) { - ep = oc_obt_get_unsecure_endpoint(device->endpoint); - } else { - ep = oc_obt_get_secure_endpoint(device->endpoint); - } - if (oc_do_get(url, ep, NULL, cb, HIGH_QOS, data)) { - return 0; + return oc_obt_get_unsecure_endpoint(device->endpoint); } + return oc_obt_get_secure_endpoint(device->endpoint); +} +/* General GET, POST and DELETE */ +int +oc_obt_general_get(const oc_uuid_t *uuid, const char *url, + oc_response_handler_t cb, void *data) +{ + const oc_endpoint_t *ep = obt_get_endpoint(uuid); + if (ep == NULL) { + OC_ERR("Could not find ep from device"); + return -1; + } + oc_tls_select_psk_ciphersuite(); + if (!oc_do_get(url, ep, NULL, cb, HIGH_QOS, data)) { + OC_ERR("Could not send GET request"); + return -1; + } return 0; } @@ -3598,67 +3674,64 @@ oc_obt_general_post(const oc_uuid_t *uuid, const char *query, const char *url, return -1; } - if (oc_init_post(url, ep, query, cb, HIGH_QOS, user_data)) { - oc_rep_start_root_object(); - for (int i = 0; i < array_size; i++) { - if (strstr(payload_types[i], "bool") != NULL) { - long payload_int = strtol(payload_values[i], NULL, 10); - bool payload_bool = (payload_int != 0 ? true : false); - - oc_rep_encode_text_string(&root_map, payload_properties[i], - strlen(payload_properties[i])); - oc_rep_encode_boolean(&root_map, payload_bool); - - } else if (strstr(payload_types[i], "int") != NULL) { - long payload_int = strtol(payload_values[i], NULL, 10); - - oc_rep_encode_text_string(&root_map, payload_properties[i], - strlen(payload_properties[i])); - oc_rep_encode_int(&root_map, payload_int); - } else if (strstr(payload_types[i], "float") != NULL) { - double payload_double = strtod(payload_values[i], NULL); - - oc_rep_encode_text_string(&root_map, payload_properties[i], - strlen(payload_properties[i])); - oc_rep_encode_double(&root_map, payload_double); - } else if (strstr(payload_types[i], "str") != NULL) { - oc_rep_encode_text_string(&root_map, payload_properties[i], - strlen(payload_properties[i])); - if ((const char *)payload_values[i] != NULL) { - oc_rep_encode_text_string(&root_map, payload_values[i], - strlen(payload_values[i])); - } else { - oc_rep_encode_text_string(&root_map, "", 0); - } - } else if (strstr(payload_types[i], "bytes") != NULL) { - size_t byte_string_len = (strlen(payload_values[i]) + 1) / 2; - unsigned char payload_byte_string[10240]; - - const char *pos = payload_values[i]; - for (size_t j = 0; j < byte_string_len; j++) { - sscanf(pos, "%2hhx", &payload_byte_string[j]); - pos += 2; - } - - oc_rep_encode_text_string(&root_map, payload_properties[i], - strlen(payload_properties[i])); - oc_rep_encode_byte_string(&root_map, payload_byte_string, - byte_string_len); + if (!oc_init_post(url, ep, query, cb, HIGH_QOS, user_data)) { + OC_ERR("Could not init POST request"); + return -1; + } + oc_rep_start_root_object(); + for (int i = 0; i < array_size; i++) { + if (strstr(payload_types[i], "bool") != NULL) { + long payload_int = strtol(payload_values[i], NULL, 10); + bool payload_bool = (payload_int != 0 ? true : false); + + oc_rep_encode_text_string(&root_map, payload_properties[i], + strlen(payload_properties[i])); + oc_rep_encode_boolean(&root_map, payload_bool); + + } else if (strstr(payload_types[i], "int") != NULL) { + long payload_int = strtol(payload_values[i], NULL, 10); + + oc_rep_encode_text_string(&root_map, payload_properties[i], + strlen(payload_properties[i])); + oc_rep_encode_int(&root_map, payload_int); + } else if (strstr(payload_types[i], "float") != NULL) { + double payload_double = strtod(payload_values[i], NULL); + + oc_rep_encode_text_string(&root_map, payload_properties[i], + strlen(payload_properties[i])); + oc_rep_encode_double(&root_map, payload_double); + } else if (strstr(payload_types[i], "str") != NULL) { + oc_rep_encode_text_string(&root_map, payload_properties[i], + strlen(payload_properties[i])); + if ((const char *)payload_values[i] != NULL) { + oc_rep_encode_text_string(&root_map, payload_values[i], + strlen(payload_values[i])); + } else { + oc_rep_encode_text_string(&root_map, "", 0); + } + } else if (strstr(payload_types[i], "bytes") != NULL) { + size_t byte_string_len = (strlen(payload_values[i]) + 1) / 2; + unsigned char payload_byte_string[10240]; + + const char *pos = payload_values[i]; + for (size_t j = 0; j < byte_string_len; j++) { + sscanf(pos, "%2hhx", &payload_byte_string[j]); + pos += 2; } - } - oc_rep_end_root_object(); - if (oc_do_post()) - OC_DBG("\n\n\nSent POST request %s?%s\n\n", url, query); - else { - OC_ERR("Could not send POST request"); - return -1; + oc_rep_encode_text_string(&root_map, payload_properties[i], + strlen(payload_properties[i])); + oc_rep_encode_byte_string(&root_map, payload_byte_string, + byte_string_len); } - } else { - OC_ERR("Could not init POST request"); - return -1; } + oc_rep_end_root_object(); + if (!oc_do_post()) { + OC_ERR("Could not send POST request"); + return -1; + } + OC_DBG("\n\n\nSent POST request %s?%s\n\n", url, query); return 0; } @@ -3666,32 +3739,16 @@ int oc_obt_general_delete(const oc_uuid_t *uuid, const char *query, const char *url, oc_response_handler_t cb, void *data) { - const oc_device_t *device; - if (!oc_obt_is_owned_device(uuid)) { - device = oc_obt_get_cached_device_handle(uuid); - } else { - device = oc_obt_get_owned_device_handle(uuid); - } - if (!device) { + const oc_endpoint_t *ep = obt_get_endpoint(uuid); + if (ep == NULL) { + OC_ERR("Could not find ep from device"); return -1; } - - char di[OC_UUID_LEN]; - oc_uuid_to_str(&(device->uuid), di, OC_ARRAY_SIZE(di)); - OC_DBG("[C] Target uuid = %s", di); - oc_tls_select_psk_ciphersuite(); - - const oc_endpoint_t *ep; - if (!oc_obt_is_owned_device(uuid)) { - ep = oc_obt_get_unsecure_endpoint(device->endpoint); - } else { - ep = oc_obt_get_secure_endpoint(device->endpoint); - } - if (oc_do_delete(url, ep, query, cb, HIGH_QOS, data)) { - return 0; + if (!oc_do_delete(url, ep, query, cb, HIGH_QOS, data)) { + OC_ERR("Could not send DELETE request"); + return -1; } - return 0; } From eede00d2b978576fe0744e87763c99802bc2cbb1 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Mon, 24 Jul 2023 11:13:39 +0200 Subject: [PATCH 10/11] SonarCloud: don't use variable tainted by fread --- api/oc_server_api.c | 4 +++- apps/client_certification_tests.c | 3 ++- apps/cloud_certification_tests.c | 5 +++-- apps/cloud_client.c | 5 +++-- apps/cloud_proxy.c | 5 +++-- apps/cloud_server.c | 5 +++-- apps/server_certification_tests.c | 3 ++- apps/smart_home_server_linux.c | 3 ++- apps/smart_home_server_with_mock_swupdate.cpp | 3 ++- onboarding_tool/obtmain.c | 5 +++-- python/oc_python.c | 5 +++-- 11 files changed, 29 insertions(+), 17 deletions(-) diff --git a/api/oc_server_api.c b/api/oc_server_api.c index 17da1465e5..d6458762b8 100644 --- a/api/oc_server_api.c +++ b/api/oc_server_api.c @@ -506,7 +506,9 @@ oc_add_collection_v1(oc_resource_t *collection) void oc_add_collection(oc_resource_t *collection) { - oc_add_collection_v1(collection); + if (!oc_add_collection_v1(collection)) { + OC_ERR("failed to add collection"); + } } oc_resource_t * diff --git a/apps/client_certification_tests.c b/apps/client_certification_tests.c index 8063b1d4ee..14e910c9de 100644 --- a/apps/client_certification_tests.c +++ b/apps/client_certification_tests.c @@ -603,7 +603,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/apps/cloud_certification_tests.c b/apps/cloud_certification_tests.c index d2a809727b..cfad6ee187 100644 --- a/apps/cloud_certification_tests.c +++ b/apps/cloud_certification_tests.c @@ -544,7 +544,7 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (pem_len > (long)*buffer_len) { + if (pem_len >= (long)*buffer_len) { OC_PRINTF("ERROR: buffer provided too small\n"); fclose(fp); return -1; @@ -554,7 +554,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/apps/cloud_client.c b/apps/cloud_client.c index 8935b7ebc0..423d9ddb82 100644 --- a/apps/cloud_client.c +++ b/apps/cloud_client.c @@ -315,7 +315,7 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (pem_len > (long)*buffer_len) { + if (pem_len >= (long)*buffer_len) { OC_PRINTF("ERROR: buffer provided too small\n"); fclose(fp); return -1; @@ -325,7 +325,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/apps/cloud_proxy.c b/apps/cloud_proxy.c index 3666a5bc77..156d57aea0 100644 --- a/apps/cloud_proxy.c +++ b/apps/cloud_proxy.c @@ -1634,7 +1634,7 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (pem_len > (long)*buffer_len) { + if (pem_len >= (long)*buffer_len) { OC_PRINTF("ERROR: buffer provided too small\n"); fclose(fp); return -1; @@ -1644,7 +1644,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/apps/cloud_server.c b/apps/cloud_server.c index 84dbb29171..346e21d362 100644 --- a/apps/cloud_server.c +++ b/apps/cloud_server.c @@ -828,7 +828,7 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (pem_len > (long)*buffer_len) { + if (pem_len >= (long)*buffer_len) { OC_PRINTF("ERROR: buffer provided too small\n"); fclose(fp); return -1; @@ -838,7 +838,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/apps/server_certification_tests.c b/apps/server_certification_tests.c index 84472be2d9..d44d1b4fc5 100644 --- a/apps/server_certification_tests.c +++ b/apps/server_certification_tests.c @@ -2023,7 +2023,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/apps/smart_home_server_linux.c b/apps/smart_home_server_linux.c index e025792425..17a045e706 100644 --- a/apps/smart_home_server_linux.c +++ b/apps/smart_home_server_linux.c @@ -737,7 +737,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { printf("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/apps/smart_home_server_with_mock_swupdate.cpp b/apps/smart_home_server_with_mock_swupdate.cpp index c66a7bb69c..f0b61bd502 100644 --- a/apps/smart_home_server_with_mock_swupdate.cpp +++ b/apps/smart_home_server_with_mock_swupdate.cpp @@ -272,7 +272,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/onboarding_tool/obtmain.c b/onboarding_tool/obtmain.c index 48a401fa1b..b2e308c6b2 100644 --- a/onboarding_tool/obtmain.c +++ b/onboarding_tool/obtmain.c @@ -1760,7 +1760,7 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (pem_len > (long)*buffer_len) { + if (pem_len >= (long)*buffer_len) { OC_PRINTF("ERROR: buffer provided too small\n"); fclose(fp); return -1; @@ -1770,7 +1770,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("ERROR: unable to read PEM\n"); fclose(fp); return -1; diff --git a/python/oc_python.c b/python/oc_python.c index eeb0810511..4477e56708 100644 --- a/python/oc_python.c +++ b/python/oc_python.c @@ -1492,7 +1492,7 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (pem_len > (long)*buffer_len) { + if (pem_len >= (long)*buffer_len) { OC_PRINTF("[C]ERROR: buffer provided too small\n"); fclose(fp); return -1; @@ -1502,7 +1502,8 @@ read_pem(const char *file_path, char *buffer, size_t *buffer_len) fclose(fp); return -1; } - if (fread(buffer, 1, pem_len, fp) < (size_t)pem_len) { + size_t to_read = (size_t)pem_len; + if (fread(buffer, 1, to_read, fp) < (size_t)pem_len) { OC_PRINTF("[C]ERROR: unable to read PEM\n"); fclose(fp); return -1; From e5899d1596fc612385d2f02360a4e03e3bd425e3 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Mon, 24 Jul 2023 12:10:50 +0200 Subject: [PATCH 11/11] Fix issues reported by SonarCloud --- api/oc_base64.c | 36 +++++----- api/oc_helpers.c | 2 +- api/unittest/base64test.cpp | 14 ++++ api/unittest/logtest.cpp | 7 ++ api/unittest/ocapitest.cpp | 14 ++-- api/unittest/plgdtimetest.cpp | 2 +- api/unittest/swupdatetest.cpp | 6 +- apps/cloud_proxy.c | 1 + include/oc_base64.h | 1 + include/oc_log.h | 3 +- messaging/coap/conf.h | 4 -- messaging/coap/observe.c | 6 ++ messaging/coap/unittest/coapsignaltest.cpp | 13 ++-- security/unittest/csrtest.cpp | 2 +- security/unittest/sditest.cpp | 3 +- security/unittest/sptest.cpp | 6 +- security/unittest/tls_cert_test.cpp | 83 +++++++++++----------- 17 files changed, 114 insertions(+), 89 deletions(-) diff --git a/api/oc_base64.c b/api/oc_base64.c index 3e6a0822bb..dd3875ab7e 100644 --- a/api/oc_base64.c +++ b/api/oc_base64.c @@ -29,16 +29,13 @@ oc_base64_encode(const uint8_t *input, size_t input_len, uint8_t *output_buffer, /* The Base64 alphabet. This table provides a mapping from 6-bit binary * values to Base64 characters. */ - uint8_t alphabet[65] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '+', '/', '=' }; - uint8_t val = 0; - size_t i; - int j = 0; + const uint8_t alphabet[65] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=', + }; /* Calculate the length of the Base64 encoded output. * Every sequence of 3 bytes (with padding, if necessary) @@ -50,13 +47,17 @@ oc_base64_encode(const uint8_t *input, size_t input_len, uint8_t *output_buffer, } /* If the output buffer provided was not large enough, return an error. */ - if (output_buffer_len < output_len) + if (output_buffer_len < output_len) { return -1; + } /* handle the case that an empty input is provided */ if (input_len == 0) { output_buffer[0] = '\0'; } + size_t i; + int j = 0; + uint8_t val = 0; /* Process every byte of input by keeping state across 3 byte blocks * to capture 4 6-bit binary blocks that each map to a Base64 character. */ @@ -70,7 +71,7 @@ oc_base64_encode(const uint8_t *input, size_t input_len, uint8_t *output_buffer, if (i % 3 == 0) { val = (input[i] >> 2); output_buffer[j++] = alphabet[val]; - val = input[i] << 4; + val = (uint8_t)(input[i] << 4); val &= 0x30; } /* This is the second byte of a 3 byte block of input. Combine @@ -83,7 +84,7 @@ oc_base64_encode(const uint8_t *input, size_t input_len, uint8_t *output_buffer, else if (i % 3 == 1) { val |= (input[i] >> 4); output_buffer[j++] = alphabet[val]; - val = input[i] << 2; + val = (uint8_t)(input[i] << 2); val &= 0x3D; } /* This is the last byte of a 3 byte block of input. Combine @@ -164,29 +165,30 @@ oc_base64_decode(uint8_t *str, size_t len) /* Return an error if we encounter a character that is outside * of the Base64 alphabet. */ - else + else { return -1; + } /* Decode all 4 byte blocks to 3 bytes of binary output by * laying out their 6-bit blocks into a sequence of 3 bytes. */ if (i % 4 == 0) { /* 1st 6 bits of output byte 1 */ - val_c = val_s << 2; + val_c = (uint8_t)(val_s << 2); val_c &= 0xFD; } else if (i % 4 == 1) { /* Last 2 bits of output byte 1 */ val_c |= (val_s >> 4); str[j++] = val_c; /* 1st 4 bits of output byte 2 */ - val_c = val_s << 4; + val_c = (uint8_t)(val_s << 4); val_c &= 0xF0; } else if (i % 4 == 2) { /* Last 4 bits of output byte 2 */ val_c |= (val_s >> 2); str[j++] = val_c; /* 1st 2 bits of output byte 3 */ - val_c = val_s << 6; + val_c = (uint8_t)(val_s << 6); val_c &= 0xD0; } else { /* Last 6 bits of output byte 3 */ diff --git a/api/oc_helpers.c b/api/oc_helpers.c index be65735543..b81904b6c5 100644 --- a/api/oc_helpers.c +++ b/api/oc_helpers.c @@ -258,7 +258,7 @@ _oc_alloc_string_array( for (size_t i = 0; i < size; ++i) { size_t pos = i * STRING_ARRAY_ITEM_MAX_LEN; - memcpy((char *)oc_string(*ocstringarray) + pos, (const char *)"", 1); + memcpy(oc_string(*ocstringarray) + pos, (const char *)"", 1); } } diff --git a/api/unittest/base64test.cpp b/api/unittest/base64test.cpp index b97f894e7e..1f8be07d86 100644 --- a/api/unittest/base64test.cpp +++ b/api/unittest/base64test.cpp @@ -54,6 +54,20 @@ toString(From *arr, size_t arrSize) return str; } +TEST(B64Test, RFC4648_EncodeFail) +{ + std::vector inputs = { + "foo", + "foobar", + }; + + std::for_each(inputs.begin(), inputs.end(), [](const std::string &str) { + auto toEncode = fromString(str); + EXPECT_EQ(-1, + oc_base64_encode(toEncode.data(), toEncode.size(), nullptr, 0)); + }); +} + /* * Expected input and output comes from section 10 of RFC4648 */ diff --git a/api/unittest/logtest.cpp b/api/unittest/logtest.cpp index 63b76ec7b2..8e31d6ab63 100644 --- a/api/unittest/logtest.cpp +++ b/api/unittest/logtest.cpp @@ -18,6 +18,7 @@ #include "oc_log.h" #include "port/oc_log_internal.h" +#include "util/oc_compiler.h" #include #include @@ -48,6 +49,12 @@ TEST_F(TestLog, LogToStdout) OC_DBG("debug"); } +static void expectWarningOrError(oc_log_level_t log_level, + oc_log_component_t component, const char *file, + int line, const char *func_name, + const char *format, ...) + OC_PRINTF_FORMAT(6, 7); + static void expectWarningOrError(oc_log_level_t log_level, oc_log_component_t component, const char *file, int line, const char *func_name, diff --git a/api/unittest/ocapitest.cpp b/api/unittest/ocapitest.cpp index 3c3efa949a..5bd9bcf95c 100644 --- a/api/unittest/ocapitest.cpp +++ b/api/unittest/ocapitest.cpp @@ -389,8 +389,7 @@ class ApiHelper { oc_set_con_res_announced(false); - int initResult = oc_main_init(&s_handler); - if (initResult < 0) { + if (oc_main_init(&s_handler) < 0) { errorMessage += "Initialization of main server failed"; s_isServerStarted = false; return false; @@ -517,8 +516,8 @@ ApiResource ApiHelper::s_TestResource{}; class ResourceDiscovered { private: - std::set requiredURI_; - std::set deviceURI_; + std::set> requiredURI_; + std::set> deviceURI_; void addRequired(const std::string &uri) { requiredURI_.insert(uri); } @@ -558,8 +557,8 @@ class ResourceDiscovered { class DevicesDiscovered { private: - std::set requiredDevices_; - std::set devices_; + std::set> requiredDevices_; + std::set> devices_; public: bool isDone() const @@ -925,7 +924,8 @@ TEST_F(TestObt, DiscoverUnownedResources) for (const auto &device : devices) { OC_PRINTF("Discovered unowned device: %s\n", device.c_str()); } - std::set deviceUUIDs(devices.begin(), devices.end()); + std::set> deviceUUIDs(devices.begin(), + devices.end()); if (ApiHelper::s_LightResource.enabled) { EXPECT_EQ(1, deviceUUIDs.count(ApiHelper::s_LightResource.uuid)); deviceUUIDs.erase(ApiHelper::s_LightResource.uuid); diff --git a/api/unittest/plgdtimetest.cpp b/api/unittest/plgdtimetest.cpp index f2d2e5fea1..c617f29c6e 100644 --- a/api/unittest/plgdtimetest.cpp +++ b/api/unittest/plgdtimetest.cpp @@ -487,13 +487,13 @@ TEST_F(TestPlgdTimeWithServer, PostRequestFail) ASSERT_TRUE(epOpt.has_value()); auto ep = std::move(*epOpt); - bool invoked = false; auto post_handler = [](oc_client_response_t *data) { oc::TestDevice::Terminate(); ASSERT_LT(OC_STATUS_NOT_MODIFIED, data->code); *static_cast(data->user_data) = true; }; + bool invoked = false; ASSERT_TRUE(oc_init_post(PLGD_TIME_URI, &ep, nullptr, post_handler, HIGH_QOS, &invoked)); oc_rep_start_root_object(); diff --git a/api/unittest/swupdatetest.cpp b/api/unittest/swupdatetest.cpp index 8e6c3a548e..141a61ab88 100644 --- a/api/unittest/swupdatetest.cpp +++ b/api/unittest/swupdatetest.cpp @@ -778,8 +778,7 @@ postRequest(const std::function &payloadFn) EXPECT_EQ(OC_STATUS_CHANGED, data->code); oc::TestDevice::Terminate(); OC_DBG("POST payload: %s", oc::RepPool::GetJson(data->payload).data()); - auto *invoked = static_cast(data->user_data); - *invoked = true; + *static_cast(data->user_data) = true; }; bool invoked = false; @@ -918,8 +917,7 @@ postRequestWithFailure(const std::function &payloadFn) EXPECT_EQ(ErrorCode, data->code); oc::TestDevice::Terminate(); OC_DBG("POST payload: %s", oc::RepPool::GetJson(data->payload).data()); - auto *invoked = static_cast(data->user_data); - *invoked = true; + *static_cast(data->user_data) = true; }; bool invoked = false; diff --git a/apps/cloud_proxy.c b/apps/cloud_proxy.c index 156d57aea0..f0a935bc56 100644 --- a/apps/cloud_proxy.c +++ b/apps/cloud_proxy.c @@ -157,6 +157,7 @@ #endif /* OC_INTROSPECTION && OC_IDD_API */ #include +#include #ifndef DOXYGEN // Force doxygen to document static inline diff --git a/include/oc_base64.h b/include/oc_base64.h index d4d571fa59..cc749d2eea 100644 --- a/include/oc_base64.h +++ b/include/oc_base64.h @@ -21,6 +21,7 @@ #ifndef OC_BASE64_H #define OC_BASE64_H +#include "util/oc_compiler.h" #include #include diff --git a/include/oc_log.h b/include/oc_log.h index 8b4ea631a3..7a38134a49 100644 --- a/include/oc_log.h +++ b/include/oc_log.h @@ -75,7 +75,8 @@ extern "C" { #endif /* !OC_SNPRINTF */ #define OC_IPADDR_BUFF_SIZE \ - 64 // max size : scheme://[ipv6%scope]:port = 63 bytes + (64) // max size : scheme://[ipv6%scope]:port = 63 bytes + #define OC_SNPRINT_ENDPOINT_ADDR(str, size, endpoint, addr_memb) \ do { \ const char *scheme = "coap"; \ diff --git a/messaging/coap/conf.h b/messaging/coap/conf.h index 19723401ef..69162e6e6b 100644 --- a/messaging/coap/conf.h +++ b/messaging/coap/conf.h @@ -82,10 +82,6 @@ extern "C" { (OC_MAX_APP_RESOURCES + OC_MAX_NUM_CONCURRENT_REQUESTS) #endif /* COAP_MAX_OBSERVERS */ -/* Interval in notifies in which NON notifies are changed to CON notifies to - * check client. */ -#define COAP_OBSERVE_REFRESH_INTERVAL 5 - #ifdef __cplusplus } #endif diff --git a/messaging/coap/observe.c b/messaging/coap/observe.c index b97b9b8226..69e8cf4e27 100644 --- a/messaging/coap/observe.c +++ b/messaging/coap/observe.c @@ -95,6 +95,12 @@ #include #include +/* Interval in notifies in which NON notifies are changed to CON notifies to + * check client. */ +enum { + COAP_OBSERVE_REFRESH_INTERVAL = 5, +}; + #ifndef OC_MAX_OBSERVE_SIZE #define OC_MAX_OBSERVE_SIZE OC_MAX_APP_DATA_SIZE #endif diff --git a/messaging/coap/unittest/coapsignaltest.cpp b/messaging/coap/unittest/coapsignaltest.cpp index bb61030094..b2f5281385 100644 --- a/messaging/coap/unittest/coapsignaltest.cpp +++ b/messaging/coap/unittest/coapsignaltest.cpp @@ -29,11 +29,12 @@ #if defined(OC_TCP) && defined(OC_IPV4) -static const size_t device = 0; +static constexpr size_t kDeviceID = 0; static void signal_event_loop(void) { + // no-op } static int @@ -46,7 +47,7 @@ app_init(void) } class TestCoapSignal : public testing::Test { -protected: +public: void SetUp() override { static oc_handler_t handler = { /*.init =*/app_init, @@ -55,7 +56,7 @@ class TestCoapSignal : public testing::Test { /*.requests_entry =*/nullptr }; oc_main_init(&handler); - oc_endpoint_t *ep = oc_connectivity_get_endpoints(device); + oc_endpoint_t *ep = oc_connectivity_get_endpoints(kDeviceID); while (ep) { if ((ep->flags & TCP) && !(ep->flags & SECURED) && (ep->flags & IPV4)) { break; @@ -73,13 +74,15 @@ class TestCoapSignal : public testing::Test { TEST_F(TestCoapSignal, coap_send_csm_message_P) { - int ret = coap_send_csm_message(&_target_ep, (uint32_t)OC_PDU_SIZE, 1); + int ret = + coap_send_csm_message(&_target_ep, static_cast(OC_PDU_SIZE), 1); EXPECT_EQ(1, ret); } TEST_F(TestCoapSignal, coap_send_csm_message_N) { - int ret = coap_send_csm_message(nullptr, (uint32_t)OC_PDU_SIZE, 0); + int ret = + coap_send_csm_message(nullptr, static_cast(OC_PDU_SIZE), 0); EXPECT_NE(1, ret); } diff --git a/security/unittest/csrtest.cpp b/security/unittest/csrtest.cpp index dd116b764c..b95b576c14 100644 --- a/security/unittest/csrtest.cpp +++ b/security/unittest/csrtest.cpp @@ -300,7 +300,7 @@ TEST_F(TestCSRWithDevice, Resource) auto csr_handler = [](oc_client_response_t *data) { oc::TestDevice::Terminate(); - EXPECT_EQ(OC_STATUS_OK, data->code); + ASSERT_EQ(OC_STATUS_OK, data->code); *static_cast(data->user_data) = true; }; diff --git a/security/unittest/sditest.cpp b/security/unittest/sditest.cpp index f3db2fc946..ec0ea67e6b 100644 --- a/security/unittest/sditest.cpp +++ b/security/unittest/sditest.cpp @@ -276,8 +276,7 @@ TEST_F(TestSdiWithServer, PostRequest) oc::TestDevice::Terminate(); OC_DBG("POST payload: %s", oc::RepPool::GetJson(data->payload).data()); // TODO: fill response in SDI - auto *invoked = static_cast(data->user_data); - *invoked = true; + *static_cast(data->user_data) = true; }; bool invoked = false; diff --git a/security/unittest/sptest.cpp b/security/unittest/sptest.cpp index ccc880c35b..a7aa5ed2dc 100644 --- a/security/unittest/sptest.cpp +++ b/security/unittest/sptest.cpp @@ -371,8 +371,7 @@ TEST_F(TestSecurityProfileWithServer, PostRequest) EXPECT_EQ(OC_STATUS_CHANGED, data->code); oc::TestDevice::Terminate(); OC_DBG("POST payload: %s", oc::RepPool::GetJson(data->payload).data()); - auto *invoked = static_cast(data->user_data); - *invoked = true; + *static_cast(data->user_data) = true; }; bool invoked = false; @@ -399,8 +398,7 @@ TEST_F(TestSecurityProfileWithServer, PostRequest_FailInvalidData) EXPECT_EQ(OC_STATUS_BAD_REQUEST, data->code); oc::TestDevice::Terminate(); OC_DBG("POST payload: %s", oc::RepPool::GetJson(data->payload).data()); - auto *invoked = static_cast(data->user_data); - *invoked = true; + *static_cast(data->user_data) = true; }; bool invoked = false; diff --git a/security/unittest/tls_cert_test.cpp b/security/unittest/tls_cert_test.cpp index ce7cd0dfb7..da37452ec7 100644 --- a/security/unittest/tls_cert_test.cpp +++ b/security/unittest/tls_cert_test.cpp @@ -50,6 +50,8 @@ #include #include +static constexpr size_t kDeviceID = 0; + class TestTlsCertificates : public testing::Test { public: void SetUp() override @@ -66,18 +68,16 @@ class TestTlsCertificates : public testing::Test { cfg.spec_version = "ocf.1.0.0"; cfg.data_model_version = "ocf.res.1.0.0"; oc_device_info_t *info = oc_core_add_new_device(cfg); - EXPECT_NE(nullptr, info); + ASSERT_NE(nullptr, info); oc_sec_svr_create(); - EXPECT_EQ(1, oc_core_get_num_devices()); - device_ = oc_core_get_num_devices() - 1; - EXPECT_GE(device_, 0); + ASSERT_EQ(1, oc_core_get_num_devices()); - ASSERT_TRUE(mfgcert_.Add(device_)); - ASSERT_TRUE(subca1_.Add(device_, mfgcert_.CredentialID())); - ASSERT_TRUE(idcert_.Add(device_)); - ASSERT_TRUE(rootca1_.Add(device_)); - ASSERT_TRUE(rootca2_.Add(device_)); + ASSERT_TRUE(mfgcert_.Add(kDeviceID)); + ASSERT_TRUE(subca1_.Add(kDeviceID, mfgcert_.CredentialID())); + ASSERT_TRUE(idcert_.Add(kDeviceID)); + ASSERT_TRUE(rootca1_.Add(kDeviceID)); + ASSERT_TRUE(rootca2_.Add(kDeviceID)); } void TearDown() override @@ -85,7 +85,7 @@ class TestTlsCertificates : public testing::Test { #ifdef OC_HAS_FEATURE_PUSH oc_push_free(); #endif /* OC_HAS_FEATURE_PUSH */ - oc_connectivity_shutdown(device_); + oc_connectivity_shutdown(kDeviceID); oc_sec_svr_free(); oc_tls_shutdown(); oc_core_shutdown(); @@ -94,7 +94,6 @@ class TestTlsCertificates : public testing::Test { oc_network_event_handler_mutex_destroy(); } - int device_{ -1 }; oc::pki::IdentityCertificate mfgcert_{ "pki_certs/ee.pem", "pki_certs/key.pem", true }; oc::pki::IdentityCertificate idcert_{ "pki_certs/certification_tests_ee.pem", @@ -125,38 +124,38 @@ oc_sec_cred_count(size_t device) TEST_F(TestTlsCertificates, ClearCertificates) { // 4 = 2 root certificates + 1 mfg certs + 1 identity certificate - EXPECT_EQ(4, oc_sec_cred_count(device_)); + ASSERT_EQ(4, oc_sec_cred_count(kDeviceID)); oc_sec_cred_clear( - device_, [](const oc_sec_cred_t *, void *) { return false; }, nullptr); - EXPECT_EQ(4, oc_sec_cred_count(device_)); + kDeviceID, [](const oc_sec_cred_t *, void *) { return false; }, nullptr); + EXPECT_EQ(4, oc_sec_cred_count(kDeviceID)); EXPECT_NE(nullptr, - oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), device_)); + oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), kDeviceID)); oc_sec_cred_clear( - device_, + kDeviceID, [](const oc_sec_cred_t *cred, void *data) { const auto *cert = static_cast(data); return cred->credid == cert->CredentialID(); }, &mfgcert_); - EXPECT_EQ(3, oc_sec_cred_count(device_)); + EXPECT_EQ(3, oc_sec_cred_count(kDeviceID)); EXPECT_EQ(nullptr, - oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), device_)); + oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), kDeviceID)); EXPECT_NE(nullptr, - oc_sec_get_cred_by_credid(idcert_.CredentialID(), device_)); + oc_sec_get_cred_by_credid(idcert_.CredentialID(), kDeviceID)); auto removeMfgCert = [](const oc_sec_cred_t *cred, void *) { return cred->credtype == OC_CREDTYPE_CERT && cred->credusage == OC_CREDUSAGE_MFG_CERT; }; - oc_sec_cred_clear(device_, removeMfgCert, nullptr); - EXPECT_EQ(3, oc_sec_cred_count(device_)); + oc_sec_cred_clear(kDeviceID, removeMfgCert, nullptr); + EXPECT_EQ(3, oc_sec_cred_count(kDeviceID)); EXPECT_EQ(nullptr, - oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), device_)); + oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), kDeviceID)); - oc_sec_cred_clear(device_, nullptr, nullptr); - EXPECT_EQ(0, oc_sec_cred_count(device_)); + oc_sec_cred_clear(kDeviceID, nullptr, nullptr); + EXPECT_EQ(0, oc_sec_cred_count(kDeviceID)); } #ifdef OC_TEST @@ -164,18 +163,18 @@ TEST_F(TestTlsCertificates, ClearCertificates) TEST_F(TestTlsCertificates, RemoveIdentityCertificates) { EXPECT_TRUE(oc_tls_validate_identity_certs_consistency()); - EXPECT_TRUE(oc_sec_remove_cred_by_credid(mfgcert_.CredentialID(), device_)); + EXPECT_TRUE(oc_sec_remove_cred_by_credid(mfgcert_.CredentialID(), kDeviceID)); EXPECT_TRUE(oc_tls_validate_identity_certs_consistency()); - EXPECT_TRUE(oc_sec_remove_cred_by_credid(idcert_.CredentialID(), device_)); + EXPECT_TRUE(oc_sec_remove_cred_by_credid(idcert_.CredentialID(), kDeviceID)); EXPECT_TRUE(oc_tls_validate_identity_certs_consistency()); } TEST_F(TestTlsCertificates, RemoveTrustAnchors) { EXPECT_TRUE(oc_tls_validate_trust_anchors_consistency()); - EXPECT_TRUE(oc_sec_remove_cred_by_credid(rootca1_.CredentialID(), device_)); + EXPECT_TRUE(oc_sec_remove_cred_by_credid(rootca1_.CredentialID(), kDeviceID)); EXPECT_TRUE(oc_tls_validate_trust_anchors_consistency()); - EXPECT_TRUE(oc_sec_remove_cred_by_credid(rootca2_.CredentialID(), device_)); + EXPECT_TRUE(oc_sec_remove_cred_by_credid(rootca2_.CredentialID(), kDeviceID)); EXPECT_TRUE(oc_tls_validate_trust_anchors_consistency()); } @@ -203,36 +202,36 @@ test_oc_tls_load_cert_chain(bool exp, size_t device, bool owned) TEST_F(TestTlsCertificates, LoadClientCertificateToMbedtls) { - EXPECT_EQ(4, oc_sec_cred_count(device_)); - test_oc_tls_load_cert_chain_selected(0, device_, mfgcert_.CredentialID(), + ASSERT_EQ(4, oc_sec_cred_count(kDeviceID)); + test_oc_tls_load_cert_chain_selected(0, kDeviceID, mfgcert_.CredentialID(), oc_tls_load_mfg_cert_chain); - test_oc_tls_load_cert_chain_selected(0, device_, -1, + test_oc_tls_load_cert_chain_selected(0, kDeviceID, -1, oc_tls_load_mfg_cert_chain); - test_oc_tls_load_cert_chain_selected(-1, device_, -2, + test_oc_tls_load_cert_chain_selected(-1, kDeviceID, -2, oc_tls_load_mfg_cert_chain); - test_oc_tls_load_cert_chain_selected(0, device_, idcert_.CredentialID(), + test_oc_tls_load_cert_chain_selected(0, kDeviceID, idcert_.CredentialID(), oc_tls_load_identity_cert_chain); - test_oc_tls_load_cert_chain_selected(0, device_, -1, + test_oc_tls_load_cert_chain_selected(0, kDeviceID, -1, oc_tls_load_identity_cert_chain); - test_oc_tls_load_cert_chain_selected(-1, device_, -2, + test_oc_tls_load_cert_chain_selected(-1, kDeviceID, -2, oc_tls_load_identity_cert_chain); oc_tls_select_mfg_cert_chain(-2); oc_tls_select_identity_cert_chain(-1); - test_oc_tls_load_cert_chain(true, device_, true); + test_oc_tls_load_cert_chain(true, kDeviceID, true); oc_tls_select_identity_cert_chain(idcert_.CredentialID()); - test_oc_tls_load_cert_chain(true, device_, true); + test_oc_tls_load_cert_chain(true, kDeviceID, true); oc_tls_select_identity_cert_chain(-2); oc_tls_select_mfg_cert_chain(-1); - test_oc_tls_load_cert_chain(true, device_, true); + test_oc_tls_load_cert_chain(true, kDeviceID, true); oc_tls_select_mfg_cert_chain(mfgcert_.CredentialID()); - test_oc_tls_load_cert_chain(true, device_, true); + test_oc_tls_load_cert_chain(true, kDeviceID, true); oc_tls_select_identity_cert_chain(-2); oc_tls_select_mfg_cert_chain(-2); - test_oc_tls_load_cert_chain(false, device_, true); + test_oc_tls_load_cert_chain(false, kDeviceID, true); } TEST_F(TestTlsCertificates, VerifyCredCerts) @@ -248,13 +247,13 @@ TEST_F(TestTlsCertificates, VerifyCredCerts) // valid - rootca1_ valid_from: 30.11.2018, valid_to: 27.11.2028 oc_sec_cred_t *cred = - oc_sec_get_cred_by_credid(rootca1_.CredentialID(), device_); + oc_sec_get_cred_by_credid(rootca1_.CredentialID(), kDeviceID); EXPECT_NE(nullptr, cred); EXPECT_EQ( 0, oc_cred_verify_certificate_chain(cred, verify_cert_validity, nullptr)); // expired - mfgcert_ valid_from: 14.4.2020, valid_to: 14.5.2020 - cred = oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), device_); + cred = oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), kDeviceID); EXPECT_NE(nullptr, cred); EXPECT_EQ( 1, oc_cred_verify_certificate_chain(cred, verify_cert_validity, nullptr));