diff --git a/.github/workflows/anjay-tests.yml b/.github/workflows/anjay-tests.yml index 630d7ce2..2386dbe3 100644 --- a/.github/workflows/anjay-tests.yml +++ b/.github/workflows/anjay-tests.yml @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # @@ -138,11 +138,12 @@ jobs: CXX: clang++ macOS-compilers-test: - runs-on: macos-12 + runs-on: macos-14 env: CC: ${{ matrix.CC }} CXX: ${{ matrix.CXX }} COMPILER_VERSION: ${{ matrix.COMPILER_VERSION }} + MEM_CHECK_TOOL: ${{ matrix.MEM_CHECK_TOOL }} steps: # NOTE: v2 requires Git 2.18 for submodules, it's not present in the image - uses: actions/checkout@v1 @@ -150,24 +151,29 @@ jobs: submodules: recursive - run: brew update # NOTE: try the brew install command twice to work around "brew link" errors - - run: INSTALL_CMD="brew install openssl $COMPILER_VERSION"; $INSTALL_CMD || $INSTALL_CMD + - run: INSTALL_CMD="brew install python3 openssl ${COMPILER_VERSION:+$COMPILER_VERSION}"; $INSTALL_CMD || $INSTALL_CMD # NOTE: Some tests don't pass on mbedTLS 3.6.2 now, so we need to install an older version # Homebrew only specifiers major version of mbedTLS, so let's pin the version to 3.6.0 manually - run: curl -f https://raw.githubusercontent.com/Homebrew/homebrew-core/219dabf6cab172fb8b62b4d8598e016e190c3c20/Formula/m/mbedtls.rb > /tmp/mbedtls.rb - run: brew install --formula /tmp/mbedtls.rb - run: brew pin mbedtls # NOTE: The above command may have installed a new version of Python, that's why we launch it weirdly - - run: /usr/bin/env python3 -m pip install -r requirements.txt - - run: env JAVA_HOME="$JAVA_HOME_17_X64" ./devconfig --with-asan --without-analysis --no-examples -DWITH_VALGRIND_TRACK_ORIGINS=OFF -DWITH_URL_CHECK=OFF -DWITH_IPV6=OFF + - run: /usr/bin/env python3 -m pip install -r requirements.txt --break-system-packages + - run: env JAVA_HOME="$JAVA_HOME_17_X64" ./devconfig $MEM_CHECK_TOOL --without-analysis --no-examples -DWITH_VALGRIND_TRACK_ORIGINS=OFF -DWITH_URL_CHECK=OFF -DWITH_IPV6=OFF -DMBEDTLS_ROOT_DIR=/opt/homebrew/opt/mbedtls - run: LC_ALL=en_US.UTF-8 make -j - run: LC_ALL=en_US.UTF-8 make check strategy: fail-fast: false matrix: include: - - CC: gcc-12 - CXX: g++-12 - COMPILER_VERSION: gcc@12 + - CC: /opt/homebrew/opt/gcc/bin/gcc-14 + CXX: /opt/homebrew/opt/gcc/bin/g++-14 + COMPILER_VERSION: gcc@14 + MEM_CHECK_TOOL: --without-memcheck + - CC: /opt/homebrew/opt/llvm/bin/clang + CXX: /opt/homebrew/opt/llvm/bin/clang++ + COMPILER_VERSION: llvm + MEM_CHECK_TOOL: --with-asan - CC: cc CXX: c++ - COMPILER_VERSION: llvm + MEM_CHECK_TOOL: --with-asan diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index bc19e748..6e4615ca 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/.gitmodules b/.gitmodules index 9d09d0cb..4d44b11d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,7 +4,7 @@ ignore = untracked [submodule "tests/integration/framework/nsh-lwm2m/powercmd"] path = tests/integration/framework/nsh-lwm2m/powercmd - url = https://github.com/dextero/powercmd + url = https://github.com/dextero/powercmd.git [submodule "deps/avs_commons"] path = deps/avs_commons url = https://github.com/AVSystem/avs_commons.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e82faa1..31fe7f7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## 3.9.0 (February 28th, 2025) + +### Features + +- LwM2M Gateway functionality was added. To see the feature description, API + documentation and tutorial on its usage, see Anjay docs +- Added a ``coap_downloader_retry_count`` and ``coap_downloader_retry_delay`` + configuration options that allow to resume the CoAP download process in case + of network errors. + +### Improvements + +- Extended the functionality of the flag enabling Connection ID to also include + connections to the file download CoAP server, in addition to the LwM2M server +- Migrated GitHub Actions tests on macOS to the macos-14 runner. +- Refactored test_ghactions.py. +- Added Github Actions test on macOS for the AppleClang. + +### Bugfixes + +- Ensured that Github Actions tests on macOS actually runs on LLVM installed + from Homebrew instead of AppleClang. +- Minor fix in the devconfig. + ## 3.8.1 (November 13th, 2024) ### Improvements diff --git a/CMakeLists.txt b/CMakeLists.txt index ffc5144f..51625c0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # @@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.6.0) project(anjay C) -set(ANJAY_VERSION "3.8.1" CACHE STRING "Anjay library version") +set(ANJAY_VERSION "3.9.0" CACHE STRING "Anjay library version") set(ANJAY_BINARY_VERSION 1.0.0) set(ANJAY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") @@ -272,6 +272,7 @@ option(WITHOUT_IP_STICKINESS "Disable support for IP stickiness" OFF) option(WITHOUT_COMPOSITE_OPERATIONS "Disable composite operations" OFF) cmake_dependent_option(WITH_SENML_JSON "Enable support for SenML JSON content format" ON WITH_LWM2M11 OFF) cmake_dependent_option(WITH_CBOR "Enable support for CBOR and SenML CBOR content formats" ON WITH_LWM2M11 OFF) +cmake_dependent_option(WITH_LWM2M_GATEWAY "Enable support /25 LwM2M Gateway Object" OFF "WITH_LWM2M11;NOT WITH_CORE_PERSISTENCE" OFF) cmake_dependent_option(WITH_SEND "Enable support for LwM2M 1.1 Send operation" ON "WITH_CBOR OR WITH_SENML_JSON" OFF) option(WITHOUT_QUEUE_MODE_AUTOCLOSE "Disable automatic closing of server connection sockets after MAX_TRANSMIT_WAIT of inactivity" OFF) @@ -352,6 +353,7 @@ add_library(anjay include_public/anjay/io.h include_public/anjay/ipso_objects.h include_public/anjay/ipso_objects_v2.h + include_public/anjay/lwm2m_gateway.h include_public/anjay/lwm2m_send.h include_public/anjay/security.h include_public/anjay/server.h @@ -492,6 +494,7 @@ add_library(anjay src/modules/ipso/anjay_ipso_button.c src/modules/ipso_v2/anjay_ipso_v2_3d_sensor.c src/modules/ipso_v2/anjay_ipso_v2_basic_sensor.c + src/modules/lwm2m_gateway/anjay_lwm2m_gateway.c src/modules/security/anjay_mod_security.c src/modules/security/anjay_mod_security.h src/modules/security/anjay_security_persistence.c @@ -561,6 +564,7 @@ set(ANJAY_WITH_SEND "${WITH_SEND}") set(ANJAY_WITH_SENML_JSON "${WITH_SENML_JSON}") set(ANJAY_WITHOUT_QUEUE_MODE_AUTOCLOSE "${WITHOUT_QUEUE_MODE_AUTOCLOSE}") set(ANJAY_WITH_CONN_STATUS_API "${WITH_CONN_STATUS_API}") +set(ANJAY_WITH_LWM2M_GATEWAY "${WITH_LWM2M_GATEWAY}") configure_file(include_public/anjay/anjay_config.h.in include_public/anjay/anjay_config.h) @@ -870,6 +874,10 @@ if(WITH_SEND) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/include_public/anjay/lwm2m_send.h" DESTINATION include/anjay) endif() +if(WITH_LWM2M_GATEWAY) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/include_public/anjay/lwm2m_gateway.h" + DESTINATION include/anjay) +endif() if(WITH_MODULE_access_control) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/include_public/anjay/access_control.h" DESTINATION include/anjay) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index d0f80e50..c03865e2 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/Dockerfile b/Dockerfile index 1a93fcf0..5fcee85f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/NOTICE b/NOTICE index 2fec434f..70458bce 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Anjay -Copyright 2017-2024 AVSystem +Copyright 2017-2025 AVSystem This product includes software developed at AVSystem (www.avsystem.com). diff --git a/README.md b/README.md index 3dc8afff..d9d80988 100644 --- a/README.md +++ b/README.md @@ -117,9 +117,12 @@ This version includes full support for OMA LwM2M TS 1.1 features. Some features, - Server - Firmware Update - IPSO single and three-axis sensor objects + - LwM2M Gateway - Stream-oriented persistence API +- [LwM2M Gateway functionality](https://www.openmobilealliance.org/release/LwM2M_Gateway/V1_1_1-20240312-A/OMA-TS-LWM2M_Gateway-V1_1_1-20240312-A.pdf) + ## About OMA LwM2M OMA LwM2M is a remote device management and telemetry protocol designed to conserve network resources. It is especially suitable for constrained wireless devices, where network communication is a major factor affecting battery life. LwM2M features secure (DTLS-encrypted) methods of remote bootstrapping, configuration and notifications over UDP or SMS. diff --git a/cmake/anjay-config.cmake.in b/cmake/anjay-config.cmake.in index 006e2c28..ba44fc91 100644 --- a/cmake/anjay-config.cmake.in +++ b/cmake/anjay-config.cmake.in @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/cmake/anjay-version.cmake.in b/cmake/anjay-version.cmake.in index a058a321..5ef89737 100644 --- a/cmake/anjay-version.cmake.in +++ b/cmake/anjay-version.cmake.in @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/cmake/sphinx.cmake b/cmake/sphinx.cmake index 29bf736b..beee46e5 100644 --- a/cmake/sphinx.cmake +++ b/cmake/sphinx.cmake @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/cmake/toolchain/afl-gcc.cmake b/cmake/toolchain/afl-gcc.cmake index b83bb479..51d52ce1 100644 --- a/cmake/toolchain/afl-gcc.cmake +++ b/cmake/toolchain/afl-gcc.cmake @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 13482f69..5c6b118e 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # @@ -53,6 +53,13 @@ if (${ANJAY_WITH_MODULE_SW_MGMT}) set(SOURCES ${SOURCES} software_mgmt.c) endif() +if (${ANJAY_WITH_LWM2M_GATEWAY}) + set(SOURCES ${SOURCES} lwm2m_gateway.c + objects/gateway_end_devices/temperature_object.c + objects/gateway_end_devices/push_button_object.c + objects/gateway_end_devices/binary_app_data_container.c + ) +endif() if(NOT WIN32) set(SOURCES ${SOURCES} objects/ip_ping.c) diff --git a/demo/advanced_firmware_update.c b/demo/advanced_firmware_update.c index f201862e..5978b0dd 100644 --- a/demo/advanced_firmware_update.c +++ b/demo/advanced_firmware_update.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/advanced_firmware_update.h b/demo/advanced_firmware_update.h index e66eb334..afad5dd1 100644 --- a/demo/advanced_firmware_update.h +++ b/demo/advanced_firmware_update.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/advanced_firmware_update_addimg.c b/demo/advanced_firmware_update_addimg.c index f856ecd0..befa8ee3 100644 --- a/demo/advanced_firmware_update_addimg.c +++ b/demo/advanced_firmware_update_addimg.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/advanced_firmware_update_app.c b/demo/advanced_firmware_update_app.c index 16a1566b..27018333 100644 --- a/demo/advanced_firmware_update_app.c +++ b/demo/advanced_firmware_update_app.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/demo.c b/demo/demo.c index 06fcb93a..49fd52d2 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -63,6 +63,10 @@ # include #endif // ANJAY_WITH_MODULE_FACTORY_PROVISIONING +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include "lwm2m_gateway.h" +#endif // ANJAY_WITH_LWM2M_GATEWAY + static int security_object_reload(anjay_demo_t *demo) { #ifdef WITH_DEMO_USE_STANDALONE_OBJECTS standalone_security_object_purge(demo->security_obj_ptr); @@ -279,6 +283,9 @@ static void demo_delete(anjay_demo_t *demo) { } } +#ifdef ANJAY_WITH_LWM2M_GATEWAY + lwm2m_gateway_cleanup(demo->anjay); +#endif // ANJAY_WITH_LWM2M_GATEWAY if (demo->anjay) { anjay_delete(demo->anjay); } @@ -576,6 +583,11 @@ static int demo_init(anjay_demo_t *demo, cmdline_args_t *cmdline_args) { .server_connection_status_cb = server_connection_status_change_callback, .server_connection_status_cb_arg = demo, #endif // ANJAY_WITH_CONN_STATUS_API +#ifdef ANJAY_WITH_DOWNLOADER + .coap_downloader_retry_count = + cmdline_args->coap_downloader_retry_count, + .coap_downloader_retry_delay = cmdline_args->coap_downloader_retry_delay +#endif // ANJAY_WITH_DOWNLOADER }; #ifdef ANJAY_WITH_LWM2M11 @@ -702,6 +714,13 @@ static int demo_init(anjay_demo_t *demo, cmdline_args_t *cmdline_args) { NULL, event_log_object_release)) { return -1; } +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (cmdline_args->lwm2m_gateway_enabled) { + if (lwm2m_gateway_setup(demo->anjay)) { + return -1; + } + } +#endif // ANJAY_WITH_LWM2M_GATEWAY if (cmdline_args->location_csv && location_open_csv(demo_find_object(demo, DEMO_OID_LOCATION), diff --git a/demo/demo.h b/demo/demo.h index eba34152..fbdc8896 100644 --- a/demo/demo.h +++ b/demo/demo.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/demo_args.c b/demo/demo_args.c index 88ac87bc..6eee6bfc 100644 --- a/demo/demo_args.c +++ b/demo/demo_args.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -598,6 +598,16 @@ static void print_help(const struct option *options) { { 348, NULL, NULL, "Treat failures of the \"connect\" socket operation (e.g. (D)TLS " "handshake failures) as a failed LwM2M Register operation." }, +#ifdef ANJAY_WITH_LWM2M_GATEWAY + { 'g', NULL, NULL, + "Enable LwM2M Gateway funcitonality and register example End Devices " + "with their objects" }, +#endif // ANJAY_WITH_LWM2M_GATEWAY +#ifdef ANJAY_WITH_DOWNLOADER + { 349, "RETRY COUNT", NULL, "Number of CoAP downloader retry" }, + { 350, "RETRY DELAY", NULL, + "Delay (in seconds) between CoAP downloader retry" } +#endif // ANJAY_WITH_DOWNLOADER }; const size_t screen_width = get_screen_width(); @@ -999,6 +1009,13 @@ int demo_parse_argv(cmdline_args_t *parsed_args, int argc, char *argv[]) { # endif // ANJAY_WITH_DOWNLOADER #endif // ANJAY_WITH_MODULE_SW_MGMT { "connection-error-is-registration-failure", no_argument, 0, 348 }, +#ifdef ANJAY_WITH_LWM2M_GATEWAY + { "lwm2m_gateway", no_argument, 0, 'g' }, +#endif // ANJAY_WITH_LWM2M_GATEWAY +#ifdef ANJAY_WITH_DOWNLOADER + {"coap-downloader-retry-count", required_argument, 0, 349}, + {"coap-downloader-retry-delay", required_argument, 0, 350}, +#endif // ANJAY_WITH_DOWNLOADER { 0, 0, 0, 0 } // clang-format on }; @@ -2009,6 +2026,32 @@ int demo_parse_argv(cmdline_args_t *parsed_args, int argc, char *argv[]) { case 348: parsed_args->connection_error_is_registration_failure = true; break; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + case 'g': { + parsed_args->lwm2m_gateway_enabled = true; + break; + } +#endif // ANJAY_WITH_LWM2M_GATEWAY +#ifdef ANJAY_WITH_DOWNLOADER + case 349: + if (parse_size(optarg, &parsed_args->coap_downloader_retry_count)) { + demo_log(ERROR, "Invalid retry count value: %s", optarg); + goto finish; + } + break; + case 350: { + double delay_s; + if (parse_double(optarg, &delay_s) || !isfinite(delay_s) + || delay_s <= 0.0) { + demo_log(ERROR, "Expected retry delay to be a positive " + "floating point number"); + goto finish; + } + parsed_args->coap_downloader_retry_delay = + avs_time_duration_from_fscalar(delay_s, AVS_TIME_S); + break; + } +#endif // ANJAY_WITH_DOWNLOADER case 0: goto process; } diff --git a/demo/demo_args.h b/demo/demo_args.h index a38a6207..a7f76331 100644 --- a/demo/demo_args.h +++ b/demo/demo_args.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -51,6 +51,10 @@ typedef struct cmdline_args { int32_t msg_cache_size; bool confirmable_notifications; bool disable_stdin; +#ifdef ANJAY_WITH_DOWNLOADER + size_t coap_downloader_retry_count; + avs_time_duration_t coap_downloader_retry_delay; +#endif // ANJAY_WITH_DOWNLOADER #ifdef ANJAY_WITH_MODULE_FW_UPDATE const char *fw_updated_marker_path; avs_net_security_info_t fw_security_info; @@ -187,6 +191,9 @@ typedef struct cmdline_args { #endif // defined(ANJAY_WITH_LWM2M11) && defined(WITH_AVS_COAP_TCP) AVS_LIST(anjay_demo_allocated_buffer_t) allocated_buffers; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + bool lwm2m_gateway_enabled; +#endif // ANJAY_WITH_LWM2M_GAYEWAY } cmdline_args_t; int demo_parse_argv(cmdline_args_t *parsed_args, int argc, char **argv); diff --git a/demo/demo_cmds.c b/demo/demo_cmds.c index 38f41b5d..b536a347 100644 --- a/demo/demo_cmds.c +++ b/demo/demo_cmds.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -40,10 +41,33 @@ # include #endif // ANJAY_WITH_SEND +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include "lwm2m_gateway.h" +# include +#endif // ANJAY_WITH_LWM2M_GATEWAY + #include #define MAX_SEND_RESOURCES 32 +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# define LWM2M_GATEWAY_PATH_LOG_PART " | dev_id /OID/IID/RID" +# define LWM2M_GATEWAY_DEVID_LOG_PART \ + " dev_id must be in range " \ + "[0," AVS_QUOTE_MACRO(LWM2M_GATEWAY_END_DEVICE_RANGE) "]." + +static inline int verify_device_count(anjay_iid_t end_dev_iid) { + if (end_dev_iid >= LWM2M_GATEWAY_END_DEVICE_COUNT) { + demo_log(ERROR, LWM2M_GATEWAY_DEVID_LOG_PART); + return -1; + } + return 0; +} +#else // ANJAY_WITH_LWM2M_GATEWAY +# define LWM2M_GATEWAY_PATH_LOG_PART "" +# define LWM2M_GATEWAY_DEVID_LOG_PART "" +#endif // ANJAY_WITH_LWM2M_GATEWAY + static int parse_ssid(const char *text, anjay_ssid_t *out_ssid) { unsigned id; if (sscanf(text, "%u", &id) < 1 || id > UINT16_MAX) { @@ -477,9 +501,24 @@ anjay_send_func_t(anjay_t *anjay, void *finished_handler_data); static void print_send_usage(const char *command) { - demo_log(WARNING, "%s usage: %s SSID [/OID/IID/RID [...]]", command, - command); + demo_log(WARNING, + "%s usage: %s SSID (/OID/IID/RID" LWM2M_GATEWAY_PATH_LOG_PART + ") [...]", + command, command); +} + +# ifdef ANJAY_WITH_LWM2M_GATEWAY +static bool all_paths_have_same_iid(const anjay_iid_t *iids, + size_t paths_count) { + anjay_iid_t iid = iids[0]; + for (size_t i = 1; i < paths_count; i++) { + if (iids[i] != iid) { + return false; + } + } + return true; } +# endif // ANJAY_WITH_LWM2M_GATEWAY static void cmd_send_impl(anjay_demo_t *demo, const char *command, @@ -499,6 +538,10 @@ static void cmd_send_impl(anjay_demo_t *demo, } anjay_send_resource_path_t paths[MAX_SEND_RESOURCES]; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + anjay_iid_t gateway_iids[MAX_SEND_RESOURCES]; + memset(gateway_iids, ANJAY_ID_INVALID, sizeof(gateway_iids)); +# endif // ANJAY_WITH_LWM2M_GATEWAY size_t paths_count = 0; while ((args_string = strchr(args_string, ' '))) { @@ -512,18 +555,59 @@ static void cmd_send_impl(anjay_demo_t *demo, anjay_oid_t oid; anjay_iid_t iid; anjay_rid_t rid; - if (sscanf(args_string, "/%" SCNu16 "/%" SCNu16 "/%" SCNu16, &oid, &iid, - &rid) - != 3) { + int consumed; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + anjay_iid_t gateway_iid; + if (sscanf(args_string, + "%" SCNu16 " /%" SCNu16 "/%" SCNu16 "/%" SCNu16 "%n", + &gateway_iid, &oid, &iid, &rid, &consumed) + == 4) { + gateway_iids[paths_count] = gateway_iid; + } else +# endif // ANJAY_WITH_LWM2M_GATEWAY + if (sscanf(args_string, + "/%" SCNu16 "/%" SCNu16 "/%" SCNu16 "%n", &oid, &iid, + &rid, &consumed) + != 3) { print_send_usage(command); anjay_send_batch_builder_cleanup(&builder); return; } + args_string += consumed; paths[paths_count++] = (anjay_send_resource_path_t) { oid, iid, rid }; } int result = 0; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (paths_count > 1 && all_paths_have_same_iid(gateway_iids, paths_count)) { + // For this function timestamp value is encoded only once - this is + // required by Integration Tests + if (gateway_iids[0] == ANJAY_ID_INVALID) { + result = anjay_send_batch_data_add_current_multiple( + builder, demo->anjay, paths, paths_count); + } else { + result = anjay_lwm2m_gateway_send_batch_data_add_current_multiple( + builder, demo->anjay, gateway_iids[0], paths, paths_count); + } + } else { + for (size_t i = 0; i < paths_count; i++) { + if (gateway_iids[i] == ANJAY_ID_INVALID) { + result = anjay_send_batch_data_add_current(builder, demo->anjay, + paths[i].oid, + paths[i].iid, + paths[i].rid); + } else { + result = anjay_lwm2m_gateway_send_batch_data_add_current( + builder, demo->anjay, gateway_iids[i], paths[i].oid, + paths[i].iid, paths[i].rid); + } + if (result) { + break; + } + } + } +# else // ANJAY_WITH_LWM2M_GATEWAY if (paths_count == 1) { result = anjay_send_batch_data_add_current( builder, demo->anjay, paths[0].oid, paths[0].iid, paths[0].rid); @@ -532,7 +616,7 @@ static void cmd_send_impl(anjay_demo_t *demo, anjay_send_batch_data_add_current_multiple(builder, demo->anjay, paths, paths_count); } - +# endif // ANJAY_WITH_LWM2M_GATEWAY if (result) { demo_log(ERROR, "Error during reading values from data model"); anjay_send_batch_builder_cleanup(&builder); @@ -999,35 +1083,24 @@ static void cmd_set_queue_mode_preference(anjay_demo_t *demo, #endif // ANJAY_WITH_LWM2M11 #ifdef ANJAY_WITH_OBSERVATION_STATUS -static void cmd_observation_status(anjay_demo_t *demo, - const char *args_string) { - anjay_oid_t oid; - anjay_iid_t iid; - anjay_rid_t rid; - if (sscanf(args_string, " /%" SCNu16 "/%" SCNu16 "/%" SCNu16, &oid, &iid, - &rid) - != 3) { - demo_log(WARNING, - "observation-status usage: observation_status /OID/IID/RID"); - return; - } - anjay_resource_observation_status_t status = - anjay_resource_observation_status(demo->anjay, oid, iid, rid); +static void +log_observation_status(const anjay_resource_observation_status_t *status) { demo_log(INFO, "anjay_resource_observation_status, is_observed == %s, " "min_period == %" PRId32 ", max_eval_period == %" PRId32, - status.is_observed ? "true" : "false", status.min_period, - status.max_eval_period); + status->is_observed ? "true" : "false", status->min_period, + status->max_eval_period); + # if (ANJAY_MAX_OBSERVATION_SERVERS_REPORTED_NUMBER > 0) - if (status.servers_number > 0) { + if (status->servers_number > 0) { char *ssid_list = (char *) avs_calloc((AVS_UINT_STR_BUF_SIZE(anjay_ssid_t) + 2) - * status.servers_number, + * status->servers_number, 1); if (ssid_list) { - for (uint16_t i = 0; i < status.servers_number; i++) { + for (uint16_t i = 0; i < status->servers_number; i++) { char ssid_string[AVS_UINT_STR_BUF_SIZE(anjay_ssid_t) + 2]; - sprintf(ssid_string, " %" PRIu16 ",", status.servers[i]); + sprintf(ssid_string, " %" PRIu16 ",", status->servers[i]); strcat(ssid_list, ssid_string); } ssid_list[strlen(ssid_list) - 1] = '\0'; // remove trailing comma @@ -1036,7 +1109,41 @@ static void cmd_observation_status(anjay_demo_t *demo, avs_free(ssid_list); } } -# endif //(ANJAY_MAX_OBSERVATION_SERVERS_REPORTED_NUMBER > 0) +# endif // (ANJAY_MAX_OBSERVATION_SERVERS_REPORTED_NUMBER > 0) +} + +static void cmd_observation_status(anjay_demo_t *demo, + const char *args_string) { + anjay_oid_t oid; + anjay_iid_t iid; + anjay_rid_t rid; + +# ifdef ANJAY_WITH_LWM2M_GATEWAY + anjay_iid_t end_dev_iid = ANJAY_ID_INVALID; + if (sscanf(args_string, " %" SCNu16 " /%" SCNu16 "/%" SCNu16 "/%" SCNu16, + &end_dev_iid, &oid, &iid, &rid) + == 4) { + if (verify_device_count(end_dev_iid)) { + return; + } + // even if there is no end-device with given dev id, we still want to + // print that such resource is not observed due to tests + anjay_resource_observation_status_t status = + anjay_lwm2m_gateway_resource_observation_status( + demo->anjay, end_dev_iid, oid, iid, rid); + log_observation_status(&status); + } else +# endif // ANJAY_WITH_LWM2M_GATEWAY + if (sscanf(args_string, " /%" SCNu16 "/%" SCNu16 "/%" SCNu16, &oid, + &iid, &rid) + == 3) { + anjay_resource_observation_status_t status = + anjay_resource_observation_status(demo->anjay, oid, iid, rid); + log_observation_status(&status); + } else { + demo_log(WARNING, "observation-status usage: " + "(/OID/IID/RID" LWM2M_GATEWAY_PATH_LOG_PART ")"); + } } #endif // ANJAY_WITH_OBSERVATION_STATUS @@ -1448,6 +1555,87 @@ static void cmd_get_server_connection_status(anjay_demo_t *demo, } #endif // ANJAY_WITH_CONN_STATUS_API +#ifdef ANJAY_WITH_LWM2M_GATEWAY +static void cmd_setup_end_device(anjay_demo_t *demo, const char *args_string) { + anjay_iid_t end_dev_iid; + if (sscanf(args_string, " %" SCNu16, &end_dev_iid) != 1) { + demo_log(ERROR, "invalid format"); + return; + } + if (verify_device_count(end_dev_iid)) { + return; + } + if (lwm2m_gateway_setup_end_device(demo->anjay, end_dev_iid)) { + demo_log(ERROR, "Failed to set up Gateway End Device id = %" PRIu16, + end_dev_iid); + } else { + demo_log(INFO, "Successfully set up Gateway End Device id = %" PRIu16, + end_dev_iid); + } +} + +static void cmd_cleanup_end_device(anjay_demo_t *demo, + const char *args_string) { + anjay_iid_t end_dev_iid; + if (sscanf(args_string, " %" SCNu16, &end_dev_iid) < 1) { + demo_log(ERROR, "invalid format"); + return; + } + if (verify_device_count(end_dev_iid)) { + return; + } + lwm2m_gateway_cleanup_end_device(demo->anjay, end_dev_iid); +} + +static void cmd_press_button_end_device(anjay_demo_t *demo, + const char *args_string) { + (void) demo; + anjay_iid_t end_dev_iid; + if (sscanf(args_string, " %" SCNu16, &end_dev_iid) < 1) { + demo_log(ERROR, "invalid format"); + return; + } + if (verify_device_count(end_dev_iid)) { + return; + } + lwm2m_gateway_press_button_end_device(demo->anjay, end_dev_iid); +} + +static void cmd_release_button_end_device(anjay_demo_t *demo, + const char *args_string) { + (void) demo; + anjay_iid_t end_dev_iid; + if (sscanf(args_string, " %" SCNu16, &end_dev_iid) < 1) { + demo_log(ERROR, "invalid format"); + return; + } + if (verify_device_count(end_dev_iid)) { + return; + } + lwm2m_gateway_release_button_end_device(demo->anjay, end_dev_iid); +} + +static void cmd_badc_write_end_device(anjay_demo_t *demo, + const char *args_string) { + anjay_iid_t iid; + anjay_riid_t riid; + int length; + anjay_riid_t end_dev_iid; + if (sscanf(args_string, " %" SCNu16 " %" SCNu16 " %" SCNu16 " %n", + &end_dev_iid, &iid, &riid, &length) + < 3) { + demo_log(ERROR, "invalid format"); + return; + } + + if (verify_device_count(end_dev_iid)) { + return; + } + lwm2m_gateway_binary_app_data_container_write(demo->anjay, end_dev_iid, iid, + riid, &args_string[length]); +} +#endif // ANJAY_WITH_LWM2M_GATEWAY + static void cmd_help(anjay_demo_t *demo, const char *args_string); struct cmd_handler_def { @@ -1535,11 +1723,13 @@ static const struct cmd_handler_def COMMAND_HANDLERS[] = { CMD_HANDLER("notify", "", cmd_notify, "Executes anjay_notify_* on a specified path"), #ifdef ANJAY_WITH_SEND - CMD_HANDLER("send_deferrable", "SSID [/OID/IID/RID [...]]", + CMD_HANDLER("send_deferrable", "SSID (/OID/IID/RID" LWM2M_GATEWAY_PATH_LOG_PART ") [...]", cmd_send_deferrable, - "Executes anjay_send_deferrable on a specified path"), - CMD_HANDLER("send", "SSID [/OID/IID/RID [...]]", cmd_send, - "Executes anjay_send on a specified path"), + "Executes anjay_send_deferrable on a specified path." LWM2M_GATEWAY_DEVID_LOG_PART + "\ne.g. send_deferrable 1 /3/0/0"), + CMD_HANDLER("send", "SSID (/OID/IID/RID" LWM2M_GATEWAY_PATH_LOG_PART ") [...]", cmd_send, + "Executes anjay_send on a specified path." LWM2M_GATEWAY_DEVID_LOG_PART + "\ne.g. send 1 /3/0/0"), #endif // ANJAY_WITH_SEND CMD_HANDLER("unregister-object", "oid", cmd_unregister_object, "Unregister an LwM2M Object"), @@ -1580,8 +1770,10 @@ static const struct cmd_handler_def COMMAND_HANDLERS[] = { "Advances real and monotonic clock readings by specified " "number of seconds"), #ifdef ANJAY_WITH_OBSERVATION_STATUS - CMD_HANDLER("observation-status", "/OID/IID/RID", cmd_observation_status, - "Queries the observation status of a given Resource"), + CMD_HANDLER("observation-status", "(/OID/IID/RID" LWM2M_GATEWAY_PATH_LOG_PART ")", + cmd_observation_status, + "Queries the observation status of a given Resource." + LWM2M_GATEWAY_DEVID_LOG_PART), #endif // ANJAY_WITH_OBSERVATION_STATUS CMD_HANDLER("badc-write", "IID RIID value", cmd_badc_write, "Writes new value to Binary App Data Container object"), @@ -1689,6 +1881,23 @@ static const struct cmd_handler_def COMMAND_HANDLERS[] = { "Displays current connection status for the server with SSID " "specified by the argument."), #endif // ANJAY_WITH_CONN_STATUS_API +#ifdef ANJAY_WITH_LWM2M_GATEWAY + CMD_HANDLER("gw_register", "dev_id", + cmd_setup_end_device, + "Registers End Device in LwM2M gateway context." LWM2M_GATEWAY_DEVID_LOG_PART), + CMD_HANDLER("gw_deregister", "dev_id", + cmd_cleanup_end_device, + "Deregisters End Device in LwM2M gateway context. " LWM2M_GATEWAY_DEVID_LOG_PART), + CMD_HANDLER("gw_press_button", "dev_id", + cmd_press_button_end_device, + "Simulates pressing the button on End Device. " LWM2M_GATEWAY_DEVID_LOG_PART), + CMD_HANDLER("gw_release_button", "dev_id", + cmd_release_button_end_device, + "Simulates releasing the button on End Device. " LWM2M_GATEWAY_DEVID_LOG_PART), + CMD_HANDLER("gw-badc-write", "dev_id IID RIID value", + cmd_badc_write_end_device, + "Writes new value to Binary App Data Container object on End Device. " LWM2M_GATEWAY_DEVID_LOG_PART), +#endif // ANJAY_WITH_LWM2M_GATEWAY CMD_HANDLER("help", "", cmd_help, "Prints this message") // clang-format on }; diff --git a/demo/demo_cmds.h b/demo/demo_cmds.h index c39969d1..eb013b48 100644 --- a/demo/demo_cmds.h +++ b/demo/demo_cmds.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/demo_time.c b/demo/demo_time.c index 21ddcd7a..0ee72bf7 100644 --- a/demo/demo_time.c +++ b/demo/demo_time.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/demo_utils.c b/demo/demo_utils.c index 8985ff5b..a219f9d7 100644 --- a/demo/demo_utils.c +++ b/demo/demo_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/demo_utils.h b/demo/demo_utils.h index 63a3a5b2..8c77f271 100644 --- a/demo/demo_utils.h +++ b/demo/demo_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/firmware_update.c b/demo/firmware_update.c index b6aba921..bdcc9012 100644 --- a/demo/firmware_update.c +++ b/demo/firmware_update.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/firmware_update.h b/demo/firmware_update.h index a262476f..95efaccf 100644 --- a/demo/firmware_update.h +++ b/demo/firmware_update.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/lwm2m_gateway.c b/demo/lwm2m_gateway.c new file mode 100644 index 00000000..7826935d --- /dev/null +++ b/demo/lwm2m_gateway.c @@ -0,0 +1,236 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ +#include +#ifdef ANJAY_WITH_LWM2M_GATEWAY + +# include + +# include +# include + +# include +# include + +# include "demo_utils.h" +# include "lwm2m_gateway.h" +# include "objects/gateway_end_devices/binary_app_data_container.h" +# include "objects/gateway_end_devices/push_button_object.h" +# include "objects/gateway_end_devices/temperature_object.h" + +static struct end_dev { + const anjay_dm_object_def_t **push_button_object; + const anjay_dm_object_def_t **temperature_object; + const anjay_dm_object_def_t **binary_app_data_container; + const char *device_id; + // lwm2m_gateway_setup() sets the IDs equally to this array index, but + // ANJAY_ID_INVALID set to this field helps determining whether the device + // is initialized or not + anjay_iid_t end_dev_iid; + avs_sched_handle_t notify_job_handle; +} devs[] = { + { + .device_id = "urn:dev:001234", + .end_dev_iid = ANJAY_ID_INVALID + }, + { + .device_id = "urn:dev:556789", + .end_dev_iid = ANJAY_ID_INVALID + } +}; + +AVS_STATIC_ASSERT(AVS_ARRAY_SIZE(devs) == LWM2M_GATEWAY_END_DEVICE_COUNT, + changing_dev_count_requires_setting_dev_id); +AVS_STATIC_ASSERT(LWM2M_GATEWAY_END_DEVICE_COUNT - 1 + == LWM2M_GATEWAY_END_DEVICE_RANGE, + end_dev_range_equal_to_dev_count_minus_one); + +typedef struct { + anjay_t *anjay; + struct end_dev *dev; +} notify_job_args_t; + +// Periodically notifies the library about Resource value changes +static void notify_job(avs_sched_t *sched, const void *args_ptr) { + const notify_job_args_t *args = (const notify_job_args_t *) args_ptr; + + temperature_object_update_value(args->anjay, args->dev->temperature_object); + + // Schedule run of the same function after 1 second + AVS_SCHED_DELAYED(sched, &args->dev->notify_job_handle, + avs_time_duration_from_scalar(1, AVS_TIME_S), notify_job, + args, sizeof(*args)); +} + +static struct end_dev *get_dev_ptr(anjay_iid_t end_dev_iid) { + for (uint16_t i = 0; i < AVS_ARRAY_SIZE(devs); i++) { + if (devs[i].end_dev_iid == end_dev_iid) { + return &devs[i]; + } + } + return NULL; +} + +int lwm2m_gateway_setup_end_device(anjay_t *anjay, anjay_iid_t end_dev_iid) { + if (end_dev_iid >= LWM2M_GATEWAY_END_DEVICE_COUNT) { + // invalid iid + return -1; + } + struct end_dev *dev = &devs[end_dev_iid]; + + if (dev->end_dev_iid != ANJAY_ID_INVALID) { + demo_log(ERROR, "End Device id = %" PRIu16 " already registered!", + end_dev_iid); + return -1; + } + + if (anjay_lwm2m_gateway_register_device(anjay, dev->device_id, + &dev->end_dev_iid)) { + demo_log(ERROR, "Failed to add End Device id = %" PRIu16, end_dev_iid); + return -1; + } + + dev->push_button_object = push_button_object_create(dev->end_dev_iid); + if (!dev->push_button_object + || anjay_lwm2m_gateway_register_object(anjay, dev->end_dev_iid, + dev->push_button_object)) { + demo_log(ERROR, "Failed to create Push Button Object %" PRIu16, + end_dev_iid); + return -1; + } + + dev->temperature_object = temperature_object_create(dev->end_dev_iid); + if (!dev->temperature_object + || anjay_lwm2m_gateway_register_object(anjay, dev->end_dev_iid, + dev->temperature_object)) { + demo_log(ERROR, "Failed to create Temperature Object %" PRIu16, + end_dev_iid); + return -1; + } + + dev->binary_app_data_container = + gw_binary_app_data_container_object_create(dev->end_dev_iid); + if (!dev->binary_app_data_container + || anjay_lwm2m_gateway_register_object( + anjay, dev->end_dev_iid, + dev->binary_app_data_container)) { + demo_log(ERROR, + "Failed to create Binary Data Container Object %" PRIu16, + end_dev_iid); + return -1; + } + + notify_job(anjay_get_scheduler(anjay), + &(const notify_job_args_t) { + .anjay = anjay, + .dev = dev + }); + return 0; +} + +void lwm2m_gateway_cleanup_end_device(anjay_t *anjay, anjay_iid_t end_dev_iid) { + if (end_dev_iid >= LWM2M_GATEWAY_END_DEVICE_COUNT) { + // invalid iid + return; + } + struct end_dev *dev = &devs[end_dev_iid]; + + if (dev->end_dev_iid == ANJAY_ID_INVALID) { + // device already deregistered + return; + } + + if (anjay_lwm2m_gateway_unregister_object(anjay, dev->end_dev_iid, + dev->push_button_object)) { + AVS_UNREACHABLE("Failed to unregister Time Object"); + } + + if (anjay_lwm2m_gateway_unregister_object(anjay, dev->end_dev_iid, + dev->temperature_object)) { + AVS_UNREACHABLE("Failed to unregister Temperature Object"); + } + + if (anjay_lwm2m_gateway_unregister_object(anjay, dev->end_dev_iid, + dev->binary_app_data_container)) { + AVS_UNREACHABLE( + "Failed to unregister Binary App Data Container Object"); + } + + if (anjay_lwm2m_gateway_deregister_device(anjay, dev->end_dev_iid)) { + AVS_UNREACHABLE("Failed to deregister End Device"); + } + + avs_sched_del(&dev->notify_job_handle); + push_button_object_release(dev->push_button_object); + temperature_object_release(dev->temperature_object); + gw_binary_app_data_container_object_release(dev->binary_app_data_container); + dev->end_dev_iid = ANJAY_ID_INVALID; +} + +int lwm2m_gateway_setup(anjay_t *anjay) { + if (anjay_lwm2m_gateway_install(anjay)) { + demo_log(ERROR, "Failed to add /25 Gateway Object"); + return -1; + } + + for (anjay_iid_t end_dev_iid = 0; end_dev_iid < AVS_ARRAY_SIZE(devs); + ++end_dev_iid) { + if (lwm2m_gateway_setup_end_device(anjay, end_dev_iid)) { + demo_log(ERROR, "Failed to setup End Device id = %" PRIu16, + end_dev_iid); + return -1; + } + } + + return 0; +} + +void lwm2m_gateway_cleanup(anjay_t *anjay) { + for (anjay_iid_t end_dev_iid = 0; end_dev_iid <= AVS_ARRAY_SIZE(devs); + ++end_dev_iid) { + lwm2m_gateway_cleanup_end_device(anjay, end_dev_iid); + } +} + +void lwm2m_gateway_press_button_end_device(anjay_t *anjay, + anjay_iid_t end_dev_iid) { + struct end_dev *dev = get_dev_ptr(end_dev_iid); + if (!dev) { + return; + } + const anjay_dm_object_def_t **obj = dev->push_button_object; + + push_button_press(anjay, obj); +} + +void lwm2m_gateway_release_button_end_device(anjay_t *anjay, + anjay_iid_t end_dev_iid) { + struct end_dev *dev = get_dev_ptr(end_dev_iid); + if (!dev) { + return; + } + const anjay_dm_object_def_t **obj = dev->push_button_object; + + push_button_release(anjay, obj); +} + +void lwm2m_gateway_binary_app_data_container_write(anjay_t *anjay, + anjay_iid_t end_dev_iid, + anjay_iid_t iid, + anjay_riid_t riid, + const char *value) { + struct end_dev *dev = get_dev_ptr(end_dev_iid); + if (!dev) { + return; + } + const anjay_dm_object_def_t **obj = dev->binary_app_data_container; + + gw_binary_app_data_container_write(anjay, obj, iid, riid, value); +} + +#endif // ANJAY_WITH_LWM2M_GATEWAY diff --git a/demo/lwm2m_gateway.h b/demo/lwm2m_gateway.h new file mode 100644 index 00000000..980a3108 --- /dev/null +++ b/demo/lwm2m_gateway.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ + +#ifndef LWM2M_GATEWAY_H +#define LWM2M_GATEWAY_H + +#include + +#ifdef ANJAY_WITH_LWM2M_GATEWAY + +# include + +# define LWM2M_GATEWAY_END_DEVICE_COUNT 2 +// keep it equal to LWM2M_GATEWAY_END_DEVICE_COUNT - 1 +# define LWM2M_GATEWAY_END_DEVICE_RANGE 1 + +int lwm2m_gateway_setup(anjay_t *anjay); +void lwm2m_gateway_cleanup(anjay_t *anjay); + +int lwm2m_gateway_setup_end_device(anjay_t *anjay, anjay_iid_t iid); +void lwm2m_gateway_cleanup_end_device(anjay_t *anjay, anjay_iid_t iid); + +void lwm2m_gateway_press_button_end_device(anjay_t *anjay, anjay_iid_t iid); +void lwm2m_gateway_release_button_end_device(anjay_t *anjay, anjay_iid_t iid); + +void lwm2m_gateway_binary_app_data_container_write(anjay_t *anjay, + uint16_t dev_no, + anjay_iid_t iid, + anjay_riid_t riid, + const char *value); + +#endif // ANJAY_WITH_LWM2M_GATEWAY + +#endif // LWM2M_GATEWAY_H diff --git a/demo/objects.h b/demo/objects.h index 7c784889..d5e2f81a 100644 --- a/demo/objects.h +++ b/demo/objects.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/apn_conn_profile.c b/demo/objects/apn_conn_profile.c index 267c088e..bd4b7ae2 100644 --- a/demo/objects/apn_conn_profile.c +++ b/demo/objects/apn_conn_profile.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/binary_app_data_container.c b/demo/objects/binary_app_data_container.c index 6e800e3e..ed66cb04 100644 --- a/demo/objects/binary_app_data_container.c +++ b/demo/objects/binary_app_data_container.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/cell_connectivity.c b/demo/objects/cell_connectivity.c index d67b61c3..5bb38d50 100644 --- a/demo/objects/cell_connectivity.c +++ b/demo/objects/cell_connectivity.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/conn_monitoring.c b/demo/objects/conn_monitoring.c index 951be0c0..0eb41e8f 100644 --- a/demo/objects/conn_monitoring.c +++ b/demo/objects/conn_monitoring.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/conn_statistics.c b/demo/objects/conn_statistics.c index c3402aa2..47753c55 100644 --- a/demo/objects/conn_statistics.c +++ b/demo/objects/conn_statistics.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/device.c b/demo/objects/device.c index fbef3173..fff1c9ac 100644 --- a/demo/objects/device.c +++ b/demo/objects/device.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/download_diagnostics.c b/demo/objects/download_diagnostics.c index bfffde65..f0a38d76 100644 --- a/demo/objects/download_diagnostics.c +++ b/demo/objects/download_diagnostics.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/event_log.c b/demo/objects/event_log.c index b8721b8a..1e99dea1 100644 --- a/demo/objects/event_log.c +++ b/demo/objects/event_log.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/ext_dev_info.c b/demo/objects/ext_dev_info.c index 6aadf9e9..b00b45ec 100644 --- a/demo/objects/ext_dev_info.c +++ b/demo/objects/ext_dev_info.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/gateway_end_devices/binary_app_data_container.c b/demo/objects/gateway_end_devices/binary_app_data_container.c new file mode 100644 index 00000000..453a2b62 --- /dev/null +++ b/demo/objects/gateway_end_devices/binary_app_data_container.c @@ -0,0 +1,516 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../../demo_utils.h" +#include "binary_app_data_container.h" + +/** + * Data: RW, Multiple, Mandatory + * type: opaque, range: N/A, unit: N/A + * Indicates the application data content. + */ +#define RID_DATA 0 + +/** + * Data Priority: RW, Single, Optional + * type: integer, range: 1 bytes, unit: N/A + * Indicates the Application data priority: 0:Immediate 1:BestEffort + * 2:Latest 3-100: Reserved for future use. 101-254: Proprietary mode. + */ +#define RID_DATA_PRIORITY 1 + +/** + * Data Creation Time: RW, Single, Optional + * type: time, range: N/A, unit: N/A + * Indicates the Data instance creation timestamp. + */ +#define RID_DATA_CREATION_TIME 2 + +/** + * Data Description: RW, Single, Optional + * type: string, range: 32 bytes, unit: N/A + * Indicates the data description. e.g. "meter reading". + */ +#define RID_DATA_DESCRIPTION 3 + +/** + * Data Format: RW, Single, Optional + * type: string, range: 32 bytes, unit: N/A + * Indicates the format of the Application Data. e.g. YG-Meter-Water- + * Reading UTF8-string + */ +#define RID_DATA_FORMAT 4 + +/** + * App ID: RW, Single, Optional + * type: integer, range: 2 bytes, unit: N/A + * Indicates the destination Application ID. + */ +#define RID_APP_ID 5 + +#define MAX_BINARY_DATA_SIZE 1024 + +typedef struct { + anjay_riid_t riid; + uint8_t data[MAX_BINARY_DATA_SIZE]; + size_t data_length; +} data_resource_instance_t; + +typedef struct binary_app_data_container_instance_struct { + anjay_iid_t iid; + AVS_LIST(data_resource_instance_t) data_list; +} binary_app_data_container_instance_t; + +typedef struct binary_app_data_container_struct { + const anjay_dm_object_def_t *def; + AVS_LIST(binary_app_data_container_instance_t) instances; + AVS_LIST(binary_app_data_container_instance_t) saved_instances; + anjay_iid_t end_device_iid; +} binary_app_data_container_t; + +static inline binary_app_data_container_t * +get_obj(const anjay_dm_object_def_t *const *obj_ptr) { + assert(obj_ptr); + return AVS_CONTAINER_OF(obj_ptr, binary_app_data_container_t, def); +} + +static binary_app_data_container_instance_t * +find_instance(const binary_app_data_container_t *obj, anjay_iid_t iid) { + AVS_LIST(binary_app_data_container_instance_t) it; + AVS_LIST_FOREACH(it, obj->instances) { + if (it->iid == iid) { + return it; + } else if (it->iid > iid) { + break; + } + } + + return NULL; +} + +static int list_instances(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_dm_list_ctx_t *ctx) { + (void) anjay; + + AVS_LIST(binary_app_data_container_instance_t) it; + AVS_LIST_FOREACH(it, get_obj(obj_ptr)->instances) { + anjay_dm_emit(ctx, it->iid); + } + + return 0; +} + +static int init_instance(binary_app_data_container_instance_t *inst, + anjay_iid_t iid) { + assert(iid != ANJAY_ID_INVALID); + + inst->iid = iid; + return 0; +} + +static void release_instance(binary_app_data_container_instance_t *inst) { + AVS_LIST_CLEAR(&inst->data_list); +} + +static binary_app_data_container_instance_t * +add_instance(binary_app_data_container_t *obj, anjay_iid_t iid) { + assert(find_instance(obj, iid) == NULL); + + AVS_LIST(binary_app_data_container_instance_t) created = + AVS_LIST_NEW_ELEMENT(binary_app_data_container_instance_t); + if (!created) { + return NULL; + } + + int result = init_instance(created, iid); + if (result) { + AVS_LIST_CLEAR(&created); + return NULL; + } + + AVS_LIST(binary_app_data_container_instance_t) *ptr; + AVS_LIST_FOREACH_PTR(ptr, &obj->instances) { + if ((*ptr)->iid > created->iid) { + break; + } + } + + AVS_LIST_INSERT(ptr, created); + return created; +} + +static int instance_create(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid) { + (void) anjay; + binary_app_data_container_t *obj = get_obj(obj_ptr); + + return add_instance(obj, iid) ? 0 : ANJAY_ERR_INTERNAL; +} + +static int instance_remove(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid) { + (void) anjay; + binary_app_data_container_t *obj = get_obj(obj_ptr); + + AVS_LIST(binary_app_data_container_instance_t) *it; + AVS_LIST_FOREACH_PTR(it, &obj->instances) { + if ((*it)->iid == iid) { + release_instance(*it); + AVS_LIST_DELETE(it); + return 0; + } else if ((*it)->iid > iid) { + break; + } + } + + assert(0); + return ANJAY_ERR_NOT_FOUND; +} + +static int instance_reset(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid) { + (void) anjay; + + binary_app_data_container_t *obj = get_obj(obj_ptr); + binary_app_data_container_instance_t *inst = find_instance(obj, iid); + assert(inst); + + AVS_LIST_CLEAR(&inst->data_list); + return 0; +} + +static int list_resources(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_dm_resource_list_ctx_t *ctx) { + (void) anjay; + (void) obj_ptr; + (void) iid; + + anjay_dm_emit_res(ctx, RID_DATA, ANJAY_DM_RES_RWM, ANJAY_DM_RES_PRESENT); + return 0; +} + +static int resource_read(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + anjay_output_ctx_t *ctx) { + (void) anjay; + + binary_app_data_container_t *obj = get_obj(obj_ptr); + binary_app_data_container_instance_t *inst = find_instance(obj, iid); + assert(inst); + + switch (rid) { + case RID_DATA: { + data_resource_instance_t *it; + AVS_LIST_FOREACH(it, inst->data_list) { + if (it->riid == riid) { + break; + } + } + if (!it) { + return ANJAY_ERR_NOT_FOUND; + } + return anjay_ret_bytes(ctx, it->data, it->data_length); + } + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static AVS_LIST(data_resource_instance_t) * +resource_instance_create(binary_app_data_container_instance_t *inst, + anjay_riid_t riid) { + AVS_LIST(data_resource_instance_t) created = + AVS_LIST_NEW_ELEMENT(data_resource_instance_t); + if (!created) { + return NULL; + } + + created->riid = riid; + + AVS_LIST(data_resource_instance_t) *ptr; + AVS_LIST_FOREACH_PTR(ptr, &inst->data_list) { + if ((*ptr)->riid > created->riid) { + break; + } + } + + AVS_LIST_INSERT(ptr, created); + return ptr; +} + +static int resource_write(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + anjay_input_ctx_t *ctx) { + (void) anjay; + + binary_app_data_container_t *obj = get_obj(obj_ptr); + binary_app_data_container_instance_t *inst = find_instance(obj, iid); + assert(inst); + + switch (rid) { + case RID_DATA: { + AVS_LIST(data_resource_instance_t) *it; + AVS_LIST_FOREACH_PTR(it, &inst->data_list) { + if ((*it)->riid >= riid) { + break; + } + } + bool created = false; + if (!(*it) || (*it)->riid != riid) { + if (!(it = resource_instance_create(inst, riid))) { + return ANJAY_ERR_INTERNAL; + } + created = true; + } + + bool finished; + int retval = anjay_get_bytes(ctx, &(*it)->data_length, &finished, + (*it)->data, sizeof((*it)->data)); + + if (!retval && !finished) { + retval = ANJAY_ERR_INTERNAL; + } + + if (retval) { + if (created) { + AVS_LIST_DELETE(it); + } else { + (*it)->data_length = 0; + } + } + return retval; + } + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static int resource_reset(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid) { + (void) anjay; + + binary_app_data_container_t *obj = get_obj(obj_ptr); + binary_app_data_container_instance_t *inst = find_instance(obj, iid); + assert(inst); + + switch (rid) { + case RID_DATA: + AVS_LIST_CLEAR(&inst->data_list); + return 0; + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static int list_resource_instances(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_dm_list_ctx_t *ctx) { + (void) anjay; + (void) ctx; + + binary_app_data_container_t *obj = get_obj(obj_ptr); + binary_app_data_container_instance_t *inst = find_instance(obj, iid); + assert(inst); + + switch (rid) { + case RID_DATA: { + data_resource_instance_t *it; + AVS_LIST_FOREACH(it, inst->data_list) { + anjay_dm_emit(ctx, it->riid); + } + return 0; + } + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static int transaction_begin(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr) { + (void) anjay; + binary_app_data_container_t *repr = get_obj(obj_ptr); + if (!repr->instances) { + return 0; + } + + AVS_LIST(binary_app_data_container_instance_t) *saved_instances_tail = + &repr->saved_instances; + AVS_LIST(binary_app_data_container_instance_t) instance; + bool failed = false; + AVS_LIST_FOREACH(instance, repr->instances) { + AVS_LIST(binary_app_data_container_instance_t) saved_instance = + AVS_LIST_APPEND_NEW(binary_app_data_container_instance_t, + saved_instances_tail); + if (!saved_instance) { + demo_log(ERROR, "cannot allocate a new instance"); + failed = true; + break; + } + if (instance->data_list) { + saved_instance->data_list = + AVS_LIST_SIMPLE_CLONE(instance->data_list); + if (!saved_instance->data_list) { + demo_log(ERROR, "cannot clone resource instances list"); + failed = true; + break; + } + } + saved_instance->iid = instance->iid; + AVS_LIST_ADVANCE_PTR(&saved_instances_tail); + } + + if (failed) { + AVS_LIST_CLEAR(&repr->saved_instances) { + AVS_LIST_CLEAR(&repr->saved_instances->data_list); + } + return ANJAY_ERR_INTERNAL; + } + return 0; +} + +static int transaction_commit(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr) { + (void) anjay; + binary_app_data_container_t *repr = get_obj(obj_ptr); + AVS_LIST_CLEAR(&repr->saved_instances) { + AVS_LIST_CLEAR(&repr->saved_instances->data_list); + } + return 0; +} + +static int transaction_rollback(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr) { + (void) anjay; + binary_app_data_container_t *repr = get_obj(obj_ptr); + AVS_LIST_CLEAR(&repr->instances) { + AVS_LIST_CLEAR(&repr->instances->data_list); + } + repr->instances = repr->saved_instances; + repr->saved_instances = NULL; + return 0; +} + +static const anjay_dm_object_def_t OBJ_DEF = { + .oid = 19, + .handlers = { + .list_instances = list_instances, + .instance_create = instance_create, + .instance_remove = instance_remove, + .instance_reset = instance_reset, + + .list_resources = list_resources, + .resource_read = resource_read, + .resource_write = resource_write, + .resource_reset = resource_reset, + .list_resource_instances = list_resource_instances, + + .transaction_begin = transaction_begin, + .transaction_validate = anjay_dm_transaction_NOOP, + .transaction_commit = transaction_commit, + .transaction_rollback = transaction_rollback + } +}; + +const anjay_dm_object_def_t ** +gw_binary_app_data_container_object_create(anjay_iid_t id) { + binary_app_data_container_t *obj = + (binary_app_data_container_t *) avs_calloc( + 1, sizeof(binary_app_data_container_t)); + if (!obj) { + return NULL; + } + obj->def = &OBJ_DEF; + obj->end_device_iid = id; + + /* Create at least one instance for the End Devices */ + binary_app_data_container_instance_t *inst = add_instance(obj, 0); + resource_instance_create(inst, 0); + + return &obj->def; +} + +void gw_binary_app_data_container_object_release( + const anjay_dm_object_def_t **def) { + if (def) { + binary_app_data_container_t *obj = get_obj(def); + AVS_LIST_CLEAR(&obj->instances) { + release_instance(obj->instances); + } + + avs_free(obj); + } +} + +int gw_binary_app_data_container_write(anjay_t *anjay, + const anjay_dm_object_def_t **def, + anjay_iid_t iid, + anjay_riid_t riid, + const char *value) { + (void) anjay; + + size_t length = strlen(value); + if (length > MAX_BINARY_DATA_SIZE) { + demo_log(ERROR, "Value too long: %s", value); + return -1; + } + + binary_app_data_container_t *obj = get_obj(def); + binary_app_data_container_instance_t *inst = find_instance(obj, iid); + if (!inst) { + demo_log(ERROR, "No such instance: %" PRIu16, iid); + return -1; + } + AVS_LIST(data_resource_instance_t) *it; + AVS_LIST_FOREACH_PTR(it, &inst->data_list) { + if ((*it)->riid >= riid) { + break; + } + } + if (!(*it) || (*it)->riid != riid) { + if (!(it = resource_instance_create(inst, riid))) { + return -1; + } + } + + memcpy((*it)->data, value, length); + (*it)->data_length = length; + (void) anjay_lwm2m_gateway_notify_changed(anjay, obj->end_device_iid, + (*def)->oid, iid, RID_DATA); + return 0; +} diff --git a/demo/objects/gateway_end_devices/binary_app_data_container.h b/demo/objects/gateway_end_devices/binary_app_data_container.h new file mode 100644 index 00000000..d9e8fe1e --- /dev/null +++ b/demo/objects/gateway_end_devices/binary_app_data_container.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ +#ifndef GW_BINARY_APP_DATA_CONTAINER_H +#define GW_BINARY_APP_DATA_CONTAINER_H + +#include + +#include + +const anjay_dm_object_def_t ** +gw_binary_app_data_container_object_create(anjay_iid_t id); +void gw_binary_app_data_container_object_release( + const anjay_dm_object_def_t **def); +int gw_binary_app_data_container_write(anjay_t *anjay, + const anjay_dm_object_def_t **def, + anjay_iid_t iid, + anjay_riid_t riid, + const char *value); + +#endif // GW_BINARY_APP_DATA_CONTAINER_H diff --git a/demo/objects/gateway_end_devices/push_button_object.c b/demo/objects/gateway_end_devices/push_button_object.c new file mode 100644 index 00000000..3f9ec89f --- /dev/null +++ b/demo/objects/gateway_end_devices/push_button_object.c @@ -0,0 +1,237 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ +#include +#include + +#include +#include +#include +#include + +#include "push_button_object.h" + +/** + * Digital Input State: R, Single, Mandatory + * type: boolean, range: N/A, unit: N/A + * The current state of a digital input. + */ +#define RID_DIGITAL_INPUT_STATE 5500 + +/** + * Digital Input Counter: R, Single, Optional + * type: integer, range: N/A, unit: N/A + * The cumulative value of active state detected. + */ +#define RID_DIGITAL_INPUT_COUNTER 5501 + +/** + * Application Type: RW, Single, Optional + * type: string, range: N/A, unit: N/A + * The application type of the sensor or actuator as a string depending + * on the use case. + */ +#define RID_APPLICATION_TYPE 5750 + +typedef struct push_button_instance_struct { + bool digital_input_state; + int32_t digital_input_counter; + char application_type[64]; + char application_type_backup[64]; +} push_button_instance_t; + +typedef struct push_button_object_struct { + const anjay_dm_object_def_t *def; + push_button_instance_t instances[1]; + anjay_iid_t end_device_iid; +} push_button_object_t; + +static inline push_button_object_t * +get_obj(const anjay_dm_object_def_t *const *obj_ptr) { + assert(obj_ptr); + return AVS_CONTAINER_OF(obj_ptr, push_button_object_t, def); +} + +static int list_instances(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_dm_list_ctx_t *ctx) { + (void) anjay; + + push_button_object_t *obj = get_obj(obj_ptr); + for (anjay_iid_t iid = 0; iid < AVS_ARRAY_SIZE(obj->instances); iid++) { + anjay_dm_emit(ctx, iid); + } + + return 0; +} + +static int instance_reset(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid) { + (void) anjay; + + push_button_object_t *obj = get_obj(obj_ptr); + assert(iid < AVS_ARRAY_SIZE(obj->instances)); + push_button_instance_t *inst = &obj->instances[iid]; + + inst->digital_input_state = false; + inst->digital_input_counter = 0; + inst->application_type[0] = '\0'; + + return 0; +} + +static int list_resources(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_dm_resource_list_ctx_t *ctx) { + (void) anjay; + (void) obj_ptr; + (void) iid; + + anjay_dm_emit_res(ctx, RID_DIGITAL_INPUT_STATE, ANJAY_DM_RES_R, + ANJAY_DM_RES_PRESENT); + anjay_dm_emit_res(ctx, RID_DIGITAL_INPUT_COUNTER, ANJAY_DM_RES_R, + ANJAY_DM_RES_PRESENT); + anjay_dm_emit_res(ctx, RID_APPLICATION_TYPE, ANJAY_DM_RES_RW, + ANJAY_DM_RES_PRESENT); + return 0; +} + +static int resource_read(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + anjay_output_ctx_t *ctx) { + (void) anjay; + + push_button_object_t *obj = get_obj(obj_ptr); + assert(iid < AVS_ARRAY_SIZE(obj->instances)); + push_button_instance_t *inst = &obj->instances[iid]; + + switch (rid) { + case RID_DIGITAL_INPUT_STATE: + assert(riid == ANJAY_ID_INVALID); + return anjay_ret_bool(ctx, inst->digital_input_state); + + case RID_DIGITAL_INPUT_COUNTER: + assert(riid == ANJAY_ID_INVALID); + return anjay_ret_i32(ctx, inst->digital_input_counter); + + case RID_APPLICATION_TYPE: + assert(riid == ANJAY_ID_INVALID); + return anjay_ret_string(ctx, inst->application_type); + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static int resource_write(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + anjay_input_ctx_t *ctx) { + (void) anjay; + + push_button_object_t *obj = get_obj(obj_ptr); + assert(iid < AVS_ARRAY_SIZE(obj->instances)); + push_button_instance_t *inst = &obj->instances[iid]; + + switch (rid) { + case RID_APPLICATION_TYPE: { + assert(riid == ANJAY_ID_INVALID); + return anjay_get_string(ctx, inst->application_type, + sizeof(inst->application_type)); + } + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static int transaction_begin(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr) { + (void) anjay; + + push_button_object_t *obj = get_obj(obj_ptr); + push_button_instance_t *instance = &obj->instances[0]; + strcpy(instance->application_type_backup, instance->application_type); + + return 0; +} + +static int transaction_rollback(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr) { + (void) anjay; + + push_button_object_t *obj = get_obj(obj_ptr); + push_button_instance_t *instance = &obj->instances[0]; + strcpy(instance->application_type, instance->application_type_backup); + + return 0; +} + +const anjay_dm_object_def_t OBJ_DEF = { + .oid = 3347, + .handlers = { + .list_instances = list_instances, + .instance_reset = instance_reset, + .list_resources = list_resources, + .resource_read = resource_read, + .resource_write = resource_write, + .transaction_begin = transaction_begin, + .transaction_validate = anjay_dm_transaction_NOOP, + .transaction_commit = anjay_dm_transaction_NOOP, + .transaction_rollback = transaction_rollback + } +}; + +const anjay_dm_object_def_t **push_button_object_create(anjay_iid_t id) { + push_button_object_t *obj = + (push_button_object_t *) avs_calloc(1, + sizeof(push_button_object_t)); + if (!obj) { + return NULL; + } + obj->def = &OBJ_DEF; + obj->instances[0].digital_input_state = false; + obj->instances[0].digital_input_counter = 0; + sprintf(obj->instances[0].application_type, "Button %d", id); + obj->end_device_iid = id; + + return &obj->def; +} + +void push_button_object_release(const anjay_dm_object_def_t **def) { + if (def) { + push_button_object_t *obj = get_obj(def); + avs_free(obj); + } +} + +void push_button_press(anjay_t *anjay, const anjay_dm_object_def_t **def) { + push_button_object_t *obj = get_obj(def); + if (!obj->instances[0].digital_input_state) { + obj->instances[0].digital_input_counter++; + (void) anjay_lwm2m_gateway_notify_changed( + anjay, obj->end_device_iid, 3347, 0, RID_DIGITAL_INPUT_COUNTER); + } + obj->instances[0].digital_input_state = true; + (void) anjay_lwm2m_gateway_notify_changed(anjay, obj->end_device_iid, 3347, + 0, RID_DIGITAL_INPUT_STATE); +} + +void push_button_release(anjay_t *anjay, const anjay_dm_object_def_t **def) { + push_button_object_t *obj = get_obj(def); + obj->instances[0].digital_input_state = false; + (void) anjay_lwm2m_gateway_notify_changed(anjay, obj->end_device_iid, 3347, + 0, RID_DIGITAL_INPUT_STATE); +} diff --git a/demo/objects/gateway_end_devices/push_button_object.h b/demo/objects/gateway_end_devices/push_button_object.h new file mode 100644 index 00000000..17fc1b21 --- /dev/null +++ b/demo/objects/gateway_end_devices/push_button_object.h @@ -0,0 +1,19 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ +#ifndef PUSH_BUTTON_OBJECT_H +#define PUSH_BUTTON_OBJECT_H + +#include + +const anjay_dm_object_def_t **push_button_object_create(anjay_iid_t id); +void push_button_object_release(const anjay_dm_object_def_t **def); +void push_button_press(anjay_t *anjay, const anjay_dm_object_def_t **def); +void push_button_release(anjay_t *anjay, const anjay_dm_object_def_t **def); + +#endif // PUSH_BUTTON_OBJECT_H diff --git a/demo/objects/gateway_end_devices/temperature_object.c b/demo/objects/gateway_end_devices/temperature_object.c new file mode 100644 index 00000000..d4acc627 --- /dev/null +++ b/demo/objects/gateway_end_devices/temperature_object.c @@ -0,0 +1,382 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ +#include +#include + +#include +#include +#include +#include +#include + +#include "temperature_object.h" + +/** + * Min Measured Value: R, Single, Optional + * type: float, range: N/A, unit: N/A + * The minimum value measured by the sensor since power ON or reset. + */ +#define RID_MIN_MEASURED_VALUE 5601 + +/** + * Max Measured Value: R, Single, Optional + * type: float, range: N/A, unit: N/A + * The maximum value measured by the sensor since power ON or reset. + */ +#define RID_MAX_MEASURED_VALUE 5602 + +/** + * Reset Min and Max Measured Values: E, Single, Optional + * type: N/A, range: N/A, unit: N/A + * Reset the Min and Max Measured Values to Current Value. + */ +#define RID_RESET_MIN_AND_MAX_MEASURED_VALUES 5605 + +/** + * Sensor Value: R, Single, Mandatory + * type: float, range: N/A, unit: N/A + * Last or Current Measured Value from the Sensor. + */ +#define RID_SENSOR_VALUE 5700 + +/** + * Application Type: RW, Single, Optional + * type: string, range: N/A, unit: N/A + * The application type of the sensor or actuator as a string depending + * on the use case. + */ +#define RID_APPLICATION_TYPE 5750 + +typedef struct temperature_instance_struct { + anjay_iid_t iid; + + double value; + double min_measured; + double max_measured; + char application_type[64]; + char application_type_backup[64]; +} temperature_instance_t; + +typedef struct temperature_object_struct { + const anjay_dm_object_def_t *def; + AVS_LIST(temperature_instance_t) instances; + anjay_iid_t end_device_iid; +} temperature_object_t; + +static inline temperature_object_t * +get_obj(const anjay_dm_object_def_t *const *obj_ptr) { + assert(obj_ptr); + return AVS_CONTAINER_OF(obj_ptr, temperature_object_t, def); +} + +static temperature_instance_t *find_instance(const temperature_object_t *obj, + anjay_iid_t iid) { + AVS_LIST(temperature_instance_t) it; + AVS_LIST_FOREACH(it, obj->instances) { + if (it->iid == iid) { + return it; + } else if (it->iid > iid) { + break; + } + } + + return NULL; +} + +static int list_instances(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_dm_list_ctx_t *ctx) { + (void) anjay; + + AVS_LIST(temperature_instance_t) it; + AVS_LIST_FOREACH(it, get_obj(obj_ptr)->instances) { + anjay_dm_emit(ctx, it->iid); + } + + return 0; +} + +static int init_instance(temperature_instance_t *inst, anjay_iid_t iid) { + assert(iid != ANJAY_ID_INVALID); + + inst->iid = iid; + return 0; +} + +static void release_instance(temperature_instance_t *inst) { + (void) inst; +} + +static temperature_instance_t *add_instance(temperature_object_t *obj, + anjay_iid_t iid) { + assert(find_instance(obj, iid) == NULL); + + AVS_LIST(temperature_instance_t) created = + AVS_LIST_NEW_ELEMENT(temperature_instance_t); + if (!created) { + return NULL; + } + + int result = init_instance(created, iid); + if (result) { + AVS_LIST_CLEAR(&created); + return NULL; + } + + AVS_LIST(temperature_instance_t) *ptr; + AVS_LIST_FOREACH_PTR(ptr, &obj->instances) { + if ((*ptr)->iid > created->iid) { + break; + } + } + + AVS_LIST_INSERT(ptr, created); + return created; +} + +static int instance_create(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid) { + (void) anjay; + temperature_object_t *obj = get_obj(obj_ptr); + + return add_instance(obj, iid) ? 0 : ANJAY_ERR_INTERNAL; +} + +static int instance_remove(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid) { + (void) anjay; + temperature_object_t *obj = get_obj(obj_ptr); + + AVS_LIST(temperature_instance_t) *it; + AVS_LIST_FOREACH_PTR(it, &obj->instances) { + if ((*it)->iid == iid) { + release_instance(*it); + AVS_LIST_DELETE(it); + return 0; + } else if ((*it)->iid > iid) { + break; + } + } + + assert(0); + return ANJAY_ERR_NOT_FOUND; +} + +static int instance_reset(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid) { + (void) anjay; + + temperature_object_t *obj = get_obj(obj_ptr); + temperature_instance_t *inst = find_instance(obj, iid); + assert(inst); + + inst->application_type[0] = '\0'; + return 0; +} + +static int list_resources(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_dm_resource_list_ctx_t *ctx) { + (void) anjay; + (void) obj_ptr; + (void) iid; + + anjay_dm_emit_res(ctx, RID_MIN_MEASURED_VALUE, ANJAY_DM_RES_R, + ANJAY_DM_RES_PRESENT); + anjay_dm_emit_res(ctx, RID_MAX_MEASURED_VALUE, ANJAY_DM_RES_R, + ANJAY_DM_RES_PRESENT); + anjay_dm_emit_res(ctx, RID_RESET_MIN_AND_MAX_MEASURED_VALUES, + ANJAY_DM_RES_E, ANJAY_DM_RES_PRESENT); + anjay_dm_emit_res(ctx, RID_SENSOR_VALUE, ANJAY_DM_RES_R, + ANJAY_DM_RES_PRESENT); + anjay_dm_emit_res(ctx, RID_APPLICATION_TYPE, ANJAY_DM_RES_RW, + ANJAY_DM_RES_PRESENT); + return 0; +} + +static int resource_read(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + anjay_output_ctx_t *ctx) { + (void) anjay; + + temperature_object_t *obj = get_obj(obj_ptr); + temperature_instance_t *inst = find_instance(obj, iid); + assert(inst); + + switch (rid) { + case RID_MIN_MEASURED_VALUE: + assert(riid == ANJAY_ID_INVALID); + return anjay_ret_double(ctx, inst->min_measured); + + case RID_MAX_MEASURED_VALUE: + assert(riid == ANJAY_ID_INVALID); + return anjay_ret_double(ctx, inst->max_measured); + + case RID_SENSOR_VALUE: + assert(riid == ANJAY_ID_INVALID); + return anjay_ret_double(ctx, inst->value); + + case RID_APPLICATION_TYPE: + assert(riid == ANJAY_ID_INVALID); + return anjay_ret_string(ctx, inst->application_type); + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static int resource_write(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + anjay_input_ctx_t *ctx) { + (void) anjay; + + temperature_object_t *obj = get_obj(obj_ptr); + temperature_instance_t *inst = find_instance(obj, iid); + assert(inst); + + switch (rid) { + case RID_APPLICATION_TYPE: { + assert(riid == ANJAY_ID_INVALID); + return anjay_get_string(ctx, inst->application_type, + sizeof(inst->application_type)); + } + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static int resource_execute(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_execute_ctx_t *arg_ctx) { + (void) anjay; + (void) arg_ctx; + + temperature_object_t *obj = get_obj(obj_ptr); + temperature_instance_t *inst = find_instance(obj, iid); + assert(inst); + + switch (rid) { + case RID_RESET_MIN_AND_MAX_MEASURED_VALUES: + inst->min_measured = NAN; + inst->max_measured = NAN; + return 0; + + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static int transaction_begin(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr) { + (void) anjay; + + temperature_object_t *obj = get_obj(obj_ptr); + + temperature_instance_t *element; + AVS_LIST_FOREACH(element, obj->instances) { + strcpy(element->application_type_backup, element->application_type); + } + return 0; +} + +static int transaction_rollback(anjay_t *anjay, + const anjay_dm_object_def_t *const *obj_ptr) { + (void) anjay; + + temperature_object_t *obj = get_obj(obj_ptr); + + temperature_instance_t *element; + AVS_LIST_FOREACH(element, obj->instances) { + strcpy(element->application_type, element->application_type_backup); + } + return 0; +} + +static const anjay_dm_object_def_t OBJ_DEF = { + .oid = 3303, + .version = "1.1", + .handlers = { + .list_instances = list_instances, + .instance_create = instance_create, + .instance_remove = instance_remove, + .instance_reset = instance_reset, + + .list_resources = list_resources, + .resource_read = resource_read, + .resource_write = resource_write, + .resource_execute = resource_execute, + + .transaction_begin = transaction_begin, + .transaction_validate = anjay_dm_transaction_NOOP, + .transaction_commit = anjay_dm_transaction_NOOP, + .transaction_rollback = transaction_rollback + } +}; + +const anjay_dm_object_def_t **temperature_object_create(anjay_iid_t id) { + temperature_object_t *obj = + (temperature_object_t *) avs_calloc(1, + sizeof(temperature_object_t)); + if (!obj) { + return NULL; + } + obj->def = &OBJ_DEF; + obj->end_device_iid = id; + + temperature_instance_t *inst = add_instance(obj, 0); + sprintf(inst->application_type, "Sensor %d", id); + + return &obj->def; +} + +void temperature_object_release(const anjay_dm_object_def_t **def) { + if (def) { + temperature_object_t *obj = get_obj(def); + AVS_LIST_CLEAR(&obj->instances) { + release_instance(obj->instances); + } + avs_free(obj); + } +} + +void temperature_object_update_value(anjay_t *anjay, + const anjay_dm_object_def_t **def) { + assert(anjay); + temperature_object_t *obj = get_obj(def); + + AVS_LIST(temperature_instance_t) *ptr; + AVS_LIST_FOREACH_PTR(ptr, &obj->instances) { + double new_value = ((double) (rand() % 12600) / 100.0) - 40.0; + + (*ptr)->value = new_value; + + if (isnan((*ptr)->min_measured) || new_value < (*ptr)->min_measured) { + (*ptr)->min_measured = new_value; + } + if (isnan((*ptr)->max_measured) || new_value > (*ptr)->max_measured) { + (*ptr)->max_measured = new_value; + } + anjay_lwm2m_gateway_notify_changed(anjay, obj->end_device_iid, + (*def)->oid, (*ptr)->iid, + RID_SENSOR_VALUE); + } +} diff --git a/demo/objects/gateway_end_devices/temperature_object.h b/demo/objects/gateway_end_devices/temperature_object.h new file mode 100644 index 00000000..687c74bb --- /dev/null +++ b/demo/objects/gateway_end_devices/temperature_object.h @@ -0,0 +1,19 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ +#ifndef TEMPERATURE_OBJECT_H +#define TEMPERATURE_OBJECT_H + +#include + +const anjay_dm_object_def_t **temperature_object_create(anjay_iid_t id); +void temperature_object_release(const anjay_dm_object_def_t **def); +void temperature_object_update_value(anjay_t *anjay, + const anjay_dm_object_def_t **def); + +#endif // TEMPERATURE_OBJECT_H diff --git a/demo/objects/geopoints.c b/demo/objects/geopoints.c index 88a81d25..77e9c9ff 100644 --- a/demo/objects/geopoints.c +++ b/demo/objects/geopoints.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/ip_ping.c b/demo/objects/ip_ping.c index 03f8acd7..f9302bd1 100644 --- a/demo/objects/ip_ping.c +++ b/demo/objects/ip_ping.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/ipso_objects.c b/demo/objects/ipso_objects.c index 3c812a02..f6191d54 100644 --- a/demo/objects/ipso_objects.c +++ b/demo/objects/ipso_objects.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/location.c b/demo/objects/location.c index 8cf4a369..c3144d58 100644 --- a/demo/objects/location.c +++ b/demo/objects/location.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/portfolio.c b/demo/objects/portfolio.c index 59c66b76..01dd830b 100644 --- a/demo/objects/portfolio.c +++ b/demo/objects/portfolio.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/objects/test.c b/demo/objects/test.c index d59e86af..83466f5e 100644 --- a/demo/objects/test.c +++ b/demo/objects/test.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/software_mgmt.c b/demo/software_mgmt.c index fdcc15aa..2625fd9a 100644 --- a/demo/software_mgmt.c +++ b/demo/software_mgmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/demo/software_mgmt.h b/demo/software_mgmt.h index 5437b532..a0b3dcf5 100644 --- a/demo/software_mgmt.h +++ b/demo/software_mgmt.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/deps/avs_coap/CMakeLists.txt b/deps/avs_coap/CMakeLists.txt index 1e2cdf6b..cefc79e5 100644 --- a/deps/avs_coap/CMakeLists.txt +++ b/deps/avs_coap/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/NOTICE b/deps/avs_coap/NOTICE index b869bc8d..bb0dacc6 100644 --- a/deps/avs_coap/NOTICE +++ b/deps/avs_coap/NOTICE @@ -1,5 +1,5 @@ AVSystem CoAP Library -Copyright 2017-2024 AVSystem +Copyright 2017-2025 AVSystem This product includes software developed at AVSystem (www.avsystem.com). diff --git a/deps/avs_coap/cmake/AddHeaderSelfSufficiencyTests.cmake b/deps/avs_coap/cmake/AddHeaderSelfSufficiencyTests.cmake index 6fb773c8..eed081e8 100644 --- a/deps/avs_coap/cmake/AddHeaderSelfSufficiencyTests.cmake +++ b/deps/avs_coap/cmake/AddHeaderSelfSufficiencyTests.cmake @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/cmake/avs_coap-config.cmake.in b/deps/avs_coap/cmake/avs_coap-config.cmake.in index bd1649db..c2634b06 100644 --- a/deps/avs_coap/cmake/avs_coap-config.cmake.in +++ b/deps/avs_coap/cmake/avs_coap-config.cmake.in @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/cmake/fill-placeholders.cmake b/deps/avs_coap/cmake/fill-placeholders.cmake index 56979aac..b13f2e87 100644 --- a/deps/avs_coap/cmake/fill-placeholders.cmake +++ b/deps/avs_coap/cmake/fill-placeholders.cmake @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # @@ -10,7 +10,7 @@ string(TIMESTAMP current_year "%Y") foreach(file IN LISTS CMAKE_INSTALL_MANIFEST_FILES) if(file MATCHES ".(h|hpp|c|cpp|cmake|py|sh)$") file(READ ${file} file_contents) - string(REPLACE "2017-2024" "${current_year}" file_contents_replaced "${file_contents}") + string(REPLACE "2017-2025" "${current_year}" file_contents_replaced "${file_contents}") file(WRITE ${file} "${file_contents_replaced}") endif() endforeach() diff --git a/deps/avs_coap/devconfig b/deps/avs_coap/devconfig index ee7b9bc7..138dbb44 100755 --- a/deps/avs_coap/devconfig +++ b/deps/avs_coap/devconfig @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/doc/CMakeLists.txt b/deps/avs_coap/doc/CMakeLists.txt index 2cfc2068..56f021c2 100644 --- a/deps/avs_coap/doc/CMakeLists.txt +++ b/deps/avs_coap/doc/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/doc/sphinx/source/ErrorHandling.rst b/deps/avs_coap/doc/sphinx/source/ErrorHandling.rst index 270f5f10..baaf230f 100644 --- a/deps/avs_coap/doc/sphinx/source/ErrorHandling.rst +++ b/deps/avs_coap/doc/sphinx/source/ErrorHandling.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem CoAP library All rights reserved. diff --git a/deps/avs_coap/doc/sphinx/source/Fuzzing.rst b/deps/avs_coap/doc/sphinx/source/Fuzzing.rst index 3f3ecd29..8351e4b1 100644 --- a/deps/avs_coap/doc/sphinx/source/Fuzzing.rst +++ b/deps/avs_coap/doc/sphinx/source/Fuzzing.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem CoAP library All rights reserved. diff --git a/deps/avs_coap/doc/sphinx/source/Overview.rst b/deps/avs_coap/doc/sphinx/source/Overview.rst index 1a6a459e..37366f2b 100644 --- a/deps/avs_coap/doc/sphinx/source/Overview.rst +++ b/deps/avs_coap/doc/sphinx/source/Overview.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem CoAP library All rights reserved. diff --git a/deps/avs_coap/doc/sphinx/source/_static/theme_overrides.css b/deps/avs_coap/doc/sphinx/source/_static/theme_overrides.css index bbb4efaa..a9329385 100644 --- a/deps/avs_coap/doc/sphinx/source/_static/theme_overrides.css +++ b/deps/avs_coap/doc/sphinx/source/_static/theme_overrides.css @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/doc/sphinx/source/conf.py.in b/deps/avs_coap/doc/sphinx/source/conf.py.in index e3bdfa37..19086e31 100644 --- a/deps/avs_coap/doc/sphinx/source/conf.py.in +++ b/deps/avs_coap/doc/sphinx/source/conf.py.in @@ -18,7 +18,7 @@ # -- Project information ----------------------------------------------------- project = 'avs_coap' -copyright = '2017-2024, AVSystem' +copyright = '2017-2025, AVSystem' author = 'AVSystem' version = '@AVS_COAP_VERSION@' release = version diff --git a/deps/avs_coap/doc/sphinx/source/index.rst b/deps/avs_coap/doc/sphinx/source/index.rst index 88544355..da21591a 100644 --- a/deps/avs_coap/doc/sphinx/source/index.rst +++ b/deps/avs_coap/doc/sphinx/source/index.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem CoAP library All rights reserved. diff --git a/deps/avs_coap/examples/CMakeLists.txt b/deps/avs_coap/examples/CMakeLists.txt index 22c46fe1..693b418a 100644 --- a/deps/avs_coap/examples/CMakeLists.txt +++ b/deps/avs_coap/examples/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/examples/async-client/CMakeLists.txt b/deps/avs_coap/examples/async-client/CMakeLists.txt index cc42691b..82e5c026 100644 --- a/deps/avs_coap/examples/async-client/CMakeLists.txt +++ b/deps/avs_coap/examples/async-client/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/examples/async-client/src/main.c b/deps/avs_coap/examples/async-client/src/main.c index 76bd56a2..f7b44bc2 100644 --- a/deps/avs_coap/examples/async-client/src/main.c +++ b/deps/avs_coap/examples/async-client/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/async.h b/deps/avs_coap/include_public/avsystem/coap/async.h index 802deb93..76e8751e 100644 --- a/deps/avs_coap/include_public/avsystem/coap/async.h +++ b/deps/avs_coap/include_public/avsystem/coap/async.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/async_client.h b/deps/avs_coap/include_public/avsystem/coap/async_client.h index 3aa16164..303f12f9 100644 --- a/deps/avs_coap/include_public/avsystem/coap/async_client.h +++ b/deps/avs_coap/include_public/avsystem/coap/async_client.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/async_exchange.h b/deps/avs_coap/include_public/avsystem/coap/async_exchange.h index 37166ee7..50df2837 100644 --- a/deps/avs_coap/include_public/avsystem/coap/async_exchange.h +++ b/deps/avs_coap/include_public/avsystem/coap/async_exchange.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/async_server.h b/deps/avs_coap/include_public/avsystem/coap/async_server.h index 05470bef..934a50f1 100644 --- a/deps/avs_coap/include_public/avsystem/coap/async_server.h +++ b/deps/avs_coap/include_public/avsystem/coap/async_server.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/avs_coap_config.h.in b/deps/avs_coap/include_public/avsystem/coap/avs_coap_config.h.in index c3c1291a..bbef429c 100644 --- a/deps/avs_coap/include_public/avsystem/coap/avs_coap_config.h.in +++ b/deps/avs_coap/include_public/avsystem/coap/avs_coap_config.h.in @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/coap.h b/deps/avs_coap/include_public/avsystem/coap/coap.h index ce07bc4a..db8fdf87 100644 --- a/deps/avs_coap/include_public/avsystem/coap/coap.h +++ b/deps/avs_coap/include_public/avsystem/coap/coap.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/code.h b/deps/avs_coap/include_public/avsystem/coap/code.h index 3b90db9a..cd565d59 100644 --- a/deps/avs_coap/include_public/avsystem/coap/code.h +++ b/deps/avs_coap/include_public/avsystem/coap/code.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/ctx.h b/deps/avs_coap/include_public/avsystem/coap/ctx.h index ceb42e4d..80b4fabe 100644 --- a/deps/avs_coap/include_public/avsystem/coap/ctx.h +++ b/deps/avs_coap/include_public/avsystem/coap/ctx.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/observe.h b/deps/avs_coap/include_public/avsystem/coap/observe.h index 5cc560ea..a089db9e 100644 --- a/deps/avs_coap/include_public/avsystem/coap/observe.h +++ b/deps/avs_coap/include_public/avsystem/coap/observe.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/option.h b/deps/avs_coap/include_public/avsystem/coap/option.h index af94915f..a186e6d2 100644 --- a/deps/avs_coap/include_public/avsystem/coap/option.h +++ b/deps/avs_coap/include_public/avsystem/coap/option.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/streaming.h b/deps/avs_coap/include_public/avsystem/coap/streaming.h index 78395430..4acdca37 100644 --- a/deps/avs_coap/include_public/avsystem/coap/streaming.h +++ b/deps/avs_coap/include_public/avsystem/coap/streaming.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/tcp.h b/deps/avs_coap/include_public/avsystem/coap/tcp.h index 3bd10e43..007c8a2d 100644 --- a/deps/avs_coap/include_public/avsystem/coap/tcp.h +++ b/deps/avs_coap/include_public/avsystem/coap/tcp.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/token.h b/deps/avs_coap/include_public/avsystem/coap/token.h index 44e3ea5c..3bfb4d86 100644 --- a/deps/avs_coap/include_public/avsystem/coap/token.h +++ b/deps/avs_coap/include_public/avsystem/coap/token.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/udp.h b/deps/avs_coap/include_public/avsystem/coap/udp.h index 0f3a0f28..bbdce9ed 100644 --- a/deps/avs_coap/include_public/avsystem/coap/udp.h +++ b/deps/avs_coap/include_public/avsystem/coap/udp.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/include_public/avsystem/coap/writer.h b/deps/avs_coap/include_public/avsystem/coap/writer.h index 446cb892..b1d7d3a5 100644 --- a/deps/avs_coap/include_public/avsystem/coap/writer.h +++ b/deps/avs_coap/include_public/avsystem/coap/writer.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/async/avs_coap_async_client.c b/deps/avs_coap/src/async/avs_coap_async_client.c index 70240fb7..56e62b28 100644 --- a/deps/avs_coap/src/async/avs_coap_async_client.c +++ b/deps/avs_coap/src/async/avs_coap_async_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/async/avs_coap_async_client.h b/deps/avs_coap/src/async/avs_coap_async_client.h index 86981043..f4c78f05 100644 --- a/deps/avs_coap/src/async/avs_coap_async_client.h +++ b/deps/avs_coap/src/async/avs_coap_async_client.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/async/avs_coap_async_server.c b/deps/avs_coap/src/async/avs_coap_async_server.c index 0fb6a34a..83330175 100644 --- a/deps/avs_coap/src/async/avs_coap_async_server.c +++ b/deps/avs_coap/src/async/avs_coap_async_server.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/async/avs_coap_async_server.h b/deps/avs_coap/src/async/avs_coap_async_server.h index 520096da..f13796eb 100644 --- a/deps/avs_coap/src/async/avs_coap_async_server.h +++ b/deps/avs_coap/src/async/avs_coap_async_server.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/async/avs_coap_exchange.c b/deps/avs_coap/src/async/avs_coap_exchange.c index 8fd8a74c..d0404d63 100644 --- a/deps/avs_coap/src/async/avs_coap_exchange.c +++ b/deps/avs_coap/src/async/avs_coap_exchange.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/async/avs_coap_exchange.h b/deps/avs_coap/src/async/avs_coap_exchange.h index 5f3395dc..6ab22aa6 100644 --- a/deps/avs_coap/src/async/avs_coap_exchange.h +++ b/deps/avs_coap/src/async/avs_coap_exchange.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_code_utils.c b/deps/avs_coap/src/avs_coap_code_utils.c index 59bbb87f..f8d1faa0 100644 --- a/deps/avs_coap/src/avs_coap_code_utils.c +++ b/deps/avs_coap/src/avs_coap_code_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_code_utils.h b/deps/avs_coap/src/avs_coap_code_utils.h index 9cf7ce63..b1592680 100644 --- a/deps/avs_coap/src/avs_coap_code_utils.h +++ b/deps/avs_coap/src/avs_coap_code_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_common_utils.c b/deps/avs_coap/src/avs_coap_common_utils.c index bb19d7ce..d378fbeb 100644 --- a/deps/avs_coap/src/avs_coap_common_utils.c +++ b/deps/avs_coap/src/avs_coap_common_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_common_utils.h b/deps/avs_coap/src/avs_coap_common_utils.h index c239c752..b3e1a670 100644 --- a/deps/avs_coap/src/avs_coap_common_utils.h +++ b/deps/avs_coap/src/avs_coap_common_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_ctx.c b/deps/avs_coap/src/avs_coap_ctx.c index bb843454..888d38d6 100644 --- a/deps/avs_coap/src/avs_coap_ctx.c +++ b/deps/avs_coap/src/avs_coap_ctx.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_ctx.h b/deps/avs_coap/src/avs_coap_ctx.h index 96732be7..410fe7f8 100644 --- a/deps/avs_coap/src/avs_coap_ctx.h +++ b/deps/avs_coap/src/avs_coap_ctx.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_ctx_vtable.h b/deps/avs_coap/src/avs_coap_ctx_vtable.h index 704d5984..de1669d6 100644 --- a/deps/avs_coap/src/avs_coap_ctx_vtable.h +++ b/deps/avs_coap/src/avs_coap_ctx_vtable.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_init.h b/deps/avs_coap/src/avs_coap_init.h index b14069f5..a696bc69 100644 --- a/deps/avs_coap/src/avs_coap_init.h +++ b/deps/avs_coap/src/avs_coap_init.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_observe.c b/deps/avs_coap/src/avs_coap_observe.c index e16fb56c..dfed3dd5 100644 --- a/deps/avs_coap/src/avs_coap_observe.c +++ b/deps/avs_coap/src/avs_coap_observe.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_observe.h b/deps/avs_coap/src/avs_coap_observe.h index b06af411..94dea498 100644 --- a/deps/avs_coap/src/avs_coap_observe.h +++ b/deps/avs_coap/src/avs_coap_observe.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_parse_utils.h b/deps/avs_coap/src/avs_coap_parse_utils.h index 75147555..6fa709a8 100644 --- a/deps/avs_coap/src/avs_coap_parse_utils.h +++ b/deps/avs_coap/src/avs_coap_parse_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_poison.h b/deps/avs_coap/src/avs_coap_poison.h index 05f8e87b..399fa5fe 100644 --- a/deps/avs_coap/src/avs_coap_poison.h +++ b/deps/avs_coap/src/avs_coap_poison.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/avs_coap_x_log_config.h b/deps/avs_coap/src/avs_coap_x_log_config.h index d9979097..1fdec6d5 100644 --- a/deps/avs_coap/src/avs_coap_x_log_config.h +++ b/deps/avs_coap/src/avs_coap_x_log_config.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/options/avs_coap_iterator.c b/deps/avs_coap/src/options/avs_coap_iterator.c index 31364de5..52ffa9fd 100644 --- a/deps/avs_coap/src/options/avs_coap_iterator.c +++ b/deps/avs_coap/src/options/avs_coap_iterator.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/options/avs_coap_iterator.h b/deps/avs_coap/src/options/avs_coap_iterator.h index 80ce364c..896dc262 100644 --- a/deps/avs_coap/src/options/avs_coap_iterator.h +++ b/deps/avs_coap/src/options/avs_coap_iterator.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/options/avs_coap_option.c b/deps/avs_coap/src/options/avs_coap_option.c index 032ae1cc..d219a66a 100644 --- a/deps/avs_coap/src/options/avs_coap_option.c +++ b/deps/avs_coap/src/options/avs_coap_option.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/options/avs_coap_option.h b/deps/avs_coap/src/options/avs_coap_option.h index 6cbc6fe3..3ea19112 100644 --- a/deps/avs_coap/src/options/avs_coap_option.h +++ b/deps/avs_coap/src/options/avs_coap_option.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/options/avs_coap_options.c b/deps/avs_coap/src/options/avs_coap_options.c index af95b4bb..509dd84f 100644 --- a/deps/avs_coap/src/options/avs_coap_options.c +++ b/deps/avs_coap/src/options/avs_coap_options.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/options/avs_coap_options.h b/deps/avs_coap/src/options/avs_coap_options.h index e8fb62c1..6d9a377c 100644 --- a/deps/avs_coap/src/options/avs_coap_options.h +++ b/deps/avs_coap/src/options/avs_coap_options.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/streaming/avs_coap_streaming_client.c b/deps/avs_coap/src/streaming/avs_coap_streaming_client.c index 83dc5843..2100afd6 100644 --- a/deps/avs_coap/src/streaming/avs_coap_streaming_client.c +++ b/deps/avs_coap/src/streaming/avs_coap_streaming_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/streaming/avs_coap_streaming_client.h b/deps/avs_coap/src/streaming/avs_coap_streaming_client.h index 9090239c..62ecf701 100644 --- a/deps/avs_coap/src/streaming/avs_coap_streaming_client.h +++ b/deps/avs_coap/src/streaming/avs_coap_streaming_client.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/streaming/avs_coap_streaming_server.c b/deps/avs_coap/src/streaming/avs_coap_streaming_server.c index b43962bb..c200ebb6 100644 --- a/deps/avs_coap/src/streaming/avs_coap_streaming_server.c +++ b/deps/avs_coap/src/streaming/avs_coap_streaming_server.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/streaming/avs_coap_streaming_server.h b/deps/avs_coap/src/streaming/avs_coap_streaming_server.h index a169c862..8581dd9a 100644 --- a/deps/avs_coap/src/streaming/avs_coap_streaming_server.h +++ b/deps/avs_coap/src/streaming/avs_coap_streaming_server.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_ctx.c b/deps/avs_coap/src/tcp/avs_coap_tcp_ctx.c index dc7a9caa..a039dd03 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_ctx.c +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_ctx.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_ctx.h b/deps/avs_coap/src/tcp/avs_coap_tcp_ctx.h index 1cd52677..b9bfec87 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_ctx.h +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_ctx.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_header.c b/deps/avs_coap/src/tcp/avs_coap_tcp_header.c index 958d146f..cb0def84 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_header.c +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_header.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_header.h b/deps/avs_coap/src/tcp/avs_coap_tcp_header.h index 1474b16e..db1b01d6 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_header.h +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_header.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_msg.c b/deps/avs_coap/src/tcp/avs_coap_tcp_msg.c index d6a45043..1ae79019 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_msg.c +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_msg.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_msg.h b/deps/avs_coap/src/tcp/avs_coap_tcp_msg.h index ce66bc8a..dc96e81b 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_msg.h +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_msg.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_pending_requests.c b/deps/avs_coap/src/tcp/avs_coap_tcp_pending_requests.c index 2b8fa79f..fab4f2f6 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_pending_requests.c +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_pending_requests.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_pending_requests.h b/deps/avs_coap/src/tcp/avs_coap_tcp_pending_requests.h index 0a536d87..183f9eb0 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_pending_requests.h +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_pending_requests.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_signaling.c b/deps/avs_coap/src/tcp/avs_coap_tcp_signaling.c index ef6a39da..321f7e80 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_signaling.c +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_signaling.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_signaling.h b/deps/avs_coap/src/tcp/avs_coap_tcp_signaling.h index 10570f46..a97f19b3 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_signaling.h +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_signaling.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_utils.c b/deps/avs_coap/src/tcp/avs_coap_tcp_utils.c index 18746495..e169885f 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_utils.c +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/tcp/avs_coap_tcp_utils.h b/deps/avs_coap/src/tcp/avs_coap_tcp_utils.h index 8b13b536..bc18a26b 100644 --- a/deps/avs_coap/src/tcp/avs_coap_tcp_utils.h +++ b/deps/avs_coap/src/tcp/avs_coap_tcp_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_ctx.c b/deps/avs_coap/src/udp/avs_coap_udp_ctx.c index 3050b4ae..225a790b 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_ctx.c +++ b/deps/avs_coap/src/udp/avs_coap_udp_ctx.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_ctx.h b/deps/avs_coap/src/udp/avs_coap_udp_ctx.h index a63cce9b..955f5471 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_ctx.h +++ b/deps/avs_coap/src/udp/avs_coap_udp_ctx.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_header.h b/deps/avs_coap/src/udp/avs_coap_udp_header.h index 3d60fd83..68d1abf0 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_header.h +++ b/deps/avs_coap/src/udp/avs_coap_udp_header.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_msg.c b/deps/avs_coap/src/udp/avs_coap_udp_msg.c index a99c7e5c..c0e66402 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_msg.c +++ b/deps/avs_coap/src/udp/avs_coap_udp_msg.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_msg.h b/deps/avs_coap/src/udp/avs_coap_udp_msg.h index 2fedfbbf..a8294a08 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_msg.h +++ b/deps/avs_coap/src/udp/avs_coap_udp_msg.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_msg_cache.c b/deps/avs_coap/src/udp/avs_coap_udp_msg_cache.c index 9f1b30b8..a10621d6 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_msg_cache.c +++ b/deps/avs_coap/src/udp/avs_coap_udp_msg_cache.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_msg_cache.h b/deps/avs_coap/src/udp/avs_coap_udp_msg_cache.h index 9225d495..d20426b8 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_msg_cache.h +++ b/deps/avs_coap/src/udp/avs_coap_udp_msg_cache.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_tx_params.c b/deps/avs_coap/src/udp/avs_coap_udp_tx_params.c index bc30ab29..d82e55a5 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_tx_params.c +++ b/deps/avs_coap/src/udp/avs_coap_udp_tx_params.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/src/udp/avs_coap_udp_tx_params.h b/deps/avs_coap/src/udp/avs_coap_udp_tx_params.h index e4589815..73996bc6 100644 --- a/deps/avs_coap/src/udp/avs_coap_udp_tx_params.h +++ b/deps/avs_coap/src/udp/avs_coap_udp_tx_params.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/fuzz/CMakeLists.txt b/deps/avs_coap/tests/fuzz/CMakeLists.txt index 72f4d61c..ebe93453 100644 --- a/deps/avs_coap/tests/fuzz/CMakeLists.txt +++ b/deps/avs_coap/tests/fuzz/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/tests/fuzz/coap_async_api_tcp.c b/deps/avs_coap/tests/fuzz/coap_async_api_tcp.c index 1907575b..0b2f3888 100644 --- a/deps/avs_coap/tests/fuzz/coap_async_api_tcp.c +++ b/deps/avs_coap/tests/fuzz/coap_async_api_tcp.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/fuzz/coap_async_api_udp.c b/deps/avs_coap/tests/fuzz/coap_async_api_udp.c index b4c7ea67..8974b598 100644 --- a/deps/avs_coap/tests/fuzz/coap_async_api_udp.c +++ b/deps/avs_coap/tests/fuzz/coap_async_api_udp.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/fuzz/coap_parse.c b/deps/avs_coap/tests/fuzz/coap_parse.c index 89d7a309..fd01f578 100644 --- a/deps/avs_coap/tests/fuzz/coap_parse.c +++ b/deps/avs_coap/tests/fuzz/coap_parse.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/mock_clock.c b/deps/avs_coap/tests/mock_clock.c index 5aa60395..f6073e20 100644 --- a/deps/avs_coap/tests/mock_clock.c +++ b/deps/avs_coap/tests/mock_clock.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/mock_clock.h b/deps/avs_coap/tests/mock_clock.h index a9f8ea92..34a9efdc 100644 --- a/deps/avs_coap/tests/mock_clock.h +++ b/deps/avs_coap/tests/mock_clock.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/options/option.c b/deps/avs_coap/tests/options/option.c index a18af724..212b2c3e 100644 --- a/deps/avs_coap/tests/options/option.c +++ b/deps/avs_coap/tests/options/option.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/options/options.c b/deps/avs_coap/tests/options/options.c index 478d7228..ce6c137f 100644 --- a/deps/avs_coap/tests/options/options.c +++ b/deps/avs_coap/tests/options/options.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/socket.c b/deps/avs_coap/tests/socket.c index 5bbd004e..3b8b4478 100644 --- a/deps/avs_coap/tests/socket.c +++ b/deps/avs_coap/tests/socket.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/socket.h b/deps/avs_coap/tests/socket.h index 50b7973c..5668e408 100644 --- a/deps/avs_coap/tests/socket.h +++ b/deps/avs_coap/tests/socket.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/async_client.c b/deps/avs_coap/tests/tcp/async_client.c index 056db54c..639f4988 100644 --- a/deps/avs_coap/tests/tcp/async_client.c +++ b/deps/avs_coap/tests/tcp/async_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/async_server.c b/deps/avs_coap/tests/tcp/async_server.c index e2187aed..52b2f5bb 100644 --- a/deps/avs_coap/tests/tcp/async_server.c +++ b/deps/avs_coap/tests/tcp/async_server.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/csm.c b/deps/avs_coap/tests/tcp/csm.c index a775ca21..febe46e8 100644 --- a/deps/avs_coap/tests/tcp/csm.c +++ b/deps/avs_coap/tests/tcp/csm.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/ctx.c b/deps/avs_coap/tests/tcp/ctx.c index 5f484911..da92dfc7 100644 --- a/deps/avs_coap/tests/tcp/ctx.c +++ b/deps/avs_coap/tests/tcp/ctx.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/env.h b/deps/avs_coap/tests/tcp/env.h index 1d8d74fb..acfdde6e 100644 --- a/deps/avs_coap/tests/tcp/env.h +++ b/deps/avs_coap/tests/tcp/env.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/header.c b/deps/avs_coap/tests/tcp/header.c index a5974165..02d2b847 100644 --- a/deps/avs_coap/tests/tcp/header.c +++ b/deps/avs_coap/tests/tcp/header.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/helper_functions.h b/deps/avs_coap/tests/tcp/helper_functions.h index e89cc884..cb8c445f 100644 --- a/deps/avs_coap/tests/tcp/helper_functions.h +++ b/deps/avs_coap/tests/tcp/helper_functions.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/payload_escaper.c b/deps/avs_coap/tests/tcp/payload_escaper.c index 73f974dd..97b29677 100644 --- a/deps/avs_coap/tests/tcp/payload_escaper.c +++ b/deps/avs_coap/tests/tcp/payload_escaper.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/requesting.c b/deps/avs_coap/tests/tcp/requesting.c index df630e13..04910695 100644 --- a/deps/avs_coap/tests/tcp/requesting.c +++ b/deps/avs_coap/tests/tcp/requesting.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/responding.c b/deps/avs_coap/tests/tcp/responding.c index d18c3d22..b1563337 100644 --- a/deps/avs_coap/tests/tcp/responding.c +++ b/deps/avs_coap/tests/tcp/responding.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/setsock.c b/deps/avs_coap/tests/tcp/setsock.c index 6aa6910d..6c83c4b6 100644 --- a/deps/avs_coap/tests/tcp/setsock.c +++ b/deps/avs_coap/tests/tcp/setsock.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/tcp/utils.h b/deps/avs_coap/tests/tcp/utils.h index b32c57af..baa93306 100644 --- a/deps/avs_coap/tests/tcp/utils.h +++ b/deps/avs_coap/tests/tcp/utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/async_client.c b/deps/avs_coap/tests/udp/async_client.c index a7bc0c9c..9461d368 100644 --- a/deps/avs_coap/tests/udp/async_client.c +++ b/deps/avs_coap/tests/udp/async_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/async_client_with_big_data.c b/deps/avs_coap/tests/udp/async_client_with_big_data.c index b0832bf8..72deed4e 100644 --- a/deps/avs_coap/tests/udp/async_client_with_big_data.c +++ b/deps/avs_coap/tests/udp/async_client_with_big_data.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/async_observe.c b/deps/avs_coap/tests/udp/async_observe.c index 5c6b1596..4e25af50 100644 --- a/deps/avs_coap/tests/udp/async_observe.c +++ b/deps/avs_coap/tests/udp/async_observe.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/async_server.c b/deps/avs_coap/tests/udp/async_server.c index aed16b8c..42c7515a 100644 --- a/deps/avs_coap/tests/udp/async_server.c +++ b/deps/avs_coap/tests/udp/async_server.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/big_data.h b/deps/avs_coap/tests/udp/big_data.h index bed8802b..fdad9b2b 100644 --- a/deps/avs_coap/tests/udp/big_data.h +++ b/deps/avs_coap/tests/udp/big_data.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/fuzzer_cases.c b/deps/avs_coap/tests/udp/fuzzer_cases.c index b839bb97..a5d62dce 100644 --- a/deps/avs_coap/tests/udp/fuzzer_cases.c +++ b/deps/avs_coap/tests/udp/fuzzer_cases.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/msg.c b/deps/avs_coap/tests/udp/msg.c index 267ae177..37631753 100644 --- a/deps/avs_coap/tests/udp/msg.c +++ b/deps/avs_coap/tests/udp/msg.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/msg_cache.c b/deps/avs_coap/tests/udp/msg_cache.c index 6fe02ef5..a8b5ddc6 100644 --- a/deps/avs_coap/tests/udp/msg_cache.c +++ b/deps/avs_coap/tests/udp/msg_cache.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/setsock.c b/deps/avs_coap/tests/udp/setsock.c index 5ad4ac45..5ee36052 100644 --- a/deps/avs_coap/tests/udp/setsock.c +++ b/deps/avs_coap/tests/udp/setsock.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/streaming_client.c b/deps/avs_coap/tests/udp/streaming_client.c index c737f14a..95a87991 100644 --- a/deps/avs_coap/tests/udp/streaming_client.c +++ b/deps/avs_coap/tests/udp/streaming_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/streaming_observe.c b/deps/avs_coap/tests/udp/streaming_observe.c index 09074c11..6578436a 100644 --- a/deps/avs_coap/tests/udp/streaming_observe.c +++ b/deps/avs_coap/tests/udp/streaming_observe.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/streaming_server.c b/deps/avs_coap/tests/udp/streaming_server.c index 5072a6e7..3fd06ba0 100644 --- a/deps/avs_coap/tests/udp/streaming_server.c +++ b/deps/avs_coap/tests/udp/streaming_server.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/tx_params_mock.h b/deps/avs_coap/tests/udp/tx_params_mock.h index 39598e44..8a25abf3 100644 --- a/deps/avs_coap/tests/udp/tx_params_mock.h +++ b/deps/avs_coap/tests/udp/tx_params_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/udp_tx_params.c b/deps/avs_coap/tests/udp/udp_tx_params.c index 4da8d7f3..b705596d 100644 --- a/deps/avs_coap/tests/udp/udp_tx_params.c +++ b/deps/avs_coap/tests/udp/udp_tx_params.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/udp/utils.h b/deps/avs_coap/tests/udp/utils.h index ad9b11a1..9157b326 100644 --- a/deps/avs_coap/tests/udp/utils.h +++ b/deps/avs_coap/tests/udp/utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/utils.c b/deps/avs_coap/tests/utils.c index fd419111..b9b34957 100644 --- a/deps/avs_coap/tests/utils.c +++ b/deps/avs_coap/tests/utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tests/utils.h b/deps/avs_coap/tests/utils.h index c0632279..1a98e4ae 100644 --- a/deps/avs_coap/tests/utils.h +++ b/deps/avs_coap/tests/utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem CoAP library * All rights reserved. * diff --git a/deps/avs_coap/tools/avs_common.py b/deps/avs_coap/tools/avs_common.py index c32d57d7..b78fde2d 100644 --- a/deps/avs_coap/tools/avs_common.py +++ b/deps/avs_coap/tools/avs_common.py @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/tools/coverage b/deps/avs_coap/tools/coverage index dace48ba..3724aee1 100755 --- a/deps/avs_coap/tools/coverage +++ b/deps/avs_coap/tools/coverage @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # diff --git a/deps/avs_coap/tools/license_headers.py b/deps/avs_coap/tools/license_headers.py index eb809421..1e3b3cb0 100755 --- a/deps/avs_coap/tools/license_headers.py +++ b/deps/avs_coap/tools/license_headers.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem CoAP library # All rights reserved. # @@ -17,7 +17,7 @@ import avs_common -EXPECTED_COPYRIGHT_HEADER = 'Copyright 2017-2024 AVSystem ' +EXPECTED_COPYRIGHT_HEADER = 'Copyright 2017-2025 AVSystem ' LICENSE = ( 'AVSystem CoAP library', diff --git a/devconfig b/devconfig index b23ad8d3..e881c49d 100755 --- a/devconfig +++ b/devconfig @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # @@ -14,8 +14,11 @@ rm -rf avs_commons/install rm -rf deps/avs_commons/CMakeFiles rm -f deps/avs_commons/CMakeCache.txt +ANJAY_VERSION="unknown" + if [[ -d '.git' ]]; then echo "Updating submodules" && git submodule update --init --recursive || exit 1 + ANJAY_VERSION = $(git rev-parse --short HEAD) fi C_FLAGS='-g -std=c99 -Werror=implicit-function-declaration' @@ -25,7 +28,6 @@ EXTRA_FLAGS=() MODULE_DYNAMIC_LIBS='ON' MODULE_STATIC_LIBS='ON' -ANJAY_VERSION=$(git rev-parse --short HEAD) DTLS_BACKEND="mbedtls" WITH_STATIC_ANALYSIS='ON' WITH_EXAMPLES='ON' @@ -38,10 +40,6 @@ else WITH_ASAN=ON fi -if [[ "$ANJAY_VERSION" == "" ]]; then - ANJAY_VERSION="unknown" -fi - if ! which afl-gcc &>/dev/null; then if [[ -d "$HOME/tools/afl/latest" ]]; then AFL_FUZZER_DIR="$HOME/tools/afl/latest" diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index dca9f2fa..315c5ee0 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/doc/sphinx/extensions/builders/__init__.py b/doc/sphinx/extensions/builders/__init__.py index 9317eb23..94337195 100644 --- a/doc/sphinx/extensions/builders/__init__.py +++ b/doc/sphinx/extensions/builders/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/doc/sphinx/extensions/builders/dummy.py b/doc/sphinx/extensions/builders/dummy.py index 71cf2064..6010cd29 100644 --- a/doc/sphinx/extensions/builders/dummy.py +++ b/doc/sphinx/extensions/builders/dummy.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/doc/sphinx/extensions/builders/snippet_source_linter.py b/doc/sphinx/extensions/builders/snippet_source_linter.py index d2ab7b3e..136ab8f1 100644 --- a/doc/sphinx/extensions/builders/snippet_source_linter.py +++ b/doc/sphinx/extensions/builders/snippet_source_linter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/doc/sphinx/extensions/builders/snippet_source_list_references.py b/doc/sphinx/extensions/builders/snippet_source_list_references.py index b9611875..602885a5 100644 --- a/doc/sphinx/extensions/builders/snippet_source_list_references.py +++ b/doc/sphinx/extensions/builders/snippet_source_list_references.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/doc/sphinx/extensions/file_dirtiness_checker.py b/doc/sphinx/extensions/file_dirtiness_checker.py index f3967e2c..7b29130a 100644 --- a/doc/sphinx/extensions/file_dirtiness_checker.py +++ b/doc/sphinx/extensions/file_dirtiness_checker.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/doc/sphinx/extensions/small_literal.py b/doc/sphinx/extensions/small_literal.py new file mode 100644 index 00000000..c0b3ed79 --- /dev/null +++ b/doc/sphinx/extensions/small_literal.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2017-2025 AVSystem +# AVSystem Anjay LwM2M SDK +# All rights reserved. +# +# Licensed under the AVSystem-5-clause License. +# See the attached LICENSE file for details. + +from docutils import nodes +from sphinx.application import Sphinx + +def small_literal_role(name, rawtext, text, lineno, inliner, options={}, content=[]): + return [nodes.literal(rawtext, text, classes=['small-literal'])], [] + +def setup(app: Sphinx): + app.add_role('small-literal', small_literal_role) diff --git a/doc/sphinx/extensions/snippet_source.py b/doc/sphinx/extensions/snippet_source.py index e34d3a20..881f83d1 100644 --- a/doc/sphinx/extensions/snippet_source.py +++ b/doc/sphinx/extensions/snippet_source.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # @@ -12,6 +12,7 @@ import sphinx.writers.latex import sphinx.writers.text from docutils.parsers.rst import directives +from sphinx.application import Sphinx from sphinx.directives.code import container_wrapper from sphinx.transforms.post_transforms.code import HighlightLanguageVisitor from sphinx.util import parselinenos @@ -85,7 +86,7 @@ def run(self): return [node] -def setup(app): +def setup(app: Sphinx): app.add_node(SnippetSourceNode, html=(sphinx.writers.html.HTMLTranslator.visit_literal_block, sphinx.writers.html.HTMLTranslator.depart_literal_block), diff --git a/doc/sphinx/snippet_sources.md5 b/doc/sphinx/snippet_sources.md5 index 4ecfca11..5ca8598f 100644 --- a/doc/sphinx/snippet_sources.md5 +++ b/doc/sphinx/snippet_sources.md5 @@ -1,5 +1,5 @@ -563b9fc06ed0c55bae149f839ab80f11 deps/avs_coap/include_public/avsystem/coap/tcp.h -8d609e7d1e46df8b37f8d694f6d78e7f deps/avs_coap/include_public/avsystem/coap/udp.h +42d50b4f7ccd647eea1c1b60775c5c6b deps/avs_coap/include_public/avsystem/coap/tcp.h +3c1fd09be1f89dd8339b2e55c2bee4cf deps/avs_coap/include_public/avsystem/coap/udp.h 6979acbbeda62d10befc6f7aa7e0865e deps/avs_commons/include_public/avsystem/commons/avs_addrinfo.h 0e56e80e053a9afedc7a714f2acbcc7b deps/avs_commons/include_public/avsystem/commons/avs_base64.h e9bc875ab314a3d88787889cfe282f8f deps/avs_commons/include_public/avsystem/commons/avs_crypto_common.h @@ -82,13 +82,16 @@ f971df7872a8f052bb72ae64610a8031 examples/tutorial/firmware-update/basic-implem 1d85bb08f511fcc7b321f0be56ddb119 examples/tutorial/firmware-update/basic-implementation/src/main.c 844cd7d9d0ebe80007dc5ae8d6a719b0 examples/tutorial/firmware-update/download-resumption/src/firmware_update.c 077f6b89dad59ef3b9b58e2abe93aff6 examples/tutorial/firmware-update/secure-downloads/src/firmware_update.c -99ef6e1d741fbfefab9ddf0db97c61e7 include_public/anjay/advanced_fw_update.h -be8a4c22a41c2ab79bf3a68f1f74f301 include_public/anjay/attr_storage.h -8da010b13c862c6730a6e41624f16266 include_public/anjay/core.h -9771c6bc4940d778a12ab93cb400a11c include_public/anjay/dm.h -56b500ecbd5ffc8d468327c650883cbd include_public/anjay/fw_update.h -b49ca67d9f4f04bf20261c261ad41822 include_public/anjay/io.h -e7c2357db51f9896d2b82245699e0a42 include_public/anjay/security.h -f76d50fd887c4ada8500f67bccffdd74 tests/integration/framework/test_utils.py -88058893fb17ae75099f6b998233a693 tools/provisioning-tool/factory_prov/factory_prov.py -70d3ff815fb42ff052a7a05d47f9aee9 tools/provisioning-tool/ptool.py +abce3c19d5ee5d6047149d0cbe941ac2 examples/tutorial/LwM2M-Gateway/src/gateway_server.c +e94802478883921402927aa8fee1a3bf examples/tutorial/LwM2M-Gateway/src/main.c +6990f616a230d2a2cbdcb55c7b3ce6fe examples/tutorial/LwM2M-Gateway/src/temperature_object.c +b8b6b4e257e666806de88f3a2a08c6bc include_public/anjay/advanced_fw_update.h +207ec4f486627d27f517ec1f2d40eb53 include_public/anjay/attr_storage.h +fee6ef0cba46431d86ff22664ce3c0d7 include_public/anjay/core.h +ff017be77afa5de89af57960b1ba3623 include_public/anjay/dm.h +d916dd34be13c1dbc9d33d6d0a2dc9bf include_public/anjay/fw_update.h +e99d76eedcc0544c8e2c6d7da38ba1fa include_public/anjay/io.h +7797cb3aa8b055f7506a5ee54a02db3d include_public/anjay/security.h +fbbc991fcbdef8f002352b47de1cd792 tests/integration/framework/test_utils.py +eda8a63a463f2e435b51dc81547cd7dc tools/provisioning-tool/factory_prov/factory_prov.py +628ebb066aaad44696595dd9d8c9e4a4 tools/provisioning-tool/ptool.py diff --git a/doc/sphinx/source/AdvancedTopics.rst b/doc/sphinx/source/AdvancedTopics.rst index a6c1702b..828abeb1 100644 --- a/doc/sphinx/source/AdvancedTopics.rst +++ b/doc/sphinx/source/AdvancedTopics.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-AccessControl.rst b/doc/sphinx/source/AdvancedTopics/AT-AccessControl.rst index 1c57f0d5..2e9765b9 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-AccessControl.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-AccessControl.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-AttributeStorage.rst b/doc/sphinx/source/AdvancedTopics/AT-AttributeStorage.rst index 33cd7200..ff367e63 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-AttributeStorage.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-AttributeStorage.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-Certificates.rst b/doc/sphinx/source/AdvancedTopics/AT-Certificates.rst index 3b163e97..4a2c3446 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-Certificates.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-Certificates.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomEventLoop.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomEventLoop.rst index 84c0c6e4..04856c64 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomEventLoop.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomEventLoop.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects.rst index 7f67f2d9..52ce970a 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO1_SingleInstanceReadOnly.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO1_SingleInstanceReadOnly.rst index acc788ae..967c82c4 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO1_SingleInstanceReadOnly.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO1_SingleInstanceReadOnly.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO2_SingleInstanceExecutableAndReadOnly.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO2_SingleInstanceExecutableAndReadOnly.rst index e36f22a5..373131b7 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO2_SingleInstanceExecutableAndReadOnly.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO2_SingleInstanceExecutableAndReadOnly.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO3_MultiInstanceReadOnlyFixed.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO3_MultiInstanceReadOnlyFixed.rst index b474a07c..55e01304 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO3_MultiInstanceReadOnlyFixed.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO3_MultiInstanceReadOnlyFixed.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO4_FixedInstanceWritable.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO4_FixedInstanceWritable.rst index ee0fad54..7323c986 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO4_FixedInstanceWritable.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO4_FixedInstanceWritable.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO5_MultiInstanceDynamic.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO5_MultiInstanceDynamic.rst index 9b2771f7..10e2e7ab 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO5_MultiInstanceDynamic.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO5_MultiInstanceDynamic.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO6_MultipleResourceInstances.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO6_MultipleResourceInstances.rst index ee7aef3f..7e7e9ef1 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO6_MultipleResourceInstances.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO6_MultipleResourceInstances.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO7_BootstrapAwareness.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO7_BootstrapAwareness.rst index 8418a8ee..fe27d440 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO7_BootstrapAwareness.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO7_BootstrapAwareness.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_BootstrapAwareness.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_BootstrapAwareness.rst index 853b4588..a1b00305 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_BootstrapAwareness.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_BootstrapAwareness.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_FixedInstanceWritable.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_FixedInstanceWritable.rst index 52521363..e3f0bf05 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_FixedInstanceWritable.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_FixedInstanceWritable.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultiInstanceDynamic.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultiInstanceDynamic.rst index 32162407..7b646f31 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultiInstanceDynamic.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultiInstanceDynamic.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultiInstanceReadOnlyFixed.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultiInstanceReadOnlyFixed.rst index 668b760f..d33ed683 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultiInstanceReadOnlyFixed.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultiInstanceReadOnlyFixed.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultipleResourceInstances.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultipleResourceInstances.rst index 54433220..ef923223 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultipleResourceInstances.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_MultipleResourceInstances.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_SingleInstanceExecutableAndReadOnly.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_SingleInstanceExecutableAndReadOnly.rst index 5ac148f6..b66a9137 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_SingleInstanceExecutableAndReadOnly.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_SingleInstanceExecutableAndReadOnly.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_SingleInstanceReadOnly.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_SingleInstanceReadOnly.rst index 5fd1fabc..98c5e11e 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_SingleInstanceReadOnly.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/AT_CO_SingleInstanceReadOnly.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/Anjay_codegen_note.rst b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/Anjay_codegen_note.rst index e1b66d87..22a876c8 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/Anjay_codegen_note.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-CustomObjects/Anjay_codegen_note.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-EventLoopNotes.rst b/doc/sphinx/source/AdvancedTopics/AT-EventLoopNotes.rst index 16af7211..67e51453 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-EventLoopNotes.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-EventLoopNotes.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-IpsoObjects.rst b/doc/sphinx/source/AdvancedTopics/AT-IpsoObjects.rst index 7296bf78..b0dd6a5d 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-IpsoObjects.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-IpsoObjects.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-NetworkErrorHandling.rst b/doc/sphinx/source/AdvancedTopics/AT-NetworkErrorHandling.rst index 6e23e6ab..3255c1f7 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-NetworkErrorHandling.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-NetworkErrorHandling.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. @@ -128,6 +128,8 @@ Other error conditions will be passed to the appropriate callback handler, see the `documentation to anjay_download_finished_handler_t <../api/download_8h.html#a44f0d37ec9ef8123bf88aa9ea9ee7291>`_ for details. + CoAP downloads support automatic resumption of downloads after network errors, + see the :ref:`how-can-we-ensure-higher-success-rate` for details. .. rubric:: Footnotes diff --git a/doc/sphinx/source/AdvancedTopics/AT-OtherFeatures.rst b/doc/sphinx/source/AdvancedTopics/AT-OtherFeatures.rst index a0d1082f..2612ade3 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-OtherFeatures.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-OtherFeatures.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-Persistence.rst b/doc/sphinx/source/AdvancedTopics/AT-Persistence.rst index 2b471e0d..726ab27e 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-Persistence.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-Persistence.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/AdvancedTopics/AT-RetransmissionsTimeoutsCaching.rst b/doc/sphinx/source/AdvancedTopics/AT-RetransmissionsTimeoutsCaching.rst index b22cdb28..c4070dc2 100644 --- a/doc/sphinx/source/AdvancedTopics/AT-RetransmissionsTimeoutsCaching.rst +++ b/doc/sphinx/source/AdvancedTopics/AT-RetransmissionsTimeoutsCaching.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient.rst b/doc/sphinx/source/BasicClient.rst index 5fd9fb1d..b4cb1d2b 100644 --- a/doc/sphinx/source/BasicClient.rst +++ b/doc/sphinx/source/BasicClient.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC-Initialization.rst b/doc/sphinx/source/BasicClient/BC-Initialization.rst index 1dd8059e..964faa75 100644 --- a/doc/sphinx/source/BasicClient/BC-Initialization.rst +++ b/doc/sphinx/source/BasicClient/BC-Initialization.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC-MandatoryObjects.rst b/doc/sphinx/source/BasicClient/BC-MandatoryObjects.rst index 9c244613..394af0de 100644 --- a/doc/sphinx/source/BasicClient/BC-MandatoryObjects.rst +++ b/doc/sphinx/source/BasicClient/BC-MandatoryObjects.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC-Notifications.rst b/doc/sphinx/source/BasicClient/BC-Notifications.rst index f695da81..cddcee87 100644 --- a/doc/sphinx/source/BasicClient/BC-Notifications.rst +++ b/doc/sphinx/source/BasicClient/BC-Notifications.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC-ObjectImplementation.rst b/doc/sphinx/source/BasicClient/BC-ObjectImplementation.rst index 70e8fb87..aa760cfe 100644 --- a/doc/sphinx/source/BasicClient/BC-ObjectImplementation.rst +++ b/doc/sphinx/source/BasicClient/BC-ObjectImplementation.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC-Security.rst b/doc/sphinx/source/BasicClient/BC-Security.rst index 8de0609a..49ec83d1 100644 --- a/doc/sphinx/source/BasicClient/BC-Security.rst +++ b/doc/sphinx/source/BasicClient/BC-Security.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC-Send.rst b/doc/sphinx/source/BasicClient/BC-Send.rst index d7cd9394..36916342 100644 --- a/doc/sphinx/source/BasicClient/BC-Send.rst +++ b/doc/sphinx/source/BasicClient/BC-Send.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC-ThreadSafety.rst b/doc/sphinx/source/BasicClient/BC-ThreadSafety.rst index babe9ec6..fb412eac 100644 --- a/doc/sphinx/source/BasicClient/BC-ThreadSafety.rst +++ b/doc/sphinx/source/BasicClient/BC-ThreadSafety.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC1.rst b/doc/sphinx/source/BasicClient/BC1.rst index b75c5d8b..1cabe96d 100644 --- a/doc/sphinx/source/BasicClient/BC1.rst +++ b/doc/sphinx/source/BasicClient/BC1.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC2.rst b/doc/sphinx/source/BasicClient/BC2.rst index d326fb70..1cb54f21 100644 --- a/doc/sphinx/source/BasicClient/BC2.rst +++ b/doc/sphinx/source/BasicClient/BC2.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC3.rst b/doc/sphinx/source/BasicClient/BC3.rst index 1f4d8157..9749e319 100644 --- a/doc/sphinx/source/BasicClient/BC3.rst +++ b/doc/sphinx/source/BasicClient/BC3.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC4.rst b/doc/sphinx/source/BasicClient/BC4.rst index aaeb07af..34246875 100644 --- a/doc/sphinx/source/BasicClient/BC4.rst +++ b/doc/sphinx/source/BasicClient/BC4.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC5.rst b/doc/sphinx/source/BasicClient/BC5.rst index 9a6a6f67..2f553317 100644 --- a/doc/sphinx/source/BasicClient/BC5.rst +++ b/doc/sphinx/source/BasicClient/BC5.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC6.rst b/doc/sphinx/source/BasicClient/BC6.rst index 4ccabc20..420f65b0 100644 --- a/doc/sphinx/source/BasicClient/BC6.rst +++ b/doc/sphinx/source/BasicClient/BC6.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC7.rst b/doc/sphinx/source/BasicClient/BC7.rst index be13978e..4f11a039 100644 --- a/doc/sphinx/source/BasicClient/BC7.rst +++ b/doc/sphinx/source/BasicClient/BC7.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/BasicClient/BC8.rst b/doc/sphinx/source/BasicClient/BC8.rst index 0166cc09..85bfff8f 100644 --- a/doc/sphinx/source/BasicClient/BC8.rst +++ b/doc/sphinx/source/BasicClient/BC8.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures.rst b/doc/sphinx/source/CommercialFeatures.rst index 3c0ed296..294796f1 100644 --- a/doc/sphinx/source/CommercialFeatures.rst +++ b/doc/sphinx/source/CommercialFeatures.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-CorePersistence.rst b/doc/sphinx/source/CommercialFeatures/CF-CorePersistence.rst index 135f6074..a704b588 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-CorePersistence.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-CorePersistence.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. @@ -81,6 +81,9 @@ Reconnection, successful resumption: The difference is **4523 bytes (87.6 % reduction)**. +.. note:: + Core Persistence must not be used in LwM2M Clients acting as LwM2M Gateway. + Technical documentation ----------------------- diff --git a/doc/sphinx/source/CommercialFeatures/CF-CustomHardwareSupport.rst b/doc/sphinx/source/CommercialFeatures/CF-CustomHardwareSupport.rst index bb553cdc..5190add0 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-CustomHardwareSupport.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-CustomHardwareSupport.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-EST.rst b/doc/sphinx/source/CommercialFeatures/CF-EST.rst index dc179216..ffce5c1a 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-EST.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-EST.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-FSDM.rst b/doc/sphinx/source/CommercialFeatures/CF-FSDM.rst index f1da29b1..03143e09 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-FSDM.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-FSDM.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-HSM.rst b/doc/sphinx/source/CommercialFeatures/CF-HSM.rst index c935115c..aab9c0ae 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-HSM.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-HSM.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-IoTSAFE.rst b/doc/sphinx/source/CommercialFeatures/CF-IoTSAFE.rst index 084e41e2..d716e97f 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-IoTSAFE.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-IoTSAFE.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-NIDD.rst b/doc/sphinx/source/CommercialFeatures/CF-NIDD.rst index b9b458fc..36473800 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-NIDD.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-NIDD.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-OSCORE.rst b/doc/sphinx/source/CommercialFeatures/CF-OSCORE.rst index 44d3ddc8..8436b3de 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-OSCORE.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-OSCORE.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-SMSBinding.rst b/doc/sphinx/source/CommercialFeatures/CF-SMSBinding.rst index cd4ae570..47def7ef 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-SMSBinding.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-SMSBinding.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/CommercialFeatures/CF-SmartCardBootstrap.rst b/doc/sphinx/source/CommercialFeatures/CF-SmartCardBootstrap.rst index 9ced1426..a9103227 100644 --- a/doc/sphinx/source/CommercialFeatures/CF-SmartCardBootstrap.rst +++ b/doc/sphinx/source/CommercialFeatures/CF-SmartCardBootstrap.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/Compiling_client_applications.rst b/doc/sphinx/source/Compiling_client_applications.rst index bfd700c2..1a7ceb00 100644 --- a/doc/sphinx/source/Compiling_client_applications.rst +++ b/doc/sphinx/source/Compiling_client_applications.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/FirmwareUpdateTutorial.rst b/doc/sphinx/source/FirmwareUpdateTutorial.rst index 36129fb1..e141b852 100644 --- a/doc/sphinx/source/FirmwareUpdateTutorial.rst +++ b/doc/sphinx/source/FirmwareUpdateTutorial.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate.rst b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate.rst index 31695d82..7ec5bbdd 100644 --- a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate.rst +++ b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-BasicImplementation.rst b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-BasicImplementation.rst index 89d208c6..f7ca3279 100644 --- a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-BasicImplementation.rst +++ b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-BasicImplementation.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-Examples.rst b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-Examples.rst index fb45fffb..ebff0da5 100644 --- a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-Examples.rst +++ b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-Examples.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-ResourceDefinitions.rst b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-ResourceDefinitions.rst index 63c556df..5145ef2f 100644 --- a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-ResourceDefinitions.rst +++ b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-ResourceDefinitions.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-StateDiagram.rst b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-StateDiagram.rst index a9196edb..c7a4f539 100644 --- a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-StateDiagram.rst +++ b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/FU-AFU-StateDiagram.rst @@ -1,5 +1,5 @@ .. - Copyright 2017-2024 AVSystem + Copyright 2017-2025 AVSystem AVSystem Anjay LwM2M SDK All rights reserved. diff --git a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/_files/33629.xml b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/_files/33629.xml index ef3502ca..4686e6a4 100644 --- a/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/_files/33629.xml +++ b/doc/sphinx/source/FirmwareUpdateTutorial/FU-AdvancedFirmwareUpdate/_files/33629.xml @@ -1,7 +1,7 @@ | - intervals between resource reads + * |<------>| * - point in time when underlying state + * min_period actually changes + * + * the specification would require the notification to be sent exactly at the + * time of the (*) event, but with this naive implementation, will be delayed + * until the next (|). + */ +anjay_resource_observation_status_t +anjay_lwm2m_gateway_resource_observation_status(anjay_t *anjay_locked, + anjay_iid_t end_dev, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid); +# endif // ANJAY_WITH_OBSERVATION_STATUS +# ifdef __cplusplus +} +# endif + +#endif // ANJAY_WITH_LWM2M_GATEWAY +#endif // ANJAY_INCLUDE_LWM2M_GATEWAY_H diff --git a/include_public/anjay/lwm2m_send.h b/include_public/anjay/lwm2m_send.h index 71f3197c..3842db9e 100644 --- a/include_public/anjay/lwm2m_send.h +++ b/include_public/anjay/lwm2m_send.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -111,6 +111,15 @@ typedef void anjay_send_finished_handler_t(anjay_t *anjay, * anjay_send_batch_builder_compile function call. * 4. Pass the resulting batch to @ref anjay_send . * + * IMPORTANT NOTE: + * LwM2M SEND API can be also used with LwM2M Gateway End Device objects \ref + * lwm2m_gateway.h . In such case, use anjay_lwm2m_gateway_send_batch_add_* + * functions to add values from Gateway End Device objects to the batch. In one + * batch builder you can mix data from different End Devices and Gateway + * objects. Do not use @ref anjay_lwm2m_gateway_deregister_device or @ref + * anjay_lwm2m_gateway_register_device when building data batch because the + * records in batch may refer to the wrong End Device. + * * Example use (error checking omitted for brevity): * @code * // Creates a builder for a batch. diff --git a/include_public/anjay/security.h b/include_public/anjay/security.h index 9256f940..20ed984e 100644 --- a/include_public/anjay/security.h +++ b/include_public/anjay/security.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/include_public/anjay/server.h b/include_public/anjay/server.h index c35ea4f1..a39d961a 100644 --- a/include_public/anjay/server.h +++ b/include_public/anjay/server.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/include_public/anjay/stats.h b/include_public/anjay/stats.h index cae756ea..b7e31850 100644 --- a/include_public/anjay/stats.h +++ b/include_public/anjay/stats.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/include_public/anjay/sw_mgmt.h b/include_public/anjay/sw_mgmt.h index 42d067c8..924c6172 100644 --- a/include_public/anjay/sw_mgmt.h +++ b/include_public/anjay/sw_mgmt.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/ltoconfig b/ltoconfig index f055dbae..bdc686b9 100755 --- a/ltoconfig +++ b/ltoconfig @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/requirements.txt b/requirements.txt index b8d6a617..aefe0356 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/src/anjay_config_log.h b/src/anjay_config_log.h index 2e755a75..c0cbe223 100644 --- a/src/anjay_config_log.h +++ b/src/anjay_config_log.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -164,6 +164,11 @@ static inline void _anjay_log_feature_list(void) { #else // ANJAY_WITH_LWM2M11 _anjay_log(anjay, TRACE, "ANJAY_WITH_LWM2M11 = OFF"); #endif // ANJAY_WITH_LWM2M11 +#ifdef ANJAY_WITH_LWM2M_GATEWAY + _anjay_log(anjay, TRACE, "ANJAY_WITH_LWM2M_GATEWAY = ON"); +#else // ANJAY_WITH_LWM2M_GATEWAY + _anjay_log(anjay, TRACE, "ANJAY_WITH_LWM2M_GATEWAY = OFF"); +#endif // ANJAY_WITH_LWM2M_GATEWAY #ifdef ANJAY_WITH_LWM2M_JSON _anjay_log(anjay, TRACE, "ANJAY_WITH_LWM2M_JSON = ON"); #else // ANJAY_WITH_LWM2M_JSON diff --git a/src/anjay_init.h b/src/anjay_init.h index d190a32c..063f9d67 100644 --- a/src/anjay_init.h +++ b/src/anjay_init.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -16,6 +16,12 @@ # error "ANJAY_WITH_MODULE_ATTR_STORAGE has been removed since Anjay 3.0. Please update your anjay_config.h to use ANJAY_WITH_ATTR_STORAGE instead." #endif // ANJAY_WITH_MODULE_ATTR_STORAGE +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# ifndef ANJAY_WITH_LWM2M11 +# error "LwM2M Gateway functionality requires LwM2M 1.1 support." +# endif // ANJAY_WITH_LWM2M11 +#endif // ANJAY_WITH_LWM2M_GATEWAY + #if defined(AVS_COMMONS_HAVE_VISIBILITY) && !defined(ANJAY_TEST) /* set default visibility for external symbols */ # pragma GCC visibility push(default) diff --git a/src/anjay_modules/anjay_access_utils.h b/src/anjay_modules/anjay_access_utils.h index faeebe91..1c9f101c 100644 --- a/src/anjay_modules/anjay_access_utils.h +++ b/src/anjay_modules/anjay_access_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/anjay_modules/anjay_attr_storage_utils.h b/src/anjay_modules/anjay_attr_storage_utils.h new file mode 100644 index 00000000..5d47d974 --- /dev/null +++ b/src/anjay_modules/anjay_attr_storage_utils.h @@ -0,0 +1,15 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ + +#ifndef ANJAY_INCLUDE_ANJAY_MODULES_AS_H +#define ANJAY_INCLUDE_ANJAY_MODULES_AS_H + +typedef struct anjay_attr_storage_struct anjay_attr_storage_t; + +#endif // ANJAY_INCLUDE_ANJAY_MODULES_AS_H diff --git a/src/anjay_modules/anjay_bootstrap.h b/src/anjay_modules/anjay_bootstrap.h index 700ddd64..ae90cc22 100644 --- a/src/anjay_modules/anjay_bootstrap.h +++ b/src/anjay_modules/anjay_bootstrap.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/anjay_modules/anjay_dm_utils.h b/src/anjay_modules/anjay_dm_utils.h index 23c78ce9..695b2b9a 100644 --- a/src/anjay_modules/anjay_dm_utils.h +++ b/src/anjay_modules/anjay_dm_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -14,45 +14,28 @@ # include #endif // ANJAY_WITH_SEND +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +# include + +# include +#endif // ANJAY_WITH_LWM2M_GATEWAY + #include #include #include VISIBILITY_PRIVATE_HEADER_BEGIN -#define MAX_PATH_STRING_SIZE sizeof("/65535/65535/65535/65535") - -// NOTE: A lot of code depends on numerical values of these constants. -// Please be careful when refactoring. -typedef enum { - ANJAY_ID_OID, - ANJAY_ID_IID, - ANJAY_ID_RID, - ANJAY_ID_RIID, - _ANJAY_URI_PATH_MAX_LENGTH -} anjay_id_type_t; - -/** - * A data type that represents a data model path. - * - * It may represent a root path, an Object path, an Object Instance path, a - * Resource path, or a Resource Instance path. - * - * The path is terminated either by an @ref ANJAY_ID_INVALID value, or - * end-of-array (in case of Resource Instance paths). In case of root, Object - * and Object Instance paths, the array elements past the terminating invalid ID - * value are undefined and shall not be used. They are NOT required to be set to - * @ref ANJAY_ID_INVALID. Paths object that numerically differ only in values - * past the terminating invalid ID shall be treated as equal (and this is how - * @ref _anjay_uri_path_equal is implemented). - * - * The ids array is designed to be safely and meaningfully indexed by - * @ref anjay_id_type_t values. - */ -typedef struct { - uint16_t ids[_ANJAY_URI_PATH_MAX_LENGTH]; - -} anjay_uri_path_t; +#ifdef ANJAY_WITH_LWM2M_GATEWAY +// ANJAY_GATEWAY_MAX_PREFIX_LEN contains space for null-terminator, but since +// sizeof(...) already includes null-terminator, we use that one additional byte +// for the new leading '/' in path +# define MAX_PATH_STRING_SIZE \ + sizeof("/65535/65535/65535/65535") + ANJAY_GATEWAY_MAX_PREFIX_LEN +#else // ANJAY_WITH_LWM2M_GATEWAY +# define MAX_PATH_STRING_SIZE sizeof("/65535/65535/65535/65535") +#endif // ANJAY_WITH_LWM2M_GATEWAY static inline size_t _anjay_uri_path_length(const anjay_uri_path_t *path) { size_t result; @@ -74,8 +57,50 @@ static inline bool _anjay_uri_path_leaf_is(const anjay_uri_path_t *path, return _anjay_uri_path_length(path) == (size_t) id_type + 1u; } +#ifdef ANJAY_WITH_LWM2M_GATEWAY +static inline bool _anjay_uri_path_prefix_is(const anjay_uri_path_t *path, + const char *prefix) { + return strcmp(path->prefix, prefix) == 0; +} + +static inline bool _anjay_uri_path_prefix_equal(const anjay_uri_path_t *left, + const anjay_uri_path_t *right) { + return strcmp(left->prefix, right->prefix) == 0; +} + +static inline bool _anjay_uri_path_has_prefix(const anjay_uri_path_t *path) { + return path->prefix[0] != '\0'; +} + +static inline void +_anjay_uri_path_with_prefix_from_end_device_iid(anjay_uri_path_t *path, + anjay_iid_t end_device_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid) { + *path = (anjay_uri_path_t) { + .ids = { + [ANJAY_ID_OID] = oid, + [ANJAY_ID_IID] = iid, + [ANJAY_ID_RID] = rid, + [ANJAY_ID_RIID] = riid + } + }; + avs_simple_snprintf(path->prefix, ANJAY_GATEWAY_MAX_PREFIX_LEN, + "dev%" PRIu16, end_device_iid); +} + +#endif // ANJAY_WITH_LWM2M_GATEWAY + static inline int _anjay_uri_path_compare(const anjay_uri_path_t *left, const anjay_uri_path_t *right) { +#ifdef ANJAY_WITH_LWM2M_GATEWAY + int prefix_cmp = strcmp(left->prefix, right->prefix); + if (prefix_cmp) { + return prefix_cmp; + } +#endif // ANJAY_WITH_LWM2M_GATEWAY for (size_t i = 0; i < AVS_ARRAY_SIZE(left->ids); ++i) { if (left->ids[i] < right->ids[i]) { return -1; @@ -184,6 +209,62 @@ const char *_anjay_debug_make_path__(char *buffer, MAKE_URI_PATH(ANJAY_ID_INVALID, ANJAY_ID_INVALID, ANJAY_ID_INVALID, \ ANJAY_ID_INVALID) +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# define URI_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid, Iid, Rid, Riid) \ + { \ + .ids = { \ + [ANJAY_ID_OID] = (Oid), \ + [ANJAY_ID_IID] = (Iid), \ + [ANJAY_ID_RID] = (Rid), \ + [ANJAY_ID_RIID] = (Riid) \ + }, \ + .prefix = Prefix \ + } + +# define RESOURCE_INSTANCE_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid, Iid, \ + Rid, Riid) \ + URI_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid, Iid, Rid, Riid) + +# define RESOURCE_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid, Iid, Rid) \ + URI_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid, Iid, Rid, \ + ANJAY_ID_INVALID) + +# define INSTANCE_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid, Iid) \ + URI_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid, Iid, ANJAY_ID_INVALID, \ + ANJAY_ID_INVALID) + +# define OBJECT_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid) \ + URI_PATH_INITIALIZER_WITH_PREFIX(Prefix, Oid, ANJAY_ID_INVALID, \ + ANJAY_ID_INVALID, ANJAY_ID_INVALID) + +# define ROOT_PATH_INITIALIZER_WITH_PREFIX(Prefix) \ + URI_PATH_INITIALIZER_WITH_PREFIX(Prefix, ANJAY_ID_INVALID, \ + ANJAY_ID_INVALID, ANJAY_ID_INVALID, \ + ANJAY_ID_INVALID) + +# define MAKE_URI_PATH_WITH_PREFIX(...) \ + ((anjay_uri_path_t) URI_PATH_INITIALIZER_WITH_PREFIX(__VA_ARGS__)) + +# define MAKE_RESOURCE_INSTANCE_PATH_WITH_PREFIX(Prefix, Oid, Iid, Rid, \ + Riid) \ + MAKE_URI_PATH_WITH_PREFIX(Prefix, Oid, Iid, Rid, Riid) + +# define MAKE_RESOURCE_PATH_WITH_PREFIX(Prefix, Oid, Iid, Rid) \ + MAKE_URI_PATH_WITH_PREFIX(Prefix, Oid, Iid, Rid, ANJAY_ID_INVALID) + +# define MAKE_INSTANCE_PATH_WITH_PREFIX(Prefix, Oid, Iid) \ + MAKE_URI_PATH_WITH_PREFIX(Prefix, Oid, Iid, ANJAY_ID_INVALID, \ + ANJAY_ID_INVALID) + +# define MAKE_OBJECT_PATH_WITH_PREFIX(Prefix, Oid) \ + MAKE_URI_PATH_WITH_PREFIX(Prefix, Oid, ANJAY_ID_INVALID, \ + ANJAY_ID_INVALID, ANJAY_ID_INVALID) + +# define MAKE_ROOT_PATH_WITH_PREFIX(Prefix) \ + MAKE_URI_PATH_WITH_PREFIX(Prefix, ANJAY_ID_INVALID, ANJAY_ID_INVALID, \ + ANJAY_ID_INVALID, ANJAY_ID_INVALID) +#endif // ANJAY_WITH_LWM2M_GATEWAY + typedef enum anjay_request_action { ANJAY_ACTION_READ, #ifdef ANJAY_WITH_LWM2M11 @@ -884,16 +965,11 @@ int _anjay_register_object_unlocked( AVS_LIST(anjay_dm_installed_object_t) *elem_ptr_move); #ifdef ANJAY_WITH_SEND -int _anjay_send_batch_data_add_current_unlocked( - anjay_send_batch_builder_t *builder, - anjay_unlocked_t *anjay, - anjay_oid_t oid, - anjay_iid_t iid, - anjay_rid_t rid); int _anjay_send_batch_data_add_current_multiple_unlocked( anjay_send_batch_builder_t *builder, anjay_unlocked_t *anjay, + anjay_iid_t gateway_iid, const anjay_send_resource_path_t *paths, size_t paths_length, bool ignore_not_found); @@ -988,6 +1064,21 @@ int _anjay_execute_get_arg_value_unlocked(anjay_unlocked_execute_ctx_t *ctx, anjay_dm_t *_anjay_get_dm(anjay_unlocked_t *anjay); +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# define DM_LOG_PREFIX "%s%s" +# define DM_LOG_PREFIX_ARG(Prefix) \ + ((Prefix && Prefix[0] != '\0') ? "/" : ""), \ + ((Prefix && Prefix[0] != '\0') ? Prefix : ""), +# define DM_LOG_PREFIX_OBJ_ARG(Obj) \ + (((Obj)->prefix && (Obj)->prefix[0] != '\0') ? "/" : ""), \ + (((Obj)->prefix && (Obj)->prefix[0] != '\0') ? (Obj)->prefix \ + : ""), +#else +# define DM_LOG_PREFIX +# define DM_LOG_PREFIX_ARG(Prefix) +# define DM_LOG_PREFIX_OBJ_ARG(Obj) +#endif + VISIBILITY_PRIVATE_HEADER_END #endif /* ANJAY_INCLUDE_ANJAY_MODULES_DM_H */ diff --git a/src/anjay_modules/anjay_io_utils.h b/src/anjay_modules/anjay_io_utils.h index f7b3f108..03ef17cd 100644 --- a/src/anjay_modules/anjay_io_utils.h +++ b/src/anjay_modules/anjay_io_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/anjay_modules/anjay_lwm2m_gateway.h b/src/anjay_modules/anjay_lwm2m_gateway.h new file mode 100644 index 00000000..23e324e4 --- /dev/null +++ b/src/anjay_modules/anjay_lwm2m_gateway.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ + +#ifndef ANJAY_INCLUDE_ANJAY_MODULES_LWM2M_GATEWAY_H +#define ANJAY_INCLUDE_ANJAY_MODULES_LWM2M_GATEWAY_H + +#include "anjay_init.h" + +#include +#include +#include + +VISIBILITY_PRIVATE_HEADER_BEGIN + +#ifdef ANJAY_WITH_LWM2M_GATEWAY + +/** + * Maps URI prefix to target End Device Data Model + * + * @param anjay Anjay object to operate on + * @param prefix DM prefix from the LwM2M request + * @param[out] dm End Device DM. If prefix is found in the Gateway scope, + * this pointer is set to a proper DM, set to NULL otherwise + * + * @returns 0 on success, or a negative value in case of error. + */ +int _anjay_lwm2m_gateway_prefix_to_dm(anjay_unlocked_t *anjay, + const char *prefix, + const anjay_dm_t **dm); + +# ifdef ANJAY_WITH_ATTR_STORAGE +/** + * Maps URI prefix to target End Device Attribute Storage + * + * @param anjay Anjay object to operate on + * @param prefix DM prefix from the LwM2M request + * @param[out] as End Device Attribute Storage. If prefix is found in the + * Gateway scope, this pointer is set to a proper AS, + * set to NULL otherwise + * + * @returns 0 on success, or a negative value in case of error. + */ +int _anjay_lwm2m_gateway_prefix_to_as(anjay_unlocked_t *anjay, + const char *prefix, + anjay_attr_storage_t **as); +# endif // ANJAY_WITH_ATTR_STORAGE + +/** + * Maps Instance ID to target End Device Data Model + * + * @param anjay Anjay object to operate on + * @param iid End Device Instance ID + * @param[out] dm End Device DM. If prefix is found in the Gateway scope, + * this pointer is set to a proper DM, set to NULL otherwise + */ +void _anjay_lwm2m_gateway_iid_to_dm(anjay_unlocked_t *anjay, + anjay_iid_t iid, + const anjay_dm_t **dm); + +#endif // ANJAY_WITH_LWM2M_GATEWAY + +VISIBILITY_PRIVATE_HEADER_END + +#endif // ANJAY_INCLUDE_ANJAY_MODULES_LWM2M_GATEWAY_H diff --git a/src/anjay_modules/anjay_notify.h b/src/anjay_modules/anjay_notify.h index 4afd0518..8a353cd6 100644 --- a/src/anjay_modules/anjay_notify.h +++ b/src/anjay_modules/anjay_notify.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -28,6 +28,9 @@ typedef struct { } anjay_notify_queue_resource_entry_t; typedef struct { +#ifdef ANJAY_WITH_LWM2M_GATEWAY + char prefix[ANJAY_GATEWAY_MAX_PREFIX_LEN]; +#endif // ANJAY_WITH_LWM2M_GATEWAY anjay_oid_t oid; anjay_notify_queue_instance_entry_t instance_set_changes; AVS_LIST(anjay_notify_queue_resource_entry_t) resources_changed; @@ -60,24 +63,20 @@ int _anjay_notify_flush(anjay_unlocked_t *anjay, anjay_notify_queue_t *queue_ptr); int _anjay_notify_queue_instance_created(anjay_notify_queue_t *out_queue, - anjay_oid_t oid, - anjay_iid_t iid); + const anjay_uri_path_t *path); int _anjay_notify_queue_instance_removed(anjay_notify_queue_t *out_queue, - anjay_oid_t oid, - anjay_iid_t iid); + const anjay_uri_path_t *path); int _anjay_notify_queue_instance_set_unknown_change( - anjay_notify_queue_t *out_queue, anjay_oid_t oid); + anjay_notify_queue_t *out_queue, const anjay_uri_path_t *path); /** * Adds a notification about the change of value of the data model resource - * specified by oid, iid and rid. + * specified by path. */ int _anjay_notify_queue_resource_change(anjay_notify_queue_t *out_queue, - anjay_oid_t oid, - anjay_iid_t iid, - anjay_rid_t rid); + const anjay_uri_path_t *path); void _anjay_notify_clear_queue(anjay_notify_queue_t *out_queue); @@ -90,6 +89,18 @@ int _anjay_notify_changed_unlocked(anjay_unlocked_t *anjay, anjay_iid_t iid, anjay_rid_t rid); +#ifdef ANJAY_WITH_LWM2M_GATEWAY +int _anjay_notify_changed_gw_unlocked(anjay_unlocked_t *anjay, + const char *prefix, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid); + +int _anjay_notify_instances_changed_gw_unlocked(anjay_unlocked_t *anjay, + const char *prefix, + anjay_oid_t oid); +#endif // ANJAY_WITH_LWM2M_GATEWAY + int _anjay_notify_instances_changed_unlocked(anjay_unlocked_t *anjay, anjay_oid_t oid); @@ -97,6 +108,16 @@ typedef int anjay_notify_callback_t(anjay_unlocked_t *anjay, anjay_notify_queue_t queue, void *data); +#ifdef ANJAY_WITH_OBSERVATION_STATUS +void _anjay_notify_observation_status_impl_unlocked( + anjay_unlocked_t *anjay, + anjay_resource_observation_status_t *status, + const char *prefix, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid); +#endif // ANJAY_WITH_OBSERVATION_STATUS + VISIBILITY_PRIVATE_HEADER_END #endif /* ANJAY_INCLUDE_ANJAY_NOTIFY_IO_H */ diff --git a/src/anjay_modules/anjay_raw_buffer.h b/src/anjay_modules/anjay_raw_buffer.h index 63e377f8..e43591bf 100644 --- a/src/anjay_modules/anjay_raw_buffer.h +++ b/src/anjay_modules/anjay_raw_buffer.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/anjay_modules/anjay_sched.h b/src/anjay_modules/anjay_sched.h index cf4eca4a..a3098061 100644 --- a/src/anjay_modules/anjay_sched.h +++ b/src/anjay_modules/anjay_sched.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/anjay_modules/anjay_servers.h b/src/anjay_modules/anjay_servers.h index a247e0d3..146e7c85 100644 --- a/src/anjay_modules/anjay_servers.h +++ b/src/anjay_modules/anjay_servers.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/anjay_modules/anjay_time_defs.h b/src/anjay_modules/anjay_time_defs.h index 75375526..f078b934 100644 --- a/src/anjay_modules/anjay_time_defs.h +++ b/src/anjay_modules/anjay_time_defs.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/anjay_modules/anjay_utils_core.h b/src/anjay_modules/anjay_utils_core.h index c9a1ff74..d42b3fbb 100644 --- a/src/anjay_modules/anjay_utils_core.h +++ b/src/anjay_modules/anjay_utils_core.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -57,6 +57,42 @@ VISIBILITY_PRIVATE_HEADER_BEGIN +// NOTE: A lot of code depends on numerical values of these constants. +// Please be careful when refactoring. +typedef enum { + ANJAY_ID_OID, + ANJAY_ID_IID, + ANJAY_ID_RID, + ANJAY_ID_RIID, + _ANJAY_URI_PATH_MAX_LENGTH +} anjay_id_type_t; + +/** + * A data type that represents a data model path. + * + * It may represent a root path, an Object path, an Object Instance path, a + * Resource path, or a Resource Instance path. + * + * The path is terminated either by an @ref ANJAY_ID_INVALID value, or + * end-of-array (in case of Resource Instance paths). In case of root, Object + * and Object Instance paths, the array elements past the terminating invalid ID + * value are undefined and shall not be used. They are NOT required to be set to + * @ref ANJAY_ID_INVALID. Paths object that numerically differ only in values + * past the terminating invalid ID shall be treated as equal (and this is how + * @ref _anjay_uri_path_equal is implemented). + * + * The ids array is designed to be safely and meaningfully indexed by + * @ref anjay_id_type_t values. + */ +typedef struct { + uint16_t ids[_ANJAY_URI_PATH_MAX_LENGTH]; + +#ifdef ANJAY_WITH_LWM2M_GATEWAY + // NULL-terminated string + char prefix[ANJAY_GATEWAY_MAX_PREFIX_LEN]; +#endif // ANJAY_WITH_LWM2M_GATEWAY +} anjay_uri_path_t; + #ifdef ANJAY_WITH_EVENT_LOOP typedef enum { ANJAY_EVENT_LOOP_IDLE, diff --git a/src/anjay_modules/dm/anjay_execute.h b/src/anjay_modules/dm/anjay_execute.h index 6bcf6660..dd5c8240 100644 --- a/src/anjay_modules/dm/anjay_execute.h +++ b/src/anjay_modules/dm/anjay_execute.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/anjay_modules/dm/anjay_modules.h b/src/anjay_modules/dm/anjay_modules.h index 28a87fb1..dcc32047 100644 --- a/src/anjay_modules/dm/anjay_modules.h +++ b/src/anjay_modules/dm/anjay_modules.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -43,6 +43,19 @@ typedef struct { const anjay_dm_object_def_t *const *user_provided; const anjay_unlocked_dm_object_def_t *const *unlocked; } impl; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + /* + * Prefix that helps to identify which DM is the object installed in. + * It is set to NULL by default in _anjay_register_object_unlocked() + * and set to a specific prefix only in lwm2m_gateway implementation, + * anjay_lwm2m_gateway_register_object() function. The link is necessary + * for uri_path_outside_base() checkers. Link to parent DM might make more + * sense, but ultimately we just need to compare paths that include prefix. + * + * Also it's not currently possible to include anjay_dm_t * reference here. + */ + const char *prefix; +# endif // ANJAY_WITH_LWM2M_GATEWAY } anjay_dm_installed_object_t; static inline void _anjay_dm_installed_object_init_unlocked( diff --git a/src/core/anjay_access_utils.c b/src/core/anjay_access_utils.c index 1e37085c..6fbd3891 100644 --- a/src/core/anjay_access_utils.c +++ b/src/core/anjay_access_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -12,6 +12,7 @@ #include #include +#include #include #include "anjay_access_utils_private.h" @@ -336,12 +337,18 @@ _anjay_instance_action_allowed_stateless(anjay_unlocked_t *anjay, if (info->oid == ANJAY_DM_OID_SECURITY) { return ANJAY_INSTANCE_ACTION_DISALLOWED; } - assert(info->iid != ANJAY_ID_INVALID || info->action == ANJAY_ACTION_CREATE); #ifndef ANJAY_WITH_ACCESS_CONTROL return ANJAY_INSTANCE_ACTION_ALLOWED; #else + +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (info->end_device) { + return ANJAY_INSTANCE_ACTION_ALLOWED; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY + if (info->ssid == ANJAY_SSID_BOOTSTRAP) { // Access Control is not applicable to Bootstrap Server return ANJAY_INSTANCE_ACTION_ALLOWED; @@ -366,7 +373,7 @@ _anjay_instance_action_allowed_stateless(anjay_unlocked_t *anjay, } return ANJAY_INSTANCE_ACTION_NEEDS_ACL_CHECK; -#endif // ANJAY_WITH_ACCESS_CONTROL +#endif // ANJAY_WITH_ACCESS_CONTROL } #ifdef ANJAY_WITH_ACCESS_CONTROL @@ -649,8 +656,9 @@ process_orphaned_instances_clb(anjay_unlocked_t *anjay, ANJAY_ID_INVALID, elect_instance_owner(acl))) || (result = _anjay_notify_queue_resource_change( args->out_dm_changes, - ANJAY_DM_OID_ACCESS_CONTROL, iid, - ANJAY_DM_RID_ACCESS_CONTROL_OWNER))); + &MAKE_RESOURCE_PATH( + ANJAY_DM_OID_ACCESS_CONTROL, iid, + ANJAY_DM_RID_ACCESS_CONTROL_OWNER)))); } // Rewrite the modified ACL to the data model if (!result) { @@ -666,8 +674,9 @@ process_orphaned_instances_clb(anjay_unlocked_t *anjay, } if (!result) { result = _anjay_notify_queue_resource_change( - args->out_dm_changes, ANJAY_DM_OID_ACCESS_CONTROL, iid, - ANJAY_DM_RID_ACCESS_CONTROL_ACL); + args->out_dm_changes, + &MAKE_RESOURCE_PATH(ANJAY_DM_OID_ACCESS_CONTROL, iid, + ANJAY_DM_RID_ACCESS_CONTROL_ACL)); } } finish: @@ -692,7 +701,8 @@ static int remove_referred_instance(anjay_unlocked_t *anjay, && !(result = _anjay_dm_call_instance_remove( anjay, obj, (anjay_iid_t) it->target_iid))) { result = _anjay_notify_queue_instance_removed( - out_dm_changes, it->target_oid, it->target_iid); + out_dm_changes, + &MAKE_INSTANCE_PATH(it->target_oid, it->target_iid)); } if (result) { anjay_log(ERROR, @@ -747,8 +757,8 @@ remove_orphaned_instances(anjay_unlocked_t *anjay, anjay, ac_obj, instances_to_remove->ac_iid)) || (result = _anjay_notify_queue_instance_removed( new_notifications_queue, - ANJAY_DM_OID_ACCESS_CONTROL, - instances_to_remove->ac_iid))); + &MAKE_INSTANCE_PATH(ANJAY_DM_OID_ACCESS_CONTROL, + instances_to_remove->ac_iid)))); } AVS_LIST_CLEAR(&ssid_list); return result; @@ -887,8 +897,8 @@ static int perform_removes(anjay_unlocked_t *anjay, anjay, ac_obj, *args.iids_to_remove)) || (result = _anjay_notify_queue_instance_removed( new_notifications_queue, - ANJAY_DM_OID_ACCESS_CONTROL, - *args.iids_to_remove))); + &MAKE_INSTANCE_PATH(ANJAY_DM_OID_ACCESS_CONTROL, + *args.iids_to_remove)))); } return result; } @@ -1015,7 +1025,8 @@ static int perform_adds(anjay_unlocked_t *anjay, ANJAY_ID_INVALID, origin_ssid)) || (result = _anjay_notify_queue_instance_created( notifications_queue, - ANJAY_DM_OID_ACCESS_CONTROL, ac_iid))) { + &MAKE_INSTANCE_PATH(ANJAY_DM_OID_ACCESS_CONTROL, + ac_iid)))) { return result; } } @@ -1062,7 +1073,8 @@ static int generate_apparent_instance_set_change_notifications( if ((result = read_ids_from_ac_instance(anjay, it->iid, &target_oid, NULL, NULL)) || (result = _anjay_notify_queue_instance_set_unknown_change( - notifications_queue, target_oid))) { + notifications_queue, + &MAKE_OBJECT_PATH(target_oid)))) { return result; } } @@ -1078,7 +1090,12 @@ int _anjay_sync_access_control(anjay_unlocked_t *anjay, (void) anjay; (void) notifications_queue; return 0; -#else // ANJAY_WITH_ACCESS_CONTROL +#else // ANJAY_WITH_ACCESS_CONTROL +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if ((*notifications_queue)->prefix[0] != '\0') { + return 0; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY const anjay_dm_installed_object_t *ac_obj = get_access_control(anjay); if (!ac_obj) { return 0; @@ -1107,5 +1124,5 @@ int _anjay_sync_access_control(anjay_unlocked_t *anjay, anjay, notifications_queue); } return _anjay_dm_transaction_finish(anjay, result); -#endif // ANJAY_WITH_ACCESS_CONTROL +#endif // ANJAY_WITH_ACCESS_CONTROL } diff --git a/src/core/anjay_access_utils_private.h b/src/core/anjay_access_utils_private.h index 738a2e53..1c7fada3 100644 --- a/src/core/anjay_access_utils_private.h +++ b/src/core/anjay_access_utils_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -20,6 +20,9 @@ typedef struct { anjay_iid_t iid; anjay_ssid_t ssid; anjay_request_action_t action; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + bool end_device; +#endif // ANJAY_WITH_LWM2M_GATEWAY } anjay_action_info_t; typedef enum { diff --git a/src/core/anjay_bootstrap_core.c b/src/core/anjay_bootstrap_core.c index fed02166..cd79894c 100644 --- a/src/core/anjay_bootstrap_core.c +++ b/src/core/anjay_bootstrap_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -224,6 +224,7 @@ static int with_instance_on_demand(anjay_unlocked_t *anjay, with_instance_on_demand_cb_t callback) { int result = 0; int ipresent = _anjay_dm_instance_present(anjay, obj, iid); + anjay_oid_t oid = _anjay_dm_installed_object_oid(obj); if (ipresent < 0) { return ipresent; } else if (ipresent == 0 @@ -231,7 +232,7 @@ static int with_instance_on_demand(anjay_unlocked_t *anjay, anjay_log(DEBUG, _("Instance Create handler for object ") "%" PRIu16 _( " failed"), - _anjay_dm_installed_object_oid(obj)); + oid); return result; } @@ -241,7 +242,7 @@ static int with_instance_on_demand(anjay_unlocked_t *anjay, if (ipresent == 0 && !result) { result = _anjay_notify_queue_instance_created( &anjay->bootstrap.notification_queue, - _anjay_dm_installed_object_oid(obj), iid); + &MAKE_INSTANCE_PATH(oid, iid)); } return result; } @@ -447,10 +448,7 @@ int _anjay_bootstrap_write_composite(anjay_unlocked_t *anjay, } if ((retval = _anjay_notify_queue_resource_change( - &anjay->bootstrap.notification_queue, - path.ids[ANJAY_ID_OID], - path.ids[ANJAY_ID_IID], - path.ids[ANJAY_ID_RID]))) { + &anjay->bootstrap.notification_queue, &path))) { return retval; } @@ -474,17 +472,17 @@ int _anjay_bootstrap_write_composite(anjay_unlocked_t *anjay, static int delete_instance(anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj, anjay_iid_t iid) { + anjay_oid_t oid = _anjay_dm_installed_object_oid(obj); int retval = _anjay_dm_call_instance_remove(anjay, obj, iid); if (retval) { anjay_log(WARNING, _("delete_instance: cannot delete ") "/%d/%d" _(": ") "%d", - _anjay_dm_installed_object_oid(obj), iid, retval); + oid, iid, retval); } else { - bootstrap_remove_notify_changed( - &anjay->bootstrap, _anjay_dm_installed_object_oid(obj), iid); + bootstrap_remove_notify_changed(&anjay->bootstrap, oid, iid); retval = _anjay_notify_queue_instance_removed( &anjay->bootstrap.notification_queue, - _anjay_dm_installed_object_oid(obj), iid); + &MAKE_INSTANCE_PATH(oid, iid)); } return retval; } @@ -638,8 +636,9 @@ static void purge_bootstrap(avs_sched_t *sched, const void *dummy) { (void) (retval || (retval = _anjay_dm_call_instance_remove(anjay, obj, iid)) || (retval = _anjay_notify_queue_instance_removed( - ¬ification, _anjay_dm_installed_object_oid(obj), - iid)) + ¬ification, + &MAKE_INSTANCE_PATH( + _anjay_dm_installed_object_oid(obj), iid))) || (retval = _anjay_notify_flush(anjay, ANJAY_SSID_BOOTSTRAP, ¬ification))); retval = _anjay_dm_transaction_finish(anjay, retval); @@ -1043,6 +1042,14 @@ int _anjay_bootstrap_perform_action(anjay_connection_ref_t bootstrap_connection, .format = AVS_COAP_FORMAT_NONE }; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(&request->uri)) { + anjay_log(DEBUG, _("Bootstrap Interface can't operate on LwM2M Gateway " + "End Devices")); + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY + if (!_anjay_coap_setup_response_stream(request->ctx, &msg_details)) { return -1; } diff --git a/src/core/anjay_bootstrap_core.h b/src/core/anjay_bootstrap_core.h index e6f020f3..e8d61f22 100644 --- a/src/core/anjay_bootstrap_core.h +++ b/src/core/anjay_bootstrap_core.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_core.c b/src/core/anjay_core.c index e63d072a..1ba91b75 100644 --- a/src/core/anjay_core.c +++ b/src/core/anjay_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -41,13 +41,16 @@ #include "anjay_io_core.h" #include "anjay_servers_utils.h" #include "anjay_utils_private.h" +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +#endif // ANJAY_WITH_LWM2M_GATEWAY #include "dm/anjay_dm_write_attrs.h" VISIBILITY_SOURCE_BEGIN #ifndef ANJAY_VERSION -# define ANJAY_VERSION "3.8.1" +# define ANJAY_VERSION "3.9.0" #endif // ANJAY_VERSION #ifdef ANJAY_WITH_LWM2M11 @@ -247,6 +250,11 @@ static int init_anjay(anjay_unlocked_t *anjay, anjay->use_connection_id = config->use_connection_id; anjay->additional_tls_config_clb = config->additional_tls_config_clb; +#ifdef ANJAY_WITH_COAP_DOWNLOAD + anjay->coap_downloader_retry_count = config->coap_downloader_retry_count; + anjay->coap_downloader_retry_delay = config->coap_downloader_retry_delay; +#endif // ANJAY_WITH_COAP_DOWNLOAD + if (config->prng_ctx) { anjay->prng_ctx.allocated_by_user = true; anjay->prng_ctx.ctx = config->prng_ctx; @@ -259,7 +267,7 @@ static int init_anjay(anjay_unlocked_t *anjay, } #ifdef ANJAY_WITH_ATTR_STORAGE - if (_anjay_attr_storage_init(anjay)) { + if (_anjay_attr_storage_init(&anjay->attr_storage, &anjay->dm)) { return -1; } #endif // ANJAY_WITH_ATTR_STORAGE @@ -770,6 +778,9 @@ static int parse_dm_uri(const avs_coap_request_header_t *hdr, size_t segment_index = 0; bool expect_no_more_options = false; int result = 0; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + bool prefix_found = false; +#endif // ANJAY_WITH_LWM2M_GATEWAY while (!(result = avs_coap_options_get_string_it( &hdr->options, AVS_COAP_OPTION_URI_PATH, &it, &uri_size, @@ -781,6 +792,28 @@ static int parse_dm_uri(const avs_coap_request_header_t *hdr, } else if (expect_no_more_options || uri[0] == '\0') { anjay_log(WARNING, _("superfluous empty Uri-Path segment")); return -1; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + } else if (segment_index + >= _ANJAY_URI_PATH_MAX_LENGTH + (prefix_found ? 1 : 0)) { + // too many segments + anjay_log(WARNING, _("too many Uri-Path options")); + return -1; + } else if (segment_index == 0 && isalpha(uri[0])) { + // first segment starts with a letter + if (uri_size > ANJAY_GATEWAY_MAX_PREFIX_LEN) { + anjay_log(WARNING, _("prefix too long")); + return -1; + } + strcpy(out_uri->prefix, uri); + prefix_found = true; + } else { + size_t path_depth = + prefix_found ? segment_index - 1 : segment_index; + if (parse_request_uri_segment(uri, &out_uri->ids[path_depth])) { + return -1; + } + } +#else // ANJAY_WITH_LWM2M_GATEWAY } else if (segment_index >= _ANJAY_URI_PATH_MAX_LENGTH) { // 5 or more segments... anjay_log(WARNING, _("prefixed Uri-Path are not supported")); @@ -789,6 +822,7 @@ static int parse_dm_uri(const avs_coap_request_header_t *hdr, &out_uri->ids[segment_index])) { return -1; } +#endif // ANJAY_WITH_LWM2M_GATEWAY ++segment_index; } diff --git a/src/core/anjay_core.h b/src/core/anjay_core.h index 017d1e12..2a8194d5 100644 --- a/src/core/anjay_core.h +++ b/src/core/anjay_core.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -165,6 +165,10 @@ struct anjay_atomic_fields_t atomic_fields; #endif // !defined(ANJAY_WITH_THREAD_SAFETY) && // defined(ANJAY_ATOMIC_FIELDS_DEFINED) +#ifdef ANJAY_WITH_COAP_DOWNLOAD + size_t coap_downloader_retry_count; + avs_time_duration_t coap_downloader_retry_delay; +#endif // ANJAY_WITH_COAP_DOWNLOAD }; #define ANJAY_DM_DEFAULT_PMIN_VALUE 0 diff --git a/src/core/anjay_dm_core.c b/src/core/anjay_dm_core.c index c4fd2d08..5573a0a4 100644 --- a/src/core/anjay_dm_core.c +++ b/src/core/anjay_dm_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -22,6 +22,9 @@ #include #include +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +#endif // ANJAY_WITH_LWM2M_GATEWAY #include @@ -148,6 +151,10 @@ int _anjay_register_object_unlocked( return -1; } +#ifdef ANJAY_WITH_LWM2M_GATEWAY + (*elem_ptr_move)->prefix = NULL; +#endif // ANJAY_WITH_LWM2M_GATEWAY + dm_log(INFO, _("successfully registered object ") "/%u", _anjay_dm_installed_object_oid(*elem_ptr_move)); if (_anjay_notify_instances_changed_unlocked( @@ -248,19 +255,23 @@ void _anjay_unregister_object_handle_transaction_state( void _anjay_unregister_object_handle_notify_queue( anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *def_ptr) { anjay_notify_queue_t notify = NULL; - if (_anjay_notify_queue_instance_set_unknown_change( - ¬ify, _anjay_dm_installed_object_oid(def_ptr)) + anjay_oid_t oid = _anjay_dm_installed_object_oid(def_ptr); + anjay_uri_path_t path = MAKE_OBJECT_PATH(oid); +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (def_ptr->prefix != NULL) { + strcpy(path.prefix, def_ptr->prefix); + } +#endif // ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_notify_queue_instance_set_unknown_change(¬ify, &path) || _anjay_notify_flush(anjay, ANJAY_SSID_BOOTSTRAP, ¬ify)) { dm_log(WARNING, _("could not perform notifications about removed object ") "%" PRIu16, - _anjay_dm_installed_object_oid(def_ptr)); + oid); } - remove_oid_from_notify_queue(&anjay->scheduled_notify.queue, - _anjay_dm_installed_object_oid(def_ptr)); + remove_oid_from_notify_queue(&anjay->scheduled_notify.queue, oid); #ifdef ANJAY_WITH_BOOTSTRAP - remove_oid_from_notify_queue(&anjay->bootstrap.notification_queue, - _anjay_dm_installed_object_oid(def_ptr)); + remove_oid_from_notify_queue(&anjay->bootstrap.notification_queue, oid); #endif // ANJAY_WITH_BOOTSTRAP } @@ -410,13 +421,23 @@ void _anjay_uri_path_update_common_prefix(const anjay_uri_path_t **prefix_ptr, assert(*prefix_ptr == prefix_buf); size_t index = 0; anjay_uri_path_t new_prefix = MAKE_ROOT_PATH(); +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (strcmp(prefix_buf->prefix, path->prefix)) { + *prefix_buf = new_prefix; + return; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY while (index < AVS_ARRAY_SIZE(prefix_buf->ids) && prefix_buf->ids[index] != ANJAY_ID_INVALID && prefix_buf->ids[index] == path->ids[index]) { new_prefix.ids[index] = prefix_buf->ids[index]; index++; } +# ifdef ANJAY_WITH_LWM2M_GATEWAY + memcpy(prefix_buf->ids, new_prefix.ids, sizeof(new_prefix.ids)); +# else *prefix_buf = new_prefix; +# endif // ANJAY_WITH_LWM2M_GATEWAY } } #endif // ANJAY_WITH_LWM2M11 @@ -429,13 +450,22 @@ const char *_anjay_debug_make_path__(char *buffer, char *ptr = buffer; char *buffer_end = buffer + buffer_size; size_t length = _anjay_uri_path_length(uri); - if (!length) { - result = avs_simple_snprintf(buffer, buffer_size, "/"); - } else { - for (size_t i = 0; result >= 0 && i < length; ++i) { - result = avs_simple_snprintf(ptr, (size_t) (buffer_end - ptr), - "/%u", (unsigned) uri->ids[i]); - ptr += result; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(uri)) { + result = avs_simple_snprintf(buffer, buffer_size, "/%s", uri->prefix); + ptr += result; + } + if (result >= 0) +#endif // ANJAY_WITH_LWM2M_GATEWAY + { + if (!length) { + result = avs_simple_snprintf(ptr, (size_t) (buffer_end - ptr), "/"); + } else { + for (size_t i = 0; result >= 0 && i < length; ++i) { + result = avs_simple_snprintf(ptr, (size_t) (buffer_end - ptr), + "/%u", (unsigned) uri->ids[i]); + ptr += result; + } } } if (result < 0) { @@ -645,9 +675,8 @@ static int dm_delete_object_instance(anjay_unlocked_t *anjay, anjay_notify_queue_t notify_queue = NULL; (void) ((retval = _anjay_dm_call_instance_remove( anjay, obj, request->uri.ids[ANJAY_ID_IID])) - || (retval = _anjay_notify_queue_instance_removed( - ¬ify_queue, request->uri.ids[ANJAY_ID_OID], - request->uri.ids[ANJAY_ID_IID])) + || (retval = _anjay_notify_queue_instance_removed(¬ify_queue, + &request->uri)) || (retval = _anjay_notify_flush(anjay, ssid, ¬ify_queue))); return retval; } @@ -751,12 +780,25 @@ int _anjay_dm_perform_action(anjay_connection_ref_t connection, if (_anjay_uri_path_has(&request->uri, ANJAY_ID_OID)) { const anjay_dm_t *dm; - { dm = &_anjay_from_server(connection.server)->dm; } +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (strlen(request->uri.prefix) != 0) { + if (_anjay_lwm2m_gateway_prefix_to_dm(_anjay_from_server( + connection.server), + request->uri.prefix, &dm)) { + dm_log(ERROR, _("No End Device with specified prefix found")); + return ANJAY_ERR_NOT_FOUND; + } + } else +#endif // ANJAY_WITH_LWM2M_GATEWAY + { + dm = &_anjay_from_server(connection.server)->dm; + } if (!(obj = _anjay_dm_find_object_by_oid( dm, request->uri.ids[ANJAY_ID_OID]))) { - dm_log(DEBUG, _("Object not found: ") "%u", - request->uri.ids[ANJAY_ID_OID]); + dm_log(DEBUG, _("Object not found: ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_ARG(request->uri.prefix) + request->uri.ids[ANJAY_ID_OID]); return ANJAY_ERR_NOT_FOUND; } } else @@ -819,14 +861,17 @@ int _anjay_dm_foreach_object(anjay_unlocked_t *anjay, AVS_LIST_FOREACH(obj, dm->objects) { int result = handler(anjay, obj, data); if (result == ANJAY_FOREACH_BREAK) { - dm_log(TRACE, _("foreach_object: break on ") "/%u", - _anjay_dm_installed_object_oid(obj)); + dm_log(TRACE, _("foreach_object: break on ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj) + _anjay_dm_installed_object_oid(obj)); return 0; } else if (result) { dm_log(DEBUG, - _("foreach_object_handler failed for ") "/%u" _(" (") "%d" _( - ")"), - _anjay_dm_installed_object_oid(obj), result); + _("foreach_object_handler failed for ") DM_LOG_PREFIX + "/%u" _(" (") "%d" _(")"), + DM_LOG_PREFIX_OBJ_ARG(obj) + _anjay_dm_installed_object_oid(obj), + result); return result; } } @@ -867,13 +912,18 @@ static void foreach_instance_emit(anjay_unlocked_dm_list_ctx_t *ctx_, ctx->result = ctx->handler(ctx->anjay, ctx->obj, iid, ctx->handler_data); if (ctx->result == ANJAY_FOREACH_BREAK) { - dm_log(TRACE, _("foreach_instance: break on ") "/%u/%u", - _anjay_dm_installed_object_oid(ctx->obj), iid); + dm_log(TRACE, + _("foreach_instance: break on ") DM_LOG_PREFIX "/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(ctx->obj) + _anjay_dm_installed_object_oid(ctx->obj), + iid); } else if (ctx->result) { dm_log(DEBUG, - _("foreach_instance_handler failed for ") "/%u/%u" _( - " (") "%d" _(")"), - _anjay_dm_installed_object_oid(ctx->obj), iid, ctx->result); + _("foreach_instance_handler failed for ") DM_LOG_PREFIX + "/%u/%u" _(" (") "%d" _(")"), + DM_LOG_PREFIX_OBJ_ARG(ctx->obj) + _anjay_dm_installed_object_oid(ctx->obj), + iid, ctx->result); } } } @@ -903,9 +953,10 @@ int _anjay_dm_foreach_instance(anjay_unlocked_t *anjay, anjay, obj, (anjay_unlocked_dm_list_ctx_t *) &ctx); if (result < 0) { dm_log(WARNING, - _("list_instances handler for ") "/%u" _(" failed (") "%d" _( - ")"), - _anjay_dm_installed_object_oid(obj), result); + _("list_instances handler for ") DM_LOG_PREFIX + "/%u" _(" failed (") "%d" _(")"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + result); return result; } return ctx.result == ANJAY_FOREACH_BREAK ? 0 : ctx.result; @@ -1028,14 +1079,18 @@ void _anjay_dm_emit_res_unlocked(anjay_unlocked_dm_resource_list_ctx_t *ctx, ctx->result = ctx->handler(ctx->anjay, ctx->obj, ctx->iid, rid, kind, presence, ctx->handler_data); if (ctx->result == ANJAY_FOREACH_BREAK) { - dm_log(TRACE, _("foreach_resource: break on ") "/%u/%u/%u", - _anjay_dm_installed_object_oid(ctx->obj), ctx->iid, rid); + dm_log(TRACE, + _("foreach_resource: break on ") DM_LOG_PREFIX "/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(ctx->obj) + _anjay_dm_installed_object_oid(ctx->obj), + ctx->iid, rid); } else if (ctx->result) { dm_log(DEBUG, - _("foreach_resource_handler failed for ") "/%u/%u/%u" _( - " (") "%d" _(")"), - _anjay_dm_installed_object_oid(ctx->obj), ctx->iid, rid, - ctx->result); + _("foreach_resource_handler failed for ") DM_LOG_PREFIX + "/%u/%u/%u" _(" (") "%d" _(")"), + DM_LOG_PREFIX_OBJ_ARG(ctx->obj) + _anjay_dm_installed_object_oid(ctx->obj), + ctx->iid, rid, ctx->result); } } } @@ -1079,9 +1134,10 @@ int _anjay_dm_foreach_resource(anjay_unlocked_t *anjay, int result = _anjay_dm_call_list_resources(anjay, obj, iid, &ctx); if (result < 0) { dm_log(ERROR, - _("list_resources handler for ") "/%u/%u" _(" failed (") "%d" _( - ")"), - _anjay_dm_installed_object_oid(obj), iid, result); + _("list_resources handler for ") DM_LOG_PREFIX + "/%u/%u" _(" failed (") "%d" _(")"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid, result); return result; } return ctx.result == ANJAY_FOREACH_BREAK ? 0 : ctx.result; @@ -1238,15 +1294,18 @@ static void foreach_resource_instance_emit(anjay_unlocked_dm_list_ctx_t *ctx_, riid, ctx->handler_data); if (ctx->result == ANJAY_FOREACH_BREAK) { dm_log(TRACE, - _("foreach_resource_instance: break on ") "/%u/%u/%u/%u", - _anjay_dm_installed_object_oid(ctx->obj), ctx->iid, ctx->rid, - riid); + _("foreach_resource_instance: break on ") DM_LOG_PREFIX + "/%u/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(ctx->obj) + _anjay_dm_installed_object_oid(ctx->obj), + ctx->iid, ctx->rid, riid); } else if (ctx->result) { dm_log(DEBUG, - _("foreach_resource_handler failed for ") "/%u/%u/%u/%u" _( - " (") "%d" _(")"), - _anjay_dm_installed_object_oid(ctx->obj), ctx->iid, ctx->rid, - riid, ctx->result); + _("foreach_resource_handler failed for ") DM_LOG_PREFIX + "/%u/%u/%u/%u" _(" (") "%d" _(")"), + DM_LOG_PREFIX_OBJ_ARG(ctx->obj) + _anjay_dm_installed_object_oid(ctx->obj), + ctx->iid, ctx->rid, riid, ctx->result); } } } @@ -1281,9 +1340,10 @@ int _anjay_dm_foreach_resource_instance( anjay, obj, iid, rid, (anjay_unlocked_dm_list_ctx_t *) &ctx); if (result < 0) { dm_log(ERROR, - _("list_resource_instances handler for ") "/%u/%u/%u" _( - " failed (") "%d" _(")"), - _anjay_dm_installed_object_oid(obj), iid, rid, result); + _("list_resource_instances handler for ") DM_LOG_PREFIX + "/%u/%u/%u" _(" failed (") "%d" _(")"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid, rid, result); return result; } return ctx.result == ANJAY_FOREACH_BREAK ? 0 : ctx.result; diff --git a/src/core/anjay_dm_core.h b/src/core/anjay_dm_core.h index 667765c6..31bcd703 100644 --- a/src/core/anjay_dm_core.h +++ b/src/core/anjay_dm_core.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -69,13 +69,24 @@ typedef struct { anjay_request_attributes_t attributes; } anjay_request_t; -#define REQUEST_TO_ACTION_INFO(Request, Ssid) \ - (const anjay_action_info_t) { \ - .oid = (Request)->uri.ids[ANJAY_ID_OID], \ - .iid = (Request)->uri.ids[ANJAY_ID_IID], \ - .ssid = (Ssid), \ - .action = (Request)->action \ - } +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# define REQUEST_TO_ACTION_INFO(Request, Ssid) \ + (const anjay_action_info_t) { \ + .end_device = _anjay_uri_path_has_prefix(&(Request)->uri), \ + .oid = (Request)->uri.ids[ANJAY_ID_OID], \ + .iid = (Request)->uri.ids[ANJAY_ID_IID], \ + .ssid = (Ssid), \ + .action = (Request)->action \ + } +#else // ANJAY_WITH_LWM2M_GATEWAY +# define REQUEST_TO_ACTION_INFO(Request, Ssid) \ + (const anjay_action_info_t) { \ + .oid = (Request)->uri.ids[ANJAY_ID_OID], \ + .iid = (Request)->uri.ids[ANJAY_ID_IID], \ + .ssid = (Ssid), \ + .action = (Request)->action \ + } +#endif // ANJAY_WITH_LWM2M_GATEWAY int _anjay_dm_transaction_validate(anjay_unlocked_t *anjay); int _anjay_dm_transaction_finish_without_validation(anjay_unlocked_t *anjay, diff --git a/src/core/anjay_downloader.h b/src/core/anjay_downloader.h index 063cbbc9..05ab41b8 100644 --- a/src/core/anjay_downloader.h +++ b/src/core/anjay_downloader.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_event_loop.c b/src/core/anjay_event_loop.c index 4223e631..9e6a2901 100644 --- a/src/core/anjay_event_loop.c +++ b/src/core/anjay_event_loop.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_io_core.c b/src/core/anjay_io_core.c index 9a053dbc..372a1527 100644 --- a/src/core/anjay_io_core.c +++ b/src/core/anjay_io_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_io_core.h b/src/core/anjay_io_core.h index a82e738e..0e83e310 100644 --- a/src/core/anjay_io_core.h +++ b/src/core/anjay_io_core.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_io_utils.c b/src/core/anjay_io_utils.c index 211f56f8..fc1e5e7b 100644 --- a/src/core/anjay_io_utils.c +++ b/src/core/anjay_io_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_lwm2m_send.c b/src/core/anjay_lwm2m_send.c index 1fccefce..2a18232c 100644 --- a/src/core/anjay_lwm2m_send.c +++ b/src/core/anjay_lwm2m_send.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -21,6 +21,12 @@ # include +# ifdef ANJAY_WITH_LWM2M_GATEWAY +# include + +# include "../anjay_modules/anjay_lwm2m_gateway.h" +# endif // ANJAY_WITH_LWM2M_GATEWAY + # include "anjay_access_utils_private.h" # include "anjay_core.h" # include "anjay_io_core.h" @@ -605,13 +611,130 @@ int anjay_send_batch_add_objlnk(anjay_send_batch_builder_t *builder, timestamp, objlnk_oid, objlnk_iid); } +# ifdef ANJAY_WITH_LWM2M_GATEWAY +int anjay_lwm2m_gateway_send_batch_add_int(anjay_send_batch_builder_t *builder, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + avs_time_real_t timestamp, + int64_t value) { + anjay_uri_path_t path; + _anjay_uri_path_with_prefix_from_end_device_iid(&path, gateway_iid, oid, + iid, rid, riid); + return _anjay_batch_add_int(cast_to_builder(builder), &path, timestamp, + value); +} + +int anjay_lwm2m_gateway_send_batch_add_uint(anjay_send_batch_builder_t *builder, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + avs_time_real_t timestamp, + uint64_t value) { + anjay_uri_path_t path; + _anjay_uri_path_with_prefix_from_end_device_iid(&path, gateway_iid, oid, + iid, rid, riid); + return _anjay_batch_add_uint(cast_to_builder(builder), &path, timestamp, + value); +} + +int anjay_lwm2m_gateway_send_batch_add_double( + anjay_send_batch_builder_t *builder, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + avs_time_real_t timestamp, + double value) { + anjay_uri_path_t path; + _anjay_uri_path_with_prefix_from_end_device_iid(&path, gateway_iid, oid, + iid, rid, riid); + return _anjay_batch_add_double(cast_to_builder(builder), &path, timestamp, + value); +} + +int anjay_lwm2m_gateway_send_batch_add_bool(anjay_send_batch_builder_t *builder, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + avs_time_real_t timestamp, + bool value) { + anjay_uri_path_t path; + _anjay_uri_path_with_prefix_from_end_device_iid(&path, gateway_iid, oid, + iid, rid, riid); + return _anjay_batch_add_bool(cast_to_builder(builder), &path, timestamp, + value); +} + +int anjay_lwm2m_gateway_send_batch_add_string( + anjay_send_batch_builder_t *builder, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + avs_time_real_t timestamp, + const char *str) { + anjay_uri_path_t path; + _anjay_uri_path_with_prefix_from_end_device_iid(&path, gateway_iid, oid, + iid, rid, riid); + return _anjay_batch_add_string(cast_to_builder(builder), &path, timestamp, + str); +} + +int anjay_lwm2m_gateway_send_batch_add_bytes( + anjay_send_batch_builder_t *builder, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + avs_time_real_t timestamp, + const void *data, + size_t length) { + anjay_uri_path_t path; + _anjay_uri_path_with_prefix_from_end_device_iid(&path, gateway_iid, oid, + iid, rid, riid); + return _anjay_batch_add_bytes(cast_to_builder(builder), &path, timestamp, + data, length); +} + +int anjay_lwm2m_gateway_send_batch_add_objlnk( + anjay_send_batch_builder_t *builder, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + avs_time_real_t timestamp, + anjay_oid_t objlnk_oid, + anjay_iid_t objlnk_iid) { + anjay_uri_path_t path; + _anjay_uri_path_with_prefix_from_end_device_iid(&path, gateway_iid, oid, + iid, rid, riid); + return _anjay_batch_add_objlnk(cast_to_builder(builder), &path, timestamp, + objlnk_oid, objlnk_iid); +} + +# endif // ANJAY_WITH_LWM2M_GATEWAY + static int batch_data_add_current_impl(anjay_send_batch_builder_t *builder, anjay_unlocked_t *anjay, + const anjay_dm_t *dm, + anjay_iid_t gateway_iid, anjay_oid_t oid, anjay_iid_t iid, anjay_rid_t rid, const avs_time_real_t *forced_timestamp) { + (void) gateway_iid; assert(builder); assert(anjay); @@ -620,15 +743,28 @@ batch_data_add_current_impl(anjay_send_batch_builder_t *builder, } const anjay_dm_installed_object_t *obj = - _anjay_dm_find_object_by_oid(&anjay->dm, oid); + _anjay_dm_find_object_by_oid(dm, oid); if (!obj) { +# ifdef ANJAY_WITH_LWM2M_GATEWAY + send_log(ERROR, _("unregistered Object ID: ") "%s/%u", + obj->prefix ? obj->prefix : "", oid); +# else // ANJAY_WITH_LWM2M_GATEWAY send_log(ERROR, _("unregistered Object ID: ") "%u", oid); +# endif // ANJAY_WITH_LWM2M_GATEWAY return ANJAY_ERR_NOT_FOUND; } anjay_dm_path_info_t path_info; - int result = - _anjay_dm_path_info(anjay, obj, &MAKE_RESOURCE_PATH(oid, iid, rid), - &path_info); + anjay_uri_path_t path; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (gateway_iid != ANJAY_ID_INVALID) { + _anjay_uri_path_with_prefix_from_end_device_iid( + &path, gateway_iid, oid, iid, rid, ANJAY_ID_INVALID); + } else +# endif // ANJAY_WITH_LWM2M_GATEWAY + { + path = MAKE_RESOURCE_PATH(oid, iid, rid); + } + int result = _anjay_dm_path_info(anjay, obj, &path, &path_info); if (result) { return result; } @@ -637,13 +773,29 @@ batch_data_add_current_impl(anjay_send_batch_builder_t *builder, forced_timestamp); } -int _anjay_send_batch_data_add_current_unlocked( - anjay_send_batch_builder_t *builder, - anjay_unlocked_t *anjay, - anjay_oid_t oid, - anjay_iid_t iid, - anjay_rid_t rid) { - return batch_data_add_current_impl(builder, anjay, oid, iid, rid, NULL); +static int +_anjay_send_batch_data_add_current_unlocked(anjay_send_batch_builder_t *builder, + anjay_unlocked_t *anjay, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid) { + const anjay_dm_t *dm; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (gateway_iid != ANJAY_ID_INVALID) { + _anjay_lwm2m_gateway_iid_to_dm(anjay, gateway_iid, &dm); + if (!dm) { + dm_log(ERROR, _("No End Device with specified iid found")); + return ANJAY_ERR_NOT_FOUND; + } + } else +# endif // ANJAY_WITH_LWM2M_GATEWAY + { + dm = &anjay->dm; + } + + return batch_data_add_current_impl(builder, anjay, dm, gateway_iid, oid, + iid, rid, NULL); } int anjay_send_batch_data_add_current(anjay_send_batch_builder_t *builder, @@ -653,8 +805,8 @@ int anjay_send_batch_data_add_current(anjay_send_batch_builder_t *builder, anjay_rid_t rid) { int result = -1; ANJAY_MUTEX_LOCK(anjay, anjay_locked); - result = _anjay_send_batch_data_add_current_unlocked(builder, anjay, oid, - iid, rid); + result = _anjay_send_batch_data_add_current_unlocked( + builder, anjay, ANJAY_ID_INVALID, oid, iid, rid); ANJAY_MUTEX_UNLOCK(anjay_locked); return result; } @@ -662,6 +814,7 @@ int anjay_send_batch_data_add_current(anjay_send_batch_builder_t *builder, int _anjay_send_batch_data_add_current_multiple_unlocked( anjay_send_batch_builder_t *builder, anjay_unlocked_t *anjay, + anjay_iid_t gateway_iid, const anjay_send_resource_path_t *paths, size_t paths_length, bool ignore_not_found) { @@ -672,21 +825,49 @@ int _anjay_send_batch_data_add_current_multiple_unlocked( AVS_LIST(anjay_batch_entry_t) *append_ptr = batch_builder->append_ptr; avs_time_real_t timestamp = avs_time_real_now(); + const anjay_dm_t *dm; + int result; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (gateway_iid != ANJAY_ID_INVALID) { + _anjay_lwm2m_gateway_iid_to_dm(anjay, gateway_iid, &dm); + if (!dm) { + dm_log(ERROR, _("No End Device with specified iid found")); + result = ANJAY_ERR_NOT_FOUND; + goto cleanup; + } + } else +# endif // ANJAY_WITH_LWM2M_GATEWAY + { + dm = &anjay->dm; + } + for (size_t i = 0; i < paths_length; i++) { - int result = batch_data_add_current_impl(builder, anjay, paths[i].oid, - paths[i].iid, paths[i].rid, - ×tamp); + result = batch_data_add_current_impl(builder, anjay, dm, gateway_iid, + paths[i].oid, paths[i].iid, + paths[i].rid, ×tamp); if (result == ANJAY_ERR_NOT_FOUND && ignore_not_found) { - send_log(WARNING, - _("resource ") "/%u/%u/%u" _(" not found, ignoring"), - paths[i].oid, paths[i].iid, paths[i].rid); + anjay_uri_path_t uri_path = { + .ids = { paths[i].oid, paths[i].iid, paths[i].rid, + ANJAY_ID_INVALID } + }; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (gateway_iid != ANJAY_ID_INVALID) { + avs_simple_snprintf(uri_path.prefix, sizeof(uri_path.prefix), + "dev%" PRIu16, gateway_iid); + } +# endif // ANJAY_WITH_LWM2M_GATEWAY + send_log(WARNING, _("resource ") "/%s" _(" not found, ignoring"), + ANJAY_DEBUG_MAKE_PATH(&uri_path)); } else if (result) { - batch_builder->append_ptr = append_ptr; - _anjay_batch_entry_list_cleanup(batch_builder->append_ptr); - return result; + goto cleanup; } } return 0; + +cleanup: + batch_builder->append_ptr = append_ptr; + _anjay_batch_entry_list_cleanup(batch_builder->append_ptr); + return result; } int anjay_send_batch_data_add_current_multiple( @@ -697,7 +878,7 @@ int anjay_send_batch_data_add_current_multiple( int result = -1; ANJAY_MUTEX_LOCK(anjay, anjay_locked); result = _anjay_send_batch_data_add_current_multiple_unlocked( - builder, anjay, paths, paths_length, false); + builder, anjay, ANJAY_ID_INVALID, paths, paths_length, false); ANJAY_MUTEX_UNLOCK(anjay_locked); return result; } @@ -710,11 +891,58 @@ int anjay_send_batch_data_add_current_multiple_ignore_not_found( int result = -1; ANJAY_MUTEX_LOCK(anjay, anjay_locked); result = _anjay_send_batch_data_add_current_multiple_unlocked( - builder, anjay, paths, paths_length, true); + builder, anjay, ANJAY_ID_INVALID, paths, paths_length, true); + ANJAY_MUTEX_UNLOCK(anjay_locked); + return result; +} + +# ifdef ANJAY_WITH_LWM2M_GATEWAY + +int anjay_lwm2m_gateway_send_batch_data_add_current( + anjay_send_batch_builder_t *builder, + anjay_t *anjay_locked, + anjay_iid_t gateway_iid, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid) { + int result = -1; + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + result = _anjay_send_batch_data_add_current_unlocked( + builder, anjay, gateway_iid, oid, iid, rid); + ANJAY_MUTEX_UNLOCK(anjay_locked); + return result; +} + +int anjay_lwm2m_gateway_send_batch_data_add_current_multiple( + anjay_send_batch_builder_t *builder, + anjay_t *anjay_locked, + anjay_iid_t gateway_iid, + const anjay_send_resource_path_t *paths, + size_t paths_length) { + int result = -1; + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + result = _anjay_send_batch_data_add_current_multiple_unlocked( + builder, anjay, gateway_iid, paths, paths_length, false); + ANJAY_MUTEX_UNLOCK(anjay_locked); + return result; +} + +int anjay_lwm2m_gateway_send_batch_data_add_current_multiple_ignore_not_found( + anjay_send_batch_builder_t *builder, + anjay_t *anjay_locked, + anjay_iid_t gateway_iid, + const anjay_send_resource_path_t *paths, + size_t paths_length) { + int result = -1; + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + result = _anjay_send_batch_data_add_current_multiple_unlocked( + builder, anjay, gateway_iid, paths, paths_length, true); ANJAY_MUTEX_UNLOCK(anjay_locked); return result; } +# endif // ANJAY_WITH_LWM2M_GATEWAY + anjay_send_batch_t * anjay_send_batch_builder_compile(anjay_send_batch_builder_t **builder_ptr) { anjay_batch_builder_t *builder = cast_to_builder(*builder_ptr); diff --git a/src/core/anjay_lwm2m_send.h b/src/core/anjay_lwm2m_send.h index 50ec6098..6f5e29df 100644 --- a/src/core/anjay_lwm2m_send.h +++ b/src/core/anjay_lwm2m_send.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_notify.c b/src/core/anjay_notify.c index d9b97d8e..e0b4643c 100644 --- a/src/core/anjay_notify.c +++ b/src/core/anjay_notify.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -11,6 +11,9 @@ #include #include +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +#endif // ANJAY_WITH_LWM2M_GATEWAY #include "coap/anjay_content_format.h" @@ -28,20 +31,24 @@ static int observe_notify(anjay_unlocked_t *anjay, int ret = 0; AVS_LIST(anjay_notify_queue_object_entry_t) it; AVS_LIST_FOREACH(it, queue) { + anjay_uri_path_t path = MAKE_OBJECT_PATH(it->oid); +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (queue->prefix[0] != '\0') { + strcpy(path.prefix, queue->prefix); + } +# endif // ANJAY_WITH_LWM2M_GATEWAY if (it->instance_set_changes.instance_set_changed) { _anjay_update_ret(&ret, - _anjay_observe_notify(anjay, - &MAKE_OBJECT_PATH(it->oid), - origin_ssid, true)); + _anjay_observe_notify(anjay, &path, origin_ssid, + true)); } else { AVS_LIST(anjay_notify_queue_resource_entry_t) it2; AVS_LIST_FOREACH(it2, it->resources_changed) { + path.ids[ANJAY_ID_IID] = it2->iid; + path.ids[ANJAY_ID_RID] = it2->rid; _anjay_update_ret(&ret, - _anjay_observe_notify( - anjay, - &MAKE_RESOURCE_PATH(it->oid, it2->iid, - it2->rid), - origin_ssid, true)); + _anjay_observe_notify(anjay, &path, + origin_ssid, true)); } } } @@ -182,17 +189,27 @@ int _anjay_notify_flush(anjay_unlocked_t *anjay, } static AVS_LIST(anjay_notify_queue_object_entry_t) * -find_or_create_object_entry(anjay_notify_queue_t *out_queue, anjay_oid_t oid) { +find_or_create_object_entry(anjay_notify_queue_t *out_queue, + const anjay_uri_path_t *path) { AVS_LIST(anjay_notify_queue_object_entry_t) *it; AVS_LIST_FOREACH_PTR(it, out_queue) { - if ((*it)->oid == oid) { - return it; - } else if ((*it)->oid > oid) { - break; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + // for gateway the search must include comparing the prefix as well + if ((!strcmp((*it)->prefix, path->prefix))) +#endif // ANJAY_WITH_LWM2M_GATEWAY + { + if ((*it)->oid == path->ids[ANJAY_ID_OID]) { + return it; + } else if ((*it)->oid > path->ids[ANJAY_ID_OID]) { + break; + } } } if (AVS_LIST_INSERT_NEW(anjay_notify_queue_object_entry_t, it)) { - (*it)->oid = oid; + (*it)->oid = path->ids[ANJAY_ID_OID]; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + strcpy((*it)->prefix, path->prefix); +#endif // ANJAY_WITH_LWM2M_GATEWAY return it; } else { return NULL; @@ -243,16 +260,16 @@ static void delete_notify_queue_object_entry_if_empty( } int _anjay_notify_queue_instance_created(anjay_notify_queue_t *out_queue, - anjay_oid_t oid, - anjay_iid_t iid) { + const anjay_uri_path_t *path) { AVS_LIST(anjay_notify_queue_object_entry_t) *entry_ptr = - find_or_create_object_entry(out_queue, oid); + find_or_create_object_entry(out_queue, path); if (!entry_ptr) { _anjay_log_oom(); return -1; } if (add_entry_to_iid_set( - &(*entry_ptr)->instance_set_changes.known_added_iids, iid)) { + &(*entry_ptr)->instance_set_changes.known_added_iids, + path->ids[ANJAY_ID_IID])) { _anjay_log_oom(); delete_notify_queue_object_entry_if_empty(entry_ptr); return -1; @@ -262,24 +279,24 @@ int _anjay_notify_queue_instance_created(anjay_notify_queue_t *out_queue, } int _anjay_notify_queue_instance_removed(anjay_notify_queue_t *out_queue, - anjay_oid_t oid, - anjay_iid_t iid) { + const anjay_uri_path_t *path) { AVS_LIST(anjay_notify_queue_object_entry_t) *entry_ptr = - find_or_create_object_entry(out_queue, oid); + find_or_create_object_entry(out_queue, path); if (!entry_ptr) { _anjay_log_oom(); return -1; } remove_entry_from_iid_set( - &(*entry_ptr)->instance_set_changes.known_added_iids, iid); + &(*entry_ptr)->instance_set_changes.known_added_iids, + path->ids[ANJAY_ID_IID]); (*entry_ptr)->instance_set_changes.instance_set_changed = true; return 0; } int _anjay_notify_queue_instance_set_unknown_change( - anjay_notify_queue_t *out_queue, anjay_oid_t oid) { + anjay_notify_queue_t *out_queue, const anjay_uri_path_t *path) { AVS_LIST(anjay_notify_queue_object_entry_t) *entry_ptr = - find_or_create_object_entry(out_queue, oid); + find_or_create_object_entry(out_queue, path); if (!entry_ptr) { _anjay_log_oom(); return -1; @@ -299,18 +316,16 @@ compare_resource_entries(const anjay_notify_queue_resource_entry_t *left, } int _anjay_notify_queue_resource_change(anjay_notify_queue_t *out_queue, - anjay_oid_t oid, - anjay_iid_t iid, - anjay_rid_t rid) { + const anjay_uri_path_t *path) { AVS_LIST(anjay_notify_queue_object_entry_t) *obj_entry_ptr = - find_or_create_object_entry(out_queue, oid); + find_or_create_object_entry(out_queue, path); if (!obj_entry_ptr) { _anjay_log_oom(); return -1; } anjay_notify_queue_resource_entry_t new_entry = { - .iid = iid, - .rid = rid + .iid = path->ids[ANJAY_ID_IID], + .rid = path->ids[ANJAY_ID_RID] }; AVS_LIST(anjay_notify_queue_resource_entry_t) *res_entry_ptr; AVS_LIST_FOREACH_PTR(res_entry_ptr, &(*obj_entry_ptr)->resources_changed) { @@ -363,7 +378,8 @@ int _anjay_notify_instance_created(anjay_unlocked_t *anjay, anjay_iid_t iid) { int retval; (void) ((retval = _anjay_notify_queue_instance_created( - &anjay->scheduled_notify.queue, oid, iid)) + &anjay->scheduled_notify.queue, + &MAKE_INSTANCE_PATH(oid, iid))) || (retval = reschedule_notify(anjay))); return retval; } @@ -374,7 +390,8 @@ int _anjay_notify_changed_unlocked(anjay_unlocked_t *anjay, anjay_rid_t rid) { int retval; (void) ((retval = _anjay_notify_queue_resource_change( - &anjay->scheduled_notify.queue, oid, iid, rid)) + &anjay->scheduled_notify.queue, + &MAKE_RESOURCE_PATH(oid, iid, rid))) || (retval = reschedule_notify(anjay))); return retval; } @@ -390,11 +407,40 @@ int anjay_notify_changed(anjay_t *anjay_locked, return retval; } +#ifdef ANJAY_WITH_LWM2M_GATEWAY +int _anjay_notify_changed_gw_unlocked(anjay_unlocked_t *anjay, + const char *prefix, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid) { + int retval; + anjay_uri_path_t path = MAKE_RESOURCE_PATH(oid, iid, rid); + strcpy(path.prefix, prefix); + (void) ((retval = _anjay_notify_queue_resource_change( + &anjay->scheduled_notify.queue, &path)) + || (retval = reschedule_notify(anjay))); + return retval; +} + +int _anjay_notify_instances_changed_gw_unlocked(anjay_unlocked_t *anjay, + const char *prefix, + anjay_oid_t oid) { + int retval; + anjay_uri_path_t path = MAKE_OBJECT_PATH(oid); + strcpy(path.prefix, prefix); + (void) ((retval = _anjay_notify_queue_instance_set_unknown_change( + &anjay->scheduled_notify.queue, &path)) + || (retval = reschedule_notify(anjay))); + return retval; +} + +#endif // ANJAY_WITH_LWM2M_GATEWAY + int _anjay_notify_instances_changed_unlocked(anjay_unlocked_t *anjay, anjay_oid_t oid) { int retval; (void) ((retval = _anjay_notify_queue_instance_set_unknown_change( - &anjay->scheduled_notify.queue, oid)) + &anjay->scheduled_notify.queue, &MAKE_OBJECT_PATH(oid))) || (retval = reschedule_notify(anjay))); return retval; } @@ -408,6 +454,55 @@ int anjay_notify_instances_changed(anjay_t *anjay_locked, anjay_oid_t oid) { } #ifdef ANJAY_WITH_OBSERVATION_STATUS +void _anjay_notify_observation_status_impl_unlocked( + anjay_unlocked_t *anjay, + anjay_resource_observation_status_t *status, + const char *prefix, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid) { + (void) prefix; + + if (oid == ANJAY_ID_INVALID || iid == ANJAY_ID_INVALID + || rid == ANJAY_ID_INVALID || (prefix && prefix[0] == '\0')) { + return; + } + + anjay_uri_path_t path = MAKE_RESOURCE_PATH(oid, iid, rid); +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (prefix) { + strcpy(path.prefix, prefix); + *status = _anjay_observe_status(anjay, &path); + return; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY + + if (oid == ANJAY_DM_OID_SECURITY + && _anjay_servers_find_active_by_security_iid(anjay, iid)) { + // All resources in active Security instances are always considered + // observed, as server connections need to be refreshed if they + // changed; compare with _anjay_notify_perform() + status->is_observed = true; + } else if (oid == ANJAY_DM_OID_SERVER + && (rid == ANJAY_DM_RID_SERVER_LIFETIME + || rid == ANJAY_DM_RID_SERVER_BINDING +# ifdef ANJAY_WITH_LWM2M11 + || rid == ANJAY_DM_RID_SERVER_PREFERRED_TRANSPORT +# endif // ANJAY_WITH_LWM2M11 + )) { + // Lifetime and Binding in Server Object are always considered + // observed, as server connections need to be refreshed if they + // changed; compare with _anjay_notify_perform() + status->is_observed = true; + } else { + // Note: some modules may also depend on resource notifications, + // particularly Firmware Update depends on notifications on /5/0/3, + // but it also implements that object and generates relevant + // notifications internally, so there's no need to check that here. + *status = _anjay_observe_status(anjay, &path); + } +} + anjay_resource_observation_status_t anjay_resource_observation_status(anjay_t *anjay_locked, anjay_oid_t oid, @@ -419,37 +514,14 @@ anjay_resource_observation_status(anjay_t *anjay_locked, .max_eval_period = ANJAY_ATTRIB_INTEGER_NONE, # if (ANJAY_MAX_OBSERVATION_SERVERS_REPORTED_NUMBER > 0) .servers_number = 0 -# endif //(ANJAY_MAX_OBSERVATION_SERVERS_REPORTED_NUMBER > 0) +# endif // (ANJAY_MAX_OBSERVATION_SERVERS_REPORTED_NUMBER > 0) }; + ANJAY_MUTEX_LOCK(anjay, anjay_locked); - if (oid != ANJAY_ID_INVALID && iid != ANJAY_ID_INVALID - && rid != ANJAY_ID_INVALID) { - if (oid == ANJAY_DM_OID_SECURITY - && _anjay_servers_find_active_by_security_iid(anjay, iid)) { - // All resources in active Security instances are always considered - // observed, as server connections need to be refreshed if they - // changed; compare with _anjay_notify_perform() - retval.is_observed = true; - } else if (oid == ANJAY_DM_OID_SERVER - && (rid == ANJAY_DM_RID_SERVER_LIFETIME - || rid == ANJAY_DM_RID_SERVER_BINDING -# ifdef ANJAY_WITH_LWM2M11 - || rid == ANJAY_DM_RID_SERVER_PREFERRED_TRANSPORT -# endif // ANJAY_WITH_LWM2M11 - )) { - // Lifetime and Binding in Server Object are always considered - // observed, as server connections need to be refreshed if they - // changed; compare with _anjay_notify_perform() - retval.is_observed = true; - } else { - // Note: some modules may also depend on resource notifications, - // particularly Firmware Update depends on notifications on /5/0/3, - // but it also implements that object and generates relevant - // notifications internally, so there's no need to check that here. - retval = _anjay_observe_status(anjay, oid, iid, rid); - } - } + _anjay_notify_observation_status_impl_unlocked(anjay, &retval, NULL, oid, + iid, rid); ANJAY_MUTEX_UNLOCK(anjay_locked); return retval; } + #endif // ANJAY_WITH_OBSERVATION_STATUS diff --git a/src/core/anjay_raw_buffer.c b/src/core/anjay_raw_buffer.c index 6ba18dcf..224264c9 100644 --- a/src/core/anjay_raw_buffer.c +++ b/src/core/anjay_raw_buffer.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_servers_inactive.h b/src/core/anjay_servers_inactive.h index b9a60428..97dc5345 100644 --- a/src/core/anjay_servers_inactive.h +++ b/src/core/anjay_servers_inactive.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_servers_private.h b/src/core/anjay_servers_private.h index 7203e02c..2a06d599 100644 --- a/src/core/anjay_servers_private.h +++ b/src/core/anjay_servers_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_servers_reload.h b/src/core/anjay_servers_reload.h index fb5380e1..eaaf66a4 100644 --- a/src/core/anjay_servers_reload.h +++ b/src/core/anjay_servers_reload.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_servers_utils.c b/src/core/anjay_servers_utils.c index 8351f3bf..a4121d11 100644 --- a/src/core/anjay_servers_utils.c +++ b/src/core/anjay_servers_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_servers_utils.h b/src/core/anjay_servers_utils.h index f690d534..e0abb05f 100644 --- a/src/core/anjay_servers_utils.h +++ b/src/core/anjay_servers_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_stats.c b/src/core/anjay_stats.c index 95405d4e..3148e086 100644 --- a/src/core/anjay_stats.c +++ b/src/core/anjay_stats.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_stats.h b/src/core/anjay_stats.h index abfd4bde..dc1bc9b7 100644 --- a/src/core/anjay_stats.h +++ b/src/core/anjay_stats.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_utils_core.c b/src/core/anjay_utils_core.c index 4693890a..db4c9ad6 100644 --- a/src/core/anjay_utils_core.c +++ b/src/core/anjay_utils_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/anjay_utils_private.h b/src/core/anjay_utils_private.h index fa7f4b32..4b1620ed 100644 --- a/src/core/anjay_utils_private.h +++ b/src/core/anjay_utils_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/attr_storage/anjay_attr_storage.c b/src/core/attr_storage/anjay_attr_storage.c index c438b2bd..cf05e3fa 100644 --- a/src/core/attr_storage/anjay_attr_storage.c +++ b/src/core/attr_storage/anjay_attr_storage.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -20,6 +20,9 @@ # include # include +# ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +# endif // ANJAY_WITH_LWM2M_GATEWAY # include "../anjay_core.h" @@ -31,12 +34,12 @@ VISIBILITY_SOURCE_BEGIN //// LIFETIME AND OBJECT HANDLING ////////////////////////////////////////////// -int _anjay_attr_storage_init(anjay_unlocked_t *anjay) { - assert(anjay); - if (!(anjay->attr_storage.saved_state.persist_data = - avs_stream_membuf_create())) { +int _anjay_attr_storage_init(anjay_attr_storage_t *as, anjay_dm_t *dm) { + assert(as); + if (!(as->saved_state.persist_data = avs_stream_membuf_create())) { return -1; } + as->dm = dm; return 0; } @@ -75,6 +78,27 @@ AVS_STATIC_ASSERT(offsetof(as_resource_entry_t, rid) == 0, resource_id_offset); AVS_STATIC_ASSERT(offsetof(as_resource_instance_entry_t, riid) == 0, resource_instance_id_offset); +# ifdef ANJAY_WITH_LWM2M_GATEWAY +static anjay_attr_storage_t * +get_attr_storage(anjay_unlocked_t *anjay, + const anjay_dm_installed_object_t *def_ptr) { + if (def_ptr->prefix) { + anjay_attr_storage_t *as = NULL; + _anjay_lwm2m_gateway_prefix_to_as(anjay, def_ptr->prefix, &as); + assert(as); + return as; + } + return &anjay->attr_storage; +} +# else +static inline anjay_attr_storage_t * +get_attr_storage(anjay_unlocked_t *anjay, + const anjay_dm_installed_object_t *def_ptr) { + (void) def_ptr; + return &anjay->attr_storage; +} +# endif // ANJAY_WITH_LWM2M_GATEWAY + static AVS_LIST(void) * find_or_create_entry_impl(AVS_LIST(void) *children_list_ptr, size_t entry_size, @@ -291,11 +315,12 @@ int _anjay_attr_storage_remove_absent_instances_clb( anjay_iid_t iid, void *instance_ptr_ptr_) { (void) def_ptr; + anjay_attr_storage_t *as = get_attr_storage(anjay, def_ptr); AVS_LIST(as_instance_entry_t) **instance_ptr_ptr = (AVS_LIST(as_instance_entry_t) **) instance_ptr_ptr_; if (**instance_ptr_ptr && (**instance_ptr_ptr)->iid < iid) { while (**instance_ptr_ptr && (**instance_ptr_ptr)->iid < iid) { - remove_instance_entry(&anjay->attr_storage, *instance_ptr_ptr); + remove_instance_entry(as, *instance_ptr_ptr); } } if (**instance_ptr_ptr && (**instance_ptr_ptr)->iid == iid) { @@ -316,14 +341,15 @@ remove_absent_resources_clb(anjay_unlocked_t *anjay, (void) def_ptr; (void) iid; (void) kind; + anjay_attr_storage_t *as = get_attr_storage(anjay, def_ptr); AVS_LIST(as_resource_entry_t) **resource_ptr_ptr = (AVS_LIST(as_resource_entry_t) **) resource_ptr_ptr_; while (**resource_ptr_ptr && (**resource_ptr_ptr)->rid < rid) { - remove_resource_entry(&anjay->attr_storage, *resource_ptr_ptr); + remove_resource_entry(as, *resource_ptr_ptr); } if (**resource_ptr_ptr && (**resource_ptr_ptr)->rid == rid) { if (presence == ANJAY_DM_RES_ABSENT) { - remove_resource_entry(&anjay->attr_storage, *resource_ptr_ptr); + remove_resource_entry(as, *resource_ptr_ptr); } else { AVS_LIST_ADVANCE_PTR(resource_ptr_ptr); } @@ -335,6 +361,7 @@ int _anjay_attr_storage_remove_absent_resources( anjay_unlocked_t *anjay, AVS_LIST(as_instance_entry_t) *instance_ptr, const anjay_dm_installed_object_t *def_ptr) { + anjay_attr_storage_t *as = get_attr_storage(anjay, def_ptr); AVS_LIST(as_resource_entry_t) *resource_ptr = &(*instance_ptr)->resources; int result = 0; if (def_ptr) { @@ -345,7 +372,7 @@ int _anjay_attr_storage_remove_absent_resources( } if (!result) { while (*resource_ptr) { - remove_resource_entry(&anjay->attr_storage, resource_ptr); + remove_resource_entry(as, resource_ptr); } } remove_instance_if_empty(instance_ptr); @@ -364,13 +391,13 @@ remove_absent_resource_instances_clb(anjay_unlocked_t *anjay, (void) def_ptr; (void) iid; (void) rid; + anjay_attr_storage_t *as = get_attr_storage(anjay, def_ptr); AVS_LIST(as_resource_instance_entry_t) **resource_instance_ptr_ptr = (AVS_LIST(as_resource_instance_entry_t) **) resource_instance_ptr_ptr_; while (**resource_instance_ptr_ptr && (**resource_instance_ptr_ptr)->riid < riid) { - remove_resource_instance_entry(&anjay->attr_storage, - *resource_instance_ptr_ptr); + remove_resource_instance_entry(as, *resource_instance_ptr_ptr); } if (**resource_instance_ptr_ptr && (**resource_instance_ptr_ptr)->riid == riid) { @@ -384,6 +411,7 @@ int _anjay_attr_storage_remove_absent_resource_instances( const anjay_dm_installed_object_t *def_ptr, anjay_iid_t iid, AVS_LIST(as_resource_entry_t) *resource_ptr) { + anjay_attr_storage_t *as = get_attr_storage(anjay, def_ptr); AVS_LIST(as_resource_instance_entry_t) *resource_instance_ptr = &(*resource_ptr)->resource_instances; int result = 0; @@ -400,8 +428,7 @@ int _anjay_attr_storage_remove_absent_resource_instances( } if (!result) { while (*resource_instance_ptr) { - remove_resource_instance_entry(&anjay->attr_storage, - resource_instance_ptr); + remove_resource_instance_entry(as, resource_instance_ptr); } } remove_resource_if_empty(resource_ptr); @@ -487,15 +514,14 @@ static int write_object_attrs(anjay_unlocked_t *anjay, anjay_ssid_t ssid, const anjay_dm_installed_object_t *obj_ptr, const anjay_dm_oi_attributes_t *attrs) { + anjay_attr_storage_t *as = get_attr_storage(anjay, obj_ptr); AVS_LIST(as_object_entry_t) *object_ptr = - find_or_create_object(&anjay->attr_storage, - _anjay_dm_installed_object_oid(obj_ptr)); + find_or_create_object(as, _anjay_dm_installed_object_oid(obj_ptr)); if (!object_ptr) { return -1; } - int result = - WRITE_ATTRS(&anjay->attr_storage, &(*object_ptr)->default_attrs, - default_attrs_empty, ssid, attrs); + int result = WRITE_ATTRS(as, &(*object_ptr)->default_attrs, + default_attrs_empty, ssid, attrs); remove_object_if_empty(object_ptr); return result; } @@ -509,11 +535,11 @@ static int write_instance_attrs(anjay_unlocked_t *anjay, int result = -1; AVS_LIST(as_object_entry_t) *object_ptr = NULL; AVS_LIST(as_instance_entry_t) *instance_ptr = NULL; - if ((object_ptr = find_or_create_object( - &anjay->attr_storage, _anjay_dm_installed_object_oid(obj_ptr))) + anjay_attr_storage_t *as = get_attr_storage(anjay, obj_ptr); + if ((object_ptr = find_or_create_object(as, _anjay_dm_installed_object_oid( + obj_ptr))) && (instance_ptr = find_or_create_instance(*object_ptr, iid))) { - result = WRITE_ATTRS(&anjay->attr_storage, - &(*instance_ptr)->default_attrs, + result = WRITE_ATTRS(as, &(*instance_ptr)->default_attrs, default_attrs_empty, ssid, attrs); } @@ -537,12 +563,13 @@ static int write_resource_attrs(anjay_unlocked_t *anjay, AVS_LIST(as_object_entry_t) *object_ptr = NULL; AVS_LIST(as_instance_entry_t) *instance_ptr = NULL; AVS_LIST(as_resource_entry_t) *resource_ptr = NULL; - if ((object_ptr = find_or_create_object( - &anjay->attr_storage, _anjay_dm_installed_object_oid(obj_ptr))) + anjay_attr_storage_t *as = get_attr_storage(anjay, obj_ptr); + if ((object_ptr = find_or_create_object(as, _anjay_dm_installed_object_oid( + obj_ptr))) && (instance_ptr = find_or_create_instance(*object_ptr, iid)) && (resource_ptr = find_or_create_resource(*instance_ptr, rid))) { - result = WRITE_ATTRS(&anjay->attr_storage, &(*resource_ptr)->attrs, - resource_attrs_empty, ssid, attrs); + result = WRITE_ATTRS(as, &(*resource_ptr)->attrs, resource_attrs_empty, + ssid, attrs); } if (resource_ptr) { @@ -573,14 +600,14 @@ write_resource_instance_attrs(anjay_unlocked_t *anjay, AVS_LIST(as_instance_entry_t) *instance_ptr = NULL; AVS_LIST(as_resource_entry_t) *resource_ptr = NULL; AVS_LIST(as_resource_instance_entry_t) *resource_instance_ptr = NULL; - if ((object_ptr = find_or_create_object( - &anjay->attr_storage, _anjay_dm_installed_object_oid(obj_ptr))) + anjay_attr_storage_t *as = get_attr_storage(anjay, obj_ptr); + if ((object_ptr = find_or_create_object(as, _anjay_dm_installed_object_oid( + obj_ptr))) && (instance_ptr = find_or_create_instance(*object_ptr, iid)) && (resource_ptr = find_or_create_resource(*instance_ptr, rid)) && (resource_instance_ptr = find_or_create_resource_instance( *resource_ptr, riid))) { - result = WRITE_ATTRS(&anjay->attr_storage, - &(*resource_instance_ptr)->attrs, + result = WRITE_ATTRS(as, &(*resource_instance_ptr)->attrs, resource_attrs_empty, ssid, attrs); } @@ -654,8 +681,9 @@ static int remove_absent_instances_and_enumerate_ssids( if (result) { return result; } + anjay_attr_storage_t *as = get_attr_storage(anjay, def_ptr); while (args.instance_ptr && *args.instance_ptr) { - remove_instance_entry(&anjay->attr_storage, args.instance_ptr); + remove_instance_entry(as, args.instance_ptr); } return 0; } @@ -690,9 +718,9 @@ static int remove_absent_resources_in_all_instances( const anjay_dm_installed_object_t *def_ptr, AVS_LIST(anjay_notify_queue_resource_entry_t) resources_changed) { int result = 0; + anjay_attr_storage_t *as = get_attr_storage(anjay, def_ptr); AVS_LIST(as_object_entry_t) *object_ptr = - find_object(&anjay->attr_storage, - _anjay_dm_installed_object_oid(def_ptr)); + find_object(as, _anjay_dm_installed_object_oid(def_ptr)); if (object_ptr) { anjay_iid_t last_iid = ANJAY_ID_INVALID; AVS_LIST(anjay_notify_queue_resource_entry_t) resource_entry; @@ -760,9 +788,9 @@ static int object_read_default_attrs(anjay_unlocked_t *anjay, const anjay_dm_installed_object_t obj_ptr, anjay_ssid_t ssid, anjay_dm_oi_attributes_t *out) { + anjay_attr_storage_t *as = get_attr_storage(anjay, &obj_ptr); AVS_LIST(as_object_entry_t) *object_ptr = - find_object(&anjay->attr_storage, - _anjay_dm_installed_object_oid(&obj_ptr)); + find_object(as, _anjay_dm_installed_object_oid(&obj_ptr)); read_default_attrs(object_ptr ? (*object_ptr)->default_attrs : NULL, ssid, out); return 0; @@ -782,9 +810,9 @@ instance_read_default_attrs(anjay_unlocked_t *anjay, anjay_iid_t iid, anjay_ssid_t ssid, anjay_dm_oi_attributes_t *out) { + anjay_attr_storage_t *as = get_attr_storage(anjay, &obj_ptr); AVS_LIST(as_object_entry_t) *object_ptr = - find_object(&anjay->attr_storage, - _anjay_dm_installed_object_oid(&obj_ptr)); + find_object(as, _anjay_dm_installed_object_oid(&obj_ptr)); AVS_LIST(as_instance_entry_t) *instance_ptr = object_ptr ? find_instance(*object_ptr, iid) : NULL; read_default_attrs(instance_ptr ? (*instance_ptr)->default_attrs : NULL, @@ -809,9 +837,9 @@ static int resource_read_attrs(anjay_unlocked_t *anjay, anjay_rid_t rid, anjay_ssid_t ssid, anjay_dm_r_attributes_t *out) { + anjay_attr_storage_t *as = get_attr_storage(anjay, &obj_ptr); AVS_LIST(as_object_entry_t) *object_ptr = - find_object(&anjay->attr_storage, - _anjay_dm_installed_object_oid(&obj_ptr)); + find_object(as, _anjay_dm_installed_object_oid(&obj_ptr)); AVS_LIST(as_instance_entry_t) *instance_ptr = object_ptr ? find_instance(*object_ptr, iid) : NULL; AVS_LIST(as_resource_entry_t) *res_ptr = @@ -840,9 +868,9 @@ resource_instance_read_attrs(anjay_unlocked_t *anjay, anjay_riid_t riid, anjay_ssid_t ssid, anjay_dm_r_attributes_t *out) { + anjay_attr_storage_t *as = get_attr_storage(anjay, &obj_ptr); AVS_LIST(as_object_entry_t) *object_ptr = - find_object(&anjay->attr_storage, - _anjay_dm_installed_object_oid(&obj_ptr)); + find_object(as, _anjay_dm_installed_object_oid(&obj_ptr)); AVS_LIST(as_instance_entry_t) *instance_ptr = object_ptr ? find_instance(*object_ptr, iid) : NULL; AVS_LIST(as_resource_entry_t) *res_ptr = @@ -889,28 +917,25 @@ static void saved_state_reset(anjay_attr_storage_t *as) { avs_stream_membuf_fit(as->saved_state.persist_data); } -avs_error_t _anjay_attr_storage_transaction_begin(anjay_unlocked_t *anjay) { - anjay->attr_storage.saved_state.modified_since_persist = - anjay->attr_storage.modified_since_persist; - return _anjay_attr_storage_persist_inner( - &anjay->attr_storage, anjay->attr_storage.saved_state.persist_data); +avs_error_t _anjay_attr_storage_transaction_begin(anjay_attr_storage_t *as) { + as->saved_state.modified_since_persist = as->modified_since_persist; + return _anjay_attr_storage_persist_inner(as, as->saved_state.persist_data); } -void _anjay_attr_storage_transaction_commit(anjay_unlocked_t *anjay) { - saved_state_reset(&anjay->attr_storage); +void _anjay_attr_storage_transaction_commit(anjay_attr_storage_t *as) { + saved_state_reset(as); } -avs_error_t _anjay_attr_storage_transaction_rollback(anjay_unlocked_t *anjay) { +avs_error_t _anjay_attr_storage_transaction_rollback(anjay_unlocked_t *anjay, + anjay_attr_storage_t *as) { avs_error_t err; if (avs_is_err((err = _anjay_attr_storage_restore_inner( - anjay, - anjay->attr_storage.saved_state.persist_data)))) { - anjay->attr_storage.modified_since_persist = true; + anjay, as, as->saved_state.persist_data)))) { + as->modified_since_persist = true; } else { - anjay->attr_storage.modified_since_persist = - anjay->attr_storage.saved_state.modified_since_persist; + as->modified_since_persist = as->saved_state.modified_since_persist; } - saved_state_reset(&anjay->attr_storage); + saved_state_reset(as); return err; } @@ -942,18 +967,21 @@ maybe_get_object_before_setting_attrs(anjay_unlocked_t *anjay, # define ERR_INSTANCE_PRESENCE_CHECK \ _("instance ") \ + DM_LOG_PREFIX \ "/%" PRIu16 \ "/%" PRIu16 _(" does not exist or an error occurred during " \ "querying its presence") # define ERR_RESOURCE_PRESENCE_CHECK \ _("resource ") \ + DM_LOG_PREFIX \ "/%" PRIu16 "/%" PRIu16 "/%" PRIu16 _( \ "does not exist or an error occurred during querying its " \ "presence") # define ERR_RESOURCE_INSTANCE_PRESENCE_CHECK \ _("resource instance ") \ + DM_LOG_PREFIX \ "/%" PRIu16 "/%" PRIu16 "/%" PRIu16 "/%" PRIu16 _( \ "does not exist or an error occurred during querying its " \ "presence") @@ -994,7 +1022,8 @@ int anjay_attr_storage_set_instance_attrs( "instance_read_default_attrs", "instance_write_default_attrs"); } else if (_anjay_dm_verify_instance_present(anjay, obj, iid)) { - as_log(DEBUG, ERR_INSTANCE_PRESENCE_CHECK, oid, iid); + as_log(DEBUG, ERR_INSTANCE_PRESENCE_CHECK, + DM_LOG_PREFIX_OBJ_ARG(obj) oid, iid); } else if (!(result = write_instance_attrs(anjay, ssid, obj, iid, attrs))) { (void) _anjay_notify_instances_changed_unlocked(anjay, oid); @@ -1020,10 +1049,12 @@ int anjay_attr_storage_set_resource_attrs( as_log(DEBUG, ERR_HANDLERS_IMPLEMENTED_BY_BACKEND, "resource", "resource_read_attrs", "resource_write_attrs"); } else if (_anjay_dm_verify_instance_present(anjay, obj, iid)) { - as_log(DEBUG, ERR_INSTANCE_PRESENCE_CHECK, oid, iid); + as_log(DEBUG, ERR_INSTANCE_PRESENCE_CHECK, + DM_LOG_PREFIX_OBJ_ARG(obj) oid, iid); } else if (_anjay_dm_verify_resource_present(anjay, obj, iid, rid, NULL)) { - as_log(DEBUG, ERR_RESOURCE_PRESENCE_CHECK, oid, iid, rid); + as_log(DEBUG, ERR_RESOURCE_PRESENCE_CHECK, + DM_LOG_PREFIX_OBJ_ARG(obj) oid, iid, rid); } else if (!(result = write_resource_attrs(anjay, ssid, obj, iid, rid, attrs))) { (void) _anjay_notify_instances_changed_unlocked(anjay, oid); @@ -1053,15 +1084,17 @@ int anjay_attr_storage_set_resource_instance_attrs( "resource instance", "resource_instance_read_attrs", "resource_instance_write_attrs"); } else if (_anjay_dm_verify_instance_present(anjay, obj, iid)) { - as_log(DEBUG, ERR_INSTANCE_PRESENCE_CHECK, oid, iid); + as_log(DEBUG, ERR_INSTANCE_PRESENCE_CHECK, + DM_LOG_PREFIX_OBJ_ARG(obj) oid, iid); } else if (_anjay_dm_verify_resource_present(anjay, obj, iid, rid, &kind) || !_anjay_dm_res_kind_multiple(kind)) { - as_log(DEBUG, ERR_RESOURCE_PRESENCE_CHECK, oid, iid, rid); + as_log(DEBUG, ERR_RESOURCE_PRESENCE_CHECK, + DM_LOG_PREFIX_OBJ_ARG(obj) oid, iid, rid); } else if (_anjay_dm_verify_resource_instance_present(anjay, obj, iid, rid, riid)) { - as_log(DEBUG, ERR_RESOURCE_INSTANCE_PRESENCE_CHECK, oid, iid, rid, - riid); + as_log(DEBUG, ERR_RESOURCE_INSTANCE_PRESENCE_CHECK, + DM_LOG_PREFIX_OBJ_ARG(obj) oid, iid, rid, riid); } else if (!(result = write_resource_instance_attrs( anjay, ssid, obj, iid, rid, riid, attrs))) { (void) _anjay_notify_instances_changed_unlocked(anjay, oid); diff --git a/src/core/attr_storage/anjay_attr_storage.h b/src/core/attr_storage/anjay_attr_storage.h index b31b01fc..a55cb212 100644 --- a/src/core/attr_storage/anjay_attr_storage.h +++ b/src/core/attr_storage/anjay_attr_storage.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -13,6 +13,7 @@ #include #include +#include #include VISIBILITY_PRIVATE_HEADER_BEGIN @@ -24,11 +25,12 @@ typedef struct { bool modified_since_persist; } as_saved_state_t; -typedef struct { +struct anjay_attr_storage_struct { AVS_LIST(as_object_entry_t) objects; bool modified_since_persist; as_saved_state_t saved_state; -} anjay_attr_storage_t; + anjay_dm_t *dm; +}; static inline bool _anjay_dm_implements_any_object_default_attrs_handlers( const anjay_dm_installed_object_t *obj_ptr) { @@ -64,12 +66,13 @@ static inline bool _anjay_dm_implements_any_resource_instance_attrs_handlers( } #endif // ANJAY_WITH_LWM2M11 -int _anjay_attr_storage_init(anjay_unlocked_t *anjay); +int _anjay_attr_storage_init(anjay_attr_storage_t *as, anjay_dm_t *dm); void _anjay_attr_storage_cleanup(anjay_attr_storage_t *as); -avs_error_t _anjay_attr_storage_transaction_begin(anjay_unlocked_t *anjay); -void _anjay_attr_storage_transaction_commit(anjay_unlocked_t *anjay); -avs_error_t _anjay_attr_storage_transaction_rollback(anjay_unlocked_t *anjay); +avs_error_t _anjay_attr_storage_transaction_begin(anjay_attr_storage_t *as); +void _anjay_attr_storage_transaction_commit(anjay_attr_storage_t *as); +avs_error_t _anjay_attr_storage_transaction_rollback(anjay_unlocked_t *anjay, + anjay_attr_storage_t *as); int _anjay_attr_storage_notify(anjay_unlocked_t *anjay, anjay_notify_queue_t queue); diff --git a/src/core/attr_storage/anjay_attr_storage_persistence.c b/src/core/attr_storage/anjay_attr_storage_persistence.c index a40b39a4..edaf81cc 100644 --- a/src/core/attr_storage/anjay_attr_storage_persistence.c +++ b/src/core/attr_storage/anjay_attr_storage_persistence.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -343,7 +343,7 @@ static avs_error_t clear_nonexistent_entries(anjay_unlocked_t *anjay, AVS_LIST(as_object_entry_t) object_helper; AVS_LIST_DELETABLE_FOREACH_PTR(object_ptr, object_helper, &as->objects) { const anjay_dm_installed_object_t *def_ptr = - _anjay_dm_find_object_by_oid(&anjay->dm, (*object_ptr)->oid); + _anjay_dm_find_object_by_oid(as->dm, (*object_ptr)->oid); if (!def_ptr) { remove_object_entry(as, object_ptr); } else { @@ -385,8 +385,9 @@ _anjay_attr_storage_persist_inner(anjay_attr_storage_t *attr_storage, } avs_error_t _anjay_attr_storage_restore_inner(anjay_unlocked_t *anjay, + anjay_attr_storage_t *as, avs_stream_t *in) { - _anjay_attr_storage_clear(&anjay->attr_storage); + _anjay_attr_storage_clear(as); avs_persistence_context_t ctx = avs_persistence_restore_context_create(in); as_persistence_version_t version = (as_persistence_version_t) 0; @@ -397,15 +398,13 @@ avs_error_t _anjay_attr_storage_restore_inner(anjay_unlocked_t *anjay, &ctx, (uint8_t *) &version, SUPPORTED_VERSIONS_ARRAY, sizeof(SUPPORTED_VERSIONS_ARRAY)))) - || avs_is_err((err = HANDLE_LIST(object, &ctx, - &anjay->attr_storage.objects, + || avs_is_err((err = HANDLE_LIST(object, &ctx, &as->objects, (void *) version))) - || avs_is_err((err = (is_attr_storage_sane(&anjay->attr_storage) + || avs_is_err((err = (is_attr_storage_sane(as) ? AVS_OK : avs_errno(AVS_EBADMSG)))) - || avs_is_err((err = clear_nonexistent_entries( - anjay, &anjay->attr_storage)))) { - _anjay_attr_storage_clear(&anjay->attr_storage); + || avs_is_err((err = clear_nonexistent_entries(anjay, as)))) { + _anjay_attr_storage_clear(as); } return err; } @@ -427,15 +426,17 @@ avs_error_t anjay_attr_storage_restore(anjay_t *anjay_locked, avs_stream_t *in) { avs_error_t err = avs_errno(AVS_EINVAL); ANJAY_MUTEX_LOCK(anjay, anjay_locked); - if (avs_is_ok((err = _anjay_attr_storage_transaction_begin(anjay)))) { - if (avs_is_ok((err = _anjay_attr_storage_restore_inner(anjay, in)))) { - _anjay_attr_storage_transaction_commit(anjay); + if (avs_is_ok((err = _anjay_attr_storage_transaction_begin( + &anjay->attr_storage)))) { + if (avs_is_ok((err = _anjay_attr_storage_restore_inner( + anjay, &anjay->attr_storage, in)))) { + _anjay_attr_storage_transaction_commit(&anjay->attr_storage); anjay->attr_storage.modified_since_persist = false; as_log(INFO, _("Attribute Storage state restored")); } else { - avs_error_t rollback_err = - _anjay_attr_storage_transaction_rollback(anjay); + avs_error_t rollback_err = _anjay_attr_storage_transaction_rollback( + anjay, &anjay->attr_storage); if (avs_is_err(rollback_err)) { err = rollback_err; } diff --git a/src/core/attr_storage/anjay_attr_storage_private.h b/src/core/attr_storage/anjay_attr_storage_private.h index 7e3d1afb..4d2e3a28 100644 --- a/src/core/attr_storage/anjay_attr_storage_private.h +++ b/src/core/attr_storage/anjay_attr_storage_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -169,6 +169,7 @@ _anjay_attr_storage_persist_inner(anjay_attr_storage_t *attr_storage, avs_stream_t *out); avs_error_t _anjay_attr_storage_restore_inner(anjay_unlocked_t *anjay, + anjay_attr_storage_t *as, avs_stream_t *in); VISIBILITY_PRIVATE_HEADER_END diff --git a/src/core/coap/anjay_content_format.h b/src/core/coap/anjay_content_format.h index d3f71ab5..03356e50 100644 --- a/src/core/coap/anjay_content_format.h +++ b/src/core/coap/anjay_content_format.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/coap/anjay_msg_details.h b/src/core/coap/anjay_msg_details.h index 7acea94c..c0ce7f12 100644 --- a/src/core/coap/anjay_msg_details.h +++ b/src/core/coap/anjay_msg_details.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_discover.c b/src/core/dm/anjay_discover.c index 7ab060f5..d0e24139 100644 --- a/src/core/dm/anjay_discover.c +++ b/src/core/dm/anjay_discover.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_discover.h b/src/core/dm/anjay_discover.h index 471851b6..c6c9bcae 100644 --- a/src/core/dm/anjay_discover.h +++ b/src/core/dm/anjay_discover.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_attributes.c b/src/core/dm/anjay_dm_attributes.c index 1f904b77..ebe032f2 100644 --- a/src/core/dm/anjay_dm_attributes.c +++ b/src/core/dm/anjay_dm_attributes.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_attributes.h b/src/core/dm/anjay_dm_attributes.h index 2a973d27..93ac788a 100644 --- a/src/core/dm/anjay_dm_attributes.h +++ b/src/core/dm/anjay_dm_attributes.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_create.c b/src/core/dm/anjay_dm_create.c index 38bb0ff0..bb02bada 100644 --- a/src/core/dm/anjay_dm_create.c +++ b/src/core/dm/anjay_dm_create.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -94,16 +94,18 @@ dm_create_inner_and_move_to_next_entry(anjay_unlocked_t *anjay, int result = _anjay_dm_call_instance_create(anjay, obj, iid); if (result) { dm_log(DEBUG, - _("Instance Create handler for object ") "%" PRIu16 _(" failed"), - _anjay_dm_installed_object_oid(obj)); + _("Instance Create handler for object ") DM_LOG_PREFIX + "/%" PRIu16 _(" failed"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj)); return result; } else if ((result = _anjay_dm_write_created_instance_and_move_to_next_entry( anjay, obj, iid, in_ctx))) { dm_log(DEBUG, - _("Writing Resources for newly created ") "/%" PRIu16 "/%" PRIu16 - _(" failed; removing"), - _anjay_dm_installed_object_oid(obj), iid); + _("Writing Resources for newly created ") DM_LOG_PREFIX + "/%" PRIu16 "/%" PRIu16 _(" failed; removing"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid); } return result; } @@ -118,14 +120,17 @@ static int dm_create_with_explicit_iid(anjay_unlocked_t *anjay, int result = _anjay_dm_instance_present(anjay, obj, iid); if (result > 0) { dm_log(DEBUG, - _("Instance ") "/%" PRIu16 "/%" PRIu16 _(" already exists"), - _anjay_dm_installed_object_oid(obj), iid); + _("Instance ") DM_LOG_PREFIX "/%" PRIu16 + "/%" PRIu16 _(" already exists"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid); return ANJAY_ERR_BAD_REQUEST; } else if (result) { dm_log(DEBUG, - _("Instance Present handler for ") "/%" PRIu16 - "/%" PRIu16 _(" failed"), - _anjay_dm_installed_object_oid(obj), iid); + _("Instance Present handler for ") DM_LOG_PREFIX + "/%" PRIu16 "/%" PRIu16 _(" failed"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid); return result; } result = dm_create_inner_and_move_to_next_entry(anjay, obj, iid, in_ctx); @@ -181,9 +186,14 @@ int _anjay_dm_create(anjay_unlocked_t *anjay, } if (!result) { anjay_notify_queue_t notify_queue = NULL; - (void) ((result = _anjay_notify_queue_instance_created( - ¬ify_queue, request->uri.ids[ANJAY_ID_OID], - path.ids[ANJAY_ID_IID])) + path.ids[ANJAY_ID_OID] = request->uri.ids[ANJAY_ID_OID]; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(&request->uri)) { + strcpy(path.prefix, request->uri.prefix); + } +#endif // ANJAY_WITH_LWM2M_GATEWAY + (void) ((result = _anjay_notify_queue_instance_created(¬ify_queue, + &path)) || (result = _anjay_notify_flush(anjay, ssid, ¬ify_queue))); } return result; diff --git a/src/core/dm/anjay_dm_create.h b/src/core/dm/anjay_dm_create.h index 010f4366..9defd98a 100644 --- a/src/core/dm/anjay_dm_create.h +++ b/src/core/dm/anjay_dm_create.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_execute.c b/src/core/dm/anjay_dm_execute.c index d99bb1fa..707c6f59 100644 --- a/src/core/dm/anjay_dm_execute.c +++ b/src/core/dm/anjay_dm_execute.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_execute.h b/src/core/dm/anjay_dm_execute.h index f7881c51..fdb0711b 100644 --- a/src/core/dm/anjay_dm_execute.h +++ b/src/core/dm/anjay_dm_execute.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_handlers.c b/src/core/dm/anjay_dm_handlers.c index 9c35f110..bd77a646 100644 --- a/src/core/dm/anjay_dm_handlers.c +++ b/src/core/dm/anjay_dm_handlers.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -20,6 +20,9 @@ #ifdef ANJAY_WITH_ATTR_STORAGE # include "../attr_storage/anjay_attr_storage.h" #endif // ANJAY_WITH_ATTR_STORAGE +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include "anjay_modules/anjay_lwm2m_gateway.h" +#endif // ANJAY_WITH_LWM2M_GATEWAY VISIBILITY_SOURCE_BEGIN @@ -692,8 +695,9 @@ int _anjay_dm_call_object_read_default_attrs( const anjay_dm_installed_object_t *obj_ptr, anjay_ssid_t ssid, anjay_dm_oi_attributes_t *out) { - dm_log(TRACE, _("object_read_default_attrs ") "/%u", - _anjay_dm_installed_object_oid(obj_ptr)); + dm_log(TRACE, _("object_read_default_attrs ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr)); CHECKED_TAIL_CALL_HANDLER(obj_ptr, object_read_default_attrs, anjay, *obj_ptr, ssid, out); } @@ -703,8 +707,9 @@ int _anjay_dm_call_object_write_default_attrs( const anjay_dm_installed_object_t *obj_ptr, anjay_ssid_t ssid, const anjay_dm_oi_attributes_t *attrs) { - dm_log(TRACE, _("object_write_default_attrs ") "/%u", - _anjay_dm_installed_object_oid(obj_ptr)); + dm_log(TRACE, _("object_write_default_attrs ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr)); CHECKED_TAIL_CALL_HANDLER(obj_ptr, object_write_default_attrs, anjay, *obj_ptr, ssid, attrs); } @@ -712,16 +717,19 @@ int _anjay_dm_call_object_write_default_attrs( int _anjay_dm_call_list_instances(anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr, anjay_unlocked_dm_list_ctx_t *ctx) { - dm_log(TRACE, _("list_instances ") "/%u", - _anjay_dm_installed_object_oid(obj_ptr)); + dm_log(TRACE, _("list_instances ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr)); CHECKED_TAIL_CALL_HANDLER(obj_ptr, list_instances, anjay, *obj_ptr, ctx); } int _anjay_dm_call_instance_reset(anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr, anjay_iid_t iid) { - dm_log(TRACE, _("instance_reset ") "/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid); + dm_log(TRACE, _("instance_reset ") DM_LOG_PREFIX "/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid); int result = _anjay_dm_transaction_include_object(anjay, obj_ptr); if (result) { return result; @@ -732,8 +740,10 @@ int _anjay_dm_call_instance_reset(anjay_unlocked_t *anjay, int _anjay_dm_call_instance_create(anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr, anjay_iid_t iid) { - dm_log(TRACE, _("instance_create ") "/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid); + dm_log(TRACE, _("instance_create ") DM_LOG_PREFIX "/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid); int result = _anjay_dm_transaction_include_object(anjay, obj_ptr); if (result) { return result; @@ -744,8 +754,10 @@ int _anjay_dm_call_instance_create(anjay_unlocked_t *anjay, int _anjay_dm_call_instance_remove(anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr, anjay_iid_t iid) { - dm_log(TRACE, _("instance_remove ") "/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid); + dm_log(TRACE, _("instance_remove ") DM_LOG_PREFIX "/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid); int result = _anjay_dm_transaction_include_object(anjay, obj_ptr); if (result) { return result; @@ -759,8 +771,10 @@ int _anjay_dm_call_instance_read_default_attrs( anjay_iid_t iid, anjay_ssid_t ssid, anjay_dm_oi_attributes_t *out) { - dm_log(TRACE, _("instance_read_default_attrs ") "/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid); + dm_log(TRACE, _("instance_read_default_attrs ") DM_LOG_PREFIX "/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid); CHECKED_TAIL_CALL_HANDLER(obj_ptr, instance_read_default_attrs, anjay, *obj_ptr, iid, ssid, out); } @@ -771,8 +785,10 @@ int _anjay_dm_call_instance_write_default_attrs( anjay_iid_t iid, anjay_ssid_t ssid, const anjay_dm_oi_attributes_t *attrs) { - dm_log(TRACE, _("instance_write_default_attrs ") "/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid); + dm_log(TRACE, _("instance_write_default_attrs ") DM_LOG_PREFIX "/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid); CHECKED_TAIL_CALL_HANDLER(obj_ptr, instance_write_default_attrs, anjay, *obj_ptr, iid, ssid, attrs); } @@ -781,8 +797,10 @@ int _anjay_dm_call_list_resources(anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr, anjay_iid_t iid, anjay_unlocked_dm_resource_list_ctx_t *ctx) { - dm_log(TRACE, _("list_resources ") "/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid); + dm_log(TRACE, _("list_resources ") DM_LOG_PREFIX "/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid); CHECKED_TAIL_CALL_HANDLER(obj_ptr, list_resources, anjay, *obj_ptr, iid, ctx); } @@ -793,9 +811,15 @@ int _anjay_dm_call_resource_read(anjay_unlocked_t *anjay, anjay_rid_t rid, anjay_riid_t riid, anjay_unlocked_output_ctx_t *ctx) { - dm_log(LAZY_TRACE, _("resource_read ") "%s", - ANJAY_DEBUG_MAKE_PATH(&MAKE_RESOURCE_INSTANCE_PATH( - _anjay_dm_installed_object_oid(obj_ptr), iid, rid, riid))); + anjay_uri_path_t path = + MAKE_RESOURCE_INSTANCE_PATH(_anjay_dm_installed_object_oid(obj_ptr), + iid, rid, riid); +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (obj_ptr->prefix) { + strncpy(path.prefix, obj_ptr->prefix, sizeof(path.prefix)); + } +#endif // ANJAY_WITH_LWM2M_GATEWAY + dm_log(LAZY_TRACE, _("resource_read ") "%s", ANJAY_DEBUG_MAKE_PATH(&path)); CHECKED_TAIL_CALL_HANDLER(obj_ptr, resource_read, anjay, *obj_ptr, iid, rid, riid, ctx); } @@ -806,9 +830,15 @@ int _anjay_dm_call_resource_write(anjay_unlocked_t *anjay, anjay_rid_t rid, anjay_riid_t riid, anjay_unlocked_input_ctx_t *ctx) { - dm_log(LAZY_TRACE, _("resource_write ") "%s", - ANJAY_DEBUG_MAKE_PATH(&MAKE_RESOURCE_INSTANCE_PATH( - _anjay_dm_installed_object_oid(obj_ptr), iid, rid, riid))); + anjay_uri_path_t path = + MAKE_RESOURCE_INSTANCE_PATH(_anjay_dm_installed_object_oid(obj_ptr), + iid, rid, riid); +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (obj_ptr->prefix) { + strncpy(path.prefix, obj_ptr->prefix, sizeof(path.prefix)); + } +#endif // ANJAY_WITH_LWM2M_GATEWAY + dm_log(TRACE, _("resource_write ") "%s", ANJAY_DEBUG_MAKE_PATH(&path)); int result = _anjay_dm_transaction_include_object(anjay, obj_ptr); if (result) { return result; @@ -822,8 +852,10 @@ int _anjay_dm_call_resource_execute(anjay_unlocked_t *anjay, anjay_iid_t iid, anjay_rid_t rid, anjay_unlocked_execute_ctx_t *execute_ctx) { - dm_log(TRACE, _("resource_execute ") "/%u/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid, rid); + dm_log(TRACE, _("resource_execute ") DM_LOG_PREFIX "/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid, rid); CHECKED_TAIL_CALL_HANDLER(obj_ptr, resource_execute, anjay, *obj_ptr, iid, rid, execute_ctx); } @@ -832,8 +864,10 @@ int _anjay_dm_call_resource_reset(anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr, anjay_iid_t iid, anjay_rid_t rid) { - dm_log(TRACE, _("resource_reset ") "/%u/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid, rid); + dm_log(TRACE, _("resource_reset ") DM_LOG_PREFIX "/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid, rid); int result = _anjay_dm_transaction_include_object(anjay, obj_ptr); if (result) { return result; @@ -848,8 +882,10 @@ int _anjay_dm_call_list_resource_instances( anjay_iid_t iid, anjay_rid_t rid, anjay_unlocked_dm_list_ctx_t *ctx) { - dm_log(TRACE, _("list_resource_instances ") "/%u/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid, rid); + dm_log(TRACE, _("list_resource_instances ") DM_LOG_PREFIX "/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid, rid); if (!_anjay_dm_handler_implemented( obj_ptr, ANJAY_DM_HANDLER_list_resource_instances)) { dm_log(TRACE, @@ -868,8 +904,10 @@ int _anjay_dm_call_resource_read_attrs( anjay_rid_t rid, anjay_ssid_t ssid, anjay_dm_r_attributes_t *out) { - dm_log(TRACE, _("resource_read_attrs ") "/%u/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid, rid); + dm_log(TRACE, _("resource_read_attrs ") DM_LOG_PREFIX "/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid, rid); CHECKED_TAIL_CALL_HANDLER(obj_ptr, resource_read_attrs, anjay, *obj_ptr, iid, rid, ssid, out); } @@ -881,8 +919,10 @@ int _anjay_dm_call_resource_write_attrs( anjay_rid_t rid, anjay_ssid_t ssid, const anjay_dm_r_attributes_t *attrs) { - dm_log(TRACE, _("resource_write_attrs ") "/%u/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid, rid); + dm_log(TRACE, _("resource_write_attrs ") DM_LOG_PREFIX "/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid, rid); CHECKED_TAIL_CALL_HANDLER(obj_ptr, resource_write_attrs, anjay, *obj_ptr, iid, rid, ssid, attrs); } @@ -896,8 +936,11 @@ int _anjay_dm_call_resource_instance_read_attrs( anjay_riid_t riid, anjay_ssid_t ssid, anjay_dm_r_attributes_t *out) { - dm_log(TRACE, _("resource_instance_read_attrs ") "/%u/%u/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid, rid, riid); + dm_log(TRACE, + _("resource_instance_read_attrs ") DM_LOG_PREFIX "/%u/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid, rid, riid); CHECKED_TAIL_CALL_HANDLER(obj_ptr, resource_instance_read_attrs, anjay, *obj_ptr, iid, rid, riid, ssid, out); } @@ -910,8 +953,11 @@ int _anjay_dm_call_resource_instance_write_attrs( anjay_riid_t riid, anjay_ssid_t ssid, const anjay_dm_r_attributes_t *attrs) { - dm_log(TRACE, _("resource_instance_write_attrs ") "/%u/%u/%u/%u", - _anjay_dm_installed_object_oid(obj_ptr), iid, rid, riid); + dm_log(TRACE, + _("resource_instance_write_attrs ") DM_LOG_PREFIX "/%u/%u/%u/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr), + iid, rid, riid); CHECKED_TAIL_CALL_HANDLER(obj_ptr, resource_instance_write_attrs, anjay, *obj_ptr, iid, rid, riid, ssid, attrs); } @@ -920,29 +966,33 @@ int _anjay_dm_call_resource_instance_write_attrs( int _anjay_dm_call_transaction_begin( anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr) { - dm_log(TRACE, _("begin_object_transaction ") "/%u", - _anjay_dm_installed_object_oid(obj_ptr)); + dm_log(TRACE, _("begin_object_transaction ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr)); CHECKED_TAIL_CALL_HANDLER(obj_ptr, transaction_begin, anjay, *obj_ptr); } int _anjay_dm_call_transaction_validate( anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr) { - dm_log(TRACE, _("validate_object ") "/%u", - _anjay_dm_installed_object_oid(obj_ptr)); + dm_log(TRACE, _("validate_object ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr)); CHECKED_TAIL_CALL_HANDLER(obj_ptr, transaction_validate, anjay, *obj_ptr); } int _anjay_dm_call_transaction_commit( anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr) { - dm_log(TRACE, _("commit_object ") "/%u", - _anjay_dm_installed_object_oid(obj_ptr)); + dm_log(TRACE, _("commit_object ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr)); CHECKED_TAIL_CALL_HANDLER(obj_ptr, transaction_commit, anjay, *obj_ptr); } int _anjay_dm_call_transaction_rollback( anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr) { - dm_log(TRACE, _("rollback_object ") "/%u", - _anjay_dm_installed_object_oid(obj_ptr)); + dm_log(TRACE, _("rollback_object ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr)); CHECKED_TAIL_CALL_HANDLER(obj_ptr, transaction_rollback, anjay, *obj_ptr); } @@ -952,7 +1002,7 @@ avs_error_t _anjay_dm_transaction_begin(anjay_unlocked_t *anjay) { dm_log(TRACE, _("transaction_begin")); avs_error_t err = AVS_OK; #ifdef ANJAY_WITH_ATTR_STORAGE - err = _anjay_attr_storage_transaction_begin(anjay); + err = _anjay_attr_storage_transaction_begin(&anjay->attr_storage); #endif // ANJAY_WITH_ATTR_STORAGE if (avs_is_ok(err)) { ++anjay->transaction_state.depth; @@ -963,8 +1013,9 @@ avs_error_t _anjay_dm_transaction_begin(anjay_unlocked_t *anjay) { int _anjay_dm_transaction_include_object( anjay_unlocked_t *anjay, const anjay_dm_installed_object_t *obj_ptr) { - dm_log(TRACE, _("transaction_include_object ") "/%u", - _anjay_dm_installed_object_oid(obj_ptr)); + dm_log(TRACE, _("transaction_include_object ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj_ptr) + _anjay_dm_installed_object_oid(obj_ptr)); assert(anjay->transaction_state.depth > 0); AVS_LIST(const anjay_dm_installed_object_t *) *it; AVS_LIST_FOREACH_PTR(it, &anjay->transaction_state.objs_in_transaction) { @@ -981,6 +1032,15 @@ int _anjay_dm_transaction_include_object( } *new_entry = obj_ptr; AVS_LIST_INSERT(it, new_entry); +#if defined(ANJAY_WITH_LWM2M_GATEWAY) && defined(ANJAY_WITH_ATTR_STORAGE) + if (obj_ptr->prefix) { + anjay_attr_storage_t *as = NULL; + if (_anjay_lwm2m_gateway_prefix_to_as(anjay, obj_ptr->prefix, &as) + || avs_is_err(_anjay_attr_storage_transaction_begin(as))) { + return -1; + } + } +#endif // defined(ANJAY_WITH_LWM2M_GATEWAY) && defined(ANJAY_WITH_ATTR_STORAGE) int result = _anjay_dm_call_transaction_begin(anjay, obj_ptr); if (result) { // transaction_begin may have added new entries @@ -1001,14 +1061,15 @@ static int commit_or_rollback_object(anjay_unlocked_t *anjay, if (predicate) { if ((result = _anjay_dm_call_transaction_rollback(anjay, obj))) { dm_log(ERROR, - _("cannot rollback transaction on ") "/%u" _( - ", object may be left in undefined state"), - _anjay_dm_installed_object_oid(obj)); + _("cannot rollback transaction on ") DM_LOG_PREFIX + "/%u" _(", object may be left in undefined state"), + DM_LOG_PREFIX_OBJ_ARG(obj) + _anjay_dm_installed_object_oid(obj)); return result; } } else if ((result = _anjay_dm_call_transaction_commit(anjay, obj))) { - dm_log(ERROR, _("cannot commit transaction on ") "/%u", - _anjay_dm_installed_object_oid(obj)); + dm_log(ERROR, _("cannot commit transaction on ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj)); predicate = result; } return predicate; @@ -1018,12 +1079,14 @@ int _anjay_dm_transaction_validate(anjay_unlocked_t *anjay) { dm_log(TRACE, _("transaction_validate")); AVS_LIST(const anjay_dm_installed_object_t *) obj; AVS_LIST_FOREACH(obj, anjay->transaction_state.objs_in_transaction) { - dm_log(TRACE, _("validate_object ") "/%u", - _anjay_dm_installed_object_oid(*obj)); + dm_log(TRACE, _("validate_object ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(*obj) + _anjay_dm_installed_object_oid(*obj)); int result = _anjay_dm_call_transaction_validate(anjay, *obj); if (result) { - dm_log(ERROR, _("Validation failed for ") "/%u", - _anjay_dm_installed_object_oid(*obj)); + dm_log(ERROR, _("Validation failed for ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_OBJ_ARG(*obj) + _anjay_dm_installed_object_oid(*obj)); return result; } } @@ -1037,6 +1100,11 @@ int _anjay_dm_transaction_finish_without_validation(anjay_unlocked_t *anjay, if (--anjay->transaction_state.depth != 0) { return result; } + +#if defined(ANJAY_WITH_LWM2M_GATEWAY) && defined(ANJAY_WITH_ATTR_STORAGE) + AVS_LIST(anjay_attr_storage_t *) affected_end_devs_attr_storages = NULL; +#endif // defined(ANJAY_WITH_LWM2M_GATEWAY) && defined(ANJAY_WITH_ATTR_STORAGE) + int final_result = result; AVS_LIST_CLEAR(&anjay->transaction_state.objs_in_transaction) { int commit_result = commit_or_rollback_object( @@ -1044,14 +1112,57 @@ int _anjay_dm_transaction_finish_without_validation(anjay_unlocked_t *anjay, if (!final_result && commit_result) { final_result = commit_result; } +#if defined(ANJAY_WITH_LWM2M_GATEWAY) && defined(ANJAY_WITH_ATTR_STORAGE) + // add affected Attr Storages to a list, if they are not already there + const char *prefix = + (*anjay->transaction_state.objs_in_transaction)->prefix; + if (prefix) { + anjay_attr_storage_t *as = NULL; + if (_anjay_lwm2m_gateway_prefix_to_as(anjay, prefix, &as)) { + // object or end device deleted during transaction + continue; + } + bool found = false; + AVS_LIST(anjay_attr_storage_t *) it; + AVS_LIST_FOREACH(it, affected_end_devs_attr_storages) { + if (*it == as) { + found = true; + break; + } + } + if (!found) { + AVS_LIST(anjay_attr_storage_t *) attr_storage = + AVS_LIST_NEW_ELEMENT(anjay_attr_storage_t *); + if (!attr_storage) { + _anjay_log_oom(); + AVS_LIST_CLEAR(&affected_end_devs_attr_storages); + return -1; + } + *attr_storage = as; + AVS_LIST_APPEND(&affected_end_devs_attr_storages, attr_storage); + } + } +#endif // defined(ANJAY_WITH_LWM2M_GATEWAY) && defined(ANJAY_WITH_ATTR_STORAGE) } #ifdef ANJAY_WITH_ATTR_STORAGE if (!final_result) { - _anjay_attr_storage_transaction_commit(anjay); + _anjay_attr_storage_transaction_commit(&anjay->attr_storage); } else { - (void) _anjay_attr_storage_transaction_rollback(anjay); + (void) _anjay_attr_storage_transaction_rollback(anjay, + &anjay->attr_storage); } -#endif // ANJAY_WITH_ATTR_STORAGE +# ifdef ANJAY_WITH_LWM2M_GATEWAY + AVS_LIST_CLEAR(&affected_end_devs_attr_storages) { + if (!final_result) { + _anjay_attr_storage_transaction_commit( + *affected_end_devs_attr_storages); + } else { + (void) _anjay_attr_storage_transaction_rollback( + anjay, *affected_end_devs_attr_storages); + } + } +# endif // ANJAY_WITH_LWM2M_GATEWAY +#endif // ANJAY_WITH_ATTR_STORAGE return final_result; } diff --git a/src/core/dm/anjay_dm_read.c b/src/core/dm/anjay_dm_read.c index 93f2cc37..272f9f64 100644 --- a/src/core/dm/anjay_dm_read.c +++ b/src/core/dm/anjay_dm_read.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -13,6 +13,10 @@ #include +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +#endif // ANJAY_WITH_LWM2M_GATEWAY + #include "anjay_dm_read.h" #include "../anjay_access_utils_private.h" @@ -32,6 +36,11 @@ read_resource_instance_internal(anjay_unlocked_t *anjay, anjay_uri_path_t path = MAKE_RESOURCE_INSTANCE_PATH(_anjay_dm_installed_object_oid(obj), iid, rid, riid); +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (obj->prefix) { + strcpy(path.prefix, obj->prefix); + } +#endif // ANJAY_WITH_LWM2M_GATEWAY (void) ((result = _anjay_output_set_path(out_ctx, &path)) || (result = _anjay_dm_call_resource_read(anjay, obj, iid, rid, riid, out_ctx))); @@ -77,9 +86,10 @@ static int read_resource_instance_clb(anjay_unlocked_t *anjay, || result == ANJAY_ERR_NOT_FOUND) && !(result = _anjay_output_clear_path(out_ctx))) { dm_log(DEBUG, - "%s" _(" when attempted to read ") "/%u/%u/%u/%u" _( - ", skipping"), - AVS_COAP_CODE_STRING((uint8_t) -result), + "%s" _(" when attempted to read ") DM_LOG_PREFIX + "/%u/%u/%u/%u" _(", skipping"), + DM_LOG_PREFIX_OBJ_ARG(obj) + AVS_COAP_CODE_STRING((uint8_t) -result), _anjay_dm_installed_object_oid(obj), iid, rid, riid); } return result; @@ -93,6 +103,11 @@ static int read_multiple_resource(anjay_unlocked_t *anjay, int result; anjay_uri_path_t path = MAKE_RESOURCE_PATH(_anjay_dm_installed_object_oid(obj), iid, rid); +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (obj->prefix) { + strcpy(path.prefix, obj->prefix); + } +#endif // ANJAY_WITH_LWM2M_GATEWAY (void) ((result = _anjay_output_set_path(out_ctx, &path)) || (result = _anjay_output_start_aggregate(out_ctx)) || (result = _anjay_dm_foreach_resource_instance( @@ -114,6 +129,11 @@ static int read_resource_internal(anjay_unlocked_t *anjay, anjay_uri_path_t path = MAKE_RESOURCE_PATH(_anjay_dm_installed_object_oid(obj), iid, rid); +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (obj->prefix) { + strcpy(path.prefix, obj->prefix); + } +#endif // ANJAY_WITH_LWM2M_GATEWAY (void) ((result = _anjay_output_set_path(out_ctx, &path)) || (result = _anjay_dm_call_resource_read( anjay, obj, iid, rid, ANJAY_ID_INVALID, out_ctx))); @@ -128,8 +148,9 @@ static int read_resource(anjay_unlocked_t *anjay, anjay_dm_resource_kind_t kind, anjay_unlocked_output_ctx_t *out_ctx) { if (!_anjay_dm_res_kind_readable(kind)) { - dm_log(DEBUG, "/%u/%u/%u" _(" is not readable"), - _anjay_dm_installed_object_oid(obj), iid, rid); + dm_log(DEBUG, DM_LOG_PREFIX "/%u/%u/%u" _(" is not readable"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid, rid); return ANJAY_ERR_METHOD_NOT_ALLOWED; } return read_resource_internal(anjay, obj, iid, rid, kind, out_ctx); @@ -150,8 +171,9 @@ static int read_instance_resource_clb(anjay_unlocked_t *anjay, read_instance_resource_clb_args_t *args = (read_instance_resource_clb_args_t *) args_; if (presence == ANJAY_DM_RES_ABSENT) { - dm_log(DEBUG, "/%u/%u/%u" _(" is not present, skipping"), - _anjay_dm_installed_object_oid(obj), iid, rid); + dm_log(DEBUG, DM_LOG_PREFIX "/%u/%u/%u" _(" is not present, skipping"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid, rid); return 0; } bool read_allowed = _anjay_dm_res_kind_readable(kind); @@ -160,8 +182,9 @@ static int read_instance_resource_clb(anjay_unlocked_t *anjay, || _anjay_dm_res_kind_writable(kind); } if (!read_allowed) { - dm_log(DEBUG, "/%u/%u/%u" _(" is not readable, skipping"), - _anjay_dm_installed_object_oid(obj), iid, rid); + dm_log(DEBUG, DM_LOG_PREFIX "/%u/%u/%u" _(" is not readable, skipping"), + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid, rid); return 0; } @@ -171,9 +194,11 @@ static int read_instance_resource_clb(anjay_unlocked_t *anjay, || result == ANJAY_ERR_NOT_FOUND) && !(result = _anjay_output_clear_path(args->out_ctx))) { dm_log(DEBUG, - "%s" _(" when attempted to read ") "/%u/%u/%u" _(", skipping"), + "%s" _(" when attempted to read ") DM_LOG_PREFIX + "/%u/%u/%u" _(", skipping"), AVS_COAP_CODE_STRING((uint8_t) -result), - _anjay_dm_installed_object_oid(obj), iid, rid); + DM_LOG_PREFIX_OBJ_ARG(obj) _anjay_dm_installed_object_oid(obj), + iid, rid); } return result; } @@ -186,6 +211,11 @@ static int read_instance(anjay_unlocked_t *anjay, int result; anjay_uri_path_t path = MAKE_INSTANCE_PATH(_anjay_dm_installed_object_oid(obj), iid); +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (obj->prefix) { + strcpy(path.prefix, obj->prefix); + } +#endif // ANJAY_WITH_LWM2M_GATEWAY (void) ((result = _anjay_output_set_path(out_ctx, &path)) || (result = _anjay_output_start_aggregate(out_ctx)) || (result = _anjay_dm_foreach_resource( @@ -209,6 +239,9 @@ static int read_instance_clb(anjay_unlocked_t *anjay, void *args_) { read_instance_clb_args_t *args = (read_instance_clb_args_t *) args_; anjay_action_info_t info = { +#ifdef ANJAY_WITH_LWM2M_GATEWAY + .end_device = _anjay_uri_path_has_prefix(&args->uri), +#endif // ANJAY_WITH_LWM2M_GATEWAY .oid = args->uri.ids[ANJAY_ID_OID], .iid = iid, .ssid = args->requesting_ssid, @@ -271,6 +304,9 @@ int _anjay_dm_read(anjay_unlocked_t *anjay, } if (_anjay_uri_path_has(&path_info->uri, ANJAY_ID_IID)) { const anjay_action_info_t action_info = { +#ifdef ANJAY_WITH_LWM2M_GATEWAY + .end_device = _anjay_uri_path_has_prefix(&path_info->uri), +#endif // ANJAY_WITH_LWM2M_GATEWAY .iid = path_info->uri.ids[ANJAY_ID_IID], .oid = path_info->uri.ids[ANJAY_ID_OID], .ssid = requesting_ssid, @@ -395,8 +431,19 @@ int _anjay_dm_read_resource_into_ctx(anjay_unlocked_t *anjay, const anjay_uri_path_t *path, anjay_unlocked_output_ctx_t *ctx) { assert(_anjay_uri_path_leaf_is(path, ANJAY_ID_RID)); + const anjay_dm_t *dm; +#ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(path)) { + if (_anjay_lwm2m_gateway_prefix_to_dm(anjay, path->prefix, &dm)) { + return -1; + } + } else +#endif // ANJAY_WITH_LWM2M_GATEWAY + { + dm = &anjay->dm; + } const anjay_dm_installed_object_t *obj = - _anjay_dm_find_object_by_oid(&anjay->dm, path->ids[ANJAY_ID_OID]); + _anjay_dm_find_object_by_oid(dm, path->ids[ANJAY_ID_OID]); if (!obj) { dm_log(ERROR, _("unregistered Object ID: ") "%u", path->ids[ANJAY_ID_OID]); @@ -469,9 +516,19 @@ int _anjay_dm_read_resource_u32_array(anjay_unlocked_t *anjay, assert(_anjay_uri_path_leaf_is(path, ANJAY_ID_RID)); assert(out_array); assert(out_array_size_elements); - + const anjay_dm_t *dm; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(path)) { + if (_anjay_lwm2m_gateway_prefix_to_dm(anjay, path->prefix, &dm)) { + return -1; + } + } else +# endif // ANJAY_WITH_LWM2M_GATEWAY + { + dm = &anjay->dm; + } const anjay_dm_installed_object_t *obj = - _anjay_dm_find_object_by_oid(&anjay->dm, path->ids[ANJAY_ID_OID]); + _anjay_dm_find_object_by_oid(dm, path->ids[ANJAY_ID_OID]); if (!obj) { return -1; } @@ -610,6 +667,15 @@ int _anjay_dm_read_or_observe_composite(anjay_connection_ref_t connection, dm_log(DEBUG, _("Read Composite ") "%s", ANJAY_DEBUG_MAKE_PATH(&path)); +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(&path)) { + dm_log(ERROR, + _("Read Composite on End Devices DMs is not supported")); + result = ANJAY_ERR_METHOD_NOT_ALLOWED; + break; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY + const anjay_dm_installed_object_t *obj = NULL; if (_anjay_uri_path_has(&path, ANJAY_ID_OID)) { obj = _anjay_dm_find_object_by_oid(&anjay->dm, @@ -617,8 +683,10 @@ int _anjay_dm_read_or_observe_composite(anjay_connection_ref_t connection, if (!obj) { dm_log(DEBUG, - _("Object not found: ") "%u" _(", ignoring it"), - path.ids[ANJAY_ID_OID]); + _("Object not found: ") DM_LOG_PREFIX + "/%u" _(", ignoring it"), + DM_LOG_PREFIX_ARG(path.prefix) + path.ids[ANJAY_ID_OID]); continue; } } diff --git a/src/core/dm/anjay_dm_read.h b/src/core/dm/anjay_dm_read.h index d79744c4..37a51a80 100644 --- a/src/core/dm/anjay_dm_read.h +++ b/src/core/dm/anjay_dm_read.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_write.c b/src/core/dm/anjay_dm_write.c index eeff3eda..776d31f7 100644 --- a/src/core/dm/anjay_dm_write.c +++ b/src/core/dm/anjay_dm_write.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -92,10 +92,7 @@ static int write_resource_instance(anjay_unlocked_t *anjay, path->ids[ANJAY_ID_RIID], in_ctx); if (!result && notify_queue) { - result = _anjay_notify_queue_resource_change(notify_queue, - path->ids[ANJAY_ID_OID], - path->ids[ANJAY_ID_IID], - path->ids[ANJAY_ID_RID]); + result = _anjay_notify_queue_resource_change(notify_queue, path); } return result; } @@ -201,10 +198,7 @@ write_resource_and_move_to_next_entry(anjay_unlocked_t *anjay, is_array, in_ctx); } if (!result && notify_queue) { - result = _anjay_notify_queue_resource_change(notify_queue, - path->ids[ANJAY_ID_OID], - path->ids[ANJAY_ID_IID], - path->ids[ANJAY_ID_RID]); + result = _anjay_notify_queue_resource_change(notify_queue, path); } return result; } @@ -260,9 +254,8 @@ static int write_resource_raw(anjay_unlocked_t *anjay, result = _anjay_dm_transaction_finish(anjay, result); } if (result) { - anjay_log(DEBUG, _("writing to ") "/%u/%u/%u" _(" failed: ") "%d", - path.ids[ANJAY_ID_OID], path.ids[ANJAY_ID_IID], - path.ids[ANJAY_ID_RID], result); + anjay_log(DEBUG, _("writing to ") "%s" _(" failed: ") "%d", + ANJAY_DEBUG_MAKE_PATH(&path), result); } return result; } @@ -427,12 +420,23 @@ int _anjay_dm_write_composite(anjay_unlocked_t *anjay, result = ANJAY_ERR_BAD_REQUEST; goto finish; } + +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(&path)) { + dm_log(ERROR, + _("Write Composite on End Devices DMs is not supported")); + result = ANJAY_ERR_METHOD_NOT_ALLOWED; + goto finish; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY + const anjay_dm_installed_object_t *obj = _anjay_dm_find_object_by_oid(&anjay->dm, path.ids[ANJAY_ID_OID]); if (!obj) { - dm_log(DEBUG, _("Object not found: ") "%u", path.ids[ANJAY_ID_OID]); + dm_log(DEBUG, _("Object not found: ") DM_LOG_PREFIX "/%u", + DM_LOG_PREFIX_ARG(path.prefix) path.ids[ANJAY_ID_OID]); result = ANJAY_ERR_NOT_FOUND; goto finish; } diff --git a/src/core/dm/anjay_dm_write.h b/src/core/dm/anjay_dm_write.h index 8a82f611..a1736bc4 100644 --- a/src/core/dm/anjay_dm_write.h +++ b/src/core/dm/anjay_dm_write.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_write_attrs.c b/src/core/dm/anjay_dm_write_attrs.c index 8d90ff11..c0dd259b 100644 --- a/src/core/dm/anjay_dm_write_attrs.c +++ b/src/core/dm/anjay_dm_write_attrs.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_dm_write_attrs.h b/src/core/dm/anjay_dm_write_attrs.h index 29afecf9..0ba1ff3f 100644 --- a/src/core/dm/anjay_dm_write_attrs.h +++ b/src/core/dm/anjay_dm_write_attrs.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_modules.c b/src/core/dm/anjay_modules.c index 3df36f5d..c24db0b5 100644 --- a/src/core/dm/anjay_modules.c +++ b/src/core/dm/anjay_modules.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_query.c b/src/core/dm/anjay_query.c index cdeb90cf..dd4bae55 100644 --- a/src/core/dm/anjay_query.c +++ b/src/core/dm/anjay_query.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/dm/anjay_query.h b/src/core/dm/anjay_query.h index 63eddb9c..4e69da61 100644 --- a/src/core/dm/anjay_query.h +++ b/src/core/dm/anjay_query.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/downloader/anjay_coap.c b/src/core/downloader/anjay_coap.c index 74d28ab9..4944a959 100644 --- a/src/core/downloader/anjay_coap.c +++ b/src/core/downloader/anjay_coap.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -68,6 +68,10 @@ typedef struct { avs_sched_handle_t job_start; bool aborting; bool reconnecting; + bool retry_in_progress; + size_t coap_downloader_retry_count; + size_t retry_count; + avs_time_duration_t coap_downloader_retry_delay; } anjay_coap_download_ctx_t; typedef struct { @@ -75,6 +79,9 @@ typedef struct { avs_net_socket_t *socket; } cleanup_coap_context_args_t; +static void suspend_coap_transfer(anjay_download_ctx_t *ctx_); +static avs_error_t sched_reconnect(anjay_coap_download_ctx_t *ctx); + static void cleanup_coap_context_unlocked(anjay_unlocked_t *anjay, cleanup_coap_context_args_t args) { _anjay_coap_ctx_cleanup(anjay, &args.coap_ctx); @@ -94,6 +101,7 @@ static void cleanup_coap_context(avs_sched_t *sched, const void *args) { static void cleanup_coap_transfer(AVS_LIST(anjay_download_ctx_t) *ctx_ptr) { anjay_coap_download_ctx_t *ctx = (anjay_coap_download_ctx_t *) *ctx_ptr; avs_sched_del(&ctx->job_start); + avs_sched_del(&ctx->common.reconnect_job_handle); _anjay_url_cleanup(&ctx->uri); if (ctx->common.same_socket_download) { @@ -131,6 +139,15 @@ static void cleanup_coap_transfer(AVS_LIST(anjay_download_ctx_t) *ctx_ptr) { &args, sizeof(args))) { cleanup_coap_context_unlocked(NULL, args); } + } else { +# ifndef ANJAY_TEST + /** + * HACK: if download is aborted between sched_reconnect() call and + * reconnect_job() execution coap context may not exist, in this case we + * need to cleanup socket here. + */ + _anjay_socket_cleanup(anjay, &ctx->socket); +# endif // ANJAY_TEST } AVS_LIST_DELETE(ctx_ptr); } @@ -252,6 +269,7 @@ handle_coap_response(avs_coap_ctx_t *ctx, _("transfer id = ") "%" PRIuPTR _(": ") "%lu" _( " B downloaded"), dl_ctx->common.id, (unsigned long) dl_ctx->bytes_downloaded); + dl_ctx->retry_count = 0; } break; } @@ -260,6 +278,25 @@ handle_coap_response(avs_coap_ctx_t *ctx, if (err.category == AVS_COAP_ERR_CATEGORY && err.code == AVS_COAP_ERR_ETAG_MISMATCH) { abort_download_transfer(dl_ctx, _anjay_download_status_expired()); + } else if (((err.category == AVS_COAP_ERR_CATEGORY + && err.code == AVS_COAP_ERR_TIMEOUT) + || err.category == AVS_ERRNO_CATEGORY) + && dl_ctx->retry_count + < dl_ctx->coap_downloader_retry_count) { + dl_ctx->retry_count++; + // shutdown the socket and cancel the exchange before reconnecting + suspend_coap_transfer((anjay_download_ctx_t *) dl_ctx); + if (dl_ctx->aborting) { + // suspend_coap_transfer() may abort the download + err = avs_errno(AVS_UNKNOWN_ERROR); + } else { + err = sched_reconnect(dl_ctx); + } + if (avs_is_err(err)) { + dl_log(ERROR, _("could not schedule download connect job")); + abort_download_transfer(dl_ctx, + _anjay_download_status_failed(err)); + } } else { abort_download_transfer(dl_ctx, _anjay_download_status_failed(err)); } @@ -267,7 +304,7 @@ handle_coap_response(avs_coap_ctx_t *ctx, } case AVS_COAP_CLIENT_REQUEST_CANCEL: dl_log(DEBUG, _("download request canceled")); - if (!dl_ctx->reconnecting) { + if (!dl_ctx->reconnecting && !dl_ctx->retry_in_progress) { abort_download_transfer(dl_ctx, _anjay_download_status_aborted()); } break; @@ -306,6 +343,7 @@ static void start_download_job(avs_sched_t *sched, const void *id_ptr) { anjay_coap_download_ctx_t *ctx = (anjay_coap_download_ctx_t *) *dl_ctx_ptr; ctx->reconnecting = false; + ctx->retry_in_progress = false; avs_error_t err; avs_coap_options_t options; @@ -420,7 +458,9 @@ static void suspend_coap_transfer(anjay_download_ctx_t *ctx_) { anjay_coap_download_ctx_t *ctx = (anjay_coap_download_ctx_t *) ctx_; dl_log(INFO, _("suspending download ") "%" PRIuPTR, ctx->common.id); ctx->reconnecting = true; + ctx->retry_in_progress = false; avs_sched_del(&ctx->job_start); + avs_sched_del(&ctx->common.reconnect_job_handle); if (avs_coap_exchange_id_valid(ctx->exchange_id)) { assert(ctx->coap); avs_coap_exchange_cancel(ctx->coap, ctx->exchange_id); @@ -457,7 +497,6 @@ static avs_error_t sched_start_download(anjay_coap_download_ctx_t *ctx) { static avs_error_t reconnect_coap_transfer(AVS_LIST(anjay_download_ctx_t) *ctx_ptr) { - (void) ctx_ptr; anjay_coap_download_ctx_t *ctx = (anjay_coap_download_ctx_t *) *ctx_ptr; ctx->reconnecting = true; @@ -477,7 +516,12 @@ reconnect_coap_transfer(AVS_LIST(anjay_download_ctx_t) *ctx_ptr) { dl_log(WARNING, _("could not connect socket for download id = ") "%" PRIuPTR, ctx->common.id); - return err; + if (ctx->retry_count < ctx->coap_downloader_retry_count) { + // Retry the download, err is reset to AVS_OK if sched_reconnect + // succeeds + ctx->retry_count++; + err = sched_reconnect(ctx); + } } else { // A new DTLS session requires resetting the CoAP context. // If we manage to resume the session, we can simply continue sending @@ -487,9 +531,37 @@ reconnect_coap_transfer(AVS_LIST(anjay_download_ctx_t) *ctx_ptr) { return err; } if (!avs_coap_exchange_id_valid(ctx->exchange_id)) { - return sched_start_download(ctx); + err = sched_start_download(ctx); } } + return err; +} + +static avs_error_t sched_reconnect(anjay_coap_download_ctx_t *ctx) { + anjay_unlocked_t *anjay = _anjay_downloader_get_anjay(ctx->common.dl); + ctx->retry_in_progress = true; + + dl_log(INFO, + _("retrying download ") "%" PRIuPTR _( + ", attempt number ") "%" PRIu64 _(", with delay ") "%s", + ctx->common.id, (uint64_t) ctx->retry_count, + AVS_TIME_DURATION_AS_STRING(ctx->coap_downloader_retry_delay)); + + if (ctx->common.reconnect_job_handle) { + return AVS_OK; + } + + if (AVS_SCHED_DELAYED(anjay->sched, &ctx->common.reconnect_job_handle, + ctx->coap_downloader_retry_delay, + _anjay_downloader_reconnect_job, &ctx->common.id, + sizeof(ctx->common.id))) { + dl_log(WARNING, + _("could not schedule reconnect job for id = ") "%" PRIuPTR, + ctx->common.id); + return avs_errno(AVS_ENOMEM); + } + + dl_log(DEBUG, _("scheduling reconnect ") "%" PRIuPTR, ctx->common.id); return AVS_OK; } @@ -507,6 +579,15 @@ static avs_error_t set_next_coap_block_offset(anjay_download_ctx_t *ctx_, return err; } +static bool is_socket_online_or_retry_in_progress(anjay_download_ctx_t *ctx_) { + anjay_coap_download_ctx_t *ctx = (anjay_coap_download_ctx_t *) ctx_; + if (ctx->retry_in_progress) { + return true; + } else { + return _anjay_socket_is_online(ctx->socket); + } +} + avs_error_t _anjay_downloader_coap_ctx_new(anjay_downloader_t *dl, AVS_LIST(anjay_download_ctx_t) *out_dl_ctx, @@ -537,9 +618,13 @@ _anjay_downloader_coap_ctx_new(anjay_downloader_t *dl, .cleanup = cleanup_coap_transfer, .suspend = suspend_coap_transfer, .reconnect = reconnect_coap_transfer, - .set_next_block_offset = set_next_coap_block_offset + .set_next_block_offset = set_next_coap_block_offset, + .is_socket_online_or_retry_in_progress = + is_socket_online_or_retry_in_progress }; ctx->common.vtable = &VTABLE; + ctx->coap_downloader_retry_count = anjay->coap_downloader_retry_count; + ctx->coap_downloader_retry_delay = anjay->coap_downloader_retry_delay; const anjay_transport_info_t *transport_info = _anjay_transport_info_by_uri_scheme(cfg->url); @@ -573,6 +658,7 @@ _anjay_downloader_coap_ctx_new(anjay_downloader_t *dl, : anjay->default_tls_ciphersuites, .backend_configuration = anjay->socket_config, .prng_ctx = anjay->prng_ctx.ctx, + .use_connection_id = anjay->use_connection_id, # ifdef ANJAY_WITH_LWM2M11 .server_name_indication = cfg->security_config.server_name_indication, diff --git a/src/core/downloader/anjay_downloader.c b/src/core/downloader/anjay_downloader.c index 9e1f3aca..932b8416 100644 --- a/src/core/downloader/anjay_downloader.c +++ b/src/core/downloader/anjay_downloader.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -381,7 +381,7 @@ void _anjay_downloader_suspend(anjay_downloader_t *dl, } } -static void reconnect_job(avs_sched_t *sched, const void *id_ptr) { +void _anjay_downloader_reconnect_job(avs_sched_t *sched, const void *id_ptr) { anjay_t *anjay_locked = _anjay_get_from_sched(sched); ANJAY_MUTEX_LOCK(anjay, anjay_locked); uintptr_t id = *(const uintptr_t *) id_ptr; @@ -404,8 +404,9 @@ static void reconnect_job(avs_sched_t *sched, const void *id_ptr) { int _anjay_downloader_sched_reconnect_ctx(anjay_download_ctx_t *ctx) { return AVS_SCHED_NOW(_anjay_downloader_get_anjay(ctx->common.dl)->sched, - &ctx->common.reconnect_job_handle, reconnect_job, - &ctx->common.id, sizeof(ctx->common.id)); + &ctx->common.reconnect_job_handle, + _anjay_downloader_reconnect_job, &ctx->common.id, + sizeof(ctx->common.id)); } int _anjay_downloader_sched_reconnect_by_handle( @@ -420,10 +421,9 @@ int _anjay_downloader_sched_reconnect_by_handle( return -1; } (*ctx_ptr)->common.administratively_suspended = false; - if (!(*ctx_ptr)->common.reconnect_job_handle - && _anjay_socket_transport_included( - _anjay_downloader_get_anjay(dl)->online_transports, - get_ctx_socket_transport(*ctx_ptr))) { + if (_anjay_socket_transport_included( + _anjay_downloader_get_anjay(dl)->online_transports, + get_ctx_socket_transport(*ctx_ptr))) { return _anjay_downloader_sched_reconnect_ctx(*ctx_ptr); } return 0; @@ -483,9 +483,8 @@ int _anjay_downloader_sched_reconnect_by_transports( int result = 0; AVS_LIST(anjay_download_ctx_t) ctx; AVS_LIST_FOREACH(ctx, dl->downloads) { - if (!ctx->common.reconnect_job_handle - && _anjay_socket_transport_included( - transport_set, get_ctx_socket_transport(ctx))) { + if (_anjay_socket_transport_included(transport_set, + get_ctx_socket_transport(ctx))) { int partial_result = _anjay_downloader_sched_reconnect_ctx(ctx); if (!result && partial_result) { result = partial_result; @@ -499,12 +498,34 @@ int _anjay_downloader_sync_online_transports(anjay_downloader_t *dl) { int result = 0; AVS_LIST(anjay_download_ctx_t) ctx; AVS_LIST_FOREACH(ctx, dl->downloads) { - if (!ctx->common.reconnect_job_handle - && _anjay_socket_transport_included( - _anjay_downloader_get_anjay(dl)->online_transports, - get_ctx_socket_transport(ctx)) - != _anjay_socket_is_online( - get_ctx_socket(ctx))) { + + /** + * This condition implements the XOR logic; + * if the downloader transport is not included in the + * online_transports while the socket is online, or if the + * downloader transport is included in the online_transports + * while the socket is offline, then call + * _anjay_downloader_sched_reconnect_ctx() to synchronize + * the downloader transport and suspend or reconnect the + * download. + */ + if (_anjay_socket_transport_included( + _anjay_downloader_get_anjay(dl)->online_transports, + get_ctx_socket_transport(ctx)) + /** + * The reason why we need a callback here instead + * of a simple call to _anjay_socket_is_online() + * is that there is an additional mechanism to + * handle CoAP downloader retries (the user can + * enable it by modifying the + * coap_downloader_retry_count variable). For + * example, when Anjay enters offline mode, the + * suspend callback should be called if a retry + * is in progress - even if the socket is already + * offline - to cancel any scheduled retry job. + */ + != ctx->common.vtable->is_socket_online_or_retry_in_progress( + ctx)) { int partial_result = _anjay_downloader_sched_reconnect_ctx(ctx); if (!result && partial_result) { result = partial_result; diff --git a/src/core/downloader/anjay_http.c b/src/core/downloader/anjay_http.c index a990f93e..2ef4803a 100644 --- a/src/core/downloader/anjay_http.c +++ b/src/core/downloader/anjay_http.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -529,6 +529,10 @@ static avs_error_t http_ssl_pre_connect_cb(avs_http_t *http, }); } +static bool is_socket_online_or_retry_in_progress(anjay_download_ctx_t *ctx_) { + return _anjay_socket_is_online(get_http_socket(ctx_)); +} + avs_error_t _anjay_downloader_http_ctx_new(anjay_downloader_t *dl, AVS_LIST(anjay_download_ctx_t) *out_dl_ctx, @@ -559,7 +563,9 @@ _anjay_downloader_http_ctx_new(anjay_downloader_t *dl, .cleanup = cleanup_http_transfer, .suspend = suspend_http_transfer, .reconnect = reconnect_http_transfer, - .set_next_block_offset = set_next_http_block_offset + .set_next_block_offset = set_next_http_block_offset, + .is_socket_online_or_retry_in_progress = + is_socket_online_or_retry_in_progress }; ctx->common.vtable = &VTABLE; diff --git a/src/core/downloader/anjay_private.h b/src/core/downloader/anjay_private.h index 7095f236..f3446d99 100644 --- a/src/core/downloader/anjay_private.h +++ b/src/core/downloader/anjay_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -30,6 +30,8 @@ typedef struct { avs_error_t (*reconnect)(AVS_LIST(anjay_download_ctx_t) *ctx_ptr); avs_error_t (*set_next_block_offset)(anjay_download_ctx_t *ctx, size_t next_block_offset); + bool (*is_socket_online_or_retry_in_progress)( + anjay_download_ctx_t *ctx_ptr); } anjay_download_ctx_vtable_t; typedef struct { @@ -59,6 +61,8 @@ _anjay_downloader_find_ctx_ptr_by_id(anjay_downloader_t *dl, uintptr_t id); void _anjay_downloader_abort_transfer(AVS_LIST(anjay_download_ctx_t) *ctx_ptr, anjay_download_status_t status); +void _anjay_downloader_reconnect_job(avs_sched_t *sched, const void *id_ptr); + int _anjay_downloader_sched_reconnect_ctx(anjay_download_ctx_t *ctx); avs_error_t diff --git a/src/core/io/anjay_base64_out.c b/src/core/io/anjay_base64_out.c index da39b082..fe1ed9b0 100644 --- a/src/core/io/anjay_base64_out.c +++ b/src/core/io/anjay_base64_out.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_base64_out.h b/src/core/io/anjay_base64_out.h index 87f59670..980dc8a6 100644 --- a/src/core/io/anjay_base64_out.h +++ b/src/core/io/anjay_base64_out.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_batch_builder.c b/src/core/io/anjay_batch_builder.c index a1445f02..bdc5550f 100644 --- a/src/core/io/anjay_batch_builder.c +++ b/src/core/io/anjay_batch_builder.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -776,12 +776,16 @@ int _anjay_batch_data_output_entry( } while (it && !_anjay_instance_action_allowed( - anjay, &(const anjay_action_info_t) { - .oid = it->path.ids[ANJAY_ID_OID], - .iid = it->path.ids[ANJAY_ID_IID], - .ssid = target_ssid, - .action = ANJAY_ACTION_READ - })) { + anjay, + &(const anjay_action_info_t) { +# ifdef ANJAY_WITH_LWM2M_GATEWAY + .end_device = _anjay_uri_path_has_prefix(&it->path), +# endif // ANJAY_WITH_LWM2M_GATEWAY + .oid = it->path.ids[ANJAY_ID_OID], + .iid = it->path.ids[ANJAY_ID_IID], + .ssid = target_ssid, + .action = ANJAY_ACTION_READ + })) { AVS_LIST_ADVANCE((AVS_LIST(anjay_batch_entry_t) *) (intptr_t) &it); } int result = 0; @@ -866,12 +870,17 @@ int _anjay_batch_outputable_item_count(anjay_unlocked_t *anjay, AVS_LIST_FOREACH(it, batch->list) { anjay_instance_action_allowed_stateless_result_t result = _anjay_instance_action_allowed_stateless( - anjay, &(const anjay_action_info_t) { - .oid = it->path.ids[ANJAY_ID_OID], - .iid = it->path.ids[ANJAY_ID_IID], - .ssid = target_ssid, - .action = ANJAY_ACTION_READ - }); + anjay, + &(const anjay_action_info_t) { +# ifdef ANJAY_WITH_LWM2M_GATEWAY + .end_device = + _anjay_uri_path_has_prefix(&it->path), +# endif // ANJAY_WITH_LWM2M_GATEWAY + .oid = it->path.ids[ANJAY_ID_OID], + .iid = it->path.ids[ANJAY_ID_IID], + .ssid = target_ssid, + .action = ANJAY_ACTION_READ + }); # ifdef ANJAY_WITH_ACCESS_CONTROL if (result == ANJAY_INSTANCE_ACTION_NEEDS_ACL_CHECK) { return -1; diff --git a/src/core/io/anjay_batch_builder.h b/src/core/io/anjay_batch_builder.h index 57753b33..83273377 100644 --- a/src/core/io/anjay_batch_builder.h +++ b/src/core/io/anjay_batch_builder.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_cbor_in.c b/src/core/io/anjay_cbor_in.c index 80be84ac..9a4cd1a3 100644 --- a/src/core/io/anjay_cbor_in.c +++ b/src/core/io/anjay_cbor_in.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_cbor_out.c b/src/core/io/anjay_cbor_out.c index 5b1ad426..d6ddfda7 100644 --- a/src/core/io/anjay_cbor_out.c +++ b/src/core/io/anjay_cbor_out.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_common.c b/src/core/io/anjay_common.c index 36dbf450..284a8e60 100644 --- a/src/core/io/anjay_common.c +++ b/src/core/io/anjay_common.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_common.h b/src/core/io/anjay_common.h index 9a4cebfd..fbbd58e5 100644 --- a/src/core/io/anjay_common.h +++ b/src/core/io/anjay_common.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_corelnk.c b/src/core/io/anjay_corelnk.c index b05f14a3..ca25cfa1 100644 --- a/src/core/io/anjay_corelnk.c +++ b/src/core/io/anjay_corelnk.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_corelnk.h b/src/core/io/anjay_corelnk.h index 611c0016..254ddb31 100644 --- a/src/core/io/anjay_corelnk.h +++ b/src/core/io/anjay_corelnk.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_dynamic.c b/src/core/io/anjay_dynamic.c index 3cb7a668..fe33ba69 100644 --- a/src/core/io/anjay_dynamic.c +++ b/src/core/io/anjay_dynamic.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_input_buf.c b/src/core/io/anjay_input_buf.c index 3d3f9d34..39a5b7dc 100644 --- a/src/core/io/anjay_input_buf.c +++ b/src/core/io/anjay_input_buf.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_json_encoder.c b/src/core/io/anjay_json_encoder.c index 4c9095e0..f7f9fc15 100644 --- a/src/core/io/anjay_json_encoder.c +++ b/src/core/io/anjay_json_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_json_like_decoder.c b/src/core/io/anjay_json_like_decoder.c index 4d75e3de..51f5749d 100644 --- a/src/core/io/anjay_json_like_decoder.c +++ b/src/core/io/anjay_json_like_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_json_like_decoder.h b/src/core/io/anjay_json_like_decoder.h index 35fce547..af36db10 100644 --- a/src/core/io/anjay_json_like_decoder.h +++ b/src/core/io/anjay_json_like_decoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_json_like_decoder_vtable.h b/src/core/io/anjay_json_like_decoder_vtable.h index 36f4c1dc..ea0f88cd 100644 --- a/src/core/io/anjay_json_like_decoder_vtable.h +++ b/src/core/io/anjay_json_like_decoder_vtable.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_opaque.c b/src/core/io/anjay_opaque.c index 803e64e6..8b6d1926 100644 --- a/src/core/io/anjay_opaque.c +++ b/src/core/io/anjay_opaque.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_output_buf.c b/src/core/io/anjay_output_buf.c index e8078ebb..347b4f35 100644 --- a/src/core/io/anjay_output_buf.c +++ b/src/core/io/anjay_output_buf.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_senml_in.c b/src/core/io/anjay_senml_in.c index d4a4db5e..656a3cc6 100644 --- a/src/core/io/anjay_senml_in.c +++ b/src/core/io/anjay_senml_in.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -29,6 +29,9 @@ # include "anjay_common.h" # include "anjay_vtable.h" +# ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +# endif // ANJAY_WITH_LWM2M_GATEWAY # include # include @@ -303,6 +306,23 @@ static int parse_absolute_path(anjay_uri_path_t *out_path, const char *input) { } const char *ch; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + bool is_prefix = false; + size_t prefix_len = 0; + for (ch = &input[1]; *ch != '/' && *ch; ch++, prefix_len++) { + if (!isdigit(*ch)) { + is_prefix = true; + } + } + if (is_prefix) { + if (prefix_len >= ANJAY_GATEWAY_MAX_PREFIX_LEN) { + return -1; + } + memcpy(out_path->prefix, &input[1], prefix_len); + assert(out_path->prefix[prefix_len] == '\0'); + input = ch; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY size_t curr_len = 0; for (ch = input; *ch;) { @@ -323,6 +343,13 @@ static int parse_absolute_path(anjay_uri_path_t *out_path, const char *input) { static bool uri_path_outside_base(const anjay_uri_path_t *path, const anjay_uri_path_t *base) { +# ifdef ANJAY_WITH_LWM2M_GATEWAY + bool base_set = _anjay_uri_path_length(base) > 0 + || _anjay_uri_path_has_prefix(base); + if (base_set && !_anjay_uri_path_prefix_equal(path, base)) { + return true; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY return _anjay_uri_path_outside_base(path, base); } diff --git a/src/core/io/anjay_senml_like_encoder.c b/src/core/io/anjay_senml_like_encoder.c index 2d3c5ff6..ec15f4e6 100644 --- a/src/core/io/anjay_senml_like_encoder.c +++ b/src/core/io/anjay_senml_like_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_senml_like_encoder.h b/src/core/io/anjay_senml_like_encoder.h index 59eb8928..b1bdca93 100644 --- a/src/core/io/anjay_senml_like_encoder.h +++ b/src/core/io/anjay_senml_like_encoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_senml_like_encoder_vtable.h b/src/core/io/anjay_senml_like_encoder_vtable.h index 81b0f1e8..4373afd8 100644 --- a/src/core/io/anjay_senml_like_encoder_vtable.h +++ b/src/core/io/anjay_senml_like_encoder_vtable.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_senml_like_out.c b/src/core/io/anjay_senml_like_out.c index 6781b493..d2b20b33 100644 --- a/src/core/io/anjay_senml_like_out.c +++ b/src/core/io/anjay_senml_like_out.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -27,6 +27,10 @@ # include "anjay_senml_like_encoder.h" # include "anjay_vtable.h" +# ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +# endif // ANJAY_WITH_LWM2M_GATEWAY + # define senml_log(level, ...) _anjay_log(senml_like_out, level, __VA_ARGS__) VISIBILITY_SOURCE_BEGIN @@ -51,6 +55,22 @@ static int path_to_string(const anjay_uri_path_t *path, size_t end_index, char *dest, size_t size) { +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(path)) { + if (start_index == 0) { + int written_chars = + avs_simple_snprintf(dest, size, "/%s", path->prefix); + if (written_chars < 0) { + return -1; + } + dest += written_chars; + size -= (size_t) written_chars; + } else { + start_index--; + } + end_index--; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY for (; start_index < end_index; start_index++) { int written_chars = avs_simple_snprintf(dest, size, "/%" PRIu16, path->ids[start_index]); @@ -65,6 +85,9 @@ static int path_to_string(const anjay_uri_path_t *path, static char *maybe_get_basename(senml_out_t *ctx, char *buf, size_t size) { size_t base_path_length = _anjay_uri_path_length(&ctx->base_path); +# ifdef ANJAY_WITH_LWM2M_GATEWAY + base_path_length += (size_t) _anjay_uri_path_has_prefix(&ctx->base_path); +# endif // ANJAY_WITH_LWM2M_GATEWAY char *retptr = NULL; if (!ctx->basename_written && base_path_length > 0) { *buf = '\0'; @@ -80,6 +103,10 @@ static char *maybe_get_basename(senml_out_t *ctx, char *buf, size_t size) { static char *maybe_get_name(senml_out_t *ctx, char *buf, size_t size) { size_t base_path_length = _anjay_uri_path_length(&ctx->base_path); size_t path_length = _anjay_uri_path_length(&ctx->path); +# ifdef ANJAY_WITH_LWM2M_GATEWAY + base_path_length += (size_t) _anjay_uri_path_has_prefix(&ctx->base_path); + path_length += (size_t) _anjay_uri_path_has_prefix(&ctx->path); +# endif // ANJAY_WITH_LWM2M_GATEWAY char *retptr = NULL; if (path_length > base_path_length) { *buf = '\0'; @@ -226,6 +253,12 @@ static int senml_ret_start_aggregate(anjay_unlocked_output_ctx_t *ctx_) { static bool uri_path_outside_base(const anjay_uri_path_t *path, const anjay_uri_path_t *base) { +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(base) + && !_anjay_uri_path_prefix_equal(path, base)) { + return true; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY return _anjay_uri_path_outside_base(path, base); } @@ -235,7 +268,11 @@ static int senml_set_path(anjay_unlocked_output_ctx_t *ctx_, AVS_ASSERT(!uri_path_outside_base(uri, &ctx->base_path), "Attempted to set path outside the context's base path. " "This is a bug in resource reading logic."); - if (_anjay_uri_path_length(&ctx->path) > 0) { + if (_anjay_uri_path_length(&ctx->path) > 0 +# ifdef ANJAY_WITH_LWM2M_GATEWAY + || _anjay_uri_path_has_prefix(&ctx->path) +# endif // ANJAY_WITH_LWM2M_GATEWAY + ) { senml_log(ERROR, _("Path already set")); return -1; } @@ -245,7 +282,11 @@ static int senml_set_path(anjay_unlocked_output_ctx_t *ctx_, static int senml_clear_path(anjay_unlocked_output_ctx_t *ctx_) { senml_out_t *ctx = (senml_out_t *) ctx_; - if (_anjay_uri_path_length(&ctx->path) == 0) { + if (_anjay_uri_path_length(&ctx->path) == 0 +# ifdef ANJAY_WITH_LWM2M_GATEWAY + && !_anjay_uri_path_has_prefix(&ctx->path) +# endif // ANJAY_WITH_LWM2M_GATEWAY + ) { senml_log(ERROR, _("Path not set")); return -1; } @@ -268,7 +309,11 @@ static int senml_output_close(anjay_unlocked_output_ctx_t *ctx_) { _anjay_update_ret(&result, _anjay_senml_like_encoder_cleanup(&ctx->encoder)); - if (_anjay_uri_path_length(&ctx->path) > 0) { + if (_anjay_uri_path_length(&ctx->path) > 0 +# ifdef ANJAY_WITH_LWM2M_GATEWAY + || _anjay_uri_path_has_prefix(&ctx->path) +# endif // ANJAY_WITH_LWM2M_GATEWAY + ) { _anjay_update_ret(&result, ANJAY_OUTCTXERR_ANJAY_RET_NOT_CALLED); } return result; diff --git a/src/core/io/anjay_text.c b/src/core/io/anjay_text.c index 63087a5c..2c75ccb0 100644 --- a/src/core/io/anjay_text.c +++ b/src/core/io/anjay_text.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_tlv.h b/src/core/io/anjay_tlv.h index dfc0d0cc..a1755ce6 100644 --- a/src/core/io/anjay_tlv.h +++ b/src/core/io/anjay_tlv.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_tlv_in.c b/src/core/io/anjay_tlv_in.c index 5fa7c61d..09fb47c2 100644 --- a/src/core/io/anjay_tlv_in.c +++ b/src/core/io/anjay_tlv_in.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_tlv_out.c b/src/core/io/anjay_tlv_out.c index bfe51c41..180b4ffb 100644 --- a/src/core/io/anjay_tlv_out.c +++ b/src/core/io/anjay_tlv_out.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/anjay_vtable.h b/src/core/io/anjay_vtable.h index 0d427d91..777cd1fe 100644 --- a/src/core/io/anjay_vtable.h +++ b/src/core/io/anjay_vtable.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/cbor/anjay_cbor_encoder_ll.c b/src/core/io/cbor/anjay_cbor_encoder_ll.c index 2fd4e28b..bd176224 100644 --- a/src/core/io/cbor/anjay_cbor_encoder_ll.c +++ b/src/core/io/cbor/anjay_cbor_encoder_ll.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/cbor/anjay_cbor_encoder_ll.h b/src/core/io/cbor/anjay_cbor_encoder_ll.h index ebbb632f..08ba8753 100644 --- a/src/core/io/cbor/anjay_cbor_encoder_ll.h +++ b/src/core/io/cbor/anjay_cbor_encoder_ll.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/cbor/anjay_cbor_types.h b/src/core/io/cbor/anjay_cbor_types.h index b2271ea9..20b461e6 100644 --- a/src/core/io/cbor/anjay_cbor_types.h +++ b/src/core/io/cbor/anjay_cbor_types.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/cbor/anjay_json_like_cbor_decoder.c b/src/core/io/cbor/anjay_json_like_cbor_decoder.c index 152c4dbc..4da9e388 100644 --- a/src/core/io/cbor/anjay_json_like_cbor_decoder.c +++ b/src/core/io/cbor/anjay_json_like_cbor_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/cbor/anjay_json_like_cbor_decoder.h b/src/core/io/cbor/anjay_json_like_cbor_decoder.h index d77e6e97..880c044a 100644 --- a/src/core/io/cbor/anjay_json_like_cbor_decoder.h +++ b/src/core/io/cbor/anjay_json_like_cbor_decoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -27,6 +27,27 @@ VISIBILITY_PRIVATE_HEADER_BEGIN */ #define MAX_SENML_CBOR_NEST_STACK_SIZE 3 +#ifdef ANJAY_WITH_LWM2M_GATEWAY +/** + * Compared to variant without support for LwM2M gateway: + * - the paths can be up to 5 components long, as they might contain a prefix + * which selects an end device, + * - the prefix is a string; it can be a key directly, or an initial element of + * an array key, + * - the prefix, if any, is the first component of a path, therefore only the + * root map can contain such keys. + * + * This means that: + * - the root map can be 5 levels deep now (so that's 1 more), + * - CBOR decoder's stack when parsing a key can grow by 2 levels now (array key + * with prefix as indefinite text string), but that is valid only for the root + * map, of which the maximum stack growth determined by inner maps will be + * larger anyway. + * + * Therefore, the maximum stack size is 1+1+1+1+2 = 6; + */ +# define MAX_LWM2M_CBOR_NEST_STACK_SIZE 6 +#else // ANJAY_WITH_LWM2M_GATEWAY /** * LwM2M CBOR is a tree of nested maps. Root map is up to 4 levels deep. This * happens in case there's a value of multi-instance resource, and key for each @@ -51,7 +72,8 @@ VISIBILITY_PRIVATE_HEADER_BEGIN * * Therefore, the maximum stack size is 1+1+1+2 = 5; */ -#define MAX_LWM2M_CBOR_NEST_STACK_SIZE 5 +# define MAX_LWM2M_CBOR_NEST_STACK_SIZE 5 +#endif // ANJAY_WITH_LWM2M_GATEWAY anjay_json_like_decoder_t *_anjay_cbor_decoder_new(avs_stream_t *stream, size_t max_nesting_depth); diff --git a/src/core/io/cbor/anjay_senml_cbor_encoder.c b/src/core/io/cbor/anjay_senml_cbor_encoder.c index 6c410f9f..165c1771 100644 --- a/src/core/io/cbor/anjay_senml_cbor_encoder.c +++ b/src/core/io/cbor/anjay_senml_cbor_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/json/anjay_json_decoder.c b/src/core/io/json/anjay_json_decoder.c index db4957ee..5ba228ae 100644 --- a/src/core/io/json/anjay_json_decoder.c +++ b/src/core/io/json/anjay_json_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/io/json/anjay_json_decoder.h b/src/core/io/json/anjay_json_decoder.h index 54381029..5fac8caf 100644 --- a/src/core/io/json/anjay_json_decoder.h +++ b/src/core/io/json/anjay_json_decoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/observe/anjay_observe_core.c b/src/core/observe/anjay_observe_core.c index b85161e7..59fc14e3 100644 --- a/src/core/observe/anjay_observe_core.c +++ b/src/core/observe/anjay_observe_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -19,6 +19,12 @@ # include # include +# ifdef ANJAY_WITH_LWM2M_GATEWAY +# include + +# include +# include +# endif // ANJAY_WITH_LWM2M_GATEWAY # include "../anjay_core.h" # include "../anjay_io_core.h" @@ -587,9 +593,20 @@ static int get_effective_attrs(anjay_unlocked_t *anjay, anjay_dm_r_attributes_t *out_attrs, const anjay_uri_path_t *path, anjay_ssid_t ssid) { + const anjay_dm_t *dm; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(path)) { + if (_anjay_lwm2m_gateway_prefix_to_dm(anjay, path->prefix, &dm)) { + return ANJAY_ERR_NOT_FOUND; + } + } else +# endif // ANJAY_WITH_LWM2M_GATEWAY + { + dm = &anjay->dm; + } anjay_dm_attrs_query_details_t details = { .obj = _anjay_uri_path_has(path, ANJAY_ID_OID) - ? _anjay_dm_find_object_by_oid(&anjay->dm, + ? _anjay_dm_find_object_by_oid(dm, path->ids[ANJAY_ID_OID]) : NULL, .iid = ANJAY_ID_INVALID, @@ -1193,7 +1210,18 @@ static int read_observation_path(anjay_unlocked_t *anjay, anjay_batch_t **out_batch) { const anjay_dm_installed_object_t *obj = NULL; if (_anjay_uri_path_has(path, ANJAY_ID_OID)) { - obj = _anjay_dm_find_object_by_oid(&anjay->dm, path->ids[ANJAY_ID_OID]); + const anjay_dm_t *dm; +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (_anjay_uri_path_has_prefix(path)) { + if (_anjay_lwm2m_gateway_prefix_to_dm(anjay, path->prefix, &dm)) { + return ANJAY_ERR_NOT_FOUND; + } + } else +# endif // ANJAY_WITH_LWM2M_GATEWAY + { + dm = &anjay->dm; + } + obj = _anjay_dm_find_object_by_oid(dm, path->ids[ANJAY_ID_OID]); } int result; anjay_dm_path_info_t path_info; @@ -1226,6 +1254,15 @@ static int read_observation_values(anjay_unlocked_t *anjay, size_t index = 0; AVS_LIST(const anjay_uri_path_t) path; AVS_LIST_FOREACH(path, paths->paths) { +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (action == ANJAY_ACTION_READ_COMPOSITE + && _anjay_uri_path_has_prefix(path)) { + dm_log(ERROR, _("Observe Composite on End Devices DMs is not " + "supported")); + result = ANJAY_ERR_METHOD_NOT_ALLOWED; + break; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY if ((result = read_observation_path(anjay, path, action, connection_ssid, timestamp, &(*out_batches)[index]))) { @@ -1237,6 +1274,15 @@ static int read_observation_values(anjay_unlocked_t *anjay, } case PATHS_POINTER_ARRAY: for (size_t index = 0; index < paths->count; ++index) { +# ifdef ANJAY_WITH_LWM2M_GATEWAY + if (action == ANJAY_ACTION_READ_COMPOSITE + && _anjay_uri_path_has_prefix(&paths->paths[index])) { + dm_log(ERROR, _("Observe Composite on End Devices DMs is not " + "supported")); + result = ANJAY_ERR_METHOD_NOT_ALLOWED; + break; + } +# endif // ANJAY_WITH_LWM2M_GATEWAY if ((result = read_observation_path( anjay, &paths->paths[index], action, connection_ssid, timestamp, &(*out_batches)[index]))) { @@ -1960,7 +2006,6 @@ observe_for_each_in_wildcard(anjay_observe_connection_entry_t *connection, anjay_uri_path_t path = *specimen_path; for (int i = wildcard_level; i < _ANJAY_URI_PATH_MAX_LENGTH; ++i) { path.ids[i] = ANJAY_ID_INVALID; - path.ids[i] = ANJAY_ID_INVALID; } return observe_for_each_in_bounds(connection, &path, &path, clb, clb_arg); } @@ -1985,7 +2030,7 @@ observe_for_each_in_wildcard(anjay_observe_connection_entry_t *connection, * ----------------------- * A wildcard for any type of ID is represented as the number 65535. The * registered observation entries for any given connection are stored in a - * sorted tree, with the sort key being (OID, IID, RID, RIID) - in + * sorted tree, with the sort key being ((prefix), OID, IID, RID, RIID) - in * lexicographical order over all elements of that tuple - much like C++11's * std::tuple comparison operators. * @@ -2095,32 +2140,31 @@ static int get_observe_status(anjay_observe_connection_entry_t *connection, } anjay_resource_observation_status_t -_anjay_observe_status(anjay_unlocked_t *anjay, - anjay_oid_t oid, - anjay_iid_t iid, - anjay_rid_t rid) { - assert(oid != ANJAY_ID_INVALID); - assert(iid != ANJAY_ID_INVALID); - assert(rid != ANJAY_ID_INVALID); +_anjay_observe_status(anjay_unlocked_t *anjay, const anjay_uri_path_t *path) { + assert(path); + assert(path->ids[0] != ANJAY_ID_INVALID); + assert(path->ids[1] != ANJAY_ID_INVALID); + assert(path->ids[2] != ANJAY_ID_INVALID); anjay_resource_observation_status_t result = { .is_observed = false, .min_period = ANJAY_ATTRIB_INTEGER_NONE, .max_eval_period = ANJAY_ATTRIB_INTEGER_NONE }; + AVS_LIST(anjay_observe_connection_entry_t) connection; AVS_LIST_FOREACH(connection, anjay->observe.connection_entries) { - int retval = - observe_for_each_matching(connection, - &MAKE_RESOURCE_PATH(oid, iid, rid), - get_observe_status, &result); + int retval = observe_for_each_matching(connection, path, + get_observe_status, &result); assert(!retval); (void) retval; } + result.min_period = AVS_MAX(result.min_period, 0); return result; } + # endif // ANJAY_WITH_OBSERVATION_STATUS # ifdef ANJAY_TEST diff --git a/src/core/observe/anjay_observe_core.h b/src/core/observe/anjay_observe_core.h index 28c9d3a8..cbb5d6d4 100644 --- a/src/core/observe/anjay_observe_core.h +++ b/src/core/observe/anjay_observe_core.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -90,10 +90,7 @@ int _anjay_observe_notify(anjay_unlocked_t *anjay, # ifdef ANJAY_WITH_OBSERVATION_STATUS anjay_resource_observation_status_t -_anjay_observe_status(anjay_unlocked_t *anjay, - anjay_oid_t oid, - anjay_iid_t iid, - anjay_rid_t rid); +_anjay_observe_status(anjay_unlocked_t *anjay, const anjay_uri_path_t *path); # endif // ANJAY_WITH_OBSERVATION_STATUS #else // ANJAY_WITH_OBSERVE diff --git a/src/core/observe/anjay_observe_internal.h b/src/core/observe/anjay_observe_internal.h index c01f4051..2e60ebf7 100644 --- a/src/core/observe/anjay_observe_internal.h +++ b/src/core/observe/anjay_observe_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/observe/anjay_observe_planning.c b/src/core/observe/anjay_observe_planning.c index 4234b2ed..48576873 100644 --- a/src/core/observe/anjay_observe_planning.c +++ b/src/core/observe/anjay_observe_planning.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_activate.c b/src/core/servers/anjay_activate.c index 41b0254b..5c2cb783 100644 --- a/src/core/servers/anjay_activate.c +++ b/src/core/servers/anjay_activate.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_activate.h b/src/core/servers/anjay_activate.h index dfdb9bc4..2186eedc 100644 --- a/src/core/servers/anjay_activate.h +++ b/src/core/servers/anjay_activate.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_connection_ip.c b/src/core/servers/anjay_connection_ip.c index 9c245bac..511d8350 100644 --- a/src/core/servers/anjay_connection_ip.c +++ b/src/core/servers/anjay_connection_ip.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_connections.c b/src/core/servers/anjay_connections.c index 69ce468d..65a67d2d 100644 --- a/src/core/servers/anjay_connections.c +++ b/src/core/servers/anjay_connections.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_connections.h b/src/core/servers/anjay_connections.h index a78bb4bc..88f08635 100644 --- a/src/core/servers/anjay_connections.h +++ b/src/core/servers/anjay_connections.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_connections_internal.h b/src/core/servers/anjay_connections_internal.h index 8f568dcc..95740269 100644 --- a/src/core/servers/anjay_connections_internal.h +++ b/src/core/servers/anjay_connections_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_register.c b/src/core/servers/anjay_register.c index e8300f97..dcb2900d 100644 --- a/src/core/servers/anjay_register.c +++ b/src/core/servers/anjay_register.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_register.h b/src/core/servers/anjay_register.h index 94ea0fed..28328d2d 100644 --- a/src/core/servers/anjay_register.h +++ b/src/core/servers/anjay_register.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_reload.c b/src/core/servers/anjay_reload.c index 659c29da..fc2b2df5 100644 --- a/src/core/servers/anjay_reload.c +++ b/src/core/servers/anjay_reload.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_security.h b/src/core/servers/anjay_security.h index c8b5a4d7..6a5c2a74 100644 --- a/src/core/servers/anjay_security.h +++ b/src/core/servers/anjay_security.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_security_generic.c b/src/core/servers/anjay_security_generic.c index fc2eba28..edc8c658 100644 --- a/src/core/servers/anjay_security_generic.c +++ b/src/core/servers/anjay_security_generic.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_server_connections.c b/src/core/servers/anjay_server_connections.c index 110f5b1b..214c0b5e 100644 --- a/src/core/servers/anjay_server_connections.c +++ b/src/core/servers/anjay_server_connections.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_server_connections.h b/src/core/servers/anjay_server_connections.h index 44aebb57..d6bd30cf 100644 --- a/src/core/servers/anjay_server_connections.h +++ b/src/core/servers/anjay_server_connections.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_servers_internal.c b/src/core/servers/anjay_servers_internal.c index 2c3064c2..3e90a58f 100644 --- a/src/core/servers/anjay_servers_internal.c +++ b/src/core/servers/anjay_servers_internal.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/core/servers/anjay_servers_internal.h b/src/core/servers/anjay_servers_internal.h index 346c84b9..84c6b02c 100644 --- a/src/core/servers/anjay_servers_internal.h +++ b/src/core/servers/anjay_servers_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/access_control/anjay_access_control_handlers.c b/src/modules/access_control/anjay_access_control_handlers.c index 3d0ec19d..a108f9b6 100644 --- a/src/modules/access_control/anjay_access_control_handlers.c +++ b/src/modules/access_control/anjay_access_control_handlers.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/access_control/anjay_access_control_persistence.c b/src/modules/access_control/anjay_access_control_persistence.c index 258dc980..4426f23e 100644 --- a/src/modules/access_control/anjay_access_control_persistence.c +++ b/src/modules/access_control/anjay_access_control_persistence.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/access_control/anjay_mod_access_control.c b/src/modules/access_control/anjay_mod_access_control.c index ce2e77a8..2dea12e6 100644 --- a/src/modules/access_control/anjay_mod_access_control.c +++ b/src/modules/access_control/anjay_mod_access_control.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -81,8 +81,9 @@ static int add_instances_without_iids( if (!*insert_ptr || proposed_iid < (*insert_ptr)->iid) { if (out_dm_changes) { int result = _anjay_notify_queue_instance_created( - out_dm_changes, ANJAY_DM_OID_ACCESS_CONTROL, - proposed_iid); + out_dm_changes, + &MAKE_INSTANCE_PATH(ANJAY_DM_OID_ACCESS_CONTROL, + proposed_iid)); if (result) { return result; } @@ -127,7 +128,8 @@ int _anjay_access_control_add_instance( int result = 0; if (out_dm_changes) { result = _anjay_notify_queue_instance_created( - out_dm_changes, ANJAY_DM_OID_ACCESS_CONTROL, instance->iid); + out_dm_changes, &MAKE_INSTANCE_PATH(ANJAY_DM_OID_ACCESS_CONTROL, + instance->iid)); } if (!result) { AVS_LIST_INSERT(ptr, instance); diff --git a/src/modules/access_control/anjay_mod_access_control.h b/src/modules/access_control/anjay_mod_access_control.h index a6a495e3..274090e7 100644 --- a/src/modules/access_control/anjay_mod_access_control.h +++ b/src/modules/access_control/anjay_mod_access_control.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/advanced_fw_update/anjay_advanced_fw_update.c b/src/modules/advanced_fw_update/anjay_advanced_fw_update.c index 004425d8..6444646b 100644 --- a/src/modules/advanced_fw_update/anjay_advanced_fw_update.c +++ b/src/modules/advanced_fw_update/anjay_advanced_fw_update.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -182,7 +182,8 @@ static void perform_lwm2m_send(anjay_unlocked_t *anjay, return; } if (_anjay_send_batch_data_add_current_multiple_unlocked( - batch_builder, anjay, paths, paths_len, true)) { + batch_builder, anjay, ANJAY_ID_INVALID, paths, paths_len, + true)) { fw_log(ERROR, _("failed to add data to batch")); anjay_send_batch_builder_cleanup(&batch_builder); return; diff --git a/src/modules/factory_provisioning/anjay_provisioning.c b/src/modules/factory_provisioning/anjay_provisioning.c index 6d8414b4..b01f8162 100644 --- a/src/modules/factory_provisioning/anjay_provisioning.c +++ b/src/modules/factory_provisioning/anjay_provisioning.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/fw_update/anjay_fw_update.c b/src/modules/fw_update/anjay_fw_update.c index 44b0fb12..33d61f1e 100644 --- a/src/modules/fw_update/anjay_fw_update.c +++ b/src/modules/fw_update/anjay_fw_update.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * @@ -155,7 +155,8 @@ static void perform_lwm2m_send(anjay_unlocked_t *anjay, } if (_anjay_send_batch_data_add_current_multiple_unlocked( - batch_builder, anjay, paths, paths_len, true)) { + batch_builder, anjay, ANJAY_ID_INVALID, paths, paths_len, + true)) { fw_log(ERROR, _("failed to add data to batch")); anjay_send_batch_builder_cleanup(&batch_builder); return; diff --git a/src/modules/ipso/anjay_ipso_3d_sensor.c b/src/modules/ipso/anjay_ipso_3d_sensor.c index d7e97022..1b7a557a 100644 --- a/src/modules/ipso/anjay_ipso_3d_sensor.c +++ b/src/modules/ipso/anjay_ipso_3d_sensor.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/ipso/anjay_ipso_basic_sensor.c b/src/modules/ipso/anjay_ipso_basic_sensor.c index d2c229b2..52faf3df 100644 --- a/src/modules/ipso/anjay_ipso_basic_sensor.c +++ b/src/modules/ipso/anjay_ipso_basic_sensor.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/ipso/anjay_ipso_button.c b/src/modules/ipso/anjay_ipso_button.c index befe1d9d..1eadae41 100644 --- a/src/modules/ipso/anjay_ipso_button.c +++ b/src/modules/ipso/anjay_ipso_button.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/ipso_v2/anjay_ipso_v2_3d_sensor.c b/src/modules/ipso_v2/anjay_ipso_v2_3d_sensor.c index e15e6b4d..d231ceb4 100644 --- a/src/modules/ipso_v2/anjay_ipso_v2_3d_sensor.c +++ b/src/modules/ipso_v2/anjay_ipso_v2_3d_sensor.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/ipso_v2/anjay_ipso_v2_basic_sensor.c b/src/modules/ipso_v2/anjay_ipso_v2_basic_sensor.c index 762bb013..1cbb52ac 100644 --- a/src/modules/ipso_v2/anjay_ipso_v2_basic_sensor.c +++ b/src/modules/ipso_v2/anjay_ipso_v2_basic_sensor.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/lwm2m_gateway/anjay_lwm2m_gateway.c b/src/modules/lwm2m_gateway/anjay_lwm2m_gateway.c new file mode 100644 index 00000000..c55ea6b6 --- /dev/null +++ b/src/modules/lwm2m_gateway/anjay_lwm2m_gateway.c @@ -0,0 +1,698 @@ +/* + * Copyright 2017-2025 AVSystem + * AVSystem Anjay LwM2M SDK + * All rights reserved. + * + * Licensed under the AVSystem-5-clause License. + * See the attached LICENSE file for details. + */ +#include + +#ifdef ANJAY_WITH_LWM2M_GATEWAY +# include +# include +# include +# include + +# include +# include +# include +# include +# include +# include + +# include +# include +# include +# include +# include + +# include "../../core/anjay_dm_core.h" +# include "../../core/attr_storage/anjay_attr_storage.h" +# include "../../core/io/anjay_corelnk.h" + +VISIBILITY_SOURCE_BEGIN + +# if !defined(ANJAY_WITH_LWM2M11) +# error "LwM2M Gateway requires LwM2M version 1.1 or above!" +# endif + +# define gw_log(level, ...) _anjay_log(lwm2m_gateway, level, __VA_ARGS__) + +/** + * Device ID: R, Single, Mandatory + * type: string, range: N/A, unit: N/A + * This resource identifies the IoT Device connected to the LwM2M + * Gateway. + */ +# define RID_DEVICE_ID 0 + +/** + * Prefix: R, Single, Mandatory + * type: string, range: N/A, unit: N/A + * This resource defines what prefix MUST be used for access to LwM2M + * Objects of this IoT Device. + */ +# define RID_PREFIX 1 + +/** + * IoT Device Objects: R, Single, Mandatory + * type: corelnk, range: N/A, unit: N/A + * This resource contains the Objects and Object Instances exposed by the + * LwM2M Gateway on behalf of the IoT Device. It uses the same CoreLnk + * format as Registration Interface. + */ +# define RID_IOT_DEVICE_OBJECTS 3 + +typedef struct lwm2m_gateway_instance_struct { + anjay_iid_t iid; + + const char *device_id; + char prefix[ANJAY_GATEWAY_MAX_PREFIX_LEN]; + anjay_dm_t dm; +# ifdef ANJAY_WITH_ATTR_STORAGE + anjay_attr_storage_t as; +# endif // ANJAY_WITH_ATTR_STORAGE +} lwm2m_gateway_instance_t; + +typedef struct lwm2m_gateway_object_struct { + anjay_dm_installed_object_t obj_def_ptr; + const anjay_unlocked_dm_object_def_t *obj_def; + + AVS_LIST(lwm2m_gateway_instance_t) instances; +} lwm2m_gateway_obj_t; + +static inline void +delete_instance(AVS_LIST(lwm2m_gateway_instance_t) *instances, + lwm2m_gateway_instance_t *inst) { + AVS_LIST(lwm2m_gateway_instance_t) *inst_ptr = + AVS_LIST_FIND_PTR(instances, inst); + AVS_LIST_DELETE(inst_ptr); +} + +static anjay_iid_t get_new_iid(AVS_LIST(lwm2m_gateway_instance_t) instances) { + anjay_iid_t iid = 0; + AVS_LIST(lwm2m_gateway_instance_t) it; + AVS_LIST_FOREACH(it, instances) { + if (it->iid == iid) { + ++iid; + } else if (it->iid > iid) { + break; + } + } + return iid; +} + +static inline lwm2m_gateway_instance_t *find_instance(lwm2m_gateway_obj_t *gw, + anjay_iid_t iid) { + AVS_LIST(lwm2m_gateway_instance_t) it; + AVS_LIST_FOREACH(it, gw->instances) { + if (it->iid == iid) { + return it; + } else if (it->iid > iid) { + break; + } + } + return NULL; +} + +static inline lwm2m_gateway_obj_t * +get_obj(const anjay_dm_installed_object_t *obj_ptr) { + return AVS_CONTAINER_OF(_anjay_dm_installed_object_get_unlocked(obj_ptr), + lwm2m_gateway_obj_t, obj_def); +} + +static int gateway_list_instances(anjay_unlocked_t *anjay, + const anjay_dm_installed_object_t obj_ptr, + anjay_unlocked_dm_list_ctx_t *ctx) { + (void) anjay; + + AVS_LIST(lwm2m_gateway_instance_t) it; + AVS_LIST_FOREACH(it, get_obj(&obj_ptr)->instances) { + _anjay_dm_emit_unlocked(ctx, it->iid); + } + + return 0; +} + +static int init_instance(lwm2m_gateway_instance_t *inst, anjay_iid_t iid) { + if (avs_simple_snprintf(inst->prefix, sizeof(inst->prefix), "dev%" PRIu16, + iid) + < (int) strlen("dev0")) { + return -1; + } + inst->iid = iid; + return 0; +} + +static lwm2m_gateway_instance_t * +gateway_instance_create(lwm2m_gateway_obj_t *gw, anjay_iid_t iid) { + assert(iid != ANJAY_ID_INVALID); + + AVS_LIST(lwm2m_gateway_instance_t) created = + AVS_LIST_NEW_ELEMENT(lwm2m_gateway_instance_t); + if (!created) { + _anjay_log_oom(); + return NULL; + } + if (init_instance(created, iid)) { + // failed, clean up newly added instance + delete_instance(&gw->instances, created); + return NULL; + } + +# ifdef ANJAY_WITH_ATTR_STORAGE + if (_anjay_attr_storage_init(&created->as, &created->dm)) { + delete_instance(&gw->instances, created); + return NULL; + } +# endif // ANJAY_WITH_ATTR_STORAGE + + AVS_LIST(lwm2m_gateway_instance_t) *ptr; + AVS_LIST_FOREACH_PTR(ptr, &gw->instances) { + if ((*ptr)->iid > created->iid) { + break; + } + } + + AVS_LIST_INSERT(ptr, created); + return created; +} + +static int gateway_list_resources(anjay_unlocked_t *anjay, + const anjay_dm_installed_object_t obj_ptr, + anjay_iid_t iid, + anjay_unlocked_dm_resource_list_ctx_t *ctx) { + (void) anjay; + + lwm2m_gateway_obj_t *gw = get_obj(&obj_ptr); + lwm2m_gateway_instance_t *inst = find_instance(gw, iid); + assert(inst); + + _anjay_dm_emit_res_unlocked(ctx, RID_DEVICE_ID, ANJAY_DM_RES_R, + ANJAY_DM_RES_PRESENT); + _anjay_dm_emit_res_unlocked(ctx, RID_PREFIX, ANJAY_DM_RES_R, + ANJAY_DM_RES_PRESENT); + _anjay_dm_emit_res_unlocked(ctx, RID_IOT_DEVICE_OBJECTS, ANJAY_DM_RES_R, + ANJAY_DM_RES_PRESENT); + return 0; +} + +static int gateway_resource_read(anjay_unlocked_t *anjay, + const anjay_dm_installed_object_t obj_ptr, + anjay_iid_t iid, + anjay_rid_t rid, + anjay_riid_t riid, + anjay_unlocked_output_ctx_t *ctx) { + (void) anjay; + + lwm2m_gateway_obj_t *gw = get_obj(&obj_ptr); + lwm2m_gateway_instance_t *inst = find_instance(gw, iid); + assert(inst); + + switch (rid) { + case RID_DEVICE_ID: { + assert(riid == ANJAY_ID_INVALID); + return _anjay_ret_string_unlocked(ctx, inst->device_id); + } + case RID_PREFIX: { + assert(riid == ANJAY_ID_INVALID); + return _anjay_ret_string_unlocked(ctx, inst->prefix); + } + case RID_IOT_DEVICE_OBJECTS: { + assert(riid == ANJAY_ID_INVALID); + int ret = 0; + char *dm_buffer = NULL; + // There is no chance to determine what is the LwM2M Version that the + // Anjay client registered with to the server, that is now performing + // this read (anjay_registration_info_t::lwm2m_version). Lets just + // assume version 1.1. + if (_anjay_corelnk_query_dm(anjay, &inst->dm, ANJAY_LWM2M_VERSION_1_1, + &dm_buffer)) { + return ANJAY_ERR_INTERNAL; + } + ret = _anjay_ret_string_unlocked(ctx, dm_buffer); + avs_free(dm_buffer); + return ret; + } + default: + return ANJAY_ERR_METHOD_NOT_ALLOWED; + } +} + +static const anjay_unlocked_dm_object_def_t LWM2M_GATEWAY = { + .oid = ANJAY_DM_OID_LWM2M_GATEWAY, + .version = "2.0", + .handlers = { + .list_instances = gateway_list_instances, + .list_resources = gateway_list_resources, + .resource_read = gateway_resource_read, + } +}; + +static void gateway_delete(void *lwm2m_gateway_) { + lwm2m_gateway_obj_t *gw = (lwm2m_gateway_obj_t *) lwm2m_gateway_; + + AVS_LIST_CLEAR(&gw->instances) { +# ifdef ANJAY_WITH_ATTR_STORAGE + _anjay_attr_storage_cleanup(&gw->instances->as); +# endif // ANJAY_WITH_ATTR_STORAGE + _anjay_dm_cleanup(&gw->instances->dm); + } +} + +int anjay_lwm2m_gateway_install(anjay_t *anjay_locked) { + assert(anjay_locked); + + int result = -1; + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + AVS_LIST(lwm2m_gateway_obj_t) lwm2m_gateway = + AVS_LIST_NEW_ELEMENT(lwm2m_gateway_obj_t); + if (lwm2m_gateway) { + lwm2m_gateway->obj_def = &LWM2M_GATEWAY; + _anjay_dm_installed_object_init_unlocked(&lwm2m_gateway->obj_def_ptr, + &lwm2m_gateway->obj_def); + + if (!_anjay_dm_module_install(anjay, gateway_delete, lwm2m_gateway)) { + _ANJAY_ASSERT_INSTALLED_OBJECT_IS_FIRST_FIELD(lwm2m_gateway_obj_t, + obj_def_ptr); + + AVS_LIST(anjay_dm_installed_object_t) entry = + &lwm2m_gateway->obj_def_ptr; + if (_anjay_register_object_unlocked(anjay, &entry)) { + result = _anjay_dm_module_uninstall(anjay, gateway_delete); + assert(!result); + result = -1; + } else { + result = 0; + } + } + if (result) { + AVS_LIST_CLEAR(&lwm2m_gateway); + } + } else { + _anjay_log_oom(); + } + ANJAY_MUTEX_UNLOCK(anjay_locked); + return result; +} + +static lwm2m_gateway_instance_t *add_instance(lwm2m_gateway_obj_t *gw, + anjay_iid_t *inout_iid) { + if (*inout_iid != ANJAY_ID_INVALID) { + // verify if user-defined iid is free + if (find_instance(gw, *inout_iid)) { + return NULL; + } + } else { + // assign new, free iid + *inout_iid = get_new_iid(gw->instances); + if (*inout_iid == ANJAY_ID_INVALID) { + return NULL; + } + } + + lwm2m_gateway_instance_t *inst = gateway_instance_create(gw, *inout_iid); + if (!inst) { + return NULL; + } + + return inst; +} + +int anjay_lwm2m_gateway_register_device(anjay_t *anjay_locked, + const char *device_id, + anjay_iid_t *inout_iid) { + assert(anjay_locked && device_id && inout_iid); + int retval = -1; + + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(ERROR, _("LwM2M Gateway object not installed")); + } else { + lwm2m_gateway_instance_t *inst = NULL; + if ((inst = add_instance(gw, inout_iid))) { + inst->device_id = device_id; + gw_log(INFO, + _("Registered new device: ") "%s" + " with ID: %" PRIu16, + device_id, *inout_iid); + _anjay_notify_instances_changed_unlocked( + anjay, ANJAY_DM_OID_LWM2M_GATEWAY); + retval = 0; + } else { + gw_log(ERROR, + _("Failed to register new device: ") "%s" + " with ID: %" PRIu16, + device_id, *inout_iid); + } + } + ANJAY_MUTEX_UNLOCK(anjay_locked); + + return retval; +} + +int anjay_lwm2m_gateway_deregister_device(anjay_t *anjay_locked, + anjay_iid_t iid) { + assert(anjay_locked); + int retval = -1; + + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(ERROR, _("LwM2M Gateway object not installed")); + } else { + lwm2m_gateway_instance_t *inst; + if ((inst = find_instance(gw, iid))) { + _anjay_dm_cleanup(&inst->dm); +# ifdef ANJAY_WITH_ATTR_STORAGE + _anjay_attr_storage_cleanup(&inst->as); +# endif // ANJAY_WITH_ATTR_STORAGE + delete_instance(&gw->instances, inst); + + _anjay_notify_instances_changed_unlocked( + anjay, ANJAY_DM_OID_LWM2M_GATEWAY); + gw_log(INFO, _("Device deregistered: ") "%" PRIu16, iid); + + retval = 0; + } else { + gw_log(WARNING, + _("LwM2M Gateway instance %" PRIu16 " does not exist"), iid); + } + } + ANJAY_MUTEX_UNLOCK(anjay_locked); + + return retval; +} + +void _anjay_lwm2m_gateway_iid_to_dm(anjay_unlocked_t *anjay, + anjay_iid_t iid, + const anjay_dm_t **dm) { + assert(anjay && dm); + *dm = NULL; + + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(WARNING, _("LwM2M Gateway object not installed")); + } else { + AVS_LIST(lwm2m_gateway_instance_t) it; + AVS_LIST_FOREACH(it, gw->instances) { + if (it->iid == iid) { + *dm = &it->dm; + break; + } + } + } +} + +/** + * This function is extracted from anjay_lwm2m_gateway_register_object() to + * allow easier to read early returns without goto. + * It has a lot in common with anjay_register_object() but is tweaked to allow + * to operate on a different DM than Anjay's. + */ +static int +register_object_unlocked(anjay_unlocked_t *anjay, + anjay_iid_t iid, + const anjay_dm_object_def_t *const *def_ptr) { + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(ERROR, _("LwM2M Gateway object not installed")); + return -1; + } + lwm2m_gateway_instance_t *inst; + if (!(inst = find_instance(gw, iid))) { + gw_log(ERROR, _("End Device %" PRIu16 " is not registered"), iid); + return -1; + } + + AVS_LIST(anjay_dm_installed_object_t) new_elem = + _anjay_prepare_user_provided_object(def_ptr); + if (!new_elem) { + return -1; + } + + new_elem->prefix = inst->prefix; + + //_anjay_dm_installed_object_init_unlocked(obj_ptr, new_elem); + if (_anjay_dm_register_object(&inst->dm, &new_elem)) { + gw_log(ERROR, _("Object registration failed")); + AVS_LIST_CLEAR(&new_elem); + return -1; + } + + // no need to call _anjay_notify_instances_changed_unlocked() or + // _anjay_schedule_registration_update_unlocked() as the + // End Devices DM's contents are not reported in Register and Update + // messages + gw_log(DEBUG, _("Successfully registered object ") "/%s/%" PRIu16, + new_elem->prefix, _anjay_dm_installed_object_oid(new_elem)); + return 0; +} + +int anjay_lwm2m_gateway_register_object( + anjay_t *anjay_locked, + anjay_iid_t iid, + const anjay_dm_object_def_t *const *def_ptr) { + assert(anjay_locked); + int result = -1; + + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + result = register_object_unlocked(anjay, iid, def_ptr); + ANJAY_MUTEX_UNLOCK(anjay_locked); + + return result; +} + +/** + * This function is extracted from anjay_lwm2m_gateway_unregister_object() to + * allow easier to read early returns without goto. + * It has a lot in common with anjay_unregister_object() but is tweaked to allow + * to operate on a different DM than Anjay's. + */ +static int +unregister_object_unlocked(anjay_unlocked_t *anjay, + anjay_iid_t iid, + const anjay_dm_object_def_t *const *def_ptr) { + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(ERROR, _("LwM2M Gateway object not installed")); + return -1; + } + lwm2m_gateway_instance_t *inst; + if (!(inst = find_instance(gw, iid))) { + gw_log(ERROR, _("End Device %" PRIu16 " is not registered"), iid); + return -1; + } + + AVS_LIST(anjay_dm_installed_object_t) *obj = + _anjay_find_and_verify_object_to_unregister(&inst->dm, def_ptr); + if (!obj) { + gw_log(ERROR, _("Object not installed for given End Device")); + return -1; + } + + assert(AVS_LIST_FIND_PTR(&inst->dm.objects, *obj)); + AVS_LIST(anjay_dm_installed_object_t) detached = AVS_LIST_DETACH(obj); + + _anjay_unregister_object_handle_transaction_state(anjay, detached); + _anjay_unregister_object_handle_notify_queue(anjay, detached); + + gw_log(INFO, _("Successfully unregistered object ") "/%s/%" PRIu16, + detached->prefix, _anjay_dm_installed_object_oid(detached)); + AVS_LIST_DELETE(&detached); + + // no need to call _anjay_notify_instances_changed_unlocked() or + // _anjay_schedule_registration_update_unlocked() as the + // End Devices DM's contents are not reported in Register and Update + // messages + + return 0; +} + +int anjay_lwm2m_gateway_unregister_object( + anjay_t *anjay_locked, + anjay_iid_t iid, + const anjay_dm_object_def_t *const *def_ptr) { + assert(anjay_locked); + + if (!def_ptr || !*def_ptr) { + gw_log(ERROR, _("invalid object pointer")); + return -1; + } + + int result = -1; + + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + result = unregister_object_unlocked(anjay, iid, def_ptr); + ANJAY_MUTEX_UNLOCK(anjay_locked); + + return result; +} + +static lwm2m_gateway_instance_t * +find_instance_by_prefix(anjay_unlocked_t *anjay, const char *prefix) { + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(WARNING, _("LwM2M Gateway object not installed")); + } else { + AVS_LIST(lwm2m_gateway_instance_t) it; + AVS_LIST_FOREACH(it, gw->instances) { + if (!strcmp(it->prefix, prefix)) { + return it; + } + } + } + return NULL; +} + +int _anjay_lwm2m_gateway_prefix_to_dm(anjay_unlocked_t *anjay, + const char *prefix, + const anjay_dm_t **dm) { + assert(anjay && prefix && dm); + *dm = NULL; + + lwm2m_gateway_instance_t *inst = find_instance_by_prefix(anjay, prefix); + if (inst) { + *dm = &inst->dm; + return 0; + } + return -1; +} + +# ifdef ANJAY_WITH_ATTR_STORAGE +int _anjay_lwm2m_gateway_prefix_to_as(anjay_unlocked_t *anjay, + const char *prefix, + anjay_attr_storage_t **as) { + assert(anjay && prefix && as); + *as = NULL; + + lwm2m_gateway_instance_t *inst = find_instance_by_prefix(anjay, prefix); + if (inst) { + *as = &inst->as; + return 0; + } + return -1; +} +# endif // ANJAY_WITH_ATTR_STORAGE + +static int gateway_notify_changed_unlocked(anjay_unlocked_t *anjay, + anjay_iid_t end_dev, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid) { + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(ERROR, _("LwM2M Gateway object not installed")); + return -1; + } + lwm2m_gateway_instance_t *inst; + if (!(inst = find_instance(gw, end_dev))) { + gw_log(ERROR, _("End Device %" PRIu16 " is not registered"), end_dev); + return -1; + } + return _anjay_notify_changed_gw_unlocked(anjay, inst->prefix, oid, iid, + rid); +} + +int anjay_lwm2m_gateway_notify_changed(anjay_t *anjay_locked, + anjay_iid_t end_dev, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid) { + assert(anjay_locked); + int result = -1; + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + result = gateway_notify_changed_unlocked(anjay, end_dev, oid, iid, rid); + ANJAY_MUTEX_UNLOCK(anjay_locked); + return result; +} + +static int gateway_notify_instances_changed_unlocked(anjay_unlocked_t *anjay, + anjay_iid_t end_dev, + anjay_oid_t oid) { + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(ERROR, _("LwM2M Gateway object not installed")); + return -1; + } + lwm2m_gateway_instance_t *inst; + if (!(inst = find_instance(gw, end_dev))) { + gw_log(ERROR, _("End Device %" PRIu16 " is not registered"), end_dev); + return -1; + } + + return _anjay_notify_instances_changed_gw_unlocked(anjay, inst->prefix, + oid); +} + +int anjay_lwm2m_gateway_notify_instances_changed(anjay_t *anjay_locked, + anjay_iid_t end_dev, + anjay_oid_t oid) { + assert(anjay_locked); + int result = -1; + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + result = gateway_notify_instances_changed_unlocked(anjay, end_dev, oid); + ANJAY_MUTEX_UNLOCK(anjay_locked); + return result; +} + +# ifdef ANJAY_WITH_OBSERVATION_STATUS +anjay_resource_observation_status_t +anjay_lwm2m_gateway_resource_observation_status(anjay_t *anjay_locked, + anjay_iid_t end_dev, + anjay_oid_t oid, + anjay_iid_t iid, + anjay_rid_t rid) { + assert(anjay_locked); + anjay_resource_observation_status_t retval = { + .is_observed = false, + .min_period = 0, + .max_eval_period = ANJAY_ATTRIB_INTEGER_NONE, +# if (ANJAY_MAX_OBSERVATION_SERVERS_REPORTED_NUMBER > 0) + .servers_number = 0 +# endif // (ANJAY_MAX_OBSERVATION_SERVERS_REPORTED_NUMBER > 0) + }; + + ANJAY_MUTEX_LOCK(anjay, anjay_locked); + lwm2m_gateway_obj_t *gw = + (lwm2m_gateway_obj_t *) _anjay_dm_module_get_arg(anjay, + gateway_delete); + if (!gw) { + gw_log(ERROR, _("LwM2M Gateway object not installed")); + goto exit; + } + lwm2m_gateway_instance_t *inst; + if (!(inst = find_instance(gw, end_dev))) { + gw_log(ERROR, _("End Device %" PRIu16 " is not registered"), end_dev); + goto exit; + } + _anjay_notify_observation_status_impl_unlocked(anjay, &retval, inst->prefix, + oid, iid, rid); +exit: + ANJAY_MUTEX_UNLOCK(anjay_locked); + return retval; +} +# endif // ANJAY_WITH_OBSERVATION_STATUS +# ifdef ANJAY_TEST +# include "tests/modules/lwm2m_gateway/lwm2m_gateway.c" +# endif + +#endif // ANJAY_WITH_LWM2M_GATEWAY diff --git a/src/modules/security/anjay_mod_security.c b/src/modules/security/anjay_mod_security.c index 40b4117e..e41d58f5 100644 --- a/src/modules/security/anjay_mod_security.c +++ b/src/modules/security/anjay_mod_security.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/security/anjay_mod_security.h b/src/modules/security/anjay_mod_security.h index cfa6efdf..edc403df 100644 --- a/src/modules/security/anjay_mod_security.h +++ b/src/modules/security/anjay_mod_security.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/security/anjay_security_persistence.c b/src/modules/security/anjay_security_persistence.c index 8ba4b293..38ce266f 100644 --- a/src/modules/security/anjay_security_persistence.c +++ b/src/modules/security/anjay_security_persistence.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/security/anjay_security_transaction.c b/src/modules/security/anjay_security_transaction.c index 7cc0f0d0..a6969859 100644 --- a/src/modules/security/anjay_security_transaction.c +++ b/src/modules/security/anjay_security_transaction.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/security/anjay_security_transaction.h b/src/modules/security/anjay_security_transaction.h index 0b567b07..2490ea6f 100644 --- a/src/modules/security/anjay_security_transaction.h +++ b/src/modules/security/anjay_security_transaction.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/security/anjay_security_utils.c b/src/modules/security/anjay_security_utils.c index 58726e89..1a02ceb3 100644 --- a/src/modules/security/anjay_security_utils.c +++ b/src/modules/security/anjay_security_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/security/anjay_security_utils.h b/src/modules/security/anjay_security_utils.h index e5431367..111bc67a 100644 --- a/src/modules/security/anjay_security_utils.h +++ b/src/modules/security/anjay_security_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/server/anjay_mod_server.c b/src/modules/server/anjay_mod_server.c index c41577f9..c87d36ce 100644 --- a/src/modules/server/anjay_mod_server.c +++ b/src/modules/server/anjay_mod_server.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/server/anjay_mod_server.h b/src/modules/server/anjay_mod_server.h index e802dad9..dcb80bdf 100644 --- a/src/modules/server/anjay_mod_server.h +++ b/src/modules/server/anjay_mod_server.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/server/anjay_server_persistence.c b/src/modules/server/anjay_server_persistence.c index a5b722d5..262c262a 100644 --- a/src/modules/server/anjay_server_persistence.c +++ b/src/modules/server/anjay_server_persistence.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/server/anjay_server_transaction.c b/src/modules/server/anjay_server_transaction.c index 1322fe30..6e8519a6 100644 --- a/src/modules/server/anjay_server_transaction.c +++ b/src/modules/server/anjay_server_transaction.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/server/anjay_server_transaction.h b/src/modules/server/anjay_server_transaction.h index 35570236..2d31533f 100644 --- a/src/modules/server/anjay_server_transaction.h +++ b/src/modules/server/anjay_server_transaction.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/server/anjay_server_utils.c b/src/modules/server/anjay_server_utils.c index ff30bb61..3072876c 100644 --- a/src/modules/server/anjay_server_utils.c +++ b/src/modules/server/anjay_server_utils.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/server/anjay_server_utils.h b/src/modules/server/anjay_server_utils.h index 897e17f6..42f1aded 100644 --- a/src/modules/server/anjay_server_utils.h +++ b/src/modules/server/anjay_server_utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/src/modules/sw_mgmt/anjay_sw_mgmt.c b/src/modules/sw_mgmt/anjay_sw_mgmt.c index 529029b4..71e7e2a1 100644 --- a/src/modules/sw_mgmt/anjay_sw_mgmt.c +++ b/src/modules/sw_mgmt/anjay_sw_mgmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 AVSystem + * Copyright 2017-2025 AVSystem * AVSystem Anjay LwM2M SDK * All rights reserved. * diff --git a/tests/codegen/CMakeLists.txt b/tests/codegen/CMakeLists.txt index 049721ae..10ac2507 100644 --- a/tests/codegen/CMakeLists.txt +++ b/tests/codegen/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/tests/codegen/check_with_object_registry.sh b/tests/codegen/check_with_object_registry.sh index c0618951..ec3c34f3 100755 --- a/tests/codegen/check_with_object_registry.sh +++ b/tests/codegen/check_with_object_registry.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright 2017-2024 AVSystem +# Copyright 2017-2025 AVSystem # AVSystem Anjay LwM2M SDK # All rights reserved. # diff --git a/tests/codegen/input/execute.xml b/tests/codegen/input/execute.xml index 2c0e8d20..0a98c7cc 100644 --- a/tests/codegen/input/execute.xml +++ b/tests/codegen/input/execute.xml @@ -1,6 +1,6 @@