Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-client-c by
Revision 4:5d91b0f5038c, committed 2016-04-02
- Comitter:
- Yogesh Pande
- Date:
- Sat Apr 02 00:39:03 2016 +0300
- Parent:
- 3:a8b2ff761ade
- Commit message:
- Latest mbed-client-c sources from Github.
Changed in this revision
--- a/nsdl-c/sn_coap_header.h Fri Feb 19 17:46:29 2016 +0000 +++ b/nsdl-c/sn_coap_header.h Sat Apr 02 00:39:03 2016 +0300 @@ -279,13 +279,13 @@ * * \param *dst_packet_data_ptr is pointer to allocated destination to built CoAP packet * - * \param *src_coap_msg_ptr is pointer to source structure for building Packet data + * \param *src_coap_msg_ptr is pointer to source structure for building Packet data * * \return Return value is byte count of built Packet data. In failure cases:\n * -1 = Failure in given CoAP header structure\n * -2 = Failure in given pointer (= NULL) */ -extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr); +extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr); /** * \fn uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr) @@ -293,7 +293,7 @@ * \brief Calculates needed Packet data memory size for given CoAP message * * \param *src_coap_msg_ptr is pointer to data which needed Packet - * data length is calculated + * data length is calculated * * \return Return value is count of needed memory as bytes for build Packet data * Null if failed @@ -301,6 +301,37 @@ extern uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr); /** + * \fn int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_size) + * + * \brief Builds an outgoing message buffer from a CoAP header structure. + * + * \param *dst_packet_data_ptr is pointer to allocated destination to built CoAP packet + * + * \param *src_coap_msg_ptr is pointer to source structure for building Packet data + * + * \param blockwise_payload_size Blockwise message maximum payload size + * + * \return Return value is byte count of built Packet data. In failure cases:\n + * -1 = Failure in given CoAP header structure\n + * -2 = Failure in given pointer (= NULL) + */ +extern int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size); + +/** + * \fn uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) + * + * \brief Calculates needed Packet data memory size for given CoAP message + * + * \param *src_coap_msg_ptr is pointer to data which needed Packet + * data length is calculated + * \param blockwise_payload_size Blockwise message maximum payload size + * + * \return Return value is count of needed memory as bytes for build Packet data + * Null if failed + */ +extern uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size); + +/** * \fn sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) * * \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s @@ -320,4 +351,3 @@ #endif #endif /* SN_COAP_HEADER_H_ */ -
--- a/nsdl-c/sn_coap_protocol.h Fri Feb 19 17:46:29 2016 +0000 +++ b/nsdl-c/sn_coap_protocol.h Sat Apr 02 00:39:03 2016 +0300 @@ -141,7 +141,7 @@ * \return 0 = success * -1 = failure */ -extern int8_t sn_coap_protocol_set_block_size(uint16_t block_size); +extern int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size); /** * \fn int8_t sn_coap_protocol_set_duplicate_buffer_size(uint8_t message_count) @@ -152,7 +152,7 @@ * \return 0 = success * -1 = failure */ -extern int8_t sn_coap_protocol_set_duplicate_buffer_size(uint8_t message_count); +extern int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count); /** * \fn int8_t sn_coap_protocol_set_retransmission_parameters(uint8_t resending_count, uint8_t resending_intervall) @@ -161,10 +161,10 @@ * * \param uint8_t resending_count max number of resendings for message * \param uint8_t resending_intervall message resending intervall in seconds - * \return 0 = success - * -1 = failure + * \return 0 = success, -1 = failure */ -extern int8_t sn_coap_protocol_set_retransmission_parameters(uint8_t resending_count, uint8_t resending_interval); +extern int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle, + uint8_t resending_count, uint8_t resending_interval); /** * \fn int8_t sn_coap_protocol_set_retransmission_buffer(uint8_t buffer_size_messages, uint16_t buffer_size_bytes) @@ -174,10 +174,10 @@ * * \param uint8_t buffer_size_messages queue size - maximum number of messages to be saved to queue * \param uint8_t buffer_size_bytes queue size - maximum size of messages saved to queue - * \return 0 = success - * -1 = failure + * \return 0 = success, -1 = failure */ -extern int8_t sn_coap_protocol_set_retransmission_buffer(uint8_t buffer_size_messages, uint16_t buffer_size_bytes); +extern int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle, + uint8_t buffer_size_messages, uint16_t buffer_size_bytes); /** * \fn void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle) @@ -186,11 +186,10 @@ * * \brief If re-transmissions are enabled, this function removes all messages from the retransmission queue. */ -extern void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle); +extern void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle); #endif /* SN_COAP_PROTOCOL_H_ */ #ifdef __cplusplus } #endif -
--- a/nsdl-c/sn_nsdl.h Fri Feb 19 17:46:29 2016 +0000 +++ b/nsdl-c/sn_nsdl.h Sat Apr 02 00:39:03 2016 +0300 @@ -100,4 +100,3 @@ #ifdef __cplusplus } #endif -
--- a/nsdl-c/sn_nsdl_lib.h Fri Feb 19 17:46:29 2016 +0000 +++ b/nsdl-c/sn_nsdl_lib.h Sat Apr 02 00:39:03 2016 +0300 @@ -1,598 +1,682 @@ -/* - * Copyright (c) 2011-2015 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** -* \file sn_nsdl_lib.h -* -* \brief NanoService Devices Library header file -* -* -*/ - -#ifndef SN_NSDL_LIB_H_ -#define SN_NSDL_LIB_H_ - -#include "ns_list.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define SN_NSDL_ENDPOINT_NOT_REGISTERED 0 -#define SN_NSDL_ENDPOINT_IS_REGISTERED 1 - -/* Handle structure */ -struct nsdl_s; - -/** - * \brief Received device server security - */ -typedef enum omalw_server_security_ { - SEC_NOT_SET = -1, - PSK = 0, - RPK = 1, - CERTIFICATE = 2, - NO_SEC = 3 -} omalw_server_security_t; - -/** - * \brief Endpoint binding and mode - */ -typedef enum sn_nsdl_oma_binding_and_mode_ { - BINDING_MODE_NOT_SET = 0, - BINDING_MODE_U = 0x01, - BINDING_MODE_Q = 0x02, - BINDING_MODE_S = 0x04 -} sn_nsdl_oma_binding_and_mode_t; - -/** - * \brief Endpoint registration mode. - * If REGISTER_WITH_RESOURCES, endpoint sends list of all resources during registration. - * If REGISTER_WITH_TEMPLATE, endpoint sends registration without resource list. Device server must have - * correctly configured template. - */ -typedef enum sn_nsdl_registration_mode_ { - REGISTER_WITH_RESOURCES = 0, - REGISTER_WITH_TEMPLATE -} sn_nsdl_registration_mode_t; - - -typedef struct omalw_certificate_list_ { - uint8_t certificate_chain_len; - uint8_t *certificate_ptr[2]; - uint16_t certificate_len[2]; - uint8_t *own_private_key_ptr; - uint16_t own_private_key_len; -} omalw_certificate_list_t; - -/** - * \brief Endpoint registration parameters - */ -typedef struct sn_nsdl_ep_parameters_ { - uint8_t *endpoint_name_ptr; /**< Endpoint name */ - uint8_t endpoint_name_len; - - uint8_t *domain_name_ptr; /**< Domain to register. If null, NSP uses default domain */ - uint8_t domain_name_len; - - uint8_t *type_ptr; /**< Endpoint type */ - uint8_t type_len; - - uint8_t *lifetime_ptr; /**< Endpoint lifetime in seconds. eg. "1200" = 1200 seconds */ - uint8_t lifetime_len; - - sn_nsdl_registration_mode_t ds_register_mode; /**< Defines registration mode */ - sn_nsdl_oma_binding_and_mode_t binding_and_mode; /**< Defines endpoints binding and mode */ - - uint8_t *location_ptr; /**< Endpoint location in server, optional parameter,default is NULL */ - uint8_t location_len; - -} sn_nsdl_ep_parameters_s; - -/** - * \brief For internal use - */ -typedef struct sn_nsdl_sent_messages_ { - uint16_t msg_id_number; - uint8_t message_type; - ns_list_link_t link; -} sn_nsdl_sent_messages_s; - -/** - * \brief Includes resource path - */ -typedef struct sn_grs_resource_ { - uint8_t pathlen; - uint8_t *path; -} sn_grs_resource_s; - -/** - * \brief Table of created resources - */ -typedef struct sn_grs_resource_list_ { - uint8_t res_count; /**< Number of resources */ - sn_grs_resource_s *res; -} sn_grs_resource_list_s; - -/** - * \brief Resource access rights - */ -typedef enum sn_grs_resource_acl_ { - SN_GRS_GET_ALLOWED = 0x01 , - SN_GRS_PUT_ALLOWED = 0x02, - SN_GRS_POST_ALLOWED = 0x04, - SN_GRS_DELETE_ALLOWED = 0x08 -} sn_grs_resource_acl_e; - - -typedef enum sn_nsdl_oma_device_error_ { - NO_ERROR = 0, - LOW_BATTERY_POWER = 1, - EXTERNAL_POWER_SUPPLY_OFF = 2, - GPS_MODULE_FAILURE = 3, - LOW_RECEIVED_SIGNAL_STRENGTH = 4, - OUT_OF_MEMORY = 5, - SMS_FAILURE = 6, - IP_CONN_FAILURE = 7, - PERIPHERAL_MALFUNCTION = 8 -} sn_nsdl_oma_device_error_t; - -/** - * \brief Defines the resource mode - */ -typedef enum sn_nsdl_resource_mode_ { - SN_GRS_STATIC, /**< Static resources have some value that doesn't change */ - SN_GRS_DYNAMIC, /**< Dynamic resources are handled in application. Therefore one must give function callback pointer to them */ - SN_GRS_DIRECTORY /**< Directory resources are unused and unsupported */ -} sn_nsdl_resource_mode_e; - -/** - * \brief Resource registration parameters - */ -typedef struct sn_nsdl_resource_parameters_ { - uint8_t *resource_type_ptr; - uint16_t resource_type_len; - - uint8_t *interface_description_ptr; - uint16_t interface_description_len; - - uint8_t coap_content_type; - - uint8_t mime_content_type; - - uint8_t observable; - - uint8_t registered; - -} sn_nsdl_resource_parameters_s; - -/** - * \brief Defines parameters for the resource. - */ -typedef struct sn_nsdl_resource_info_ { - sn_nsdl_resource_parameters_s *resource_parameters_ptr; - - sn_nsdl_resource_mode_e mode; /**< STATIC etc.. */ - - uint16_t pathlen; /**< Address */ - uint8_t *path; - - uint16_t resourcelen; /**< 0 if dynamic resource, resource information in static resource */ - uint8_t *resource; /**< NULL if dynamic resource */ - - sn_grs_resource_acl_e access; - - uint8_t (*sn_grs_dyn_res_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *, sn_nsdl_capab_e); - - ns_list_link_t link; - -} sn_nsdl_resource_info_s; - -/** - * \brief Defines OMA device object parameters. - */ -typedef struct sn_nsdl_oma_device_ { - sn_nsdl_oma_device_error_t error_code; /**< Error code. Mandatory. Can be more than one */ - uint8_t (*sn_oma_device_boot_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *, sn_nsdl_capab_e); /**< Device boot callback function. If defined, this is called when reset request is received */ - -} sn_nsdl_oma_device_t; - -/** - * \brief Defines OMAlw server information - */ -typedef struct sn_nsdl_oma_server_info_ { - sn_nsdl_addr_s *omalw_address_ptr; - omalw_server_security_t omalw_server_security; - -} sn_nsdl_oma_server_info_t; - -/** - * \brief Defines endpoint parameters to OMA bootstrap. - */ -typedef struct sn_nsdl_bs_ep_info_ { - void (*oma_bs_status_cb)(sn_nsdl_oma_server_info_t *); /**< Callback for OMA bootstrap status */ - sn_nsdl_oma_device_t *device_object; /**< OMA LWM2M mandatory device resources */ -} sn_nsdl_bs_ep_info_t; - - - - -/** - * \fn struct nsdl_s *sn_nsdl_init (uint8_t (*sn_nsdl_tx_cb)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), - * uint8_t (*sn_nsdl_rx_cb)(sn_coap_hdr_s *, sn_nsdl_addr_s *), - * sn_nsdl_mem_s *sn_memory) - * - * \brief Initialization function for NSDL library. Initializes NSDL, GRS, HTTP and CoAP. - * - * \param *sn_nsdl_tx_callback A callback function for sending messages. - * - * \param *sn_nsdl_rx_callback A callback function for parsed messages. If received message is not CoAP protocol message (eg. ACK), message for GRS (GET, PUT, POST, DELETE) or - * reply for some DS messages (register message etc.), rx callback will be called. - * - * \param *sn_memory Memory structure which includes function pointers to the allocation and free functions. - * - * \return pointer to created handle structure. NULL if failed - */ -struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), - uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), - void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *)); - -/** - * \fn extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); - * - * \brief Registers endpoint to mbed Device Server. - * \param *handle Pointer to nsdl-library handle - * \param *endpoint_info_ptr Contains endpoint information. - * - * \return registration message ID, 0 if failed - */ -extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); - -/** - * \fn extern uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle) - * - * \brief Sends unregister-message to mbed Device Server. - * - * \param *handle Pointer to nsdl-library handle - * - * \return unregistration message ID, 0 if failed - */ -extern uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle); - -/** - * \fn extern uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len); - * - * \brief Update the registration with mbed Device Server. - * - * \param *handle Pointer to nsdl-library handle - * \param *lt_ptr Pointer to lifetime value string in ascii form, eg. "1200" - * \param lt_len Length of the lifetime string - * - * \return registration update message ID, 0 if failed - */ -extern uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len); - -/** - * \fn extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len); - * - * \brief Sets the location receievd from Device Server. - * - * \param *handle Pointer to nsdl-library handle - * \param *lt_ptr Pointer to location value string , eg. "s322j4k" - * \param lt_len Length of the location string - * - * \return success, 0 if failed -1 - */ -extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len); - - -/** - * \fn extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle) - * - * \brief Checks if endpoint is registered. - * - * \param *handle Pointer to nsdl-library handle - * - * \return 1 Endpoint registration is done successfully - * \return 0 Endpoint is not registered - */ -extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle); - -/** - * \fn extern void sn_nsdl_nsp_lost(struct nsdl_s *handle); - * - * \brief A function to inform mbed Device C client library if application detects a fault in mbed Device Server registration. - * - * \param *handle Pointer to nsdl-library handle - * - * After calling this function sn_nsdl_is_ep_registered() will return "not registered". - */ -extern void sn_nsdl_nsp_lost(struct nsdl_s *handle); - -/** - * \fn extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, - * uint8_t *payload_ptr, uint16_t payload_len, - * uint8_t *observe_ptr, uint8_t observe_len, - * sn_coap_msg_type_e message_type, uint8_t content_type) - * - * - * \brief Sends observation message to mbed Device Server - * - * \param *handle Pointer to nsdl-library handle - * \param *token_ptr Pointer to token to be used - * \param token_len Token length - * \param *payload_ptr Pointer to payload to be sent - * \param payload_len Payload length - * \param *observe_ptr Pointer to observe number to be sent - * \param observe_len Observe number len - * \param message_type Observation message type (confirmable or non-confirmable) - * \param contetnt_type Observation message payload contetnt type - * - * \return !0 Success, observation messages message ID - * \return 0 Failure - */ -extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, - uint8_t *payload_ptr, uint16_t payload_len, - uint8_t *observe_ptr, uint8_t observe_len, - sn_coap_msg_type_e message_type, uint8_t content_type); - -/** - * \fn extern uint32_t sn_nsdl_get_version(void) - * - * \brief Version query function. - * - * Used to retrieve the version information from the mbed Device C Client library. - * - * \return Pointer to library version string -*/ -extern char *sn_nsdl_get_version(void); - -/** - * \fn extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src) - * - * \brief To push CoAP packet to mbed Device C Client library - * - * Used to push an CoAP packet to mbed Device C Client library for processing. - * - * \param *handle Pointer to nsdl-library handle - * - * \param *packet Pointer to a uint8_t array containing the packet (including the CoAP headers). - * After successful execution this array may contain the response packet. - * - * \param *packet_len Pointer to length of the packet. After successful execution this array may contain the length - * of the response packet. - * - * \param *src Pointer to packet source address information. After successful execution this array may contain - * the destination address of the response packet. - * - * \return 0 Success - * \return -1 Failure - */ -extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src); - -/** - * \fn extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time); - * - * \brief CoAP retransmission function. - * - * Used to give execution time for the mbed Device C Client library for retransmissions. - * - * \param *handle Pointer to nsdl-library handle - * - * \param time Time in seconds. - * - * \return 0 Success - * \return -1 Failure - */ -extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time); - -/** - * \fn extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); - * - * \brief Resource creating function. - * - * Used to create a static or dynamic CoAP resource. - * - * \param *res Pointer to a structure of type sn_nsdl_resource_info_t that contains the information - * about the resource. - * - * \return 0 Success - * \return -1 Failure - * \return -2 Resource already exists - * \return -3 Invalid path - * \return -4 List adding failure - */ -extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); - -/** - * \fn extern int8_t sn_nsdl_update_resource(sn_nsdl_resource_info_s *res) - * - * \brief Resource updating function. - * - * Used to update the direct value of a static resource, the callback function pointer of a dynamic resource - * and access rights of the recource. - * - * \param *handle Pointer to nsdl-library handle - * \param *res Pointer to a structure of type sn_nsdl_resource_info_t that contains the information - * about the resource. Only the pathlen and path elements are evaluated along with - * either resourcelen and resource or the function pointer. - * - * \return 0 Success - * \return -1 Failure - */ -extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); - -/** - * \fn extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint8_t pathlen, uint8_t *path) - * - * \brief Resource delete function. - * - * Used to delete a resource. If resource has a subresources, these all must also be removed. - * - * \param *handle Pointer to nsdl-library handle - * \param pathlen Contains the length of the path that is to be deleted (excluding possible trailing "\0"). - * \param *path_ptr A pointer to an array containing the path. - * - * \return 0 Success - * \return -1 Failure (No such resource) - */ -extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); - -/** - * \fn extern sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) - * - * \brief Resource get function. - * - * Used to get a resource. - * - * \param *handle Pointer to nsdl-library handle - * \param pathlen Contains the length of the path that is to be returned (excluding possible trailing '\0'). - * \param *path A pointer to an array containing the path. - * - * \return !NULL Success, pointer to a sn_nsdl_resource_info_s that contains the resource information\n - * \return NULL Failure - */ -extern sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); - -/** - * \fn extern sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) - * - * \brief Resource list function. - * - * \param *handle Pointer to nsdl-library handle - * \param pathlen Contains the length of the target path (excluding possible trailing '\0'). - * The length value is not examined if the path itself is a NULL pointer. - * \param *path A pointer to an array containing the path or a NULL pointer. - * - * \return !NULL A pointer to a sn_grs_resource_list_s structure containing the resource listing. - * \return NULL Failure with an unspecified error - */ -sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); - -/** - * \fn extern void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list) - * - * \brief Free a resource list obtained from sn_nsdl_list_resource() - * - * \param list The list to free, or NULL. - */ -void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list); - -/** - * \fn extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr); - * - * \brief Send an outgoing CoAP request. - * - * \param *handle Pointer to nsdl-library handle - * \param *address_ptr Pointer to source address struct - * \param *coap_hdr_ptr Pointer to CoAP message to be sent - * - * \return 0 Success - * \return -1 Failure - */ -extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr); - -/** - * \fn extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type); - * - * \brief This function is used to set the mbed Device Server address given by an application. - * - * \param *handle Pointer to nsdl-library handle - * \return 0 Success - * \return -1 Failed to indicate that internal address pointer is not allocated (call nsdl_init() first). - */ -extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type); - -/** - * \fn extern int8_t sn_nsdl_destroy(struct nsdl_s *handle); - * - * \param *handle Pointer to nsdl-library handle - * \brief This function releases all allocated memory in mbed Device C Client library. - */ -extern int8_t sn_nsdl_destroy(struct nsdl_s *handle); - -/** - * \fn extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr); - * - * \brief Starts OMA bootstrap process - * - * \param *handle Pointer to nsdl-library handle - * - * \return bootstrap message ID, 0 if failed - */ -extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr); - -/** - * \fn extern omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle); - * - * \brief Get pointer to received device server certificates - * - * \param *handle Pointer to nsdl-library handle - */ -extern omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle); - -/** - * \fn extern int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t* certificate_ptr, uint8_t certificate_chain); - * - * \brief Updates certificate pointers to resource server. - * - * \param *handle Pointer to nsdl-library handle - */ -extern int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t *certificate_ptr, uint8_t certificate_chain); - -/** - * \fn extern int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr); - * - * \brief Creates new device object resource - * - * \param *handle Pointer to nsdl-library handle - */ -extern int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr); - -/** - * \fn sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) - * - * \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s - * - * \param *handle Pointer to library handle - * \param *coap_packet_ptr The request packet pointer - * \param msg_code response messages code - * - * \return *coap_packet_ptr The allocated and pre-filled response packet pointer - * NULL Error in parsing the request - * - */ -extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code); - -/** - * \fn void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) - * - * \brief Releases memory of given CoAP message - * - * Note!!! Does not release Payload part - * - * \param *handle Pointer to CoAP library handle - * - * \param *freed_coap_msg_ptr is pointer to released CoAP message - */ -extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr); - -#ifdef __cplusplus -} -#endif - -#endif /* SN_NSDL_LIB_H_ */ - +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** +* \file sn_nsdl_lib.h +* +* \brief NanoService Devices Library header file +* +* +*/ + +#ifndef SN_NSDL_LIB_H_ +#define SN_NSDL_LIB_H_ + +#include "ns_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SN_NSDL_ENDPOINT_NOT_REGISTERED 0 +#define SN_NSDL_ENDPOINT_IS_REGISTERED 1 + +/* Handle structure */ +struct nsdl_s; + +/** + * \brief Received device server security + */ +typedef enum omalw_server_security_ { + SEC_NOT_SET = -1, + PSK = 0, + RPK = 1, + CERTIFICATE = 2, + NO_SEC = 3 +} omalw_server_security_t; + +/** + * \brief Endpoint binding and mode + */ +typedef enum sn_nsdl_oma_binding_and_mode_ { + BINDING_MODE_NOT_SET = 0, + BINDING_MODE_U = 0x01, + BINDING_MODE_Q = 0x02, + BINDING_MODE_S = 0x04 +} sn_nsdl_oma_binding_and_mode_t; + +/** + * \brief Endpoint registration mode. + * If REGISTER_WITH_RESOURCES, endpoint sends list of all resources during registration. + * If REGISTER_WITH_TEMPLATE, endpoint sends registration without resource list. Device server must have + * correctly configured template. + */ +typedef enum sn_nsdl_registration_mode_ { + REGISTER_WITH_RESOURCES = 0, + REGISTER_WITH_TEMPLATE +} sn_nsdl_registration_mode_t; + + +typedef struct omalw_certificate_list_ { + uint8_t certificate_chain_len; + uint8_t *certificate_ptr[2]; + uint16_t certificate_len[2]; + uint8_t *own_private_key_ptr; + uint16_t own_private_key_len; +} omalw_certificate_list_t; + +/** + * \brief Endpoint registration parameters + */ +typedef struct sn_nsdl_ep_parameters_ { + uint8_t *endpoint_name_ptr; /**< Endpoint name */ + uint8_t endpoint_name_len; + + uint8_t *domain_name_ptr; /**< Domain to register. If null, NSP uses default domain */ + uint8_t domain_name_len; + + uint8_t *type_ptr; /**< Endpoint type */ + uint8_t type_len; + + uint8_t *lifetime_ptr; /**< Endpoint lifetime in seconds. eg. "1200" = 1200 seconds */ + uint8_t lifetime_len; + + sn_nsdl_registration_mode_t ds_register_mode; /**< Defines registration mode */ + sn_nsdl_oma_binding_and_mode_t binding_and_mode; /**< Defines endpoints binding and mode */ + + uint8_t *location_ptr; /**< Endpoint location in server, optional parameter,default is NULL */ + uint8_t location_len; + +} sn_nsdl_ep_parameters_s; + +/** + * \brief For internal use + */ +typedef struct sn_nsdl_sent_messages_ { + uint16_t msg_id_number; + uint8_t message_type; + ns_list_link_t link; +} sn_nsdl_sent_messages_s; + +/** + * \brief Includes resource path + */ +typedef struct sn_grs_resource_ { + uint8_t pathlen; + uint8_t *path; +} sn_grs_resource_s; + +/** + * \brief Table of created resources + */ +typedef struct sn_grs_resource_list_ { + uint8_t res_count; /**< Number of resources */ + sn_grs_resource_s *res; +} sn_grs_resource_list_s; + +/** + * \brief Resource access rights + */ +typedef enum sn_grs_resource_acl_ { + SN_GRS_GET_ALLOWED = 0x01 , + SN_GRS_PUT_ALLOWED = 0x02, + SN_GRS_POST_ALLOWED = 0x04, + SN_GRS_DELETE_ALLOWED = 0x08 +} sn_grs_resource_acl_e; + + +typedef enum sn_nsdl_oma_device_error_ { + NO_ERROR = 0, + LOW_BATTERY_POWER = 1, + EXTERNAL_POWER_SUPPLY_OFF = 2, + GPS_MODULE_FAILURE = 3, + LOW_RECEIVED_SIGNAL_STRENGTH = 4, + OUT_OF_MEMORY = 5, + SMS_FAILURE = 6, + IP_CONN_FAILURE = 7, + PERIPHERAL_MALFUNCTION = 8 +} sn_nsdl_oma_device_error_t; + +/** + * \brief Defines the resource mode + */ +typedef enum sn_nsdl_resource_mode_ { + SN_GRS_STATIC, /**< Static resources have some value that doesn't change */ + SN_GRS_DYNAMIC, /**< Dynamic resources are handled in application. Therefore one must give function callback pointer to them */ + SN_GRS_DIRECTORY /**< Directory resources are unused and unsupported */ +} sn_nsdl_resource_mode_e; + +/** + * \brief Resource registration parameters + */ +typedef struct sn_nsdl_resource_parameters_ { + uint8_t *resource_type_ptr; + uint16_t resource_type_len; + + uint8_t *interface_description_ptr; + uint16_t interface_description_len; + + uint8_t coap_content_type; + + uint8_t mime_content_type; + + uint8_t observable; + + uint8_t registered; + +} sn_nsdl_resource_parameters_s; + +/** + * \brief Defines parameters for the resource. + */ +typedef struct sn_nsdl_resource_info_ { + sn_nsdl_resource_parameters_s *resource_parameters_ptr; + + sn_nsdl_resource_mode_e mode; /**< STATIC etc.. */ + + uint16_t pathlen; /**< Address */ + uint8_t *path; + + uint16_t resourcelen; /**< 0 if dynamic resource, resource information in static resource */ + uint8_t *resource; /**< NULL if dynamic resource */ + + sn_grs_resource_acl_e access; + + uint8_t (*sn_grs_dyn_res_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *, sn_nsdl_capab_e); + + ns_list_link_t link; + + uint8_t publish_uri; + +} sn_nsdl_resource_info_s; + +/** + * \brief Defines OMA device object parameters. + */ +typedef struct sn_nsdl_oma_device_ { + sn_nsdl_oma_device_error_t error_code; /**< Error code. Mandatory. Can be more than one */ + uint8_t (*sn_oma_device_boot_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *, sn_nsdl_capab_e); /**< Device boot callback function. If defined, this is called when reset request is received */ + +} sn_nsdl_oma_device_t; + +/** + * \brief Defines OMAlw server information + */ +typedef struct sn_nsdl_oma_server_info_ { + sn_nsdl_addr_s *omalw_address_ptr; + omalw_server_security_t omalw_server_security; + +} sn_nsdl_oma_server_info_t; + +/** + * \brief Defines endpoint parameters to OMA bootstrap. + */ +typedef struct sn_nsdl_bs_ep_info_ { + void (*oma_bs_status_cb)(sn_nsdl_oma_server_info_t *); /**< Callback for OMA bootstrap status */ + sn_nsdl_oma_device_t *device_object; /**< OMA LWM2M mandatory device resources */ +} sn_nsdl_bs_ep_info_t; + + + + +/** + * \fn struct nsdl_s *sn_nsdl_init (uint8_t (*sn_nsdl_tx_cb)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + * uint8_t (*sn_nsdl_rx_cb)(sn_coap_hdr_s *, sn_nsdl_addr_s *), + * sn_nsdl_mem_s *sn_memory) + * + * \brief Initialization function for NSDL library. Initializes NSDL, GRS, HTTP and CoAP. + * + * \param *sn_nsdl_tx_callback A callback function for sending messages. + * + * \param *sn_nsdl_rx_callback A callback function for parsed messages. If received message is not CoAP protocol message (eg. ACK), message for GRS (GET, PUT, POST, DELETE) or + * reply for some DS messages (register message etc.), rx callback will be called. + * + * \param *sn_memory Memory structure which includes function pointers to the allocation and free functions. + * + * \return pointer to created handle structure. NULL if failed + */ +struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *)); + +/** + * \fn extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); + * + * \brief Registers endpoint to mbed Device Server. + * \param *handle Pointer to nsdl-library handle + * \param *endpoint_info_ptr Contains endpoint information. + * + * \return registration message ID, 0 if failed + */ +extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); + +/** + * \fn extern uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle) + * + * \brief Sends unregister-message to mbed Device Server. + * + * \param *handle Pointer to nsdl-library handle + * + * \return unregistration message ID, 0 if failed + */ +extern uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle); + +/** + * \fn extern uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len); + * + * \brief Update the registration with mbed Device Server. + * + * \param *handle Pointer to nsdl-library handle + * \param *lt_ptr Pointer to lifetime value string in ascii form, eg. "1200" + * \param lt_len Length of the lifetime string + * + * \return registration update message ID, 0 if failed + */ +extern uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len); + +/** + * \fn extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len); + * + * \brief Sets the location receievd from Device Server. + * + * \param *handle Pointer to nsdl-library handle + * \param *lt_ptr Pointer to location value string , eg. "s322j4k" + * \param lt_len Length of the location string + * + * \return success, 0 if failed -1 + */ +extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len); + + +/** + * \fn extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle) + * + * \brief Checks if endpoint is registered. + * + * \param *handle Pointer to nsdl-library handle + * + * \return 1 Endpoint registration is done successfully + * \return 0 Endpoint is not registered + */ +extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle); + +/** + * \fn extern void sn_nsdl_nsp_lost(struct nsdl_s *handle); + * + * \brief A function to inform mbed Device C client library if application detects a fault in mbed Device Server registration. + * + * \param *handle Pointer to nsdl-library handle + * + * After calling this function sn_nsdl_is_ep_registered() will return "not registered". + */ +extern void sn_nsdl_nsp_lost(struct nsdl_s *handle); + +/** + * \fn extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + * uint8_t *payload_ptr, uint16_t payload_len, + * uint8_t *observe_ptr, uint8_t observe_len, + * sn_coap_msg_type_e message_type, uint8_t content_type) + * + * + * \brief Sends observation message to mbed Device Server + * + * \param *handle Pointer to nsdl-library handle + * \param *token_ptr Pointer to token to be used + * \param token_len Token length + * \param *payload_ptr Pointer to payload to be sent + * \param payload_len Payload length + * \param *observe_ptr Pointer to observe number to be sent + * \param observe_len Observe number len + * \param message_type Observation message type (confirmable or non-confirmable) + * \param content_type Observation message payload contetnt type + * + * \return !0 Success, observation messages message ID + * \return 0 Failure + */ +extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, + uint8_t content_type); + +/** + * \fn extern uint16_t sn_nsdl_send_observation_notification_with_uri_path(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + * uint8_t *payload_ptr, uint16_t payload_len, + * uint8_t *observe_ptr, uint8_t observe_len, + * sn_coap_msg_type_e message_type, uint8_t content_type, + * uint8_t *uri_path_ptr, + * uint16_t uri_path_len) + * + * + * \brief Sends observation message to mbed Device Server with uri path + * + * \param *handle Pointer to nsdl-library handle + * \param *token_ptr Pointer to token to be used + * \param token_len Token length + * \param *payload_ptr Pointer to payload to be sent + * \param payload_len Payload length + * \param *observe_ptr Pointer to observe number to be sent + * \param observe_len Observe number len + * \param message_type Observation message type (confirmable or non-confirmable) + * \param content_type Observation message payload contetnt type + * \param uri_path_ptr Pointer to uri path to be sent + * \param uri_path_len Uri path len + * + * \return !0 Success, observation messages message ID + * \return 0 Failure + */ +extern uint16_t sn_nsdl_send_observation_notification_with_uri_path(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, + uint8_t content_type, + uint8_t *uri_path_ptr, + uint16_t uri_path_len); + +/** + * \fn extern uint32_t sn_nsdl_get_version(void) + * + * \brief Version query function. + * + * Used to retrieve the version information from the mbed Device C Client library. + * + * \return Pointer to library version string +*/ +extern char *sn_nsdl_get_version(void); + +/** + * \fn extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src) + * + * \brief To push CoAP packet to mbed Device C Client library + * + * Used to push an CoAP packet to mbed Device C Client library for processing. + * + * \param *handle Pointer to nsdl-library handle + * + * \param *packet Pointer to a uint8_t array containing the packet (including the CoAP headers). + * After successful execution this array may contain the response packet. + * + * \param *packet_len Pointer to length of the packet. After successful execution this array may contain the length + * of the response packet. + * + * \param *src Pointer to packet source address information. After successful execution this array may contain + * the destination address of the response packet. + * + * \return 0 Success + * \return -1 Failure + */ +extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src); + +/** + * \fn extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time); + * + * \brief CoAP retransmission function. + * + * Used to give execution time for the mbed Device C Client library for retransmissions. + * + * \param *handle Pointer to nsdl-library handle + * + * \param time Time in seconds. + * + * \return 0 Success + * \return -1 Failure + */ +extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time); + +/** + * \fn extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); + * + * \brief Resource creating function. + * + * Used to create a static or dynamic CoAP resource. + * + * \param *res Pointer to a structure of type sn_nsdl_resource_info_t that contains the information + * about the resource. + * + * \return 0 Success + * \return -1 Failure + * \return -2 Resource already exists + * \return -3 Invalid path + * \return -4 List adding failure + */ +extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); + +/** + * \fn extern int8_t sn_nsdl_update_resource(sn_nsdl_resource_info_s *res) + * + * \brief Resource updating function. + * + * Used to update the direct value of a static resource, the callback function pointer of a dynamic resource + * and access rights of the recource. + * + * \param *handle Pointer to nsdl-library handle + * \param *res Pointer to a structure of type sn_nsdl_resource_info_t that contains the information + * about the resource. Only the pathlen and path elements are evaluated along with + * either resourcelen and resource or the function pointer. + * + * \return 0 Success + * \return -1 Failure + */ +extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); + +/** + * \fn extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint8_t pathlen, uint8_t *path) + * + * \brief Resource delete function. + * + * Used to delete a resource. If resource has a subresources, these all must also be removed. + * + * \param *handle Pointer to nsdl-library handle + * \param pathlen Contains the length of the path that is to be deleted (excluding possible trailing "\0"). + * \param *path_ptr A pointer to an array containing the path. + * + * \return 0 Success + * \return -1 Failure (No such resource) + */ +extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); + +/** + * \fn extern sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) + * + * \brief Resource get function. + * + * Used to get a resource. + * + * \param *handle Pointer to nsdl-library handle + * \param pathlen Contains the length of the path that is to be returned (excluding possible trailing '\0'). + * \param *path A pointer to an array containing the path. + * + * \return !NULL Success, pointer to a sn_nsdl_resource_info_s that contains the resource information\n + * \return NULL Failure + */ +extern sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); + +/** + * \fn extern sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) + * + * \brief Resource list function. + * + * \param *handle Pointer to nsdl-library handle + * \param pathlen Contains the length of the target path (excluding possible trailing '\0'). + * The length value is not examined if the path itself is a NULL pointer. + * \param *path A pointer to an array containing the path or a NULL pointer. + * + * \return !NULL A pointer to a sn_grs_resource_list_s structure containing the resource listing. + * \return NULL Failure with an unspecified error + */ +sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); + +/** + * \fn extern void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list) + * + * \brief Free a resource list obtained from sn_nsdl_list_resource() + * + * \param list The list to free, or NULL. + */ +void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list); + +/** + * \fn extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr); + * + * \brief Send an outgoing CoAP request. + * + * \param *handle Pointer to nsdl-library handle + * \param *address_ptr Pointer to source address struct + * \param *coap_hdr_ptr Pointer to CoAP message to be sent + * + * \return 0 Success + * \return -1 Failure + */ +extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr); + +/** + * \fn extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type); + * + * \brief This function is used to set the mbed Device Server address given by an application. + * + * \param *handle Pointer to nsdl-library handle + * \return 0 Success + * \return -1 Failed to indicate that internal address pointer is not allocated (call nsdl_init() first). + */ +extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type); + +/** + * \fn extern int8_t sn_nsdl_destroy(struct nsdl_s *handle); + * + * \param *handle Pointer to nsdl-library handle + * \brief This function releases all allocated memory in mbed Device C Client library. + */ +extern int8_t sn_nsdl_destroy(struct nsdl_s *handle); + +/** + * \fn extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr); + * + * \brief Starts OMA bootstrap process + * + * \param *handle Pointer to nsdl-library handle + * + * \return bootstrap message ID, 0 if failed + */ +extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr); + +/** + * \fn extern omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle); + * + * \brief Get pointer to received device server certificates + * + * \param *handle Pointer to nsdl-library handle + */ +extern omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle); + +/** + * \fn extern int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t* certificate_ptr, uint8_t certificate_chain); + * + * \brief Updates certificate pointers to resource server. + * + * \param *handle Pointer to nsdl-library handle + */ +extern int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t *certificate_ptr, uint8_t certificate_chain); + +/** + * \fn extern int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr); + * + * \brief Creates new device object resource + * + * \param *handle Pointer to nsdl-library handle + */ +extern int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr); + +/** + * \fn sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) + * + * \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s + * + * \param *handle Pointer to library handle + * \param *coap_packet_ptr The request packet pointer + * \param msg_code response messages code + * + * \return *coap_packet_ptr The allocated and pre-filled response packet pointer + * NULL Error in parsing the request + * + */ +extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code); + +/** + * \fn void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) + * + * \brief Releases memory of given CoAP message + * + * Note!!! Does not release Payload part + * + * \param *handle Pointer to CoAP library handle + * + * \param *freed_coap_msg_ptr is pointer to released CoAP message + */ +extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr); + +/** + * \fn int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, uint8_t resending_count, uint8_t resending_intervall) + * + * \brief If re-transmissions are enabled, this function changes resending count and interval. + * + * \param *handle Pointer to library handle + * \param uint8_t resending_count max number of resendings for message + * \param uint8_t resending_intervall message resending intervall in seconds + * \return 0 = success, -1 = failure + */ +extern int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, uint8_t resending_count, uint8_t resending_interval); + +/** + * \fn int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle, uint8_t buffer_size_messages, uint16_t buffer_size_bytes) + * + * \brief If re-transmissions are enabled, this function changes message retransmission queue size. + * Set size to '0' to disable feature. If both are set to '0', then re-sendings are disabled. + * + * \param *handle Pointer to library handle + * \param uint8_t buffer_size_messages queue size - maximum number of messages to be saved to queue + * \param uint8_t buffer_size_bytes queue size - maximum size of messages saved to queue + * \return 0 = success, -1 = failure + */ +extern int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle, + uint8_t buffer_size_messages, uint16_t buffer_size_bytes); + +/** + * \fn int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size) + * + * \brief If block transfer is enabled, this function changes the block size. + * + * \param *handle Pointer to library handle + * \param uint16_t block_size maximum size of CoAP payload. Valid sizes are 16, 32, 64, 128, 256, 512 and 1024 bytes + * \return 0 = success, -1 = failure + */ +extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size); + +/** + * \fn int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle,uint8_t message_count) + * + * \brief If dublicate message detection is enabled, this function changes buffer size. + * + * \param *handle Pointer to library handle + * \param uint8_t message_count max number of messages saved for duplicate control + * \return 0 = success, -1 = failure + */ +extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count); + +#ifdef __cplusplus +} +#endif + +#endif /* SN_NSDL_LIB_H_ */
--- a/source/libCoap/src/include/sn_coap_header_internal.h Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libCoap/src/include/sn_coap_header_internal.h Sat Apr 02 00:39:03 2016 +0300 @@ -64,6 +64,8 @@ uint16_t packet_len; uint8_t *packet_ptr; + uint8_t *uri_path_ptr; + uint8_t uri_path_len; } sn_nsdl_transmit_s; /* * * * * * * * * * * * * * * * * * * * * * */ @@ -76,4 +78,3 @@ #ifdef __cplusplus } #endif -
--- a/source/libCoap/src/include/sn_coap_protocol_internal.h Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libCoap/src/include/sn_coap_protocol_internal.h Sat Apr 02 00:39:03 2016 +0300 @@ -31,13 +31,6 @@ extern "C" { #endif -struct coap_s { - void *(*sn_coap_protocol_malloc)(uint16_t); - void (*sn_coap_protocol_free)(void *); - - uint8_t (*sn_coap_tx_callback)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *); - int8_t (*sn_coap_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *); -}; /* * * * * * * * * * * */ /* * * * DEFINES * * * */ @@ -63,8 +56,8 @@ /* Init value for the maximum count of messages to be stored for duplication detection */ /* Setting of this value to 0 will disable duplication check, also reduce use of ROM memory */ -#ifndef SN_COAP_DUPLICATION_MAX_MSGS_COUNT -#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT 0 +#ifndef YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT +#define YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT 0 #endif /* Maximum allowed number of saved messages for duplicate searching */ #define SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT 6 @@ -78,8 +71,8 @@ /* Setting of this value to 0 will disable this feature, and also reduce use of ROM memory */ /* Note: Current Coap implementation supports Blockwise transfers specification version draft-ietf-core-block-03 */ /* Note: This define is common for both received and sent Blockwise messages */ -#ifndef SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE -#define SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE 0 /**< Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024 */ +#ifndef YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE +#define YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 0 /**< Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024 */ #endif #ifndef SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED @@ -87,6 +80,7 @@ #endif + /* * * * * * * * * * * * * * */ /* * * * ENUMERATIONS * * * */ /* * * * * * * * * * * * * * */ @@ -96,6 +90,8 @@ /* * * * * * * * * * * * * */ + + /* Structure which is stored to Linked list for message sending purposes */ typedef struct coap_send_msg_ { uint8_t resending_counter; /* Tells how many times message is still tried to resend */ @@ -157,10 +153,40 @@ typedef NS_LIST_HEAD(coap_blockwise_payload_s, link) coap_blockwise_payload_list_t; +struct coap_s { + void *(*sn_coap_protocol_malloc)(uint16_t); + void (*sn_coap_protocol_free)(void *); + + uint8_t (*sn_coap_tx_callback)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *); + int8_t (*sn_coap_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *); + + #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ + coap_send_msg_list_t linked_list_resent_msgs; /* Active resending messages are stored to this Linked list */ + uint16_t count_resent_msgs; + #endif + + #if YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ + coap_duplication_info_list_t linked_list_duplication_msgs; /* Messages for duplicated messages detection is stored to this Linked list */ + uint16_t count_duplication_msgs; + #endif + + #if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not used at all, this part of code will not be compiled */ + coap_blockwise_msg_list_t linked_list_blockwise_sent_msgs; /* Blockwise message to to be sent is stored to this Linked list */ + coap_blockwise_payload_list_t linked_list_blockwise_received_payloads; /* Blockwise payload to to be received is stored to this Linked list */ + #endif + + uint32_t system_time; /* System time seconds */ + uint16_t sn_coap_block_data_size; + uint8_t sn_coap_resending_queue_msgs; + uint8_t sn_coap_resending_queue_bytes; + uint8_t sn_coap_resending_count; + uint8_t sn_coap_resending_intervall; + uint8_t sn_coap_duplication_buffer_size; +}; + #ifdef __cplusplus } #endif #endif /* SN_COAP_PROTOCOL_INTERNAL_H_ */ -
--- a/source/libCoap/src/sn_coap_builder.c Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libCoap/src/sn_coap_builder.c Sat Apr 02 00:39:03 2016 +0300 @@ -39,23 +39,15 @@ static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option); -static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, uint8_t *option_ptr, sn_coap_option_numbers_e option_number); -static int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number); -static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option); +static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number); +static int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number); +static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number); static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option); static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option); static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option); static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option); -/* * * * GLOBAL DECLARATIONS * * * */ -static uint16_t global_previous_option_number = 0; /* Previous Option number in CoAP message */ - -/* * * * EXTERN VARIABLES * * * */ -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE -extern uint16_t sn_coap_block_data_size; /* From sn_coap_protocol_ieft_draft_12.c */ -#endif - sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) { sn_coap_hdr_s *coap_res_ptr; @@ -102,6 +94,11 @@ int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr) { + return sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); +} + +int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) +{ uint8_t *base_packet_data_ptr = NULL; /* * * * Check given pointers * * * */ @@ -110,7 +107,7 @@ } /* Initialize given Packet data memory area with zero values */ - uint16_t dst_byte_count_to_be_built = sn_coap_builder_calc_needed_packet_data_size(src_coap_msg_ptr); + uint16_t dst_byte_count_to_be_built = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, blockwise_payload_size); if (!dst_byte_count_to_be_built) { return -1; @@ -145,8 +142,12 @@ /* * * * Return built Packet data length * * * */ return (dst_packet_data_ptr - base_packet_data_ptr); } +uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr) +{ + return sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); +} -uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr) +uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) { uint16_t returned_byte_count = 0; @@ -175,16 +176,20 @@ } /* URI PATH - Repeatable option. Length of one option is 0-255 */ - if (src_coap_msg_ptr->uri_path_ptr != NULL) { - repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->uri_path_len, - src_coap_msg_ptr->uri_path_ptr, COAP_OPTION_URI_PATH); - if (repeatable_option_size) { - returned_byte_count += repeatable_option_size; - } else { - return 0; + /* Do not add uri-path for notification message. + * Uri-path is needed for cancelling observation with RESET message */ + if (!src_coap_msg_ptr->options_list_ptr || + (src_coap_msg_ptr->options_list_ptr && !src_coap_msg_ptr->options_list_ptr->observe_len && !src_coap_msg_ptr->options_list_ptr->observe_ptr)) { + if (src_coap_msg_ptr->uri_path_ptr != NULL) { + repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->uri_path_len, + src_coap_msg_ptr->uri_path_ptr, COAP_OPTION_URI_PATH); + if (repeatable_option_size) { + returned_byte_count += repeatable_option_size; + } else { + return 0; + } } } - /* CONTENT TYPE - Length of this option is 0-2 bytes */ if (src_coap_msg_ptr->content_type_ptr != NULL) { returned_byte_count++; @@ -346,8 +351,8 @@ } /* * * * * PAYLOAD * * * * */ -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ - if ((src_coap_msg_ptr->payload_len > sn_coap_block_data_size) && (sn_coap_block_data_size > 0)) { +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ + if ((src_coap_msg_ptr->payload_len > blockwise_payload_size) && (blockwise_payload_size > 0)) { /* Two bytes for Block option */ returned_byte_count += 2; @@ -357,7 +362,7 @@ returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 2); } /* Add maximum payload at one Blockwise message */ - returned_byte_count += sn_coap_block_data_size; + returned_byte_count += blockwise_payload_size; returned_byte_count ++; /* For payload marker */ } else { returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 0); @@ -495,7 +500,7 @@ previous_option_number = (COAP_OPTION_CONTENT_FORMAT); } -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE //block_option 1 & 2 only used if this maro is defined +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE //block_option 1 & 2 only used if this maro is defined if (block_option == 2) { if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12) { needed_space += 1; @@ -585,7 +590,7 @@ /* Then build rest of the options */ /* * * * Initialize previous Option number for new built message * * * */ - global_previous_option_number = 0; + uint16_t previous_option_number = 0; //missing: COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH, COAP_OPTION_SIZE @@ -593,65 +598,73 @@ if (src_coap_msg_ptr->options_list_ptr != NULL) { /* * * * Build Uri-Host option * * * */ sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_host_len, - src_coap_msg_ptr->options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST); + src_coap_msg_ptr->options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST, &previous_option_number); /* * * * Build ETag option * * * */ sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->etag_ptr, - (uint16_t *)&src_coap_msg_ptr->options_list_ptr->etag_len, COAP_OPTION_ETAG); + (uint16_t *)&src_coap_msg_ptr->options_list_ptr->etag_len, COAP_OPTION_ETAG, &previous_option_number); /* * * * Build Observe option * * * * */ ret_status = sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->observe_len, - src_coap_msg_ptr->options_list_ptr->observe_ptr, COAP_OPTION_OBSERVE); + src_coap_msg_ptr->options_list_ptr->observe_ptr, COAP_OPTION_OBSERVE, &previous_option_number); if (ret_status == 0) { - sn_coap_builder_options_build_add_zero_length_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->observe_len, src_coap_msg_ptr->options_list_ptr->observe, COAP_OPTION_OBSERVE); + sn_coap_builder_options_build_add_zero_length_option(dst_packet_data_pptr, + src_coap_msg_ptr->options_list_ptr->observe_len, + src_coap_msg_ptr->options_list_ptr->observe, + COAP_OPTION_OBSERVE, + &previous_option_number); } /* * * * Build Uri-Port option * * * */ sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_port_len, - src_coap_msg_ptr->options_list_ptr->uri_port_ptr, COAP_OPTION_URI_PORT); + src_coap_msg_ptr->options_list_ptr->uri_port_ptr, COAP_OPTION_URI_PORT, &previous_option_number); /* * * * Build Location-Path option * * * */ sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_path_ptr, - &src_coap_msg_ptr->options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH); + &src_coap_msg_ptr->options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH, &previous_option_number); } /* * * * Build Uri-Path option * * * */ - sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->uri_path_ptr, - &src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH); + /* Do not add uri-path for notification message. + * Uri-path is needed for cancelling observation with RESET message */ + if (!src_coap_msg_ptr->options_list_ptr || + (src_coap_msg_ptr->options_list_ptr && !src_coap_msg_ptr->options_list_ptr->observe_len && !src_coap_msg_ptr->options_list_ptr->observe_ptr)) + sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->uri_path_ptr, + &src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH, &previous_option_number); /* * * * Build Content-Type option * * * */ sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->content_type_len, - src_coap_msg_ptr->content_type_ptr, COAP_OPTION_CONTENT_FORMAT); + src_coap_msg_ptr->content_type_ptr, COAP_OPTION_CONTENT_FORMAT, &previous_option_number); if (src_coap_msg_ptr->options_list_ptr != NULL) { /* * * * Build Max-Age option * * * */ sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->max_age_len, - src_coap_msg_ptr->options_list_ptr->max_age_ptr, COAP_OPTION_MAX_AGE); + src_coap_msg_ptr->options_list_ptr->max_age_ptr, COAP_OPTION_MAX_AGE, &previous_option_number); /* * * * Build Uri-Query option * * * * */ sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->uri_query_ptr, - &src_coap_msg_ptr->options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY); + &src_coap_msg_ptr->options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY, &previous_option_number); /* * * * Build Accept option * * * * */ sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->accept_ptr, - (uint16_t *)&src_coap_msg_ptr->options_list_ptr->accept_len, COAP_OPTION_ACCEPT); + (uint16_t *)&src_coap_msg_ptr->options_list_ptr->accept_len, COAP_OPTION_ACCEPT, &previous_option_number); } if (src_coap_msg_ptr->options_list_ptr != NULL) { /* * * * Build Location-Query option * * * */ sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_query_ptr, - &src_coap_msg_ptr->options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY); + &src_coap_msg_ptr->options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY, &previous_option_number); /* * * * Build Block2 option * * * * */ sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block2_len, - src_coap_msg_ptr->options_list_ptr->block2_ptr, COAP_OPTION_BLOCK2); + src_coap_msg_ptr->options_list_ptr->block2_ptr, COAP_OPTION_BLOCK2, &previous_option_number); /* * * * Build Block1 option * * * * */ sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block1_len, - src_coap_msg_ptr->options_list_ptr->block1_ptr, COAP_OPTION_BLOCK1); + src_coap_msg_ptr->options_list_ptr->block1_ptr, COAP_OPTION_BLOCK1, &previous_option_number); /* * * * Build Proxy-Uri option * * * */ sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->proxy_uri_len, - src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI); + src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI, &previous_option_number); } /* Success */ @@ -674,13 +687,13 @@ * \return Return value is 0 if option was not added, 1 if added */ static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, - uint8_t *option_ptr, sn_coap_option_numbers_e option_number) + uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number) { /* Check if there is option at all */ if (option_ptr != NULL) { uint16_t option_delta; - option_delta = (option_number - global_previous_option_number); + option_delta = (option_number - *previous_option_number); /* * * Build option header * * */ @@ -732,7 +745,7 @@ *dst_packet_data_pptr += 2; } - global_previous_option_number = option_number; + *previous_option_number = option_number; /* Write Option value */ memcpy(*dst_packet_data_pptr, option_ptr, option_len); @@ -750,12 +763,16 @@ /* * @return 1 if was added 0 otherwise */ -int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number) +int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, + uint8_t option_length, + uint8_t option_exist, + sn_coap_option_numbers_e option_number, + uint16_t *previous_option_number) { if ((option_exist != 0) && (option_length == 0)) { uint16_t option_delta; - option_delta = (option_number - global_previous_option_number); + option_delta = (option_number - *previous_option_number); /* * * Build option header * * */ @@ -786,7 +803,7 @@ } //<-- Cannot happen currently - global_previous_option_number = option_number; + *previous_option_number = option_number; return 1; } @@ -808,7 +825,7 @@ * * \return Return value is 0 always */ -static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option) +static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number) { /* Check if there is option at all */ if (*src_pptr != NULL) { @@ -830,7 +847,7 @@ query_part_offset = sn_coap_builder_options_get_option_part_position(query_len, query_ptr, i, option); /* Add Uri-query's one part to Options */ - sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, *src_pptr + query_part_offset, option); + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, *src_pptr + query_part_offset, option, previous_option_number); } } /* Success */ @@ -1086,7 +1103,7 @@ static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) { /* Check if Payload is used at all */ - if (src_coap_msg_ptr->payload_ptr != NULL) { + if (src_coap_msg_ptr->payload_len && src_coap_msg_ptr->payload_ptr != NULL) { /* Write Payload marker */ **dst_packet_data_pptr = 0xff; @@ -1099,4 +1116,3 @@ (*dst_packet_data_pptr) += src_coap_msg_ptr->payload_len; } } -
--- a/source/libCoap/src/sn_coap_header_check.c Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libCoap/src/sn_coap_header_check.c Sat Apr 02 00:39:03 2016 +0300 @@ -97,4 +97,3 @@ /* Success */ return 0; } -
--- a/source/libCoap/src/sn_coap_parser.c Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libCoap/src/sn_coap_parser.c Sat Apr 02 00:39:03 2016 +0300 @@ -70,20 +70,18 @@ /* * * * Header parsing, move pointer over the header... * * * */ sn_coap_parser_header_parse(&data_temp_ptr, parsed_and_returned_coap_msg_ptr, coap_version_ptr); - /* * * * Options parsing, move pointer over the options... * * * */ - if (sn_coap_parser_options_parse(handle, &data_temp_ptr, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len) != 0) { - /* Release memory of CoAP message */ - sn_coap_parser_release_allocated_coap_msg_mem(handle, parsed_and_returned_coap_msg_ptr); - return NULL; + if (sn_coap_parser_options_parse(handle, &data_temp_ptr, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len) != 0) { + parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; + return parsed_and_returned_coap_msg_ptr; } /* * * * Payload parsing * * * */ if (sn_coap_parser_payload_parse(packet_data_len, packet_data_ptr, &data_temp_ptr, parsed_and_returned_coap_msg_ptr) == -1) { - /* Release memory of CoAP message */ - sn_coap_parser_release_allocated_coap_msg_mem(handle, parsed_and_returned_coap_msg_ptr); - return NULL; + parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; + return parsed_and_returned_coap_msg_ptr; } + /* * * * Return parsed CoAP message * * * * */ return parsed_and_returned_coap_msg_ptr; } @@ -683,6 +681,9 @@ if(ret_value >= packet_left_len) break; + if( i == packet_left_len ) + break; + if ((*(packet_data_ptr + i) >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0) { return (ret_value - 1); /* -1 because last Part path does not include separator */ } @@ -747,4 +748,3 @@ } return 0; } -
--- a/source/libCoap/src/sn_coap_protocol.c Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libCoap/src/sn_coap_protocol.c Sat Apr 02 00:39:03 2016 +0300 @@ -31,7 +31,7 @@ #include <stdio.h> #include <stdlib.h> /* For libary malloc() */ #include <string.h> /* For memset() and memcpy() */ -#ifdef __linux__ +#if defined __linux__ || defined TARGET_LIKE_MBED #include <time.h> #endif @@ -46,27 +46,27 @@ /* * * * * * * * * * * * * * * * * * * * */ static void sn_coap_protocol_send_rst(struct coap_s *handle, uint16_t msg_id, sn_nsdl_addr_s *addr_ptr, void *param); -#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); -static int8_t sn_coap_protocol_linked_list_duplication_info_search(sn_nsdl_addr_s *scr_addr_ptr, uint16_t msg_id); +static int8_t sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle, sn_nsdl_addr_s *scr_addr_ptr, uint16_t msg_id); static void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, uint8_t *scr_addr_ptr, uint16_t port, uint16_t msg_id); static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle); #endif -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr); static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, uint16_t stored_payload_len, uint8_t *stored_payload_ptr); -static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length); +static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length); static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, coap_blockwise_payload_s *removed_payload_ptr); static void sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle); -static uint16_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(sn_nsdl_addr_s *src_addr_ptr); +static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr); static void sn_coap_protocol_linked_list_blockwise_remove_old_data(struct coap_s *handle); static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param); static int8_t sn_coap_convert_block_size(uint16_t block_size); static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr); #endif #if ENABLE_RESENDINGS -static void sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param); -static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); +static void sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param, uint8_t *uri_path_ptr, uint8_t uri_path_len); +static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(struct coap_s *handle,sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); static coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len); static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr); @@ -78,32 +78,6 @@ /* * * * * * * * * * * * * * * * * */ static uint16_t message_id; -#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ -static coap_send_msg_list_t NS_LIST_NAME_INIT(global_linked_list_resent_msgs); /* Active resending messages are stored to this Linked list */ -static uint16_t global_count_resent_msgs = 0; -#endif -#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ -static coap_duplication_info_list_t NS_LIST_NAME_INIT(global_linked_list_duplication_msgs); /* Messages for duplicated messages detection is stored to this Linked list */ -static uint16_t global_count_duplication_msgs = 0; - -#endif -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwise is not used at all, this part of code will not be compiled */ -static coap_blockwise_msg_list_t NS_LIST_NAME_INIT(global_linked_list_blockwise_sent_msgs); /* Blockwise message to to be sent is stored to this Linked list */ -static coap_blockwise_payload_list_t NS_LIST_NAME_INIT(global_linked_list_blockwise_received_payloads); /* Blockwise payload to to be received is stored to this Linked list */ -#endif - -static uint32_t global_system_time = 0; /* System time seconds */ - -uint16_t sn_coap_block_data_size = 0; - -uint8_t sn_coap_resending_queue_msgs = 0; -uint8_t sn_coap_resending_queue_bytes = 0; -uint8_t sn_coap_resending_count = 0; -uint8_t sn_coap_resending_intervall = 0; - -uint8_t sn_coap_duplication_buffer_size = 0; - - int8_t sn_coap_protocol_destroy(struct coap_s *handle) { if (handle == NULL) { @@ -115,23 +89,23 @@ #endif -#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ - ns_list_foreach_safe(coap_duplication_info_s, tmp, &global_linked_list_duplication_msgs) { +#if YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ + ns_list_foreach_safe(coap_duplication_info_s, tmp, &handle->linked_list_duplication_msgs) { if (tmp->coap == handle) { if (tmp->addr_ptr) { handle->sn_coap_protocol_free(tmp->addr_ptr); tmp->addr_ptr = 0; } - ns_list_remove(&global_linked_list_duplication_msgs, tmp); - global_count_duplication_msgs--; + ns_list_remove(&handle->linked_list_duplication_msgs, tmp); + handle->count_duplication_msgs--; handle->sn_coap_protocol_free(tmp); tmp = 0; } } #endif -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwise is not used at all, this part of code will not be compiled */ - ns_list_foreach_safe(coap_blockwise_msg_s, tmp, &global_linked_list_blockwise_sent_msgs) { +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not used at all, this part of code will not be compiled */ + ns_list_foreach_safe(coap_blockwise_msg_s, tmp, &handle->linked_list_blockwise_sent_msgs) { if (tmp->coap == handle) { if (tmp->coap_msg_ptr) { if (tmp->coap_msg_ptr->payload_ptr) { @@ -140,12 +114,12 @@ } sn_coap_parser_release_allocated_coap_msg_mem(tmp->coap, tmp->coap_msg_ptr); } - ns_list_remove(&global_linked_list_blockwise_sent_msgs, tmp); + ns_list_remove(&handle->linked_list_blockwise_sent_msgs, tmp); handle->sn_coap_protocol_free(tmp); tmp = 0; } } - ns_list_foreach_safe(coap_blockwise_payload_s, tmp, &global_linked_list_blockwise_received_payloads) { + ns_list_foreach_safe(coap_blockwise_payload_s, tmp, &handle->linked_list_blockwise_received_payloads) { if (tmp->coap == handle) { if (tmp->addr_ptr) { handle->sn_coap_protocol_free(tmp->addr_ptr); @@ -155,7 +129,7 @@ handle->sn_coap_protocol_free(tmp->payload_ptr); tmp->payload_ptr = 0; } - ns_list_remove(&global_linked_list_blockwise_received_payloads, tmp); + ns_list_remove(&handle->linked_list_blockwise_received_payloads, tmp); handle->sn_coap_protocol_free(tmp); tmp = 0; } @@ -194,31 +168,37 @@ /* If pointer = 0, then re-sending does not return error when failed */ handle->sn_coap_rx_callback = used_rx_callback_ptr; + + #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ /* * * * Create Linked list for storing active resending messages * * * */ - sn_coap_resending_queue_msgs = SN_COAP_RESENDING_QUEUE_SIZE_MSGS; - sn_coap_resending_queue_bytes = SN_COAP_RESENDING_QUEUE_SIZE_BYTES; - sn_coap_resending_intervall = DEFAULT_RESPONSE_TIMEOUT; - sn_coap_resending_count = SN_COAP_RESENDING_MAX_COUNT; + ns_list_init(&handle->linked_list_resent_msgs); + handle->sn_coap_resending_queue_msgs = SN_COAP_RESENDING_QUEUE_SIZE_MSGS; + handle->sn_coap_resending_queue_bytes = SN_COAP_RESENDING_QUEUE_SIZE_BYTES; + handle->sn_coap_resending_intervall = DEFAULT_RESPONSE_TIMEOUT; + handle->sn_coap_resending_count = SN_COAP_RESENDING_MAX_COUNT; + #endif /* ENABLE_RESENDINGS */ -#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ /* * * * Create Linked list for storing Duplication info * * * */ - sn_coap_duplication_buffer_size = SN_COAP_DUPLICATION_MAX_MSGS_COUNT; + ns_list_init(&handle->linked_list_duplication_msgs); + handle->sn_coap_duplication_buffer_size = YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT; #endif -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ - sn_coap_block_data_size = SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE; + ns_list_init(&handle->linked_list_blockwise_sent_msgs); + ns_list_init(&handle->linked_list_blockwise_received_payloads); + handle->sn_coap_block_data_size = YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE; #endif /* ENABLE_RESENDINGS */ /* Randomize global message ID */ #if defined __linux__ || defined TARGET_LIKE_MBED srand(rand()^time(NULL)); - message_id = rand() % 400 + 100; #else message_id = 100; @@ -227,9 +207,14 @@ return handle; } -int8_t sn_coap_protocol_set_block_size(uint16_t block_size) +int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size) { -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE + (void) handle; + (void) block_size; +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + if (handle == NULL) { + return -1; + } switch (block_size) { case 0: case 16: @@ -239,7 +224,7 @@ case 256: case 512: case 1024: - sn_coap_block_data_size = block_size; + handle->sn_coap_block_data_size = block_size; return 0; default: break; @@ -249,28 +234,37 @@ } -int8_t sn_coap_protocol_set_duplicate_buffer_size(uint8_t message_count) +int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count) { -#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT + (void) handle; + (void) message_count; +#if YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT + if (handle == NULL) { + return -1; + } if (message_count <= SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT) { - sn_coap_duplication_buffer_size = message_count; + handle->sn_coap_duplication_buffer_size = message_count; return 0; } #endif return -1; } -int8_t sn_coap_protocol_set_retransmission_parameters(uint8_t resending_count, uint8_t resending_intervall) +int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle, + uint8_t resending_count, uint8_t resending_intervall) { #if ENABLE_RESENDINGS + if (handle == NULL) { + return -1; + } if (resending_count <= SN_COAP_MAX_ALLOWED_RESENDING_COUNT && resending_intervall <= SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT) { - sn_coap_resending_count = resending_count; + handle->sn_coap_resending_count = resending_count; if (resending_intervall == 0) { - sn_coap_resending_intervall = 1; + handle->sn_coap_resending_intervall = 1; } else { - sn_coap_resending_intervall = resending_intervall; + handle->sn_coap_resending_intervall = resending_intervall; } return 0; } @@ -278,13 +272,17 @@ return -1; } -int8_t sn_coap_protocol_set_retransmission_buffer(uint8_t buffer_size_messages, uint16_t buffer_size_bytes) +int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle, + uint8_t buffer_size_messages, uint16_t buffer_size_bytes) { #if ENABLE_RESENDINGS + if (handle == NULL) { + return -1; + } if (buffer_size_bytes <= SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES && buffer_size_messages <= SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS ) { - sn_coap_resending_queue_bytes = buffer_size_bytes; - sn_coap_resending_queue_msgs = buffer_size_messages; + handle->sn_coap_resending_queue_bytes = buffer_size_bytes; + handle->sn_coap_resending_queue_msgs = buffer_size_messages; return 0; } @@ -296,7 +294,10 @@ void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle) { #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ - ns_list_foreach_safe(coap_send_msg_s, tmp, &global_linked_list_resent_msgs) { + if (handle == NULL) { + return; + } + ns_list_foreach_safe(coap_send_msg_s, tmp, &handle->linked_list_resent_msgs) { if (tmp->send_msg_ptr) { if (tmp->send_msg_ptr->dst_addr_ptr) { if (tmp->send_msg_ptr->dst_addr_ptr->addr_ptr) { @@ -310,11 +311,15 @@ handle->sn_coap_protocol_free(tmp->send_msg_ptr->packet_ptr); tmp->send_msg_ptr->packet_ptr = 0; } + if (tmp->send_msg_ptr->uri_path_ptr) { + handle->sn_coap_protocol_free(tmp->send_msg_ptr->uri_path_ptr); + tmp->send_msg_ptr->uri_path_ptr = 0; + } handle->sn_coap_protocol_free(tmp->send_msg_ptr); tmp->send_msg_ptr = 0; } - ns_list_remove(&global_linked_list_resent_msgs, tmp); - --global_count_resent_msgs; + ns_list_remove(&handle->linked_list_resent_msgs, tmp); + --handle->count_resent_msgs; handle->sn_coap_protocol_free(tmp); tmp = 0; } @@ -326,10 +331,9 @@ uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param) { int16_t byte_count_built = 0; -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ uint16_t original_payload_len = 0; #endif - /* * * * Check given pointers * * * */ if ((dst_addr_ptr == NULL) || (dst_packet_data_ptr == NULL) || (src_coap_msg_ptr == NULL) || handle == NULL) { return -2; @@ -352,12 +356,11 @@ } } -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ /* If blockwising needed */ - if ((src_coap_msg_ptr->payload_len > sn_coap_block_data_size) && (sn_coap_block_data_size > 0)) { + if ((src_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) && (handle->sn_coap_block_data_size > 0)) { /* * * * Add Blockwise option to send CoAP message * * */ - if (src_coap_msg_ptr->options_list_ptr == NULL) { /* Allocate memory for less used options */ src_coap_msg_ptr->options_list_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_options_list_s)); @@ -386,7 +389,7 @@ } *(src_coap_msg_ptr->options_list_ptr->block1_ptr) = 0x08; /* First block (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */ - *(src_coap_msg_ptr->options_list_ptr->block1_ptr) |= sn_coap_convert_block_size(sn_coap_block_data_size); + *(src_coap_msg_ptr->options_list_ptr->block1_ptr) |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); } else { /* Response message */ /* Add Blockwise option, use Block2 because Response payload */ @@ -405,14 +408,13 @@ } *(src_coap_msg_ptr->options_list_ptr->block2_ptr) = 0x08; /* First block (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */ - *(src_coap_msg_ptr->options_list_ptr->block2_ptr) |= sn_coap_convert_block_size(sn_coap_block_data_size); + *(src_coap_msg_ptr->options_list_ptr->block2_ptr) |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); } /* Store original Payload length */ original_payload_len = src_coap_msg_ptr->payload_len; - /* Change Payload length of send message because Payload is blockwised */ - src_coap_msg_ptr->payload_len = sn_coap_block_data_size; + src_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size; } #endif @@ -420,7 +422,7 @@ /* * * * Build Packet data from CoAP message by using CoAP Header builder * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - byte_count_built = sn_coap_builder(dst_packet_data_ptr, src_coap_msg_ptr); + byte_count_built = sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, handle->sn_coap_block_data_size); if (byte_count_built < 0) { return byte_count_built; @@ -432,16 +434,16 @@ if (src_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { /* Store message to Linked list for resending purposes */ sn_coap_protocol_linked_list_send_msg_store(handle, dst_addr_ptr, byte_count_built, dst_packet_data_ptr, - global_system_time + (uint32_t)(sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR), - param); + handle->system_time + (uint32_t)(handle->sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR), + param, src_coap_msg_ptr->uri_path_ptr, src_coap_msg_ptr->uri_path_len); } #endif /* ENABLE_RESENDINGS */ -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ /* If blockwising needed */ - if ((original_payload_len > sn_coap_block_data_size) && (sn_coap_block_data_size > 0)) { + if ((original_payload_len > handle->sn_coap_block_data_size) && (handle->sn_coap_block_data_size > 0)) { /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * Manage rest blockwise messages sending by storing them to Linked list * * * */ @@ -457,7 +459,7 @@ memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s)); /* Fill struct */ - stored_blockwise_msg_ptr->timestamp = global_system_time; + stored_blockwise_msg_ptr->timestamp = handle->system_time; stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr); if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){ @@ -480,7 +482,7 @@ stored_blockwise_msg_ptr->coap = handle; - ns_list_add_to_end(&global_linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); + ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); } else if (src_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) { @@ -494,7 +496,7 @@ memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s)); /* Fill struct */ - stored_blockwise_msg_ptr->timestamp = global_system_time; + stored_blockwise_msg_ptr->timestamp = handle->system_time; stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr); if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){ @@ -505,10 +507,10 @@ stored_blockwise_msg_ptr->coap = handle; - ns_list_add_to_end(&global_linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); + ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); } -#endif /* SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE */ +#endif /* YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ /* * * * Return built CoAP message Packet data length * * * */ return byte_count_built; @@ -533,6 +535,12 @@ /* Memory allocation error in parser */ return NULL; } + /* * * * Send bad request response if parsing fails * * * */ + if (returned_dst_coap_msg_ptr->coap_status == COAP_STATUS_PARSER_ERROR_IN_HEADER) { + sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param); + sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); + return NULL; + } /* * * * Check validity of parsed Header values * * * */ if (sn_coap_header_validity_check(returned_dst_coap_msg_ptr, coap_version) != 0) { @@ -540,7 +548,7 @@ if (((returned_dst_coap_msg_ptr->msg_code >> 5) == 1) || // if class == 1 ((returned_dst_coap_msg_ptr->msg_code >> 5) == 6) || // if class == 6 ((returned_dst_coap_msg_ptr->msg_code >> 5) == 7)) { // if class == 7 - sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, handle); + sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param); } /* Release memory of CoAP message */ @@ -570,7 +578,8 @@ } } -#if !SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is used, this part of code will not be compiled */ + +#if !YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is used, this part of code will not be compiled */ /* If blockwising used in received message */ if (returned_dst_coap_msg_ptr->options_list_ptr != NULL && (returned_dst_coap_msg_ptr->options_list_ptr->block1_ptr != NULL || @@ -580,23 +589,23 @@ //todo: send response -> not implemented return returned_dst_coap_msg_ptr; } -#endif /* !SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE */ +#endif /* !YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ -#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication is used, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication is used, this part of code will not be compiled */ /* * * * Manage received CoAP message duplicate detection * * * */ /* If no message duplication detected */ - if (sn_coap_protocol_linked_list_duplication_info_search(src_addr_ptr, returned_dst_coap_msg_ptr->msg_id) == -1) { + if (sn_coap_protocol_linked_list_duplication_info_search(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id) == -1) { /* * * No Message duplication: Store received message for detecting later duplication * * */ /* Get count of stored duplication messages */ - uint16_t stored_duplication_msgs_count = global_count_duplication_msgs; + uint16_t stored_duplication_msgs_count = handle->count_duplication_msgs; /* Check if there is no room to store message for duplication detection purposes */ - if (stored_duplication_msgs_count >= sn_coap_duplication_buffer_size) { + if (stored_duplication_msgs_count >= handle->sn_coap_duplication_buffer_size) { /* Get oldest stored duplication message */ - coap_duplication_info_s *stored_duplication_info_ptr = ns_list_get_first(&global_linked_list_duplication_msgs); + coap_duplication_info_s *stored_duplication_info_ptr = ns_list_get_first(&handle->linked_list_duplication_msgs); /* Remove oldest stored duplication message for getting room for new duplication message */ sn_coap_protocol_linked_list_duplication_info_remove(handle, stored_duplication_info_ptr->addr_ptr, stored_duplication_info_ptr->port, stored_duplication_info_ptr->msg_id); @@ -616,7 +625,7 @@ /*** And here we check if message was block message ***/ /*** If so, we call own block handling function and ***/ /*** return to caller. ***/ -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE if (returned_dst_coap_msg_ptr->options_list_ptr != NULL && (returned_dst_coap_msg_ptr->options_list_ptr->block1_ptr != NULL || @@ -626,7 +635,7 @@ /* Get ... */ coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = NULL; - ns_list_foreach(coap_blockwise_msg_s, msg, &global_linked_list_blockwise_sent_msgs) { + ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) { if (returned_dst_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) { stored_blockwise_msg_temp_ptr = msg; break; @@ -634,7 +643,7 @@ } if (stored_blockwise_msg_temp_ptr) { - ns_list_remove(&global_linked_list_blockwise_sent_msgs, stored_blockwise_msg_temp_ptr); + ns_list_remove(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_temp_ptr); if (stored_blockwise_msg_temp_ptr->coap_msg_ptr) { if(stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr){ @@ -663,17 +672,25 @@ /* * * * Manage CoAP message resending by removing active resending message from Linked list * * */ /* Get node count i.e. count of active resending messages */ - uint16_t stored_resending_msgs_count = global_count_resent_msgs; + uint16_t stored_resending_msgs_count = handle->count_resent_msgs; /* Check if there is ongoing active message resendings */ if (stored_resending_msgs_count > 0) { sn_nsdl_transmit_s *removed_msg_ptr = NULL; /* Check if received message was confirmation for some active resending message */ - - removed_msg_ptr = sn_coap_protocol_linked_list_send_msg_search(src_addr_ptr, returned_dst_coap_msg_ptr->msg_id); + removed_msg_ptr = sn_coap_protocol_linked_list_send_msg_search(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id); if (removed_msg_ptr != NULL) { + if (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_RESET) { + if(removed_msg_ptr->uri_path_len) { + returned_dst_coap_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(removed_msg_ptr->uri_path_len); + if (returned_dst_coap_msg_ptr->uri_path_ptr != NULL) { + memcpy(returned_dst_coap_msg_ptr->uri_path_ptr, removed_msg_ptr->uri_path_ptr, removed_msg_ptr->uri_path_len); + returned_dst_coap_msg_ptr->uri_path_len = removed_msg_ptr->uri_path_len; + } + } + } /* Remove resending message from active message resending Linked list */ sn_coap_protocol_linked_list_send_msg_remove(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id); } @@ -682,33 +699,33 @@ #endif /* ENABLE_RESENDINGS */ /* * * * Return parsed CoAP message * * * */ - return (returned_dst_coap_msg_ptr); + return returned_dst_coap_msg_ptr; } int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time) { - /* * * * Store current System time * * * */ - global_system_time = current_time; - if( !handle ){ return -1; } -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE + /* * * * Store current System time * * * */ + handle->system_time = current_time; + +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* * * * Remove old blocwise data * * * */ sn_coap_protocol_linked_list_blockwise_remove_old_data(handle); #endif -#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT +#if YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT /* * * * Remove old duplication messages * * * */ sn_coap_protocol_linked_list_duplication_info_remove_old_ones(handle); #endif #if ENABLE_RESENDINGS /* Check if there is ongoing active message sendings */ - ns_list_foreach_safe(coap_send_msg_s, stored_msg_ptr, &global_linked_list_resent_msgs) { + ns_list_foreach_safe(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { // First check that msg belongs to handle if( stored_msg_ptr->coap == handle ){ /* Check if it is time to send this message */ @@ -717,7 +734,7 @@ stored_msg_ptr->resending_counter++; /* Check if all re-sendings have been done */ - if (stored_msg_ptr->resending_counter > sn_coap_resending_count) { + if (stored_msg_ptr->resending_counter > handle->sn_coap_resending_count) { coap_version_e coap_version = COAP_VERSION_UNKNOWN; /* Get message ID from stored sending message */ @@ -746,7 +763,7 @@ stored_msg_ptr->send_msg_ptr->packet_len, stored_msg_ptr->send_msg_ptr->dst_addr_ptr, stored_msg_ptr->param); /* * * Count new Resending time * * */ - stored_msg_ptr->resending_time = current_time + (((uint32_t)(sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR)) << + stored_msg_ptr->resending_time = current_time + (((uint32_t)(handle->sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR)) << stored_msg_ptr->resending_counter); } @@ -776,25 +793,25 @@ *****************************************************************************/ static void sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, - uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param) + uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param, uint8_t *uri_path_ptr, uint8_t uri_path_len) { coap_send_msg_s *stored_msg_ptr = NULL; /* If both queue parameters are "0" or resending count is "0", then re-sending is disabled */ - if (((sn_coap_resending_queue_msgs == 0) && (sn_coap_resending_queue_bytes == 0)) || (sn_coap_resending_count == 0)) { + if (((handle->sn_coap_resending_queue_msgs == 0) && (handle->sn_coap_resending_queue_bytes == 0)) || (handle->sn_coap_resending_count == 0)) { return; } - if (sn_coap_resending_queue_msgs > 0) { - if (global_count_resent_msgs >= sn_coap_resending_queue_msgs) { + if (handle->sn_coap_resending_queue_msgs > 0) { + if (handle->count_resent_msgs >= handle->sn_coap_resending_queue_msgs) { return; } } /* Count resending queue size, if buffer size is defined */ - if (sn_coap_resending_queue_bytes > 0) { - if ((sn_coap_count_linked_list_size(&global_linked_list_resent_msgs) + send_packet_data_len) > sn_coap_resending_queue_bytes) { + if (handle->sn_coap_resending_queue_bytes > 0) { + if ((sn_coap_count_linked_list_size(&handle->linked_list_resent_msgs) + send_packet_data_len) > handle->sn_coap_resending_queue_bytes) { return; } } @@ -824,9 +841,19 @@ stored_msg_ptr->coap = handle; stored_msg_ptr->param = param; + if (uri_path_len) { + stored_msg_ptr->send_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(uri_path_len); + if (stored_msg_ptr->send_msg_ptr->uri_path_ptr == NULL){ + return; + } + stored_msg_ptr->send_msg_ptr->uri_path_len = uri_path_len; + memcpy(stored_msg_ptr->send_msg_ptr->uri_path_ptr, uri_path_ptr, uri_path_len); + } + + /* Storing Resending message to Linked list */ - ns_list_add_to_end(&global_linked_list_resent_msgs, stored_msg_ptr); - ++global_count_resent_msgs; + ns_list_add_to_end(&handle->linked_list_resent_msgs, stored_msg_ptr); + ++handle->count_resent_msgs; } /**************************************************************************//** @@ -842,10 +869,11 @@ * list or NULL if message not found *****************************************************************************/ -static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) +static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(struct coap_s *handle, + sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) { /* Loop all stored resending messages Linked list */ - ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &global_linked_list_resent_msgs) { + ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { /* Get message ID from stored resending message */ uint16_t temp_msg_id = (stored_msg_ptr->send_msg_ptr->packet_ptr[2] << 8); temp_msg_id += (uint16_t)stored_msg_ptr->send_msg_ptr->packet_ptr[3]; @@ -878,7 +906,7 @@ static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) { /* Loop all stored resending messages in Linked list */ - ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &global_linked_list_resent_msgs) { + ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { /* Get message ID from stored resending message */ uint16_t temp_msg_id = (stored_msg_ptr->send_msg_ptr->packet_ptr[2] << 8); temp_msg_id += (uint16_t)stored_msg_ptr->send_msg_ptr->packet_ptr[3]; @@ -892,8 +920,8 @@ /* * * Message found * * */ /* Remove message from Linked list */ - ns_list_remove(&global_linked_list_resent_msgs, stored_msg_ptr); - --global_count_resent_msgs; + ns_list_remove(&handle->linked_list_resent_msgs, stored_msg_ptr); + --handle->count_resent_msgs; /* Free memory of stored message */ sn_coap_protocol_release_allocated_send_msg_mem(handle, stored_msg_ptr); @@ -926,7 +954,7 @@ handle->sn_coap_tx_callback(packet_ptr, 4, addr_ptr, param); } -#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ /**************************************************************************//** * \fn static void sn_coap_protocol_linked_list_duplication_info_store(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id) @@ -962,7 +990,7 @@ /* * * * Filling fields of stored Duplication info * * * */ - stored_duplication_info_ptr->timestamp = global_system_time; + stored_duplication_info_ptr->timestamp = handle->system_time; stored_duplication_info_ptr->addr_len = addr_ptr->addr_len; memcpy(stored_duplication_info_ptr->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len); stored_duplication_info_ptr->port = addr_ptr->port; @@ -972,8 +1000,8 @@ /* * * * Storing Duplication info to Linked list * * * */ - ns_list_add_to_end(&global_linked_list_duplication_msgs, stored_duplication_info_ptr); - ++global_count_duplication_msgs; + ns_list_add_to_end(&handle->linked_list_duplication_msgs, stored_duplication_info_ptr); + ++handle->count_duplication_msgs; } /**************************************************************************//** @@ -987,11 +1015,11 @@ * \return Return value is 0 when message found and -1 if not found *****************************************************************************/ -static int8_t sn_coap_protocol_linked_list_duplication_info_search(sn_nsdl_addr_s *addr_ptr, - uint16_t msg_id) +static int8_t sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle, + sn_nsdl_addr_s *addr_ptr, uint16_t msg_id) { /* Loop all nodes in Linked list for searching Message ID */ - ns_list_foreach(coap_duplication_info_s, stored_duplication_info_ptr, &global_linked_list_duplication_msgs) { + ns_list_foreach(coap_duplication_info_s, stored_duplication_info_ptr, &handle->linked_list_duplication_msgs) { /* If message's Message ID is same than is searched */ if (stored_duplication_info_ptr->msg_id == msg_id) { /* If message's Source address is same than is searched */ @@ -1023,7 +1051,7 @@ static void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, uint8_t *addr_ptr, uint16_t port, uint16_t msg_id) { /* Loop all stored duplication messages in Linked list */ - ns_list_foreach(coap_duplication_info_s, removed_duplication_info_ptr, &global_linked_list_duplication_msgs) { + ns_list_foreach(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) { /* If message's Address is same than is searched */ if (handle == removed_duplication_info_ptr->coap && 0 == memcmp(addr_ptr, removed_duplication_info_ptr->addr_ptr, removed_duplication_info_ptr->addr_len)) { /* If message's Address prt is same than is searched */ @@ -1031,8 +1059,8 @@ /* If Message ID is same than is searched */ if (removed_duplication_info_ptr->msg_id == msg_id) { /* * * * Correct Duplication info found, remove it from Linked list * * * */ - ns_list_remove(&global_linked_list_duplication_msgs, removed_duplication_info_ptr); - --global_count_duplication_msgs; + ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr); + --handle->count_duplication_msgs; /* Free memory of stored Duplication info */ handle->sn_coap_protocol_free(removed_duplication_info_ptr->addr_ptr); @@ -1056,11 +1084,11 @@ static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle) { /* Loop all stored duplication messages in Linked list */ - ns_list_foreach_safe(coap_duplication_info_s, removed_duplication_info_ptr, &global_linked_list_duplication_msgs) { - if ((global_system_time - removed_duplication_info_ptr->timestamp) > SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED) { + ns_list_foreach_safe(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) { + if ((handle->system_time - removed_duplication_info_ptr->timestamp) > SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED) { /* * * * Old Duplication info found, remove it from Linked list * * * */ - ns_list_remove(&global_linked_list_duplication_msgs, removed_duplication_info_ptr); - --global_count_duplication_msgs; + ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr); + --handle->count_duplication_msgs; /* Free memory of stored Duplication info */ handle->sn_coap_protocol_free(removed_duplication_info_ptr->addr_ptr); @@ -1071,9 +1099,9 @@ } } -#endif /* SN_COAP_DUPLICATION_MAX_MSGS_COUNT */ +#endif /* YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT */ -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /**************************************************************************//** * \fn static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr) * @@ -1085,7 +1113,7 @@ static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr) { if( removed_msg_ptr->coap == handle ){ - ns_list_remove(&global_linked_list_blockwise_sent_msgs, removed_msg_ptr); + ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_msg_ptr); if( removed_msg_ptr->coap_msg_ptr ){ if (removed_msg_ptr->coap_msg_ptr->payload_ptr) { @@ -1153,7 +1181,7 @@ /* * * * Filling fields of stored Payload * * * */ - stored_blockwise_payload_ptr->timestamp = global_system_time; + stored_blockwise_payload_ptr->timestamp = handle->system_time; memcpy(stored_blockwise_payload_ptr->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len); stored_blockwise_payload_ptr->port = addr_ptr->port; @@ -1164,7 +1192,7 @@ /* * * * Storing Payload to Linked list * * * */ - ns_list_add_to_end(&global_linked_list_blockwise_received_payloads, stored_blockwise_payload_ptr); + ns_list_add_to_end(&handle->linked_list_blockwise_received_payloads, stored_blockwise_payload_ptr); } /**************************************************************************//** @@ -1179,10 +1207,10 @@ * list or NULL if payload not found *****************************************************************************/ -static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length) +static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length) { /* Loop all stored blockwise payloads in Linked list */ - ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &global_linked_list_blockwise_received_payloads) { + ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { /* If payload's Source address is same than is searched */ if (0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) { /* If payload's Source address port is same than is searched */ @@ -1209,7 +1237,7 @@ coap_blockwise_payload_s *removed_payload_ptr; /* Remove oldest node in Linked list*/ - removed_payload_ptr = ns_list_get_first(&global_linked_list_blockwise_received_payloads); + removed_payload_ptr = ns_list_get_first(&handle->linked_list_blockwise_received_payloads); if (removed_payload_ptr != NULL) { sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_payload_ptr); @@ -1228,7 +1256,7 @@ static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, coap_blockwise_payload_s *removed_payload_ptr) { - ns_list_remove(&global_linked_list_blockwise_received_payloads, removed_payload_ptr); + ns_list_remove(&handle->linked_list_blockwise_received_payloads, removed_payload_ptr); /* Free memory of stored payload */ if (removed_payload_ptr->addr_ptr != NULL) { @@ -1246,7 +1274,7 @@ } /**************************************************************************//** - * \fn static uint16_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(sn_nsdl_addr_s *src_addr_ptr) + * \fn static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(sn_nsdl_addr_s *src_addr_ptr) * * \brief Counts length of Payloads in Linked list (Address as key) * @@ -1255,12 +1283,11 @@ * \return Return value is length of Payloads as bytes *****************************************************************************/ -static uint16_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(sn_nsdl_addr_s *src_addr_ptr) +static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr) { - uint16_t ret_whole_payload_len = 0; - + uint32_t ret_whole_payload_len = 0; /* Loop all stored blockwise payloads in Linked list */ - ns_list_foreach(coap_blockwise_payload_s, searched_payload_info_ptr, &global_linked_list_blockwise_received_payloads) { + ns_list_foreach(coap_blockwise_payload_s, searched_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { /* If payload's Source address is same than is searched */ if (0 == memcmp(src_addr_ptr->addr_ptr, searched_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) { /* If payload's Source address port is same than is searched */ @@ -1283,8 +1310,8 @@ static void sn_coap_protocol_linked_list_blockwise_remove_old_data(struct coap_s *handle) { /* Loop all stored Blockwise messages in Linked list */ - ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &global_linked_list_blockwise_sent_msgs) { - if ((global_system_time - removed_blocwise_msg_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { + ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) { + if ((handle->system_time - removed_blocwise_msg_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { //TODO: Check do we need to check handle == removed_blocwise_msg_ptr->coap here? /* * * * Old Blockise message found, remove it from Linked list * * * */ @@ -1301,15 +1328,15 @@ } /* Loop all stored Blockwise payloads in Linked list */ - ns_list_foreach_safe(coap_blockwise_payload_s, removed_blocwise_payload_ptr, &global_linked_list_blockwise_received_payloads) { - if ((global_system_time - removed_blocwise_payload_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { + ns_list_foreach_safe(coap_blockwise_payload_s, removed_blocwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) { + if ((handle->system_time - removed_blocwise_payload_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { /* * * * Old Blockise payload found, remove it from Linked list * * * */ sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_blocwise_payload_ptr); } } } -#endif /* SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE */ +#endif /* YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ @@ -1400,6 +1427,11 @@ freed_send_msg_ptr->send_msg_ptr->packet_ptr = 0; } + if (freed_send_msg_ptr->send_msg_ptr->uri_path_ptr != NULL) { + handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr->uri_path_ptr); + freed_send_msg_ptr->send_msg_ptr->uri_path_ptr = 0; + } + handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr); freed_send_msg_ptr->send_msg_ptr = 0; } @@ -1430,7 +1462,7 @@ } #endif -#if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ +#if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ /**************************************************************************//** * \fn static int8_t sn_coap_handle_blockwise_message(void) @@ -1459,7 +1491,7 @@ coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = NULL; /* Get */ - ns_list_foreach(coap_blockwise_msg_s, msg, &global_linked_list_blockwise_sent_msgs) { + ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) { if (msg->coap_msg_ptr && received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) { stored_blockwise_msg_temp_ptr = msg; break; @@ -1562,7 +1594,7 @@ } /* Build and send block message */ - dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size(src_coap_blockwise_ack_msg_ptr); + dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); if (!dst_ack_packet_data_ptr) { @@ -1583,7 +1615,7 @@ message_id = 1; } - sn_coap_builder(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr); + sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); @@ -1604,8 +1636,8 @@ // Blocked request receiving else { - if (received_coap_msg_ptr->payload_len > sn_coap_block_data_size) { - received_coap_msg_ptr->payload_len = sn_coap_block_data_size; + if (received_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) { + received_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size; } sn_coap_protocol_linked_list_blockwise_payload_store(handle, src_addr_ptr, received_coap_msg_ptr->payload_len, received_coap_msg_ptr->payload_ptr); @@ -1659,14 +1691,14 @@ /* Check block size */ block_temp = (*(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) & 0x07); - if (block_temp > sn_coap_convert_block_size(sn_coap_block_data_size)) { + if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) { *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) &= 0xF8; - *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) |= sn_coap_convert_block_size(sn_coap_block_data_size); + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); } src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id; - dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size(src_coap_blockwise_ack_msg_ptr); + dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); if (!dst_ack_packet_data_ptr) { @@ -1680,7 +1712,7 @@ return NULL; } - sn_coap_builder(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr); + sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); @@ -1696,20 +1728,18 @@ /* Store last Blockwise payload to Linked list */ uint16_t payload_len = 0; - uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(src_addr_ptr, &payload_len); - uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(src_addr_ptr); + uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len); + uint32_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr); uint8_t *temp_whole_payload_ptr = NULL; temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len); - if (!temp_whole_payload_ptr) { + if (temp_whole_payload_ptr == NULL || whole_payload_len > UINT16_MAX) { sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + handle->sn_coap_protocol_free(temp_whole_payload_ptr); return 0; } - //TODO: This might cause crashes, but if not deleted leaks memory? - if( received_coap_msg_ptr->payload_ptr ){ - free(received_coap_msg_ptr->payload_ptr); - } + // In block message case, payload_ptr freeing must be done in application level received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr; received_coap_msg_ptr->payload_len = whole_payload_len; @@ -1720,7 +1750,7 @@ temp_whole_payload_ptr += payload_len; sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle); - payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(src_addr_ptr, &payload_len); + payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len); } received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; } @@ -1746,7 +1776,7 @@ //build and send ack received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING; - ns_list_foreach(coap_blockwise_msg_s, msg, &global_linked_list_blockwise_sent_msgs) { + ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) { if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) { previous_blockwise_msg_ptr = msg; break; @@ -1764,7 +1794,7 @@ } memset(src_coap_blockwise_ack_msg_ptr,0,sizeof(sn_coap_hdr_s)); - ns_list_remove(&global_linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr); + ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr); if( previous_blockwise_msg_ptr->coap_msg_ptr ){ if(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr){ handle->sn_coap_protocol_free(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr); @@ -1854,7 +1884,7 @@ } /* Then get needed memory count for Packet data */ - dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size(src_coap_blockwise_ack_msg_ptr); + dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr ,handle->sn_coap_block_data_size); /* Then allocate memory for Packet data */ dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); @@ -1872,7 +1902,7 @@ memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem); /* * * Then build Acknowledgement message to Packed data * * */ - if ((sn_coap_builder(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr)) < 0) { + if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) { handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); dst_ack_packet_data_ptr = 0; handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr); @@ -1903,12 +1933,12 @@ } memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s)); - stored_blockwise_msg_ptr->timestamp = global_system_time; + stored_blockwise_msg_ptr->timestamp = handle->system_time; stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr; stored_blockwise_msg_ptr->coap = handle; - ns_list_add_to_end(&global_linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); + ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); /* * * Then release memory of CoAP Acknowledgement message * * */ handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, @@ -1918,7 +1948,7 @@ sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr, dst_packed_data_needed_mem, dst_ack_packet_data_ptr, - global_system_time + (uint32_t)(sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR), param); + handle->system_time + (uint32_t)(handle->sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR), param, NULL, 0); #endif handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); dst_ack_packet_data_ptr = 0; @@ -1931,8 +1961,8 @@ /* Store last Blockwise payload to Linked list */ uint16_t payload_len = 0; - uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(src_addr_ptr, &payload_len); - uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(src_addr_ptr); + uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len); + uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr); uint8_t *temp_whole_payload_ptr = NULL; temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len); @@ -1950,7 +1980,7 @@ temp_whole_payload_ptr += payload_len; sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle); - payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(src_addr_ptr, &payload_len); + payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len); } received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; @@ -1963,7 +1993,7 @@ else { //Get message by using block number //NOTE: Getting the first from list might not be correct one - coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = ns_list_get_first(&global_linked_list_blockwise_sent_msgs); + coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = ns_list_get_first(&handle->linked_list_blockwise_sent_msgs); if (stored_blockwise_msg_temp_ptr) { uint16_t block_size = 1; uint32_t block_number = 0; @@ -2045,7 +2075,7 @@ } /* Build and send block message */ - dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size(src_coap_blockwise_ack_msg_ptr); + dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); if (!dst_ack_packet_data_ptr) { @@ -2062,7 +2092,7 @@ return NULL; } - sn_coap_builder(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr); + sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); @@ -2285,4 +2315,3 @@ return destination_header_ptr; } #endif -
--- a/source/libNsdl/src/include/sn_grs.h Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libNsdl/src/include/sn_grs.h Sat Apr 02 00:39:03 2016 +0300 @@ -124,4 +124,3 @@ #endif /* GRS_H_ */ -
--- a/source/libNsdl/src/sn_grs.c Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libNsdl/src/sn_grs.c Sat Apr 02 00:39:03 2016 +0300 @@ -29,6 +29,7 @@ #include "sn_nsdl.h" #include "sn_coap_header.h" #include "sn_coap_protocol.h" +#include "sn_coap_protocol_internal.h" #include "sn_nsdl_lib.h" #include "sn_grs.h" @@ -144,6 +145,7 @@ extern sn_grs_resource_list_s *sn_grs_list_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path) { + (void) pathlen; sn_grs_resource_list_s *grs_resource_list_ptr = NULL; if( handle == NULL || path == NULL){ @@ -631,8 +633,7 @@ } /* Calculate message length */ - message_len = sn_coap_builder_calc_needed_packet_data_size(coap_hdr_ptr); - + message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_hdr_ptr, handle->grs->coap->sn_coap_block_data_size); /* Allocate memory for message and check was allocating successfully */ message_ptr = handle->grs->sn_grs_alloc(message_len); if (message_ptr == NULL) { @@ -811,6 +812,7 @@ resource_copy_ptr->resourcelen = resource_ptr->resourcelen; resource_copy_ptr->sn_grs_dyn_res_callback = resource_ptr->sn_grs_dyn_res_callback; resource_copy_ptr->access = resource_ptr->access; + resource_copy_ptr->publish_uri = resource_ptr->publish_uri; /* Remove '/' - chars from the beginning and from the end */ @@ -1009,4 +1011,3 @@ temp_resource = sn_grs_get_next_resource(handle->grs, temp_resource); } } -
--- a/source/libNsdl/src/sn_nsdl.c Fri Feb 19 17:46:29 2016 +0000 +++ b/source/libNsdl/src/sn_nsdl.c Sat Apr 02 00:39:03 2016 +0300 @@ -1,2345 +1,2440 @@ -/* - * Copyright (c) 2011-2015 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * \file sn_nsdl.c - * - * \brief Nano service device library - * - */ - -#include <string.h> - -#include "ns_types.h" -#include "sn_nsdl.h" -#include "sn_coap_header.h" -#include "sn_coap_protocol.h" -#include "sn_nsdl_lib.h" -#include "sn_grs.h" - -/* Defines */ -#define RESOURCE_DIR_LEN 2 -#define EP_NAME_PARAMETERS_LEN 3 -#define ET_PARAMETER_LEN 3 -#define LT_PARAMETER_LEN 3 -#define DOMAIN_PARAMETER_LEN 2 -#define RT_PARAMETER_LEN 3 -#define IF_PARAMETER_LEN 3 -#define OBS_PARAMETER_LEN 3 -#define AOBS_PARAMETER_LEN 8 -#define COAP_CON_PARAMETER_LEN 3 -#define BS_EP_PARAMETER_LEN 3 -#define BS_QUEUE_MODE_PARAMATER_LEN 2 - -#define SN_NSDL_EP_REGISTER_MESSAGE 1 -#define SN_NSDL_EP_UPDATE_MESSAGE 2 - -#define SN_NSDL_MSG_UNDEFINED 0 -#define SN_NSDL_MSG_REGISTER 1 -#define SN_NSDL_MSG_UNREGISTER 2 -#define SN_NSDL_MSG_UPDATE 3 - -/* Constants */ -static uint8_t ep_name_parameter_string[] = {'e', 'p', '='}; /* Endpoint name. A unique name for the registering node in a domain. */ -static uint8_t resource_path_ptr[] = {'r', 'd'}; /* For resource directory */ -static uint8_t resource_type_parameter[] = {'r', 't', '='}; /* Resource type. Only once for registration */ -static uint8_t obs_parameter[] = {'o', 'b', 's'}; /* Observable */ -//static uint8_t aobs_parameter[] = {'a','o','b','s',';','i','d','='}; /* Auto-observable - TBD */ -static uint8_t if_description_parameter[] = {'i', 'f', '='}; /* Interface description. Only once */ -static uint8_t ep_lifetime_parameter[] = {'l', 't', '='}; /* Lifetime. Number of seconds that this registration will be valid for. Must be updated within this time, or will be removed. */ -static uint8_t ep_domain_parameter[] = {'d', '='}; /* Domain name. If this parameter is missing, a default domain is assumed. */ -static uint8_t coap_con_type_parameter[] = {'c', 't', '='}; /* CoAP content type */ -/* * OMA BS parameters * */ -static uint8_t bs_uri[] = {'b', 's'}; -static uint8_t bs_ep_name[] = {'e', 'p', '='}; -static uint8_t et_parameter[] = {'e', 't', '='}; /* Endpoint type */ -static uint8_t bs_queue_mode[] = {'b', '='}; - -/* Function prototypes */ -static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description); -static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle); -int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration); -static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration); -static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type); -static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type); -static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr); -static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr); -static uint8_t sn_nsdl_itoa_len(uint8_t value); -static uint8_t *sn_nsdl_itoa(uint8_t *ptr, uint8_t value); -static int32_t sn_nsdl_atoi(uint8_t *ptr, uint8_t len); -static uint32_t sn_nsdl_ahextoi(uint8_t *ptr, uint8_t len); -static int8_t sn_nsdl_resolve_lwm2m_address(struct nsdl_s *handle, uint8_t *uri, uint16_t uri_len); -static int8_t sn_nsdl_process_oma_tlv(struct nsdl_s *handle, uint8_t *data_ptr, uint16_t data_len); -static void sn_nsdl_check_oma_bs_status(struct nsdl_s *handle); -static int8_t sn_nsdl_create_oma_device_object_base(struct nsdl_s *handle, sn_nsdl_oma_device_t *oma_device_setup_ptr, sn_nsdl_oma_binding_and_mode_t binding_and_mode); -static int8_t set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); -static bool validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr); -static bool validate(uint8_t* ptr, uint32_t len, char illegalChar); - -int8_t sn_nsdl_destroy(struct nsdl_s *handle) -{ - if (handle == NULL) { - return SN_NSDL_FAILURE; - } - - if (handle->ep_information_ptr) { - if (handle->ep_information_ptr->endpoint_name_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); - handle->ep_information_ptr->endpoint_name_ptr = 0; - } - if (handle->ep_information_ptr->domain_name_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); - handle->ep_information_ptr->domain_name_ptr = 0; - handle->ep_information_ptr->domain_name_len = 0; - } - if (handle->ep_information_ptr->location_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->location_ptr); - handle->ep_information_ptr->location_ptr = 0; - handle->ep_information_ptr->location_len = 0; - } - if (handle->ep_information_ptr->type_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->type_ptr); - handle->ep_information_ptr->type_ptr = 0; - } - - if (handle->ep_information_ptr->lifetime_ptr) - - { - handle->sn_nsdl_free(handle->ep_information_ptr->lifetime_ptr); - handle->ep_information_ptr->lifetime_ptr = 0; - } - - handle->sn_nsdl_free(handle->ep_information_ptr); - handle->ep_information_ptr = 0; - } - - if (handle->nsp_address_ptr) { - if (handle->nsp_address_ptr->omalw_address_ptr) { - if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { - handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); - handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = 0; - } - handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr); - } - - handle->sn_nsdl_free(handle->nsp_address_ptr); - handle->nsp_address_ptr = 0; - } - - if (handle->oma_bs_address_ptr) { - handle->sn_nsdl_free(handle->oma_bs_address_ptr); - } - - /* Destroy also libCoap and grs part of libNsdl */ - sn_coap_protocol_destroy(handle->grs->coap); - sn_grs_destroy(handle->grs); - handle->sn_nsdl_free(handle); - - return SN_NSDL_SUCCESS; -} - -struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), - uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), - void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *)) -{ - /* Check pointers and define function pointers */ - if (!sn_nsdl_alloc || !sn_nsdl_free || !sn_nsdl_tx_cb || !sn_nsdl_rx_cb) { - return NULL; - } - - struct nsdl_s *handle = NULL; - - handle = sn_nsdl_alloc(sizeof(struct nsdl_s)); - - if (handle == NULL) { - return NULL; - } - - memset(handle, 0, sizeof(struct nsdl_s)); - - /* Define function pointers */ - handle->sn_nsdl_alloc = sn_nsdl_alloc; - handle->sn_nsdl_free = sn_nsdl_free; - - handle->sn_nsdl_tx_callback = sn_nsdl_tx_cb; - handle->sn_nsdl_rx_callback = sn_nsdl_rx_cb; - - /* Initialize ep parameters struct */ - if (!handle->ep_information_ptr) { - handle->ep_information_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_ep_parameters_s)); - if (!handle->ep_information_ptr) { - sn_nsdl_free(handle); - return NULL; - } - memset(handle->ep_information_ptr, 0, sizeof(sn_nsdl_ep_parameters_s)); - } - - handle->grs = sn_grs_init(sn_nsdl_tx_cb, &sn_nsdl_local_rx_function, sn_nsdl_alloc, sn_nsdl_free); - - /* Initialize GRS */ - if (handle->grs == NULL) { - handle->sn_nsdl_free(handle->ep_information_ptr); - handle->ep_information_ptr = 0; - sn_nsdl_free(handle); - return NULL; - } - - sn_nsdl_resolve_nsp_address(handle); - - handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED; - - return handle; -} - -uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr) -{ - /* Local variables */ - sn_coap_hdr_s *register_message_ptr; - uint16_t message_id = 0; - - if (endpoint_info_ptr == NULL || handle == NULL) { - return 0; - } - - /*** Build endpoint register message ***/ - - /* Allocate memory for header struct */ - register_message_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_hdr_s)); - if (register_message_ptr == NULL) { - return 0; - } - - memset(register_message_ptr, 0, sizeof(sn_coap_hdr_s)); - - /* Fill message fields -> confirmable post to specified NSP path */ - register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; - register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST; - - /* Allocate memory for the extended options list */ - register_message_ptr->options_list_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_options_list_s)); - if (register_message_ptr->options_list_ptr == NULL) { - handle->sn_nsdl_free(register_message_ptr); - register_message_ptr = 0; - return 0; - } - - memset(register_message_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); - - register_message_ptr->uri_path_len = sizeof(resource_path_ptr); - register_message_ptr->uri_path_ptr = resource_path_ptr; - - /* Fill Uri-query options */ - if( SN_NSDL_FAILURE == sn_nsdl_fill_uri_query_options(handle, endpoint_info_ptr, - register_message_ptr, SN_NSDL_EP_REGISTER_MESSAGE) ){ - register_message_ptr->uri_path_ptr = NULL; - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - return 0; - } - - if (endpoint_info_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) { - /* Built body for message */ - if (sn_nsdl_build_registration_body(handle, register_message_ptr, 0) == SN_NSDL_FAILURE) { - register_message_ptr->uri_path_ptr = NULL; - register_message_ptr->options_list_ptr->uri_host_ptr = NULL; - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - return 0; - } - } - - /* Clean (possible) existing and save new endpoint info to handle */ - if (set_endpoint_info(handle, endpoint_info_ptr) == -1) { - if (register_message_ptr->payload_ptr) { - handle->sn_nsdl_free(register_message_ptr->payload_ptr); - register_message_ptr->payload_ptr = NULL; - } - - register_message_ptr->uri_path_ptr = NULL; - register_message_ptr->options_list_ptr->uri_host_ptr = NULL; - - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - - return 0; - } - - /* Build and send coap message to NSP */ - message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_REGISTER); - - if (register_message_ptr->payload_ptr) { - handle->sn_nsdl_free(register_message_ptr->payload_ptr); - register_message_ptr->payload_ptr = NULL; - } - - register_message_ptr->uri_path_ptr = NULL; - register_message_ptr->options_list_ptr->uri_host_ptr = NULL; - - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - - return message_id; -} - -uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle) -{ - /* Local variables */ - sn_coap_hdr_s *unregister_message_ptr; - uint8_t *temp_ptr = 0; - uint16_t message_id = 0; - - /* Check parameters */ - if (handle == NULL) { - return 0; - } - - /* Check that EP have been registered */ - if (sn_nsdl_is_ep_registered(handle)) { - - /* Memory allocation for unregister message */ - unregister_message_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_hdr_s)); - if (!unregister_message_ptr) { - return 0; - } - - memset(unregister_message_ptr, 0, sizeof(sn_coap_hdr_s)); - - /* Fill unregister message */ - unregister_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; - unregister_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_DELETE; - - if(handle->ep_information_ptr->location_ptr) { - unregister_message_ptr->uri_path_len = handle->ep_information_ptr->location_len; - unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len); - if (!unregister_message_ptr->uri_path_ptr) { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); - return 0; - } - - temp_ptr = unregister_message_ptr->uri_path_ptr; - - memcpy(temp_ptr , handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len); - } else { - unregister_message_ptr->uri_path_len = (RESOURCE_DIR_LEN + 1 + handle->ep_information_ptr->domain_name_len + 1 + handle->ep_information_ptr->endpoint_name_len); - unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len); - if (!unregister_message_ptr->uri_path_ptr) { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); - return 0; - } - - temp_ptr = unregister_message_ptr->uri_path_ptr; - - memcpy(temp_ptr, resource_path_ptr, RESOURCE_DIR_LEN); - temp_ptr += RESOURCE_DIR_LEN; - - *temp_ptr++ = '/'; - - memcpy(temp_ptr , handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len); - temp_ptr += handle->ep_information_ptr->domain_name_len; - - *temp_ptr++ = '/'; - - memcpy(temp_ptr , handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len); - } - - /* Send message */ - message_id = sn_nsdl_internal_coap_send(handle, unregister_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UNREGISTER); - - /* Free memory */ - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); - - } - - return message_id; -} - -uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len) -{ - /* Local variables */ - sn_coap_hdr_s *register_message_ptr; - uint8_t *temp_ptr; - sn_nsdl_ep_parameters_s temp_parameters; - uint16_t message_id = 0; - - /* Check parameters */ - if (handle == NULL) { - return 0; - } - - if (!sn_nsdl_is_ep_registered(handle)){ - return 0; - } - - memset(&temp_parameters, 0, sizeof(sn_nsdl_ep_parameters_s)); - - temp_parameters.lifetime_len = lt_len; - temp_parameters.lifetime_ptr = lt_ptr; - - /*** Build endpoint register update message ***/ - - /* Allocate memory for header struct */ - register_message_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_hdr_s)); - if (register_message_ptr == NULL) { - return 0; - } - - memset(register_message_ptr, 0, sizeof(sn_coap_hdr_s)); - - /* Fill message fields -> confirmable post to specified NSP path */ - register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; - register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST; - - if(handle->ep_information_ptr->location_ptr) { - register_message_ptr->uri_path_len = handle->ep_information_ptr->location_len; /* = Only location set by Device Server*/ - - register_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(register_message_ptr->uri_path_len); - if (!register_message_ptr->uri_path_ptr) { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - return 0; - } - - temp_ptr = register_message_ptr->uri_path_ptr; - - /* location */ - memcpy(temp_ptr, handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len); - } else { - register_message_ptr->uri_path_len = sizeof(resource_path_ptr) + handle->ep_information_ptr->domain_name_len + handle->ep_information_ptr->endpoint_name_len + 2; /* = rd/domain/endpoint */ - - register_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(register_message_ptr->uri_path_len); - if (!register_message_ptr->uri_path_ptr) { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - return 0; - } - - temp_ptr = register_message_ptr->uri_path_ptr; - - /* rd/ */ - memcpy(temp_ptr, resource_path_ptr, sizeof(resource_path_ptr)); - temp_ptr += sizeof(resource_path_ptr); - *temp_ptr++ = '/'; - - /* rd/DOMAIN/ */ - memcpy(temp_ptr, handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len); - temp_ptr += handle->ep_information_ptr->domain_name_len; - *temp_ptr++ = '/'; - - /* rd/domain/ENDPOINT */ - memcpy(temp_ptr, handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len); - } - - /* Allocate memory for the extended options list */ - register_message_ptr->options_list_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_options_list_s)); - if (register_message_ptr->options_list_ptr == NULL) { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - return 0; - } - - memset(register_message_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); - - /* Fill Uri-query options */ - sn_nsdl_fill_uri_query_options(handle, &temp_parameters, register_message_ptr, SN_NSDL_EP_UPDATE_MESSAGE); - - /* Build payload */ - if (handle->ep_information_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) { - - if (sn_nsdl_build_registration_body(handle, register_message_ptr, 1) == SN_NSDL_FAILURE) { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - return 0; - } - } - - /* Build and send coap message to NSP */ - message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UPDATE); - - if (register_message_ptr->payload_ptr) { - handle->sn_nsdl_free(register_message_ptr->payload_ptr); - } - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); - - return message_id; -} - -int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len) -{ - if(!handle || !location_ptr || (location_len == 0)) { - return -1; - } - handle->ep_information_ptr->location_ptr = handle->sn_nsdl_alloc(location_len); - memcpy(handle->ep_information_ptr->location_ptr, location_ptr, location_len); - handle->ep_information_ptr->location_len = location_len; - - return 0; -} - -void sn_nsdl_nsp_lost(struct nsdl_s *handle) -{ - /* Check parameters */ - if (handle == NULL) { - return; - } - - handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED; -} - -int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle) -{ - /* Check parameters */ - if (handle == NULL) { - return SN_NSDL_FAILURE; - } - - return handle->sn_nsdl_endpoint_registered; -} - -uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, - uint8_t *payload_ptr, uint16_t payload_len, - uint8_t *observe_ptr, uint8_t observe_len, - sn_coap_msg_type_e message_type, uint8_t content_type) -{ - sn_coap_hdr_s *notification_message_ptr; - uint16_t return_msg_id = 0; - - /* Check parameters */ - if (handle == NULL) { - return 0; - } - - /* Allocate and initialize memory for header struct */ - notification_message_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_hdr_s)); - if (notification_message_ptr == NULL) { - return 0; - } - - memset(notification_message_ptr, 0, sizeof(sn_coap_hdr_s)); - - notification_message_ptr->options_list_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_options_list_s)); - if (notification_message_ptr->options_list_ptr == NULL) { - handle->sn_nsdl_free(notification_message_ptr); - return 0; - } - - memset(notification_message_ptr->options_list_ptr , 0, sizeof(sn_coap_options_list_s)); - - /* Fill header */ - notification_message_ptr->msg_type = message_type; - notification_message_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; - - /* Fill token */ - notification_message_ptr->token_len = token_len; - notification_message_ptr->token_ptr = token_ptr; - - /* Fill payload */ - notification_message_ptr->payload_len = payload_len; - notification_message_ptr->payload_ptr = payload_ptr; - - /* Fill observe */ - notification_message_ptr->options_list_ptr->observe_len = observe_len; - notification_message_ptr->options_list_ptr->observe_ptr = observe_ptr; - - /* Fill content type */ - if (content_type) { - notification_message_ptr->content_type_len = 1; - notification_message_ptr->content_type_ptr = &content_type; - } - - /* Send message */ - if (sn_nsdl_send_coap_message(handle, handle->nsp_address_ptr->omalw_address_ptr, notification_message_ptr) == SN_NSDL_FAILURE) { - return_msg_id = 0; - } else { - return_msg_id = notification_message_ptr->msg_id; - } - - /* Free memory */ - - notification_message_ptr->payload_ptr = NULL; - notification_message_ptr->options_list_ptr->observe_ptr = NULL; - notification_message_ptr->token_ptr = NULL; - notification_message_ptr->content_type_ptr = NULL; - - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, notification_message_ptr); - - return return_msg_id; -} - -/* * * * * * * * * * */ -/* ~ OMA functions ~ */ -/* * * * * * * * * * */ - -uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr) -{ - - /* Local variables */ - sn_coap_hdr_s bootstrap_coap_header; - uint8_t *uri_query_tmp_ptr; - uint16_t message_id = 0; - - /* Check parameters */ - if (!bootstrap_address_ptr || !bootstrap_endpoint_info_ptr || !endpoint_info_ptr || !handle) { - return 0; - } - - /* Create device object */ - if (sn_nsdl_create_oma_device_object_base(handle, bootstrap_endpoint_info_ptr->device_object, endpoint_info_ptr->binding_and_mode) < 0) { - return 0; - } - - handle->sn_nsdl_oma_bs_done_cb = bootstrap_endpoint_info_ptr->oma_bs_status_cb; - - /* Init CoAP header struct */ - memset(&bootstrap_coap_header, 0, sizeof(sn_coap_hdr_s)); - - bootstrap_coap_header.options_list_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_options_list_s)); - if (!bootstrap_coap_header.options_list_ptr) { - return 0; - } - - memset(bootstrap_coap_header.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); - - /* Build bootstrap start message */ - bootstrap_coap_header.msg_code = COAP_MSG_CODE_REQUEST_POST; - bootstrap_coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE; - - bootstrap_coap_header.uri_path_ptr = bs_uri; - bootstrap_coap_header.uri_path_len = sizeof(bs_uri); - - uri_query_tmp_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN); - if (!uri_query_tmp_ptr) { - handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); - return 0; - } - - memcpy(uri_query_tmp_ptr, bs_ep_name, BS_EP_PARAMETER_LEN); - memcpy((uri_query_tmp_ptr + BS_EP_PARAMETER_LEN), endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len); - - bootstrap_coap_header.options_list_ptr->uri_query_len = endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN; - bootstrap_coap_header.options_list_ptr->uri_query_ptr = uri_query_tmp_ptr; - - /* Save bootstrap server address */ - handle->oma_bs_address_len = bootstrap_address_ptr->addr_len; /* Length.. */ - handle->oma_bs_address_ptr = handle->sn_nsdl_alloc(handle->oma_bs_address_len); /* Address.. */ - if (!handle->oma_bs_address_ptr) { - handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); - handle->sn_nsdl_free(uri_query_tmp_ptr); - return 0; - } - memcpy(handle->oma_bs_address_ptr, bootstrap_address_ptr->addr_ptr, handle->oma_bs_address_len); - handle->oma_bs_port = bootstrap_address_ptr->port; /* And port */ - - /* Send message */ - message_id = sn_nsdl_internal_coap_send(handle, &bootstrap_coap_header, bootstrap_address_ptr, SN_NSDL_MSG_UNDEFINED); - - /* Free allocated memory */ - handle->sn_nsdl_free(uri_query_tmp_ptr); - handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); - - return message_id; -} - -omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle) -{ - sn_nsdl_resource_info_s *resource_ptr = 0;; - omalw_certificate_list_t *certi_list_ptr = 0; - - /* Check parameters */ - if (handle == NULL) { - return NULL; - } - - certi_list_ptr = handle->sn_nsdl_alloc(sizeof(omalw_certificate_list_t)); - - if (!certi_list_ptr) { - return NULL; - } - - /* Get private key resource */ - resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/5"); - if (!resource_ptr) { - handle->sn_nsdl_free(certi_list_ptr); - return NULL; - } - certi_list_ptr->own_private_key_ptr = resource_ptr->resource; - certi_list_ptr->own_private_key_len = resource_ptr->resourcelen; - - /* Get client certificate resource */ - resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/4"); - if (!resource_ptr) { - handle->sn_nsdl_free(certi_list_ptr); - return NULL; - } - certi_list_ptr->certificate_ptr[0] = resource_ptr->resource; - certi_list_ptr->certificate_len[0] = resource_ptr->resourcelen; - - /* Get root certificate resource */ - resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/3"); - if (!resource_ptr) { - handle->sn_nsdl_free(certi_list_ptr); - return NULL; - } - certi_list_ptr->certificate_ptr[1] = resource_ptr->resource; - certi_list_ptr->certificate_len[1] = resource_ptr->resourcelen; - - /* return filled list */ - return certi_list_ptr; - -} - -int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t *certificate_ptr, uint8_t certificate_chain) -{ - (void)certificate_chain; - - /* Check pointers */ - if (!certificate_ptr || !handle) { - return SN_NSDL_FAILURE; - } - - sn_nsdl_resource_info_s *resource_ptr = 0;; - - /* Get private key resource */ - resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/5"); - if (!resource_ptr) { - return SN_NSDL_FAILURE; - } - handle->sn_nsdl_free(resource_ptr->resource); - resource_ptr->resource = certificate_ptr->own_private_key_ptr; - resource_ptr->resourcelen = certificate_ptr->own_private_key_len; - - /* Get client certificate resource */ - resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/4"); - if (!resource_ptr) { - return SN_NSDL_FAILURE; - } - handle->sn_nsdl_free(resource_ptr->resource); - resource_ptr->resource = certificate_ptr->certificate_ptr[0]; - resource_ptr->resourcelen = certificate_ptr->certificate_len[0]; - - /* Get root certificate resource */ - resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/3"); - if (!resource_ptr) { - return SN_NSDL_FAILURE; - } - handle->sn_nsdl_free(resource_ptr->resource); - resource_ptr->resource = certificate_ptr->certificate_ptr[1]; - resource_ptr->resourcelen = certificate_ptr->certificate_len[1]; - - return SN_NSDL_SUCCESS; -} - -int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr) -{ - sn_nsdl_resource_info_s *resource_temp = 0; - uint8_t path[8] = "3/0/11/0"; - - if (!device_object_ptr || !handle) { - return SN_NSDL_FAILURE; - } - - /* * Error code * */ - - /* Get first error message */ - resource_temp = sn_grs_search_resource(handle->grs, 8, path, SN_GRS_SEARCH_METHOD); - - while (resource_temp) { - if (resource_temp->resource) { - /* If no error code set */ - if (*resource_temp->resource == 0) { - /* Set error code */ - *resource_temp->resource = (uint8_t)device_object_ptr->error_code; - resource_temp->resourcelen = 1; - - sn_nsdl_update_resource(handle, resource_temp); - return SN_NSDL_SUCCESS; - } - break; - } - - if (path[7] == '9') { - return SN_NSDL_FAILURE; - } - - path[7]++; - resource_temp = sn_grs_search_resource(handle->grs, 8, path, SN_GRS_SEARCH_METHOD); - } - - /* Create new resource for this error */ - resource_temp = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_info_s)); - if (!resource_temp) { - return SN_NSDL_FAILURE; - } - - memset(resource_temp, 0, sizeof(sn_nsdl_resource_info_s)); - - resource_temp->access = SN_GRS_GET_ALLOWED; - resource_temp->mode = SN_GRS_DYNAMIC; - - resource_temp->path = path; - resource_temp->pathlen = 8; - - resource_temp->resource = handle->sn_nsdl_alloc(1); - if (!resource_temp->resource) { - handle->sn_nsdl_free(resource_temp); - return SN_NSDL_FAILURE; - } - - *resource_temp->resource = (uint8_t)device_object_ptr->error_code; - resource_temp->resourcelen = 1; - - resource_temp->resource_parameters_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_parameters_s)); - - if (!resource_temp->resource_parameters_ptr) { - handle->sn_nsdl_free(resource_temp->resource); - handle->sn_nsdl_free(resource_temp); - - return SN_NSDL_FAILURE; - } - - memset(resource_temp->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); - - sn_nsdl_create_resource(handle, resource_temp); - - handle->sn_nsdl_free(resource_temp->resource); - handle->sn_nsdl_free(resource_temp->resource_parameters_ptr); - handle->sn_nsdl_free(resource_temp); - - return SN_NSDL_SUCCESS; -} - -char *sn_nsdl_get_version(void) -{ -#if defined(YOTTA_MBED_CLIENT_C_VERSION_STRING) - return YOTTA_MBED_CLIENT_C_VERSION_STRING; -#elif defined(VERSION) - return VERSION; -#else - return "0.0.0"; -#endif -} - - -int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet_ptr, uint16_t packet_len, sn_nsdl_addr_s *src_ptr) -{ - sn_coap_hdr_s *coap_packet_ptr = NULL; - sn_coap_hdr_s *coap_response_ptr = NULL; - - /* Check parameters */ - if (handle == NULL) { - return SN_NSDL_FAILURE; - } - - /* Parse CoAP packet */ - coap_packet_ptr = sn_coap_protocol_parse(handle->grs->coap, src_ptr, packet_len, packet_ptr, (void *)handle); - - /* Check if parsing was successfull */ - if (coap_packet_ptr == (sn_coap_hdr_s *)NULL) { - return SN_NSDL_FAILURE; - } - - /* Check, if coap itself sends response, or block receiving is ongoing... */ - if (coap_packet_ptr->coap_status != COAP_STATUS_OK && coap_packet_ptr->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return SN_NSDL_SUCCESS; - } - - /* If proxy options added, return not supported */ - if (coap_packet_ptr->options_list_ptr) { - if (coap_packet_ptr->options_list_ptr->proxy_uri_len) { - coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED); - if (coap_response_ptr) { - sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return SN_NSDL_SUCCESS; - } else { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return SN_NSDL_FAILURE; - } - } - } - - /* * * * * * * * * * * * * * * * * * * * * * * * * * */ - /* If message is response message, call RX callback */ - /* * * * * * * * * * * * * * * * * * * * * * * * * * */ - - if ((coap_packet_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) || (coap_packet_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT)) { - int8_t retval = sn_nsdl_local_rx_function(handle, coap_packet_ptr, src_ptr); - if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { - handle->sn_nsdl_free(coap_packet_ptr->payload_ptr); - coap_packet_ptr->payload_ptr = 0; - } - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return retval; - } - - /* * If OMA bootstrap message... * */ - if (src_ptr && (handle->oma_bs_address_len == src_ptr->addr_len) && (handle->oma_bs_port == src_ptr->port) && !memcmp(handle->oma_bs_address_ptr, src_ptr->addr_ptr, handle->oma_bs_address_len)) { - /* TLV message. Parse message and check status of the OMA bootstrap */ - /* process. If ok, call cb function and return. Otherwise send error */ - /* and return failure. */ - - if (coap_packet_ptr->content_type_len == 1) { //todo check message type - if (*coap_packet_ptr->content_type_ptr == 99) { - /* TLV parsing failed. Send response to get non-tlv messages */ - if (sn_nsdl_process_oma_tlv(handle, coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len) == SN_NSDL_FAILURE) { - coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE); - if (coap_response_ptr) { - sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); - } else { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return SN_NSDL_FAILURE; - } - } - /* Success TLV parsing */ - else { - coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_CREATED); - if (coap_response_ptr) { - sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); - - } else { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return SN_NSDL_FAILURE; - } - sn_nsdl_check_oma_bs_status(handle); - } - - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return SN_NSDL_SUCCESS; - } - - /* Non - TLV message */ - else if (*coap_packet_ptr->content_type_ptr == 97) { - sn_grs_process_coap(handle, coap_packet_ptr, src_ptr); - - /* Todo: move this copying to sn_nsdl_check_oma_bs_status(), also from TLV parser */ - /* Security mode */ - if (*(coap_packet_ptr->uri_path_ptr + (coap_packet_ptr->uri_path_len - 1)) == '2') { - handle->nsp_address_ptr->omalw_server_security = (omalw_server_security_t)sn_nsdl_atoi(coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len); - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - } - - /* NSP address */ - else if (*(coap_packet_ptr->uri_path_ptr + (coap_packet_ptr->uri_path_len - 1)) == '0') { - sn_nsdl_resolve_lwm2m_address(handle, coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len); - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - } - - sn_nsdl_check_oma_bs_status(handle); - } else { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return SN_NSDL_FAILURE; - } - } else { - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); - return SN_NSDL_FAILURE; - } - - - return SN_NSDL_SUCCESS; - } - - - /* * * * * * * * * * * * * * * */ - /* Other messages are for GRS */ - /* * * * * * * * * * * * * * * */ - - return sn_grs_process_coap(handle, coap_packet_ptr, src_ptr); -} - -int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time) -{ - if(!handle || !handle->grs){ - return SN_NSDL_FAILURE; - } - /* Call CoAP execution function */ - return sn_coap_protocol_exec(handle->grs->coap, time); -} - -sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path_ptr) -{ - /* Check parameters */ - if (handle == NULL) { - return NULL; - } - - return sn_grs_search_resource(handle->grs, pathlen, path_ptr, SN_GRS_SEARCH_METHOD); -} - - -/** - * \fn static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description) - * - * - * \brief To send NSDL messages. Stores message id?s and message description to catch response from NSP server - * \param *handle Pointer to nsdl-library handle - * \param *coap_header_ptr Pointer to the CoAP message header to be sent - * \param *dst_addr_ptr Pointer to the address structure that contains destination address information - * \param message_description Message description to be stored to list for waiting response - * - * \return message id, 0 if failed - */ -static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description) -{ - uint8_t *coap_message_ptr = NULL; - uint16_t coap_message_len = 0; - - coap_message_len = sn_coap_builder_calc_needed_packet_data_size(coap_header_ptr); - - if (coap_message_len == 0) { - return 0; - } - - coap_message_ptr = handle->sn_nsdl_alloc(coap_message_len); - if (!coap_message_ptr) { - return 0; - } - - /* Build message */ - if (sn_coap_protocol_build(handle->grs->coap, dst_addr_ptr, coap_message_ptr, coap_header_ptr, (void *)handle) < 0) { - handle->sn_nsdl_free(coap_message_ptr); - return 0; - } - - /* If mesage type is confirmable, save it to list to wait for reply */ - if (coap_header_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { - if (message_description == SN_NSDL_MSG_REGISTER) { - handle->register_msg_id = coap_header_ptr->msg_id; - } - if (message_description == SN_NSDL_MSG_UNREGISTER) { - handle->unregister_msg_id = coap_header_ptr->msg_id; - } - - } - - handle->sn_nsdl_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, coap_message_ptr, coap_message_len, dst_addr_ptr); - handle->sn_nsdl_free(coap_message_ptr); - - return coap_header_ptr->msg_id; -} - -/** - * \fn static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle) - * - * \brief Resolves NSP server address. - * - * \param *handle Pointer to nsdl-library handle - * \note Application must set NSP address with set_nsp_address - */ -static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle) -{ - /* Local variables */ - if (!handle->nsp_address_ptr) { - //allocate only if previously not allocated - handle->nsp_address_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_oma_server_info_t)); - } - - if (handle->nsp_address_ptr) { - handle->nsp_address_ptr->omalw_server_security = SEC_NOT_SET; - handle->nsp_address_ptr->omalw_address_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_addr_s)); - if (handle->nsp_address_ptr->omalw_address_ptr) { - memset(handle->nsp_address_ptr->omalw_address_ptr, 0, sizeof(sn_nsdl_addr_s)); - handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_NONE; - } - } -} - -static int8_t sn_nsdl_create_oma_device_object_base(struct nsdl_s *handle, sn_nsdl_oma_device_t *oma_device_setup_ptr, sn_nsdl_oma_binding_and_mode_t binding_and_mode) -{ - sn_nsdl_resource_info_s new_resource; - uint8_t object_path[8] = "3/0/11/0"; - uint8_t resource_temp[3]; - uint8_t x = 0; - - if (!oma_device_setup_ptr) { - return SN_NSDL_FAILURE; - } - - /* * Create resources. * */ - - /* These resources can be created multiple times. */ - memset(&new_resource, 0, sizeof(sn_nsdl_resource_info_s)); - new_resource.resource_parameters_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_parameters_s)); - if (!new_resource.resource_parameters_ptr) { - return SN_NSDL_FAILURE; - } - - memset(new_resource.resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); - - /* Create error - resource */ - new_resource.mode = SN_GRS_STATIC; - new_resource.access = SN_GRS_GET_ALLOWED; - - new_resource.path = object_path; - new_resource.pathlen = 8; - - sn_nsdl_itoa(resource_temp, (uint8_t)oma_device_setup_ptr->error_code); - - new_resource.resource = resource_temp; - new_resource.resourcelen = 1; - - if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { - handle->sn_nsdl_free(new_resource.resource_parameters_ptr); - return SN_NSDL_FAILURE; - } - - /* These resources can be only once, during OMA bootstrap.. */ - /* Create supported binding and modes */ - object_path[5] = '6'; - new_resource.path = object_path; - new_resource.pathlen = 6; - - if (binding_and_mode & 0x01) { - resource_temp[x] = 'U'; - x++; - if (binding_and_mode & 0x02) { - resource_temp[x] = 'Q'; - x++; - } - } - if (binding_and_mode & 0x04) { - resource_temp[x] = 'S'; - x++; - if ((binding_and_mode & 0x02) && !(binding_and_mode & 0x01)) { - resource_temp[x] = 'Q'; - x++; - } - } - - new_resource.resourcelen = x; - - if (new_resource.resourcelen) { - new_resource.resource = resource_temp; - } else { - new_resource.resource = 0; - } - - - if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { - handle->sn_nsdl_free(new_resource.resource_parameters_ptr); - return SN_NSDL_FAILURE; - } - - - /* Create dynamic reboot object */ - new_resource.mode = SN_GRS_DYNAMIC; - - new_resource.access = SN_GRS_POST_ALLOWED; - - object_path[4] = '4'; - - new_resource.path = object_path; - new_resource.pathlen = 5; - - new_resource.resourcelen = 0; - new_resource.resource = 0; - - new_resource.sn_grs_dyn_res_callback = oma_device_setup_ptr->sn_oma_device_boot_callback; - - if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { - handle->sn_nsdl_free(new_resource.resource_parameters_ptr); - return SN_NSDL_FAILURE; - } - - handle->sn_nsdl_free(new_resource.resource_parameters_ptr); - return SN_NSDL_SUCCESS; -} - -/** - * \fn int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration) - * - * \brief To build GRS resources to registration message payload - * \param *handle Pointer to nsdl-library handle - * \param *message_ptr Pointer to CoAP message header - * - * \return SN_NSDL_SUCCESS = 0, Failed = -1 - */ -int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration) -{ - /* Local variables */ - uint8_t *temp_ptr; - const sn_nsdl_resource_info_s *resource_temp_ptr; - - - /* Calculate needed memory and allocate */ - message_ptr->payload_len = sn_nsdl_calculate_registration_body_size(handle, updating_registeration); - - /* If no resources to be registered, return SN_NSDL_SUCCESS */ - if (!message_ptr->payload_len) { - return SN_NSDL_SUCCESS; - } - - message_ptr->payload_ptr = handle->sn_nsdl_alloc(message_ptr->payload_len); - if (!message_ptr->payload_ptr) { - return SN_NSDL_FAILURE; - } - - /* Build message */ - temp_ptr = message_ptr->payload_ptr; - - resource_temp_ptr = sn_grs_get_first_resource(handle->grs); - - /* Loop trough all resources */ - while (resource_temp_ptr) { - /* if resource needs to be registered */ - if (resource_temp_ptr->resource_parameters_ptr) { - if (updating_registeration && resource_temp_ptr->resource_parameters_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) { - resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); - continue; - } else { - resource_temp_ptr->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERED; - } - - /* If not first resource, add '.' to separator */ - if (temp_ptr != message_ptr->payload_ptr) { - *temp_ptr++ = ','; - } - - *temp_ptr++ = '<'; - *temp_ptr++ = '/'; - memcpy(temp_ptr, resource_temp_ptr->path, resource_temp_ptr->pathlen); - temp_ptr += resource_temp_ptr->pathlen; - *temp_ptr++ = '>'; - - /* Resource attributes */ - if (resource_temp_ptr->resource_parameters_ptr->resource_type_len) { - *temp_ptr++ = ';'; - memcpy(temp_ptr, resource_type_parameter, RT_PARAMETER_LEN); - temp_ptr += RT_PARAMETER_LEN; - *temp_ptr++ = '"'; - memcpy(temp_ptr, resource_temp_ptr->resource_parameters_ptr->resource_type_ptr, resource_temp_ptr->resource_parameters_ptr->resource_type_len); - temp_ptr += resource_temp_ptr->resource_parameters_ptr->resource_type_len; - *temp_ptr++ = '"'; - } - - if (resource_temp_ptr->resource_parameters_ptr->interface_description_len) { - *temp_ptr++ = ';'; - memcpy(temp_ptr, if_description_parameter, IF_PARAMETER_LEN); - temp_ptr += IF_PARAMETER_LEN; - *temp_ptr++ = '"'; - memcpy(temp_ptr, resource_temp_ptr->resource_parameters_ptr->interface_description_ptr, resource_temp_ptr->resource_parameters_ptr->interface_description_len); - temp_ptr += resource_temp_ptr->resource_parameters_ptr->interface_description_len; - *temp_ptr++ = '"'; - } - - if (resource_temp_ptr->resource_parameters_ptr->coap_content_type != 0) { - *temp_ptr++ = ';'; - memcpy(temp_ptr, coap_con_type_parameter, COAP_CON_PARAMETER_LEN); - temp_ptr += COAP_CON_PARAMETER_LEN; - *temp_ptr++ = '"'; - temp_ptr = sn_nsdl_itoa(temp_ptr, resource_temp_ptr->resource_parameters_ptr->coap_content_type); - *temp_ptr++ = '"'; - } - - /* ;obs */ - if (resource_temp_ptr->resource_parameters_ptr->observable) { - *temp_ptr++ = ';'; - memcpy(temp_ptr, obs_parameter, OBS_PARAMETER_LEN); - temp_ptr += OBS_PARAMETER_LEN; - } - - /* ;aobs;id= */ - /* todo: aosb not supported ATM */ - /* - if((resource_temp_ptr->resource_parameters_ptr->auto_obs_len > 0 && resource_temp_ptr->resource_parameters_ptr->auto_obs_len <= 8) && - resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr) - { - uint8_t i = 0; - - *temp_ptr++ = ';'; - memcpy(temp_ptr, aobs_parameter, AOBS_PARAMETER_LEN); - temp_ptr += AOBS_PARAMETER_LEN; - - while(i < resource_temp_ptr->resource_parameters_ptr->auto_obs_len) - { - temp_ptr = sn_nsdl_itoa(temp_ptr, *(resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr + i)); - i++; - } - } - */ - - } - - resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); - } - - return SN_NSDL_SUCCESS; -} - -/** - * \fn static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration) - * - * - * \brief Calculates registration message payload size - * \param *handle Pointer to nsdl-library handle - * \param *grs_resources_list_ptr Pointer to list of GRS resources - * - * \return Needed payload size - */ -static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration) -{ - /* Local variables */ - uint16_t return_value = 0; - const sn_nsdl_resource_info_s *resource_temp_ptr; - - /* check pointer */ - - resource_temp_ptr = sn_grs_get_first_resource(handle->grs); - - while (resource_temp_ptr) { - if (resource_temp_ptr->resource_parameters_ptr) { - if (updating_registeration && resource_temp_ptr->resource_parameters_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) { - resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); - continue; - } - - /* If not first resource, then '.' will be added */ - if (return_value) { - return_value++; - } - - /* Count length for the resource path </path> */ - return_value += (3 + resource_temp_ptr->pathlen); - - /* Count lengths of the attributes */ - - /* Resource type parameter */ - if (resource_temp_ptr->resource_parameters_ptr->resource_type_len) { - /* ;rt="restype" */ - return_value += (6 + resource_temp_ptr->resource_parameters_ptr->resource_type_len); - } - - /* Interface description parameter */ - if (resource_temp_ptr->resource_parameters_ptr->interface_description_len) { - /* ;if="iftype" */ - return_value += (6 + resource_temp_ptr->resource_parameters_ptr->interface_description_len); - } - - if (resource_temp_ptr->resource_parameters_ptr->coap_content_type != 0) { - /* ;if="content" */ - return_value += 6; // all but not content - return_value += sn_nsdl_itoa_len(resource_temp_ptr->resource_parameters_ptr->coap_content_type); - } - - if (resource_temp_ptr->resource_parameters_ptr->observable) { - /* ;obs */ - return_value += 4; - } - /*todo: aobs not supported ATM */ - /* - if((resource_temp_ptr->resource_parameters_ptr->auto_obs_len > 0 && resource_temp_ptr->resource_parameters_ptr->auto_obs_len <= 8) && - resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr) - { - uint8_t i = resource_temp_ptr->resource_parameters_ptr->auto_obs_len; - // ;aobs;id= - return_value += 9; - while(i--) - { - return_value += sn_nsdl_itoa_len(*(resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr + i)); - } - } - */ - - } - - resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); - - } - - return return_value; -} - -/** - * \fn static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type) - * - * - * \brief Calculates needed uri query option length - * - * \param *endpoint_info_ptr Pointer to endpoint info structure - * \param msg_type Message type - * - * \return number of parameters in uri query - */ -static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type) -{ - uint8_t return_value = 0; - uint8_t number_of_parameters = 0; - - - if ((endpoint_info_ptr->endpoint_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && endpoint_info_ptr->endpoint_name_ptr != 0) { - return_value += endpoint_info_ptr->endpoint_name_len; - return_value += EP_NAME_PARAMETERS_LEN; //ep= - number_of_parameters++; - } - - if ((endpoint_info_ptr->type_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->type_ptr != 0)) { - return_value += endpoint_info_ptr->type_len; - return_value += ET_PARAMETER_LEN; //et= - number_of_parameters++; - } - - if ((endpoint_info_ptr->lifetime_len != 0) && (endpoint_info_ptr->lifetime_ptr != 0)) { - return_value += endpoint_info_ptr->lifetime_len; - return_value += LT_PARAMETER_LEN; //lt= - number_of_parameters++; - } - - if ((endpoint_info_ptr->domain_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->domain_name_ptr != 0)) { - return_value += endpoint_info_ptr->domain_name_len; - return_value += DOMAIN_PARAMETER_LEN; //d= - number_of_parameters++; - } - - if (((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01)) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { - return_value += BS_QUEUE_MODE_PARAMATER_LEN; - - if (endpoint_info_ptr->binding_and_mode & 0x01) { - return_value++; - } - if (endpoint_info_ptr->binding_and_mode & 0x04) { - return_value++; - } - if ((endpoint_info_ptr->binding_and_mode & 0x02) && ((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01))) { - return_value++; - } - - number_of_parameters++; - } - - if (number_of_parameters != 0) { - return_value += (number_of_parameters - 1); - } - - return return_value; -} - -/** - * \fn static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type) - * - * - * \brief Fills uri-query options to message header struct - * \param *handle Pointer to nsdl-library handle - * \param *parameter_ptr Pointer to endpoint parameters struct - * \param *source_msg_ptr Pointer to CoAP header struct - * \param msg_type Message type - * - * \return SN_NSDL_SUCCESS = 0, Failed = -1 - */ -static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type) -{ - uint8_t *temp_ptr = NULL; - if( !validateParameters(parameter_ptr) ){ - return SN_NSDL_FAILURE; - } - source_msg_ptr->options_list_ptr->uri_query_len = sn_nsdl_calculate_uri_query_option_len(parameter_ptr, msg_type); - if (source_msg_ptr->options_list_ptr->uri_query_len == 0) { - return 0; - } - - source_msg_ptr->options_list_ptr->uri_query_ptr = handle->sn_nsdl_alloc(source_msg_ptr->options_list_ptr->uri_query_len); - - if (source_msg_ptr->options_list_ptr->uri_query_ptr == NULL) { - return SN_NSDL_FAILURE; - } - memset(source_msg_ptr->options_list_ptr->uri_query_ptr,0,source_msg_ptr->options_list_ptr->uri_query_len); - - temp_ptr = source_msg_ptr->options_list_ptr->uri_query_ptr; - - /******************************************************/ - /* If endpoint name is configured, fill needed fields */ - /******************************************************/ - - if ((parameter_ptr->endpoint_name_len != 0) && (parameter_ptr->endpoint_name_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { - /* fill endpoint name, first ?ep=, then endpoint name */ - memcpy(temp_ptr, ep_name_parameter_string, sizeof(ep_name_parameter_string)); - temp_ptr += EP_NAME_PARAMETERS_LEN; - memcpy(temp_ptr, parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len); - temp_ptr += parameter_ptr->endpoint_name_len; - } - - /******************************************************/ - /* If endpoint type is configured, fill needed fields */ - /******************************************************/ - - if ((parameter_ptr->type_len != 0) && (parameter_ptr->type_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { - if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { - *temp_ptr++ = '&'; - } - - memcpy(temp_ptr, et_parameter, sizeof(et_parameter)); - temp_ptr += ET_PARAMETER_LEN; - memcpy(temp_ptr, parameter_ptr->type_ptr, parameter_ptr->type_len); - temp_ptr += parameter_ptr->type_len; - } - - - /******************************************************/ - /* If lifetime is configured, fill needed fields */ - /******************************************************/ - - if ((parameter_ptr->lifetime_len != 0) && (parameter_ptr->lifetime_ptr != 0)) { - if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { - *temp_ptr++ = '&'; - } - - memcpy(temp_ptr, ep_lifetime_parameter, sizeof(ep_lifetime_parameter)); - temp_ptr += LT_PARAMETER_LEN; - memcpy(temp_ptr, parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len); - temp_ptr += parameter_ptr->lifetime_len; - } - - /******************************************************/ - /* If domain is configured, fill needed fields */ - /******************************************************/ - - if ((parameter_ptr->domain_name_len != 0) && (parameter_ptr->domain_name_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { - if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { - *temp_ptr++ = '&'; - } - - memcpy(temp_ptr, ep_domain_parameter, sizeof(ep_domain_parameter)); - temp_ptr += DOMAIN_PARAMETER_LEN; - memcpy(temp_ptr, parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len); - temp_ptr += parameter_ptr->domain_name_len; - } - - /******************************************************/ - /* If queue-mode is configured, fill needed fields */ - /******************************************************/ - - if (((parameter_ptr->binding_and_mode & 0x01) || (parameter_ptr->binding_and_mode & 0x04)) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { - if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { - *temp_ptr++ = '&'; - } - - memcpy(temp_ptr, bs_queue_mode, sizeof(bs_queue_mode)); - temp_ptr += BS_QUEUE_MODE_PARAMATER_LEN; - - if (parameter_ptr->binding_and_mode & 0x01) { - *temp_ptr++ = 'U'; - if (parameter_ptr->binding_and_mode & 0x02) { - *temp_ptr++ = 'Q'; - } - } - - if (parameter_ptr->binding_and_mode & 0x04) { - *temp_ptr++ = 'S'; - if ((parameter_ptr->binding_and_mode & 0x02) && !(parameter_ptr->binding_and_mode & 0x01)) { - *temp_ptr++ = 'Q'; - } - } - } - - return SN_NSDL_SUCCESS; -} - -static bool validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr) -{ - if( !validate( parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len, '&' ) ){ - return false; - } - - if( !validate( parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len, '&' ) ){ - return false; - } - - if( !validate( parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len, '&' ) ){ - return false; - } - - if( !validate( parameter_ptr->type_ptr, parameter_ptr->type_len, '&' ) ){ - return false; - } - return true; -} - -static bool validate(uint8_t* ptr, uint32_t len, char illegalChar) -{ - if( ptr ){ - for( int i=0; i < len; i++ ){ - if( ptr[i] == illegalChar ){ - return false; - } - } - } - return true; -} - -/** - * \fn static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr) - * - * \brief If received message is reply for the message that NSDL has been sent, it is processed here. Else, packet will be sent to application. - * \param *handle Pointer to nsdl-library handle - * \param *coap_packet_ptr Pointer to received CoAP packet - * \param *address_ptr Pointer to source address struct - * - * \return SN_NSDL_SUCCESS = 0, Failed = -1 - */ -static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr) -{ - if ((coap_packet_ptr == 0) || (address_ptr == 0)) { - return -1; - } - - if (coap_packet_ptr->msg_id == handle->register_msg_id) { - if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CREATED) { - handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_IS_REGISTERED; - sn_grs_mark_resources_as_registered(handle); - if (sn_nsdl_resolve_ep_information(handle, coap_packet_ptr) != SN_NSDL_SUCCESS) { - return SN_NSDL_FAILURE; - } - - handle->register_msg_id = 0; - } - } - - if (coap_packet_ptr->msg_id == handle->unregister_msg_id) { - if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_DELETED) { - if (handle->ep_information_ptr->endpoint_name_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); - handle->ep_information_ptr->endpoint_name_ptr = 0; - handle->ep_information_ptr->endpoint_name_len = 0; - } - if (handle->ep_information_ptr->domain_name_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); - handle->ep_information_ptr->domain_name_ptr = 0; - handle->ep_information_ptr->domain_name_len = 0; - } - - handle->unregister_msg_id = 0; - } - } - - /* No messages to wait for, or message was not response to our request */ - return handle->sn_nsdl_rx_callback(handle, coap_packet_ptr, address_ptr); -} - -/** - * \fn static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr) - * - * - * \brief Resolves endpoint information from received CoAP message - * \param *handle Pointer to nsdl-library handle - * \param *coap_packet_ptr Pointer to received CoAP message - * - * \return SN_NSDL_SUCCESS = 0, Failed = -1 - */ -static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr) -{ - uint8_t *temp_ptr; - uint8_t parameter_count = 0; - uint16_t parameter_len = 0; - - if (!coap_packet_ptr || !coap_packet_ptr->options_list_ptr || - !coap_packet_ptr->options_list_ptr->location_path_ptr) { - return SN_NSDL_FAILURE; - } - - temp_ptr = coap_packet_ptr->options_list_ptr->location_path_ptr; - - while (temp_ptr <= (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) { - - if ((temp_ptr == (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) || (*temp_ptr == '/')) { - - parameter_count++; - if (parameter_count == 2) { - if (!handle->ep_information_ptr->domain_name_ptr) { - handle->ep_information_ptr->domain_name_len = parameter_len - 1; - handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->domain_name_len); - if (!handle->ep_information_ptr->domain_name_ptr) { - return SN_NSDL_FAILURE; - } - memcpy(handle->ep_information_ptr->domain_name_ptr, temp_ptr - handle->ep_information_ptr->domain_name_len, handle->ep_information_ptr->domain_name_len); - } - - } - if (parameter_count == 3) { - if (!handle->ep_information_ptr->endpoint_name_ptr) { - handle->ep_information_ptr->endpoint_name_len = parameter_len - 1; - handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->endpoint_name_len); - if (!handle->ep_information_ptr->endpoint_name_ptr) { - if (handle->ep_information_ptr->domain_name_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); - handle->ep_information_ptr->domain_name_ptr = NULL; - handle->ep_information_ptr->domain_name_len = 0; - } - - return SN_NSDL_FAILURE; - - } - memcpy(handle->ep_information_ptr->endpoint_name_ptr, temp_ptr - handle->ep_information_ptr->endpoint_name_len, handle->ep_information_ptr->endpoint_name_len); - } - } - parameter_len = 0; - } - parameter_len++; - temp_ptr++; - } - - - return SN_NSDL_SUCCESS; -} - -int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type) -{ - - /* Check parameters and source pointers */ - if (!handle || !handle->nsp_address_ptr || !handle->nsp_address_ptr->omalw_address_ptr || !NSP_address) { - return SN_NSDL_FAILURE; - } - - handle->nsp_address_ptr->omalw_address_ptr->type = address_type; - handle->nsp_address_ptr->omalw_server_security = SEC_NOT_SET; - - if (address_type == SN_NSDL_ADDRESS_TYPE_IPV4) { - if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { - handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); - } - - handle->nsp_address_ptr->omalw_address_ptr->addr_len = 4; - - handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(handle->nsp_address_ptr->omalw_address_ptr->addr_len); - if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { - return SN_NSDL_FAILURE; - } - - memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, NSP_address, handle->nsp_address_ptr->omalw_address_ptr->addr_len); - handle->nsp_address_ptr->omalw_address_ptr->port = port; - } - - else if (address_type == SN_NSDL_ADDRESS_TYPE_IPV6) { - if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { - handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); - } - - handle->nsp_address_ptr->omalw_address_ptr->addr_len = 16; - - handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(handle->nsp_address_ptr->omalw_address_ptr->addr_len); - if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { - return SN_NSDL_FAILURE; - } - - memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, NSP_address, handle->nsp_address_ptr->omalw_address_ptr->addr_len); - handle->nsp_address_ptr->omalw_address_ptr->port = port; - } - return SN_NSDL_SUCCESS; -} - - -static uint8_t sn_nsdl_itoa_len(uint8_t value) -{ - uint8_t i = 0; - - do { - i++; - } while ((value /= 10) > 0); - - return i; -} - -static uint8_t *sn_nsdl_itoa(uint8_t *ptr, uint8_t value) -{ - - uint8_t start = 0; - uint8_t end = 0; - uint8_t i; - - i = 0; - - /* ITOA */ - do { - ptr[i++] = (value % 10) + '0'; - } while ((value /= 10) > 0); - - end = i - 1; - - /* reverse (part of ITOA) */ - while (start < end) { - uint8_t chr; - - chr = ptr[start]; - ptr[start] = ptr[end]; - ptr[end] = chr; - - start++; - end--; - - } - return (ptr + i); -} - -static int32_t sn_nsdl_atoi(uint8_t *ptr, uint8_t len) -{ - - int32_t result = 0; - - while (len--) { - - if (result) { - result *= 10; - } - - if (*ptr >= '0' && *ptr <= '9') { - result += *ptr - '0'; - } else{ - return -1; - } - - ptr++; - - } - return result; - -} - -static uint32_t sn_nsdl_ahextoi(uint8_t *ptr, uint8_t len) -{ - - uint32_t result = 0; - - while (len--) { - - if (result) { - result *= 16; - } - - if (*ptr >= '0' && *ptr <= '9') { - result += *ptr - '0'; - } else if (*ptr >= 'a' && *ptr <= 'f') { - result += *ptr - 87; - } else if (*ptr >= 'A' && *ptr <= 'F') { - result += *ptr - 55; - } - - ptr++; - - } - return result; - -} - -static int8_t sn_nsdl_resolve_lwm2m_address(struct nsdl_s *handle, uint8_t *uri, uint16_t uri_len) -{ - if( uri_len < 2 ){ - return SN_NSDL_FAILURE; - } - uint8_t *temp_ptr = uri+2; - uint16_t i = 0; - uint8_t char_cnt = 0; - - /* jump over coap// */ - while ((*(temp_ptr - 2) != '/') || (*(temp_ptr - 1) != '/')) { - temp_ptr++; - if (temp_ptr - uri >= uri_len) { - return SN_NSDL_FAILURE; - } - } - - /* Resolve address type */ - /* Count semicolons */ - - int8_t endPos = -1; - - while (i < (uri_len - (temp_ptr - uri))) { - if (*(temp_ptr + i) == ':') { - char_cnt++; - }else if(*(temp_ptr + i) == ']'){ - endPos = i; - } - i++; - } - - uint8_t *temp_pos = temp_ptr; //store starting point in case of IPv4 parsing fails - - /* IPv6 */ - if (char_cnt > 2) { - i = 0; - - if( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ){ - handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); - } - - handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_IPV6; - handle->nsp_address_ptr->omalw_address_ptr->addr_len = 16; - handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(16); - if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { - return SN_NSDL_FAILURE; - } - - memset(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, 0, 16); - if (*temp_ptr == '[' && endPos > 0 && (temp_ptr - uri) + endPos < uri_len && *(temp_ptr + endPos + 1) == ':') { - temp_ptr++; - endPos--; - }else{ - /* return failure, because port is mandatory */ - return SN_NSDL_FAILURE; - } - - int8_t loopbackPos = -1; - if( char_cnt != 8 ){ - i = 0; - char_cnt -= 1; - while( i+1 < endPos ){ - if(*(temp_ptr + i) == ':' && *(temp_ptr + i+1) == ':') { - loopbackPos = i; - break; - } - i++; - } - } - i = 0; - - uint8_t numberOfZeros = 8 - char_cnt; - if(loopbackPos == 0){ - numberOfZeros++; - } - - if(loopbackPos == endPos-2){ - numberOfZeros++; - } - - /* Resolve address */ - int8_t pos = loopbackPos == 0?0:-1; - while (i < 16 && ((temp_ptr - uri) + char_cnt) < uri_len) { - char_cnt = 0; - if( pos == loopbackPos ){ - for( int k=0; k < numberOfZeros; k++ ){ - i+=2; - } - pos+=2; - temp_ptr += 2; - if( numberOfZeros == 8 ){ - temp_ptr++; - } - continue; - } - while (*(temp_ptr + char_cnt) != ':' && *(temp_ptr + char_cnt) != ']') { - char_cnt++; - pos++; - } - pos++; - - if (char_cnt <= 2) { - i++; - } - - while (char_cnt) { - if (char_cnt % 2) { - *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + i) = (uint8_t)sn_nsdl_ahextoi(temp_ptr, 1); - temp_ptr++; - char_cnt --; - } else { - *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + i) = (uint8_t)sn_nsdl_ahextoi(temp_ptr, 2); - temp_ptr += 2; - char_cnt -= 2; - } - i++; - } - temp_ptr++; - } - - temp_ptr++; - uint16_t handled = (temp_ptr - uri); - if( handled < uri_len ){ - if( *(temp_ptr + (uri_len - (temp_ptr - uri) -1)) == '/' ){ - handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); - }else{ - handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); - } - } - } - /* IPv4 or Hostname */ - else if (char_cnt == 1) { - char_cnt = 0; - i = 0; - - if( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ){ - handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); - } - - /* Check address type */ - while (i < (uri_len - (temp_ptr - uri))) { - if (*(temp_ptr + i) == '.') { - char_cnt++; - } - i++; - } - - bool parseOk = true; - - /* Try IPv4 first */ - if (char_cnt == 3) { - i = 0; - char_cnt = 0; - - handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_IPV4; - handle->nsp_address_ptr->omalw_address_ptr->addr_len = 4; - handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(4); - if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { - return SN_NSDL_FAILURE; - } - - while (parseOk && ((temp_ptr - uri) < uri_len) && *(temp_ptr - 1) != ':') { - i++; - - if (*(temp_ptr + i) == ':' || *(temp_ptr + i) == '.') { - int8_t value = (int8_t)sn_nsdl_atoi(temp_ptr, i); - if( value == -1 ){ - parseOk = false; - char_cnt = 3; - handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); - handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; - break; - } - *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + char_cnt) = value; - temp_ptr = temp_ptr + i + 1; - char_cnt++; - i = 0; - } - } - if(parseOk) { - if( *(temp_ptr + (uri_len - (temp_ptr - uri) -1)) == '/' ){ - handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); - }else{ - handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); - } - } - }else{ - parseOk = false; - } - - /* Then try Hostname */ - if(!parseOk) { - i = 0; - temp_ptr = temp_pos; - - handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_HOSTNAME; - - /* Resolve address length */ - if (uri_len > 0xff) { - return SN_NSDL_FAILURE; - } - - while (((temp_ptr - uri) + i < uri_len) && *(temp_ptr + i) != ':') { - i++; - } - - handle->nsp_address_ptr->omalw_address_ptr->addr_len = i; - - /* Copy address */ - handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(i); - if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { - return SN_NSDL_FAILURE; - } - - memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, temp_ptr, i); - - temp_ptr += i + 1; - - /* Set port */ - if( *(temp_ptr + (uri_len - (temp_ptr - uri) - 1)) == '/' ){ - handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); - }else{ - handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); - } - } - } else { - return SN_NSDL_FAILURE; - } - - return SN_NSDL_SUCCESS; -} - - -int8_t sn_nsdl_process_oma_tlv(struct nsdl_s *handle, uint8_t *data_ptr, uint16_t data_len) -{ - uint8_t *temp_ptr = data_ptr; - uint8_t type = 0; - uint16_t identifier = 0; - uint32_t length = 0; - uint8_t path_temp[5] = "0/0/x"; - - sn_nsdl_resource_info_s resource_temp = { - .resource_parameters_ptr = 0, - .mode = SN_GRS_STATIC, - .pathlen = 5, - .path = path_temp, - .resourcelen = 0, - .resource = 0, - .access = (sn_grs_resource_acl_e) 0x0f, /* All allowed */ - .sn_grs_dyn_res_callback = 0 - }; - - while ((temp_ptr - data_ptr) < data_len) { - /* Save type for future use */ - type = *temp_ptr++; - - /* * Bit 5: Indicates the Length of the Identifier. * */ - if (type & 0x20) { - /* 1=The Identifier field of this TLV is 16 bits long */ - identifier = (uint8_t)(*temp_ptr++) << 8; - identifier += (uint8_t) * temp_ptr++; - } else { - /* 0=The Identifier field of this TLV is 8 bits long */ - identifier = (uint8_t) * temp_ptr++; - } - - /* * Bit 4-3: Indicates the type of Length. * */ - if ((type & 0x18) == 0) { - /* 00 = No length field, the value immediately follows the Identifier field in is of the length indicated by Bits 2-0 of this field */ - length = (type & 0x07); - } else if ((type & 0x18) == 0x08) { - /* 01 = The Length field is 8-bits and Bits 2-0 MUST be ignored */ - length = *temp_ptr++; - } else if ((type & 0x18) == 0x10) { - /* 10 = The Length field is 16-bits and Bits 2-0 MUST be ignored */ - length = (uint8_t)(*temp_ptr++) << 8; - length += (uint8_t) * temp_ptr++; - } else if ((type & 0x18) == 0x18) { - /* 11 = The Length field is 24-bits and Bits 2-0 MUST be ignored */ - length = (uint8_t)(*temp_ptr++); - length = length << 16; - length += (uint8_t)(*temp_ptr++) << 8; - length += (uint8_t) * temp_ptr++; - } - - /* * Bits 7-6: Indicates the type of Identifier. * */ - if ((type & 0xC0) == 0x00) { - /* 00 = Object Instance in which case the Value contains one or more Resource TLVs */ - /* Not implemented, return failure */ - } else if ((type & 0xC0) == 0xC0) { - /* 11 = Resource with Value */ - switch (identifier) { - case 0: - /* Resolve LWM2M Server URI */ - sn_nsdl_resolve_lwm2m_address(handle, temp_ptr, length); - path_temp[4] = '0'; - resource_temp.resource = temp_ptr; - resource_temp.resourcelen = length; - if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { - return SN_NSDL_FAILURE; - } - break; - case 2: - /* Resolve security Mode */ - handle->nsp_address_ptr->omalw_server_security = (omalw_server_security_t)sn_nsdl_atoi(temp_ptr, length); - path_temp[4] = '2'; - resource_temp.resource = temp_ptr; - resource_temp.resourcelen = length; - if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { - return SN_NSDL_FAILURE; - } - - break; - case 3: - /* Public Key or Identity */ - path_temp[4] = '3'; - resource_temp.resource = temp_ptr; - resource_temp.resourcelen = length; - if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { - return SN_NSDL_FAILURE; - } - break; - case 4: - /* Server Public Key or Identity */ - ; - path_temp[4] = '4'; - resource_temp.resource = temp_ptr; - resource_temp.resourcelen = length; - if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { - return SN_NSDL_FAILURE; - } - - break; - case 5: - /* Secret Key */ - path_temp[4] = '5'; - resource_temp.resource = temp_ptr; - resource_temp.resourcelen = length; - if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { - return SN_NSDL_FAILURE; - } - break; - default: - break; - } - - /* Move pointer to next TLV message */ - temp_ptr += length; - } - } - - return SN_NSDL_SUCCESS; -} - -static void sn_nsdl_check_oma_bs_status(struct nsdl_s *handle) -{ - /* Check OMA BS status */ - if ((handle->nsp_address_ptr->omalw_server_security == PSK) && (handle->nsp_address_ptr->omalw_address_ptr->type != SN_NSDL_ADDRESS_TYPE_NONE)) { - /* call cb that oma bootstrap is done */ - if(handle->sn_nsdl_oma_bs_done_cb != 0){ - handle->sn_nsdl_oma_bs_done_cb(handle->nsp_address_ptr); - } - } else if ((handle->nsp_address_ptr->omalw_server_security == CERTIFICATE) && (handle->nsp_address_ptr->omalw_address_ptr->type != SN_NSDL_ADDRESS_TYPE_NONE) && - ((sn_nsdl_get_resource(handle, 5, (void *)"0/0/5") != 0) && - (sn_nsdl_get_resource(handle, 5, (void *)"0/0/4") != 0) && - (sn_nsdl_get_resource(handle, 5, (void *)"0/0/3") != 0))) { - if( handle->sn_nsdl_oma_bs_done_cb ){ - handle->sn_nsdl_oma_bs_done_cb(handle->nsp_address_ptr); - } - } -} - -static int8_t set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr) -{ - if (handle->ep_information_ptr->domain_name_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); - handle->ep_information_ptr->domain_name_ptr = 0; - handle->ep_information_ptr->domain_name_len = 0; - } - - if (handle->ep_information_ptr->endpoint_name_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); - handle->ep_information_ptr->endpoint_name_ptr = 0; - handle->ep_information_ptr->endpoint_name_len = 0; - } - - if (endpoint_info_ptr->domain_name_ptr && endpoint_info_ptr->domain_name_len) { - handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->domain_name_len); - - if (!handle->ep_information_ptr->domain_name_ptr) { - return -1; - } - - memcpy(handle->ep_information_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_len); - handle->ep_information_ptr->domain_name_len = endpoint_info_ptr->domain_name_len; - } - - if (endpoint_info_ptr->endpoint_name_ptr && endpoint_info_ptr->endpoint_name_len) { - handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len); - - if (!handle->ep_information_ptr->endpoint_name_ptr) { - if (handle->ep_information_ptr->domain_name_ptr) { - handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); - handle->ep_information_ptr->domain_name_ptr = 0; - handle->ep_information_ptr->domain_name_len = 0; - } - return -1; - } - - memcpy(handle->ep_information_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len); - handle->ep_information_ptr->endpoint_name_len = endpoint_info_ptr->endpoint_name_len; - } - - handle->ep_information_ptr->binding_and_mode = endpoint_info_ptr->binding_and_mode; - handle->ep_information_ptr->ds_register_mode = endpoint_info_ptr->ds_register_mode; - - handle->ep_information_ptr->location_ptr = 0; - handle->ep_information_ptr->location_len = 0; - - return 0; -} - -/* Wrapper */ -sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) -{ - /* Check parameters */ - if (handle == NULL) { - return NULL; - } - - return sn_grs_list_resource(handle->grs, pathlen, path); -} - -void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list) -{ - /* Check parameters */ - if (handle == NULL) { - return; - } - - sn_grs_free_resource_list(handle->grs, list); -} - -extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res) -{ - /* Check parameters */ - if (handle == NULL) { - return SN_NSDL_FAILURE; - } - - return sn_grs_update_resource(handle->grs, res); -} - -extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr) -{ - /* Check parameters */ - if (handle == NULL) { - return SN_NSDL_FAILURE; - } - - return sn_grs_send_coap_message(handle, address_ptr, coap_hdr_ptr); -} - -extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res) -{ - /* Check parameters */ - if (handle == NULL) { - return SN_NSDL_FAILURE; - } - - return sn_grs_create_resource(handle->grs, res); -} - -extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) -{ - /* Check parameters */ - if (handle == NULL) { - return SN_NSDL_FAILURE; - } - - return sn_grs_delete_resource(handle->grs, pathlen, path); -} -extern const sn_nsdl_resource_info_s *sn_nsdl_get_first_resource(struct nsdl_s *handle) -{ - /* Check parameters */ - if (handle == NULL) { - return NULL; - } - - return sn_grs_get_first_resource(handle->grs); -} -extern const sn_nsdl_resource_info_s *sn_nsdl_get_next_resource(struct nsdl_s *handle, const sn_nsdl_resource_info_s *resource) -{ - /* Check parameters */ - if (handle == NULL) { - return NULL; - } - - return sn_grs_get_next_resource(handle->grs, resource); -} - -extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) -{ - if (handle == NULL) { - return NULL; - } - - return sn_coap_build_response(handle->grs->coap, coap_packet_ptr, msg_code); -} - -extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) -{ - if (handle == NULL) { - return; - } - - sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, freed_coap_msg_ptr); -} - +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * \file sn_nsdl.c + * + * \brief Nano service device library + * + */ + +#include <string.h> + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_coap_protocol_internal.h" +#include "sn_nsdl_lib.h" +#include "sn_grs.h" + +/* Defines */ +#define RESOURCE_DIR_LEN 2 +#define EP_NAME_PARAMETERS_LEN 3 +#define ET_PARAMETER_LEN 3 +#define LT_PARAMETER_LEN 3 +#define DOMAIN_PARAMETER_LEN 2 +#define RT_PARAMETER_LEN 3 +#define IF_PARAMETER_LEN 3 +#define OBS_PARAMETER_LEN 3 +#define AOBS_PARAMETER_LEN 8 +#define COAP_CON_PARAMETER_LEN 3 +#define BS_EP_PARAMETER_LEN 3 +#define BS_QUEUE_MODE_PARAMATER_LEN 2 + +#define SN_NSDL_EP_REGISTER_MESSAGE 1 +#define SN_NSDL_EP_UPDATE_MESSAGE 2 + +#define SN_NSDL_MSG_UNDEFINED 0 +#define SN_NSDL_MSG_REGISTER 1 +#define SN_NSDL_MSG_UNREGISTER 2 +#define SN_NSDL_MSG_UPDATE 3 + +/* Constants */ +static uint8_t ep_name_parameter_string[] = {'e', 'p', '='}; /* Endpoint name. A unique name for the registering node in a domain. */ +static uint8_t resource_path_ptr[] = {'r', 'd'}; /* For resource directory */ +static uint8_t resource_type_parameter[] = {'r', 't', '='}; /* Resource type. Only once for registration */ +#ifndef YOTTA_CFG_DISABLE_OBS_FEATURE +static uint8_t obs_parameter[] = {'o', 'b', 's'}; /* Observable */ +#endif +//static uint8_t aobs_parameter[] = {'a','o','b','s',';','i','d','='}; /* Auto-observable - TBD */ +static uint8_t if_description_parameter[] = {'i', 'f', '='}; /* Interface description. Only once */ +static uint8_t ep_lifetime_parameter[] = {'l', 't', '='}; /* Lifetime. Number of seconds that this registration will be valid for. Must be updated within this time, or will be removed. */ +static uint8_t ep_domain_parameter[] = {'d', '='}; /* Domain name. If this parameter is missing, a default domain is assumed. */ +static uint8_t coap_con_type_parameter[] = {'c', 't', '='}; /* CoAP content type */ +/* * OMA BS parameters * */ +static uint8_t bs_uri[] = {'b', 's'}; +static uint8_t bs_ep_name[] = {'e', 'p', '='}; +static uint8_t et_parameter[] = {'e', 't', '='}; /* Endpoint type */ +static uint8_t bs_queue_mode[] = {'b', '='}; + +/* Function prototypes */ +static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description); +static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle); +int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration); +static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration); +static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type); +static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type); +static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr); +static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr); +static uint8_t sn_nsdl_itoa_len(uint8_t value); +static uint8_t *sn_nsdl_itoa(uint8_t *ptr, uint8_t value); +static int32_t sn_nsdl_atoi(uint8_t *ptr, uint8_t len); +static uint32_t sn_nsdl_ahextoi(uint8_t *ptr, uint8_t len); +static int8_t sn_nsdl_resolve_lwm2m_address(struct nsdl_s *handle, uint8_t *uri, uint16_t uri_len); +static int8_t sn_nsdl_process_oma_tlv(struct nsdl_s *handle, uint8_t *data_ptr, uint16_t data_len); +static void sn_nsdl_check_oma_bs_status(struct nsdl_s *handle); +static int8_t sn_nsdl_create_oma_device_object_base(struct nsdl_s *handle, sn_nsdl_oma_device_t *oma_device_setup_ptr, sn_nsdl_oma_binding_and_mode_t binding_and_mode); +static int8_t set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); +static bool validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr); +static bool validate(uint8_t* ptr, uint32_t len, char illegalChar); + +int8_t sn_nsdl_destroy(struct nsdl_s *handle) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + if (handle->ep_information_ptr) { + if (handle->ep_information_ptr->endpoint_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); + handle->ep_information_ptr->endpoint_name_ptr = 0; + } + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = 0; + handle->ep_information_ptr->domain_name_len = 0; + } + if (handle->ep_information_ptr->location_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->location_ptr); + handle->ep_information_ptr->location_ptr = 0; + handle->ep_information_ptr->location_len = 0; + } + if (handle->ep_information_ptr->type_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->type_ptr); + handle->ep_information_ptr->type_ptr = 0; + } + + if (handle->ep_information_ptr->lifetime_ptr) + + { + handle->sn_nsdl_free(handle->ep_information_ptr->lifetime_ptr); + handle->ep_information_ptr->lifetime_ptr = 0; + } + + handle->sn_nsdl_free(handle->ep_information_ptr); + handle->ep_information_ptr = 0; + } + + if (handle->nsp_address_ptr) { + if (handle->nsp_address_ptr->omalw_address_ptr) { + if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = 0; + } + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr); + } + + handle->sn_nsdl_free(handle->nsp_address_ptr); + handle->nsp_address_ptr = 0; + } + + if (handle->oma_bs_address_ptr) { + handle->sn_nsdl_free(handle->oma_bs_address_ptr); + } + + /* Destroy also libCoap and grs part of libNsdl */ + sn_coap_protocol_destroy(handle->grs->coap); + sn_grs_destroy(handle->grs); + handle->sn_nsdl_free(handle); + + return SN_NSDL_SUCCESS; +} + +struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *)) +{ + /* Check pointers and define function pointers */ + if (!sn_nsdl_alloc || !sn_nsdl_free || !sn_nsdl_tx_cb || !sn_nsdl_rx_cb) { + return NULL; + } + + struct nsdl_s *handle = NULL; + + handle = sn_nsdl_alloc(sizeof(struct nsdl_s)); + + if (handle == NULL) { + return NULL; + } + + memset(handle, 0, sizeof(struct nsdl_s)); + + /* Define function pointers */ + handle->sn_nsdl_alloc = sn_nsdl_alloc; + handle->sn_nsdl_free = sn_nsdl_free; + + handle->sn_nsdl_tx_callback = sn_nsdl_tx_cb; + handle->sn_nsdl_rx_callback = sn_nsdl_rx_cb; + + /* Initialize ep parameters struct */ + if (!handle->ep_information_ptr) { + handle->ep_information_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_ep_parameters_s)); + if (!handle->ep_information_ptr) { + sn_nsdl_free(handle); + return NULL; + } + memset(handle->ep_information_ptr, 0, sizeof(sn_nsdl_ep_parameters_s)); + } + + handle->grs = sn_grs_init(sn_nsdl_tx_cb, &sn_nsdl_local_rx_function, sn_nsdl_alloc, sn_nsdl_free); + + /* Initialize GRS */ + if (handle->grs == NULL) { + handle->sn_nsdl_free(handle->ep_information_ptr); + handle->ep_information_ptr = 0; + sn_nsdl_free(handle); + return NULL; + } + + sn_nsdl_resolve_nsp_address(handle); + + handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED; + + return handle; +} + +uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr) +{ + /* Local variables */ + sn_coap_hdr_s *register_message_ptr; + uint16_t message_id = 0; + + if (endpoint_info_ptr == NULL || handle == NULL) { + return 0; + } + + /*** Build endpoint register message ***/ + + /* Allocate memory for header struct */ + register_message_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_hdr_s)); + if (register_message_ptr == NULL) { + return 0; + } + + memset(register_message_ptr, 0, sizeof(sn_coap_hdr_s)); + + /* Fill message fields -> confirmable post to specified NSP path */ + register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST; + + /* Allocate memory for the extended options list */ + register_message_ptr->options_list_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_options_list_s)); + if (register_message_ptr->options_list_ptr == NULL) { + handle->sn_nsdl_free(register_message_ptr); + register_message_ptr = 0; + return 0; + } + + memset(register_message_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + register_message_ptr->uri_path_len = sizeof(resource_path_ptr); + register_message_ptr->uri_path_ptr = resource_path_ptr; + + /* Fill Uri-query options */ + if( SN_NSDL_FAILURE == sn_nsdl_fill_uri_query_options(handle, endpoint_info_ptr, + register_message_ptr, SN_NSDL_EP_REGISTER_MESSAGE) ){ + register_message_ptr->uri_path_ptr = NULL; + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + + if (endpoint_info_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) { + /* Built body for message */ + if (sn_nsdl_build_registration_body(handle, register_message_ptr, 0) == SN_NSDL_FAILURE) { + register_message_ptr->uri_path_ptr = NULL; + register_message_ptr->options_list_ptr->uri_host_ptr = NULL; + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + } + + /* Clean (possible) existing and save new endpoint info to handle */ + if (set_endpoint_info(handle, endpoint_info_ptr) == -1) { + if (register_message_ptr->payload_ptr) { + handle->sn_nsdl_free(register_message_ptr->payload_ptr); + register_message_ptr->payload_ptr = NULL; + } + + register_message_ptr->uri_path_ptr = NULL; + register_message_ptr->options_list_ptr->uri_host_ptr = NULL; + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + + return 0; + } + + /* Build and send coap message to NSP */ + message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_REGISTER); + + if (register_message_ptr->payload_ptr) { + handle->sn_nsdl_free(register_message_ptr->payload_ptr); + register_message_ptr->payload_ptr = NULL; + } + + register_message_ptr->uri_path_ptr = NULL; + register_message_ptr->options_list_ptr->uri_host_ptr = NULL; + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + + return message_id; +} + +uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle) +{ + /* Local variables */ + sn_coap_hdr_s *unregister_message_ptr; + uint8_t *temp_ptr = 0; + uint16_t message_id = 0; + + /* Check parameters */ + if (handle == NULL) { + return 0; + } + + /* Check that EP have been registered */ + if (sn_nsdl_is_ep_registered(handle)) { + + /* Memory allocation for unregister message */ + unregister_message_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_hdr_s)); + if (!unregister_message_ptr) { + return 0; + } + + memset(unregister_message_ptr, 0, sizeof(sn_coap_hdr_s)); + + /* Fill unregister message */ + unregister_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + unregister_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + + if(handle->ep_information_ptr->location_ptr) { + unregister_message_ptr->uri_path_len = handle->ep_information_ptr->location_len; + unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len); + if (!unregister_message_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); + return 0; + } + + temp_ptr = unregister_message_ptr->uri_path_ptr; + + memcpy(temp_ptr , handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len); + } else { + unregister_message_ptr->uri_path_len = (RESOURCE_DIR_LEN + 1 + handle->ep_information_ptr->domain_name_len + 1 + handle->ep_information_ptr->endpoint_name_len); + unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len); + if (!unregister_message_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); + return 0; + } + + temp_ptr = unregister_message_ptr->uri_path_ptr; + + memcpy(temp_ptr, resource_path_ptr, RESOURCE_DIR_LEN); + temp_ptr += RESOURCE_DIR_LEN; + + *temp_ptr++ = '/'; + + memcpy(temp_ptr , handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len); + temp_ptr += handle->ep_information_ptr->domain_name_len; + + *temp_ptr++ = '/'; + + memcpy(temp_ptr , handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len); + } + + /* Send message */ + message_id = sn_nsdl_internal_coap_send(handle, unregister_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UNREGISTER); + + /* Free memory */ + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); + + } + + return message_id; +} + +uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len) +{ + /* Local variables */ + sn_coap_hdr_s *register_message_ptr; + uint8_t *temp_ptr; + sn_nsdl_ep_parameters_s temp_parameters; + uint16_t message_id = 0; + + /* Check parameters */ + if (handle == NULL) { + return 0; + } + + if (!sn_nsdl_is_ep_registered(handle)){ + return 0; + } + + memset(&temp_parameters, 0, sizeof(sn_nsdl_ep_parameters_s)); + + temp_parameters.lifetime_len = lt_len; + temp_parameters.lifetime_ptr = lt_ptr; + + /*** Build endpoint register update message ***/ + + /* Allocate memory for header struct */ + register_message_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_hdr_s)); + if (register_message_ptr == NULL) { + return 0; + } + + memset(register_message_ptr, 0, sizeof(sn_coap_hdr_s)); + + /* Fill message fields -> confirmable post to specified NSP path */ + register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST; + + if(handle->ep_information_ptr->location_ptr) { + register_message_ptr->uri_path_len = handle->ep_information_ptr->location_len; /* = Only location set by Device Server*/ + + register_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(register_message_ptr->uri_path_len); + if (!register_message_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + + temp_ptr = register_message_ptr->uri_path_ptr; + + /* location */ + memcpy(temp_ptr, handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len); + } else { + register_message_ptr->uri_path_len = sizeof(resource_path_ptr) + handle->ep_information_ptr->domain_name_len + handle->ep_information_ptr->endpoint_name_len + 2; /* = rd/domain/endpoint */ + + register_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(register_message_ptr->uri_path_len); + if (!register_message_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + + temp_ptr = register_message_ptr->uri_path_ptr; + + /* rd/ */ + memcpy(temp_ptr, resource_path_ptr, sizeof(resource_path_ptr)); + temp_ptr += sizeof(resource_path_ptr); + *temp_ptr++ = '/'; + + /* rd/DOMAIN/ */ + memcpy(temp_ptr, handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len); + temp_ptr += handle->ep_information_ptr->domain_name_len; + *temp_ptr++ = '/'; + + /* rd/domain/ENDPOINT */ + memcpy(temp_ptr, handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len); + } + + /* Allocate memory for the extended options list */ + register_message_ptr->options_list_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_options_list_s)); + if (register_message_ptr->options_list_ptr == NULL) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + + memset(register_message_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + /* Fill Uri-query options */ + sn_nsdl_fill_uri_query_options(handle, &temp_parameters, register_message_ptr, SN_NSDL_EP_UPDATE_MESSAGE); + + /* Build payload */ + if (handle->ep_information_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) { + + if (sn_nsdl_build_registration_body(handle, register_message_ptr, 1) == SN_NSDL_FAILURE) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + } + + /* Build and send coap message to NSP */ + message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UPDATE); + + if (register_message_ptr->payload_ptr) { + handle->sn_nsdl_free(register_message_ptr->payload_ptr); + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + + return message_id; +} + +int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len) +{ + if(!handle || !location_ptr || (location_len == 0)) { + return -1; + } + handle->ep_information_ptr->location_ptr = handle->sn_nsdl_alloc(location_len); + memcpy(handle->ep_information_ptr->location_ptr, location_ptr, location_len); + handle->ep_information_ptr->location_len = location_len; + + return 0; +} + +void sn_nsdl_nsp_lost(struct nsdl_s *handle) +{ + /* Check parameters */ + if (handle == NULL) { + return; + } + + handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED; +} + +int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return handle->sn_nsdl_endpoint_registered; +} + +uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, uint8_t content_type) +{ + return sn_nsdl_send_observation_notification_with_uri_path(handle, + token_ptr, + token_len, + payload_ptr, + payload_len, + observe_ptr, + observe_len, + message_type, + content_type, + NULL, + 0); +} + +uint16_t sn_nsdl_send_observation_notification_with_uri_path(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, uint8_t content_type, + uint8_t *uri_path_ptr, uint16_t uri_path_len) +{ + sn_coap_hdr_s *notification_message_ptr; + uint16_t return_msg_id = 0; + + /* Check parameters */ + if (handle == NULL) { + return 0; + } + + /* Allocate and initialize memory for header struct */ + notification_message_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_hdr_s)); + if (notification_message_ptr == NULL) { + return 0; + } + + memset(notification_message_ptr, 0, sizeof(sn_coap_hdr_s)); + + notification_message_ptr->options_list_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_options_list_s)); + if (notification_message_ptr->options_list_ptr == NULL) { + handle->sn_nsdl_free(notification_message_ptr); + return 0; + } + + memset(notification_message_ptr->options_list_ptr , 0, sizeof(sn_coap_options_list_s)); + + /* Fill header */ + notification_message_ptr->msg_type = message_type; + notification_message_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + + /* Fill token */ + notification_message_ptr->token_len = token_len; + notification_message_ptr->token_ptr = token_ptr; + + /* Fill payload */ + notification_message_ptr->payload_len = payload_len; + notification_message_ptr->payload_ptr = payload_ptr; + + /* Fill uri path */ + notification_message_ptr->uri_path_len = uri_path_len; + notification_message_ptr->uri_path_ptr = uri_path_ptr; + + /* Fill observe */ + notification_message_ptr->options_list_ptr->observe_len = observe_len; + notification_message_ptr->options_list_ptr->observe_ptr = observe_ptr; + + /* Fill content type */ + if (content_type) { + notification_message_ptr->content_type_len = 1; + notification_message_ptr->content_type_ptr = &content_type; + } + + /* Send message */ + if (sn_nsdl_send_coap_message(handle, handle->nsp_address_ptr->omalw_address_ptr, notification_message_ptr) == SN_NSDL_FAILURE) { + return_msg_id = 0; + } else { + return_msg_id = notification_message_ptr->msg_id; + } + + /* Free memory */ + notification_message_ptr->uri_path_ptr = NULL; + notification_message_ptr->payload_ptr = NULL; + notification_message_ptr->options_list_ptr->observe_ptr = NULL; + notification_message_ptr->token_ptr = NULL; + notification_message_ptr->content_type_ptr = NULL; + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, notification_message_ptr); + + return return_msg_id; +} + + +/* * * * * * * * * * */ +/* ~ OMA functions ~ */ +/* * * * * * * * * * */ + +uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr) +{ +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + /* Local variables */ + sn_coap_hdr_s bootstrap_coap_header; + uint8_t *uri_query_tmp_ptr; + uint16_t message_id = 0; + + /* Check parameters */ + if (!bootstrap_address_ptr || !bootstrap_endpoint_info_ptr || !endpoint_info_ptr || !handle) { + return 0; + } + + /* Create device object */ + if (sn_nsdl_create_oma_device_object_base(handle, bootstrap_endpoint_info_ptr->device_object, endpoint_info_ptr->binding_and_mode) < 0) { + return 0; + } + + handle->sn_nsdl_oma_bs_done_cb = bootstrap_endpoint_info_ptr->oma_bs_status_cb; + + /* Init CoAP header struct */ + memset(&bootstrap_coap_header, 0, sizeof(sn_coap_hdr_s)); + + bootstrap_coap_header.options_list_ptr = handle->sn_nsdl_alloc(sizeof(sn_coap_options_list_s)); + if (!bootstrap_coap_header.options_list_ptr) { + return 0; + } + + memset(bootstrap_coap_header.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + /* Build bootstrap start message */ + bootstrap_coap_header.msg_code = COAP_MSG_CODE_REQUEST_POST; + bootstrap_coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE; + + bootstrap_coap_header.uri_path_ptr = bs_uri; + bootstrap_coap_header.uri_path_len = sizeof(bs_uri); + + uri_query_tmp_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN); + if (!uri_query_tmp_ptr) { + handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); + return 0; + } + + memcpy(uri_query_tmp_ptr, bs_ep_name, BS_EP_PARAMETER_LEN); + memcpy((uri_query_tmp_ptr + BS_EP_PARAMETER_LEN), endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len); + + bootstrap_coap_header.options_list_ptr->uri_query_len = endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN; + bootstrap_coap_header.options_list_ptr->uri_query_ptr = uri_query_tmp_ptr; + + /* Save bootstrap server address */ + handle->oma_bs_address_len = bootstrap_address_ptr->addr_len; /* Length.. */ + handle->oma_bs_address_ptr = handle->sn_nsdl_alloc(handle->oma_bs_address_len); /* Address.. */ + if (!handle->oma_bs_address_ptr) { + handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); + handle->sn_nsdl_free(uri_query_tmp_ptr); + return 0; + } + memcpy(handle->oma_bs_address_ptr, bootstrap_address_ptr->addr_ptr, handle->oma_bs_address_len); + handle->oma_bs_port = bootstrap_address_ptr->port; /* And port */ + + /* Send message */ + message_id = sn_nsdl_internal_coap_send(handle, &bootstrap_coap_header, bootstrap_address_ptr, SN_NSDL_MSG_UNDEFINED); + + /* Free allocated memory */ + handle->sn_nsdl_free(uri_query_tmp_ptr); + handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); + + return message_id; +#else + return 0; +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + +} + +omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle) +{ +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + sn_nsdl_resource_info_s *resource_ptr = 0;; + omalw_certificate_list_t *certi_list_ptr = 0; + + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + certi_list_ptr = handle->sn_nsdl_alloc(sizeof(omalw_certificate_list_t)); + + if (!certi_list_ptr) { + return NULL; + } + + /* Get private key resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/5"); + if (!resource_ptr) { + handle->sn_nsdl_free(certi_list_ptr); + return NULL; + } + certi_list_ptr->own_private_key_ptr = resource_ptr->resource; + certi_list_ptr->own_private_key_len = resource_ptr->resourcelen; + + /* Get client certificate resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/4"); + if (!resource_ptr) { + handle->sn_nsdl_free(certi_list_ptr); + return NULL; + } + certi_list_ptr->certificate_ptr[0] = resource_ptr->resource; + certi_list_ptr->certificate_len[0] = resource_ptr->resourcelen; + + /* Get root certificate resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/3"); + if (!resource_ptr) { + handle->sn_nsdl_free(certi_list_ptr); + return NULL; + } + certi_list_ptr->certificate_ptr[1] = resource_ptr->resource; + certi_list_ptr->certificate_len[1] = resource_ptr->resourcelen; + + /* return filled list */ + return certi_list_ptr; +#else + return NULL; +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +} + +int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t *certificate_ptr, uint8_t certificate_chain) +{ +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + (void)certificate_chain; + + /* Check pointers */ + if (!certificate_ptr || !handle) { + return SN_NSDL_FAILURE; + } + + sn_nsdl_resource_info_s *resource_ptr = 0;; + + /* Get private key resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/5"); + if (!resource_ptr) { + return SN_NSDL_FAILURE; + } + handle->sn_nsdl_free(resource_ptr->resource); + resource_ptr->resource = certificate_ptr->own_private_key_ptr; + resource_ptr->resourcelen = certificate_ptr->own_private_key_len; + + /* Get client certificate resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/4"); + if (!resource_ptr) { + return SN_NSDL_FAILURE; + } + handle->sn_nsdl_free(resource_ptr->resource); + resource_ptr->resource = certificate_ptr->certificate_ptr[0]; + resource_ptr->resourcelen = certificate_ptr->certificate_len[0]; + + /* Get root certificate resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/3"); + if (!resource_ptr) { + return SN_NSDL_FAILURE; + } + handle->sn_nsdl_free(resource_ptr->resource); + resource_ptr->resource = certificate_ptr->certificate_ptr[1]; + resource_ptr->resourcelen = certificate_ptr->certificate_len[1]; + + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +} + +int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr) +{ +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + sn_nsdl_resource_info_s *resource_temp = 0; + uint8_t path[8] = "3/0/11/0"; + + if (!device_object_ptr || !handle) { + return SN_NSDL_FAILURE; + } + + /* * Error code * */ + + /* Get first error message */ + resource_temp = sn_grs_search_resource(handle->grs, 8, path, SN_GRS_SEARCH_METHOD); + + while (resource_temp) { + if (resource_temp->resource) { + /* If no error code set */ + if (*resource_temp->resource == 0) { + /* Set error code */ + *resource_temp->resource = (uint8_t)device_object_ptr->error_code; + resource_temp->resourcelen = 1; + + sn_nsdl_update_resource(handle, resource_temp); + return SN_NSDL_SUCCESS; + } + break; + } + + if (path[7] == '9') { + return SN_NSDL_FAILURE; + } + + path[7]++; + resource_temp = sn_grs_search_resource(handle->grs, 8, path, SN_GRS_SEARCH_METHOD); + } + + /* Create new resource for this error */ + resource_temp = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_info_s)); + if (!resource_temp) { + return SN_NSDL_FAILURE; + } + + memset(resource_temp, 0, sizeof(sn_nsdl_resource_info_s)); + + resource_temp->access = SN_GRS_GET_ALLOWED; + resource_temp->mode = SN_GRS_DYNAMIC; + + resource_temp->path = path; + resource_temp->pathlen = 8; + + resource_temp->resource = handle->sn_nsdl_alloc(1); + if (!resource_temp->resource) { + handle->sn_nsdl_free(resource_temp); + return SN_NSDL_FAILURE; + } + + *resource_temp->resource = (uint8_t)device_object_ptr->error_code; + resource_temp->resourcelen = 1; + + resource_temp->resource_parameters_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_parameters_s)); + + if (!resource_temp->resource_parameters_ptr) { + handle->sn_nsdl_free(resource_temp->resource); + handle->sn_nsdl_free(resource_temp); + + return SN_NSDL_FAILURE; + } + + memset(resource_temp->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + + sn_nsdl_create_resource(handle, resource_temp); + + handle->sn_nsdl_free(resource_temp->resource); + handle->sn_nsdl_free(resource_temp->resource_parameters_ptr); + handle->sn_nsdl_free(resource_temp); + + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +} + +char *sn_nsdl_get_version(void) +{ +#if defined(YOTTA_MBED_CLIENT_C_VERSION_STRING) + return YOTTA_MBED_CLIENT_C_VERSION_STRING; +#elif defined(VERSION) + return VERSION; +#else + return "0.0.0"; +#endif +} + + +int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet_ptr, uint16_t packet_len, sn_nsdl_addr_s *src_ptr) +{ + sn_coap_hdr_s *coap_packet_ptr = NULL; + sn_coap_hdr_s *coap_response_ptr = NULL; + + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + /* Parse CoAP packet */ + coap_packet_ptr = sn_coap_protocol_parse(handle->grs->coap, src_ptr, packet_len, packet_ptr, (void *)handle); + + /* Check if parsing was successfull */ + if (coap_packet_ptr == (sn_coap_hdr_s *)NULL) { + return SN_NSDL_FAILURE; + } + + /* Check, if coap itself sends response, or block receiving is ongoing... */ + if (coap_packet_ptr->coap_status != COAP_STATUS_OK && coap_packet_ptr->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } + + /* If proxy options added, return not supported */ + if (coap_packet_ptr->options_list_ptr) { + if (coap_packet_ptr->options_list_ptr->proxy_uri_len) { + coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED); + if (coap_response_ptr) { + sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + } + } + + /* * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* If message is response message, call RX callback */ + /* * * * * * * * * * * * * * * * * * * * * * * * * * */ + + if ((coap_packet_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) || (coap_packet_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT)) { + int8_t retval = sn_nsdl_local_rx_function(handle, coap_packet_ptr, src_ptr); + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_nsdl_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return retval; + } +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + /* * If OMA bootstrap message... * */ + if (src_ptr && (handle->oma_bs_address_len == src_ptr->addr_len) && (handle->oma_bs_port == src_ptr->port) && !memcmp(handle->oma_bs_address_ptr, src_ptr->addr_ptr, handle->oma_bs_address_len)) { + /* TLV message. Parse message and check status of the OMA bootstrap */ + /* process. If ok, call cb function and return. Otherwise send error */ + /* and return failure. */ + + if (coap_packet_ptr->content_type_len == 1) { //todo check message type + if (*coap_packet_ptr->content_type_ptr == 99) { + /* TLV parsing failed. Send response to get non-tlv messages */ + if (sn_nsdl_process_oma_tlv(handle, coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len) == SN_NSDL_FAILURE) { + coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE); + if (coap_response_ptr) { + sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + } + /* Success TLV parsing */ + else { + coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_CREATED); + if (coap_response_ptr) { + sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); + + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + sn_nsdl_check_oma_bs_status(handle); + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } + + /* Non - TLV message */ + else if (*coap_packet_ptr->content_type_ptr == 97) { + sn_grs_process_coap(handle, coap_packet_ptr, src_ptr); + + /* Todo: move this copying to sn_nsdl_check_oma_bs_status(), also from TLV parser */ + /* Security mode */ + if (*(coap_packet_ptr->uri_path_ptr + (coap_packet_ptr->uri_path_len - 1)) == '2') { + handle->nsp_address_ptr->omalw_server_security = (omalw_server_security_t)sn_nsdl_atoi(coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + } + + /* NSP address */ + else if (*(coap_packet_ptr->uri_path_ptr + (coap_packet_ptr->uri_path_len - 1)) == '0') { + sn_nsdl_resolve_lwm2m_address(handle, coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + } + + sn_nsdl_check_oma_bs_status(handle); + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + + + return SN_NSDL_SUCCESS; + } +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + + /* * * * * * * * * * * * * * * */ + /* Other messages are for GRS */ + /* * * * * * * * * * * * * * * */ + + return sn_grs_process_coap(handle, coap_packet_ptr, src_ptr); +} + +int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time) +{ + if(!handle || !handle->grs){ + return SN_NSDL_FAILURE; + } + /* Call CoAP execution function */ + return sn_coap_protocol_exec(handle->grs->coap, time); +} + +sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path_ptr) +{ + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + return sn_grs_search_resource(handle->grs, pathlen, path_ptr, SN_GRS_SEARCH_METHOD); +} + + +/** + * \fn static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description) + * + * + * \brief To send NSDL messages. Stores message id?s and message description to catch response from NSP server + * \param *handle Pointer to nsdl-library handle + * \param *coap_header_ptr Pointer to the CoAP message header to be sent + * \param *dst_addr_ptr Pointer to the address structure that contains destination address information + * \param message_description Message description to be stored to list for waiting response + * + * \return message id, 0 if failed + */ +static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description) +{ + uint8_t *coap_message_ptr = NULL; + uint16_t coap_message_len = 0; + + coap_message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_header_ptr, handle->grs->coap->sn_coap_block_data_size); + + if (coap_message_len == 0) { + return 0; + } + + coap_message_ptr = handle->sn_nsdl_alloc(coap_message_len); + if (!coap_message_ptr) { + return 0; + } + + /* Build message */ + if (sn_coap_protocol_build(handle->grs->coap, dst_addr_ptr, coap_message_ptr, coap_header_ptr, (void *)handle) < 0) { + handle->sn_nsdl_free(coap_message_ptr); + return 0; + } + + /* If mesage type is confirmable, save it to list to wait for reply */ + if (coap_header_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { + if (message_description == SN_NSDL_MSG_REGISTER) { + handle->register_msg_id = coap_header_ptr->msg_id; + } + if (message_description == SN_NSDL_MSG_UNREGISTER) { + handle->unregister_msg_id = coap_header_ptr->msg_id; + } + + } + + handle->sn_nsdl_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, coap_message_ptr, coap_message_len, dst_addr_ptr); + handle->sn_nsdl_free(coap_message_ptr); + + return coap_header_ptr->msg_id; +} + +/** + * \fn static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle) + * + * \brief Resolves NSP server address. + * + * \param *handle Pointer to nsdl-library handle + * \note Application must set NSP address with set_nsp_address + */ +static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle) +{ + /* Local variables */ + if (!handle->nsp_address_ptr) { + //allocate only if previously not allocated + handle->nsp_address_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_oma_server_info_t)); + } + + if (handle->nsp_address_ptr) { + handle->nsp_address_ptr->omalw_server_security = SEC_NOT_SET; + handle->nsp_address_ptr->omalw_address_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_addr_s)); + if (handle->nsp_address_ptr->omalw_address_ptr) { + memset(handle->nsp_address_ptr->omalw_address_ptr, 0, sizeof(sn_nsdl_addr_s)); + handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_NONE; + } + } +} + +static int8_t sn_nsdl_create_oma_device_object_base(struct nsdl_s *handle, sn_nsdl_oma_device_t *oma_device_setup_ptr, sn_nsdl_oma_binding_and_mode_t binding_and_mode) +{ +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + sn_nsdl_resource_info_s new_resource; + uint8_t object_path[8] = "3/0/11/0"; + uint8_t resource_temp[3]; + uint8_t x = 0; + + if (!oma_device_setup_ptr) { + return SN_NSDL_FAILURE; + } + + /* * Create resources. * */ + + /* These resources can be created multiple times. */ + memset(&new_resource, 0, sizeof(sn_nsdl_resource_info_s)); + new_resource.resource_parameters_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_parameters_s)); + if (!new_resource.resource_parameters_ptr) { + return SN_NSDL_FAILURE; + } + + memset(new_resource.resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + + /* Create error - resource */ + new_resource.mode = SN_GRS_STATIC; + new_resource.access = SN_GRS_GET_ALLOWED; + + new_resource.path = object_path; + new_resource.pathlen = 8; + + sn_nsdl_itoa(resource_temp, (uint8_t)oma_device_setup_ptr->error_code); + + new_resource.resource = resource_temp; + new_resource.resourcelen = 1; + + if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { + handle->sn_nsdl_free(new_resource.resource_parameters_ptr); + return SN_NSDL_FAILURE; + } + + /* These resources can be only once, during OMA bootstrap.. */ + /* Create supported binding and modes */ + object_path[5] = '6'; + new_resource.path = object_path; + new_resource.pathlen = 6; + + if (binding_and_mode & 0x01) { + resource_temp[x] = 'U'; + x++; + if (binding_and_mode & 0x02) { + resource_temp[x] = 'Q'; + x++; + } + } + if (binding_and_mode & 0x04) { + resource_temp[x] = 'S'; + x++; + if ((binding_and_mode & 0x02) && !(binding_and_mode & 0x01)) { + resource_temp[x] = 'Q'; + x++; + } + } + + new_resource.resourcelen = x; + + if (new_resource.resourcelen) { + new_resource.resource = resource_temp; + } else { + new_resource.resource = 0; + } + + + if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { + handle->sn_nsdl_free(new_resource.resource_parameters_ptr); + return SN_NSDL_FAILURE; + } + + + /* Create dynamic reboot object */ + new_resource.mode = SN_GRS_DYNAMIC; + + new_resource.access = SN_GRS_POST_ALLOWED; + + object_path[4] = '4'; + + new_resource.path = object_path; + new_resource.pathlen = 5; + + new_resource.resourcelen = 0; + new_resource.resource = 0; + + new_resource.sn_grs_dyn_res_callback = oma_device_setup_ptr->sn_oma_device_boot_callback; + + if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { + handle->sn_nsdl_free(new_resource.resource_parameters_ptr); + return SN_NSDL_FAILURE; + } + + handle->sn_nsdl_free(new_resource.resource_parameters_ptr); + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +} + +/** + * \fn int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration) + * + * \brief To build GRS resources to registration message payload + * \param *handle Pointer to nsdl-library handle + * \param *message_ptr Pointer to CoAP message header + * + * \return SN_NSDL_SUCCESS = 0, Failed = -1 + */ +int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration) +{ + /* Local variables */ + uint8_t *temp_ptr; + const sn_nsdl_resource_info_s *resource_temp_ptr; + + + /* Calculate needed memory and allocate */ + message_ptr->payload_len = sn_nsdl_calculate_registration_body_size(handle, updating_registeration); + + /* If no resources to be registered, return SN_NSDL_SUCCESS */ + if (!message_ptr->payload_len) { + return SN_NSDL_SUCCESS; + } + + message_ptr->payload_ptr = handle->sn_nsdl_alloc(message_ptr->payload_len); + if (!message_ptr->payload_ptr) { + return SN_NSDL_FAILURE; + } + + /* Build message */ + temp_ptr = message_ptr->payload_ptr; + + resource_temp_ptr = sn_grs_get_first_resource(handle->grs); + + /* Loop trough all resources */ + while (resource_temp_ptr) { + /* if resource needs to be registered */ + if (resource_temp_ptr->resource_parameters_ptr && resource_temp_ptr->publish_uri) { + if (updating_registeration && resource_temp_ptr->resource_parameters_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) { + resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); + continue; + } else { + resource_temp_ptr->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERED; + } + + /* If not first resource, add '.' to separator */ + if (temp_ptr != message_ptr->payload_ptr) { + *temp_ptr++ = ','; + } + + *temp_ptr++ = '<'; + *temp_ptr++ = '/'; + memcpy(temp_ptr, resource_temp_ptr->path, resource_temp_ptr->pathlen); + temp_ptr += resource_temp_ptr->pathlen; + *temp_ptr++ = '>'; + + /* Resource attributes */ + if (resource_temp_ptr->resource_parameters_ptr->resource_type_len) { + *temp_ptr++ = ';'; + memcpy(temp_ptr, resource_type_parameter, RT_PARAMETER_LEN); + temp_ptr += RT_PARAMETER_LEN; + *temp_ptr++ = '"'; + memcpy(temp_ptr, resource_temp_ptr->resource_parameters_ptr->resource_type_ptr, resource_temp_ptr->resource_parameters_ptr->resource_type_len); + temp_ptr += resource_temp_ptr->resource_parameters_ptr->resource_type_len; + *temp_ptr++ = '"'; + } + + if (resource_temp_ptr->resource_parameters_ptr->interface_description_len) { + *temp_ptr++ = ';'; + memcpy(temp_ptr, if_description_parameter, IF_PARAMETER_LEN); + temp_ptr += IF_PARAMETER_LEN; + *temp_ptr++ = '"'; + memcpy(temp_ptr, resource_temp_ptr->resource_parameters_ptr->interface_description_ptr, resource_temp_ptr->resource_parameters_ptr->interface_description_len); + temp_ptr += resource_temp_ptr->resource_parameters_ptr->interface_description_len; + *temp_ptr++ = '"'; + } + + if (resource_temp_ptr->resource_parameters_ptr->coap_content_type != 0) { + *temp_ptr++ = ';'; + memcpy(temp_ptr, coap_con_type_parameter, COAP_CON_PARAMETER_LEN); + temp_ptr += COAP_CON_PARAMETER_LEN; + *temp_ptr++ = '"'; + temp_ptr = sn_nsdl_itoa(temp_ptr, resource_temp_ptr->resource_parameters_ptr->coap_content_type); + *temp_ptr++ = '"'; + } + + /* ;obs */ + // This needs to be re-visited and may be need an API for maganging obs value for different server implementation +#ifndef YOTTA_CFG_DISABLE_OBS_FEATURE + if (resource_temp_ptr->resource_parameters_ptr->observable) { + *temp_ptr++ = ';'; + memcpy(temp_ptr, obs_parameter, OBS_PARAMETER_LEN); + temp_ptr += OBS_PARAMETER_LEN; + } +#endif + /* ;aobs;id= */ + /* todo: aosb not supported ATM */ + /* + if((resource_temp_ptr->resource_parameters_ptr->auto_obs_len > 0 && resource_temp_ptr->resource_parameters_ptr->auto_obs_len <= 8) && + resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr) + { + uint8_t i = 0; + + *temp_ptr++ = ';'; + memcpy(temp_ptr, aobs_parameter, AOBS_PARAMETER_LEN); + temp_ptr += AOBS_PARAMETER_LEN; + + while(i < resource_temp_ptr->resource_parameters_ptr->auto_obs_len) + { + temp_ptr = sn_nsdl_itoa(temp_ptr, *(resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr + i)); + i++; + } + } + */ + + } + + resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); + } + + return SN_NSDL_SUCCESS; +} + +/** + * \fn static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration) + * + * + * \brief Calculates registration message payload size + * \param *handle Pointer to nsdl-library handle + * \param *grs_resources_list_ptr Pointer to list of GRS resources + * + * \return Needed payload size + */ +static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration) +{ + /* Local variables */ + uint16_t return_value = 0; + const sn_nsdl_resource_info_s *resource_temp_ptr; + + /* check pointer */ + + resource_temp_ptr = sn_grs_get_first_resource(handle->grs); + + while (resource_temp_ptr) { + if (resource_temp_ptr->resource_parameters_ptr && resource_temp_ptr->publish_uri) { + if (updating_registeration && resource_temp_ptr->resource_parameters_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) { + resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); + continue; + } + + /* If not first resource, then '.' will be added */ + if (return_value) { + return_value++; + } + + /* Count length for the resource path </path> */ + return_value += (3 + resource_temp_ptr->pathlen); + + /* Count lengths of the attributes */ + + /* Resource type parameter */ + if (resource_temp_ptr->resource_parameters_ptr->resource_type_len) { + /* ;rt="restype" */ + return_value += (6 + resource_temp_ptr->resource_parameters_ptr->resource_type_len); + } + + /* Interface description parameter */ + if (resource_temp_ptr->resource_parameters_ptr->interface_description_len) { + /* ;if="iftype" */ + return_value += (6 + resource_temp_ptr->resource_parameters_ptr->interface_description_len); + } + + if (resource_temp_ptr->resource_parameters_ptr->coap_content_type != 0) { + /* ;if="content" */ + return_value += 6; // all but not content + return_value += sn_nsdl_itoa_len(resource_temp_ptr->resource_parameters_ptr->coap_content_type); + } +#ifndef YOTTA_CFG_DISABLE_OBS_FEATURE + // This needs to be re-visited and may be need an API for maganging obs value for different server implementation + if (resource_temp_ptr->resource_parameters_ptr->observable) { + return_value += 4; // ;obs + } +#endif + /*todo: aobs not supported ATM */ + /* + if((resource_temp_ptr->resource_parameters_ptr->auto_obs_len > 0 && resource_temp_ptr->resource_parameters_ptr->auto_obs_len <= 8) && + resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr) + { + uint8_t i = resource_temp_ptr->resource_parameters_ptr->auto_obs_len; + // ;aobs;id= + return_value += 9; + while(i--) + { + return_value += sn_nsdl_itoa_len(*(resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr + i)); + } + } + */ + + } + + resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); + + } + + return return_value; +} + +/** + * \fn static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type) + * + * + * \brief Calculates needed uri query option length + * + * \param *endpoint_info_ptr Pointer to endpoint info structure + * \param msg_type Message type + * + * \return number of parameters in uri query + */ +static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type) +{ + uint8_t return_value = 0; + uint8_t number_of_parameters = 0; + + + if ((endpoint_info_ptr->endpoint_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && endpoint_info_ptr->endpoint_name_ptr != 0) { + return_value += endpoint_info_ptr->endpoint_name_len; + return_value += EP_NAME_PARAMETERS_LEN; //ep= + number_of_parameters++; + } + + if ((endpoint_info_ptr->type_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->type_ptr != 0)) { + return_value += endpoint_info_ptr->type_len; + return_value += ET_PARAMETER_LEN; //et= + number_of_parameters++; + } + + if ((endpoint_info_ptr->lifetime_len != 0) && (endpoint_info_ptr->lifetime_ptr != 0)) { + return_value += endpoint_info_ptr->lifetime_len; + return_value += LT_PARAMETER_LEN; //lt= + number_of_parameters++; + } + + if ((endpoint_info_ptr->domain_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->domain_name_ptr != 0)) { + return_value += endpoint_info_ptr->domain_name_len; + return_value += DOMAIN_PARAMETER_LEN; //d= + number_of_parameters++; + } + + if (((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01)) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + return_value += BS_QUEUE_MODE_PARAMATER_LEN; + + if (endpoint_info_ptr->binding_and_mode & 0x01) { + return_value++; + } + if (endpoint_info_ptr->binding_and_mode & 0x04) { + return_value++; + } + if ((endpoint_info_ptr->binding_and_mode & 0x02) && ((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01))) { + return_value++; + } + + number_of_parameters++; + } + + if (number_of_parameters != 0) { + return_value += (number_of_parameters - 1); + } + + return return_value; +} + +/** + * \fn static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type) + * + * + * \brief Fills uri-query options to message header struct + * \param *handle Pointer to nsdl-library handle + * \param *parameter_ptr Pointer to endpoint parameters struct + * \param *source_msg_ptr Pointer to CoAP header struct + * \param msg_type Message type + * + * \return SN_NSDL_SUCCESS = 0, Failed = -1 + */ +static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type) +{ + uint8_t *temp_ptr = NULL; + if( !validateParameters(parameter_ptr) ){ + return SN_NSDL_FAILURE; + } + source_msg_ptr->options_list_ptr->uri_query_len = sn_nsdl_calculate_uri_query_option_len(parameter_ptr, msg_type); + if (source_msg_ptr->options_list_ptr->uri_query_len == 0) { + return 0; + } + + source_msg_ptr->options_list_ptr->uri_query_ptr = handle->sn_nsdl_alloc(source_msg_ptr->options_list_ptr->uri_query_len); + + if (source_msg_ptr->options_list_ptr->uri_query_ptr == NULL) { + return SN_NSDL_FAILURE; + } + memset(source_msg_ptr->options_list_ptr->uri_query_ptr,0,source_msg_ptr->options_list_ptr->uri_query_len); + + temp_ptr = source_msg_ptr->options_list_ptr->uri_query_ptr; + + /******************************************************/ + /* If endpoint name is configured, fill needed fields */ + /******************************************************/ + + if ((parameter_ptr->endpoint_name_len != 0) && (parameter_ptr->endpoint_name_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + /* fill endpoint name, first ?ep=, then endpoint name */ + memcpy(temp_ptr, ep_name_parameter_string, sizeof(ep_name_parameter_string)); + temp_ptr += EP_NAME_PARAMETERS_LEN; + memcpy(temp_ptr, parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len); + temp_ptr += parameter_ptr->endpoint_name_len; + } + + /******************************************************/ + /* If endpoint type is configured, fill needed fields */ + /******************************************************/ + + if ((parameter_ptr->type_len != 0) && (parameter_ptr->type_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { + *temp_ptr++ = '&'; + } + + memcpy(temp_ptr, et_parameter, sizeof(et_parameter)); + temp_ptr += ET_PARAMETER_LEN; + memcpy(temp_ptr, parameter_ptr->type_ptr, parameter_ptr->type_len); + temp_ptr += parameter_ptr->type_len; + } + + + /******************************************************/ + /* If lifetime is configured, fill needed fields */ + /******************************************************/ + + if ((parameter_ptr->lifetime_len != 0) && (parameter_ptr->lifetime_ptr != 0)) { + if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { + *temp_ptr++ = '&'; + } + + memcpy(temp_ptr, ep_lifetime_parameter, sizeof(ep_lifetime_parameter)); + temp_ptr += LT_PARAMETER_LEN; + memcpy(temp_ptr, parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len); + temp_ptr += parameter_ptr->lifetime_len; + } + + /******************************************************/ + /* If domain is configured, fill needed fields */ + /******************************************************/ + + if ((parameter_ptr->domain_name_len != 0) && (parameter_ptr->domain_name_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { + *temp_ptr++ = '&'; + } + + memcpy(temp_ptr, ep_domain_parameter, sizeof(ep_domain_parameter)); + temp_ptr += DOMAIN_PARAMETER_LEN; + memcpy(temp_ptr, parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len); + temp_ptr += parameter_ptr->domain_name_len; + } + + /******************************************************/ + /* If queue-mode is configured, fill needed fields */ + /******************************************************/ + + if (((parameter_ptr->binding_and_mode & 0x01) || (parameter_ptr->binding_and_mode & 0x04)) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { + *temp_ptr++ = '&'; + } + + memcpy(temp_ptr, bs_queue_mode, sizeof(bs_queue_mode)); + temp_ptr += BS_QUEUE_MODE_PARAMATER_LEN; + + if (parameter_ptr->binding_and_mode & 0x01) { + *temp_ptr++ = 'U'; + if (parameter_ptr->binding_and_mode & 0x02) { + *temp_ptr++ = 'Q'; + } + } + + if (parameter_ptr->binding_and_mode & 0x04) { + *temp_ptr++ = 'S'; + if ((parameter_ptr->binding_and_mode & 0x02) && !(parameter_ptr->binding_and_mode & 0x01)) { + *temp_ptr++ = 'Q'; + } + } + } + + return SN_NSDL_SUCCESS; +} + +static bool validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr) +{ + if( !validate( parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len, '&' ) ){ + return false; + } + + if( !validate( parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len, '&' ) ){ + return false; + } + + if( !validate( parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len, '&' ) ){ + return false; + } + + if( !validate( parameter_ptr->type_ptr, parameter_ptr->type_len, '&' ) ){ + return false; + } + return true; +} + +static bool validate(uint8_t* ptr, uint32_t len, char illegalChar) +{ + if( ptr ){ + for( uint32_t i=0; i < len; i++ ){ + if( ptr[i] == illegalChar ){ + return false; + } + } + } + return true; +} + +/** + * \fn static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr) + * + * \brief If received message is reply for the message that NSDL has been sent, it is processed here. Else, packet will be sent to application. + * \param *handle Pointer to nsdl-library handle + * \param *coap_packet_ptr Pointer to received CoAP packet + * \param *address_ptr Pointer to source address struct + * + * \return SN_NSDL_SUCCESS = 0, Failed = -1 + */ +static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr) +{ + if ((coap_packet_ptr == 0) || (address_ptr == 0)) { + return -1; + } + + if (coap_packet_ptr->msg_id == handle->register_msg_id) { + if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CREATED) { + handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_IS_REGISTERED; + sn_grs_mark_resources_as_registered(handle); + if (sn_nsdl_resolve_ep_information(handle, coap_packet_ptr) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + + handle->register_msg_id = 0; + } + } + + if (coap_packet_ptr->msg_id == handle->unregister_msg_id) { + if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_DELETED) { + if (handle->ep_information_ptr->endpoint_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); + handle->ep_information_ptr->endpoint_name_ptr = 0; + handle->ep_information_ptr->endpoint_name_len = 0; + } + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = 0; + handle->ep_information_ptr->domain_name_len = 0; + } + + handle->unregister_msg_id = 0; + } + } + + /* No messages to wait for, or message was not response to our request */ + return handle->sn_nsdl_rx_callback(handle, coap_packet_ptr, address_ptr); +} + +/** + * \fn static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr) + * + * + * \brief Resolves endpoint information from received CoAP message + * \param *handle Pointer to nsdl-library handle + * \param *coap_packet_ptr Pointer to received CoAP message + * + * \return SN_NSDL_SUCCESS = 0, Failed = -1 + */ +static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr) +{ + uint8_t *temp_ptr; + uint8_t parameter_count = 0; + uint16_t parameter_len = 0; + + if (!coap_packet_ptr || !coap_packet_ptr->options_list_ptr || + !coap_packet_ptr->options_list_ptr->location_path_ptr) { + return SN_NSDL_FAILURE; + } + + temp_ptr = coap_packet_ptr->options_list_ptr->location_path_ptr; + + while (temp_ptr <= (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) { + + if ((temp_ptr == (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) || (*temp_ptr == '/')) { + + parameter_count++; + if (parameter_count == 2) { + if (!handle->ep_information_ptr->domain_name_ptr) { + handle->ep_information_ptr->domain_name_len = parameter_len - 1; + handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->domain_name_len); + if (!handle->ep_information_ptr->domain_name_ptr) { + return SN_NSDL_FAILURE; + } + memcpy(handle->ep_information_ptr->domain_name_ptr, temp_ptr - handle->ep_information_ptr->domain_name_len, handle->ep_information_ptr->domain_name_len); + } + + } + if (parameter_count == 3) { + if (!handle->ep_information_ptr->endpoint_name_ptr) { + handle->ep_information_ptr->endpoint_name_len = parameter_len - 1; + handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->endpoint_name_len); + if (!handle->ep_information_ptr->endpoint_name_ptr) { + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = NULL; + handle->ep_information_ptr->domain_name_len = 0; + } + + return SN_NSDL_FAILURE; + + } + memcpy(handle->ep_information_ptr->endpoint_name_ptr, temp_ptr - handle->ep_information_ptr->endpoint_name_len, handle->ep_information_ptr->endpoint_name_len); + } + } + parameter_len = 0; + } + parameter_len++; + temp_ptr++; + } + + + return SN_NSDL_SUCCESS; +} + +int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type) +{ + + /* Check parameters and source pointers */ + if (!handle || !handle->nsp_address_ptr || !handle->nsp_address_ptr->omalw_address_ptr || !NSP_address) { + return SN_NSDL_FAILURE; + } + + handle->nsp_address_ptr->omalw_address_ptr->type = address_type; + handle->nsp_address_ptr->omalw_server_security = SEC_NOT_SET; + + if (address_type == SN_NSDL_ADDRESS_TYPE_IPV4) { + if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + } + + handle->nsp_address_ptr->omalw_address_ptr->addr_len = 4; + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(handle->nsp_address_ptr->omalw_address_ptr->addr_len); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, NSP_address, handle->nsp_address_ptr->omalw_address_ptr->addr_len); + handle->nsp_address_ptr->omalw_address_ptr->port = port; + } + + else if (address_type == SN_NSDL_ADDRESS_TYPE_IPV6) { + if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + } + + handle->nsp_address_ptr->omalw_address_ptr->addr_len = 16; + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(handle->nsp_address_ptr->omalw_address_ptr->addr_len); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, NSP_address, handle->nsp_address_ptr->omalw_address_ptr->addr_len); + handle->nsp_address_ptr->omalw_address_ptr->port = port; + } + return SN_NSDL_SUCCESS; +} + + +static uint8_t sn_nsdl_itoa_len(uint8_t value) +{ + uint8_t i = 0; + + do { + i++; + } while ((value /= 10) > 0); + + return i; +} + +static uint8_t *sn_nsdl_itoa(uint8_t *ptr, uint8_t value) +{ + + uint8_t start = 0; + uint8_t end = 0; + uint8_t i; + + i = 0; + + /* ITOA */ + do { + ptr[i++] = (value % 10) + '0'; + } while ((value /= 10) > 0); + + end = i - 1; + + /* reverse (part of ITOA) */ + while (start < end) { + uint8_t chr; + + chr = ptr[start]; + ptr[start] = ptr[end]; + ptr[end] = chr; + + start++; + end--; + + } + return (ptr + i); +} + +static int32_t sn_nsdl_atoi(uint8_t *ptr, uint8_t len) +{ + + int32_t result = 0; + + while (len--) { + + if (result) { + result *= 10; + } + + if (*ptr >= '0' && *ptr <= '9') { + result += *ptr - '0'; + } else{ + return -1; + } + + ptr++; + + } + return result; + +} + +static uint32_t sn_nsdl_ahextoi(uint8_t *ptr, uint8_t len) +{ + + uint32_t result = 0; + + while (len--) { + + if (result) { + result *= 16; + } + + if (*ptr >= '0' && *ptr <= '9') { + result += *ptr - '0'; + } else if (*ptr >= 'a' && *ptr <= 'f') { + result += *ptr - 87; + } else if (*ptr >= 'A' && *ptr <= 'F') { + result += *ptr - 55; + } + + ptr++; + + } + return result; + +} + +static int8_t sn_nsdl_resolve_lwm2m_address(struct nsdl_s *handle, uint8_t *uri, uint16_t uri_len) +{ +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + if( uri_len < 2 ){ + return SN_NSDL_FAILURE; + } + uint8_t *temp_ptr = uri+2; + uint16_t i = 0; + uint8_t char_cnt = 0; + + /* jump over coap// */ + while ((*(temp_ptr - 2) != '/') || (*(temp_ptr - 1) != '/')) { + temp_ptr++; + if (temp_ptr - uri >= uri_len) { + return SN_NSDL_FAILURE; + } + } + + /* Resolve address type */ + /* Count semicolons */ + + int8_t endPos = -1; + + while (i < (uri_len - (temp_ptr - uri))) { + if (*(temp_ptr + i) == ':') { + char_cnt++; + }else if(*(temp_ptr + i) == ']'){ + endPos = i; + } + i++; + } + + uint8_t *temp_pos = temp_ptr; //store starting point in case of IPv4 parsing fails + + /* IPv6 */ + if (char_cnt > 2) { + i = 0; + + if( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ){ + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + } + + handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_IPV6; + handle->nsp_address_ptr->omalw_address_ptr->addr_len = 16; + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(16); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + memset(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, 0, 16); + if (*temp_ptr == '[' && endPos > 0 && (temp_ptr - uri) + endPos < uri_len && *(temp_ptr + endPos + 1) == ':') { + temp_ptr++; + endPos--; + }else{ + /* return failure, because port is mandatory */ + return SN_NSDL_FAILURE; + } + + int8_t loopbackPos = -1; + if( char_cnt != 8 ){ + i = 0; + char_cnt -= 1; + while( i+1 < endPos ){ + if(*(temp_ptr + i) == ':' && *(temp_ptr + i+1) == ':') { + loopbackPos = i; + break; + } + i++; + } + } + i = 0; + + uint8_t numberOfZeros = 8 - char_cnt; + if(loopbackPos == 0){ + numberOfZeros++; + } + + if(loopbackPos == endPos-2){ + numberOfZeros++; + } + + /* Resolve address */ + int8_t pos = loopbackPos == 0?0:-1; + while (i < 16 && ((temp_ptr - uri) + char_cnt) < uri_len) { + char_cnt = 0; + if( pos == loopbackPos ){ + for( int k=0; k < numberOfZeros; k++ ){ + i+=2; + } + pos+=2; + temp_ptr += 2; + if( numberOfZeros == 8 ){ + temp_ptr++; + } + continue; + } + while (*(temp_ptr + char_cnt) != ':' && *(temp_ptr + char_cnt) != ']') { + char_cnt++; + pos++; + } + pos++; + + if (char_cnt <= 2) { + i++; + } + + while (char_cnt) { + if (char_cnt % 2) { + *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + i) = (uint8_t)sn_nsdl_ahextoi(temp_ptr, 1); + temp_ptr++; + char_cnt --; + } else { + *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + i) = (uint8_t)sn_nsdl_ahextoi(temp_ptr, 2); + temp_ptr += 2; + char_cnt -= 2; + } + i++; + } + temp_ptr++; + } + + temp_ptr++; + uint16_t handled = (temp_ptr - uri); + if( handled < uri_len ){ + if( *(temp_ptr + (uri_len - (temp_ptr - uri) -1)) == '/' ){ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); + }else{ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); + } + } + } + /* IPv4 or Hostname */ + else if (char_cnt == 1) { + char_cnt = 0; + i = 0; + + if( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ){ + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + } + + /* Check address type */ + while (i < (uri_len - (temp_ptr - uri))) { + if (*(temp_ptr + i) == '.') { + char_cnt++; + } + i++; + } + + bool parseOk = true; + + /* Try IPv4 first */ + if (char_cnt == 3) { + i = 0; + char_cnt = 0; + + handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_IPV4; + handle->nsp_address_ptr->omalw_address_ptr->addr_len = 4; + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(4); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + while (parseOk && ((temp_ptr - uri) < uri_len) && *(temp_ptr - 1) != ':') { + i++; + + if (*(temp_ptr + i) == ':' || *(temp_ptr + i) == '.') { + int8_t value = (int8_t)sn_nsdl_atoi(temp_ptr, i); + if( value == -1 ){ + parseOk = false; + char_cnt = 3; + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + break; + } + *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + char_cnt) = value; + temp_ptr = temp_ptr + i + 1; + char_cnt++; + i = 0; + } + } + if(parseOk) { + if( *(temp_ptr + (uri_len - (temp_ptr - uri) -1)) == '/' ){ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); + }else{ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); + } + } + }else{ + parseOk = false; + } + + /* Then try Hostname */ + if(!parseOk) { + i = 0; + temp_ptr = temp_pos; + + handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_HOSTNAME; + + /* Resolve address length */ + if (uri_len > 0xff) { + return SN_NSDL_FAILURE; + } + + while (((temp_ptr - uri) + i < uri_len) && *(temp_ptr + i) != ':') { + i++; + } + + handle->nsp_address_ptr->omalw_address_ptr->addr_len = i; + + /* Copy address */ + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(i); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, temp_ptr, i); + + temp_ptr += i + 1; + + /* Set port */ + if( *(temp_ptr + (uri_len - (temp_ptr - uri) - 1)) == '/' ){ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); + }else{ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); + } + } + } else { + return SN_NSDL_FAILURE; + } + + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +} + + +int8_t sn_nsdl_process_oma_tlv(struct nsdl_s *handle, uint8_t *data_ptr, uint16_t data_len) +{ +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + uint8_t *temp_ptr = data_ptr; + uint8_t type = 0; + uint16_t identifier = 0; + uint32_t length = 0; + uint8_t path_temp[5] = "0/0/x"; + + sn_nsdl_resource_info_s resource_temp = { + .resource_parameters_ptr = 0, + .mode = SN_GRS_STATIC, + .pathlen = 5, + .path = path_temp, + .resourcelen = 0, + .resource = 0, + .access = (sn_grs_resource_acl_e) 0x0f, /* All allowed */ + .sn_grs_dyn_res_callback = 0 + }; + + while ((temp_ptr - data_ptr) < data_len) { + /* Save type for future use */ + type = *temp_ptr++; + + /* * Bit 5: Indicates the Length of the Identifier. * */ + if (type & 0x20) { + /* 1=The Identifier field of this TLV is 16 bits long */ + identifier = (uint8_t)(*temp_ptr++) << 8; + identifier += (uint8_t) * temp_ptr++; + } else { + /* 0=The Identifier field of this TLV is 8 bits long */ + identifier = (uint8_t) * temp_ptr++; + } + + /* * Bit 4-3: Indicates the type of Length. * */ + if ((type & 0x18) == 0) { + /* 00 = No length field, the value immediately follows the Identifier field in is of the length indicated by Bits 2-0 of this field */ + length = (type & 0x07); + } else if ((type & 0x18) == 0x08) { + /* 01 = The Length field is 8-bits and Bits 2-0 MUST be ignored */ + length = *temp_ptr++; + } else if ((type & 0x18) == 0x10) { + /* 10 = The Length field is 16-bits and Bits 2-0 MUST be ignored */ + length = (uint8_t)(*temp_ptr++) << 8; + length += (uint8_t) * temp_ptr++; + } else if ((type & 0x18) == 0x18) { + /* 11 = The Length field is 24-bits and Bits 2-0 MUST be ignored */ + length = (uint8_t)(*temp_ptr++); + length = length << 16; + length += (uint8_t)(*temp_ptr++) << 8; + length += (uint8_t) * temp_ptr++; + } + + /* * Bits 7-6: Indicates the type of Identifier. * */ + if ((type & 0xC0) == 0x00) { + /* 00 = Object Instance in which case the Value contains one or more Resource TLVs */ + /* Not implemented, return failure */ + } else if ((type & 0xC0) == 0xC0) { + /* 11 = Resource with Value */ + switch (identifier) { + case 0: + /* Resolve LWM2M Server URI */ + sn_nsdl_resolve_lwm2m_address(handle, temp_ptr, length); + path_temp[4] = '0'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + break; + case 2: + /* Resolve security Mode */ + handle->nsp_address_ptr->omalw_server_security = (omalw_server_security_t)sn_nsdl_atoi(temp_ptr, length); + path_temp[4] = '2'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + + break; + case 3: + /* Public Key or Identity */ + path_temp[4] = '3'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + break; + case 4: + /* Server Public Key or Identity */ + ; + path_temp[4] = '4'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + + break; + case 5: + /* Secret Key */ + path_temp[4] = '5'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + break; + default: + break; + } + + /* Move pointer to next TLV message */ + temp_ptr += length; + } + } + + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +} + +static void sn_nsdl_check_oma_bs_status(struct nsdl_s *handle) +{ +#ifndef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE + /* Check OMA BS status */ + if ((handle->nsp_address_ptr->omalw_server_security == PSK) && (handle->nsp_address_ptr->omalw_address_ptr->type != SN_NSDL_ADDRESS_TYPE_NONE)) { + /* call cb that oma bootstrap is done */ + if(handle->sn_nsdl_oma_bs_done_cb != 0){ + handle->sn_nsdl_oma_bs_done_cb(handle->nsp_address_ptr); + } + } else if ((handle->nsp_address_ptr->omalw_server_security == CERTIFICATE) && (handle->nsp_address_ptr->omalw_address_ptr->type != SN_NSDL_ADDRESS_TYPE_NONE) && + ((sn_nsdl_get_resource(handle, 5, (void *)"0/0/5") != 0) && + (sn_nsdl_get_resource(handle, 5, (void *)"0/0/4") != 0) && + (sn_nsdl_get_resource(handle, 5, (void *)"0/0/3") != 0))) { + if( handle->sn_nsdl_oma_bs_done_cb ){ + handle->sn_nsdl_oma_bs_done_cb(handle->nsp_address_ptr); + } + } +#endif //YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +} + +static int8_t set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr) +{ + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = 0; + handle->ep_information_ptr->domain_name_len = 0; + } + + if (handle->ep_information_ptr->endpoint_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); + handle->ep_information_ptr->endpoint_name_ptr = 0; + handle->ep_information_ptr->endpoint_name_len = 0; + } + + if (endpoint_info_ptr->domain_name_ptr && endpoint_info_ptr->domain_name_len) { + handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->domain_name_len); + + if (!handle->ep_information_ptr->domain_name_ptr) { + return -1; + } + + memcpy(handle->ep_information_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_len); + handle->ep_information_ptr->domain_name_len = endpoint_info_ptr->domain_name_len; + } + + if (endpoint_info_ptr->endpoint_name_ptr && endpoint_info_ptr->endpoint_name_len) { + handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len); + + if (!handle->ep_information_ptr->endpoint_name_ptr) { + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = 0; + handle->ep_information_ptr->domain_name_len = 0; + } + return -1; + } + + memcpy(handle->ep_information_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len); + handle->ep_information_ptr->endpoint_name_len = endpoint_info_ptr->endpoint_name_len; + } + + handle->ep_information_ptr->binding_and_mode = endpoint_info_ptr->binding_and_mode; + handle->ep_information_ptr->ds_register_mode = endpoint_info_ptr->ds_register_mode; + + handle->ep_information_ptr->location_ptr = 0; + handle->ep_information_ptr->location_len = 0; + + return 0; +} + +/* Wrapper */ +sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) +{ + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + return sn_grs_list_resource(handle->grs, pathlen, path); +} + +void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list) +{ + /* Check parameters */ + if (handle == NULL) { + return; + } + + sn_grs_free_resource_list(handle->grs, list); +} + +extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return sn_grs_update_resource(handle->grs, res); +} + +extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return sn_grs_send_coap_message(handle, address_ptr, coap_hdr_ptr); +} + +extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return sn_grs_create_resource(handle->grs, res); +} + +extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return sn_grs_delete_resource(handle->grs, pathlen, path); +} +extern const sn_nsdl_resource_info_s *sn_nsdl_get_first_resource(struct nsdl_s *handle) +{ + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + return sn_grs_get_first_resource(handle->grs); +} +extern const sn_nsdl_resource_info_s *sn_nsdl_get_next_resource(struct nsdl_s *handle, const sn_nsdl_resource_info_s *resource) +{ + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + return sn_grs_get_next_resource(handle->grs, resource); +} + +extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) +{ + if (handle == NULL) { + return NULL; + } + + return sn_coap_build_response(handle->grs->coap, coap_packet_ptr, msg_code); +} + +extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) +{ + if (handle == NULL) { + return; + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, freed_coap_msg_ptr); +} + +extern int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, + uint8_t resending_count, uint8_t resending_interval) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + return sn_coap_protocol_set_retransmission_parameters(handle->grs->coap, + resending_count,resending_interval); +} + +extern int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle, + uint8_t buffer_size_messages, uint16_t buffer_size_bytes) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + return sn_coap_protocol_set_retransmission_buffer(handle->grs->coap, + buffer_size_messages, buffer_size_bytes); +} + +extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + return sn_coap_protocol_set_block_size(handle->grs->coap, block_size); +} + +extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + return sn_coap_protocol_set_duplicate_buffer_size(handle->grs->coap, message_count); +} +