diff options
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/context_manager/iot_context_manager.c')
-rw-r--r-- | thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/context_manager/iot_context_manager.c | 561 |
1 files changed, 561 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/context_manager/iot_context_manager.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/context_manager/iot_context_manager.c new file mode 100644 index 0000000..a0c66ac --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/context_manager/iot_context_manager.c @@ -0,0 +1,561 @@ +/** + * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nordic_common.h" +#include "sdk_common.h" +#include "sdk_config.h" +#include "iot_common.h" +#include "iot_context_manager.h" + +#if IOT_CONTEXT_MANAGER_CONFIG_LOG_ENABLED + +#define NRF_LOG_MODULE_NAME context_manager + +#define NRF_LOG_LEVEL IOT_CONTEXT_MANAGER_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR IOT_CONTEXT_MANAGER_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR IOT_CONTEXT_MANAGER_CONFIG_DEBUG_COLOR + +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define CM_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */ +#define CM_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */ +#define CM_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */ + +#define CM_ENTRY() CM_TRC(">> %s", __func__) +#define CM_EXIT() CM_TRC("<< %s", __func__) + +#else // IOT_CONTEXT_MANAGER_CONFIG_LOG_ENABLED + +#define CM_TRC(...) /**< Disables traces. */ +#define CM_DUMP(...) /**< Disables dumping of octet streams. */ +#define CM_ERR(...) /**< Disables error logs. */ + +#define CM_ENTRY(...) +#define CM_EXIT(...) + +#endif // IOT_CONTEXT_MANAGER_CONFIG_LOG_ENABLED + +/**@brief Parameter maximum values. */ +#define CID_VALUE_MAX 15 +#define PREFIX_LENGTH_VALUE_MAX 128 + +/** + * @defgroup api_param_check API Parameters check macros. + * + * @details Macros that verify parameters passed to the module in the APIs. These macros + * could be mapped to nothing in final versions of code to save execution and size. + * IOT_CONTEXT_MANAGER_DISABLE_API_PARAM_CHECK should be defined to disable these checks. + * + * @{ + */ +#if (IOT_CONTEXT_MANAGER_DISABLE_API_PARAM_CHECK == 0) + +/**@brief Macro to check is module is initialized before requesting one of the module procedures. */ +#define VERIFY_MODULE_IS_INITIALIZED() \ + if (m_initialization_state == false) \ + { \ + return (SDK_ERR_MODULE_NOT_INITIALIZED | IOT_CONTEXT_MANAGER_ERR_BASE); \ + } + +/**@brief Macro to check is module is initialized before requesting one of the module procedures. */ +#define VERIFY_MODULE_IS_INITIALIZED_NULL() \ + if (m_initialization_state == false) \ + { \ + return NULL; \ + } + +/** + * @brief Verify NULL parameters are not passed to API by application. + */ +#define NULL_PARAM_CHECK(PARAM) \ + if ((PARAM) == NULL) \ + { \ + return (NRF_ERROR_NULL | IOT_CONTEXT_MANAGER_ERR_BASE); \ + } + +/** + * @brief Verify CID has valid value. + */ +#define VERIFY_CID_VALUE(CID) \ + if (!((CID) <= CID_VALUE_MAX)) \ + { \ + return (NRF_ERROR_INVALID_PARAM | IOT_CONTEXT_MANAGER_ERR_BASE); \ + } + +/** + * @brief Verify prefix length value. + */ +#define VERIFY_PREFIX_LEN_VALUE(PREFIX_LEN) \ + if (!(PREFIX_LEN <= PREFIX_LENGTH_VALUE_MAX)) \ + { \ + return (NRF_ERROR_INVALID_PARAM | IOT_CONTEXT_MANAGER_ERR_BASE); \ + } + +#else // IOT_IOT_CONTEXT_MANAGER_DISABLE_API_PARAM_CHECK + +#define VERIFY_MODULE_IS_INITIALIZED() +#define VERIFY_MODULE_IS_INITIALIZED_NULL() +#define NULL_PARAM_CHECK(PARAM) +#define VERIFY_CID_VALUE(CID) +#define VERIFY_PREFIX_LEN_VALUE(PREFIX_LEN) + +#endif //IOT_CONTEXT_MANAGER_DISABLE_API_PARAM_CHECK +/** @} */ + +/** + * @defgroup iot_context_manager_mutex_lock_unlock Module's Mutex Lock/Unlock Macros. + * + * @details Macros used to lock and unlock modules. Currently, SDK does not use mutexes but + * framework is provided in case need arises to use an alternative architecture. + * @{ + */ +#define CM_MUTEX_LOCK() SDK_MUTEX_LOCK(m_iot_context_manager_mutex) /**< Lock module using mutex */ +#define CM_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_iot_context_manager_mutex) /**< Unlock module using mutex */ +/** @} */ + +/**@brief Context table, managing by IPv6 stack. */ +typedef struct +{ + iot_interface_t * p_interface; /**< IoT interface pointer. */ + uint8_t context_count; /**< Number of valid contexts in the table. */ + iot_context_t contexts[IOT_CONTEXT_MANAGER_MAX_CONTEXTS]; /**< Array of valid contexts. */ +}iot_context_table_t; + + +SDK_MUTEX_DEFINE(m_iot_context_manager_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */ +static bool m_initialization_state = false; /**< Variable to maintain module initialization state. */ +static iot_context_table_t m_context_table[IOT_CONTEXT_MANAGER_MAX_TABLES]; /**< Array of contexts table managed by the module. */ + +/**@brief Initializes context entry. */ +static void context_init(iot_context_t * p_context) +{ + p_context->context_id = IPV6_CONTEXT_IDENTIFIER_NONE; + p_context->prefix_len = 0; + p_context->compression_flag = false; + + memset(p_context->prefix.u8, 0, IPV6_ADDR_SIZE); +} + + +/**@brief Initializes context table. */ +static void context_table_init(uint32_t table_id) +{ + uint32_t index; + + for (index = 0; index < IOT_CONTEXT_MANAGER_MAX_CONTEXTS; index++) + { + context_init(&m_context_table[table_id].contexts[index]); + m_context_table[table_id].context_count = 0; + m_context_table[table_id].p_interface = NULL; + } +} + + +/**@brief Initializes context table. */ +static uint32_t context_table_find(const iot_interface_t * p_interface) +{ + uint32_t index; + + for (index = 0; index < IOT_CONTEXT_MANAGER_MAX_TABLES; index++) + { + if (m_context_table[index].p_interface == p_interface) + { + break; + } + } + + return index; +} + + +/**@brief Looks up context table for specific context identifier. */ +static uint32_t context_find_by_cid(uint32_t table_id, + uint8_t context_id, + iot_context_t ** pp_context) +{ + uint32_t index; + + for (index = 0; index < IOT_CONTEXT_MANAGER_MAX_CONTEXTS; index++) + { + if (m_context_table[table_id].contexts[index].context_id == context_id) + { + *pp_context = &m_context_table[table_id].contexts[index]; + return NRF_SUCCESS; + } + } + + return (NRF_ERROR_NOT_FOUND | IOT_CONTEXT_MANAGER_ERR_BASE); +} + + +static uint32_t context_find_by_prefix(uint32_t table_id, + const ipv6_addr_t * p_prefix, + iot_context_t ** pp_context) +{ + uint32_t index; + uint32_t context_left; + uint16_t context_cmp_len; + iot_context_t * p_best_match = NULL; + + context_left = m_context_table[table_id].context_count; + + for (index = 0; index < IOT_CONTEXT_MANAGER_MAX_CONTEXTS && context_left; index++) + { + if (m_context_table[table_id].contexts[index].context_id != IPV6_CONTEXT_IDENTIFIER_NONE && + m_context_table[table_id].contexts[index].compression_flag == true) + { + if ((context_cmp_len = m_context_table[table_id].contexts[index].prefix_len) < 64) + { + context_cmp_len = 64; + } + + // Check if address have matched in CID table. + if (IPV6_ADDRESS_PREFIX_CMP(m_context_table[table_id].contexts[index].prefix.u8, + p_prefix->u8, + context_cmp_len)) + { + if (p_best_match == NULL || p_best_match->prefix_len < + m_context_table[table_id].contexts[index].prefix_len) + { + p_best_match = &m_context_table[table_id].contexts[index]; + } + } + + // Decrease left context in table, to avoid too many checking. + context_left--; + } + } + + if (p_best_match) + { + *pp_context = p_best_match; + return NRF_SUCCESS; + } + + return (NRF_ERROR_NOT_FOUND | IOT_CONTEXT_MANAGER_ERR_BASE); +} + + +/**@brief Looks up for first empty entry in the table. */ +static uint32_t context_find_free(uint32_t table_id, iot_context_t ** pp_context) +{ + uint32_t index; + + for (index = 0; index < IOT_CONTEXT_MANAGER_MAX_CONTEXTS; index++) + { + if (m_context_table[table_id].contexts[index].context_id == IPV6_CONTEXT_IDENTIFIER_NONE) + { + *pp_context = &m_context_table[table_id].contexts[index]; + return NRF_SUCCESS; + } + } + + return (NRF_ERROR_NO_MEM | IOT_CONTEXT_MANAGER_ERR_BASE); +} + + +uint32_t iot_context_manager_init(void) +{ + uint32_t index; + + CM_ENTRY(); + + SDK_MUTEX_INIT(m_iot_context_manager_mutex); + + CM_MUTEX_LOCK(); + + for (index = 0; index < IOT_CONTEXT_MANAGER_MAX_TABLES; index++) + { + context_table_init(index); + } + + m_initialization_state = true; + + CM_MUTEX_UNLOCK(); + + CM_EXIT(); + + return NRF_SUCCESS; +} + + +uint32_t iot_context_manager_table_alloc(const iot_interface_t * p_interface) +{ + VERIFY_MODULE_IS_INITIALIZED(); + NULL_PARAM_CHECK(p_interface); + + uint32_t err_code = NRF_SUCCESS; + + CM_ENTRY(); + + CM_MUTEX_LOCK(); + + const uint32_t table_id = context_table_find(NULL); + + if (table_id != IOT_CONTEXT_MANAGER_MAX_TABLES) + { + // Found a free context table and assign to it. + CM_TRC("Assigned new context table."); + m_context_table[table_id].p_interface = (iot_interface_t *)p_interface; + } + else + { + // No free context table found. + CM_ERR("No context table found."); + err_code = (NRF_ERROR_NO_MEM | IOT_CONTEXT_MANAGER_ERR_BASE); + } + + CM_MUTEX_UNLOCK(); + + CM_EXIT(); + + return err_code; +} + + +uint32_t iot_context_manager_table_free(const iot_interface_t * p_interface) +{ + VERIFY_MODULE_IS_INITIALIZED(); + NULL_PARAM_CHECK(p_interface); + + uint32_t err_code = NRF_SUCCESS; + + CM_ENTRY(); + + SDK_MUTEX_INIT(m_iot_context_manager_mutex); + + CM_MUTEX_LOCK(); + + const uint32_t table_id = context_table_find(p_interface); + + if (table_id != IOT_CONTEXT_MANAGER_MAX_TABLES) + { + // Clear context table. + CM_TRC("Found context table assigned to interface."); + context_table_init(table_id); + } + else + { + // No free context table found. + CM_ERR("No context table found."); + err_code = (NRF_ERROR_NOT_FOUND | IOT_CONTEXT_MANAGER_ERR_BASE); + } + + CM_MUTEX_UNLOCK(); + + CM_EXIT(); + + return err_code; +} + + +uint32_t iot_context_manager_update(const iot_interface_t * p_interface, + iot_context_t * p_context) +{ + VERIFY_MODULE_IS_INITIALIZED(); + NULL_PARAM_CHECK(p_context); + VERIFY_CID_VALUE(p_context->context_id); + VERIFY_PREFIX_LEN_VALUE(p_context->prefix_len); + + uint32_t retval = NRF_SUCCESS; + uint32_t err_code = NRF_SUCCESS; + iot_context_t * p_internal_context; + + CM_ENTRY(); + + CM_MUTEX_LOCK(); + + const uint32_t table_id = context_table_find(p_interface); + + if (table_id != IOT_CONTEXT_MANAGER_MAX_TABLES) + { + // Try to find context in context table. + retval = context_find_by_cid(table_id, p_context->context_id, &p_internal_context); + + if (retval != NRF_SUCCESS) + { + err_code = context_find_free(table_id, &p_internal_context); + + // Increase context count. + if (err_code == NRF_SUCCESS) + { + m_context_table[table_id].context_count++; + } + } + + if (err_code == NRF_SUCCESS) + { + // Update context table, with parameters from application. + p_internal_context->context_id = p_context->context_id; + p_internal_context->prefix_len = p_context->prefix_len; + p_internal_context->compression_flag = p_context->compression_flag; + memset(p_internal_context->prefix.u8, 0, IPV6_ADDR_SIZE); + IPV6_ADDRESS_PREFIX_SET(p_internal_context->prefix.u8, p_context->prefix.u8, p_context->prefix_len); + } + else + { + CM_ERR("No place in context table."); + } + } + else + { + // No free context table found. + CM_ERR("No context table found."); + err_code = (NRF_ERROR_NOT_FOUND | IOT_CONTEXT_MANAGER_ERR_BASE); + } + + CM_MUTEX_UNLOCK(); + + CM_EXIT(); + + return err_code; +} + + +uint32_t iot_context_manager_remove(const iot_interface_t * p_interface, + iot_context_t * p_context) +{ + VERIFY_MODULE_IS_INITIALIZED(); + NULL_PARAM_CHECK(p_interface); + NULL_PARAM_CHECK(p_context); + + uint32_t err_code = NRF_SUCCESS; + + CM_ENTRY(); + + CM_MUTEX_LOCK(); + + const uint32_t table_id = context_table_find(p_interface); + + if (table_id != IOT_CONTEXT_MANAGER_MAX_TABLES) + { + if (p_context->context_id != IPV6_CONTEXT_IDENTIFIER_NONE) + { + m_context_table[table_id].context_count--; + } + + // Reinit context entry. + context_init(p_context); + } + else + { + // No free context table found. + CM_ERR("No context table found."); + err_code = (NRF_ERROR_NOT_FOUND | IOT_CONTEXT_MANAGER_ERR_BASE); + } + + CM_MUTEX_UNLOCK(); + + CM_EXIT(); + + return err_code; +} + + +uint32_t iot_context_manager_get_by_addr(const iot_interface_t * p_interface, + const ipv6_addr_t * p_addr, + iot_context_t ** pp_context) +{ + VERIFY_MODULE_IS_INITIALIZED(); + NULL_PARAM_CHECK(p_interface); + NULL_PARAM_CHECK(p_addr); + NULL_PARAM_CHECK(pp_context); + + uint32_t err_code; + + CM_ENTRY(); + + CM_MUTEX_LOCK(); + + const uint32_t table_id = context_table_find(p_interface); + + if (table_id != IOT_CONTEXT_MANAGER_MAX_TABLES) + { + err_code = context_find_by_prefix(table_id, p_addr, pp_context); + } + else + { + // No free context table found. + CM_ERR("No context table found."); + err_code = (NRF_ERROR_NOT_FOUND | IOT_CONTEXT_MANAGER_ERR_BASE); + } + + CM_MUTEX_UNLOCK(); + + CM_EXIT(); + + return err_code; +} + + +uint32_t iot_context_manager_get_by_cid(const iot_interface_t * p_interface, + uint8_t context_id, + iot_context_t ** pp_context) +{ + VERIFY_MODULE_IS_INITIALIZED(); + NULL_PARAM_CHECK(p_interface); + NULL_PARAM_CHECK(pp_context); + VERIFY_CID_VALUE(context_id); + + uint32_t err_code; + + CM_ENTRY(); + + CM_MUTEX_LOCK(); + + const uint32_t table_id = context_table_find(p_interface); + + if (table_id != IOT_CONTEXT_MANAGER_MAX_TABLES) + { + err_code = context_find_by_cid(table_id, context_id, pp_context); + } + else + { + // No free context table found. + CM_TRC("No context table found."); + err_code = (NRF_ERROR_NOT_FOUND | IOT_CONTEXT_MANAGER_ERR_BASE); + } + + CM_MUTEX_UNLOCK(); + + CM_EXIT(); + + return err_code; +} |