11.10. Migrating from Anjay 3.1 or 3.2

11.10.1. Introduction

avs_commons 5.2.0 that is used by Anjay 3.3.0, has removed one specific functionality of the avs_unit module that has not been used by Anjay. If you are developing your own unit tests based on avs_unit, you may need to update them.

Since Anjay 3.4.0 and avs_commons 5.4.0, time handling in avs_sched and avs_coap has been refactored, which slightly redefined existing APIs. These changes should not require any changes to user code in typical usage, but may break some edge cases, especially on platforms where the system clock has a low resolution and you are scheduling custom jobs through the avs_sched module.

11.10.2. Refactor of time handling in avs_sched and avs_coap

It is now enforced more strictly that time-based events shall happen when the clock reaches at least the expected value. Previously, the tasks scheduled via avs_sched were executed only when the clock reached a value later than the scheduled job execution time.

This change will have no impact on your code if your platform has enough clock resolution so that two subsequent calls to avs_time_real_now() or avs_time_monotonic_now() will always return different values. As a rule of thumb, this should be the case if your clock has a resolution no worse than about 1-2 orders of magnitude smaller than the CPU clock. For example, for a 100 MHz CPU, a clock resolution of around 100-1000 ns (i.e., 1-10 MHz) should be sufficient, depending on the specific architecture.

If your clock has a lower resolution, you may observe the following changes:

  • anjay_sched_run() is now properly guaranteed to execute at least one job if the time reported by anjay_sched_time_to_next() passed. Previously this could require waiting for another change of the numerical value of the clock, which could cause undesirable active waiting in the event loop. This is the motivating factor in introducing these changes.

  • Jobs scheduled using AVS_SCHED_NOW() during an execution of anjay_sched_run() before the numerical value of the clock changes, will be executed during the same run. The previous behavior more strictly enforced the policy to not execute such jobs in the same run.

If you are scheduling custom jobs through the avs_sched module, you may want or need to modify their logic accordingly to accommodate for these changes. In most typical use cases, no changes are expected to be necessary.

11.10.3. Changed flow of cancelling observations in case of errors

CoAP observations are implicitly cancelled if a notification bearing a 4.xx or 5.xx error code is delivered.

In Anjay 3.4.x and earlier, this cancellation (which involves calling the avs_coap_observe_cancel_handler_t callback) was performed before calling the avs_coap_delivery_status_handler_t callback for the specific notification. Since Anjay 3.5.0, this order is reversed, so any code that relies on this logic may break.

This change is only relevant if you are using avs_coap APIs directly (e.g. when communicating over raw CoAP protocol) and in case of notifications intended to be delivered as confirmable. The LwM2M Observe/Notify implementation in Anjay has been updated accordingly.

11.10.4. Persistence of disabled servers

Core Persistence API (anjay_new_from_core_persistence(), anjay_delete_with_core_persistence()) now also persists disabled servers (either by execution of /1/x/4 or call to function from anjay_disable_server*() family) and the time at which the client shall reconnect them. Previously those disabled servers weren’t persisted at all and freshly initialized client was automatically connecting to them without any regard for specified timeout.

11.10.5. Addition of resource_instance_remove handler

LwM2M TS 1.2 introduced possibility to delete a Resource Instance, so one additional data model handler had to be added.

New resource_instance_remove handler (and its associated anjay_dm_resource_instance_remove_t function type) has been introduced. It is analogous to the instance_remove handler; its job is to remove a specific Resource Instance from a multiple-instance Resource.

Its implementation is required in objects that include at least one writeable multiple-instance Resource, if the client application aims for compliance with LwM2M 1.2.

11.10.6. Limiting the maximum Hold Off Time for Bootstrap

A limit has been introduced on the maximum Hold Off Time (LwM2M Security Object, Resource ID: 11) to avoid excessive delays when initiating the Bootstrap process. Previously, the upper bound was implicitly 120 seconds, but it is now explicitly limited to 20 seconds by default.

This behavior can be customized at build time using the MAX_HOLDOFF_TIME macro.

11.10.7. Handling of Trust Store for certain Certificate Usages settings

avs_commons 5.5.0 that is used by Anjay 3.11.0 does not pass the configured Trust Store (whether manually provided or acquired through the EST process) to Mbed TLS when the certificate usage is set to DANE-TA or DANE-EE, if the Data Model already contains a Server certificate intended for verifying the Server during a secure connection.

If the Server certificate is missing from the Data Model, Anjay falls back to PKIX verification, provided that a Trust Store is available, even when the certificate usage is set to DANE-TA or DANE-EE.

For more information on how Anjay manages the Trust Store and the Certificate Usage resource, see Certificate Usage.

11.10.8. Removal of avs_unit_memstream

avs_unit_memstream was a specific implementation of avs_stream_t within the avs_unit module that implemented a simple FIFO stream in a fixed-size memory area.

This feature has been removed. Instead, you can use an avs_stream_inbuf/avs_stream_outbuf pair, or an avs_stream_membuf object.

11.10.9. Python environment isolation

All Python-based tools (e.g. integration tests) must be executed within a Python virtual environment. See Virtual environments for more information.

11.10.10. Dropping built-in support for TinyDTLS as a crypto backend

Built-in support for TinyDTLS as a (D)TLS backend has been removed.

In previous versions of Anjay, TinyDTLS could be selected as a lightweight crypto backend, primarily intended for constrained environments. However, due to its limited feature set, lack of ongoing maintenance, and incompatibility with newer security requirements and LwM2M specifications, it is no longer supported.

Users are now required to use one of the supported and actively maintained (D)TLS backends, such as Mbed TLS or OpenSSL (via avs_commons abstraction layer) or creating there own Custom (D)TLS layer.

11.10.11. Changing Server Initiated Bootstrap behavior

Previously, Anjay did not use the Client Hold Off Time resource (/1/x/11) during Server Initiated Bootstrap. This was because the description of /1/x/11 states that its value should be used during Client Initiated Bootstrap.

The LwM2M specification also states that Server Initiated Bootstrap causes the LwM2M Client to enter Client Initiated Bootstrap. For consistency with this behavior, Anjay now applies the Client Hold Off Time resource in this scenario as well.

To avoid additional delay, adjust resource /1/x/11 as needed.

11.10.12. Default ciphersuite list

If neither the DTLS/TLS Ciphersuite Resource (/0/x/16) nor anjay_configuration_t::default_tls_ciphersuites is configured, Anjay now uses a built-in allowlist of secure ciphersuites instead of all ciphersuites supported by the TLS backend.

Applications that require ciphersuites outside this list must configure them explicitly through anjay_configuration_t::default_tls_ciphersuites or /0/x/16.

11.10.13. Changes in Anjay configuration

The ANJAY_MAX_PK_OR_IDENTITY_SIZE configuration option has been renamed to ANJAY_EST_CSR_BUFFER_SIZE to better reflect its actual purpose. The option specifies the size of the buffer used when generating certificate signing requests during EST enrollment and re-enrollment.

Users with custom Anjay configuration files should replace ANJAY_MAX_PK_OR_IDENTITY_SIZE with ANJAY_EST_CSR_BUFFER_SIZE while preserving the previously configured value.

The ANJAY_MAX_SECRET_KEY_SIZE configuration option has been renamed to ANJAY_EST_SECRET_KEY_BUFFER_SIZE to better reflect its actual purpose. The option specifies the size, in bytes, of the buffer used for generating and storing a private key during EST enrollment.

Users with custom Anjay configuration files should replace ANJAY_MAX_SECRET_KEY_SIZE with ANJAY_EST_SECRET_KEY_BUFFER_SIZE while preserving the previously configured value.

11.10.14. Message cache size configuration

The type of anjay_configuration_t::msg_cache_size has changed from size_t to size_t *. NULL pointer now indicates that the default value of 4000 will be used.

Applications that previously relied on the zero/default value to disable the message cache must now explicitly set this field to point to a size_t value equal to 0, for example:

size_t msg_cache_size = 0;
anjay_configuration_t config = {
    .msg_cache_size = &msg_cache_size,
    // other fields...
};

11.10.15. Disable unsecure configuration

Anjay added a new configuration define ANJAY_WITH_UNSECURE_CONNECTIONS which is unset by default in the configuration. Having this option unset will prevent Anjay from using unecrypted communication. If you relay on a NOSEC communication you must set this define.

Also Anjay added a new configuration define AVS_COMMONS_WITH_LEGACY_SSL_VERSIONS, which is unset by default in the configuration. Having this option unset will prevent Anjay from using legacy SSL, TLS and DTLS protocol versions, including SSLv2, SSLv3, TLS 1.0, TLS 1.1 and DTLS 1.0.

If you rely on any of these legacy protocol versions, you must enable AVS_COMMONS_WITH_LEGACY_SSL_VERSIONS.

11.10.16. Changes in automatic reconnection in the event loop

Previously, anjay_event_loop_run_with_error_handling() called anjay_transport_schedule_reconnect(anjay, ANJAY_TRANSPORT_SET_ALL) when all configured LwM2M servers were unreachable. This also forced reconnection of ongoing downloads.

The event loop now schedules reconnects for individual Server Object instances using anjay_server_schedule_reconnect(). Ongoing downloads using dedicated downloader sockets are no longer reconnected as a side effect of LwM2M server connection failures. Downloads that share a socket with a LwM2M server remain dependent on that server’s connection.

Applications that relied on this side effect to reconnect ongoing downloads must now request it explicitly:

  • Use anjay_download_reconnect() with the download handle for downloads started through anjay_download().

  • Use anjay_fw_update_pull_reconnect() for PULL-mode downloads managed by the Firmware Update module.

If reconnecting all sockets on selected transports is intentional, call anjay_transport_schedule_reconnect() explicitly with the appropriate transport set.

Automatic CoAP download retries configured through anjay_configuration_t::coap_downloader_retry_count and anjay_configuration_t::coap_downloader_retry_delay remain available and operate independently of this event loop recovery mechanism.

Applications that did not rely on the transport-wide reconnect side effect require no changes.