diff --git a/CHANGELOG.md b/CHANGELOG.md index b7764e0c7..b477e87af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,26 +1,62 @@ ## Changelog for Pelion Device Management Client +### Release 4.9.0 (20.05.2021) + +### Device Management Client + +- Fixed a race condition in the handling of message status callback (particularly the handling of `MESSAGE_STATUS_SENT`). Previously, it was getting reported just before the operation had finished successfully. +- Added support for TLV to single resource. +- PUT to a resource 1/0/1 now triggers a registration update. +- POST to a resource 1/0/4 now triggers a deregister process. +- Removed deprecated STL APIs. These APIs and classes were removed: + - `SimpleM2MResource*`. + - `MbedCloudClient::set_device_resource_value(M2MDevice::DeviceResource resource, const std::string &value)`. + - `MbedCloudClient::register_update_callback(string route, SimpleM2MResourceBase* resource)`. +- Added new API `MbedCloudClient::alert()` to send high-priority messages. + - In alert mode, Device Management Client halts all data sendings/active operations and waits for priority data to be sent. +- Added new status callback API `MbedCloudClient::on_status_changed()`, which replaces these callback APIs: + - `MbedCloudClient::on_registered()`. + - `MbedCloudClient::on_unregistered()`. + - `MbedCloudClient::on_registration_updated()`. + - The old APIs are deprecated and will be removed in a future release. +- Added option to reduce traffic in bootstrap flow: + - `MBED_CONF_MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE` flag added to control whether delay or piggybacked response is used. By default, piggybacked response type is used. + - Piggybacked response can be disabled by setting `mbed-client.bootstrap-piggybacked-response" : 0` in `mbed_app.json`. +- Fixed register and register update content type to `COAP_CT_LINK_FORMAT` (Core Link Format). +- Fixed a memory leak when `setup()` and `close()` were called multiple times in row. + +#### Device Management Update client + +- Removed the `need_reboot = false` option in the `fota_component_add()` API. When registering a component, the `need_reboot` option must always be `true`. +- Fixed storage erase calculations for boards with a non-uniform sector map. +- Fixed the FOTA defer download behaviour. Device registration update won't cause the client to resume FOTA download after the application calls the `fota_app_defer()` API. + +### Platform Adaptation Layer (PAL) + +- Added new PAL_DNS_API_VERSION 3. It's an asynchronous DNS API that can return multiple DNS results. + - This feature is currently implemented only for Linux platform and is disabled by default. You can enable it by defining PAL_DNS_API_VERSION=3. In future releases, this feature will be enabled by default for Linux. + ### Release 4.8.0 (19.04.2021) #### Device Management Client -- Client internal timers were not using event_ids correctly. Previously, if there were two timers running at the same time, cancel might have stopped the wrong timer. +- Client internal timers were not using event IDs correctly. Previously, if two timers were running at the same time, cancel might have stopped the wrong timer. - Added fallback timer for asynchronous DNS requests (`PAL_DNS_API_VERSION` = 2). The client waits 10 minutes for a response to DNS query before aborting the request and raising a DNS error event. - Improved client bootstrap recovery handling. -- The client doesn't go sleep if update register, unregistering or reconnecting is ongoing. +- The client doesn't go to sleep if update register, unregistering or reconnecting is ongoing. - Added LwM2M version as part of the registration message. - Added API to get M2MServer instance. - tinycbor: Removed the default usage of asserts in input validation. Instead of asserting, the library returns an error if an invalid cbor input is given. Introduced a new `TINYCBOR_USE_ASSERT` flag to save on code size. This saves approximately 200 bytes. - Deprecated the `MBED_CLIENT_USER_CONFIG_FILE` macro. An application only needs to use `MBED_CLOUD_CLIENT_USER_CONFIG_FILE`. - Allow Write-Attributes to GET resource. - Parent resource of resource-instance also set observable flag. Now also parent resource can be observed. -- Added API `m2mbase::set_confirmable(bool confirmable)` to choose whether notification is sent as a confirmable or non-confirmable way. By default, the confirmable message type is used. +- Added API `m2mbase::set_confirmable(bool confirmable)` to choose whether a notification is sent in a confirmable or nonconfirmable way. By default, the confirmable message type is used. - M2MDevice now accepts PUT/POST requests, and you can also observe it. -- Fixed an issue which can cause a crash if there is a lot of network traffic during the `pause()` call. -- Don't report notification sending timeout to the application. Notification sending can't fail after the message has been created because it has its own queue for resending. -- Removed deprecated notification delivery status APIs. Use `M2MBase::set_message_delivery_status_cb` instead. -- Changed default content type from `COAP_CONTENT_OMA_TLV_TYPE_OLD` to` COAP_CONTENT_OMA_TLV_TYPE`. -- Deprecated `kcm_ecdh_key_agreement()` API for psa configuration, due to `psa_set_key_enrollment_algorithm()` API deprecation in mbed-crypto. +- Fixed an issue that could cause a crash if there were a lot of network traffic during the `pause()` call. +- Do not report notification sending timeout to application. Notification sending can't fail once message has been because since they have own queue for resending. +- Removed deprecated notification delivery status APIs. Use `M2MBase::set_message_delivery_status_cb`, instead. +- Changed default content type from `COAP_CONTENT_OMA_TLV_TYPE_OLD` to `COAP_CONTENT_OMA_TLV_TYPE`. +- Deprecated `kcm_ecdh_key_agreement()` API for PSA configuration, due to `psa_set_key_enrollment_algorithm()` API deprecation in Mbed Crypto. #### Device Management Update client @@ -123,7 +159,7 @@ However, the notification will still be stored internally in client and it will * Added a compile-time check to prevent configuring the client with LIFETIME values below 60 seconds. 60 seconds is the minimum allowed. * [Mbed OS] Changed the default storage location for update to `ARM_UCP_FLASHIAP`. * Added support for Device Sentry feature. -* Added new library flag `MBED_CONF_MBED_CLOUD_CLIENT_NON_PROVISIONED_SECURE_ELEMENT`, The default is `null`. Should be set to `1` if SE hasn't pre-provisioned credentials. +* Added new library flag `MBED_CONF_MBED_CLOUD_CLIENT_NON_PROVISIONED_SECURE_ELEMENT`, The default is `null`. Should be set to `1` if SE hasn't pre-provisioned credentials. ### Release 4.4.0 (17.04.2020) @@ -700,7 +736,7 @@ Added a temporary workaround for Cypress PSOC6 target to read each block from an * Full support for the `device generated keys` mode. You can activate the mode using the Factory Configurator Utility (FCU) or the KCM APIs. **Note:** Cloud Client and Mbed Cloud do not yet support this mode. - + * A certificate signed request (CSR) that is generated on the device, can be created with the `Extended key usage` extension. * A new KCM API introduced: * `kcm_certificate_verify_with_private_key` - a self-generated certificate can be checked against a stored private key. diff --git a/CMakeLists.txt b/CMakeLists.txt index 22d358de6..c6283807d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -288,11 +288,19 @@ if (FOTA_ENABLE) endif() include_directories(${FOTA_SOURCE_DIR}) + include_directories("${FOTA_SOURCE_DIR}/platform/linux") FILE(GLOB FOTA_SRC "${FOTA_SOURCE_DIR}/*.c" "${FOTA_SOURCE_DIR}/*.cpp" "${FOTA_SOURCE_DIR}/bspatch/*.c" +if ( (${OS_BRAND} MATCHES "Linux")) + "${FOTA_SOURCE_DIR}/platform/linux/*.c*" +else +if ( (${OS_BRAND} MATCHES "NXP")) + "${FOTA_SOURCE_DIR}/platform/nxp/*.c*" +endif +endif ) message("FOTA sources = \n ${FOTA_SRC}") target_sources(mbedCloudClient PRIVATE "${FOTA_SRC}") @@ -301,16 +309,18 @@ if (FOTA_ENABLE) add_library(fota STATIC ${FOTA_SRC}) - if (MBED_CLOUD_CLIENT_CURL_DYNAMIC_LINK) - include(FindPkgConfig) - pkg_check_modules(CURL libcurl REQUIRED) - message("curl include at: ${CURL_INCLUDE_DIRS}") - message("curl link: ${CURL_LIBRARIES}") - include_directories(SYSTEM ${CURL_LIBRARIES}) - target_link_libraries(fota ${CURL_LIBRARIES}) - else() - add_dependencies(fota libcurl) - target_link_libraries(fota libcurl) + if ( NOT FOTA_COAP_DOWNLOAD) + if (MBED_CLOUD_CLIENT_CURL_DYNAMIC_LINK) + include(FindPkgConfig) + pkg_check_modules(CURL libcurl REQUIRED) + message("curl include at: ${CURL_INCLUDE_DIRS}") + message("curl link: ${CURL_LIBRARIES}") + include_directories(SYSTEM ${CURL_LIBRARIES}) + target_link_libraries(fota ${CURL_LIBRARIES}) + else() + add_dependencies(fota libcurl) + target_link_libraries(fota libcurl) + endif() endif() add_dependencies(mbedCloudClient fota) target_link_libraries(mbedCloudClient fota) diff --git a/certificate-enrollment-client/source/ce_safe_renewal_internal.c b/certificate-enrollment-client/source/ce_safe_renewal_internal.c index 43620871b..11ef25fd1 100644 --- a/certificate-enrollment-client/source/ce_safe_renewal_internal.c +++ b/certificate-enrollment-client/source/ce_safe_renewal_internal.c @@ -21,7 +21,7 @@ #include "ce_internal.h" #include "est_defs.h" #include "storage_kcm.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" const char g_lwm2m_name[] = "LWM2M"; const char g_renewal_status_file[] = "renewal_status"; diff --git a/factory-configurator-client/crypto-service/crypto-service/cs_der_certs.h b/factory-configurator-client/crypto-service/crypto-service/cs_der_certs.h index 7bacb00a3..30d9192b1 100644 --- a/factory-configurator-client/crypto-service/crypto-service/cs_der_certs.h +++ b/factory-configurator-client/crypto-service/crypto-service/cs_der_certs.h @@ -26,7 +26,7 @@ extern "C" { #include #include "kcm_status.h" #include "storage_kcm.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" /* * Types certificate's attributes diff --git a/factory-configurator-client/crypto-service/crypto-service/cs_hash.h b/factory-configurator-client/crypto-service/crypto-service/cs_hash.h index 42ab6cebf..daa58a356 100644 --- a/factory-configurator-client/crypto-service/crypto-service/cs_hash.h +++ b/factory-configurator-client/crypto-service/crypto-service/cs_hash.h @@ -22,7 +22,7 @@ #include #include "kcm_status.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #ifdef __cplusplus extern "C" { diff --git a/factory-configurator-client/crypto-service/crypto-service/pal_Crypto.h b/factory-configurator-client/crypto-service/crypto-service/cs_pal_crypto.h similarity index 99% rename from factory-configurator-client/crypto-service/crypto-service/pal_Crypto.h rename to factory-configurator-client/crypto-service/crypto-service/cs_pal_crypto.h index 8a8e312cf..ddda6a825 100644 --- a/factory-configurator-client/crypto-service/crypto-service/pal_Crypto.h +++ b/factory-configurator-client/crypto-service/crypto-service/cs_pal_crypto.h @@ -16,8 +16,8 @@ // limitations under the License. // ---------------------------------------------------------------------------- -#ifndef _FCC_PAL_CRYPTO_H_ -#define _FCC_PAL_CRYPTO_H_ +#ifndef _CS_PAL_CRYPTO_H_ +#define _CS_PAL_CRYPTO_H_ #ifdef __cplusplus extern "C" { @@ -27,7 +27,7 @@ extern "C" { #include #include #include -#include +#include "cs_pal_crypto_configuration.h" #include "mbed-trace/mbed_trace.h" #if !defined(MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT) || defined(MBED_CONF_MBED_CLOUD_CLIENT_PSA_SUPPORT) #include "pal.h" @@ -36,7 +36,7 @@ extern "C" { #define NULLPTR 0 typedef int32_t palStatus_t; -/*! \file pal_Crypto.h +/*! \file cs_pal_crypto.h * \brief PAL cryptographic. * This file contains cryptographic APIs and is part of the PAL service API. * diff --git a/factory-configurator-client/crypto-service/crypto-service/pal_crypto_configuration.h b/factory-configurator-client/crypto-service/crypto-service/cs_pal_crypto_configuration.h similarity index 95% rename from factory-configurator-client/crypto-service/crypto-service/pal_crypto_configuration.h rename to factory-configurator-client/crypto-service/crypto-service/cs_pal_crypto_configuration.h index f96776c27..871409284 100644 --- a/factory-configurator-client/crypto-service/crypto-service/pal_crypto_configuration.h +++ b/factory-configurator-client/crypto-service/crypto-service/cs_pal_crypto_configuration.h @@ -16,8 +16,8 @@ // limitations under the License. // ---------------------------------------------------------------------------- -#ifndef _FCC_PAL_CRYPTO_COFIGURATION_H -#define _FCC_PAL_CRYPTO_COFIGURATION_H +#ifndef _CS_PAL_CRYPTO_CONFIGURATION_H +#define _CS_PAL_CRYPTO_CONFIGURATION_H #include "limits.h" #ifdef PAL_USER_DEFINED_CONFIGURATION diff --git a/factory-configurator-client/crypto-service/crypto-service/pal_plat_Crypto.h b/factory-configurator-client/crypto-service/crypto-service/cs_pal_plat_crypto.h similarity index 99% rename from factory-configurator-client/crypto-service/crypto-service/pal_plat_Crypto.h rename to factory-configurator-client/crypto-service/crypto-service/cs_pal_plat_crypto.h index cb4ff7739..031008be3 100644 --- a/factory-configurator-client/crypto-service/crypto-service/pal_plat_Crypto.h +++ b/factory-configurator-client/crypto-service/crypto-service/cs_pal_plat_crypto.h @@ -14,16 +14,15 @@ * limitations under the License. *******************************************************************************/ -#ifndef _PAL_PLAT_CRYPTO_H_ -#define _PAL_PLAT_CRYPTO_H_ +#ifndef _CS_PAL_PLAT_CRYPTO_H_ +#define _CS_PAL_PLAT_CRYPTO_H_ #ifdef __cplusplus extern "C" { #endif -#include "pal_Crypto.h" -//#include "pal_crypto_configuration.h" -/*! \file pal_plat_Crypto.h +#include "cs_pal_crypto.h" +/*! \file cs_pal_plat_crypto.h * \brief PAL cryptographic - platform. * This file contains cryptographic APIs that need to be implemented in the platform layer. */ diff --git a/factory-configurator-client/crypto-service/source/cs_hash.c b/factory-configurator-client/crypto-service/source/cs_hash.c index f212a6741..378c3a5eb 100644 --- a/factory-configurator-client/crypto-service/source/cs_hash.c +++ b/factory-configurator-client/crypto-service/source/cs_hash.c @@ -16,7 +16,7 @@ #include "pv_error_handling.h" #include "cs_hash.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "cs_utils.h" #include "pv_macros.h" diff --git a/factory-configurator-client/crypto-service/source/pal_Crypto.c b/factory-configurator-client/crypto-service/source/cs_pal_crypto.c similarity index 99% rename from factory-configurator-client/crypto-service/source/pal_Crypto.c rename to factory-configurator-client/crypto-service/source/cs_pal_crypto.c index 02b55c881..cfd901e9f 100644 --- a/factory-configurator-client/crypto-service/source/pal_Crypto.c +++ b/factory-configurator-client/crypto-service/source/cs_pal_crypto.c @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ -#include "pal_plat_Crypto.h" +#include "cs_pal_plat_crypto.h" #include "pv_macros.h" #include diff --git a/factory-configurator-client/crypto-service/source/pal_plat_Crypto.c b/factory-configurator-client/crypto-service/source/cs_pal_plat_crypto.c similarity index 99% rename from factory-configurator-client/crypto-service/source/pal_plat_Crypto.c rename to factory-configurator-client/crypto-service/source/cs_pal_plat_crypto.c index f31dbfd8a..82ed0ebda 100644 --- a/factory-configurator-client/crypto-service/source/pal_plat_Crypto.c +++ b/factory-configurator-client/crypto-service/source/cs_pal_plat_crypto.c @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ -#include "pal_plat_Crypto.h" +#include "cs_pal_plat_crypto.h" #if !defined(MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT) || defined(MBED_CONF_MBED_CLOUD_CLIENT_PSA_SUPPORT) #include "pal.h" #endif @@ -1230,7 +1230,7 @@ palStatus_t pal_plat_CtrDRBGIsSeeded(palCtrDrbgCtxHandle_t ctx) #endif } -// FIXME: Currently not public in pal_plat_Crypto.h and is called from pal_plat_drbg_w_entropy_sources.c +// FIXME: Currently not public in cs_pal_plat_crypto.h and is called from pal_plat_drbg_w_entropy_sources.c // With a forward declaration // This function will later be public, deprecating pal_plat_CtrDRBGSeed() (pal_plat_CtrDRBGInit will call this directly). // Changing this requires some work - therefore not done yet diff --git a/factory-configurator-client/crypto-service/source/pal_plat_drbg_w_entropy_sources_kv.c b/factory-configurator-client/crypto-service/source/cs_pal_plat_drbg_w_entropy_sources_kv.c similarity index 98% rename from factory-configurator-client/crypto-service/source/pal_plat_drbg_w_entropy_sources_kv.c rename to factory-configurator-client/crypto-service/source/cs_pal_plat_drbg_w_entropy_sources_kv.c index 4a417f6eb..c1c4ed228 100644 --- a/factory-configurator-client/crypto-service/source/pal_plat_drbg_w_entropy_sources_kv.c +++ b/factory-configurator-client/crypto-service/source/cs_pal_plat_drbg_w_entropy_sources_kv.c @@ -28,7 +28,7 @@ #include "mbedtls/ctr_drbg.h" #include "mbedtls/entropy.h" #include "mbedtls/config.h" -#include "pal_plat_Crypto.h" +#include "cs_pal_plat_crypto.h" #ifndef FCC_NANOCLIENT_ENABLED #if PAL_USE_HW_TRNG #include "pal_plat_drbg_noise.h" @@ -36,8 +36,7 @@ #endif #include "mbed_trace.h" #include -#include "pal_Crypto.h" -#include "pal_plat_Crypto.h" +#include "cs_pal_crypto.h" #define TRACE_GROUP "DRBG" diff --git a/factory-configurator-client/crypto-service/source/cs_utils.c b/factory-configurator-client/crypto-service/source/cs_utils.c index f8d692536..77da8ce76 100644 --- a/factory-configurator-client/crypto-service/source/cs_utils.c +++ b/factory-configurator-client/crypto-service/source/cs_utils.c @@ -17,7 +17,7 @@ #include "pv_log.h" #include "cs_der_keys_and_csrs.h" #include "cs_der_certs.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "pv_error_handling.h" #include "key_slot_allocator.h" diff --git a/factory-configurator-client/crypto-service/source/include/cs_utils.h b/factory-configurator-client/crypto-service/source/include/cs_utils.h index 51e6ff5fc..6f65d70b0 100644 --- a/factory-configurator-client/crypto-service/source/include/cs_utils.h +++ b/factory-configurator-client/crypto-service/source/include/cs_utils.h @@ -19,7 +19,7 @@ #include #include -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "kcm_status.h" #include "kcm_defs.h" diff --git a/factory-configurator-client/factory-configurator-client/source/factory_configurator_client.c b/factory-configurator-client/factory-configurator-client/source/factory_configurator_client.c index 5c3c20b5f..79bf482e0 100644 --- a/factory-configurator-client/factory-configurator-client/source/factory_configurator_client.c +++ b/factory-configurator-client/factory-configurator-client/source/factory_configurator_client.c @@ -25,7 +25,7 @@ #ifndef FCC_NANOCLIENT_ENABLED #include "pal.h" #endif -#include "pal_plat_Crypto.h" +#include "cs_pal_plat_crypto.h" #include "fcc_utils.h" /** diff --git a/factory-configurator-client/factory-configurator-client/source/include/fcc_utils.h b/factory-configurator-client/factory-configurator-client/source/include/fcc_utils.h index f8f36d623..aef648f97 100644 --- a/factory-configurator-client/factory-configurator-client/source/include/fcc_utils.h +++ b/factory-configurator-client/factory-configurator-client/source/include/fcc_utils.h @@ -26,7 +26,7 @@ #ifndef FCC_NANOCLIENT_ENABLED #include "pal.h" #endif -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #ifdef __cplusplus extern "C" { diff --git a/factory-configurator-client/key-config-manager/key-config-manager/kcm_defs.h b/factory-configurator-client/key-config-manager/key-config-manager/kcm_defs.h index e635b3861..aed086812 100644 --- a/factory-configurator-client/key-config-manager/key-config-manager/kcm_defs.h +++ b/factory-configurator-client/key-config-manager/key-config-manager/kcm_defs.h @@ -32,8 +32,8 @@ extern "C" { * KCM item types. */ typedef enum { - KCM_PRIVATE_KEY_ITEM, //!< KCM private key item type. KCM supports ECC keys with curves defined in palGroupIndex_t (pal_Crypto.h). - KCM_PUBLIC_KEY_ITEM, //!< KCM public key item type. KCM supports ECC keys with curves defined in palGroupIndex_t (pal_Crypto.h). + KCM_PRIVATE_KEY_ITEM, //!< KCM private key item type. KCM supports ECC keys with curves defined in palGroupIndex_t (cs_pal_crypto.h). + KCM_PUBLIC_KEY_ITEM, //!< KCM public key item type. KCM supports ECC keys with curves defined in palGroupIndex_t (cs_pal_crypto.h). KCM_SYMMETRIC_KEY_ITEM, //!< KCM symmetric key item type. KCM_CERTIFICATE_ITEM, //!< KCM certificate item type. Supports x509 certificates in DER format. KCM_CONFIG_ITEM, //!< KCM configuration parameter item type. diff --git a/factory-configurator-client/key-config-manager/source/key_config_manager.c b/factory-configurator-client/key-config-manager/source/key_config_manager.c index 7795b1c7a..19ef6e5ee 100644 --- a/factory-configurator-client/key-config-manager/source/key_config_manager.c +++ b/factory-configurator-client/key-config-manager/source/key_config_manager.c @@ -22,7 +22,7 @@ #ifndef FCC_NANOCLIENT_ENABLED #include "pal.h" #endif -#include "pal_plat_Crypto.h" +#include "cs_pal_plat_crypto.h" #include "cs_utils.h" #include "pv_macros.h" #include "key_slot_allocator.h" @@ -782,7 +782,7 @@ kcm_status_e kcm_generate_random(uint8_t *buffer, size_t buffer_size) return kcm_status; } - +#ifndef MBED_CONF_MBED_CLOUD_CLIENT_PSA_SUPPORT kcm_status_e kcm_ecdh_key_agreement(const uint8_t *private_key_name, size_t private_key_name_len, const uint8_t *peer_public_key, size_t peer_public_key_size, uint8_t *shared_secret, size_t shared_secret_max_size, size_t *shared_secret_act_size_out) { @@ -830,5 +830,6 @@ kcm_status_e kcm_ecdh_key_agreement(const uint8_t *private_key_name, size_t priv return kcm_status; } +#endif diff --git a/factory-configurator-client/mbed-client-esfs/source/include/esfs.h b/factory-configurator-client/mbed-client-esfs/source/include/esfs.h index e8b6335a0..100529731 100644 --- a/factory-configurator-client/mbed-client-esfs/source/include/esfs.h +++ b/factory-configurator-client/mbed-client-esfs/source/include/esfs.h @@ -18,7 +18,7 @@ #include #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" diff --git a/factory-configurator-client/psa-driver/source/psa_driver_crypto.c b/factory-configurator-client/psa-driver/source/psa_driver_crypto.c index ed05c9624..7f4a28aed 100644 --- a/factory-configurator-client/psa-driver/source/psa_driver_crypto.c +++ b/factory-configurator-client/psa-driver/source/psa_driver_crypto.c @@ -75,23 +75,10 @@ static void set_generic_attr(uint32_t extra_flags, psa_key_attributes_t *psa_key } //Set algorithm and usage flags -#if !defined(TARGET_LPC55S69_NS) - /* FIXME - we should skip this if key should be generated into secure element */ - /* FIXME: currently, mbed-os has no SPM (Secure Partitioning Manager) support for LPC55S69_NS platforms. - * that is why we mask the PSA multiple usage for those platforms, however, this workaround should be reverted once mbed-os - * team will add the necessary implementation to support the psa_key_policy_set_enrollment_algorithm API. - */ - // Set policy for ECDH (key agreement) - psa_key_usage |= (PSA_KEY_USAGE_DERIVE); -#endif - // set key usage psa_set_key_usage_flags(psa_key_attr, psa_key_usage); // set key algorithm psa_set_key_algorithm(psa_key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); -#if !defined(TARGET_LPC55S69_NS) - psa_set_key_enrollment_algorithm(psa_key_attr, PSA_ALG_ECDH); -#endif } #ifdef MBED_CONF_MBED_CLOUD_CLIENT_SECURE_ELEMENT_SUPPORT @@ -236,7 +223,7 @@ kcm_status_e psa_drv_crypto_init(void) #ifdef MBED_CONF_MBED_CLOUD_CLIENT_SECURE_ELEMENT_SUPPORT //Register se driver before calling to psa_crypto_init - psa_status = psa_register_se_driver(PSA_DRIVER_SE_DRIVER_LIFETIME_VALUE, g_se_driver_info); + psa_status = psa_register_se_driver(PSA_DRIVER_SE_DRIVER_LOCATION_VALUE, g_se_driver_info); SA_PV_ERR_RECOVERABLE_RETURN_IF((psa_status != PSA_SUCCESS), psa_drv_translate_to_kcm_error(psa_status), "Failed psa_register_se_driver (%" PRIu32 ")", (uint32_t)psa_status); #endif diff --git a/factory-configurator-client/storage/source/storage_non_psa.c b/factory-configurator-client/storage/source/storage_non_psa.c index 26b110936..4b6ccbd9e 100644 --- a/factory-configurator-client/storage/source/storage_non_psa.c +++ b/factory-configurator-client/storage/source/storage_non_psa.c @@ -22,7 +22,7 @@ #include "pv_error_handling.h" #include "fcc_malloc.h" #include "pv_macros.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" /*The function copies certificate chain or single certificate from source to destination (inside storage)*/ static kcm_status_e copy_certificate_chain(const uint8_t *item_name, size_t item_name_len, storage_item_prefix_type_e source_item_prefix_type, storage_item_prefix_type_e destination_item_prefix_type) diff --git a/factory-configurator-client/storage/source/storage_psa.cpp b/factory-configurator-client/storage/source/storage_psa.cpp index 6ec06b4d7..2b5bd1a53 100644 --- a/factory-configurator-client/storage/source/storage_psa.cpp +++ b/factory-configurator-client/storage/source/storage_psa.cpp @@ -21,7 +21,7 @@ #include "pv_error_handling.h" #include "storage_internal.h" #include "pv_macros.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #ifdef TARGET_LIKE_MBED #include "mbed.h" #if !(defined(TARGET_TFM) && (MBED_MAJOR_VERSION > 5)) diff --git a/factory-configurator-client/storage/storage/storage_kcm.h b/factory-configurator-client/storage/storage/storage_kcm.h index 8e925c70e..f9252f752 100644 --- a/factory-configurator-client/storage/storage/storage_kcm.h +++ b/factory-configurator-client/storage/storage/storage_kcm.h @@ -26,7 +26,7 @@ #if defined MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT #include "pal_sst.h" #endif -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #ifdef __cplusplus extern "C" { diff --git a/fota/bspatch_fota_mbed.c b/fota/bspatch_fota_mbed.c index 04648f6d4..741a2c54e 100644 --- a/fota/bspatch_fota_mbed.c +++ b/fota/bspatch_fota_mbed.c @@ -2,9 +2,9 @@ // in order to avoid collision with the ones used in UC-Hub // (due to the nature of mbed-os source file globbing) +#if (defined(__MBED__) || defined(__NANOSIMULATOR__)) && defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) #include "MbedCloudClientConfig.h" -#if (defined(__MBED__) || defined(__NANOSIMULATOR__)) && defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) #include "bspatch/bspatch.c" #include "bspatch/lz4.c" #include "bspatch/varint.c" diff --git a/fota/fota.c b/fota/fota.c index d81b4bba9..337dd9769 100644 --- a/fota/fota.c +++ b/fota/fota.c @@ -29,7 +29,7 @@ #include "fota/fota_source.h" #include "fota/fota_delta.h" #include "fota/fota_app_ifs.h" -#include "fota/fota_platform.h" +#include "fota_platform_hooks.h" #include "fota/fota_nvm.h" #include "fota/fota_block_device.h" #include "fota/fota_crypto.h" @@ -58,7 +58,7 @@ #endif #if defined(TARGET_LIKE_LINUX) -#include "fota_platform_linux.h" +#include "fota/platform/linux/fota_platform_linux.h" #endif #if (MBED_CLOUD_CLIENT_FOTA_RESUME_SUPPORT == FOTA_RESUME_SUPPORT_RESUME) && !FOTA_HEADER_HAS_CANDIDATE_READY @@ -76,6 +76,8 @@ static void fota_on_install_authorize(bool defer); static bool initialized = false; static size_t storage_available; +static bool fota_defer_by_user = false; + // Multicast related variables here should not be part of the FOTA context, as they live also outside of FOTA scope #if (MBED_CLOUD_CLIENT_FOTA_MULTICAST_SUPPORT != FOTA_MULTICAST_UNSUPPORTED) static size_t mc_image_data_addr; @@ -225,12 +227,11 @@ static void abort_update(int ret, const char *msg) fota_source_report_update_result(upd_res); fota_source_report_state(FOTA_SOURCE_STATE_IDLE, NULL, NULL); manifest_delete(); + fota_nvm_fw_encryption_key_delete(); } else { fota_source_report_state(FOTA_SOURCE_STATE_PROCESSING_MANIFEST, NULL, NULL); } - fota_nvm_fw_encryption_key_delete(); - const fota_component_desc_t *comp_desc; fota_component_get_desc(fota_ctx->comp_id, &comp_desc); fota_platform_abort_update_hook(comp_desc->name); @@ -641,6 +642,7 @@ int fota_init(void *m2m_interface, void *resource_list) #endif initialized = true; + FOTA_TRACE_DEBUG("init complete"); return FOTA_STATUS_SUCCESS; @@ -669,6 +671,7 @@ int fota_deinit(void) fota_linux_deinit(); #endif initialized = false; + return FOTA_STATUS_SUCCESS; } @@ -950,6 +953,8 @@ void fota_on_defer(int32_t status) if (!fota_ctx) { return; // gracefully ignore this call if update is not running } + /* mark call to defer only if FOTA is active */ + fota_defer_by_user = true; // for now we assume that defer called always by user app if (fota_ctx->state == FOTA_STATE_AWAIT_INSTALL_AUTHORIZATION) { FOTA_TRACE_INFO("Installation deferred by application."); @@ -1147,7 +1152,7 @@ static int prepare_and_program_header(void) fota_set_header_info_magic(&header_info); header_info.fw_size = fota_ctx->fw_info->installed_size; header_info.version = fota_ctx->fw_info->version; - header_info.external_header_size = (uint16_t)(sizeof(fota_header_info_t) - offsetof(fota_header_info_t,internal_header_barrier)); + header_info.external_header_size = (uint16_t)(sizeof(fota_header_info_t) - offsetof(fota_header_info_t, internal_header_barrier)); memcpy(header_info.digest, fota_ctx->fw_info->installed_digest, FOTA_CRYPTO_HASH_SIZE); memcpy(header_info.precursor, fota_ctx->fw_info->precursor_digest, FOTA_CRYPTO_HASH_SIZE); memcpy(header_info.vendor_data, fota_ctx->fw_info->vendor_data, FOTA_MANIFEST_VENDOR_DATA_SIZE); @@ -1381,7 +1386,7 @@ static int analyze_resume_state(fota_state_e *next_fota_state) static int calc_and_erase_needed_storage() { int ret; - size_t storage_needed = 0, erase_size, total_erase_size; + size_t storage_needed = 0, erase_size, total_erase_size, end_addr; if (fota_ctx) { // Calculate needed space for FW data in storage: @@ -1427,12 +1432,16 @@ static int calc_and_erase_needed_storage() return FOTA_STATUS_INSUFFICIENT_STORAGE; } - ret = fota_bd_get_erase_size(fota_candidate_get_config()->storage_start_addr + storage_needed - 1, &erase_size); + end_addr = fota_candidate_get_config()->storage_start_addr + storage_needed; + ret = fota_bd_get_erase_size(end_addr - 1, &erase_size); if (ret) { FOTA_TRACE_ERROR("Get erase size failed %d", ret); return ret; } - total_erase_size = FOTA_ALIGN_UP(storage_needed, erase_size); + + // Align erase size to the end of last sector + total_erase_size = end_addr % erase_size ? FOTA_ALIGN_DOWN(end_addr, erase_size) + erase_size - fota_candidate_get_config()->storage_start_addr : + storage_needed; FOTA_TRACE_DEBUG("Erasing storage at %zu, size %zu", fota_candidate_get_config()->storage_start_addr, total_erase_size); ret = fota_bd_erase(fota_candidate_get_config()->storage_start_addr, total_erase_size); if (ret) { @@ -1655,7 +1664,7 @@ void fota_on_authorize(int32_t status) FOTA_ASSERT( (fota_ctx->state == FOTA_STATE_AWAIT_DOWNLOAD_AUTHORIZATION) || (fota_ctx->state == FOTA_STATE_AWAIT_INSTALL_AUTHORIZATION) - ) + ); if (fota_ctx->state == FOTA_STATE_AWAIT_INSTALL_AUTHORIZATION) { FOTA_TRACE_INFO("Install authorization granted."); @@ -1984,14 +1993,33 @@ void fota_on_fragment(uint8_t *buf, size_t size) } -void fota_on_resume(int32_t status) +void fota_on_resume(int32_t param) { #if (MBED_CLOUD_CLIENT_FOTA_RESUME_SUPPORT != FOTA_RESUME_UNSUPPORTED) - (void)status; // unused + + bool fota_resume_by_user = !param; // param=0 - called from user app + // param=1 - called from internal flow + if (fota_ctx) { + /* + * FOTA context exists therefore defer was not called. Got here because of internal resume event, continue update + */ + FOTA_TRACE_DEBUG("FOTA already running"); return; // FOTA is already running - ignore } + FOTA_TRACE_INFO("fota_on_resume - resume by %u", fota_resume_by_user); + + //if we got here, there is no fota context: + // either defer was called or context was deleted because of internal error + if ((fota_defer_by_user == true) && (fota_resume_by_user == false)) { + /* fota was deferred by user app and resume was called from internal flow + * ignore the resume for now and wait for call from user app + */ + FOTA_TRACE_INFO("Internal resume followed by user app defer - abort!"); + return; // don't resume now, wait for explicit user call for resume + } + size_t manifest_size; uint8_t *manifest = calloc(1, FOTA_MANIFEST_MAX_SIZE); @@ -2016,6 +2044,7 @@ void fota_on_resume(int32_t status) if (ret) { FOTA_TRACE_ERROR("failed to load manifest from NVM (ret code %d) - update resume aborted.", ret); } + fota_defer_by_user = false; //resume completed, remove the flag #endif } diff --git a/fota/fota_app_ifs.c b/fota/fota_app_ifs.c index add9ca855..ff4e72483 100644 --- a/fota/fota_app_ifs.c +++ b/fota/fota_app_ifs.c @@ -53,7 +53,7 @@ void fota_app_defer() void fota_app_resume(void) { - fota_event_handler_defer_with_result_ignore_busy(fota_on_resume, 0); + fota_event_handler_defer_with_result_ignore_busy(fota_on_resume, /*fota resume by user app */ 0); } #if defined (FOTA_DEFAULT_APP_IFS) && FOTA_DEFAULT_APP_IFS==1 diff --git a/fota/fota_app_ifs.h b/fota/fota_app_ifs.h index f0548a9ba..a68732018 100644 --- a/fota/fota_app_ifs.h +++ b/fota/fota_app_ifs.h @@ -42,13 +42,16 @@ extern "C" { /** * FOTA download authorization callback to be implemented by the device application. * - * Should be implemented by the application if it wants to authorize FOTA to start downloading the candidate image. + * The application must implement this callback if you want the application to authorize the FOTA client to start downloading the candidate image. + * The client invokes this callback for the first time when the device receives the update manifest from Device Management. * * FOTA expects the callback implementation to call one of these APIs: - * - ::fota_app_authorize() - Authorize request to download image. - * - ::fota_app_reject() - Reject request to download image and discard the manifest. The update will not be re-prompted. - * - ::fota_app_defer() - Defer image download to a later phase. This aborts the current update attempt, while preserving the update manifest. - * Update will be restarted on next boot. Alternatively update can be restarted by calling ::fota_app_resume(). + * - ::fota_app_authorize() - Authorize request to download image. The download phase will proceed. + * - ::fota_app_reject() - Reject request to download image and discard the manifest. The client will not re-prompt the update. + * - ::fota_app_defer() - Defer image download to a later phase. This aborts the current image download attempt, while preserving the update manifest. + * Image download continues on the next boot after device registration or when the device application calls the :fota_app_resume() API. + * The client invokes ::fota_app_on_download_authorization when the update flow continues. + * Both ::fota_app_defer() and ::fota_app_resume() APIs are implemented only if the ::MBED_CLOUD_CLIENT_FOTA_RESUME_SUPPORT build flag is not equal to ::FOTA_RESUME_UNSUPPORTED. * * \note Only required if the ::MBED_CLOUD_CLIENT_FOTA_ENABLE build flag is specified. * \note Only required if the ::FOTA_DEFAULT_APP_IFS build flag is disabled. @@ -69,16 +72,20 @@ int fota_app_on_download_authorization( * Pelion FOTA install authorization callback to be implemented by the device application. * * Should be implemented by the application if it wants to authorize FOTA to install the update. + * The client invokes this callback for the first time when the device fully downloads the update candidate image. * * FOTA client expects the callback implementation to call one of these APIs: * - ::fota_app_authorize() - Authorize FOTA to install the candidate image. Reboot or connectivity loss may occur during installation. - * This phase is critical because power loss can brick the device. + * This phase is critical because power loss can brick the device. * - ::fota_app_reject() - Reject request to install, and discard the update. The update will not be re-prompted. * - ::fota_app_defer() - Defer the installation to a later phase. This marks the candidate image as valid, but the device will not reboot. + * For the main component, the installation proceeds automatically after the device reboots. + * For user components, the update flow proceeds on the next boot after device registration or when the device application calls the ::fota_app_resume() API. + * The application invokes the ::fota_app_on_download_authorization and ::fota_app_on_install_authorization() callbacks when the update flow proceeds. + * The client implements the ::fota_app_defer() and ::fota_app_resume() APIs only if the ::MBED_CLOUD_CLIENT_FOTA_RESUME_SUPPORT build flag is not equal to ::FOTA_RESUME_UNSUPPORTED. * * \note Only required if the ::MBED_CLOUD_CLIENT_FOTA_ENABLE build flag is specified. * \note Only required if the ::FOTA_DEFAULT_APP_IFS build flag is disabled. - * \note After the application defers installation by calling ::fota_app_defer(), the device has to reboot before installing the candidate image. Calling ::fota_app_resume() after ::fota_app_defer() has no effect. * * \return ::FOTA_STATUS_SUCCESS to acknowledge that the application received the authorization callback properly. */ @@ -103,8 +110,14 @@ int fota_app_on_complete(int32_t status); /** * Resume Pelion FOTA update. * - * If the update process is interrupted, the application can call this function to restart the process. - */ + * If the update process is interrupted, the application can call this function to resume the process. + * This API invokes ::fota_app_on_download_authorization() CB. + * + * \note The function is implemented only if ::MBED_CLOUD_CLIENT_FOTA_RESUME_SUPPORT build flag is not equal to ::FOTA_RESUME_UNSUPPORTED. + * \note If ::MBED_CLOUD_CLIENT_FOTA_RESUME_SUPPORT build flag is equal to ::FOTA_RESUME_SUPPORT_RESTART, the update flow will restart from the beginning. + * \note If ::MBED_CLOUD_CLIENT_FOTA_RESUME_SUPPORT build flag is equal to ::FOTA_RESUME_SUPPORT_RESUME, the update flow will resume from the point that it was interrupted. + * + */ void fota_app_resume(void); /** @@ -118,7 +131,7 @@ void fota_app_authorize(void); /** * Reject Pelion FOTA update. * - * FOTA client expects the ::fota_app_on_download_authorization() and ::fota_app_on_install_authorization() application callbacks to call this API. + * ::fota_app_on_download_authorization() and ::fota_app_on_install_authorization() application callbacks may call this API. * * \param[in] reason Reject reason code. */ @@ -127,9 +140,11 @@ void fota_app_reject(int32_t reason); /** * Defer Pelion FOTA update. * - * FOTA client resources will be released and update will be reattempted on next boot or by - * calling the ::fota_app_resume() API. - * FOTA client expects the ::fota_app_on_download_authorization() and ::fota_app_on_install_authorization() application callbacks to call this API. + * The FOTA client releases resources and reattempts the update on the next boot after device registration or when the device application calls + * the ::fota_app_resume() API. + * ::fota_app_on_download_authorization() and ::fota_app_on_install_authorization() application callbacks may call this API. + * + * \note The function is implemented only if ::MBED_CLOUD_CLIENT_FOTA_RESUME_SUPPORT build flag is not equal to ::FOTA_RESUME_UNSUPPORTED. */ void fota_app_defer(void); @@ -183,12 +198,12 @@ int fota_app_on_install_candidate(const char *candidate_fs_name, const manifest_ #if defined(MBED_CLOUD_CLIENT_FOTA_LINUX_SINGLE_MAIN_FILE) /** - * Install MAIN application by overwriting current executable file. + * Install main application by overwriting current executable file. * - * This function will overwrite the executable file and relaunch the process. - * The API is expected to be called from ::fota_app_on_install_candidate() application - * callback. - * It is only available in case of a single main file mode. + * This function overwrites the executable file and relaunches the process. + * The client expects the ::fota_app_on_install_candidate() application + * callback to call this API. + * It is only available if there is a single main file. * * \note This function does not validate candidate file integrity or authenticity. * diff --git a/fota/fota_base.h b/fota/fota_base.h index 8575b72a3..e0c85ab56 100644 --- a/fota/fota_base.h +++ b/fota/fota_base.h @@ -76,7 +76,10 @@ extern "C" { #endif #if !defined(FOTA_HALT) -#if defined(TARGET_LIKE_LINUX) +#if defined(FOTA_UNIT_TEST) +void unitest_halt(void); +#define FOTA_HALT unitest_halt() +#elif defined(TARGET_LIKE_LINUX) #define FOTA_HALT assert(0) #else #define FOTA_HALT for(;;) diff --git a/fota/fota_block_device.h b/fota/fota_block_device.h index bb5d8cc22..4dd3017df 100644 --- a/fota/fota_block_device.h +++ b/fota/fota_block_device.h @@ -130,6 +130,17 @@ int fota_bd_get_erase_size(size_t addr, size_t *erase_size); */ int fota_bd_get_erase_value(int *erase_value); +/** + * Pelion FOTA block device translate physical address to logical one. + * It is required that block device addresses will be continuous and start from 0. + * In most devices, this is the case and this function should simply return the physical address. + * Devices like like internal flash, where addresses don't start from 0. require a less trivial translation logic. + * + * \param[in] phys_addr Physical address. + * \return Logical address + */ +size_t fota_bd_physical_addr_to_logical_addr(size_t phys_addr); + #ifdef __cplusplus } #endif diff --git a/fota/fota_candidate.c b/fota/fota_candidate.c index 4a97bbfda..362809779 100644 --- a/fota/fota_candidate.c +++ b/fota/fota_candidate.c @@ -57,8 +57,6 @@ static fota_candidate_config_t fota_candidate_config = { static candidate_contex_t *ctx = NULL; -uint32_t fota_bd_physical_addr_to_logical_addr(uint32_t phys_addr); - void fota_candidate_set_config(fota_candidate_config_t *in_fota_candidate_config) { FOTA_ASSERT(in_fota_candidate_config->storage_size); @@ -167,7 +165,7 @@ int fota_candidate_read_header(size_t *addr, uint32_t bd_read_size, uint32_t bd_ goto end; } - if (header_size < header->external_header_size + offsetof(fota_header_info_t, internal_header_barrier)){ + if (header_size < header->external_header_size + offsetof(fota_header_info_t, internal_header_barrier)) { *addr += FOTA_ALIGN_UP(header->external_header_size + offsetof(fota_header_info_t, internal_header_barrier), bd_prog_size); } else { *addr += FOTA_ALIGN_UP(header_size, bd_prog_size); diff --git a/fota/fota_component.c b/fota/fota_component.c index 433bbfc8a..5f9c5cd69 100644 --- a/fota/fota_component.c +++ b/fota/fota_component.c @@ -96,24 +96,43 @@ int fota_component_add(const fota_component_desc_info_t *comp_desc_info, const c fota_component_desc_t *comp_table = user_comp_table; unsigned int *num_components = &num_user_components; - FOTA_ASSERT(comp_name); - FOTA_ASSERT(!(comp_desc_info->support_delta && (!comp_desc_info->curr_fw_get_digest || !comp_desc_info->curr_fw_read))); - + if (!comp_name) { + FOTA_TRACE_ERROR("Empty component name"); + return FOTA_STATUS_INVALID_ARGUMENT; + } + if (comp_desc_info->support_delta && (!comp_desc_info->curr_fw_get_digest || !comp_desc_info->curr_fw_read)) { + FOTA_TRACE_ERROR("empty fields in component description"); + return FOTA_STATUS_INVALID_ARGUMENT; + } + #ifdef FOTA_INTERNAL_COMPONENTS_SUPPORT if (comp_name[0] == '%') { comp_table = malloc((num_int_components + 1) * sizeof(fota_component_desc_t)); - FOTA_ASSERT(comp_table); + if (!comp_table) { + FOTA_TRACE_ERROR("comp_table wasn't allocated"); + return FOTA_STATUS_OUT_OF_MEMORY; + } memcpy(comp_table, int_comp_table, num_int_components * sizeof(fota_component_desc_t)); free(int_comp_table); int_comp_table = comp_table; num_components = &num_int_components; } else { - FOTA_ASSERT(*num_components < FOTA_NUM_COMPONENTS); + if (*num_components > FOTA_NUM_COMPONENTS) { + FOTA_TRACE_ERROR("Wrong number of components"); + return FOTA_STATUS_INVALID_ARGUMENT; + } } #else - FOTA_ASSERT(*num_components < FOTA_NUM_COMPONENTS); + if (*num_components > FOTA_NUM_COMPONENTS) { + FOTA_TRACE_ERROR("Wrong number of components"); + return FOTA_STATUS_INVALID_ARGUMENT; + } #endif + if (comp_desc_info->need_reboot == false && comp_table == user_comp_table){ + FOTA_TRACE_ERROR("Component with need_reboot false is not supported"); + return FOTA_STATUS_INVALID_ARGUMENT; + } memcpy(&comp_table[*num_components].desc_info, comp_desc_info, sizeof(*comp_desc_info)); strncpy(comp_table[*num_components].name, comp_name, FOTA_COMPONENT_MAX_NAME_SIZE - 1); fota_component_version_semver_to_int(comp_semver, &comp_table[*num_components].version); @@ -136,7 +155,7 @@ void fota_component_get_desc(unsigned int comp_id, const fota_component_desc_t * comp_id_translate(&comp_id, &comp_table, &num_components); #endif - FOTA_ASSERT(comp_id < num_components) + FOTA_ASSERT(comp_id < num_components); *comp_desc = &comp_table[comp_id]; } @@ -148,7 +167,7 @@ void fota_component_get_curr_version(unsigned int comp_id, fota_component_versio #ifdef FOTA_INTERNAL_COMPONENTS_SUPPORT comp_id_translate(&comp_id, &comp_table, &num_components); #endif - FOTA_ASSERT(comp_id < num_components) + FOTA_ASSERT(comp_id < num_components); *version = comp_table[comp_id].version; } @@ -160,7 +179,7 @@ void fota_component_set_curr_version(unsigned int comp_id, fota_component_versio #ifdef FOTA_INTERNAL_COMPONENTS_SUPPORT comp_id_translate(&comp_id, &comp_table, &num_components); #endif - FOTA_ASSERT(comp_id < num_components) + FOTA_ASSERT(comp_id < num_components); comp_table[comp_id].version = version; } diff --git a/fota/fota_component.h b/fota/fota_component.h index 0faa86b03..f824926d4 100644 --- a/fota/fota_component.h +++ b/fota/fota_component.h @@ -79,6 +79,7 @@ typedef int (*fota_component_verify_install_handler_t)(const char *comp_name, co * @param install_alignment The preferred installer fragment size. Typically equal to the flash program size. * @param support_delta Specify whether the component supports differential (delta) update. * @param need_reboot Specify whether the component requires system reboot after the component installation has completed. + Only `true` parameter is currently supported. * @param candidate_iterate_cb A callback function the FOTA client calls for installing the candidate. * The FOTA client calls the callback iteratively with a firmware fragment buffer pointer as an argument. * Note: For Linux systems, this iterative callback is replaced by ::fota_app_on_install_candidate(). diff --git a/fota/fota_config.h b/fota/fota_config.h index 19547a822..0cf376bd3 100644 --- a/fota/fota_config.h +++ b/fota/fota_config.h @@ -157,21 +157,12 @@ extern char *program_invocation_name; #define MBED_CLOUD_CLIENT_FOTA_LINUX_CURR_FW_FILENAME program_invocation_name #endif -#if defined(FOTA_CUSTOM_CURR_FW_STRUCTURE) && FOTA_CUSTOM_CURR_FW_STRUCTURE -#error Custom current firmware structure should not be defined in Linux targets. -#endif - // No legacy bootloader here - force up to date header #undef MBED_CLOUD_CLIENT_FOTA_FW_HEADER_VERSION #define MBED_CLOUD_CLIENT_FOTA_FW_HEADER_VERSION 3 #endif // defined(TARGET_LIKE_LINUX) - -#if !defined(FOTA_CUSTOM_CURR_FW_STRUCTURE) && !defined(__MBED__) && !defined(FOTA_UNIT_TEST) && !defined(TARGET_LIKE_LINUX) -#define FOTA_CUSTOM_CURR_FW_STRUCTURE 1 -#endif - // Set this flag to 1 to use custom verification logic for main app installation #if !defined(FOTA_CUSTOM_MAIN_APP_VERIFY_INSTALL) // Use default verification logic otherwise @@ -261,8 +252,8 @@ extern char *program_invocation_name; #endif #if (MBED_CLOUD_CLIENT_FOTA_KEY_ENCRYPTION == FOTA_USE_DEVICE_KEY) -#if (MBED_CLOUD_CLIENT_FOTA_ENCRYPTION_SUPPORT == 0) || !defined(__MBED__) -#error FOTA_USE_DEVICE_KEY should be used only for with __MBED__ with encryption enabled +#if (MBED_CLOUD_CLIENT_FOTA_ENCRYPTION_SUPPORT == 0) || (!(defined(MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT)) && !(defined(__MBED__))) +#error FOTA_USE_DEVICE_KEY should be used only for with MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT or __MBED__ with encryption enabled #endif #endif diff --git a/fota/fota_crypto.c b/fota/fota_crypto.c index d4686dcba..67acd221a 100644 --- a/fota/fota_crypto.c +++ b/fota/fota_crypto.c @@ -557,7 +557,13 @@ int fota_verify_signature_prehashed( mbedtls_x509_crt_init(&crt); +/*mbedtls_x509_crt_parse_der_nocopy not supported for mbedtls 2.16.0 and lower versions, + use older version of x509 cert parse function */ +#if (MBEDTLS_VERSION_NUMBER < 0x02110000) + ret = mbedtls_x509_crt_parse_der( +#else ret = mbedtls_x509_crt_parse_der_nocopy( +#endif &crt, update_crt_data, update_crt_size ); diff --git a/fota/fota_curr_fw.h b/fota/fota_curr_fw.h index 83853f80d..363541646 100644 --- a/fota/fota_curr_fw.h +++ b/fota/fota_curr_fw.h @@ -32,26 +32,9 @@ extern "C" { /** * @file fota_curr_fw.h * \brief FOTA requires access to the currently installed firmware (FW) and the FW metadata header. - * By default, on non-Mbed-OS targets, the FOTA library assumes a custom FW layout structure and expects that the application will implement the current FW interfaces described in this file. - * If the FW image and the FW header reside in a memory mapped flash, you can define the ::FOTA_CUSTOM_CURR_FW_STRUCTURE=0 macro, in which case, the application only has to implement these functions: - * uint8_t *fota_curr_fw_get_app_start_addr(void) - * uint8_t *fota_curr_fw_get_app_header_addr(void) + * Support code for each platform should implement the current FW interfaces described in this file. */ -/** - * Returns a pointer to the application start. - * - * \return Pointer to the application start. - */ -uint8_t *fota_curr_fw_get_app_start_addr(void); - -/** - * Returns a pointer to the header start. - * - * \return Pointers to the header start. - */ -uint8_t *fota_curr_fw_get_app_header_addr(void); - /** * Reads the header of the current firmware. * diff --git a/fota/fota_device_key.cpp b/fota/fota_device_key.cpp index 7449c108a..4471205c3 100644 --- a/fota/fota_device_key.cpp +++ b/fota/fota_device_key.cpp @@ -23,15 +23,14 @@ #include "fota/fota_crypto_defs.h" #include "fota/fota_status.h" -#ifdef __MBED__ - // fota_get_device_key_128bit in use only in case defined MBED_CLOUD_CLIENT_FOTA_KEY_ENCRYPTION == FOTA_USE_DEVICE_KEY or external legacy header #if ((MBED_CLOUD_CLIENT_FOTA_FW_HEADER_VERSION == 2) && (MBED_CLOUD_CLIENT_FOTA_FW_HEADER_EXTERNAL == 1)) || (MBED_CLOUD_CLIENT_FOTA_KEY_ENCRYPTION == FOTA_USE_DEVICE_KEY) +#include "kv_config.h" #include "KVMap.h" -#include "mbed.h" #include "TDBStore.h" -#include "DeviceKey.h" + +using namespace mbed; extern "C" int8_t fota_get_device_key_128bit(uint8_t *key, uint32_t keyLenBytes) { @@ -64,5 +63,4 @@ extern "C" int8_t fota_get_device_key_128bit(uint8_t *key, uint32_t keyLenBytes) } #endif // #if ((MBED_CLOUD_CLIENT_FOTA_FW_HEADER_VERSION == 2) && (MBED_CLOUD_CLIENT_FOTA_FW_HEADER_EXTERNAL == 1)) || (MBED_CLOUD_CLIENT_FOTA_KEY_ENCRYPTION == FOTA_USE_DEVICE_KEY) -#endif // #ifdef __MBED__ #endif //MBED_CLOUD_CLIENT_FOTA_ENABLE diff --git a/fota/fota_event_handler.c b/fota/fota_event_handler.c index d70d4ef02..f457e92c8 100644 --- a/fota/fota_event_handler.c +++ b/fota/fota_event_handler.c @@ -20,6 +20,9 @@ #ifdef MBED_CLOUD_CLIENT_FOTA_ENABLE +// TODO: Replace this with a proper define +#if !defined(FOTA_UNIT_TEST) + #define TRACE_GROUP "FOTA" #include @@ -195,4 +198,5 @@ void fota_event_handler_defer_with_result_ignore_busy( } } +#endif // !defined(FOTA_UNIT_TEST) #endif // MBED_CLOUD_CLIENT_FOTA_ENABLE diff --git a/fota/fota_event_handler.h b/fota/fota_event_handler.h index 077b86cd8..4a4c296d9 100644 --- a/fota/fota_event_handler.h +++ b/fota/fota_event_handler.h @@ -29,7 +29,7 @@ extern "C" { #include "fota_internal.h" typedef void (*fota_deferred_data_callabck_t)(uint8_t *data, size_t size); -typedef void (*fota_deferred_result_callabck_t)(int32_t status); +typedef void (*fota_deferred_result_callabck_t)(int32_t param); /* * Initialize event handler diff --git a/fota/fota_internal.h b/fota/fota_internal.h index 9a2faee16..2ae201d61 100644 --- a/fota/fota_internal.h +++ b/fota/fota_internal.h @@ -100,7 +100,7 @@ void fota_on_defer(int32_t status); void fota_on_authorize(int32_t status); void fota_on_fragment(uint8_t *buf, size_t size); void fota_on_fragment_failure(int32_t status); -void fota_on_resume(int32_t status); +void fota_on_resume(int32_t param); #ifdef __cplusplus } #endif diff --git a/fota/fota_internal_ifs.c b/fota/fota_internal_ifs.c new file mode 100644 index 000000000..73a2e53a8 --- /dev/null +++ b/fota/fota_internal_ifs.c @@ -0,0 +1,30 @@ +// ---------------------------------------------------------------------------- +// Copyright 2021 Pelion Ltd. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------- + +#include "fota_internal_ifs.h" + +#ifdef MBED_CLOUD_CLIENT_FOTA_ENABLE + +#include "fota/fota_event_handler.h" + +void fota_internal_resume() +{ + fota_event_handler_defer_with_result_ignore_busy(fota_on_resume, /*fota resume by internal flow */ 1); +} + +#endif diff --git a/fota/fota_internal_ifs.h b/fota/fota_internal_ifs.h new file mode 100644 index 000000000..e74479aec --- /dev/null +++ b/fota/fota_internal_ifs.h @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------- +// Copyright 2021 Pelion Ltd. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------- + +#ifndef __FOTA_INTERNAL_IFS_H_ +#define __FOTA_INTERNAL_IFS_H_ + +#include "fota/fota_config.h" + +#if defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Resume Pelion FOTA update - internal + * + * If the update process is interrupted, the interal flow can call this function to resume the process. + */ +void fota_internal_resume(void); + + +#ifdef __cplusplus +} +#endif + +#endif // (MBED_CLOUD_CLIENT_FOTA_ENABLE) + +#endif // __FOTA_INTERNAL_IFS_H_ diff --git a/fota/fota_nvm.c b/fota/fota_nvm.c index c36185f0f..5d3e56fdd 100644 --- a/fota/fota_nvm.c +++ b/fota/fota_nvm.c @@ -20,6 +20,9 @@ #ifdef MBED_CLOUD_CLIENT_FOTA_ENABLE +// TODO: Replace this with a proper define +#if !defined(FOTA_UNIT_TEST) + #define TRACE_GROUP "FOTA" #include "fota/fota_status.h" @@ -52,6 +55,7 @@ static fota_status_e map_store_result(int result) return res; } + #if (MBED_CLOUD_CLIENT_PROFILE == MBED_CLOUD_CLIENT_PROFILE_FULL) int fota_nvm_get(cloud_client_param key, uint8_t *buffer, size_t buffer_size, size_t *bytes_read, ccs_item_type_e item_type) { @@ -104,10 +108,8 @@ int fota_nvm_remove(cloud_client_param key, ccs_item_type_e item_type) return map_store_result(status); } - #endif // (MBED_CLOUD_CLIENT_PROFILE == MBED_CLOUD_CLIENT_PROFILE_FULL) - #if !defined(FOTA_KEY_ENCRYPTION_EXTERNAL_STORAGE) int fota_nvm_fw_encryption_key_get(uint8_t buffer[FOTA_ENCRYPT_KEY_SIZE]) { @@ -372,4 +374,5 @@ int fota_nvm_comp_version_get(const char *comp_name, fota_component_version_t *v return fota_nvm_get(key, (uint8_t *)version, sizeof(*version), &bytes_read, CCS_CONFIG_ITEM); } +#endif //!defined(FOTA_UNIT_TEST) #endif // MBED_CLOUD_CLIENT_FOTA_ENABLE diff --git a/fota/fota_platform.h b/fota/fota_platform_hooks.h similarity index 98% rename from fota/fota_platform.h rename to fota/fota_platform_hooks.h index 88d3ec78a..f292c206b 100644 --- a/fota/fota_platform.h +++ b/fota/fota_platform_hooks.h @@ -30,7 +30,7 @@ extern "C" { #endif /** - * @file fota_platform.h + * @file fota_platform_hooks.h * \brief Platform hooks that the platform can implement if the target requires more complex FOTA initialization and teardown steps. * By default, Pelion FOTA provides an empty implementation for these hooks. * An application developer can override these hooks by injecting the ::FOTA_CUSTOM_PLATFORM macro to the build and implementing all the callback functions listed below. diff --git a/fota/fota_platform_default.c b/fota/fota_platform_hooks_default.c similarity index 97% rename from fota/fota_platform_default.c rename to fota/fota_platform_hooks_default.c index bd16998c6..e4d1400a4 100644 --- a/fota/fota_platform_default.c +++ b/fota/fota_platform_hooks_default.c @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // ---------------------------------------------------------------------------- -#include "fota_platform.h" +#include "fota_platform_hooks.h" #if defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) diff --git a/fota/fota_source_profile_full.cpp b/fota/fota_source_profile_full.cpp index 6983508f1..0092b7ed0 100644 --- a/fota/fota_source_profile_full.cpp +++ b/fota/fota_source_profile_full.cpp @@ -19,7 +19,7 @@ #include "fota/fota_base.h" #ifdef MBED_CLOUD_CLIENT_FOTA_ENABLE -#if (MBED_CLOUD_CLIENT_PROFILE == MBED_CLOUD_CLIENT_PROFILE_FULL) +#if (MBED_CLOUD_CLIENT_PROFILE == MBED_CLOUD_CLIENT_PROFILE_FULL) && !defined(FOTA_UNIT_TEST) #define TRACE_GROUP "FOTA" @@ -303,11 +303,11 @@ int fota_source_init( bin_to_hex_string(curr_fw_digest, FOTA_CRYPTO_HASH_SIZE, str_digest, FOTA_CRYPTO_HASH_SIZE * 2 + 1); M2MResource *pkg_name_resource = lwm2m_object_instance->create_dynamic_resource( - "5", - "PkgName", - M2MResourceInstance::STRING, - false // observable - ); + "5", + "PkgName", + M2MResourceInstance::STRING, + false // observable + ); FOTA_ASSERT(pkg_name_resource); pkg_name_resource->set_operation(M2MBase::GET_ALLOWED); pkg_name_resource->set_value(str_digest, curr_fw_digest_size); @@ -318,11 +318,11 @@ int fota_source_init( // Create package version resource /10252/0/6 FOTA_TRACE_DEBUG("Announcing version is %" PRIu64, curr_fw_version); M2MResource *pkg_version_resource = lwm2m_object_instance->create_dynamic_resource( - "6", - "PkgVersion", - M2MResourceInstance::INTEGER, - false // observable - ); + "6", + "PkgVersion", + M2MResourceInstance::INTEGER, + false // observable + ); FOTA_ASSERT(pkg_version_resource); pkg_version_resource->set_operation(M2MBase::GET_ALLOWED); pkg_version_resource->set_value(curr_fw_version); @@ -378,7 +378,7 @@ int fota_source_init( #if (FOTA_SOURCE_LEGACY_OBJECTS_REPORT == 0) // Create g_component_lwm2m_object = M2MInterfaceFactory::create_object("14"); - FOTA_ASSERT(g_component_lwm2m_object ); + FOTA_ASSERT(g_component_lwm2m_object); m2m_object_list->push_back(g_component_lwm2m_object); #endif diff --git a/fota/fota_status.h b/fota/fota_status.h index bfa94d4e9..41428de1f 100644 --- a/fota/fota_status.h +++ b/fota/fota_status.h @@ -63,6 +63,7 @@ typedef enum { FOTA_STATUS_RESOURCE_BUSY = -85, /**< Resource (typically storage) is busy */ FOTA_STATUS_MULTICAST_UPDATE_ABORTED = -86, /**< Received abort request from Multicast */ FOTA_STATUS_MULTICAST_UPDATE_ACTIVATED = -87, /**< Received abort request or new manifest from Multicast, when previous one was activated*/ + FOTA_STATUS_INVALID_ARGUMENT = -88 /**< Invalid argument was received */ } fota_status_e; diff --git a/fota/import_ref.txt b/fota/import_ref.txt index 78206e02a..a1fa4e7c0 100644 --- a/fota/import_ref.txt +++ b/fota/import_ref.txt @@ -1 +1 @@ -Imported from origin/nanoclient at hash: 6f7eaea4f420967339ce6d47721f8e120a408cb5 +Imported from nanoclient at hash: 030df6546e99d8b1ccbf97361e48a7b4220156b7 diff --git a/fota/platform/linux/.mbedignore b/fota/platform/linux/.mbedignore new file mode 100644 index 000000000..72e8ffc0d --- /dev/null +++ b/fota/platform/linux/.mbedignore @@ -0,0 +1 @@ +* diff --git a/fota/fota_block_device_linux.c b/fota/platform/linux/fota_block_device_linux.c similarity index 98% rename from fota/fota_block_device_linux.c rename to fota/platform/linux/fota_block_device_linux.c index 829413607..545faaa56 100644 --- a/fota/fota_block_device_linux.c +++ b/fota/platform/linux/fota_block_device_linux.c @@ -217,6 +217,11 @@ int fota_bd_get_erase_value(int *erase_value) return FOTA_STATUS_SUCCESS; } +size_t fota_bd_physical_addr_to_logical_addr(size_t phys_addr) +{ + return phys_addr; +} + #endif // (MBED_CLOUD_CLIENT_FOTA_BLOCK_DEVICE_TYPE != FOTA_EXTERNAL_BD) #endif // defined(TARGET_LIKE_LINUX) #endif // MBED_CLOUD_CLIENT_FOTA_ENABLE diff --git a/fota/fota_curr_fw_linux.c b/fota/platform/linux/fota_curr_fw_linux.c similarity index 100% rename from fota/fota_curr_fw_linux.c rename to fota/platform/linux/fota_curr_fw_linux.c diff --git a/fota/fota_curr_fw_linux.h b/fota/platform/linux/fota_curr_fw_linux.h similarity index 100% rename from fota/fota_curr_fw_linux.h rename to fota/platform/linux/fota_curr_fw_linux.h diff --git a/fota/fota_platform_linux.c b/fota/platform/linux/fota_platform_linux.c similarity index 97% rename from fota/fota_platform_linux.c rename to fota/platform/linux/fota_platform_linux.c index 7e22434fa..5085cbdaf 100644 --- a/fota/fota_platform_linux.c +++ b/fota/platform/linux/fota_platform_linux.c @@ -63,8 +63,8 @@ static void set_full_file_name(char **var, const char *base) #if MBED_CLOUD_CLIENT_FOTA_SUPPORT_PAL // In yocto, header file and temp header file reside in primary pal partition (mnt/config),and defined in fota_config.h as a simple file name. // The candidate and raw candidate files reside in /mnt/cache directory and defined as a full path. - - // If fota file starts with '/' -> its already have a full path, we don't need to build full file name. + + // If fota file starts with '/' - its already have a full path, we don't need to build full file name if (base[0] != '/') { char primary[PAL_MAX_FILE_AND_FOLDER_LENGTH]; pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, primary); @@ -249,7 +249,7 @@ int fota_linux_init() // Header completely invalid - regenerate it from scratch memset(&header_info, 0, sizeof(header_info)); - if( fota_component_version_semver_to_int(INIT_MAIN_VERSION, &header_info.version)){ + if (fota_component_version_semver_to_int(INIT_MAIN_VERSION, &header_info.version)) { FOTA_TRACE_ERROR("Invalid initial version " INIT_MAIN_VERSION); FOTA_ASSERT(!status); } diff --git a/fota/fota_platform_linux.h b/fota/platform/linux/fota_platform_linux.h similarity index 100% rename from fota/fota_platform_linux.h rename to fota/platform/linux/fota_platform_linux.h diff --git a/fota/fota_block_device.cpp b/fota/platform/mbed-os/fota_block_device_mbed_os.cpp similarity index 97% rename from fota/fota_block_device.cpp rename to fota/platform/mbed-os/fota_block_device_mbed_os.cpp index 27d901258..7f9420f5c 100644 --- a/fota/fota_block_device.cpp +++ b/fota/platform/mbed-os/fota_block_device_mbed_os.cpp @@ -28,6 +28,7 @@ // External BD should supply all these APIs #if (MBED_CLOUD_CLIENT_FOTA_BLOCK_DEVICE_TYPE != FOTA_EXTERNAL_BD) +#if defined(__MBED__) static bool initialized = false; @@ -183,12 +184,6 @@ int fota_bd_get_erase_value(int *erase_value) return FOTA_STATUS_SUCCESS; } -#ifdef __cplusplus -} -#endif - -#endif // (MBED_CLOUD_CLIENT_FOTA_BLOCK_DEVICE_TYPE != FOTA_EXTERNAL_BD) - static bool is_internal_flash_bd() { #if (MBED_CLOUD_CLIENT_FOTA_BLOCK_DEVICE_TYPE == FOTA_INTERNAL_FLASH_MBED_OS_BD) @@ -205,7 +200,7 @@ static bool is_internal_flash_bd() #endif } -extern "C" size_t fota_bd_physical_addr_to_logical_addr(size_t phys_addr) +size_t fota_bd_physical_addr_to_logical_addr(size_t phys_addr) { #ifdef __MBED__ if (is_internal_flash_bd()) { @@ -215,4 +210,10 @@ extern "C" size_t fota_bd_physical_addr_to_logical_addr(size_t phys_addr) return phys_addr; } +#ifdef __cplusplus +} +#endif + +#endif // defined(__MBED__) +#endif // (MBED_CLOUD_CLIENT_FOTA_BLOCK_DEVICE_TYPE != FOTA_EXTERNAL_BD) #endif // MBED_CLOUD_CLIENT_FOTA_ENABLE diff --git a/fota/fota_curr_fw.c b/fota/platform/mbed-os/fota_curr_fw_mbed_os.c similarity index 86% rename from fota/fota_curr_fw.c rename to fota/platform/mbed-os/fota_curr_fw_mbed_os.c index 92def312b..218d9b383 100644 --- a/fota/fota_curr_fw.c +++ b/fota/platform/mbed-os/fota_curr_fw_mbed_os.c @@ -20,17 +20,14 @@ #ifdef MBED_CLOUD_CLIENT_FOTA_ENABLE +#if defined(__MBED__) + #define TRACE_GROUP "FOTA" #include "fota/fota_curr_fw.h" #include "fota/fota_status.h" #include -// Non Linux target here means an embedded target. -// Note that MBED (mbed-os) targets are a subset of embedded targets. -// MBED targets don't have custom FW structure. Embedded ones that aren't MBED based - do. -#if !FOTA_CUSTOM_CURR_FW_STRUCTURE && !defined(TARGET_LIKE_LINUX) -#if defined(__MBED__) // Bootloader and application have different defines #if !defined(APPLICATION_ADDR) #if defined(MBED_CONF_MBED_BOOTLOADER_APPLICATION_START_ADDRESS) @@ -52,9 +49,7 @@ #endif #endif // !defined(HEADER_ADDR) - -// The following two functions should be overridden in the non mbed-os cases. -uint8_t *fota_curr_fw_get_app_start_addr(void) +static uint8_t *fota_curr_fw_get_app_start_addr(void) { #ifdef APPLICATION_ADDR return (uint8_t *) APPLICATION_ADDR; @@ -65,7 +60,7 @@ uint8_t *fota_curr_fw_get_app_start_addr(void) #endif } -uint8_t *fota_curr_fw_get_app_header_addr(void) +static uint8_t *fota_curr_fw_get_app_header_addr(void) { #ifdef HEADER_ADDR return (uint8_t *) HEADER_ADDR; @@ -75,7 +70,6 @@ uint8_t *fota_curr_fw_get_app_header_addr(void) return NULL; #endif } -#endif // defined(__MBED__) int fota_curr_fw_read_header(fota_header_info_t *header_info) { @@ -119,6 +113,6 @@ int fota_curr_fw_get_digest(uint8_t *buf) return FOTA_STATUS_SUCCESS; } -#endif // !FOTA_CUSTOM_CURR_FW_STRUCTURE && !defined(TARGET_LIKE_LINUX) +#endif // defined(__MBED__) #endif // MBED_CLOUD_CLIENT_FOTA_ENABLE diff --git a/fota/platform/nxp/fota_block_device_nxp_lpc.cpp b/fota/platform/nxp/fota_block_device_nxp_lpc.cpp new file mode 100644 index 000000000..505a02d58 --- /dev/null +++ b/fota/platform/nxp/fota_block_device_nxp_lpc.cpp @@ -0,0 +1,143 @@ +// ---------------------------------------------------------------------------- +// Copyright 2021 Pelion Ltd. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------- +#include "fota/fota_base.h" + +#ifdef MBED_CLOUD_CLIENT_FOTA_ENABLE + +#define TRACE_GROUP "FOTA" + +#include "fota/fota_config.h" +#include "fota/fota_status.h" +#include "fota/fota_block_device.h" + +#if (MBED_CLOUD_CLIENT_FOTA_BLOCK_DEVICE_TYPE == FOTA_EXTERNAL_BD) +//Should be compiled only for nxp freertos and nxp bootloader +#if defined(__NXP_FREERTOS__) || defined(FLASH_W25Q) || defined(FLASH_MT25Q) || defined(FLASH_MX25R) +#include "ExternalBlockDevice.h" + +// This ifdef is here (always true) to prevent astyle from indenting enclosed functions +#ifdef __cplusplus +extern "C" { +#endif + + +/*Fota block device implementation for external bd of NXP LPC */ +using namespace mbed; +static bool initialized = false; +static ExternalBlockDevice *bd = 0; + +int fota_bd_init(void) +{ + if (initialized) { + return 0; + } + if (!bd) { + bd = new ExternalBlockDevice(); + } + + if (!bd) { + return FOTA_STATUS_INTERNAL_ERROR; + } + + int ret = bd->init(); + if (!ret) { + initialized = true; + } + return ret; +} + +int fota_bd_deinit(void) +{ + + if (!initialized) { + return 0; + } + + int ret = bd->deinit(); + + delete bd; + initialized = false; + + return ret; +} + +int fota_bd_size(size_t *size) +{ + FOTA_ASSERT(bd); + + *size = (size_t)bd->size(); + + return 0; +} + +int fota_bd_read(void *buffer, size_t addr, size_t size) +{ + FOTA_ASSERT(bd); + return bd->read(buffer,(bd_addr_t)addr, (bd_size_t)size); +} + +int fota_bd_program(const void *buffer, size_t addr, size_t size) +{ + FOTA_ASSERT(bd); + return bd->program(buffer, addr, size); +} + +int fota_bd_erase(size_t addr, size_t size) +{ + FOTA_ASSERT(bd); + return bd->erase((bd_addr_t)addr, (bd_size_t)size); +} + +int fota_bd_get_read_size(size_t *read_size) +{ + FOTA_ASSERT(bd); + *read_size = (size_t)bd->get_read_size(); + return 0; +} + +int fota_bd_get_program_size(size_t *prog_size) +{ + FOTA_ASSERT(bd); + *prog_size = (size_t)bd->get_program_size(); + return 0; +} + +int fota_bd_get_erase_size(size_t addr, size_t *erase_size) +{ + FOTA_ASSERT(bd); + *erase_size = (size_t)bd->get_erase_size(); + return 0; +} + +int fota_bd_get_erase_value(int *erase_value) +{ + FOTA_DBG_ASSERT(initialized); + *erase_value = (int)bd->get_erase_value(); + return 0; +} +size_t fota_bd_physical_addr_to_logical_addr(size_t phys_addr) +{ + return phys_addr; +} + +#ifdef __cplusplus +} +#endif +#endif // __NXP_FREERTOS__ +#endif // MBED_CLOUD_CLIENT_FOTA_BLOCK_DEVICE_TYPE == FOTA_EXTERNAL_BD) +#endif // MBED_CLOUD_CLIENT_FOTA_ENABLE diff --git a/fota/platform/nxp/fota_curr_fw_nxp_lpc.c b/fota/platform/nxp/fota_curr_fw_nxp_lpc.c new file mode 100644 index 000000000..59f7f6390 --- /dev/null +++ b/fota/platform/nxp/fota_curr_fw_nxp_lpc.c @@ -0,0 +1,122 @@ +// ---------------------------------------------------------------------------- +// Copyright 2021 Pelion Ltd. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------- +#include "fota/fota_base.h" + +#ifdef MBED_CLOUD_CLIENT_FOTA_ENABLE + +#ifdef __NXP_FREERTOS__ + +#define TRACE_GROUP "FOTA" + +#include "fota/fota_curr_fw.h" +#include "fota/fota_status.h" +#include + +// Bootloader and application have different defines +#if !defined(APPLICATION_ADDR) +#if defined(MBED_CONF_MBED_BOOTLOADER_APPLICATION_START_ADDRESS) +#define APPLICATION_ADDR MBED_CONF_MBED_BOOTLOADER_APPLICATION_START_ADDRESS +#elif defined(MBED_CONF_TARGET_APP_OFFSET) +#define APPLICATION_ADDR MBED_CONF_TARGET_APP_OFFSET +#else +#error Application start address not defined +#endif +#endif // !defined(APPLICATION_ADDR) + +#if !defined(HEADER_ADDR) +#if defined(MBED_CONF_MBED_BOOTLOADER_APPLICATION_HEADER_ADDRESS) +#define HEADER_ADDR MBED_CONF_MBED_BOOTLOADER_APPLICATION_HEADER_ADDRESS +#elif defined(MBED_CONF_TARGET_HEADER_OFFSET) +#define HEADER_ADDR MBED_CONF_TARGET_HEADER_OFFSET +#else +#error Header start address not defined +#endif +#endif // !defined(HEADER_ADDR) + + +/*Custom fw implementation */ +#if defined(FOTA_CUSTOM_CURR_FW_STRUCTURE) && (FOTA_CUSTOM_CURR_FW_STRUCTURE == 0) + +static uint8_t *fota_curr_fw_get_app_start_addr(void) +{ +#ifdef APPLICATION_ADDR + return (uint8_t *) APPLICATION_ADDR; +#else +//#error No address was defined for application + FOTA_ASSERT(!"No app start address defined"); + return NULL; +#endif +} + +static uint8_t *fota_curr_fw_get_app_header_addr(void) +{ +#ifdef HEADER_ADDR + return (uint8_t *) HEADER_ADDR; +#else +//#error No address was defined for application header + FOTA_ASSERT(!"No app start address defined"); + return NULL; +#endif +} + +int fota_curr_fw_read_header(fota_header_info_t *header_info) +{ + uint8_t *header_in_curr_fw = (uint8_t *)fota_curr_fw_get_app_header_addr(); + return fota_deserialize_header(header_in_curr_fw, fota_get_header_size(), header_info); +} + +int fota_curr_fw_read(uint8_t *buf, size_t offset, size_t size, size_t *num_read) +{ + fota_header_info_t header_info; + int ret = FOTA_STATUS_INTERNAL_ERROR; + + ret = fota_curr_fw_read_header(&header_info); + if (ret) { + return ret; + } + + if (offset >= header_info.fw_size) { + return FOTA_STATUS_INTERNAL_ERROR; + } + + *num_read = header_info.fw_size - offset; + if (*num_read > size) { + *num_read = size; + } + + memcpy(buf, fota_curr_fw_get_app_start_addr() + offset, *num_read); + return FOTA_STATUS_SUCCESS; + +} + +int fota_curr_fw_get_digest(uint8_t *buf) +{ + fota_header_info_t curr_fw_info; + int ret = fota_curr_fw_read_header(&curr_fw_info); + if (ret) { + FOTA_TRACE_ERROR("Failed to read current header"); + return ret; + } + memcpy(buf, curr_fw_info.digest, FOTA_CRYPTO_HASH_SIZE); + return FOTA_STATUS_SUCCESS; +} + +#endif //defined(FOTA_CUSTOM_CURR_FW_STRUCTURE) && (FOTA_CUSTOM_CURR_FW_STRUCTURE == 0) + +#endif // __NXP_FREERTOS__ +#endif // MBED_CLOUD_CLIENT_FOTA_ENABLE diff --git a/mbed-client-pal/Configs/mbedTLS/pelion_mbedtls_config.h b/mbed-client-pal/Configs/mbedTLS/pelion_mbedtls_config.h new file mode 100644 index 000000000..d8521a47c --- /dev/null +++ b/mbed-client-pal/Configs/mbedTLS/pelion_mbedtls_config.h @@ -0,0 +1,1099 @@ +/* Copyright (c) 2021 Pelion IoT + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PELION_MBEDTLS_CONFIG_H +#define PELION_MBEDTLS_CONFIG_H + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#ifndef MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_MODE_CBC +#endif + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#ifndef MBEDTLS_CIPHER_MODE_CTR +#define MBEDTLS_CIPHER_MODE_CTR +#endif + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#ifndef MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#endif + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#ifndef MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#endif + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#ifndef MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#ifndef MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_ECP_NIST_OPTIM +#endif + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#ifndef MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_ECDSA_DETERMINISTIC +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#ifndef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#ifndef MBEDTLS_PKCS1_V15 +#define MBEDTLS_PKCS1_V15 +#endif + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#ifndef MBEDTLS_PKCS1_V21 +#define MBEDTLS_PKCS1_V21 +#endif + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#ifndef MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES +#endif + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#ifndef MBEDTLS_SSL_ENCRYPT_THEN_MAC +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC +#endif + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#ifndef MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#endif + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + * \note This feature is required by Device Management Client for Client-side + * certificate expiration verification. Disabling it will also require + * setting PAL_USE_SECURE_TIME to 0. + * + */ +#ifndef MBEDTLS_SSL_RENEGOTIATION +#define MBEDTLS_SSL_RENEGOTIATION +#endif + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#ifndef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#endif + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#ifndef MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_PROTO_TLS1_2 +#endif + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#ifndef MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_PROTO_DTLS +#endif + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#ifndef MBEDTLS_SSL_ALPN +#define MBEDTLS_SSL_ALPN +#endif + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +#ifndef MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY +#endif + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#ifndef MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY +#endif + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#ifndef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE +#endif + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +#ifndef MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#endif + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintainance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#ifndef MBEDTLS_SSL_SESSION_TICKETS +#define MBEDTLS_SSL_SESSION_TICKETS +#endif + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +#ifndef MBEDTLS_SSL_EXPORT_KEYS +#define MBEDTLS_SSL_EXPORT_KEYS +#endif + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#ifndef MBEDTLS_SSL_SERVER_NAME_INDICATION +#define MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#ifndef MBEDTLS_X509_CHECK_KEY_USAGE +#define MBEDTLS_X509_CHECK_KEY_USAGE +#endif + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#ifndef MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#endif + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#ifndef MBEDTLS_AES_C +#define MBEDTLS_AES_C +#endif + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#ifndef MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_PARSE_C +#endif + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#ifndef MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_ASN1_WRITE_C +#endif + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +// needed for Base64 encoding Opaque data for +// registration payload, adds 500 bytes to flash. +#ifndef MBEDTLS_BASE64_C +#define MBEDTLS_BASE64_C +#endif + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#ifndef MBEDTLS_BIGNUM_C +#define MBEDTLS_BIGNUM_C +#endif + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#ifndef MBEDTLS_CCM_C +#define MBEDTLS_CCM_C +#endif + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#ifndef MBEDTLS_CIPHER_C +#define MBEDTLS_CIPHER_C +#endif + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +#ifndef MBEDTLS_CMAC_C +#define MBEDTLS_CMAC_C +#endif + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#ifndef MBEDTLS_CTR_DRBG_C +#define MBEDTLS_CTR_DRBG_C +#endif + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#ifndef MBEDTLS_ECDH_C +#define MBEDTLS_ECDH_C +#endif + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#ifndef MBEDTLS_ECDSA_C +#define MBEDTLS_ECDSA_C +#endif + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#ifndef MBEDTLS_ECP_C +#define MBEDTLS_ECP_C +#endif + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#ifndef MBEDTLS_ENTROPY_C +#define MBEDTLS_ENTROPY_C +#endif + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#ifndef MBEDTLS_GCM_C +#define MBEDTLS_GCM_C +#endif + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#ifndef MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_HMAC_DRBG_C +#endif + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#ifndef MBEDTLS_MD_C +#define MBEDTLS_MD_C +#endif + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#ifndef MBEDTLS_OID_C +#define MBEDTLS_OID_C +#endif + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#ifndef MBEDTLS_PK_C +#define MBEDTLS_PK_C +#endif + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#ifndef MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_PARSE_C +#endif + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#ifndef MBEDTLS_PK_WRITE_C +#define MBEDTLS_PK_WRITE_C +#endif + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#ifndef MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_C +#endif + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#ifndef MBEDTLS_SHA256_C +#define MBEDTLS_SHA256_C +#endif + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#ifndef MBEDTLS_SSL_CACHE_C +#define MBEDTLS_SSL_CACHE_C +#endif + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#ifndef MBEDTLS_SSL_COOKIE_C +#define MBEDTLS_SSL_COOKIE_C +#endif + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +#ifndef MBEDTLS_SSL_TICKET_C +#define MBEDTLS_SSL_TICKET_C +#endif + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#ifndef MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_CLI_C +#endif + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#ifndef MBEDTLS_SSL_TLS_C +#define MBEDTLS_SSL_TLS_C +#endif + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#ifndef MBEDTLS_VERSION_C +#define MBEDTLS_VERSION_C +#endif + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#ifndef MBEDTLS_X509_USE_C +#define MBEDTLS_X509_USE_C +#endif + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#ifndef MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_CRT_PARSE_C +#endif + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#ifndef MBEDTLS_X509_CRL_PARSE_C +#define MBEDTLS_X509_CRL_PARSE_C +#endif + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#ifndef MBEDTLS_X509_CSR_PARSE_C +#define MBEDTLS_X509_CSR_PARSE_C +#endif + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#ifndef MBEDTLS_X509_CREATE_C +#define MBEDTLS_X509_CREATE_C +#endif + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#ifndef MBEDTLS_X509_CSR_WRITE_C +#define MBEDTLS_X509_CSR_WRITE_C +#endif + +/* SSL options */ +#ifndef MBEDTLS_SSL_MAX_CONTENT_LEN +#define MBEDTLS_SSL_MAX_CONTENT_LEN 4096 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ +#endif + +/** + * Enable ARIA ciphersuites. + */ +#ifndef MBEDTLS_ARIA_C +#define MBEDTLS_ARIA_C +#endif + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +#ifndef MBEDTLS_SSL_CIPHERSUITES +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \ + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, \ + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 +#endif + +// Need MBEDTLS_SSL_CONTEXT_SERIALIZATION and MBEDTLS_SSL_DTLS_CONNECTION_ID for CID feature +#ifndef MBEDTLS_SSL_CONTEXT_SERIALIZATION +#define MBEDTLS_SSL_CONTEXT_SERIALIZATION +#endif + +#ifndef MBEDTLS_SSL_DTLS_CONNECTION_ID +#define MBEDTLS_SSL_DTLS_CONNECTION_ID +#endif + +#endif // PELION_MBEDTLS_CONFIG_H diff --git a/mbed-client-pal/Configs/pal_config/Linux/Linux_default.h b/mbed-client-pal/Configs/pal_config/Linux/Linux_default.h index 818f7df56..540d210d3 100644 --- a/mbed-client-pal/Configs/pal_config/Linux/Linux_default.h +++ b/mbed-client-pal/Configs/pal_config/Linux/Linux_default.h @@ -84,6 +84,15 @@ #endif #endif +#ifndef PAL_ASYNC_DNS_THREAD_STACK_SIZE + #define PAL_ASYNC_DNS_THREAD_STACK_SIZE (1024 * 24) +#else + #if (PAL_ASYNC_DNS_THREAD_STACK_SIZE < PTHREAD_STACK_MIN) + #undef PAL_ASYNC_DNS_THREAD_STACK_SIZE + #define PAL_ASYNC_DNS_THREAD_STACK_SIZE PTHREAD_STACK_MIN + #endif +#endif + #ifndef PAL_FORMAT_CMD_MAX_LENGTH #define PAL_FORMAT_CMD_MAX_LENGTH 256 #endif diff --git a/mbed-client-pal/Source/PAL-Impl/Modules/Networking/pal_network.c b/mbed-client-pal/Source/PAL-Impl/Modules/Networking/pal_network.c index 3322bde32..d1b5b5f80 100644 --- a/mbed-client-pal/Source/PAL-Impl/Modules/Networking/pal_network.c +++ b/mbed-client-pal/Source/PAL-Impl/Modules/Networking/pal_network.c @@ -206,20 +206,20 @@ palStatus_t pal_setSockAddrNAT64Addr(palSocketAddress_t* address, palIpV4Addr_t pal_socketAddressInternal6_t* innerAddr = (pal_socketAddressInternal6_t*)address; innerAddr->pal_sin6_family = PAL_AF_INET6; - innerAddr->pal_sin6_addr[0] = 0x00; - innerAddr->pal_sin6_addr[1] = 0x64; - innerAddr->pal_sin6_addr[2] = 0xFF; - innerAddr->pal_sin6_addr[3] = 0x9B; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[0] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[1] = 0x64; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[2] = 0xFF; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[3] = 0x9B; - innerAddr->pal_sin6_addr[4] = 0x00; - innerAddr->pal_sin6_addr[5] = 0x00; - innerAddr->pal_sin6_addr[6] = 0x00; - innerAddr->pal_sin6_addr[7] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[4] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[5] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[6] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[7] = 0x00; - innerAddr->pal_sin6_addr[8] = 0x00; - innerAddr->pal_sin6_addr[9] = 0x00; - innerAddr->pal_sin6_addr[10] = 0x00; - innerAddr->pal_sin6_addr[11] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[8] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[9] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[10] = 0x00; + ((volatile uint8_t*) innerAddr->pal_sin6_addr)[11] = 0x00; innerAddr->pal_sin6_addr[12] = ipV4Addr[0]; innerAddr->pal_sin6_addr[13] = ipV4Addr[1]; @@ -491,18 +491,23 @@ palStatus_t pal_getAddressInfoAsync(const char* hostname, } return status; } -#elif (PAL_DNS_API_VERSION == 2) -#ifndef TARGET_LIKE_MBED + +#elif (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) +#if !defined(TARGET_LIKE_MBED) && (PAL_DNS_API_VERSION == 2) #error "PAL_DNS_API_VERSION 2 is only supported with mbed-os" #endif palStatus_t pal_getAddressInfoAsync(const char* hostname, - palSocketAddress_t* address, - palGetAddressInfoAsyncCallback_t callback, - void* callbackArgument, - palDNSQuery_t* queryHandle) +#if (PAL_DNS_API_VERSION == 2) + palSocketAddress_t* address, +#endif + palGetAddressInfoAsyncCallback_t callback, + void* callbackArgument, + palDNSQuery_t* queryHandle) { - PAL_VALIDATE_ARGUMENTS ((NULL == hostname) || (NULL == address) || (NULL == callback)) - + PAL_VALIDATE_ARGUMENTS ((NULL == hostname) || (NULL == callback)) +#if (PAL_DNS_API_VERSION == 2) + PAL_VALIDATE_ARGUMENTS (NULL == address) +#endif palStatus_t status; pal_asyncAddressInfo_t* info = (pal_asyncAddressInfo_t*)malloc(sizeof(pal_asyncAddressInfo_t)); @@ -511,7 +516,9 @@ palStatus_t pal_getAddressInfoAsync(const char* hostname, } else { info->hostname = (char*)hostname; +#if (PAL_DNS_API_VERSION == 2) info->address = address; +#endif info->callback = callback; info->callbackArgument = callbackArgument; info->queryHandle = queryHandle; @@ -528,6 +535,29 @@ palStatus_t pal_cancelAddressInfoAsync(palDNSQuery_t queryHandle) return pal_plat_cancelAddressInfoAsync(queryHandle); } +#if (PAL_DNS_API_VERSION == 3) +palStatus_t pal_getDNSAddress(palAddressInfo_t *addrInfo, uint16_t index, palSocketAddress_t *addr) +{ + PAL_VALIDATE_ARGUMENTS ((NULL == addrInfo) || (NULL == addr)) + PAL_VALIDATE_ARGUMENTS (pal_getDNSCount(addrInfo) <= index) + return pal_plat_getDNSAddress(addrInfo, index, addr); +} + +int pal_getDNSCount(palAddressInfo_t *addrInfo) +{ + return pal_plat_getDNSCount(addrInfo); +} + +void pal_freeAddrInfo(palAddressInfo_t* addrInfo) +{ + pal_plat_freeAddrInfo(addrInfo); +} + +palStatus_t pal_free_addressinfoAsync(palDNSQuery_t handle) +{ + return pal_plat_free_addressinfoAsync(handle); +} +#endif #endif // PAL_DNS_API_VERSION #endif // PAL_NET_DNS_SUPPORT diff --git a/mbed-client-pal/Source/PAL-Impl/Modules/ROT/pal_rot.c b/mbed-client-pal/Source/PAL-Impl/Modules/ROT/pal_rot.c index df7913c93..a292fa549 100644 --- a/mbed-client-pal/Source/PAL-Impl/Modules/ROT/pal_rot.c +++ b/mbed-client-pal/Source/PAL-Impl/Modules/ROT/pal_rot.c @@ -16,7 +16,7 @@ #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "pal_plat_rot.h" #ifndef MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT #include "sotp.h" diff --git a/mbed-client-pal/Source/PAL-Impl/Modules/TLS/pal_TLS.c b/mbed-client-pal/Source/PAL-Impl/Modules/TLS/pal_TLS.c index c44907b50..384bce3c6 100644 --- a/mbed-client-pal/Source/PAL-Impl/Modules/TLS/pal_TLS.c +++ b/mbed-client-pal/Source/PAL-Impl/Modules/TLS/pal_TLS.c @@ -17,7 +17,7 @@ #include "pal.h" #include "pal_plat_TLS.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" // do not require storage unless this modules is configured to use it #if PAL_USE_SECURE_TIME @@ -448,17 +448,19 @@ PAL_PRIVATE palStatus_t pal_updateTime(uint64_t serverTime, bool trustedTimeServ } #endif //PAL_USE_SECURE_TIME -palStatus_t pal_handShake_ping(palTLSHandle_t palTLSHandle) +#if (PAL_USE_SSL_SESSION_RESUME == 1) +void pal_print_cid(palTLSHandle_t palTLSHandle) { - palTLSService_t* palTLSCtx = (palTLSService_t*)palTLSHandle; - - PAL_VALIDATE_ARGUMENTS(NULLPTR == palTLSCtx); - PAL_VALIDATE_ARGUMENTS(NULLPTR == palTLSCtx->platTlsHandle); - - return pal_plat_handShake_ping(palTLSCtx->platTlsHandle); + uint8_t data_ptr[32];// MBEDTLS_SSL_CID_OUT_LEN_MAX = 32 + size_t data_len = 0; + pal_plat_get_cid_value(palTLSHandle, data_ptr, &data_len); + if (data_len) { + PAL_LOG_DBG("CID: %s", PAL_LOG_ARRAY_FUNC(data_ptr, data_len)); + } } +#endif -palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf) +palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf, bool skipResume) { palStatus_t status = PAL_SUCCESS; palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf; @@ -468,9 +470,10 @@ palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLS PAL_VALIDATE_ARGUMENTS((NULLPTR == palTLSCtx->platTlsHandle || NULLPTR == palTLSConfCtx->platTlsConfHandle)); #if (PAL_USE_SSL_SESSION_RESUME == 1) - if(palTLSConfCtx->isDtlsMode) { - if(pal_plat_sslSessionAvailable()) { - PAL_LOG_DBG("Using stored session"); + if (!skipResume && palTLSConfCtx->isDtlsMode) { + if (pal_plat_sslSessionAvailable()) { + PAL_LOG_DBG("pal_handShake: using stored session"); + pal_print_cid(palTLSCtx->platTlsHandle); return status; } } @@ -481,62 +484,56 @@ palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLS status = pal_plat_handShake(palTLSCtx->platTlsHandle, &palTLSCtx->serverTime); if (PAL_SUCCESS == status) { -#if PAL_USE_SECURE_TIME int32_t verifyResult = 0; status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult); if (PAL_ERR_X509_CERT_VERIFY_FAILED == status) { - if ((PAL_ERR_X509_BADCERT_FUTURE & verifyResult) || ((true == palTLSConfCtx->trustedTimeServer) && (PAL_ERR_X509_BADCERT_EXPIRED & verifyResult))) +#if PAL_USE_SECURE_TIME + // if cert verification fails _only_ on certificate time being wrong (and we use 'secure time' feature), + // try to renegotiate using server's time + + // Cert being in future means client is actually in the past, so we're allowed to correct it always (sleepy device...) + // Cert being in the past (expired) means client is in future, so we only trust it when talking to Time RoT (trustedTimeServer) + if ((PAL_ERR_X509_BADCERT_FUTURE == verifyResult) || ((true == palTLSConfCtx->trustedTimeServer) && (PAL_ERR_X509_BADCERT_EXPIRED == verifyResult))) { - PAL_LOG_DBG("SSL EXPIRED OR FUTURE - retry"); + PAL_LOG_DBG("SSL EXPIRED OR FUTURE - renegotiate"); palTLSCtx->retryHandShake = true; status = PAL_SUCCESS; } - else if (PAL_SUCCESS != status) +#else + // If PAL_USE_SECURE_TIME is not on, don't do time verification from certificate + if ((PAL_ERR_X509_BADCERT_FUTURE == verifyResult) || (PAL_ERR_X509_BADCERT_EXPIRED == verifyResult)) + { + PAL_LOG_WARN("SSL EXPIRED OR FUTURE - passing due to PAL_USE_SECURE_TIME not set"); + status = PAL_SUCCESS; + } +#endif + if (PAL_SUCCESS != status) { - status = PAL_ERR_X509_CERT_VERIFY_FAILED; palTLSCtx->serverTime = 0; #if (PAL_USE_SSL_SESSION_RESUME == 1) pal_removeSslSessionFromStorage(palTLSConfCtx->platTlsConfHandle); #endif } } -#else - if (PAL_SUCCESS != status) - { - status = PAL_ERR_X509_CERT_VERIFY_FAILED; - palTLSCtx->serverTime = 0; - } - -#endif //PAL_USE_SECURE_TIME } } #if PAL_USE_SECURE_TIME if ((PAL_SUCCESS == status) && (palTLSCtx->retryHandShake)) { PAL_LOG_DBG("SSL START RENEGOTIATE"); - if (!palTLSConfCtx->trustedTimeServer) //! if we are not proccessing handshake with the time trusted server we - { //! will use PAL_TLS_VERIFY_REQUIRED authentication mode - status = pal_plat_setAuthenticationMode(palTLSConfCtx->platTlsConfHandle, PAL_TLS_VERIFY_REQUIRED); - if (PAL_SUCCESS != status) - { + // We can now set verify required which does full certificate verification inside pal_plat_renegotiate call + // since time should be fine as we just got it from the server. + status = pal_plat_setAuthenticationMode(palTLSConfCtx->platTlsConfHandle, PAL_TLS_VERIFY_REQUIRED); + if (PAL_SUCCESS != status) + { #if (PAL_USE_SSL_SESSION_RESUME == 1) - pal_removeSslSessionFromStorage(palTLSConfCtx->platTlsConfHandle); + pal_removeSslSessionFromStorage(palTLSConfCtx->platTlsConfHandle); #endif - goto finish; - } + goto finish; } + status = pal_plat_renegotiate(palTLSCtx->platTlsHandle, palTLSCtx->serverTime); - if (PAL_SUCCESS == status) - { - int32_t verifyResult = 0; - status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult); - if ((palTLSConfCtx->trustedTimeServer) && - ((PAL_ERR_X509_CERT_VERIFY_FAILED == status) && ((PAL_ERR_X509_BADCERT_EXPIRED & verifyResult) || (PAL_ERR_X509_BADCERT_FUTURE & verifyResult)))) - { - status = PAL_SUCCESS; - } - } } if (PAL_SUCCESS == status) @@ -549,14 +546,19 @@ palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLS #if (PAL_USE_SSL_SESSION_RESUME == 1) if (PAL_SUCCESS == status) { pal_saveSslSessionToStorage(palTLSHandle, palTLSConf); - PAL_LOG_DBG("Storing session !"); + PAL_LOG_DBG("pal_handShake: handshake done, storing session!"); + if (palTLSConfCtx->isDtlsMode) { + pal_print_cid(palTLSCtx->platTlsHandle); + } } + #endif // PAL_USE_SSL_SESSION_RESUME +#if PAL_USE_SECURE_TIME finish: +#endif //PAL_USE_SECURE_TIME return status; } -#if PAL_USE_SECURE_TIME palStatus_t pal_sslGetVerifyResultExtended(palTLSHandle_t palTLSHandle, int32_t* verifyResult) { palStatus_t status = PAL_SUCCESS; @@ -571,29 +573,12 @@ palStatus_t pal_sslGetVerifyResultExtended(palTLSHandle_t palTLSHandle, int32_t* if (0 != *verifyResult) { status = PAL_ERR_X509_CERT_VERIFY_FAILED; - *verifyResult = *verifyResult ^ PAL_ERR_MODULE_BITMASK_BASE; //! in order to turn off the MSB bit. } return status; } -palStatus_t pal_sslGetVerifyResult(palTLSHandle_t palTLSHandle) -{ - palStatus_t status = PAL_SUCCESS; - palTLSService_t* palTLSCtx = NULL; - int32_t verifyResult = 0; - - PAL_VALIDATE_ARGUMENTS(NULLPTR == palTLSHandle); - - palTLSCtx = (palTLSService_t*)palTLSHandle; - PAL_VALIDATE_ARGUMENTS(NULLPTR == palTLSCtx->platTlsHandle); - - status = pal_plat_sslGetVerifyResultExtended(palTLSCtx->platTlsHandle, &verifyResult); - return status; -} -#endif //PAL_USE_SECURE_TIME - palStatus_t pal_setHandShakeTimeOut(palTLSConfHandle_t palTLSConf, uint32_t minTimeout, uint32_t maxTimeout) { palStatus_t status = PAL_SUCCESS; @@ -625,11 +610,12 @@ palStatus_t pal_sslWrite(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSC palTLSService_t* palTLSCtx = (palTLSService_t*)palTLSHandle; PAL_VALIDATE_ARGUMENTS((NULLPTR == palTLSHandle || NULL == buffer || NULL == bytesWritten)); - status = pal_plat_sslWrite(palTLSCtx->platTlsHandle, buffer, len, bytesWritten); #if (PAL_USE_SSL_SESSION_RESUME == 1) - palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf; - if(palTLSConfCtx->isDtlsMode) { + palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf; + if (palTLSConfCtx->isDtlsMode) { + PAL_LOG_DBG("pal_plat_sslWrite, using stored session!"); + pal_print_cid(palTLSCtx->platTlsHandle); pal_saveSslSessionToStorage(palTLSHandle, palTLSConf); } #endif // (PAL_USE_SSL_SESSION_RESUME == 1) @@ -908,10 +894,11 @@ void pal_setDTLSSocketCallback(palTLSConfHandle_t palTLSConf, palSocketCallback_ pal_plat_SetDTLSSocketCallback(palTLSConfCtx->platTlsConfHandle, callback, argument); } -void pal_set_cid_value(palTLSHandle_t palTLSHandle, const uint8_t *data_ptr, const size_t data_len) +void pal_set_cid_value(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf, const uint8_t *data_ptr, const size_t data_len) { #if (PAL_USE_SSL_SESSION_RESUME == 1) palTLSService_t* palTLSCtx = (palTLSService_t*)palTLSHandle; pal_plat_set_cid_value(palTLSCtx->platTlsHandle, data_ptr, data_len); + pal_loadSslSessionFromStorage(palTLSHandle, palTLSConf); #endif } diff --git a/mbed-client-pal/Source/PAL-Impl/Services-API/pal_TLS.h b/mbed-client-pal/Source/PAL-Impl/Services-API/pal_TLS.h index 5e7c11035..81a972950 100644 --- a/mbed-client-pal/Source/PAL-Impl/Services-API/pal_TLS.h +++ b/mbed-client-pal/Source/PAL-Impl/Services-API/pal_TLS.h @@ -204,10 +204,11 @@ palStatus_t pal_tlsSetSocket(palTLSConfHandle_t palTLSConf, palTLSSocket_t* sock * with the peer. * @param[in] palTLSHandle: The TLS context. * @param[in] palTLSConf: The TLS configuration context. + * @param[in] skipResume: If true, will skip resume. Resume may be active only in UDP DTLS. * * \return PAL_SUCCESS on success, or a negative value indicating a specific error code in case of failure. */ -palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf); +palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf, bool skipResume); /*! \brief Set the retransmit timeout values for the DTLS handshake. * DTLS only, no effect on TLS. @@ -220,15 +221,6 @@ palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLS */ palStatus_t pal_setHandShakeTimeOut(palTLSConfHandle_t palTLSConf, uint32_t minTimeout, uint32_t maxTimeout); -#if PAL_USE_SECURE_TIME -/*! \brief Return the result of the certificate verification. - * - * @param[in] palTLSHandle: The TLS context. - * - * \return PAL_SUCCESS on success, or a negative value indicating a specific error code in case of failure. - */ -palStatus_t pal_sslGetVerifyResult(palTLSHandle_t palTLSHandle); - /*! \brief Return the result of the certificate verification. * * @param[in] palTLSHandle: The TLS context. @@ -239,7 +231,6 @@ palStatus_t pal_sslGetVerifyResult(palTLSHandle_t palTLSHandle); * \return PAL_ERR_X509_CERT_VERIFY_FAILED in case of failure. */ palStatus_t pal_sslGetVerifyResultExtended(palTLSHandle_t palTLSHandle, int32_t* verifyResult); -#endif //PAL_USE_SECURE_TIME /*! \brief Read the application data bytes (the max number of bytes). * @@ -298,13 +289,6 @@ void pal_remove_cid(); */ bool pal_is_cid_available(); -/*! \brief DTLS ping to Cloud to check connectivity status. - * @param[in] palTLSHandle: The TLS context. - * - * \return PAL_SUCCESS on success, or a negative value indicating a specific error code in case of failure. - */ -palStatus_t pal_handShake_ping(palTLSHandle_t palTLSHandle); - #if (PAL_USE_SSL_SESSION_RESUME == 1) /*! \brief Enable SSL session storing. Disabled by default. * @@ -331,10 +315,11 @@ void pal_setDTLSSocketCallback(palTLSConfHandle_t palTLSConf, palSocketCallback_ /** * \brief Internal test function. Set CID for current tls session. - * @param palTLSHandle: The TLS context. - * @param data_ptr: CID - * @param data_len: length of the CID + * @param[in] palTLSHandle: The TLS context. + * @param[in] palTLSConf: The DTLS configuration context. + * @param[in] data_ptr: CID + * @param[in] data_len: length of the CID */ -void pal_set_cid_value(palTLSHandle_t palTLSHandle, const uint8_t *data_ptr, const size_t data_len); +void pal_set_cid_value(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf, const uint8_t *data_ptr, const size_t data_len); #endif // _PAL_DTLS_H_ diff --git a/mbed-client-pal/Source/PAL-Impl/Services-API/pal_macros.h b/mbed-client-pal/Source/PAL-Impl/Services-API/pal_macros.h index 61a1dd932..34640253c 100644 --- a/mbed-client-pal/Source/PAL-Impl/Services-API/pal_macros.h +++ b/mbed-client-pal/Source/PAL-Impl/Services-API/pal_macros.h @@ -220,10 +220,11 @@ extern "C" { assert(0);\ } -#define PAL_LOG_ERR_FUNC tr_err -#define PAL_LOG_WARN_FUNC tr_warn -#define PAL_LOG_INFO_FUNC tr_info -#define PAL_LOG_DBG_FUNC tr_debug +#define PAL_LOG_ERR_FUNC tr_err +#define PAL_LOG_WARN_FUNC tr_warn +#define PAL_LOG_INFO_FUNC tr_info +#define PAL_LOG_DBG_FUNC tr_debug +#define PAL_LOG_ARRAY_FUNC tr_array // Little trick with mbed-trace error level is equal to function name handling the same level of log output #define PAL_LOG_LEVEL_ERR TRACE_LEVEL_ERROR diff --git a/mbed-client-pal/Source/PAL-Impl/Services-API/pal_network.h b/mbed-client-pal/Source/PAL-Impl/Services-API/pal_network.h index 4769482a8..5ddf0d8b0 100644 --- a/mbed-client-pal/Source/PAL-Impl/Services-API/pal_network.h +++ b/mbed-client-pal/Source/PAL-Impl/Services-API/pal_network.h @@ -20,7 +20,7 @@ #define _PAL_SOCKET_H #ifndef _PAL_H - #error "Please do not include this file directly, use pal.h instead" +#error "Please do not include this file directly, use pal.h instead" #endif @@ -41,7 +41,7 @@ extern "C" { */ typedef uint32_t palSocketLength_t; /*!< \brief The length of data. */ -typedef void* palSocket_t; /*!< \brief PAL socket handle type. */ +typedef void *palSocket_t; /*!< \brief PAL socket handle type. */ #define PAL_NET_MAX_ADDR_SIZE 32 // check if we can make this more efficient @@ -50,7 +50,13 @@ typedef struct palSocketAddress { char addressData[PAL_NET_MAX_ADDR_SIZE]; /*!< \brief Address based on the protocol used. */ } palSocketAddress_t; /*!< \brief Address data structure with enough room to support IPV4 and IPV6. */ -typedef struct palNetInterfaceInfo{ +#if PAL_NET_DNS_SUPPORT +#if (PAL_DNS_API_VERSION == 3) +typedef void *palAddressInfo_t; /*!< \brief PAL address info handle type. */ +#endif // (PAL_DNS_API_VERSION == 3) +#endif // PAL_NET_DNS_SUPPORT + +typedef struct palNetInterfaceInfo { char interfaceName[16]; //15 + ‘\0’ palSocketAddress_t address; uint32_t addressSize; @@ -88,13 +94,14 @@ typedef enum { #endif //PAL_NET_TCP_AND_TLS_SUPPORT PAL_SO_SNDTIMEO = 0x1005, /*!< \brief Send timeout. */ PAL_SO_RCVTIMEO = 0x1006, /*!< \brief Receive timeout. */ - PAL_SO_IPV6_MULTICAST_HOPS = 0x1007 /*!< \brief Hop limit for subsequent multicast datagrams to be set to any value from 0 to 255. This ability is used to control the scope of the multicasts. */ + PAL_SO_IPV6_MULTICAST_HOPS = 0x1007, /*!< \brief Hop limit for subsequent multicast datagrams to be set to any value from 0 to 255. This ability is used to control the scope of the multicasts. */ + PAL_SO_IPV6_TRAFFIC_CLASS = 0x1008 /*!< \brief Use to set IPv6 traffic class priority. Default is 0. */ } palSocketOptionName_t; /*! \brief Socket protocol level options supported by PAL. */ typedef enum { PAL_SOL_SOCKET = 0, - PAL_SOL_IPPROTO_IPV6 =1 + PAL_SOL_IPPROTO_IPV6 = 1 } palSocketOptionLevelName_t; #define PAL_NET_DEFAULT_INTERFACE 0xFFFFFFFF @@ -105,7 +112,7 @@ typedef enum { typedef uint8_t palIpV4Addr_t[PAL_IPV4_ADDRESS_SIZE]; typedef uint8_t palIpV6Addr_t[PAL_IPV6_ADDRESS_SIZE]; -typedef void(*connectionStatusCallback) (palNetworkStatus_t status, void *client_arg); +typedef void(*connectionStatusCallback)(palNetworkStatus_t status, void *client_arg); /*! \brief Register a network interface for use with PAL sockets. * @@ -119,7 +126,7 @@ typedef void(*connectionStatusCallback) (palNetworkStatus_t status, void *client * * \note If a context is not applicable on a target configuration, use \c NULL . */ -palStatus_t pal_registerNetworkInterface(void* networkInterfaceContext, uint32_t* interfaceIndex); +palStatus_t pal_registerNetworkInterface(void *networkInterfaceContext, uint32_t *interfaceIndex); /*! \brief Unregister a network interface. * @param interfaceIndex Index of the network interface to be removed. @@ -127,56 +134,56 @@ palStatus_t pal_registerNetworkInterface(void* networkInterfaceContext, uint32_t */ palStatus_t pal_unregisterNetworkInterface(uint32_t interfaceIndex); - /*! \brief Set a port to an address data structure. - * @param[in,out] address The address data structure to configure. - * @param[in] port The port number to set. - * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. - * \note To set the socket correctly, the `addressType` field of the address must be set correctly. - * You can set it either directly, or using the `pal_setSockAddrIPV4Addr` or `pal_setSockAddrIPV6Addr` functions. - */ -palStatus_t pal_setSockAddrPort(palSocketAddress_t* address, uint16_t port); +/*! \brief Set a port to an address data structure. + * @param[in,out] address The address data structure to configure. + * @param[in] port The port number to set. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. + * \note To set the socket correctly, the `addressType` field of the address must be set correctly. + * You can set it either directly, or using the `pal_setSockAddrIPV4Addr` or `pal_setSockAddrIPV6Addr` functions. + */ +palStatus_t pal_setSockAddrPort(palSocketAddress_t *address, uint16_t port); /*! \brief Set an IPv4 address to an address data structure and set `addressType` as IPv4. * @param[in,out] address The address data structure to configure. * @param[in] ipV4Addr The address value to set. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_setSockAddrIPV4Addr(palSocketAddress_t* address, palIpV4Addr_t ipV4Addr); +palStatus_t pal_setSockAddrIPV4Addr(palSocketAddress_t *address, palIpV4Addr_t ipV4Addr); /*! \brief Get an IPv4 address from an address data structure. * @param[in] address The address data structure to query. * @param[out] ipV4Addr The IPv4 address to get. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_getSockAddrIPV4Addr(const palSocketAddress_t* address, palIpV4Addr_t ipV4Addr); +palStatus_t pal_getSockAddrIPV4Addr(const palSocketAddress_t *address, palIpV4Addr_t ipV4Addr); /*! \brief Set an IPv6 address to an address data structure and set the `addressType` as IPv6. * @param[in,out] address The address data structure to configure. * @param[in] ipV6Addr The address value to set. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_setSockAddrIPV6Addr(palSocketAddress_t* address, palIpV6Addr_t ipV6Addr); +palStatus_t pal_setSockAddrIPV6Addr(palSocketAddress_t *address, palIpV6Addr_t ipV6Addr); /*! \brief Get an IPv6 address from an address data structure. * @param[in] address The address data structure to query. * @param[out] ipV6Addr The address to get. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_getSockAddrIPV6Addr(const palSocketAddress_t* address, palIpV6Addr_t ipV6Addr); +palStatus_t pal_getSockAddrIPV6Addr(const palSocketAddress_t *address, palIpV6Addr_t ipV6Addr); /*! \brief Set a NAT64 address from an IPv4 address data structure and set `addressType` as IPv6. * @param[in,out] address The address data structure to configure. * @param[in] ipV4Addr The address value to set. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_setSockAddrNAT64Addr(palSocketAddress_t* address, palIpV4Addr_t ipV4Addr); +palStatus_t pal_setSockAddrNAT64Addr(palSocketAddress_t *address, palIpV4Addr_t ipV4Addr); /*! \brief Get a port from an address data structure. * @param[in] address The address data structure to query. * @param[out] port The port to get. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_getSockAddrPort(const palSocketAddress_t* address, uint16_t* port); +palStatus_t pal_getSockAddrPort(const palSocketAddress_t *address, uint16_t *port); /*! \brief Set the value for a socket option on a network socket. * @param[in] socket The socket to configure. @@ -185,7 +192,7 @@ palStatus_t pal_getSockAddrPort(const palSocketAddress_t* address, uint16_t* por * @param[in] optionLength The size of the buffer provided for `optionValue`. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength); +palStatus_t pal_setSocketOptions(palSocket_t socket, int optionName, const void *optionValue, palSocketLength_t optionLength); /*! \brief Set the value for a socket option on a network socket. * @param[in] socket The socket to configure. @@ -195,14 +202,14 @@ palStatus_t pal_setSocketOptions(palSocket_t socket, int optionName, const void* * @param[in] optionLength The size of the buffer provided for `optionValue`. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_setSocketOptionsWithLevel(palSocket_t socket, palSocketOptionLevelName_t optionLevel, int optionName, const void* optionValue, palSocketLength_t optionLength); +palStatus_t pal_setSocketOptionsWithLevel(palSocket_t socket, palSocketOptionLevelName_t optionLevel, int optionName, const void *optionValue, palSocketLength_t optionLength); /*! \brief Check if a socket is non-blocking. * @param[in] socket The socket to check. * @param[out] isNonBlocking `True` if the socket is non-blocking, otherwise `false`. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_isNonBlocking(palSocket_t socket, bool* isNonBlocking); +palStatus_t pal_isNonBlocking(palSocket_t socket, bool *isNonBlocking); /*! \brief Bind a socket to a local address. * @param[in] socket The socket to bind. @@ -210,7 +217,7 @@ palStatus_t pal_isNonBlocking(palSocket_t socket, bool* isNonBlocking); * @param[in] addressLength The length of the address passed in `myAddress`. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength); +palStatus_t pal_bind(palSocket_t socket, palSocketAddress_t *myAddress, palSocketLength_t addressLength); /*! \brief Receive a payload from a specific socket. * @param[in] socket The socket to receive from. The socket passed to this function should usually be of type `PAL_SOCK_DGRAM`, though your specific implementation may support other types as well. @@ -221,7 +228,7 @@ palStatus_t pal_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocke * @param[out] bytesReceived The actual amount of payload data received in the buffer. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived); +palStatus_t pal_receiveFrom(palSocket_t socket, void *buffer, size_t length, palSocketAddress_t *from, palSocketLength_t *fromLength, size_t *bytesReceived); /*! \brief Send a payload to an address using a specific socket. * @param[in] socket The socket to use for sending the payload. The socket passed to this function should usually be of type `PAL_SOCK_DGRAM`, though your specific implementation may support other types as well. @@ -232,27 +239,27 @@ palStatus_t pal_receiveFrom(palSocket_t socket, void* buffer, size_t length, pal * @param[out] bytesSent The actual amount of payload data sent. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent); +palStatus_t pal_sendTo(palSocket_t socket, const void *buffer, size_t length, const palSocketAddress_t *to, palSocketLength_t toLength, size_t *bytesSent); /*! \brief Close a network socket. * @param[in,out] socket The socket to be closed. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. * \note Receives `palSocket_t*`, \e not `palSocket_t`, so that it can zero the socket to avoid re-use. */ -palStatus_t pal_close(palSocket_t* socket); +palStatus_t pal_close(palSocket_t *socket); /*! \brief Get the number of current network interfaces. * @param[out] numInterfaces The number of interfaces. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_getNumberOfNetInterfaces(uint32_t* numInterfaces); +palStatus_t pal_getNumberOfNetInterfaces(uint32_t *numInterfaces); /*! \brief Get information regarding the socket at the interface index number given. This number is returned when registering the socket. * @param[in] interfaceNum The number of the interface to get information for. * @param[out] interfaceInfo The information for the given interface number. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t* interfaceInfo); +palStatus_t pal_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t *interfaceInfo); /*! \brief Set listener for connection status events. * @param[in] interfaceNum Index of the network interface to be listen. @@ -274,7 +281,7 @@ palStatus_t pal_setConnectionStatusCallback(uint32_t interfaceNum, connectionSta /*! \brief The type of the callback function passed when creating asynchronous sockets. * @param[in] argument The user provided argument passed to the callback function. */ -typedef void(*palAsyncSocketCallback_t)(void*); +typedef void(*palAsyncSocketCallback_t)(void *); #if PAL_NET_TCP_AND_TLS_SUPPORT // The functionality below is supported only if TCP is supported. @@ -296,7 +303,7 @@ palStatus_t pal_listen(palSocket_t socket, int backlog); * @param[in] callbackArgument The callback argument to be attached to the asynchronous accepted socket. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_accept(palSocket_t socket, palSocketAddress_t* address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket, palAsyncSocketCallback_t callback, void* callbackArgument); +palStatus_t pal_accept(palSocket_t socket, palSocketAddress_t *address, palSocketLength_t *addressLen, palSocket_t *acceptedSocket, palAsyncSocketCallback_t callback, void *callbackArgument); #endif // PAL_NET_SERVER_SOCKET_API @@ -306,7 +313,7 @@ palStatus_t pal_accept(palSocket_t socket, palSocketAddress_t* address, palSocke * @param[in] addressLen The length of the `address` field. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen); +palStatus_t pal_connect(palSocket_t socket, const palSocketAddress_t *address, palSocketLength_t addressLen); /*! \brief Receive data from a connected socket. * @param[in] socket The connected socket on which to receive data. The socket passed to this function should usually be of type `PAL_SOCK_STREAM`, though your specific implementation may support other types as well. @@ -315,7 +322,7 @@ palStatus_t pal_connect(palSocket_t socket, const palSocketAddress_t* address, p * @param[out] recievedDataSize The length of the data actually received. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_recv(palSocket_t socket, void* buf, size_t len, size_t* recievedDataSize); +palStatus_t pal_recv(palSocket_t socket, void *buf, size_t len, size_t *recievedDataSize); /*! \brief Send a buffer via a connected socket. * @param[in] socket The connected socket on which to send data. The socket passed to this function should usually be of type `PAL_SOCK_STREAM`, though your specific implementation may support other types as well. @@ -324,7 +331,7 @@ palStatus_t pal_recv(palSocket_t socket, void* buf, size_t len, size_t* recieved * @param[out] sentDataSize The length of the data sent. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_send(palSocket_t socket, const void* buf, size_t len, size_t* sentDataSize); +palStatus_t pal_send(palSocket_t socket, const void *buf, size_t len, size_t *sentDataSize); #endif //PAL_NET_TCP_AND_TLS_SUPPORT @@ -338,7 +345,7 @@ palStatus_t pal_send(palSocket_t socket, const void* buf, size_t len, size_t* se * @param[out] socket The socket is returned through this output parameter. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, palSocket_t* socket); +palStatus_t pal_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, palSocket_t *socket); /*! \brief Get an asynchronous network socket that passes the provided `callbackArgument` to a specified callback when it is triggered. * @param[in] domain The domain for the created socket. See enum `palSocketDomain_t` for supported types. @@ -350,7 +357,7 @@ palStatus_t pal_asynchronousSocket(palSocketDomain_t domain, palSocketType_t typ * @param[out] socket The socket is returned through this output parameter. * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_asynchronousSocketWithArgument(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback,void* callbackArgument, palSocket_t* socket); +palStatus_t pal_asynchronousSocketWithArgument(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void *callbackArgument, palSocket_t *socket); #if PAL_NET_DNS_SUPPORT @@ -361,8 +368,9 @@ palStatus_t pal_asynchronousSocketWithArgument(palSocketDomain_t domain, palSock * Supports both IP address as a string, and hostnames (using DNS lookup). * @param[in] hostname The hostname (or IP address string) to be translated to a `palSocketAddress_t`. * @param[out] address The address for the output of the translation. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_getAddressInfo(const char* hostname, palSocketAddress_t* address, palSocketLength_t* addressLength); +palStatus_t pal_getAddressInfo(const char *hostname, palSocketAddress_t *address, palSocketLength_t *addressLength); #if (PAL_DNS_API_VERSION == 1) @@ -372,8 +380,9 @@ palStatus_t pal_getAddressInfo(const char* hostname, palSocketAddress_t* address * @param[in] addressLength The length of the address for the output of the translation in bytes. * @param[in] status The status of the operation - PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. * @param[in] callbackArgument The user callback argument. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -typedef void(*palGetAddressInfoAsyncCallback_t)(const char* hostname, palSocketAddress_t* address, palSocketLength_t* addressLength, palStatus_t status, void* callbackArgument); +typedef void(*palGetAddressInfoAsyncCallback_t)(const char *hostname, palSocketAddress_t *address, palSocketLength_t *addressLength, palStatus_t status, void *callbackArgument); /*! \brief This function translates a hostname to `palSocketAddress_t` which can be used with PAL sockets. * @@ -384,11 +393,12 @@ typedef void(*palGetAddressInfoAsyncCallback_t)(const char* hostname, palSocketA * @param[out] addressLength The length of the address for the output of the translation in bytes. * @param[in] callback The user-provided callback to be invoked once the function has completed. * @param[in] callbackArgument The user-provided callback argument which will be passed back to the callback function. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -palStatus_t pal_getAddressInfoAsync(const char* hostname, palSocketAddress_t* address, palSocketLength_t* addressLength, palGetAddressInfoAsyncCallback_t callback, void* callbackArgument); +palStatus_t pal_getAddressInfoAsync(const char *hostname, palSocketAddress_t *address, palSocketLength_t *addressLength, palGetAddressInfoAsyncCallback_t callback, void *callbackArgument); #endif - -#elif (PAL_DNS_API_VERSION == 2) +#elif (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) +#if (PAL_DNS_API_VERSION == 2) typedef int32_t palDNSQuery_t; /*!< \brief PAL DNS query handle. Can be used to cancel the asynchronous DNS query. */ /*! \brief Prototype of the callback function invoked when querying address info asynchronously using `pal_getAddressInfoAsync`. @@ -396,8 +406,9 @@ typedef int32_t palDNSQuery_t; /*!< \brief PAL DNS query handle. Can be used to * @param[out] address The address for the output of the translation. * @param[out] status The status of the operation - PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. * @param[in] callbackArgument The user callback argument. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ -typedef void(*palGetAddressInfoAsyncCallback_t)(const char* hostname, palSocketAddress_t* address, palStatus_t status, void* callbackArgument); +typedef void(*palGetAddressInfoAsyncCallback_t)(const char *hostname, palSocketAddress_t *address, palStatus_t status, void *callbackArgument); /*! \brief Structure used by pal_getAddressInfoAsync. * @param[in] hostname The user-provided hostname (or IP address string) to be translated. @@ -405,37 +416,109 @@ typedef void(*palGetAddressInfoAsyncCallback_t)(const char* hostname, palSocketA * @param[in] callback The user-provided callback. * @param[in] callbackArgument The user callback argument of `pal_GetAddressInfoAsyncCallback_t`. * @param[out] queryHandle Handler ID, which can be used for a cancellation request. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. + */ +typedef struct pal_asyncAddressInfo { + char *hostname; + palSocketAddress_t *address; + palGetAddressInfoAsyncCallback_t callback; + void *callbackArgument; + palDNSQuery_t *queryHandle; +} pal_asyncAddressInfo_t; + +/*! \brief This function translates a hostname to `palSocketAddress_t` which can be used with PAL sockets. + * + * Supports both IP address as a string, and hostname (using DNS lookup). + * \note The function is non-blocking. + * @param[in] hostname The user-provided hostname (or IP address string) to be translated. + * @param[out] address The address for the output of the translation. + * @param[in] callback The user-provided callback to be invoked once the function has completed. + * @param[in] callbackArgument The user callback argument of `pal_GetAddressInfoAsyncCallback_t`. + * @param[out] queryHandle DNS query handler. Caller must take care of allocation. If not used, then set as `NULL`. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. + */ +palStatus_t pal_getAddressInfoAsync(const char *hostname, + palSocketAddress_t *address, + palGetAddressInfoAsyncCallback_t callback, + void *callbackArgument, + palDNSQuery_t *queryHandle); + +#elif (PAL_DNS_API_VERSION == 3) +typedef uintptr_t palDNSQuery_t; /*!< \brief PAL DNS query handle. Can be used to cancel the asynchronous DNS query. */ + +/*! \brief This function puts the palSocketAddress_t from the given index in palAddressInfo_t to the given addr + * @param[in] addrInfo The palAddressInfo_t which (if any) palSocketAddress_t is get. + * @param[in] index Index of the address in addrInfo to fetch. + * @param[out] addr palSocketAddress_t is put to this instance is any if found. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. + */ +palStatus_t pal_getDNSAddress(palAddressInfo_t *addrInfo, uint16_t index, palSocketAddress_t *addr); + +/*! \brief Return the number of dns addresses in the given addrInfo + * @param[in] addrInfo The palAddressInfo_t to be used for countung dns addresses. + * \return Number of DNS addresses in the given addrInfo. + */ +int pal_getDNSCount(palAddressInfo_t *addrInfo); + +/*! \brief Free the given addrInfo. + * @param[in] addrInfo OS specific palAddressInfo_t which holds dns addresses. + */ +void pal_freeAddrInfo(palAddressInfo_t *addrInfo); + +/*! \brief This function free's the thread needed in pal_getAddressInfoAsync + * @param[out] handle PAL DNS query handle, used to cancel the asynchronous DNS query. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. +*/ +palStatus_t pal_free_addressinfoAsync(palDNSQuery_t handle); + +/*! \brief Prototype of the callback function invoked when querying address info asynchronously using `pal_getAddressInfoAsync`. + * @param[in] hostname The user-provided hostname (or IP address string) to be translated. + * @param[out] addrInfo OS specific palAddressInfo_t which holds dns addresses. + * @param[out] status The status of the operation - PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. + * @param[in] callbackArgument The user callback argument. + */ +typedef void(*palGetAddressInfoAsyncCallback_t)(const char *hostname, palAddressInfo_t *addrInfo, palStatus_t status, void *callbackArgument); + +/*! \brief Structure used by pal_getAddressInfoAsync. + * @param[in] hostname The user-provided hostname (or IP address string) to be translated. + * @param[out] addrInfo OS specific palAddressInfo_t which holds dns addresses. + * @param[in] callback The user-provided callback. + * @param[in] callbackArgument The user callback argument of `pal_GetAddressInfoAsyncCallback_t`. + * @param[out] queryHandle Handler ID, which can be used for a cancellation request. */ typedef struct pal_asyncAddressInfo { char* hostname; - palSocketAddress_t* address; + palAddressInfo_t *addrInfo; palGetAddressInfoAsyncCallback_t callback; void* callbackArgument; palDNSQuery_t *queryHandle; } pal_asyncAddressInfo_t; -/*! \brief This function translates a hostname to `palSocketAddress_t` which can be used with PAL sockets. +/*! \brief This function translates a hostname to `palSocketAddress_t`(s) which can be used with PAL sockets. * * Supports both IP address as a string, and hostname (using DNS lookup). * \note The function is non-blocking. * @param[in] hostname The user-provided hostname (or IP address string) to be translated. - * @param[out] address The address for the output of the translation. * @param[in] callback The user-provided callback to be invoked once the function has completed. + * @param[in] callbackArgument The user callback argument of `pal_GetAddressInfoAsyncCallback_t`. * @param[out] queryHandle DNS query handler. Caller must take care of allocation. If not used, then set as `NULL`. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ palStatus_t pal_getAddressInfoAsync(const char* hostname, - palSocketAddress_t* address, palGetAddressInfoAsyncCallback_t callback, void* callbackArgument, palDNSQuery_t* queryHandle); +#endif + /*! \brief This function is a cancellation for `pal_getAddressInfoAsync`. * @param[in] queryHandle Id of the ongoing DNS query. +* \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. */ palStatus_t pal_cancelAddressInfoAsync(palDNSQuery_t queryHandle); #else - #error "Please specify the platform PAL_DNS_API_VERSION 0, 1, or 2." + #error "Please specify the platform PAL_DNS_API_VERSION 0, 1, 2 or 3" #endif // PAL_DNS_API_VERSION #endif // PAL_NET_DNS_SUPPORT diff --git a/mbed-client-pal/Source/PAL-Impl/Services-API/pal_rtos.h b/mbed-client-pal/Source/PAL-Impl/Services-API/pal_rtos.h index 409a6abba..43683c115 100644 --- a/mbed-client-pal/Source/PAL-Impl/Services-API/pal_rtos.h +++ b/mbed-client-pal/Source/PAL-Impl/Services-API/pal_rtos.h @@ -141,7 +141,7 @@ uint64_t pal_osKernelSysTickFrequency(void); * * @param[in] function A function pointer to the thread callback function. * @param[in] funcArgument An argument for the thread function. -* @param[in] priority The priority of the thread. +* @param[in] priority The priority of the thread. Not used in Linux. * @param[in] stackSize The stack size of the thread, can NOT be 0. * @param[in] store \b MUST be `NULL` - this functionality is not supported. * @param[out] threadID: The created thread ID handle. In case of error, this value is `NULL`. diff --git a/mbed-client-pal/Source/PAL-Impl/pal_init.c b/mbed-client-pal/Source/PAL-Impl/pal_init.c index d74d3ca61..8acd995cc 100644 --- a/mbed-client-pal/Source/PAL-Impl/pal_init.c +++ b/mbed-client-pal/Source/PAL-Impl/pal_init.c @@ -18,7 +18,7 @@ #include "pal.h" #include "pal_plat_network.h" #include "pal_plat_TLS.h" -#include "pal_plat_Crypto.h" +#include "cs_pal_plat_crypto.h" #include "pal_plat_drbg.h" #include "pal_macros.h" #ifndef MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT diff --git a/mbed-client-pal/Source/Port/Platform-API/pal_plat_TLS.h b/mbed-client-pal/Source/Port/Platform-API/pal_plat_TLS.h index a7b39aa55..a5d3c194a 100644 --- a/mbed-client-pal/Source/Port/Platform-API/pal_plat_TLS.h +++ b/mbed-client-pal/Source/Port/Platform-API/pal_plat_TLS.h @@ -192,14 +192,6 @@ palStatus_t pal_plat_setHandShakeTimeOut(palTLSConfHandle_t palTLSConf, uint32_t */ palStatus_t pal_plat_sslSetup(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf); -/*! \brief Perform the TLS handshake ping. - * - * @param[in] palTLSHandle: The TLS context. - * - * \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure. - */ -palStatus_t pal_plat_handShake_ping(palTLSHandle_t palTLSHandle); - /*! \brief Perform the TLS handshake. * * @param[in] palTLSHandle: The TLS context. @@ -401,6 +393,14 @@ void pal_plat_set_cid(const uint8_t* context, const size_t length); */ void pal_plat_set_cid_value(palTLSHandle_t palTLSHandle, const uint8_t *data_ptr, const size_t data_len); +/** + * \brief Internal test function. Get CID for the current tls session. + * \param[in] palTLSHandle: The TLS context. + * \param[out] data_ptr: CID + * \param[in,out] data_len: length of the CID + */ +void pal_plat_get_cid_value(palTLSHandle_t palTLSHandle, uint8_t *data_ptr, size_t *data_len); + #endif //PAL_USE_SSL_SESSION_RESUME #endif //_PAL_PLAT_TLS_H_ diff --git a/mbed-client-pal/Source/Port/Platform-API/pal_plat_network.h b/mbed-client-pal/Source/Port/Platform-API/pal_plat_network.h index a0d77f0df..8e8b37253 100644 --- a/mbed-client-pal/Source/Port/Platform-API/pal_plat_network.h +++ b/mbed-client-pal/Source/Port/Platform-API/pal_plat_network.h @@ -230,7 +230,31 @@ palStatus_t pal_plat_asynchronousSocket(palSocketDomain_t domain, palSocketType_ */ palStatus_t pal_plat_getAddressInfo(const char* hostname, palSocketAddress_t* address, palSocketLength_t* addressLength); -#elif (PAL_DNS_API_VERSION == 2) +#elif (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) +#if (PAL_DNS_API_VERSION == 3) +/*! \brief This function puts the palSocketAddress_t from the given index in palAddressInfo_t to the given addr + * @param[in] addrInfo The palAddressInfo_t which (if any) palSocketAddress_t is get. + * @param[in] index Index of the address in addrInfo to fetch. + * @param[out] addr palSocketAddress_t is put to this instance is any if found. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. + */ +palStatus_t pal_plat_getDNSAddress(palAddressInfo_t *addrInfo, uint16_t index, palSocketAddress_t *addr); + +/*! \brief Return the number of dns addresses in the given addrInfo + * @param[in] addrInfo The palAddressInfo_t to be used for countung dns addresses. + * \return Number of DNS addresses in the given addrInfo. + */ +int pal_plat_getDNSCount(palAddressInfo_t *addrInfo); + +/*! \brief Free the given addrInfo. + * @param[in] addrInfo OS specific palAddressInfo_t which holds dns addresses. + */ +void pal_plat_freeAddrInfo(palAddressInfo_t* addrInfo); + +/*! \brief This function free's the thread used in pal_getAddressInfoAsync +*/ +palStatus_t pal_plat_free_addressinfoAsync(palDNSQuery_t queryHandle); +#endif /*! \brief This function translates a hostname to a `palSocketAddress_t` that can be used with PAL sockets. * @param[in] info address of `pal_asyncAddressInfo_t`. @@ -242,7 +266,7 @@ palStatus_t pal_plat_getAddressInfoAsync(pal_asyncAddressInfo_t* info); */ palStatus_t pal_plat_cancelAddressInfoAsync(palDNSQuery_t queryHandle); #else - #error "Please specify the platform PAL_DNS_API_VERSION 0, 1, or 2." + #error "Please specify the platform PAL_DNS_API_VERSION 0, 1, 2 or 3." #endif // PAL_DNS_API_VERSION #endif // PAL_NET_DNS_SUPPORT diff --git a/mbed-client-pal/Source/Port/Platform-API/pal_plat_rtos.h b/mbed-client-pal/Source/Port/Platform-API/pal_plat_rtos.h index 5adc1afbc..67d720974 100644 --- a/mbed-client-pal/Source/Port/Platform-API/pal_plat_rtos.h +++ b/mbed-client-pal/Source/Port/Platform-API/pal_plat_rtos.h @@ -81,7 +81,7 @@ uint64_t pal_plat_osKernelSysTickFrequency(void); * * @param[in] function A function pointer to the thread callback function. * @param[in] funcArgument An argument for the thread function. - * @param[in] priority The priority of the thread. + * @param[in] priority The priority of the thread. Not used in Linux. * @param[in] stackSize The stack size of the thread in bytes, can NOT be 0. * @param[out] threadID: The created thread ID handle. In case of error, this value is NULL. * diff --git a/mbed-client-pal/Source/Port/Reference-Impl/Generic/DRBG/SOTP/pal_plat_drbg_sotp.c b/mbed-client-pal/Source/Port/Reference-Impl/Generic/DRBG/SOTP/pal_plat_drbg_sotp.c index 8d5548699..40b850452 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/Generic/DRBG/SOTP/pal_plat_drbg_sotp.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/Generic/DRBG/SOTP/pal_plat_drbg_sotp.c @@ -19,7 +19,7 @@ #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "pal_plat_drbg.h" #include "pal_plat_drbg_noise.h" #include "sotp.h" diff --git a/mbed-client-pal/Source/Port/Reference-Impl/Generic/DRBG/pal_plat_drbg_noise.c b/mbed-client-pal/Source/Port/Reference-Impl/Generic/DRBG/pal_plat_drbg_noise.c index d8368d676..060a4fac2 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/Generic/DRBG/pal_plat_drbg_noise.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/Generic/DRBG/pal_plat_drbg_noise.c @@ -15,7 +15,7 @@ *******************************************************************************/ #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "pal_plat_drbg.h" /** diff --git a/mbed-client-pal/Source/Port/Reference-Impl/Generic/Entropy/PSA/pal_plat_entropy_psa.c b/mbed-client-pal/Source/Port/Reference-Impl/Generic/Entropy/PSA/pal_plat_entropy_psa.c index e369e7d6f..ff88f3dc8 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/Generic/Entropy/PSA/pal_plat_entropy_psa.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/Generic/Entropy/PSA/pal_plat_entropy_psa.c @@ -19,7 +19,7 @@ #if defined(MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT) || defined (MBED_CONF_MBED_CLOUD_CLIENT_PSA_SUPPORT) #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "pal_plat_entropy.h" // Include mbedtls config file explicitly for MBEDTLS_ENTROPY_NV_SEED flag diff --git a/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/DRBG/pal_plat_drbg_w_entropy_sources.c b/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/DRBG/pal_plat_drbg_w_entropy_sources.c index ba6c23b21..c841b13c3 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/DRBG/pal_plat_drbg_w_entropy_sources.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/DRBG/pal_plat_drbg_w_entropy_sources.c @@ -30,7 +30,7 @@ #include "mbedtls/ctr_drbg.h" #include "mbedtls/entropy.h" #include "mbedtls/config.h" -#include "pal_plat_Crypto.h" +#include "cs_pal_plat_crypto.h" #if PAL_USE_HW_TRNG #include "pal_plat_drbg_noise.h" #endif diff --git a/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/TLS/pal_plat_TLS.c b/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/TLS/pal_plat_TLS.c index a0270e15f..ffcd5a7c6 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/TLS/pal_plat_TLS.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/TLS/pal_plat_TLS.c @@ -232,6 +232,8 @@ PAL_PRIVATE palStatus_t translateTLSHandShakeErrToPALError(palTLS_t* tlsCtx, int status = PAL_ERR_X509_CERT_VERIFY_FAILED; break; #endif + // Treat unexpected messages during renegotiation as fatal. + case MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO: case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: // In some cases the ssl->f_send() can already return connection termination. case PAL_ERR_SOCKET_CONNECTION_RESET: @@ -844,32 +846,6 @@ palStatus_t pal_plat_sslSetup(palTLSHandle_t palTLSHandle, palTLSConfHandle_t pa return status; } -palStatus_t pal_plat_handShake_ping(palTLSHandle_t palTLSHandle) -{ - palStatus_t status = PAL_SUCCESS; - palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle; - int32_t platStatus = SSL_LIB_SUCCESS; - - while( (MBEDTLS_SSL_SERVER_HELLO != localTLSCtx->tlsCtx.state) && (PAL_SUCCESS == status) ) - { - platStatus = mbedtls_ssl_handshake_step( &localTLSCtx->tlsCtx ); - - /* Extract the first 4 bytes of the ServerHello random */ - if( MBEDTLS_SSL_SERVER_HELLO == localTLSCtx->tlsCtx.state ) - { - PAL_LOG_DBG("Server responded to CLIENT HELLO PING -success"); - } - - if (SSL_LIB_SUCCESS != platStatus) - { - status = translateTLSHandShakeErrToPALError(localTLSCtx, platStatus); - } - } - - return status; -} - - palStatus_t pal_plat_handShake(palTLSHandle_t palTLSHandle, uint64_t* serverTime) { palStatus_t status = PAL_SUCCESS; @@ -1572,7 +1548,7 @@ void pal_plat_set_cid(const uint8_t* context, const size_t length) memcpy(ssl_session_context, context, length); ssl_session_context_length = length; } else { - PAL_LOG_ERR("pal_plat_set_cid - cid set failed, too long %lu (max was %d)", length, SSL_SESSION_STORE_SIZE); + PAL_LOG_ERR("pal_plat_set_cid - cid set failed, too long %" PRIu32 " (max was %d)", (uint32_t)length, SSL_SESSION_STORE_SIZE); } } @@ -1586,4 +1562,21 @@ void pal_plat_set_cid_value(palTLSHandle_t palTLSHandle, const uint8_t *data_ptr pal_plat_saveSslSessionBuffer(palTLSHandle); #endif } + +void pal_plat_get_cid_value(palTLSHandle_t palTLSHandle, uint8_t *data_ptr, size_t *data_len) +{ + palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle; + assert(data_ptr != NULL); + assert(data_len != NULL); + assert(MBEDTLS_SSL_CID_OUT_LEN_MAX >= *data_len); + + *data_len = 0; + *data_ptr = 0; +#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID + if (localTLSCtx->tlsCtx.transform_out) { + memcpy(data_ptr, localTLSCtx->tlsCtx.transform_out->out_cid, localTLSCtx->tlsCtx.transform_out->out_cid_len); + *data_len = localTLSCtx->tlsCtx.transform_out->out_cid_len; + } +#endif +} #endif // PAL_USE_SSL_SESSION_RESUME diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/pal_plat_linux_common.c b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/pal_plat_linux_common.c index 527c50af6..f9c9388af 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/pal_plat_linux_common.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/pal_plat_linux_common.c @@ -74,6 +74,8 @@ palStatus_t pal_plat_osEntropyRead(const char *entropyFileName, uint8_t *randomB status = PAL_ERR_FS_NO_FILE; } + printf("Finished generating random from %s.\n", entropySourceFileName); + if (NULL != actualRandomSizeBytesOut) { *actualRandomSizeBytesOut = actualRead; } diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Networking/pal_plat_network.c b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Networking/pal_plat_network.c index 7f6a516f3..58992e8f2 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Networking/pal_plat_network.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Networking/pal_plat_network.c @@ -1173,9 +1173,8 @@ palStatus_t pal_plat_getAddressInfo(const char *hostname, palSocketAddress_t *ad struct addrinfo *pAddrInf = NULL; struct addrinfo hints = {0}; int res; - int supportedAddressType1 = 0; - int supportedAddressType2 = 0; - hints.ai_family = AF_UNSPEC; + int supportedAddressType1; + int supportedAddressType2; #if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY supportedAddressType1 = AF_INET; @@ -1227,7 +1226,173 @@ palStatus_t pal_plat_getAddressInfo(const char *hostname, palSocketAddress_t *ad return result; } +#if (PAL_DNS_API_VERSION == 3) + +PAL_PRIVATE palStatus_t getAddressInfo(const char *hostname, struct addrinfo **addrInfo) +{ + palStatus_t result = PAL_SUCCESS; + struct addrinfo hints = {0}; + int err; + int supportedAddressType1; + int supportedAddressType2; + +#if PAL_NET_TCP_AND_TLS_SUPPORT == true + hints.ai_socktype = SOCK_STREAM; +#else + hints.ai_socktype = SOCK_DGRAM; #endif +#if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY + supportedAddressType1 = AF_INET; + supportedAddressType2 = AF_INET6; + hints.ai_family = AF_UNSPEC; +#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV4_ONLY + supportedAddressType1 = AF_INET; + supportedAddressType2 = AF_INET; + hints.ai_family = AF_INET; +#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV6_ONLY + supportedAddressType1 = AF_INET6; + supportedAddressType2 = AF_INET6; + hints.ai_family = AF_INET6; +#else +#error PAL_NET_DNS_IP_SUPPORT is not defined to a valid value. +#endif + + err = getaddrinfo(hostname, NULL, &hints, addrInfo); + if (err < 0) + { + // getaddrinfo returns EAI-error. In case of EAI_SYSTEM, the error + // is 'Other system error, check errno for details' + // (http://man7.org/linux/man-pages/man3/getaddrinfo.3.html#RETURN_VALUE) + if (err == EAI_SYSTEM) + { + result = translateErrorToPALError(errno); + } + else + { + // errno values are positive, getaddrinfo errors are negative so they can be mapped + // in the same place. + result = translateErrorToPALError(err); + } + } + else + { + // remove addresses that don't match what hints tried to tell + struct addrinfo *prev = *addrInfo, *curr = *addrInfo; + while (curr) { + if ((curr->ai_family != supportedAddressType1 && curr->ai_family != supportedAddressType2) || + curr->ai_socktype != hints.ai_socktype) + { + // remove from the list + if (prev == curr) + { + // remove first item + *addrInfo = curr->ai_next; + prev = curr->ai_next; + } + else + { + // remove from the middle or end + prev->ai_next = curr->ai_next; + prev = curr; + } + free(curr); + curr = prev->ai_next; + } + else + { + prev = curr; + curr = curr->ai_next; + } + } + } + + return result; +} + +// Thread function. +PAL_PRIVATE void asyncDNSQueryFunc(void const *arg) +{ + pal_asyncAddressInfo_t *info = (pal_asyncAddressInfo_t *)(arg); + struct addrinfo *addr; + palStatus_t result = getAddressInfo(info->hostname, &addr); + if (result == PAL_SUCCESS) + { + info->addrInfo = (palAddressInfo_t *)addr; + } + else + { + info->addrInfo = NULL; + } + + info->callback(info->hostname, info->addrInfo, result, info->callbackArgument); // invoke callback + free(info); +} + +int pal_plat_getDNSCount(palAddressInfo_t *addrInfo) +{ + int count = 0; + struct addrinfo *curr = (struct addrinfo *)addrInfo; + while (curr) + { + count++; + curr = curr->ai_next; + } + return count; +} + +palStatus_t pal_plat_getDNSAddress(palAddressInfo_t *addressInfo, uint16_t index, palSocketAddress_t *addr) +{ + struct addrinfo *info = (struct addrinfo *)addressInfo; + uint16_t count = 0; + palStatus_t result = PAL_ERR_INVALID_ARGUMENT; + + while (info) + { + if (count == index) + { + mempcpy((void *)addr, info->ai_addr, info->ai_addrlen); + result = PAL_SUCCESS; + break; + } + count++; + info = info->ai_next; + } + return result; +} + +void pal_plat_freeAddrInfo(palAddressInfo_t *addressInfo) +{ + freeaddrinfo((struct addrinfo *)addressInfo); +} + +palStatus_t pal_plat_free_addressinfoAsync(palDNSQuery_t queryHandle) +{ + return pal_plat_cancelAddressInfoAsync(queryHandle); +} + +palStatus_t pal_plat_getAddressInfoAsync(pal_asyncAddressInfo_t *info) +{ + return pal_osThreadCreateWithAlloc(asyncDNSQueryFunc, (void *)info, PAL_osPriorityReservedDNS, PAL_ASYNC_DNS_THREAD_STACK_SIZE, NULL, info->queryHandle); +} + +palStatus_t pal_plat_cancelAddressInfoAsync(palDNSQuery_t queryHandle) +{ + // just try to delete thread + palStatus_t result = PAL_SUCCESS; + if (queryHandle != NULLPTR) + { + palStatus_t result = pal_osThreadTerminate(&queryHandle); + if (PAL_SUCCESS != result) + { + PAL_LOG_ERR("error terminating dns async thread: %d", result); + } + queryHandle = NULLPTR; + } + return result; +} + +#endif // (PAL_DNS_API_VERSION == 3) +#endif // PAL_NET_DNS_SUPPORT palStatus_t pal_plat_setConnectionStatusCallback(uint32_t interfaceIndex, connectionStatusCallback callback, void *arg) { diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/RTOS/pal_plat_rtos.c b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/RTOS/pal_plat_rtos.c index 8c9431227..3998d024a 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/RTOS/pal_plat_rtos.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/RTOS/pal_plat_rtos.c @@ -244,9 +244,9 @@ PAL_PRIVATE void* threadFunction(void* arg) palStatus_t pal_plat_osThreadCreate(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadID_t* threadID) { + (void)priority; palStatus_t status = PAL_ERR_GENERIC_FAILURE; pthread_t sysThreadID = (pthread_t)NULL; - struct sched_param schedParam; pthread_attr_t attr; pthread_attr_t* ptrAttr = NULL; palThreadData_t* threadData; @@ -269,29 +269,8 @@ palStatus_t pal_plat_osThreadCreate(palThreadFuncPtr function, void* funcArgumen goto finish; } - err = pthread_attr_setschedpolicy(ptrAttr, SCHED_RR); - if (0 != err) - { - goto finish; - } - -#if (PAL_SIMULATOR_TEST_ENABLE == 0) // disable ONLY for Linux PC simulator - err = pthread_attr_setinheritsched(ptrAttr, PTHREAD_EXPLICIT_SCHED); - if (0 != err) - { - goto finish; - } -#endif - err = pthread_attr_setdetachstate(ptrAttr, PTHREAD_CREATE_DETACHED); if (0 != err) - { - goto finish; - } - - schedParam.sched_priority = PAL_THREAD_PRIORITY_TRANSLATE(priority); - err = pthread_attr_setschedparam(ptrAttr, &schedParam); - if (0 != err) { goto finish; } diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/fd_work_poll.h b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/fd_work_poll.h index 6a7f13745..0315c8829 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/fd_work_poll.h +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/fd_work_poll.h @@ -40,7 +40,7 @@ extern "C" { typedef struct fd_work_poll_s { #if (defined(PAL_SOCKET_USE_LONG_POLLING) && (PAL_SOCKET_USE_LONG_POLLING == 1)) || \ (defined(PAL_SOCKET_USE_LONG_POLLING_THREAD) && (PAL_SOCKET_USE_LONG_POLLING_THREAD == 1)) - struct k_delayed_work work; + struct k_work_delayable work; int nfds; k_ticks_t timeout; k_ticks_t remaining; diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/fd_work_poll_polling.c b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/fd_work_poll_polling.c index 775fa309a..c95ca0bd4 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/fd_work_poll_polling.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/fd_work_poll_polling.c @@ -90,7 +90,7 @@ void fd_work_poll_init(fd_work_poll_t *work, fd_work_handler_t handler) } #endif - k_delayed_work_init(&work->work, fd_work_delayed_handler); + k_work_init_delayable(&work->work, fd_work_delayed_handler); work->handler = handler; } @@ -112,7 +112,9 @@ int fd_work_poll_submit(fd_work_poll_t *work, struct zsock_pollfd *fds, int nfds k_mutex_unlock(&fd_work_mutex); /* wait at least one polling interval before actually polling. */ - k_delayed_work_submit_to_queue(&WORK_QUEUE_NAME, &work->work, Z_TIMEOUT_TICKS(work->timeout)); + k_work_reschedule_for_queue(&WORK_QUEUE_NAME, + &work->work, + Z_TIMEOUT_TICKS(work->timeout)); } return 0; @@ -126,7 +128,7 @@ static void fd_work_delayed_handler(struct k_work* input) * Get the encapsulating container which contains variables carried across * work queue invocations. */ - struct k_delayed_work* delayed = CONTAINER_OF(input, struct k_delayed_work, work); + struct k_work_delayable* delayed = CONTAINER_OF(input, struct k_work_delayable, work); fd_work_poll_t* work = CONTAINER_OF(delayed, fd_work_poll_t, work); @@ -188,7 +190,9 @@ static void fd_work_delayed_handler(struct k_work* input) } else { /* reschedule work. */ - k_delayed_work_submit_to_queue(&WORK_QUEUE_NAME, &work->work, Z_TIMEOUT_TICKS(work_delay)); + k_work_reschedule_for_queue(&WORK_QUEUE_NAME, + delayed, + Z_TIMEOUT_TICKS(work_delay)); } } } @@ -202,7 +206,7 @@ int fd_work_poll_cancel(fd_work_poll_t *work) if (work) { /* remove work from queue. */ - status = k_delayed_work_cancel(&work->work); + status = k_work_cancel_delayable(&work->work); /* Work is submitted from another thread. Ensure all values are set atomically. */ k_mutex_lock(&fd_work_mutex, K_FOREVER); diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/pal_plat_network.c b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/pal_plat_network.c index a40168349..f8350b3e0 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/pal_plat_network.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/Networking/pal_plat_network.c @@ -34,6 +34,10 @@ #if 1 #define TRACE_GROUP "PAL" +//#include +//#define DEBUG_DEBUG(...) { printf(__VA_ARGS__); printf("\r\n"); } +//#define DEBUG_ERROR(...) { printf(__VA_ARGS__); printf("\r\n"); } + #define DEBUG_DEBUG PAL_LOG_DBG #define DEBUG_ERROR PAL_LOG_ERR #else @@ -653,6 +657,11 @@ palStatus_t pal_plat_close(palSocket_t* handle) return result; } +/******************************************************************************/ +/* DNS */ +/******************************************************************************/ + +#if (PAL_DNS_API_VERSION == 0) palStatus_t pal_plat_getAddressInfo(const char* hostname, palSocketAddress_t* address, palSocketLength_t* addressLength) { DEBUG_DEBUG("pal_plat_getAddressInfo"); @@ -704,8 +713,203 @@ palStatus_t pal_plat_getAddressInfo(const char* hostname, palSocketAddress_t* ad return result; } +#elif (PAL_DNS_API_VERSION == 3) + +#if (PAL_SUPPORT_IP_V4 || PAL_SUPPORT_NAT64) +#define PAL_DNS_DEFAULT_QUERY_TYPE DNS_QUERY_TYPE_A +#else +#define PAL_DNS_DEFAULT_QUERY_TYPE DNS_QUERY_TYPE_AAAA +#endif + +static size_t pal_dns_counter = 0; // number of records in cache +static uint16_t pal_dns_id = 0; // handle for cancelling request in progress +static palSocketAddress_t pal_dns_cache[PAL_DNS_CACHE_MAX] = { 0 }; // cache + +/** + * @brief Callback function for Zephyr's DNS Resolve. + * + * @param[in] status Ongoing request's status. + * @param info DNS information. + * @param user_data User provided context. + */ +static void pal_plat_dns_resolve_cb(enum dns_resolve_status status, + struct dns_addrinfo *info, + void *user_data) +{ + DEBUG_DEBUG("pal_plat_dns_resolve_cb: %d", status); + + /** + * Handle DNS record. + */ + if ((status == DNS_EAI_INPROGRESS) && + (pal_dns_counter < PAL_DNS_CACHE_MAX) && info) { + DEBUG_DEBUG("PAL DNS in progress"); + + palStatus_t result = PAL_ERR_SOCKET_DNS_ERROR; + + /* get pointer to next slot in cache */ + palSocketAddress_t* address = &pal_dns_cache[pal_dns_counter]; + + /* convert Zephyr address to PAL address */ + if (info->ai_family == AF_INET) { + +#if !PAL_SUPPORT_IP_V4 && PAL_SUPPORT_NAT64 + /* got IPv4 address on IPv6 network, convert to NAT64 address */ + result = pal_setSockAddrNAT64Addr(address, net_sin(&info->ai_addr)->sin_addr.s4_addr); +#else + result = pal_setSockAddrIPV4Addr(address, net_sin(&info->ai_addr)->sin_addr.s4_addr); +#endif + } else if (info->ai_family == AF_INET6) { + + result = pal_setSockAddrIPV6Addr(address, net_sin6(&info->ai_addr)->sin6_addr.s6_addr); + + } else { + DEBUG_ERROR("Invalid IP address family %d", info->ai_family); + assert(0); + } + + /* increment number of records in cache */ + if (result == PAL_SUCCESS) { + pal_dns_counter++; + } + + /** + * DNS lookup complete or failed. + */ + } else { + DEBUG_DEBUG("PAL DNS done"); + + if (user_data) { + + palStatus_t result = PAL_ERR_SOCKET_DNS_ERROR; + + /* return success if at least one record has been received*/ + if (pal_dns_counter) { + result = PAL_SUCCESS; + } + + /* access user provided data */ + pal_asyncAddressInfo_t* pal_info = (pal_asyncAddressInfo_t*) user_data; + + /* invoke callback function with result */ + pal_info->callback(pal_info->hostname, + (palAddressInfo_t*) pal_dns_cache, + result, + pal_info->callbackArgument); + } + } +} + +/*! \brief This function translates a hostname to a `palSocketAddress_t` that can be used with PAL sockets. + * @param[in] info address of `pal_asyncAddressInfo_t`. + */ +palStatus_t pal_plat_getAddressInfoAsync(pal_asyncAddressInfo_t* info) +{ + DEBUG_DEBUG("pal_plat_getAddressInfoAsync"); + + palStatus_t result = PAL_ERR_SOCKET_DNS_ERROR; + + if (info) { + DEBUG_DEBUG("hostname: %s", info->hostname); + + /* reset counter */ + pal_dns_counter = 0; + + /* lookup address using Zephyr's DNS Resolve */ + int retval = dns_get_addr_info(info->hostname, // const char *query, + PAL_DNS_DEFAULT_QUERY_TYPE, // enum dns_query_type type, + &pal_dns_id, // uint16_t *dns_id, + pal_plat_dns_resolve_cb, // dns_resolve_cb_tcb, + (void*) info, // void *user_data, + PAL_DNS_TIMEOUT_MS); // int32_t timeout + + if (retval == 0) { + + /* return handle for cancelling requests */ + *info->queryHandle = pal_dns_id; + + result = PAL_SUCCESS; + } + } + + return result; +} + +/*! \brief This function puts the palSocketAddress_t from the given index in palAddressInfo_t to the given addr + * @param[in] addrInfo The palAddressInfo_t which (if any) palSocketAddress_t is get. + * @param[in] index Index of the address in addrInfo to fetch. + * @param[out] addr palSocketAddress_t is put to this instance is any if found. + * \return PAL_SUCCESS (0) in case of success, or a specific negative error code in case of failure. + */ +palStatus_t pal_plat_getDNSAddress(palAddressInfo_t *addrInfo, uint16_t index, palSocketAddress_t *addr) +{ + DEBUG_DEBUG("pal_plat_getDNSAddress"); + + palStatus_t result = PAL_ERR_SOCKET_DNS_ERROR; + + if (addr && (index < PAL_DNS_CACHE_MAX)) { + + /* copy record from cache */ + memcpy(addr, &pal_dns_cache[index], sizeof(palSocketAddress_t)); + + result = PAL_SUCCESS; + } + + return result; +} + +/*! \brief Return the number of dns addresses in the given addrInfo + * @param[in] addrInfo The palAddressInfo_t to be used for countung dns addresses. + * \return Number of DNS addresses in the given addrInfo. + */ +int pal_plat_getDNSCount(palAddressInfo_t *addrInfo) +{ + DEBUG_DEBUG("pal_plat_getDNSCount"); + + return pal_dns_counter; +} + +/*! \brief This function is cancelation for `pal_plat_getAddressInfoAsync()`. + * @param[in] queryHandle ID of ongoing DNS query. + */ +palStatus_t pal_plat_cancelAddressInfoAsync(palDNSQuery_t queryHandle) +{ + DEBUG_DEBUG("pal_plat_cancelAddressInfoAsync"); + + /* cancel request */ + int result = dns_cancel_addr_info(queryHandle); + + return (result == 0) ? PAL_SUCCESS : PAL_ERR_SOCKET_DNS_ERROR; +} + +/*! \brief This function free's the thread used in pal_getAddressInfoAsync +*/ +palStatus_t pal_plat_free_addressinfoAsync(palDNSQuery_t queryHandle) +{ + DEBUG_DEBUG("pal_plat_free_addressinfoAsync"); + + /* reset counter */ + pal_dns_counter = 0; + + return PAL_SUCCESS; +} + +/*! \brief Free the given addrInfo. + * @param[in] addrInfo OS specific palAddressInfo_t which holds dns addresses. + */ +void pal_plat_freeAddrInfo(palAddressInfo_t* addrInfo) +{ + DEBUG_DEBUG("pal_plat_freeAddrInfo"); + + /* unused */ +} +#else +#error PAL_DNS_API_VERSION must be either 0 or 3 +#endif + +/******************************************************************************/ +/* Feature dependant */ /******************************************************************************/ -/* Feature dependant */ // for blocking sockets palStatus_t pal_plat_setSocketOptions(palSocket_t handle, int optionName, const void* optionValue, palSocketLength_t optionLength) @@ -778,27 +982,36 @@ uint16_t pal_plat_getStaggerEstimate(uint16_t data_amount) return PAL_DEFAULT_STAGGER_ESTIMATE; } - /******************************************************************************/ -/* Unused */ +/* Network Interface */ +/******************************************************************************/ -palStatus_t pal_plat_getNumberOfNetInterfaces(uint32_t* numInterfaces) +#if !(defined(PAL_USE_APPLICATION_NETWORK_CALLBACK) && \ + (PAL_USE_APPLICATION_NETWORK_CALLBACK == 1)) +palStatus_t pal_plat_setConnectionStatusCallback(uint32_t interfaceIndex, + connectionStatusCallback callback, + void *client_arg) { - DEBUG_DEBUG("pal_plat_getNumberOfNetInterfaces"); + DEBUG_DEBUG("pal_plat_setConnectionStatusCallback"); return PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED; } +#endif -palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t* interfaceInfo) +/******************************************************************************/ +/* Unused */ +/******************************************************************************/ + +palStatus_t pal_plat_getNumberOfNetInterfaces(uint32_t* numInterfaces) { - DEBUG_DEBUG("pal_plat_getNetInterfaceInfo"); + DEBUG_DEBUG("pal_plat_getNumberOfNetInterfaces"); return PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED; } -palStatus_t pal_plat_setConnectionStatusCallback(uint32_t interfaceIndex, connectionStatusCallback callback, void *client_arg) +palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t* interfaceInfo) { - DEBUG_DEBUG("pal_plat_setConnectionStatusCallback"); + DEBUG_DEBUG("pal_plat_getNetInterfaceInfo"); return PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED; } diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/RTOS/pal_plat_rtos.c b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/RTOS/pal_plat_rtos.c index 0377202c3..409d990e5 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/RTOS/pal_plat_rtos.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/ZephyrOS/RTOS/pal_plat_rtos.c @@ -59,11 +59,9 @@ palStatus_t pal_plat_RTOSInitialize(void *opaqueContext) palStatus_t pal_plat_RTOSDestroy(void) { - assert(0); return PAL_ERR_NOT_IMPLEMENTED; } - uint64_t pal_plat_osKernelSysTick(void) { return k_uptime_ticks(); @@ -183,7 +181,7 @@ palStatus_t pal_plat_osDelay(uint32_t milliseconds) } struct timer_data { - struct k_delayed_work work; + struct k_work_delayable work; palTimerFuncPtr callback; void *arg; struct k_mutex lock; @@ -194,7 +192,7 @@ struct timer_data { static void work_fn(struct k_work *work) { - struct k_delayed_work *dwork = CONTAINER_OF(work, struct k_delayed_work, work); + struct k_work_delayable *dwork = CONTAINER_OF(work, struct k_work_delayable, work); struct timer_data *timer_data = CONTAINER_OF(dwork, struct timer_data, work); uint64_t uptime = k_uptime_get(); @@ -228,15 +226,14 @@ static void work_fn(struct k_work *work) delay = 0; } - int err = k_delayed_work_submit(&timer_data->work, K_MSEC(delay)); - __ASSERT_NO_MSG(!err); + k_work_reschedule(&timer_data->work, K_MSEC(delay)); /* If timer was started reference is already taken. */ k_sem_take(&timer_data->busy, K_NO_WAIT); } } else { - if (!k_delayed_work_submit(&timer_data->work, - K_MSEC(timer_data->timeout - uptime))) { + if (!k_work_reschedule(&timer_data->work, + K_MSEC(timer_data->timeout - uptime))) { k_sem_take(&timer_data->busy, K_NO_WAIT); } } @@ -270,7 +267,7 @@ palStatus_t pal_plat_osTimerCreate(palTimerFuncPtr function, k_sem_init(&timer_data->busy, 2, 2); k_mutex_init(&timer_data->lock); - k_delayed_work_init(&timer_data->work, work_fn); + k_work_init_delayable(&timer_data->work, work_fn); *timerID = (palTimerID_t)timer_data; return PAL_SUCCESS; @@ -298,12 +295,11 @@ palStatus_t pal_plat_osTimerStart(palTimerID_t timerID, uint32_t millisec) timer_data->period = millisec; } - if (!k_delayed_work_cancel(&timer_data->work)) { + if (!k_work_cancel_delayable(&timer_data->work)) { k_sem_give(&timer_data->busy); - int err = k_delayed_work_submit(&timer_data->work, get_timeout(millisec)); - __ASSERT_NO_MSG(!err); + k_work_reschedule(&timer_data->work, get_timeout(millisec)); k_sem_take(&timer_data->busy, K_NO_WAIT); - } else if (!k_delayed_work_submit(&timer_data->work, get_timeout(millisec))) { + } else if (!k_work_reschedule(&timer_data->work, get_timeout(millisec))) { k_sem_take(&timer_data->busy, K_NO_WAIT); } else { /* Callback cannot be stopped or resubmitted. @@ -331,7 +327,7 @@ palStatus_t pal_plat_osTimerStop(palTimerID_t timerID) timer_data->period = UINT64_MAX; } - if (!k_delayed_work_cancel(&timer_data->work)) { + if (!k_work_cancel_delayable(&timer_data->work)) { k_sem_give(&timer_data->busy); } else { /* Callback cannot be stopped. @@ -585,18 +581,15 @@ palStatus_t pal_plat_osSetRtcTime(uint64_t rtcSetTime) palStatus_t pal_plat_rtcDeInit(void) { - assert(0); return PAL_ERR_NOT_IMPLEMENTED; } palStatus_t pal_plat_rtcInit(void) { - assert(0); return PAL_ERR_NOT_IMPLEMENTED; } palStatus_t pal_plat_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes, size_t *actualRandomSizeBytes) { - assert(0); return PAL_ERR_NOT_IMPLEMENTED; } diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Networking/pal_plat_network.cpp b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Networking/pal_plat_network.cpp index 3beaa0f8c..d9fb845f6 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Networking/pal_plat_network.cpp +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Networking/pal_plat_network.cpp @@ -30,15 +30,15 @@ typedef void(*palSelectCallbackFunction_t)(); -typedef struct pal_plat_NetworkInterface{ - NetworkInterface* interface; +typedef struct pal_plat_NetworkInterface { + NetworkInterface *interface; void *clientArg; connectionStatusCallback connectionStatusCb; } pal_plat_NetworkInterface_t; #if defined (__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) -void palSelectCallbackNull(void* arg) +void palSelectCallbackNull(void *arg) { } @@ -67,356 +67,339 @@ void palConnectCallBack() { } - class PALSocketWrapper - { - public: - PALSocketWrapper() : initialized(false), activeSocket(NULL), isNonBlockingOnCreation(false), callbackFunction(NULL_FUNCTION), callbackArgument(NULL), selectCallbackFunction(NULL), connectState(PAL_PLAT_SOCKET_NOT_CONNECTED), socketTypeVal(PAL_SOCK_DGRAM), attachCallbackObject(NULL), rxBuffer(0), rxBufferSet(false) - { +class PALSocketWrapper { +public: + PALSocketWrapper() : initialized(false), activeSocket(NULL), isNonBlockingOnCreation(false), callbackFunction(NULL_FUNCTION), callbackArgument(NULL), selectCallbackFunction(NULL), connectState(PAL_PLAT_SOCKET_NOT_CONNECTED), socketTypeVal(PAL_SOCK_DGRAM), attachCallbackObject(NULL), rxBuffer(0), rxBufferSet(false) + { - } - nsapi_error_t initialize(Socket* socket, palSocketType_t socketType,bool isNonBlocking, palAsyncSocketCallback_t callback, void* argument); - palAsyncSocketCallback_t getCallback( ) const; - void* getCallbackArgument() const ; - bool isNonBlocking() const ; - bool isConnected() const ; - void attachCallback(); - Socket* getActiveSocket(); - - palSocketType_t getSocketType() const; - char getAndResetRxBuffer(); - bool isRxBufferSet() const; - palStatus_t setRxBuffer(char data); - void updateCallback(/*palAsyncSocketCallback_t callback, void* argument,*/ palSelectCallbackFunction_t selectCallback); - virtual ~PALSocketWrapper() - { - if (NULL != activeSocket ) - { - activeSocket->close(); - delete activeSocket; - } - } + } + nsapi_error_t initialize(Socket *socket, palSocketType_t socketType, bool isNonBlocking, palAsyncSocketCallback_t callback, void *argument); + palAsyncSocketCallback_t getCallback() const; + void *getCallbackArgument() const ; + bool isNonBlocking() const ; + bool isConnected() const ; + void attachCallback(); + Socket *getActiveSocket(); + + palSocketType_t getSocketType() const; + char getAndResetRxBuffer(); + bool isRxBufferSet() const; + palStatus_t setRxBuffer(char data); + void updateCallback(/*palAsyncSocketCallback_t callback, void* argument,*/ palSelectCallbackFunction_t selectCallback); + virtual ~PALSocketWrapper() + { + if (NULL != activeSocket) { + activeSocket->close(); + delete activeSocket; + } + } - // nsapi socket funcitons exposed: - nsapi_error_t close(); - nsapi_error_t bind(const SocketAddress &address); - void set_blocking(bool blocking); - void set_timeout(int timeout); - nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen); - nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen); - void attach(mbed::Callback func); - //void sigio(mbed::Callback func); // switch attach to sigio for verison 5.4 - // nsapi UDP socket funcitons exposed: - nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size); - nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size); - //nsapi TCP socket funcitons exposed: - nsapi_error_t connect(const SocketAddress &address); - nsapi_size_or_error_t send(const void *data, nsapi_size_t size); - nsapi_size_or_error_t recv(void *data, nsapi_size_t size); + // nsapi socket funcitons exposed: + nsapi_error_t close(); + nsapi_error_t bind(const SocketAddress &address); + void set_blocking(bool blocking); + void set_timeout(int timeout); + nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen); + nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen); + void attach(mbed::Callback func); + //void sigio(mbed::Callback func); // switch attach to sigio for verison 5.4 + // nsapi UDP socket funcitons exposed: + nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size); + nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size); + //nsapi TCP socket funcitons exposed: + nsapi_error_t connect(const SocketAddress &address); + nsapi_size_or_error_t send(const void *data, nsapi_size_t size); + nsapi_size_or_error_t recv(void *data, nsapi_size_t size); #if PAL_NET_SERVER_SOCKET_API - //nsapi TCP server socket funcitons exposed: - nsapi_error_t listen(int backlog = 1); - Socket* accept(nsapi_error_t *error); + //nsapi TCP server socket funcitons exposed: + nsapi_error_t listen(int backlog = 1); + Socket *accept(nsapi_error_t *error); #endif // PAL_NET_SERVER_SOCKET_API - void freeSocket(bool freeSocket); - - private: - bool initialized; - Socket* activeSocket; - bool isNonBlockingOnCreation; - palAsyncSocketCallback_t callbackFunction; - void* callbackArgument; - palSelectCallbackFunction_t selectCallbackFunction; - palConnectState connectState; - palSocketType_t socketTypeVal; - Callback attachCallbackObject; - events::EventQueue* shared_event_queue; - char rxBuffer; - bool rxBufferSet; - bool deleteSocket; - }; - - void PALSocketWrapper::updateCallback( palSelectCallbackFunction_t selectCallback ) - { - bool shouldSetCallback = false; - if ((NULL == selectCallbackFunction) && (NULL == callbackFunction)) //callback already set - no need to set again - { - shouldSetCallback = true; - } + void freeSocket(bool freeSocket); + +private: + bool initialized; + Socket *activeSocket; + bool isNonBlockingOnCreation; + palAsyncSocketCallback_t callbackFunction; + void *callbackArgument; + palSelectCallbackFunction_t selectCallbackFunction; + palConnectState connectState; + palSocketType_t socketTypeVal; + Callback attachCallbackObject; + events::EventQueue *shared_event_queue; + char rxBuffer; + bool rxBufferSet; + bool deleteSocket; +}; + +void PALSocketWrapper::updateCallback(palSelectCallbackFunction_t selectCallback) +{ + bool shouldSetCallback = false; + if ((NULL == selectCallbackFunction) && (NULL == callbackFunction)) { //callback already set - no need to set again + shouldSetCallback = true; + } - selectCallbackFunction = selectCallback; + selectCallbackFunction = selectCallback; - if ((NULL != selectCallbackFunction) || (NULL != callbackFunction)) - { - if (shouldSetCallback) - { - Callback mycall(this, &PALSocketWrapper::attachCallback); - activeSocket->sigio(mycall); - } - } - else - { - activeSocket->sigio(NULL); - } + if ((NULL != selectCallbackFunction) || (NULL != callbackFunction)) { + if (shouldSetCallback) { + Callback mycall(this, &PALSocketWrapper::attachCallback); + activeSocket->sigio(mycall); } + } else { + activeSocket->sigio(NULL); + } +} - Socket* PALSocketWrapper::getActiveSocket() - { - return activeSocket; - } +Socket *PALSocketWrapper::getActiveSocket() +{ + return activeSocket; +} - char PALSocketWrapper::getAndResetRxBuffer() - { - rxBufferSet = false; - return rxBuffer; - } +char PALSocketWrapper::getAndResetRxBuffer() +{ + rxBufferSet = false; + return rxBuffer; +} - bool PALSocketWrapper::isRxBufferSet() const - { - return rxBufferSet; - } +bool PALSocketWrapper::isRxBufferSet() const +{ + return rxBufferSet; +} - palStatus_t PALSocketWrapper::setRxBuffer( char data) - { - PAL_VALIDATE_CONDITION_WITH_ERROR((true == rxBufferSet), PAL_ERR_SOCKET_GENERIC); +palStatus_t PALSocketWrapper::setRxBuffer(char data) +{ + PAL_VALIDATE_CONDITION_WITH_ERROR((true == rxBufferSet), PAL_ERR_SOCKET_GENERIC); - rxBuffer = data; - rxBufferSet = true; + rxBuffer = data; + rxBufferSet = true; - return PAL_SUCCESS; - } + return PAL_SUCCESS; +} - palAsyncSocketCallback_t PALSocketWrapper::getCallback() const - { - return callbackFunction; - } +palAsyncSocketCallback_t PALSocketWrapper::getCallback() const +{ + return callbackFunction; +} - palSocketType_t PALSocketWrapper::getSocketType() const - { - return socketTypeVal; - } +palSocketType_t PALSocketWrapper::getSocketType() const +{ + return socketTypeVal; +} - void * PALSocketWrapper::getCallbackArgument() const - { - return callbackArgument; - } +void *PALSocketWrapper::getCallbackArgument() const +{ + return callbackArgument; +} - bool PALSocketWrapper::isNonBlocking() const - { - return isNonBlockingOnCreation; - } +bool PALSocketWrapper::isNonBlocking() const +{ + return isNonBlockingOnCreation; +} - bool PALSocketWrapper::isConnected() const - { - return ((PAL_PLAT_SOCKET_CONNECTED == connectState) && (PAL_SOCK_STREAM == socketTypeVal)); - } +bool PALSocketWrapper::isConnected() const +{ + return ((PAL_PLAT_SOCKET_CONNECTED == connectState) && (PAL_SOCK_STREAM == socketTypeVal)); +} - void PALSocketWrapper::attachCallback() - { - if (NULL != callbackFunction) - { - // Since the socket callback may be called from interrupt context, depending on the - // network interface used, we need to debounce the client callback to happen from - // a thread context to keep client side implementation platform agnostic. - assert(shared_event_queue); - shared_event_queue->call(callbackFunction, callbackArgument); - } - if (NULL != selectCallbackFunction) - { - // Note: this is not tested yet - assert(shared_event_queue); - shared_event_queue->call(selectCallbackFunction); - } - if (PAL_PLAT_SOCKET_CONNECTING == connectState) - { - connectState = PAL_PLAT_SOCKET_CONNECTED;// if we got a callback while connecting assume we are connected - if (palConnectCallBack == selectCallbackFunction) - { - selectCallbackFunction = NULL; - } - } +void PALSocketWrapper::attachCallback() +{ + if (NULL != callbackFunction) { + // Since the socket callback may be called from interrupt context, depending on the + // network interface used, we need to debounce the client callback to happen from + // a thread context to keep client side implementation platform agnostic. + assert(shared_event_queue); + shared_event_queue->call(callbackFunction, callbackArgument); + } + if (NULL != selectCallbackFunction) { + // Note: this is not tested yet + assert(shared_event_queue); + shared_event_queue->call(selectCallbackFunction); + } + if (PAL_PLAT_SOCKET_CONNECTING == connectState) { + connectState = PAL_PLAT_SOCKET_CONNECTED;// if we got a callback while connecting assume we are connected + if (palConnectCallBack == selectCallbackFunction) { + selectCallbackFunction = NULL; } + } +} - nsapi_error_t PALSocketWrapper::initialize(Socket* socket, palSocketType_t socketType, bool isNonBlocking, palAsyncSocketCallback_t callback, void* argument) - { - // check that we got a valid socket and the socket type is supported - PAL_VALIDATE_CONDITION_WITH_ERROR(((true == initialized) || (NULL == socket) || - ((socketType != PAL_SOCK_STREAM) && (socketType != PAL_SOCK_STREAM_SERVER) && - (socketType != PAL_SOCK_DGRAM))),NSAPI_ERROR_PARAMETER); - - - // Pre fetch and store the shared queue used for bouncing the callbacks out of interrupt - // context, as the user of it may be ran from interrupt and it can't go and start - // creating worker threads from there. - // Note: the code uses mbed_highprio_event_queue() instead of mbed_event_queue() - // as the high priority queue and its thread is likely there already thanks to - // arm_hal_timer.cpp. Technically the client side does not really care, if the events - // were delayed a bit by other events or not. +nsapi_error_t PALSocketWrapper::initialize(Socket *socket, palSocketType_t socketType, bool isNonBlocking, palAsyncSocketCallback_t callback, void *argument) +{ + // check that we got a valid socket and the socket type is supported + PAL_VALIDATE_CONDITION_WITH_ERROR(((true == initialized) || (NULL == socket) || + ((socketType != PAL_SOCK_STREAM) && (socketType != PAL_SOCK_STREAM_SERVER) && + (socketType != PAL_SOCK_DGRAM))), NSAPI_ERROR_PARAMETER); + + + // Pre fetch and store the shared queue used for bouncing the callbacks out of interrupt + // context, as the user of it may be ran from interrupt and it can't go and start + // creating worker threads from there. + // Note: the code uses mbed_highprio_event_queue() instead of mbed_event_queue() + // as the high priority queue and its thread is likely there already thanks to + // arm_hal_timer.cpp. Technically the client side does not really care, if the events + // were delayed a bit by other events or not. #if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT - shared_event_queue = mbed_highprio_event_queue(); + shared_event_queue = mbed_highprio_event_queue(); #else - shared_event_queue = mbed_event_queue(); + shared_event_queue = mbed_event_queue(); #endif - PAL_VALIDATE_CONDITION_WITH_ERROR((shared_event_queue == NULL),NSAPI_ERROR_UNSUPPORTED); + PAL_VALIDATE_CONDITION_WITH_ERROR((shared_event_queue == NULL), NSAPI_ERROR_UNSUPPORTED); + + Callback mycall(this, &PALSocketWrapper::attachCallback); + attachCallbackObject = mycall; + activeSocket = socket; + socketTypeVal = socketType; + isNonBlockingOnCreation = isNonBlocking; + deleteSocket = true; + activeSocket->set_blocking(!isNonBlocking); + if (NULL != callback) { + callbackFunction = callback; + callbackArgument = argument; + activeSocket->sigio(attachCallbackObject); + } - Callback mycall(this, &PALSocketWrapper::attachCallback); - attachCallbackObject = mycall; - activeSocket = socket; - socketTypeVal = socketType; - isNonBlockingOnCreation = isNonBlocking; - deleteSocket = true; - activeSocket->set_blocking(!isNonBlocking); - if (NULL != callback) - { - callbackFunction = callback; - callbackArgument = argument; - activeSocket->sigio(attachCallbackObject); - } + initialized = true; + return NSAPI_ERROR_OK; +} - initialized = true; - return NSAPI_ERROR_OK; +nsapi_error_t PALSocketWrapper::close() +{ + nsapi_error_t status = NSAPI_ERROR_OK; + if (NULL != activeSocket) { + status = activeSocket->close(); + // When allocated by accept() call, socket will destroy itself on close(); + if (deleteSocket) { + delete activeSocket; } + activeSocket = NULL; + } + return status; +} - nsapi_error_t PALSocketWrapper::close() - { - nsapi_error_t status= NSAPI_ERROR_OK; - if (NULL != activeSocket) - { - status = activeSocket->close(); - // When allocated by accept() call, socket will destroy itself on close(); - if (deleteSocket) - { - delete activeSocket; - } - activeSocket = NULL; - } - return status; - } +nsapi_error_t PALSocketWrapper::bind(const SocketAddress &address) +{ + nsapi_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized), NSAPI_ERROR_PARAMETER); + status = activeSocket->bind(address); + return status; +} - nsapi_error_t PALSocketWrapper::bind(const SocketAddress &address) - { - nsapi_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized), NSAPI_ERROR_PARAMETER); - status= activeSocket->bind(address); - return status; - } +void PALSocketWrapper::set_blocking(bool blocking) +{ + activeSocket->set_blocking(blocking); +} - void PALSocketWrapper::set_blocking(bool blocking) - { - activeSocket->set_blocking(blocking); - } +void PALSocketWrapper::set_timeout(int timeout) +{ + activeSocket->set_timeout(timeout); +} - void PALSocketWrapper::set_timeout(int timeout) - { - activeSocket->set_timeout(timeout); - } +nsapi_error_t PALSocketWrapper::setsockopt(int level, int optname, const void *optval, unsigned optlen) +{ + nsapi_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized), NSAPI_ERROR_PARAMETER); + status = activeSocket->setsockopt(level, optname, optval, optlen); + return status; +} - nsapi_error_t PALSocketWrapper::setsockopt(int level, int optname, const void *optval, unsigned optlen) - { - nsapi_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized),NSAPI_ERROR_PARAMETER); - status = activeSocket->setsockopt(level, optname, optval, optlen); - return status; - } +nsapi_error_t PALSocketWrapper::getsockopt(int level, int optname, void *optval, unsigned *optlen) +{ + nsapi_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized), NSAPI_ERROR_PARAMETER); + status = activeSocket->getsockopt(level, optname, optval, optlen); + return status; +} - nsapi_error_t PALSocketWrapper::getsockopt(int level, int optname, void *optval, unsigned *optlen) - { - nsapi_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized),NSAPI_ERROR_PARAMETER); - status = activeSocket->getsockopt(level, optname, optval, optlen); - return status; - } +void PALSocketWrapper::attach(mbed::Callback func) +{ + activeSocket->sigio(func); +} +//void sigio(mbed::Callback func); // switch attach to sigio for verison 5.4 +// nsapi UDP socket funcitons exposed: +nsapi_size_or_error_t PALSocketWrapper::recvfrom(SocketAddress *address, void *data, nsapi_size_t size) +{ + nsapi_size_or_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_DGRAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only - void PALSocketWrapper::attach(mbed::Callback func) - { - activeSocket->sigio(func); - } - //void sigio(mbed::Callback func); // switch attach to sigio for verison 5.4 - // nsapi UDP socket funcitons exposed: - nsapi_size_or_error_t PALSocketWrapper::recvfrom(SocketAddress *address, void *data, nsapi_size_t size) - { - nsapi_size_or_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_DGRAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only - - status = activeSocket->recvfrom(address, data, size); - return status; - } + status = activeSocket->recvfrom(address, data, size); + return status; +} - nsapi_size_or_error_t PALSocketWrapper::sendto(const SocketAddress &address, const void *data, nsapi_size_t size) - { - nsapi_size_or_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_DGRAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only - status = activeSocket->sendto(address, data, size); - return status; - } +nsapi_size_or_error_t PALSocketWrapper::sendto(const SocketAddress &address, const void *data, nsapi_size_t size) +{ + nsapi_size_or_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_DGRAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only + status = activeSocket->sendto(address, data, size); + return status; +} - //nsapi TCP socket funcitons exposed: - nsapi_error_t PALSocketWrapper::connect(const SocketAddress &address) - { - nsapi_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // tcp sockets only - - connectState = PAL_PLAT_SOCKET_CONNECTING; - updateCallback(palConnectCallBack); // make sure callback is enabled to see if we get callback to signal connections end - status = activeSocket->connect(address); - if (status >= 0 || status == NSAPI_ERROR_IS_CONNECTED) - { - connectState = PAL_PLAT_SOCKET_CONNECTED; - updateCallback(NULL); // make sure callback is enabled to see if we get callback to signal connections end - } - else if ((NSAPI_ERROR_WOULD_BLOCK != status) && (NSAPI_ERROR_IN_PROGRESS != status) && (NSAPI_ERROR_ALREADY != status)) - { - connectState = PAL_PLAT_SOCKET_NOT_CONNECTED; - } - return status; - } +//nsapi TCP socket funcitons exposed: +nsapi_error_t PALSocketWrapper::connect(const SocketAddress &address) +{ + nsapi_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // tcp sockets only + + connectState = PAL_PLAT_SOCKET_CONNECTING; + updateCallback(palConnectCallBack); // make sure callback is enabled to see if we get callback to signal connections end + status = activeSocket->connect(address); + if (status >= 0 || status == NSAPI_ERROR_IS_CONNECTED) { + connectState = PAL_PLAT_SOCKET_CONNECTED; + updateCallback(NULL); // make sure callback is enabled to see if we get callback to signal connections end + } else if ((NSAPI_ERROR_WOULD_BLOCK != status) && (NSAPI_ERROR_IN_PROGRESS != status) && (NSAPI_ERROR_ALREADY != status)) { + connectState = PAL_PLAT_SOCKET_NOT_CONNECTED; + } + return status; +} - nsapi_size_or_error_t PALSocketWrapper::send(const void *data, nsapi_size_t size) - { - nsapi_size_or_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // tcp sockets only +nsapi_size_or_error_t PALSocketWrapper::send(const void *data, nsapi_size_t size) +{ + nsapi_size_or_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // tcp sockets only - status = ((TCPSocket*)activeSocket)->send(data, size); - return status; - } + status = ((TCPSocket *)activeSocket)->send(data, size); + return status; +} - nsapi_size_or_error_t PALSocketWrapper::recv(void *data, nsapi_size_t size) - { - nsapi_size_or_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)),NSAPI_ERROR_PARAMETER); // tcp sockets only - status = activeSocket->recv(data, size); - return status; - } +nsapi_size_or_error_t PALSocketWrapper::recv(void *data, nsapi_size_t size) +{ + nsapi_size_or_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // tcp sockets only + status = activeSocket->recv(data, size); + return status; +} #if PAL_NET_SERVER_SOCKET_API - //nsapi TCP server socket funcitons exposed: - nsapi_error_t PALSocketWrapper::listen(int backlog ) - { - nsapi_error_t status = NSAPI_ERROR_OK; - PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM_SERVER != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only - status = activeSocket->listen(backlog); - return status; - } +//nsapi TCP server socket funcitons exposed: +nsapi_error_t PALSocketWrapper::listen(int backlog) +{ + nsapi_error_t status = NSAPI_ERROR_OK; + PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM_SERVER != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only + status = activeSocket->listen(backlog); + return status; +} - Socket* PALSocketWrapper::accept(nsapi_error_t *error) - { - *error = NSAPI_ERROR_OK; +Socket *PALSocketWrapper::accept(nsapi_error_t *error) +{ + *error = NSAPI_ERROR_OK; - if (!initialized || PAL_SOCK_STREAM_SERVER != socketTypeVal) { - *error = NSAPI_ERROR_PARAMETER; - return NULL; - } + if (!initialized || PAL_SOCK_STREAM_SERVER != socketTypeVal) { + *error = NSAPI_ERROR_PARAMETER; + return NULL; + } - return activeSocket->accept(error); - } + return activeSocket->accept(error); +} #endif // PAL_NET_SERVER_SOCKET_API - void PALSocketWrapper::freeSocket(bool freeSocket) - { - deleteSocket = freeSocket; - } +void PALSocketWrapper::freeSocket(bool freeSocket) +{ + deleteSocket = freeSocket; +} PAL_PRIVATE pal_plat_NetworkInterface_t s_pal_networkInterfacesSupported[PAL_MAX_SUPORTED_NET_INTERFACES] = { 0 }; @@ -425,83 +408,81 @@ PAL_PRIVATE uint32_t s_pal_numberOFInterfaces = 0; PAL_PRIVATE uint32_t s_pal_network_initialized = 0; -PAL_PRIVATE palStatus_t create_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* arg, palSocket_t* socket); +PAL_PRIVATE palStatus_t create_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void *arg, palSocket_t *socket); -PAL_PRIVATE palStatus_t set_sock_options(PALSocketWrapper *socketObj, int optionLevel, int optionName, const void* optionValue, palSocketLength_t optionLength); +PAL_PRIVATE palStatus_t set_sock_options(PALSocketWrapper *socketObj, int optionLevel, int optionName, const void *optionValue, palSocketLength_t optionLength); void pal_plat_connectionStatusCallback(void *interfaceIndex, nsapi_event_t status, intptr_t param); PAL_PRIVATE palStatus_t translateErrorToPALError(int errnoValue) { palStatus_t status; - switch (errnoValue) - { - case NSAPI_ERROR_WOULD_BLOCK: - status = PAL_ERR_SOCKET_WOULD_BLOCK; - break; - case NSAPI_ERROR_UNSUPPORTED: - status = PAL_ERR_NOT_SUPPORTED; - break; - case NSAPI_ERROR_PARAMETER: - status = PAL_ERR_SOCKET_INVALID_VALUE; - break; - case NSAPI_ERROR_NO_CONNECTION: - status = PAL_ERR_SOCKET_NOT_CONNECTED; - break; - - case NSAPI_ERROR_NO_SOCKET: - status = PAL_ERR_SOCKET_ALLOCATION_FAILED; - break; - case NSAPI_ERROR_NO_ADDRESS: - status = PAL_ERR_SOCKET_INVALID_ADDRESS; - break; - case NSAPI_ERROR_NO_MEMORY: - status = PAL_ERR_NO_MEMORY; - break; - case NSAPI_ERROR_DNS_FAILURE: - status = PAL_ERR_SOCKET_DNS_ERROR; - break; - case NSAPI_ERROR_DHCP_FAILURE: - status = PAL_ERR_SOCKET_HDCP_ERROR; - break; - case NSAPI_ERROR_AUTH_FAILURE: - status = PAL_ERR_SOCKET_AUTH_ERROR; - break; - case NSAPI_ERROR_DEVICE_ERROR: - status = PAL_ERR_SOCKET_INPUT_OUTPUT_ERROR; - break; - case NSAPI_ERROR_IN_PROGRESS: - case NSAPI_ERROR_ALREADY: - status = PAL_ERR_SOCKET_IN_PROGRES; - break; - case NSAPI_ERROR_IS_CONNECTED: - status = PAL_SUCCESS; - break; - case NSAPI_ERROR_CONNECTION_LOST: - status = PAL_ERR_SOCKET_CONNECTION_RESET; - break; - case NSAPI_ERROR_CONNECTION_TIMEOUT: - case NSAPI_ERROR_TIMEOUT: - status = PAL_ERR_TIMEOUT_EXPIRED; - break; - case NSAPI_ERROR_ADDRESS_IN_USE: - status = PAL_ERR_SOCKET_ADDRESS_IN_USE; - break; - - default: - PAL_LOG_ERR("translateErrorToPALError() cannot translate %d", errnoValue); - status = PAL_ERR_SOCKET_GENERIC; - break; + switch (errnoValue) { + case NSAPI_ERROR_WOULD_BLOCK: + status = PAL_ERR_SOCKET_WOULD_BLOCK; + break; + case NSAPI_ERROR_UNSUPPORTED: + status = PAL_ERR_NOT_SUPPORTED; + break; + case NSAPI_ERROR_PARAMETER: + status = PAL_ERR_SOCKET_INVALID_VALUE; + break; + case NSAPI_ERROR_NO_CONNECTION: + status = PAL_ERR_SOCKET_NOT_CONNECTED; + break; + + case NSAPI_ERROR_NO_SOCKET: + status = PAL_ERR_SOCKET_ALLOCATION_FAILED; + break; + case NSAPI_ERROR_NO_ADDRESS: + status = PAL_ERR_SOCKET_INVALID_ADDRESS; + break; + case NSAPI_ERROR_NO_MEMORY: + status = PAL_ERR_NO_MEMORY; + break; + case NSAPI_ERROR_DNS_FAILURE: + status = PAL_ERR_SOCKET_DNS_ERROR; + break; + case NSAPI_ERROR_DHCP_FAILURE: + status = PAL_ERR_SOCKET_HDCP_ERROR; + break; + case NSAPI_ERROR_AUTH_FAILURE: + status = PAL_ERR_SOCKET_AUTH_ERROR; + break; + case NSAPI_ERROR_DEVICE_ERROR: + status = PAL_ERR_SOCKET_INPUT_OUTPUT_ERROR; + break; + case NSAPI_ERROR_IN_PROGRESS: + case NSAPI_ERROR_ALREADY: + status = PAL_ERR_SOCKET_IN_PROGRES; + break; + case NSAPI_ERROR_IS_CONNECTED: + status = PAL_SUCCESS; + break; + case NSAPI_ERROR_CONNECTION_LOST: + status = PAL_ERR_SOCKET_CONNECTION_RESET; + break; + case NSAPI_ERROR_CONNECTION_TIMEOUT: + case NSAPI_ERROR_TIMEOUT: + status = PAL_ERR_TIMEOUT_EXPIRED; + break; + case NSAPI_ERROR_ADDRESS_IN_USE: + status = PAL_ERR_SOCKET_ADDRESS_IN_USE; + break; + + default: + PAL_LOG_ERR("translateErrorToPALError() cannot translate %d", errnoValue); + status = PAL_ERR_SOCKET_GENERIC; + break; } return status; } -palStatus_t pal_plat_socketsInit(void* context) +palStatus_t pal_plat_socketsInit(void *context) { (void)context; // replace with macro int result = PAL_SUCCESS; - if (s_pal_network_initialized == 1) - { + if (s_pal_network_initialized == 1) { return PAL_SUCCESS; // already initialized. } @@ -510,32 +491,26 @@ palStatus_t pal_plat_socketsInit(void* context) return result; } -palStatus_t pal_plat_registerNetworkInterface(void* context, uint32_t* interfaceIndex) +palStatus_t pal_plat_registerNetworkInterface(void *context, uint32_t *interfaceIndex) { palStatus_t result = PAL_SUCCESS; uint32_t index = 0; bool found = false; - for (index = 0; index < s_pal_numberOFInterfaces; index++) // if specific context already registered return exisitng index instead of registering again. - { - if (s_pal_networkInterfacesSupported[index].interface == context) - { + for (index = 0; index < s_pal_numberOFInterfaces; index++) { // if specific context already registered return exisitng index instead of registering again. + if (s_pal_networkInterfacesSupported[index].interface == context) { found = true; *interfaceIndex = index; break; } } - if (false == found) - { - if (s_pal_numberOFInterfaces < PAL_MAX_SUPORTED_NET_INTERFACES) - { - s_pal_networkInterfacesSupported[s_pal_numberOFInterfaces].interface = (NetworkInterface*)context; + if (false == found) { + if (s_pal_numberOFInterfaces < PAL_MAX_SUPORTED_NET_INTERFACES) { + s_pal_networkInterfacesSupported[s_pal_numberOFInterfaces].interface = (NetworkInterface *)context; *interfaceIndex = s_pal_numberOFInterfaces; ++s_pal_numberOFInterfaces; - } - else - { + } else { result = PAL_ERR_SOCKET_MAX_NUMBER_OF_INTERFACES_REACHED; } } @@ -549,7 +524,7 @@ palStatus_t pal_plat_setConnectionStatusCallback(uint32_t interfaceIndex, connec if (interfaceIndex > PAL_MAX_SUPORTED_NET_INTERFACES - 1) { result = PAL_ERR_INVALID_ARGUMENT; } else { - s_pal_networkInterfacesSupported[interfaceIndex].interface->add_event_listener(mbed::callback(&pal_plat_connectionStatusCallback, (void*)interfaceIndex)); + s_pal_networkInterfacesSupported[interfaceIndex].interface->add_event_listener(mbed::callback(&pal_plat_connectionStatusCallback, (void *)interfaceIndex)); s_pal_networkInterfacesSupported[interfaceIndex].connectionStatusCb = callback; s_pal_networkInterfacesSupported[interfaceIndex].clientArg = arg; } @@ -560,8 +535,8 @@ palStatus_t pal_plat_setConnectionStatusCallback(uint32_t interfaceIndex, connec palStatus_t pal_plat_unregisterNetworkInterface(uint32_t interfaceIndex) { if (interfaceIndex < PAL_MAX_SUPORTED_NET_INTERFACES && - s_pal_networkInterfacesSupported[interfaceIndex].interface) { - s_pal_networkInterfacesSupported[interfaceIndex].interface->remove_event_listener(mbed::callback(&pal_plat_connectionStatusCallback, (void*)interfaceIndex)); + s_pal_networkInterfacesSupported[interfaceIndex].interface) { + s_pal_networkInterfacesSupported[interfaceIndex].interface->remove_event_listener(mbed::callback(&pal_plat_connectionStatusCallback, (void *)interfaceIndex)); s_pal_networkInterfacesSupported[interfaceIndex].interface = NULL; s_pal_networkInterfacesSupported[interfaceIndex].clientArg = NULL; s_pal_networkInterfacesSupported[interfaceIndex].connectionStatusCb = NULL; @@ -572,7 +547,7 @@ palStatus_t pal_plat_unregisterNetworkInterface(uint32_t interfaceIndex) } } -palStatus_t pal_plat_socketsTerminate(void* context) +palStatus_t pal_plat_socketsTerminate(void *context) { (void)context; // replace with macro return PAL_SUCCESS; @@ -581,67 +556,64 @@ palStatus_t pal_plat_socketsTerminate(void* context) PAL_PRIVATE int translateNSAPItoPALSocketOption(int option) { int optionVal = PAL_SOCKET_OPTION_ERROR; - switch (option) - { - case PAL_SO_REUSEADDR: - optionVal = NSAPI_REUSEADDR; - break; + switch (option) { + case PAL_SO_REUSEADDR: + optionVal = NSAPI_REUSEADDR; + break; #if PAL_NET_TCP_AND_TLS_SUPPORT // socket options below supported only if TCP is supported. - case PAL_SO_KEEPALIVE: - optionVal = NSAPI_KEEPALIVE; - break; - case PAL_SO_KEEPIDLE: - optionVal = NSAPI_KEEPIDLE; - break; - case PAL_SO_KEEPINTVL: - optionVal = NSAPI_KEEPINTVL; - break; + case PAL_SO_KEEPALIVE: + optionVal = NSAPI_KEEPALIVE; + break; + case PAL_SO_KEEPIDLE: + optionVal = NSAPI_KEEPIDLE; + break; + case PAL_SO_KEEPINTVL: + optionVal = NSAPI_KEEPINTVL; + break; #endif //PAL_NET_TCP_AND_TLS_SUPPORT - case PAL_SO_IPV6_MULTICAST_HOPS: - optionVal = SOCKET_IPV6_MULTICAST_HOPS; - break; - case PAL_SO_SNDTIMEO: - case PAL_SO_RCVTIMEO: - default: - optionVal = PAL_SOCKET_OPTION_ERROR; + case PAL_SO_IPV6_MULTICAST_HOPS: + optionVal = SOCKET_IPV6_MULTICAST_HOPS; + break; + case PAL_SO_IPV6_TRAFFIC_CLASS: + optionVal = SOCKET_IPV6_TCLASS; + break; + case PAL_SO_SNDTIMEO: + case PAL_SO_RCVTIMEO: + default: + optionVal = PAL_SOCKET_OPTION_ERROR; } return optionVal; } -PAL_PRIVATE palStatus_t palSockAddrToSocketAddress(const palSocketAddress_t* palAddr, int length, SocketAddress& output) +PAL_PRIVATE palStatus_t palSockAddrToSocketAddress(const palSocketAddress_t *palAddr, int length, SocketAddress &output) { palStatus_t result = PAL_SUCCESS; uint16_t port = 0; nsapi_version_t version = NSAPI_IPv4; result = pal_getSockAddrPort(palAddr, &port); - if (result != PAL_SUCCESS) - { + if (result != PAL_SUCCESS) { return result; } output.set_port(port); #if PAL_SUPPORT_IP_V4 - if (PAL_AF_INET == palAddr->addressType) - { + if (PAL_AF_INET == palAddr->addressType) { palIpV4Addr_t ipV4Addr; version = NSAPI_IPv4; result = pal_getSockAddrIPV4Addr(palAddr, ipV4Addr); - if (result == PAL_SUCCESS) - { + if (result == PAL_SUCCESS) { output.set_ip_bytes(&ipV4Addr, version); } } #endif #if PAL_SUPPORT_IP_V6 - if (PAL_AF_INET6 == palAddr->addressType) - { + if (PAL_AF_INET6 == palAddr->addressType) { palIpV6Addr_t ipV6Addr; version = NSAPI_IPv6; result = pal_getSockAddrIPV6Addr(palAddr, ipV6Addr); - if (result == PAL_SUCCESS) - { + if (result == PAL_SUCCESS) { output.set_ip_bytes(&ipV6Addr, version); } } @@ -651,9 +623,9 @@ PAL_PRIVATE palStatus_t palSockAddrToSocketAddress(const palSocketAddress_t* pal } #if (PAL_DNS_API_VERSION != 2) -PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress& input, palSocketAddress_t* out, palSocketLength_t* length) +PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress &input, palSocketAddress_t *out, palSocketLength_t *length) #else -PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress& input, palSocketAddress_t* out) +PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress &input, palSocketAddress_t *out) #endif { palStatus_t result = PAL_SUCCESS; @@ -661,14 +633,12 @@ PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress& input, palSock bool found = false; #if PAL_SUPPORT_IP_V4 - if (input.get_ip_version() == NSAPI_IPv4) - { + if (input.get_ip_version() == NSAPI_IPv4) { palIpV4Addr_t addr; found = true; - const void* tmp = input.get_ip_bytes(); - for (index = 0; index < PAL_IPV4_ADDRESS_SIZE; index++) - { - addr[index] = ((const uint8_t*)tmp)[index]; + const void *tmp = input.get_ip_bytes(); + for (index = 0; index < PAL_IPV4_ADDRESS_SIZE; index++) { + addr[index] = ((const uint8_t *)tmp)[index]; } result = pal_setSockAddrIPV4Addr(out, addr); #if (PAL_DNS_API_VERSION != 2) @@ -678,14 +648,12 @@ PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress& input, palSock } #endif #if PAL_SUPPORT_IP_V6 - if (input.get_ip_version() == NSAPI_IPv6) - { + if (input.get_ip_version() == NSAPI_IPv6) { palIpV6Addr_t addr; found = true; - const void* tmp = input.get_ip_bytes(); - for (index = 0; index < PAL_IPV6_ADDRESS_SIZE; index++) - { - addr[index] = ((const uint8_t*)tmp)[index]; + const void *tmp = input.get_ip_bytes(); + for (index = 0; index < PAL_IPV6_ADDRESS_SIZE; index++) { + addr[index] = ((const uint8_t *)tmp)[index]; } result = pal_setSockAddrIPV6Addr(out, addr); #if (PAL_DNS_API_VERSION != 2) @@ -693,26 +661,24 @@ PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress& input, palSock #endif } #endif - if (false == found ) - { + if (false == found) { result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY; } - if (result == PAL_SUCCESS) - { + if (result == PAL_SUCCESS) { result = pal_setSockAddrPort(out, input.get_port()); } return result; } -palStatus_t pal_plat_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength) +palStatus_t pal_plat_setSocketOptions(palSocket_t socket, int optionName, const void *optionValue, palSocketLength_t optionLength) { return pal_plat_setSocketOptionsWithLevel(socket, PAL_SOL_SOCKET, optionName, optionValue, optionLength); } -palStatus_t pal_plat_setSocketOptionsWithLevel(palSocket_t socket, palSocketOptionLevelName_t optionLevel, int optionName, const void* optionValue, palSocketLength_t optionLength) +palStatus_t pal_plat_setSocketOptionsWithLevel(palSocket_t socket, palSocketOptionLevelName_t optionLevel, int optionName, const void *optionValue, palSocketLength_t optionLength) { int result = PAL_SUCCESS; - PALSocketWrapper* socketObj = (PALSocketWrapper*)socket; + PALSocketWrapper *socketObj = (PALSocketWrapper *)socket; PAL_VALIDATE_ARGUMENTS(NULL == socket); int level; @@ -724,40 +690,37 @@ palStatus_t pal_plat_setSocketOptionsWithLevel(palSocket_t socket, palSocketOpti level = PAL_SOCKET_OPTION_ERROR; } - if (PAL_SOCKET_OPTION_ERROR != level) - { + if (PAL_SOCKET_OPTION_ERROR != level) { result = set_sock_options(socketObj, level, optionName, optionValue, optionLength); } return result; } -palStatus_t pal_plat_isNonBlocking(palSocket_t socket, bool* isNonBlocking) +palStatus_t pal_plat_isNonBlocking(palSocket_t socket, bool *isNonBlocking) { - PALSocketWrapper* socketObj = NULL; + PALSocketWrapper *socketObj = NULL; PAL_VALIDATE_ARGUMENTS(NULL == socket); - socketObj = (PALSocketWrapper*)socket; + socketObj = (PALSocketWrapper *)socket; *isNonBlocking = socketObj->isNonBlocking(); return PAL_SUCCESS; } -palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength) +palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t *myAddress, palSocketLength_t addressLength) { int result = PAL_SUCCESS; - PALSocketWrapper* socketObj = (PALSocketWrapper*)socket; + PALSocketWrapper *socketObj = (PALSocketWrapper *)socket; SocketAddress internalAddr; - PAL_VALIDATE_ARGUMENTS ((NULL == socket)); + PAL_VALIDATE_ARGUMENTS((NULL == socket)); result = palSockAddrToSocketAddress(myAddress, addressLength, internalAddr); - if (result == 0) - { + if (result == 0) { result = socketObj->bind(internalAddr); - if (result < 0) - { + if (result < 0) { result = translateErrorToPALError(result); } } @@ -765,57 +728,46 @@ palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t* myAddress, pal return result; } -palStatus_t pal_plat_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived) +palStatus_t pal_plat_receiveFrom(palSocket_t socket, void *buffer, size_t length, palSocketAddress_t *from, palSocketLength_t *fromLength, size_t *bytesReceived) { int result = PAL_SUCCESS; int status = 0; *bytesReceived = 0; SocketAddress sockAddr; - PALSocketWrapper* socketObj; - uint8_t* internalBufferPtr = (uint8_t*)buffer; + PALSocketWrapper *socketObj; + uint8_t *internalBufferPtr = (uint8_t *)buffer; uint32_t bufferUsed = 0; PAL_VALIDATE_ARGUMENTS((NULL == socket)); - socketObj = (PALSocketWrapper*)socket; + socketObj = (PALSocketWrapper *)socket; - if (true == socketObj->isRxBufferSet()) - { + if (true == socketObj->isRxBufferSet()) { internalBufferPtr[0] = socketObj->getAndResetRxBuffer(); internalBufferPtr++; length--; bufferUsed += 1; } - if (length > 0) - { + if (length > 0) { status = socketObj->recvfrom(&sockAddr, internalBufferPtr, length); - if (status < 0) - { + if (status < 0) { result = translateErrorToPALError(status); - } - else if (status == 0) - { + } else if (status == 0) { result = PAL_ERR_SOCKET_CONNECTION_CLOSED; - } - else // only return address / bytesReceived in case of success - { + } else { // only return address / bytesReceived in case of success #if (PAL_DNS_API_VERSION != 2) - if ((NULL != from) && (NULL != fromLength)) - { + if ((NULL != from) && (NULL != fromLength)) { result = socketAddressToPalSockAddr(sockAddr, from, fromLength); } #else - if (NULL != from) - { + if (NULL != from) { result = socketAddressToPalSockAddr(sockAddr, from); } #endif *bytesReceived = status + bufferUsed; } - } - else - { + } else { *bytesReceived = bufferUsed; } @@ -823,7 +775,7 @@ palStatus_t pal_plat_receiveFrom(palSocket_t socket, void* buffer, size_t length } -palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent) +palStatus_t pal_plat_sendTo(palSocket_t socket, const void *buffer, size_t length, const palSocketAddress_t *to, palSocketLength_t toLength, size_t *bytesSent) { int result = PAL_SUCCESS; int status = 0; @@ -831,19 +783,15 @@ palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t lengt PAL_VALIDATE_ARGUMENTS((NULL == socket)); - PALSocketWrapper* socketObj = (PALSocketWrapper*)socket; + PALSocketWrapper *socketObj = (PALSocketWrapper *)socket; *bytesSent = 0; result = palSockAddrToSocketAddress(to, toLength, sockAddr); - if (result == 0) - { + if (result == 0) { status = socketObj->sendto(sockAddr, buffer, length); - if (status < 0) - { + if (status < 0) { result = translateErrorToPALError(status); - } - else - { + } else { *bytesSent = status; } } @@ -851,18 +799,16 @@ palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t lengt return result; } -palStatus_t pal_plat_close(palSocket_t* socket) +palStatus_t pal_plat_close(palSocket_t *socket) { int result = PAL_SUCCESS; - if (NULL == *socket) - { + if (NULL == *socket) { PAL_LOG_DBG("socket close called on socket which was already closed"); return result; // socket already closed (or not opened) - no need to close. } - PALSocketWrapper* socketObj = (PALSocketWrapper*)*socket; + PALSocketWrapper *socketObj = (PALSocketWrapper *)*socket; result = socketObj->close(); - if (result < 0) - { + if (result < 0) { result = translateErrorToPALError(result); } delete socketObj; @@ -870,20 +816,20 @@ palStatus_t pal_plat_close(palSocket_t* socket) return result; } -palStatus_t pal_plat_getNumberOfNetInterfaces( uint32_t* numInterfaces) +palStatus_t pal_plat_getNumberOfNetInterfaces(uint32_t *numInterfaces) { *numInterfaces = s_pal_numberOFInterfaces; return PAL_SUCCESS; } -palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t * interfaceInfo) +palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t *interfaceInfo) { palStatus_t result = PAL_SUCCESS; SocketAddress addr; PAL_VALIDATE_ARGUMENTS((interfaceNum >= s_pal_numberOFInterfaces)); #if defined (MBED_MAJOR_VERSION) && (MBED_MAJOR_VERSION==5) - const char* address = NULL; + const char *address = NULL; address = s_pal_networkInterfacesSupported[interfaceNum].interface->get_ip_address(); // ip address returned is a null terminated string if (NULL != address) { @@ -962,34 +908,31 @@ palStatus_t pal_plat_listen(palSocket_t socket, int backlog) int result = PAL_SUCCESS; PAL_VALIDATE_ARGUMENTS(NULL == socket); - PALSocketWrapper* socketObj = (PALSocketWrapper*)socket; + PALSocketWrapper *socketObj = (PALSocketWrapper *)socket; result = socketObj->listen(backlog); - if (result < 0) - { + if (result < 0) { return translateErrorToPALError(result); } return PAL_SUCCESS; } -palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t * address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket, palAsyncSocketCallback_t callback, void* callbackArgument) +palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t *address, palSocketLength_t *addressLen, palSocket_t *acceptedSocket, palAsyncSocketCallback_t callback, void *callbackArgument) { int result = PAL_SUCCESS; bool isNonBlocking = callback ? true : false; - PAL_VALIDATE_ARGUMENTS ((NULL == socket)); - PALSocketWrapper* socketObj = (PALSocketWrapper*)socket; + PAL_VALIDATE_ARGUMENTS((NULL == socket)); + PALSocketWrapper *socketObj = (PALSocketWrapper *)socket; // Create wrapper PALSocketWrapper *out = new PALSocketWrapper; // Try to accept incoming socket Socket *s = socketObj->accept(&result); - if (result < 0) - { + if (result < 0) { result = translateErrorToPALError(result); delete out; - } else - { + } else { // Incoming socket accepted - initialize the wrapper out->initialize(s, PAL_SOCK_STREAM, isNonBlocking, callback, callbackArgument); out->freeSocket(false); @@ -1001,19 +944,17 @@ palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t * address, pa #endif // PAL_NET_SERVER_SOCKET_API -palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen) +palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t *address, palSocketLength_t addressLen) { int result = PAL_SUCCESS; SocketAddress internalAddr; - PALSocketWrapper* socketObj = (PALSocketWrapper*)socket; - PAL_VALIDATE_ARGUMENTS ((NULL == socket)); + PALSocketWrapper *socketObj = (PALSocketWrapper *)socket; + PAL_VALIDATE_ARGUMENTS((NULL == socket)); result = palSockAddrToSocketAddress(address, addressLen, internalAddr); - if (result == PAL_SUCCESS) - { + if (result == PAL_SUCCESS) { result = socketObj->connect(internalAddr); - if (result < 0) - { + if (result < 0) { result = translateErrorToPALError(result); } } @@ -1021,33 +962,29 @@ palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t* addre return result; } -palStatus_t pal_plat_recv(palSocket_t socket, void *buf, size_t len, size_t* recievedDataSize) +palStatus_t pal_plat_recv(palSocket_t socket, void *buf, size_t len, size_t *recievedDataSize) { int result = PAL_SUCCESS; int status = 0; - uint8_t* internalBufferPtr = (uint8_t*)buf; + uint8_t *internalBufferPtr = (uint8_t *)buf; uint32_t bufferUsed = 0; - PALSocketWrapper* socketObj = (PALSocketWrapper*)socket; - PAL_VALIDATE_ARGUMENTS ((NULL == socket)); + PALSocketWrapper *socketObj = (PALSocketWrapper *)socket; + PAL_VALIDATE_ARGUMENTS((NULL == socket)); - if (true == socketObj->isRxBufferSet()) - { + if (true == socketObj->isRxBufferSet()) { internalBufferPtr[0] = socketObj->getAndResetRxBuffer(); internalBufferPtr++; len--; bufferUsed += 1; } - if (len > 0) - { + if (len > 0) { status = socketObj->recv(internalBufferPtr, len); - if (status < 0) - { + if (status < 0) { result = translateErrorToPALError(status); - } - else if (status == 0) { + } else if (status == 0) { return PAL_ERR_SOCKET_CONNECTION_CLOSED; } } @@ -1056,23 +993,20 @@ palStatus_t pal_plat_recv(palSocket_t socket, void *buf, size_t len, size_t* rec return result; } -palStatus_t pal_plat_send(palSocket_t socket, const void *buf, size_t len, size_t* sentDataSize) +palStatus_t pal_plat_send(palSocket_t socket, const void *buf, size_t len, size_t *sentDataSize) { palStatus_t result = PAL_SUCCESS; int status = 0; - PALSocketWrapper* socketObj = (PALSocketWrapper*)socket; - PAL_VALIDATE_ARGUMENTS ((NULL == socket)); + PALSocketWrapper *socketObj = (PALSocketWrapper *)socket; + PAL_VALIDATE_ARGUMENTS((NULL == socket)); status = socketObj->send(buf, len); - if (status < 0) - { - PAL_LOG_DBG("pal_plat_send status %d",status); + if (status < 0) { + PAL_LOG_DBG("pal_plat_send status %d", status); result = translateErrorToPALError(status); - } - else - { + } else { *sentDataSize = status; } @@ -1081,14 +1015,14 @@ palStatus_t pal_plat_send(palSocket_t socket, const void *buf, size_t len, size_ #endif //PAL_NET_TCP_AND_TLS_SUPPORT -palStatus_t pal_plat_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* arg, palSocket_t* socket) +palStatus_t pal_plat_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void *arg, palSocket_t *socket) { return create_socket(domain, type, nonBlockingSocket, interfaceNum, callback, arg, socket); } #if PAL_NET_DNS_SUPPORT #if (PAL_DNS_API_VERSION == 0) || (PAL_DNS_API_VERSION == 1) -palStatus_t pal_plat_getAddressInfo(const char *hostname, palSocketAddress_t *address, palSocketLength_t* length) +palStatus_t pal_plat_getAddressInfo(const char *hostname, palSocketAddress_t *address, palSocketLength_t *length) { palStatus_t result = PAL_SUCCESS; SocketAddress translatedAddress; // by default use the fist supported net interface - TODO: do we need to select a different interface? @@ -1108,8 +1042,7 @@ palStatus_t pal_plat_getAddressInfo(const char *hostname, palSocketAddress_t *ad if (result == 0) { result = socketAddressToPalSockAddr(translatedAddress, address, length); - } - else { // error happened + } else { // error happened result = translateErrorToPALError(result); } return result; @@ -1119,12 +1052,11 @@ palStatus_t pal_plat_getAddressInfo(const char *hostname, palSocketAddress_t *ad void pal_plat_getAddressInfoAsync_callback(void *data, nsapi_error_t result, SocketAddress *address) { palStatus_t status = PAL_SUCCESS; - pal_asyncAddressInfo_t* info = (pal_asyncAddressInfo_t*)(data); + pal_asyncAddressInfo_t *info = (pal_asyncAddressInfo_t *)(data); if (result >= NSAPI_ERROR_OK) { status = socketAddressToPalSockAddr(*address, info->address); - } - else { // error happened + } else { // error happened status = translateErrorToPALError(result); } @@ -1132,7 +1064,7 @@ void pal_plat_getAddressInfoAsync_callback(void *data, nsapi_error_t result, Soc free(info); } -palStatus_t pal_plat_getAddressInfoAsync(pal_asyncAddressInfo* info) +palStatus_t pal_plat_getAddressInfoAsync(pal_asyncAddressInfo *info) { PAL_LOG_DBG("pal_plat_getAddressInfoAsync"); palStatus_t result; @@ -1149,18 +1081,17 @@ palStatus_t pal_plat_getAddressInfoAsync(pal_asyncAddressInfo* info) if (s_pal_networkInterfacesSupported[0].interface == NULL) { result = PAL_ERR_INVALID_ARGUMENT; } else { - result = s_pal_networkInterfacesSupported[0].interface->gethostbyname_async(info->hostname, mbed::Callback(pal_plat_getAddressInfoAsync_callback,(void*)info), version); + result = s_pal_networkInterfacesSupported[0].interface->gethostbyname_async(info->hostname, mbed::Callback(pal_plat_getAddressInfoAsync_callback, (void *)info), version); } PAL_LOG_DBG("pal_plat_getAddressInfoAsync result %" PRId32 ".", result); if (result < 0) { result = translateErrorToPALError(result); - } - else { + } else { /* Skip over setting queryHandle when: * 1. info->queryHandle not allocated * 2. if result is zero then callback pal_plat_getAddressInfoAsync_callback will be called immediately and address info has been deallocated. */ - if ( (info->queryHandle != NULL) && result) { + if ((info->queryHandle != NULL) && result) { *(info->queryHandle) = result; } result = PAL_SUCCESS; @@ -1181,73 +1112,57 @@ palStatus_t pal_plat_cancelAddressInfoAsync(palDNSQuery_t queryHandle) return status; } #else - #error "Please specify the platform PAL_DNS_API_VERSION 0, 1 or 2." +#error "Please specify the platform PAL_DNS_API_VERSION 0, 1 or 2." #endif // PAL_DNS_API_VERSION #endif -PAL_PRIVATE palStatus_t create_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* arg, palSocket_t* socket) +PAL_PRIVATE palStatus_t create_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void *arg, palSocket_t *socket) { int result = PAL_SUCCESS; - PALSocketWrapper * socketObj = NULL; - InternetSocket* internalSocket = NULL; + PALSocketWrapper *socketObj = NULL; + InternetSocket *internalSocket = NULL; PAL_VALIDATE_ARGUMENTS((NULL == socket)); - if (PAL_NET_DEFAULT_INTERFACE == interfaceNum) - { + if (PAL_NET_DEFAULT_INTERFACE == interfaceNum) { interfaceNum = 0; } - if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_DGRAM == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) //check that we got correct parameters for UDP socket - { + if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_DGRAM == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) { //check that we got correct parameters for UDP socket internalSocket = new UDPSocket; } #if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported. - else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM == type || PAL_SOCK_STREAM_SERVER == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) //check that we got correct parameters for TCP socket - { + else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM == type || PAL_SOCK_STREAM_SERVER == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) { //check that we got correct parameters for TCP socket internalSocket = new TCPSocket; } #endif - else - { + else { result = PAL_ERR_INVALID_ARGUMENT; } - if (internalSocket && result == PAL_SUCCESS) - { + if (internalSocket && result == PAL_SUCCESS) { result = internalSocket->open(s_pal_networkInterfacesSupported[interfaceNum].interface); - if (result < 0) - { + if (result < 0) { result = translateErrorToPALError(result); } - } - else - { + } else { result = PAL_ERR_NO_MEMORY; } - if (PAL_SUCCESS == result) - { + if (PAL_SUCCESS == result) { socketObj = new PALSocketWrapper(); - if (NULL != socketObj) - { - if (0 == socketObj->initialize(internalSocket, type, nonBlockingSocket, callback, arg)) - { + if (NULL != socketObj) { + if (0 == socketObj->initialize(internalSocket, type, nonBlockingSocket, callback, arg)) { *socket = (palSocket_t)socketObj; - } - else - { + } else { result = PAL_ERR_INVALID_ARGUMENT; } - } - else - { + } else { result = PAL_ERR_NO_MEMORY; } } - if (PAL_SUCCESS != result) //cleanup - { + if (PAL_SUCCESS != result) { //cleanup delete internalSocket; delete socketObj; @@ -1259,23 +1174,19 @@ PAL_PRIVATE palStatus_t create_socket(palSocketDomain_t domain, palSocketType_t void pal_plat_connectionStatusCallback(void *interfaceIndex, nsapi_event_t status, intptr_t param) { uint32_t index = (uint32_t)interfaceIndex; - if (status == NSAPI_EVENT_CONNECTION_STATUS_CHANGE) - { - switch(param) - { + if (status == NSAPI_EVENT_CONNECTION_STATUS_CHANGE) { + switch (param) { case NSAPI_STATUS_GLOBAL_UP: - if (s_pal_networkInterfacesSupported[index].connectionStatusCb) - { - s_pal_networkInterfacesSupported[index].connectionStatusCb(PAL_NETWORK_STATUS_CONNECTED, - s_pal_networkInterfacesSupported[index].clientArg); + if (s_pal_networkInterfacesSupported[index].connectionStatusCb) { + s_pal_networkInterfacesSupported[index].connectionStatusCb(PAL_NETWORK_STATUS_CONNECTED, + s_pal_networkInterfacesSupported[index].clientArg); } break; case NSAPI_STATUS_DISCONNECTED: - if (s_pal_networkInterfacesSupported[index].connectionStatusCb) - { + if (s_pal_networkInterfacesSupported[index].connectionStatusCb) { s_pal_networkInterfacesSupported[index].connectionStatusCb(PAL_NETWORK_STATUS_DISCONNECTED, - s_pal_networkInterfacesSupported[index].clientArg); + s_pal_networkInterfacesSupported[index].clientArg); } break; @@ -1297,7 +1208,7 @@ uint8_t pal_plat_getRttEstimate() SocketAddress sa; nsapi_error_t err; - NetworkInterface* net; + NetworkInterface *net; UDPSocket socket; net = s_pal_networkInterfacesSupported[0].interface; @@ -1326,7 +1237,7 @@ uint8_t pal_plat_getRttEstimate() } // Returned value is in milliseconds, convert to seconds and limit to uint8_t max - rtt_temp = rtt_temp/1000; + rtt_temp = rtt_temp / 1000; if (rtt_temp > UINT8_MAX) { rtt_temp = UINT8_MAX; } @@ -1357,7 +1268,7 @@ uint16_t pal_plat_getStaggerEstimate(uint16_t data_amount) PAL_LOG_DBG("pal_plat_getStaggerEstimate asking stack"); SocketAddress sa; nsapi_error_t err; - NetworkInterface* net; + NetworkInterface *net; UDPSocket socket; net = s_pal_networkInterfacesSupported[0].interface; @@ -1393,50 +1304,40 @@ uint16_t pal_plat_getStaggerEstimate(uint16_t data_amount) return stagger_rand; } -PAL_PRIVATE palStatus_t set_sock_options(PALSocketWrapper *socketObj, int optionLevel, int optionName, const void* optionValue, palSocketLength_t optionLength) +PAL_PRIVATE palStatus_t set_sock_options(PALSocketWrapper *socketObj, int optionLevel, int optionName, const void *optionValue, palSocketLength_t optionLength) { int result = PAL_SUCCESS; int socketOption = PAL_SOCKET_OPTION_ERROR; socketOption = translateNSAPItoPALSocketOption(optionName); - if (PAL_SOCKET_OPTION_ERROR != socketOption) - { - if (PAL_SO_REUSEADDR == optionName) - { + if (PAL_SOCKET_OPTION_ERROR != socketOption) { + if (PAL_SO_REUSEADDR == optionName) { result = socketObj->setsockopt(optionLevel, socketOption, optionValue, optionLength); } #if PAL_NET_TCP_AND_TLS_SUPPORT else if (PAL_SO_KEEPIDLE == optionName || - PAL_SO_KEEPINTVL == optionName ) - { - // Timeouts are in milliseconds - uint32_t timeout = (*(int *)optionValue) * 1000; - result = socketObj->setsockopt(optionLevel, socketOption, (void*)&timeout, sizeof(timeout)); + PAL_SO_KEEPINTVL == optionName) { + // Timeouts are in milliseconds + uint32_t timeout = (*(int *)optionValue) * 1000; + result = socketObj->setsockopt(optionLevel, socketOption, (void *)&timeout, sizeof(timeout)); } #endif - else - { + else { result = socketObj->setsockopt(optionLevel, socketOption, optionValue, optionLength); } - if (result < 0) - { + if (result < 0) { result = translateErrorToPALError(result); } - } - else - { - if ((PAL_SO_SNDTIMEO == optionName) || (PAL_SO_RCVTIMEO == optionName)) // timeouts in MBED API are not managed though socket options, bun instead via a different funciton call - { - int timeout = *((int*)optionValue); + } else { + if ((PAL_SO_SNDTIMEO == optionName) || (PAL_SO_RCVTIMEO == optionName)) { // timeouts in MBED API are not managed though socket options, bun instead via a different funciton call + int timeout = *((int *)optionValue); // SO_xxxTIMEO should only affect blocking sockets - it only limits the block, // whereas NSAPI's set_timeout is coupled with the blocking setting if (!socketObj->isNonBlocking()) { socketObj->set_timeout(timeout); } - } - else - { + } else { result = PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED; } } diff --git a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/nanosimulator/Networking/pal_plat_network.c b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/nanosimulator/Networking/pal_plat_network.c index f8246c607..0b8808b75 100644 --- a/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/nanosimulator/Networking/pal_plat_network.c +++ b/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/nanosimulator/Networking/pal_plat_network.c @@ -44,7 +44,7 @@ static struct { } sock_control[NUMBER_OF_SOCKETS]; -static int8_t get_socket_handle(const palSocket_t* socket, int8_t* index) +static int8_t get_socket_handle(const palSocket_t *socket, int8_t *index) { for (int i = 0; i < NUMBER_OF_SOCKETS; i++) { if (sock_control[i].socket_id == (intptr_t)socket) { @@ -60,10 +60,10 @@ static int8_t get_socket_handle(const palSocket_t* socket, int8_t* index) void socket_callback(void *raw_param) { - const socket_callback_t *cb_event = (const socket_callback_t*)raw_param; + const socket_callback_t *cb_event = (const socket_callback_t *)raw_param; if (cb_event != NULL && cb_event->event_type == SOCKET_DATA) { int8_t index; - int8_t socket_handle = get_socket_handle((const palSocket_t*)cb_event->socket_id, &index); + int8_t socket_handle = get_socket_handle((const palSocket_t *)cb_event->socket_id, &index); if (socket_handle == -1) { PAL_LOG_ERR("socket_callback - socket id not found!"); } else { @@ -112,7 +112,7 @@ static int8_t address_pal2nanostack(const palSocketAddress_t *pal_addr, ns_addre { uint16_t port; - if (pal_getSockAddrPort (pal_addr, &port) != PAL_SUCCESS) { + if (pal_getSockAddrPort(pal_addr, &port) != PAL_SUCCESS) { return 0; } @@ -122,7 +122,7 @@ static int8_t address_pal2nanostack(const palSocketAddress_t *pal_addr, ns_addre ns_addr->type = ADDRESS_IPV6; ns_addr->identifier = port; memcpy(ns_addr->address, &addr, sizeof(addr)); - return (sizeof (addr)); + return (sizeof(addr)); } else { return 0; } @@ -131,7 +131,7 @@ static int8_t address_pal2nanostack(const palSocketAddress_t *pal_addr, ns_addre return 0; } -palStatus_t pal_plat_socketsInit(void* context) +palStatus_t pal_plat_socketsInit(void *context) { (void)context; @@ -140,7 +140,7 @@ palStatus_t pal_plat_socketsInit(void* context) return PAL_SUCCESS; } -palStatus_t pal_plat_registerNetworkInterface(void* context, uint32_t* interfaceIndex) +palStatus_t pal_plat_registerNetworkInterface(void *context, uint32_t *interfaceIndex) { (void)context; (void)interfaceIndex; @@ -153,13 +153,13 @@ palStatus_t pal_plat_unregisterNetworkInterface(uint32_t interfaceIndex) return PAL_SUCCESS; } -palStatus_t pal_plat_socketsTerminate(void* context) +palStatus_t pal_plat_socketsTerminate(void *context) { (void)context; return PAL_SUCCESS; } -palStatus_t pal_plat_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* socket) +palStatus_t pal_plat_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t *socket) { (void)interfaceNum; (void)type; @@ -172,12 +172,12 @@ palStatus_t pal_plat_socket(palSocketDomain_t domain, palSocketType_t type, bool return PAL_ERR_NOT_SUPPORTED; } -palStatus_t pal_plat_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength) +palStatus_t pal_plat_setSocketOptions(palSocket_t socket, int optionName, const void *optionValue, palSocketLength_t optionLength) { return pal_plat_setSocketOptionsWithLevel(socket, PAL_SOL_IPPROTO_IPV6, optionName, optionValue, optionLength); } -palStatus_t pal_plat_setSocketOptionsWithLevel(palSocket_t socket, palSocketOptionLevelName_t optionLevel, int optionName, const void* optionValue, palSocketLength_t optionLength) +palStatus_t pal_plat_setSocketOptionsWithLevel(palSocket_t socket, palSocketOptionLevelName_t optionLevel, int optionName, const void *optionValue, palSocketLength_t optionLength) { int8_t index; int8_t socket_handle = get_socket_handle(socket, &index); @@ -200,6 +200,8 @@ palStatus_t pal_plat_setSocketOptionsWithLevel(palSocket_t socket, palSocketOpti int optionVal; if (optionName == PAL_SO_IPV6_MULTICAST_HOPS) { optionVal = SOCKET_IPV6_MULTICAST_HOPS; + } else if (optionName == PAL_SO_IPV6_TRAFFIC_CLASS) { + optionVal = SOCKET_IPV6_TCLASS; } else { return PAL_ERR_SOCKET_GENERIC; } @@ -214,14 +216,14 @@ palStatus_t pal_plat_setSocketOptionsWithLevel(palSocket_t socket, palSocketOpti return PAL_SUCCESS; } -palStatus_t pal_plat_isNonBlocking(palSocket_t socket, bool* isNonBlocking) +palStatus_t pal_plat_isNonBlocking(palSocket_t socket, bool *isNonBlocking) { *isNonBlocking = true; return PAL_SUCCESS; } -palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength) +palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t *myAddress, palSocketLength_t addressLength) { if (myAddress == NULL) { return PAL_ERR_INVALID_ARGUMENT; @@ -250,7 +252,7 @@ palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t* myAddress, pal return PAL_SUCCESS; } -palStatus_t pal_plat_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived) +palStatus_t pal_plat_receiveFrom(palSocket_t socket, void *buffer, size_t length, palSocketAddress_t *from, palSocketLength_t *fromLength, size_t *bytesReceived) { if ((bytesReceived == NULL) || (from == NULL) || (fromLength == NULL)) { return PAL_ERR_INVALID_ARGUMENT; @@ -281,7 +283,7 @@ palStatus_t pal_plat_receiveFrom(palSocket_t socket, void* buffer, size_t length } } -palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent) +palStatus_t pal_plat_sendTo(palSocket_t socket, const void *buffer, size_t length, const palSocketAddress_t *to, palSocketLength_t toLength, size_t *bytesSent) { if ((bytesSent == NULL) || (to == NULL)) { return PAL_ERR_INVALID_ARGUMENT; @@ -300,7 +302,7 @@ palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t lengt return PAL_ERR_SOCKET_INVALID_ADDRESS; } - int16_t ret = socket_sendto(socket_handle, &ns_addr, (void*)buffer, length); + int16_t ret = socket_sendto(socket_handle, &ns_addr, (void *)buffer, length); if (ret < 0) { PAL_LOG_ERR("pal_plat_sendTo - socket_sendto failed: %d", ret); @@ -311,7 +313,7 @@ palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t lengt return PAL_SUCCESS; } -palStatus_t pal_plat_close(palSocket_t* socket) +palStatus_t pal_plat_close(palSocket_t *socket) { int8_t index; int8_t socket_index = get_socket_handle(*socket, &index); @@ -340,7 +342,7 @@ palStatus_t pal_plat_close(palSocket_t* socket) return PAL_SUCCESS; } -palStatus_t pal_plat_getNumberOfNetInterfaces(uint32_t* numInterfaces) +palStatus_t pal_plat_getNumberOfNetInterfaces(uint32_t *numInterfaces) { if (numInterfaces == NULL) { return (PAL_ERR_INVALID_ARGUMENT); @@ -351,7 +353,7 @@ palStatus_t pal_plat_getNumberOfNetInterfaces(uint32_t* numInterfaces) return PAL_SUCCESS; } -palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t * interfaceInfo) +palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t *interfaceInfo) { (void)interfaceNum; (void)interfaceInfo; @@ -379,7 +381,7 @@ palStatus_t pal_plat_listen(palSocket_t socket, int backlog) return PAL_SUCCESS; } -palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t* address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket, palAsyncSocketCallback_t callback, void* callbackArgument) +palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t *address, palSocketLength_t *addressLen, palSocket_t *acceptedSocket, palAsyncSocketCallback_t callback, void *callbackArgument) { if (acceptedSocket == NULL) { return PAL_ERR_INVALID_ARGUMENT; @@ -407,7 +409,7 @@ palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t* address, pal return PAL_SUCCESS; } -palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen) +palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t *address, palSocketLength_t addressLen) { if (address == NULL) { return PAL_ERR_INVALID_ARGUMENT; @@ -443,7 +445,7 @@ palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t* addre } } -palStatus_t pal_plat_recv(palSocket_t socket, void *buffer, size_t len, size_t* receivedDataSize) +palStatus_t pal_plat_recv(palSocket_t socket, void *buffer, size_t len, size_t *receivedDataSize) { if (receivedDataSize == NULL) { return (PAL_ERR_INVALID_ARGUMENT); @@ -486,7 +488,7 @@ palStatus_t pal_plat_send(palSocket_t socket, const void *buf, size_t len, size_ return PAL_ERR_ITEM_NOT_EXIST; } - int16_t ret = socket_send(socket_handle, (void*)buf, len); + int16_t ret = socket_send(socket_handle, (void *)buf, len); PAL_LOG_DBG("pal_plat_send - socket_send return %d", ret); @@ -511,8 +513,8 @@ palStatus_t pal_plat_asynchronousSocket(palSocketDomain_t domain, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, - void* callbackArgument, - palSocket_t* socket) + void *callbackArgument, + palSocket_t *socket) { uint8_t protocol; int8_t socket_id; @@ -583,64 +585,63 @@ palStatus_t pal_plat_setConnectionStatusCallback(uint32_t interfaceIndex, connec PAL_PRIVATE palStatus_t translateErrorToPALError(int errnoValue) { palStatus_t status; - switch (errnoValue) - { - case EAI_MEMORY: - status = PAL_ERR_NO_MEMORY; - break; - case EWOULDBLOCK: - status = PAL_ERR_SOCKET_WOULD_BLOCK; - break; - case ENOTSOCK: - status = PAL_ERR_SOCKET_INVALID_VALUE; - break; - case EPERM: - case EACCES: - status = PAL_ERR_SOCKET_OPERATION_NOT_PERMITTED; - break; - case ETIMEDOUT: - status = PAL_ERR_TIMEOUT_EXPIRED; - break; - case EISCONN: - status = PAL_ERR_SOCKET_ALREADY_CONNECTED; - break; - case EAI_FAMILY: - status = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY; - break; - case EINPROGRESS: - status = PAL_ERR_SOCKET_IN_PROGRES; - break; - case EALREADY: - status = PAL_ERR_SOCKET_ALREADY_CONNECTED; - break; - case EINVAL: - status = PAL_ERR_SOCKET_INVALID_VALUE; - break; - case EADDRINUSE: - status = PAL_ERR_SOCKET_ADDRESS_IN_USE; - break; - case ECONNABORTED: - status = PAL_ERR_SOCKET_CONNECTION_ABORTED; - break; - case ECONNRESET: - case ECONNREFUSED: - status = PAL_ERR_SOCKET_CONNECTION_RESET; - break; - case ENOBUFS: - case ENOMEM: - status = PAL_ERR_SOCKET_NO_BUFFERS; - break; - case EINTR: - status = PAL_ERR_SOCKET_INTERRUPTED; - break; - case EAI_AGAIN: - case EAI_NONAME: - status = PAL_ERR_SOCKET_DNS_ERROR; - break; - default: - PAL_LOG_ERR("translateErrorToPALError() cannot translate %d", errnoValue); - status = PAL_ERR_SOCKET_GENERIC; - break; + switch (errnoValue) { + case EAI_MEMORY: + status = PAL_ERR_NO_MEMORY; + break; + case EWOULDBLOCK: + status = PAL_ERR_SOCKET_WOULD_BLOCK; + break; + case ENOTSOCK: + status = PAL_ERR_SOCKET_INVALID_VALUE; + break; + case EPERM: + case EACCES: + status = PAL_ERR_SOCKET_OPERATION_NOT_PERMITTED; + break; + case ETIMEDOUT: + status = PAL_ERR_TIMEOUT_EXPIRED; + break; + case EISCONN: + status = PAL_ERR_SOCKET_ALREADY_CONNECTED; + break; + case EAI_FAMILY: + status = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY; + break; + case EINPROGRESS: + status = PAL_ERR_SOCKET_IN_PROGRES; + break; + case EALREADY: + status = PAL_ERR_SOCKET_ALREADY_CONNECTED; + break; + case EINVAL: + status = PAL_ERR_SOCKET_INVALID_VALUE; + break; + case EADDRINUSE: + status = PAL_ERR_SOCKET_ADDRESS_IN_USE; + break; + case ECONNABORTED: + status = PAL_ERR_SOCKET_CONNECTION_ABORTED; + break; + case ECONNRESET: + case ECONNREFUSED: + status = PAL_ERR_SOCKET_CONNECTION_RESET; + break; + case ENOBUFS: + case ENOMEM: + status = PAL_ERR_SOCKET_NO_BUFFERS; + break; + case EINTR: + status = PAL_ERR_SOCKET_INTERRUPTED; + break; + case EAI_AGAIN: + case EAI_NONAME: + status = PAL_ERR_SOCKET_DNS_ERROR; + break; + default: + PAL_LOG_ERR("translateErrorToPALError() cannot translate %d", errnoValue); + status = PAL_ERR_SOCKET_GENERIC; + break; } return status; } @@ -648,7 +649,7 @@ PAL_PRIVATE palStatus_t translateErrorToPALError(int errnoValue) #if PAL_NET_DNS_SUPPORT -palStatus_t pal_plat_getAddressInfo(const char *url, palSocketAddress_t *address, palSocketLength_t* length) +palStatus_t pal_plat_getAddressInfo(const char *url, palSocketAddress_t *address, palSocketLength_t *length) { if ((url == NULL) || (address == NULL) || (length == NULL)) { return PAL_ERR_INVALID_ARGUMENT; @@ -661,10 +662,10 @@ palStatus_t pal_plat_getAddressInfo(const char *url, palSocketAddress_t *address struct addrinfo *addr_result; struct addrinfo hints; - memset (&hints, 0, sizeof (hints)); + memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; int res = getaddrinfo(url, NULL, &hints, &addr_result); - if(res < 0) { + if (res < 0) { // getaddrinfo returns EAI-error. In case of EAI_SYSTEM, the error // is 'Other system error, check errno for details' // (http://man7.org/linux/man-pages/man3/getaddrinfo.3.html#RETURN_VALUE) @@ -677,7 +678,7 @@ palStatus_t pal_plat_getAddressInfo(const char *url, palSocketAddress_t *address } } else { if (addr_result != NULL) { - int error = getnameinfo((struct sockaddr*)addr_result->ai_addr, addr_result->ai_addrlen, ip_addr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + int error = getnameinfo((struct sockaddr *)addr_result->ai_addr, addr_result->ai_addrlen, ip_addr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (error == 0) { ns_address_t ns_address; int8_t ns_addr_len = strlen(ip_addr); diff --git a/mbed-client-pal/Test/PAL_Modules/Networking/pal_socket_test.c b/mbed-client-pal/Test/PAL_Modules/Networking/pal_socket_test.c index 6540201af..439714534 100644 --- a/mbed-client-pal/Test/PAL_Modules/Networking/pal_socket_test.c +++ b/mbed-client-pal/Test/PAL_Modules/Networking/pal_socket_test.c @@ -15,7 +15,7 @@ *******************************************************************************/ #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "unity.h" #include "unity_fixture.h" #include "test_runners.h" @@ -68,7 +68,9 @@ PAL_PRIVATE palSocket_t g_testSockets[PAL_NET_TEST_SOCKETS] = {0,0,0,0}; #define PAL_NET_TEST_BUFFERED_UDP_MESSAGE_SIZE (1024 * 256) PAL_PRIVATE uint8_t *g_testRecvBuffer = NULLPTR; PAL_PRIVATE uint8_t *g_testSendBuffer = NULLPTR; +#ifdef TARGET_LIKE_MBED PAL_PRIVATE bool g_interfaceConnected = false; +#endif #define PAL_NET_TEST_ECHO_TEST_SERVER_ADDRESS "echo.mbedcloudtesting.com" // the tests expect to have guaranteed forward progress, even if they fail. So the semaphore @@ -156,21 +158,30 @@ PAL_PRIVATE void socketCallback1( void * arg) static palSemaphoreID_t s_semaphoreID = NULLPTR; static palSemaphoreID_t s_semaphoreID3 = NULLPTR; -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) static palSemaphoreID_t s_asyncDnsSemaphore = NULLPTR; // flag marking if the pal_getAddressInfoAsync callback has been invoked PAL_PRIVATE bool g_getAddressInfoAsyncCallbackInvoked = false; - +#if (PAL_DNS_API_VERSION == 3) +static palAddressInfo_t *global_addrInfo = NULLPTR; +static palDNSQuery_t dns_query_t = 0; +// callback invoked from the call to pal_getAddressInfoAsync +PAL_PRIVATE void getAddressInfoAsyncCallback(const char* url, palAddressInfo_t *addrInfo, palStatus_t status, void* callbackArgument) +{ + global_addrInfo = addrInfo; +#else // callback invoked from the call to pal_getAddressInfoAsync PAL_PRIVATE void getAddressInfoAsyncCallback(const char* url, palSocketAddress_t* address, palStatus_t status, void* callbackArgument) { +#endif TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); g_getAddressInfoAsyncCallbackInvoked = true; pal_osSemaphoreRelease(s_asyncDnsSemaphore); } + #endif PAL_PRIVATE palStatus_t doDnsQuery(const char* hostname, palSocketAddress_t *address, palSocketLength_t *addrlen) @@ -186,6 +197,20 @@ PAL_PRIVATE palStatus_t doDnsQuery(const char* hostname, palSocketAddress_t *add NULL); result = pal_osSemaphoreWait(s_asyncDnsSemaphore, 5000, NULL); +#elif (PAL_DNS_API_VERSION == 3) + result = pal_osSemaphoreCreate(0, &s_asyncDnsSemaphore); + TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); + result = pal_getAddressInfoAsync(hostname, + &getAddressInfoAsyncCallback, + NULL, + &dns_query_t); + result = pal_osSemaphoreWait(s_asyncDnsSemaphore, 5000, NULL); + result = pal_free_addressinfoAsync(dns_query_t); + result = pal_getDNSAddress(global_addrInfo, 0, address); + *addrlen = sizeof(palSocketAddress_t); + pal_freeAddrInfo(global_addrInfo); + global_addrInfo = NULLPTR; + dns_query_t = 0; #else result = pal_getAddressInfo(hostname, address, addrlen); #endif @@ -777,7 +802,7 @@ TEST(pal_socket, ServerSocketScenario) /*#S3*/ uint32_t rand_number = 0; uint16_t incoming_port; - + #if !PAL_USE_HW_TRNG palStatus_t status = PAL_SUCCESS; // If no hardware trng - entropy must be injected for random to work @@ -1334,7 +1359,7 @@ PAL_PRIVATE void socketTCPBuffered(size_t bufSize) TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); /*#1*/ - result = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback3, &g_testSockets[0]); + result = pal_asynchronousSocket(address.addressType, PAL_SOCK_STREAM, true, 0, socketCallback3, &g_testSockets[0]); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); /*#3*/ @@ -1739,7 +1764,7 @@ PAL_PRIVATE void echo_test(bool tcp) result = pal_osSemaphoreCreate(1, &s_semaphoreID3); TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); - result = pal_asynchronousSocket(PAL_AF_INET, sockType, true, 0, socketCallback3, &g_testSockets[0]); + result = pal_asynchronousSocket(address.addressType, sockType, true, 0, socketCallback3, &g_testSockets[0]); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); /*#3*/ @@ -1750,7 +1775,7 @@ PAL_PRIVATE void echo_test(bool tcp) if (sockType == PAL_SOCK_STREAM) { do { - result = pal_connect(g_testSockets[0], &address, 16); + result = pal_connect(g_testSockets[0], &address, addrlen); pal_osSemaphoreWait(s_semaphoreID3, 10000, &temp); } while (result == PAL_ERR_SOCKET_IN_PROGRES || result == PAL_ERR_SOCKET_WOULD_BLOCK); @@ -1768,7 +1793,7 @@ PAL_PRIVATE void echo_test(bool tcp) } else { - result = pal_sendTo(g_testSockets[0], message, strlen(message), &address, 16, &sent); + result = pal_sendTo(g_testSockets[0], message, strlen(message), &address, addrlen, &sent); } pal_osSemaphoreWait(s_semaphoreID3, 1000, &temp); } while (PAL_ERR_SOCKET_WOULD_BLOCK == result); diff --git a/mbed-client-pal/Test/PAL_Modules/SOTP/pal_SOTP_test.c b/mbed-client-pal/Test/PAL_Modules/SOTP/pal_SOTP_test.c index c8fe2feef..d003554ee 100644 --- a/mbed-client-pal/Test/PAL_Modules/SOTP/pal_SOTP_test.c +++ b/mbed-client-pal/Test/PAL_Modules/SOTP/pal_SOTP_test.c @@ -15,7 +15,7 @@ *******************************************************************************/ #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "unity.h" #include "unity_fixture.h" #include "test_runners.h" diff --git a/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test.c b/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test.c index 0b467e7cb..3b7bd23c0 100644 --- a/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test.c +++ b/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test.c @@ -18,7 +18,7 @@ #include "unity.h" #include "unity_fixture.h" #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "pal_tls_utils.h" #include "storage_kcm.h" #include "test_runners.h" @@ -62,17 +62,19 @@ PAL_PRIVATE palSocket_t g_socket = 0; extern void * g_palTestTLSInterfaceCTX; // this is set by the palTestMain funciton PAL_PRIVATE uint32_t g_interfaceCTXIndex = 0; -#if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1)) +#if (PAL_USE_INTERNAL_FLASH == 1) PAL_PRIVATE uint8_t g_trustedServerID[PAL_CERT_ID_SIZE] __attribute__((aligned(4))) = { 0 }; PAL_PRIVATE size_t g_actualServerIDSize = 0; #endif +#if ((PAL_USE_SECURE_TIME == 1) && (PAL_ENABLE_X509 == 1)) PAL_PRIVATE palMutexID_t g_mutex1 = NULLPTR; #if (PAL_ENABLE_X509 == 1) PAL_PRIVATE palMutexID_t g_mutex2 = NULLPTR; #endif PAL_PRIVATE palMutexID_t g_mutexHandShake1 = NULLPTR; PAL_PRIVATE bool g_retryHandshake = false; +#endif #define PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(a, b) \ if (a != b) \ @@ -81,18 +83,48 @@ PAL_PRIVATE bool g_retryHandshake = false; goto finish;\ } -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) static palSemaphoreID_t s_asyncDnsSemaphore = NULLPTR; // callback invoked from the call to pal_getAddressInfoAsync +#if (PAL_DNS_API_VERSION == 2) + PAL_PRIVATE void getAddressInfoAsyncCallback(const char* url, palSocketAddress_t* address, palStatus_t status, void* callbackArgument) { +#else // (PAL_DNS_API_VERSION == 3) +static palAddressInfo_t *global_addrInfo = NULLPTR; +static palDNSQuery_t dns_query_t = 0; +PAL_PRIVATE void getAddressInfoAsyncCallback(const char* url, palAddressInfo_t *addrInfo, palStatus_t status, void* callbackArgument) +{ + global_addrInfo = addrInfo; +#endif TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); pal_osSemaphoreRelease(s_asyncDnsSemaphore); } #endif +#if !(PAL_USE_SECURE_TIME) +// If testing without PAL secure time, some tests require faking the time to mbedtls to get desired effect +// from certificate verification +#include "mbedtls/ssl.h" +#include "mbedtls/platform.h" +static mbedtls_time_t time_to_return; +static mbedtls_time_t definately_in_future = 1935316090; // Wednesday, April 30, 2031 11:48:10 AM +static int return_fake_time = 0; +mbedtls_time_t pal_mbedtlsTimeCB(mbedtls_time_t* timer) +{ + if(return_fake_time) { + return time_to_return++; + } + else { + // this is what mbedtls calls by default if mbedtls_platform_set_time was not called + return MBEDTLS_PLATFORM_STD_TIME(timer); + } +} +#endif + + PAL_PRIVATE palStatus_t doDnsQuery(const char* hostname, palSocketAddress_t *address, palSocketLength_t *addrlen) { palStatus_t result = PAL_SUCCESS; @@ -106,6 +138,20 @@ PAL_PRIVATE palStatus_t doDnsQuery(const char* hostname, palSocketAddress_t *add NULL); result = pal_osSemaphoreWait(s_asyncDnsSemaphore, 5000, NULL); +#elif (PAL_DNS_API_VERSION == 3) + result = pal_osSemaphoreCreate(0, &s_asyncDnsSemaphore); + TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); + result = pal_getAddressInfoAsync(hostname, + &getAddressInfoAsyncCallback, + NULL, + &dns_query_t); + result = pal_osSemaphoreWait(s_asyncDnsSemaphore, 5000, NULL); + result = pal_free_addressinfoAsync(dns_query_t); + result = pal_getDNSAddress(global_addrInfo, 0, address); + *addrlen = sizeof(palSocketAddress_t); + pal_freeAddrInfo(global_addrInfo); + global_addrInfo = NULLPTR; + dns_query_t = 0; #else result = pal_getAddressInfo(hostname, address, addrlen); #endif @@ -123,6 +169,7 @@ PAL_PRIVATE void socketCallback1( void * arg) } static void setCredentials(palTLSConfHandle_t handle); +static void setCredentialsWrongCA(palTLSConfHandle_t handle); static void do_handshake(palTLSTransportMode_t mode, bool enable_session_storing); //! This structre is for tests only and MUST be the same structure as in the pal_TLS.c file @@ -193,10 +240,16 @@ TEST_SETUP(pal_tls) status = pal_osSetTime(currentTime); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); +#if !(PAL_USE_SECURE_TIME) + mbedtls_platform_set_time(pal_mbedtlsTimeCB); +#endif } TEST_TEAR_DOWN(pal_tls) { +#if !(PAL_USE_SECURE_TIME) + return_fake_time = 0; +#endif if (0 != g_socket) { pal_close(&g_socket); @@ -449,8 +502,8 @@ TEST(pal_tls, tlsCACertandPSK) * * | # | Step | Expected | * |---|--------------------------------|-------------| -* | 1 | Create a TCP socket. | PAL_SUCCESS | -* | 2 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 1 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 2 | Create a TCP socket. | PAL_SUCCESS | * | 3 | Set the server port. | PAL_SUCCESS | * | 4 | Connect the TCP socket to the server. | PAL_SUCCESS | * | 5 | Initialize the TLS configuration using `pal_initTLSConfiguration`. | PAL_SUCCESS | @@ -490,10 +543,6 @@ TEST(pal_tls, tlsHandshakeTCP) struct server_address server; /*#1*/ - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - - /*#2*/ parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); status = doDnsQuery(server.hostname, &socketAddr, &addressLength); @@ -504,6 +553,10 @@ TEST(pal_tls, tlsHandshakeTCP) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#2*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + tlsSocket.addressLength = addressLength; tlsSocket.socket = g_socket; @@ -559,7 +612,7 @@ TEST(pal_tls, tlsHandshakeTCP) curTimeInSec = pal_osGetTime(); TEST_ASSERT_TRUE(curTimeInSec >= minSecSinceEpoch); timePassedInSec = curTimeInSec - minSecSinceEpoch; - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while ((PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status) && @@ -617,8 +670,8 @@ TEST(pal_tls, tlsHandshakeTCP) * * | # | Step | Expected | * |---|--------------------------------|-------------| -* | 1 | Create a UDP socket. | PAL_SUCCESS | -* | 2 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 1 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 2 | Create a UDP socket. | PAL_SUCCESS | * | 3 | Set the server port. | PAL_SUCCESS | * | 4 | Initialize the TLS configuration using `pal_initTLSConfiguration`. | PAL_SUCCESS | * | 5 | Initialize the TLS context using `pal_initTLS`. | PAL_SUCCESS | @@ -654,16 +707,12 @@ TEST(pal_tls, tlsHandshakeUDP) palTLSSocket_t tlsSocket = {g_socket, &socketAddr, 0, transportationMode}; int32_t verifyResult = 0; struct server_address server; - - /*#1*/ int32_t temp; - status = pal_osSemaphoreCreate(1, &s_semaphoreID); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_DGRAM, true, 0, socketCallback1, &g_socket); + status = pal_osSemaphoreCreate(1, &s_semaphoreID); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - /*#2*/ + /*#1*/ parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); status = doDnsQuery(server.hostname, &socketAddr, &addressLength); @@ -673,6 +722,10 @@ TEST(pal_tls, tlsHandshakeUDP) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#2*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_DGRAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + tlsSocket.addressLength = addressLength; tlsSocket.socket = g_socket; @@ -711,7 +764,7 @@ TEST(pal_tls, tlsHandshakeUDP) /*#9*/ do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); @@ -763,8 +816,8 @@ TEST(pal_tls, tlsHandshakeUDP) * * | # | Step | Expected | * |---|--------------------------------|-------------| -* | 1 | Create a UDP socket. | PAL_SUCCESS | -* | 2 | Perform a DNS lookup on server adderss. | PAL_SUCCESS | +* | 1 | Perform a DNS lookup on server adderss. | PAL_SUCCESS | +* | 2 | Create a UDP socket. | PAL_SUCCESS | * | 3 | Set the server port. | PAL_SUCCESS | * | 4 | Initialize the TLS configuration using `pal_initTLSConfiguration`. | PAL_SUCCESS | * | 5 | Initialize the TLS context using `pal_initTLS`. | PAL_SUCCESS | @@ -792,19 +845,14 @@ TEST(pal_tls, tlsHandshakeUDPTimeOut) #endif palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode }; struct server_address server; - + int32_t temp; uint64_t curTimeInSec; const uint64_t minSecSinceEpoch = PAL_MIN_SEC_FROM_EPOCH + 1; //At least 47 years passed from 1.1.1970 in seconds - /*#1*/ - int32_t temp; status = pal_osSemaphoreCreate(1, &s_semaphoreID); TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, status); - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_DGRAM, true, 0, socketCallback1, &g_socket); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - - /*#2*/ + /*#1*/ parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); status = doDnsQuery(server.hostname, &socketAddr, &addressLength); if (PAL_SUCCESS != status) @@ -813,6 +861,10 @@ TEST(pal_tls, tlsHandshakeUDPTimeOut) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#2*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_DGRAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + tlsSocket.addressLength = addressLength; tlsSocket.socket = g_socket; @@ -854,7 +906,7 @@ TEST(pal_tls, tlsHandshakeUDPTimeOut) /*#9*/ do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); @@ -885,8 +937,8 @@ TEST(pal_tls, tlsHandshakeUDPTimeOut) * * | # | Step | Expected | * |---|--------------------------------|-------------| -* | 1 | Create a TCP socket. | PAL_SUCCESS | -* | 2 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 1 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 2 | Create a TCP socket. | PAL_SUCCESS | * | 3 | Set the server port. | PAL_SUCCESS | * | 4 | Connect the TCP socket to the server. | PAL_SUCCESS | * | 5 | Initialize the TLS configuration using `pal_initTLSConfiguration`. | PAL_SUCCESS | @@ -927,16 +979,12 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M) uint64_t initialTime = 0; int32_t verifyResult = 0; struct server_address server; - int32_t temp; + status = pal_osSemaphoreCreate(1, &s_semaphoreID); TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, status); /*#1*/ - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - - /*#2*/ parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); status = doDnsQuery(server.hostname, &socketAddr, &addressLength); if (PAL_SUCCESS != status) @@ -945,6 +993,10 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#2*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + tlsSocket.addressLength = addressLength; tlsSocket.socket = g_socket; @@ -987,7 +1039,7 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M) /*#10*/ do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); @@ -1064,8 +1116,8 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M) * |---|--------------------------------|-------------| * | 1 | Get saved time from storage, move backward half day and set time to RAM | PAL_SUCCESS | * | 2 | Update `STORAGE_RBP_SAVED_TIME_NAME` directly in storage to the new time from #1 | PAL_SUCCESS | -* | 3 | Create a TCP socket. | PAL_SUCCESS | -* | 4 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 3 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 4 | Create a TCP socket. | PAL_SUCCESS | * | 5 | Set the server port. | PAL_SUCCESS | * | 6 | Connect the TCP socket to the server. | PAL_SUCCESS | * | 7 | Initialize the TLS configuration using `pal_initTLSConfiguration`. | PAL_SUCCESS | @@ -1125,10 +1177,6 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M_NoTimeUpdate) TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); /*#3*/ - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - - /*#4*/ status = doDnsQuery(server.hostname, &socketAddr, &addressLength); if (PAL_SUCCESS != status) { @@ -1136,6 +1184,10 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M_NoTimeUpdate) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#4*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#5*/ status = pal_setSockAddrPort(&socketAddr, server.port); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); @@ -1182,7 +1234,7 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M_NoTimeUpdate) /*#11*/ do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); @@ -1253,13 +1305,14 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M_NoTimeUpdate) /** -* @brief Test TLS handshake (TCP) with future time to make handshake to fail due to bad cert time from server. +* @brief Test TLS handshake (TCP) with future time to make handshake to fail when PAL_USE_SECURE_TIME is set +* and pass if unset, due to bad cert time from server. * * * | # | Step | Expected | * |---|--------------------------------|-------------| -* | 1 | Create a TCP socket. | PAL_SUCCESS | -* | 2 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 1 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 2 | Create a TCP socket. | PAL_SUCCESS | * | 3 | Set the server port. | PAL_SUCCESS | * | 4 | Connect the TCP socket to the server. | PAL_SUCCESS | * | 5 | Initialize the TLS configuration using `pal_initTLSConfiguration`. | PAL_SUCCESS | @@ -1267,7 +1320,7 @@ TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M_NoTimeUpdate) * | 7 | Set the certificate and keys. | PAL_SUCCESS | * | 8 | Set the socket chain to the configuration using `pal_tlsSetSocket`. | PAL_SUCCESS | * | 9 | Setsystem time to be far in the future `pal_osSetTime`. | PAL_SUCCESS | -* | 10 | Perform a TLS handshake with the server using `pal_handShake`. | PAL_ERR_X509_CERT_VERIFY_FAILED | +* | 10 | Perform a TLS handshake with the server using `pal_handShake`. | PAL_ERR_X509_CERT_VERIFY_FAILED OR PAL_SUCCESS | * | 11 | Verify the handshake result using `pal_sslGetVerifyResult`. | PAL_ERR_X509_BADCERT_EXPIRED | * | 12 | Set tme back to the original time before the test. | PAL_SUCCESS | * | 13 | Uninitialize the TLS context using `pal_freeTLS`. | PAL_SUCCESS | @@ -1279,7 +1332,7 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) #ifndef MBED_CONF_MBED_CLOUD_CLIENT_PSA_SUPPORT -#if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1)) +#if (PAL_USE_INTERNAL_FLASH) palStatus_t status = PAL_SUCCESS; palTLSConfHandle_t palTLSConf = NULLPTR; palTLSHandle_t palTLSHandle = NULLPTR; @@ -1287,9 +1340,11 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) palSocketAddress_t socketAddr = {0}; palSocketLength_t addressLength = 0; palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode }; +#if PAL_USE_SECURE_TIME uint64_t futureTime = 2145542642; //Wed, 27 Dec 2037 16:04:02 GMT uint64_t currentTime = 0; size_t actualSavedTimeSize = 0; +#endif int32_t verifyResult = 0; struct server_address server; @@ -1301,10 +1356,6 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) do_handshake(PAL_TLS_MODE, false); /*#1*/ - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - - /*#2*/ parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); status = doDnsQuery(server.hostname, &socketAddr, &addressLength); @@ -1314,6 +1365,10 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#2*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + tlsSocket.addressLength = addressLength; tlsSocket.socket = g_socket; @@ -1359,6 +1414,7 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) } /*#9*/ +#if PAL_USE_SECURE_TIME status = storage_rbp_read(STORAGE_RBP_SAVED_TIME_NAME, (uint8_t*)¤tTime, sizeof(currentTime), &actualSavedTimeSize); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); status = pal_osSetTime(futureTime); @@ -1368,15 +1424,21 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) pal_tlsConfigurationFree(&palTLSConf); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); } +#else + // Set time to future + return_fake_time = 1; + time_to_return = definately_in_future; +#endif /*#10*/ do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); +#if PAL_USE_SECURE_TIME if (PAL_ERR_X509_CERT_VERIFY_FAILED != status) { pal_osSetTime(currentTime); @@ -1384,20 +1446,32 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) pal_tlsConfigurationFree(&palTLSConf); TEST_ASSERT_EQUAL_HEX(PAL_ERR_X509_CERT_VERIFY_FAILED, status); } +#else + if (PAL_SUCCESS != status) + { + pal_freeTLS(&palTLSHandle); + pal_tlsConfigurationFree(&palTLSConf); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } +#endif /*#11*/ status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult); if ((PAL_ERR_X509_CERT_VERIFY_FAILED != status) || (0 == (PAL_ERR_X509_BADCERT_EXPIRED & verifyResult))) { +#if PAL_USE_SECURE_TIME pal_osSetTime(currentTime); +#endif pal_freeTLS(&palTLSHandle); pal_tlsConfigurationFree(&palTLSConf); TEST_ASSERT_TRUE(PAL_ERR_X509_BADCERT_EXPIRED & verifyResult); } +#if PAL_USE_SECURE_TIME /*#12*/ status = pal_osSetTime(currentTime); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); +#endif /*#13*/ status = pal_freeTLS(&palTLSHandle); @@ -1414,19 +1488,19 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) status = pal_close(&g_socket); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); +#if PAL_USE_SECURE_TIME /*#15*/ status = storage_rbp_read(STORAGE_RBP_SAVED_TIME_NAME, (uint8_t*)¤tTime, sizeof(currentTime), &actualSavedTimeSize); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); TEST_ASSERT_TRUE(futureTime > currentTime); +#endif #else - TEST_IGNORE_MESSAGE("Ignored, PAL_USE_SECURE_TIME or PAL_USE_INTERNAL_FLASH not set"); + TEST_IGNORE_MESSAGE("Ignored, PAL_USE_INTERNAL_FLASH not set"); #endif #else //MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT TEST_IGNORE_MESSAGE("Ignored, MBED_CONF_MBED_CLOUD_CLIENT_PSA_SUPPORT is defined"); #endif - - } /** @@ -1435,8 +1509,8 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert) * * | # | Step | Expected | * |---|--------------------------------|-------------| -* | 1 | Create a TCP socket. | PAL_SUCCESS | -* | 2 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 1 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 2 | Create a TCP socket. | PAL_SUCCESS | * | 3 | Set the server port. | PAL_SUCCESS | * | 4 | Parse the CA cert. | PAL_SUCCESS | * | 5 | Get the CA cert ID. | PAL_SUCCESS | @@ -1484,10 +1558,6 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredServerCert_Trusted) TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, status); /*#1*/ - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - - /*#2*/ parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); status = doDnsQuery(server.hostname, &socketAddr, &addressLength); if (PAL_SUCCESS != status) @@ -1496,6 +1566,10 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredServerCert_Trusted) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#1*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#3*/ status = pal_setSockAddrPort(&socketAddr, server.port); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); @@ -1587,7 +1661,7 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredServerCert_Trusted) /*#13*/ do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); @@ -1698,8 +1772,8 @@ TEST(pal_tls, tlsHandshakeTCP_ExpiredServerCert_Trusted) * | # | Step | Expected | * |---|--------------------------------|-------------| * | 1 | Get saved time from storage, move backward half day and set time to RAM | PAL_SUCCESS | -* | 2 | Create a TCP socket. | PAL_SUCCESS | -* | 3 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 2 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 3 | Create a TCP socket. | PAL_SUCCESS | * | 4 | Set the server port. | PAL_SUCCESS | * | 5 | Parse the CA cert. | PAL_SUCCESS | * | 6 | Get the CA cert ID. | PAL_SUCCESS | @@ -1757,10 +1831,6 @@ TEST(pal_tls, tlsHandshakeTCP_FutureTrustedServer_NoTimeUpdate) TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); /*#2*/ - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - - /*#3*/ parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); status = doDnsQuery(server.hostname, &socketAddr, &addressLength); if (PAL_SUCCESS != status) @@ -1769,6 +1839,10 @@ TEST(pal_tls, tlsHandshakeTCP_FutureTrustedServer_NoTimeUpdate) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#3*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#4*/ status = pal_setSockAddrPort(&socketAddr, server.port); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); @@ -1854,7 +1928,7 @@ TEST(pal_tls, tlsHandshakeTCP_FutureTrustedServer_NoTimeUpdate) /*#13*/ do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); @@ -1959,8 +2033,8 @@ TEST(pal_tls, tlsHandshakeTCP_FutureTrustedServer_NoTimeUpdate) * | # | Step | Expected | * |---|--------------------------------|-------------| * | 1 | Get saved time from storage, move forward half day and set time to RAM | PAL_SUCCESS | -* | 2 | Create a TCP socket. | PAL_SUCCESS | -* | 3 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 2 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 3 | Create a TCP socket. | PAL_SUCCESS | * | 4 | Set the server port. | PAL_SUCCESS | * | 5 | Parse the CA cert. | PAL_SUCCESS | * | 6 | Get the CA cert ID. | PAL_SUCCESS | @@ -2020,10 +2094,6 @@ TEST(pal_tls, tlsHandshakeTCP_NearPastTrustedServer_NoTimeUpdate) TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); /*#2*/ - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - - /*#3*/ status = doDnsQuery(server.hostname, &socketAddr, &addressLength); if (PAL_SUCCESS != status) { @@ -2031,6 +2101,10 @@ TEST(pal_tls, tlsHandshakeTCP_NearPastTrustedServer_NoTimeUpdate) } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#3*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + /*#4*/ status = pal_setSockAddrPort(&socketAddr, server.port); TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); @@ -2116,7 +2190,7 @@ TEST(pal_tls, tlsHandshakeTCP_NearPastTrustedServer_NoTimeUpdate) /*#13*/ do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); @@ -2229,16 +2303,6 @@ static void do_handshake(palTLSTransportMode_t mode, bool enable_session_storing palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode }; struct server_address server; - if (mode == PAL_TLS_MODE) - { - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); - } - else - { - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_DGRAM, true, 0, socketCallback1, &g_socket); - } - TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); - parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); status = doDnsQuery(server.hostname, &socketAddr, &addressLength); @@ -2249,6 +2313,16 @@ static void do_handshake(palTLSTransportMode_t mode, bool enable_session_storing } TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + if (mode == PAL_TLS_MODE) + { + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + } + else + { + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_DGRAM, true, 0, socketCallback1, &g_socket); + } + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + tlsSocket.addressLength = addressLength; tlsSocket.socket = g_socket; @@ -2298,7 +2372,7 @@ static void do_handshake(palTLSTransportMode_t mode, bool enable_session_storing do { - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); } while ((PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status)); @@ -2346,12 +2420,12 @@ static palStatus_t ThreadHandshakeTCP() mutexWait = true; /*#1*/ - status = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, socketCallback1, &socketTCP); + parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); + status = doDnsQuery(server.hostname, &socketAddr, &addressLength); PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status); /*#2*/ - parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); - status = doDnsQuery(server.hostname, &socketAddr, &addressLength); + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &socketTCP); PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status); tlsSocket.addressLength = addressLength; @@ -2409,7 +2483,7 @@ static palStatus_t ThreadHandshakeTCP() pal_osDelay(600); } } - status = pal_handShake(palTLSHandle, palTLSConf); + status = pal_handShake(palTLSHandle, palTLSConf, false); pal_osDelay(1000); } while ( (PAL_ERR_TLS_WANT_READ == status) || (PAL_ERR_TLS_WANT_WRITE == status)); @@ -2708,6 +2782,228 @@ TEST(pal_tls, tlsHandshake_SessionResume) } +/** +* @brief Test TLS handshake (TCP) to make sure client handles multiple error messages from certificate verification. +* +* +* | # | Step | Expected | +* |---|--------------------------------|-------------| +* | 1 | Perform a DNS lookup on the server address. | PAL_SUCCESS | +* | 2 | Create a TCP socket. | PAL_SUCCESS | +* | 3 | Set the server port. | PAL_SUCCESS | +* | 4 | Parse the CA cert. | PAL_SUCCESS | +* | 5 | Get the CA cert ID. | PAL_SUCCESS | +* | 6 | Set the CA cert ID into the storage. | PAL_SUCCESS | +* | 7 | Connect the TCP socket to the server. | PAL_SUCCESS | +* | 8 | Initialize the TLS configuration using `pal_initTLSConfiguration`. | PAL_SUCCESS | +* | 9 | Initialize the TLS context using `pal_initTLS`. | PAL_SUCCESS | +* | 10 | Set the certificate and keys. set CA cert so that it will not be valid. | PAL_SUCCESS | +* | 11 | Set the socket to the configuration using `pal_tlsSetSocket`. | PAL_SUCCESS | +* | 12 | Set system time to be far in the future `pal_osSetTime`. | PAL_SUCCESS | +* | 13 | Perform a TLS handshake with the server using `pal_handShake`. | PAL_ERR_X509_CERT_VERIFY_FAILED | +* | 14 | Uninitialize the TLS context using `pal_freeTLS`. | PAL_SUCCESS | +* | 15 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`. | PAL_SUCCESS | +* | 16 | Free X509 handle. | PAL_SUCCESS | +*/ +// this is copy-paste of palTLSService_t from pal_TLS.c. It's not meant to be used outside PAL but +// since this test needs to mimic malicious server returning a certificate which is wrong in two +// ways and also returning non-valid 'secure time' in the ServerHello message we need to modify +// it during the test. +typedef struct tls_ctx +{ + bool retryHandShake; + uint64_t serverTime; + uintptr_t platTlsHandle; +}tls_ctx_t; + +TEST(pal_tls, tlsHandshakeTCP_ExpiredServerCert_UnTrusted) +{ + +#ifndef MBED_CONF_MBED_CLOUD_CLIENT_PSA_SUPPORT + +#if (PAL_USE_INTERNAL_FLASH) + palStatus_t status = PAL_SUCCESS; + palTLSConfHandle_t palTLSConf = NULLPTR; + palTLSHandle_t palTLSHandle = NULLPTR; + palTLSTransportMode_t transportationMode = PAL_TLS_MODE; + palSocketAddress_t socketAddr = { 0 }; + palSocketLength_t addressLength = 0; + palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode }; + uint64_t futureTime = 2145542642; //Wed, 27 Dec 2037 16:04:02 GMT + uint64_t updatedTime = 0; + size_t actualSavedTimeSize = 0; + palX509Handle_t trustedServerCA = NULLPTR; + struct server_address server; + + int32_t temp; + status = pal_osSemaphoreCreate(1, &s_semaphoreID); + TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, status); + + /*#1*/ + parseServerAddress(&server, PAL_TLS_TEST_SERVER_ADDRESS); + status = doDnsQuery(server.hostname, &socketAddr, &addressLength); + if (PAL_SUCCESS != status) + { + PAL_LOG_ERR("DNS query error for %s", PAL_TLS_TEST_SERVER_ADDRESS); + } + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + + /*#2*/ + status = pal_asynchronousSocket(socketAddr.addressType, PAL_SOCK_STREAM, true, 0, socketCallback1, &g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + + /*#3*/ + status = pal_setSockAddrPort(&socketAddr, server.port); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + + tlsSocket.addressLength = addressLength; + tlsSocket.socket = g_socket; + + /*#4*/ + status = pal_x509Initiate(&trustedServerCA); + TEST_ASSERT_NOT_EQUAL(trustedServerCA, NULLPTR); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + + status = pal_x509CertParse(trustedServerCA, (const unsigned char *)PAL_TLS_TEST_DEVICE_CERTIFICATE, MAX_CERTIFICATE_SIZE); + if (PAL_SUCCESS != status) + { + pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#5*/ + status = pal_x509CertGetAttribute(trustedServerCA, PAL_X509_CERT_ID_ATTR, g_trustedServerID, sizeof(g_trustedServerID), &g_actualServerIDSize); + if (PAL_SUCCESS != status) + { + pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#6*/ + status = storage_rbp_write(STORAGE_RBP_TRUSTED_TIME_SRV_ID_NAME, (uint8_t*)g_trustedServerID, g_actualServerIDSize, false); + if (PAL_SUCCESS != status) + { + status = pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#7*/ + do { + status = pal_connect(g_socket, &socketAddr, addressLength); + pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); + } while (status == PAL_ERR_SOCKET_IN_PROGRES || status == PAL_ERR_SOCKET_WOULD_BLOCK); + + if (status == PAL_ERR_SOCKET_ALREADY_CONNECTED) { + status = PAL_SUCCESS; + } + + if (PAL_SUCCESS != status) + { + pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#8*/ + status = pal_initTLSConfiguration(&palTLSConf, transportationMode); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + + /*#9*/ + status = pal_initTLS(palTLSConf, &palTLSHandle, false); + if (PAL_SUCCESS != status) + { + pal_freeTLS(&palTLSHandle); + pal_tlsConfigurationFree(&palTLSConf); + pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#10*/ + setCredentialsWrongCA(palTLSConf); + + /*#11*/ + status = pal_tlsSetSocket(palTLSConf, &tlsSocket); + if (PAL_SUCCESS != status) + { + pal_freeTLS(&palTLSHandle); + pal_tlsConfigurationFree(&palTLSConf); + pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#12*/ + status = pal_osSetStrongTime(futureTime); + if (PAL_SUCCESS != status) + { + pal_freeTLS(&palTLSHandle); + pal_tlsConfigurationFree(&palTLSConf); + pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#13*/ + do + { + status = pal_handShake(palTLSHandle, palTLSConf, false); + tls_ctx_t* tls_ctx = (tls_ctx_t*)palTLSHandle; + if (tls_ctx->retryHandShake) { + // server should really fail before logic goes to renegotiation... + // ..but this hack ensures we get server's cert to appear from future + // if it happens to still continue there + tls_ctx->serverTime = 50; + } + pal_osSemaphoreWait(s_semaphoreID, 1000, &temp); + } + while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status); + + if (PAL_ERR_X509_CERT_VERIFY_FAILED != status) + { + pal_freeTLS(&palTLSHandle); + pal_tlsConfigurationFree(&palTLSConf); + pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_ERR_X509_CERT_VERIFY_FAILED, status); + } + + /*#14*/ + status = pal_freeTLS(&palTLSHandle); + if (PAL_SUCCESS != status) + { + pal_x509Free(&trustedServerCA); + pal_tlsConfigurationFree(&palTLSConf); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#15*/ + status = pal_tlsConfigurationFree(&palTLSConf); + if (PAL_SUCCESS != status) + { + pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + } + + /*#16*/ + status = pal_x509Free(&trustedServerCA); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + + status = pal_close(&g_socket); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + + status = storage_rbp_read(STORAGE_RBP_SAVED_TIME_NAME, (uint8_t*)&updatedTime, sizeof(updatedTime), &actualSavedTimeSize); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + TEST_ASSERT_TRUE(updatedTime <= futureTime); + + status = storage_rbp_read(STORAGE_RBP_LAST_TIME_BACK_NAME, (uint8_t*)&updatedTime, sizeof(updatedTime), &actualSavedTimeSize); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + TEST_ASSERT_TRUE(updatedTime <= futureTime); +#else + TEST_IGNORE_MESSAGE("Ignored, PAL_USE_INTERNAL_FLASH not set"); +#endif + +#else //MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT + TEST_IGNORE_MESSAGE("Ignored, MBED_CONF_MBED_CLOUD_CLIENT_PSA_SUPPORT is defined"); +#endif + +} + static void setCredentials(palTLSConfHandle_t handle) { palX509_t pubKey = {(const void*)PAL_TLS_TEST_DEVICE_CERTIFICATE, MAX_CERTIFICATE_SIZE}; @@ -2726,6 +3022,24 @@ static void setCredentials(palTLSConfHandle_t handle) TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); } +static void setCredentialsWrongCA(palTLSConfHandle_t handle) +{ + palX509_t pubKey = {(const void*)PAL_TLS_TEST_DEVICE_CERTIFICATE, MAX_CERTIFICATE_SIZE}; + palX509_t caCert = { (const void*)PAL_TLS_TEST_DEVICE_CERTIFICATE, MAX_CERTIFICATE_SIZE }; + + palStatus_t status; + palPrivateKey_t prvKey; + status = pal_initPrivateKey((const void*)PAL_TLS_TEST_DEVICE_PRIVATE_KEY, MAX_CERTIFICATE_SIZE, &prvKey); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + + status = pal_setOwnCertChain(handle, &pubKey); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + status = pal_setOwnPrivateKey(handle, &prvKey); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); + status = pal_setCAChain(handle, &caCert, NULL); + TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); +} + #if (PAL_USE_SSL_SESSION_RESUME == 1) static bool isSslSessionAvailable() { diff --git a/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test_runner.c b/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test_runner.c index ad6d49c7b..84e8498cb 100644 --- a/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test_runner.c +++ b/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test_runner.c @@ -37,5 +37,6 @@ TEST_GROUP_RUNNER(pal_tls) RUN_TEST_CASE(pal_tls, TCPHandshakeWhileCertVerify_threads); RUN_TEST_CASE(pal_tls, tlsHandshakeUDP); RUN_TEST_CASE(pal_tls, tlsHandshake_SessionResume); + RUN_TEST_CASE(pal_tls, tlsHandshakeTCP_ExpiredServerCert_UnTrusted); #endif } diff --git a/mbed-client/mbed-client-c/nsdl-c/sn_nsdl_lib.h b/mbed-client/mbed-client-c/nsdl-c/sn_nsdl_lib.h index df615358d..9f8af8116 100755 --- a/mbed-client/mbed-client-c/nsdl-c/sn_nsdl_lib.h +++ b/mbed-client/mbed-client-c/nsdl-c/sn_nsdl_lib.h @@ -343,7 +343,7 @@ extern int32_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint extern char *sn_nsdl_get_version(void); /** - * \fn extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src) + * \fn extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *src_ptr) * * \brief To push CoAP packet to mbed Device C Client library * @@ -361,9 +361,9 @@ extern char *sn_nsdl_get_version(void); * the destination address of the response packet. * * \return 0 Success - * \return -1 Failure + * \return < 0 Failure */ -extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src); +extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *src_ptr); /** * \fn extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time); @@ -494,7 +494,7 @@ extern int32_t sn_nsdl_send_request(struct nsdl_s *handle, * * \param *handle Pointer to nsdl-library handle * \return 0 Success - * \return -1 Failed to indicate that internal address pointer is not allocated (call nsdl_init() first). + * \return < 0 Failed to indicate that internal address pointer is not allocated (call nsdl_init() first). */ extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint8_t address_length, uint16_t port, sn_nsdl_addr_type_e address_type); diff --git a/mbed-client/mbed-client-c/source/sn_grs.c b/mbed-client/mbed-client-c/source/sn_grs.c index 24d3d4e32..105f48666 100755 --- a/mbed-client/mbed-client-c/source/sn_grs.c +++ b/mbed-client/mbed-client-c/source/sn_grs.c @@ -271,19 +271,21 @@ extern int8_t sn_grs_process_coap(struct nsdl_s *nsdl_handle, sn_coap_hdr_s *coa return sn_grs_core_request(nsdl_handle, src_addr_ptr, coap_packet_ptr); } - /* Get resource */ - char* path = nsdl_handle->grs->sn_grs_alloc(coap_packet_ptr->uri_path_len + 1); - if (!path) { - return SN_NSDL_FAILURE; - } + if (coap_packet_ptr->uri_path_len > 0) { + /* Get resource */ + char* path = nsdl_handle->grs->sn_grs_alloc(coap_packet_ptr->uri_path_len + 1); + if (!path) { + return SN_NSDL_FAILURE; + } - memcpy(path, - coap_packet_ptr->uri_path_ptr, - coap_packet_ptr->uri_path_len); - path[coap_packet_ptr->uri_path_len] = '\0'; + memcpy(path, + coap_packet_ptr->uri_path_ptr, + coap_packet_ptr->uri_path_len); + path[coap_packet_ptr->uri_path_len] = '\0'; - resource_temp_ptr = sn_grs_search_resource(handle, path, SN_GRS_SEARCH_METHOD); - nsdl_handle->grs->sn_grs_free(path); + resource_temp_ptr = sn_grs_search_resource(handle, path, SN_GRS_SEARCH_METHOD); + nsdl_handle->grs->sn_grs_free(path); + } /* * * * * * * * * * * */ /* If resource exists */ diff --git a/mbed-client/mbed-client-c/source/sn_nsdl.c b/mbed-client/mbed-client-c/source/sn_nsdl.c index b35b35b9d..57c0210b6 100755 --- a/mbed-client/mbed-client-c/source/sn_nsdl.c +++ b/mbed-client/mbed-client-c/source/sn_nsdl.c @@ -262,6 +262,9 @@ int32_t sn_nsdl_register_endpoint(struct nsdl_s *handle, register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST; + /* Register message content format must be Core Link Format as stated in OMA LwM2M */ + register_message_ptr->content_format = COAP_CT_LINK_FORMAT; + /* Allocate memory for the extended options list */ if (sn_coap_parser_alloc_options(handle->grs->coap, register_message_ptr) == NULL) { sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); @@ -283,11 +286,12 @@ int32_t sn_nsdl_register_endpoint(struct nsdl_s *handle, if (endpoint_info_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) { /* Built body for message */ - if (sn_nsdl_build_registration_body(handle, register_message_ptr, 0) == SN_NSDL_FAILURE) { + int ret = sn_nsdl_build_registration_body(handle, register_message_ptr, 0); + if (ret != SN_NSDL_SUCCESS) { register_message_ptr->uri_path_ptr = NULL; register_message_ptr->options_list_ptr->uri_host_ptr = NULL; sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - return SN_NSDL_FAILURE; + return ret; } } @@ -458,6 +462,9 @@ int32_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST; + /* Register update message content format must be same as register messages content format which is Core Link Format */ + register_message_ptr->content_format = COAP_CT_LINK_FORMAT; + if (handle->ep_information_ptr->location_ptr) { register_message_ptr->uri_path_len = handle->ep_information_ptr->location_len; /* = Only location set by Device Server*/ @@ -507,9 +514,10 @@ int32_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint /* Build payload */ if (handle->ep_information_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) { - if (sn_nsdl_build_registration_body(handle, register_message_ptr, 1) == SN_NSDL_FAILURE) { + int8_t ret = sn_nsdl_build_registration_body(handle, register_message_ptr, 1); + if (ret != SN_NSDL_SUCCESS) { sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - return SN_NSDL_MEMORY_ALLOCATION_FAILED; + return ret; } } @@ -651,12 +659,13 @@ int32_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, return SN_NSDL_FAILURE; } - if (set_NSP_address(handle, - bootstrap_address_ptr->addr_ptr, - bootstrap_address_ptr->addr_len, - bootstrap_address_ptr->port, - bootstrap_address_ptr->type) == SN_NSDL_FAILURE) { - return SN_NSDL_FAILURE; + int8_t ret = set_NSP_address(handle, + bootstrap_address_ptr->addr_ptr, + bootstrap_address_ptr->addr_len, + bootstrap_address_ptr->port, + bootstrap_address_ptr->type); + if (ret != SN_NSDL_SUCCESS) { + return ret; } handle->is_bs_server = true; @@ -737,24 +746,15 @@ char *sn_nsdl_get_version(void) #endif } -int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet_ptr, uint16_t packet_len, sn_nsdl_addr_s *src_ptr) +int8_t sn_nsdl_process_coap(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *src_ptr) { - sn_coap_hdr_s *coap_packet_ptr = NULL; sn_coap_hdr_s *coap_response_ptr = NULL; sn_nsdl_dynamic_resource_parameters_s *resource = NULL; - /* Check parameters */ - if (handle == NULL) { - return SN_NSDL_FAILURE; - } - /* Parse CoAP packet */ - coap_packet_ptr = sn_coap_protocol_parse(handle->grs->coap, src_ptr, packet_len, packet_ptr, (void *)handle); - - /* Check if parsing was successfull */ - if (coap_packet_ptr == (sn_coap_hdr_s *)NULL) { + /* Check parameters */ + if (handle == NULL || coap_packet_ptr == NULL) { return SN_NSDL_FAILURE; } - sn_nsdl_print_coap_data(coap_packet_ptr, false); #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_DUPLICATED_MSG) { @@ -989,7 +989,7 @@ static char *sn_nsdl_build_resource_attribute_str(char *dst, const sn_nsdl_attri * \param *handle Pointer to nsdl-library handle * \param *message_ptr Pointer to CoAP message header * - * \return SN_NSDL_SUCCESS = 0, Failed = -1 + * \return SN_NSDL_SUCCESS = 0, Failed < 0 */ int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration) { @@ -1687,8 +1687,9 @@ static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *co handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_IS_REGISTERED; sn_grs_mark_resources_as_registered(handle); is_reg_msg = true; - if (sn_nsdl_resolve_ep_information(handle, coap_packet_ptr) != SN_NSDL_SUCCESS) { - return SN_NSDL_FAILURE; + int8_t ret = sn_nsdl_resolve_ep_information(handle, coap_packet_ptr); + if (ret != SN_NSDL_SUCCESS) { + return ret; } } @@ -1762,7 +1763,7 @@ static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *co * \param *handle Pointer to nsdl-library handle * \param *coap_packet_ptr Pointer to received CoAP message * - * \return SN_NSDL_SUCCESS = 0, Failed = -1 + * \return SN_NSDL_SUCCESS = 0, Failed < 0 */ static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr) { diff --git a/mbed-client/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h b/mbed-client/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h index aa0a2361d..d8c92f9f2 100644 --- a/mbed-client/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h +++ b/mbed-client/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h @@ -24,16 +24,16 @@ #include "mbed-client/m2minterface.h" #include "mbed-client/m2mconnectionobserver.h" #include "mbed-client/m2mconnectionsecurity.h" +#include "mbed-client/m2mconnectionhandler.h" #include "nsdl-c/sn_nsdl.h" #include "pal.h" -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) #include "mbed-client/m2mtimerobserver.h" #endif class M2MConnectionSecurity; -class M2MConnectionHandler; class M2MSecurity; -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) class M2MTimer; #endif @@ -43,7 +43,7 @@ class M2MTimer; */ -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) class M2MConnectionHandlerPimpl : public M2MTimerObserver { #else class M2MConnectionHandlerPimpl { @@ -51,13 +51,14 @@ class M2MConnectionHandlerPimpl { public: enum SocketEvent { - ESocketIdle = 0x00, - ESocketCallback = 0x02, - ESocketConnect = 0x04, - ESocketSend = 0x08, - ESocketDnsResolved = 0x10, - ESocketDnsError = 0x20, - ESocketClose = 0x40 + ESocketIdle = 0x00, + ESocketCallback = 0x02, + ESocketConnect = 0x04, + ESocketSend = 0x08, + ESocketDnsResolved = 0x10, + ESocketDnsError = 0x20, + ESocketAlreadyConnected = 0x40, + ESocketClose = 0x80 }; // NOTE! Check that these values does not overlap with the SocketEvent values @@ -69,15 +70,15 @@ class M2MConnectionHandlerPimpl { /** * @brief Constructor */ - M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer, - M2MConnectionSecurity* sec, + M2MConnectionHandlerPimpl(M2MConnectionHandler *base, M2MConnectionObserver &observer, + M2MConnectionSecurity *sec, M2MInterface::BindingMode mode, M2MInterface::NetworkStack /*stack*/); /** * @brief Destructor */ - ~M2MConnectionHandlerPimpl(); + virtual ~M2MConnectionHandlerPimpl(); void start_timer(void); @@ -97,11 +98,11 @@ class M2MConnectionHandlerPimpl { * @param is_server_ping Defines whether the call is for Server ping or not. * @return true if address is valid else false. */ - bool resolve_server_address(const String& server_address, + bool resolve_server_address(const String &server_address, const uint16_t server_port, M2MConnectionObserver::ServerType server_type, - const M2MSecurity* security, - bool is_server_ping =false); + const M2MSecurity *security, + bool is_server_ping = false); /** * @brief Sends data, to the connected sent to server. @@ -187,6 +188,12 @@ class M2MConnectionHandlerPimpl { */ void unregister_network_handler(); + /** + * \brief Set socket priority. + * \return true if socket option was set correctly. + */ + bool set_socket_priority(M2MConnectionHandler::SocketPriority priority); + /** * \brief Stores CID persistently for DTLS connections. */ @@ -210,11 +217,18 @@ class M2MConnectionHandlerPimpl { */ void set_cid_value(const uint8_t *data_ptr, const size_t data_len); -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) /** * \brief stop _dns_fallback_timer */ void stop_dns_fallback_timer(); +#if (PAL_DNS_API_VERSION == 3) + /** + * \brief Set palAddressInfo_t. Used from callback address_resolver_cb. + * \param addrInfo pointer to palAddressInfo_t object + */ + void set_address_info(palAddressInfo_t *addrInfo); +#endif #endif private: @@ -267,7 +281,7 @@ class M2MConnectionHandlerPimpl { */ void initialize_event(arm_event_storage_t *event); -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) /** * \brief Indicates that the timer has expired. * \param type The type of the timer that has expired. @@ -295,13 +309,16 @@ class M2MConnectionHandlerPimpl { /** * @brief Get first item from the queue list. */ - send_data_queue_s* get_item_from_list(); + send_data_queue_s *get_item_from_list(); /** * @brief Add queue data back to list. */ - void add_item_to_list(send_data_queue_s* data); - + void add_item_to_list(send_data_queue_s *data); +#if (PAL_DNS_API_VERSION == 3) +private: + void free_address_info(); +#endif private: enum SocketState { @@ -358,7 +375,12 @@ class M2MConnectionHandlerPimpl { uint32_t _net_iface; #if (PAL_DNS_API_VERSION == 0) || (PAL_DNS_API_VERSION == 1) palSocketLength_t _socket_address_len; -#else +#elif (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) +#if (PAL_DNS_API_VERSION == 3) + uint16_t _current_address_info; + uint16_t _address_info_count; + palAddressInfo_t *_address_info; +#endif palDNSQuery_t _handler_async_DNS; M2MTimer *_dns_fallback_timer; #endif @@ -375,10 +397,10 @@ class M2MConnectionHandlerPimpl { bool _is_server_ping; arm_event_storage_t _event; arm_event_storage_t _socket_callback_event; -friend class Test_M2MConnectionHandlerPimpl; -friend class Test_M2MConnectionHandlerPimpl_mbed; -friend class Test_M2MConnectionHandlerPimpl_classic; -friend class M2MConnection_TestObserver; + friend class Test_M2MConnectionHandlerPimpl; + friend class Test_M2MConnectionHandlerPimpl_mbed; + friend class Test_M2MConnectionHandlerPimpl_classic; + friend class M2MConnection_TestObserver; }; #endif //M2M_CONNECTION_HANDLER_PIMPL_H__ diff --git a/mbed-client/mbed-client-classic/source/m2mconnectionhandler.cpp b/mbed-client/mbed-client-classic/source/m2mconnectionhandler.cpp index 44dbcfa05..fa1664046 100644 --- a/mbed-client/mbed-client-classic/source/m2mconnectionhandler.cpp +++ b/mbed-client/mbed-client-classic/source/m2mconnectionhandler.cpp @@ -19,10 +19,10 @@ #include "mbed-client/m2mconstants.h" M2MConnectionHandler::M2MConnectionHandler(M2MConnectionObserver &observer, - M2MConnectionSecurity* sec, + M2MConnectionSecurity *sec, M2MInterface::BindingMode mode, M2MInterface::NetworkStack stack) -:_observer(observer) + : _observer(observer) { _private_impl = new M2MConnectionHandlerPimpl(this, observer, sec, mode, stack); } @@ -38,11 +38,11 @@ bool M2MConnectionHandler::bind_connection(const uint16_t listen_port) return _private_impl->bind_connection(listen_port); } -bool M2MConnectionHandler::resolve_server_address(const String& server_address, - const uint16_t server_port, - M2MConnectionObserver::ServerType server_type, - const M2MSecurity* security, - bool is_server_ping) +bool M2MConnectionHandler::resolve_server_address(const String &server_address, + const uint16_t server_port, + M2MConnectionObserver::ServerType server_type, + const M2MSecurity *security, + bool is_server_ping) { return _private_impl->resolve_server_address(server_address, server_port, server_type, security, is_server_ping); @@ -114,3 +114,8 @@ void M2MConnectionHandler::set_cid_value(const uint8_t *data_ptr, const size_t d { _private_impl->set_cid_value(data_ptr, data_len); } + +bool M2MConnectionHandler::set_socket_priority(M2MConnectionHandler::SocketPriority priority) +{ + return _private_impl->set_socket_priority(priority); +} diff --git a/mbed-client/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp b/mbed-client/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp index 2037e5315..7b5eb4258 100644 --- a/mbed-client/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp +++ b/mbed-client/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp @@ -23,7 +23,7 @@ #include "mbed-client/m2mconstants.h" #include "mbed-client/m2msecurity.h" #include "mbed-client/m2mconnectionhandler.h" -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) #include "mbed-client/m2mtimer.h" #endif #include "pal.h" @@ -38,7 +38,7 @@ #error "For async PAL DNS only API v2 or greater is supported on Mbed." #endif -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) #define DNS_FALLBACK_TIMEOUT 600000 #endif @@ -127,6 +127,10 @@ void M2MConnectionHandlerPimpl::event_handler(arm_event_s *event) socket_connect_handler(); break; + case M2MConnectionHandlerPimpl::ESocketAlreadyConnected: + socket_connect_handler(); + break; + case M2MConnectionHandlerPimpl::ESocketClose: close_socket(); break; @@ -168,7 +172,12 @@ M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler *base, _net_iface(0), #if (PAL_DNS_API_VERSION == 0) || (PAL_DNS_API_VERSION == 1) _socket_address_len(0), -#elif (PAL_DNS_API_VERSION == 2) +#elif (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) +#if (PAL_DNS_API_VERSION == 3) + _current_address_info(0), + _address_info_count(0), + _address_info(0), +#endif _handler_async_DNS(0), #endif _socket_state(ESocketStateDisconnected), @@ -181,7 +190,7 @@ M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler *base, return; } #endif -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) _dns_fallback_timer = new M2MTimer(*this); #endif if (PAL_SUCCESS != pal_init()) { @@ -189,6 +198,7 @@ M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler *base, } memset(&_address, 0, sizeof _address); + _address._stack = stack; memset((void *)&_socket_address, 0, sizeof _socket_address); memset(&_ipV4Addr, 0, sizeof(palIpV4Addr_t)); memset(&_ipV6Addr, 0, sizeof(palIpV6Addr_t)); @@ -207,13 +217,16 @@ M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler *base, M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl() { tr_debug("~M2MConnectionHandlerPimpl()"); -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) if (_handler_async_DNS > 0) { pal_cancelAddressInfoAsync(_handler_async_DNS); } delete _dns_fallback_timer; #endif +#if (PAL_DNS_API_VERSION == 3) + free_address_info(); +#endif close_socket(); delete _security_impl; _security_impl = NULL; @@ -251,12 +264,19 @@ void M2MConnectionHandlerPimpl::send_event(SocketEvent event_type) } // This callback is used from PAL pal_getAddressInfoAsync, +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) #if (PAL_DNS_API_VERSION == 2) extern "C" void address_resolver_cb(const char *url, palSocketAddress_t *address, palStatus_t status, void *callbackArgument) +#elif (PAL_DNS_API_VERSION == 3) +extern "C" void address_resolver_cb(const char *url, palAddressInfo_t *addrInfo, palStatus_t status, void *callbackArgument) +#endif { tr_debug("M2MConnectionHandlerPimpl::address_resolver callback"); M2MConnectionHandlerPimpl *instance = (M2MConnectionHandlerPimpl *)callbackArgument; instance->stop_dns_fallback_timer(); +#if (PAL_DNS_API_VERSION == 3) + instance->set_address_info(addrInfo); +#endif if (PAL_SUCCESS != status) { tr_error("M2MConnectionHandlerPimpl::address_resolver callback failed with %" PRIx32, status); instance->send_event(M2MConnectionHandlerPimpl::ESocketDnsError); @@ -266,27 +286,60 @@ extern "C" void address_resolver_cb(const char *url, palSocketAddress_t *address } #endif +#if (PAL_DNS_API_VERSION == 3) +void M2MConnectionHandlerPimpl::set_address_info(palAddressInfo_t *addrInfo) +{ + _address_info = addrInfo; + _address_info_count = pal_getDNSCount(_address_info); + tr_debug("Found %d dns addresses", _address_info_count); +} + +void M2MConnectionHandlerPimpl::free_address_info() +{ + _current_address_info = 0; + _address_info_count = 0; + pal_freeAddrInfo(_address_info); + _address_info = NULL; +} +#endif + bool M2MConnectionHandlerPimpl::address_resolver(void) { palStatus_t status; bool ret = false; +#if (PAL_DNS_API_VERSION == 3) + if (_current_address_info < _address_info_count) { + send_event(ESocketDnsResolved); + return true; + } + // start new dns query, reset current address info + free_address_info(); +#endif -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) tr_debug("M2MConnectionHandlerPimpl::address_resolver:asynchronous DNS"); _handler_async_DNS = 0; tr_debug("M2MConnectionHandlerPimpl::address_resolver start _dns_fallback_timer"); _dns_fallback_timer->stop_timer(); _dns_fallback_timer->start_timer(DNS_FALLBACK_TIMEOUT, M2MTimerObserver::DnsQueryFallback, true); +#if (PAL_DNS_API_VERSION == 2) status = pal_getAddressInfoAsync(_server_address.c_str(), (palSocketAddress_t *)&_socket_address, &address_resolver_cb, this, &_handler_async_DNS); +#elif (PAL_DNS_API_VERSION == 3) + status = pal_getAddressInfoAsync(_server_address.c_str(), &address_resolver_cb, this, &_handler_async_DNS); +#endif if (PAL_SUCCESS != status) { _dns_fallback_timer->stop_timer(); tr_error("M2MConnectionHandlerPimpl::address_resolver, pal_getAddressInfoAsync fail. %" PRIx32, status); +#if (PAL_DNS_API_VERSION == 3) + free_address_info(); +#endif _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR); } else { ret = true; } #else // #if (PAL_DNS_API_VERSION == 0) tr_debug("M2MConnectionHandlerPimpl::address_resolver:synchronous DNS"); + status = pal_getAddressInfo(_server_address.c_str(), (palSocketAddress_t *)&_socket_address, &_socket_address_len); if (PAL_SUCCESS != status) { tr_error("M2MConnectionHandlerPimpl::getAddressInfo failed with %" PRIx32, status); @@ -302,7 +355,10 @@ bool M2MConnectionHandlerPimpl::address_resolver(void) void M2MConnectionHandlerPimpl::handle_dns_result(bool success) { -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) +#if (PAL_DNS_API_VERSION == 3) + pal_free_addressinfoAsync(_handler_async_DNS); +#endif _handler_async_DNS = 0; #endif if (_socket_state != ESocketStateDNSResolving) { @@ -315,6 +371,9 @@ void M2MConnectionHandlerPimpl::handle_dns_result(bool success) socket_connect_handler(); } else { +#if (PAL_DNS_API_VERSION == 3) + free_address_info(); +#endif _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR); } } @@ -325,13 +384,33 @@ bool M2MConnectionHandlerPimpl::resolve_server_address(const String &server_addr const M2MSecurity *security, bool is_server_ping) { -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) if (_handler_async_DNS > 0) { if (pal_cancelAddressInfoAsync(_handler_async_DNS) != PAL_SUCCESS) { return false; } } #endif + + // if we already have a secure connection set up for the server address (and LWM2MServer, not bootstrap) + // we should skip over the DNS query. In case of CID there might be situation that we have a valid CID for ip address x, now if we query + // dns again we might get ip address to y and COAP sending with the CID will fail. We will skip unnecessary dns query also if CID is not in use. + if ((_socket_state == ESocketStateSecureConnection) && + (server_type == M2MConnectionObserver::LWM2MServer) && (_server_address == server_address)) { + _is_server_ping = is_server_ping; + if (is_server_ping) { + // skip over dns query to handshake. This will reset tls and do a clean tls handshake + tr_debug("M2MConnectionHandlerPimpl::resolve_server_address (server ping), skip dns to handshake"); + _socket_state = ESocketStateDNSResolving; + send_event(ESocketDnsResolved); + } else { + // skip over dns query straight to COAP sending + tr_debug("M2MConnectionHandlerPimpl::resolve_server_address (), skip dns to COAP sending"); + send_event(M2MConnectionHandlerPimpl::ESocketAlreadyConnected); + } + return true; + } + _socket_state = ESocketStateDNSResolving; _security = security; @@ -349,12 +428,18 @@ bool M2MConnectionHandlerPimpl::resolve_server_address(const String &server_addr _secure_connection = false; } +#if (PAL_DNS_API_VERSION == 3) + if (!(server_address == _server_address)) { + // new address, must do dns query + free_address_info(); + tr_debug("M2MConnectionHandlerPimpl::resolve_server_address, new address, must do dns query."); + } +#endif _server_port = server_port; _server_type = server_type; _server_address = server_address; _is_server_ping = is_server_ping; - return address_resolver(); } @@ -374,7 +459,6 @@ void M2MConnectionHandlerPimpl::socket_connect_handler() case ESocketStateDisconnected: case ESocketStateHandshaking: case ESocketStateUnsecureConnection: - case ESocketStateSecureConnection: // Ignore these events break; @@ -382,13 +466,27 @@ void M2MConnectionHandlerPimpl::socket_connect_handler() // Initialize the socket to stable state close_socket(); - +#if (PAL_DNS_API_VERSION == 3) + if (_address_info) { + status = pal_getDNSAddress(_address_info, _current_address_info, (palSocketAddress_t *)&_socket_address); + _current_address_info++; + if (PAL_SUCCESS != status) { + tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - pal_getDNSAddress %" PRIx32, status); + _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR); + return; + } + tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - trying dns address %d of possible %d", _current_address_info, _address_info_count); + } else { + // current DNS should be ok, resources are free'd + tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - continue with current DNS"); + } +#endif status = pal_setSockAddrPort((palSocketAddress_t *)&_socket_address, _server_port); if (PAL_SUCCESS != status) { tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - setSockAddrPort err: %" PRIx32, status); } else { - tr_debug("address family: %d", (int)_socket_address.addressType); + tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - address family: %d", (int)_socket_address.addressType); } if (_socket_address.addressType == PAL_AF_INET) { @@ -401,7 +499,7 @@ void M2MConnectionHandlerPimpl::socket_connect_handler() tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - IPv4 Address %d.%d.%d.%d", _ipV4Addr[0], _ipV4Addr[1], _ipV4Addr[2], _ipV4Addr[3]); - + _address._stack = M2MInterface::LwIP_IPv4; _address._address = (void *)_ipV4Addr; _address._length = PAL_IPV4_ADDRESS_SIZE; _address._port = _server_port; @@ -414,7 +512,7 @@ void M2MConnectionHandlerPimpl::socket_connect_handler() } tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - IPv6 Address: %s", mbed_trace_ipv6(_ipV6Addr)); - + _address._stack = M2MInterface::LwIP_IPv6; _address._address = (void *)_ipV6Addr; _address._length = PAL_IPV6_ADDRESS_SIZE; _address._port = _server_port; @@ -435,7 +533,7 @@ void M2MConnectionHandlerPimpl::socket_connect_handler() // Now that we just retry connect when it is not yet succeeded anyway this state might be removed completely. _socket_state = ESocketStateConnectBeingCalled; - // fall through is intentional + // fall through case ESocketStateConnectBeingCalled: case ESocketStateConnecting: if (is_tcp_connection()) { @@ -470,13 +568,14 @@ void M2MConnectionHandlerPimpl::socket_connect_handler() tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - Using UDP"); _socket_state = ESocketStateConnected; } - - // fall through is a normal flow in case the UDP was used or pal_connect() happened to return immediately with PAL_SUCCESS + // fall through + // is a normal flow in case the UDP was used or pal_connect() happened to return immediately with PAL_SUCCESS case ESocketStateConnected: if (_security && security_instance_id >= 0) { if (_secure_connection) { if (_security_impl != NULL) { _security_impl->reset(); + tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - security reseted!"); int ret_code = _security_impl->init(_security, security_instance_id, _is_server_ping); if (ret_code == M2MConnectionHandler::ERROR_NONE) { ret_code = _security_impl->set_dtls_socket_callback(&socket_event_handler, this); @@ -507,11 +606,12 @@ void M2MConnectionHandlerPimpl::socket_connect_handler() } if (_socket_state != ESocketStateHandshaking) { _socket_state = ESocketStateUnsecureConnection; - _observer.address_ready(_address, - _server_type, - _address._port); + _observer.address_ready(_address, _server_type, _address._port); } break; + case ESocketStateSecureConnection: + _observer.address_ready(_address, _server_type, _address._port); + break; } } @@ -708,22 +808,30 @@ void M2MConnectionHandlerPimpl::receive_handshake_handler() int return_value; tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler()"); - // assert(_socket_state == ESocketStateHandshaking); + assert(_socket_state == ESocketStateHandshaking); return_value = _security_impl->connect(_base, _is_server_ping); - +#if (PAL_DNS_API_VERSION == 3) + if (return_value == M2MConnectionHandler::ERROR_NONE) { + // current address worked so let's continue using that + _current_address_info--; + // free current dns resources + pal_freeAddrInfo(_address_info); + _address_info = NULL; + } +#endif if (_is_server_ping && return_value == M2MConnectionHandler::ERROR_NONE) { // The callback for server-ping may trigger more than once. // Only handle it if CID exists, ignore otherwise. if (_security_impl->is_cid_available()) { tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler() - Server ping success"); + _socket_state = ESocketStateSecureConnection; _observer.data_available(NULL, 0, _address); } return; } if (return_value == M2MConnectionHandler::ERROR_NONE) { - _socket_state = ESocketStateSecureConnection; _observer.address_ready(_address, _server_type, @@ -1016,7 +1124,7 @@ void M2MConnectionHandlerPimpl::initialize_event(arm_event_storage_t *event) event->link.next = NULL; event->link.prev = NULL; } -#if (PAL_DNS_API_VERSION == 2) +#if (PAL_DNS_API_VERSION == 2) || (PAL_DNS_API_VERSION == 3) void M2MConnectionHandlerPimpl::stop_dns_fallback_timer() { _dns_fallback_timer->stop_timer(); @@ -1037,3 +1145,26 @@ void M2MConnectionHandlerPimpl::timer_expired(M2MTimerObserver::Type type) } } #endif + +bool M2MConnectionHandlerPimpl::set_socket_priority(M2MConnectionHandler::SocketPriority priority) +{ + if (!_socket) { + tr_error("M2MConnectionHandlerPimpl::set_socket_priority - socket not created"); + return false; + } + + palStatus_t status; + int16_t traffic_class = priority; + status = pal_setSocketOptionsWithLevel(_socket, + PAL_SOL_IPPROTO_IPV6, + PAL_SO_IPV6_TRAFFIC_CLASS, + &traffic_class, + sizeof(traffic_class)); + + if (PAL_ERR_NOT_SUPPORTED != status && PAL_SUCCESS != status) { + tr_error("M2MConnectionHandlerPimpl::set_socket_priority - err: %" PRIx32, status); + return false; + } + + return true; +} diff --git a/mbed-client/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp b/mbed-client/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp index 5ddf9f7a7..d81dff616 100644 --- a/mbed-client/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp +++ b/mbed-client/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp @@ -123,12 +123,11 @@ int M2MConnectionSecurityPimpl::init(const M2MSecurity *security, uint16_t secur palX509_t owncert; palPrivateKey_t privateKey; palX509_t caChain; - size_t len; + size_t len = MAX_CERTIFICATE_SIZE; uint8_t certificate[MAX_CERTIFICATE_SIZE]; uint8_t *certificate_ptr = (uint8_t *)&certificate; - size_t resource_buffer_size; + size_t resource_buffer_size = MAX_CERTIFICATE_SIZE; - caChain.size = MAX_CERTIFICATE_SIZE; int ret_code = security->resource_value_buffer(M2MSecurity::ServerPublicKey, certificate_ptr, security_instance_id, &resource_buffer_size); caChain.buffer = certificate_ptr; caChain.size = static_cast(resource_buffer_size); @@ -174,8 +173,8 @@ int M2MConnectionSecurityPimpl::init(const M2MSecurity *security, uint16_t secur size_t index = 0; while (index < cert_chain_size) { - size_t resource_buffer_size = 0; - owncert.size = MAX_CERTIFICATE_SIZE; + size_t resource_buffer_size = MAX_CERTIFICATE_SIZE; + ret_code = security->resource_value_buffer(M2MSecurity::ReadDeviceCertificateChain, certificate_ptr, security_instance_id, &resource_buffer_size); owncert.buffer = certificate_ptr; @@ -199,10 +198,10 @@ int M2MConnectionSecurityPimpl::init(const M2MSecurity *security, uint16_t secur uint8_t identity[MAX_CERTIFICATE_SIZE]; uint8_t *identity_ptr = (uint8_t *)&identity; - size_t identity_len = 0; + size_t identity_len = MAX_CERTIFICATE_SIZE; uint8_t psk[MAX_CERTIFICATE_SIZE]; uint8_t *psk_ptr = (uint8_t *)&psk; - size_t psk_len = 0; + size_t psk_len = MAX_CERTIFICATE_SIZE; int ret_code = security->resource_value_buffer(M2MSecurity::PublicKey, identity_ptr, security_instance_id, &identity_len); if (ret_code < 0) { @@ -253,12 +252,12 @@ int M2MConnectionSecurityPimpl::init(const M2MSecurity *security, uint16_t secur int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* /*connHandler*/, bool is_server_ping) { palStatus_t ret = PAL_SUCCESS; - if(is_server_ping) { + if (is_server_ping) { tr_info("M2MConnectionSecurityPimpl::connect is SERVER PING"); - ret = pal_handShake_ping(_ssl); + ret = pal_handShake(_ssl, _conf, true); } else { tr_debug("M2MConnectionSecurityPimpl::connect is normal HANDSHAKE"); - ret = pal_handShake(_ssl, _conf); + ret = pal_handShake(_ssl, _conf, false); } tr_debug("M2MConnectionSecurityPimpl::connect return code %" PRIx32, ret); @@ -392,5 +391,5 @@ bool M2MConnectionSecurityPimpl::is_cid_available() void M2MConnectionSecurityPimpl::set_cid_value(const uint8_t *data_ptr, const size_t data_len) { - pal_set_cid_value(_ssl, data_ptr, data_len); + pal_set_cid_value(_ssl, _conf, data_ptr, data_len); } diff --git a/mbed-client/mbed-client/m2mbase.h b/mbed-client/mbed-client/m2mbase.h index 01ab00405..4c28da66b 100644 --- a/mbed-client/mbed-client/m2mbase.h +++ b/mbed-client/mbed-client/m2mbase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 ARM Limited. All rights reserved. + * Copyright (c) 2015-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -87,9 +87,9 @@ class M2MBase : public M2MReportObserver { * \brief Enum defining a resource type. */ typedef enum { - Static, - Dynamic, - Directory + Static, ///< Static resource, value cannot change. + Dynamic, ///< Dynamic resource. + Directory ///< Unsupported. \deprecated. Obsolete resource type. } Mode; /** @@ -110,22 +110,22 @@ class M2MBase : public M2MReportObserver { * supported by a given resource. */ typedef enum { - NOT_ALLOWED = 0x00, - GET_ALLOWED = 0x01, - PUT_ALLOWED = 0x02, - GET_PUT_ALLOWED = 0x03, - POST_ALLOWED = 0x04, - GET_POST_ALLOWED = 0x05, - PUT_POST_ALLOWED = 0x06, - GET_PUT_POST_ALLOWED = 0x07, - DELETE_ALLOWED = 0x08, - GET_DELETE_ALLOWED = 0x09, - PUT_DELETE_ALLOWED = 0x0A, - GET_PUT_DELETE_ALLOWED = 0x0B, - POST_DELETE_ALLOWED = 0x0C, - GET_POST_DELETE_ALLOWED = 0x0D, - PUT_POST_DELETE_ALLOWED = 0x0E, - GET_PUT_POST_DELETE_ALLOWED = 0x0F + NOT_ALLOWED = 0x00, ///< No operations allowed. + GET_ALLOWED = 0x01, ///< Only GET operation allowed. + PUT_ALLOWED = 0x02, ///< Only PUT operation allowed. + GET_PUT_ALLOWED = 0x03, ///< GET and PUT operations allowed. + POST_ALLOWED = 0x04, ///< Only POST operation allowed. + GET_POST_ALLOWED = 0x05, ///< \deprecated Unsupported operation mode. + PUT_POST_ALLOWED = 0x06, ///< \deprecated Unsupported operation mode. + GET_PUT_POST_ALLOWED = 0x07, ///< \deprecated Unsupported operation mode. + DELETE_ALLOWED = 0x08, ///< Only DELETE operation allowed. + GET_DELETE_ALLOWED = 0x09, ///< GET and DELETE operations allowed. + PUT_DELETE_ALLOWED = 0x0A, ///< PUT and DELETE operations allowed. + GET_PUT_DELETE_ALLOWED = 0x0B, ///< GET, PUT and DELETE operations allowed. + POST_DELETE_ALLOWED = 0x0C, ///< \deprecated Unsupported operation mode. + GET_POST_DELETE_ALLOWED = 0x0D, ///< \deprecated Unsupported operation mode. + PUT_POST_DELETE_ALLOWED = 0x0E, ///< \deprecated Unsupported operation mode. + GET_PUT_POST_DELETE_ALLOWED = 0x0F ///< \deprecated Unsupported operation mode. } Operation; /** @@ -194,6 +194,7 @@ class M2MBase : public M2MReportObserver { #endif // ENABLE_ASYNC_REST_RESPONSE /*! \brief LwM2M parameters. + * \deprecated This is internal datastructure and subject to be changed or removed. Do not use on application. */ typedef struct lwm2m_parameters { //add multiple_instances @@ -262,26 +263,31 @@ class M2MBase : public M2MReportObserver { /** * \brief Sets the operation type for an object. * \param operation The operation to be set. + * + * \deprecated Switching of operation mode on run time is deprecated. Set correct operation mode when creating the resource. */ void set_operation(M2MBase::Operation operation); #if !defined(MEMORY_OPTIMIZED_API) || defined(RESOURCE_ATTRIBUTES_LIST) +#if !defined(DISABLE_INTERFACE_DESCRIPTION) || defined(RESOURCE_ATTRIBUTES_LIST) /** * \brief Sets the interface description of the object. * \param description The description to be set. + * \deprecated Human readable interface descriptions are deprecated. */ -#if !defined(DISABLE_INTERFACE_DESCRIPTION) || defined(RESOURCE_ATTRIBUTES_LIST) void set_interface_description(const String &description); /** * \brief Sets the interface description of the object. * \param description The description to be set. + * \deprecated Human readable interface descriptions are deprecated. */ void set_interface_description(const char *description); /** * \brief Returns the interface description of the object. * \return The interface description of the object. + * \deprecated Human readable interface descriptions are deprecated. */ const char *interface_description() const; #endif @@ -289,18 +295,21 @@ class M2MBase : public M2MReportObserver { /** * \brief Sets the resource type of the object. * \param resource_type The resource type to be set. + * \deprecated Textual content types are deprecated. Please define correct content type when resource is created. */ virtual void set_resource_type(const String &resource_type); /** * \brief Sets the resource type of the object. * \param resource_type The resource type to be set. + * \deprecated Textual content types are deprecated. Please define correct content type when resource is created. */ virtual void set_resource_type(const char *resource_type); /** * \brief Returns the resource type of the object. * \return The resource type of the object. + * \deprecated Textual content types are deprecated. Please define correct content type when resource is created. */ const char *resource_type() const; #endif @@ -310,12 +319,14 @@ class M2MBase : public M2MReportObserver { * \brief Sets the CoAP content type of the object. * \param content_type The content type to be set based on * CoAP specifications. + * \deprecated Modifying underlying CoAP library parameters is deprecated. Please define correct content type when resource is created. */ void set_coap_content_type(const uint16_t content_type); /** * \brief Sets the observable mode for the object. * \param observable A value for the observation. + * \deprecated By default, all resources are now observable so this API is subject to be removed. */ void set_observable(bool observable); @@ -346,12 +357,14 @@ class M2MBase : public M2MReportObserver { /** * \brief Adds the observation level for the object. * \param observation_level The level of observation. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ virtual void add_observation_level(M2MBase::Observation observation_level); /** * \brief Removes the observation level for the object. * \param observation_level The level of observation. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ virtual void remove_observation_level(M2MBase::Observation observation_level); @@ -360,24 +373,28 @@ class M2MBase : public M2MReportObserver { * \param observed The value for observation. When true, starts observing. When false, the ongoing observation is cancelled. * \param handler A handler object for sending * observation callbacks. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ void set_under_observation(bool observed, M2MObservationHandler *handler); /** * \brief Returns the Observation Handler object. * \return M2MObservationHandler object. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ virtual M2MObservationHandler *observation_handler() const = 0; /** * \brief Sets the observation handler * \param handler Observation handler + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ virtual void set_observation_handler(M2MObservationHandler *handler) = 0; /** * \brief Sets the instance ID of the object. * \param instance_id The instance ID of the object. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ void set_instance_id(const uint16_t instance_id); @@ -426,12 +443,14 @@ class M2MBase : public M2MReportObserver { /** * \brief Returns the CoAP content type of the object. * \return The CoAP content type of the object. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ uint16_t coap_content_type() const; /** * \brief Returns the observation status of the object. * \return True if observable, else false. + * \deprecated All resources are observable by default. */ bool is_observable() const; @@ -444,6 +463,7 @@ class M2MBase : public M2MReportObserver { /** * \brief Returns the observation level of the object. * \return The observation level of the object. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ M2MBase::Observation observation_level() const; @@ -471,6 +491,7 @@ class M2MBase : public M2MReportObserver { * attribute. * \param query The query that needs to be parsed. * \return True if required attributes are present, else false. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ virtual bool handle_observation_attribute(const char *query); #endif @@ -482,6 +503,7 @@ class M2MBase : public M2MReportObserver { * \param observation_handler A handler object for sending * observation callbacks. * \return sn_coap_hdr_s The message that needs to be sent to server. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ virtual sn_coap_hdr_s *handle_get_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -494,6 +516,7 @@ class M2MBase : public M2MReportObserver { * observation callbacks. * \param execute_value_updated True executes the "value_updated" callback. * \return sn_coap_hdr_s The message that needs to be sent to server. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ virtual sn_coap_hdr_s *handle_put_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -508,6 +531,7 @@ class M2MBase : public M2MReportObserver { * observation callbacks. * \param execute_value_updated True executes the "value_updated" callback. * \return sn_coap_hdr_s The message that needs to be sent to server. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ virtual sn_coap_hdr_s *handle_post_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -523,18 +547,21 @@ class M2MBase : public M2MReportObserver { /** * \brief Sets whether this resource is published to server or not. * \param register_uri True sets the resource as part of registration message. + * \deprecated All resources are published. This API is subject to be removed. */ void set_register_uri(bool register_uri); /** * \brief Returns whether this resource is published to server or not. * \return True if the resource is a part of the registration message, else false. + * \deprecated All resources are published. This API is subject to be removed. */ bool register_uri(); /** * @brief Returns whether this resource is under observation or not. * @return True if the resource is under observation, else false, + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ bool is_under_observation() const; @@ -543,6 +570,7 @@ class M2MBase : public M2MReportObserver { * object receives a PUT or POST command. * @param callback The function pointer that is called. * @return True, if callback could be set, false otherwise. + * \deprecated Function pointer classes are deprecated. Please use the M2MBase::set_value_updated_function(value_updated_callback2) instead. */ bool set_value_updated_function(value_updated_callback callback); @@ -557,12 +585,14 @@ class M2MBase : public M2MReportObserver { /** * @brief Returns whether a callback function is set or not. * @return True if the callback function is set, else false. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ bool is_value_updated_function_set() const; /** * @brief Calls the function that is set in the "set_value_updated_function". * @param name The name of the object. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ void execute_value_updated(const String &name); @@ -575,12 +605,14 @@ class M2MBase : public M2MReportObserver { /** * @brief Returns the resource information. * @return Resource information. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ sn_nsdl_dynamic_resource_parameters_s *get_nsdl_resource() const; /** * @brief Returns the resource structure. * @return Resource structure. + * \deprecated Internal API. Subject to be removed, please don't use on application code. */ M2MBase::lwm2m_parameters_s *get_lwm2m_parameters() const; @@ -798,8 +830,9 @@ class M2MBase : public M2MReportObserver { * \brief Cancels the ongoing observation. * * \param status Delivery status to be sent to application + * \param notify Whether application is notified or not */ - void cancel_observation(M2MBase::MessageDeliveryStatus status = M2MBase::MESSAGE_STATUS_UNSUBSCRIBED); + void cancel_observation(M2MBase::MessageDeliveryStatus status = M2MBase::MESSAGE_STATUS_UNSUBSCRIBED, bool notify = true); /** * \brief Start the observation. diff --git a/mbed-client/mbed-client/m2mconfig.h b/mbed-client/mbed-client/m2mconfig.h index 9b0fb14ab..b7860c853 100644 --- a/mbed-client/mbed-client/m2mconfig.h +++ b/mbed-client/mbed-client/m2mconfig.h @@ -110,11 +110,11 @@ typedef uint32_t (*random_number_cb)(void) ; * a complement. */ typedef struct mbedtls_entropy { - int (*entropy_source_ptr)(void *, unsigned char *,size_t , size_t *); + int (*entropy_source_ptr)(void *, unsigned char *, size_t, size_t *); void *p_source; size_t threshold; int strong; -}entropy_cb; +} entropy_cb; // Include user provided configuration @@ -174,10 +174,23 @@ typedef struct mbedtls_entropy { #define MEMORY_OPTIMIZED_API MBED_CONF_MBED_CLIENT_MEMORY_OPTIMIZED_API #endif +#ifdef MBED_CONF_MBED_CLIENT_MAX_CERTIFICATE_SIZE +#define MAX_CERTIFICATE_SIZE MBED_CONF_MBED_CLIENT_MAX_CERTIFICATE_SIZE +#else +#define MAX_CERTIFICATE_SIZE 1024 +#endif + #ifndef MBED_CONF_MBED_CLIENT_ENABLE_OBSERVATION_PARAMETERS #define MBED_CONF_MBED_CLIENT_ENABLE_OBSERVATION_PARAMETERS 1 #endif +#ifdef MBED_CONF_MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE +#define MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE MBED_CONF_MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE +#endif +#ifndef MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE +#define MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE 1 +#endif + // Define defaults if not defined yet. #ifndef MBED_CLIENT_RECONNECTION_COUNT diff --git a/mbed-client/mbed-client/m2mconnectionhandler.h b/mbed-client/mbed-client/m2mconnectionhandler.h index 8e7072bab..3b44a3ca9 100644 --- a/mbed-client/mbed-client/m2mconnectionhandler.h +++ b/mbed-client/mbed-client/m2mconnectionhandler.h @@ -52,13 +52,24 @@ class M2MConnectionHandler { SOCKET_TIMEOUT = -13, } ConnectionError; + /** + * @enum SocketPriority + * This enum defines priority for the socket. + * Used for setting traffic class socket option. + */ + typedef enum { + DEFAULT_PRIORITY = 0, + HIGH_PRIORITY = 10, + ALERT_PRIORITY = 46 + } SocketPriority; + public: /** * \brief Constructor */ M2MConnectionHandler(M2MConnectionObserver &observer, - M2MConnectionSecurity* sec, + M2MConnectionSecurity *sec, M2MInterface::BindingMode mode, M2MInterface::NetworkStack stack); @@ -85,10 +96,10 @@ class M2MConnectionHandler { * \param is_server_ping Defines whether the call is for Server ping or not. * \return True if the address is valid, else false. */ - bool resolve_server_address(const String& server_address, + bool resolve_server_address(const String &server_address, const uint16_t server_port, M2MConnectionObserver::ServerType server_type, - const M2MSecurity* security, + const M2MSecurity *security, bool is_server_ping = false); /** @@ -99,8 +110,8 @@ class M2MConnectionHandler { * \return True if data is sent successfully, else false. */ bool send_data(uint8_t *data_ptr, - uint16_t data_len, - sn_nsdl_addr_s *address_ptr); + uint16_t data_len, + sn_nsdl_addr_s *address_ptr); /** * \brief Listens to the incoming data from a remote server. @@ -151,6 +162,12 @@ class M2MConnectionHandler { */ void unregister_network_handler(); + /** + * \brief Set socket priority. + * \return true if socket option was set correctly. + */ + bool set_socket_priority(M2MConnectionHandler::SocketPriority priority); + /** * \brief Stores CID persistently for DTLS connections. */ @@ -163,7 +180,7 @@ class M2MConnectionHandler { /** * \brief Status of CID availability in client. - * return true if CID is available else false. + * \return true if CID is available else false. */ bool is_cid_available(); @@ -179,10 +196,10 @@ class M2MConnectionHandler { M2MConnectionObserver &_observer; M2MConnectionHandlerPimpl *_private_impl; -friend class Test_M2MConnectionHandler; -friend class Test_M2MConnectionHandler_mbed; -friend class Test_M2MConnectionHandler_linux; -friend class M2MConnection_TestObserver; + friend class Test_M2MConnectionHandler; + friend class Test_M2MConnectionHandler_mbed; + friend class Test_M2MConnectionHandler_linux; + friend class M2MConnection_TestObserver; }; #endif //M2M_CONNECTION_HANDLER_H__ diff --git a/mbed-client/mbed-client/m2mconstants.h b/mbed-client/mbed-client/m2mconstants.h index 2c3e27a3c..67198f95b 100644 --- a/mbed-client/mbed-client/m2mconstants.h +++ b/mbed-client/mbed-client/m2mconstants.h @@ -30,8 +30,8 @@ const uint8_t MINIMUM_REGISTRATION_TIME = 60; //in seconds const uint8_t ONE_SECOND_TIMER = 1; const uint8_t MAX_ALLOWED_STRING_LENGTH = 64; const uint8_t MAX_ALLOWED_ERROR_STRING_LENGTH = 64; -const uint16_t MAX_CERTIFICATE_SIZE = 1024; const uint16_t CONFIG_BOOLEAN_ITEM_SIZE = 4; +const uint16_t MAX_FIRMWARE_PACKAGE_URI_PATH_LEN = 255; const uint32_t HANDSHAKE_TIMEOUT_MSECS = (30 * 60 * 1000); // XXX: @@ -150,7 +150,7 @@ const uint32_t HANDSHAKE_TIMEOUT_MSECS = (30 * 60 * 1000); #define FIRMWARE_UPDATE_RESULT "5" #define FIRMWARE_PACKAGE_NAME "6" #define FIRMWARE_PACKAGE_VERSION "7" -#define FIRMAWARE_PACKAGE_URI_PATH FIRMWARE_PATH_PREFIX FIRMWARE_PACKAGE_URI +#define FIRMWARE_PACKAGE_URI_PATH FIRMWARE_PATH_PREFIX FIRMWARE_PACKAGE_URI // Error Strings diff --git a/mbed-client/mbed-client/m2minterface.h b/mbed-client/mbed-client/m2minterface.h index 234a3c2b4..c0460d4d4 100644 --- a/mbed-client/mbed-client/m2minterface.h +++ b/mbed-client/mbed-client/m2minterface.h @@ -34,8 +34,8 @@ class M2MBase; class M2MInterfaceObserver; class M2MServer; -typedef Vector M2MObjectList; -typedef Vector M2MBaseList; +typedef Vector M2MObjectList; +typedef Vector M2MBaseList; typedef FP callback_handler; typedef enum request_error_e { @@ -112,7 +112,7 @@ class M2MInterface { ESTEnrollmentFailed, FailedToStoreCredentials, FailedToReadCredentials - }Error; + } Error; /** * \brief An enum defining different kinds of binding @@ -123,13 +123,13 @@ class M2MInterface { UDP = 0x01, UDP_QUEUE = 0x03, SMS = 0x04, - SMS_QUEUE =0x06, + SMS_QUEUE = 0x06, UDP_SMS_QUEUE = 0x07, TCP = 0x09, //not real value, spec does not have one! - //this has nsdl binding mode bit UDP set + //this has nsdl binding mode bit UDP set TCP_QUEUE = 0x0b //not real value, spec does not have one! - //this has nsdl binding mode bits, UDP and UDP_QUEUE set - }BindingMode; + //this has nsdl binding mode bits, UDP and UDP_QUEUE set + } BindingMode; /** * \brief An enum defining different kinds of network @@ -143,11 +143,11 @@ class M2MInterface { Nanostack_IPv6, ATWINC_IPv4, Unknown - }NetworkStack; + } NetworkStack; public: - virtual ~M2MInterface(){} + virtual ~M2MInterface() {} #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE /** @@ -250,7 +250,7 @@ class M2MInterface { * needs to be unregistered. If there is only one LWM2M server registered, * this parameter can be NULL. */ - virtual void unregister_object(M2MSecurity* security_object = NULL) = 0; + virtual void unregister_object(M2MSecurity *security_object = NULL) = 0; /** * \brief Sets the function that is called for indicating that the client @@ -380,13 +380,25 @@ class M2MInterface { */ virtual void pause() = 0; - virtual nsdl_s* get_nsdl_handle() const = 0; + /** + * \brief Sets client into an alert mode. + * + * \note In alert mode client halts all data + * sendings/active operations and waits for priority data to be sent. + */ + virtual void alert() = 0; + + /** + * @brief Get ndsl handle. + * @return nsdl handle + */ + virtual nsdl_s *get_nsdl_handle() const = 0; /** * @brief Returns M2MServer handle. * @return M2MServer handle */ - virtual M2MServer* get_m2mserver() const = 0; + virtual M2MServer *get_m2mserver() const = 0; virtual uint16_t stagger_wait_time(bool boostrap) const = 0; diff --git a/mbed-client/mbed-client/m2minterfaceobserver.h b/mbed-client/mbed-client/m2minterfaceobserver.h index 1d5a2f164..b76f62200 100644 --- a/mbed-client/mbed-client/m2minterfaceobserver.h +++ b/mbed-client/mbed-client/m2minterfaceobserver.h @@ -67,7 +67,7 @@ class M2MInterfaceObserver { * \param server_object An object containing information about the LWM2M server. * The client maintains the object. */ - virtual void registration_updated(M2MSecurity *security_object, const M2MServer & server_object) = 0; + virtual void registration_updated(M2MSecurity *security_object, const M2MServer &server_object) = 0; /** * \brief A callback indicating that there was an error during the operation. @@ -94,6 +94,15 @@ class M2MInterfaceObserver { */ virtual void network_status_changed(bool connected) = 0; + /** + * \brief A callback indicating that client is paused. + */ + virtual void paused() = 0; + + /** + * \brief A callback indicating that client is in alert mode. + */ + virtual void alert_mode() = 0; }; #endif // M2M_INTERFACE_OBSERVER_H diff --git a/mbed-client/mbed-client/m2mobject.h b/mbed-client/mbed-client/m2mobject.h index dfc6ba479..c98fe399a 100644 --- a/mbed-client/mbed-client/m2mobject.h +++ b/mbed-client/mbed-client/m2mobject.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 ARM Limited. All rights reserved. + * Copyright (c) 2015-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -85,6 +85,8 @@ protected : * \brief Creates a new object instance for a given mbed Client Interface object. With this, * the client can respond to server's GET methods with the provided value. * \return M2MObjectInstance. An object instance for managing other client operations. + * + * \deprecated Internal lwm2m_parameter_s structure is deprecated. Please use M2MObject::create_object_instance(uint16_t) instead. */ M2MObjectInstance* create_object_instance(const lwm2m_parameters_s* s); @@ -117,24 +119,28 @@ protected : /** * \brief Returns the Observation Handler object. * \return M2MObservationHandler object. + * \deprecated Internal API, subject to be modified or removed. */ virtual M2MObservationHandler* observation_handler() const; /** * \brief Sets the observation handler * \param handler Observation handler + * \deprecated Internal API, subject to be modified or removed. */ virtual void set_observation_handler(M2MObservationHandler *handler); /** * \brief Adds the observation level for the object. * \param observation_level The level of observation. + * \deprecated Internal API, subject to be modified or removed. */ virtual void add_observation_level(M2MBase::Observation observation_level); /** * \brief Removes the observation level from the object. * \param observation_level The level of observation. + * \deprecated Internal API, subject to be modified or removed. */ virtual void remove_observation_level(M2MBase::Observation observation_level); @@ -145,6 +151,7 @@ protected : * \param observation_handler The handler object for sending * observation callbacks. * \return sn_coap_hdr_s The message that needs to be sent to server. + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -158,6 +165,7 @@ protected : * observation callbacks. * \param execute_value_updated True will execute the "value_updated" callback. * \return sn_coap_hdr_s The message that needs to be sent to server. + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -172,6 +180,7 @@ protected : * observation callbacks. * \param execute_value_updated True will execute the "value_updated" callback. * \return sn_coap_hdr_s The message that needs to be sent to server. + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -179,6 +188,9 @@ protected : bool &execute_value_updated, sn_nsdl_addr_s *address = NULL); + /** + * \deprecated Internal API, subject to be modified or removed. + */ void notification_update(uint16_t obj_instance_id); #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION diff --git a/mbed-client/mbed-client/m2mobjectinstance.h b/mbed-client/mbed-client/m2mobjectinstance.h index 0e5bb1086..5bd201120 100644 --- a/mbed-client/mbed-client/m2mobjectinstance.h +++ b/mbed-client/mbed-client/m2mobjectinstance.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 ARM Limited. All rights reserved. + * Copyright (c) 2015-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -75,6 +75,7 @@ friend class M2MObject; /** * \brief TODO! * \return M2MResource The resource for managing other client operations. + * \deprecated Please use M2MInterfaceFactory::create_resource() instead. */ M2MResource* create_static_resource(const lwm2m_parameters_s* static_res, M2MResourceInstance::ResourceType type); @@ -91,6 +92,7 @@ friend class M2MObject; * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks * otherwise handled in mbed-client-c. * \return M2MResource The resource for managing other client operations. + * \deprecated Please use M2MInterfaceFactory::create_resource() instead. */ M2MResource* create_static_resource(const String &resource_name, const String &resource_type, @@ -112,6 +114,7 @@ friend class M2MObject; * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks * otherwise handled in mbed-client-c. * \return M2MResource The resource for managing other client operations. + * \deprecated Please use M2MInterfaceFactory::create_resource() instead. */ M2MResource* create_dynamic_resource(const String &resource_name, const String &resource_type, @@ -132,6 +135,7 @@ friend class M2MObject; * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks * otherwise handled in mbed-client-c. * \return M2MResource The resource for managing other client operations. + * \deprecated Please use M2MInterfaceFactory::create_resource() instead. */ M2MResource* create_dynamic_resource(const uint16_t resource_name, const char *resource_type, @@ -143,6 +147,7 @@ friend class M2MObject; /** * \brief TODO! * \return M2MResource The resource for managing other client operations. + * \deprecated Please use M2MInterfaceFactory::create_resource() instead. */ M2MResource* create_dynamic_resource(const lwm2m_parameters_s* static_res, M2MResourceInstance::ResourceType type, @@ -159,6 +164,7 @@ friend class M2MObject; * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks * otherwise handled in mbed-client-c. * \return M2MResourceInstance The resource instance for managing other client operations. + * \deprecated Please use M2MInterfaceFactory::create_resource() instead. */ M2MResourceInstance* create_static_resource_instance(const String &resource_name, const String &resource_type, @@ -179,6 +185,7 @@ friend class M2MObject; * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks * otherwise handled in mbed-client-c. * \return M2MResourceInstance The resource instance for managing other client operations. + * \deprecated Please use M2MInterfaceFactory::create_resource() instead. */ M2MResourceInstance* create_dynamic_resource_instance(const String &resource_name, const String &resource_type, @@ -193,6 +200,7 @@ friend class M2MObject; * Note: this will be removed in next version, please use the * remove_resource(const char*) version instead. * \return True if removed, else false. + * \deprecated String based APIs are deprecated. Please use the id or path instead. */ bool remove_resource(const String &name); @@ -219,6 +227,9 @@ friend class M2MObject; */ M2MResource* resource(const uint16_t resource_id) const; + /** + * \deprecated String based APIs are deprecated. Please use resource_id or path instead. + */ M2MResource* resource(const String &name) const; M2MResource* resource(const char *resource) const; @@ -241,6 +252,7 @@ friend class M2MObject; * resource_count(const char*) version instead. * \param resource The name of the resource. * \return Total number of the resources. + * \deprecated String based APIs are deprecated. Please use resource_id or path instead. */ uint16_t resource_count(const String& resource) const; @@ -254,24 +266,28 @@ friend class M2MObject; /** * \brief Adds the observation level for the object. * \param observation_level The level of observation. + * \deprecated Internal API, subject to be modified or removed. */ virtual void add_observation_level(M2MBase::Observation observation_level); /** * \brief Removes the observation level from the object. * \param observation_level The level of observation. + * \deprecated Internal API, subject to be modified or removed. */ virtual void remove_observation_level(M2MBase::Observation observation_level); /** * \brief Returns the Observation Handler object. * \return M2MObservationHandler object. + * \deprecated Internal API, subject to be modified or removed. */ virtual M2MObservationHandler* observation_handler() const; /** * \brief Sets the observation handler * \param handler Observation handler + * \deprecated Internal API, subject to be modified or removed. */ virtual void set_observation_handler(M2MObservationHandler *handler); @@ -282,6 +298,7 @@ friend class M2MObject; * \param observation_handler The handler object for sending * observation callbacks. * return sn_coap_hdr_s The message that needs to be sent to the server. + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -294,6 +311,7 @@ friend class M2MObject; * observation callbacks. * \param execute_value_updated True will execute the "value_updated" callback. * \return sn_coap_hdr_s The message that needs to be sent to server. + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -308,6 +326,7 @@ friend class M2MObject; * observation callbacks. * \param execute_value_updated True will execute the "value_updated" callback. * \return sn_coap_hdr_s The message that needs to be sent to server. + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -317,7 +336,9 @@ friend class M2MObject; inline M2MObject& get_parent_object() const; - // callback used from M2MResource/M2MResourceInstance + /** callback used from M2MResource/M2MResourceInstance + * \deprecated Internal API, subject to be modified or removed. + */ void notification_update(M2MBase::Observation observation_level); protected: @@ -353,6 +374,7 @@ friend class M2MObject; friend class Test_M2MResourceInstance; friend class Test_M2MReportHandler; friend class TestFactory; + friend class Test_M2MInterfaceImpl; }; inline M2MObject& M2MObjectInstance::get_parent_object() const diff --git a/mbed-client/mbed-client/m2mresource.h b/mbed-client/mbed-client/m2mresource.h index 9a9b505fa..50eefa51d 100644 --- a/mbed-client/mbed-client/m2mresource.h +++ b/mbed-client/mbed-client/m2mresource.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 ARM Limited. All rights reserved. + * Copyright (c) 2015-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -144,6 +144,13 @@ class M2MResource : public M2MResourceBase #else void set_delayed_response(bool delayed_response); #endif + /** + * \brief Check if resource is set to send delayed responses for POST request. + * Use set_delayed_response() for enabling or disabling delayed response. + * \return True, if delayed response is enabled. + */ + bool delayed_response() const; + /** * \brief A trigger to send the delayed response for the POST request. * The delayed_response flag must be set before receiving the POST request @@ -152,22 +159,19 @@ class M2MResource : public M2MResourceBase * Please use M2MBase::send_async_response_with_code method, if you are using * ENABLE_ASYNC_REST_RESPONSE flag, because this method will be deprecated. * \param code Response code to be sent. - * \return True if a response is sent, else false. + * \return True if delayed response is enabled. */ bool send_delayed_post_response(sn_coap_msg_code_e code = COAP_MSG_CODE_RESPONSE_CHANGED); - /** + /** \internal * \brief Provides the value of the token of the delayed post response. * \param[out] token A pointer to the token value. * \param[out] token_length The length of the token pointer. + * + * \deprecated Internal API, subject to be modified or removed. */ void get_delayed_token(uint8_t *&token, uint8_t &token_length); - /** - * \brief Returns the value set for delayed response for POST requests. - * \return The value for delayed response. - */ - bool delayed_response() const; #endif //DISABLE_DELAYED_RESPONSE /** @@ -199,12 +203,16 @@ class M2MResource : public M2MResourceBase /** * \brief Returns the Observation Handler object. * \return M2MObservationHandler object. + * + * \deprecated Internal API, subject to be modified or removed. */ virtual M2MObservationHandler* observation_handler() const; /** * \brief Sets the observation handler * \param handler Observation handler + * + * \deprecated Internal API, subject to be modified or removed. */ virtual void set_observation_handler(M2MObservationHandler *handler); @@ -213,6 +221,8 @@ class M2MResource : public M2MResourceBase * \brief Parses the received query for a notification * attribute. * \return True if required attributes are present, else false. + * + * \deprecated Internal API, subject to be modified or removed. */ virtual bool handle_observation_attribute(const char *query); #endif @@ -220,12 +230,16 @@ class M2MResource : public M2MResourceBase /** * \brief Adds the observation level for the object. * \param observation_level The level of observation. + * + * \deprecated Internal API, subject to be modified or removed. */ virtual void add_observation_level(M2MBase::Observation observation_level); /** * \brief Removes the observation level from an object. * \param observation_level The level of observation. + * + * \deprecated Internal API, subject to be modified or removed. */ virtual void remove_observation_level(M2MBase::Observation observation_level); @@ -236,6 +250,8 @@ class M2MResource : public M2MResourceBase * \param observation_handler A handler object for sending * observation callbacks. * \return sn_coap_hdr_s The message that needs to be sent to the server. + * + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -248,6 +264,8 @@ class M2MResource : public M2MResourceBase * observation callbacks. * \param execute_value_updated True executes the "value_updated" callback. * \return sn_coap_hdr_s The message that needs to be sent to the server. + * + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -261,6 +279,8 @@ class M2MResource : public M2MResourceBase * observation callbacks. * \param execute_value_updated True executes the "value_updated" callback. * \return sn_coap_hdr_s The message that needs to be sent to the server. + * + * \deprecated Internal API, subject to be modified or removed. */ virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl, sn_coap_hdr_s *received_coap_header, @@ -268,6 +288,9 @@ class M2MResource : public M2MResourceBase bool &execute_value_updated, sn_nsdl_addr_s *address = NULL); + /** + * \deprecated Internal API, subject to be modified or removed. + */ M2MObjectInstance& get_parent_object_instance() const; /** @@ -326,6 +349,7 @@ friend class Test_M2MTLVDeserializer; friend class Test_M2MBase; friend class Test_M2MResourceInstance; friend class TestFactory; +friend class Test_M2MInterfaceImpl; }; /** @@ -344,7 +368,9 @@ class M2MResource::M2MExecuteParameter { #ifdef MEMORY_OPTIMIZED_API M2MExecuteParameter(const char *object_name, const char *resource_name, uint16_t object_instance_id); #else - // This is a deprecated constructor, to be removed on next release. + /** + * \deprecated This is a deprecated constructor. Subject to be removed. + */ M2MExecuteParameter(const String &object_name, const String &resource_name, uint16_t object_instance_id); #endif public: diff --git a/mbed-client/mbed-client/m2mresourcebase.h b/mbed-client/mbed-client/m2mresourcebase.h index 5908e0161..62bc14dbd 100644 --- a/mbed-client/mbed-client/m2mresourcebase.h +++ b/mbed-client/mbed-client/m2mresourcebase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 ARM Limited. All rights reserved. + * Copyright (c) 2015-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -66,7 +66,7 @@ class M2MResourceBase : public M2MBase { OBJLINK } ResourceType; - /* + /** * \brief Value set callback function. * \param resource Pointer to resource whose value should be updated * \param value Pointer to value buffer containing new value, ownership is transferred to callback function @@ -74,7 +74,7 @@ class M2MResourceBase : public M2MBase { */ typedef void(*value_set_callback)(const M2MResourceBase *resource, uint8_t *value, const uint32_t value_length); - /* + /** * \brief Read resource value callback function. * \param resource Pointer to resource whose value should will be read * \param buffer[OUT] Buffer containing the resource value @@ -87,7 +87,7 @@ class M2MResourceBase : public M2MBase { size_t *buffer_size, void *client_args); - /* + /** * \brief Type definition for a read resource value callback function. * \param[in] resource Pointer to resource whose value should will be read. * \param[out] buffer Pointer to value buffer. @@ -104,9 +104,7 @@ class M2MResourceBase : public M2MBase { const size_t offset, void *client_args); - - - /* + /** * \brief Read resource value size callback function. * \param resource Pointer to resource whose size will be read * \param buffer_size[OUT] Buffer size @@ -117,7 +115,7 @@ class M2MResourceBase : public M2MBase { size_t *buffer_size, void *client_args); - /* + /** * \brief Set resource value callback function. * \param resource Pointer to resource whose value will be updated * \param buffer Buffer containing the new value @@ -207,6 +205,8 @@ class M2MResourceBase : public M2MBase { * resource receives a POST command. * \param callback The function pointer that needs to be executed. * \return True, if callback could be set, false otherwise. + * + * \deprecated Function pointer classes are deprecated. Please use M2MResourceBase::set_execute_function(execute_callback_2 callback) instead. */ bool set_execute_function(execute_callback callback); @@ -393,6 +393,8 @@ class M2MResourceBase : public M2MBase { /** * \brief Function to report the value changes to the object instance and object parent of the * resource if they have been subscribed + * + * \deprecated Internal API, subject to be modified or removed. */ void report_to_parents(); @@ -433,6 +435,9 @@ class M2MResourceBase : public M2MBase { */ virtual const char *object_name() const = 0; + /** + * \deprecated Internal API, subject to be modified or removed. + */ virtual M2MResource &get_parent_resource() const = 0; #ifndef DISABLE_BLOCK_MESSAGE @@ -462,7 +467,7 @@ class M2MResourceBase : public M2MBase { #endif /** - * @brief Set the status whether resource value will be part of registration message. * + * @brief Set the status whether resource value will be part of registration message. * This only allowed for following resource types: * STRING, * INTEGER, @@ -471,6 +476,8 @@ class M2MResourceBase : public M2MBase { * OPAQUE * * @param publish_value If true then resource value will be part of registration message. + * + * \deprecated Internal API, subject to be modified or removed. */ void publish_value_in_registration_msg(bool publish_value); diff --git a/mbed-client/mbed-client/m2mserver.h b/mbed-client/mbed-client/m2mserver.h index 8942678e7..5b47b9902 100644 --- a/mbed-client/mbed-client/m2mserver.h +++ b/mbed-client/mbed-client/m2mserver.h @@ -33,6 +33,7 @@ class M2MServer : public M2MObject friend class M2MInterfaceFactory; friend class M2MNsdlInterface; +friend class M2MInterfaceImpl; public: diff --git a/mbed-client/mbed_lib.json b/mbed-client/mbed_lib.json index 77ace385a..36b4ff10f 100644 --- a/mbed-client/mbed_lib.json +++ b/mbed-client/mbed_lib.json @@ -20,6 +20,12 @@ "disable-delayed-response": null, "disable-block-message": null, "memory-optimized-api": null, - "enable-observation-parameters" : 1 + "max-certificate-size": { + "help": "Maximum size for buffer passing around certificate chain.", + "default": 1024, + "value": 1024 + }, + "enable-observation-parameters" : 1, + "bootstrap-piggybacked-response" : null } } diff --git a/mbed-client/source/include/m2minterfaceimpl.h b/mbed-client/source/include/m2minterfaceimpl.h index 83ff4019a..9b153e2f2 100644 --- a/mbed-client/source/include/m2minterfaceimpl.h +++ b/mbed-client/source/include/m2minterfaceimpl.h @@ -41,18 +41,17 @@ class M2MUpdateRegisterData; */ class M2MInterfaceImpl : public M2MInterface, - public M2MNsdlObserver, - public M2MConnectionObserver, - public M2MTimerObserver -{ + public M2MNsdlObserver, + public M2MConnectionObserver, + public M2MTimerObserver { private: // Prevents the use of assignment operator by accident. - M2MInterfaceImpl& operator=( const M2MInterfaceImpl& /*other*/ ); + M2MInterfaceImpl &operator=(const M2MInterfaceImpl & /*other*/); // Prevents the use of copy constructor by accident - M2MInterfaceImpl( const M2MInterfaceImpl& /*other*/ ); + M2MInterfaceImpl(const M2MInterfaceImpl & /*other*/); -friend class M2MInterfaceFactory; + friend class M2MInterfaceFactory; private: @@ -70,7 +69,7 @@ friend class M2MInterfaceFactory; * @param context_address Context address, default is empty. * @param version Version of the LwM2M Enabler that the LwM2M Client supports. */ - M2MInterfaceImpl(M2MInterfaceObserver& observer, + M2MInterfaceImpl(M2MInterfaceObserver &observer, const String &endpoint_name, const String &endpoint_type, const int32_t life_time, @@ -179,7 +178,7 @@ friend class M2MInterfaceFactory; * needs to be unregistered. If there is only one LWM2M server registered * this parameter can be NULL. */ - virtual void unregister_object(M2MSecurity* security = NULL); + virtual void unregister_object(M2MSecurity *security = NULL); /** * @brief Sets the function which will be called indicating client @@ -315,13 +314,25 @@ friend class M2MInterfaceFactory; */ virtual void pause(); - virtual nsdl_s* get_nsdl_handle() const; + /** + * \brief Sets client into an alert mode. + * + * \note In alert mode client halts all data + * sendings/active operations and waits for priority data to be sent. + */ + virtual void alert(); + + /** + * @brief Get ndsl handle. + * @return nsdl handle + */ + virtual nsdl_s *get_nsdl_handle() const; /** * @brief Returns M2MServer handle. * @return M2MServer handle */ - virtual M2MServer* get_m2mserver() const; + virtual M2MServer *get_m2mserver() const; /** * \brief Internal test function. Set CID for current tls session. @@ -365,7 +376,7 @@ friend class M2MInterfaceFactory; protected: // From M2MConnectionObserver - virtual void data_available(uint8_t* data, + virtual void data_available(uint8_t *data, uint16_t data_size, const M2MConnectionObserver::SocketAddress &address); @@ -389,94 +400,94 @@ friend class M2MInterfaceFactory; /** * When the state is Idle. */ - void state_idle(EventData* data); + void state_idle(EventData *data); #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE /** * When the client starts bootstrap. */ - void state_bootstrap( EventData *data); + void state_bootstrap(EventData *data); /** * When the bootstrap server address is resolved. */ - void state_bootstrap_address_resolved( EventData *data); + void state_bootstrap_address_resolved(EventData *data); /** * When the bootstrap resource is created. */ - void state_bootstrap_resource_created( EventData *data); + void state_bootstrap_resource_created(EventData *data); /** * When the server has sent response and bootstrapping is done. */ - void state_bootstrapped( EventData *data); + void state_bootstrapped(EventData *data); #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE /** * When the client starts register. */ - void state_register( EventData *data); + void state_register(EventData *data); /** * When the server address for register is resolved. */ - void state_register_address_resolved( EventData *data); + void state_register_address_resolved(EventData *data); /** * When the client is registered. */ - void state_registered( EventData *data); + void state_registered(EventData *data); /** * When the client is updating registration. */ - void state_update_registration( EventData *data); + void state_update_registration(EventData *data); /** * When the client starts unregister. */ - void state_unregister( EventData *data); + void state_unregister(EventData *data); /** * When the client has been unregistered. */ - void state_unregistered( EventData *data); + void state_unregistered(EventData *data); /** * When the coap data is been sent through socket. */ - void state_sending_coap_data( EventData *data); + void state_sending_coap_data(EventData *data); /** * When the coap data is sent successfully. */ - void state_coap_data_sent( EventData *data); + void state_coap_data_sent(EventData *data); /** * When the socket is receiving coap data. */ - void state_receiving_coap_data( EventData *data); + void state_receiving_coap_data(EventData *data); /** * When the socket has received coap data. */ - void state_coap_data_received( EventData *data); + void state_coap_data_received(EventData *data); /** * When the coap message is being processed. */ - void state_processing_coap_data( EventData *data); + void state_processing_coap_data(EventData *data); /** * When the coap message has been processed. */ - void state_coap_data_processed( EventData *data); + void state_coap_data_processed(EventData *data); /** * When the client is waiting to receive or send data. */ - void state_waiting( EventData *data); + void state_waiting(EventData *data); /** * Start registration update. @@ -517,7 +528,7 @@ friend class M2MInterfaceFactory; * @param current_state Current state to be set. * @param data Data to be passed to the state function. */ - void state_function( uint8_t current_state, EventData* data ); + void state_function(uint8_t current_state, EventData *data); /** * @brief State Engine maintaining state machine logic. @@ -529,14 +540,14 @@ friend class M2MInterfaceFactory; * @param New The state to which the state machine should go. * @param data The data to be passed to the state machine. */ - void external_event(uint8_t, EventData* = NULL); + void external_event(uint8_t, EventData * = NULL); /** * Internal event generated by state machine. * @param New State which the state machine should go to. * @param data The data to be passed to the state machine. */ - void internal_event(uint8_t, EventData* = NULL); + void internal_event(uint8_t, EventData * = NULL); /** * Queue mode enabled or not. @@ -544,8 +555,7 @@ friend class M2MInterfaceFactory; */ bool queue_mode() const; - enum - { + enum { EVENT_IGNORED = 0xFE, CANNOT_HAPPEN }; @@ -557,7 +567,7 @@ friend class M2MInterfaceFactory; * @param ip_address The extracted IP. * @param port The extracted port. */ - static void process_address(const String& server_address, String& ip_address, uint16_t& port); + static void process_address(const String &server_address, String &ip_address, uint16_t &port); /** * Helper method for storing the error description to _error_description if the feature @@ -569,11 +579,26 @@ friend class M2MInterfaceFactory; /** * Helper method for creating random initial reconnection time interval. */ - void create_random_initial_reconnection_time(); + void create_random_initial_reconnection_time(); - void update_network_latency_configurations_with_rtt(); + void update_network_latency_configurations_with_rtt(); + + /** + * @brief Callback function which is called when POST comes to resource 1/0/4. Triggers de-registration. + * @param argument, Pointer to M2MResource::M2MExecuteParameter. + */ + void disable_callback(void *argument); + + /** + * @brief Callback function which is called when acknowledgement for the response to POST to resource 1/0/4 + * is received from server. + */ + static void post_response_status_handler(const M2MBase &base, + const M2MBase::MessageDeliveryStatus status, + const M2MBase::MessageType type, + void *me); - enum ReconnectionState{ + enum ReconnectionState { None, WithUpdate, Unregistration, @@ -582,40 +607,41 @@ friend class M2MInterfaceFactory; private: - EventData *_event_data; - uint16_t _server_port; - uint16_t _listen_port; - int32_t _life_time; - String _server_ip_address; - M2MSecurity *_register_server; //TODO: to be the list not owned - M2MTimer _queue_sleep_timer; - M2MTimer _retry_timer; - callback_handler _callback_handler; - const uint8_t _max_states; - bool _event_ignored; - bool _event_generated; - bool _reconnecting; - bool _retry_timer_expired; - bool _bootstrapped; - bool _bootstrap_finished; - bool _queue_mode_timer_ongoing; - uint8_t _current_state; - BindingMode _binding_mode; - ReconnectionState _reconnection_state; - M2MInterfaceObserver &_observer; - M2MConnectionSecurity *_security_connection; // Doesn't own - M2MConnectionHandler _connection_handler; - M2MNsdlInterface _nsdl_interface; - M2MSecurity *_security; + EventData *_event_data; + M2MConnectionObserver::SocketAddress _server_address; + uint16_t _server_port; + uint16_t _listen_port; + int32_t _life_time; + String _server_ip_address; + M2MSecurity *_register_server; //TODO: to be the list not owned + M2MTimer _queue_sleep_timer; + M2MTimer _retry_timer; + callback_handler _callback_handler; + const uint8_t _max_states; + bool _event_ignored; + bool _event_generated; + bool _reconnecting; + bool _retry_timer_expired; + bool _bootstrapped; + bool _bootstrap_finished; + bool _queue_mode_timer_ongoing; + uint8_t _current_state; + BindingMode _binding_mode; + ReconnectionState _reconnection_state; + M2MInterfaceObserver &_observer; + M2MConnectionSecurity *_security_connection; // Doesn't own + M2MConnectionHandler _connection_handler; + M2MNsdlInterface _nsdl_interface; + M2MSecurity *_security; #ifndef DISABLE_ERROR_DESCRIPTION // The DISABLE_ERROR_DESCRIPTION macro will reduce the flash usage by ~1800 bytes. - char _error_description[MAX_ALLOWED_ERROR_STRING_LENGTH]; + char _error_description[MAX_ALLOWED_ERROR_STRING_LENGTH]; #endif // Reconnection related variables (in seconds) - uint16_t _initial_reconnection_time; - uint32_t _reconnection_time; + uint16_t _initial_reconnection_time; + uint32_t _reconnection_time; friend class Test_M2MInterfaceImpl; diff --git a/mbed-client/source/include/m2mnsdlinterface.h b/mbed-client/source/include/m2mnsdlinterface.h index 0b98c0cb1..3cf133c02 100644 --- a/mbed-client/source/include/m2mnsdlinterface.h +++ b/mbed-client/source/include/m2mnsdlinterface.h @@ -89,6 +89,15 @@ class M2MNsdlInterface : public M2MTimerObserver, typedef NS_LIST_HEAD(coap_response_s, link) response_list_t; + /** + * Enum defining an Notification queue options + */ + typedef enum { + SEND_NOTIFICATION, // Send next notification + CLEAR_NOTIFICATION_TOKEN, // Clear notification token + REMOVE_NOTIFICATION // Remove notification from queue + } NotificationQueueOption; + /** * @brief Constructor * @param observer, Observer to pass the event callbacks from nsdl library. @@ -289,6 +298,18 @@ class M2MNsdlInterface : public M2MTimerObserver, */ void stop_timers(); + /** + * @brief Store alert mode state. + * @param alert Alert mode set or not. + */ + void set_alert_mode(bool alert); + + /** + * @brief Get the client alert mode status. + * @return True if client in alert mode otherwise False. + */ + bool alert_mode() const; + /** * @brief Returns nsdl handle. * @return ndsl handle @@ -325,7 +346,7 @@ class M2MNsdlInterface : public M2MTimerObserver, */ bool remove_object_from_list(M2MBase *base); - /* + /** * @brief Get NSDL timer. * @return NSDL execution timer. */ @@ -348,6 +369,11 @@ class M2MNsdlInterface : public M2MTimerObserver, */ void start_nsdl_execution_timer(); + /** + * @brief Stops the NSDL execution timer. + */ + void stop_nsdl_execution_timer(); + /** * @brief Returns security object. * @return M2MSecurity object, contains lwm2m server information. @@ -383,7 +409,7 @@ class M2MNsdlInterface : public M2MTimerObserver, /** * @brief Send next notification message. */ - void send_next_notification(bool clear_token); + void send_next_notification(NotificationQueueOption option); #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE /** @@ -463,6 +489,13 @@ class M2MNsdlInterface : public M2MTimerObserver, */ void set_cid_value(const uint8_t *data_ptr, const size_t data_len); + /** + * Helper method called from lifetime_write_callback. + * \param buffer Data holding lifetime value. + * \param buffer_size Size of the buffer. + */ + bool update_server_lifetime(const uint8_t *buffer, const size_t buffer_size); + protected: // from M2MTimerObserver virtual void timer_expired(M2MTimerObserver::Type type); @@ -664,7 +697,7 @@ class M2MNsdlInterface : public M2MTimerObserver, bool lifetime_value_changed() const; - void execute_notification_delivery_status_cb(M2MBase *object, int32_t msgid); + void handle_observation_response(M2MBase *object, int32_t msgid); bool is_response_to_request(const sn_coap_hdr_s *coap_header, struct request_context_s &get_data); @@ -685,7 +718,8 @@ class M2MNsdlInterface : public M2MTimerObserver, * @param clear_token, Flag to indicate whether observation token should be cleared. * @return True if notification sent, false otherwise or if send already in progress */ - bool send_next_notification_for_object(M2MObject &object, bool clear_token); + bool send_next_notification_for_object(M2MObject &object, NotificationQueueOption option); + bool handle_notification_queue(M2MObject &object, NotificationQueueOption option); static char *parse_uri_query_parameters(char *uri); @@ -706,7 +740,7 @@ class M2MNsdlInterface : public M2MTimerObserver, void handle_request_response(const sn_coap_hdr_s *coap_header, struct request_context_s *request_context); - void handle_message_delivered(M2MBase *base, const M2MBase::MessageType type); + void handle_message_status_callback(M2MBase *base, const M2MBase::MessageType type, const M2MBase::MessageDeliveryStatus status); void handle_empty_ack(const sn_coap_hdr_s *coap_header, bool is_bootstrap_msg); @@ -779,6 +813,9 @@ class M2MNsdlInterface : public M2MTimerObserver, M2MTimer _download_retry_timer; uint32_t _download_retry_time; uint8_t _network_rtt_estimate; + bool _alert_mode; + NotificationQueueOption _last_notif_queue_event; + sn_coap_msg_code_e _current_request_code; friend class Test_M2MNsdlInterface; diff --git a/mbed-client/source/include/m2mreporthandler.h b/mbed-client/source/include/m2mreporthandler.h index 769d79194..f832bc5da 100644 --- a/mbed-client/source/include/m2mreporthandler.h +++ b/mbed-client/source/include/m2mreporthandler.h @@ -277,6 +277,11 @@ class M2MReportHandler */ void start_timers(); + /** + * @brief Stop pmin & pmax timers. + */ + void stop_timers(); + protected : // from M2MTimerObserver virtual void timer_expired(M2MTimerObserver::Type type = @@ -310,10 +315,7 @@ protected : // from M2MTimerObserver */ bool check_attribute_validity() const; - /** - * @brief Stop pmin & pmax timers. - */ - void stop_timers(); + /** * @brief Check if current value match threshold values. diff --git a/mbed-client/source/include/m2mtlvdeserializer.h b/mbed-client/source/include/m2mtlvdeserializer.h index c926f0eaa..20a547a5c 100644 --- a/mbed-client/source/include/m2mtlvdeserializer.h +++ b/mbed-client/source/include/m2mtlvdeserializer.h @@ -34,7 +34,8 @@ public : NotFound, NotAllowed, NotValid, - OutOfMemory + OutOfMemory, + NotAccepted } Error; typedef enum { @@ -97,6 +98,15 @@ public : M2MObjectInstance &object_instance, M2MTLVDeserializer::Operation operation); + /** + * Deserialises the given binary that must encode a resource. Binary array + * can be checked before invoking this method. + */ + static M2MTLVDeserializer::Error deserialize_resource(const uint8_t *tlv, + uint32_t tlv_size, + M2MResource &resource, + M2MTLVDeserializer::Operation operation); + /** * Deserialises the given binary that must encode resource instances. Binary array * can be checked before invoking this method. @@ -128,6 +138,12 @@ public : M2MTLVDeserializer::Operation operation, bool update_value); + static M2MTLVDeserializer::Error deserialize_resource(const uint8_t *tlv, + uint32_t tlv_size, + M2MResource &resource, + M2MTLVDeserializer::Operation operation, + bool update_value); + static M2MTLVDeserializer::Error deserialize_resource_instances(const uint8_t *tlv, uint32_t tlv_size, uint32_t offset, diff --git a/mbed-client/source/m2mbase.cpp b/mbed-client/source/m2mbase.cpp index 6383a2a54..545e14209 100644 --- a/mbed-client/source/m2mbase.cpp +++ b/mbed-client/source/m2mbase.cpp @@ -142,6 +142,7 @@ M2MBase::~M2MBase() delete callback; M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2); + M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseMessageDeliveryStatusCallback); #ifdef ENABLE_ASYNC_REST_RESPONSE M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseAsyncCoapRequestCallback); #endif @@ -1019,7 +1020,7 @@ bool M2MBase::is_blockwise_needed(const nsdl_s *nsdl, uint32_t payload_len) return false; } } -void M2MBase::cancel_observation(M2MBase::MessageDeliveryStatus status) +void M2MBase::cancel_observation(M2MBase::MessageDeliveryStatus status, bool notify) { tr_info("M2MBase::cancel_observation()"); @@ -1047,7 +1048,9 @@ void M2MBase::cancel_observation(M2MBase::MessageDeliveryStatus status) _report_handler->set_under_observation(false); } - send_message_delivery_status(*this, status, M2MBase::NOTIFICATION); + if (notify) { + send_message_delivery_status(*this, status, M2MBase::NOTIFICATION); + } } void M2MBase::handle_observation(nsdl_s *nsdl, diff --git a/mbed-client/source/m2mcallbackstorage.cpp b/mbed-client/source/m2mcallbackstorage.cpp index 337f299ca..36ea7ebca 100644 --- a/mbed-client/source/m2mcallbackstorage.cpp +++ b/mbed-client/source/m2mcallbackstorage.cpp @@ -18,6 +18,7 @@ #include + // Dummy constructor, which does not init any value to something meaningful but needed for array construction. // It is better to leave values unintialized, so the Valgrind will point out if the Vector is used without // setting real values in there. @@ -48,9 +49,13 @@ void M2MCallbackStorage::delete_instance() M2MCallbackStorage::~M2MCallbackStorage() { - // TODO: go through the list and delete all the FP objects if there are any. - // On the other hand, if the system is done properly, each m2mobject should actually + // Go through the list and delete all the FP objects if there are any. + // If the system is done properly, each m2mobject should actually // remove its callbacks from its destructor so there is nothing here to do + // find any association to given object and delete them from the vector + for (int index = _callbacks.size()-1; index >=0; index --) { + _callbacks.erase(index); + } } bool M2MCallbackStorage::add_callback(const M2MBase &object, @@ -72,13 +77,12 @@ bool M2MCallbackStorage::do_add_callback(const M2MBase &object, void *callback, bool add_success = false; // verify that the same callback is not re-added. - if (does_callback_exist(object, callback, type) == false) { + if (!does_callback_exist(object, callback, type)) { const M2MCallbackAssociation association(&object, callback, type, client_args); _callbacks.push_back(association); add_success = true; } - return add_success; } @@ -109,11 +113,9 @@ void M2MCallbackStorage::do_remove_callbacks(const M2MBase &object) void* M2MCallbackStorage::remove_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type) { void* callback = NULL; - // do not use the get_instance() here as it might create the instance M2MCallbackStorage* instance = M2MCallbackStorage::_static_instance; if (instance) { - callback = instance->do_remove_callback(object, type); } return callback; @@ -127,7 +129,6 @@ void* M2MCallbackStorage::do_remove_callback(const M2MBase &object, M2MCallbackA if ((_callbacks[index]._object == &object) && (_callbacks[index]._type == type)) { callback = _callbacks[index]._callback; _callbacks.erase(index); - break; } } return callback; diff --git a/mbed-client/source/m2mdevice.cpp b/mbed-client/source/m2mdevice.cpp index d5c2588d1..2f5edeb3f 100644 --- a/mbed-client/source/m2mdevice.cpp +++ b/mbed-client/source/m2mdevice.cpp @@ -24,11 +24,11 @@ #define BUFFER_SIZE 21 #define TRACE_GROUP "mClt" -M2MDevice* M2MDevice::_instance = NULL; +M2MDevice *M2MDevice::_instance = NULL; -M2MDevice* M2MDevice::get_instance() +M2MDevice *M2MDevice::get_instance() { - if(_instance == NULL) { + if (_instance == NULL) { // ownership of this path is transferred to M2MBase. // Since this object is a singleton, we could use the C-structs to avoid heap // allocation on a lot of M2MDevice -objects data. @@ -47,32 +47,31 @@ void M2MDevice::delete_instance() } M2MDevice::M2MDevice(char *path) -: M2MObject(M2M_DEVICE_ID, path) + : M2MObject(M2M_DEVICE_ID, path) { M2MBase::set_register_uri(false); M2MBase::set_operation(M2MBase::GET_ALLOWED); _device_instance = M2MObject::create_object_instance(); - if(_device_instance) { + if (_device_instance) { _device_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED); _device_instance->set_register_uri(false); _device_instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); _device_instance->set_observable(true); // this object instance has observable resources so also obj inst should be observable - M2MResource* res = _device_instance->create_dynamic_resource(DEVICE_REBOOT, + M2MResource *res = _device_instance->create_dynamic_resource(DEVICE_REBOOT, OMA_RESOURCE_TYPE, M2MResourceInstance::OPAQUE, false); - if(res) { + if (res) { res->set_operation(M2MBase::POST_ALLOWED); res->set_register_uri(true); } - M2MResourceInstance* instance = _device_instance->create_dynamic_resource_instance(DEVICE_ERROR_CODE, - OMA_RESOURCE_TYPE, - M2MResourceInstance::INTEGER, - true,0); - if(instance) { - M2MResource *dev_res = _device_instance->resource(DEVICE_ERROR_CODE); + M2MResourceInstance *instance = _device_instance->create_dynamic_resource_instance(DEVICE_ERROR_CODE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true, 0); + if (instance) { instance->set_operation(M2MBase::GET_ALLOWED); instance->set_value(0); instance->set_register_uri(true); @@ -82,9 +81,9 @@ M2MDevice::M2MDevice(char *path) OMA_RESOURCE_TYPE, M2MResourceInstance::STRING, true); - if(res) { + if (res) { res->set_operation(M2MBase::GET_ALLOWED); - res->set_value((const uint8_t*)BINDING_MODE_UDP,sizeof(BINDING_MODE_UDP)-1); + res->set_value((const uint8_t *)BINDING_MODE_UDP, sizeof(BINDING_MODE_UDP) - 1); res->set_register_uri(true); } } @@ -94,16 +93,16 @@ M2MDevice::~M2MDevice() { } -M2MResource* M2MDevice::create_resource(DeviceResource resource, const String &value) +M2MResource *M2MDevice::create_resource(DeviceResource resource, const String &value) { - M2MResource* res = NULL; - const char* device_id_ptr = ""; + M2MResource *res = NULL; + const char *device_id_ptr = ""; M2MBase::Operation operation = M2MBase::GET_ALLOWED; - if(!is_resource_present(resource) && value.size() <= MAX_ALLOWED_STRING_LENGTH) { - switch(resource) { + if (!is_resource_present(resource) && value.size() <= MAX_ALLOWED_STRING_LENGTH) { + switch (resource) { case Manufacturer: - device_id_ptr = DEVICE_MANUFACTURER; - break; + device_id_ptr = DEVICE_MANUFACTURER; + break; case DeviceType: device_id_ptr = DEVICE_DEVICE_TYPE; break; @@ -136,19 +135,19 @@ M2MResource* M2MDevice::create_resource(DeviceResource resource, const String &v } const String device_id(device_id_ptr); - if(!device_id.empty()) { - if(_device_instance) { + if (!device_id.empty()) { + if (_device_instance) { res = _device_instance->create_dynamic_resource(device_id, OMA_RESOURCE_TYPE, M2MResourceInstance::STRING, true); - if(res ) { + if (res) { res->set_operation(operation); if (value.empty()) { res->clear_value(); } else { - res->set_value((const uint8_t*)value.c_str(), + res->set_value((const uint8_t *)value.c_str(), (uint32_t)value.length()); } res->set_register_uri(true); @@ -158,48 +157,48 @@ M2MResource* M2MDevice::create_resource(DeviceResource resource, const String &v return res; } -M2MResource* M2MDevice::create_resource(DeviceResource resource, int64_t value) +M2MResource *M2MDevice::create_resource(DeviceResource resource, int64_t value) { - M2MResource* res = NULL; - const char* device_id_ptr = ""; + M2MResource *res = NULL; + const char *device_id_ptr = ""; M2MBase::Operation operation = M2MBase::GET_ALLOWED; - if(!is_resource_present(resource)) { - switch(resource) { - case BatteryLevel: - if(check_value_range(resource, value)) { - device_id_ptr = DEVICE_BATTERY_LEVEL; - } - break; - case BatteryStatus: - if(check_value_range(resource, value)) { - device_id_ptr = DEVICE_BATTERY_STATUS; - } - break; - case MemoryFree: - device_id_ptr = DEVICE_MEMORY_FREE; - break; - case MemoryTotal: - device_id_ptr = DEVICE_MEMORY_TOTAL; - break; - case CurrentTime: - device_id_ptr = DEVICE_CURRENT_TIME; - operation = M2MBase::GET_PUT_ALLOWED; - break; - default: - break; + if (!is_resource_present(resource)) { + switch (resource) { + case BatteryLevel: + if (check_value_range(resource, value)) { + device_id_ptr = DEVICE_BATTERY_LEVEL; + } + break; + case BatteryStatus: + if (check_value_range(resource, value)) { + device_id_ptr = DEVICE_BATTERY_STATUS; + } + break; + case MemoryFree: + device_id_ptr = DEVICE_MEMORY_FREE; + break; + case MemoryTotal: + device_id_ptr = DEVICE_MEMORY_TOTAL; + break; + case CurrentTime: + device_id_ptr = DEVICE_CURRENT_TIME; + operation = M2MBase::GET_PUT_ALLOWED; + break; + default: + break; } } const String device_id(device_id_ptr); - if(!device_id.empty()) { - if(_device_instance) { + if (!device_id.empty()) { + if (_device_instance) { res = _device_instance->create_dynamic_resource(device_id, OMA_RESOURCE_TYPE, M2MResourceInstance::INTEGER, true); - if(res) { + if (res) { res->set_operation(operation); @@ -212,39 +211,39 @@ M2MResource* M2MDevice::create_resource(DeviceResource resource, int64_t value) return res; } -M2MResourceInstance* M2MDevice::create_resource_instance(DeviceResource resource, int64_t value, - uint16_t instance_id) +M2MResourceInstance *M2MDevice::create_resource_instance(DeviceResource resource, int64_t value, + uint16_t instance_id) { - M2MResourceInstance* res_instance = NULL; - const char* device_id_ptr = ""; + M2MResourceInstance *res_instance = NULL; + const char *device_id_ptr = ""; // For these resources multiple instance can exist - if(AvailablePowerSources == resource) { - if(check_value_range(resource, value)) { + if (AvailablePowerSources == resource) { + if (check_value_range(resource, value)) { device_id_ptr = DEVICE_AVAILABLE_POWER_SOURCES; } - } else if(PowerSourceVoltage == resource) { + } else if (PowerSourceVoltage == resource) { device_id_ptr = DEVICE_POWER_SOURCE_VOLTAGE; - } else if(PowerSourceCurrent == resource) { + } else if (PowerSourceCurrent == resource) { device_id_ptr = DEVICE_POWER_SOURCE_CURRENT; - } else if(ErrorCode == resource) { - if(check_value_range(resource, value)) { + } else if (ErrorCode == resource) { + if (check_value_range(resource, value)) { device_id_ptr = DEVICE_ERROR_CODE; } } const String device_id(device_id_ptr); - if(!device_id.empty()) { - if(_device_instance) { - res_instance = _device_instance->create_dynamic_resource_instance(device_id,OMA_RESOURCE_TYPE, - M2MResourceInstance::INTEGER, - true, instance_id); + if (!device_id.empty()) { + if (_device_instance) { + res_instance = _device_instance->create_dynamic_resource_instance(device_id, OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true, instance_id); M2MResource *res = _device_instance->resource(device_id); - if(res) { + if (res) { res->set_register_uri(true); } - if(res_instance) { + if (res_instance) { res_instance->set_value(value); // Only read operation is allowed for above resources res_instance->set_operation(M2MBase::GET_ALLOWED); @@ -254,24 +253,24 @@ M2MResourceInstance* M2MDevice::create_resource_instance(DeviceResource resource } return res_instance; } -M2MResource* M2MDevice::create_resource(DeviceResource resource) +M2MResource *M2MDevice::create_resource(DeviceResource resource) { - M2MResource* res = NULL; - if(!is_resource_present(resource)) { - const char* device_Id_ptr = ""; - if(FactoryReset == resource) { + M2MResource *res = NULL; + if (!is_resource_present(resource)) { + const char *device_Id_ptr = ""; + if (FactoryReset == resource) { device_Id_ptr = DEVICE_FACTORY_RESET; - } else if(ResetErrorCode == resource) { + } else if (ResetErrorCode == resource) { device_Id_ptr = DEVICE_RESET_ERROR_CODE; } const String device_Id(device_Id_ptr); - if(_device_instance && !device_Id.empty()) { + if (_device_instance && !device_Id.empty()) { res = _device_instance->create_dynamic_resource(device_Id, OMA_RESOURCE_TYPE, M2MResourceInstance::OPAQUE, false); - if(res) { + if (res) { res->set_operation(M2MBase::POST_ALLOWED); res->set_register_uri(true); @@ -290,10 +289,10 @@ M2MResource* M2MDevice::create_resource(DeviceResource resource) bool M2MDevice::delete_resource(DeviceResource resource) { bool success = false; - if(M2MDevice::Reboot != resource && - M2MDevice::ErrorCode != resource && - M2MDevice::SupportedBindingMode != resource) { - if(_device_instance) { + if (M2MDevice::Reboot != resource && + M2MDevice::ErrorCode != resource && + M2MDevice::SupportedBindingMode != resource) { + if (_device_instance) { success = _device_instance->remove_resource(resource_name(resource)); } } @@ -304,11 +303,11 @@ bool M2MDevice::delete_resource_instance(DeviceResource resource, uint16_t instance_id) { bool success = false; - if(M2MDevice::Reboot != resource && - M2MDevice::ErrorCode != resource && - M2MDevice::SupportedBindingMode != resource) { - if(_device_instance) { - success = _device_instance->remove_resource_instance(resource_name(resource),instance_id); + if (M2MDevice::Reboot != resource && + M2MDevice::ErrorCode != resource && + M2MDevice::SupportedBindingMode != resource) { + if (_device_instance) { + success = _device_instance->remove_resource_instance(resource_name(resource), instance_id); } } return success; @@ -319,45 +318,45 @@ bool M2MDevice::set_resource_value(DeviceResource resource, uint16_t instance_id) { bool success = false; - M2MResourceBase* res = get_resource_instance(resource, instance_id); - if(res && value.size() <= MAX_ALLOWED_STRING_LENGTH) { - if(M2MDevice::Manufacturer == resource || - M2MDevice::ModelNumber == resource || - M2MDevice::DeviceType == resource || - M2MDevice::SerialNumber == resource || - M2MDevice::HardwareVersion == resource || - M2MDevice::FirmwareVersion == resource || - M2MDevice::SoftwareVersion == resource || - M2MDevice::UTCOffset == resource || - M2MDevice::Timezone == resource || - M2MDevice::SupportedBindingMode == resource) { - if (value.empty()) { - res->clear_value(); - success = true; - } else { - success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length()); - } + M2MResourceBase *res = get_resource_instance(resource, instance_id); + if (res && value.size() <= MAX_ALLOWED_STRING_LENGTH) { + if (M2MDevice::Manufacturer == resource || + M2MDevice::ModelNumber == resource || + M2MDevice::DeviceType == resource || + M2MDevice::SerialNumber == resource || + M2MDevice::HardwareVersion == resource || + M2MDevice::FirmwareVersion == resource || + M2MDevice::SoftwareVersion == resource || + M2MDevice::UTCOffset == resource || + M2MDevice::Timezone == resource || + M2MDevice::SupportedBindingMode == resource) { + if (value.empty()) { + res->clear_value(); + success = true; + } else { + success = res->set_value((const uint8_t *)value.c_str(), (uint32_t)value.length()); + } } } return success; } bool M2MDevice::set_resource_value(DeviceResource resource, - int64_t value, - uint16_t instance_id) + int64_t value, + uint16_t instance_id) { bool success = false; - M2MResourceBase* res = get_resource_instance(resource, instance_id); - if(res) { - if(M2MDevice::BatteryLevel == resource || - M2MDevice::BatteryStatus == resource || - M2MDevice::MemoryFree == resource || - M2MDevice::MemoryTotal == resource || - M2MDevice::ErrorCode == resource || - M2MDevice::CurrentTime == resource || - M2MDevice::AvailablePowerSources == resource || - M2MDevice::PowerSourceVoltage == resource || - M2MDevice::PowerSourceCurrent == resource) { + M2MResourceBase *res = get_resource_instance(resource, instance_id); + if (res) { + if (M2MDevice::BatteryLevel == resource || + M2MDevice::BatteryStatus == resource || + M2MDevice::MemoryFree == resource || + M2MDevice::MemoryTotal == resource || + M2MDevice::ErrorCode == resource || + M2MDevice::CurrentTime == resource || + M2MDevice::AvailablePowerSources == resource || + M2MDevice::PowerSourceVoltage == resource || + M2MDevice::PowerSourceCurrent == resource) { // If it is any of the above resource // set the value of the resource. if (check_value_range(resource, value)) { @@ -373,18 +372,18 @@ String M2MDevice::resource_value_string(DeviceResource resource, uint16_t instance_id) const { String value = ""; - const M2MResourceBase* res = get_resource_instance(resource, instance_id); - if(res) { - if(M2MDevice::Manufacturer == resource || - M2MDevice::ModelNumber == resource || - M2MDevice::DeviceType == resource || - M2MDevice::SerialNumber == resource || - M2MDevice::HardwareVersion == resource || - M2MDevice::FirmwareVersion == resource || - M2MDevice::SoftwareVersion == resource || - M2MDevice::UTCOffset == resource || - M2MDevice::Timezone == resource || - M2MDevice::SupportedBindingMode == resource) { + const M2MResourceBase *res = get_resource_instance(resource, instance_id); + if (res) { + if (M2MDevice::Manufacturer == resource || + M2MDevice::ModelNumber == resource || + M2MDevice::DeviceType == resource || + M2MDevice::SerialNumber == resource || + M2MDevice::HardwareVersion == resource || + M2MDevice::FirmwareVersion == resource || + M2MDevice::SoftwareVersion == resource || + M2MDevice::UTCOffset == resource || + M2MDevice::Timezone == resource || + M2MDevice::SupportedBindingMode == resource) { value = res->get_value_string(); @@ -397,17 +396,17 @@ int64_t M2MDevice::resource_value_int(DeviceResource resource, uint16_t instance_id) const { int64_t value = -1; - M2MResourceBase* res = get_resource_instance(resource, instance_id); - if(res) { - if(M2MDevice::BatteryLevel == resource || - M2MDevice::BatteryStatus == resource || - M2MDevice::MemoryFree == resource || - M2MDevice::MemoryTotal == resource || - M2MDevice::ErrorCode == resource || - M2MDevice::CurrentTime == resource || - M2MDevice::AvailablePowerSources == resource || - M2MDevice::PowerSourceVoltage == resource || - M2MDevice::PowerSourceCurrent == resource) { + M2MResourceBase *res = get_resource_instance(resource, instance_id); + if (res) { + if (M2MDevice::BatteryLevel == resource || + M2MDevice::BatteryStatus == resource || + M2MDevice::MemoryFree == resource || + M2MDevice::MemoryTotal == resource || + M2MDevice::ErrorCode == resource || + M2MDevice::CurrentTime == resource || + M2MDevice::AvailablePowerSources == resource || + M2MDevice::PowerSourceVoltage == resource || + M2MDevice::PowerSourceCurrent == resource) { // note: the value may be 32bit int on 32b archs. value = res->get_value_int(); @@ -419,8 +418,8 @@ int64_t M2MDevice::resource_value_int(DeviceResource resource, bool M2MDevice::is_resource_present(DeviceResource resource) const { bool success = false; - const M2MResourceBase* res = get_resource_instance(resource,0); - if(res) { + const M2MResourceBase *res = get_resource_instance(resource, 0); + if (res) { success = true; } return success; @@ -429,7 +428,7 @@ bool M2MDevice::is_resource_present(DeviceResource resource) const uint16_t M2MDevice::per_resource_count(DeviceResource res) const { uint16_t count = 0; - if(_device_instance) { + if (_device_instance) { count = _device_instance->resource_count(resource_name(res)); } return count; @@ -438,22 +437,22 @@ uint16_t M2MDevice::per_resource_count(DeviceResource res) const uint16_t M2MDevice::total_resource_count() const { uint16_t count = 0; - if(_device_instance) { + if (_device_instance) { count = _device_instance->resources().size(); } return count; } -M2MResourceBase* M2MDevice::get_resource_instance(DeviceResource dev_res, - uint16_t instance_id) const +M2MResourceBase *M2MDevice::get_resource_instance(DeviceResource dev_res, + uint16_t instance_id) const { - M2MResource* res = NULL; - M2MResourceBase* inst = NULL; - if(_device_instance) { + M2MResource *res = NULL; + M2MResourceBase *inst = NULL; + if (_device_instance) { res = _device_instance->resource(resource_name(dev_res)); - if(res) { - if(res->supports_multiple_instances()) { - inst = res->resource_instance(instance_id); + if (res) { + if (res->supports_multiple_instances()) { + inst = res->resource_instance(instance_id); } else { inst = res; } @@ -462,10 +461,10 @@ M2MResourceBase* M2MDevice::get_resource_instance(DeviceResource dev_res, return inst; } -const char* M2MDevice::resource_name(DeviceResource resource) +const char *M2MDevice::resource_name(DeviceResource resource) { - const char* res_name = ""; - switch(resource) { + const char *res_name = ""; + switch (resource) { case Manufacturer: res_name = DEVICE_MANUFACTURER; break; @@ -541,7 +540,7 @@ bool M2MDevice::check_value_range(DeviceResource resource, int64_t value) bool success = false; switch (resource) { case AvailablePowerSources: - if(value >= 0 && value <= 7) { + if (value >= 0 && value <= 7) { success = true; } break; @@ -560,9 +559,9 @@ bool M2MDevice::check_value_range(DeviceResource resource, int64_t value) success = true; } break; - default: - success = true; - break; + default: + success = true; + break; } return success; } diff --git a/mbed-client/source/m2minterfacefactory.cpp b/mbed-client/source/m2minterfacefactory.cpp index 05fdcd41f..fc00fd7e1 100644 --- a/mbed-client/source/m2minterfacefactory.cpp +++ b/mbed-client/source/m2minterfacefactory.cpp @@ -34,7 +34,7 @@ #define TRACE_GROUP "mClt" -M2MInterface* M2MInterfaceFactory::create_interface(M2MInterfaceObserver &observer, +M2MInterface *M2MInterfaceFactory::create_interface(M2MInterfaceObserver &observer, const String &endpoint_name, const String &endpoint_type, const int32_t life_time, @@ -46,77 +46,77 @@ M2MInterface* M2MInterfaceFactory::create_interface(M2MInterfaceObserver &observ const String &version) { tr_debug("M2MInterfaceFactory::create_interface - IN"); - tr_info("M2MInterfaceFactory::create_interface - parameters endpoint name : %s",endpoint_name.c_str()); - tr_info("M2MInterfaceFactory::create_interface - parameters endpoint type : %s",endpoint_type.c_str()); - tr_info("M2MInterfaceFactory::create_interface - parameters life time(in secs): %" PRId32,life_time); - tr_info("M2MInterfaceFactory::create_interface - parameters Listen Port : %d",listen_port); - tr_info("M2MInterfaceFactory::create_interface - parameters Binding Mode : %d",(int)mode); - tr_info("M2MInterfaceFactory::create_interface - parameters NetworkStack : %d",(int)stack); - tr_info("M2MInterfaceFactory::create_interface - parameters version : %s",version.c_str()); + tr_info("M2MInterfaceFactory::create_interface - parameters endpoint name : %s", endpoint_name.c_str()); + tr_info("M2MInterfaceFactory::create_interface - parameters endpoint type : %s", endpoint_type.c_str()); + tr_info("M2MInterfaceFactory::create_interface - parameters life time(in secs): %" PRId32, life_time); + tr_info("M2MInterfaceFactory::create_interface - parameters Listen Port : %d", listen_port); + tr_info("M2MInterfaceFactory::create_interface - parameters Binding Mode : %d", (int)mode); + tr_info("M2MInterfaceFactory::create_interface - parameters NetworkStack : %d", (int)stack); + tr_info("M2MInterfaceFactory::create_interface - parameters version : %s", version.c_str()); M2MInterfaceImpl *interface = NULL; bool endpoint_type_valid = true; - if(!endpoint_type.empty()) { - if(endpoint_type.size() > MAX_ALLOWED_STRING_LENGTH){ + if (!endpoint_type.empty()) { + if (endpoint_type.size() > MAX_ALLOWED_STRING_LENGTH) { endpoint_type_valid = false; } } bool domain_valid = true; - if(!domain.empty()) { - if(domain.size() > MAX_ALLOWED_STRING_LENGTH){ + if (!domain.empty()) { + if (domain.size() > MAX_ALLOWED_STRING_LENGTH) { domain_valid = false; } } bool version_valid = true; - if(!version.empty()) { - if(version.size() > MAX_ALLOWED_STRING_LENGTH){ + if (!version.empty()) { + if (version.size() > MAX_ALLOWED_STRING_LENGTH) { version_valid = false; } } - if(((life_time == -1) || (life_time >= MINIMUM_REGISTRATION_TIME)) && - !endpoint_name.empty() && (endpoint_name.size() <= MAX_ALLOWED_STRING_LENGTH) && - endpoint_type_valid && domain_valid && version_valid) { + if (((life_time == -1) || (life_time >= MINIMUM_REGISTRATION_TIME)) && + !endpoint_name.empty() && (endpoint_name.size() <= MAX_ALLOWED_STRING_LENGTH) && + endpoint_type_valid && domain_valid && version_valid) { tr_debug("M2MInterfaceFactory::create_interface - Creating M2MInterfaceImpl"); interface = new M2MInterfaceImpl(observer, endpoint_name, - endpoint_type, life_time, - listen_port, domain, mode, - stack, context_address, - version); + endpoint_type, life_time, + listen_port, domain, mode, + stack, context_address, + version); } tr_debug("M2MInterfaceFactory::create_interface - OUT"); return interface; } -M2MSecurity* M2MInterfaceFactory::create_security(M2MSecurity::ServerType server_type) +M2MSecurity *M2MInterfaceFactory::create_security(M2MSecurity::ServerType server_type) { tr_debug("M2MInterfaceFactory::create_security"); M2MSecurity *security = M2MSecurity::get_instance(); return security; } -M2MServer* M2MInterfaceFactory::create_server() +M2MServer *M2MInterfaceFactory::create_server() { tr_debug("M2MInterfaceFactory::create_server"); M2MServer *server = new M2MServer(); return server; } -M2MDevice* M2MInterfaceFactory::create_device() +M2MDevice *M2MInterfaceFactory::create_device() { tr_debug("M2MInterfaceFactory::create_device"); - M2MDevice* device = M2MDevice::get_instance(); + M2MDevice *device = M2MDevice::get_instance(); return device; } -M2MObject* M2MInterfaceFactory::create_object(const String &name) +M2MObject *M2MInterfaceFactory::create_object(const String &name) { tr_debug("M2MInterfaceFactory::create_object : Name : %s", name.c_str()); - if(name.size() > MAX_ALLOWED_STRING_LENGTH || name.empty()){ + if (name.size() > MAX_ALLOWED_STRING_LENGTH || name.empty()) { return NULL; } @@ -128,13 +128,13 @@ M2MObject* M2MInterfaceFactory::create_object(const String &name) return object; } -M2MObject* M2MInterfaceFactory::find_or_create_object(M2MObjectList &object_list, +M2MObject *M2MInterfaceFactory::find_or_create_object(M2MObjectList &object_list, const uint16_t object_id, bool &object_created) { // Check list for existing object object_created = false; - for (int i=0; iname_id() == object_id) { tr_debug("Found existing /%" PRIu16, object_id); return object_list[i]; @@ -157,7 +157,7 @@ M2MObject* M2MInterfaceFactory::find_or_create_object(M2MObjectList &object_list return object; } -M2MObjectInstance* M2MInterfaceFactory::find_or_create_object_instance(M2MObject &object, +M2MObjectInstance *M2MInterfaceFactory::find_or_create_object_instance(M2MObject &object, const uint16_t object_instance_id, bool &object_instance_created) { @@ -173,7 +173,7 @@ M2MObjectInstance* M2MInterfaceFactory::find_or_create_object_instance(M2MObject if (object_instance == NULL) { object_instance = object.create_object_instance(object_instance_id); if (object_instance == NULL) { - tr_err("Couldn't create /%d/%" PRIu16 " (out of memory?)", object.name_id(), object_instance_id); + tr_err("Couldn't create /%" PRId32 "s/%" PRIu16 " (out of memory?)", object.name_id(), object_instance_id); return NULL; } } @@ -184,7 +184,7 @@ M2MObjectInstance* M2MInterfaceFactory::find_or_create_object_instance(M2MObject return object_instance; } -M2MResource* M2MInterfaceFactory::find_or_create_resource(M2MObjectInstance &object_instance, +M2MResource *M2MInterfaceFactory::find_or_create_resource(M2MObjectInstance &object_instance, const uint16_t resource_id, const M2MResourceInstance::ResourceType resource_type, bool multiple_instance, @@ -194,7 +194,7 @@ M2MResource* M2MInterfaceFactory::find_or_create_resource(M2MObjectInstance &obj M2MResource *resource = object_instance.resource(resource_id); if (resource != NULL) { tr_debug("Found existing /%d/%d/%" PRIu16, - object_instance.get_parent_object().name_id(), object_instance.instance_id(), resource_id); + object_instance.get_parent_object().name_id(), object_instance.instance_id(), resource_id); return resource; } @@ -202,18 +202,18 @@ M2MResource* M2MInterfaceFactory::find_or_create_resource(M2MObjectInstance &obj resource = object_instance.create_dynamic_resource(resource_id, "", resource_type, true, multiple_instance, external_blockwise_store); if (resource == NULL) { - tr_err("Couldn't create /%d/%d/%" PRIu16 " (out of memory?)", - object_instance.get_parent_object().name_id(), object_instance.instance_id(), resource_id); + tr_err("Couldn't create /%" PRId32 "/%" PRIu16 "/%" PRIu16 " (out of memory?)", + object_instance.get_parent_object().name_id(), object_instance.instance_id(), resource_id); return NULL; } // All good tr_debug("Created new /%d/%d/%" PRIu16, - object_instance.get_parent_object().name_id(), object_instance.instance_id(), resource_id); + object_instance.get_parent_object().name_id(), object_instance.instance_id(), resource_id); return resource; } -M2MResource* M2MInterfaceFactory::create_resource(M2MObjectList &object_list, +M2MResource *M2MInterfaceFactory::create_resource(M2MObjectList &object_list, const uint16_t object_id, const uint16_t object_instance_id, const uint16_t resource_id, @@ -223,7 +223,7 @@ M2MResource* M2MInterfaceFactory::create_resource(M2MObjectList &object_list, bool external_blockwise_store) { tr_debug("M2MInterfaceFactory::create_resource() - creating /%" PRIu16 "/%" PRIu16 "/%" PRIu16, - object_id, object_instance_id, resource_id); + object_id, object_instance_id, resource_id); M2MObject *object; M2MObjectInstance *object_instance; @@ -240,7 +240,7 @@ M2MResource* M2MInterfaceFactory::create_resource(M2MObjectList &object_list, // Check and create object instance if necessary bool object_instance_created; object_instance = M2MInterfaceFactory::find_or_create_object_instance( - *object, object_instance_id, object_instance_created); + *object, object_instance_id, object_instance_created); if (object_instance == NULL) { tr_err("M2MInterfaceFactory::create_resource() - failed to get object instance"); goto cleanup_object; @@ -248,8 +248,8 @@ M2MResource* M2MInterfaceFactory::create_resource(M2MObjectList &object_list, // Check and create resource if necessary resource = M2MInterfaceFactory::find_or_create_resource( - *object_instance, resource_id, resource_type, - multiple_instance, external_blockwise_store); + *object_instance, resource_id, resource_type, + multiple_instance, external_blockwise_store); if (resource == NULL) { tr_err("M2MInterfaceFactory::create_resource() - failed to get resource"); goto cleanup_object_instance; @@ -277,15 +277,15 @@ M2MResource* M2MInterfaceFactory::create_resource(M2MObjectList &object_list, } #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION -M2MEndpoint* M2MInterfaceFactory::create_endpoint(const String &name) +M2MEndpoint *M2MInterfaceFactory::create_endpoint(const String &name) { tr_debug("M2MInterfaceFactory::create_endpoint : Name : %s", name.c_str()); - if(name.size() > MAX_ALLOWED_STRING_LENGTH || name.empty()){ + if (name.size() > MAX_ALLOWED_STRING_LENGTH || name.empty()) { return NULL; } M2MEndpoint *object = NULL; - char *path = (char*)malloc(2 + name.size() + 1); + char *path = (char *)malloc(2 + name.size() + 1); if (path) { // Prepend path with directory prefix "d/" so that all endpoints will be under common path path[0] = 'd'; diff --git a/mbed-client/source/m2minterfaceimpl.cpp b/mbed-client/source/m2minterfaceimpl.cpp index 06cc379e6..c99eba1ac 100644 --- a/mbed-client/source/m2minterfaceimpl.cpp +++ b/mbed-client/source/m2minterfaceimpl.cpp @@ -56,6 +56,7 @@ M2MInterfaceImpl::M2MInterfaceImpl(M2MInterfaceObserver &observer, const String &con_addr, const String &version) : _event_data(NULL), + _server_address{stack, NULL, 0, 0}, _server_port(0), _listen_port(listen_port), _life_time(l_time), @@ -99,9 +100,36 @@ M2MInterfaceImpl::M2MInterfaceImpl(M2MInterfaceObserver &observer, //Here we must use TCP still _connection_handler.bind_connection(_listen_port); + M2MResource *disable_res = get_m2mserver()->get_resource(M2MServer::Disable); + if (disable_res) { + disable_res->set_execute_function(execute_callback(this, &M2MInterfaceImpl::disable_callback)); + disable_res->set_delayed_response(true); + disable_res->set_message_delivery_status_cb(M2MInterfaceImpl::post_response_status_handler, this); + } + tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -OUT"); } +void M2MInterfaceImpl::post_response_status_handler(const M2MBase &base, + const M2MBase::MessageDeliveryStatus status, + const M2MBase::MessageType type, + void *me) +{ + if (status == M2MBase::MESSAGE_STATUS_DELIVERED && type == M2MBase::DELAYED_POST_RESPONSE) { + ((M2MInterfaceImpl *)me)->unregister_object(); + } +} + + +void M2MInterfaceImpl::disable_callback(void *) +{ + // Don't perform unregister yet, as server will not get response. Instead, send response and wait + // for acknowledgement before unregistering. + M2MResource *disable_res = get_m2mserver()->get_resource(M2MServer::Disable); + if (disable_res) { + disable_res->send_delayed_post_response(); + } +} M2MInterfaceImpl::~M2MInterfaceImpl() { @@ -273,7 +301,7 @@ void M2MInterfaceImpl::update_registration(M2MSecurity *security_object, void M2MInterfaceImpl::unregister_object(M2MSecurity * /*security*/) { tr_debug("M2MInterfaceImpl::unregister_object - IN - current state %d", _current_state); - if (_nsdl_interface.is_unregister_ongoing()) { + if (_nsdl_interface.is_unregister_ongoing() || _nsdl_interface.alert_mode()) { set_error_description(ERROR_REASON_27); _observer.error(M2MInterface::NotAllowed); return; @@ -387,6 +415,10 @@ void M2MInterfaceImpl::registration_error(uint8_t error_code, bool retry, bool f // else // Network issue, do not delete CID but continue reconnection logic (99%) tr_error("M2MInterfaceImpl::registration_error sending CLIENT HELLO PING"); + + // Make sure that FW download do resume after register update + _nsdl_interface.set_request_context_to_be_resend(NULL, 0); + _reconnection_state = M2MInterfaceImpl::ClientPing; _connection_handler.resolve_server_address(_server_ip_address, _server_port, M2MConnectionObserver::LWM2MServer, @@ -542,31 +574,12 @@ void M2MInterfaceImpl::data_available(uint8_t *data, { tr_debug("M2MInterfaceImpl::data_available"); if (_reconnection_state == M2MInterfaceImpl::ClientPing) { - tr_info("M2MInterfaceImpl::data_available() : Ping success, remove CID"); - // Lwm2m server has responded so it implies that CID has expired and - // thats why message sending had failed so delete CID and re-do connection with full handshake - if (_nsdl_interface.is_registered()) { - _reconnection_state = M2MInterfaceImpl::WithUpdate; - } else { - _reconnection_state = M2MInterfaceImpl::None; - } - - _connection_handler.remove_cid(); - // Update network stagger values as now device has to do full handshake for registration. - _nsdl_interface.update_network_rtt_estimate(); - - uint16_t rand_time = 10 + _nsdl_interface.get_network_stagger_estimate(false); - // The new timeout is randomized to + 10% and -10% range from original random value - randLIB_seed_random(); - rand_time = randLIB_randomise_base(rand_time, 0x7333, 0x8CCD); - - // Take in use the new timer. For single-device networks, reconnecting fast is the primary goal. - // For multidevice networks sharing same pipe should provide stagger_estimates. In such case we need to - // enforce that to prevent too large reconnection spike in the network. + tr_info("M2MInterfaceImpl::data_available() : Ping success"); + _server_address = address; + // There can't be delay between handshake finished and sending the first COAP message as server + // needs the first message after handshake to set handshake successful. So let's launch timer after 1ms. _retry_timer.stop_timer(); - _retry_timer.start_timer(rand_time * 1000, - M2MTimerObserver::RetryTimer); - + _retry_timer.start_timer(1, M2MTimerObserver::RetryTimer); return; } ReceivedData event; @@ -591,6 +604,13 @@ void M2MInterfaceImpl::socket_error(int error_code, bool retry) tr_error("M2MInterfaceImpl::socket_error: (%d), retry (%d), reconnecting (%d), reconnection_state (%d)", error_code, retry, _reconnecting, (int)_reconnection_state); + // Reconnection can't be done when in alert mode + if (_nsdl_interface.alert_mode()) { + tr_info("M2MInterfaceImpl::socket_error - in alert mode --> go to pause state"); + pause(); + return; + } + // Ignore errors while client is sleeping if (queue_mode()) { if (_callback_handler && _queue_mode_timer_ongoing) { @@ -598,8 +618,8 @@ void M2MInterfaceImpl::socket_error(int error_code, bool retry) return; } } - _queue_sleep_timer.stop_timer(); + _queue_sleep_timer.stop_timer(); _retry_timer.stop_timer(); const char *error_code_des; @@ -647,6 +667,8 @@ void M2MInterfaceImpl::socket_error(int error_code, bool retry) // Do a reconnect if (retry) { + _nsdl_interface.set_registration_status(false); + if ((error == M2MInterface::SecureConnectionFailed || error == M2MInterface::InvalidParameters) && _bootstrapped) { // Connector client will start the bootstrap flow again @@ -655,7 +677,6 @@ void M2MInterfaceImpl::socket_error(int error_code, bool retry) return; } - _nsdl_interface.set_request_context_to_be_resend(NULL, 0); _reconnecting = true; _connection_handler.stop_listening(); _retry_timer_expired = false; @@ -772,14 +793,26 @@ void M2MInterfaceImpl::timer_expired(M2MTimerObserver::Type type) } else if (M2MTimerObserver::RetryTimer == type) { tr_debug("M2MInterfaceImpl::timer_expired() - retry"); _retry_timer_expired = true; - if (_bootstrapped) { - internal_event(STATE_REGISTER); - } + + if (_reconnection_state == M2MInterfaceImpl::ClientPing) { + // Lwm2m server has responded TLS handshake, set the reconnection state to correct state + if (_nsdl_interface.is_registered()) { + _reconnection_state = M2MInterfaceImpl::WithUpdate; + } else { + _reconnection_state = M2MInterfaceImpl::None; + } + // as we have now done handshake already we MUST NOT do any dns queries -> continue to address ready + address_ready(_server_address, M2MConnectionObserver::LWM2MServer, _server_address._port); + } else { + if (_bootstrapped) { + internal_event(STATE_REGISTER); + } #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE - else { - internal_event(STATE_BOOTSTRAP); - } + else { + internal_event(STATE_BOOTSTRAP); + } #endif + } } else if (M2MTimerObserver::BootstrapFlowTimer == type) { #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE @@ -811,6 +844,10 @@ void M2MInterfaceImpl::state_idle(EventData * /*data*/) void M2MInterfaceImpl::state_bootstrap(EventData *data) { tr_debug("M2MInterfaceImpl::state_bootstrap"); + + // Disable CoAP retransmissions when connection is not ready. + _nsdl_interface.stop_nsdl_execution_timer(); + // Start with bootstrapping preparation _bootstrapped = false; _bootstrap_finished = false; @@ -939,9 +976,13 @@ void M2MInterfaceImpl::state_bootstrapped(EventData */*data*/) void M2MInterfaceImpl::state_register(EventData *data) { tr_debug("M2MInterfaceImpl::state_register"); - _nsdl_interface.set_registration_status(false); + + // Disable CoAP retransmissions when connection is not ready. + _nsdl_interface.stop_nsdl_execution_timer(); + M2MRegisterData *event = static_cast(data); if (!_security) { + _nsdl_interface.set_registration_status(false); M2MInterface::Error error = M2MInterface::InvalidParameters; // Start with registration preparation if (event) { @@ -1064,6 +1105,14 @@ void M2MInterfaceImpl::state_register_address_resolved(EventData *data) _retry_timer.stop_timer(); + // Reset back to normal mode + if (_nsdl_interface.alert_mode()) { + _nsdl_interface.set_alert_mode(false); + if (!_connection_handler.set_socket_priority(M2MConnectionHandler::DEFAULT_PRIORITY)) { + tr_warn("M2MInterfaceImpl::state_register_address_resolved - failed to set socket priority"); + } + } + switch (_reconnection_state) { case M2MInterfaceImpl::None: if (!_nsdl_interface.send_register_message()) { @@ -1079,6 +1128,8 @@ void M2MInterfaceImpl::state_register_address_resolved(EventData *data) // Start registration update in case it is reconnection logic because of network issue. internal_event(STATE_UPDATE_REGISTRATION); break; + default: + break; } } } @@ -1139,9 +1190,11 @@ void M2MInterfaceImpl::pause() { tr_debug("M2MInterfaceImpl::pause()"); internal_event(STATE_IDLE); + if (_binding_mode == M2MInterface::UDP || _binding_mode == M2MInterface::UDP_QUEUE) { _connection_handler.store_cid(); } + _connection_handler.unregister_network_handler(); _connection_handler.stop_listening(); _retry_timer.stop_timer(); @@ -1151,7 +1204,34 @@ void M2MInterfaceImpl::pause() sn_nsdl_clear_coap_resending_queue(_nsdl_interface.get_nsdl_handle()); + _observer.paused(); +} + +void M2MInterfaceImpl::alert() +{ + if (!_nsdl_interface.is_registered() || _reconnecting) { + tr_info("M2MInterfaceImpl::alert() - in reconnection or not registered --> go to pause"); + pause(); + return; + } + + if (!_connection_handler.set_socket_priority(M2MConnectionHandler::ALERT_PRIORITY)) { + tr_warn("M2MInterfaceImpl::alert - failed to set socket into high priority mode"); + } + + sn_nsdl_clear_coap_resending_queue(_nsdl_interface.get_nsdl_handle()); + _connection_handler.claim_mutex(); + _nsdl_interface.set_request_context_to_be_resend(NULL, 0); + _connection_handler.release_mutex(); + _queue_sleep_timer.stop_timer(); + + _nsdl_interface.set_alert_mode(true); + _nsdl_interface.clear_sent_blockwise_messages(); + _nsdl_interface.clear_received_blockwise_messages(); + + internal_event(STATE_WAITING); + _observer.alert_mode(); } void M2MInterfaceImpl::state_unregister(EventData */*data*/) @@ -1500,7 +1580,7 @@ void M2MInterfaceImpl::network_interface_status_change(NetworkInterfaceStatus st _retry_timer.start_timer(rand_time * 1000, M2MTimerObserver::RetryTimer); // The old value is an estimate as it has been randomized before use (+/- 10%). - tr_info("M2MInterfaceImpl::network_interface_status_change - old value %d - new reconnection time %d", _reconnection_time / RECONNECT_INCREMENT_FACTOR, rand_time); + tr_info("M2MInterfaceImpl::network_interface_status_change - old value %" PRIu32 " - new reconnection time %" PRIu32, _reconnection_time / RECONNECT_INCREMENT_FACTOR, rand_time); _reconnection_time = rand_time; } } diff --git a/mbed-client/source/m2mnotificationhandler.cpp b/mbed-client/source/m2mnotificationhandler.cpp index a97c32e2d..a6609a955 100644 --- a/mbed-client/source/m2mnotificationhandler.cpp +++ b/mbed-client/source/m2mnotificationhandler.cpp @@ -29,9 +29,9 @@ int8_t M2MNotificationHandler::_tasklet_id = -1; extern "C" void notification_tasklet_func(arm_event_s *event) { - M2MNsdlInterface *iface = (M2MNsdlInterface*)event->data_ptr; + M2MNsdlInterface *iface = (M2MNsdlInterface *)event->data_ptr; if (event->event_type == MBED_CLIENT_NOTIFICATION_HANDLER_EVENT) { - iface->send_next_notification(false); + iface->send_next_notification(M2MNsdlInterface::SEND_NOTIFICATION); event->event_data = 0; } } @@ -52,7 +52,11 @@ M2MNotificationHandler::~M2MNotificationHandler() void M2MNotificationHandler::send_notification(M2MNsdlInterface *interface) { - tr_debug("M2MNotificationHandler::send_notification"); + if (interface->alert_mode()) { + tr_debug("M2MNotificationHandler::send_notification - in alert mode skip sending"); + return; + } + if (!_event.data.event_data) { _event.data.event_data = 1; _event.data.event_type = MBED_CLIENT_NOTIFICATION_HANDLER_EVENT; diff --git a/mbed-client/source/m2mnsdlinterface.cpp b/mbed-client/source/m2mnsdlinterface.cpp index bb852dd9c..4a3291c7b 100644 --- a/mbed-client/source/m2mnsdlinterface.cpp +++ b/mbed-client/source/m2mnsdlinterface.cpp @@ -64,11 +64,12 @@ #define MBED_CLIENT_NSDLINTERFACE_TASKLET_INIT_EVENT 0 // Tasklet init occurs always when generating a tasklet #define MBED_CLIENT_NSDLINTERFACE_EVENT 30 +#define MBED_CLIENT_NSDLINTERFACE_MESSAGE_STATUS_CB_EVENT 31 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE -#define MBED_CLIENT_NSDLINTERFACE_BS_EVENT 31 -#define MBED_CLIENT_NSDLINTERFACE_BS_PUT_EVENT 32 -#define MBED_CLIENT_NSDLINTERFACE_BS_FINISH_EVENT 33 +#define MBED_CLIENT_NSDLINTERFACE_BS_EVENT 32 +#define MBED_CLIENT_NSDLINTERFACE_BS_PUT_EVENT 33 +#define MBED_CLIENT_NSDLINTERFACE_BS_FINISH_EVENT 34 #endif #ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE @@ -85,12 +86,16 @@ #define TRACE_GROUP "mClt" #define MAX_QUERY_COUNT 10 -const char *MCC_VERSION = "mccv=4.8.0"; +#define REGISTRATION_UPDATE_DELAY 10 // wait 10ms before sending registration update for PUT to resource 1/0/1 + +const char *MCC_VERSION = "mccv=4.9.0"; int8_t M2MNsdlInterface::_tasklet_id = -1; extern "C" void nsdlinterface_tasklet_func(arm_event_s *event) { + event->event_id = 0; + // skip the init event as there will be a timer event after if (event->event_type == MBED_CLIENT_NSDLINTERFACE_EVENT) { eventOS_scheduler_mutex_wait(); @@ -130,9 +135,11 @@ extern "C" void nsdlinterface_tasklet_func(arm_event_s *event) coap_data->received_coap_header, coap_data->received_coap_header->msg_code); if (coap_response) { +#if (MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE == 0) coap_response->msg_type = coap_data->received_coap_header->msg_type; // Let CoAP to choose next message id coap_response->msg_id = 0; +#endif // MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE if (sn_nsdl_send_coap_message(coap_data->nsdl_handle, &coap_data->address, coap_response) == 0) { interface->store_bs_finished_response_id(coap_response->msg_id); @@ -172,10 +179,46 @@ extern "C" void nsdlinterface_tasklet_func(arm_event_s *event) nsdl_s *nsdl_handle = (nsdl_s *)event->data_ptr; M2MNsdlInterface *interface = (M2MNsdlInterface *)sn_nsdl_get_context(nsdl_handle); interface->handle_bootstrap_finish_ack(event->event_data); + } else if (event->event_type == MBED_CLIENT_NSDLINTERFACE_MESSAGE_STATUS_CB_EVENT) { + M2MObject *object = (M2MObject *)event->data_ptr; + uint8_t status = event->event_data >> 8; + uint8_t type = event->event_data; + object->send_message_delivery_status(*object, + (M2MBase::MessageDeliveryStatus)status, + (M2MBase::MessageType)type); } #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +bool lifetime_write_callback(const M2MResourceBase &resource, const uint8_t *buffer, const size_t buffer_size, void *client_args) +{ + M2MNsdlInterface *m2m_interface = (M2MNsdlInterface *)client_args; + + return m2m_interface->update_server_lifetime(buffer, buffer_size); +} + +bool M2MNsdlInterface::update_server_lifetime(const uint8_t *buffer, const size_t buffer_size) +{ + bool retval = false; + + M2MResource *lifetime_res = _server->get_resource(M2MServer::Lifetime); + if (lifetime_res) { + uint8_t *value_copy = alloc_string_copy(buffer, buffer_size); + if (value_copy) { + lifetime_res->update_value(value_copy, buffer_size); + retval = true; + } - event->event_data = 0; + if (_current_request_code == COAP_MSG_CODE_REQUEST_PUT) { + _current_request_code = COAP_MSG_CODE_EMPTY; + if (retval) { + // OMA Registration Update, put to 1/0/1 must trigger update. + update_trigger_callback(NULL); + } + } + } + + return retval; } M2MNsdlInterface::M2MNsdlInterface(M2MNsdlObserver &observer, M2MConnectionHandler &connection_handler) @@ -202,7 +245,10 @@ M2MNsdlInterface::M2MNsdlInterface(M2MNsdlObserver &observer, M2MConnectionHandl _waiting_for_bs_finish_ack(false), _download_retry_timer(*this), _download_retry_time(0), - _network_rtt_estimate(10) // Use reasonable initialization value for the RTT estimate. Must be larger than 0. + _network_rtt_estimate(10), // Use reasonable initialization value for the RTT estimate. Must be larger than 0. + _alert_mode(false), + _last_notif_queue_event(M2MNsdlInterface::SEND_NOTIFICATION), + _current_request_code(COAP_MSG_CODE_EMPTY) { tr_debug("M2MNsdlInterface::M2MNsdlInterface()"); @@ -289,6 +335,11 @@ bool M2MNsdlInterface::initialize() &M2MNsdlInterface::update_trigger_callback)); } + M2MResource *lifetime_res = _server->get_resource(M2MServer::Lifetime); + if (lifetime_res) { + lifetime_res->set_resource_write_callback(lifetime_write_callback, (void *)this); + } + add_object_to_list(_server); create_nsdl_object_structure(_server); ns_list_init(&_request_context_list); @@ -501,7 +552,7 @@ bool M2MNsdlInterface::send_register_message() bool success = false; // Clear the observation tokens - send_next_notification(true); + send_next_notification(M2MNsdlInterface::CLEAR_NOTIFICATION_TOKEN); if (_server_address) { success = parse_and_send_uri_query_parameters(); @@ -531,8 +582,8 @@ void M2MNsdlInterface::send_request(DownloadType type, int32_t message_id = 0; request_context_s *data_request = NULL; - if (msg_code == COAP_MSG_CODE_REQUEST_GET && !_registered) { - tr_error("M2MNsdlInterface::send_request - client not registered!"); + if (msg_code == COAP_MSG_CODE_REQUEST_GET && (!_registered || _alert_mode)) { + tr_error("M2MNsdlInterface::send_request - client registered: %d, alert mode: %d!", _registered, _alert_mode); error_cb(ERROR_NOT_REGISTERED, context); return; } @@ -767,14 +818,18 @@ uint8_t M2MNsdlInterface::received_from_server_callback(struct nsdl_s *nsdl_hand if (COAP_MSG_CODE_REQUEST_PUT == coap_header->msg_code) { if (is_bootstrap_msg) { #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + +#if (MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE == 0) send_empty_ack(coap_header, address); +#endif // MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE + nsdl_coap_data_s *nsdl_coap_data = create_coap_event_data(coap_header, address, nsdl_handle, coap_header->msg_code); if (nsdl_coap_data) { - if (!_event.data.event_data) { - _event.data.event_data = true; + if (!_event.data.event_id) { + _event.data.event_id = true; _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_BS_PUT_EVENT; _event.data.data_ptr = (void *)nsdl_coap_data; eventOS_event_send_user_allocated(&_event); @@ -831,7 +886,7 @@ uint8_t M2MNsdlInterface::received_from_server_callback(struct nsdl_s *nsdl_hand base->handle_observation(nsdl_handle, *coap_header, *coap_header, this, code); base->start_observation(*coap_header, this); } else { - handle_message_delivered(base, resp->type); + handle_message_status_callback(base, resp->type, M2MBase::MESSAGE_STATUS_DELIVERED); } remove_item_from_response_list(NULL, coap_header->msg_id); @@ -849,7 +904,7 @@ uint8_t M2MNsdlInterface::received_from_server_callback(struct nsdl_s *nsdl_hand // Do not report notification sending timeout to application. // Notifications has own queue which will take care of re-sending. if (base && resp->type != M2MBase::NOTIFICATION) { - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_SEND_FAILED, resp->type); + handle_message_status_callback(base, resp->type, M2MBase::MESSAGE_STATUS_SEND_FAILED); } remove_item_from_response_list(resp->uri_path, coap_header->msg_id); } @@ -1000,13 +1055,13 @@ uint8_t M2MNsdlInterface::resource_callback(struct nsdl_s *nsdl_handle, } send_empty_ack(received_coap_header, address); - if (!_event.data.event_data) { + if (!_event.data.event_id) { nsdl_coap_data_s *nsdl_coap_data = create_coap_event_data(received_coap_header, address, nsdl_handle, received_coap_header->msg_code); if (nsdl_coap_data) { - _event.data.event_data = true; + _event.data.event_id = true; _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_EVENT; _event.data.data_ptr = (void *)nsdl_coap_data; eventOS_event_send_user_allocated(&_event); @@ -1034,6 +1089,7 @@ uint8_t M2MNsdlInterface::resource_callback_handle_event(sn_coap_hdr_s *received M2MBase *base = find_resource(resource_name); bool subscribed = false; if (base) { + _current_request_code = received_coap_header->msg_code; if (COAP_MSG_CODE_REQUEST_GET == received_coap_header->msg_code) { coap_response = base->handle_get_request(_nsdl_handle, received_coap_header, this); @@ -1166,10 +1222,10 @@ uint8_t M2MNsdlInterface::resource_callback_handle_event(sn_coap_hdr_s *received // Notify application that message has been sent so it can release the memory if (!result) { if (!coap_response->options_list_ptr || !(coap_response->options_list_ptr->block2 & 0x08) || coap_response->options_list_ptr->block2 == -1) { - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_DELIVERED, M2MBase::DELAYED_RESPONSE); + handle_message_status_callback(base, M2MBase::DELAYED_RESPONSE, M2MBase::MESSAGE_STATUS_DELIVERED); } } else { - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_SEND_FAILED, M2MBase::DELAYED_RESPONSE); + handle_message_status_callback(base, M2MBase::DELAYED_RESPONSE, M2MBase::MESSAGE_STATUS_SEND_FAILED); } } else { free(coap_response->payload_ptr); @@ -1260,9 +1316,28 @@ bool M2MNsdlInterface::process_received_data(uint8_t *data, sn_nsdl_addr_s *address) { tr_debug("M2MNsdlInterface::process_received_data(data size %d)", data_size); + + sn_coap_hdr_s *coap_packet_ptr = NULL; + /* Parse CoAP packet */ + coap_packet_ptr = sn_coap_protocol_parse(_nsdl_handle->grs->coap, address, data_size, data, (void *)_nsdl_handle); + + /* Check if parsing was successfull */ + if (coap_packet_ptr == (sn_coap_hdr_s *)NULL) { + tr_error("M2MNsdlInterface::process_received_data - coap parsing fails"); + return false; + } + + sn_nsdl_print_coap_data(coap_packet_ptr, false); + + // Do not process any incoming CON message while in alert mode + if (_alert_mode && coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { + tr_info("M2MNsdlInterface::process_received_data - skip message in alert mode"); + sn_coap_parser_release_allocated_coap_msg_mem(_nsdl_handle->grs->coap, coap_packet_ptr); + return true; + } + return (0 == sn_nsdl_process_coap(_nsdl_handle, - data, - data_size, + coap_packet_ptr, address)) ? true : false; } @@ -1278,6 +1353,27 @@ void M2MNsdlInterface::stop_timers() _download_retry_timer.stop_timer(); } +void M2MNsdlInterface::set_alert_mode(bool alert) +{ + tr_debug("M2MNsdlInterface::set_alert_mode() - %d", alert); + _alert_mode = alert; + + if (_alert_mode) { + // Remove pending notifications from the queue + send_next_notification(M2MNsdlInterface::REMOVE_NOTIFICATION); + _registration_timer.stop_timer(); + _bootstrap_id = 0; + _nsdl_handle->update_register_token = 0; + _nsdl_handle->unregister_token = 0; + _download_retry_timer.stop_timer(); + } +} + +bool M2MNsdlInterface::alert_mode() const +{ + return _alert_mode; +} + void M2MNsdlInterface::timer_expired(M2MTimerObserver::Type type) { if (M2MTimerObserver::NsdlExecution == type) { @@ -1367,10 +1463,10 @@ void M2MNsdlInterface::send_delayed_response(M2MBase *base, sn_coap_msg_code_e c if (sn_nsdl_send_coap_message(_nsdl_handle, &_nsdl_handle->server_address, &coap_response) >= 0) { // Update msgid, this will be used to track server response resp->msg_id = coap_response.msg_id; - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_SENT, M2MBase::DELAYED_POST_RESPONSE); + handle_message_status_callback(base, M2MBase::DELAYED_POST_RESPONSE, M2MBase::MESSAGE_STATUS_SENT); } else { // Failed to create a message - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_SEND_FAILED, M2MBase::DELAYED_POST_RESPONSE); + handle_message_status_callback(base, M2MBase::DELAYED_POST_RESPONSE, M2MBase::MESSAGE_STATUS_SEND_FAILED); // Remove stored response from the list remove_item_from_response_list(resource->uri_path(), UNDEFINED_MSG_ID); } @@ -1416,7 +1512,7 @@ void M2MNsdlInterface::send_asynchronous_response(M2MBase *base, if (sn_nsdl_send_coap_message(_nsdl_handle, &_nsdl_handle->server_address, coap_response) >= 0) { // Update msgid, this will be used to track server response resp->msg_id = coap_response->msg_id; - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_SENT, M2MBase::DELAYED_RESPONSE); + handle_message_status_callback(base, M2MBase::DELAYED_RESPONSE, M2MBase::MESSAGE_STATUS_SENT); msg_sent = true; if (M2MBase::is_blockwise_needed(_nsdl_handle, payload_len)) { resp->blockwise_used = true; @@ -1430,7 +1526,7 @@ void M2MNsdlInterface::send_asynchronous_response(M2MBase *base, if (!msg_sent) { // Failed to create a message - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_SEND_FAILED, M2MBase::DELAYED_RESPONSE); + handle_message_status_callback(base, M2MBase::DELAYED_RESPONSE, M2MBase::MESSAGE_STATUS_SEND_FAILED); // Remove stored response from the list remove_item_from_response_list(base->uri_path(), UNDEFINED_MSG_ID); } @@ -2088,7 +2184,8 @@ void M2MNsdlInterface::send_object_observation(M2MObject *object, int32_t msgid = sn_nsdl_send_observation_notification(_nsdl_handle, token, token_length, value, length, sn_coap_observe_e(obs_number), object->report_handler()->is_confirmable(), sn_coap_content_format_e(object->coap_content_type()), -1, object->max_age()); - execute_notification_delivery_status_cb(object, msgid); + + handle_observation_response(object, msgid); memory_free(value); } @@ -2114,7 +2211,7 @@ void M2MNsdlInterface::send_object_instance_observation(M2MObjectInstance *objec sn_coap_observe_e(obs_number), object_instance->report_handler()->is_confirmable(), sn_coap_content_format_e(object_instance->coap_content_type()), -1, object_instance->max_age()); - execute_notification_delivery_status_cb(object_instance, msgid); + handle_observation_response(object_instance, msgid); memory_free(value); } @@ -2148,7 +2245,7 @@ void M2MNsdlInterface::send_resource_observation(M2MResource *resource, sn_coap_observe_e(obs_number), resource->report_handler()->is_confirmable(), sn_coap_content_format_e(content_type), -1, resource->max_age()); - execute_notification_delivery_status_cb(resource, msgid); + handle_observation_response(resource, msgid); memory_free(value); } @@ -2198,7 +2295,7 @@ void M2MNsdlInterface::handle_bootstrap_put_message(sn_coap_hdr_s *coap_header, else if (resource_name.compare(0, 1, "3") == 0) { M2MDevice *dev = M2MInterfaceFactory::create_device(); // Not mandatory resource, that's why it must be created first - M2MResource *res = dev->create_resource(M2MDevice::CurrentTime, 0); + (void)dev->create_resource(M2MDevice::CurrentTime, 0); object_type = M2MNsdlInterface::DEVICE; success = true; } @@ -2243,10 +2340,12 @@ void M2MNsdlInterface::handle_bootstrap_put_message(sn_coap_hdr_s *coap_header, response_code); if (coap_response) { +#if (MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE == 0) // Set the correct message type. Must be confirmable since this is a separate response. // Clear the message id so CoAP will add a new one. coap_response->msg_type = coap_header->msg_type; coap_response->msg_id = 0; +#endif // MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response); sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response); @@ -2424,7 +2523,11 @@ void M2MNsdlInterface::handle_bootstrap_finished(sn_coap_hdr_s *coap_header, sn_ // In ok case send response as a separate response if (msg_code == COAP_MSG_CODE_RESPONSE_CHANGED) { _waiting_for_bs_finish_ack = true; + +#if (MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE == 0) send_empty_ack(coap_header, address); +#endif // MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE + // In error case use piggybacked response } else { coap_response = sn_nsdl_build_response(_nsdl_handle, coap_header, msg_code); @@ -2447,7 +2550,7 @@ void M2MNsdlInterface::handle_bootstrap_finished(sn_coap_hdr_s *coap_header, sn_ memory_free(_endpoint->endpoint_name_ptr); _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t *)_endpoint_name.c_str(), _endpoint_name.length()); if (_endpoint->endpoint_name_ptr) { - if (!_event.data.event_data) { + if (!_event.data.event_id) { _endpoint->endpoint_name_len = _endpoint_name.length(); nsdl_coap_data_s *nsdl_coap_data = create_coap_event_data(coap_message, address, @@ -2455,7 +2558,7 @@ void M2MNsdlInterface::handle_bootstrap_finished(sn_coap_hdr_s *coap_header, sn_ (sn_coap_msg_code_e)msg_code); if (nsdl_coap_data) { alloc_failed = false; - _event.data.event_data = true; + _event.data.event_id = true; _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_BS_EVENT; _event.data.data_ptr = (void *)nsdl_coap_data; eventOS_event_send_user_allocated(&_event); @@ -2727,6 +2830,13 @@ void M2MNsdlInterface::start_nsdl_execution_timer() false); } +void M2MNsdlInterface::stop_nsdl_execution_timer() +{ + tr_debug("M2MNsdlInterface::stop_nsdl_execution_timer"); + _nsdl_execution_timer_running = false; + _nsdl_execution_timer.stop_timer(); +} + M2MSecurity *M2MNsdlInterface::get_security_object() { return _security; @@ -2734,9 +2844,9 @@ M2MSecurity *M2MNsdlInterface::get_security_object() void M2MNsdlInterface::update_trigger_callback(void */*argument*/) { - if (!send_update_registration()) { - // Most likely case would be memory allocation failure - _observer.registration_error(M2MInterface::MemoryFail, false); + if (is_registered()) { + _registration_timer.stop_timer(); + _registration_timer.start_timer(REGISTRATION_UPDATE_DELAY, M2MTimerObserver::Registration, true); } } @@ -2752,23 +2862,22 @@ bool M2MNsdlInterface::lifetime_value_changed() const return false; } -void M2MNsdlInterface::execute_notification_delivery_status_cb(M2MBase *object, int32_t msgid) +void M2MNsdlInterface::handle_observation_response(M2MBase *object, int32_t msgid) { + uint8_t status; if (msgid > 0) { - object->send_message_delivery_status(*object, - M2MBase::MESSAGE_STATUS_SENT, - M2MBase::NOTIFICATION); + status = (uint8_t)M2MBase::MESSAGE_STATUS_SENT; if (object->report_handler()->is_confirmable()) { store_to_response_list(object->uri_path(), msgid, M2MBase::NOTIFICATION); } else { _notification_send_ongoing = false; } } else { - object->send_message_delivery_status(*object, - M2MBase::MESSAGE_STATUS_BUILD_ERROR, - M2MBase::NOTIFICATION); + status = (uint8_t)M2MBase::MESSAGE_STATUS_BUILD_ERROR; _notification_send_ongoing = false; } + + handle_message_status_callback(object, M2MBase::NOTIFICATION, (M2MBase::MessageDeliveryStatus)status); } uint8_t M2MNsdlInterface::find_auto_obs_token(const char *path, uint8_t *token) const @@ -2937,16 +3046,16 @@ void M2MNsdlInterface::calculate_new_coap_ping_send_time() _next_coap_ping_send_time = _counter_for_nsdl + MBED_CLIENT_TCP_KEEPALIVE_INTERVAL; } -void M2MNsdlInterface::send_next_notification(bool clear_token) +void M2MNsdlInterface::send_next_notification(NotificationQueueOption option) { - tr_debug("M2MNsdlInterface::send_next_notification"); + tr_info("M2MNsdlInterface::send_next_notification - option %d", option); claim_mutex(); if (!_base_list.empty()) { M2MBaseList::const_iterator base_iterator; base_iterator = _base_list.begin(); for (; base_iterator != _base_list.end(); base_iterator++) { if ((*base_iterator)->base_type() == M2MBase::Object) { - if (send_next_notification_for_object(*(M2MObject *)*base_iterator, clear_token)) { + if (send_next_notification_for_object(*(M2MObject *)*base_iterator, option)) { release_mutex(); return; } @@ -2960,7 +3069,7 @@ void M2MNsdlInterface::send_next_notification(bool clear_token) object_iterator = object_list.begin(); // Object level for (; object_iterator != object_list.end(); object_iterator++) { - if (send_next_notification_for_object(**object_iterator, clear_token)) { + if (send_next_notification_for_object(**object_iterator, option)) { release_mutex(); return; } @@ -2972,24 +3081,16 @@ void M2MNsdlInterface::send_next_notification(bool clear_token) } _notification_send_ongoing = false; + _last_notif_queue_event = option; release_mutex(); tr_debug("M2MNsdlInterface::send_next_notification - nothing to send"); } -bool M2MNsdlInterface::send_next_notification_for_object(M2MObject &object, bool clear_token) +bool M2MNsdlInterface::send_next_notification_for_object(M2MObject &object, NotificationQueueOption option) { const M2MObjectInstanceList &object_instance_list = object.instances(); - M2MReportHandler *reporter = object.report_handler(); - if (reporter) { - // Auto obs token can't be cleared - if (clear_token && !object.get_nsdl_resource()->auto_observable) { - reporter->set_observation_token(NULL, 0); - object.cancel_observation(M2MBase::MESSAGE_STATUS_SEND_FAILED); - } else if (reporter->is_under_observation() && - (reporter->notification_in_queue() || reporter->notification_send_in_progress())) { - reporter->schedule_report(true); - return true; - } + if (handle_notification_queue(object, option)) { + return true; } // Object instance level @@ -2997,17 +3098,8 @@ bool M2MNsdlInterface::send_next_notification_for_object(M2MObject &object, bool M2MObjectInstanceList::const_iterator object_instance_iterator; object_instance_iterator = object_instance_list.begin(); for (; object_instance_iterator != object_instance_list.end(); object_instance_iterator++) { - reporter = (*object_instance_iterator)->report_handler(); - if (reporter) { - // Auto obs token can't be cleared - if (clear_token && !(*object_instance_iterator)->get_nsdl_resource()->auto_observable) { - reporter->set_observation_token(NULL, 0); - (*object_instance_iterator)->cancel_observation(M2MBase::MESSAGE_STATUS_SEND_FAILED); - } else if (reporter->is_under_observation() && - (reporter->notification_in_queue() || reporter->notification_send_in_progress())) { - reporter->schedule_report(true); - return true; - } + if (handle_notification_queue(*(M2MObject *)*object_instance_iterator, option)) { + return true; } // Resource level @@ -3016,26 +3108,8 @@ bool M2MNsdlInterface::send_next_notification_for_object(M2MObject &object, bool M2MResourceList::const_iterator resource_iterator; resource_iterator = resource_list.begin(); for (; resource_iterator != resource_list.end(); resource_iterator++) { - reporter = (*resource_iterator)->report_handler(); - if (reporter) { - // Auto obs token can't be cleared - if (clear_token) { - if ((*resource_iterator)->get_nsdl_resource()->auto_observable) { - sn_nsdl_dynamic_resource_parameters_s *res = (*resource_iterator)->get_nsdl_resource(); - // Do not send unnecessary notification since resource value is going to be part of registration message - if (res->publish_value != 0) { - reporter->set_notification_in_queue(false); - reporter->set_notification_send_in_progress(false); - } - } else { - reporter->set_observation_token(NULL, 0); - (*resource_iterator)->cancel_observation(M2MBase::MESSAGE_STATUS_SEND_FAILED); - } - } else if (reporter->is_under_observation() && - (reporter->notification_in_queue() || reporter->notification_send_in_progress())) { - reporter->schedule_report(true); - return true; - } + if (handle_notification_queue(*(M2MObject *)*resource_iterator, option)) { + return true; } } } @@ -3064,6 +3138,20 @@ void M2MNsdlInterface::store_bs_finished_response_id(uint16_t msg_id) { tr_debug("M2MNsdlInterface::store_bs_finished_response_id - id %d", msg_id); _bootstrap_id = msg_id; + + // Fire event to continue with BS flow since empty ack is not coming in this case. +#if (MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE == 1) + if (!_event.data.event_id) { + tr_debug("M2MNsdlInterface::store_bs_finished_response_id - send finish event"); + _event.data.event_id = true; + _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_BS_FINISH_EVENT; + _event.data.event_data = msg_id; + _event.data.data_ptr = _nsdl_handle; + _observer.bootstrap_wait(); + _waiting_for_bs_finish_ack = false; + eventOS_event_send_user_allocated(&_event); + } +#endif // MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE } #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE @@ -3235,7 +3323,7 @@ void M2MNsdlInterface::handle_register_update_response(const sn_coap_hdr_s *coap _observer.registration_error(M2MInterface::NetworkError, true); } else { // Clear observation tokens and do a full registration - send_next_notification(true); + send_next_notification(M2MNsdlInterface::CLEAR_NOTIFICATION_TOKEN); bool msg_sent = false; if (_server_address) { @@ -3477,7 +3565,8 @@ void M2MNsdlInterface::handle_empty_ack(const sn_coap_hdr_s *coap_header, bool i handle_bootstrap_error(M2MInterface::BootstrapFailed, ERROR_REASON_28, false); } else { tr_debug("M2MNsdlInterface::handle_empty_ack - sending finish event - status %d", coap_header->coap_status); - if (!_event.data.event_data) { + if (!_event.data.event_id) { + _event.data.event_id = true; _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_BS_FINISH_EVENT; tr_debug("M2MNsdlInterface::handle_empty_ack - sending finish event - msg id %d", coap_header->msg_id); _event.data.event_data = coap_header->msg_id; @@ -3503,11 +3592,11 @@ void M2MNsdlInterface::handle_empty_ack(const sn_coap_hdr_s *coap_header, bool i _notification_send_ongoing = false; _notification_handler->send_notification(this); } else if (resp->type == M2MBase::DELAYED_POST_RESPONSE) { - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_REJECTED, M2MBase::DELAYED_POST_RESPONSE); + handle_message_status_callback(base, M2MBase::DELAYED_POST_RESPONSE, M2MBase::MESSAGE_STATUS_REJECTED); } #ifdef ENABLE_ASYNC_REST_RESPONSE else if (resp->type == M2MBase::DELAYED_RESPONSE) { - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_REJECTED, M2MBase::DELAYED_RESPONSE); + handle_message_status_callback(base, M2MBase::DELAYED_RESPONSE, M2MBase::MESSAGE_STATUS_REJECTED); } #endif // ENABLE_ASYNC_REST_RESPONSE remove_item_from_response_list(resp->uri_path, coap_header->msg_id); @@ -3528,7 +3617,7 @@ void M2MNsdlInterface::handle_empty_ack(const sn_coap_hdr_s *coap_header, bool i if (report) { if (!data->blockwise_used) { - handle_message_delivered(base, data->type); + handle_message_status_callback(base, data->type, M2MBase::MESSAGE_STATUS_DELIVERED); remove_item_from_response_list(NULL, coap_header->msg_id); } } @@ -3555,16 +3644,32 @@ void M2MNsdlInterface::handle_bootstrap_finish_ack(uint16_t msg_id) } #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE -void M2MNsdlInterface::handle_message_delivered(M2MBase *base, const M2MBase::MessageType type) +void M2MNsdlInterface::handle_message_status_callback(M2MBase *base, const M2MBase::MessageType type, const M2MBase::MessageDeliveryStatus status) { - if (M2MBase::NOTIFICATION == type) { + if (M2MBase::NOTIFICATION == type && status == M2MBase::MESSAGE_STATUS_DELIVERED) { base->report_handler()->set_notification_send_in_progress(false); _notification_send_ongoing = false; _notification_handler->send_notification(this); } - base->send_message_delivery_status(*base, M2MBase::MESSAGE_STATUS_DELIVERED, type); + uint16_t data = (uint8_t)status << 8 | (uint8_t)type; + arm_event_s event = { + .receiver = M2MNsdlInterface::_tasklet_id, // ID we got when creating our handler + .sender = 0, + .event_type = MBED_CLIENT_NSDLINTERFACE_MESSAGE_STATUS_CB_EVENT, + .event_id = 0, + .data_ptr = base, + .priority = ARM_LIB_HIGH_PRIORITY_EVENT, // Application level priority + .event_data = data, + }; + + if (eventOS_event_send(&event) < 0) { + tr_warn("M2MNsdlInterface::handle_message_status_callback - failed to allocate event!"); + base->send_message_delivery_status(*base, + status, + type); + } } void M2MNsdlInterface::set_retransmission_parameters() @@ -3581,11 +3686,11 @@ void M2MNsdlInterface::set_retransmission_parameters() reconnection_total_time = total_retransmission_time(--resend_count); } - tr_info("M2MNsdlInterface::set_retransmission_parameters() - setting max resend count to %" PRIu32 " with total time: %" PRIu32, + tr_info("M2MNsdlInterface::set_retransmission_parameters() - setting max resend count to %" PRIu8 " with total time: %" PRIu32, resend_count, reconnection_total_time); sn_nsdl_set_retransmission_parameters(_nsdl_handle, resend_count, _network_rtt_estimate); #else - tr_info("M2MNsdlInterface::set_retransmission_parameters() - setting resend count to %" PRIu32 " with initial retransmission time: %" PRIu32, + tr_info("M2MNsdlInterface::set_retransmission_parameters() - setting resend count to %" PRIu8 " with initial retransmission time: %" PRIu8, sn_nsdl_get_retransmission_count(_nsdl_handle), _network_rtt_estimate); sn_nsdl_set_retransmission_parameters(_nsdl_handle, @@ -3840,26 +3945,41 @@ bool M2MNsdlInterface::handle_delayed_response_store(const char *uri_path, uint16_t M2MNsdlInterface::estimate_stagger_data_amount(bool bootstrap, bool using_cid) const { - // The full TLS/DTLS handshake amounts to roughly 5 KiB data. - // Boostrap takes roughly 4 KiB. - // Registration goes to roughly 5 KiB. - // On top of this we need to calculate 300 byte overhead per packet in transit. - // ~30 for bootstrap, ~25 for registration. 10 for DTLS. - const static uint16_t bootstrap_amount = 4 + 9; - const static uint16_t registration_amount = 5 + 8; - const static uint16_t handshake = 8; + const static uint16_t bs_handshake_amount = 5; + // 10 messages * 300 bytes + const static uint16_t bs_handshake_overhead = 3; + +#if (MBED_CLIENT_BOOTSTRAP_PIGGYBACKED_RESPONSE == 1) + const static uint16_t bootstrap_amount = 4; + // 17 messages * 300 bytes + const static uint16_t bootstrap_overhead = 5; +#else + const static uint16_t bootstrap_amount = 5; + // 23 messages * 300 bytes + const static uint16_t bootstrap_overhead = 7 +#endif + + // 6 messages * 300 bytes + const static uint16_t mds_handshake_amount = 3; + const static uint16_t mds_handshake_overhead = 2; + const static uint16_t registration_amount = 2; + // 4 messages * 300 bytes + const static uint16_t registration_overhead = 2; + // registration traffic overhead. + // this considers initial customer data generated traffic on the network. + const static uint16_t registration_extra_overhead = 4; if (using_cid) { // Bootstrap and registration handshake done, thus doing registration - return registration_amount; + return registration_amount + registration_overhead + registration_extra_overhead; } if (bootstrap) { // Doing bootstrap stagger - return bootstrap_amount + handshake; + return bootstrap_amount + bootstrap_overhead + bs_handshake_amount + bs_handshake_overhead; } else { // Doing register stagger - return registration_amount + handshake; + return registration_amount + registration_overhead + registration_extra_overhead + mds_handshake_amount + mds_handshake_overhead; } } @@ -3900,3 +4020,58 @@ void M2MNsdlInterface::set_cid_value(const uint8_t *data_ptr, const size_t data_ { _connection_handler.set_cid_value(data_ptr, data_len); } + +bool M2MNsdlInterface::handle_notification_queue(M2MObject &object, M2MNsdlInterface::NotificationQueueOption option) +{ + M2MReportHandler *reporter = object.report_handler(); + if (!reporter) { + return false; + } + + bool scheduled = false; + switch (option) { + case SEND_NOTIFICATION: + // Alert mode will clear the queue and stop the timers, so we need to start the timers again in that case + if (_last_notif_queue_event == REMOVE_NOTIFICATION) { + reporter->start_timers(); + } + + if (reporter->is_under_observation() && + (reporter->notification_in_queue() || reporter->notification_send_in_progress())) { + reporter->schedule_report(true); + scheduled = true; + } + + break; + + case CLEAR_NOTIFICATION_TOKEN: + if (object.base_type() == M2MBase::Resource && + object.get_nsdl_resource()->auto_observable) { + sn_nsdl_dynamic_resource_parameters_s *res = object.get_nsdl_resource(); + // Do not send unnecessary notification since resource value is going to be part of registration message + if (res->publish_value != 0) { + reporter->set_notification_in_queue(false); + reporter->set_notification_send_in_progress(false); + } + } + + if (!object.get_nsdl_resource()->auto_observable) { + reporter->set_observation_token(NULL, 0); + object.cancel_observation(M2MBase::MESSAGE_STATUS_SEND_FAILED, reporter->notification_in_queue()); + } + + break; + + case REMOVE_NOTIFICATION: + reporter->set_notification_in_queue(false); + reporter->set_notification_send_in_progress(false); + reporter->stop_timers(); + + break; + + default: + break; + } + + return scheduled; +} diff --git a/mbed-client/source/m2mobjectinstance.cpp b/mbed-client/source/m2mobjectinstance.cpp index aa26b26e2..81b3b917a 100644 --- a/mbed-client/source/m2mobjectinstance.cpp +++ b/mbed-client/source/m2mobjectinstance.cpp @@ -728,8 +728,8 @@ sn_coap_hdr_s *M2MObjectInstance::handle_post_request(nsdl_s *nsdl, break; } } else { - msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; - } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) + msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; + } } else { // Operation is not allowed. tr_error("M2MObjectInstance::handle_post_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); diff --git a/mbed-client/source/m2mresource.cpp b/mbed-client/source/m2mresource.cpp index de3912a77..c0b21fd61 100644 --- a/mbed-client/source/m2mresource.cpp +++ b/mbed-client/source/m2mresource.cpp @@ -405,20 +405,22 @@ sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *nsdl, tr_info("M2MResource::handle_put_request()"); sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 sn_coap_hdr_s * coap_response = NULL; - if(supports_multiple_instances()) { + if (supports_multiple_instances() || + (received_coap_header->content_format == COAP_CONTENT_OMA_TLV_TYPE || + received_coap_header->content_format == COAP_CONTENT_OMA_TLV_TYPE_OLD)) { coap_response = sn_nsdl_build_response(nsdl, received_coap_header, msg_code); // process the PUT if we have registered a callback for it - if(received_coap_header) { + if (received_coap_header) { uint16_t coap_content_type = 0; bool content_type_present = false; - if(received_coap_header->content_format != COAP_CT_NONE && coap_response) { + if (received_coap_header->content_format != COAP_CT_NONE && coap_response) { content_type_present = true; coap_content_type = received_coap_header->content_format; } - if(received_coap_header->options_list_ptr && - received_coap_header->options_list_ptr->uri_query_ptr) { + if (received_coap_header->options_list_ptr && + received_coap_header->options_list_ptr->uri_query_ptr) { char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr, received_coap_header->options_list_ptr->uri_query_len); if (query){ @@ -436,7 +438,7 @@ sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *nsdl, free(query); } } else if ((operation() & M2MBase::PUT_ALLOWED) != 0) { - if(!content_type_present && + if (!content_type_present && (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE || M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) { coap_content_type = COAP_CONTENT_OMA_TLV_TYPE; @@ -444,17 +446,28 @@ sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *nsdl, tr_debug("M2MResource::handle_put_request() - Request Content-type: %d", coap_content_type); - if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type || - COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) { + if (COAP_CONTENT_OMA_TLV_TYPE == coap_content_type || COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) { set_coap_content_type(coap_content_type); M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; - error = M2MTLVDeserializer::deserialize_resource_instances(received_coap_header->payload_ptr, + if (supports_multiple_instances()) { + error = M2MTLVDeserializer::deserialize_resource_instances(received_coap_header->payload_ptr, received_coap_header->payload_len, *this, M2MTLVDeserializer::Put); - switch(error) { + } else { + if ((strcmp(uri_path(), FIRMWARE_PACKAGE_URI_PATH) == 0) && received_coap_header->payload_len > MAX_FIRMWARE_PACKAGE_URI_PATH_LEN) { + // Firmware object uri path is limited to be max MAX_FIRMWARE_PACKAGE_URI_PATH_LEN bytes + error = M2MTLVDeserializer::NotAccepted; + } else { + error = M2MTLVDeserializer::deserialize_resource(received_coap_header->payload_ptr, + received_coap_header->payload_len, + *this, + M2MTLVDeserializer::Put); + } + } + switch (error) { case M2MTLVDeserializer::None: - if(observation_handler) { + if (observation_handler) { String value = ""; if (received_coap_header->uri_path_ptr != NULL && received_coap_header->uri_path_len > 0) { @@ -477,10 +490,13 @@ sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *nsdl, case M2MTLVDeserializer::OutOfMemory: msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE; break; + case M2MTLVDeserializer::NotAccepted: + msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; + break; } } else { msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; - } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) + } } else { // Operation is not allowed. tr_error("M2MResource::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); @@ -489,7 +505,7 @@ sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *nsdl, } else { msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; } - if(coap_response) { + if (coap_response) { coap_response->msg_code = msg_code; } } else { diff --git a/mbed-client/source/m2mresourcebase.cpp b/mbed-client/source/m2mresourcebase.cpp index 2b9477e98..9636417fe 100644 --- a/mbed-client/source/m2mresourcebase.cpp +++ b/mbed-client/source/m2mresourcebase.cpp @@ -135,6 +135,8 @@ M2MResourceBase::~M2MResourceBase() M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceBaseValueReadCallback); + M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceBaseValueReadSizeCallback); + M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceBaseValueWriteCallback); M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceReadCallback); @@ -598,14 +600,22 @@ sn_coap_hdr_s *M2MResourceBase::handle_get_request(nsdl_s *nsdl, } if (received_coap_header && (operation() & M2MBase::GET_ALLOWED) != 0) { - bool content_type_present = false; coap_response->payload_ptr = NULL; - size_t payload_len = 0; - - if (received_coap_header->options_list_ptr && - received_coap_header->options_list_ptr->accept != COAP_CT_NONE) { - coap_response->content_format = received_coap_header->options_list_ptr->accept; - set_coap_content_type(coap_response->content_format); + uint32_t payload_len = 0; + + if (received_coap_header->options_list_ptr && received_coap_header->options_list_ptr->accept != COAP_CT_NONE) { + if ((received_coap_header->options_list_ptr->accept == COAP_CONTENT_OMA_OPAQUE_TYPE) || + (received_coap_header->options_list_ptr->accept == COAP_CONTENT_OMA_PLAIN_TEXT_TYPE) || + (received_coap_header->options_list_ptr->accept == COAP_CONTENT_OMA_TLV_TYPE_OLD) || + (received_coap_header->options_list_ptr->accept == COAP_CONTENT_OMA_TLV_TYPE)) { + coap_response->content_format = received_coap_header->options_list_ptr->accept; + set_coap_content_type(coap_response->content_format); + } else { + // Invalid accept or json which we don't support + tr_error("M2MResourceBase::handle_get_request() - invalid or unsupported accept: %d", received_coap_header->options_list_ptr->accept); + coap_response->msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; + return coap_response; + } } else { if (resource_instance_type() == M2MResourceInstance::OPAQUE) { coap_response->content_format = sn_coap_content_format_e(COAP_CONTENT_OMA_OPAQUE_TYPE); @@ -631,17 +641,19 @@ sn_coap_hdr_s *M2MResourceBase::handle_get_request(nsdl_s *nsdl, received_coap_header->uri_path_len > 0) { name.append_raw((char *)received_coap_header->uri_path_ptr, received_coap_header->uri_path_len); } - (*outgoing_block_message_cb)(name, coap_response->payload_ptr, (uint32_t &)payload_len); + (*outgoing_block_message_cb)(name, coap_response->payload_ptr, payload_len); } #endif // Read resource data from application M2MCallbackAssociation *item = M2MCallbackStorage::get_association_item(*this, M2MCallbackAssociation::M2MResourceInstanceReadCallback); if (item) { - read_data_from_application(item, nsdl, received_coap_header, coap_response, payload_len); + size_t len = 0; + read_data_from_application(item, nsdl, received_coap_header, coap_response, len); + payload_len = len; } else { if (coap_response->content_format == COAP_CONTENT_OMA_TLV_TYPE || coap_response->content_format == COAP_CONTENT_OMA_TLV_TYPE_OLD) { - coap_response->payload_ptr = M2MTLVSerializer::serialize(&get_parent_resource(), (uint32_t &)payload_len); + coap_response->payload_ptr = M2MTLVSerializer::serialize(&get_parent_resource(), payload_len); } else { get_value(coap_response->payload_ptr, (uint32_t &)payload_len); } @@ -752,8 +764,8 @@ sn_coap_hdr_s *M2MResourceBase::handle_put_request(nsdl_s *nsdl, } #endif // Firmware object uri path is limited to be max 255 bytes - if ((strcmp(uri_path(), FIRMAWARE_PACKAGE_URI_PATH) == 0) && - received_coap_header->payload_len > 255) { + if ((strcmp(uri_path(), FIRMWARE_PACKAGE_URI_PATH) == 0) && + received_coap_header->payload_len > MAX_FIRMWARE_PACKAGE_URI_PATH_LEN) { msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; } else if ((strcmp(uri_path(), SERVER_LIFETIME_PATH) == 0)) { // Check that lifetime can't go below 60s diff --git a/mbed-client/source/m2mserver.cpp b/mbed-client/source/m2mserver.cpp index 8c9b31d6b..aa8e82ba9 100644 --- a/mbed-client/source/m2mserver.cpp +++ b/mbed-client/source/m2mserver.cpp @@ -32,7 +32,7 @@ M2MServer::M2MServer() _server_instance = object_instance(); - if(_server_instance) { + if (_server_instance) { _server_instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); _server_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED); @@ -40,51 +40,59 @@ M2MServer::M2MServer() OMA_RESOURCE_TYPE, M2MResourceInstance::INTEGER, true); - if(res) { + if (res) { res->set_operation(M2MBase::GET_PUT_ALLOWED); } res = _server_instance->create_dynamic_resource(SERVER_LIFETIME, OMA_RESOURCE_TYPE, M2MResourceInstance::INTEGER, true); - if(res) { + if (res) { res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); } + + res = _server_instance->create_dynamic_resource(SERVER_DISABLE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if (res) { + res->set_operation(M2MBase::POST_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SERVER_NOTIFICATION_STORAGE, OMA_RESOURCE_TYPE, M2MResourceInstance::BOOLEAN, true); - if(res) { + if (res) { res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); } res = _server_instance->create_dynamic_resource(SERVER_BINDING, OMA_RESOURCE_TYPE, M2MResourceInstance::STRING, true); - if(res) { + if (res) { res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); } res = _server_instance->create_dynamic_resource(SERVER_REGISTRATION_UPDATE, OMA_RESOURCE_TYPE, M2MResourceInstance::OPAQUE, false); - if(res) { - res->set_operation(M2MBase::POST_ALLOWED); + if (res) { + res->set_operation(M2MBase::POST_ALLOWED); } } } M2MServer::~M2MServer() { - } M2MResource* M2MServer::create_resource(ServerResource resource, uint32_t value) { M2MResource* res = NULL; const char* server_id_ptr = ""; - if(!is_resource_present(resource)) { - switch(resource) { + if (!is_resource_present(resource)) { + switch (resource) { case DefaultMinPeriod: server_id_ptr = SERVER_DEFAULT_MIN_PERIOD; break; @@ -99,16 +107,15 @@ M2MResource* M2MServer::create_resource(ServerResource resource, uint32_t value) } } String server_id(server_id_ptr); - - if(!server_id.empty()) { - if(_server_instance) { + + if (!server_id.empty()) { + if (_server_instance) { res = _server_instance->create_dynamic_resource(server_id, OMA_RESOURCE_TYPE, M2MResourceInstance::INTEGER, true); - if(res) { + if (res) { res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); - res->set_value(value); } } @@ -119,14 +126,14 @@ M2MResource* M2MServer::create_resource(ServerResource resource, uint32_t value) M2MResource* M2MServer::create_resource(ServerResource resource) { M2MResource* res = NULL; - if(!is_resource_present(resource)) { - if(M2MServer::Disable == resource) { - if(_server_instance) { + if (!is_resource_present(resource)) { + if (M2MServer::Disable == resource) { + if (_server_instance) { res = _server_instance->create_dynamic_resource(SERVER_DISABLE, OMA_RESOURCE_TYPE, M2MResourceInstance::OPAQUE, false); - if(res) { + if (res) { res->set_operation(M2MBase::POST_ALLOWED); } } @@ -139,7 +146,7 @@ bool M2MServer::delete_resource(ServerResource resource) { bool success = false; const char* server_id_ptr; - switch(resource) { + switch (resource) { case DefaultMinPeriod: server_id_ptr = SERVER_DEFAULT_MIN_PERIOD; break; @@ -157,8 +164,8 @@ bool M2MServer::delete_resource(ServerResource resource) break; } - if(server_id_ptr) { - if(_server_instance) { + if (server_id_ptr) { + if (_server_instance) { success = _server_instance->remove_resource(server_id_ptr); } } @@ -170,8 +177,8 @@ bool M2MServer::set_resource_value(ServerResource resource, { bool success = false; M2MResource* res = get_resource(resource); - if(res && (M2MServer::Binding == resource)) { - success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length()); + if (res && (M2MServer::Binding == resource)) { + success = res->set_value((const uint8_t*)value.c_str(), (uint32_t)value.length()); } return success; } @@ -181,17 +188,16 @@ bool M2MServer::set_resource_value(ServerResource resource, { bool success = false; M2MResource* res = get_resource(resource); - if(res) { - if(M2MServer::ShortServerID == resource || - M2MServer::Lifetime == resource || - M2MServer::DefaultMinPeriod == resource || - M2MServer::DefaultMaxPeriod == resource || - M2MServer::DisableTimeout == resource || - M2MServer::NotificationStorage == resource) { - // If it is any of the above resource - // set the value of the resource. - - success = res->set_value(value); + if (res) { + if (M2MServer::ShortServerID == resource || + M2MServer::Lifetime == resource || + M2MServer::DefaultMinPeriod == resource || + M2MServer::DefaultMaxPeriod == resource || + M2MServer::DisableTimeout == resource || + M2MServer::NotificationStorage == resource) { + // If it is any of the above resource + // set the value of the resource. + success = res->set_value(value); } } return success; @@ -201,27 +207,24 @@ String M2MServer::resource_value_string(ServerResource resource) const { String value = ""; M2MResource* res = get_resource(resource); - if(res && (M2MServer::Binding == resource)) { - + if (res && (M2MServer::Binding == resource)) { value = res->get_value_string(); } return value; } - uint32_t M2MServer::resource_value_int(ServerResource resource) const { uint32_t value = 0; M2MResource* res = get_resource(resource); - if(res) { - if(M2MServer::ShortServerID == resource || - M2MServer::Lifetime == resource || - M2MServer::DefaultMinPeriod == resource || - M2MServer::DefaultMaxPeriod == resource || - M2MServer::DisableTimeout == resource || - M2MServer::NotificationStorage == resource) { - - value = res->get_value_int(); + if (res) { + if (M2MServer::ShortServerID == resource || + M2MServer::Lifetime == resource || + M2MServer::DefaultMinPeriod == resource || + M2MServer::DefaultMaxPeriod == resource || + M2MServer::DisableTimeout == resource || + M2MServer::NotificationStorage == resource) { + value = res->get_value_int(); } } return value; @@ -231,7 +234,7 @@ bool M2MServer::is_resource_present(ServerResource resource) const { bool success = false; M2MResource *res = get_resource(resource); - if(res) { + if (res) { success = true; } return success; @@ -240,8 +243,8 @@ bool M2MServer::is_resource_present(ServerResource resource) const uint16_t M2MServer::total_resource_count() const { uint16_t total_count = 0; - if(_server_instance) { - total_count = _server_instance->resources().size(); + if (_server_instance) { + total_count = _server_instance->resources().size(); } return total_count; } @@ -250,38 +253,38 @@ M2MResource* M2MServer::get_resource(ServerResource res) const { M2MResource* res_object = NULL; const char* res_name_ptr = NULL; - switch(res) { - case ShortServerID: - res_name_ptr = SERVER_SHORT_SERVER_ID; - break; - case Lifetime: - res_name_ptr = SERVER_LIFETIME; - break; - case DefaultMinPeriod: - res_name_ptr = SERVER_DEFAULT_MIN_PERIOD; - break; - case DefaultMaxPeriod: - res_name_ptr = SERVER_DEFAULT_MAX_PERIOD; - break; - case Disable: - res_name_ptr = SERVER_DISABLE; - break; - case DisableTimeout: - res_name_ptr = SERVER_DISABLE_TIMEOUT; - break; - case NotificationStorage: - res_name_ptr = SERVER_NOTIFICATION_STORAGE; - break; - case Binding: - res_name_ptr = SERVER_BINDING; - break; - case RegistrationUpdate: - res_name_ptr = SERVER_REGISTRATION_UPDATE; - break; - } + switch (res) { + case ShortServerID: + res_name_ptr = SERVER_SHORT_SERVER_ID; + break; + case Lifetime: + res_name_ptr = SERVER_LIFETIME; + break; + case DefaultMinPeriod: + res_name_ptr = SERVER_DEFAULT_MIN_PERIOD; + break; + case DefaultMaxPeriod: + res_name_ptr = SERVER_DEFAULT_MAX_PERIOD; + break; + case Disable: + res_name_ptr = SERVER_DISABLE; + break; + case DisableTimeout: + res_name_ptr = SERVER_DISABLE_TIMEOUT; + break; + case NotificationStorage: + res_name_ptr = SERVER_NOTIFICATION_STORAGE; + break; + case Binding: + res_name_ptr = SERVER_BINDING; + break; + case RegistrationUpdate: + res_name_ptr = SERVER_REGISTRATION_UPDATE; + break; + } - if(res_name_ptr) { - if(_server_instance) { + if (res_name_ptr) { + if (_server_instance) { res_object = _server_instance->resource(res_name_ptr); } } diff --git a/mbed-client/source/m2mtlvdeserializer.cpp b/mbed-client/source/m2mtlvdeserializer.cpp index e1b86f29c..8528c2652 100755 --- a/mbed-client/source/m2mtlvdeserializer.cpp +++ b/mbed-client/source/m2mtlvdeserializer.cpp @@ -53,17 +53,17 @@ bool M2MTLVDeserializer::is_resource_instance(const uint8_t *tlv) return is_resource_instance(tlv, 0); } -M2MTLVDeserializer::Error M2MTLVDeserializer::deserialise_object_instances(const uint8_t* tlv, +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialise_object_instances(const uint8_t *tlv, uint32_t tlv_size, M2MObject &object, M2MTLVDeserializer::Operation operation) { M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; - if (is_object_instance(tlv) ) { + if (is_object_instance(tlv)) { tr_debug("M2MTLVDeserializer::deserialise_object_instances"); - error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,false); - if(M2MTLVDeserializer::None == error) { - error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,true); + error = deserialize_object_instances(tlv, tlv_size, 0, object, operation, false); + if (M2MTLVDeserializer::None == error) { + error = deserialize_object_instances(tlv, tlv_size, 0, object, operation, true); } } else { tr_debug("M2MTLVDeserializer::deserialise_object_instances ::NotValid"); @@ -81,17 +81,34 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_ if (!is_resource(tlv) && !is_multiple_resource(tlv)) { error = M2MTLVDeserializer::NotValid; } else { - error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,false); - if(M2MTLVDeserializer::None == error) { + error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation, false); + if (M2MTLVDeserializer::None == error) { if (M2MTLVDeserializer::Put == operation) { remove_resources(tlv, tlv_size, object_instance, 0); } - error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,true); + error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation, true); } } return error; } +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource(const uint8_t *tlv, + uint32_t tlv_size, + M2MResource &resource, + M2MTLVDeserializer::Operation operation) +{ + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + if (!is_resource(tlv)) { + error = M2MTLVDeserializer::NotValid; + } else if (operation != M2MTLVDeserializer::Put) { + error = M2MTLVDeserializer::NotValid; + } else { + error = deserialize_resource(tlv, tlv_size, resource, operation, true); + } + + return error; +} + M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv, uint32_t tlv_size, M2MResource &resource, @@ -107,21 +124,21 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(con ((tlv[0] & 0x20) == 0) ? offset : offset++; uint8_t length = tlv[0] & 0x18; - if(length == 0x08) { + if (length == 0x08) { offset += 1; - } else if(length == 0x10) { + } else if (length == 0x10) { offset += 2; - } else if(length == 0x18) { + } else if (length == 0x18) { offset += 3; } tr_debug("M2MTLVDeserializer::deserialize_resource_instances() Offset %d", offset); - error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,false); - if(M2MTLVDeserializer::None == error) { + error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation, false); + if (M2MTLVDeserializer::None == error) { if (M2MTLVDeserializer::Put == operation) { remove_resource_instances(tlv, tlv_size, resource, offset); } - error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,true); + error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation, true); } } return error; @@ -145,14 +162,14 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_object_instances(const it = list.begin(); if (TYPE_OBJECT_INSTANCE == til._type) { - for (; it!=list.end(); it++) { - if((*it)->instance_id() == til._id) { - error = deserialize_resources(tlv, tlv_size, offset, (**it),operation, update_value); + for (; it != list.end(); it++) { + if ((*it)->instance_id() == til._id) { + error = deserialize_resources(tlv, tlv_size, offset, (**it), operation, update_value); } } offset += til._length; - if(offset < tlv_size) { + if (offset < tlv_size) { error = deserialize_object_instances(tlv, tlv_size, offset, object, operation, update_value); } } @@ -180,14 +197,14 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_ bool multi = false; if (TYPE_RESOURCE == til._type || TYPE_RESOURCE_INSTANCE == til._type) { multi = false; - for (; it!=list.end(); it++) { - if((*it)->name_id() == til._id){ + for (; it != list.end(); it++) { + if ((*it)->name_id() == til._id) { tr_debug("M2MTLVDeserializer::deserialize_resources() - Resource ID %d ", til._id); found = true; - if(update_value) { - if(til._length > 0) { + if (update_value) { + if (til._length > 0) { tr_debug("M2MTLVDeserializer::deserialize_resources() - Update value"); - if (!set_resource_instance_value((*it), tlv+offset, til._length)) { + if (!set_resource_instance_value((*it), tlv + offset, til._length)) { error = M2MTLVDeserializer::OutOfMemory; break; } @@ -196,7 +213,7 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_ (*it)->clear_value(); } break; - } else if(0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { + } else if (0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { tr_debug("M2MTLVDeserializer::deserialize_resources() - NOT_ALLOWED"); error = M2MTLVDeserializer::NotAllowed; break; @@ -205,8 +222,8 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_ } } else if (TYPE_MULTIPLE_RESOURCE == til._type) { multi = true; - for (; it!=list.end(); it++) { - if((*it)->supports_multiple_instances() && + for (; it != list.end(); it++) { + if ((*it)->supports_multiple_instances() && (*it)->name_id() == til._id) { found = true; error = deserialize_resource_instances(tlv, tlv_size, offset, (**it), object_instance, operation, update_value); @@ -225,7 +242,7 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_ M2MResource *resource = object_instance.create_dynamic_resource(id, "", M2MResourceInstance::OPAQUE, true, multi); if (resource) { resource->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED); - if (TYPE_MULTIPLE_RESOURCE == til._type) { + if (TYPE_MULTIPLE_RESOURCE == til._type) { error = deserialize_resource_instances(tlv, tlv_size, offset, (*resource), object_instance, operation, update_value); } } @@ -243,6 +260,42 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_ return error; } +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource(const uint8_t *tlv, + uint32_t tlv_size, + M2MResource &resource, + M2MTLVDeserializer::Operation operation, + bool update_value) +{ + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + if (resource.operation() & M2MBase::PUT_ALLOWED) { + int offset = 0; + TypeIdLength til(tlv, offset); + til.deserialize(); + offset = til._offset; + + if (resource.resource_instance_type() == M2MResourceBase::INTEGER) { + int64_t value = String::convert_array_to_integer(tlv + offset, til._length); + if ((strcmp(resource.uri_path(), SERVER_LIFETIME_PATH) == 0) && (value < MINIMUM_REGISTRATION_TIME)) { + // Check that lifetime can't go below 60s + return M2MTLVDeserializer::NotAccepted; + } else { + if (!resource.set_value(value)) { + error = M2MTLVDeserializer::OutOfMemory; + } + } + } + + tr_debug("M2MTLVDeserializer::deserialize_resource() - Update value"); + if (!set_resource_instance_value(&resource, tlv + offset, til._length)) { + error = M2MTLVDeserializer::OutOfMemory; + } + } else { + error = M2MTLVDeserializer::NotAllowed; + } + + return error; +} + M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv, uint32_t tlv_size, uint32_t offset, @@ -261,12 +314,12 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(con M2MResourceInstanceList::const_iterator it; it = list.begin(); bool found = false; - for (; it!=list.end(); it++) { - if((*it)->instance_id() == til._id && TYPE_RESOURCE_INSTANCE == til._type) { + for (; it != list.end(); it++) { + if ((*it)->instance_id() == til._id && TYPE_RESOURCE_INSTANCE == til._type) { found = true; - if(update_value) { - if(til._length > 0) { - if (!set_resource_instance_value((*it), tlv+offset, til._length)) { + if (update_value) { + if (til._length > 0) { + if (!set_resource_instance_value((*it), tlv + offset, til._length)) { error = M2MTLVDeserializer::OutOfMemory; break; } @@ -274,24 +327,24 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(con (*it)->clear_value(); } break; - } else if(0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { + } else if (0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { error = M2MTLVDeserializer::NotAllowed; break; } } } - if(!found) { - if(M2MTLVDeserializer::Post == operation) { + if (!found) { + if (M2MTLVDeserializer::Post == operation) { // Create a new Resource Instance - M2MResourceInstance *res_instance = object_instance.create_dynamic_resource_instance(resource.name(),"", - resource.resource_instance_type(), - true, - til._id); - if(res_instance) { + M2MResourceInstance *res_instance = object_instance.create_dynamic_resource_instance(resource.name(), "", + resource.resource_instance_type(), + true, + til._id); + if (res_instance) { res_instance->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED); } - } else if(M2MTLVDeserializer::Put == operation) { + } else if (M2MTLVDeserializer::Put == operation) { error = M2MTLVDeserializer::NotFound; } } @@ -302,8 +355,8 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(con offset += til._length; - if(offset < tlv_size) { - error = deserialize_resource_instances(tlv, tlv_size, offset, resource, object_instance, operation, update_value); + if (offset < tlv_size) { + error = deserialize_resource_instances(tlv, tlv_size, offset, resource, object_instance, operation, update_value); } return error; } @@ -315,6 +368,9 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(con M2MTLVDeserializer::Operation operation, bool update_value) { + if (tlv_size < offset + 1) { + return M2MTLVDeserializer::NotValid; + } M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; TypeIdLength til(tlv, offset); til.deserialize(); @@ -325,12 +381,12 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(con M2MResourceInstanceList::const_iterator it; it = list.begin(); bool found = false; - for (; it!=list.end(); it++) { - if((*it)->instance_id() == til._id) { + for (; it != list.end(); it++) { + if ((*it)->instance_id() == til._id) { found = true; - if(update_value) { - if(til._length > 0) { - if (!set_resource_instance_value((*it),tlv+offset, til._length)) { + if (update_value) { + if (til._length > 0) { + if (!set_resource_instance_value((*it), tlv + offset, til._length)) { error = M2MTLVDeserializer::OutOfMemory; break; } @@ -338,24 +394,24 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(con (*it)->clear_value(); } break; - } else if(0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { + } else if (0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { error = M2MTLVDeserializer::NotAllowed; break; } } } - if(!found) { - if(M2MTLVDeserializer::Post == operation) { + if (!found) { + if (M2MTLVDeserializer::Post == operation) { error = M2MTLVDeserializer::NotAllowed; - } else if(M2MTLVDeserializer::Put == operation) { + } else if (M2MTLVDeserializer::Put == operation) { // Create a new Resource Instance M2MResourceInstance *res_instance = resource.get_parent_object_instance().create_dynamic_resource_instance( - resource.name(), - "", - resource.resource_instance_type(), - true, - til._id); - if(res_instance) { + resource.name(), + "", + resource.resource_instance_type(), + true, + til._id); + if (res_instance) { res_instance->set_operation(M2MBase::GET_PUT_DELETE_ALLOWED); } } @@ -368,8 +424,8 @@ M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(con offset += til._length; - if(offset < tlv_size) { - error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation, update_value); + if (offset < tlv_size) { + error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation, update_value); } return error; } @@ -425,22 +481,22 @@ bool M2MTLVDeserializer::set_resource_instance_value(M2MResourceBase *res, const switch (res->resource_instance_type()) { case M2MResourceBase::INTEGER: case M2MResourceBase::BOOLEAN: - case M2MResourceBase::TIME: - { + case M2MResourceBase::TIME: { int64_t value = String::convert_array_to_integer(tlv, size); success = res->set_value(value); break; - // Todo! implement conversion for other types as well + // Todo! implement conversion for other types as well } case M2MResourceBase::STRING: case M2MResourceBase::OPAQUE: case M2MResourceBase::OBJLINK: success = res->set_value(tlv, size); break; - case M2MResourceBase::FLOAT: - { + case M2MResourceBase::FLOAT: { uint32_t value = common_read_32_bit(tlv); - success = res->set_value_float(*(float*)&value); + float float_value = 0; + memcpy(&float_value, &value, size); + success = res->set_value_float(float_value); break; } default: @@ -460,14 +516,14 @@ void M2MTLVDeserializer::remove_resources(const uint8_t *tlv, M2MResourceList::const_iterator it; it = list.begin(); - for (; it!=list.end();) { + for (; it != list.end();) { bool found = false; - while(offset < tlv_size) { + while (offset < tlv_size) { TypeIdLength til(tlv, offset); til.deserialize(); offset = til._offset; offset += til._length; - if((*it)->name_id() == til._id){ + if ((*it)->name_id() == til._id) { offset = offset_size; found = true; break; @@ -486,9 +542,9 @@ void M2MTLVDeserializer::remove_resources(const uint8_t *tlv, } void M2MTLVDeserializer::remove_resource_instances(const uint8_t *tlv, - uint32_t tlv_size, - M2MResource &resource, - uint32_t offset_size) + uint32_t tlv_size, + M2MResource &resource, + uint32_t offset_size) { tr_debug("M2MTLVDeserializer::remove_resource_instances"); uint32_t offset = offset_size; @@ -496,14 +552,14 @@ void M2MTLVDeserializer::remove_resource_instances(const uint8_t *tlv, M2MResourceInstanceList::const_iterator it; it = list.begin(); - for (; it!=list.end();) { + for (; it != list.end();) { bool found = false; while (offset < tlv_size) { TypeIdLength til(tlv, offset); til.deserialize(); offset = til._offset; offset += til._length; - if ((*it)->instance_id() == til._id){ + if ((*it)->instance_id() == til._id) { offset = offset_size; found = true; break; @@ -522,7 +578,7 @@ void M2MTLVDeserializer::remove_resource_instances(const uint8_t *tlv, } TypeIdLength::TypeIdLength(const uint8_t *tlv, uint32_t offset) -: _tlv(tlv), _offset(offset), _type(tlv[offset] & 0xC0), _id(0), _length(0) + : _tlv(tlv), _offset(offset), _type(tlv[offset] & 0xC0), _id(0), _length(0) { } diff --git a/mbed-client/source/m2mtlvserializer.cpp b/mbed-client/source/m2mtlvserializer.cpp index 1815bf94e..eb9602ede 100644 --- a/mbed-client/source/m2mtlvserializer.cpp +++ b/mbed-client/source/m2mtlvserializer.cpp @@ -25,57 +25,57 @@ #define MAX_TLV_ID_SIZE 2 #define TLV_TYPE_SIZE 1 -uint8_t* M2MTLVSerializer::serialize(const M2MObjectInstanceList &object_instance_list, uint32_t &size) +uint8_t *M2MTLVSerializer::serialize(const M2MObjectInstanceList &object_instance_list, uint32_t &size) { return serialize_object_instances(object_instance_list, size); } -uint8_t* M2MTLVSerializer::serialize(const M2MResourceList &resource_list, uint32_t &size) +uint8_t *M2MTLVSerializer::serialize(const M2MResourceList &resource_list, uint32_t &size) { bool valid = true; - return serialize_resources(resource_list, size,valid); + return serialize_resources(resource_list, size, valid); } -uint8_t* M2MTLVSerializer::serialize(const M2MResource *resource, uint32_t &size) +uint8_t *M2MTLVSerializer::serialize(const M2MResource *resource, uint32_t &size) { - uint8_t* data = NULL; + uint8_t *data = NULL; serialize(resource, data, size); return data; } -uint8_t* M2MTLVSerializer::serialize_object_instances(const M2MObjectInstanceList &object_instance_list, uint32_t &size) +uint8_t *M2MTLVSerializer::serialize_object_instances(const M2MObjectInstanceList &object_instance_list, uint32_t &size) { uint8_t *data = NULL; - if(!object_instance_list.empty()) { + if (!object_instance_list.empty()) { M2MObjectInstanceList::const_iterator it; it = object_instance_list.begin(); - for (; it!=object_instance_list.end(); it++) { + for (; it != object_instance_list.end(); it++) { uint16_t id = (*it)->instance_id(); - serialize(id, *it, data, size); + serialize(id, *it, data, size); } } return data; } -uint8_t* M2MTLVSerializer::serialize_resources(const M2MResourceList &resource_list, uint32_t &size, bool &valid) +uint8_t *M2MTLVSerializer::serialize_resources(const M2MResourceList &resource_list, uint32_t &size, bool &valid) { uint8_t *data = NULL; - if(!resource_list.empty()) { + if (!resource_list.empty()) { M2MResourceList::const_iterator it; it = resource_list.begin(); - for (; it!=resource_list.end(); it++) { - if((*it)->name_id() == -1) { + for (; it != resource_list.end(); it++) { + if ((*it)->name_id() == -1) { valid = false; break; } } - if(valid) { + if (valid) { it = resource_list.begin(); - for (; it!=resource_list.end(); it++) { + for (; it != resource_list.end(); it++) { if (((*it)->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) { - if(!serialize(*it, data, size)) { + if (!serialize(*it, data, size)) { /* serializing has failed */ /* free data so far */ free(data); @@ -98,9 +98,9 @@ bool M2MTLVSerializer::serialize(uint16_t id, const M2MObjectInstance *object_in bool success; bool valid = true; - resource_data = serialize_resources(object_instance->resources(),resource_size,valid); - if(valid) { - if(serialize_TILV(TYPE_OBJECT_INSTANCE, id, resource_data, resource_size, data, size)) { + resource_data = serialize_resources(object_instance->resources(), resource_size, valid); + if (valid) { + if (serialize_TILV(TYPE_OBJECT_INSTANCE, id, resource_data, resource_size, data, size)) { success = true; } else { /* serializing object instance failed */ @@ -117,10 +117,10 @@ bool M2MTLVSerializer::serialize(uint16_t id, const M2MObjectInstance *object_in bool M2MTLVSerializer::serialize(const M2MResource *resource, uint8_t *&data, uint32_t &size) { bool success = false; - if(resource->name_id() != -1) { + if (resource->name_id() != -1) { success = resource->supports_multiple_instances() ? - serialize_multiple_resource(resource, data, size) : - serialize_resource(resource, data, size); + serialize_multiple_resource(resource, data, size) : + serialize_resource(resource, data, size); } return success; } @@ -128,18 +128,16 @@ bool M2MTLVSerializer::serialize(const M2MResource *resource, uint8_t *&data, ui bool M2MTLVSerializer::serialize_resource(const M2MResource *resource, uint8_t *&data, uint32_t &size) { bool success = false; - if(resource->name_id() != -1) { - if ( (resource->resource_instance_type() == M2MResourceBase::INTEGER) || - (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) || - (resource->resource_instance_type() == M2MResourceBase::TIME) ) { + if (resource->name_id() != -1) { + if ((resource->resource_instance_type() == M2MResourceBase::INTEGER) || + (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) || + (resource->resource_instance_type() == M2MResourceBase::TIME)) { success = serialize_TLV_binary_int(resource, TYPE_RESOURCE, resource->name_id(), data, size); - } - else if (resource->resource_instance_type() == M2MResourceBase::FLOAT) { + } else if (resource->resource_instance_type() == M2MResourceBase::FLOAT) { success = serialize_TLV_binary_float(resource, TYPE_RESOURCE, resource->name_id(), data, size); - } - else { - success = serialize_TILV(TYPE_RESOURCE, resource->name_id(), - resource->value(), resource->value_length(), data, size); + } else { + success = serialize_TILV(TYPE_RESOURCE, resource->name_id(), + resource->value(), resource->value_length(), data, size); } } return success; @@ -152,13 +150,13 @@ bool M2MTLVSerializer::serialize_multiple_resource(const M2MResource *resource, uint32_t nested_data_size = 0; const M2MResourceInstanceList &instance_list = resource->resource_instances(); - if(!instance_list.empty()) { + if (!instance_list.empty()) { M2MResourceInstanceList::const_iterator it; it = instance_list.begin(); - for (; it!=instance_list.end(); it++) { + for (; it != instance_list.end(); it++) { uint16_t id = (*it)->instance_id(); if (((*it)->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) { - if(!serialize_resource_instance(id, (*it), nested_data, nested_data_size)) { + if (!serialize_resource_instance(id, (*it), nested_data, nested_data_size)) { /* serializing instance has failed */ /* free data so far allocated */ free(nested_data); @@ -169,10 +167,10 @@ bool M2MTLVSerializer::serialize_multiple_resource(const M2MResource *resource, } } } - if(resource->name_id() != -1 && + if (resource->name_id() != -1 && (resource->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) { success = serialize_TILV(TYPE_MULTIPLE_RESOURCE, resource->name_id(), - nested_data, nested_data_size, data, size); + nested_data, nested_data_size, data, size); } free(nested_data); @@ -183,16 +181,14 @@ bool M2MTLVSerializer::serialize_resource_instance(uint16_t id, const M2MResourc { bool success; - if ( (resource->resource_instance_type() == M2MResourceBase::INTEGER) || - (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) || - (resource->resource_instance_type() == M2MResourceBase::TIME) ) { - success=serialize_TLV_binary_int(resource, TYPE_RESOURCE_INSTANCE, id, data, size); - } - else if (resource->resource_instance_type() == M2MResourceBase::FLOAT) { - success=serialize_TLV_binary_float(resource, TYPE_RESOURCE_INSTANCE, id, data, size); - } - else { - success=serialize_TILV(TYPE_RESOURCE_INSTANCE, id, resource->value(), resource->value_length(), data, size); + if ((resource->resource_instance_type() == M2MResourceBase::INTEGER) || + (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) || + (resource->resource_instance_type() == M2MResourceBase::TIME)) { + success = serialize_TLV_binary_int(resource, TYPE_RESOURCE_INSTANCE, id, data, size); + } else if (resource->resource_instance_type() == M2MResourceBase::FLOAT) { + success = serialize_TLV_binary_float(resource, TYPE_RESOURCE_INSTANCE, id, data, size); + } else { + success = serialize_TILV(TYPE_RESOURCE_INSTANCE, id, resource->value(), resource->value_length(), data, size); } return success; @@ -226,7 +222,7 @@ bool M2MTLVSerializer::serialize_TLV_binary_float(const M2MResourceBase *resourc /* max len 8 bytes */ uint8_t buffer[4]; - common_write_32_bit(*(uint32_t*)&valueFloat, buffer); + common_write_32_bit(valueFloat, buffer); return serialize_TILV(type, id, buffer, 4, data, size); } @@ -251,21 +247,21 @@ bool M2MTLVSerializer::serialize_TILV(uint8_t type, uint16_t id, uint8_t *value, uint8_t length_array[MAX_TLV_LENGTH_SIZE]; serialize_length(value_length, length_size, length_array); - tlv = (uint8_t*)malloc(size + type_length + id_size + length_size + value_length); + tlv = (uint8_t *)malloc(size + type_length + id_size + length_size + value_length); if (!tlv) { /* memory allocation has failed */ /* return failure immediately */ return false; /* eventually NULL will be returned to serializer public method caller */ } - if(data) { + if (data) { memcpy(tlv, data, size); free(data); } - memcpy(tlv+size, &tlv_type, type_length); - memcpy(tlv+size+type_length, id_array, id_size); - memcpy(tlv+size+type_length+id_size, length_array, length_size); - memcpy(tlv+size+type_length+id_size+length_size, value, value_length); + memcpy(tlv + size, &tlv_type, type_length); + memcpy(tlv + size + type_length, id_array, id_size); + memcpy(tlv + size + type_length + id_size, length_array, length_size); + memcpy(tlv + size + type_length + id_size + length_size, value, value_length); data = tlv; size += type_length + id_size + length_size + value_length; @@ -274,12 +270,12 @@ bool M2MTLVSerializer::serialize_TILV(uint8_t type, uint16_t id, uint8_t *value, void M2MTLVSerializer::serialize_id(uint16_t id, uint32_t &size, uint8_t *id_ptr) { - if(id > 255) { - size=2; + if (id > 255) { + size = 2; id_ptr[0] = (id & 0xFF00) >> 8; id_ptr[1] = id & 0xFF; } else { - size=1; + size = 1; id_ptr[0] = id & 0xFF; } } @@ -299,7 +295,7 @@ void M2MTLVSerializer::serialize_length(uint32_t length, uint32_t &size, uint8_t size = 1; length_ptr[0] = length & 0xFF; } else { - size=0; + size = 0; } } diff --git a/mbed-cloud-client/MbedCloudClient.h b/mbed-cloud-client/MbedCloudClient.h index 1e50ca414..497de02f9 100644 --- a/mbed-cloud-client/MbedCloudClient.h +++ b/mbed-cloud-client/MbedCloudClient.h @@ -46,22 +46,6 @@ #include "multicast.h" #endif // MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE -#if MBED_CLOUD_CLIENT_STL_API -#include -#include -#include -#endif - -#if MBED_CLOUD_CLIENT_STD_NAMESPACE_POLLUTION -// We should not really pollute application's namespace with std:: by having this in -// a public header file. -// But as as removal of the next line may break existing applications, which build due to this -// leakage, we need to maintain the old behavior for a while and just allow one to remove it. -using namespace std; -#endif - -class SimpleM2MResourceBase; - /** * \brief MbedCloudClientCallback * A callback class for informing updated Object and Resource value from the @@ -212,7 +196,7 @@ class MbedCloudClient : public ServiceClientCallback { MulticastErrorEnd = MULTICAST_STATUS_RANGE_END #endif // MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE - }Error; + } Error; #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE /** @@ -225,6 +209,18 @@ class MbedCloudClient : public ServiceClientCallback { }; #endif + /** + * \brief An enum defining different statuses + * that can occur during various client operations. + */ + typedef enum { + Unregistered = 0, + Registered, + RegistrationUpdated, + AlertMode, + Paused + } Status; + /** * \brief Constructor */ @@ -241,12 +237,30 @@ class MbedCloudClient : public ServiceClientCallback { * \param on_update_authorize_cb Callback function that Update Client calls to authorize firmware download or * an firmware update. * \param on_update_progress_cb Callback function that Update Client calls to report download progress. + * \deprecated */ MbedCloudClient(void(*on_registered_cb)(void), void(*on_unregistered_cb)(void), void(*on_error_cb)(int) #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE - ,void(*update_authorize_cb)(int32_t request) = NULL, + , void(*update_authorize_cb)(int32_t request) = NULL, + void(*update_progress_cb)(uint32_t progress, uint32_t total) = NULL +#endif + ) m2m_deprecated; + + /** + * \brief Constructor a Cloud Client with given callbacks. + * \param on_status_changed_cb Callback function that Device Management Client calls when the client status has changed. + * \param on_error_cb Callback function that Device Management Client calls when there is an error occuring in the + * client functionality. + * \param on_update_authorize_cb Callback function that Update Client calls to authorize firmware download or + * an firmware update. + * \param on_update_progress_cb Callback function that Update Client calls to report download progress. + */ + MbedCloudClient(void(*on_status_changed_cb)(int), + void(*on_error_cb)(int) +#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE + , void(*update_authorize_cb)(int32_t request) = NULL, void(*update_progress_cb)(uint32_t progress, uint32_t total) = NULL #endif ); @@ -264,7 +278,7 @@ class MbedCloudClient : public ServiceClientCallback { * \param object_list Objects that contain information about Device Management Client * attempting to register to the LwM2M server. */ - void add_objects(const M2MObjectList& object_list); + void add_objects(const M2MObjectList &object_list); /** * \brief Add a list of M2MBase interface implementing objects that the application wants @@ -274,7 +288,7 @@ class MbedCloudClient : public ServiceClientCallback { * \param base_list Object implementing the M2MBase interface that contain information about Device Management * Client attempting to register to the LwM2M server. */ - void add_objects(const M2MBaseList& base_list); + void add_objects(const M2MBaseList &base_list); void remove_object(M2MBase *object); @@ -284,6 +298,8 @@ class MbedCloudClient : public ServiceClientCallback { * typically on receiving `PUT` commands on the registered Objects. * \param callback Passes the class Object that implements the callback * function to handle the incoming `PUT` request on a given Object. + * + * \deprecate Please use M2MBase::set_value_updated_function() instead. */ void set_update_callback(MbedCloudClientCallback *callback); @@ -315,24 +331,26 @@ class MbedCloudClient : public ServiceClientCallback { * An application using Device Management Client must be able to recover from the failure and retry the initialization of * Device Management Client by calling this API or `init()` at later stage. */ - bool setup(void* iface); + bool setup(void *iface); /** * \brief Set the callback function that is called when Device Management Client is registered * successfully to Device Management. This is used for a statically defined function. * \param fn Function pointer to the function that is called when Device Management Client * is registered. + * \deprecated Please use `on_status_changed()` function callback instead. */ - void on_registered(void(*fn)(void)); + void on_registered(void(*fn)(void)) m2m_deprecated; /** * \brief Set the callback function that is called when Device Management Client is registered * successfully to Device Management. This is an overloaded function for a class function. * \param object Function pointer to the function that is called when Device Management Client * is registered. + * \deprecated Please use `on_status_changed()` function callback instead. */ template - void on_registered(T *object, void (T::*member)(void)); + void on_registered(T *object, void (T::*member)(void)) m2m_deprecated; /** * \brief Set the callback function that is called when there is any error @@ -353,30 +371,51 @@ class MbedCloudClient : public ServiceClientCallback { template void on_error(T *object, void (T::*member)(int)); + /** + * \brief Set the callback function that is called when the client status change. + * The status code can be mapped from the `MbedCloudClient::Status` enum. + * This is used for a statically defined function. + * \param fn Function pointer to the function that is called when the Device Management Client status change. + */ + void on_status_changed(void(*fn)(int)); + + /** + * \brief Set the callback function that is called when the client status change. + * The status code can be mapped from the `MbedCloudClient::Status` enum. + * This is an overloaded function for a class function. + * \param object Function pointer to the function that is called when the + * Device Management Client status change. + */ + template + void on_status_changed(T *object, void (T::*member)(int)); + /** * \brief Set the callback function that is called when Device Management Client is unregistered * successfully from Device Management. This is used for a statically defined function. * \param fn Function pointer to the function that is called when Device Management Client * is unregistered. + * \deprecated Please use `on_status_changed()` function callback instead. */ - void on_unregistered(void(*fn)(void)); + void on_unregistered(void(*fn)(void)) m2m_deprecated; /** * \brief Set the callback function that is called when Device Management Client is unregistered * successfully from Device Management. This is an overloaded function for a class function. * \param object Function pointer to the function that is called when Device Management Client * is unregistered. + * \deprecated Please use `on_status_changed()` function callback instead. */ template - void on_unregistered(T *object, void (T::*member)(void)); + void on_unregistered(T *object, void (T::*member)(void)) m2m_deprecated; /** * \brief Set the callback function that is called when Device Management Client registration * is updated successfully to Device Management. This is used for a statically defined function. * \param fn Function pointer to the function that is called when Device Management Client * registration is updated. + * \deprecated Please use `on_status_changed()` function callback instead. */ - void on_registration_updated(void(*fn)(void)); + void on_registration_updated(void(*fn)(void)) m2m_deprecated; /** * \brief Set the callback function that is called when Device Management Client registration @@ -384,16 +423,17 @@ class MbedCloudClient : public ServiceClientCallback { * function. * \param object Function pointer to the function that is called when Device Management Client * registration is updated. + * \deprecated Please use `on_status_changed()` function callback instead. */ template - void on_registration_updated(T *object, void (T::*member)(void)); + void on_registration_updated(T *object, void (T::*member)(void)) m2m_deprecated; /** * \brief Send a registration update message to Device Management when Device Management Client is registered * successfully and there is no internal connection error. * If Device Management Client is not connected and there is some other internal network * transaction ongoing, this function triggers an error `MbedCloudClient::ConnectNotAllowed`. - * \deprecated + * \deprecated Please, use the MbedCloudClient::register_update() instead. */ void keep_alive() m2m_deprecated; @@ -451,21 +491,6 @@ class MbedCloudClient : public ServiceClientCallback { */ void set_entropy_callback(entropy_cb callback); -#if MBED_CLOUD_CLIENT_STL_API - /** - * \brief Set resource value in the Device Object. - * - * \note This API and functionality using STL is being phased out, as it is wasting resources by - * duplicating data and harming portability by requiring an STL implementation. - * - * \param resource Device enum to have value set. - * \param value String object. - * \return True if successful, false otherwise. - */ - bool set_device_resource_value(M2MDevice::DeviceResource resource, - const std::string &value) m2m_deprecated; -#endif - #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE /** * \brief Register a callback function for authorizing firmware downloads and reboots. @@ -579,6 +604,14 @@ class MbedCloudClient : public ServiceClientCallback { */ void resume(void *iface); + /** + * \brief Sets Device Management Client into an alert mode. + * + * \note In alert mode Device Management Client halts all data + * sendings/active operations and waits for priority data to be sent. + */ + void alert(); + #ifndef MBED_CLIENT_DISABLE_EST_FEATURE /** * \brief Perform enrollment over secure transport for a certificate signing request. @@ -639,18 +672,6 @@ class MbedCloudClient : public ServiceClientCallback { virtual void external_update(uint32_t start_address, uint32_t firmware_size); #endif -private: - - /** - * \brief Register the update callback functions for `SimpleM2MResourceBase` - * objects. - * \param route The URI path of the registered Resource such as `/Test/0/res/`. - * \param resource Object of the `SimpleM2MResourceBase`. - */ -#if MBED_CLOUD_CLIENT_STL_API - void register_update_callback(string route, SimpleM2MResourceBase* resource) m2m_deprecated; -#endif - private: ServiceClient _client; @@ -659,23 +680,14 @@ class MbedCloudClient : public ServiceClientCallback { FP0 _on_registered; FP0 _on_unregistered; FP0 _on_registration_updated; - FP1 _on_error; + FP1 _on_error; + FP1 _on_status_changed; const char *_error_description; bool _init_done; #ifdef MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE FP2 _on_external_update; #endif -#if MBED_CLOUD_CLIENT_STL_API - // This API and functionality is being phased out, as it is wasting resources by - // duplicating data and harming portability by requiring an STL implementation. - map _objects; - map _resources; - map _update_values; - -friend class SimpleM2MResourceBase; - -#endif // MBED_CLOUD_CLIENT_STL_API }; template @@ -705,4 +717,11 @@ void MbedCloudClient::on_registration_updated(T *object, void (T::*member)(void) FP0 fp(object, member); _on_registration_updated = fp; } + +template +void MbedCloudClient::on_status_changed(T *object, void (T::*member)(int)) +{ + FP1 fp(object, member); + _on_status_changed = fp; +} #endif // __MBED_CLOUD_CLIENT_H__ diff --git a/mbed-cloud-client/MbedCloudClientConfig.h b/mbed-cloud-client/MbedCloudClientConfig.h index a954bc106..562dd431c 100644 --- a/mbed-cloud-client/MbedCloudClientConfig.h +++ b/mbed-cloud-client/MbedCloudClientConfig.h @@ -40,7 +40,7 @@ #ifdef MBED_CLIENT_USER_CONFIG_FILE #include MBED_CLIENT_USER_CONFIG_FILE #warning MBED_CLIENT_USER_CONFIG_FILE macro is deprecated. \ - Please use only MBED_CLOUD_CLIENT_USER_CONFIG_FILE. +Please use only MBED_CLOUD_CLIENT_USER_CONFIG_FILE. #endif #ifdef __cplusplus @@ -97,34 +97,6 @@ #define MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP #endif -/** - * \def MBED_CLOUD_CLIENT_STL_API - * - * \brief This flag controls the API's which use C++'s - * Standard Template Library (STL). The cost of STL is ~15KB of flash, depending on compiler, - * so on resource constrained devices it is essential to be able to remove any reference to it. - * In practice the SimpleM2MResourceString and SimpleM2MResourceInt classes are build with STL, - * so if one is not using them and wants to save RAM and ROM, setting this define to zero - * may help quite a lot. The SimpleM2MResource* classes and related API's are marked as deprecated, - * so they may be removed in the future releases. - */ -#if !defined(MBED_CLOUD_CLIENT_STL_API) || __DOXYGEN__ -#define MBED_CLOUD_CLIENT_STL_API 0 -#endif - -/** - * \def MBED_CLOUD_CLIENT_STD_NAMESPACE_POLLUTION - * \brief This causes a inclusion of "MbedCloudCLient.h - * to "pollute" the namespace with "using namespace std;". This has been always the case, but - * any library should not pollute application's namespace with std by having the "using std" - * in a a public header file. - * But as as removal of it from our headers may break existing applications, which build due to this - * leakage, we need to maintain the old behavior for a while and just allow one to remove it. - */ -#ifndef MBED_CLOUD_CLIENT_STD_NAMESPACE_POLLUTION -#define MBED_CLOUD_CLIENT_STD_NAMESPACE_POLLUTION 0 -#endif - /** * \def MBED_CLOUD_CLIENT_LISTEN_PORT * diff --git a/mbed-cloud-client/MbedCloudClientConfigCheck.h b/mbed-cloud-client/MbedCloudClientConfigCheck.h index 0a576a6b3..138bea5ad 100644 --- a/mbed-cloud-client/MbedCloudClientConfigCheck.h +++ b/mbed-cloud-client/MbedCloudClientConfigCheck.h @@ -76,14 +76,6 @@ defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE) || defined(MBED_CLOUD_CLIEN #error "One MBED_CLOUD_CLIENT_TRANSPORT_MODE must be defined at a time" #endif -#if !defined(MBED_CLOUD_CLIENT_STL_API) -#error "MBED_CLOUD_CLIENT_STL_API must have a value, nonzero enables API with STL" -#endif - -#if !defined(MBED_CLOUD_CLIENT_STD_NAMESPACE_POLLUTION) -#error "MBED_CLOUD_CLIENT_STD_NAMESPACE_POLLUTION must have a value, nonzero maintains legacy behavior" -#endif - #if defined(ARM_UC_PROFILE_MBED_CLIENT_LITE) && (ARM_UC_PROFILE_MBED_CLIENT_LITE==1) #error "Pelion Device Management Client must use ARM_UC_PROFILE_MBED_CLIENT_LITE=0 configuration." #endif diff --git a/mbed-cloud-client/SimpleM2MResource.h b/mbed-cloud-client/SimpleM2MResource.h deleted file mode 100644 index 05eeb14f4..000000000 --- a/mbed-cloud-client/SimpleM2MResource.h +++ /dev/null @@ -1,291 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright 2016-2020 ARM Ltd. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ---------------------------------------------------------------------------- - -/** \file SimpleM2MResource.h \brief header for SimpleM2MResourceBase */ - -#ifndef SIMPLE_M2M_RESOURCE_H -#define SIMPLE_M2M_RESOURCE_H - -#include "mbed-cloud-client/MbedCloudClient.h" - -#if MBED_CLOUD_CLIENT_STL_API - -#include - -/** This class provides an easy wrapper base class for creating a simple M2MResource based on - * integer and string values. You are not meant to directly instantiate it but it is used - * by the SimpleM2MResourceInt and SimpleM2MResourceString classes to create resources. - * - * As this whole class is build by using C++'s standard template library (STL), - * we have it behind a \ref MBED_CLOUD_CLIENT_STL_API flag. The cost of STL is 15KB of flash, depending on compiler, - * so on resource constrained devices it is essential to be able to remove any reference to it. - */ -class SimpleM2MResourceBase { - -protected: - - // Prevents the use of default constructor. - SimpleM2MResourceBase(); - - // Prevents the use of assignment operator. - SimpleM2MResourceBase& operator=( const SimpleM2MResourceBase& /*other*/ ); - - // Prevents the use of copy constructor - SimpleM2MResourceBase( const M2MBase& /*other*/ ); - - SimpleM2MResourceBase(MbedCloudClient* client, string route); - - /** - * \brief Destructor - */ - virtual ~SimpleM2MResourceBase(); - - -public: - - /** - * \brief Defines M2MResource internally and creates a necessary LWM2M - * structure like object and object instance based on the given string - * URI path and sets the right M2M operation to the resource. - * \param v The URI path for the resource "Test/0/res" in this format. - * \param opr An operation to be set for the resource. - * \param observable True if the resource is observable, else false. - * \return True if resource is created, else false. - */ - bool define_resource_internal(string v, - M2MBase::Operation opr, - bool observable); - - /** - * \brief Gets the value set in a resource in text format. - * \return The value set in the resource. - */ - string get() const; - - /** - * \brief Sets the value in a resource in text format. - * \param v The value to be set. - * \return True if set successfully, else false. - */ - bool set(string v); - - /** - * \brief Sets the value in a resource in integer format. - * \param v The value to be set. - * \return True if set successfully, else false. - */ - bool set(const int& v); - - /** - * \brief Sets the callback function to be called - * when the resource received a POST command. - * \param fn A function to be called. - * This is used for a statically defined function. - * \return True if set successfully, else false. - */ - bool set_post_function(void(*fn)(void*)); - - /** - * \brief Sets the callback function to be called - * when a resource received the POST command. - * \param fn A function to be called. - * This is an overloaded function for a class function. - * \return True if set successfully, else false. - */ - bool set_post_function(execute_callback fn); - - /** - * \brief Returns the M2MResource object of the registered object through - * the SimpleM2MResourceBase objects. - * \return The object of the M2MResource. - */ - M2MResource* get_resource(); - - /** - * \brief Calls when there is an indication that the value of the resource - * object is updated by the LWM2M Cloud server. - */ - virtual void update(){} - -private: - - /** - * \brief An internal helper function to break the URI path into a list of - * strings such as "Test/0/res" into a list of three strings. - * \param route The URI path in the format "Test/0/res". - * \return A list of strings parsed from the URI path. - */ - vector parse_route(const char* route); - -private: - MbedCloudClient* _client; // Not owned - string _route; -}; - -/** - * \brief SimpleM2MResourceString. - * This class provides an easy wrapper base class for creating a simple M2MResource based on - * string values. This class provides an easy access to the M2MResource objects without the application - * requiring to create Objects and Object Instances. - */ - -class SimpleM2MResourceString : public SimpleM2MResourceBase -{ -public: - - /** - * \brief Constructor. - * \note This class is deprecated and may be removed in future releases. - * \param client A handler for MbedCloudClient. - * \param route The route for the resource such as "Test/0/res". - * \param v The value of the resource. - * \param opr An operation that can be supported by the resource. - * \param observable True if the resource is observable. - * \param on_update If the resource supports the PUT operation, a function pointer - * for the callback function that is called when the client receives an - * updated value for this resource. - */ - SimpleM2MResourceString(MbedCloudClient* client, - const char* route, - string v, - M2MBase::Operation opr = M2MBase::GET_PUT_ALLOWED, - bool observable = true, - FP1 on_update = NULL) m2m_deprecated; - - /** - * \brief Constructor. This is overloaded function. - * \note This class is deprecated and may be removed in future releases. - * \param client A handler for MbedCloudClient. - * \param route The route for the resource such as "Test/0/res". - * \param v The value of the resource. - * \param opr An operation that can be supported by the resource. - * \param observable True if resource is observable. - * \param on_update If the resource supports the PUT operation, a function pointer - * for the callback function that is called when the client receives an - * updated value for this resource. - */ - SimpleM2MResourceString(MbedCloudClient* client, - const char* route, - string v, - M2MBase::Operation opr, - bool observable, - void(*on_update)(string)) m2m_deprecated; - - - /** - * \brief Destructor - */ - virtual ~SimpleM2MResourceString(); - - /** - * \brief Overloaded operator for = operation. - */ - string operator=(const string& new_value); - - /** - * \brief Overloaded operator for string() operation. - */ - operator string() const; - - /** - * \brief Calls when there is an indication that the value of the resource - * object is updated by the LWM2M Cloud server. - */ - virtual void update(); - -private: - FP1 _on_update; -}; - -/** - * \brief SimpleM2MResourceInt. - * This class provides an easy wrapper base class for creating a simple M2MResource based on - * integer values. This class provides easy access to M2MResource objects without the application - * requiring to create Objects and Object Instances. - */ - -class SimpleM2MResourceInt : public SimpleM2MResourceBase -{ -public: - - /** - * \brief Constructor. - * \note This class is deprecated and may be removed in future releases. - * \param client A handler for MbedCloudClient. - * \param route The route for the resource such as "Test/0/res". - * \param v The value of the resource. - * \param opr An operation that can be supported by the resource. - * \param observable True if the resource is observable, else false. - * \param on_update If the resource supports the PUT operation, a function pointer - * for the callback function that is called when the client receives an - * updated value for this resource. - */ - SimpleM2MResourceInt(MbedCloudClient* client, - const char* route, - int v, - M2MBase::Operation opr = M2MBase::GET_PUT_ALLOWED, - bool observable = true, - FP1 on_update = NULL) m2m_deprecated; - - /** - * \brief Constructor. This is an overloaded function - * \note This class is deprecated and may be removed in future releases. - * \param client A handler for MbedCloudClient. - * \param route The route for the resource such as "Test/0/res" - * \param v The value of the resource. - * \param opr An operation that can be supported by the resource. - * \param observable True if the resource is observable, else false. - * \param on_update If the resource supports the PUT operation, a function pointer - * for the callback function that is called when the client receives an - * updated value for this resource. - */ - SimpleM2MResourceInt(MbedCloudClient* client, - const char* route, - int v, - M2MBase::Operation opr, - bool observable, - void(*on_update)(int)) m2m_deprecated; - - /** - * \brief Destructor - */ - virtual ~SimpleM2MResourceInt(); - - /** - * \brief Overloaded operator for = operation. - */ - int operator=(int new_value); - - /** - * \brief Overloaded operator for int() operation. - */ - operator int() const; - - /** - * \brief Calls when there is an indication that the value of the resource - * object is updated by the LWM2M Cloud server. - */ - virtual void update(); - -private: - FP1 _on_update; -}; - -#endif - -#endif // SIMPLE_M2M_RESOURCE_H diff --git a/multicast/multicast.cpp b/multicast/multicast.cpp index dfa461958..7f8062c65 100644 --- a/multicast/multicast.cpp +++ b/multicast/multicast.cpp @@ -875,12 +875,13 @@ static bool arm_uc_multicast_create_static_resources(M2MBaseList &list) object_inst->set_register_uri(false); if (arm_uc_multicast_ota_config.device_type == OTA_DEVICE_TYPE_BORDER_ROUTER) { - multicast_connected_nodes_res = object_inst->create_static_resource(&arm_uc_multicast_ota_connected_nodes_res, M2MResourceInstance::INTEGER); + /*multicast_connected_nodes_res = object_inst->create_static_resource(&arm_uc_multicast_ota_connected_nodes_res, M2MResourceInstance::INTEGER); if (!multicast_connected_nodes_res) { tr_error("arm_uc_multicast_create_static_resources - failed to create multicast_connected_nodes_res!"); return false; } multicast_connected_nodes_res->set_value(0); + multicast_connected_nodes_res->set_register_uri(false);*/ multicast_ready_res = object_inst->create_static_resource(&arm_uc_multicast_ota_ready_for_multicast_res, M2MResourceInstance::INTEGER); if (!multicast_ready_res) { @@ -894,14 +895,15 @@ static bool arm_uc_multicast_create_static_resources(M2MBaseList &list) if (!multicast_command_res) { tr_error("arm_uc_multicast_create_static_resources - failed to create multicast_command_res!"); return false; - } + } - multicast_estimated_total_time_res = object_inst->create_static_resource(&arm_uc_multicast_estimated_total_time_res, M2MResourceInstance::OPAQUE); + /*multicast_estimated_total_time_res = object_inst->create_static_resource(&arm_uc_multicast_estimated_total_time_res, M2MResourceInstance::OPAQUE); if (!multicast_estimated_total_time_res) { tr_error("arm_uc_multicast_create_static_resources - failed to create multicast_estimated_total_time_res!"); return false; } multicast_estimated_total_time_res->set_value(0); + multicast_estimated_total_time_res->set_register_uri(false);*/ multicast_estimated_resend_time_res = object_inst->create_static_resource(&arm_uc_multicast_estimated_resend_time_res, M2MResourceInstance::OPAQUE); if (!multicast_estimated_resend_time_res) { @@ -936,17 +938,20 @@ static bool arm_uc_multicast_create_static_resources(M2MBaseList &list) return false; } + multicast_session_res = object_inst->create_static_resource(&arm_uc_multicast_ota_session_res, M2MResourceInstance::OPAQUE); if (!multicast_session_res) { tr_error("arm_uc_multicast_create_static_resources - failed to create multicast_session_res!"); return false; } + multicast_error_res = object_inst->create_static_resource(&arm_uc_multicast_error_res, M2MResourceInstance::OPAQUE); if (!multicast_error_res) { tr_error("arm_uc_multicast_create_static_resources - failed to create multicast_error_res!"); return false; } + multicast_error_res->set_auto_observable(true); list.push_back(arm_uc_multicast_object); } else { diff --git a/network-manager/network-manager/NetworkManager.h b/network-manager/network-manager/NetworkManager.h index b3c520db4..ce1c97852 100644 --- a/network-manager/network-manager/NetworkManager.h +++ b/network-manager/network-manager/NetworkManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 ARM Limited. All rights reserved. + * Copyright (c) 2020-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -32,6 +32,29 @@ typedef enum nm_error { class NetworkManager { public: + /** + * \brief Reads MAC addresses from factory configuration and set on Mesh interface and Backhaul interface. + * + * Function reads the MAC addresses from factory configuration and set on Mesh interface and Backhaul interface. + * + * \param mesh_iface Instance of Mesh interface. + * \param backhaul_iface Instance of Backhaul interface. + * \return NM_ERROR_NONE on success. + * \return NM_ERROR_UNKNOWN in case of failure. + * */ + nm_error_t configure_factory_mac_address(void *mesh_iface, void *backhaul_iface); + + /** + * \brief Reads MAC address from factory configuration and set on Mesh interface. + * + * Function reads the MAC address from factory configuration and set on Mesh interface. + * + * \param mesh_iface Instance of mesh interface. + * \return NM_ERROR_NONE on success. + * \return NM_ERROR_UNKNOWN in case of failure. + * */ + nm_error_t configure_factory_mac_address(void *mesh_iface); + /** * \brief Registers the interfaces into Network manager and configures them with latest configuration. * diff --git a/network-manager/source/NetworkManager.cpp b/network-manager/source/NetworkManager.cpp index 349855fa5..dbc2b7cef 100644 --- a/network-manager/source/NetworkManager.cpp +++ b/network-manager/source/NetworkManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 ARM Limited. All rights reserved. + * Copyright (c) 2020-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -123,14 +123,47 @@ static void nm_event_handler(arm_event_s *event) } } +nm_error_t NetworkManager::configure_factory_mac_address(void *mesh_iface, void *backhaul_iface) +{ + if (nm_mesh_configure_factory_mac_address((NetworkInterface *)mesh_iface) == NM_STATUS_FAIL) { + tr_error("Could not configure Factory MAC Address on Mesh Interface"); + return NM_ERROR_UNKNOWN; + } + + if (nm_backhaul_configure_factory_mac_address((NetworkInterface *)backhaul_iface) == NM_STATUS_FAIL) { + tr_error("Could not configure Factory MAC Address on Backhaul Interface"); + return NM_ERROR_UNKNOWN; + } + + return NM_ERROR_NONE; +} + +nm_error_t NetworkManager::configure_factory_mac_address(void *mesh_iface) +{ + if (nm_mesh_configure_factory_mac_address((NetworkInterface *)mesh_iface) == NM_STATUS_FAIL) { + tr_error("Could not configure Factory MAC Address on Mesh Interface"); + return NM_ERROR_UNKNOWN; + } + + return NM_ERROR_NONE; +} + nm_error_t NetworkManager::reg_and_config_iface(void *mesh_iface, void *backhaul_iface, void *br_iface) { register_interfaces((NetworkInterface *)mesh_iface, (NetworkInterface *)backhaul_iface, (WisunBorderRouter *)br_iface); + if (nm_factory_configure_mesh_iface() == NM_STATUS_FAIL) { + tr_error("Could not SET Factory Configuration on Mesh Interface"); + return NM_ERROR_UNKNOWN; + } if (nm_configure_mesh_iface() == NM_STATUS_FAIL) { tr_error("Could not configure Mesh Interface"); return NM_ERROR_UNKNOWN; } + if (nm_factory_configure_border_router() == NM_STATUS_FAIL) { + tr_error("Could not SET Factory Configuration on BR Interface"); + return NM_ERROR_UNKNOWN; + } if (nm_configure_border_router() == NM_STATUS_FAIL) { tr_error("Could not configure BR Interface"); return NM_ERROR_UNKNOWN; @@ -143,6 +176,10 @@ nm_error_t NetworkManager::reg_and_config_iface(void *mesh_iface) { register_interfaces((NetworkInterface *)mesh_iface, NULL, NULL); + if (nm_factory_configure_mesh_iface() == NM_STATUS_FAIL) { + tr_error("Could not SET Factory Configuration on Mesh Interface"); + return NM_ERROR_UNKNOWN; + } if (nm_configure_mesh_iface() == NM_STATUS_FAIL) { tr_error("Could not configure Mesh Interface"); return NM_ERROR_UNKNOWN; diff --git a/network-manager/source/include/NetworkManager_internal.h b/network-manager/source/include/NetworkManager_internal.h index d9f9aa15b..0c2d877b1 100644 --- a/network-manager/source/include/NetworkManager_internal.h +++ b/network-manager/source/include/NetworkManager_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Pelion. All rights reserved. + * Copyright (c) 2020-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -32,13 +32,13 @@ typedef enum config { WS, BR, NM, - NI, - RQ + NI } config_type_t; typedef enum nm_status { NM_STATUS_FAIL = -1, - NM_STATUS_SUCCESS = 0 + NM_STATUS_SUCCESS = 0, + NM_STATUS_UNSUPPORTED } nm_status_t; typedef enum nm_event_type_e { @@ -59,7 +59,6 @@ nm_status_t nm_post_timeout_event(nm_event_t event_type, int32_t delay); #define WS_STATS_RESOURCE_VERSION 1 #define BR_STATS_RESOURCE_VERSION 1 #define NODE_INFORMATION_VERSION 1 -#define RADIO_QUALITY_VERSION 1 /* Application configuration */ /* To-Do: Application configuration not decided yet (which conf. is changeable from server) */ @@ -111,11 +110,18 @@ typedef struct { uint8_t dio_redundancy_constant; } rpl_config_t; +typedef struct { + char address[40]; + uint16_t secret_len; + uint8_t *secret; +} radius_server_t; + typedef struct { uint32_t resource_version; rpl_config_t rpl_config; uint16_t delay; uint16_t pan_id; + radius_server_t radius_config; } nm_br_config_t; /* Application Statistics */ @@ -175,6 +181,8 @@ typedef struct { uint8_t primary_parent[16]; uint16_t etx_1st_parent; /*delay = (uint16_t)int_value; } + //Finding Radius Server Secret + if (get_byte_value_from_stream(&main_value, CBOR_TAG_RADIUS_SERVER_SECRET, &map_value, &secret_buffer, &temp_buffer_size) == true) { + if (br_cfg->radius_config.secret != NULL && br_cfg->radius_config.secret_len != 0) { + free(br_cfg->radius_config.secret); + br_cfg->radius_config.secret_len = 0; + br_cfg->radius_config.secret = NULL; + } + br_cfg->radius_config.secret_len = (uint16_t)temp_buffer_size; + br_cfg->radius_config.secret = secret_buffer; + } + + //Finding Radius Server address + if (get_string_value_from_stream(&main_value, CBOR_TAG_RADIUS_SERVER_ADDR, &map_value, &temp_buffer) == true) { + if(!strcasecmp(temp_buffer,"NULL")) { + memset(br_cfg->radius_config.address, '\0', sizeof(br_cfg->radius_config.address)); + } else { + strcpy(br_cfg->radius_config.address, temp_buffer); + } + } + + if (temp_buffer != NULL) { + free(temp_buffer); + temp_buffer = NULL; + } + /* This parameters going to update from binary only */ br_cfg->resource_version = WS_BR_RESOURCE_VERSION; return NM_STATUS_SUCCESS; @@ -694,6 +747,16 @@ static nm_status_t br_config_to_cbor(void *br_cfg, uint8_t *cbor_data, size_t *l encode_uint32_value(&map, (uint32_t)st_cfg->delay); } + // radius_server_secret + if (encode_text_string(&map, CBOR_TAG_RADIUS_SERVER_SECRET, sizeof(CBOR_TAG_RADIUS_SERVER_SECRET) - 1)) { + encode_byte_array(&map, st_cfg->radius_config.secret, st_cfg->radius_config.secret_len); + } + + // radius_server_addr + if (encode_text_string(&map, CBOR_TAG_RADIUS_SERVER_ADDR, sizeof(CBOR_TAG_RADIUS_SERVER_ADDR) - 1)) { + encode_text_string(&map, st_cfg->radius_config.address, strlen(st_cfg->radius_config.address)); + } + // Close Map cbor_error = cbor_encoder_close_container(&encoder, &map); if (cbor_error) { @@ -1096,48 +1159,14 @@ static nm_status_t node_stats_to_cbor(void *stats_ni, uint8_t *cbor_data, size_t encode_uint32_value(&map, (uint32_t)node_stats->routing_info.etx_2nd_parent); } - // Close Map - cbor_error = cbor_encoder_close_container(&encoder, &map); - if (cbor_error) { - tr_debug("Failed closing presence map with error code %d", cbor_error); - return NM_STATUS_FAIL; - } - - size_t ret = cbor_encoder_get_buffer_size(&encoder, cbor_data); - tr_debug("Length of node_stats_to_cbor buffer is %d", ret); - *len = ret; - return NM_STATUS_SUCCESS; -} - -static nm_status_t radio_stats_to_cbor(void *stats_rq, uint8_t *cbor_data, size_t *len) -{ - CborError cbor_error = CborNoError; - CborEncoder encoder; - CborEncoder map; - nm_radio_quality_t *radio_stats = (nm_radio_quality_t *)stats_rq; - - cbor_encoder_init(&encoder, cbor_data, NI_STAT_MAX_ENCODER_BUF, 0); - - // Create map - cbor_error = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength); - if (cbor_error) { - tr_debug("Failed creating presence map with error code %d", cbor_error); - return NM_STATUS_FAIL; - } - - // Resource version no - if (encode_text_string(&map, CBOR_TAG_RADIO_RESOURCE_VER, sizeof(CBOR_TAG_RADIO_RESOURCE_VER) - 1)) { - encode_uint32_value(&map, RADIO_QUALITY_VERSION); - } - // rssi_in if (encode_text_string(&map, CBOR_TAG_RSSI_IN, sizeof(CBOR_TAG_RSSI_IN) - 1)) { - encode_uint32_value(&map, (uint32_t)radio_stats->rssi_in); + encode_uint32_value(&map, (uint32_t)node_stats->routing_info.rssi_in); } // rssi_out if (encode_text_string(&map, CBOR_TAG_RSSI_OUT, sizeof(CBOR_TAG_RSSI_OUT) - 1)) { - encode_uint32_value(&map, (uint32_t)radio_stats->rssi_out); + encode_uint32_value(&map, (uint32_t)node_stats->routing_info.rssi_out); } // Close Map @@ -1148,9 +1177,8 @@ static nm_status_t radio_stats_to_cbor(void *stats_rq, uint8_t *cbor_data, size_ } size_t ret = cbor_encoder_get_buffer_size(&encoder, cbor_data); - tr_debug("Length of radio_stats_to_cbor buffer is %d", ret); + tr_debug("Length of node_stats_to_cbor buffer is %d", ret); *len = ret; - return NM_STATUS_SUCCESS; } @@ -1191,12 +1219,6 @@ nm_status_t nm_statistics_to_cbor(void *stats, uint8_t *cbor_data, config_type_t tr_info("NI statistics cbor encoder fail"); } break; - case RQ: - status = radio_stats_to_cbor(stats, cbor_data, len); - if (status) { - tr_info("RQ statistics cbor encoder fail"); - } - break; } return status; } diff --git a/network-manager/source/nm_interface_manager.cpp b/network-manager/source/nm_interface_manager.cpp index 389b7eed1..564d7972f 100644 --- a/network-manager/source/nm_interface_manager.cpp +++ b/network-manager/source/nm_interface_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Pelion. All rights reserved. + * Copyright (c) 2020-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -16,7 +16,8 @@ #if defined MBED_CONF_MBED_CLOUD_CLIENT_NETWORK_MANAGER && (MBED_CONF_MBED_CLOUD_CLIENT_NETWORK_MANAGER == 1) -#include +#include +#include #include "mbed.h" #include "mbed_trace.h" #include "NetworkInterface.h" @@ -28,6 +29,7 @@ #include "nm_resource_manager.h" #include "NetworkManager_internal.h" #include "nm_dynmem_helper.h" +#include "nm_kcm_factory.h" #define TRACE_GROUP "NMif" @@ -37,9 +39,10 @@ #define NM_STAT_MAX_BUF NM_STAT_MAX_ENCODER_BUF #define BR_STAT_MAX_BUF BR_STAT_MAX_ENCODER_BUF #define NI_STAT_MAX_BUF NI_STAT_MAX_ENCODER_BUF -#define RQ_STAT_MAX_BUF RQ_STAT_MAX_ENCODER_BUF -#define DEFAULT_CONFIG_DELAY 0 +#define DEFAULT_CONFIG_DELAY 0 +#define MESH_MAC_ADDR_LEN 8 +#define BACKHAUL_MAC_ADDR_LEN 6 static SocketAddress sa; static NetworkInterface *backhaul_interface = NULL; @@ -90,6 +93,46 @@ void register_interfaces(NetworkInterface *mesh_iface, NetworkInterface *backhau ws_br = br_iface; } +nm_status_t nm_backhaul_configure_factory_mac_address(NetworkInterface *backhaul_iface) +{ +#if ((MBED_VERSION >= MBED_ENCODE_VERSION(6, 8, 0)) || ((MBED_VERSION < MBED_ENCODE_VERSION(6, 0, 0)) && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 15, 7)))) + uint8_t *backhaul_mac_address = NULL; + uint8_t *r_backhaul_mac_address = NULL; + size_t backhaul_mac_address_len = 0; + + if (backhaul_iface == NULL) { + tr_error("Could not Apply Backhaul MAC Address Factory Configuration: Backhaul Interface is NULL"); + return NM_STATUS_FAIL; + } + + if (nm_kcm_ethernet_mac_address_init(&r_backhaul_mac_address, &backhaul_mac_address_len) == NM_STATUS_SUCCESS) { + if(string2hex_mac_address(&backhaul_mac_address,r_backhaul_mac_address,backhaul_mac_address_len) == NM_STATUS_SUCCESS) { + if (backhaul_iface->set_mac_address(backhaul_mac_address, BACKHAUL_MAC_ADDR_LEN) != MESH_ERROR_NONE) { + tr_error("FAILED to set Backhaul MAC address from Factory Configuration %s", tr_array(r_backhaul_mac_address, backhaul_mac_address_len)); + free(r_backhaul_mac_address); + nm_dyn_mem_free(backhaul_mac_address); + return NM_STATUS_FAIL; + } else { + tr_info("Factory Configuration SET: Backhaul MAC address %s", tr_array(backhaul_mac_address, BACKHAUL_MAC_ADDR_LEN)); + free(r_backhaul_mac_address); + nm_dyn_mem_free(backhaul_mac_address); + } + } else { + tr_error("FAILED: Read wrong Backhaul MAC address length from KCM: %d, Expected length is 6", backhaul_mac_address_len/2); + free(r_backhaul_mac_address); + nm_dyn_mem_free(backhaul_mac_address); + return NM_STATUS_FAIL; + } + } else { + tr_info("Factory Configuration NOT FOUND: Backhaul MAC address"); + } + return NM_STATUS_SUCCESS; +#else + return NM_STATUS_UNSUPPORTED; +#endif +} + + @@ -382,6 +425,169 @@ static nm_status_t get_default_ws_config_from_nanostack(nm_ws_config_t *ws_confi return NM_STATUS_SUCCESS; } +nm_status_t string2hex_mac_address(uint8_t **mac_addr, uint8_t *recv_buffer, uint8_t length) +{ + uint8_t base_mac_addr[8] = {'\0'}; + char dummy[3] = {'\0'}; + int j = 0; + uint8_t num = 0; + + tr_debug("received length = %d",length); + + if(length / 2 == MESH_MAC_ADDR_LEN){ + *mac_addr = (uint8_t *)nm_dyn_mem_alloc(MESH_MAC_ADDR_LEN * sizeof(char)); + memset(*mac_addr, '\0' ,MESH_MAC_ADDR_LEN); + } else if (length / 2 == BACKHAUL_MAC_ADDR_LEN){ + *mac_addr = (uint8_t *)nm_dyn_mem_alloc(BACKHAUL_MAC_ADDR_LEN * sizeof(char)); + memset(*mac_addr, '\0' ,BACKHAUL_MAC_ADDR_LEN); + } else { + tr_err("Received wrong MAC ADDR length %d",length); + return NM_STATUS_FAIL; + } + + for(int k=0;k<8;k++) + { + for(int i=0;i<2;i++){ + dummy[i] = recv_buffer[i+j]; + } + num = strtol(dummy, NULL, 16); + j=j+2; + base_mac_addr[k] = num; + } + if(length / 2 == MESH_MAC_ADDR_LEN){ + memcpy(*mac_addr,base_mac_addr,MESH_MAC_ADDR_LEN); + tr_debug("MAC ADDR length set %d",MESH_MAC_ADDR_LEN); + } else if(length / 2 == BACKHAUL_MAC_ADDR_LEN){ + memcpy(*mac_addr,base_mac_addr,BACKHAUL_MAC_ADDR_LEN); + tr_debug("MAC ADDR length set %d",BACKHAUL_MAC_ADDR_LEN); + } else { + tr_err("Failed: memcpy received wrong MAC ADDR length"); + return NM_STATUS_FAIL; + } + return NM_STATUS_SUCCESS; +} + +nm_status_t nm_mesh_configure_factory_mac_address(NetworkInterface *mesh_iface) +{ +#if ((MBED_VERSION >= MBED_ENCODE_VERSION(6, 8, 0)) || ((MBED_VERSION < MBED_ENCODE_VERSION(6, 0, 0)) && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 15, 7)))) + uint8_t *mesh_mac_address = NULL; + uint8_t *r_mesh_mac_address= NULL; + size_t mesh_mac_address_len = 0; + + if (mesh_iface == NULL) { + tr_error("Could not Apply Mesh MAC Address Factory Configuration: Mesh Interface is NULL"); + return NM_STATUS_FAIL; + } + + if (nm_kcm_mesh_mac_address_init(&r_mesh_mac_address, &mesh_mac_address_len) == NM_STATUS_SUCCESS) { + if(string2hex_mac_address(&mesh_mac_address,r_mesh_mac_address,mesh_mac_address_len) == NM_STATUS_SUCCESS) { + if (mesh_iface->set_mac_address(mesh_mac_address, MESH_MAC_ADDR_LEN) != MESH_ERROR_NONE) { + tr_error("FAILED to set Mesh MAC address from Factory Configuration %s", tr_array(r_mesh_mac_address, mesh_mac_address_len)); + free(r_mesh_mac_address); + nm_dyn_mem_free(mesh_mac_address); + return NM_STATUS_FAIL; + } else { + tr_info("Factory Configuration SET: Mesh MAC address %s", tr_array(mesh_mac_address, MESH_MAC_ADDR_LEN)); + free(r_mesh_mac_address); + nm_dyn_mem_free(mesh_mac_address); + } + } else { + free(r_mesh_mac_address); + nm_dyn_mem_free(mesh_mac_address); + tr_error("FAILED: Read wrong Mesh MAC address length from KCM: %d, Expected length is 8", mesh_mac_address_len/2); + return NM_STATUS_FAIL; + } + } else { + tr_info("Factory Configuration NOT FOUND: Mesh MAC address"); + } + return NM_STATUS_SUCCESS; +#else + return NM_STATUS_UNSUPPORTED; +#endif +} + +nm_status_t nm_factory_configure_mesh_iface(void) +{ + char *network_name_ptr; + uint8_t network_size; + uint8_t regulatory_domain, operating_class, operating_mode; + uint8_t *trusted_cert; + uint16_t trusted_cert_len; + uint8_t *own_cert; + uint16_t own_cert_len; + uint8_t *own_cert_key; + uint16_t own_cert_key_len; + + tr_info("Applying Factory Configurations on Mesh Interface"); + + if (ws_iface == NULL) { + tr_warn("Could not Apply Factory Configuration: Mesh Interface is not Initialized yet"); + return NM_STATUS_FAIL; + } + + if (nm_kcm_wisun_network_name_init(&network_name_ptr) == NM_STATUS_SUCCESS) { + if (ws_iface->set_network_name(network_name_ptr) != MESH_ERROR_NONE) { + tr_error("FAILED to set network name '%s' from Factory Configuration", network_name_ptr); + nm_dyn_mem_free(network_name_ptr); + return NM_STATUS_FAIL; + } else { + nm_dyn_mem_free(network_name_ptr); + tr_info("Factory Configuration SET: Network Name = %s", network_name_ptr); + } + } else { + tr_info("Factory Configuration NOT FOUND: Network Name"); + } + + if (nm_kcm_wisun_network_size_init(&network_size) == NM_STATUS_SUCCESS) { + if (ws_iface->set_network_size(network_size) != MESH_ERROR_NONE) { + tr_error("FAILED to set network size '%d' from Factory Configuration", network_size); + return NM_STATUS_FAIL; + } else { + tr_info("Factory Configuration SET: Network Size = %d", network_size); + } + } else { + tr_info("Factory Configuration NOT FOUND: Network Size"); + } + + if (nm_kcm_wisun_network_regulatory_domain_init(®ulatory_domain, &operating_class, &operating_mode) == NM_STATUS_SUCCESS) { + if (ws_iface->set_network_regulatory_domain(regulatory_domain, operating_class, operating_mode) != MESH_ERROR_NONE) { + tr_error("FAILED to set Reg Dom '%d', OP Class '%d' and OP Mode '%d' from Factory Configuration", regulatory_domain, operating_class, operating_mode); + return NM_STATUS_FAIL; + } else { + tr_info("Factory Configuration SET: Reg Dom = %d, OP Class = %d, OP Mode = %d", regulatory_domain, operating_class, operating_mode); + } + } else { + tr_info("Factory Configuration NOT FOUND: Regulatory Domain or Operating Class or Operating Mode"); + } + + if (nm_kcm_wisun_network_trusted_certificate_init(&trusted_cert, &trusted_cert_len) == NM_STATUS_SUCCESS) { + if (ws_iface->set_trusted_certificate(trusted_cert, trusted_cert_len) != MESH_ERROR_NONE) { + tr_error("FAILED to set Trusted Certificate from Factory Configuration"); + free(trusted_cert); + return NM_STATUS_FAIL; + } else { + tr_info("Factory Configuration SET: Trusted Certificate"); + } + } else { + tr_info("Factory Configuration NOT FOUND: Trusted Certificate"); + } + + if (nm_kcm_wisun_network_own_certificate_init(&own_cert, &own_cert_len, &own_cert_key, &own_cert_key_len) == NM_STATUS_SUCCESS) { + if (ws_iface->set_own_certificate(own_cert, own_cert_len, own_cert_key, own_cert_key_len) != MESH_ERROR_NONE) { + tr_error("FAILED to set Own Certificate from Factory Configuration"); + free(own_cert); + free(own_cert_key); + return NM_STATUS_FAIL; + } else { + tr_info("Factory Configuration SET: Own Certificate"); + } + } else { + tr_info("Factory Configuration NOT FOUND: Own Certificate"); + } + + return NM_STATUS_SUCCESS; +} + nm_status_t nm_configure_mesh_iface(void) { nm_ws_config_t default_ws_config = {0}; @@ -405,6 +611,7 @@ nm_status_t nm_configure_mesh_iface(void) */ nm_iface_kvstore_read_cfg(kv_key_ws, &modified_ws_config, WS); + tr_info("Applying Latest Received Configurations from Pelion Server on Mesh Interface"); if (set_ws_config_to_nanostack(&default_ws_config, &modified_ws_config) == NM_STATUS_FAIL) { tr_warn("FAILED to set Wi-SUN config to Nanostack"); return NM_STATUS_FAIL; @@ -434,7 +641,7 @@ nm_status_t nm_configure_mesh_iface(void) /* Enable Statistics */ ws_iface->enable_statistics(); - tr_info("Mesh Interface Configured with Latest Configuration"); + tr_debug("Mesh Interface Configured with Latest Configuration"); return NM_STATUS_SUCCESS; } @@ -656,6 +863,8 @@ nm_status_t nm_res_get_node_stats(uint8_t **datap, size_t *length) memcpy(node_info.routing_info.primary_parent, stack_state_info.parent_addr, sizeof(stack_state_info.parent_addr)); node_info.routing_info.etx_1st_parent = ws_stats_temp.etx_1st_parent; node_info.routing_info.etx_2nd_parent = ws_stats_temp.etx_2nd_parent; + node_info.routing_info.rssi_in = stack_state_info.rsl_in; + node_info.routing_info.rssi_out = stack_state_info.rsl_out; *datap = (uint8_t *)nm_dyn_mem_alloc(NI_STAT_MAX_BUF); if (*datap == NULL) { @@ -672,31 +881,26 @@ nm_status_t nm_res_get_node_stats(uint8_t **datap, size_t *length) return NM_STATUS_SUCCESS; } -nm_status_t nm_res_get_radio_stats(uint8_t **datap, size_t *length) +nm_status_t nm_res_get_ch_noise_stats(uint8_t **datap, size_t *length) { - /*need to implement get radio quality information here */ - ws_stack_state_t stack_state_info = {0}; - nm_radio_quality_t radio_quality = {0}; + ws_cca_threshold_table_t channel_noise; if (ws_iface == NULL) { tr_warn("FAILED: Wi-SUN Interface is not initialized yet"); return NM_STATUS_FAIL; } - if (ws_iface->stack_info_get(&stack_state_info) != MESH_ERROR_NONE) { - tr_warn("FAILED to read Wi-SUN network stack state info from Nanostack"); + if (ws_iface->cca_threshold_table_get(&channel_noise) != MESH_ERROR_NONE) { + tr_warn("FAILED: Read Wi-SUN threshold table from Nanostack"); return NM_STATUS_FAIL; } - radio_quality.rssi_in = stack_state_info.rsl_in; - radio_quality.rssi_out = stack_state_info.rsl_out; - - *datap = (uint8_t *)nm_dyn_mem_alloc(NI_STAT_MAX_BUF); + *datap = (uint8_t *)nm_dyn_mem_alloc(CH_NOISE_TABLE_MAX_ENCODING_BUFF(channel_noise.number_of_channels)); if (*datap == NULL) { return NM_STATUS_FAIL; } - if (nm_statistics_to_cbor(&radio_quality, *datap, RQ, length) == NM_STATUS_FAIL) { + if (nm_ch_noise_statistics_to_cbor((int8_t *)channel_noise.cca_threshold_table, channel_noise.number_of_channels, *datap, length) == NM_STATUS_FAIL) { tr_warn("FAILED to CBORise Wi-SUN Statistics"); /* Free dynamically allocated memory */ nm_dyn_mem_free(*datap); @@ -706,32 +910,23 @@ nm_status_t nm_res_get_radio_stats(uint8_t **datap, size_t *length) return NM_STATUS_SUCCESS; } -nm_status_t nm_res_get_ch_noise_stats(uint8_t **datap, size_t *length) +nm_status_t nm_reset_parameters(void) { - ws_cca_threshold_table_t channel_noise; - +#if ((MBED_VERSION > MBED_ENCODE_VERSION(6, 10, 0)) || ((MBED_VERSION < MBED_ENCODE_VERSION(6, 0, 0)) && (MBED_VERSION > MBED_ENCODE_VERSION(5, 15, 7)))) if (ws_iface == NULL) { tr_warn("FAILED: Wi-SUN Interface is not initialized yet"); return NM_STATUS_FAIL; } - if (ws_iface->cca_threshold_table_get(&channel_noise) != MESH_ERROR_NONE) { - tr_warn("FAILED: Read Wi-SUN threshold table from Nanostack"); - return NM_STATUS_FAIL; - } - - *datap = (uint8_t *)nm_dyn_mem_alloc(CH_NOISE_TABLE_MAX_ENCODING_BUFF(channel_noise.number_of_channels)); - if (*datap == NULL) { - return NM_STATUS_FAIL; - } - - if (nm_ch_noise_statistics_to_cbor((int8_t *)channel_noise.cca_threshold_table, channel_noise.number_of_channels, *datap, length) == NM_STATUS_FAIL) { - tr_warn("FAILED to CBORise Wi-SUN Statistics"); - /* Free dynamically allocated memory */ - nm_dyn_mem_free(*datap); + if (ws_iface->reset_statistics() == MESH_ERROR_UNKNOWN) { + tr_info("FAILED: Unable to Reset Parameter"); return NM_STATUS_FAIL; + } else { + tr_info("Reset Parameter Success"); } - +#else + tr_warn("Not supported in this version"); +#endif return NM_STATUS_SUCCESS; } /************************************************************************/ @@ -747,9 +942,38 @@ nm_status_t nm_res_get_ch_noise_stats(uint8_t **datap, size_t *length) /****************************BR Interface********************************/ +static nm_status_t get_server_secret(radius_server_t *temp_cfg) +{ + mesh_error_t status = MESH_ERROR_UNKNOWN; + temp_cfg->secret_len = 8192; + /* Get first length */ + status = ws_br->get_radius_shared_secret(&temp_cfg->secret_len, NULL); + if (status == MESH_ERROR_NONE && temp_cfg->secret_len > 0) { + /* Allocate dynamically memory for server secret*/ + temp_cfg->secret = (uint8_t *) nm_dyn_mem_alloc(temp_cfg->secret_len); + /* Get secret */ + status = ws_br->get_radius_shared_secret(&temp_cfg->secret_len, temp_cfg->secret); + if (status == MESH_ERROR_NONE) { + tr_info("Server secret found"); + } else { + tr_warn("FAILED: Get radius server secret return %d", status); + nm_dyn_mem_free(temp_cfg->secret); + temp_cfg->secret = NULL; + return NM_STATUS_FAIL; + } + } else { + tr_warn("FAILED: Get radius server secret length : %d from Nanostack, return status %d", temp_cfg->secret_len, status); + return NM_STATUS_FAIL; + } + + return NM_STATUS_SUCCESS; +} + + static nm_status_t br_config_validation(nm_br_config_t *existing_br_config, nm_br_config_t *updated_br_config) { mesh_error_t status = MESH_ERROR_UNKNOWN; + radius_server_t temp = {0}; if ((existing_br_config == NULL) || (updated_br_config == NULL)) { tr_debug("FAILED: Validate br_config is NULL"); @@ -785,6 +1009,17 @@ static nm_status_t br_config_validation(nm_br_config_t *existing_br_config, nm_b } } + /*validation for radius server address here by getting radius server secret*/ + if (updated_br_config->radius_config.secret_len == 0) { + if ((get_server_secret(&temp) != NM_STATUS_SUCCESS)) { + tr_warn("FAILED: Get radius server secret, Skipping server address"); + memset(updated_br_config->radius_config.address, '\0', sizeof(updated_br_config->radius_config.address)); + } else { + nm_dyn_mem_free(temp.secret); + temp.secret = NULL; + } + } + /* Update for delay parameter here */ tr_debug("Validation complete of received br_configuration"); return NM_STATUS_SUCCESS; @@ -793,6 +1028,7 @@ static nm_status_t br_config_validation(nm_br_config_t *existing_br_config, nm_b static nm_status_t set_br_config_to_nanostack(nm_br_config_t *existing_br_config, nm_br_config_t *updated_br_config) { mesh_error_t status = MESH_ERROR_UNKNOWN; + radius_server_t temp = {0}; if ((existing_br_config == NULL) || (updated_br_config == NULL)) { tr_debug("FAILED: Set br_config is NULL"); @@ -821,6 +1057,42 @@ static nm_status_t set_br_config_to_nanostack(nm_br_config_t *existing_br_config tr_info("SET PAN ID: %d", updated_br_config->pan_id); } + /* Setting radius server secret */ + if (updated_br_config->radius_config.secret != NULL) { + if (memcmp(existing_br_config->radius_config.secret, updated_br_config->radius_config.secret, updated_br_config->radius_config.secret_len) != 0) { + status = ws_br->set_radius_shared_secret(updated_br_config->radius_config.secret_len, (const uint8_t *) updated_br_config->radius_config.secret); + if (status != MESH_ERROR_NONE) { + tr_warn("FAILED to set network Radius Server Secret to Nanostack %d", status); + return NM_STATUS_FAIL; + } else { + tr_info("Radius server Secret set"); + } + } + } + + /* Setting radius server address */ + if (memcmp(existing_br_config->radius_config.address, updated_br_config->radius_config.address, sizeof(updated_br_config->radius_config.address)) != 0) { + if (get_server_secret(&temp) == NM_STATUS_SUCCESS) { + if(updated_br_config->radius_config.address[0] == '\0') { + /*Clear External radius server address*/ + status = ws_br->set_radius_server_ipv6_address(NULL); + } else { + /*Set External radius server address*/ + status = ws_br->set_radius_server_ipv6_address(updated_br_config->radius_config.address); + } + nm_dyn_mem_free(temp.secret); + temp.secret = NULL; + if (status != MESH_ERROR_NONE) { + tr_info("FAILED: Set radius server address return %d", status); + return NM_STATUS_FAIL; + } else { + tr_info("SUCCESS: Set radius server address %s", updated_br_config->radius_config.address); + } + } else { + tr_warn("FAILED: Setting Radius Server address to Nanostack Skipped due to Radius Server Secret not found"); + } + } + updated_br_config->resource_version = WS_BR_RESOURCE_VERSION; tr_debug("BR_resource_version %lu", updated_br_config->resource_version); return NM_STATUS_SUCCESS; @@ -846,6 +1118,56 @@ static nm_status_t get_default_br_config_from_nanostack(nm_br_config_t *br_confi return NM_STATUS_FAIL; } + if (get_server_secret(&br_config->radius_config) == NM_STATUS_SUCCESS) { + status = ws_br->get_radius_server_ipv6_address(br_config->radius_config.address); + if (status != MESH_ERROR_NONE) { + tr_info("FAILED: Get radius server address return %d", status); + } else { + tr_info("SUCCESS: Get radius server address %s", br_config->radius_config.address); + } + } + + return NM_STATUS_SUCCESS; +} + +nm_status_t nm_factory_configure_border_router(void) +{ + size_t radius_buf_len = 0; + char *radius_serv_adr = NULL; + uint8_t * radius_serv_secret = NULL; + tr_info("Applying Factory Configurations on BR Interface"); + + if (ws_br == NULL) { + tr_warn("Could not Apply Factory Configuration: Border Router is not Initialized yet"); + return NM_STATUS_FAIL; + } + if (nm_kcm_wisun_network_radius_secret_init(&radius_serv_secret, &radius_buf_len) == NM_STATUS_SUCCESS) { + if (ws_br->set_radius_shared_secret((uint16_t)radius_buf_len, radius_serv_secret) != MESH_ERROR_NONE) { + tr_error("FAILED to set radius shared secret '%s' len '%d'from Factory Configuration", tr_array( radius_serv_secret, radius_buf_len), radius_buf_len); + free(radius_serv_secret); + return NM_STATUS_FAIL; + } else { + tr_info("Factory Configuration SET: Radius Shared Secret = %s ,Radius Shared Secret len = %d", tr_array( radius_serv_secret, radius_buf_len),radius_buf_len); + free(radius_serv_secret); + } + } else { + tr_info("Factory Configuration NOT FOUND: Radius Shared Secret"); + return NM_STATUS_SUCCESS; + } + + if (nm_kcm_wisun_network_radius_addr_init(&radius_serv_adr, &radius_buf_len) == NM_STATUS_SUCCESS) { + if (ws_br->set_radius_server_ipv6_address((char *)radius_serv_adr) != MESH_ERROR_NONE) { + tr_error("FAILED to set radius server address '%s' len '%d'from Factory Configuration", tr_array((uint8_t *)radius_serv_adr, radius_buf_len), radius_buf_len); + free(radius_serv_adr); + return NM_STATUS_FAIL; + } else { + tr_info("Factory Configuration SET: Radius Server Address = %s and Len = %d", tr_array((uint8_t *)radius_serv_adr, radius_buf_len), radius_buf_len); + free(radius_serv_adr); + } + } else { + tr_info("Factory Configuration NOT FOUND: Radius Server Address"); + } + return NM_STATUS_SUCCESS; } @@ -872,6 +1194,7 @@ nm_status_t nm_configure_border_router(void) */ nm_iface_kvstore_read_cfg(kv_key_br, &modified_br_config, BR); + tr_info("Applying Latest Received Configurations from Pelion Server on BR Interface"); if (set_br_config_to_nanostack(&default_br_config, &modified_br_config) == NM_STATUS_FAIL) { tr_warn("FAILED to set Border Router config to Nanostack"); return NM_STATUS_FAIL; @@ -898,7 +1221,7 @@ nm_status_t nm_configure_border_router(void) /* Free dynamically allocated memory */ nm_dyn_mem_free(cborise_data); - tr_info("Border Router Configured with Latest Configuration"); + tr_debug("Border Router Configured with Latest Configuration"); return NM_STATUS_SUCCESS; } @@ -907,6 +1230,7 @@ nm_status_t nm_res_set_br_config(uint8_t *data, size_t length) { nm_br_config_t kvstored_br_config = {0}; nm_br_config_t received_br_config = {0}; + uint8_t *cborise_data = NULL; size_t cborise_data_len = 0; @@ -948,6 +1272,7 @@ nm_status_t nm_res_set_br_config(uint8_t *data, size_t length) nm_dyn_mem_free(cborise_data); return NM_STATUS_FAIL; } + if (set_data_to_kvstore(kv_key_br, cborise_data, cborise_data_len) == NM_STATUS_FAIL) { tr_error("FAILED to store updated CBORised BR Configuration"); /* Free dynamically allocated memory */ diff --git a/network-manager/source/nm_kcm_factory.cpp b/network-manager/source/nm_kcm_factory.cpp new file mode 100644 index 000000000..9320305d8 --- /dev/null +++ b/network-manager/source/nm_kcm_factory.cpp @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2020-2021 Pelion. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined MBED_CONF_MBED_CLOUD_CLIENT_NETWORK_MANAGER && (MBED_CONF_MBED_CLOUD_CLIENT_NETWORK_MANAGER == 1) + +#include "string.h" +#include "mbed_trace.h" +#include "ws_management_api.h" +#include "NetworkManager_internal.h" +#include "nm_kcm_factory.h" +#include "key_config_manager.h" +#include "nm_dynmem_helper.h" + +/* Trace name */ +#define TRACE_GROUP "NMfc" + +/* KCM configuration item names */ +static const char MESH_WISUN_NETWORK_NAME_KEY[] = "mesh_wisun_network_name"; +static const char MESH_WISUN_NETWORK_SIZE_KEY[] = "mesh_wisun_network_size"; +static const char MESH_WISUN_REGULATORY_DOMAIN_KEY[] = "mesh_wisun_regulatory_domain"; +static const char MESH_WISUN_OPERATING_MODE_KEY[] = "mesh_wisun_operating_mode"; +static const char MESH_WISUN_OPERATING_CLASS_KEY[] = "mesh_wisun_operating_class"; +static const char MESH_WISUN_RADIUS_SERVER_ADDRESS_KEY[] = "radius_srv_address"; +static const char MESH_WISUN_RADIUS_SERVER_SECRET_KEY[] = "radius_srv_secret"; +static const char MESH_WISUN_TRUSTED_CERTIFICATE_KEY[] = "mesh_wisun_trusted_certificate"; +static const char MESH_WISUN_OWN_CERTIFICATE_KEY[] = "mesh_wisun_own_certificate"; +static const char MESH_MAC_ADDRESS_KEY[] = "mesh_mac_address"; +static const char ETHERNET_MAC_ADDRESS_KEY[] = "ethernet_mac_address"; + +nm_status_t nm_kcm_wisun_network_name_init(char **network_name_buf_ptr) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size = 0; + + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_NETWORK_NAME_KEY, + sizeof(MESH_WISUN_NETWORK_NAME_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + // network name found from KCM + *network_name_buf_ptr = (char *)nm_dyn_mem_alloc((kcm_item_buff_size * sizeof(char))+1); + memset(*network_name_buf_ptr,'\0',kcm_item_buff_size + 1); + strncpy(*network_name_buf_ptr, (char *)kcm_item_buffer,kcm_item_buff_size); + free(kcm_item_buffer); + return NM_STATUS_SUCCESS; + } + + return NM_STATUS_FAIL; +} + +nm_status_t nm_kcm_wisun_network_size_init(uint8_t *network_size) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size; + + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_NETWORK_SIZE_KEY, + sizeof(MESH_WISUN_NETWORK_SIZE_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + // network size as hundreds of devices + *network_size = kcm_item_buffer[0]; + free(kcm_item_buffer); + return NM_STATUS_SUCCESS; + } + + return NM_STATUS_FAIL; +} + +nm_status_t nm_kcm_mesh_mac_address_init(uint8_t **mesh_mac_address_ptr, size_t *mesh_mac_address_len) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size = 0; + + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_MAC_ADDRESS_KEY, + sizeof(MESH_MAC_ADDRESS_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + //MAC address found from KCM + *mesh_mac_address_ptr = kcm_item_buffer; + *mesh_mac_address_len = kcm_item_buff_size; + return NM_STATUS_SUCCESS; + } + + return NM_STATUS_FAIL; +} + +nm_status_t nm_kcm_ethernet_mac_address_init(uint8_t **eth_mac_address_ptr, size_t *eth_mac_address_len) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size = 0; + + kcm_status = kcm_item_get_size_and_data((uint8_t *)ETHERNET_MAC_ADDRESS_KEY, + sizeof(ETHERNET_MAC_ADDRESS_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *eth_mac_address_ptr = kcm_item_buffer; + *eth_mac_address_len = kcm_item_buff_size; + return NM_STATUS_SUCCESS; + } + + return NM_STATUS_FAIL; +} + +nm_status_t nm_kcm_wisun_network_regulatory_domain_init(uint8_t *regulatory_domain, uint8_t *operating_class, uint8_t *operating_mode) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size = 0; + + // Init REGULATORY DOMAIN + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_REGULATORY_DOMAIN_KEY, + sizeof(MESH_WISUN_REGULATORY_DOMAIN_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *regulatory_domain = kcm_item_buffer[0]; + free(kcm_item_buffer); + } else { + return NM_STATUS_FAIL; + } + + // Init OPERATING MODE + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_OPERATING_MODE_KEY, + sizeof(MESH_WISUN_OPERATING_MODE_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *operating_mode = kcm_item_buffer[0]; + free(kcm_item_buffer); + } else { + return NM_STATUS_FAIL; + } + + // Init OPERATING CLASS + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_OPERATING_CLASS_KEY, + sizeof(MESH_WISUN_OPERATING_CLASS_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *operating_class = kcm_item_buffer[0]; + free(kcm_item_buffer); + } else { + return NM_STATUS_FAIL; + } + + return NM_STATUS_SUCCESS; +} + +nm_status_t nm_kcm_wisun_network_radius_addr_init(char **srv_addr, size_t *srv_addr_len) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size = 0; + + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_RADIUS_SERVER_ADDRESS_KEY, + sizeof(MESH_WISUN_RADIUS_SERVER_ADDRESS_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *srv_addr = (char *)nm_dyn_mem_alloc((kcm_item_buff_size * sizeof(char))+1); + memset(*srv_addr,'\0',kcm_item_buff_size + 1); + strncpy(*srv_addr, (char *)kcm_item_buffer,kcm_item_buff_size); + free(kcm_item_buffer); + *srv_addr_len = kcm_item_buff_size; + return NM_STATUS_SUCCESS; + } + + return NM_STATUS_FAIL; +} + +nm_status_t nm_kcm_wisun_network_radius_secret_init(uint8_t **srv_secret_buf, size_t *actual_secret_len) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size = 0; + + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_RADIUS_SERVER_SECRET_KEY, + sizeof(MESH_WISUN_RADIUS_SERVER_SECRET_KEY) - 1, + KCM_CONFIG_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *srv_secret_buf = kcm_item_buffer; + *actual_secret_len = kcm_item_buff_size; + return NM_STATUS_SUCCESS; + } + + return NM_STATUS_FAIL; +} + +nm_status_t nm_kcm_wisun_network_trusted_certificate_init(uint8_t **trusted_cert_buf, uint16_t *trusted_cert_len) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size = 0; + + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_TRUSTED_CERTIFICATE_KEY, + sizeof(MESH_WISUN_TRUSTED_CERTIFICATE_KEY) - 1, + KCM_CERTIFICATE_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *trusted_cert_buf = kcm_item_buffer; + *trusted_cert_len = kcm_item_buff_size; + return NM_STATUS_SUCCESS; + } + + return NM_STATUS_FAIL; +} + +nm_status_t nm_kcm_wisun_network_own_certificate_init(uint8_t **own_cert_buf, uint16_t *own_cert_len, uint8_t **own_cert_key, uint16_t *own_cert_key_len) +{ + kcm_status_e kcm_status = KCM_STATUS_ERROR; + uint8_t *kcm_item_buffer = NULL; + size_t kcm_item_buff_size = 0; + + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_OWN_CERTIFICATE_KEY, + sizeof(MESH_WISUN_OWN_CERTIFICATE_KEY) - 1, + KCM_CERTIFICATE_ITEM, + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *own_cert_buf = kcm_item_buffer; + *own_cert_len = kcm_item_buff_size; + } else { + return NM_STATUS_FAIL; + } + + kcm_item_buffer = NULL; + kcm_status = kcm_item_get_size_and_data((uint8_t *)MESH_WISUN_OWN_CERTIFICATE_KEY, + sizeof(MESH_WISUN_OWN_CERTIFICATE_KEY) - 1, + KCM_PRIVATE_KEY_ITEM , + &kcm_item_buffer, + &kcm_item_buff_size); + + if (kcm_status == KCM_STATUS_SUCCESS) { + *own_cert_key = kcm_item_buffer; + *own_cert_key_len = kcm_item_buff_size; + } else { + return NM_STATUS_FAIL; + } + + return NM_STATUS_SUCCESS; +} + +//#define NM_KCM_TEST_DATA +#ifdef NM_KCM_TEST_DATA +#include + +void nm_kcm_test_data_store(void) +{ + + static bool initialized = false; + + if (initialized) { + return; + } + initialized = true; + + kcm_status_e kcm_status; + + static const char mesh_kcm_network_name[] = "KCM-Network-name"; + static const uint8_t mesh_kcm_network_size = 2; + static const uint8_t mesh_kcm_mac_addr[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; + static const uint8_t eth_kcm_mac_addr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + static const uint8_t mesh_kcm_regulatory_domain = 5; //india + static const uint8_t mesh_kcm_operating_mode = 255; + static const uint8_t mesh_kcm_operating_class = 1; + static const char mesh_kcm_radius_srv_addr[] = "2001:14b8:1830:b000:1e69:7aff:fe03:dad7"; + static const char mesh_kcm_radius_srv_secret[] = "wisun_radius_password"; + + tr_info("Set nm_kcm_network_name: %s", mesh_kcm_network_name); + kcm_status = kcm_item_store((uint8_t *)MESH_WISUN_NETWORK_NAME_KEY, + sizeof(MESH_WISUN_NETWORK_NAME_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)mesh_kcm_network_name, + sizeof(mesh_kcm_network_name), + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_network_name"); + } + + tr_info("Set nm_kcm_network_size: %d", mesh_kcm_network_size); + kcm_status = kcm_item_store((uint8_t *)MESH_WISUN_NETWORK_SIZE_KEY, + sizeof(MESH_WISUN_NETWORK_SIZE_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)&mesh_kcm_network_size, + sizeof(mesh_kcm_network_size), + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_network_size"); + } + + tr_info("Set nm_kcm_mesh_mac_address"); + kcm_status = kcm_item_store((uint8_t *)MESH_MAC_ADDRESS_KEY, + sizeof(MESH_MAC_ADDRESS_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)mesh_kcm_mac_addr, + sizeof(mesh_kcm_mac_addr), + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_mesh_mac_address"); + } + + tr_info("Set nm_kcm_eth_mac_address"); + kcm_status = kcm_item_store((uint8_t *)ETHERNET_MAC_ADDRESS_KEY, + sizeof(ETHERNET_MAC_ADDRESS_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)eth_kcm_mac_addr, + sizeof(eth_kcm_mac_addr), + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_eth_mac_address"); + } + + tr_info("Set nm_kcm_regulatory_domain: %d", mesh_kcm_regulatory_domain); + kcm_status = kcm_item_store((uint8_t *)MESH_WISUN_REGULATORY_DOMAIN_KEY, + sizeof(MESH_WISUN_REGULATORY_DOMAIN_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)&mesh_kcm_regulatory_domain, + sizeof(mesh_kcm_regulatory_domain), + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_regulatory_domain"); + } + + tr_info("Set nm_kcm_operating_class: %d", mesh_kcm_operating_class); + kcm_status = kcm_item_store((uint8_t *)MESH_WISUN_OPERATING_CLASS_KEY, + sizeof(MESH_WISUN_OPERATING_CLASS_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)&mesh_kcm_operating_class, + sizeof(mesh_kcm_operating_class), + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_operating_class"); + } + + tr_info("Set nm_kcm_operating_mode: %d", mesh_kcm_operating_mode); + kcm_status = kcm_item_store((uint8_t *)MESH_WISUN_OPERATING_MODE_KEY, + sizeof(MESH_WISUN_OPERATING_MODE_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)&mesh_kcm_operating_mode, + sizeof(mesh_kcm_operating_mode), + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_operating_mode"); + } + + + tr_info("Set nm_kcm_radius_srv_addr: %s", mesh_kcm_radius_srv_addr); + kcm_status = kcm_item_store((uint8_t *)MESH_WISUN_RADIUS_SERVER_ADDRESS_KEY, + sizeof(MESH_WISUN_RADIUS_SERVER_ADDRESS_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)mesh_kcm_radius_srv_addr, + strlen(mesh_kcm_radius_srv_addr) + 1, + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_radius_srv_addr"); + } + + tr_info("Set nm_kcm_radius_srv_secret: %s", tr_array((uint8_t *)mesh_kcm_radius_srv_secret, sizeof(mesh_kcm_radius_srv_secret) / sizeof(uint8_t))); + kcm_status = kcm_item_store((uint8_t *)MESH_WISUN_RADIUS_SERVER_SECRET_KEY, + sizeof(MESH_WISUN_RADIUS_SERVER_SECRET_KEY) - 1, + KCM_CONFIG_ITEM, + true, + (uint8_t *)mesh_kcm_radius_srv_secret, + sizeof(mesh_kcm_radius_srv_secret) / sizeof(uint8_t) -1, + NULL); + if (kcm_status != KCM_STATUS_SUCCESS) { + tr_error("Failed to set nm_kcm_radius_srv_secret"); + } +} + +void nm_kcm_test_data_delete(void) +{ + kcm_item_delete((uint8_t *)MESH_WISUN_NETWORK_NAME_KEY, strlen(MESH_WISUN_NETWORK_NAME_KEY), KCM_CONFIG_ITEM); + kcm_item_delete((uint8_t *)MESH_WISUN_NETWORK_SIZE_KEY, strlen(MESH_WISUN_NETWORK_SIZE_KEY), KCM_CONFIG_ITEM); + kcm_item_delete((uint8_t *)ETHERNET_MAC_ADDRESS_KEY, strlen(ETHERNET_MAC_ADDRESS_KEY), KCM_CONFIG_ITEM); + kcm_item_delete((uint8_t *)MESH_MAC_ADDRESS_KEY, strlen(MESH_MAC_ADDRESS_KEY), KCM_CONFIG_ITEM); + kcm_item_delete((uint8_t *)MESH_WISUN_REGULATORY_DOMAIN_KEY, strlen(MESH_WISUN_REGULATORY_DOMAIN_KEY), KCM_CONFIG_ITEM); + kcm_item_delete((uint8_t *)MESH_WISUN_OPERATING_CLASS_KEY, strlen(MESH_WISUN_OPERATING_CLASS_KEY), KCM_CONFIG_ITEM); + kcm_item_delete((uint8_t *)MESH_WISUN_OPERATING_MODE_KEY, strlen(MESH_WISUN_OPERATING_MODE_KEY), KCM_CONFIG_ITEM); + kcm_item_delete((uint8_t *)MESH_WISUN_RADIUS_SERVER_ADDRESS_KEY, strlen(MESH_WISUN_RADIUS_SERVER_ADDRESS_KEY), KCM_CONFIG_ITEM); + kcm_item_delete((uint8_t *)MESH_WISUN_RADIUS_SERVER_SECRET_KEY, strlen(MESH_WISUN_RADIUS_SERVER_SECRET_KEY), KCM_CONFIG_ITEM); + tr_info("NM KCM Test Factory Data Deleted"); +} + +#endif /* NM_KCM_TEST_DATA */ +#endif //MBED_CONF_MBED_CLOUD_CLIENT_NETWORK_MANAGER && (MBED_CONF_MBED_CLOUD_CLIENT_NETWORK_MANAGER == 1) diff --git a/network-manager/source/nm_resource_manager.cpp b/network-manager/source/nm_resource_manager.cpp index a7ce4b259..654600240 100644 --- a/network-manager/source/nm_resource_manager.cpp +++ b/network-manager/source/nm_resource_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Pelion. All rights reserved. + * Copyright (c) 2020-2021 Pelion. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -45,8 +45,8 @@ static M2MResource *routing_table; static M2MResource *nm_stats; static M2MResource *br_stats; static M2MResource *node_stats; -static M2MResource *radio_stats; static M2MResource *ch_noise; +static M2MResource *reset_parameter; typedef struct { M2MResource *res_obj; @@ -66,7 +66,6 @@ static uint8_t *ch_noise_buf = NULL; static uint8_t *br_stats_buf = NULL; static uint8_t *routing_table_buf = NULL; static uint8_t *node_stats_buf = NULL; -static uint8_t *radio_stats_buf = NULL; static uint8_t *res_data = NULL; /* Function to overcome limitation of 32 bytes of length in tr_array */ @@ -126,6 +125,18 @@ static void br_config_cb(const char * /*object_name*/) nm_post_event(NM_EVENT_RESOURCE_SET, 0, res_data); } +static void reset_parameter_cb(const char * /*object_name*/) +{ + res_set_data_t *res_data = (res_set_data_t *)nm_dyn_mem_alloc(sizeof(res_set_data_t)); + if (res_data == NULL) { + return; + } + tr_info("Reset Parameter callback received"); + res_data->res_obj = reset_parameter; + res_data->len = 0; + res_data->data = NULL; + nm_post_event(NM_EVENT_RESOURCE_SET, 0, res_data); +} static nm_status_t nm_res_get_ws_config_from_kvstore(uint8_t **datap, size_t *length) { @@ -244,9 +255,6 @@ static coap_response_code_e resource_read_requested(const M2MResourceBase &resou } else if (obj == node_stats) { status = nm_res_get_node_stats(&node_stats_buf, &len); res_data = node_stats_buf; - } else if (obj == radio_stats) { - status = nm_res_get_radio_stats(&radio_stats_buf, &len); - res_data = radio_stats_buf; } else { tr_err("FAILED: Unknown client_args received in %s", __func__); } @@ -334,12 +342,6 @@ void msg_delivery_handle(const M2MBase &base, node_stats_buf = NULL; tr_debug("node_stats data Memory freed"); } - } else if (obj == radio_stats) { - if (radio_stats_buf != NULL) { - nm_dyn_mem_free(radio_stats_buf); - radio_stats_buf = NULL; - tr_debug("radio_stats data Memory freed"); - } } else { tr_err("FAILED: Unknown client_args received in %s", __func__); } @@ -389,6 +391,12 @@ nm_status_t nm_res_manager_create(void *obj_list) ch_noise->set_read_resource_function(resource_read_requested, ch_noise); ch_noise->set_observable(true); + reset_parameter = M2MInterfaceFactory::create_resource(*m2m_obj_list, 33455, 0, 8, M2MResourceInstance::OPAQUE, M2MBase::PUT_ALLOWED); + if (reset_parameter->set_value_updated_function(reset_parameter_cb) != true) { + tr_error("reset_parameter->set_value_updated_function() failed"); + return NM_STATUS_FAIL; + } + if (MBED_CONF_MBED_MESH_API_WISUN_DEVICE_TYPE == MESH_DEVICE_TYPE_WISUN_BORDER_ROUTER) { br_stats = M2MInterfaceFactory::create_resource(*m2m_obj_list, 33455, 0, 6, M2MResourceInstance::OPAQUE, M2MBase::GET_ALLOWED); br_stats->set_message_delivery_status_cb(msg_delivery_handle, br_stats); @@ -405,11 +413,6 @@ nm_status_t nm_res_manager_create(void *obj_list) node_stats->set_message_delivery_status_cb(msg_delivery_handle, node_stats); node_stats->set_read_resource_function(resource_read_requested, node_stats); node_stats->set_observable(true); - - radio_stats = M2MInterfaceFactory::create_resource(*m2m_obj_list, 33455, 0, 8, M2MResourceInstance::OPAQUE, M2MBase::GET_ALLOWED); - radio_stats->set_message_delivery_status_cb(msg_delivery_handle, radio_stats); - radio_stats->set_read_resource_function(resource_read_requested, radio_stats); - radio_stats->set_observable(true); } return NM_STATUS_SUCCESS; } @@ -505,22 +508,6 @@ nm_status_t nm_res_manager_get(void *resource_object) return NM_STATUS_FAIL; } - if (res_obj == radio_stats) { - if (nm_res_get_radio_stats(&buf, &len) == NM_STATUS_SUCCESS) { - tr_info("Setting value of resource radio_stats [len = %u] in Cloud Client", len); - print_stream(buf, len); - if (res_obj->set_value(buf, len) != true) { - tr_warn("FAILED to set Radio Statistics resource to Cloud Client"); - return NM_STATUS_FAIL; - } - tr_info("Radio Statistics resource value Set to Cloud Client"); - nm_dyn_mem_free(buf); - return NM_STATUS_SUCCESS; - } - tr_warn("FAILED to fetch Radio Statistics"); - return NM_STATUS_FAIL; - } - if (res_obj == routing_table) { if (nm_res_get_routing_table(&buf, &len) == NM_STATUS_SUCCESS) { tr_info("Setting value of resource routing_table [len = %u] in Cloud Client", len); @@ -530,7 +517,7 @@ nm_status_t nm_res_manager_get(void *resource_object) return NM_STATUS_FAIL; } tr_info("Routing Table resource value Set to Cloud Client"); - /* Do not need to free buf pointer. We may use the same memory next time */ + nm_dyn_mem_free(buf); return NM_STATUS_SUCCESS; } tr_warn("FAILED to fetch Routing Table"); @@ -587,6 +574,18 @@ nm_status_t nm_res_manager_set(void *resource_data) return NM_STATUS_SUCCESS; } + if (res_data->res_obj == reset_parameter) { + + if(nm_reset_parameters() == NM_STATUS_FAIL) { + tr_info("Reset Parameter FAILED"); + } else { + tr_info("Reset Parameter SUCCESS"); + } + nm_dyn_mem_free(res_data); + + return NM_STATUS_SUCCESS; + } + /* To-Do :: Implement for other resources */ return NM_STATUS_FAIL; } @@ -602,7 +601,6 @@ void nm_manager_res_refresh(void) nm_post_event(NM_EVENT_RESOURCE_GET, 0, routing_table); } else if (MBED_CONF_MBED_MESH_API_WISUN_DEVICE_TYPE == MESH_DEVICE_TYPE_WISUN_ROUTER) { nm_post_event(NM_EVENT_RESOURCE_GET, 0, node_stats); - nm_post_event(NM_EVENT_RESOURCE_GET, 0, radio_stats); } } diff --git a/secure-device-access-client/cose-c/source/mbedtls.c b/secure-device-access-client/cose-c/source/mbedtls.c index 3a9e8a902..5576326b6 100644 --- a/secure-device-access-client/cose-c/source/mbedtls.c +++ b/secure-device-access-client/cose-c/source/mbedtls.c @@ -34,7 +34,7 @@ #include "cose_int.h" #include "crypto_cose.h" #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "mbedtls/bignum.h" #include "mbedtls/ecdsa.h" #include "mbedtls/ecp.h" diff --git a/secure-device-access-client/secure-device-access/source/sda_nonce_mgr.c b/secure-device-access-client/secure-device-access/source/sda_nonce_mgr.c index a4c81139c..1c52dfa5a 100644 --- a/secure-device-access-client/secure-device-access/source/sda_nonce_mgr.c +++ b/secure-device-access-client/secure-device-access/source/sda_nonce_mgr.c @@ -20,7 +20,7 @@ #include "sda_error_handling.h" #include "sda_nonce_mgr.h" #include "sda_macros.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" /** Self describing nonce structure * value - the nonce value diff --git a/source/CertificateParser.c b/source/CertificateParser.c index e9713a556..6376a04ff 100644 --- a/source/CertificateParser.c +++ b/source/CertificateParser.c @@ -18,7 +18,7 @@ #include #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" #include "mbed-trace/mbed_trace.h" #define TRACE_GROUP "mClt" diff --git a/source/CloudClientStorage.c b/source/CloudClientStorage.c index 8dd2e8dc4..1ca6c66f0 100644 --- a/source/CloudClientStorage.c +++ b/source/CloudClientStorage.c @@ -288,17 +288,8 @@ void *ccs_open_certificate_chain(const char *chain_file_name, size_t *chain_size ccs_status_e ccs_get_next_cert_chain(void *chain_handle, void *cert_data, size_t *data_size) { kcm_status_e kcm_status; - size_t max_size = 1024; - kcm_status = kcm_cert_chain_get_next_size((kcm_cert_chain_handle *) chain_handle, data_size); - - if (kcm_status != KCM_STATUS_SUCCESS) { - tr_error("CloudClientStorage::ccs_get_next_cert_chain - get_next_size error %d", kcm_status); - return CCS_STATUS_ERROR; - } - - - kcm_status = kcm_cert_chain_get_next_data((kcm_cert_chain_handle *) chain_handle, (uint8_t*)cert_data, max_size, data_size); + kcm_status = kcm_cert_chain_get_next_data((kcm_cert_chain_handle *) chain_handle, (uint8_t*)cert_data, *data_size, data_size); if (kcm_status != KCM_STATUS_SUCCESS) { tr_error("CloudClientStorage::ccs_get_next_cert_chain - get_next_data error %d", kcm_status); diff --git a/source/ConnectorClient.cpp b/source/ConnectorClient.cpp index 8c7fa2d35..7c177a88c 100644 --- a/source/ConnectorClient.cpp +++ b/source/ConnectorClient.cpp @@ -76,7 +76,7 @@ static int read_size_callback_helper(const char *key, size_t &buffer_len) { buffer_len = 0; if (strcmp(key, g_fcc_lwm2m_device_private_key_name) == 0 || - strcmp(key, g_fcc_bootstrap_device_private_key_name) == 0) { + strcmp(key, g_fcc_bootstrap_device_private_key_name) == 0) { if (ccs_item_size(key, &buffer_len, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) { return CCS_STATUS_ERROR; } @@ -92,22 +92,14 @@ static int read_size_callback_helper(const char *key, size_t &buffer_len) static int read_callback_helper(const char *key, void *buffer, size_t &buffer_len) { size_t cert_size = 0; - buffer_len = 0; - if (strcmp(key, g_fcc_lwm2m_device_private_key_name) == 0 || - strcmp(key, g_fcc_bootstrap_device_private_key_name) == 0) { - if (read_size_callback_helper(key, buffer_len) != CCS_STATUS_SUCCESS) { - return CCS_STATUS_ERROR; - } - if (ccs_get_item(key, (uint8_t*)buffer, buffer_len, &cert_size, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) { + if (strcmp(key, g_fcc_lwm2m_device_private_key_name) == 0 || + strcmp(key, g_fcc_bootstrap_device_private_key_name) == 0) { + if (ccs_get_item(key, (uint8_t *)buffer, buffer_len, &cert_size, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) { return CCS_STATUS_ERROR; } } else { - if (read_size_callback_helper(key, buffer_len) != CCS_STATUS_SUCCESS) { - return CCS_STATUS_ERROR; - } - - if (ccs_get_item(key, (uint8_t*)buffer, buffer_len, &cert_size, CCS_CERTIFICATE_ITEM) != CCS_STATUS_SUCCESS) { + if (ccs_get_item(key, (uint8_t *)buffer, buffer_len, &cert_size, CCS_CERTIFICATE_ITEM) != CCS_STATUS_SUCCESS) { return CCS_STATUS_ERROR; } } @@ -119,7 +111,7 @@ static int read_callback_helper(const char *key, void *buffer, size_t &buffer_le -static bool write_security_object_data_to_kcm(const M2MResourceBase& resource, const uint8_t *buffer, const size_t buffer_size, void */*client_args*/) +static bool write_security_object_data_to_kcm(const M2MResourceBase &resource, const uint8_t *buffer, const size_t buffer_size, void */*client_args*/) { ccs_status_e status = CCS_STATUS_ERROR; uint32_t resource_id = resource.name_id(); @@ -162,12 +154,12 @@ static bool write_security_object_data_to_kcm(const M2MResourceBase& resource, c return (status == CCS_STATUS_SUCCESS) ? true : false; } -static coap_response_code_e read_security_object_data_from_kcm(const M2MResourceBase& resource, - uint8_t *&buffer, - size_t &buffer_len, - size_t &/*total_size*/, - const size_t /*offset*/, - void */*client_args*/) +static coap_response_code_e read_security_object_data_from_kcm(const M2MResourceBase &resource, + uint8_t *&buffer, + size_t &buffer_len, + size_t &/*total_size*/, + const size_t /*offset*/, + void */*client_args*/) { uint32_t resource_id = resource.name_id(); uint16_t object_instance_id = resource.object_instance_id(); @@ -175,27 +167,27 @@ static coap_response_code_e read_security_object_data_from_kcm(const M2MResource switch (resource_id) { case M2MSecurity::PublicKey: if (object_instance_id == M2MSecurity::Bootstrap) { - status = read_callback_helper(g_fcc_bootstrap_device_certificate_name, (void*)buffer, buffer_len); + status = read_callback_helper(g_fcc_bootstrap_device_certificate_name, (void *)buffer, buffer_len); } else { - status = read_callback_helper(g_fcc_lwm2m_device_certificate_name, (void*)buffer, buffer_len); + status = read_callback_helper(g_fcc_lwm2m_device_certificate_name, (void *)buffer, buffer_len); } - break; + break; case M2MSecurity::ServerPublicKey: if (object_instance_id == M2MSecurity::Bootstrap) { - status = read_callback_helper(g_fcc_bootstrap_server_ca_certificate_name, (void*)buffer, buffer_len); + status = read_callback_helper(g_fcc_bootstrap_server_ca_certificate_name, (void *)buffer, buffer_len); } else { - status = read_callback_helper(g_fcc_lwm2m_server_ca_certificate_name, (void*)buffer, buffer_len); + status = read_callback_helper(g_fcc_lwm2m_server_ca_certificate_name, (void *)buffer, buffer_len); } - break; + break; case M2MSecurity::Secretkey: if (object_instance_id == M2MSecurity::Bootstrap) { - status = read_callback_helper(g_fcc_bootstrap_device_private_key_name, (void*)buffer, buffer_len); + status = read_callback_helper(g_fcc_bootstrap_device_private_key_name, (void *)buffer, buffer_len); } else { - status = read_callback_helper(g_fcc_lwm2m_device_private_key_name, (void*)buffer, buffer_len); + status = read_callback_helper(g_fcc_lwm2m_device_private_key_name, (void *)buffer, buffer_len); } - break; + break; default: status = -1; @@ -205,7 +197,7 @@ static coap_response_code_e read_security_object_data_from_kcm(const M2MResource return (status == 0) ? COAP_RESPONSE_VALID : COAP_RESPONSE_BAD_REQUEST; } -static int read_security_object_data_size_from_kcm(const M2MResourceBase& resource, size_t *buffer_len, void */*client_args*/) +static int read_security_object_data_size_from_kcm(const M2MResourceBase &resource, size_t *buffer_len, void */*client_args*/) { uint32_t resource_id = resource.name_id(); uint16_t object_instance_id = resource.object_instance_id(); @@ -238,11 +230,11 @@ static int read_security_object_data_size_from_kcm(const M2MResourceBase& resour return CCS_STATUS_ERROR; } -static int open_certificate_chain_callback(const M2MResourceBase& resource, size_t *chain_size, void *client_args) +static int open_certificate_chain_callback(const M2MResourceBase &resource, size_t *chain_size, void *client_args) { void *handle = NULL; uint16_t object_instance_id = resource.object_instance_id(); - ConnectorClient *client = (ConnectorClient*)client_args; + ConnectorClient *client = (ConnectorClient *)client_args; if (object_instance_id == M2MSecurity::Bootstrap) { handle = ccs_open_certificate_chain(g_fcc_bootstrap_device_certificate_name, chain_size); client->set_certificate_chain_handle(handle); @@ -254,26 +246,26 @@ static int open_certificate_chain_callback(const M2MResourceBase& resource, size return (handle) ? CCS_STATUS_SUCCESS : CCS_STATUS_ERROR; } -static coap_response_code_e read_certificate_chain_callback(const M2MResourceBase& /*resource*/, - uint8_t *&buffer, - size_t &buffer_len, - size_t &/*total_size*/, - const size_t /*offset*/, - void *client_args) +static coap_response_code_e read_certificate_chain_callback(const M2MResourceBase & /*resource*/, + uint8_t *&buffer, + size_t &buffer_len, + size_t &/*total_size*/, + const size_t /*offset*/, + void *client_args) { - ConnectorClient *client = (ConnectorClient*) client_args; + ConnectorClient *client = (ConnectorClient *) client_args; ccs_status_e status = CCS_STATUS_ERROR; if (client->certificate_chain_handle()) { - status = ccs_get_next_cert_chain(client->certificate_chain_handle(), (void*)buffer, &buffer_len); + status = ccs_get_next_cert_chain(client->certificate_chain_handle(), (void *)buffer, &buffer_len); } return (status == CCS_STATUS_SUCCESS) ? COAP_RESPONSE_VALID : COAP_RESPONSE_BAD_REQUEST; } -static int close_certificate_chain_callback(const M2MResourceBase& /*resource*/, size_t *, void *client_args) +static int close_certificate_chain_callback(const M2MResourceBase & /*resource*/, size_t *, void *client_args) { ccs_status_e status = CCS_STATUS_ERROR; - ConnectorClient *client = (ConnectorClient*) client_args; + ConnectorClient *client = (ConnectorClient *) client_args; if (client->certificate_chain_handle()) { status = ccs_close_certificate_chain(client->certificate_chain_handle()); client->set_certificate_chain_handle(NULL); @@ -281,19 +273,19 @@ static int close_certificate_chain_callback(const M2MResourceBase& /*resource*/, return status; } -ConnectorClient::ConnectorClient(ConnectorClientCallback* callback) -: _callback(callback), - _current_state(State_Bootstrap_Start), - _event_generated(false), _state_engine_running(false), - _setup_complete(false), - _interface(NULL), _security(NULL), - _endpoint_info(M2MSecurity::Certificate), _client_objs(NULL), _stagger_timer(NULL), _do_full_registration(false), +ConnectorClient::ConnectorClient(ConnectorClientCallback *callback) + : _callback(callback), + _current_state(State_Bootstrap_Start), + _event_generated(false), _state_engine_running(false), + _setup_complete(false), + _interface(NULL), _security(NULL), + _endpoint_info(M2MSecurity::Certificate), _client_objs(NULL), _stagger_timer(NULL), _do_full_registration(false), #ifndef MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE - _rebootstrap_timer(NULL), _bootstrap_security_instance(1), _rebootstrap_time(0), _rebootstrap_time_initialized(false), + _rebootstrap_timer(NULL), _rebootstrap_time(0), _bootstrap_security_instance(1), _rebootstrap_time_initialized(false), #endif - _lwm2m_security_instance(0), _certificate_chain_handle(NULL) + _lwm2m_security_instance(0), _certificate_chain_handle(NULL) #ifndef MBED_CLIENT_DISABLE_EST_FEATURE - ,_est_client(*this) + , _est_client(*this) #endif // !MBED_CLIENT_DISABLE_EST_FEATURE { @@ -329,13 +321,13 @@ bool ConnectorClient::setup() // Create the lwm2m server security object we need always M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); M2MInterface *interface = M2MInterfaceFactory::create_interface(*this, - DEFAULT_ENDPOINT, // endpoint name string - MBED_CLOUD_CLIENT_ENDPOINT_TYPE, // endpoint type string - MBED_CLOUD_CLIENT_LIFETIME, // lifetime - MBED_CLOUD_CLIENT_LISTEN_PORT, // listen port - _endpoint_info.account_id, // domain string - transport_mode(), // binding mode - M2MInterface::LwIP_IPv4); // network stack + DEFAULT_ENDPOINT, // endpoint name string + MBED_CLOUD_CLIENT_ENDPOINT_TYPE, // endpoint type string + MBED_CLOUD_CLIENT_LIFETIME, // lifetime + MBED_CLOUD_CLIENT_LISTEN_PORT, // listen port + _endpoint_info.account_id, // domain string + transport_mode(), // binding mode + M2MInterface::LwIP_IPv4); // network stack if ((security == NULL) || (interface == NULL)) { M2MSecurity::delete_instance(); @@ -408,7 +400,7 @@ bool ConnectorClient::create_bootstrap_object() uint8_t *buffer = NULL; if (success) { success = false; - buffer = (uint8_t*)malloc(max_size); + buffer = (uint8_t *)malloc(max_size); if (buffer != NULL) { success = true; } @@ -418,10 +410,10 @@ bool ConnectorClient::create_bootstrap_object() // it to bootstrap uri if device already bootstrapped uint8_t *iep = NULL; if (success && ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { - iep = (uint8_t*)malloc(strlen((const char*)buffer) + strlen(INTERNAL_ENDPOINT_PARAM) + 1); + iep = (uint8_t *)malloc(strlen((const char *)buffer) + strlen(INTERNAL_ENDPOINT_PARAM) + 1); if (iep != NULL) { - strcpy((char*)iep, INTERNAL_ENDPOINT_PARAM); - strcat((char*)iep, (const char*)buffer); + strcpy((char *)iep, INTERNAL_ENDPOINT_PARAM); + strcat((char *)iep, (const char *)buffer); tr_info("ConnectorClient::create_bootstrap_object - iep: %s", buffer); } //TODO: Should handle error if iep exists but allocation fails? @@ -431,14 +423,14 @@ bool ConnectorClient::create_bootstrap_object() if (success) { success = false; if (ccs_get_string_item(g_fcc_bootstrap_server_uri_name, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { - real_size = strlen((const char*)buffer); + real_size = strlen((const char *)buffer); // Append iep if we 1. have it 2. it doesn't already exist in uri 3. it fits if (iep && - strstr((const char*)buffer, (const char*)iep) == NULL && - (real_size + strlen((const char*)iep) + 1) <= max_size) { - strcat((char*)buffer, (const char*)iep); - real_size += strlen((const char*)iep) + 1; + strstr((const char *)buffer, (const char *)iep) == NULL && + (real_size + strlen((const char *)iep) + 1) <= max_size) { + strcat((char *)buffer, (const char *)iep); + real_size += strlen((const char *)iep) + 1; } tr_info("ConnectorClient::create_bootstrap_object - M2MServerUri %.*s", (int)real_size, buffer); @@ -455,7 +447,7 @@ bool ConnectorClient::create_bootstrap_object() success = false; if (ccs_get_item(g_fcc_endpoint_parameter_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { success = true; - _endpoint_info.endpoint_name = String((const char*)buffer, real_size); + _endpoint_info.endpoint_name = String((const char *)buffer, real_size); tr_info("ConnectorClient::create_bootstrap_object - Endpoint %s", _endpoint_info.endpoint_name.c_str()); } } @@ -463,7 +455,7 @@ bool ConnectorClient::create_bootstrap_object() // Account ID, not mandatory if (success) { if (ccs_get_item(KEY_ACCOUNT_ID, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { - _endpoint_info.account_id = String((const char*)buffer, real_size); + _endpoint_info.account_id = String((const char *)buffer, real_size); tr_info("ConnectorClient::create_bootstrap_object - AccountId %s", _endpoint_info.account_id.c_str()); } } @@ -472,7 +464,7 @@ bool ConnectorClient::create_bootstrap_object() if (!success) { tr_error("ConnectorClient::create_bootstrap_object - Failed to read credentials"); - _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR); + _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials, CREDENTIAL_ERROR); _security->remove_object_instance(bs_id); } } else { @@ -516,7 +508,7 @@ void ConnectorClient::state_bootstrap_failure() #endif //MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE -void ConnectorClient::start_registration(M2MBaseList* client_objs) +void ConnectorClient::start_registration(M2MBaseList *client_objs) { tr_debug("ConnectorClient::start_registration()"); _do_full_registration = false; @@ -528,7 +520,7 @@ void ConnectorClient::start_registration(M2MBaseList* client_objs) // XXX: actually this call should be external_event() to match the pattern used in other m2m classes if (create_register_object()) { - if(_security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { + if (_security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { _interface->update_endpoint(_endpoint_info.endpoint_name); _interface->update_domain(_endpoint_info.account_id); internal_event(State_Registration_Start); @@ -543,7 +535,7 @@ void ConnectorClient::start_registration(M2MBaseList* client_objs) state_engine(); } -M2MInterface * ConnectorClient::m2m_interface() +M2MInterface *ConnectorClient::m2m_interface() { return _interface; } @@ -565,11 +557,10 @@ void ConnectorClient::start_full_registration() void ConnectorClient::update_registration() { - if(_interface && _security && _security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { + if (_interface && _security && _security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { if (_client_objs != NULL) { _interface->update_registration(_security, *_client_objs); - } - else { + } else { _interface->update_registration(_security); } } @@ -679,7 +670,7 @@ bool ConnectorClient::create_register_object() // Allocate scratch buffer, this will be used to copy parameters from storage to security object const int max_size = MAX_CERTIFICATE_SIZE; - uint8_t *buffer = (uint8_t*)malloc(max_size); + uint8_t *buffer = (uint8_t *)malloc(max_size); size_t real_size = 0; bool success = false; @@ -702,17 +693,17 @@ bool ConnectorClient::create_register_object() // Endpoint if (success) { success = false; - // 64 characters for common name + 1 for null terminator + // 64 characters for common name + 1 for null terminator char device_id[65]; size_t cert_size = max_size; uint8_t certificate[MAX_CERTIFICATE_SIZE]; - uint8_t *certificate_ptr = (uint8_t*)&certificate; + uint8_t *certificate_ptr = (uint8_t *)&certificate; // TODO! Update to use chain api if (_security->resource_value_buffer(M2MSecurity::PublicKey, certificate_ptr, m2m_id, &cert_size) == 0) { real_size = cert_size; - if (extract_field_from_certificate((uint8_t*)certificate, real_size, "CN", device_id)) { + if (extract_field_from_certificate((uint8_t *)certificate, real_size, "CN", device_id)) { tr_info("ConnectorClient::create_register_object - CN - endpoint_name : %s", device_id); _endpoint_info.endpoint_name = String(device_id); success = true; @@ -733,8 +724,7 @@ bool ConnectorClient::create_register_object() #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION _endpoint_info.lwm2m_server_uri = _security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id); #endif - } - else { + } else { tr_error("KEY_CONNECTOR_URL failed."); } } @@ -742,10 +732,9 @@ bool ConnectorClient::create_register_object() // Try to get internal endpoint name if (success) { if (ccs_get_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { - _endpoint_info.internal_endpoint_name = String((const char*)buffer, real_size); + _endpoint_info.internal_endpoint_name = String((const char *)buffer, real_size); tr_info("ConnectorClient::create_register_object - internal endpoint name : %s", _endpoint_info.internal_endpoint_name.c_str()); - } - else { + } else { tr_debug("KEY_INTERNAL_ENDPOINT failed."); } } @@ -754,20 +743,20 @@ bool ConnectorClient::create_register_object() success = false; if (ccs_get_item(KEY_ACCOUNT_ID, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { tr_info("ConnectorClient::create_register_object - AccountId %.*s", (int)real_size, buffer); - _endpoint_info.account_id = String((const char*)buffer, real_size); + _endpoint_info.account_id = String((const char *)buffer, real_size); success = true; } else { if (ccs_get_item(g_fcc_lwm2m_server_uri_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { - String address((const char*)buffer, real_size); + String address((const char *)buffer, real_size); if (address.size() > 0) { const char *aid = NULL; - const int aid_size = parse_query_parameter_value_from_uri((const char*)address.c_str(), QUERY_PARAM_AID, &aid); + const int aid_size = parse_query_parameter_value_from_uri((const char *)address.c_str(), QUERY_PARAM_AID, &aid); if (aid_size > 0) { _endpoint_info.account_id.clear(); _endpoint_info.account_id.append_raw(aid, aid_size); if (ccs_set_item(KEY_ACCOUNT_ID, - (const uint8_t*)_endpoint_info.account_id.c_str(), - (size_t)_endpoint_info.account_id.size(), CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { + (const uint8_t *)_endpoint_info.account_id.c_str(), + (size_t)_endpoint_info.account_id.size(), CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { success = true; tr_info("ConnectorClient::create_register_object - aid from uri %s", _endpoint_info.account_id.c_str()); } else { @@ -807,7 +796,7 @@ void ConnectorClient::state_est_start() tr_debug("ConnectorClient::state_est_start - address: %s", address.c_str()); if (address.size() > 0) { const char *aid = NULL; - const int aid_size = parse_query_parameter_value_from_uri((const char*)address.c_str(), QUERY_PARAM_AID, &aid); + const int aid_size = parse_query_parameter_value_from_uri((const char *)address.c_str(), QUERY_PARAM_AID, &aid); if (aid_size > 0) { _endpoint_info.account_id.append_raw(aid, aid_size); } @@ -822,9 +811,9 @@ void ConnectorClient::state_est_start() // Check EST required parameters are in place if (m2m_id < 0 || - _endpoint_info.endpoint_name.length() <= 0 || - _endpoint_info.internal_endpoint_name.length() <= 0 || - _endpoint_info.account_id.length() <= 0) { + _endpoint_info.endpoint_name.length() <= 0 || + _endpoint_info.internal_endpoint_name.length() <= 0 || + _endpoint_info.account_id.length() <= 0) { tr_error("ConnectorClient::state_est_start - Missing parameters for EST enrollment!"); internal_event(State_EST_Failure); return; @@ -836,7 +825,7 @@ void ConnectorClient::state_est_start() size_t private_key_size = MAX_CERTIFICATE_SIZE; // Temp buffer for storing CSR and certificates - uint8_t *buffer = (uint8_t*)malloc(MAX_CERTIFICATE_SIZE); + uint8_t *buffer = (uint8_t *)malloc(MAX_CERTIFICATE_SIZE); size_t real_size = 0; if (buffer == NULL) { tr_error("ConnectorClient::state_est_start - Allocating temp buffer failed!"); @@ -878,7 +867,7 @@ void ConnectorClient::state_est_start() // For null-terminator subject_size++; - csr_params.subject = (char*)malloc(subject_size); + csr_params.subject = (char *)malloc(subject_size); if (csr_params.subject == NULL) { tr_error("ConnectorClient::state_est_start - CSR Subject formatting failed!"); free(buffer); @@ -900,7 +889,7 @@ void ConnectorClient::state_est_start() ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM); kcm_status_e status = kcm_generate_keys_and_csr(KCM_SCHEME_EC_SECP256R1, - (const uint8_t*)g_fcc_lwm2m_device_private_key_name, + (const uint8_t *)g_fcc_lwm2m_device_private_key_name, strlen(g_fcc_lwm2m_device_private_key_name), NULL, 0, @@ -984,16 +973,16 @@ void ConnectorClient::state_registration_success() //The endpoint is maximum 32 character long, we put bigger buffer for future extensions const int max_size = 64; uint8_t *buffer = NULL; - buffer = (uint8_t*)malloc(max_size); + buffer = (uint8_t *)malloc(max_size); - if(!buffer) { - _callback->registration_process_result(State_Registration_Failure); - return; + if (!buffer) { + _callback->registration_process_result(State_Registration_Failure); + return; } bool no_param_update = true; - if(ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { - if (strcmp((const char*)buffer, _endpoint_info.internal_endpoint_name.c_str()) != 0) { + if (ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { + if (strcmp((const char *)buffer, _endpoint_info.internal_endpoint_name.c_str()) != 0) { // Update is required as the stored KCM entry is different than _endpoint_info.internal_endpoint_name. no_param_update = false; } @@ -1002,11 +991,11 @@ void ConnectorClient::state_registration_success() // Update INTERNAL_ENDPOINT setting only if there is no such entry or the value is not matching the // _endpoint_info.internal_endpoint_name. - if(!no_param_update) { + if (!no_param_update) { ccs_delete_item(KEY_INTERNAL_ENDPOINT, CCS_CONFIG_ITEM); - ccs_set_item(KEY_INTERNAL_ENDPOINT, (const uint8_t*)_endpoint_info.internal_endpoint_name.c_str(), - (size_t)_endpoint_info.internal_endpoint_name.size(), - CCS_CONFIG_ITEM); + ccs_set_item(KEY_INTERNAL_ENDPOINT, (const uint8_t *)_endpoint_info.internal_endpoint_name.c_str(), + (size_t)_endpoint_info.internal_endpoint_name.size(), + CCS_CONFIG_ITEM); } _callback->registration_process_result(State_Registration_Success); } @@ -1028,7 +1017,7 @@ void ConnectorClient::bootstrap_data_ready(M2MSecurity *security_object) { #ifndef MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE tr_info("ConnectorClient::bootstrap_data_ready"); - if(security_object) { + if (security_object) { // Update bootstrap credentials (we could skip this if we knew whether they were updated) // This will also update the address in case of first to claim ccs_status_e status = set_bootstrap_credentials(security_object); @@ -1055,7 +1044,7 @@ void ConnectorClient::bootstrap_data_ready(M2MSecurity *security_object) #ifndef MBED_CLIENT_DISABLE_EST_FEATURE int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer); if (m2m_id >= 0 && - _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) == M2MSecurity::EST) { + _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) == M2MSecurity::EST) { // If EST is supported, continue to EST state to start EST enrollment tr_info("ConnectorClient::bootstrap_data_ready() - Continue to EST enrollment"); internal_event(State_EST_Start); @@ -1072,8 +1061,7 @@ void ConnectorClient::bootstrap_data_ready(M2MSecurity *security_object) //Failed to store credentials, bootstrap failed if (status == CCS_STATUS_MEMORY_ERROR) { _callback->connector_error(M2MInterface::MemoryFail, CONNECTOR_ERROR_NO_MEMORY); // Translated to error code ConnectMemoryConnectFail - } else - { + } else { _callback->connector_error(M2MInterface::FailedToStoreCredentials, CONNECTOR_ERROR_FAILED_TO_STORE_CREDENTIAL); // Translated to error code ConnectorFailedToStoreCredentials } return; @@ -1102,7 +1090,7 @@ void ConnectorClient::object_unregistered(M2MSecurity *server_object) internal_event(State_Unregistered); } -void ConnectorClient::registration_updated(M2MSecurity *security_object, const M2MServer & server_object) +void ConnectorClient::registration_updated(M2MSecurity *security_object, const M2MServer &server_object) { _callback->registration_process_result(State_Registration_Updated); } @@ -1113,9 +1101,9 @@ void ConnectorClient::error(M2MInterface::Error error) assert(_callback != NULL); #ifndef MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE if (_current_state >= State_Registration_Start && - use_bootstrap() && - (error == M2MInterface::SecureConnectionFailed || - error == M2MInterface::InvalidParameters)) { + use_bootstrap() && + (error == M2MInterface::SecureConnectionFailed || + error == M2MInterface::InvalidParameters)) { tr_info("ConnectorClient::error() - Error during lwm2m registration"); // Delete the lwm2m security instance @@ -1125,8 +1113,7 @@ void ConnectorClient::error(M2MInterface::Error error) } bootstrap_again(); - } - else { + } else { #endif _callback->connector_error(error, _interface->error_description()); #ifndef MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE @@ -1178,13 +1165,13 @@ bool ConnectorClient::use_bootstrap() bool ConnectorClient::get_key(const char *key, const char *endpoint, char *&key_name) { - if(key_name) { + if (key_name) { free(key_name); key_name = NULL; } - key_name = (char*)malloc(strlen(key)+strlen(endpoint)+1); - if(key_name) { + key_name = (char *)malloc(strlen(key) + strlen(endpoint) + 1); + if (key_name) { strcpy(key_name, key); strcat(key_name, endpoint); tr_debug("key %s", key_name); @@ -1205,7 +1192,7 @@ ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security) size_t buffer_size = MAX_CERTIFICATE_SIZE; uint8_t public_key[MAX_CERTIFICATE_SIZE]; - uint8_t *public_key_ptr = (uint8_t*)&public_key; + uint8_t *public_key_ptr = (uint8_t *)&public_key; // TODO! Update to use chain api if (security->resource_value_buffer(M2MSecurity::PublicKey, public_key_ptr, m2m_id, &buffer_size) != 0) { @@ -1218,7 +1205,7 @@ ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security) tr_info("ConnectorClient::set_connector_credentials - L internal_endpoint_name : %s", device_id); _endpoint_info.internal_endpoint_name = String(device_id); ccs_delete_item(KEY_INTERNAL_ENDPOINT, CCS_CONFIG_ITEM); - status = ccs_set_item(KEY_INTERNAL_ENDPOINT,(uint8_t*)device_id, strlen(device_id), CCS_CONFIG_ITEM); + status = ccs_set_item(KEY_INTERNAL_ENDPOINT, (uint8_t *)device_id, strlen(device_id), CCS_CONFIG_ITEM); } memset(device_id, 0, 64); @@ -1227,12 +1214,12 @@ ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security) _endpoint_info.endpoint_name = String(device_id); } - if(status == CCS_STATUS_SUCCESS) { + if (status == CCS_STATUS_SUCCESS) { ccs_delete_item(KEY_ACCOUNT_ID, CCS_CONFIG_ITEM); // AccountID optional so don't fail if unable to store - if (_endpoint_info.account_id.size() != 0 && _endpoint_info.account_id.c_str() != NULL){ + if (_endpoint_info.account_id.size() != 0 && _endpoint_info.account_id.c_str() != NULL) { ccs_set_item(KEY_ACCOUNT_ID, - (const uint8_t*)_endpoint_info.account_id.c_str(), + (const uint8_t *)_endpoint_info.account_id.c_str(), (size_t)_endpoint_info.account_id.size(), CCS_CONFIG_ITEM); } @@ -1244,9 +1231,9 @@ ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security) #endif ccs_delete_item(g_fcc_lwm2m_server_uri_name, CCS_CONFIG_ITEM); status = ccs_set_item(g_fcc_lwm2m_server_uri_name, - (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).c_str(), - (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).size(), - CCS_CONFIG_ITEM); + (const uint8_t *)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).c_str(), + (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).size(), + CCS_CONFIG_ITEM); } M2MDevice *device = M2MInterfaceFactory::create_device(); @@ -1261,18 +1248,17 @@ ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security) temp = device->resource_value_string(M2MDevice::Timezone, 0); if (temp.size() > 0) { ccs_delete_item(g_fcc_device_time_zone_parameter_name, CCS_CONFIG_ITEM); - ccs_set_item(g_fcc_device_time_zone_parameter_name, (const uint8_t*)temp.c_str(), temp.size(), CCS_CONFIG_ITEM); + ccs_set_item(g_fcc_device_time_zone_parameter_name, (const uint8_t *)temp.c_str(), temp.size(), CCS_CONFIG_ITEM); } temp = device->resource_value_string(M2MDevice::UTCOffset, 0); if (temp.size() > 0) { ccs_delete_item(g_fcc_offset_from_utc_parameter_name, CCS_CONFIG_ITEM); - ccs_set_item(g_fcc_offset_from_utc_parameter_name, (const uint8_t*)temp.c_str(), temp.size(), CCS_CONFIG_ITEM); + ccs_set_item(g_fcc_offset_from_utc_parameter_name, (const uint8_t *)temp.c_str(), temp.size(), CCS_CONFIG_ITEM); } status = CCS_STATUS_SUCCESS; - } - else { + } else { tr_debug("No device object to store!"); } @@ -1287,7 +1273,7 @@ ccs_status_e ConnectorClient::set_bootstrap_credentials(M2MSecurity *security) size_t uri_size = MAX_CERTIFICATE_SIZE; uint8_t bootstrap_uri[MAX_CERTIFICATE_SIZE]; - uint8_t *bootstrap_uri_ptr = (uint8_t*)&bootstrap_uri; + uint8_t *bootstrap_uri_ptr = (uint8_t *)&bootstrap_uri; int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap); if (bs_id == -1) { @@ -1302,13 +1288,13 @@ ccs_status_e ConnectorClient::set_bootstrap_credentials(M2MSecurity *security) // Update BS uri only if it has changed. // If uri is missing or some other error while reading the item --> return error. if (ccs_get_string_item(g_fcc_bootstrap_server_uri_name, bootstrap_uri_ptr, uri_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) { - if (strcmp((const char*)bootstrap_uri_ptr, bs_uri.c_str()) != 0) { - tr_info("ConnectorClient::set_bootstrap_credentials - update uri from: %s to: %s", (char*)bootstrap_uri_ptr, bs_uri.c_str()); + if (strcmp((const char *)bootstrap_uri_ptr, bs_uri.c_str()) != 0) { + tr_info("ConnectorClient::set_bootstrap_credentials - update uri from: %s to: %s", (char *)bootstrap_uri_ptr, bs_uri.c_str()); ccs_delete_item(g_fcc_bootstrap_server_uri_name, CCS_CONFIG_ITEM); status = ccs_set_item(g_fcc_bootstrap_server_uri_name, - (const uint8_t*)bs_uri.c_str(), - strlen(bs_uri.c_str()), - CCS_CONFIG_ITEM); + (const uint8_t *)bs_uri.c_str(), + strlen(bs_uri.c_str()), + CCS_CONFIG_ITEM); } else { status = CCS_STATUS_SUCCESS; } @@ -1362,12 +1348,10 @@ bool ConnectorClient::is_first_to_claim() void ConnectorClient::timer_expired(M2MTimerObserver::Type type) { if (type == M2MTimerObserver::StaggerWaitTimer) { - bool credentials_ready = connector_credentials_available(); - bool bootstrap = use_bootstrap(); - if (credentials_ready || !bootstrap) { + if (bootstrapped()) { if (_do_full_registration) { _interface->register_object(_security, *_client_objs, true); - } else{ + } else { _interface->register_object(_security, *_client_objs); } } else { @@ -1392,7 +1376,7 @@ void ConnectorClient::est_enrollment_result(est_enrollment_result_e result, tr_debug("ConnectorClient::est_enrollment_result - PublicKey size %d", cert_chain->chain_length); } - ConnectorClient *cc = static_cast(context); + ConnectorClient *cc = static_cast(context); assert(cc); assert(cc->_security != NULL); @@ -1400,17 +1384,16 @@ void ConnectorClient::est_enrollment_result(est_enrollment_result_e result, StartupSubStateRegistration state = State_EST_Failure; if (result == EST_ENROLLMENT_SUCCESS && - m2m_id >= 0 && - cert_chain != NULL && - cert_chain->chain_length > 0) - { + m2m_id >= 0 && + cert_chain != NULL && + cert_chain->chain_length > 0) { kcm_cert_chain_handle chain_handle; kcm_status_e status = kcm_cert_chain_create(&chain_handle, - (const uint8_t*)g_fcc_lwm2m_device_certificate_name, - strlen(g_fcc_lwm2m_device_certificate_name), - cert_chain->chain_length, - false); + (const uint8_t *)g_fcc_lwm2m_device_certificate_name, + strlen(g_fcc_lwm2m_device_certificate_name), + cert_chain->chain_length, + false); tr_debug("Cert chain create %d", status); if (status == KCM_STATUS_SUCCESS) { cert_context_s *cert = cert_chain->certs; @@ -1432,8 +1415,7 @@ void ConnectorClient::est_enrollment_result(est_enrollment_result_e result, if (cc->set_connector_credentials(cc->_security) == CCS_STATUS_SUCCESS) { state = State_EST_Success; } - } - else { + } else { tr_error("ConnectorClient::est_enrollment_result - storing certificate chain failed!"); } } @@ -1468,7 +1450,7 @@ void ConnectorClient::init_security_object() for (int i = 0; i <= M2MSecurity::Bootstrap; i++) { // _security->create_object_instance() returns NULL if object already exists if (_security->create_object_instance((M2MSecurity::ServerType)i)) { - M2MResource* res = _security->get_resource(M2MSecurity::ServerPublicKey, i); + M2MResource *res = _security->get_resource(M2MSecurity::ServerPublicKey, i); if (res) { res->set_read_resource_function(read_security_object_data_from_kcm, this); res->set_resource_read_size_callback(read_security_object_data_size_from_kcm, this); @@ -1527,9 +1509,13 @@ void ConnectorClient::external_update(uint32_t start_address, uint32_t firmware_ void ConnectorClient::resume() { - uint16_t delay = _interface->stagger_wait_time(true); - tr_info("ConnectorClient::resume() - resume after %d seconds", delay); - _stagger_timer->start_timer(delay * 1000, M2MTimerObserver::StaggerWaitTimer); + if (bootstrapped()) { + uint16_t delay = _interface->stagger_wait_time(true); + tr_info("ConnectorClient::resume() - resume after %d seconds", delay); + _stagger_timer->start_timer(delay * 1000, M2MTimerObserver::StaggerWaitTimer); + } else { + start_bootstrap(); + } } void ConnectorClient::factory_reset_credentials() @@ -1554,7 +1540,7 @@ void ConnectorClient::bootstrap_again() ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM); // delete the old session id - static const char* kcm_session_item_name = "sslsession"; + static const char *kcm_session_item_name = "sslsession"; ccs_delete_item(kcm_session_item_name, CCS_CONFIG_ITEM); tr_error("ConnectorClient::bootstrap_again in %d seconds", _rebootstrap_time); @@ -1572,3 +1558,22 @@ void ConnectorClient::bootstrap_again() } #endif //MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + +void ConnectorClient::paused() +{ + _callback->registration_process_result(ConnectorClient::State_Paused); +} + +void ConnectorClient::alert_mode() +{ + _callback->registration_process_result(ConnectorClient::State_Alert_Mode); +} + +bool ConnectorClient::bootstrapped() +{ + if (connector_credentials_available() || !use_bootstrap()) { + return true; + } else { + return false; + } +} diff --git a/source/MbedCloudClient.cpp b/source/MbedCloudClient.cpp index 4ddc700d4..c7334faf1 100755 --- a/source/MbedCloudClient.cpp +++ b/source/MbedCloudClient.cpp @@ -18,7 +18,6 @@ #include "mbed-cloud-client/MbedCloudClientConfig.h" #include "mbed-cloud-client/MbedCloudClient.h" -#include "mbed-cloud-client/SimpleM2MResource.h" #include "pal.h" #include "mbed-trace/mbed_trace.h" @@ -34,10 +33,10 @@ #define TRACE_GROUP "mClt" MbedCloudClient::MbedCloudClient() -:_client(*this), - _value_callback(NULL), - _error_description(NULL), - _init_done(false) + : _client(*this), + _value_callback(NULL), + _error_description(NULL), + _init_done(false) { } @@ -45,15 +44,15 @@ MbedCloudClient::MbedCloudClient(void(*on_registered_cb)(void), void(*on_unregistered_cb)(void), void(*on_error_cb)(int) #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE - ,void(*on_update_authorize_cb)(int32_t request), + , void(*on_update_authorize_cb)(int32_t request), void(*on_update_progress_cb)(uint32_t progress, uint32_t total) #endif ) -:_client(*this), - _value_callback(NULL), - _error_description(NULL), - _init_done(false) + : _client(*this), + _value_callback(NULL), + _error_description(NULL), + _init_done(false) { this->on_registered(on_registered_cb); this->on_unregistered(on_unregistered_cb); @@ -64,28 +63,49 @@ MbedCloudClient::MbedCloudClient(void(*on_registered_cb)(void), #endif } +MbedCloudClient::MbedCloudClient(void(*on_status_changed_cb)(int), + void(*on_error_cb)(int) +#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE + , void(*on_update_authorize_cb)(int32_t request), + void(*on_update_progress_cb)(uint32_t progress, uint32_t total) +#endif + ) + + : _client(*this), + _value_callback(NULL), + _error_description(NULL), + _init_done(false) +{ + this->on_status_changed(on_status_changed_cb); + this->on_error(on_error_cb); +#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE + this->set_update_authorize_handler(on_update_authorize_cb); + this->set_update_progress_handler(on_update_progress_cb); +#endif +} + MbedCloudClient::~MbedCloudClient() { _object_list.clear(); } -void MbedCloudClient::add_objects(const M2MObjectList& object_list) +void MbedCloudClient::add_objects(const M2MObjectList &object_list) { - if(!object_list.empty()) { + if (!object_list.empty()) { M2MObjectList::const_iterator it; it = object_list.begin(); - for (; it!= object_list.end(); it++) { - _object_list.push_back((M2MBase*)*it); + for (; it != object_list.end(); it++) { + _object_list.push_back((M2MBase *)*it); } } } -void MbedCloudClient::add_objects(const M2MBaseList& base_list) +void MbedCloudClient::add_objects(const M2MBaseList &base_list) { - if(!base_list.empty()) { + if (!base_list.empty()) { M2MBaseList::const_iterator it; it = base_list.begin(); - for (; it!= base_list.end(); it++) { + for (; it != base_list.end(); it++) { _object_list.push_back(*it); } } @@ -101,7 +121,7 @@ void MbedCloudClient::remove_object(M2MBase *object) int index; tr_debug("MbedCloudClient::remove_object %p", object); for (it = _object_list.begin(), index = 0; it != _object_list.end(); it++, index++) { - if(*it == object) { + if (*it == object) { found_index = index; break; } @@ -134,19 +154,10 @@ bool MbedCloudClient::init() return _init_done; } -bool MbedCloudClient::setup(void* iface) +bool MbedCloudClient::setup(void *iface) { tr_debug("MbedCloudClient setup()"); - // Add objects to list -#if MBED_CLOUD_CLIENT_STL_API - map::iterator it; - for (it = _objects.begin(); it != _objects.end(); it++) - { - _object_list.push_back((M2MBase*)it->second); - } -#endif - if (!init()) { return false; } @@ -169,6 +180,11 @@ void MbedCloudClient::on_error(void(*fn)(int)) _on_error = fn; } +void MbedCloudClient::on_status_changed(void(*fn)(int)) +{ + _on_status_changed = fn; +} + #ifdef MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE void MbedCloudClient::on_external_update(void(*fn)(uint32_t, uint32_t)) { @@ -248,20 +264,6 @@ void MbedCloudClient::set_entropy_callback(entropy_cb callback) } } -#if MBED_CLOUD_CLIENT_STL_API -bool MbedCloudClient::set_device_resource_value(M2MDevice::DeviceResource resource, - const std::string &value) -{ - return _client.set_device_resource_value(resource, value); -} - -void MbedCloudClient::register_update_callback(string route, - SimpleM2MResourceBase* resource) -{ - _update_values[route] = resource; -} -#endif // MBED_CLOUD_CLIENT_STL_API - #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE void MbedCloudClient::set_update_authorize_handler(void (*handler)(int32_t request)) { @@ -294,19 +296,25 @@ const char *MbedCloudClient::error_description() const return _error_description; } - void MbedCloudClient::complete(ServiceClientCallbackStatus status) { tr_info("MbedCloudClient::complete status (%d)", status); if (status == Service_Client_Status_Registered) { _on_registered.call(); + _on_status_changed.call(Registered); } else if (status == Service_Client_Status_Unregistered) { _object_list.clear(); _on_unregistered.call(); + _on_status_changed.call(Unregistered); } else if (status == Service_Client_Status_Register_Updated) { _on_registration_updated.call(); + _on_status_changed.call(RegistrationUpdated); + } else if (status == Service_Client_Status_Paused) { + _on_status_changed.call(Paused); + } else if (status == Service_Client_Status_Alert_Mode) { + _on_status_changed.call(AlertMode); } - // ToDo: should we have some handling for Service_Client_Status_Failure + // ToDo: should we have some handling for Service_Client_Status_Failure } void MbedCloudClient::error(int error, const char *reason) @@ -321,17 +329,9 @@ void MbedCloudClient::value_updated(M2MBase *base, M2MBase::BaseType type) if (base) { tr_info("MbedCloudClient::value_updated path %s", base->uri_path()); if (base->uri_path()) { -#if MBED_CLOUD_CLIENT_STL_API - if (_update_values.count(base->uri_path()) != 0) { - tr_debug("MbedCloudClient::value_updated calling update() for %s", base->uri_path()); - _update_values[base->uri_path()]->update(); - } else -#endif - { - // way to tell application that there is a value update - if (_value_callback) { - _value_callback->value_updated(base, type); - } + // way to tell application that there is a value update + if (_value_callback) { + _value_callback->value_updated(base, type); } } } @@ -349,12 +349,12 @@ void MbedCloudClient::send_get_request(DownloadType type, if (success) { _client.connector_client().m2m_interface()->get_data_request(type, - uri, - offset, - true, - data_cb, - error_cb, - context); + uri, + offset, + true, + data_cb, + error_cb, + context); } } @@ -371,7 +371,7 @@ void MbedCloudClient::on_certificate_renewal(cert_renewal_cb_f user_cb) #endif // MBED_CONF_MBED_CLOUD_CLIENT_DISABLE_CERTIFICATE_ENROLLMENT #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION -const M2MBaseList* MbedCloudClient::get_object_list() const +const M2MBaseList *MbedCloudClient::get_object_list() const { return &_object_list; } @@ -398,6 +398,16 @@ void MbedCloudClient::resume(void *iface) } } +void MbedCloudClient::alert() +{ + // finish the ServiceClient's initialization and M2MInterface + bool success = _client.connector_client().setup(); + + if (success) { + _client.connector_client().m2m_interface()->alert(); + } +} + #ifdef MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE void MbedCloudClient::external_update(uint32_t start_address, uint32_t size) { diff --git a/source/ServiceClient.cpp b/source/ServiceClient.cpp index 6d0392812..f3a97fb99 100644 --- a/source/ServiceClient.cpp +++ b/source/ServiceClient.cpp @@ -37,7 +37,7 @@ #include "mbed-trace/mbed_trace.h" #include "pal.h" #include "ns_hal_init.h" -#include "fota/fota_app_ifs.h" +#include "fota/fota_internal_ifs.h" #include "mbed-cloud-client/MbedCloudClientConfig.h" #ifndef MBED_CONF_MBED_CLOUD_CLIENT_DISABLE_CERTIFICATE_ENROLLMENT @@ -57,10 +57,6 @@ #endif #endif // MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE -#if MBED_CLOUD_CLIENT_STL_API -#include -#endif - #include #include @@ -75,22 +71,22 @@ const uint8_t ServiceClient::hex_table[16] = { '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; -ServiceClient::ServiceClient(ServiceClientCallback& callback) -: _service_callback(callback), - _service_uri(NULL), - _stack(NULL), - _client_objs(NULL), - _current_state(State_Init), - _event_generated(false), - _state_engine_running(false), +ServiceClient::ServiceClient(ServiceClientCallback &callback) + : _service_callback(callback), + _service_uri(NULL), + _stack(NULL), + _client_objs(NULL), + _current_state(State_Init), + _event_generated(false), + _state_engine_running(false), #if defined(MBED_CLOUD_CLIENT_SUPPORT_UPDATE) && !defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) - _uc_hub_tasklet_id(-1), - _setup_update_client(false), + _uc_hub_tasklet_id(-1), + _setup_update_client(false), #endif #ifdef SERVICE_CLIENT_SUPPORT_MULTICAST - _multicast_tasklet_id(-1), + _multicast_tasklet_id(-1), #endif // MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE - _connector_client(this) + _connector_client(this) { } @@ -120,20 +116,20 @@ bool ServiceClient::init() // as it will also initialize the tasklet. ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL); #if defined(MBED_CLOUD_CLIENT_SUPPORT_UPDATE) && !defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) + if (_uc_hub_tasklet_id < 0) { + _uc_hub_tasklet_id = eventOS_event_handler_create(UpdateClient::event_handler, UpdateClient::UPDATE_CLIENT_EVENT_CREATE); if (_uc_hub_tasklet_id < 0) { - _uc_hub_tasklet_id = eventOS_event_handler_create(UpdateClient::event_handler, UpdateClient::UPDATE_CLIENT_EVENT_CREATE); - if (_uc_hub_tasklet_id < 0) { - tr_error("ServiceClient::init - failed to create uc hub event handler (%d)", _uc_hub_tasklet_id); - _service_callback.error((int)UpdateClient::WarningUnknown, "Failed to create event handler"); - return false; - } - } -#ifdef SERVICE_CLIENT_SUPPORT_MULTICAST - if (ARM_UC_HUB_createEventHandler() < 0) { - tr_error("ServiceClient::init - failed to create uc hub multicast event handler"); + tr_error("ServiceClient::init - failed to create uc hub event handler (%d)", _uc_hub_tasklet_id); _service_callback.error((int)UpdateClient::WarningUnknown, "Failed to create event handler"); return false; } + } +#ifdef SERVICE_CLIENT_SUPPORT_MULTICAST + if (ARM_UC_HUB_createEventHandler() < 0) { + tr_error("ServiceClient::init - failed to create uc hub multicast event handler"); + _service_callback.error((int)UpdateClient::WarningUnknown, "Failed to create event handler"); + return false; + } #endif // SERVICE_CLIENT_SUPPORT_MULTICAST #endif // defined(MBED_CLOUD_CLIENT_SUPPORT_UPDATE) && !defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) #ifdef SERVICE_CLIENT_SUPPORT_MULTICAST @@ -152,12 +148,12 @@ bool ServiceClient::init() return true; } -void ServiceClient::initialize_and_register(M2MBaseList& reg_objs) +void ServiceClient::initialize_and_register(M2MBaseList ®_objs) { tr_debug("ServiceClient::initialize_and_register"); - if(_current_state == State_Init || - _current_state == State_Unregister || - _current_state == State_Failure) { + if (_current_state == State_Init || + _current_state == State_Unregister || + _current_state == State_Failure) { _client_objs = ®_objs; #if defined(MBED_CLOUD_CLIENT_SUPPORT_UPDATE) && !defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) @@ -168,7 +164,7 @@ void ServiceClient::initialize_and_register(M2MBaseList& reg_objs) return; } #endif - if(!_setup_update_client) { + if (!_setup_update_client) { _setup_update_client = true; #ifdef MBED_CLOUD_DEV_UPDATE_ID @@ -181,14 +177,14 @@ void ServiceClient::initialize_and_register(M2MBaseList& reg_objs) ccs_delete_item("mbed.VendorId", CCS_CONFIG_ITEM); /* Store Vendor Id to mbed.VendorId. No conversion is performed. */ set_device_resource_value(M2MDevice::Manufacturer, - (const char*) arm_uc_vendor_id, + (const char *) arm_uc_vendor_id, arm_uc_vendor_id_size); /* Delete ClassId */ ccs_delete_item("mbed.ClassId", CCS_CONFIG_ITEM); /* Store Class Id to mbed.ClassId. No conversion is performed. */ set_device_resource_value(M2MDevice::ModelNumber, - (const char*) arm_uc_class_id, + (const char *) arm_uc_class_id, arm_uc_class_id_size); #endif /* MBED_CLOUD_DEV_UPDATE_ID */ @@ -211,7 +207,7 @@ void ServiceClient::initialize_and_register(M2MBaseList& reg_objs) /* insert value from Update Client Common */ ccs_set_item(KEY_DEVICE_SOFTWAREVERSION, - (const uint8_t*) ARM_UPDATE_CLIENT_VERSION, + (const uint8_t *) ARM_UPDATE_CLIENT_VERSION, sizeof(ARM_UPDATE_CLIENT_VERSION), CCS_CONFIG_ITEM); } @@ -255,26 +251,26 @@ void ServiceClient::finish_initialization(void) M2MDevice *device_object = device_object_from_storage(); #ifndef MBED_CONF_MBED_CLOUD_CLIENT_DISABLE_CERTIFICATE_ENROLLMENT - // Initialize the certificate enrollment resources and module - if (CertificateEnrollmentClient::init(*_client_objs, &_connector_client.est_client()) != CE_STATUS_SUCCESS) { - _service_callback.error((int)CE_STATUS_INIT_FAILED, "Certificate Enrollment initialization failed"); - } + // Initialize the certificate enrollment resources and module + if (CertificateEnrollmentClient::init(*_client_objs, &_connector_client.est_client()) != CE_STATUS_SUCCESS) { + _service_callback.error((int)CE_STATUS_INIT_FAILED, "Certificate Enrollment initialization failed"); + } #endif /* !MBED_CONF_MBED_CLOUD_CLIENT_DISABLE_CERTIFICATE_ENROLLMENT */ #ifdef MBED_CONF_MBED_CLOUD_CLIENT_ENABLE_DEVICE_SENTRY // Initialize the device sentry feature if (DeviceSentryClient::init(*_client_objs) != DS_STATUS_SUCCESS) { - _service_callback.error((int)DS_STATUS_INIT_FAILED, "Device Sentry initialization failed"); + _service_callback.error((int)DS_STATUS_INIT_FAILED, "Device Sentry initialization failed"); } #endif /* MBED_CONF_MBED_CLOUD_CLIENT_ENABLE_DEVICE_SENTRY */ if (device_object) { /* Publish device object resource to mds */ M2MResourceList list = device_object->object_instance()->resources(); - if(!list.empty()) { + if (!list.empty()) { M2MResourceList::const_iterator it; it = list.begin(); - for ( ; it != list.end(); it++ ) { + for (; it != list.end(); it++) { (*it)->set_register_uri(true); } } @@ -388,22 +384,44 @@ void ServiceClient::state_register() void ServiceClient::registration_process_result(ConnectorClient::StartupSubStateRegistration status) { tr_debug("ServiceClient::registration_process_result(): status: %d", status); - if (status == ConnectorClient::State_Registration_Success) { + switch (status) { + case ConnectorClient::State_Registration_Success: #if defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) - fota_app_resume(); + fota_internal_resume(); #endif - internal_event(State_Success); - } else if (status == ConnectorClient::State_Registration_Failure || status == ConnectorClient::State_Bootstrap_Failure) { - internal_event(State_Failure); - } else if (status == ConnectorClient::State_Bootstrap_Success) { - internal_event(State_Register); - } else if (status == ConnectorClient::State_Unregistered) { - internal_event(State_Unregister); - } else if (status == ConnectorClient::State_Registration_Updated) { + internal_event(State_Success); + break; + case ConnectorClient::State_Registration_Failure: + case ConnectorClient::State_Bootstrap_Failure: + internal_event(State_Failure); + break; + + case ConnectorClient::State_Bootstrap_Success: + internal_event(State_Register); + break; + + case ConnectorClient::State_Unregistered: + internal_event(State_Unregister); + break; + + case ConnectorClient::State_Registration_Updated: #if defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) - fota_app_resume(); + fota_internal_resume(); #endif - _service_callback.complete(ServiceClientCallback::Service_Client_Status_Register_Updated); + _service_callback.complete(ServiceClientCallback::Service_Client_Status_Register_Updated); + break; + + case ConnectorClient::State_Paused: + _service_callback.complete(ServiceClientCallback::Service_Client_Status_Paused); + break; + + case ConnectorClient::State_Alert_Mode: + _service_callback.complete(ServiceClientCallback::Service_Client_Status_Alert_Mode); + break; + + default: + tr_error("ServiceClient::registration_process_result(): unknown status"); + break; } } @@ -420,8 +438,8 @@ void ServiceClient::connector_error(M2MInterface::Error error, const char *reaso // Client is in State_Failure and failing to bootstrap on InvalidCertificates. // Factory reset the credentials to clear invalid/broken certificates and try again. else if (_current_state == State_Failure && (error == M2MInterface::InvalidCertificates - || error == M2MInterface::FailedToStoreCredentials - || error == M2MInterface::FailedToReadCredentials)) { + || error == M2MInterface::FailedToStoreCredentials + || error == M2MInterface::FailedToReadCredentials)) { _connector_client.factory_reset_credentials(); _connector_client.bootstrap_again(); } @@ -434,7 +452,7 @@ void ServiceClient::connector_error(M2MInterface::Error error, const char *reaso else { internal_event(State_Failure); } - _service_callback.error(int(error),reason); + _service_callback.error(int(error), reason); } void ServiceClient::value_updated(M2MBase *base, M2MBase::BaseType type) @@ -477,14 +495,14 @@ void ServiceClient::state_unregister() _service_callback.complete(ServiceClientCallback::Service_Client_Status_Unregistered); } -M2MDevice* ServiceClient::device_object_from_storage() +M2MDevice *ServiceClient::device_object_from_storage() { M2MDevice *device_object = M2MInterfaceFactory::create_device(); if (device_object == NULL) { return NULL; } - M2MObjectInstance* instance = device_object->object_instance(0); - if(instance == NULL) { + M2MObjectInstance *instance = device_object->object_instance(0); + if (instance == NULL) { return NULL; } @@ -497,39 +515,39 @@ M2MDevice* ServiceClient::device_object_from_storage() // create_resource() function returns NULL if resource already exists ccs_status_e status = ccs_get_item(g_fcc_manufacturer_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM); if (status == CCS_STATUS_SUCCESS) { - const String data((char*)buffer, size); + const String data((char *)buffer, size); res = device_object->create_resource(M2MDevice::Manufacturer, data); if (res == NULL) { res = instance->resource(DEVICE_MANUFACTURER); device_object->set_resource_value(M2MDevice::Manufacturer, data); } - if(res) { + if (res) { res->publish_value_in_registration_msg(true); res->set_auto_observable(true); } } status = ccs_get_item(g_fcc_model_number_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM); if (status == CCS_STATUS_SUCCESS) { - const String data((char*)buffer, size); + const String data((char *)buffer, size); res = device_object->create_resource(M2MDevice::ModelNumber, data); if (res == NULL) { res = instance->resource(DEVICE_MODEL_NUMBER); device_object->set_resource_value(M2MDevice::ModelNumber, data); } - if(res) { + if (res) { res->publish_value_in_registration_msg(true); res->set_auto_observable(true); } } status = ccs_get_item(g_fcc_device_serial_number_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM); if (status == CCS_STATUS_SUCCESS) { - const String data((char*)buffer, size); + const String data((char *)buffer, size); res = device_object->create_resource(M2MDevice::SerialNumber, data); if (res == NULL) { res = instance->resource(DEVICE_SERIAL_NUMBER); device_object->set_resource_value(M2MDevice::SerialNumber, data); } - if(res) { + if (res) { res->publish_value_in_registration_msg(true); res->set_auto_observable(true); } @@ -537,7 +555,7 @@ M2MDevice* ServiceClient::device_object_from_storage() status = ccs_get_item(g_fcc_device_type_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM); if (status == CCS_STATUS_SUCCESS) { - const String data((char*)buffer, size); + const String data((char *)buffer, size); res = device_object->create_resource(M2MDevice::DeviceType, data); if (res == NULL) { (void)instance->resource(DEVICE_DEVICE_TYPE); @@ -547,7 +565,7 @@ M2MDevice* ServiceClient::device_object_from_storage() status = ccs_get_item(g_fcc_hardware_version_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM); if (status == CCS_STATUS_SUCCESS) { - const String data((char*)buffer, size); + const String data((char *)buffer, size); res = device_object->create_resource(M2MDevice::HardwareVersion, data); if (res == NULL) { (void)instance->resource(DEVICE_HARDWARE_VERSION); @@ -557,7 +575,7 @@ M2MDevice* ServiceClient::device_object_from_storage() status = ccs_get_item(KEY_DEVICE_SOFTWAREVERSION, buffer, buffer_size, &size, CCS_CONFIG_ITEM); if (status == CCS_STATUS_SUCCESS) { - const String data((char*)buffer, size); + const String data((char *)buffer, size); res = device_object->create_resource(M2MDevice::SoftwareVersion, data); if (res == NULL) { (void)instance->resource(DEVICE_SOFTWARE_VERSION); @@ -591,9 +609,9 @@ M2MDevice* ServiceClient::device_object_from_storage() status = ccs_get_item(g_fcc_device_time_zone_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM); if (status == CCS_STATUS_SUCCESS) { - const String data((char*)buffer, size); + const String data((char *)buffer, size); res = device_object->create_resource(M2MDevice::Timezone, data); - if ( res == NULL) { + if (res == NULL) { (void)instance->resource(DEVICE_TIMEZONE); device_object->set_resource_value(M2MDevice::Timezone, data); } @@ -601,7 +619,7 @@ M2MDevice* ServiceClient::device_object_from_storage() status = ccs_get_item(g_fcc_offset_from_utc_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM); if (status == CCS_STATUS_SUCCESS) { - const String data((char*)buffer, size); + const String data((char *)buffer, size); res = device_object->create_resource(M2MDevice::UTCOffset, data); if (res == NULL) { (void)instance->resource(DEVICE_UTC_OFFSET); @@ -611,9 +629,9 @@ M2MDevice* ServiceClient::device_object_from_storage() String binding_mode; M2MInterface::BindingMode mode = _connector_client.transport_mode(); if (mode == M2MInterface::UDP || mode == M2MInterface::TCP) { - binding_mode = (char*)BINDING_MODE_UDP; + binding_mode = (char *)BINDING_MODE_UDP; } else if (mode == M2MInterface::UDP_QUEUE || mode == M2MInterface::TCP_QUEUE) { - binding_mode = (char*)BINDING_MODE_UDP_QUEUE; + binding_mode = (char *)BINDING_MODE_UDP_QUEUE; } device_object->set_resource_value(M2MDevice::SupportedBindingMode, binding_mode); @@ -628,23 +646,6 @@ M2MDevice* ServiceClient::device_object_from_storage() return device_object; } -/** - * \brief Set resource value in the Device Object - * - * \param resource Device enum to have value set. - * \param value String object. - * \return True if successful, false otherwise. - */ -#if MBED_CLOUD_CLIENT_STL_API -bool ServiceClient::set_device_resource_value(M2MDevice::DeviceResource resource, - const std::string& value) -{ - return set_device_resource_value(resource, - value.c_str(), - value.size()); -} -#endif - /** * \brief Set resource value in the Device Object * @@ -654,24 +655,23 @@ bool ServiceClient::set_device_resource_value(M2MDevice::DeviceResource resource * \return True if successful, false otherwise. */ bool ServiceClient::set_device_resource_value(M2MDevice::DeviceResource resource, - const char* value, + const char *value, uint32_t length) { bool retval = false; /* sanity check */ - if (value && (length < 256) && (length > 0)) - { + if (value && (length < 256) && (length > 0)) { #if defined(MBED_CLOUD_CLIENT_SUPPORT_UPDATE) && !defined(MBED_CLOUD_CLIENT_FOTA_ENABLE) /* Pass resource value to Update Client. Used for validating the manifest. */ switch (resource) { case M2MDevice::Manufacturer: - ARM_UC_SetVendorId((const uint8_t*) value, length); + ARM_UC_SetVendorId((const uint8_t *) value, length); break; case M2MDevice::ModelNumber: - ARM_UC_SetClassId((const uint8_t*) value, length); + ARM_UC_SetClassId((const uint8_t *) value, length); break; default: break; @@ -682,18 +682,18 @@ bool ServiceClient::set_device_resource_value(M2MDevice::DeviceResource resource return retval; } -void ServiceClient::post_response_status_handler(const M2MBase& base, +void ServiceClient::post_response_status_handler(const M2MBase &base, const M2MBase::MessageDeliveryStatus status, const M2MBase::MessageType type, - void* me) + void *me) { - switch(status) { + switch (status) { case M2MBase::MESSAGE_STATUS_DELIVERED: // intentional fall-through case M2MBase::MESSAGE_STATUS_SEND_FAILED: { - M2MDevice* dev = M2MInterfaceFactory::create_device(); + M2MDevice *dev = M2MInterfaceFactory::create_device(); if (dev != NULL && dev->object_instance(0) != NULL && - &base == dev->object_instance(0)->resource(DEVICE_REBOOT)) { - ((ServiceClient*)me)->m2mdevice_reboot_execute(); + &base == dev->object_instance(0)->resource(DEVICE_REBOOT)) { + ((ServiceClient *)me)->m2mdevice_reboot_execute(); } break; } @@ -702,7 +702,7 @@ void ServiceClient::post_response_status_handler(const M2MBase& base, } } -void ServiceClient::reboot_execute_handler(void*) +void ServiceClient::reboot_execute_handler(void *) { // Don't perform reboot yet, as server will not get response. Instead, send response and wait // for acknowledgement before rebooting. diff --git a/source/SimpleM2MResource.cpp b/source/SimpleM2MResource.cpp deleted file mode 100644 index e6854a762..000000000 --- a/source/SimpleM2MResource.cpp +++ /dev/null @@ -1,324 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright 2016-2017 ARM Ltd. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ---------------------------------------------------------------------------- - -#include "mbed-cloud-client/SimpleM2MResource.h" - -#if MBED_CLOUD_CLIENT_STL_API - -#include "mbed-trace/mbed_trace.h" - -#include -#include - -#define TRACE_GROUP "mClt" - - -SimpleM2MResourceBase::SimpleM2MResourceBase() -: _client(NULL), _route("") -{ - tr_debug("SimpleM2MResourceBase::SimpleM2MResourceBase()"); -} - -SimpleM2MResourceBase::SimpleM2MResourceBase(MbedCloudClient* client, string route) -: _client(client),_route(route) -{ - tr_debug("SimpleM2MResourceBase::SimpleM2MResourceBase(), resource name %s\r\n", _route.c_str()); -} - -SimpleM2MResourceBase::~SimpleM2MResourceBase() -{ -} - -bool SimpleM2MResourceBase::define_resource_internal(std::string v, M2MBase::Operation opr, bool observable) -{ - tr_debug("SimpleM2MResourceBase::define_resource_internal(), resource name %s!\r\n", _route.c_str()); - - vector segments = parse_route(_route.c_str()); - if (segments.size() != 3) { - tr_debug("[SimpleM2MResourceBase] [ERROR] define_resource_internal(), Route needs to have three segments, split by '/' (%s)\r\n", _route.c_str()); - return false; - } - - // segments[1] should be one digit and numeric - if (!isdigit(segments.at(1).c_str()[0])) { - tr_debug("[SimpleM2MResourceBase] [ERROR] define_resource_internal(), second route segment should be numeric, but was not (%s)\r\n", _route.c_str()); - return false; - } - - int inst_id = atoi(segments.at(1).c_str()); - - // Check if object exists - M2MObject* obj; - map::iterator obj_it = _client->_objects.find(segments[0]) ; - if(obj_it != _client->_objects.end()) { - tr_debug("Found object... %s\r\n", segments.at(0).c_str()); - obj = obj_it->second; - } else { - tr_debug("Create new object... %s\r\n", segments.at(0).c_str()); - obj = M2MInterfaceFactory::create_object(segments.at(0).c_str()); - if (!obj) { - return false; - } - _client->_objects.insert(std::pair(segments.at(0), obj)); - } - - // Check if object instance exists - M2MObjectInstance* inst = obj->object_instance(inst_id); - if(!inst) { - tr_debug("Create new object instance... %s\r\n", segments.at(1).c_str()); - inst = obj->create_object_instance(inst_id); - if(!inst) { - return false; - } - } - - // @todo check if the resource exists yet - M2MResource* res = inst->resource(segments.at(2).c_str()); - if(!res) { - res = inst->create_dynamic_resource(segments.at(2).c_str(), "", - M2MResourceInstance::STRING, observable); - if(!res) { - return false; - } - res->set_operation(opr); - res->set_value((uint8_t*)v.c_str(), v.length()); - - _client->_resources.insert(pair(_route, res)); - _client->register_update_callback(_route, this); - } - - return true; -} - -vector SimpleM2MResourceBase::parse_route(const char* route) -{ - string s(route); - vector v; - std::size_t found = s.find_first_of("/"); - - while (found!=std::string::npos) { - v.push_back(s.substr(0,found)); - s = s.substr(found+1); - found=s.find_first_of("/"); - if(found == std::string::npos) { - v.push_back(s); - } - } - return v; -} - -string SimpleM2MResourceBase::get() const -{ - tr_debug("SimpleM2MResourceBase::get() resource (%s)", _route.c_str()); - if (!_client->_resources.count(_route)) { - tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str()); - return string(); - } - - // otherwise ask mbed Client... - uint8_t* buffIn = NULL; - uint32_t sizeIn; - _client->_resources[_route]->get_value(buffIn, sizeIn); - - string s((char*)buffIn, sizeIn); - tr_debug("SimpleM2MResourceBase::get() resource value (%s)", s.c_str()); - free(buffIn); - return s; -} - -bool SimpleM2MResourceBase::set(string v) -{ - // Potentially set() happens in InterruptContext. That's not good. - tr_debug("SimpleM2MResourceBase::set() resource (%s)", _route.c_str()); - if (!_client->_resources.count(_route)) { - tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str()); - return false; - } - - if (v.length() == 0) { - _client->_resources[_route]->clear_value(); - } - else { - _client->_resources[_route]->set_value((uint8_t*)v.c_str(), v.length()); - } - - return true; -} - -bool SimpleM2MResourceBase::set(const int& v) -{ - char buffer[20]; - int size = sprintf(buffer,"%d",v); - std::string stringified(buffer,size); - - return set(stringified); -} - -bool SimpleM2MResourceBase::set_post_function(void(*fn)(void*)) -{ - //TODO: Check the resource exists with right operation being set or append the operation into it. - M2MResource *resource = get_resource(); - if(!resource) { - return false; - } - M2MBase::Operation op = resource->operation(); - op = (M2MBase::Operation)(op | M2MBase::POST_ALLOWED); - resource->set_operation(op); - - _client->_resources[_route]->set_execute_function(execute_callback_2(fn)); - return true; -} - -bool SimpleM2MResourceBase::set_post_function(execute_callback fn) -{ - //TODO: Check the resource exists with right operation being set or append the operation into it. - M2MResource *resource = get_resource(); - if(!resource) { - return false; - } - M2MBase::Operation op = resource->operation(); - op = (M2MBase::Operation)(op | M2MBase::POST_ALLOWED); - resource->set_operation(op); - - // No clue why this is not working?! It works with class member, but not with static function... - _client->_resources[_route]->set_execute_function(fn); - return true; -} - -M2MResource* SimpleM2MResourceBase::get_resource() -{ - if (!_client->_resources.count(_route)) { - tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str()); - return NULL; - } - return _client->_resources[_route]; -} - -SimpleM2MResourceString::SimpleM2MResourceString(MbedCloudClient* client, - const char* route, - string v, - M2MBase::Operation opr, - bool observable, - FP1 on_update) -: SimpleM2MResourceBase(client,route),_on_update(on_update) -{ - tr_debug("SimpleM2MResourceString::SimpleM2MResourceString() creating (%s)\r\n", route); - define_resource_internal(v, opr, observable); -} - -SimpleM2MResourceString::SimpleM2MResourceString(MbedCloudClient* client, - const char* route, - string v, - M2MBase::Operation opr, - bool observable, - void(*on_update)(string)) - -: SimpleM2MResourceBase(client,route) -{ - tr_debug("SimpleM2MResourceString::SimpleM2MResourceString() overloaded creating (%s)\r\n", route); - FP1 fp; - fp.attach(on_update); - _on_update = fp; - define_resource_internal(v, opr, observable); -} - -SimpleM2MResourceString::~SimpleM2MResourceString() -{ -} - -string SimpleM2MResourceString::operator=(const string& new_value) -{ - tr_debug("SimpleM2MResourceString::operator=()"); - set(new_value); - return new_value; -} - -SimpleM2MResourceString::operator string() const -{ - tr_debug("SimpleM2MResourceString::operator string()"); - string value = get(); - return value; -} - -void SimpleM2MResourceString::update() -{ - string v = get(); - _on_update(v); -} - -SimpleM2MResourceInt::SimpleM2MResourceInt(MbedCloudClient* client, - const char* route, - int v, - M2MBase::Operation opr, - bool observable, - FP1 on_update) -: SimpleM2MResourceBase(client,route),_on_update(on_update) -{ - tr_debug("SimpleM2MResourceInt::SimpleM2MResourceInt() creating (%s)\r\n", route); - char buffer[20]; - int size = sprintf(buffer,"%d",v); - std::string stringified(buffer,size); - define_resource_internal(stringified, opr, observable); -} - -SimpleM2MResourceInt::SimpleM2MResourceInt(MbedCloudClient* client, - const char* route, - int v, - M2MBase::Operation opr, - bool observable, - void(*on_update)(int)) -: SimpleM2MResourceBase(client,route) -{ - tr_debug("SimpleM2MResourceInt::SimpleM2MResourceInt() overloaded creating (%s)\r\n", route); - FP1 fp; - fp.attach(on_update); - _on_update = fp; - char buffer[20]; - int size = sprintf(buffer,"%d",v); - std::string stringified(buffer,size); - define_resource_internal(stringified, opr, observable); -} - -SimpleM2MResourceInt::~SimpleM2MResourceInt() -{ -} - -int SimpleM2MResourceInt::operator=(int new_value) -{ - set(new_value); - return new_value; -} - -SimpleM2MResourceInt::operator int() const -{ - string v = get(); - if (v.empty()) return 0; - - return atoi((const char*)v.c_str()); -} - -void SimpleM2MResourceInt::update() -{ - string v = get(); - if (v.empty()) { - _on_update(0); - } else { - _on_update(atoi((const char*)v.c_str())); - } -} -#endif diff --git a/source/include/CloudClientStorage.h b/source/include/CloudClientStorage.h index b3b4e48b7..a08787a3c 100644 --- a/source/include/CloudClientStorage.h +++ b/source/include/CloudClientStorage.h @@ -47,8 +47,8 @@ typedef enum { * Keep these sync with ones that found from kcm_defs.h */ typedef enum { - CCS_PRIVATE_KEY_ITEM, //!< KCM private key item type. KCM Supports ECC keys with curves defined in palGroupIndex_t(pal_Crypto.h) - CCS_PUBLIC_KEY_ITEM, //!< KCM public key item type. KCM Supports ECC keys with curves defined in palGroupIndex_t(pal_Crypto.h) + CCS_PRIVATE_KEY_ITEM, //!< KCM private key item type. KCM Supports ECC keys with curves defined in palGroupIndex_t(cs_pal_crypto.h) + CCS_PUBLIC_KEY_ITEM, //!< KCM public key item type. KCM Supports ECC keys with curves defined in palGroupIndex_t(cs_pal_crypto.h) CCS_SYMMETRIC_KEY_ITEM, //!< KCM symmetric key item type. CCS_CERTIFICATE_ITEM, //!< KCM certificate item type. Supported x509 certificates in der format. CCS_CONFIG_ITEM //!< KCM configuration parameter item type. diff --git a/source/include/ConnectorClient.h b/source/include/ConnectorClient.h index ee442639f..82c1d48e8 100644 --- a/source/include/ConnectorClient.h +++ b/source/include/ConnectorClient.h @@ -43,15 +43,6 @@ class ConnectorClientCallback; -#if MBED_CLOUD_CLIENT_STD_NAMESPACE_POLLUTION -// We should not really pollute application's namespace with std by having this in -// a public header file. -// But as as removal of the next line may break existing applications, which build due to this -// leakage, we need to maintain the old behavior for a while and just allow one to remove it. -using namespace std; -#endif - - /** * \brief ConnectorClientEndpointInfo * A structure that contains the needed endpoint information to register with the Cloud service. @@ -83,7 +74,7 @@ struct ConnectorClientEndpointInfo { */ class ConnectorClient : public M2MInterfaceObserver #ifndef MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE - , public M2MTimerObserver + , public M2MTimerObserver #endif { @@ -108,7 +99,9 @@ class ConnectorClient : public M2MInterfaceObserver State_Registration_Success, State_Registration_Failure, State_Registration_Updated, - State_Unregistered + State_Unregistered, + State_Alert_Mode, + State_Paused }; public: @@ -117,7 +110,7 @@ class ConnectorClient : public M2MInterfaceObserver * \brief Constructor. * \param callback, A callback for the status from ConnectorClient. */ - ConnectorClient(ConnectorClientCallback* callback); + ConnectorClient(ConnectorClientCallback *callback); /** * \brief Destructor. @@ -143,7 +136,7 @@ class ConnectorClient : public M2MInterfaceObserver * \brief Starts the registration sequence from the Service Client. * \param client_objs, A list of objects implementing the M2MBase interface to be registered with Cloud. */ - void start_registration(M2MBaseList* client_objs); + void start_registration(M2MBaseList *client_objs); /** * \brief Starts full registration sequence from the Service Client. @@ -159,7 +152,7 @@ class ConnectorClient : public M2MInterfaceObserver * \brief Returns the M2MInterface handler. * \return M2MInterface, Handled for M2MInterface. */ - M2MInterface * m2m_interface(); + M2MInterface *m2m_interface(); #ifndef MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE /** @@ -189,46 +182,46 @@ class ConnectorClient : public M2MInterfaceObserver * \brief Returns pointer to the ConnectorClientEndpointInfo object. * \return ConnectorClientEndpointInfo pointer. */ - const ConnectorClientEndpointInfo *endpoint_info() const; + const ConnectorClientEndpointInfo *endpoint_info() const; - /** - * \brief Returns KCM Certificate chain handle pointer. - * \return KCM Certificate chain handle pointer. - */ - void *certificate_chain_handle() const; + /** + * \brief Returns KCM Certificate chain handle pointer. + * \return KCM Certificate chain handle pointer. + */ + void *certificate_chain_handle() const; - /** - * \brief Sets the KCM certificate chain handle pointer. - * \param cert_handle KCM Certificate chain handle. - */ - void set_certificate_chain_handle(void *cert_handle); + /** + * \brief Sets the KCM certificate chain handle pointer. + * \param cert_handle KCM Certificate chain handle. + */ + void set_certificate_chain_handle(void *cert_handle); #ifndef MBED_CLIENT_DISABLE_EST_FEATURE - static void est_enrollment_result(est_enrollment_result_e result, - cert_chain_context_s *cert_chain, - void *context); - - /** - * \brief Get reference to the EST client instance. - */ - const EstClient &est_client() const; + static void est_enrollment_result(est_enrollment_result_e result, + cert_chain_context_s *cert_chain, + void *context); + + /** + * \brief Get reference to the EST client instance. + */ + const EstClient &est_client() const; #endif /* MBED_CLIENT_DISABLE_EST_FEATURE */ #ifndef MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE - /** - * \brief Starts bootstrap sequence again. - * This will clean the old LwM2M credentials. - * - */ - void bootstrap_again(); + /** + * \brief Starts bootstrap sequence again. + * This will clean the old LwM2M credentials. + * + */ + void bootstrap_again(); #endif //MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE - /** - * \brief Returns the binding mode selected by the client - * through the configuration. - * \return Binding mode of the client. - */ - M2MInterface::BindingMode transport_mode(); + /** + * \brief Returns the binding mode selected by the client + * through the configuration. + * \return Binding mode of the client. + */ + M2MInterface::BindingMode transport_mode(); #ifdef MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE void external_update(uint32_t offset, uint32_t size); @@ -284,7 +277,7 @@ class ConnectorClient : public M2MInterfaceObserver * \param server_object, An object containing information about the LWM2M server. * The client maintains the object. */ - virtual void registration_updated(M2MSecurity *security_object, const M2MServer & server_object); + virtual void registration_updated(M2MSecurity *security_object, const M2MServer &server_object); /** * \brief A callback indicating that there was an error during the operation. @@ -305,6 +298,9 @@ class ConnectorClient : public M2MInterfaceObserver */ virtual void network_status_changed(bool connected); + virtual void paused(); + + virtual void alert_mode(); /** * \brief Resumes client's timed functionality and network connection @@ -456,9 +452,15 @@ class ConnectorClient : public M2MInterfaceObserver */ void init_security_object(); + /** + * \brief Bootstrap performed. + * + */ + bool bootstrapped(); + private: // A callback to be called after the sequence is complete. - ConnectorClientCallback* _callback; + ConnectorClientCallback *_callback; StartupSubStateRegistration _current_state; bool _event_generated; bool _state_engine_running; diff --git a/source/include/ServiceClient.h b/source/include/ServiceClient.h index 494c0a2f9..af8c12a80 100644 --- a/source/include/ServiceClient.h +++ b/source/include/ServiceClient.h @@ -31,11 +31,6 @@ #include -#if MBED_CLOUD_CLIENT_STL_API -#include -#endif - - // TODO: selection for whether multicast is enabled or not is still probably not working in all cases... #if defined(MBED_CLOUD_CLIENT_SUPPORT_MULTICAST_UPDATE) && defined(MBED_CLOUD_CLIENT_SUPPORT_UPDATE) #define SERVICE_CLIENT_SUPPORT_MULTICAST @@ -65,7 +60,9 @@ class ServiceClientCallback { Service_Client_Status_Failure = -1, Service_Client_Status_Registered = 0, Service_Client_Status_Unregistered = 1, - Service_Client_Status_Register_Updated = 2 + Service_Client_Status_Register_Updated = 2, + Service_Client_Status_Alert_Mode = 3, + Service_Client_Status_Paused = 4 } ServiceClientCallbackStatus; /** @@ -110,8 +107,7 @@ class ServiceClientCallback { * client. */ -class ServiceClient : private ConnectorClientCallback -{ +class ServiceClient : private ConnectorClientCallback { public: /** @@ -136,7 +132,7 @@ class ServiceClient : private ConnectorClientCallback * \param interface, Takes the structure that contains the * needed information for an endpoint client to register. */ - ServiceClient(ServiceClientCallback& callback); + ServiceClient(ServiceClientCallback &callback); /** * \brief Destructor. @@ -148,7 +144,7 @@ class ServiceClient : private ConnectorClientCallback * \param callback, Takes the callback for the status from ConnectorClient. * \param client_objs, A list of objects to be registered to Cloud. */ - void initialize_and_register(M2MBaseList& reg_objs); + void initialize_and_register(M2MBaseList ®_objs); /** * \brief Initializes event OS tasklets @@ -173,23 +169,6 @@ class ServiceClient : private ConnectorClientCallback */ const ConnectorClient &connector_client() const; -#if MBED_CLOUD_CLIENT_STL_API - /** - * \brief Set resource value in the Device Object - * - * \note This is deprecated as the rest of API's using std::string, - * but there is no m2m_deprecated tag as that would cause warning on - * default builds from MbedCloudClient::set_device_resource_value(), - * which is the public API for this as it will be built but not used. - * - * \param resource Device enum to have value set. - * \param value String object. - * \return True if successful, false otherwise. - */ - bool set_device_resource_value(M2MDevice::DeviceResource resource, - const std::string& value); -#endif - /** * \brief Set resource value in the Device Object * @@ -199,7 +178,7 @@ class ServiceClient : private ConnectorClientCallback * \return True if successful, false otherwise. */ bool set_device_resource_value(M2MDevice::DeviceResource resource, - const char* value, + const char *value, uint32_t length); #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE @@ -331,13 +310,13 @@ protected : void state_unregister(); private: - M2MDevice* device_object_from_storage(); + M2MDevice *device_object_from_storage(); - static void post_response_status_handler(const M2MBase& base, + static void post_response_status_handler(const M2MBase &base, const M2MBase::MessageDeliveryStatus status, const M2MBase::MessageType type, - void* me); - void reboot_execute_handler(void*); + void *me); + void reboot_execute_handler(void *); void m2mdevice_reboot_execute(); /* lookup table for printing hexadecimal values */ diff --git a/update-client-hub/modules/common/update-client-common/arm_uc_crypto.h b/update-client-hub/modules/common/update-client-common/arm_uc_crypto.h index d943049c0..2f64e6dc1 100644 --- a/update-client-hub/modules/common/update-client-common/arm_uc_crypto.h +++ b/update-client-hub/modules/common/update-client-common/arm_uc_crypto.h @@ -29,7 +29,7 @@ extern "C" { #if defined(ARM_UC_FEATURE_CRYPTO_PAL) && (ARM_UC_FEATURE_CRYPTO_PAL == 1) #include "pal.h" -#include "pal_Crypto.h" +#include "cs_pal_crypto.h" typedef palMDHandle_t arm_uc_mdHandle_t; typedef palMDType_t arm_uc_mdType_t; diff --git a/zephyr/Kconfig.pal b/zephyr/Kconfig.pal index 990919475..ac26e7f9b 100644 --- a/zephyr/Kconfig.pal +++ b/zephyr/Kconfig.pal @@ -1,7 +1,7 @@ # Copyright (c) 2021 Pelion IoT # SPDX-License-Identifier: Apache-2.0 -menu "PAL options" +menu "Platform Abstraction Layer options" config PELION_PAL_SUPPORT_NAT64 bool "Automatic NAT64 address support on IPv6 networks" @@ -11,4 +11,71 @@ config PELION_PAL_SUPPORT_NAT64 IPv4 addresses to IPv6 using default NAT64 prefix. Only comes into effect when an IPv6-only device receives an IPv4 address from the DNS server. + +config PELION_PAL_SUPPORT_SSL_CONNECTION_ID + bool "Use Connection Identifiers for DTLS 1.2" + help + Connection ID is an extention to DTLS 1.2 that allows a DTLS session + to persist even if the device's IP address and port changes, which + otherwise would require a new DTLS handshake. This enables devices + to power down their network interface for long periods of time, + saving power and network bandwidth. + + Requires mbed TLS 2.18.0 or newer and transport mode to be UDP or + UDP Queue. + + https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-11 + +config PELION_PAL_USE_APPLICATION_REBOOT + bool "Use reboot function provided by application" + help + Override default reboot function with one provided by application. + Useful for shutting down the device gracefully, powering down external + components and saving state. + + Signature for C function: + void pal_plat_osApplicationReboot(void) + +config PELION_PAL_USE_APPLICATION_NETWORK_CALLBACK + bool "Use network status callback provided by application" + help + Provide setter for registering network status callback function in + application. Application uses callback function to notify Pelion client + about changes in network connectivity, enabling the client to refrain + from sending data during network loss. + + Signature for C function: + #include "pal.h" + palStatus_t pal_plat_setConnectionStatusCallback(uint32_t interfaceIndex, + connectionStatusCallback callback, + void *client_arg) + +choice + prompt "DNS API" + default PELION_PAL_USE_DNS_API_RESOLVE + help + Select DNS API used by network abstraction implementation. + + config PELION_PAL_USE_DNS_API_POSIX + bool "POSIX" + help + Use POSIX's getaddrinfo. This call is synchronous and maps to + Pelion's DNS version 0. + + config PELION_PAL_USE_DNS_API_RESOLVE + bool "DNS Resolve" + depends on DNS_RESOLVER + help + Use DNS Resolve's dns_get_addr_info. This call is asynchronous and maps + to Pelion's DNS version 3. + +endchoice + +config NEWLIB_LIBC_FLOAT_PRINTF + bool "Build with newlib float printf" + default y + help + Enable floating points in Newlib's snprintf. Must be enabled for correctly + formatting floating points in LwM2M resources. + endmenu diff --git a/zephyr/cmake/CMakeLists.txt b/zephyr/cmake/CMakeLists.txt index 282a4d6a8..f15b6277e 100644 --- a/zephyr/cmake/CMakeLists.txt +++ b/zephyr/cmake/CMakeLists.txt @@ -27,6 +27,9 @@ if(CONFIG_PELION_SOURCES) -DSN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE=${CONFIG_PELION_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE} -DMBED_CONF_MBED_TRACE_ENABLE=$ -DPAL_SUPPORT_NAT64=$ + -DPAL_USE_SSL_SESSION_RESUME=$ + -DPAL_USE_APPLICATION_REBOOT=$ + -DPAL_USE_APPLICATION_NETWORK_CALLBACK=$ -DPAL_PLATFORM_DEFINED_CONFIGURATION="zephyr_default.h" -DMBED_CONF_STORAGE_STORAGE_TYPE=TDB_INTERNAL @@ -49,6 +52,14 @@ if(CONFIG_PELION_SOURCES) SET(PELION_CLIENT_DEFINITIONS ${PELION_CLIENT_DEFINITIONS} -DMBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE=1) endif() + if(${CONFIG_PELION_PAL_USE_DNS_API_POSIX}) + SET(PELION_CLIENT_DEFINITIONS ${PELION_CLIENT_DEFINITIONS} -DPAL_DNS_API_VERSION=0) + endif() + + if(${CONFIG_PELION_PAL_USE_DNS_API_RESOLVE}) + SET(PELION_CLIENT_DEFINITIONS ${PELION_CLIENT_DEFINITIONS} -DPAL_DNS_API_VERSION=3) + endif() + if(${CONFIG_PELION_UPDATE}) SET(PELION_CLIENT_DEFINITIONS ${PELION_CLIENT_DEFINITIONS} -DMBED_CLOUD_CLIENT_SUPPORT_UPDATE=1 @@ -74,8 +85,6 @@ if(CONFIG_PELION_SOURCES) add_definitions(${PELION_CLIENT_DEFINITIONS}) - include_directories(../pal_config) - # Zephyr compile options include_directories($) include_directories($) @@ -129,6 +138,7 @@ if(CONFIG_PELION_SOURCES) zephyr_system_include_directories(${PELION_LIBRARY_DIR}/mbed-client) zephyr_system_include_directories(${PELION_LIBRARY_DIR}/mbed-client/mbed-client) zephyr_system_include_directories(${PELION_LIBRARY_DIR}/mbed-client/mbed-client-c) + zephyr_system_include_directories(${PELION_LIBRARY_DIR}/mbed-client-pal/Configs/mbedTLS) zephyr_system_include_directories(${PELION_LIBRARY_DIR}/mbed-client-pal/Source) zephyr_system_include_directories(${PELION_LIBRARY_DIR}/mbed-client-pal/Source/PAL-Impl/Services-API) zephyr_system_include_directories(${PELION_LIBRARY_DIR}/mbed-cloud-client) diff --git a/zephyr/config/zephyr_default.h b/zephyr/config/zephyr_default.h index 15d35d073..2cda874cd 100644 --- a/zephyr/config/zephyr_default.h +++ b/zephyr/config/zephyr_default.h @@ -89,6 +89,22 @@ #define PAL_SUPPORT_NAT64 1 #endif +#ifndef PAL_DNS_API_VERSION + #define PAL_DNS_API_VERSION 3 +#endif + +#ifndef PAL_DNS_CACHE_MAX + #define PAL_DNS_CACHE_MAX 1 +#endif + +#ifndef PAL_DNS_TIMEOUT_MS + #define PAL_DNS_TIMEOUT_MS (60*1000) +#endif + +#ifndef PAL_USE_APPLICATION_NETWORK_CALLBACK + #define PAL_USE_APPLICATION_NETWORK_CALLBACK 0 +#endif + /*****************************************************************************/ /* RTOS */ /*****************************************************************************/ @@ -105,4 +121,16 @@ #endif #endif +#ifndef PAL_USE_APPLICATION_REBOOT + #define PAL_USE_APPLICATION_REBOOT 0 +#endif + +/*****************************************************************************/ +/* TLS */ +/*****************************************************************************/ + +#ifndef PAL_USE_SSL_SESSION_RESUME + #define PAL_USE_SSL_SESSION_RESUME 0 +#endif + #endif /* PAL_DEFAULT_ZEPHYR_CONFIGURATION_H_ */