aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap.c854
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap.h125
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_api.h663
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_block.c203
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_block.h126
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_codes.h115
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_message.c804
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_message.h158
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe.c688
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe.h248
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe_api.h222
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_option.c182
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_option.h161
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_queue.c182
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_queue.h153
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_resource.c274
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_resource.h110
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport.h165
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_dtls.c996
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_ipv6.c264
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_lwip.c255
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_socket.c292
22 files changed, 7240 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap.c
new file mode 100644
index 0000000..4d58384
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap.c
@@ -0,0 +1,854 @@
+/**
+ * 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();
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap.h
new file mode 100644
index 0000000..09d9ecb
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap.h
@@ -0,0 +1,125 @@
+/**
+ * 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.
+ *
+ */
+/** @file coap.h
+ *
+ * @defgroup iot_sdk_coap_api CoAP interface
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief Interface for the CoAP protocol.
+ */
+
+#ifndef COAP_H__
+#define COAP_H__
+
+#include "iot_errors.h"
+#include "coap_api.h"
+#include "sdk_os.h"
+
+/**
+ * @defgroup iot_coap_log Module's Log Macros
+ * @details Macros used for creating module logs which can be useful in understanding handling
+ * of events or actions on API requests. These are intended for debugging purposes and
+ * can be enabled by defining the COAP_ENABLE_LOGS to 1.
+ * @note If NRF_LOG_ENABLED is disabled, having COAP_ENABLE_LOGS has no effect.
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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); \
+ }
+
+/**@brief Verify that parameter members has been set by the application. */
+#define NULL_PARAM_MEMBER_CHECK(PARAM) \
+ if ((PARAM) == NULL) \
+ { \
+ return (NRF_ERROR_INVALID_PARAM | IOT_COAP_ERR_BASE); \
+ }
+#else
+
+#define NULL_PARAM_CHECK(PARAM)
+#define NULL_PARAM_MEMBER_CHECK(PARAM)
+
+#endif // COAP_DISABLE_API_PARAM_CHECK
+
+/**
+ * @defgroup iot_coap_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 the need to use an alternative architecture arises.
+ * @{
+ */
+#define COAP_MUTEX_LOCK() SDK_MUTEX_LOCK(m_coap_mutex) /**< Lock module using mutex */
+#define COAP_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_coap_mutex) /**< Unlock module using mutex */
+
+SDK_MUTEX_DEFINE(m_coap_mutex)
+
+/** @} */
+
+/**@brief Sends a CoAP message.
+ *
+ * @details Sends out a request using the underlying transport layer. Before sending, the
+ * \ref coap_message_t structure is serialized and added to an internal message queue
+ * in the library. The handle returned can be used to abort the message from being
+ * retransmitted at any time.
+ *
+ * @param[out] p_handle Handle to the message if CoAP CON/ACK messages has been used. Returned
+ * by reference.
+ * @param[in] p_message Message to be sent.
+ *
+ * @retval NRF_SUCCESS If the message was successfully encoded and scheduled for transmission.
+ */
+uint32_t internal_coap_message_send(uint32_t * p_handle, coap_message_t * p_message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_api.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_api.h
new file mode 100644
index 0000000..9bc0222
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_api.h
@@ -0,0 +1,663 @@
+/**
+ * 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.
+ *
+ */
+/** @file coap_api.h
+ *
+ * @defgroup iot_sdk_coap_api CoAP Application Programming Interface
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief Public API of Nordic's CoAP implementation.
+ *
+ */
+
+#ifndef COAP_API_H__
+#define COAP_API_H__
+
+#include <stdint.h>
+#include "coap_transport.h"
+#include "coap_codes.h"
+#include "sdk_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@defgroup COAP_CONTENT_TYPE_MASK Resource content type bitmask values
+ * @{ */
+#define COAP_CT_MASK_PLAIN_TEXT 0x01 /**< Content type Plain text supported in the endpoint resource. */
+#define COAP_CT_MASK_CHARSET_UTF8 0x02 /**< Content type Charset-UTF8 supported in the endpoint resource. */
+#define COAP_CT_MASK_APP_LINK_FORMAT 0x04 /**< Content type Application/link-format supported in the endpoint resource. */
+#define COAP_CT_MASK_APP_XML 0x08 /**< Content type Application/xml supported in the endpoint resource. */
+#define COAP_CT_MASK_APP_OCTET_STREAM 0x10 /**< Content type Application/octet-stream supported in the endpoint resource. */
+#define COAP_CT_MASK_APP_EXI 0x20 /**< Content type Application/exi supported in the endpoint resource. */
+#define COAP_CT_MASK_APP_JSON 0x40 /**< Content type Application/json supported in the endpoint resource. */
+/**@} */
+
+/**@defgroup COAP_METHOD_PERMISSION Resource method permission bitmask values
+ * @{ */
+#define COAP_PERM_NONE 0x0000 /**< Permission by default. Do not allow any method in the COAP/COAPS endpoint resource. */
+#define COAP_PERM_GET 0x0001 /**< Permission to allow GET method in the COAP endpoint resource. */
+#define COAP_PERM_POST 0x0002 /**< Permission to allow POST method in the COAP endpoint resource. */
+#define COAP_PERM_PUT 0x0004 /**< Permission to allow PUT method in the COAP endpoint resource. */
+#define COAP_PERM_DELETE 0x0008 /**< Permission to allow DELETE method in the COAP endpoint resource. */
+#define COAPS_PERM_GET 0x0010 /**< Permission to allow GET method in the COAPS endpoint resource. */
+#define COAPS_PERM_POST 0x0020 /**< Permission to allow POST method in the COAPS endpoint resource. */
+#define COAPS_PERM_PUT 0x0040 /**< Permission to allow PUT method in the COAPS endpoint resource. */
+#define COAPS_PERM_DELETE 0x0080 /**< Permission to allow DELETE method in the COAPS endpoint resource. */
+#define COAP_PERM_OBSERVE 0x0100 /**< Permission to allow OBSERVE of the endpoint resource. */
+/**@} */
+
+/**@cond */
+// Forward declare structs.
+typedef struct coap_message_t coap_message_t;
+typedef struct coap_resource_t coap_resource_t;
+/**@endcond */
+
+/**@brief Callback function to call upon undefined behaviour.
+ *
+ * @param[in] error_code Error code from CoAP module.
+ * @param[in] p_message CoAP message processed when error ocoured. Could be NULL.
+ */
+typedef void (*coap_error_callback_t)(uint32_t error_code, coap_message_t * p_message);
+
+/**@brief Callback function to be registered with CoAP messages.
+ *
+ * @param[in] status Response status. Possible status codes:
+ * NRF_SUCCESS If response was successfully received,
+ * COAP_TRANSMISSION_RESET_BY_PEER if a reset response was recieved or,
+ * COAP_TRANSMISSION_TIMEOUT if transmission
+ * @param[in] p_arg Miscellaneous pointer to application provided data that is associated with
+ * the message.
+ * @param[in] p_message Pointer to a CoAP Response message.
+ */
+typedef void (*coap_response_callback_t)(uint32_t status, void * p_arg, coap_message_t * p_message);
+
+/**@brief Handler function for manually handling all incoming requests.
+ *
+ * @details If the function is set, the error code given back will trigger error messages
+ * to be sent back by CoAP to indicate failure. Default error message will be 4.00
+ * BAD REQUEST. On success, it is expected that the callback has already sent a
+ * response message.
+ *
+ * @param[in] p_request Pointer to a CoAP Request message.
+ *
+ * @retval NRF_SUCCESS If the message was successfully has been handled.
+ * @retval NRF_ERROR_NOT_FOUND If the message did not match any recognized resources, and a
+ * 4.04 NOT FOUND error message should be sent back to the requester.
+ * @retval NRF_ERROR_NULL If the message resolved the resource and operation not permitted,
+ * and a 4.05 METHOD NOT ALLOWED error message should be sent back to
+ * the reqester.
+ *
+ */
+typedef uint32_t (*coap_request_handler_t)(coap_message_t * p_request);
+
+#ifdef COAP_AUTOMODE
+
+/**@brief Callback function to be registered with CoAP endpoint resources. in auto-mode.
+ *
+ * @details The callback needs to implement any action based on the request. The p_response message
+ * will automatically be sent as response when the callback function returns. The memory
+ * is allocated by the caller, so the application does not have to free up the memory used
+ * for the response.
+ *
+ * @param[in] p_resource Pointer to the request message's target resource.
+ * @param[in] p_request Pointer to the request message.
+ * @param[out] p_response Pointer to the prepared response message. The Application can override
+ * its values.
+ */
+typedef void (*coap_method_callback_t) (coap_resource_t * p_resource, coap_message_t * p_request, coap_message_t * p_response);
+
+#else // COAP_AUTOMODE
+
+/**@brief Callback function to be registered with CoAP endpoint resources. in auto-mode.
+ *
+ * @details The callback needs to implement any action based on the request. The callback is
+ * responsible of handling the sending of any response back to the requester. The memory
+ * for p_request will be freed up by the coap module after the callback has been
+ * completed.
+ *
+ * @param[in] p_resource Pointer to the request message's target resource.
+ * @param[in] p_request Pointer to the request message.
+ */
+typedef void (*coap_method_callback_t) (coap_resource_t * p_resource, coap_message_t * p_request);
+
+#endif // COAP_AUTOMODE
+
+/**@brief Enumeration of CoAP content types. */
+typedef enum
+{
+ COAP_CT_PLAIN_TEXT = 0, /**< Plain text content format number. Default. */
+ COAP_CT_APP_LINK_FORMAT = 40, /**< Application/link-format content format number. */
+ COAP_CT_APP_XML = 41, /**< Application/xml content format number. */
+ COAP_CT_APP_OCTET_STREAM = 42, /**< Application/octet-stream content format number. */
+ COAP_CT_APP_EXI = 47, /**< Application/exi content format number. */
+ COAP_CT_APP_JSON = 50 /**< Application/json content format number. */
+} coap_content_type_t;
+
+/**@brief Enumeration of CoAP options numbers. */
+
+#define COAP_OPT_RESERVED0 0 /**< Reserved option number. */
+#define COAP_OPT_IF_MATCH 1 /**< If-Match option number. */
+#define COAP_OPT_URI_HOST 3 /**< URI-Host option number. */
+#define COAP_OPT_ETAG 4 /**< ETag option number. */
+#define COAP_OPT_IF_NONE_MATCH 5 /**< If-None-Match option number. */
+#define COAP_OPT_URI_PORT 7 /**< URI-Port option number. */
+#define COAP_OPT_LOCATION_PATH 8 /**< Location-Path option number. */
+#define COAP_OPT_URI_PATH 11 /**< URI-Path option number. */
+#define COAP_OPT_CONTENT_FORMAT 12 /**< Content-Format option number. */
+#define COAP_OPT_MAX_AGE 14 /**< Max-Age option number. */
+#define COAP_OPT_URI_QUERY 15 /**< URI-Query option number. */
+#define COAP_OPT_ACCEPT 17 /**< Accept option number. */
+#define COAP_OPT_LOCATION_QUERY 20 /**< Location-Query option number. */
+#define COAP_OPT_BLOCK2 23 /**< Block2 option number. */
+#define COAP_OPT_BLOCK1 27 /**< Block1 option number. */
+#define COAP_OPT_SIZE2 28 /**< Size2 option number. */
+#define COAP_OPT_PROXY_URI 35 /**< Proxy-URI option number. */
+#define COAP_OPT_PROXY_SCHEME 39 /**< Proxy-Scheme option number. */
+#define COAP_OPT_SIZE1 60 /**< Size1 option number. */
+#define COAP_OPT_RESERVED1 128 /**< Reserved option number. */
+#define COAP_OPT_RESERVED2 132 /**< Reserved option number. */
+#define COAP_OPT_RESERVED3 136 /**< Reserved option number. */
+#define COAP_OPT_RESERVED4 140 /**< Reserved option number. */
+
+
+/**@brief Enumeration of CoAP message types. */
+typedef enum
+{
+ COAP_TYPE_CON = 0, /**< Confirmable Message type. */
+ COAP_TYPE_NON, /**< Non-Confirmable Message type. */
+ COAP_TYPE_ACK, /**< Acknowledge Message type. */
+ COAP_TYPE_RST /**< Reset Message type. */
+} coap_msg_type_t;
+
+/**@brief Structure to hold a CoAP option.
+ */
+typedef struct
+{
+ uint16_t number; /**< Option number (including the extended delta value if any). */
+ uint16_t length; /**< Option length (including the extended length value in any). */
+ uint8_t * p_data; /**< Pointer to the memory where the data of the option is located. */
+} coap_option_t;
+
+
+
+/**@brief Structure to hold a CoAP message configuration.
+ *
+ * @details The structure is used when calling the \ref coap_message_new API function.
+ * All data supplied will be copied to the created message.
+ */
+typedef struct
+{
+ coap_response_callback_t response_callback; /**< Callback function to be called when a response matching the token is identified. */
+ uint8_t token[8]; /**< Message token. token_len must be set to indicate how many of the bytes should be used in the token. */
+ uint8_t token_len; /**< Token size in bytes. */
+ uint16_t id; /**< Message ID. If 0 is given, the library will replace this number with an autogenerated value. */
+ coap_msg_type_t type; /**< Message type: COAP_TYPE_CON, COAP_TYPE_NON, COAP_TYPE_ACK, or COAP_TYPE_RST. */
+ coap_msg_code_t code; /**< Message code (definitions found in coap_msg_code_t). */
+ coap_port_t port; /**< Transport layer variable to associate the message with an underlying Transport Layer socket descriptor. */
+} coap_message_conf_t;
+
+/**@brief Structure to hold a CoAP message header.
+ *
+ * @details This structure holds the 4-byte mandatory CoAP header. The structure uses bitfields
+ * to save memory footprint.
+ */
+typedef struct
+{
+ uint8_t version :2; /**< CoAP version number. The current specification RFC7252 mandates this to be version 1. The version number can be modified in sdk_config.h. */
+ uint8_t type :2; /**< Message type: COAP_TYPE_CON, COAP_TYPE_NON, COAP_TYPE_ACK, or COAP_TYPE_RST. */
+ uint8_t token_len :4; /**< Length of the message token. */
+ uint8_t code; /**< Message code (definitions found in @ref coap_msg_code_t). */
+ uint16_t id; /**< Message ID in little-endian format. Convertion to Network Byte Order will be handled by the library. */
+} coap_message_header_t;
+
+/**@brief Structure to hold a CoAP message.
+ *
+ * @details The CoAP message structure contains both internal and public members to
+ * serialize and deserialize data supplied from the application to a byte buffer sent
+ * over UDP. The message structure is used both in transmission and reception, which
+ * makes it easy to handle in an application. Updating the message should be done
+ * using the provided APIs, not by manually assigning new values to the members directly.
+ * Reading the members, on the other hand, is fine.
+ */
+struct coap_message_t
+{
+ coap_remote_t remote; /**< Public. Structure containing address information and port number to the remote. */
+ coap_remote_t local; /**< Public. Structure containing local destination address information and port number. */
+ coap_message_header_t header; /**< Public. Header structure containing the mandatory CoAP 4-byte header fields. */
+ uint8_t * p_payload; /**< Public. Pointer to the payload buffer in the message. */
+ uint16_t payload_len; /**< Public. Size of the payload in the message. */
+ uint8_t options_count; /**< Public. The number of options in the message. */
+ coap_option_t options[COAP_MAX_NUMBER_OF_OPTIONS]; /**< Public. Array options in the message. */
+ void * p_arg; /**< Public. Miscellaneous pointer to application provided data that is associated with the message. */
+
+ coap_response_callback_t response_callback; /**< Internal. Function callback set by the application to be called when a response to this message is received. Should be set by the application through a configuration parameter. */
+ uint8_t token[8]; /**< Internal. Array holding the variable-sized message token. Should be set by the application through a configuration parameter. */
+ coap_port_t port; /**< Internal. Transport layer variable to associate the message with an underlying Transport Layer socket descriptor. */
+ uint16_t options_len; /**< Internal. Length of the options including the mandatory header with extension bytes and option data. Accumulated every time a new options is added. */
+ uint16_t options_offset; /**< Internal. Index to where the next option or payload can be added in the message's data buffer */
+ uint16_t options_delta; /**< Internal. Current option number. Used to calculate the next option delta when adding new options to the message. */
+ uint8_t * p_data; /**< Internal. Data buffer for adding dynamically sized options and payload. */
+ uint16_t data_len; /**< Internal. Length of the provided data buffer for options and payload. */
+};
+
+
+/**@brief Structure to hold a CoAP endpoint resource.
+*/
+struct coap_resource_t
+{
+ uint8_t child_count; /**< Number of children in the linked list. */
+ uint16_t permission; /**< Bitmask to tell which methods are permitted on the resource. Bit values available can be seen in \ref COAP_METHOD_PERMISSION. */
+ coap_resource_t * p_sibling; /**< Sibling pointer to the next element in the list. */
+ coap_resource_t * p_front; /**< Pointer to the beginning of the linked list. */
+ coap_resource_t * p_tail; /**< Pointer to the last added child in the list. */
+ coap_method_callback_t callback; /**< Callback to the resource handler. */
+ uint32_t ct_support_mask; /**< Bitmask to tell which content types are supported by the resource. Bit values available can be seen in \ref COAP_CONTENT_TYPE_MASK. */
+ uint32_t max_age; /**< Max age of resource endpoint value. */
+ uint32_t expire_time; /**< Number of seconds until expire. */
+ char name[COAP_RESOURCE_MAX_NAME_LEN+1]; /**< Name of the resource. Must be zero terminated. */
+};
+
+/**@brief Initializes the CoAP module.
+ *
+ * @details Initializes the library module and resets internal queues and resource registrations.
+ *
+ * @param[in] token_rand_seed Random number seed to be used to generate the token numbers.
+ * @param[in] p_transport_params Pointer to transport parameters. Providing the list of ports
+ * to be used by CoAP.
+ *
+ * @retval NRF_SUCCESS If initialization succeeded.
+ */
+uint32_t coap_init(uint32_t token_rand_seed, coap_transport_init_t * p_transport_params);
+
+/**@brief Register error handler callback to the CoAP module.
+ *
+ * @param[in] error_callback Function to be called upon unknown messages and failure.
+ *
+ * @retval NRF_SUCCESS If registration was successful.
+ */
+uint32_t coap_error_handler_register(coap_error_callback_t error_callback);
+
+/**@brief Register request handler which should handle all incoming requests.
+ *
+ * @details Setting this request handler redirects all requests to the application provided
+ * callback routine. The callback handler might be cleared by NULL, making coap
+ * module handle the requests and do resource lookup in order to process the
+ * requests.
+ *
+ * @param[in] p_request_handler Function pointer to the provided request handler.
+ *
+ * @retval NRF_SUCCESS If registration was successful.
+ */
+uint32_t coap_request_handler_register(coap_request_handler_t p_request_handler);
+
+/**@brief Sends a CoAP message.
+ *
+ * @details Sends out a request using the underlying transport layer. Before sending, the
+ * \ref coap_message_t structure is serialized and added to an internal message queue
+ * in the library. The handle returned can be used to abort the message from being
+ * retransmitted at any time.
+ *
+ * @param[out] p_handle Handle to the message if CoAP CON/ACK messages has been used. Returned
+ * by reference.
+ * @param[in] p_message Message to be sent.
+ *
+ * @retval NRF_SUCCESS If the message was successfully encoded and scheduled for transmission.
+ */
+uint32_t coap_message_send(uint32_t * p_handle, coap_message_t * p_message);
+
+/**@brief Abort a CoAP message.
+ *
+ * @details Aborts an ongoing transmission. If the message has not yet been sent, it will be
+ * deleted from the message queue as well as stop any ongoing re-transmission of the
+ * message.
+ *
+ * @param[in] handle Handle of the message to abort.
+ *
+ * @retval NRF_SUCCESS If the message was successfully aborted and removed from the
+ * message queue.
+ * @retval NRF_ERROR_NOT_FOUND If the message with the given handle was not located in the
+ * message queue.
+ */
+uint32_t coap_message_abort(uint32_t handle);
+
+/**@brief Creates CoAP message, initializes, and allocates the needed memory.
+ *
+ * @details Creates a CoAP message. This is an intermediate representation of the message,
+ * because the message will be serialized by the library before it is transmitted. The structure
+ * is verbose to facilitate configuring the message. Options, payload, and
+ * remote address information can be added using API function calls.
+ *
+ * @param[inout] p_request Pointer to be filled by the allocated CoAP message structures.
+ * @param[in] p_config Configuration for the message to be created. Manual configuration
+ * can be performed after the message creation, except for the CLIENT port
+ * association.
+ *
+ * @retval NRF_SUCCESS If the request was successfully allocated and initialized.
+ * @retval NRF_ERROR_INVALID_PARAM If local port number was not configured.
+ */
+uint32_t coap_message_new(coap_message_t ** p_request, coap_message_conf_t * p_config);
+
+/**@brief Deletes the CoAP request message.
+ *
+ * @details Frees up memory associated with the request message.
+ *
+ * @param[in] p_message Pointer to the request message to delete.
+ */
+uint32_t coap_message_delete(coap_message_t * p_message);
+
+/**@brief Adds a payload to a CoAP message.
+ *
+ * @details Sets a data payload to a request or response message.
+ *
+ * This function must be called after all CoAP options have been added.
+ * Due to internal buffers in the library, the payload will be added after any options
+ * in the buffer. If an option is added after the payload, this option will over-write
+ * the payload in the internal buffer.
+ *
+ * @param[inout] p_message Pointer to the message to add the payload to.
+ * @param[in] p_payload Pointer to the payload to be added.
+ * @param[in] payload_len Size of the payload to be added.
+ *
+ * @retval NRF_SUCCESS If the payload was successfully added to the message.
+ * @retval NRF_ERROR_NO_MEM If the payload could not fit within the allocated payload memory
+ * defined by sdk_config.h COAP_MESSAGE_DATA_MAX_SIZE.
+ */
+uint32_t coap_message_payload_set(coap_message_t * p_message,
+ void * p_payload,
+ uint16_t payload_len);
+
+/**@brief Adds an empty CoAP option to the message.
+ *
+ * Option numbers must be in ascending order, adding the one with the smallest number
+ * first and greatest last. If the order is incorrect, the delta number calculation will
+ * result in an invalid or wrong delta number for the option.
+ *
+ * @param[inout] p_message Pointer to the message to add the option to. Should not be NULL.
+ * @param[in] option_num The option number to add to the message.
+ *
+ * @retval NRF_SUCCESS If the empty option was successfully added to the message.
+ * @retval NRF_ERROR_DATA_SIZE If the data exceeds the available message buffer data size.
+ * @retval NRF_ERROR_NO_MEM If the maximum number of options that can be added to a message has been reached.
+ */
+uint32_t coap_message_opt_empty_add(coap_message_t * p_message, uint16_t option_num);
+
+/**@brief Adds a uint CoAP option to the message.
+ *
+ * Option numbers must be in ascending order, adding the one with the smallest number
+ * first and greatest last. If the order is incorrect, the delta number calculation will
+ * result in an invalid or wrong delta number for the option.
+ *
+ * @param[inout] p_message Pointer to the message to add the option to. Should not be NULL.
+ * @param[in] option_num The option number to add to the message.
+ * @param[in] data An unsigned value (8-bit, 16-bit, or 32-bit) casted to uint32_t.
+ * The value of the data is used to determine how many bytes
+ * CoAP must use to represent this option value.
+ *
+ * @retval NRF_SUCCESS If the unsigned integer option was successfully added to the message.
+ * @retval NRF_ERROR_DATA_SIZE If the data exceeds the available message buffer data size.
+ * @retval NRF_ERROR_NO_MEM If the maximum number of options that can be added to a message has been reached.
+ */
+uint32_t coap_message_opt_uint_add(coap_message_t * p_message, uint16_t option_num, uint32_t data);
+
+/**@brief Adds a string CoAP option to the message.
+ *
+ * Option numbers must be in ascending order, adding the one with the smallest number
+ * first and greatest last. If the order is incorrect, the delta number calculation will
+ * result in an invalid or wrong delta number for the option.
+ *
+ * @param[inout] p_message Pointer to the message to add the option to. Should not be NULL.
+ * @param[in] option_num The option number to add to the message.
+ * @param[in] p_data Pointer to a string buffer to be used as value for the option.
+ * Should not be NULL.
+ * @param[in] length Length of the string buffer provided.
+ *
+ * @retval NRF_SUCCESS If the string option was successfully added to the message.
+ * @retval NRF_ERROR_DATA_SIZE If the data exceeds the available message buffer data size.
+ * @retval NRF_ERROR_NO_MEM If the maximum number of options that can be added to a message has been reached.
+ */
+uint32_t coap_message_opt_str_add(coap_message_t * p_message, uint16_t option_num, uint8_t * p_data, uint16_t length);
+
+/**@brief Adds an opaque CoAP option to the message.
+ *
+ * Option numbers must be in ascending order, adding the one with the smallest number
+ * first and greatest last. If the order is incorrect, the delta number calculation will
+ * result in an invalid or wrong delta number for the option.
+ *
+ * @param[inout] p_message Pointer to the message to add the option to. Should not be NULL.
+ * @param[in] option_num The option number to add to the message.
+ * @param[in] p_data Pointer to an opaque buffer to be used as value for the option.
+ * Should not be NULL.
+ * @param[in] length Length of the opaque buffer provided.
+ *
+ * @retval NRF_SUCCESS If the opaque option was successfully added to the message.
+ * @retval NRF_ERROR_DATA_SIZE If the data exceeds the available message buffer data size.
+ * @retval NRF_ERROR_NO_MEM If the maximum number of options that can be added to a message has been reached.
+ */
+uint32_t coap_message_opt_opaque_add(coap_message_t * p_message, uint16_t option_num, uint8_t * p_data, uint16_t length);
+
+/**@brief Sets a remote address and port number to a CoAP message.
+ *
+ * @details Copies the content of the provided pointer into the CoAP message.
+ *
+ * @param[inout] p_message Pointer to the message to add the address information to.
+ * Should not be NULL.
+ * @param[in] p_address Pointer to a structure holding the address information for the remote server or client.
+ * Should not be NULL.
+ *
+ * @retval NRF_SUCCESS When copying the content has finished.
+ */
+uint32_t coap_message_remote_addr_set(coap_message_t * p_message, coap_remote_t * p_address);
+
+/**@brief Creates a CoAP endpoint resource.
+ *
+ * @details Initializes the \ref coap_resource_t members.
+ *
+ * The first resource that is created will be set as the root of the resource
+ * hierarchy.
+ *
+ * @param[in] p_resource Pointer to coap_resource_t passed in by reference.
+ * This variable must be stored in non-volatile memory.
+ * Should not be NULL.
+ * @param[in] name Verbose name of the service (zero-terminated
+ * string). The maximum length of a name is defined
+ * by COAP_RESOURCE_MAX_NAME_LEN in @c sdk_config.h
+ * and can be adjusted if needed. Should not be NULL.
+ * @retval NRF_ERROR_DATA_SIZE If the provided name is larger than the available name buffer.
+ * @retval NRF_ERROR_NULL If the pointer to the resource or the provided
+ * name buffer is NULL.
+ */
+uint32_t coap_resource_create(coap_resource_t * p_resource, const char * name);
+
+/**@brief Adds a child resource.
+ *
+ * @details The hierarchy is constructed as a linked list with a maximum number of children.
+ * COAP_RESOURCE_MAX_DEPTH in @c sdk_config.h sets the maximum depth. The maximum
+ * number of children can be adjusted if more levels are needed.
+ *
+ * @param[in] p_parent Resource to attach the child to. Should not be NULL.
+ * @param[in] p_child Child resource to attach. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If the child was successfully added.
+ * @retval COAP_ERROR_MAX_DEPTH_REACHED If the child is exceeding the maximum depth defined.
+ */
+uint32_t coap_resource_child_add(coap_resource_t * p_parent, coap_resource_t * p_child);
+
+/**@brief Generates .well-known/core string.
+ *
+ * @details This is a helper function for generating a CoRE link-format encoded string used for
+ * CoAP discovery. The function traverse the resource hierarchy recursively.
+ * The result will be resources listed in link-format. This function can be called when
+ * all resources have been added by the application.
+ *
+ * @param[inout] string Buffer to use for the .well-known/core string. Should not be NULL.
+ * @param[inout] length Length of the string buffer. Returns the used number of bytes from
+ * the provided buffer.
+ *
+ * @retval NRF_SUCCESS If string generation was successful.
+ * @retval NRF_ERROR_NULL If the string buffer was a NULL pointer.
+ * @retval NRF_ERROR_DATA_SIZE If the size of the generated string exceeds the given buffer size.
+ * @retval NRF_ERROR_INVALID_STATE If no resource has been registered.
+ */
+uint32_t coap_resource_well_known_generate(uint8_t * string, uint16_t * length);
+
+/**@brief Get the root resource pointer.
+ *
+ * @param[out] pp_resource Pointer to be filled with pointer to the root resource.
+ *
+ * @retval NRF_SUCCESS If root resource was located.
+ * @retval NRF_ERROR_NOT_FOUND If root resource was not located.
+ * @retval NRF_ERROR_NULL If output pointer was NULL.
+ */
+uint32_t coap_resource_root_get(coap_resource_t ** pp_resource);
+
+/**@brief Check whether a message contains a given CoAP Option.
+ *
+ * @param[in] p_message Pointer to the to check for the CoAP Option.
+ * Should not be NULL.
+ * @param[in] option CoAP Option to check for in the CoAP message.
+ *
+ * @retval NRF_SUCCESS If the CoAP Option is present in the message.
+ * @retval NRF_ERROR_NULL If the pointer to the message is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If the CoAP Option is not present in the message.
+ */
+uint32_t coap_message_opt_present(coap_message_t * p_message, uint16_t option);
+
+/**@brief Check whether a message contains a given CoAP Option and return the index of the entry
+ * in the message option list.
+ *
+ * @param[in] p_index Value by reference to fill the resolved index into. Should not be NULL.
+ * @param[in] p_message Pointer to the to check for the CoAP Option.
+ * Should not be NULL.
+ * @param[in] option CoAP Option to check for in the CoAP message.
+ *
+ * @retval NRF_SUCCESS If the CoAP Option is present in the message.
+ * @retval NRF_ERROR_NULL If the pointer to the message or the p_index is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If the CoAP Option is not present in the message.
+ */
+uint32_t coap_message_opt_index_get(uint8_t * p_index, coap_message_t * p_message, uint16_t option);
+
+/**@brief Find common content type between the CoAP message and the resource.
+ *
+ * @details The return value will be the first match between the ACCEPT options and the supported
+ * content types in the resource. The priority is by content-format ID starting going
+ * from the lowest value to the highest.
+ *
+ * @param[out] p_ct Resolved content type given by reference. Should not be NULL.
+ * @param[in] p_message Pointer to the message. Should not be NULL.
+ * @param[in] p_resource Pointer to the resource. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If match was found.
+ * @retval NRF_ERROR_NOT_FOUND If no match was found.
+ */
+uint32_t coap_message_ct_match_select(coap_content_type_t * p_ct, coap_message_t * p_message, coap_resource_t * p_resource);
+
+/**@brief CoAP time tick used for retransmitting any message in the queue if needed.
+ *
+ * @retval NRF_SUCCESS If time tick update was successfully handled.
+ */
+uint32_t coap_time_tick(void);
+
+#if (COAP_DISABLE_DTLS_API == 0)
+/**@brief Setup secure DTLS session.
+ *
+ * @details For the client role, this API triggers a DTLS handshake. Until the handshake is complete
+ * with the remote, \ref coap_message_send will fail.
+ * For the server role, this API does not create any DTLS session. A DTLS session is
+ * created each time a new client remote endpoint sends a request on the local port of the
+ * server.
+ *
+ * @note The success of this function does not imply that the DTLS handshake is successfull.
+ *
+ * @note Only one DTLS session is permitted between a local and remote endpoint. Therefore, in case
+ * a DTLS session was established between the local and remote endpoint, the existing DTLS
+ * session will be reused irrespective of the role and number of times this API was called.
+ * In case the application desires a fresh security setup, it must first call the
+ * \ref coap_security_destroy to tear down the existing setup.
+ *
+ * @param[in] local_port Local port to bind the session to.
+ * @param[in] role Role of the session. DTLS server or client defined in the enumeration
+ * \ref nrf_tls_role_t.
+ * @param[in] p_remote Pointer to a structure holding the address information for the remote
+ * endpoint. If a the device is acting as a server, a NULL pointer shall be
+ * given as a parameter. Rationale: The server is not envisioned to be
+ * bound a pre-known client endpoint. Therefore, security server settings
+ * shall be setup irrespective of the remote client.
+ * @param[in] p_settings Pointer to a structure holding the DTLS credentials.
+ *
+ * @retval NRF_SUCCESS If setup of the secure DTLS session was successfull.
+ */
+uint32_t coap_security_setup(uint16_t local_port,
+ nrf_tls_role_t role,
+ coap_remote_t * const p_remote,
+ nrf_tls_key_settings_t * const p_settings);
+
+
+/**@brief Destroy a secure DTLS session.
+ *
+ * @details Terminate and clean up any session associated with the local port and the remote.
+ *
+ * @param[in] local_port Local port to unbind the session from.
+ * @param[in] p_remote Pointer to a structure holding the address information for the remote
+ * endpoint. Providing a NULL as p_remote will clean up all DTLS sessions
+ * associated with the local port.
+ *
+ * @retval NRF_SUCCESS If the destruction of the secure DTLS session was successfull.
+ */
+uint32_t coap_security_destroy(uint16_t local_port,
+ coap_remote_t * const p_remote);
+
+#endif // COAP_DISABLE_DTLS_API
+
+/**@brief Process loop when using coap BSD socket transport implementation.
+ *
+ * @details This is blocking call. The function unblock is only
+ * triggered upon an socket event registered to select() by coap transport.
+ * This function must be called as often as possible in order to dispatch incoming
+ * socket events. Preferred to be put in the application's main loop or similar.
+ **/
+void coap_input(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_API_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_block.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_block.c
new file mode 100644
index 0000000..f915f54
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_block.c
@@ -0,0 +1,203 @@
+/**
+ * Copyright (c) 2015 - 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 <stddef.h>
+
+#include "coap_block.h"
+#include "nrf_error.h"
+#include "iot_errors.h"
+#include "sdk_config.h"
+
+
+/**
+ * @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.
+ * COAP_DISABLE_API_PARAM_CHECK should be defined to disable these checks.
+ *
+ * @{
+ */
+#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 // COAP_DISABLE_API_PARAM_CHECK
+
+#define NULL_PARAM_CHECK(PARAM)
+
+#endif // COAP_DISABLE_API_PARAM_CHECK
+/** @} */
+
+
+#define BLOCK_SIZE_BASE_CONSTANT 4 /**< Block size base exponent. 4 means a base block size of 2^4 = 16 bytes. */
+
+#define BLOCK_SIZE_16 0 /**< Block size of 2^(4+0) = 16 bytes. */
+#define BLOCK_SIZE_32 1 /**< Block size of 2^(4+1) = 32 bytes. */
+#define BLOCK_SIZE_64 2 /**< Block size of 2^(4+2) = 64 bytes. */
+#define BLOCK_SIZE_128 3 /**< Block size of 2^(4+3) = 128 bytes. */
+#define BLOCK_SIZE_256 4 /**< Block size of 2^(4+4) = 256 bytes. */
+#define BLOCK_SIZE_512 5 /**< Block size of 2^(4+5) = 512 bytes. */
+#define BLOCK_SIZE_1024 6 /**< Block size of 2^(4+6) = 1024 bytes. */
+#define BLOCK_SIZE_2048_RESERVED 7 /**< Reserved. */
+
+#define BLOCK_MORE_BIT_UNSET 0 /**< Value when more flag is set. */
+#define BLOCK_MORE_BIT_SET 1 /**< Value when more flag is not set. */
+
+#define BLOCK_SIZE_POS 0 /**< Bit offset to the size. */
+#define BLOCK_MORE_BIT_POS 3 /**< Bit offset to the more bit. */
+#define BLOCK_NUMBER_POS 4 /**< Bit offset to the block number. */
+
+#define BLOCK_SIZE_MASK 0x7 /**< Block size mask. */
+#define BLOCK_MORE_BIT_MASK (1 << BLOCK_MORE_BIT_POS) /**< More bit mask. */
+#define BLOCK_NUMBER_MASK (0xFFFFF << 4) /**< Block number mask. */
+
+#define BLOCK_SIZE_MAX 0x7 /**< Maximum block size number. */
+#define BLOCK_MORE_BIT_MAX BLOCK_MORE_BIT_SET /**< Maximum more bit value. */
+#define BLOCK_NUMBER_MAX 0xFFFFF /**< Maximum block number. 20 bits max value is (1 << 20) - 1. */
+
+static uint32_t block_opt_encode(uint8_t more,
+ uint16_t size,
+ uint32_t number,
+ uint32_t * p_encoded)
+{
+ if ((number > BLOCK_NUMBER_MAX) || (more > BLOCK_MORE_BIT_MAX))
+ {
+ return (NRF_ERROR_INVALID_PARAM | IOT_COAP_ERR_BASE);
+ }
+
+ uint32_t val = 0;
+
+ switch (size)
+ {
+ case 16:
+ val = BLOCK_SIZE_16;
+ break;
+
+ case 32:
+ val = BLOCK_SIZE_32;
+ break;
+
+ case 64:
+ val = BLOCK_SIZE_64;
+ break;
+
+ case 128:
+ val = BLOCK_SIZE_128;
+ break;
+
+ case 256:
+ val = BLOCK_SIZE_256;
+ break;
+
+ case 512:
+ val = BLOCK_SIZE_512;
+ break;
+
+ case 1024:
+ val = BLOCK_SIZE_1024;
+ break;
+
+ case 2048:
+ // Falltrough.
+ default:
+ // Break omitted.
+ return (NRF_ERROR_INVALID_PARAM | IOT_COAP_ERR_BASE);
+ }
+
+ // Value has been initialized.
+ val |= (more) << BLOCK_MORE_BIT_POS;
+ val |= (number) << BLOCK_NUMBER_POS;
+
+ *p_encoded = val;
+ return NRF_SUCCESS;
+}
+
+static uint32_t block_opt_decode(uint32_t encoded,
+ uint8_t * p_more,
+ uint16_t * p_size,
+ uint32_t * p_number)
+{
+ if ((encoded & BLOCK_SIZE_MASK) == BLOCK_SIZE_2048_RESERVED)
+ {
+ return (NRF_ERROR_INVALID_DATA | IOT_COAP_ERR_BASE);
+ }
+
+ if ((encoded >> BLOCK_NUMBER_POS) > BLOCK_NUMBER_MAX)
+ {
+ return (NRF_ERROR_INVALID_PARAM | IOT_COAP_ERR_BASE);
+ }
+
+ *p_size = (1 << ((BLOCK_SIZE_BASE_CONSTANT + (encoded & BLOCK_SIZE_MASK))));
+ *p_more = (encoded & BLOCK_MORE_BIT_MASK) >> BLOCK_MORE_BIT_POS;
+ *p_number = (encoded & BLOCK_NUMBER_MASK) >> BLOCK_NUMBER_POS;
+
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_block_opt_block1_encode(uint32_t * p_encoded, coap_block_opt_block1_t * p_opt)
+{
+ NULL_PARAM_CHECK(p_encoded);
+ NULL_PARAM_CHECK(p_opt);
+ return block_opt_encode(p_opt->more, p_opt->size, p_opt->number, p_encoded);
+}
+
+uint32_t coap_block_opt_block1_decode(coap_block_opt_block1_t * p_opt, uint32_t encoded)
+{
+ NULL_PARAM_CHECK(p_opt);
+ return block_opt_decode(encoded, &p_opt->more, &p_opt->size, &p_opt->number);
+}
+
+uint32_t coap_block_opt_block2_encode(uint32_t * p_encoded, coap_block_opt_block2_t * p_opt)
+{
+ NULL_PARAM_CHECK(p_encoded);
+ NULL_PARAM_CHECK(p_opt);
+ return block_opt_encode(p_opt->more, p_opt->size, p_opt->number, p_encoded);
+}
+
+uint32_t coap_block_opt_block2_decode(coap_block_opt_block2_t * p_opt, uint32_t encoded)
+{
+ NULL_PARAM_CHECK(p_opt);
+ return block_opt_decode(encoded, &p_opt->more, &p_opt->size, &p_opt->number);
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_block.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_block.h
new file mode 100644
index 0000000..fa2e9ee
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_block.h
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2015 - 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.
+ *
+ */
+/** @file coap_block.h
+ *
+ * @defgroup iot_sdk_coap_block CoAP Block transfer
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief CoAP block transfer options encoding and decoding interface and definitions.
+ *
+ */
+
+#ifndef COAP_BLOCK_H__
+#define COAP_BLOCK_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COAP_BLOCK_OPT_BLOCK_MORE_BIT_UNSET 0 /**< Value when more flag is set. */
+#define COAP_BLOCK_OPT_BLOCK_MORE_BIT_SET 1 /**< Value when more flag is not set. */
+
+typedef struct
+{
+ uint8_t more; /**< More bit value. */
+ uint16_t size; /**< Size of the block in bytes. */
+ uint32_t number; /**< Block number. */
+} coap_block_opt_block1_t;
+
+typedef coap_block_opt_block1_t coap_block_opt_block2_t;
+
+/**@brief Encode block1 option into its uint binary counter part.
+ *
+ * @param[out] p_encoded Encoded version of the coap block1 option value. Must not be NULL.
+ * @param[in] p_opt Pointer to block1 option structure to be decoded into uint format. Must
+ * not be NULL.
+ *
+ * @retval NRF_SUCCESS If encoding of option was successful.
+ * @retval NRF_ERROR_NULL If one of the parameters supplied is a null pointer.
+ * @retval NRF_ERROR_INVALID_PARAM If one of the fields in the option structure has an illegal
+ * value.
+ */
+uint32_t coap_block_opt_block1_encode(uint32_t * p_encoded, coap_block_opt_block1_t * p_opt);
+
+/**@brief Decode block1 option from a uint to its structure counter part.
+ *
+ * @param[out] p_opt Pointer to block1 option structure to be filled by the function. Must not
+ * be NULL.
+ * @param[in] encoded Encoded version of the coap block1 option value.
+ *
+ * @retval NRF_SUCCESS If decoding of the option was successful.
+ * @retval NRF_ERROR_NULL If p_opt parameter is NULL.
+ * @retval NRF_ERROR_INVALID_PARAM If the block number is higher then allowed by spec (more than
+ 20 bits).
+ * @retval NRF_ERROR_INVALID_DATA If the size has the value of the reserved 2048 value (7).
+ */
+uint32_t coap_block_opt_block1_decode(coap_block_opt_block1_t * p_opt, uint32_t encoded);
+
+/**@brief Encode block2 option into its uint binary counter part.
+ *
+ * @param[out] p_encoded Encoded version of the coap block2 option value. Must not be NULL.
+ * @param[in] p_opt Pointer to block2 option structure to be decoded into uint format. Must
+ * not be NULL.
+ *
+ * @retval NRF_SUCCESS If encoding of option was successful.
+ * @retval NRF_ERROR_NULL If one of the parameters supplied is a null pointer.
+ * @retval NRF_ERROR_INVALID_PARAM If one of the fields in the option structure has an illegal
+ * value.
+ */
+uint32_t coap_block_opt_block2_encode(uint32_t * p_encoded, coap_block_opt_block2_t * p_opt);
+
+/**@brief Decode block2 option from a uint to its structure counter part.
+ *
+ * @param[out] p_opt Pointer to block2 option structure to be filled by the function. Must not
+ * be NULL.
+ * @param[in] encoded Encoded version of the coap block2 option value.
+ *
+ * @retval NRF_SUCCESS If decoding of the option was successful.
+ * @retval NRF_ERROR_NULL If p_opt parameter is NULL.
+ * @retval NRF_ERROR_INVALID_PARAM If the block number is higher then allowed by spec (more than
+ 20 bits).
+ * @retval NRF_ERROR_INVALID_DATA If the size has the value of the reserved 2048 value (7).
+ */
+uint32_t coap_block_opt_block2_decode(coap_block_opt_block2_t * p_opt, uint32_t encoded);
+
+#endif // COAP_BLOCK_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_codes.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_codes.h
new file mode 100644
index 0000000..88b1d48
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_codes.h
@@ -0,0 +1,115 @@
+/**
+ * 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.
+ *
+ */
+/** @file coap_codes.h
+ *
+ * @defgroup iot_sdk_coap_codes CoAP Codes
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief CoAP message and response codes.
+ */
+
+#ifndef COAP_CODES_H__
+#define COAP_CODES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COAP_CODE(c, dd) \
+ ((((c) & 0x7) << 5) | (((1 ## dd) - 100) & 0x1F))
+/**
+ @note macro adds 1xx to the number in order to prevent dd from being
+ interpreted as octal.
+*/
+
+/*lint -save -e122 */ /* Suppress "Digit (8) too large for radix" */
+
+/** @brief CoAP Message codes
+*/
+typedef enum
+{
+ // CoAP Empty Message
+ COAP_CODE_EMPTY_MESSAGE = COAP_CODE(0,00), /**< CoAP code 0.00, Decimal: 0, Hex: 0x00. */
+
+ // CoAP Method Codes
+ COAP_CODE_GET = COAP_CODE(0,01), /**< CoAP code 0.01, Decimal: 1, Hex: 0x01. */
+ COAP_CODE_POST = COAP_CODE(0,02), /**< CoAP code 0.02, Decimal: 2, Hex: 0x02. */
+ COAP_CODE_PUT = COAP_CODE(0,03), /**< CoAP code 0.03, Decimal: 3, Hex: 0x03. */
+ COAP_CODE_DELETE = COAP_CODE(0,04), /**< CoAP code 0.04, Decimal: 4, Hex: 0x04. */
+
+ // CoAP Success Response Codes
+ COAP_CODE_201_CREATED = COAP_CODE(2,01), /**< CoAP code 2.01, Decimal: 65, Hex: 0x41. */
+ COAP_CODE_202_DELETED = COAP_CODE(2,02), /**< CoAP code 2.02, Decimal: 66, Hex: 0x42. */
+ COAP_CODE_203_VALID = COAP_CODE(2,03), /**< CoAP code 2.03, Decimal: 67, Hex: 0x43. */
+ COAP_CODE_204_CHANGED = COAP_CODE(2,04), /**< CoAP code 2.04, Decimal: 68, Hex: 0x44. */
+ COAP_CODE_205_CONTENT = COAP_CODE(2,05), /**< CoAP code 2.05, Decimal: 69, Hex: 0x45. */
+ COAP_CODE_231_CONTINUE = COAP_CODE(2,31), /**< CoAP code 2.31, Decimal: 95, Hex: 0x5F. */
+
+ // CoAP Client Error Response Codes
+ COAP_CODE_400_BAD_REQUEST = COAP_CODE(4,00), /**< CoAP code 4.00, Decimal: 128, Hex: 0x80. */
+ COAP_CODE_401_UNAUTHORIZED = COAP_CODE(4,01), /**< CoAP code 4.01, Decimal: 129, Hex: 0x81. */
+ COAP_CODE_402_BAD_OPTION = COAP_CODE(4,02), /**< CoAP code 4.02, Decimal: 130, Hex: 0x82. */
+ COAP_CODE_403_FORBIDDEN = COAP_CODE(4,03), /**< CoAP code 4.03, Decimal: 131, Hex: 0x83. */
+ COAP_CODE_404_NOT_FOUND = COAP_CODE(4,04), /**< CoAP code 4.04, Decimal: 132, Hex: 0x84. */
+ COAP_CODE_405_METHOD_NOT_ALLOWED = COAP_CODE(4,05), /**< CoAP code 4.05, Decimal: 133, Hex: 0x85. */
+ COAP_CODE_406_NOT_ACCEPTABLE = COAP_CODE(4,06), /**< CoAP code 4.06, Decimal: 134, Hex: 0x86. */
+ COAP_CODE_408_REQUEST_ENTITY_INCOMPLETE = COAP_CODE(4,08), /**< CoAP code 4.08, Decimal: 136, Hex: 0x88. */
+ COAP_CODE_412_PRECONDITION_FAILED = COAP_CODE(4,12), /**< CoAP code 4.12, Decimal: 140, Hex: 0x8C. */
+ COAP_CODE_413_REQUEST_ENTITY_TOO_LARGE = COAP_CODE(4,13), /**< CoAP code 4.13, Decimal: 141, Hex: 0x8D. */
+ COAP_CODE_415_UNSUPPORTED_CONTENT_FORMAT = COAP_CODE(4,15), /**< CoAP code 4.15, Decimal: 143, Hex: 0x8F. */
+
+ // CoAP Server Error Response Codes
+ COAP_CODE_500_INTERNAL_SERVER_ERROR = COAP_CODE(5,00), /**< CoAP code 5.00, Decimal: 160, Hex: 0xA0. */
+ COAP_CODE_501_NOT_IMPLEMENTED = COAP_CODE(5,01), /**< CoAP code 5.01, Decimal: 161, Hex: 0xA1. */
+ COAP_CODE_502_BAD_GATEWAY = COAP_CODE(5,02), /**< CoAP code 5.02, Decimal: 162, Hex: 0xA2. */
+ COAP_CODE_503_SERVICE_UNAVAILABLE = COAP_CODE(5,03), /**< CoAP code 5.03, Decimal: 163, Hex: 0xA3. */
+ COAP_CODE_504_GATEWAY_TIMEOUT = COAP_CODE(5,04), /**< CoAP code 5.04, Decimal: 164, Hex: 0xA4. */
+ COAP_CODE_505_PROXYING_NOT_SUPPORTED = COAP_CODE(5,05) /**< CoAP code 5.05, Decimal: 165, Hex: 0xA5. */
+} coap_msg_code_t;
+
+/*lint -restore */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_CODES_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_message.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_message.c
new file mode 100644
index 0000000..db0f7bf
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_message.c
@@ -0,0 +1,804 @@
+/**
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include "nordic_common.h"
+#include "coap_message.h"
+#include "coap_api.h"
+#include "iot_common.h"
+#include "sdk_config.h"
+#include "app_util.h"
+
+#define COAP_PAYLOAD_MARKER_SIZE 1
+
+/**@brief Verify that there is a index available for a new option. */
+#define OPTION_INDEX_AVAIL_CHECK(COUNT) \
+ if ((COUNT) >= COAP_MAX_NUMBER_OF_OPTIONS) \
+ { \
+ return (NRF_ERROR_NO_MEM | IOT_COAP_ERR_BASE); \
+ }
+
+#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)
+#define OPTION_INDEX_AVAIL_CHECK(COUNT)
+
+#endif // COAP_DISABLE_API_PARAM_CHECK
+
+uint32_t coap_message_create(coap_message_t * p_message, coap_message_conf_t * p_init_config)
+{
+ NULL_PARAM_CHECK(p_message);
+ NULL_PARAM_CHECK(p_init_config);
+
+ // Setting default value for version.
+ p_message->header.version = COAP_VERSION;
+
+ // Copy values from the init config.
+ p_message->header.type = p_init_config->type;
+ p_message->header.token_len = p_init_config->token_len;
+ p_message->header.code = p_init_config->code;
+ p_message->header.id = p_init_config->id;
+ p_message->response_callback = p_init_config->response_callback;
+ p_message->p_arg = NULL;
+
+ if (p_init_config->port.port_number == 0)
+ {
+ return (NRF_ERROR_INVALID_PARAM | IOT_COAP_ERR_BASE);
+ }
+ memcpy(&p_message->port, &p_init_config->port, sizeof(coap_port_t));
+
+ memcpy(p_message->token, p_init_config->token, sizeof(p_init_config->token));
+ return NRF_SUCCESS;
+}
+
+/**@brief Decode CoAP option
+ *
+ * @param[in] p_raw_option Pointer to the memory buffer where the raw option is located.
+ * @param[inout] p_message Pointer to the current message. Used to retrieve information about
+ * where current option delta and the size of free memory to add the
+ * values of the option. Used as a container where to put
+ * the parsed option.
+ * @param[out] byte_count Number of bytes parsed. Used to indicate where the next option
+ * might be located (if any left) in the raw message buffer.
+ *
+ * @retval NRF_SUCCESS If the option parsing went successful.
+ * @retval NRF_ERROR_DATA_SIZE If there is no more space left in the free memory to add the
+ * option value to the p_message.
+ */
+static uint32_t decode_option(const uint8_t * p_raw_option, coap_message_t * p_message, uint16_t * byte_count)
+{
+ uint16_t byte_index = 0;
+ uint8_t option_num = p_message->options_count;
+
+ // Calculate the option number.
+ uint16_t option_delta = (p_raw_option[byte_index] & 0xF0) >> 4;
+ // Calculate the option length.
+ uint16_t option_length = (p_raw_option[byte_index] & 0x0F);
+ byte_index++;
+
+ uint16_t acc_option_delta = p_message->options_delta;
+
+ if (option_delta == 13)
+ {
+ // read one additional byte to get the extended delta.
+ acc_option_delta += 13 + p_raw_option[byte_index++];
+
+ }
+ else if (option_delta == 14)
+ {
+ // read one additional byte to get the extended delta.
+ acc_option_delta += 269;
+ acc_option_delta += (p_raw_option[byte_index++] << 8);
+ acc_option_delta += (p_raw_option[byte_index++]);
+ }
+ else
+ {
+ acc_option_delta += option_delta;
+ }
+
+ // Set the accumlated delta as the option number.
+ p_message->options[option_num].number = acc_option_delta;
+
+ if (option_length == 13)
+ {
+ option_length = 13 + p_raw_option[byte_index++];
+ }
+ else if (option_length == 14)
+ {
+ option_length = 269;
+ option_length += (p_raw_option[byte_index++] << 8);
+ option_length += p_raw_option[byte_index++];
+ }
+
+ // Set the option length including extended bytes.
+ p_message->options[option_num].length = option_length;
+
+ // Point p_data to the memory where to find the option value.
+ p_message->options[option_num].p_data = (uint8_t *)&p_raw_option[byte_index];
+
+ // Update the delta counter with latest option number.
+ p_message->options_delta = p_message->options[option_num].number;
+
+ byte_index += p_message->options[option_num].length;
+ *byte_count = byte_index;
+
+ return NRF_SUCCESS;
+}
+
+
+/**@brief Encode CoAP option delta and length bytes.
+ *
+ * @param[inout] encoded_value Value to encode. In return the value after encoding.
+ * @param[out] encoded_value_ext The value of the encoded extended bytes.
+ *
+ * @return The size of the extended byte field.
+ */
+static inline uint8_t encode_extended_bytes(uint16_t * value,
+ uint16_t * value_ext)
+{
+ uint16_t raw_value = *value;
+
+ uint8_t ext_size = 0;
+
+ if (raw_value >= 269)
+ {
+ *value = 14;
+ *value_ext = raw_value - 269;
+ ext_size = 2;
+ }
+ else if (raw_value >= 13)
+ {
+ *value = 13;
+ *value_ext = raw_value - 13;
+ ext_size = 1;
+ }
+ else
+ {
+ *value = raw_value;
+ *value_ext = 0;
+ }
+
+ return ext_size;
+}
+
+
+static uint32_t encode_option(uint8_t * p_buffer, coap_option_t * p_option, uint16_t * byte_count)
+{
+ uint16_t delta_ext = 0;
+ uint16_t delta = p_option->number;
+
+ uint8_t delta_ext_size = encode_extended_bytes(&delta,
+ &delta_ext);
+
+ uint16_t length = p_option->length;
+ uint16_t length_ext = 0;
+
+ uint8_t length_ext_size = encode_extended_bytes(&length,
+ &length_ext);
+
+ if (p_buffer == NULL)
+ {
+ uint16_t header_size = 1;
+ *byte_count = header_size + delta_ext_size + length_ext_size + p_option->length;
+ return NRF_SUCCESS;
+ }
+
+ uint16_t byte_index = 0;
+
+ // Add the option header.
+ p_buffer[byte_index++] = ((delta & 0x0F) << 4) | (length & 0x0F);
+
+ // Add option delta extended bytes to the buffer.
+ if (delta_ext_size == 1)
+ {
+ // Add first byte of delta_ext to the option header.
+ p_buffer[byte_index++] = (uint8_t)delta_ext;
+ }
+ else if (delta_ext_size == 2)
+ {
+ // uint16 in Network Byte Order.
+ p_buffer[byte_index++] = (uint8_t)((delta_ext & 0xFF00) >> 8);
+ p_buffer[byte_index++] = (uint8_t)((delta_ext & 0x00FF));
+ }
+
+ if (length_ext_size == 1)
+ {
+ // Add first byte of length_ext to the option header.
+ p_buffer[byte_index++] = (uint8_t)length_ext;
+ }
+ else if (length_ext_size == 2)
+ {
+ // uint16 in Network Byte Order.
+ p_buffer[byte_index++] = (uint8_t)((length_ext & 0xFF00) >> 8);
+ p_buffer[byte_index++] = (uint8_t)((length_ext & 0x00FF));
+ }
+
+ memcpy(&p_buffer[byte_index], p_option->p_data, p_option->length);
+ *byte_count = byte_index + p_option->length;
+
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_message_decode(coap_message_t * p_message,
+ const uint8_t * p_raw_message,
+ uint16_t message_len)
+{
+ NULL_PARAM_CHECK(p_message);
+ NULL_PARAM_CHECK(p_raw_message);
+
+ // Check that the raw message contains the mandatory header.
+ if (message_len < 4)
+ {
+ return (NRF_ERROR_INVALID_LENGTH | IOT_COAP_ERR_BASE);
+ }
+
+ // Parse the content of the raw message buffer.
+ uint16_t byte_index = 0;
+
+ // Parse the 4 byte CoAP header.
+ p_message->header.version = (p_raw_message[byte_index] >> 6);
+ p_message->header.type = (coap_msg_type_t)((p_raw_message[byte_index] >> 4) & 0x03);
+ p_message->header.token_len = (p_raw_message[byte_index] & 0x0F);
+ byte_index++;
+
+ p_message->header.code = (coap_msg_code_t)p_raw_message[byte_index];
+ byte_index++;
+
+ p_message->header.id = p_raw_message[byte_index++] << 8;
+ p_message->header.id += p_raw_message[byte_index++];
+
+ // Parse the token, if any.
+ for (uint8_t index = 0; (byte_index < message_len) && (index < p_message->header.token_len); index++)
+ {
+ p_message->token[index] = p_raw_message[byte_index++];
+ }
+
+ p_message->options_count = 0;
+ p_message->options_delta = 0;
+
+ // Parse the options if any.
+ while ((byte_index < message_len) && (p_raw_message[byte_index] != COAP_PAYLOAD_MARKER))
+ {
+
+ uint32_t err_code;
+ uint16_t byte_count = 0;
+
+ err_code = decode_option(&p_raw_message[byte_index], p_message, &byte_count);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ p_message->options_count += 1;
+
+ byte_index += byte_count;
+ }
+
+ // If there any more bytes to parse this would be the payload.
+ if (byte_index < message_len)
+ {
+ // Verify that we have a payload marker.
+ if (p_raw_message[byte_index] == COAP_PAYLOAD_MARKER)
+ {
+ byte_index++;
+ }
+ else
+ {
+ return COAP_MESSAGE_INVALID_CONTENT;
+ }
+
+ p_message->payload_len = message_len - byte_index;
+ p_message->p_payload = (uint8_t *)&p_raw_message[byte_index];
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t coap_message_encode(coap_message_t * p_message,
+ uint8_t * p_buffer,
+ uint16_t * p_length)
+{
+ NULL_PARAM_CHECK(p_length);
+ NULL_PARAM_CHECK(p_message);
+
+ // calculated size
+ uint16_t total_packet_size = 4;
+
+ if (p_message->payload_len > 0)
+ {
+ total_packet_size += p_message->payload_len;
+ total_packet_size += COAP_PAYLOAD_MARKER_SIZE;
+ }
+
+ if (p_message->header.token_len > 8)
+ {
+ return (NRF_ERROR_INVALID_DATA | IOT_COAP_ERR_BASE);
+ }
+ total_packet_size += p_message->header.token_len;
+ total_packet_size += p_message->options_len;
+
+ // If this was a length check, return after setting the length in the output parameter.
+ if (*p_length == 0)
+ {
+ *p_length = total_packet_size;
+ return NRF_SUCCESS;
+ }
+
+ // Check that the buffer provided is sufficient.
+ if (*p_length < total_packet_size)
+ {
+ return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
+ }
+
+ if (((p_message->payload_len > 0 && p_message->p_payload == NULL)) ||
+ (p_buffer == NULL))
+ {
+ return COAP_MESSAGE_ERROR_NULL;
+ }
+
+ // Start filling the bytes.
+ uint16_t byte_index = 0;
+
+ // TODO: Verify the values of the header fields.
+ // if (version > 1)
+ // if (p_message->type > COAP_TYPE_RST)
+ // if (p_message->token_len > 8)
+
+
+ p_buffer[byte_index] = (((p_message->header.version & 0x3) << 6) | ((p_message->header.type & 0x3) << 4)) | (p_message->header.token_len & 0x0F);
+ byte_index++;
+
+ p_buffer[byte_index] = p_message->header.code;
+ byte_index++;
+
+ p_buffer[byte_index++] = (p_message->header.id & 0xFF00) >> 8;
+ p_buffer[byte_index++] = (p_message->header.id & 0x00FF);
+
+ memcpy(&p_buffer[byte_index], p_message->token, p_message->header.token_len);
+ byte_index += p_message->header.token_len;
+
+ //memcpy(&p_buffer[byte_index], &p_message->p_data[0], p_message->options_len);
+ for (uint8_t i = 0; i < p_message->options_count; i++)
+ {
+ uint32_t err_code;
+
+ uint16_t byte_count = 0;
+ err_code = encode_option(&p_buffer[byte_index], &p_message->options[i], &byte_count);
+ if (err_code == NRF_SUCCESS)
+ {
+ byte_index += byte_count;
+ }
+ else
+ {
+ // Throw an error.
+ }
+ }
+
+ if (p_message->payload_len > 0 && p_message->p_payload != NULL)
+ {
+ p_buffer[byte_index++] = 0xFF;
+ memcpy(&p_buffer[byte_index], p_message->p_payload, p_message->payload_len);
+ }
+
+ *p_length = total_packet_size;
+
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_message_opt_empty_add(coap_message_t * p_message, uint16_t option_num)
+{
+ OPTION_INDEX_AVAIL_CHECK(p_message->options_count);
+
+ uint32_t err_code;
+ uint16_t encoded_len = 0;
+ uint8_t current_option_index = p_message->options_count;
+
+ p_message->options[current_option_index].number = option_num - p_message->options_delta;
+ p_message->options[current_option_index].length = encoded_len;
+
+ // Set accumulated option delta for next option.
+ p_message->options_delta = option_num;
+
+ // Calculate option size
+ uint16_t option_byte_count = 0;
+
+ // do a length check to encode_option to get the header length.
+ err_code = encode_option(NULL, &p_message->options[current_option_index], &option_byte_count);
+
+ // Accumulate expected size of all options with headers.
+ p_message->options_len += option_byte_count;
+
+ p_message->options_count += 1;
+
+ return err_code;
+}
+
+uint32_t coap_message_opt_uint_add(coap_message_t * p_message,
+ uint16_t option_num,
+ uint32_t data)
+{
+ OPTION_INDEX_AVAIL_CHECK(p_message->options_count);
+
+ uint32_t err_code;
+ uint16_t encoded_len = p_message->data_len - p_message->options_offset;
+ uint8_t current_option_index = p_message->options_count;
+ uint8_t * p_next_option_data = &p_message->p_data[p_message->options_offset];
+
+ // If the value of the option is 0, do not encode the 0, as this can be omitted. (RFC7252 3.2)
+ if (data == 0)
+ {
+ encoded_len = 0;
+ }
+ else
+ {
+ err_code = coap_opt_uint_encode(p_next_option_data, &encoded_len, data);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+
+ p_message->options[current_option_index].p_data = p_next_option_data;
+ p_message->options[current_option_index].number = option_num - p_message->options_delta;
+ p_message->options[current_option_index].length = encoded_len;
+
+ // Set accumulated option delta for next option.
+ p_message->options_delta = option_num;
+
+ // Calculate option size.
+ uint16_t option_byte_count = 0;
+
+ // Do a length check to encode_option to get the header length.
+ err_code = encode_option(NULL, &p_message->options[current_option_index], &option_byte_count);
+
+ // Accumulate expected size of all options with headers.
+ p_message->options_len += option_byte_count;
+
+ p_message->options_count += 1;
+
+ // Increase the pointer offset for the next option data in the scratch buffer.
+ p_message->options_offset += encoded_len;
+
+ return err_code;
+}
+
+uint32_t coap_message_opt_str_add(coap_message_t * p_message, uint16_t option_num, uint8_t * p_data, uint16_t length)
+{
+ OPTION_INDEX_AVAIL_CHECK(p_message->options_count);
+
+ uint32_t err_code;
+
+ uint16_t encoded_len = length;
+ uint8_t current_option_index = p_message->options_count;
+ uint8_t * p_next_option_data = &p_message->p_data[p_message->options_offset];
+
+
+ err_code = coap_opt_string_encode(p_next_option_data, &encoded_len, p_data, length);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ p_message->options[current_option_index].p_data = p_next_option_data;
+ p_message->options[current_option_index].number = option_num - p_message->options_delta;
+ p_message->options[current_option_index].length = encoded_len;
+
+ // Set accumulated option delta for next option.
+ p_message->options_delta = option_num;
+
+ // Calculate option size
+ uint16_t option_byte_count = 0;
+
+ // do a length check to encode_option to get the header length.
+ err_code = encode_option(NULL, &p_message->options[current_option_index], &option_byte_count);
+
+ // Accumulate expected size of all options with headers.
+ p_message->options_len += option_byte_count;
+
+ p_message->options_count += 1;
+ p_message->options_offset += encoded_len;
+
+ return err_code;
+
+}
+
+uint32_t coap_message_opt_opaque_add(coap_message_t * p_message, uint16_t option_num, uint8_t * p_data, uint16_t length)
+{
+ OPTION_INDEX_AVAIL_CHECK(p_message->options_count);
+
+ // Check if it is possible to add a new option of this length.
+ if ((p_message->data_len - p_message->options_offset) < length)
+ {
+ return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
+ }
+
+ uint32_t err_code = NRF_SUCCESS;
+
+ uint16_t encoded_len = length;
+ uint8_t current_option_index = p_message->options_count;
+ uint8_t * p_next_option_data = &p_message->p_data[p_message->options_offset];
+
+
+ memcpy(p_next_option_data, p_data, encoded_len);
+
+ p_message->options[current_option_index].p_data = p_next_option_data;
+ p_message->options[current_option_index].number = option_num - p_message->options_delta;
+ p_message->options[current_option_index].length = encoded_len;
+
+ // Set accumulated option delta for next option.
+ p_message->options_delta = option_num;
+
+ // Calculate option size
+ uint16_t option_byte_count = 0;
+
+ // do a length check to encode_option to get the header length.
+ err_code = encode_option(NULL, &p_message->options[current_option_index], &option_byte_count);
+
+ // Accumulate expected size of all options with headers.
+ p_message->options_len += option_byte_count;
+
+ p_message->options_count += 1;
+ p_message->options_offset += encoded_len;
+
+ return err_code;
+}
+
+uint32_t coap_message_payload_set(coap_message_t * p_message,
+ void * p_payload,
+ uint16_t payload_len)
+{
+ // Check that there is available memory in the p_message->p_data scratch buffer.
+ if (payload_len > (COAP_MESSAGE_DATA_MAX_SIZE - p_message->options_offset))
+ {
+ return (NRF_ERROR_NO_MEM | IOT_COAP_ERR_BASE);
+ }
+
+ p_message->p_payload = &p_message->p_data[p_message->options_offset];
+ p_message->payload_len = payload_len;
+ memcpy(p_message->p_payload, p_payload, payload_len);
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t coap_message_remote_addr_set(coap_message_t * p_message, coap_remote_t * p_address)
+{
+ memcpy(&p_message->remote, p_address, sizeof(coap_remote_t));
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_message_opt_index_get(uint8_t * p_index, coap_message_t * p_message, uint16_t option)
+{
+ NULL_PARAM_CHECK(p_index);
+ NULL_PARAM_CHECK(p_message);
+
+ uint8_t index;
+ for (index = 0; index < p_message->options_count; index++)
+ {
+ if (p_message->options[index].number == option)
+ {
+ *p_index = index;
+ return NRF_SUCCESS;
+ }
+ }
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+uint32_t coap_message_opt_present(coap_message_t * p_message, uint16_t option)
+{
+ NULL_PARAM_CHECK(p_message);
+
+ uint8_t index;
+ for (index = 0; index < p_message->options_count; index++)
+ {
+ if (p_message->options[index].number == option)
+ {
+ return NRF_SUCCESS;
+ }
+ }
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+static uint32_t bit_to_content_format(coap_content_type_t * p_ct, uint32_t bit)
+{
+ switch (bit)
+ {
+ case COAP_CT_MASK_PLAIN_TEXT:
+ *p_ct = COAP_CT_PLAIN_TEXT;
+ break;
+
+ case COAP_CT_MASK_APP_LINK_FORMAT:
+ *p_ct = COAP_CT_APP_LINK_FORMAT;
+ break;
+
+ case COAP_CT_MASK_APP_XML:
+ *p_ct = COAP_CT_APP_XML;
+ break;
+
+ case COAP_CT_MASK_APP_OCTET_STREAM:
+ *p_ct = COAP_CT_APP_OCTET_STREAM;
+ break;
+
+ case COAP_CT_MASK_APP_EXI:
+ *p_ct = COAP_CT_APP_EXI;
+ break;
+
+ case COAP_CT_MASK_APP_JSON:
+ *p_ct = COAP_CT_APP_JSON;
+ break;
+
+ default:
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+ return NRF_SUCCESS;
+}
+
+static uint32_t content_format_to_bit(coap_content_type_t ct)
+{
+ uint32_t mask = 0;
+ switch (ct)
+ {
+ case COAP_CT_PLAIN_TEXT:
+ mask = COAP_CT_MASK_PLAIN_TEXT;
+ break;
+
+ case COAP_CT_APP_LINK_FORMAT:
+ mask = COAP_CT_MASK_APP_LINK_FORMAT;
+ break;
+
+ case COAP_CT_APP_XML:
+ mask = COAP_CT_MASK_APP_XML;
+ break;
+
+ case COAP_CT_APP_OCTET_STREAM:
+ mask = COAP_CT_MASK_APP_OCTET_STREAM;
+ break;
+
+ case COAP_CT_APP_EXI:
+ mask = COAP_CT_MASK_APP_EXI;
+ break;
+
+ case COAP_CT_APP_JSON:
+ mask = COAP_CT_MASK_APP_JSON;
+ break;
+
+ default:
+ break;
+ }
+
+ return mask;
+}
+
+uint32_t coap_message_ct_mask_get(coap_message_t * p_message, uint32_t * p_mask)
+{
+ NULL_PARAM_CHECK(p_message);
+ NULL_PARAM_CHECK(p_mask);
+
+ (*p_mask) = 0;
+
+ for (uint8_t index = 0; index < p_message->options_count; index++)
+ {
+ if (p_message->options[index].number == COAP_OPT_CONTENT_FORMAT)
+ {
+ uint32_t value;
+ uint32_t err_code = coap_opt_uint_decode(&value,
+ p_message->options[index].length,
+ p_message->options[index].p_data);
+ if (err_code == NRF_SUCCESS)
+ {
+ coap_content_type_t ct = (coap_content_type_t)value;
+ *p_mask |= content_format_to_bit(ct);
+ }
+ else
+ {
+ return err_code;
+ }
+ }
+ }
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_message_accept_mask_get(coap_message_t * p_message, uint32_t * p_mask)
+{
+ NULL_PARAM_CHECK(p_message);
+ NULL_PARAM_CHECK(p_mask);
+
+ (*p_mask) = 0;
+
+ for (uint8_t index = 0; index < p_message->options_count; index++)
+ {
+ if (p_message->options[index].number == COAP_OPT_ACCEPT)
+ {
+ uint32_t value;
+ uint32_t err_code = coap_opt_uint_decode(&value,
+ p_message->options[index].length,
+ p_message->options[index].p_data);
+ if (err_code == NRF_SUCCESS)
+ {
+ coap_content_type_t ct = (coap_content_type_t)value;
+ (*p_mask) |= content_format_to_bit(ct);
+ }
+ else
+ {
+ return err_code;
+ }
+ }
+ }
+
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_message_ct_match_select(coap_content_type_t * p_ct, coap_message_t * p_message, coap_resource_t * p_resource)
+{
+ // Check ACCEPT options
+ uint32_t accept_mask = 0;
+ (void)coap_message_accept_mask_get(p_message, &accept_mask);
+
+ if (accept_mask == 0)
+ {
+ // Default to plain text if option not set.
+ accept_mask = COAP_CT_MASK_PLAIN_TEXT;
+ }
+
+ // Select the first common content-type between the resource and the CoAP client.
+ uint32_t common_ct = p_resource->ct_support_mask & accept_mask;
+ uint32_t bit_index;
+ for (bit_index = 0; bit_index < 32; bit_index++)
+ {
+ if (((common_ct >> bit_index) & 0x1 ) == 1)
+ {
+ break;
+ }
+ }
+
+ uint32_t err_code = bit_to_content_format(p_ct, 1 << bit_index);
+
+ return err_code;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_message.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_message.h
new file mode 100644
index 0000000..efd226b
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_message.h
@@ -0,0 +1,158 @@
+/**
+ * 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.
+ *
+ */
+/** @file coap_message.h
+ *
+ * @defgroup iot_sdk_coap_msg CoAP Message
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief TODO.
+ */
+
+#ifndef COAP_MESSAGE_H__
+#define COAP_MESSAGE_H__
+
+#include <stdint.h>
+#include "coap_api.h"
+#include "coap_codes.h"
+#include "coap_transport.h"
+#include "coap_option.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COAP_PAYLOAD_MARKER 0xFF
+
+/**@brief Create a new CoAP message.
+ *
+ * @details The function will allocate memory for the message internally and return
+ * a CoAP message structure. The callback provided will be called if a matching
+ * message ID/Token occurs in a response message.
+ * @param[out] p_message Pointer to set the generated coap_message_t structure to.
+ * @param[in] p_init_config Initial configuration parameters of the message to generate.
+ *
+ * @retval NRF_SUCCESS If memory for the new message was allocated and the
+ * initialization of the message went successfully.
+ * @retval NRF_ERROR_NULL Either the message or init_config parameter was NULL.
+ * @retval NRF_ERROR_INVALID_PARAM If port number in the port field is set to 0.
+ */
+uint32_t coap_message_create(coap_message_t * p_message, coap_message_conf_t * p_init_config);
+
+/**@brief Decode a message from a raw buffer.
+ *
+ * @details When the underlying transport layer receives a message, it has to
+ * be decoded into a CoAP message type structure. This functions returns
+ * a decoded message if decoding was successfully, or NULL otherwise.
+ *
+ * @param[out] p_message The generated coap_message_t after decoding the raw message.
+ * @param[in] p_raw_message Pointer to the encoded message memory buffer.
+ * @param[in] message_len Length of the p_raw_message.
+ *
+ * @retval NRF_SUCCESS If the decoding of the message succeeds.
+ * @retval NRF_ERROR_NULL If pointer to the p_message or p_raw_message were NULL.
+ * @retval NRF_ERROR_INVALID_LENGTH If the message is less than 4 bytes, not containing a
+ * full header.
+ * @retval COAP_MESSAGE_INVALID_CONTENT If the message could not be decoded successfully. This
+ * could happen if message length provided is larger than
+ * what is possible to decode (ex. missing payload marker).
+ *
+ */
+uint32_t coap_message_decode(coap_message_t * p_message,
+ const uint8_t * p_raw_message,
+ uint16_t message_len);
+
+/**@brief Encode a CoAP message into a byte buffer.
+ *
+ * @details This functions has two operations. One is the actual encoding into a
+ * byte buffer. The other is to query the size of a potential encoding.
+ * If p_buffer variable is omitted, the return value will be the size of a
+ * potential serialized message. This can be used to get some persistent memory from
+ * transport layer. The message have to be kept until all potential
+ * retransmissions has been attempted.
+ *
+ * The p_message can be deleted after this point if the function succeeds.
+ *
+ * @param[in] p_message Message to encode.
+ * @param[in] p_buffer Pointer to the byte buffer where to put the encoded message.
+ * @param[inout] p_length Length of the provided byte buffer passed in by reference.
+ * If the value 0 is supplied, the encoding will not take place,
+ * but only the dry run calculating the expected length of the
+ * encoded message.
+ *
+ * @retval NRF_SUCCESS If the encoding of the message succeeds.
+ * @retval NRF_ERROR_NULL If message or length parameter is NULL pointer.
+ * @retval NRF_ERROR_NO_MEM If the provided buffer is not sufficient for
+ * the encoded message.
+ * @retval COAP_MESSAGE_ERROR_NULL If the message has indicated the length of data,
+ * but memory pointer is NULL.
+ */
+uint32_t coap_message_encode(coap_message_t * p_message,
+ uint8_t * p_buffer,
+ uint16_t * p_length);
+
+/**@brief Get the content format mask of the message.
+ *
+ * @param[in] p_message Pointer to the message which to generate the content format mask from.
+ * Should not be NULL.
+ * @param[out] p_mask Value by reference to the variable to fill the result mask into.
+ *
+ * @retval NRF_SUCCESS If the mask could be generated.
+ * @retval NRF_ERROR_NULL If the message pointer or the mask pointer given was NULL.
+ */
+uint32_t coap_message_ct_mask_get(coap_message_t * p_message, uint32_t * p_mask);
+
+/**@brief Get the accept mask of the message.
+ *
+ * @param[in] p_message Pointer to the message which to generate the accept mask from.
+ * Should not be NULL.
+ * @param[out] p_mask Value by reference to the variable to fill the result mask into.
+ *
+ * @retval NRF_SUCCESS If the mask could be generated.
+ * @retval NRF_ERROR_NULL If the message pointer or the mask pointer given was NULL.
+ */
+uint32_t coap_message_accept_mask_get(coap_message_t * p_message, uint32_t * p_mask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_MESSAGE_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe.c
new file mode 100644
index 0000000..b4c60aa
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe.c
@@ -0,0 +1,688 @@
+/**
+ * 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 <string.h>
+
+#include "coap_observe_api.h"
+#include "coap_observe.h"
+#include "nrf_error.h"
+#include "iot_common.h"
+#include "sdk_common.h"
+#include "sdk_config.h"
+#include "coap.h"
+
+#if IOT_COAP_CONFIG_LOG_ENABLED
+
+#define NRF_LOG_MODULE_NAME coapobs
+
+#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__)
+
+#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(...)
+
+#endif // IOT_COAP_CONFIG_LOG_ENABLED
+
+#if (COAP_ENABLE_OBSERVE_SERVER == 1)
+static coap_observer_t m_observers[COAP_OBSERVE_MAX_NUM_OBSERVERS];
+
+static void observe_server_init(void)
+{
+ COAP_ENTRY();
+
+ // Loop through the observer array and clear the memory.
+ for (uint32_t i = 0; i < COAP_OBSERVE_MAX_NUM_OBSERVERS; i++)
+ {
+ memset(&m_observers[i], 0, sizeof(coap_observer_t));
+ }
+
+ COAP_EXIT();
+}
+
+uint32_t internal_coap_observe_server_register(uint32_t * p_handle, coap_observer_t * p_observer)
+{
+ COAP_ENTRY();
+
+ NULL_PARAM_CHECK(p_handle);
+ NULL_PARAM_CHECK(p_observer);
+
+ NULL_PARAM_MEMBER_CHECK(p_observer->p_resource_of_interest);
+
+ // Check if there is already a registered observer in the list to be reused.
+ uint32_t handle;
+ uint32_t err_code = coap_observe_server_search(&handle,
+ &p_observer->remote,
+ p_observer->p_resource_of_interest);
+ if (err_code == NRF_SUCCESS)
+ {
+ memcpy(&m_observers[handle], p_observer, sizeof(coap_observer_t));
+ *p_handle = handle;
+ return NRF_SUCCESS;
+ }
+
+ // Check if there is an available spot in the observer list.
+ for (uint32_t i = 0; i < COAP_OBSERVE_MAX_NUM_OBSERVERS; i++)
+ {
+ if (m_observers[i].p_resource_of_interest == NULL)
+ {
+ memcpy(&m_observers[i], p_observer, sizeof(coap_observer_t));
+
+ *p_handle = i;
+ return NRF_SUCCESS;
+ }
+ }
+
+
+ COAP_EXIT();
+
+ return (NRF_ERROR_NO_MEM | IOT_COAP_ERR_BASE);
+}
+
+
+uint32_t internal_coap_observe_server_unregister(uint32_t handle)
+{
+ COAP_ENTRY();
+
+ if (handle >= COAP_OBSERVE_MAX_NUM_OBSERVERS)
+ {
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+
+ if (m_observers[handle].p_resource_of_interest == NULL)
+ {
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+
+ m_observers[handle].p_resource_of_interest = NULL;
+
+ COAP_EXIT();
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t internal_coap_observe_server_search(uint32_t * p_handle,
+ coap_remote_t * p_observer_addr,
+ coap_resource_t * p_resource)
+{
+ NULL_PARAM_CHECK(p_handle);
+ NULL_PARAM_CHECK(p_observer_addr);
+ NULL_PARAM_CHECK(p_resource);
+
+ for (uint32_t i = 0; i < COAP_OBSERVE_MAX_NUM_OBSERVERS; i++)
+ {
+ if (m_observers[i].p_resource_of_interest == p_resource)
+ {
+ if (m_observers[i].remote.port_number == p_observer_addr->port_number)
+ {
+ if (memcmp(p_observer_addr->addr, m_observers[i].remote.addr, sizeof(p_observer_addr->addr)) == 0)
+ {
+ *p_handle = i;
+ return NRF_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+
+uint32_t internal_coap_observe_server_next_get(coap_observer_t ** pp_observer,
+ coap_observer_t * p_observer,
+ coap_resource_t * p_resource)
+{
+ NULL_PARAM_CHECK(p_resource);
+ NULL_PARAM_CHECK(pp_observer);
+
+ if (p_observer == NULL)
+ {
+ for (uint32_t i = 0; i < COAP_OBSERVE_MAX_NUM_OBSERVERS; i++)
+ {
+ if (m_observers[i].p_resource_of_interest == p_resource)
+ {
+ (*pp_observer) = &m_observers[i];
+ return NRF_SUCCESS;
+ }
+ }
+ }
+ else
+ {
+ uint32_t index_to_previous = (uint8_t)(((uint32_t)p_observer - (uint32_t)m_observers) / (uint32_t)sizeof(coap_observer_t));
+
+ for (uint32_t i = index_to_previous + 1; i < COAP_OBSERVE_MAX_NUM_OBSERVERS; i++)
+ {
+ if (m_observers[i].p_resource_of_interest == p_resource)
+ {
+ (*pp_observer) = &m_observers[i];
+ return NRF_SUCCESS;
+ }
+ }
+ }
+ (*pp_observer) = NULL;
+
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+uint32_t internal_coap_observe_server_get(uint32_t handle, coap_observer_t ** pp_observer)
+{
+ NULL_PARAM_CHECK(pp_observer);
+
+ if (handle >= COAP_OBSERVE_MAX_NUM_OBSERVERS)
+ {
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+
+ if (m_observers[handle].p_resource_of_interest == NULL)
+ {
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+
+ *pp_observer = &m_observers[handle];
+ return NRF_SUCCESS;
+}
+#else
+#define observe_server_init(...)
+#endif
+
+#if (COAP_ENABLE_OBSERVE_CLIENT == 1)
+static coap_observable_t m_observables[COAP_OBSERVE_MAX_NUM_OBSERVABLES];
+
+static void observe_client_init(void)
+{
+ // Loop through the observable array and clear the memory.
+ for (uint32_t i = 0; i < COAP_OBSERVE_MAX_NUM_OBSERVABLES; i++)
+ {
+ memset(&m_observables[i], 0, sizeof(coap_observable_t));
+ }
+}
+
+
+uint32_t internal_coap_observe_client_register(uint32_t * p_handle,
+ coap_observable_t * p_observable)
+{
+ COAP_ENTRY();
+
+ NULL_PARAM_CHECK(p_handle);
+ NULL_PARAM_CHECK(p_observable);
+
+ NULL_PARAM_MEMBER_CHECK(p_observable->response_callback);
+
+ // Check if there is an available spot in the observer list.
+ for (uint32_t i = 0; i < COAP_OBSERVE_MAX_NUM_OBSERVABLES; i++)
+ {
+ if (m_observables[i].response_callback == NULL)
+ {
+ memcpy(&m_observables[i], p_observable, sizeof(coap_observable_t));
+ *p_handle = i;
+ return NRF_SUCCESS;
+ }
+ }
+
+ COAP_EXIT();
+
+ return (NRF_ERROR_NO_MEM | IOT_COAP_ERR_BASE);
+}
+
+
+uint32_t internal_coap_observe_client_unregister(uint32_t handle)
+{
+ COAP_ENTRY();
+
+ if (handle >= COAP_OBSERVE_MAX_NUM_OBSERVABLES)
+ {
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+
+ if (m_observables[handle].response_callback == NULL)
+ {
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+
+ m_observables[handle].response_callback = NULL;
+
+ COAP_EXIT();
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t internal_coap_observe_client_search(uint32_t * p_handle, uint8_t * p_token, uint16_t token_len)
+{
+ NULL_PARAM_CHECK(p_handle);
+ NULL_PARAM_CHECK(p_token);
+
+ for (uint32_t i = 0; i < COAP_OBSERVE_MAX_NUM_OBSERVABLES; i++)
+ {
+ if ((m_observables[i].response_callback != NULL) &&
+ (0 != m_observables[i].token_len) &&
+ (memcmp(m_observables[i].token, p_token, m_observables[i].token_len) == 0))
+ {
+ *p_handle = i;
+ return NRF_SUCCESS;
+ }
+ }
+
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+
+uint32_t internal_coap_observe_client_get(uint32_t handle, coap_observable_t ** pp_observable)
+{
+ NULL_PARAM_CHECK(pp_observable);
+
+ if (handle >= COAP_OBSERVE_MAX_NUM_OBSERVABLES)
+ {
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+
+ if (m_observables[handle].response_callback == NULL)
+ {
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+ }
+
+ *pp_observable = &m_observables[handle];
+
+ return NRF_SUCCESS;
+}
+
+uint32_t internal_coap_observe_client_next_get(coap_observable_t ** pp_observable,
+ uint32_t * p_handle,
+ coap_observable_t * p_observable)
+{
+ NULL_PARAM_CHECK(pp_observable);
+
+ if (p_observable == NULL)
+ {
+ for (uint32_t i = 0; i < COAP_OBSERVE_MAX_NUM_OBSERVABLES; i++)
+ {
+ if (m_observables[i].response_callback != NULL)
+ {
+ (*pp_observable) = &m_observables[i];
+ (*p_handle) = i;
+ return NRF_SUCCESS;
+ }
+ }
+ }
+ else
+ {
+ uint32_t index_to_previous = (uint8_t)(((uint32_t)p_observable - (uint32_t)m_observables) / (uint32_t)sizeof(coap_observable_t));
+
+ for (uint32_t i = index_to_previous + 1; i < COAP_OBSERVE_MAX_NUM_OBSERVABLES; i++)
+ {
+ if (m_observables[i].response_callback != NULL)
+ {
+ (*pp_observable) = &m_observables[i];
+ (*p_handle) = i;
+ return NRF_SUCCESS;
+ }
+ }
+ }
+ (*pp_observable) = NULL;
+
+ COAP_MUTEX_UNLOCK();
+
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+static uint32_t observe_opt_present(coap_message_t * p_message)
+{
+ uint8_t index;
+ for (index = 0; index < p_message->options_count; index++)
+ {
+ if (p_message->options[index].number == COAP_OPT_OBSERVE)
+ {
+ return NRF_SUCCESS;
+ }
+ }
+ return NRF_ERROR_NOT_FOUND;
+}
+
+static void set_max_age(coap_observable_t * observable, coap_message_t * p_response)
+{
+ uint8_t index;
+ for (index = 0; index < p_response->options_count; index++)
+ {
+ if (p_response->options[index].number == COAP_OPT_MAX_AGE)
+ {
+ uint32_t max_age;
+ observable->max_age = coap_opt_uint_decode(&max_age,
+ p_response->options[index].length,
+ p_response->options[index].p_data);
+ observable->max_age = max_age;
+ return;
+ }
+ }
+
+ // Max-Age option is not present, set default value to 60.
+ observable->max_age = 60;
+}
+
+void coap_observe_client_send_handle(coap_message_t * p_request)
+{
+ COAP_ENTRY();
+
+ if (p_request->header.code == COAP_CODE_GET)
+ {
+ uint32_t observe_option = 0;
+ if (observe_opt_present(p_request) == NRF_SUCCESS)
+ {
+ // Locate option and check value.
+ uint8_t index;
+ for (index = 0; index < p_request->options_count; index++)
+ {
+ if (p_request->options[index].number == COAP_OPT_OBSERVE)
+ {
+ uint32_t err_code = coap_opt_uint_decode(&observe_option,
+ p_request->options[index].length,
+ p_request->options[index].p_data);
+ if (err_code != NRF_SUCCESS)
+ {
+ return;
+ }
+ break;
+ }
+ }
+ }
+
+ if (observe_option == 1)
+ {
+ // Un-register observable instance.
+ uint32_t handle;
+ uint32_t err_code = internal_coap_observe_client_search(&handle,
+ p_request->token,
+ p_request->header.token_len);
+ if (err_code == NRF_SUCCESS)
+ {
+ (void)internal_coap_observe_client_unregister(handle);
+ COAP_TRC("OBSERVE=1 in request, client_unregister handle: %i", handle);
+
+ }
+ }
+ }
+
+ COAP_EXIT();
+}
+
+void coap_observe_client_response_handle(coap_message_t * p_response, coap_queue_item_t * p_item)
+{
+ COAP_ENTRY();
+
+ if (observe_opt_present(p_response) == NRF_SUCCESS)
+ {
+ if (p_item == NULL)
+ {
+ // Search for the token in the observable list.
+ uint32_t handle;
+ uint32_t err_code = internal_coap_observe_client_search(&handle, p_response->token, p_response->header.token_len);
+ if (err_code == NRF_SUCCESS)
+ {
+ // Fetch the observable.
+ coap_observable_t * p_observable;
+ err_code = internal_coap_observe_client_get(handle, &p_observable);
+ if (err_code == NRF_SUCCESS)
+ {
+ // Update max-age to the newly recieved message.
+ set_max_age(p_observable, p_response);
+
+ COAP_MUTEX_UNLOCK();
+
+ // Callback to the application.
+ p_observable->response_callback(NRF_SUCCESS, NULL, p_response);
+
+ COAP_MUTEX_LOCK();
+
+ COAP_TRC("Notification received on handle: %i", handle);
+
+ #ifdef COAP_AUTOMODE
+ if (p_response->header.type == COAP_TYPE_CON)
+ {
+ // Reply an ACK upon CON message.
+ }
+ else if (p_response->header.type == COAP_TYPE_RST)
+ {
+ // Remove observable from list.
+ }
+ #endif
+ }
+ else
+ {
+ #ifdef COAP_AUTOMODE
+ if (p_response->header.type == COAP_TYPE_CON)
+ {
+ // Reply reset upon CON message when observer is not located.
+ }
+ #endif
+ }
+ }
+ else
+ {
+ // Send RST message back to server to indicate there is no one listening.
+ }
+ }
+ else // p_item set.
+ {
+ // If there is no observable instance created yet for thit token, add it.
+ uint32_t handle;
+ uint32_t err_code = internal_coap_observe_client_search(&handle, p_response->token, p_response->header.token_len);
+ if (err_code == (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE))
+ {
+ // If the response is a valid response, add the observable resource.
+ if (p_response->header.code == COAP_CODE_205_CONTENT)
+ {
+ coap_observable_t observable;
+ // Token Length.
+ observable.token_len = p_response->header.token_len;
+ // Remote.
+ memcpy(&observable.remote, &p_response->remote, sizeof(coap_remote_t));
+ // Token.
+ memcpy(observable.token, p_response->token, observable.token_len);
+ // Callback to be called upon notification.
+ observable.response_callback = p_item->callback;
+
+ // Update max-age to the newly recieved message.
+ set_max_age(&observable, p_response);
+
+ // Register the observable.
+ uint32_t observable_resource_handle;
+ (void)internal_coap_observe_client_register(&observable_resource_handle, &observable);
+ // TODO: error check
+
+ COAP_TRC("Subscription response received, client_register handle: %i", observable_resource_handle);
+ }
+ }
+ }
+ }
+ else // COAP_OPT_OBSERVE not present
+ {
+ uint32_t handle;
+ uint32_t err_code = internal_coap_observe_client_search(&handle, p_response->token, p_response->header.token_len);
+ if (err_code == NRF_SUCCESS)
+ {
+ (void)internal_coap_observe_client_unregister(handle);
+ COAP_TRC("OBSERVE not present in notification, client_unregister handle: %i", handle);
+ }
+ }
+
+ COAP_EXIT();
+}
+#else
+#define observe_client_init(...)
+#endif
+
+void internal_coap_observe_init(void)
+{
+ observe_server_init();
+ observe_client_init();
+}
+
+#if (COAP_ENABLE_OBSERVE_SERVER == 1)
+
+uint32_t coap_observe_server_register(uint32_t * p_handle, coap_observer_t * p_observer)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_server_register(p_handle, p_observer);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+uint32_t coap_observe_server_unregister(uint32_t handle)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_server_unregister(handle);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+uint32_t coap_observe_server_search(uint32_t * p_handle, coap_remote_t * p_observer_addr, coap_resource_t * p_resource)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_server_search(p_handle, p_observer_addr, p_resource);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+uint32_t coap_observe_server_next_get(coap_observer_t ** pp_observer, coap_observer_t * p_observer, coap_resource_t * p_resource)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_server_next_get(pp_observer, p_observer, p_resource);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+uint32_t coap_observe_server_get(uint32_t handle, coap_observer_t ** pp_observer)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_server_get(handle, pp_observer);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+#endif // COAP_ENABLE_OBSERVE_SERVER = 1
+
+#if (COAP_ENABLE_OBSERVE_CLIENT == 1)
+
+uint32_t coap_observe_client_register(uint32_t * p_handle, coap_observable_t * p_observable)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_client_register(p_handle, p_observable);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+uint32_t coap_observe_client_unregister(uint32_t handle)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_client_unregister(handle);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+uint32_t coap_observe_client_search(uint32_t * p_handle, uint8_t * p_token, uint16_t token_len)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_client_search(p_handle, p_token, token_len);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+uint32_t coap_observe_client_get(uint32_t handle, coap_observable_t ** pp_observable)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_client_get(handle, pp_observable);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+uint32_t coap_observe_client_next_get(coap_observable_t ** pp_observable, uint32_t * p_handle, coap_observable_t * p_observable)
+{
+ COAP_MUTEX_UNLOCK();
+
+ uint32_t err_code = internal_coap_observe_client_next_get(pp_observable, p_handle, p_observable);
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+#endif // COAP_ENABLE_OBSERVE_CLIENT == 1
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe.h
new file mode 100644
index 0000000..bb72b89
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe.h
@@ -0,0 +1,248 @@
+/**
+ * Copyright (c) 2015 - 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.
+ *
+ */
+/** @file coap_observe.h
+ *
+ * @defgroup iot_sdk_coap_observe CoAP Observe
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief Internal API of Nordic's CoAP Observe implementation.
+ */
+#ifndef COAP_OBSERVE_H__
+#define COAP_OBSERVE_H__
+
+#include <stdint.h>
+
+#include "coap_observe_api.h"
+#include "coap_api.h"
+#include "coap_queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@cond NO_DOXYGEN */
+
+/**@brief Register a new observer.
+ *
+ * @param[out] p_handle Handle to the observer instance registered. Returned by reference.
+ * Should not be NULL.
+ * @param[in] p_observer Pointer to the observer structure to register. The data will be
+ * copied. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If the observer was registered successfully.
+ * @retval NRF_ERROR_NO_MEM If the observer could not be added to the list.
+ * @retval NRF_ERROR_NULL If one of the parameters is a NULL pointer.
+ */
+uint32_t internal_coap_observe_server_register(uint32_t * p_handle, coap_observer_t * p_observer);
+
+/**@brief Unregister an observer.
+ *
+ * @details Unregister the observer and clear the memory used by this instance.
+ *
+ * @param[in] handle Handle to the observer instance registered.
+ *
+ * @retval NRF_SUCCESS If the observer was successfully unregistered.
+ * @retval NRF_ERROR_NOT_FOUND If the given handle was not found in the observer list.
+ */
+uint32_t internal_coap_observe_server_unregister(uint32_t handle);
+
+/**@brief Search the observer list for an observer matching remote address and subject given.
+ *
+ * @param[out] p_handle Handle to the observer instance registered. Returned by reference.
+ * Should not be NULL.
+ * @param[in] p_observer_addr Pointer to an address structure giving remote address of the observer and port number.
+ * Should not be NULL.
+ * @param[in] p_resource Pointer to the resource the observer is registered to. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If observer was found in the observer list.
+ * @retval NRF_ERROR_NULL If one of the pointers are NULL.
+ * @retval NRF_ERROR_NOT_FOUND If observer was not found.
+ */
+uint32_t internal_coap_observe_server_search(uint32_t * p_handle, coap_remote_t * p_observer_addr, coap_resource_t * p_resource);
+
+/**@brief Iterate through observers subscribing to a specific resource.
+ *
+ * @param[out] pp_observer Pointer to be filled by the search function upon finding the next observer starting from
+ * from the p_observer pointer provided. Should not be NULL.
+ * @param[in] p_observer Pointer to the observer where to start the search.
+ * @param[in] p_resource Pointer to the resource of interest. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If observer was found.
+ * @retval NRF_ERROR_NULL If pp_observer or p_resource pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If next observer was not found.
+ */
+uint32_t internal_coap_observe_server_next_get(coap_observer_t ** pp_observer, coap_observer_t * p_observer, coap_resource_t * p_resource);
+
+/**@brief Retrieve the observer based on handle.
+ *
+ * @param[in] handle Handle to the coap_observer_t instance.
+ * @param[out] pp_observer Pointer to an observer return by reference.
+ * Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If observer was found in the observer list.
+ * @retval NRF_ERROR_NULL If pp_observer pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If observer associated with the handle was not found.
+ */
+uint32_t internal_coap_observe_server_get(uint32_t handle, coap_observer_t ** pp_observer);
+
+/**@brief Register a new observable resource.
+ *
+ * @param[out] p_handle Handle to the observable resource instance registered. Returned by
+ * reference. Should not be NULL.
+ * @param[in] p_observable Pointer to a observable resource structure to register. The structure
+ * will be copied. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If the observable resource was registered successfully.
+ * @retval NRF_ERROR_NO_MEM If the observable resource could not be added to the list.
+ * @retval NRF_ERROR_NULL If one of the parameters is a NULL pointer.
+ */
+uint32_t internal_coap_observe_client_register(uint32_t * p_handle, coap_observable_t * p_observable);
+
+/**@brief Unregister an observable resource.
+ *
+ * @details Unregister the observable resource and clear the memory used by this instance.
+ *
+ * @param[in] handle Handle to the observable resource instance registered.
+ *
+ * @retval NRF_SUCCESS If the observable resource was successfully unregistered.
+ * @retval NRF_ERROR_NOT_FOUND If the given handle was not found in the observable
+ * resource list.
+ */
+uint32_t internal_coap_observe_client_unregister(uint32_t handle);
+
+/**@brief Search for a observable resource instance by token.
+ *
+ * @param[out] p_handle Handle to the observable resource instance registered. Returned by
+ * reference. Should not be NULL.
+ * @param[in] p_token Pointer to the byte array holding the token id. Should not be NULL.
+ * @param[in] token_len Length of the token.
+ *
+ * @retval NRF_SUCCESS If observable resource was found in the observable
+ * resource list.
+ * @retval NRF_ERROR_NULL If one of the pointers are NULL.
+ * @retval NRF_ERROR_NOT_FOUND If observable resource was not found in the observable
+ * resource list.
+ */
+uint32_t internal_coap_observe_client_search(uint32_t * p_handle, uint8_t * p_token, uint16_t token_len);
+
+/**@brief Retrieve the observable resource based on handle.
+ *
+ * @param[in] handle Handle to the coap_observable_t instance.
+ * @param[out] pp_observable Pointer to an observable resource return by reference.
+ * Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If observable resource was found in the observable
+ * resource list.
+ * @retval NRF_ERROR_NULL If pp_observable pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If observable resource associated with the handle
+ * was not found.
+ */
+uint32_t internal_coap_observe_client_get(uint32_t handle, coap_observable_t ** pp_observable);
+
+/**@brief Iterate through observable resources.
+ *
+ * @param[out] pp_observable Pointer to be filled by the search function upon finding the next
+ * observable resource starting from from the pointer provided.
+ * Should not be NULL.
+ * @param[out] p_handle Handler to the observable resource found returned by reference. Should
+ * not be NULL.
+ * @param[in] p_observable Pointer to the observable resource where to start the search.
+ *
+ * @retval NRF_SUCCESS If observer was found.
+ * @retval NRF_ERROR_NULL If pp_observer or p_observer pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If next observer was not found.
+ */
+uint32_t internal_coap_observe_client_next_get(coap_observable_t ** pp_observable, uint32_t * p_handle, coap_observable_t * p_observable);
+
+
+#if (COAP_ENABLE_OBSERVE_SERVER == 1) || (COAP_ENABLE_OBSERVE_CLIENT == 1)
+
+/**@brief Internal function to initilize observer (client) and observable (server) lists.
+ *
+ * @retval NRF_SUCCESS If initialization was successful.
+ */
+void internal_coap_observe_init(void);
+
+#else // COAP_ENABLE_OBSERVE_SERVER || COAP_ENABLE_OBSERVE_CLIENT
+
+#define internal_coap_observe_init(...)
+
+#endif // COAP_ENABLE_OBSERVE_SERVER || COAP_ENABLE_OBSERVE_CLIENT
+
+#if (COAP_ENABLE_OBSERVE_CLIENT == 1)
+
+/**@brief Observe client function to be run when sending requests.
+ *
+ * @details The function will peek into the outgoing messages to see if any actions regarding
+ * subscription to observable resources has to be done.
+ *
+ * @param[in] p_request Pointer to the outgoing request.
+ */
+void coap_observe_client_send_handle(coap_message_t * p_request);
+
+/**@brief Observe client function to be run when response message has been received.
+ *
+ * @details The function will register and unregister observable resources based on the received
+ * response messages. Upon a notification max-age values will be updated, and the correct
+ * response callback will be called. If a notification is terminated by the peer, the function
+ * will automatically terminate the subscription from the client by unregistering the
+ * observable resource.
+ *
+ * @param[in] p_response Pointer to the response message received.
+ * @param[in] p_item Pointer to the queued element of the outgoing request.
+ */
+void coap_observe_client_response_handle(coap_message_t * p_response, coap_queue_item_t * p_item);
+
+#else // COAP_ENABLE_OBSERVE_CLIENT
+
+#define coap_observe_client_send_handle(...)
+#define coap_observe_client_response_handle(...)
+
+#endif // COAP_ENABLE_OBSERVE_CLIENT
+
+/**@endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_OBSERVE_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe_api.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe_api.h
new file mode 100644
index 0000000..3075e88
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_observe_api.h
@@ -0,0 +1,222 @@
+/**
+ * Copyright (c) 2015 - 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.
+ *
+ */
+/** @file coap_observe_api.h
+ *
+ * @defgroup iot_sdk_coap_observe CoAP Observe
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief Public API of Nordic's CoAP Observe implementation.
+ */
+#ifndef COAP_OBSERVE_API_H__
+#define COAP_OBSERVE_API_H__
+
+#include <stdint.h>
+#include "coap_api.h"
+#include "coap_transport.h"
+#include "coap_queue.h"
+#include "compiler_abstraction.h"
+#include "sdk_errors.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COAP_OPT_OBSERVE 6 /**< Observe option number. */
+
+/**@brief Struct for CoAP Server for holding an instance of a remote observer. */
+typedef struct
+{
+ coap_remote_t remote; /**< Remote address and port number. */
+ uint8_t token[8]; /**< Message Token ID. */
+ uint8_t token_len; /**< Length of the token. */
+ coap_content_type_t ct; /**< Content type to use when sending notifications. */
+ coap_resource_t * p_resource_of_interest; /**< Pointer to the resource of interest. */
+} coap_observer_t;
+
+/**@brief Struct for CoAP Client for holding an instance of a remote observable resource. */
+typedef struct
+{
+ coap_remote_t remote; /**< Remote address and port number. */
+ uint8_t token[8]; /**< Message Token ID. */
+ uint8_t token_len; /**< Length of the token. */
+ coap_response_callback_t response_callback; /**< Function callback set by the application to be called when a notifications has been received. Should be set by the application. */
+ uint32_t max_age; /**< Max-Age of the observable resources value. If timed out, the value is no longer valid as a representation of the observable resource. */
+} coap_observable_t;
+
+
+/**@brief Register a new observer.
+ *
+ * @param[out] p_handle Handle to the observer instance registered. Returned by reference.
+ * Should not be NULL.
+ * @param[in] p_observer Pointer to the observer structure to register. The data will be
+ * copied. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If the observer was registered successfully.
+ * @retval NRF_ERROR_NO_MEM If the observer could not be added to the list.
+ * @retval NRF_ERROR_NULL If one of the parameters is a NULL pointer.
+ */
+uint32_t coap_observe_server_register(uint32_t * p_handle, coap_observer_t * p_observer);
+
+/**@brief Unregister an observer.
+ *
+ * @details Unregister the observer and clear the memory used by this instance.
+ *
+ * @param[in] handle Handle to the observer instance registered.
+ *
+ * @retval NRF_SUCCESS If the observer was successfully unregistered.
+ * @retval NRF_ERROR_NOT_FOUND If the given handle was not found in the observer list.
+ */
+uint32_t coap_observe_server_unregister(uint32_t handle);
+
+/**@brief Search the observer list for an observer matching remote address and subject given.
+ *
+ * @param[out] p_handle Handle to the observer instance registered. Returned by reference.
+ * Should not be NULL.
+ * @param[in] p_observer_addr Pointer to an address structure giving remote address of the observer and port number.
+ * Should not be NULL.
+ * @param[in] p_resource Pointer to the resource the observer is registered to. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If observer was found in the observer list.
+ * @retval NRF_ERROR_NULL If one of the pointers are NULL.
+ * @retval NRF_ERROR_NOT_FOUND If observer was not found.
+ */
+uint32_t coap_observe_server_search(uint32_t * p_handle, coap_remote_t * p_observer_addr, coap_resource_t * p_resource);
+
+/**@brief Iterate through observers subscribing to a specific resource.
+ *
+ * @param[out] pp_observer Pointer to be filled by the search function upon finding the next observer starting from
+ * from the p_observer pointer provided. Should not be NULL.
+ * @param[in] p_observer Pointer to the observer where to start the search.
+ * @param[in] p_resource Pointer to the resource of interest. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If observer was found.
+ * @retval NRF_ERROR_NULL If pp_observer or p_resource pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If next observer was not found.
+ */
+uint32_t coap_observe_server_next_get(coap_observer_t ** pp_observer, coap_observer_t * p_observer, coap_resource_t * p_resource);
+
+/**@brief Retrieve the observer based on handle.
+ *
+ * @param[in] handle Handle to the coap_observer_t instance.
+ * @param[out] pp_observer Pointer to an observer return by reference.
+ * Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If observer was found in the observer list.
+ * @retval NRF_ERROR_NULL If pp_observer pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If observer associated with the handle was not found.
+ */
+uint32_t coap_observe_server_get(uint32_t handle, coap_observer_t ** pp_observer);
+
+/**@brief Register a new observable resource.
+ *
+ * @param[out] p_handle Handle to the observable resource instance registered. Returned by
+ * reference. Should not be NULL.
+ * @param[in] p_observable Pointer to a observable resource structure to register. The structure
+ * will be copied. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If the observable resource was registered successfully.
+ * @retval NRF_ERROR_NO_MEM If the observable resource could not be added to the list.
+ * @retval NRF_ERROR_NULL If one of the parameters is a NULL pointer.
+ */
+uint32_t coap_observe_client_register(uint32_t * p_handle, coap_observable_t * p_observable);
+
+/**@brief Unregister an observable resource.
+ *
+ * @details Unregister the observable resource and clear the memory used by this instance.
+ *
+ * @param[in] handle Handle to the observable resource instance registered.
+ *
+ * @retval NRF_SUCCESS If the observable resource was successfully unregistered.
+ * @retval NRF_ERROR_NOT_FOUND If the given handle was not found in the observable
+ * resource list.
+ */
+uint32_t coap_observe_client_unregister(uint32_t handle);
+
+/**@brief Search for a observable resource instance by token.
+ *
+ * @param[out] p_handle Handle to the observable resource instance registered. Returned by
+ * reference. Should not be NULL.
+ * @param[in] p_token Pointer to the byte array holding the token id. Should not be NULL.
+ * @param[in] token_len Length of the token.
+ *
+ * @retval NRF_SUCCESS If observable resource was found in the observable
+ * resource list.
+ * @retval NRF_ERROR_NULL If one of the pointers are NULL.
+ * @retval NRF_ERROR_NOT_FOUND If observable resource was not found in the observable
+ * resource list.
+ */
+uint32_t coap_observe_client_search(uint32_t * p_handle, uint8_t * p_token, uint16_t token_len);
+
+/**@brief Retrieve the observable resource based on handle.
+ *
+ * @param[in] handle Handle to the coap_observable_t instance.
+ * @param[out] pp_observable Pointer to an observable resource return by reference.
+ * Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If observable resource was found in the observable
+ * resource list.
+ * @retval NRF_ERROR_NULL If pp_observable pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If observable resource associated with the handle
+ * was not found.
+ */
+uint32_t coap_observe_client_get(uint32_t handle, coap_observable_t ** pp_observable);
+
+/**@brief Iterate through observable resources.
+ *
+ * @param[out] pp_observable Pointer to be filled by the search function upon finding the next
+ * observable resource starting from from the pointer provided.
+ * Should not be NULL.
+ * @param[out] p_handle Handler to the observable resource found returned by reference. Should
+ * not be NULL.
+ * @param[in] p_observable Pointer to the observable resource where to start the search.
+ *
+ * @retval NRF_SUCCESS If observer was found.
+ * @retval NRF_ERROR_NULL If pp_observer or p_observer pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If next observer was not found.
+ */
+uint32_t coap_observe_client_next_get(coap_observable_t ** pp_observable, uint32_t * p_handle, coap_observable_t * p_observable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_OBSERVE_API_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_option.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_option.c
new file mode 100644
index 0000000..0ae74be
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_option.c
@@ -0,0 +1,182 @@
+/**
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include "coap_option.h"
+#include "iot_common.h"
+
+#if (COAP_DISABLE_API_PARAM_CHECK == 0)
+
+#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_opt_string_encode(uint8_t * p_encoded, uint16_t * p_length, uint8_t * p_string, uint16_t str_len)
+{
+ NULL_PARAM_CHECK(p_encoded);
+ NULL_PARAM_CHECK(p_length);
+ NULL_PARAM_CHECK(p_string);
+
+ if (str_len > *p_length)
+ {
+ return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
+ }
+
+ memcpy(p_encoded, p_string, str_len);
+
+ *p_length = str_len;
+
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_opt_string_decode(uint8_t * p_string, uint16_t * p_length, uint8_t * p_encoded)
+{
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_opt_uint_encode(uint8_t * p_encoded, uint16_t * p_length, uint32_t data)
+{
+ NULL_PARAM_CHECK(p_encoded);
+ NULL_PARAM_CHECK(p_length);
+
+ uint16_t byte_index = 0;
+
+ if (data <= UINT8_MAX)
+ {
+ if (*p_length < sizeof(uint8_t))
+ {
+ return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
+ }
+
+ p_encoded[byte_index++] = (uint8_t)data;
+ }
+ else if (data <= UINT16_MAX)
+ {
+ if (*p_length < sizeof(uint16_t))
+ {
+ return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
+ }
+
+ p_encoded[byte_index++] = (uint8_t)((data & 0xFF00) >> 8);
+ p_encoded[byte_index++] = (uint8_t)(data & 0x00FF);
+ }
+ else
+ {
+ if (*p_length < sizeof(uint32_t))
+ {
+ return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
+ }
+
+ p_encoded[byte_index++] = (uint8_t)((data & 0xFF000000) >> 24);
+ p_encoded[byte_index++] = (uint8_t)((data & 0x00FF0000) >> 16);
+ p_encoded[byte_index++] = (uint8_t)((data & 0x0000FF00) >> 8);
+ p_encoded[byte_index++] = (uint8_t)(data & 0x000000FF);
+ }
+
+
+
+ *p_length = byte_index;
+
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_opt_uint_decode(uint32_t * p_data, uint16_t length, uint8_t * p_encoded)
+{
+ NULL_PARAM_CHECK(p_data);
+ NULL_PARAM_CHECK(p_encoded);
+
+ uint8_t byte_index = 0;
+ switch (length)
+ {
+ case 0:
+ {
+ *p_data = 0;
+ }
+ break;
+
+ case 1:
+ {
+ *p_data = 0;
+ *p_data |= p_encoded[byte_index++];
+ }
+ break;
+
+ case 2:
+ {
+ *p_data = 0;
+ *p_data |= (p_encoded[byte_index++] << 8);
+ *p_data |= (p_encoded[byte_index++]);
+ }
+ break;
+
+ case 3:
+ {
+ *p_data = 0;
+ *p_data |= (p_encoded[byte_index++] << 16);
+ *p_data |= (p_encoded[byte_index++] << 8);
+ *p_data |= (p_encoded[byte_index++]);
+ }
+ break;
+
+ case 4:
+ {
+ *p_data = 0;
+ *p_data |= (p_encoded[byte_index++] << 24);
+ *p_data |= (p_encoded[byte_index++] << 16);
+ *p_data |= (p_encoded[byte_index++] << 8);
+ *p_data |= (p_encoded[byte_index++]);
+ }
+ break;
+
+ default:
+ return (NRF_ERROR_INVALID_LENGTH | IOT_COAP_ERR_BASE);
+ }
+
+ return NRF_SUCCESS;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_option.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_option.h
new file mode 100644
index 0000000..3d5c5d9
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_option.h
@@ -0,0 +1,161 @@
+/**
+ * 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.
+ *
+ */
+/** @file coap_option.h
+ *
+ * @defgroup iot_sdk_coap_option CoAP Option
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief Nordic's CoAP Option APIs.
+ */
+
+#ifndef COAP_OPTION_H__
+#define COAP_OPTION_H__
+
+/*
+ +-----+---+---+---+---+----------------+--------+--------+----------+
+ | No. | C | U | N | R | Name | Format | Length | Default |
+ +-----+---+---+---+---+----------------+--------+--------+----------+
+ | 1 | x | | | x | If-Match | opaque | 0-8 | (none) |
+ | 3 | x | x | - | | Uri-Host | string | 1-255 | (see |
+ | | | | | | | | | below) |
+ | 4 | | | | x | ETag | opaque | 1-8 | (none) |
+ | 5 | x | | | | If-None-Match | empty | 0 | (none) |
+ | 7 | x | x | - | | Uri-Port | uint | 0-2 | (see |
+ | | | | | | | | | below) |
+ | 8 | | | | x | Location-Path | string | 0-255 | (none) |
+ | 11 | x | x | - | x | Uri-Path | string | 0-255 | (none) |
+ | 12 | | | | | Content-Format | uint | 0-2 | (none) |
+ | 14 | | x | - | | Max-Age | uint | 0-4 | 60 |
+ | 15 | x | x | - | x | Uri-Query | string | 0-255 | (none) |
+ | 17 | x | | | | Accept | uint | 0-2 | (none) |
+ | 20 | | | | x | Location-Query | string | 0-255 | (none) |
+ | 23 | x | x | - | - | Block2 | uint | 0-3 | (none) |
+ | 27 | x | x | - | - | Block1 | uint | 0-3 | (none) |
+ | 28 | | | x | | Size2 | uint | 0-4 | (none) |
+ | 35 | x | x | - | | Proxy-Uri | string | 1-1034 | (none) |
+ | 39 | x | x | - | | Proxy-Scheme | string | 1-255 | (none) |
+ | 60 | | | x | | Size1 | uint | 0-4 | (none) |
+ +-----+---+---+---+---+----------------+--------+--------+----------+
+*/
+
+#include <stdint.h>
+#include "coap_api.h"
+#include "nrf_error.h"
+#include "sdk_errors.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef enum
+{
+ COAP_OPT_FORMAT_EMPTY = 0,
+ COAP_OPT_FORMAT_STRING = 1,
+ COAP_OPT_FORMAT_OPAQUE = 2,
+ COAP_OPT_FORMAT_UINT = 3
+
+} coap_opt_format_t;
+
+
+/**@brief Encode zero-terminated string into utf-8 encoded string.
+ *
+ * @param[out] p_encoded Pointer to buffer that will be used to fill the
+ * encoded string into.
+ * @param[inout] p_length Length of the buffer provided. Will also be used to
+ * return the size of the used buffer.
+ * @param[in] p_string String to encode.
+ * @param[in] str_len Length of the string to encode.
+ *
+ * @retval NRF_SUCCESS Indicates that encoding was successful.
+ * @retval NRF_ERROR_DATA_SIZE Indicates that the buffer provided was not sufficient to
+ * successfully encode the data.
+ */
+uint32_t coap_opt_string_encode(uint8_t * p_encoded, uint16_t * p_length, uint8_t * p_string, uint16_t str_len);
+
+/**@brief Decode a utf-8 string into a zero-terminated string.
+ *
+ * @param[out] p_string Pointer to the string buffer where the decoded
+ * string will be placed.
+ * @param[inout] p_length p_length of the encoded string. Returns the size of the buffer
+ * used in bytes.
+ * @param[in] p_encoded Buffer to decode.
+ *
+ * @retval NRF_SUCCESS Indicates that decoding was successful.
+ * @retval NRF_ERROR_DATA_SIZE Indicates that the buffer provided was not sufficient to
+ * successfully dencode the data.
+ */
+uint32_t coap_opt_string_decode(uint8_t * p_string, uint16_t * p_length, uint8_t * p_encoded);
+
+/**@brief Encode a uint value into a uint8_t buffer in network byte order.
+ *
+ * @param[out] p_encoded Pointer to buffer that will be used to fill the
+ * encoded uint into.
+ * @param[inout] p_length Length of the buffer provided. Will also be used to
+ * return the size of the used buffer.
+ * @param[in] data uint value which could be anything from 1 to 4 bytes.
+ *
+ * @retval NRF_SUCCESS Indicates that encoding was successful.
+ * @retval NRF_ERROR_DATA_SIZE Indicates that the buffer provided was not sufficient to
+ * successfully encode the data.
+ */
+uint32_t coap_opt_uint_encode(uint8_t * p_encoded, uint16_t * p_length, uint32_t data);
+
+/**@brief Decode a uint encoded value in network byte order to a uint32_t value.
+ *
+ * @param[out] p_data Pointer to the uint32_t value where the decoded uint will
+ * be placed.
+ * @param[inout] length Size of the encoded value.
+ * @param[in] p_encoded uint value to be decoded into a uint32_t value.
+ *
+ * @retval NRF_SUCCESS Indicates that decoding was successful.
+ * @retval NRF_ERROR_NULL If p_data or p_encoded pointer is NULL.
+ * @retval NRF_ERROR_INVALID_LENGTH If buffer was greater than uint32_t.
+ */
+uint32_t coap_opt_uint_decode(uint32_t * p_data, uint16_t length, uint8_t * p_encoded);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_OPTION_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_queue.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_queue.c
new file mode 100644
index 0000000..4e12bb6
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_queue.c
@@ -0,0 +1,182 @@
+/**
+ * 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 <string.h>
+
+#include "coap_queue.h"
+#include "iot_common.h"
+#include "sdk_config.h"
+
+#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
+
+static coap_queue_item_t m_queue[COAP_MESSAGE_QUEUE_SIZE];
+static uint8_t m_message_queue_count = 0;
+
+uint32_t coap_queue_init(void)
+{
+ for (uint8_t i = 0; i < COAP_MESSAGE_QUEUE_SIZE; i++)
+ {
+ memset(&m_queue[i], 0, sizeof(coap_queue_item_t));
+ m_queue[i].handle = i;
+ }
+ m_message_queue_count = 0;
+
+ return NRF_SUCCESS;
+}
+
+uint32_t coap_queue_add(coap_queue_item_t * item)
+{
+ NULL_PARAM_CHECK(item);
+
+ if (m_message_queue_count >= COAP_MESSAGE_QUEUE_SIZE)
+ {
+ return (NRF_ERROR_NO_MEM | IOT_COAP_ERR_BASE);
+ }
+ else
+ {
+ for (uint8_t i = 0; i < COAP_MESSAGE_QUEUE_SIZE; i++)
+ {
+ if (m_queue[i].p_buffer == NULL)
+ {
+ // Free spot in message queue. Add message here...
+ memcpy(&m_queue[i], item, sizeof(coap_queue_item_t));
+
+ m_message_queue_count++;
+
+ return NRF_SUCCESS;
+ }
+ }
+
+ }
+ return (NRF_ERROR_DATA_SIZE | IOT_COAP_ERR_BASE);
+}
+
+uint32_t coap_queue_remove(coap_queue_item_t * p_item)
+{
+ for (uint8_t i = 0; i < COAP_MESSAGE_QUEUE_SIZE; i++)
+ {
+ if (p_item == (coap_queue_item_t *)&m_queue[i])
+ {
+ memset(&m_queue[i], 0, sizeof(coap_queue_item_t));
+ m_message_queue_count--;
+ return NRF_SUCCESS;
+ }
+ }
+
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+uint32_t coap_queue_item_by_token_get(coap_queue_item_t ** pp_item, uint8_t * p_token, uint8_t token_len)
+{
+ for (uint8_t i = 0; i < COAP_MESSAGE_QUEUE_SIZE; i++)
+ {
+ if (m_queue[i].token_len == token_len)
+ {
+ if ((0 != m_queue[i].token_len) &&
+ (memcmp(m_queue[i].token, p_token, m_queue[i].token_len) == 0))
+ {
+ *pp_item = &m_queue[i];
+ return NRF_SUCCESS;
+ }
+ }
+ }
+
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+
+uint32_t coap_queue_item_by_mid_get(coap_queue_item_t ** pp_item, uint16_t message_id)
+{
+
+
+ for (uint8_t i = 0; i < COAP_MESSAGE_QUEUE_SIZE; i++)
+ {
+ if (m_queue[i].mid == message_id)
+ {
+ *pp_item = &m_queue[i];
+ return NRF_SUCCESS;
+ }
+ }
+
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
+
+
+uint32_t coap_queue_item_next_get(coap_queue_item_t ** pp_item, coap_queue_item_t * p_item)
+{
+ if (p_item == NULL)
+ {
+ for (uint8_t i = 0; i < COAP_MESSAGE_QUEUE_SIZE; i++)
+ {
+ if (m_queue[i].p_buffer != NULL)
+ {
+ (*pp_item) = &m_queue[i];
+ return NRF_SUCCESS;
+ }
+ }
+ }
+ else
+ {
+ uint8_t index_to_previous = (uint8_t)(((uint32_t)p_item - (uint32_t)m_queue) / (uint32_t)sizeof(coap_queue_item_t));
+
+ for (uint8_t i = index_to_previous + 1; i < COAP_MESSAGE_QUEUE_SIZE; i++)
+ {
+ if (m_queue[i].p_buffer != NULL)
+ {
+ (*pp_item) = &m_queue[i];
+ return NRF_SUCCESS;
+ }
+ }
+ }
+ (*pp_item) = NULL;
+
+ return (NRF_ERROR_NOT_FOUND | IOT_COAP_ERR_BASE);
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_queue.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_queue.h
new file mode 100644
index 0000000..24c5db6
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_queue.h
@@ -0,0 +1,153 @@
+/**
+ * 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.
+ *
+ */
+/** @file coap_queue.h
+ *
+ * @defgroup iot_sdk_coap_queue CoAP Message Queue
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief TODO.
+ */
+
+#ifndef COAP_QUEUE_H__
+#define COAP_QUEUE_H__
+
+#include <stdint.h>
+
+#include "coap_transport.h"
+#include "coap_message.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+ void * p_arg; /**< Miscellaneous pointer to application provided data that is associated with the message. Copied from the coap_message_t when creating the item. */
+ uint32_t handle; /**< Quick reference to the handle value of the current item. */
+ uint16_t mid; /**< Message ID. */
+ uint8_t token_len; /**< Message Token length. */
+ uint8_t token[8]; /**< Message Token value up to 8 bytes. */
+ uint8_t retrans_count; /**< Re-transmission attempt count. */
+ uint16_t timeout; /**< Time until new re-transmission attempt. */
+ uint16_t timeout_val; /**< Last timeout value used. */
+ coap_port_t port; /**< Source port to use when re-transmitting. */
+ uint8_t * p_buffer; /**< Pointer to the data buffer containing the encoded CoAP message. */
+ uint32_t buffer_len; /**< Size of the data buffer containing the encoded CoAP message. */
+ coap_remote_t remote; /**< Destination address and port number to the remote. */
+ coap_response_callback_t callback; /**< Callback function to be called upon response or transmission timeout. */
+} coap_queue_item_t;
+
+/**@brief Initilize the CoAP message queue.
+ *
+ * @retval NRF_SUCCESS If initialization completed successfully.
+ */
+uint32_t coap_queue_init(void);
+
+/**@brief Add item to the queue.
+ *
+ * @param[in] p_item Pointer to an item which to add to the queue. The function will copy all
+ * data provided.
+ *
+ * @retval NRF_SUCCESS If adding the item was successful.
+ * @retval NRF_ERROR_NO_MEM If max number of queued elements has been reached. This is
+ * configured by COAP_MESSAGE_QUEUE_SIZE in sdk_config.h.
+ * @retval NRF_ERROR_DATA_SIZE If the element could not be added.
+ */
+uint32_t coap_queue_add(coap_queue_item_t * p_item);
+
+/**@brief Remove item from the queue.
+ *
+ * @param[in] p_item Pointer to an item which to remove from the queue. Should not be NULL.
+ *
+ * @retval NRF_SUCCESS If the item was successfully removed from the queue.
+ * @retval NRF_ERROR_NULL If p_item pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If the item was not located in the queue.
+ */
+uint32_t coap_queue_remove(coap_queue_item_t * p_item);
+
+/**@brief Search for item by token.
+ *
+ * @details Search the items for any item matching the token.
+ *
+ * @param[out] pp_item Pointer to be filled by the function if item matching the token
+ * has been found. Should not be NULL.
+ * @param[in] p_token Pointer to token array to be matched.
+ * @param[in] token_len Length of the token to be matched.
+ *
+ * @retval NRF_SUCCESS If an item was successfully located.
+ * @retval NRF_ERROR_NULL If pp_item pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If no item was found.
+ */
+uint32_t coap_queue_item_by_token_get(coap_queue_item_t ** pp_item, uint8_t * p_token, uint8_t token_len);
+
+/**@brief Search for item by message id.
+ *
+ * @details Search the items for any item matching the message id.
+ *
+ * @param[out] pp_item Pointer to be filled by the funciton if item matching the message id
+ * has been found. Should not be NULL.
+ * @param[in] message_id Message id to be matched.
+ *
+ * @retval NRF_SUCCESS If an item was successfully located.
+ * @retval NRF_ERROR_NULL If pp_item pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If no item was found.
+ */
+uint32_t coap_queue_item_by_mid_get(coap_queue_item_t ** pp_item, uint16_t message_id);
+
+/**@brief Iterate through items.
+ *
+ * @param[out] pp_item Pointer to be filled by the search function upon finding the next
+ * queued item starting from the p_item pointer provided. Should
+ * not be NULL.
+ * @param[in] p_item Pointer to the item where to start the search.
+ *
+ * @retval NRF_SUCCESS If item was found.
+ * @retval NRF_ERROR_NULL If pp_item pointer is NULL.
+ * @retval NRF_ERROR_NOT_FOUND If next item was not found.
+ */
+uint32_t coap_queue_item_next_get(coap_queue_item_t ** pp_item, coap_queue_item_t * p_item);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_QUEUE_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_resource.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_resource.c
new file mode 100644
index 0000000..b928e0c
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_resource.c
@@ -0,0 +1,274 @@
+/**
+ * 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 <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;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_resource.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_resource.h
new file mode 100644
index 0000000..d73ef1f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_resource.h
@@ -0,0 +1,110 @@
+/**
+ * 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.
+ *
+ */
+/** @file coap_resource.h
+ *
+ * @defgroup iot_sdk_coap_resource CoAP Resource
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief Private API of Nordic's CoAP Resource implementation.
+ */
+
+#ifndef COAP_RESOURCE_H__
+#define COAP_RESOURCE_H__
+
+#include <stdint.h>
+#include "coap_api.h"
+#include "sdk_config.h"
+#include "coap_message.h"
+#include "nrf_error.h"
+#include "sdk_errors.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Initialize the CoAP resource module.
+ *
+ * @details This function will initialize the root element pointer to NULL.
+ * This way, a new root can be assigned registered. The first
+ * resource added will be set as the new root.
+ *
+ * @retval NRF_SUCCESS This function will always return success.
+ */
+uint32_t coap_resource_init(void);
+
+/**@brief Find a resource by traversing the resource names.
+ *
+ * @param[out] p_resource Located resource.
+ * @param[in] pp_uri_pointers Array of strings which forms the hierarchical path to the resource.
+ * @param[in] num_of_uris Number of URIs supplied through the path pointer list.
+ *
+ * @retval NRF_SUCCESS The resource was instance located.
+ * @retval NRF_ERROR_NOT_FOUND The resource was not located.
+ * @retval NRF_ERROR_INVALID_STATE If no resource has been registered.
+ */
+uint32_t coap_resource_get(coap_resource_t ** p_resource,
+ uint8_t ** pp_uri_pointers,
+ uint8_t num_of_uris);
+
+
+/**@brief Process the request related to the resource.
+ *
+ * @details When a request is received and the resource has successfully been located it
+ * will pass on to this function. The method in the request will be matched against
+ * what the service provides of method handling callbacks. If the request expects a
+ * response this will be provided as output from this function. The memory provided
+ * for the response must be provided from outside.
+ *
+ * @param[in] p_resource Resource that will handle the request.
+ * @param[in] p_request The request to be handled.
+ * @param[inout] p_response Response message which can be used by the resource populate
+ * the response message.
+ */
+uint32_t coap_resource_process_request(coap_resource_t * p_resource,
+ coap_message_t * p_request,
+ coap_message_t * p_response);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COAP_MESSAGE_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport.h
new file mode 100644
index 0000000..b9fd597
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport.h
@@ -0,0 +1,165 @@
+/**
+ * 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.
+ *
+ */
+/** @file coap_transport.h
+ *
+ * @defgroup iot_sdk_coap_transport CoAP transport abstraction
+ * @ingroup iot_sdk_coap
+ * @{
+ * @brief The transport interface that the CoAP depends on for sending and receiving CoAP messages.
+ *
+ * @details While the interface is well defined and should not be altered, the implementation of the
+ * interface depends on the choice of IP stack. The only exception to this is the
+ * \ref coap_transport_read API. This API is implemented in the CoAP, and the transport layer is
+ * expected to call this function when data is received on one of the CoAP ports.
+ */
+
+#ifndef COAP_TRANSPORT_H__
+#define COAP_TRANSPORT_H__
+
+#include <stdint.h>
+#include <nrf_tls.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Port identification information. */
+typedef struct
+{
+ uint16_t port_number; /**< Port number. */
+} coap_port_t;
+
+
+/**@brief Remote endpoint. */
+typedef struct
+{
+ uint8_t addr[16]; /**< Address of the remote device. */
+ uint16_t port_number; /**< Remote port number. */
+} coap_remote_t;
+
+
+/**@brief Transport initialization information. */
+typedef struct
+{
+ coap_port_t * p_port_table; /**< Information about the ports being registered. Count is assumed to be COAP_PORT_COUNT. */
+ void * p_arg; /**< Public. Miscellaneous pointer to application provided data that should be passed to the transport. */
+} coap_transport_init_t;
+
+
+
+/**@brief Initializes the transport layer to have the data ports set up for CoAP.
+ *
+ * @param[in] p_param Port count and port numbers.
+ *
+ * @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code that indicates the reason for the failure is returned.
+ */
+uint32_t coap_transport_init (const coap_transport_init_t * p_param);
+
+
+/**@brief Sends data on a CoAP endpoint or port.
+ *
+ * @param[in] p_port Port on which the data is to be sent.
+ * @param[in] p_remote Remote endpoint to which the data is targeted.
+ * @param[in] p_data Pointer to the data to be sent.
+ * @param[in] datalen Length of the data to be sent.
+ *
+ * @retval NRF_SUCCESS If the data was sent successfully. Otherwise, an error code that indicates the reason for the failure is returned.
+ */
+uint32_t coap_transport_write(const coap_port_t * p_port,
+ const coap_remote_t * p_remote,
+ const uint8_t * p_data,
+ uint16_t datalen);
+
+
+
+/**@brief Handles data received on a CoAP endpoint or port.
+ *
+ * This API is not implemented by the transport layer, but assumed to exist. This approach
+ * avoids unnecessary registering of callback and remembering it in the transport layer.
+ *
+ * @param[in] p_port Port on which the data is received.
+ * @param[in] p_remote Remote endpoint from which the data is received.
+ * @param[in] p_local Local endpoint on which the data is received.
+ * @param[in] result Indicates if the data was processed successfully by lower layers.
+ * Possible failures could be NRF_SUCCESS,
+ * UDP_BAD_CHECKSUM,
+ * UDP_TRUNCATED_PACKET, or
+ * UDP_MALFORMED_PACKET.
+ * @param[in] p_data Pointer to the data received.
+ * @param[in] datalen Length of the data received.
+ *
+ * @retval NRF_SUCCESS If the data was handled successfully. Otherwise, an error code that indicates the reason for the failure is returned.
+ *
+ */
+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);
+
+
+/**@brief Process loop to handle DTLS processing.
+ *
+ * @details The function handles any processing of encrypted packets.
+ * Some encryption libraries requires to be run in a processing
+ * loop. This function is called by the CoAP library everytime
+ * \ref coap_time_tick is issued from the library user. Any other process
+ * specific routines that should be done regularly could be added in
+ * this function.
+ */
+void coap_transport_process(void);
+
+/**@brief Process loop when using coap BSD socket transport implementation.
+ *
+ * @details This is blocking call. The function unblock is only
+ * triggered upon an socket event registered to select() by coap transport.
+ * This function must be called as often as possible in order to dispatch incomming
+ * socket events. Preferred to be put in the application's main loop or similar.
+ */
+void coap_transport_input(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //COAP_TRANSPORT_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_dtls.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_dtls.c
new file mode 100644
index 0000000..b1fe138
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_dtls.c
@@ -0,0 +1,996 @@
+/**
+ * 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 "nrf_error.h"
+#include "nrf_drv_rng.h"
+#include "sdk_config.h"
+#include "iot_common.h"
+#include "iot_pbuffer.h"
+#include "coap_transport.h"
+#include "coap.h"
+#include "udp_api.h"
+#include "nrf_tls.h"
+#include "mem_manager.h"
+#include "iot_errors.h"
+
+
+#if IOT_COAP_CONFIG_LOG_ENABLED
+
+#define NRF_LOG_MODULE_NAME coap_dtls
+
+#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 COAPT_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
+#define COAPT_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
+#define COAPT_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
+
+#define COAPT_ENTRY() COAPT_TRC(">> %s", __func__)
+#define COAPT_EXIT() COAPT_TRC("<< %s", __func__)
+#define COAPT_ENTRY_WITH_READLEN(read_len) COAPT_TRC(">> %s, readlen %d", __func__, read_len)
+#define COAPT_EXIT_WITH_RESULT(result) COAPT_TRC("<< %s, result 0x%08lX", __func__, result)
+
+#else // IOT_COAP_CONFIG_LOG_ENABLED
+
+#define COAPT_TRC(...) /**< Disables traces. */
+#define COAPT_DUMP(...) /**< Disables dumping of octet streams. */
+#define COAPT_ERR(...) /**< Disables error logs. */
+
+#define COAPT_ENTRY(...)
+#define COAPT_EXIT(...)
+#define COAPT_ENTRY_WITH_READLEN(...)
+#define COAPT_EXIT_WITH_RESULT(...)
+
+#endif // IOT_COAP_CONFIG_LOG_ENABLED
+
+/**@brief Max size to be requested from the DTLS library when polling for decoded CoAP data. */
+#define MAX_BUFFER_SIZE 1024
+
+
+/**@brief UDP port information. */
+typedef struct
+{
+ uint32_t socket_id; /**< Socket information provided by UDP. */
+ uint16_t port_number; /**< Associated port number. */
+ nrf_tls_key_settings_t * p_settings; /**< Key preferences. */
+} udp_port_t;
+
+/**@brief CoAP remote session. Encapsulates information needed for DTLS. */
+typedef struct
+{
+ nrf_tls_instance_t dtls_instance; /**< DTLS instance identifier. */
+ coap_remote_t remote_endpoint; /**< Remote endoint indentification. */
+ uint16_t local_port_index; /**< Identifies local endpoint assoicated with the session. */
+} coap_remote_session_t;
+
+/**@brief Possible CoAP transport types. Needed for internal handling of events and data. */
+typedef enum
+{
+ COAP_TRANSPORT_NON_SECURE_DATAGRAM = 0, /**< Non-secure transport, no DTLS procedures apply. */
+ COAP_TRANSPORT_SECURE_DATAGRAM = 1, /**< Secure transport, DTLS procedures apply. */
+ COAP_TRANSPORT_MAX_TYPES = 2 /**< Maximum transport types. Not a valid transport identifer used as max count. */
+} coap_transport_type_t;
+
+/**
+ * @brief Transport write handler signature.
+ *
+ * @param[in] p_remote Remote endpoint on which data is to be written.
+ * @param[in] local_port_index Local endpoint identifier writing the data.
+ * @param[in] p_data Data to be written.
+ * @param[in] datalen Length of data to be written.
+ *
+ * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for
+ * failure.
+ */
+typedef uint32_t (* port_write_t) (const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ const uint8_t * p_data,
+ uint16_t datalen);
+
+/**
+ * @brief Transport read handler signature.
+ *
+ * @param[in] p_remote Remote endpoint which sent data.
+ * @param[in] local_port_index Local endpoint identifier to which the data was sent.
+ * @param[in] p_data Data read on the transport.
+ * @param[in] datalen Length of data read on the transport.
+ *
+ * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for
+ * failure.
+ */
+typedef uint32_t (* port_read_t) (const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ uint32_t read_result,
+ const uint8_t * p_data,
+ uint16_t datalen);
+
+/** Forward declaration. */
+uint32_t non_secure_datagram_write (const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ const uint8_t * p_data,
+ uint16_t datalen);
+
+/** Forward declaration. */
+uint32_t secure_datagram_write (const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ const uint8_t * p_data,
+ uint16_t datalen);
+
+/** Forward declaration. */
+uint32_t non_secure_datagram_read (const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ uint32_t read_result,
+ const uint8_t * p_data,
+ uint16_t datalen);
+
+/** Forward declaration. */
+uint32_t secure_datagram_read(const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ uint32_t read_result,
+ const uint8_t * p_data,
+ uint16_t datalen);
+
+/** Forward declaration. */
+uint32_t dtls_output_handler(nrf_tls_instance_t const * p_instance,
+ uint8_t const * p_data,
+ uint32_t datalen);
+
+static udp_port_t m_port_table[COAP_PORT_COUNT]; /**< Table maintaining association between CoAP ports and corresponding UDP socket identifiers. */
+static coap_remote_session_t m_remote_session[COAP_DTLS_MAX_REMOTE_SESSION]; /**< Table for managing security sessions with remote endpoints. */
+
+/**@brief Table of transport write handlers. */
+const port_write_t port_write_fn[COAP_TRANSPORT_MAX_TYPES] =
+{
+ non_secure_datagram_write,
+ secure_datagram_write
+};
+
+/**@brief Table of transport read handlers. */
+const port_read_t port_read_fn[COAP_TRANSPORT_MAX_TYPES] =
+{
+ non_secure_datagram_read,
+ secure_datagram_read
+};
+
+
+/**
+ * @brief Searches the local port reference based on the port number.
+ *
+ * @param[out] p_index Pointer where local port refernce should be provided (if found).
+ * @param[in] port_query Port number for which local port reference is requested.
+ *
+ * @retval NRF_SUCCESS if procedure succeeded else NRF_ERROR_NOT_FOUND.
+ */
+static uint32_t local_port_index_get(uint32_t * p_index, uint16_t port_query)
+{
+ uint32_t local_port_index;
+
+ // Find local port index.
+ for (local_port_index = 0; local_port_index < COAP_PORT_COUNT; local_port_index++)
+ {
+ if (m_port_table[local_port_index].port_number == port_query)
+ {
+ break;
+ }
+ }
+
+ // If we could not find the local port requested in the port table.
+ if (local_port_index >= COAP_PORT_COUNT)
+ {
+ return NRF_ERROR_NOT_FOUND;
+ }
+
+ *p_index = local_port_index;
+
+ return NRF_SUCCESS;
+}
+
+
+/**
+ * @brief Session to be initialized/freed.
+ *
+ * @param[in] p_session Session
+ */
+static void remote_session_init(coap_remote_session_t * p_session)
+{
+ memset(p_session, 0, sizeof(coap_remote_session_t));
+ NRF_TLS_INTSANCE_INIT(&p_session->dtls_instance);
+}
+
+
+/**
+ * @brief Creates DTLS session between remote and local endpoint.
+ *
+ * @param[in] local_port_index Identifies local endpoint.
+ * @param[in] role Identifies DTLS role to be played (server or client).
+ * @param[in] p_remote Identifies remote endpoint.
+ * @param[in] p_settings Security settings to be used for the session.
+ * @param[out] pp_session Pointer to the session created (if any).
+ *
+ * @retval NRF_SUCCESS is procedure succeeded else an error code indicating reason for failure.
+ */
+static uint32_t session_create(uint32_t local_port_index,
+ nrf_tls_role_t role,
+ const coap_remote_t * const p_remote,
+ nrf_tls_key_settings_t * const p_settings,
+ coap_remote_session_t ** pp_session)
+{
+ uint32_t err_code = NRF_ERROR_NO_MEM;
+
+ for (uint32_t index = 0; index < COAP_DTLS_MAX_REMOTE_SESSION; index++)
+ {
+ if (m_remote_session[index].remote_endpoint.port_number == 0)
+ {
+ // Found free session.
+ m_remote_session[index].remote_endpoint.port_number = p_remote->port_number;
+ memcpy(m_remote_session[index].remote_endpoint.addr, p_remote->addr, IPV6_ADDR_SIZE);
+ m_remote_session[index].local_port_index = local_port_index;
+
+ // Attempt Allocate TLS session.
+ const nrf_tls_options_t dtls_options =
+ {
+ .output_fn = dtls_output_handler,
+ .transport_type = NRF_TLS_TYPE_DATAGRAM,
+ .role = role,
+ .p_key_settings = p_settings
+ };
+
+ m_remote_session[index].dtls_instance.transport_id = index;
+
+ COAP_MUTEX_UNLOCK();
+
+ err_code = nrf_tls_alloc(&m_remote_session[index].dtls_instance, &dtls_options);
+
+ COAP_MUTEX_LOCK();
+
+ COAPT_TRC("[%p]: nrf_tls_alloc result %08x",
+ &m_remote_session[index],
+ err_code);
+
+ // TLS allocation succeeded, book keep information for endpoint.
+ if (err_code == NRF_SUCCESS)
+ {
+ (*pp_session) = &m_remote_session[index];
+ break;
+ }
+ else
+ {
+ // If free the session and notify failure.
+ remote_session_init(&m_remote_session[index]);
+ }
+ }
+ }
+
+ return err_code;
+}
+
+
+/**
+ * @brief API to free TLS session.
+ *
+ * @param[in] p_session Identifies the session to be freed.
+ */
+static __INLINE void session_free (coap_remote_session_t * p_session)
+{
+ // Free TLS session.
+ UNUSED_VARIABLE(nrf_tls_free(&p_session->dtls_instance));
+
+ // Free the session.
+ remote_session_init(p_session);
+}
+
+
+/**
+ * @brief Searches for DTLS session between remote and local endpoint.
+ *
+ * @param[in] local_port_index Identifies local endpoint.
+ * @param[in] p_remote Identifies remote endpoint.
+ * @param[out] pp_session Pointer to the session found (if any).
+ *
+ * @retval NRF_SUCCESS is procedure succeeded else NRF_ERROR_NOT_FOUND.
+ */
+uint32_t remote_session_search(uint32_t local_port_index,
+ const coap_remote_t * p_remote,
+ coap_remote_session_t ** pp_session)
+{
+ uint32_t err_code = NRF_ERROR_NOT_FOUND;
+ uint32_t index = 0;
+
+
+ for (index = 0; index < COAP_DTLS_MAX_REMOTE_SESSION; index++)
+ {
+ const coap_remote_session_t * session = &m_remote_session[index];
+ if ((session->local_port_index == local_port_index) &&
+ (session->remote_endpoint.port_number == p_remote->port_number) &&
+ ((memcmp(session->remote_endpoint.addr, p_remote->addr, IPV6_ADDR_SIZE) == 0)))
+ {
+ // Entry exists.
+ (*pp_session) = (coap_remote_session_t *)session;
+ err_code = NRF_SUCCESS;
+ break;
+ }
+ }
+
+ return err_code;
+}
+
+
+/**
+ * @brief Provides transport type to be used between remote and local endpoint.
+ *
+ * @param[in] local_port_index Identifies local endpoint.
+ * @param[in] p_remote Identifies remote endpoint.
+ *
+ * @retval COAP_TRANSPORT_SECURE_DATAGRAM if transport type to be used is secure.
+ * @retval COAP_TRANSPORT_NON_SECURE_DATAGRAM if transport type to be used is non-secure.
+ */
+uint8_t get_transport_type(uint32_t local_port_index, const coap_remote_t * p_remote)
+{
+ coap_remote_session_t * p_session;
+ uint8_t transport_type = COAP_TRANSPORT_NON_SECURE_DATAGRAM;
+
+ uint32_t err_code = remote_session_search(local_port_index, p_remote, &p_session);
+ if (err_code == NRF_SUCCESS)
+ {
+ COAPT_TRC("Transport type = SECURE");
+ transport_type = COAP_TRANSPORT_SECURE_DATAGRAM;
+ }
+ else if (m_port_table[local_port_index].p_settings != NULL)
+ {
+ COAPT_TRC("Transport type = SECURE");
+ transport_type = COAP_TRANSPORT_SECURE_DATAGRAM;
+ }
+ else
+ {
+ COAPT_TRC("Transport type = NON-SECURE");
+ }
+
+ return transport_type;
+}
+
+
+/**@brief Callback handler to receive data on the UDP port.
+ *
+ * @details Callback handler to receive data on the UDP port.
+ *
+ * @param[in] p_socket Socket identifier.
+ * @param[in] p_ip_header IPv6 header containing source and destination addresses.
+ * @param[in] p_udp_header UDP header identifying local and remote endpoints.
+ * @param[in] process_result Result of data reception, there could be possible errors like
+ * invalid checksum etc.
+ * @param[in] iot_pbuffer_t Packet buffer containing the received data packet.
+ *
+ * @retval NRF_SUCCESS Indicates received data was handled successfully, else an an
+ * error code indicating reason for failure..
+ */
+static uint32_t port_data_callback(const udp6_socket_t * p_socket,
+ const ipv6_header_t * p_ip_header,
+ const udp6_header_t * p_udp_header,
+ uint32_t process_result,
+ iot_pbuffer_t * p_rx_packet)
+{
+ uint32_t index;
+ uint32_t retval = NRF_ERROR_NOT_FOUND;
+
+ COAPT_TRC("port_data_callback: Src Port %d Dest Port %d. Len %08lx",
+ p_udp_header->srcport, p_udp_header->destport, p_rx_packet->length);
+
+ COAP_MUTEX_LOCK();
+
+ //Search for the port.
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ if (m_port_table[index].socket_id == p_socket->socket_id)
+ {
+ COAPT_TRC("port_data_callback->coap_transport_read");
+
+ //Matching port found.
+ coap_remote_t remote_endpoint;
+
+ memcpy(remote_endpoint.addr, p_ip_header->srcaddr.u8, IPV6_ADDR_SIZE);
+ remote_endpoint.port_number = p_udp_header->srcport;
+
+ uint8_t transport_type = get_transport_type(index, &remote_endpoint);
+
+ // Handle read data on scoket based on nature of transport.
+ retval = port_read_fn[transport_type](&remote_endpoint,
+ index,
+ process_result,
+ p_rx_packet->p_payload,
+ p_rx_packet->length);
+ break;
+ }
+ }
+
+ COAP_MUTEX_UNLOCK();
+
+ return retval;
+}
+
+
+/**
+ * @brief Transport read handler for non secure transport type.
+ *
+ * @param[in] p_remote Remote endpoint which sent data.
+ * @param[in] local_port_index Local endpoint identifier to which the data was sent.
+ * @param[in] read_result Indicator result of data read on the transport.
+ * Likely failures include UDP checksum failure, truncated packet etc.
+ * @param[in] p_data Data read on the transport.
+ * @param[in] datalen Length of data read on the transport.
+ *
+ * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for
+ * failure.
+ */
+uint32_t non_secure_datagram_read (const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ uint32_t read_result,
+ const uint8_t * p_data,
+ uint16_t datalen)
+{
+ const coap_port_t port =
+ {
+ .port_number = m_port_table[local_port_index].port_number
+ };
+
+ return coap_transport_read(&port,
+ p_remote,
+ NULL,
+ read_result,
+ p_data,
+ datalen);
+}
+
+
+/**
+ * @brief Transport write handler for non secure transport type.
+ *
+ * @param[in] p_remote Remote endpoint on which data is to be written.
+ * @param[in] local_port_index Local endpoint identifier writing the data.
+ * @param[in] p_data Data to be written.
+ * @param[in] datalen Length of data to be written.
+ *
+ * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for
+ * failure.
+ */
+uint32_t non_secure_datagram_write(const coap_remote_t * p_remote,
+ uint32_t index,
+ const uint8_t * p_data,
+ uint16_t datalen)
+{
+ uint32_t err_code;
+ udp6_socket_t socket;
+ ipv6_addr_t remote_addr;
+ iot_pbuffer_t * p_buffer;
+ iot_pbuffer_alloc_param_t buffer_param;
+
+ buffer_param.type = UDP6_PACKET_TYPE;
+ buffer_param.flags = PBUFFER_FLAG_DEFAULT;
+ buffer_param.length = datalen;
+
+ COAPT_TRC("[LP %04X]:[RP %04X]: port_write, datalen %d",
+ m_port_table[index].port_number,
+ p_remote->port_number,
+ datalen);
+
+ memcpy(remote_addr.u8, p_remote->addr, IPV6_ADDR_SIZE);
+
+ // Allocate buffer to send the data on port.
+ err_code = iot_pbuffer_allocate(&buffer_param, &p_buffer);
+
+ COAPT_TRC("port_write->iot_pbuffer_allocate result 0x%08X", err_code);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ socket.socket_id = m_port_table[index].socket_id;
+
+ // Make a copy of the data onto the buffer.
+ memcpy(p_buffer->p_payload, p_data, datalen);
+
+ // Send on UDP port.
+ err_code = udp6_socket_sendto(&socket,
+ &remote_addr,
+ p_remote->port_number,
+ p_buffer);
+
+ COAPT_TRC("port_write->udp6_socket_sendto result 0x%08X", err_code);
+ if (err_code != NRF_SUCCESS)
+ {
+ // Free the allocated buffer as send procedure has failed.
+ UNUSED_VARIABLE(iot_pbuffer_free(p_buffer, true));
+ }
+ }
+
+ return err_code;
+}
+
+
+/**
+ * @brief Transport read handler for secure transport type.
+ *
+ * @param[in] p_remote Remote endpoint which sent data.
+ * @param[in] local_port_index Local endpoint identifier to which the data was sent.
+ * @param[in] read_result Indicator result of data read on the transport.
+ * Likely failures include UDP checksum failure, truncated packet etc.
+ * @param[in] p_data Data read on the transport.
+ * @param[in] datalen Length of data read on the transport.
+ *
+ * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for
+ * failure.
+ */
+uint32_t secure_datagram_read(const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ uint32_t read_result,
+ const uint8_t * p_data,
+ uint16_t datalen)
+{
+ const uint32_t read_len = datalen;
+ uint32_t err_code;
+ coap_remote_session_t * p_session = NULL;
+
+ COAPT_ENTRY_WITH_READLEN(read_len);
+
+ // Search is a session exists.
+ err_code = remote_session_search(local_port_index, p_remote, &p_session);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ COAPT_TRC("Remote session found, processing.");
+
+ COAP_MUTEX_UNLOCK();
+
+ // Session exists, send data to DTLS for decryption.
+ err_code = nrf_tls_input(&p_session->dtls_instance, p_data, read_len);
+
+ COAP_MUTEX_LOCK();
+ }
+ else
+ {
+ COAPT_TRC("Remote session not found, look for server security settings.");
+ if (m_port_table[local_port_index].p_settings != NULL)
+ {
+ // Allocate a session for incoming client.
+ err_code = session_create(local_port_index,
+ NRF_TLS_ROLE_SERVER,
+ p_remote,
+ m_port_table[local_port_index].p_settings,
+ &p_session);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ COAP_MUTEX_UNLOCK();
+
+ COAPT_TRC("[%p]: New session created as DTLS server.", p_session);
+
+ err_code = nrf_tls_input(&p_session->dtls_instance, p_data, read_len);
+
+ COAP_MUTEX_LOCK();
+ }
+ else
+ {
+ COAPT_TRC("New session creation failed, reason 0x%08x.", err_code);
+ }
+ }
+ else
+ {
+ COAPT_TRC("No remote session, no server settings, processing as raw");
+ err_code = non_secure_datagram_read(p_remote,
+ local_port_index,
+ read_result,
+ p_data,
+ datalen);
+ }
+ }
+
+ COAPT_EXIT_WITH_RESULT(err_code);
+
+ return err_code;
+}
+
+
+/**
+ * @brief Transport write handler for secure transport type.
+ *
+ * @param[in] p_remote Remote endpoint on which data is to be written.
+ * @param[in] local_port_index Local endpoint identifier writing the data.
+ * @param[in] p_data Data to be written.
+ * @param[in] datalen Length of data to be written.
+ *
+ * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for
+ * failure.
+ */
+uint32_t secure_datagram_write(const coap_remote_t * const p_remote,
+ uint32_t local_port_index,
+ const uint8_t * p_data,
+ uint16_t datalen)
+{
+
+ uint32_t err_code;
+ coap_remote_session_t * p_session;
+
+ // Search is a session exists.
+ err_code = remote_session_search(local_port_index, p_remote, &p_session);
+
+ if (err_code == NRF_ERROR_NOT_FOUND)
+ {
+ // No session found, return error.
+ err_code = COAP_TRANSPORT_SECURITY_MISSING;
+ }
+ else
+ {
+ // Session exists, attempt a secure write.
+ uint32_t actual_len = datalen;
+ err_code = nrf_tls_write(&p_session->dtls_instance, p_data, &actual_len);
+ }
+
+ return err_code;
+}
+
+
+/**
+ * @brief Handles DTLS output to be sent on the underlying UDP transport.
+ *
+ * @param[in] p_instance Identifies the TLS instance associated with the output.
+ * @param[in] p_data DTLS library output data to be written on the transport.
+ * @param[in] datalen Length of data.
+ *
+ * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for
+ * failure.
+ */
+uint32_t dtls_output_handler(nrf_tls_instance_t const * p_instance,
+ uint8_t const * p_data,
+ uint32_t datalen)
+{
+ const uint16_t transport_write_len = datalen;
+
+ if (p_instance->transport_id >= COAP_DTLS_MAX_REMOTE_SESSION)
+ {
+ return NRF_ERROR_NOT_FOUND;
+ }
+
+ COAP_MUTEX_LOCK();
+
+ coap_remote_session_t * p_session = &m_remote_session[p_instance->transport_id];
+ uint32_t err_code = NRF_ERROR_NOT_FOUND;
+
+ if (p_session->remote_endpoint.port_number != 0)
+ {
+ // Search for instance in remote sessions.
+ err_code = non_secure_datagram_write(&p_session->remote_endpoint,
+ p_session->local_port_index,
+ p_data,
+ transport_write_len);
+ }
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+
+/**@brief Creates port as requested in p_port.
+ *
+ * @details Creates port as requested in p_port.
+ *
+ * @param[in] index Index to the m_port_table where entry of the port created is to be made.
+ * @param[in] p_port Port information to be created.
+ *
+ * @retval NRF_SUCCESS Indicates if port was created successfully, else an an error code
+ * indicating reason for failure.
+ */
+static uint32_t port_create(uint32_t index, coap_port_t * p_port)
+{
+ uint32_t err_code;
+ udp6_socket_t socket;
+
+ // Request new socket creation.
+ err_code = udp6_socket_allocate(&socket);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ // Bind the socket to the local port.
+ err_code = udp6_socket_bind(&socket, IPV6_ADDR_ANY, p_port->port_number);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ // Register data receive callback.
+ err_code = udp6_socket_recv(&socket, port_data_callback);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ // All procedure with respect to port creation succeeded, make entry in the table.
+ m_port_table[index].socket_id = socket.socket_id;
+ m_port_table[index].port_number = p_port->port_number;
+ m_port_table[index].p_settings = NULL;
+
+ socket.p_app_data = &m_port_table[index];
+ UNUSED_VARIABLE(udp6_socket_app_data_set(&socket));
+ }
+ }
+
+ if (err_code != NRF_SUCCESS)
+ {
+ // Not all procedures succeeded with allocated socket, hence free it.
+ UNUSED_VARIABLE(udp6_socket_free(&socket));
+ }
+ }
+ return err_code;
+}
+
+
+uint32_t coap_transport_init(const coap_transport_init_t * p_param)
+{
+ uint32_t err_code = NRF_ERROR_NO_MEM;
+ uint32_t index;
+
+ NULL_PARAM_CHECK(p_param);
+ NULL_PARAM_CHECK(p_param->p_port_table);
+
+ err_code = nrf_tls_init();
+
+ if (err_code == NRF_SUCCESS)
+ {
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ // Create end point for each of the CoAP ports.
+ err_code = port_create(index, &p_param->p_port_table[index]);
+ if (err_code != NRF_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ for (index = 0; index < COAP_DTLS_MAX_REMOTE_SESSION; index++)
+ {
+ remote_session_init(&m_remote_session[index]);
+ }
+ }
+
+ return err_code;
+}
+
+
+uint32_t coap_transport_write(const coap_port_t * p_port,
+ const coap_remote_t * p_remote,
+ const uint8_t * p_data,
+ uint16_t datalen)
+{
+ uint32_t err_code = NRF_ERROR_NOT_FOUND;
+ uint32_t index;
+
+ NULL_PARAM_CHECK(p_port);
+ NULL_PARAM_CHECK(p_remote);
+ NULL_PARAM_CHECK(p_data);
+
+ COAP_MUTEX_LOCK();
+
+ //Search for the corresponding port.
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ if (m_port_table[index].port_number == p_port->port_number)
+ {
+ // Get transport type for remote and local.
+ uint8_t transport_type = get_transport_type(index, p_remote);
+
+ err_code = port_write_fn[transport_type](p_remote,
+ index,
+ p_data,
+ datalen);
+ break;
+ }
+ }
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+
+void coap_transport_process(void)
+{
+ nrf_tls_process();
+
+ for (uint32_t index = 0; index < COAP_DTLS_MAX_REMOTE_SESSION; index++)
+ {
+ coap_remote_session_t * p_session = &m_remote_session[index];
+
+ if (p_session->remote_endpoint.port_number != 0x0000)
+ {
+ uint32_t datalen = MAX_BUFFER_SIZE;
+
+ COAP_MUTEX_UNLOCK();
+
+ // Check if there is data to be processed/read.
+ uint32_t err_code = nrf_tls_read(&p_session->dtls_instance, NULL, &datalen);
+
+ COAP_MUTEX_LOCK();
+
+ COAPT_TRC("nrf_tls_read result %d", err_code);
+
+ if ((err_code == NRF_SUCCESS) && (datalen > 0))
+ {
+ COAPT_TRC("nrf_tls_read datalen %d", datalen);
+
+ // Allocate memory and fecth data from DTLS layer.
+ uint8_t * p_data = NULL;
+ uint32_t buffer_size = datalen;
+
+ err_code = nrf_mem_reserve(&p_data, &buffer_size);
+
+ if (p_data != NULL)
+ {
+ COAP_MUTEX_UNLOCK();
+
+ err_code = nrf_tls_read(&p_session->dtls_instance, p_data, &datalen);
+
+ COAP_MUTEX_LOCK();
+
+ if ((err_code == NRF_SUCCESS) && (datalen > 0))
+ {
+ UNUSED_VARIABLE(non_secure_datagram_read(&p_session->remote_endpoint,
+ p_session->local_port_index,
+ NRF_SUCCESS,
+ p_data,
+ datalen));
+ }
+
+ // Free the memory reserved for the incoming packet.
+ nrf_free(p_data);
+ }
+ }
+ }
+ }
+}
+
+
+uint32_t coap_security_setup(uint16_t local_port,
+ nrf_tls_role_t role,
+ coap_remote_t * const p_remote,
+ nrf_tls_key_settings_t * const p_settings)
+{
+ uint32_t err_code = NRF_ERROR_NO_MEM;
+ uint32_t local_port_index;
+ coap_remote_session_t * p_session;
+
+ COAP_MUTEX_LOCK();
+
+ // Find local port index.
+ err_code = local_port_index_get(&local_port_index, local_port);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ if (role == NRF_TLS_ROLE_CLIENT)
+ {
+ if (p_remote == NULL)
+ {
+ // Clients can never register session with wildcard remote.
+ err_code = NRF_ERROR_NULL;
+ }
+ else
+ {
+ // Search is a session exists.
+ err_code = remote_session_search(local_port_index, p_remote, &p_session);
+
+ if (err_code != NRF_SUCCESS)
+ {
+ // Session does not already exist, create one.
+ err_code = session_create(local_port_index,
+ role, p_remote,
+ p_settings,
+ &p_session);
+ }
+ }
+ }
+ else
+ {
+ // For server role, disallow client specific settings.
+ // This may not always be desired. But a constraint added in current design.
+ if (p_remote != NULL)
+ {
+ err_code = NRF_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ // Cannot overwrite settings.
+ if (m_port_table[local_port_index].p_settings != NULL)
+ {
+ err_code = NRF_ERROR_FORBIDDEN;
+ }
+ else
+ {
+ COAPT_TRC("[0x%08lx]: Server security setup successful",
+ local_port_index);
+
+ m_port_table[local_port_index].p_settings = p_settings;
+ }
+ }
+
+ }
+ }
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
+
+
+uint32_t coap_security_destroy(uint16_t local_port,
+ coap_remote_t * const p_remote)
+{
+ uint32_t err_code;
+ coap_remote_session_t * p_session;
+ uint32_t local_port_index;
+
+ COAP_MUTEX_LOCK();
+
+ // Find local port index.
+ err_code = local_port_index_get(&local_port_index, local_port);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ if (p_remote != NULL)
+ {
+ // Search is a session exists.
+ err_code = remote_session_search(local_port_index, p_remote, &p_session);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ session_free(p_session);
+ }
+ }
+ else
+ {
+ // Remove all session associated with the local port if p_remote is NULL.
+ for (uint32_t index = 0; index < COAP_DTLS_MAX_REMOTE_SESSION ; index++)
+ {
+ if (m_remote_session[index].local_port_index == local_port_index)
+ {
+ session_free(&m_remote_session[index]);
+ }
+ }
+ }
+ }
+
+ COAP_MUTEX_UNLOCK();
+
+ return err_code;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_ipv6.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_ipv6.c
new file mode 100644
index 0000000..9cf4bdb
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_ipv6.c
@@ -0,0 +1,264 @@
+/**
+ * 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 "sdk_errors.h"
+#include "sdk_config.h"
+#include "iot_common.h"
+#include "iot_pbuffer.h"
+#include "coap_transport.h"
+#include "coap.h"
+#include "udp_api.h"
+
+
+/**@brief UDP port information. */
+typedef struct
+{
+ uint32_t socket_id; /**< Socket information provided by UDP. */
+ uint16_t port_number; /**< Associated port number. */
+} udp_port_t;
+
+static udp_port_t m_port_table[COAP_PORT_COUNT]; /**< Table maintaining association between CoAP ports and corresponding UDP socket identifiers. */
+
+
+/**@brief Callback handler to receive data on the UDP port.
+ *
+ * @details Callback handler to receive data on the UDP port.
+ *
+ * @param[in] p_socket Socket identifier.
+ * @param[in] p_ip_header IPv6 header containing source and destination addresses.
+ * @param[in] p_udp_header UDP header identifying local and remote endpoints.
+ * @param[in] process_result Result of data reception, there could be possible errors like
+ * invalid checksum etc.
+ * @param[in] iot_pbuffer_t Packet buffer containing the received data packet.
+ *
+ * @retval NRF_SUCCESS Indicates received data was handled successfully, else an an
+ * error code indicating reason for failure..
+ */
+static uint32_t port_data_callback(const udp6_socket_t * p_socket,
+ const ipv6_header_t * p_ip_header,
+ const udp6_header_t * p_udp_header,
+ uint32_t process_result,
+ iot_pbuffer_t * p_rx_packet)
+{
+ uint32_t index;
+ uint32_t retval = NRF_ERROR_NOT_FOUND;
+
+ //Search for the port.
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ //Matching port found.
+ if (m_port_table[index].socket_id == p_socket->socket_id)
+ {
+ coap_remote_t remote_endpoint;
+ coap_remote_t local_endpoint;
+ const coap_port_t port = {p_udp_header->destport};
+
+ memcpy (remote_endpoint.addr, p_ip_header->srcaddr.u8, IPV6_ADDR_SIZE);
+ remote_endpoint.port_number = p_udp_header->srcport;
+
+ memcpy (local_endpoint.addr, p_ip_header->destaddr.u8, IPV6_ADDR_SIZE);
+ local_endpoint.port_number = p_udp_header->destport;
+
+ COAP_MUTEX_LOCK();
+
+ //Notify the module of received data.
+ retval = coap_transport_read(&port,
+ &remote_endpoint,
+ &local_endpoint,
+ process_result,
+ p_rx_packet->p_payload,
+ p_rx_packet->length);
+
+ COAP_MUTEX_UNLOCK();
+ }
+ }
+
+ return retval;
+}
+
+
+/**@brief Creates port as requested in p_port.
+ *
+ * @details Creates port as requested in p_port.
+ *
+ * @param[in] index Index to the m_port_table where entry of the port created is to be made.
+ * @param[in] p_port Port information to be created.
+ *
+ * @retval NRF_SUCCESS Indicates if port was created successfully, else an an error code
+ * indicating reason for failure.
+ */
+static uint32_t port_create(uint32_t index, coap_port_t * p_port)
+{
+ uint32_t err_code;
+ udp6_socket_t socket;
+
+ //Request new socket creation.
+ err_code = udp6_socket_allocate(&socket);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ // Bind the socket to the local port.
+ err_code = udp6_socket_bind(&socket, IPV6_ADDR_ANY, p_port->port_number);
+ if (err_code == NRF_SUCCESS)
+ {
+ //Register data receive callback.
+ err_code = udp6_socket_recv(&socket, port_data_callback);
+ if (err_code == NRF_SUCCESS)
+ {
+ //All procedure with respect to port creation succeeded, make entry in the table.
+ m_port_table[index].socket_id = socket.socket_id;
+ m_port_table[index].port_number = p_port->port_number;
+ socket.p_app_data = &m_port_table[index];
+ UNUSED_VARIABLE(udp6_socket_app_data_set(&socket));
+ }
+ }
+
+ if (err_code != NRF_SUCCESS)
+ {
+ //Not all procedures succeeded with allocated socket, hence free it.
+ UNUSED_VARIABLE(udp6_socket_free(&socket));
+ }
+ }
+ return err_code;
+}
+
+
+uint32_t coap_transport_init(const coap_transport_init_t * p_param)
+{
+ uint32_t err_code = NRF_ERROR_NO_MEM;
+ uint32_t index;
+
+ NULL_PARAM_CHECK(p_param);
+ NULL_PARAM_CHECK(p_param->p_port_table);
+
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ // Create end point for each of the CoAP ports.
+ err_code = port_create(index, &p_param->p_port_table[index]);
+ if (err_code != NRF_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ return err_code;
+}
+
+
+uint32_t coap_transport_write(const coap_port_t * p_port,
+ const coap_remote_t * p_remote,
+ const uint8_t * p_data,
+ uint16_t datalen)
+{
+ uint32_t err_code = NRF_ERROR_NOT_FOUND;
+ uint32_t index;
+ udp6_socket_t socket;
+ ipv6_addr_t remote_addr;
+ iot_pbuffer_t * p_buffer;
+ iot_pbuffer_alloc_param_t buffer_param;
+
+ NULL_PARAM_CHECK(p_port);
+ NULL_PARAM_CHECK(p_remote);
+ NULL_PARAM_CHECK(p_data);
+
+ memcpy(remote_addr.u8, p_remote->addr, 16);
+
+
+ buffer_param.type = UDP6_PACKET_TYPE;
+ buffer_param.flags = PBUFFER_FLAG_DEFAULT;
+ buffer_param.length = datalen;
+
+ //Search for the corresponding port.
+ for (index = 0; index < COAP_PORT_COUNT; index ++)
+ {
+ if (m_port_table[index].port_number == p_port->port_number)
+ {
+ //Allocate buffer to send the data on port.
+ err_code = iot_pbuffer_allocate(&buffer_param, &p_buffer);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ socket.socket_id = m_port_table[index].socket_id;
+
+ //Make a copy of the data onto the buffer.
+ memcpy (p_buffer->p_payload, p_data, datalen);
+
+ COAP_MUTEX_UNLOCK();
+
+ //Send on UDP port.
+ err_code = udp6_socket_sendto(&socket,
+ &remote_addr,
+ p_remote->port_number,
+ p_buffer);
+
+ COAP_MUTEX_LOCK();
+
+ if (err_code != NRF_SUCCESS)
+ {
+ //Free the allocated buffer as send procedure has failed.
+ UNUSED_VARIABLE(iot_pbuffer_free(p_buffer, true));
+ }
+ }
+ break;
+ }
+ }
+
+ return err_code;
+}
+
+
+void coap_transport_process(void)
+{
+ return;
+}
+
+uint32_t coap_security_setup(uint16_t local_port,
+ nrf_tls_role_t role,
+ coap_remote_t * const p_remote,
+ nrf_tls_key_settings_t * const p_settings)
+{
+ return NRF_ERROR_API_NOT_IMPLEMENTED;
+}
+
+
+uint32_t coap_security_destroy(uint16_t local_port,
+ coap_remote_t * const p_remote)
+{
+ return NRF_ERROR_API_NOT_IMPLEMENTED;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_lwip.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_lwip.c
new file mode 100644
index 0000000..6245a97
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_lwip.c
@@ -0,0 +1,255 @@
+/**
+ * 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 <stdint.h>
+#include "sdk_errors.h"
+#include "sdk_config.h"
+#include "iot_common.h"
+#include "coap_transport.h"
+#include "coap.h"
+#include "lwip/ip6_addr.h"
+/*lint -save -e607 Suppress warning 607 "Parameter p of macro found within string" */
+#include "lwip/udp.h"
+/*lint -restore */
+
+
+/**@brief UDP port information. */
+typedef struct
+{
+ struct udp_pcb * p_socket; /**< Socket information provided by UDP. */
+ uint16_t port_number; /**< Associated port number. */
+}udp_port_t;
+
+static udp_port_t m_port_table[COAP_PORT_COUNT]; /**< Table maintaining association between CoAP ports and corresponding UDP socket identifiers. */
+
+
+/**@brief Callback handler to receive data on the UDP port.
+ *
+ * @details Callback handler to receive data on the UDP port.
+ *
+ * @param[in] p_arg Receive argument associated with the UDP socket.
+ * @param[in] p_socket Socket identifier.
+ * @param[in] p_ip_header IPv6 header containing source and destination addresses.
+ * @param[in] p_remote_addr IPv6 address of the remote device.
+ * @param[in] port Port number identifying the remote endpoint.
+ *
+ * @retval NRF_SUCCESS Indicates received data was handled successfully, else an an
+ * error code indicating reason for failure.
+ */
+static void udp_recv_data_handler(void * p_arg,
+ struct udp_pcb * p_socket,
+ struct pbuf * p_buffer,
+ const ip6_addr_t * p_remote_addr,
+ u16_t port)
+{
+ uint32_t index;
+ coap_remote_t remote_endpoint;
+ coap_port_t local_port = {p_socket->local_port};
+
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ if (m_port_table[index].p_socket == p_socket)
+ {
+ memcpy (remote_endpoint.addr, p_remote_addr, 16);
+ remote_endpoint.port_number = port;
+
+ COAP_MUTEX_LOCK();
+
+ UNUSED_VARIABLE(coap_transport_read(&local_port,
+ &remote_endpoint,
+ NULL,
+ NRF_SUCCESS,
+ (uint8_t *)p_buffer->payload,
+ (uint32_t)p_buffer->len));
+
+ COAP_MUTEX_UNLOCK();
+
+ break;
+ }
+ }
+
+ //Freeing packet (irrespective of matching p_socket is found or not
+ //to avoid memory leaks in the system.
+ UNUSED_VARIABLE(pbuf_free(p_buffer));
+}
+
+
+/**@brief Creates port as requested in p_port.
+ *
+ * @details Creates port as requested in p_port.
+ *
+ * @param[in] index Index to the m_port_table where entry of the port created is to be made.
+ * @param[in] p_port Port information to be created.
+ *
+ * @retval NRF_SUCCESS Indicates if port was created successfully, else an an error code
+ * indicating reason for failure.
+ */
+static uint32_t port_create(uint32_t index, coap_port_t * p_port)
+{
+ err_t err = NRF_ERROR_NO_MEM;
+ ip6_addr_t any_addr;
+ struct udp_pcb * p_socket = m_port_table[index].p_socket;
+
+ ip6_addr_set_any(&any_addr);
+
+ //Request new socket creation.
+ p_socket = udp_new();
+
+ if (NULL != p_socket)
+ {
+ // Bind the socket to the local port.
+ err = udp_bind(p_socket, &any_addr, p_port->port_number);
+ if (err == ERR_OK)
+ {
+ //Register data receive callback.
+ udp_recv(p_socket, udp_recv_data_handler, &m_port_table[index]);
+ //All procedure with respect to port creation succeeded, make entry in the table.
+ m_port_table[index].port_number = p_port->port_number;
+ m_port_table[index].p_socket = p_socket;
+ }
+ else
+ {
+ //Not all procedures succeeded with allocated socket, hence free it.
+ err = NRF_ERROR_INVALID_PARAM;
+ udp_remove(p_socket);
+ }
+ }
+
+ return err;
+}
+
+
+uint32_t coap_transport_init(const coap_transport_init_t * p_param)
+{
+ uint32_t err_code = NRF_SUCCESS;
+ uint32_t index;
+
+ NULL_PARAM_CHECK(p_param);
+ NULL_PARAM_CHECK(p_param->p_port_table);
+
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ // Create end point for each of the COAP ports.
+ err_code = port_create(index, &p_param->p_port_table[index]);
+ if (err_code != NRF_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ return err_code;
+}
+
+
+uint32_t coap_transport_write(const coap_port_t * p_port,
+ const coap_remote_t * p_remote,
+ const uint8_t * p_data,
+ uint16_t datalen)
+{
+
+ err_t err = NRF_ERROR_NOT_FOUND;
+ uint32_t index;
+
+ NULL_PARAM_CHECK(p_port);
+ NULL_PARAM_CHECK(p_remote);
+ NULL_PARAM_CHECK(p_data);
+
+ //Search for the corresponding port.
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ if (m_port_table[index].port_number == p_port->port_number)
+ {
+ //Allocate Buffer to send the data on port.
+ struct pbuf * lwip_buffer = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
+
+ if (NULL != lwip_buffer)
+ {
+ //Make a copy of the data onto the buffer.
+ memcpy(lwip_buffer->payload, p_data, datalen);
+
+ COAP_MUTEX_UNLOCK();
+
+ //Send on UDP port.
+ err = udp_sendto(m_port_table[index].p_socket,
+ lwip_buffer,
+ (ip6_addr_t *)p_remote->addr,
+ p_remote->port_number);
+
+ COAP_MUTEX_LOCK();
+
+
+ if (err != ERR_OK)
+ {
+ //Free the allocated buffer as send procedure has failed.
+ err = NRF_ERROR_INTERNAL;
+ }
+ UNUSED_VARIABLE(pbuf_free(lwip_buffer));
+ }
+ else
+ {
+ //Buffer allocation failed, cannot send data.
+ err = NRF_ERROR_NO_MEM;
+ }
+ break;
+ }
+ }
+ return err;
+}
+
+
+void coap_transport_process(void)
+{
+ return;
+}
+
+
+uint32_t coap_security_setup(uint16_t local_port,
+ nrf_tls_role_t role,
+ coap_remote_t * const p_remote,
+ nrf_tls_key_settings_t * const p_settings)
+{
+ return NRF_ERROR_API_NOT_IMPLEMENTED;
+}
+
+
+uint32_t coap_security_destroy(uint16_t local_port,
+ coap_remote_t * const p_remote)
+{
+ return NRF_ERROR_API_NOT_IMPLEMENTED;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_socket.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_socket.c
new file mode 100644
index 0000000..d19737f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/coap/coap_transport_socket.c
@@ -0,0 +1,292 @@
+/**
+ * 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 <sys/socket.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#ifdef UNIX
+#include <fcntl.h>
+#endif
+#include <errno.h>
+#include <stdint.h>
+#include "mem_manager.h"
+#include "sdk_errors.h"
+#include "sdk_config.h"
+#include "iot_common.h"
+#include "nordic_common.h"
+#include "coap_transport.h"
+#include "coap.h"
+
+/**@brief UDP port information. */
+typedef struct
+{
+ int socket_fd; /**< Socket information provided by UDP. */
+ uint16_t port_number; /**< Associated port number. */
+} udp_port_t;
+
+static udp_port_t m_port_table[COAP_PORT_COUNT]; /**< Table maintaining association between CoAP ports and corresponding UDP socket identifiers. */
+
+static fd_set m_readfds;
+static int m_max_sd = 0;
+
+/**@brief Creates port as requested in p_port.
+ *
+ * @details Creates port as requested in p_port.
+ *
+ * @param[in] index Index to the m_port_table where entry of the port created is to be made.
+ * @param[in] p_port Port information to be created.
+ *
+ * @retval NRF_SUCCESS Indicates if port was created successfully, else an an error code
+ * indicating reason for failure.
+ */
+static uint32_t port_create(uint32_t index, coap_port_t * p_port)
+{
+ // Request new socket creation.
+ int socket_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (socket_fd != -1)
+ {
+ // Bind the socket to the local port.
+ struct sockaddr_in6 sin6;
+
+ memset(&sin6, 0, sizeof(struct sockaddr_in6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_port = htons(p_port->port_number);
+ sin6.sin6_addr = in6addr_any;
+
+ int retval = bind(socket_fd, (struct sockaddr *)&sin6, sizeof(sin6));
+ if (retval != -1)
+ {
+ m_port_table[index].port_number = p_port->port_number;
+ m_port_table[index].socket_fd = socket_fd;
+ }
+ else
+ {
+ // Not all procedures succeeded with allocated socket, hence free it.
+ UNUSED_VARIABLE(close(socket_fd));
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ }
+
+ // Configure socket to be non-blocking.
+ int flags = fcntl(socket_fd, F_GETFL, 0);
+ flags |= O_NONBLOCK;
+ UNUSED_VARIABLE(fcntl(m_port_table[index].socket_fd, F_SETFL, flags));
+
+ // Add socket to file descriptor set.
+ FD_SET(m_port_table[index].socket_fd, &m_readfds);
+
+ // If enumeration is having a gap, increase the max fd count.
+ if (socket_fd >= m_max_sd)
+ {
+ m_max_sd = (socket_fd + 1);
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t coap_transport_init(const coap_transport_init_t * p_param)
+{
+ uint32_t err_code = NRF_SUCCESS;
+ uint32_t index;
+
+ NULL_PARAM_CHECK(p_param);
+ NULL_PARAM_CHECK(p_param->p_port_table);
+
+ FD_ZERO(&m_readfds);
+
+ err_code = nrf_mem_init();
+
+ if (err_code == NRF_SUCCESS) {
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ // Create end point for each of the COAP ports.
+ err_code = port_create(index, &p_param->p_port_table[index]);
+ if (err_code != NRF_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+
+ return err_code;
+}
+
+
+uint32_t coap_transport_write(const coap_port_t * p_port,
+ const coap_remote_t * p_remote,
+ const uint8_t * p_data,
+ uint16_t datalen)
+{
+
+ uint32_t err_code = NRF_ERROR_NOT_FOUND;
+ uint32_t index;
+
+ NULL_PARAM_CHECK(p_port);
+ NULL_PARAM_CHECK(p_remote);
+ NULL_PARAM_CHECK(p_data);
+
+ // Search for the corresponding port.
+ for (index = 0; index < COAP_PORT_COUNT; index++)
+ {
+ if (m_port_table[index].port_number == p_port->port_number)
+ {
+ COAP_MUTEX_UNLOCK();
+
+ static struct sockaddr_in6 dest_address_in6;
+
+ memset(&dest_address_in6, 0, sizeof(struct sockaddr_in6));
+ dest_address_in6.sin6_family = AF_INET6;
+ dest_address_in6.sin6_port = htons(p_remote->port_number);
+
+ memcpy(&dest_address_in6.sin6_addr, p_remote->addr, sizeof(struct in6_addr));
+
+ // Send on UDP port.
+ int retval = sendto(m_port_table[index].socket_fd,
+ p_data,
+ datalen,
+ 0,
+ (struct sockaddr *)&dest_address_in6,
+ sizeof(dest_address_in6));
+ if (retval == -1)
+ {
+ // Error in sendto.
+ err_code = NRF_ERROR_INTERNAL;
+ }
+ else
+ {
+ err_code = NRF_SUCCESS;
+ }
+
+ COAP_MUTEX_LOCK();
+ break;
+ }
+ }
+
+ return err_code;
+}
+
+
+void coap_transport_process(void)
+{
+ return;
+}
+
+
+uint32_t coap_security_setup(uint16_t local_port,
+ nrf_tls_role_t role,
+ coap_remote_t * const p_remote,
+ nrf_tls_key_settings_t * const p_settings)
+{
+ return SDK_ERR_API_NOT_IMPLEMENTED;
+}
+
+
+uint32_t coap_security_destroy(uint16_t local_port,
+ coap_remote_t * const p_remote)
+{
+ return SDK_ERR_API_NOT_IMPLEMENTED;
+}
+
+
+void coap_transport_input(void)
+{
+ int retval = select(m_max_sd, &m_readfds, NULL, NULL, NULL);
+
+ if (retval == -1)
+ {
+ // Error in select().
+ // Placeholder for debugging.
+ }
+ else if (retval >= 1) // Number of file descriptiors with activity.
+ {
+ uint32_t index = 0;
+ int socket_fd = m_port_table[index].socket_fd;
+
+ // The descriptor has data.
+ if (FD_ISSET(socket_fd, &m_readfds)) // If socket_fd is set to read.
+ {
+ static uint8_t read_mem[COAP_MESSAGE_DATA_MAX_SIZE];
+ static struct sockaddr_in6 client_address_in6;
+ socklen_t address_length = sizeof(struct sockaddr_in6);
+
+ int bytes_read = recvfrom(socket_fd,
+ read_mem,
+ sizeof(read_mem),
+ 0,
+ (struct sockaddr *)&client_address_in6,
+ (socklen_t *)&address_length); // Blocking call, waiting for incoming transaction.
+ if (bytes_read >= 0)
+ {
+ coap_port_t port;
+ port.port_number = m_port_table[index].port_number;
+
+ coap_remote_t remote_endpoint;
+ memcpy(remote_endpoint.addr, &client_address_in6.sin6_addr, sizeof(struct in6_addr));
+ remote_endpoint.port_number = ntohs(client_address_in6.sin6_port);
+
+ uint32_t result = NRF_SUCCESS;
+
+ // Notify the CoAP module of received data.
+ retval = coap_transport_read(&port,
+ &remote_endpoint,
+ NULL,
+ result,
+ read_mem,
+ (uint16_t)bytes_read);
+
+ // Nothing much to do if CoAP could not interpret the datagram.
+ UNUSED_VARIABLE(retval);
+ }
+ else
+ {
+ // Error in readfrom().
+ // Placeholder for debugging.
+ // If select() indicated this socket file descriptor to have pending
+ // data, this case should not occur.
+ }
+ }
+ }
+ else
+ {
+ // In case of socket() returning 0, timeout.
+ // Not implemented.
+ }
+}