123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854 |
- /**
- * 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 <stdbool.h>
- #include <string.h>
- #include "nordic_common.h"
- #include "nrf.h"
- #include "coap_api.h"
- #include "coap.h"
- #include "coap_queue.h"
- #include "coap_transport.h"
- #include "sdk_common.h"
- #include "iot_common.h"
- #include "mem_manager.h"
- #include "coap_resource.h"
- #include "coap_observe_api.h"
- #include "coap_observe.h"
- #if IOT_COAP_CONFIG_LOG_ENABLED
- #define NRF_LOG_MODULE_NAME coap
- #define NRF_LOG_LEVEL IOT_COAP_CONFIG_LOG_LEVEL
- #define NRF_LOG_INFO_COLOR IOT_COAP_CONFIG_INFO_COLOR
- #define NRF_LOG_DEBUG_COLOR IOT_COAP_CONFIG_DEBUG_COLOR
- #include "nrf_log.h"
- NRF_LOG_MODULE_REGISTER();
- #define COAP_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
- #define COAP_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
- #define COAP_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
- #define COAP_ENTRY() COAP_TRC(">> %s", __func__)
- #define COAP_EXIT() COAP_TRC("<< %s", __func__)
- #define COAP_EXIT_WITH_RESULT(result) COAP_TRC("<< %s, result: %d", __func__, result)
- #else // IOT_COAP_CONFIG_LOG_ENABLED
- #define COAP_TRC(...) /**< Disables traces. */
- #define COAP_DUMP(...) /**< Disables dumping of octet streams. */
- #define COAP_ERR(...) /**< Disables error logs. */
- #define COAP_ENTRY(...)
- #define COAP_EXIT(...)
- #define COAP_EXIT_WITH_RESULT(...)
- #endif // IOT_COAP_CONFIG_LOG_ENABLED
- #define COAP_REQUEST_ENTITY_MAX_SIZE (BLE_IPSP_RX_BUFFER_SIZE - (IPV6_IP_HEADER_SIZE + \
- UDP_HEADER_SIZE)) /** Maximum request entity size. */
- SDK_MUTEX_DEFINE(m_coap_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
- static uint32_t m_token_seed; /**< Token seed provided by application to be used for generating token numbers. */
- static uint32_t m_message_id_counter; /**< Message ID counter, used to generate unique message IDs. */
- static coap_error_callback_t m_error_callback; /**< Function pointer to an application CoAP error handler. */
- static coap_request_handler_t m_request_handler = NULL; /**< Request handler where to forward all incoming requests. */
- #define COAP_MESSAGE_ACK_SET(REMOTE, LOCAL_PORT, MID) { \
- memcpy(&m_coap_empty_message.remote, (REMOTE), sizeof(coap_remote_t)); \
- m_coap_empty_message.port.port_number = (LOCAL_PORT); \
- m_coap_empty_message.header.id = (MID); \
- m_coap_empty_message.header.type = COAP_TYPE_ACK; \
- }
- #define COAP_MESSAGE_RST_SET(REMOTE, LOCAL_PORT, MID) { \
- memcpy(&m_coap_empty_message.remote, (REMOTE), sizeof(coap_remote_t)); \
- m_coap_empty_message.port.port_number = (LOCAL_PORT); \
- m_coap_empty_message.header.id = (MID); \
- m_coap_empty_message.header.type = COAP_TYPE_RST; \
- }
- static coap_message_t m_coap_empty_message = {
- .header = {
- .version = 1,
- .type = COAP_TYPE_ACK,
- .token_len = 0,
- .code = COAP_CODE_EMPTY_MESSAGE,
- .id = 0,
- },
- .p_payload = NULL,
- .payload_len = 0,
- .options_count = 0,
- .p_arg = NULL,
- .response_callback = NULL,
- .port = {
- .port_number = 0
- },
- .options_len = 0,
- .options_offset = 0,
- .p_data = NULL,
- .data_len = 0
- };
- static inline bool is_ping(coap_message_t * p_message)
- {
- return (p_message->header.code == COAP_CODE_EMPTY_MESSAGE) &&
- (p_message->header.type == COAP_TYPE_CON);
- }
- static inline bool is_ack(coap_message_t * p_message)
- {
- return (p_message->header.code == COAP_CODE_EMPTY_MESSAGE) &&
- (p_message->header.type == COAP_TYPE_ACK);
- }
- static inline bool is_reset(coap_message_t * p_message)
- {
- return (p_message->header.type == COAP_TYPE_RST);
- }
- static inline bool is_con(coap_message_t * p_message)
- {
- return (p_message->header.type == COAP_TYPE_CON);
- }
- static inline bool is_non(coap_message_t * p_message)
- {
- return (p_message->header.type == COAP_TYPE_NON);
- }
- static inline bool is_request(uint8_t message_code)
- {
- return (message_code >= 1) && (message_code < 32);
- }
- static inline bool is_response(uint8_t message_code)
- {
- return (message_code >= 64) && (message_code < 192);
- }
- static inline void app_error_notify(uint32_t err_code, coap_message_t * p_message)
- {
- if (m_error_callback != NULL)
- {
- COAP_MUTEX_UNLOCK();
- m_error_callback(err_code, p_message);
- COAP_MUTEX_LOCK();
- }
- }
- uint32_t coap_init(uint32_t token_rand_seed, coap_transport_init_t * p_transport_param)
- {
- COAP_ENTRY();
- uint32_t err_code;
- SDK_MUTEX_INIT(m_coap_mutex);
- COAP_MUTEX_LOCK();
- internal_coap_observe_init();
- m_error_callback = NULL;
- m_token_seed = token_rand_seed;
- (void)m_token_seed;
- m_message_id_counter = 1;
- err_code = coap_transport_init(p_transport_param);
- if (err_code != NRF_SUCCESS)
- {
- COAP_MUTEX_UNLOCK();
- return err_code;
- }
- err_code = coap_queue_init();
- if (err_code != NRF_SUCCESS)
- {
- COAP_MUTEX_UNLOCK();
- return err_code;
- }
- err_code = coap_resource_init();
- COAP_MUTEX_UNLOCK();
- COAP_EXIT();
- return err_code;
- }
- uint32_t coap_error_handler_register(coap_error_callback_t error_callback)
- {
- // TODO: error handling, null pointer, module initilized etc.
- COAP_MUTEX_LOCK();
- m_error_callback = error_callback;
- COAP_MUTEX_UNLOCK();
- return NRF_SUCCESS;
- }
- uint32_t internal_coap_message_send(uint32_t * p_handle, coap_message_t * p_message)
- {
- if (p_message == NULL)
- {
- return (NRF_ERROR_NULL | IOT_COAP_ERR_BASE);
- }
- // Compiled away if COAP_ENABLE_OBSERVE_CLIENT is not set to 1.
- coap_observe_client_send_handle(p_message);
- COAP_ENTRY();
- // Fetch the expected length of the packet serialized by passing length of 0.
- uint16_t expected_length = 0;
- uint32_t err_code = coap_message_encode(p_message, NULL, &expected_length);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- // Allocate a buffer to serialize the message into.
- uint8_t * p_buffer;
- uint32_t request_length = expected_length;
- err_code = nrf_mem_reserve(&p_buffer, &request_length);
- if (err_code != NRF_SUCCESS)
- {
- COAP_TRC("p_buffer alloc error = 0x%08lX!", err_code);
- return err_code;
- }
- memset(p_buffer, 0, request_length);
- COAP_TRC("Alloc mem, p_buffer = %p", (uint8_t *)p_buffer);
- // Serialize the message.
- uint16_t buffer_length = (uint16_t)request_length;
- err_code = coap_message_encode(p_message, p_buffer, &buffer_length);
- if (err_code != NRF_SUCCESS)
- {
- COAP_TRC("Encode error!");
- COAP_TRC("Free mem, p_buffer = %p", p_buffer);
- UNUSED_VARIABLE(nrf_free(p_buffer));
- return err_code;
- }
- err_code = coap_transport_write(&p_message->port, &p_message->remote, p_buffer, buffer_length);
- if (err_code == NRF_SUCCESS)
- {
- if (is_con(p_message) || (is_non(p_message) &&
- is_request(p_message->header.code) &&
- (p_message->response_callback != NULL)))
- {
- coap_queue_item_t item;
- item.p_arg = p_message->p_arg;
- item.mid = p_message->header.id;
- item.callback = p_message->response_callback;
- item.p_buffer = p_buffer;
- item.buffer_len = buffer_length;
- item.timeout_val = COAP_ACK_TIMEOUT * COAP_ACK_RANDOM_FACTOR;
- if (p_message->header.type == COAP_TYPE_CON)
- {
- item.timeout = item.timeout_val;
- item.retrans_count = 0;
- }
- else
- {
- item.timeout = COAP_MAX_TRANSMISSION_SPAN;
- item.retrans_count = COAP_MAX_RETRANSMIT_COUNT;
- }
- item.port = p_message->port;
- item.token_len = p_message->header.token_len;
- memcpy(&item.remote, &p_message->remote, sizeof(coap_remote_t));
- memcpy(item.token, p_message->token, p_message->header.token_len);
- err_code = coap_queue_add(&item);
- if (err_code != NRF_SUCCESS)
- {
- COAP_TRC("Message queue error = 0x%08lX!", err_code);
- COAP_TRC("Free mem, p_buffer = %p", p_buffer);
- UNUSED_VARIABLE(nrf_free(p_buffer));
- return err_code;
- }
- *p_handle = item.handle;
- }
- else
- {
- *p_handle = COAP_MESSAGE_QUEUE_SIZE;
- COAP_TRC("Free mem, p_buffer = %p", p_buffer);
- UNUSED_VARIABLE(nrf_free(p_buffer));
- }
- }
- else
- {
- COAP_TRC("Free mem, p_buffer = %p", p_buffer);
- UNUSED_VARIABLE(nrf_free(p_buffer));
- }
- COAP_EXIT();
- return err_code;
- }
- static uint32_t create_response(coap_message_t ** pp_response, coap_message_t * p_request, uint16_t data_size)
- {
- uint32_t err_code;
- // Allocate space for a new message.
- uint32_t size = sizeof(coap_message_t);
- err_code = nrf_mem_reserve((uint8_t **)pp_response, &size);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- coap_message_t * p_response = (*pp_response);
- memset(p_response, 0, sizeof(coap_message_t));
- COAP_TRC("Alloc mem, p_response = %p", (uint8_t *)p_response);
- if (data_size > 0)
- {
- // Allocate a scratch buffer for payload and options.
- size = data_size;
- err_code = nrf_mem_reserve(&(p_response->p_data), &size);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- memset(p_response->p_data, 0, size);
- p_response->data_len = size;
- COAP_TRC("Alloc mem, p_response->p_data = %p", p_response->p_data);
- }
- coap_message_conf_t config;
- memset (&config, 0, sizeof(coap_message_conf_t));
- config.token_len = p_request->header.token_len;
- config.id = p_request->header.id;
- config.code = COAP_CODE_404_NOT_FOUND;
- config.port.port_number = p_request->port.port_number;
- memcpy(config.token, p_request->token, p_request->header.token_len);
- if ((coap_msg_type_t)p_request->header.type == COAP_TYPE_CON)
- {
- config.type = COAP_TYPE_ACK;
- }
- else
- {
- config.type = (coap_msg_type_t)p_request->header.type;
- }
- err_code = coap_message_create(p_response, &config);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- (void)coap_message_remote_addr_set(p_response, &p_request->remote);
- return NRF_SUCCESS;
- }
- /**@brief Common function for sending response error message
- *
- * @param[in] p_message Pointer to the original request message.
- * @param[in] code CoAP message code to send in the reponse.
- *
- * @retval NRF_SUCCESS If the response was sent out successfully.
- */
- static uint32_t send_error_response(coap_message_t * p_message, uint8_t code)
- {
- coap_message_t * p_error_response = NULL;
- uint32_t err_code = create_response(&p_error_response, p_message, COAP_MESSAGE_DATA_MAX_SIZE);
- if (err_code != NRF_SUCCESS)
- {
- // If message could not be created, notify the application.
- app_error_notify(err_code, p_message);
- return err_code;
- }
- // Set the response code.
- p_error_response->header.code = code;
- if (p_error_response != NULL)
- {
- uint32_t handle;
- err_code = internal_coap_message_send(&handle, p_error_response);
- COAP_TRC("Free mem, p_response->p_data = %p", p_error_response->p_data);
- UNUSED_VARIABLE(nrf_free(p_error_response->p_data));
- COAP_TRC("Free mem, p_response = %p", (uint8_t *)p_error_response);
- UNUSED_VARIABLE(nrf_free((uint8_t *)p_error_response));
- }
- return err_code;
- }
- uint32_t coap_transport_read(const coap_port_t * p_port,
- const coap_remote_t * p_remote,
- const coap_remote_t * p_local,
- uint32_t result,
- const uint8_t * p_data,
- uint16_t datalen)
- {
- COAP_ENTRY();
- // Discard all packets if not success or truncated.
- if (!(result == NRF_SUCCESS || result == UDP_TRUNCATED_PACKET))
- {
- return NRF_SUCCESS;
- }
- uint32_t err_code;
- coap_message_t * p_message;
- // Allocate space for a new message.
- uint32_t size = sizeof(coap_message_t);
- err_code = nrf_mem_reserve((uint8_t **)&p_message, &size);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- memset(p_message, 0, sizeof(coap_message_t));
- COAP_TRC("Alloc mem, p_message = %p", (uint8_t *)p_message);
- err_code = coap_message_decode(p_message, p_data, datalen);
- if (err_code != NRF_SUCCESS)
- {
- app_error_notify(err_code, p_message);
- UNUSED_VARIABLE(nrf_free((uint8_t *)p_message));
- return err_code;
- }
- // Copy the remote address information.
- memcpy(&p_message->remote, p_remote, sizeof(coap_remote_t));
- // Copy the destination address information.
- if (p_local)
- {
- memcpy(&p_message->local, p_local, sizeof(coap_remote_t));
- }
- // Copy the local port information.
- memcpy(&p_message->port, p_port, sizeof(coap_port_t));
- if (result == UDP_TRUNCATED_PACKET)
- {
- app_error_notify(result, p_message);
- }
- else if (is_ping(p_message))
- {
- COAP_MESSAGE_RST_SET(&p_message->remote, p_message->port.port_number, p_message->header.id);
- uint32_t handle;
- err_code = internal_coap_message_send(&handle, &m_coap_empty_message);
- }
- else if (is_ack(p_message) ||
- is_reset(p_message))
- {
- // Populate the token with the one used sending, before passing it to the application.
- coap_queue_item_t * p_item = NULL;
- err_code = coap_queue_item_by_mid_get(&p_item, p_message->header.id);
- if (err_code == NRF_SUCCESS)
- {
- if (p_item->callback != NULL)
- {
- // As the token is missing from peer, it will be added before giving it to the application.
- memcpy(p_message->token, p_item->token, p_item->token_len);
- p_message->header.token_len = p_item->token_len;
- // Compiled away if COAP_ENABLE_OBSERVE_CLIENT is not set to 1.
- coap_observe_client_response_handle(p_message, p_item);
- COAP_TRC(">> application callback");
- COAP_MUTEX_UNLOCK();
- if (is_ack(p_message))
- {
- p_item->callback(NRF_SUCCESS, p_item->p_arg, p_message);
- }
- else
- {
- p_item->callback(COAP_TRANSMISSION_RESET_BY_PEER, p_item->p_arg, p_message);
- }
- COAP_MUTEX_LOCK();
- COAP_TRC("<< application callback");
- }
- COAP_TRC("Free mem, p_item->p_buffer = %p", p_item->p_buffer);
- UNUSED_VARIABLE(nrf_free(p_item->p_buffer));
- // Remove the queue element, as a match occured.
- err_code = coap_queue_remove(p_item);
- }
- }
- else if (is_response(p_message->header.code))
- {
- COAP_TRC("CoAP message type: RESPONSE");
- coap_queue_item_t * p_item;
- err_code = coap_queue_item_by_token_get(&p_item, p_message->token, p_message->header.token_len);
- if (err_code != NRF_SUCCESS)
- {
- // Compiled away if COAP_ENABLE_OBSERVE_CLIENT is not set to 1.
- coap_observe_client_response_handle(p_message, NULL);
- UNUSED_VARIABLE(nrf_free((uint8_t *)p_message));
- COAP_MUTEX_UNLOCK();
- return err_code;
- }
- if (p_item->callback != NULL)
- {
- // Compiled away if COAP_ENABLE_OBSERVE_CLIENT is not set to 1.
- coap_observe_client_response_handle(p_message, p_item);
- COAP_TRC(">> application callback");
- COAP_MUTEX_UNLOCK();
- p_item->callback(NRF_SUCCESS, p_item->p_arg, p_message);
- COAP_MUTEX_LOCK();
- COAP_TRC("<< application callback");
- }
- COAP_TRC("Free mem, p_item->p_buffer = %p", p_item->p_buffer);
- UNUSED_VARIABLE(nrf_free(p_item->p_buffer));
- err_code = coap_queue_remove(p_item);
- }
- else if (is_request(p_message->header.code))
- {
- COAP_TRC("CoAP message type: REQUEST");
- if (m_request_handler != NULL)
- {
- uint32_t return_code = m_request_handler(p_message);
- // If success, then all processing and any responses has been sent
- // by the application callback.
- // If not success, then send an appropriate error message back to the
- // origin with the return_code from the callback.
- if (return_code != NRF_SUCCESS)
- {
- if (return_code == NRF_ERROR_NOT_FOUND)
- {
- // Send response with provided CoAP code.
- (void)send_error_response(p_message, COAP_CODE_404_NOT_FOUND);
- }
- else if (return_code == NRF_ERROR_NULL)
- {
- (void)send_error_response(p_message, COAP_CODE_405_METHOD_NOT_ALLOWED);
- }
- else
- {
- (void)send_error_response(p_message, COAP_CODE_400_BAD_REQUEST);
- }
- }
- }
- else
- {
- uint8_t * uri_pointers[COAP_RESOURCE_MAX_DEPTH] = {0, };
- uint8_t uri_path_count = 0;
- uint16_t index;
- for (index = 0; index < p_message->options_count; index++)
- {
- if (p_message->options[index].number == COAP_OPT_URI_PATH)
- {
- uri_pointers[uri_path_count++] = p_message->options[index].p_data;
- }
- }
- coap_resource_t * found_resource;
- err_code = coap_resource_get(&found_resource, uri_pointers, uri_path_count);
- if (found_resource != NULL)
- {
- if (found_resource->callback != NULL)
- {
- if (((found_resource->permission) & (1 << ((p_message->header.code) - 1))) > 0) // Has permission for the requested CoAP method.
- {
- COAP_MUTEX_UNLOCK();
- found_resource->callback(found_resource, p_message);
- COAP_MUTEX_LOCK();
- }
- else
- {
- // Reply with Method Not Allowed.
- err_code = send_error_response(p_message, COAP_CODE_405_METHOD_NOT_ALLOWED);
- }
- }
- else
- {
- // Reply with Method Not Allowed.
- err_code = send_error_response(p_message, COAP_CODE_405_METHOD_NOT_ALLOWED);
- }
- }
- else
- {
- // Reply with NOT FOUND.
- err_code = send_error_response(p_message, COAP_CODE_404_NOT_FOUND);
- }
- }
- }
- COAP_TRC("Free mem, p_message = %p", (uint8_t *)p_message);
- UNUSED_VARIABLE(nrf_free((uint8_t *)p_message));
- COAP_EXIT();
- return err_code;
- }
- uint32_t coap_message_send(uint32_t * p_handle, coap_message_t * p_message)
- {
- COAP_MUTEX_LOCK();
- uint32_t err_code = internal_coap_message_send(p_handle, p_message);
- COAP_MUTEX_UNLOCK();
- return err_code;
- }
- uint32_t coap_message_abort(uint32_t handle)
- {
- return NRF_ERROR_NOT_SUPPORTED;
- }
- uint32_t coap_message_new(coap_message_t ** p_request, coap_message_conf_t * p_config)
- {
- COAP_ENTRY();
- uint32_t err_code;
- // If port is not configured, return error and skip initialization of the message.
- if (p_config->port.port_number == 0)
- {
- return (NRF_ERROR_INVALID_PARAM | IOT_COAP_ERR_BASE);
- }
- COAP_MUTEX_LOCK();
- // Allocate space for a new message.
- uint32_t size = sizeof(coap_message_t);
- err_code = nrf_mem_reserve((uint8_t **)p_request, &size);
- if (err_code != NRF_SUCCESS)
- {
- COAP_MUTEX_UNLOCK();
- return err_code;
- }
- memset(*p_request, 0, sizeof(coap_message_t));
- COAP_TRC("Alloc mem, *p_request = %p", (uint8_t *)(*p_request));
- // Allocate a scratch buffer for payload and options.
- size = COAP_MESSAGE_DATA_MAX_SIZE;
- err_code = nrf_mem_reserve(&((*p_request)->p_data), &size);
- if (err_code != NRF_SUCCESS)
- {
- COAP_TRC("Allocation of message data buffer failed!");
- COAP_TRC("Free mem, *p_request = %p", (uint8_t *)(*p_request));
- UNUSED_VARIABLE(nrf_free((uint8_t *)(*p_request)));
- COAP_MUTEX_UNLOCK();
- return err_code;
- }
- memset((*p_request)->p_data, 0, size);
- (*p_request)->data_len = size;
- COAP_TRC("Alloc mem, (*p_request)->p_data = %p", (uint8_t *)((*p_request)->p_data));
- if (p_config->id == 0) // Message id is not set, generate one.
- {
- p_config->id = m_message_id_counter++;
- }
- err_code = coap_message_create(*p_request, p_config);
- COAP_MUTEX_UNLOCK();
- COAP_EXIT_WITH_RESULT(err_code);
- return err_code;
- }
- uint32_t coap_message_delete(coap_message_t * p_message)
- {
- COAP_ENTRY();
- COAP_MUTEX_LOCK();
- //If this is a request free the coap_message_t and the data buffer.
- COAP_TRC("Free mem, p_message->p_data = %p", p_message->p_data);
- UNUSED_VARIABLE(nrf_free(p_message->p_data));
- COAP_TRC("Free mem, p_message = %p", (uint8_t *)p_message);
- UNUSED_VARIABLE(nrf_free((uint8_t *)p_message));
- COAP_MUTEX_UNLOCK();
- COAP_EXIT();
- return NRF_SUCCESS;
- }
- uint32_t coap_time_tick(void)
- {
- COAP_MUTEX_LOCK();
- coap_transport_process();
- // Loop through the message queue to see if any packets needs retransmission, or has timed out.
- coap_queue_item_t * p_item = NULL;
- while (coap_queue_item_next_get(&p_item, p_item) == NRF_SUCCESS)
- {
- if (p_item->timeout == 0)
- {
- // If there is still retransmission attempts left.
- if (p_item->retrans_count < COAP_MAX_RETRANSMIT_COUNT)
- {
- p_item->timeout = p_item->timeout_val * 2;
- p_item->timeout_val = p_item->timeout;
- p_item->retrans_count++;
- // Retransmit the message.
- uint32_t err_code = coap_transport_write(&p_item->port, &p_item->remote, p_item->p_buffer, p_item->buffer_len);
- if (err_code != NRF_SUCCESS)
- {
- app_error_notify(err_code, NULL);
- }
- }
- // No more retransmission attempts left, or max transmit span reached.
- if ((p_item->timeout > COAP_MAX_TRANSMISSION_SPAN) ||
- (p_item->retrans_count >= COAP_MAX_RETRANSMIT_COUNT))
- {
- COAP_MUTEX_UNLOCK();
- p_item->callback(COAP_TRANSMISSION_TIMEOUT, p_item->p_arg, NULL);
- COAP_MUTEX_LOCK();
- COAP_TRC("Free mem, p_item->p_buffer = %p", p_item->p_buffer);
- UNUSED_VARIABLE(nrf_free(p_item->p_buffer));
- (void)coap_queue_remove(p_item);
- }
- }
- else
- {
- p_item->timeout--;
- }
- }
- COAP_MUTEX_UNLOCK();
- return NRF_SUCCESS;
- }
- uint32_t coap_request_handler_register(coap_request_handler_t p_request_handler)
- {
- COAP_MUTEX_LOCK();
- m_request_handler = p_request_handler;
- COAP_MUTEX_UNLOCK();
- return NRF_SUCCESS;
- }
- __WEAK void coap_transport_input(void)
- {
- // By default not implemented. Transport specific.
- }
- void coap_input(void)
- {
- COAP_MUTEX_LOCK();
- coap_transport_input();
- COAP_MUTEX_UNLOCK();
- }
|