spider-bot/fw/nrf52/nrf5_sdk/components/iot/coap/coap_resource.c

275 lines
8.4 KiB
C

/**
* Copyright (c) 2014 - 2019, 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 <string.h>
#include "coap_resource.h"
#include "coap_api.h"
#include "iot_common.h"
#include "sdk_config.h"
#define COAP_RESOURCE_MAX_AGE_INIFINITE 0xFFFFFFFF
static coap_resource_t * mp_root_resource = NULL;
static char m_scratch_buffer[(COAP_RESOURCE_MAX_NAME_LEN + 1) * COAP_RESOURCE_MAX_DEPTH + 6];
#if (COAP_DISABLE_API_PARAM_CHECK == 0)
/**@brief Verify NULL parameters are not passed to API by application. */
#define NULL_PARAM_CHECK(PARAM) \
if ((PARAM) == NULL) \
{ \
return (NRF_ERROR_NULL | IOT_COAP_ERR_BASE); \
}
#else
#define NULL_PARAM_CHECK(PARAM)
#endif // COAP_DISABLE_API_PARAM_CHECK
uint32_t coap_resource_init(void)
{
mp_root_resource = NULL;
return NRF_SUCCESS;
}
uint32_t coap_resource_create(coap_resource_t * p_resource, const char * name)
{
NULL_PARAM_CHECK(p_resource);
NULL_PARAM_CHECK(name);
if (strlen(name) > COAP_RESOURCE_MAX_NAME_LEN)
{
return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
}
memcpy(p_resource->name, name, strlen(name));
if (mp_root_resource == NULL)
{
mp_root_resource = p_resource;
}
p_resource->max_age = COAP_RESOURCE_MAX_AGE_INIFINITE;
return NRF_SUCCESS;
}
uint32_t coap_resource_child_add(coap_resource_t * p_parent, coap_resource_t * p_child)
{
NULL_PARAM_CHECK(p_parent);
NULL_PARAM_CHECK(p_child);
if (p_parent->child_count == 0)
{
p_parent->p_front = p_child;
p_parent->p_tail = p_child;
}
else
{
coap_resource_t * p_last_sibling = p_parent->p_tail;
p_last_sibling->p_sibling = p_child;
p_parent->p_tail = p_child;
}
p_parent->child_count++;
return NRF_SUCCESS;
}
static uint32_t generate_path(uint16_t buffer_pos, coap_resource_t * p_current_resource, char * parent_path, uint8_t * string, uint16_t * length)
{
uint32_t err_code = NRF_SUCCESS;
if (parent_path == NULL)
{
m_scratch_buffer[buffer_pos++] = '<';
if (p_current_resource->p_front != NULL)
{
coap_resource_t * next_child = p_current_resource->p_front;
do
{
err_code = generate_path(buffer_pos, next_child, m_scratch_buffer, string, length);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
next_child = next_child->p_sibling;
} while (next_child != NULL);
}
}
else
{
uint16_t size = strlen(p_current_resource->name);
m_scratch_buffer[buffer_pos++] = '/';
memcpy(&m_scratch_buffer[buffer_pos], p_current_resource->name, size);
buffer_pos += size;
if (p_current_resource->p_front != NULL)
{
coap_resource_t * next_child = p_current_resource->p_front;
do
{
err_code = generate_path(buffer_pos, next_child, m_scratch_buffer, string, length);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
next_child = next_child->p_sibling;
} while (next_child != NULL);
}
m_scratch_buffer[buffer_pos++] = '>';
// If the resource is observable, append 'obs;' token.
if ((p_current_resource->permission & COAP_PERM_OBSERVE) > 0)
{
memcpy(&m_scratch_buffer[buffer_pos], ";obs", 4);
buffer_pos += 4;
}
m_scratch_buffer[buffer_pos++] = ',';
if (buffer_pos <= (*length))
{
*length -= buffer_pos;
memcpy(&string[strlen((char *)string)], m_scratch_buffer, buffer_pos);
}
else
{
return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
}
}
return err_code;
}
uint32_t coap_resource_well_known_generate(uint8_t * string, uint16_t * length)
{
NULL_PARAM_CHECK(string);
NULL_PARAM_CHECK(length);
if (mp_root_resource == NULL)
{
return (NRF_ERROR_INVALID_STATE | IOT_COAP_ERR_BASE);
}
memset(string, 0, *length);
uint32_t err_code = generate_path(0, mp_root_resource, NULL, string, length);
string[strlen((char *)string) - 1] = '\0'; // remove the last comma
return err_code;
}
static coap_resource_t * coap_resource_child_resolve(coap_resource_t * p_parent,
char * p_path)
{
coap_resource_t * result = NULL;
if (p_parent->p_front != NULL)
{
coap_resource_t * sibling_in_question = p_parent->p_front;
do {
// Check if the sibling name match.
size_t size = strlen(sibling_in_question->name);
if (strncmp(sibling_in_question->name, p_path, size) == 0)
{
return sibling_in_question;
}
else
{
sibling_in_question = sibling_in_question->p_sibling;
}
} while (sibling_in_question != NULL);
}
return result;
}
uint32_t coap_resource_get(coap_resource_t ** p_resource, uint8_t ** pp_uri_pointers, uint8_t num_of_uris)
{
if (mp_root_resource == NULL)
{
// Make sure pointer is set to NULL before returning.
*p_resource = NULL;
return (NRF_ERROR_INVALID_STATE | IOT_COAP_ERR_BASE);
}
coap_resource_t * p_current_resource = mp_root_resource;
// Every node should start at root.
for (uint8_t i = 0; i < num_of_uris; i++)
{
p_current_resource = coap_resource_child_resolve(p_current_resource, (char *)pp_uri_pointers[i]);
if (p_current_resource == NULL)
{
// Stop looping as this direction will not give anything more.
break;
}
}
if (p_current_resource != NULL)
{
*p_resource = p_current_resource;
return NRF_SUCCESS;
}
// If nothing has been found.
*p_resource = NULL;
return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
}
uint32_t coap_resource_root_get(coap_resource_t ** pp_resource)
{
NULL_PARAM_CHECK(pp_resource);
if (mp_root_resource == NULL)
{
return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
}
*pp_resource = mp_root_resource;
return NRF_SUCCESS;
}