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.
Dependents: Trenton_Doormat_FRDM-KL25Z_ETH
Revision 1:14a9b0f4b9d6, committed 2014-02-18
- Comitter:
- zdshelby
- Date:
- Tue Feb 18 01:10:07 2014 +0000
- Parent:
- 0:aafd54b05111
- Commit message:
- - Added libnsdl import
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sn_grs.c Tue Feb 18 01:10:07 2014 +0000
@@ -0,0 +1,1468 @@
+/**
+ *
+ * \file sn_grs.c
+ * \brief General resource server for Sensinode NanoService platforms
+ *
+ *
+ *
+ */
+#include "nsdl_types.h"
+#include "sn_linked_list.h"
+#include "sn_nsdl.h"
+
+#if(SN_NSDL_HAVE_HTTPS_CAPABILITY&&SN_NSDL_HAVE_HTTP_CAPABILITY)
+#include "sn_http.h"
+#endif
+
+#if(SN_NSDL_HAVE_COAP_CAPABILITY)
+#include "sn_coap_header.h"
+#include "sn_coap_protocol.h"
+#endif
+
+#include "sn_nsdl_lib.h"
+#include "sn_grs.h"
+
+#include <stdlib.h>
+#include <string.h> // for memcomp
+
+/* Defines */
+#define WELLKNOWN_PATH_LEN 16
+#define WELLKNOWN_PATH (".well-known/core")
+
+/* Local static function prototypes */
+static sn_nsdl_resource_info_s * sn_grs_search_resource (uint16_t pathlen, uint8_t *path, uint8_t search_method);
+static int8_t sn_grs_resource_info_free (sn_nsdl_resource_info_s *resource_ptr);
+static uint8_t * sn_grs_convert_uri (uint16_t *uri_len, uint8_t *uri_ptr);
+static int8_t sn_grs_add_resource_to_list (sn_linked_list_t *list_ptr, sn_nsdl_resource_info_s *resource_ptr);
+#ifdef CC8051_PLAT
+void copy_code_nsdl (uint8_t * ptr, prog_uint8_t * code_ptr, uint16_t len);
+#endif
+static uint8_t sn_grs_compare_code (uint8_t * ptr, prog_uint8_t * code_ptr, uint8_t len);
+
+/* Extern function prototypes */
+extern int8_t sn_nsdl_build_registration_body (sn_coap_hdr_s *message_ptr, uint8_t updating_registeration);
+
+
+/* Local global variables */
+ static sn_linked_list_t *resource_root_list = NULL;
+
+
+/* Local global function pointers */
+static void *(*sn_grs_alloc)(uint16_t);
+static void (*sn_grs_free)(void*);
+static uint8_t (*sn_grs_tx_callback)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *);
+static int8_t (*sn_grs_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *);
+
+/**
+ * \fn int8_t sn_grs_destroy(void)
+ * \brief This function may be used to flush GRS related stuff when a program exits.
+ * @return always 0.
+ */
+ extern int8_t sn_grs_destroy(void)
+{
+ if(resource_root_list)
+ {
+ uint16_t size = sn_linked_list_count_nodes(resource_root_list);
+ uint16_t i = 0;
+ sn_nsdl_resource_info_s*tmp;
+
+ for(i=0;i<size;i++)
+ {
+ tmp = sn_linked_list_get_first_node(resource_root_list);
+
+ if(tmp)
+ {
+ if(tmp->resource_parameters_ptr->resource_type_ptr)
+ {
+ sn_grs_free(tmp->resource_parameters_ptr->resource_type_ptr);
+ tmp->resource_parameters_ptr->resource_type_ptr = 0;
+ }
+
+ if(tmp->resource_parameters_ptr->interface_description_ptr)
+ {
+ sn_grs_free(tmp->resource_parameters_ptr->interface_description_ptr);
+ tmp->resource_parameters_ptr->interface_description_ptr = 0;
+ }
+
+ if(tmp->resource_parameters_ptr)
+ {
+ sn_grs_free(tmp->resource_parameters_ptr);
+ tmp->resource_parameters_ptr = 0;
+ }
+ if(tmp->path)
+ {
+ sn_grs_free(tmp->path);
+ tmp->path = 0;
+ }
+ if(tmp->resource)
+ {
+ sn_grs_free(tmp->resource);
+ tmp->resource = 0;
+ }
+ sn_linked_list_remove_current_node(resource_root_list);
+ sn_grs_free(tmp);
+ tmp = 0;
+ }
+ }
+
+ if(!sn_linked_list_count_nodes(resource_root_list))
+ {
+ sn_linked_list_free(resource_root_list);
+ }
+
+ }
+ return 0;
+}
+
+
+/**
+ * \fn int8_t sn_grs_init (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t,
+ * sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *), sn_nsdl_mem_s *sn_memory)
+ *
+ * \brief GRS library initialize function.
+ *
+ * This function initializes GRS and CoAP libraries.
+ *
+ * \param sn_grs_tx_callback A function pointer to a transmit callback function.
+ * \param *sn_grs_rx_callback_ptr A function pointer to a receiving callback function. If received packet is not for GRS, it will be passed to
+ * upper level (NSDL) to be proceed.
+ * \param sn_memory A pointer to a structure containing the platform specific functions for memory allocation and free.
+ *
+ * \return success = 0, failure = -1
+ *
+*/
+
+extern int8_t sn_grs_init (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t,
+ sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *), sn_nsdl_mem_s *sn_memory)
+{
+ /* If application tries to init GRS more than once.. */
+ if(!resource_root_list)
+ {
+ /* if sn_memory struct is NULL or , return failure */
+ if(!sn_memory)
+ return SN_NSDL_FAILURE;
+
+ if (sn_memory->sn_nsdl_alloc == NULL ||
+ sn_memory->sn_nsdl_free == NULL ||
+ sn_grs_tx_callback_ptr == NULL)
+ {
+ /* There was a null pointer as a parameter */
+ return SN_NSDL_FAILURE;
+ }
+
+ /* Alloc and free - function pointers */
+ sn_grs_alloc = sn_memory->sn_nsdl_alloc;
+ sn_grs_free = sn_memory->sn_nsdl_free;
+
+ /* TX callback function pointer */
+ sn_grs_tx_callback = sn_grs_tx_callback_ptr;
+ sn_grs_rx_callback = sn_grs_rx_callback_ptr;
+
+ /* Initialize linked list */
+ sn_linked_list_init(sn_memory->sn_nsdl_alloc, sn_memory->sn_nsdl_free);
+
+ /* Initialize HTTP protocol library, if implemented to library*/
+#if (SN_NSDL_HAVE_HTTP_CAPABILITY || SN_NSDL_HAVE_HTTPS_CAPABILITY)
+ sn_http_init(sn_memory->sn_nsdl_alloc, sn_memory->sn_grs_free);
+#endif
+
+ /* Initialize CoAP protocol library, if implemented to library */
+
+ /* Initialize list for resources */
+ resource_root_list = sn_linked_list_create();
+ if (!resource_root_list)
+ {
+ return SN_NSDL_FAILURE;
+ }
+
+#if SN_NSDL_HAVE_COAP_CAPABILITY
+ sn_coap_builder_and_parser_init(sn_memory->sn_nsdl_alloc, sn_memory->sn_nsdl_free);
+
+ if(sn_coap_protocol_init(sn_memory->sn_nsdl_alloc, sn_memory->sn_nsdl_free, sn_grs_tx_callback))
+ {
+ sn_linked_list_free(resource_root_list);
+ return SN_NSDL_FAILURE;
+ }
+#endif
+
+ return SN_NSDL_SUCCESS;
+ }
+
+ return SN_NSDL_FAILURE;
+}
+
+/**
+ * \fn extern int8_t sn_grs_exec(uint32_t time)
+ *
+ * \brief CoAP retransmission function.
+ *
+ * Used to give execution time for the GRS (CoAP) library for retransmissions. The GRS library
+ * will call the exec functions of all enabled protocol modules.
+ *
+ * \param time Time in seconds.
+ *
+ * \return 0 = success, -1 = failure
+ *
+*/
+
+extern int8_t sn_grs_exec(uint32_t time)
+{
+#if(SN_NSDL_HAVE_COAP_CAPABILITY)
+ /* Call CoAP execution function */
+ return sn_coap_protocol_exec(time);
+#endif
+ return SN_NSDL_SUCCESS;
+}
+
+/**
+ * \fn extern sn_grs_resource_list_s *sn_grs_list_resource(uint16_t pathlen, uint8_t *path)
+ *
+ * \brief Resource list function
+ *
+ * \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 structure containing the resource listing.\n
+ * NULL failure with an unspecified error
+ */
+
+extern sn_grs_resource_list_s *sn_grs_list_resource(uint16_t pathlen, uint8_t *path)
+{
+ /* Local variables */
+ uint8_t i = 0;
+ sn_grs_resource_list_s *grs_resource_list_ptr = NULL;
+ sn_nsdl_resource_info_s *grs_resource_ptr = NULL;
+
+ /* Allocate memory for the resource list to be filled */
+ grs_resource_list_ptr = (sn_grs_resource_list_s *)sn_grs_alloc(sizeof(sn_grs_resource_list_s));
+ if(!grs_resource_list_ptr)
+ {
+ return (sn_grs_resource_list_s *)NULL;
+ }
+
+ /* Count resources to the resource list struct */
+ grs_resource_list_ptr->res_count = sn_linked_list_count_nodes(resource_root_list);
+
+ /**************************************/
+ /* Fill resource structs to the table */
+ /**************************************/
+
+ /* If resources in list */
+ if(grs_resource_list_ptr->res_count)
+ {
+ /* Allocate memory for resources */
+ grs_resource_list_ptr->res = sn_grs_alloc(grs_resource_list_ptr->res_count*(sizeof(sn_grs_resource_s)));
+ if(!grs_resource_list_ptr->res)
+ {
+ sn_grs_free(grs_resource_list_ptr);
+ return (sn_grs_resource_list_s *)NULL;
+ }
+
+ /* Get first resource */
+ grs_resource_ptr = sn_linked_list_get_first_node(resource_root_list);
+
+ for(i = 0; i < grs_resource_list_ptr->res_count; i++)
+ {
+ /* Copy pathlen to resource list */
+ grs_resource_list_ptr->res[i].pathlen = grs_resource_ptr->pathlen;
+
+ /* Allocate memory for path string */
+ grs_resource_list_ptr->res[i].path = sn_grs_alloc(grs_resource_list_ptr->res[i].pathlen);
+ if(!grs_resource_list_ptr->res[i].path)
+ //todo: free struct
+ return (sn_grs_resource_list_s *)NULL;
+
+ /* Move pathstring to resource list */
+ memmove(grs_resource_list_ptr->res[i].path,grs_resource_ptr->path, grs_resource_ptr->pathlen);
+
+ /* move to next node */
+ grs_resource_ptr = sn_linked_list_get_next_node(resource_root_list);
+ }
+ }
+ return grs_resource_list_ptr;
+}
+
+
+extern sn_nsdl_resource_info_s *sn_grs_get_first_resource(void)
+{
+
+ return sn_linked_list_get_first_node(resource_root_list);
+
+}
+
+
+extern sn_nsdl_resource_info_s *sn_grs_get_next_resource(void)
+{
+
+ return sn_linked_list_get_next_node(resource_root_list);
+
+}
+
+/**
+ * \fn extern sn_grs_resource_info_s *sn_grs_get_resource(uint16_t pathlen, uint8_t *path)
+ *
+ * \brief Resource get function.
+ *
+ * Used to get a resource.
+ *
+ * \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_grs_resource_info_t that contains the resource information\n
+ * NULL failure
+*/
+
+extern sn_nsdl_resource_info_s *sn_grs_get_resource(uint16_t pathlen, uint8_t *path)
+{
+
+ /* Search for resource */
+ return sn_grs_search_resource(pathlen, path, SN_GRS_SEARCH_METHOD);
+
+}
+
+
+
+/**
+ * \fn extern int8_t sn_grs_delete_resource(uint16_t pathlen, uint8_t *path_ptr)
+ *
+ * \brief Resource delete function.
+ *
+ * Used to delete a resource. If resource has a subresources, these all must also be removed.
+ *
+ * \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, -1 = failure (No such resource)
+*/
+
+
+extern int8_t sn_grs_delete_resource(uint16_t pathlen, uint8_t *path_ptr)
+{
+ /* Local variables */
+ sn_nsdl_resource_info_s *resource_temp = NULL;
+
+ /* Search if resource found */
+ resource_temp = sn_grs_search_resource(pathlen, path_ptr, SN_GRS_SEARCH_METHOD);
+
+ /* If not found */
+ if(resource_temp == (sn_nsdl_resource_info_s *)NULL)
+ return SN_NSDL_FAILURE;
+
+ /* If found, delete it and delete also subresources, if there is any */
+ while (resource_temp != (sn_nsdl_resource_info_s *)NULL)
+ {
+ /* Remove from list */
+ resource_temp = (sn_nsdl_resource_info_s *)sn_linked_list_remove_current_node(resource_root_list);
+
+ /* Free */
+ sn_grs_resource_info_free(resource_temp);
+
+ /* Search for subresources */
+ resource_temp = sn_grs_search_resource(pathlen, path_ptr, SN_GRS_DELETE_METHOD);
+ }
+ return SN_NSDL_SUCCESS;
+}
+
+
+
+/**
+ * \fn extern int8_t sn_grs_update_resource(sn_grs_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 *res Pointer to a structure of type sn_grs_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, -1 = failure
+*/
+
+extern int8_t sn_grs_update_resource(sn_nsdl_resource_info_s *res)
+{
+ /* Local variables */
+ sn_nsdl_resource_info_s *resource_temp = NULL;
+
+ /* Search resource */
+ resource_temp = sn_grs_search_resource(res->pathlen, res->path, SN_GRS_SEARCH_METHOD);
+ if(!resource_temp)
+ return SN_NSDL_FAILURE;
+
+ /* If there is payload on resource, free it */
+ if(resource_temp->resource != NULL)
+ {
+ sn_grs_free(resource_temp->resource);
+ resource_temp->resource = 0;
+ }
+ /* Update resource len */
+ resource_temp->resourcelen = res->resourcelen;
+
+ /* If resource len >0, allocate memory and copy payload */
+ if(res->resourcelen)
+ {
+ resource_temp->resource = sn_grs_alloc(res->resourcelen);
+ if(resource_temp->resource == NULL)
+ {
+
+ resource_temp->resourcelen = 0;
+ return SN_NSDL_FAILURE;
+
+ }
+
+ memcpy(resource_temp->resource, res->resource, resource_temp->resourcelen);
+ }
+
+ /* Update access rights and callback address */
+ resource_temp->access = res->access;
+ resource_temp->sn_grs_dyn_res_callback = res->sn_grs_dyn_res_callback;
+
+ /* TODO: resource_parameters_ptr not copied */
+
+ return SN_NSDL_SUCCESS;
+}
+
+
+
+/**
+ * \fn extern int8_t sn_grs_create_resource(sn_grs_resource_info_t *res)
+ *
+ * \brief Resource creating function.
+ *
+ * Used to create a static or dynamic HTTP(S) or CoAP resource.
+ *
+ * \param *res Pointer to a structure of type sn_grs_resource_info_t that contains the information
+ * about the resource.
+ *
+ * \return 0 success
+ * -1 Failure
+ * -2 Resource already exists
+ * -3 Invalid path
+ * -4 List adding failure
+*/
+
+extern int8_t sn_grs_create_resource(sn_nsdl_resource_info_s *res)
+{
+
+ if(!res)
+ return SN_NSDL_FAILURE;
+
+ /* Check path validity */
+ if(!res->pathlen || !res->path)
+ return SN_GRS_INVALID_PATH;
+
+ /* Check if resource already exists */
+ if(sn_grs_search_resource(res->pathlen, res->path, SN_GRS_SEARCH_METHOD) != (sn_nsdl_resource_info_s *)NULL)
+ {
+ return SN_GRS_RESOURCE_ALREADY_EXISTS;
+ }
+
+ if(res->resource_parameters_ptr)
+ {
+ res->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_NOT_REGISTERED;
+ }
+
+ /* Create resource */
+ if(sn_grs_add_resource_to_list(resource_root_list, res) == SN_NSDL_SUCCESS)
+ {
+ return SN_NSDL_SUCCESS;
+ }
+ return SN_GRS_LIST_ADDING_FAILURE;
+}
+
+
+
+/**
+ * \fn extern int8_t sn_grs_process_http(uint8_t *packet, uint16_t *packet_len, sn_grs_addr_t *src)
+ *
+ * \brief To push HTTP packet to GRS library
+ *
+ * Used to push an HTTP or unencrypted HTTPS packet to GRS library for processing.
+ *
+ * \param *packet Pointer to a uint8_t array containing the packet (including the HTTP headers).
+ * After SN_NSDL_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 SN_NSDL_SUCCESSful execution
+ * this array may contain the destination address of the response packet.
+ *
+ * \return 1 success, response packet to be sent.
+ * 0 success, no response to be sent
+ * -1 failure
+*/
+
+extern int8_t sn_grs_process_http(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src)
+{
+#if(SN_NSDL_HAVE_HTTP_CAPABILITY && SN_NSDL_HAVE_HTTPS_CAPABILITY)
+ /* Local variables */
+ sn_http_hdr_t *http_packet_ptr = NULL;
+ int8_t status = 0;
+
+ /******************************************/
+ /* Parse HTTP packet and check if succeed */
+ /******************************************/
+ http_packet_ptr = sn_http_parse(*packet_len, packet);
+ if(!http_packet_ptr)
+ return SN_NSDL_FAILURE;
+
+ if(http_packet_ptr->status != SN_HTTP_STATUS_OK)
+ return SN_NSDL_FAILURE; // Todo: other SN_NSDL_FAILUREs from HTTP
+
+ switch (http_packet_ptr->method)
+ {
+ case (SN_GRS_POST):
+ return status;
+
+ case (SN_GRS_PUT):
+ return status;
+
+ case (SN_GRS_GET):
+ return status;
+
+ case (SN_GRS_DELETE):
+ return status;
+
+ default:
+ return SN_NSDL_FAILURE;
+ }
+#endif
+ return SN_NSDL_FAILURE;
+}
+
+
+
+/**
+ * \fn extern int8_t sn_grs_process_coap(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src)
+ *
+ * \brief To push CoAP packet to GRS library
+ *
+ * Used to push an CoAP packet to GRS library for processing.
+ *
+ * \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, -1 = failure
+*/
+
+extern int8_t sn_grs_process_coap(uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src_addr_ptr)
+{
+ sn_coap_hdr_s *coap_packet_ptr = NULL;
+ sn_nsdl_resource_info_s *resource_temp_ptr = NULL;
+ sn_coap_msg_code_e status = COAP_MSG_CODE_EMPTY;
+ sn_coap_hdr_s *response_message_hdr_ptr = NULL;
+
+
+ /* Parse CoAP packet */
+ coap_packet_ptr = sn_coap_protocol_parse(src_addr_ptr, packet_len, packet);
+
+ /* 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(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)
+ {
+ status = COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED;
+ }
+
+ }
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * */
+ /* If message is response message, call RX callback */
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ if((coap_packet_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE && status == COAP_MSG_CODE_EMPTY) ||
+ (coap_packet_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT && status == COAP_MSG_CODE_EMPTY))
+ {
+ int8_t retval = sn_grs_rx_callback(coap_packet_ptr, src_addr_ptr);
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+ return retval;
+ }
+
+ /* * * * * * * * * * * * * * * */
+ /* Other messages are for GRS */
+ /* * * * * * * * * * * * * * * */
+
+ else if(coap_packet_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE && status == COAP_MSG_CODE_EMPTY)
+ {
+ /* Check if .well-known/core */
+ if(coap_packet_ptr->uri_path_len == WELLKNOWN_PATH_LEN && sn_grs_compare_code(coap_packet_ptr->uri_path_ptr, (const uint8_t*)WELLKNOWN_PATH, WELLKNOWN_PATH_LEN) == 0)
+ {
+
+ sn_coap_content_format_e wellknown_content_format = COAP_CT_LINK_FORMAT;
+
+ /* Allocate resopnse message */
+ response_message_hdr_ptr = sn_grs_alloc(sizeof(sn_coap_hdr_s));
+ if(!response_message_hdr_ptr)
+ {
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+ return SN_NSDL_FAILURE;
+ }
+ memset(response_message_hdr_ptr, 0, sizeof(sn_coap_hdr_s));
+
+ /* Build response */
+ response_message_hdr_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+ response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
+ response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
+ response_message_hdr_ptr->content_type_len = 1;
+ response_message_hdr_ptr->content_type_ptr = malloc(1);
+ if(!response_message_hdr_ptr)
+ {
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+ sn_grs_free(response_message_hdr_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ *response_message_hdr_ptr->content_type_ptr = wellknown_content_format;
+
+
+ sn_nsdl_build_registration_body(response_message_hdr_ptr, 0);
+
+ /* Send and free */
+ sn_grs_send_coap_message(src_addr_ptr, response_message_hdr_ptr);
+
+ if(response_message_hdr_ptr->payload_ptr)
+ {
+ sn_grs_free(response_message_hdr_ptr->payload_ptr);
+ response_message_hdr_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(response_message_hdr_ptr);
+
+ /* Free parsed CoAP message */
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+
+ return SN_NSDL_SUCCESS;
+ }
+
+ /* Get resource */
+ resource_temp_ptr = sn_grs_get_resource(coap_packet_ptr->uri_path_len, coap_packet_ptr->uri_path_ptr);
+
+ /* * * * * * * * * * * */
+ /* If resource exists */
+ /* * * * * * * * * * * */
+ if(resource_temp_ptr)
+ {
+ /* If dynamic resource, go to callback */
+ if(resource_temp_ptr->mode == SN_GRS_DYNAMIC)
+ {
+ /* Check accesses */
+ if(((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) && !(resource_temp_ptr->access & SN_GRS_GET_ALLOWED)) ||
+ ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) && !(resource_temp_ptr->access & SN_GRS_POST_ALLOWED)) ||
+ ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) && !(resource_temp_ptr->access & SN_GRS_PUT_ALLOWED)) ||
+ ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) && !(resource_temp_ptr->access & SN_GRS_DELETE_ALLOWED)))
+ {
+
+ status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+ }
+ else
+ {
+ resource_temp_ptr->sn_grs_dyn_res_callback(coap_packet_ptr, src_addr_ptr,0);
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+ return SN_NSDL_SUCCESS;
+ }
+ }
+ else
+ {
+ /* Static resource handling */
+ switch (coap_packet_ptr->msg_code )
+ {
+ case (COAP_MSG_CODE_REQUEST_GET):
+ if(resource_temp_ptr->access & SN_GRS_GET_ALLOWED)
+ {
+ status = COAP_MSG_CODE_RESPONSE_CONTENT;
+ }
+ else
+ status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+ break;
+ case (COAP_MSG_CODE_REQUEST_POST):
+ if(resource_temp_ptr->access & SN_GRS_POST_ALLOWED)
+ {
+ resource_temp_ptr->resourcelen = coap_packet_ptr->payload_len;
+ sn_grs_free(resource_temp_ptr->resource);
+ resource_temp_ptr->resource = 0;
+ if(resource_temp_ptr->resourcelen)
+ {
+ resource_temp_ptr->resource = sn_grs_alloc(resource_temp_ptr->resourcelen);
+ if(!resource_temp_ptr->resource)
+ {
+ status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+ break;
+ }
+ memcpy(resource_temp_ptr->resource, coap_packet_ptr->payload_ptr, resource_temp_ptr->resourcelen);
+ }
+ if(coap_packet_ptr->content_type_ptr)
+ {
+ if(resource_temp_ptr->resource_parameters_ptr)
+ {
+ resource_temp_ptr->resource_parameters_ptr->coap_content_type = *coap_packet_ptr->content_type_ptr;
+ }
+ }
+ status = COAP_MSG_CODE_RESPONSE_CHANGED;
+ }
+ else
+ status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+ break;
+ case (COAP_MSG_CODE_REQUEST_PUT):
+ if(resource_temp_ptr->access & SN_GRS_PUT_ALLOWED)
+ {
+ resource_temp_ptr->resourcelen = coap_packet_ptr->payload_len;
+ sn_grs_free(resource_temp_ptr->resource);
+ resource_temp_ptr->resource = 0;
+ if(resource_temp_ptr->resourcelen)
+ {
+ resource_temp_ptr->resource = sn_grs_alloc(resource_temp_ptr->resourcelen);
+ if(!resource_temp_ptr->resource)
+ {
+ status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+ break;
+ }
+ memcpy(resource_temp_ptr->resource, coap_packet_ptr->payload_ptr, resource_temp_ptr->resourcelen);
+ }
+ if(coap_packet_ptr->content_type_ptr)
+ {
+ if(resource_temp_ptr->resource_parameters_ptr)
+ {
+ resource_temp_ptr->resource_parameters_ptr->coap_content_type = *coap_packet_ptr->content_type_ptr;
+ }
+ }
+ status = COAP_MSG_CODE_RESPONSE_CHANGED;
+ }
+ else
+ status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+ break;
+
+ case (COAP_MSG_CODE_REQUEST_DELETE):
+ if(resource_temp_ptr->access & SN_GRS_DELETE_ALLOWED)
+ {
+ if(sn_grs_delete_resource(coap_packet_ptr->uri_path_len, coap_packet_ptr->uri_path_ptr) == SN_NSDL_SUCCESS)
+ status = COAP_MSG_CODE_RESPONSE_DELETED;
+ else
+ status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+ }
+ else
+ status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+ break;
+
+ default:
+ status = COAP_MSG_CODE_RESPONSE_FORBIDDEN;
+ break;
+ }
+ }
+ }
+
+ /* * * * * * * * * * * * * * */
+ /* If resource was not found */
+ /* * * * * * * * * * * * * * */
+
+ else
+ {
+ if(coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST ||
+ coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT)
+ {
+ resource_temp_ptr = sn_grs_alloc(sizeof(sn_nsdl_resource_info_s));
+ if(!resource_temp_ptr)
+ {
+ status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+ }
+ else
+ {
+ memset(resource_temp_ptr, 0, sizeof(sn_nsdl_resource_info_s));
+
+ resource_temp_ptr->access = (sn_grs_resource_acl_e)SN_GRS_DEFAULT_ACCESS;
+ resource_temp_ptr->mode = SN_GRS_STATIC;
+
+ resource_temp_ptr->pathlen = coap_packet_ptr->uri_path_len;
+ resource_temp_ptr->path = sn_grs_alloc(resource_temp_ptr->pathlen);
+ if(!resource_temp_ptr->path)
+ {
+ sn_grs_free(resource_temp_ptr);
+ resource_temp_ptr = 0;
+ status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+ }
+ else
+ {
+ memcpy(resource_temp_ptr->path, coap_packet_ptr->uri_path_ptr, resource_temp_ptr->pathlen);
+
+ resource_temp_ptr->resourcelen = coap_packet_ptr->payload_len;
+ resource_temp_ptr->resource = sn_grs_alloc(resource_temp_ptr->resourcelen);
+ if(!resource_temp_ptr->resource)
+ {
+ sn_grs_free(resource_temp_ptr->path);
+ resource_temp_ptr->path = 0;
+ sn_grs_free(resource_temp_ptr);
+ resource_temp_ptr = 0;
+ status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+ }
+ else
+ {
+
+ memcpy(resource_temp_ptr->resource, coap_packet_ptr->payload_ptr, resource_temp_ptr->resourcelen);
+
+ status = sn_linked_list_add_node(resource_root_list, resource_temp_ptr);
+ if(status == SN_LINKED_LIST_ERROR_NO_ERROR)
+ {
+ if(coap_packet_ptr->content_type_ptr)
+ {
+ if(resource_temp_ptr->resource_parameters_ptr)
+ {
+ resource_temp_ptr->resource_parameters_ptr->coap_content_type = *coap_packet_ptr->content_type_ptr;
+ }
+ }
+ status = COAP_MSG_CODE_RESPONSE_CREATED;
+ }
+ else
+ {
+ sn_grs_free(resource_temp_ptr->path);
+ resource_temp_ptr->path = 0;
+
+ sn_grs_free(resource_temp_ptr->resource);
+ resource_temp_ptr->resource = 0;
+
+ sn_grs_free(resource_temp_ptr);
+ resource_temp_ptr = 0;
+
+ status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+ else
+ status = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
+ }
+
+ }
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ /* If received packed was other than reset, create response */
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ if(coap_packet_ptr->msg_type != COAP_MSG_TYPE_RESET && coap_packet_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT)
+ {
+
+ /* Allocate resopnse message */
+ response_message_hdr_ptr = sn_grs_alloc(sizeof(sn_coap_hdr_s));
+ if(!response_message_hdr_ptr)
+ {
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+ return SN_NSDL_FAILURE;
+ }
+ memset(response_message_hdr_ptr, 0, sizeof(sn_coap_hdr_s));
+
+ /* If status has not been defined, response internal server error */
+ if(status == COAP_MSG_CODE_EMPTY)
+ status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+
+ /* Fill header */
+ response_message_hdr_ptr->msg_code = status;
+
+ if(coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE)
+ response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
+ else
+ response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
+
+ response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
+
+ if(coap_packet_ptr->token_ptr)
+ {
+ response_message_hdr_ptr->token_len = coap_packet_ptr->token_len;
+ response_message_hdr_ptr->token_ptr = sn_grs_alloc(response_message_hdr_ptr->token_len);
+ if(!response_message_hdr_ptr->token_ptr)
+ {
+ if(response_message_hdr_ptr->payload_ptr)
+ {
+ sn_grs_free(response_message_hdr_ptr->payload_ptr);
+ response_message_hdr_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(response_message_hdr_ptr);
+
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+ return SN_NSDL_FAILURE;
+ }
+ memcpy(response_message_hdr_ptr->token_ptr, coap_packet_ptr->token_ptr, response_message_hdr_ptr->token_len);
+ }
+
+ if(status == COAP_MSG_CODE_RESPONSE_CONTENT)
+ {
+ /* Add content type if other than default */
+ if(resource_temp_ptr->resource_parameters_ptr)
+ {
+ if(resource_temp_ptr->resource_parameters_ptr->coap_content_type != 0)
+ {
+ response_message_hdr_ptr->content_type_len = 1;
+ response_message_hdr_ptr->content_type_ptr = sn_grs_alloc(response_message_hdr_ptr->content_type_len);
+ if(!response_message_hdr_ptr->content_type_ptr)
+ {
+ sn_coap_parser_release_allocated_coap_msg_mem(response_message_hdr_ptr);
+
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+ return SN_NSDL_FAILURE;
+ }
+ memcpy(response_message_hdr_ptr->content_type_ptr, &resource_temp_ptr->resource_parameters_ptr->coap_content_type, response_message_hdr_ptr->content_type_len);
+ }
+ }
+
+ /* Add payload */
+ response_message_hdr_ptr->payload_len = resource_temp_ptr->resourcelen;
+ response_message_hdr_ptr->payload_ptr = sn_grs_alloc(response_message_hdr_ptr->payload_len);
+
+ if(!response_message_hdr_ptr->payload_ptr)
+ {
+ sn_coap_parser_release_allocated_coap_msg_mem(response_message_hdr_ptr);
+
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ memcpy(response_message_hdr_ptr->payload_ptr, resource_temp_ptr->resource, response_message_hdr_ptr->payload_len);
+ }
+
+ sn_grs_send_coap_message(src_addr_ptr, response_message_hdr_ptr);
+
+ if(response_message_hdr_ptr->payload_ptr)
+ {
+ sn_grs_free(response_message_hdr_ptr->payload_ptr);
+ response_message_hdr_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(response_message_hdr_ptr);
+ }
+
+ /* Free parsed CoAP message */
+ if(coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr)
+ {
+ sn_grs_free(coap_packet_ptr->payload_ptr);
+ coap_packet_ptr->payload_ptr = 0;
+ }
+ sn_coap_parser_release_allocated_coap_msg_mem(coap_packet_ptr);
+
+
+ return SN_NSDL_SUCCESS;
+}
+
+
+
+
+/**
+ * \fn extern int16_t sn_grs_get_capability(void)
+ *
+ * \brief Capability query function.
+ *
+ * Used to retrieve the list of supported protocols from the GRS module.
+ *
+ * \return >0 success, supported capabilities reported using bitmask with definitions from sn_grs_capab_t\n
+ * 0 success, no supported capabilities\n
+*/
+
+extern int16_t sn_grs_get_capability(void)
+{
+ int16_t capabilities = 0;
+ if(SN_NSDL_HAVE_HTTP_CAPABILITY)
+ capabilities |= 0x01;
+
+ if(SN_NSDL_HAVE_HTTPS_CAPABILITY)
+ capabilities |= 0x02;
+
+ if(SN_NSDL_HAVE_COAP_CAPABILITY)
+ capabilities |= 0x04;
+
+ return capabilities;
+}
+
+
+/**
+ * \fn extern uint32_t sn_grs_get_version(void)
+ *
+ * \brief Version query function.
+ *
+ * Used to retrieve the version information structure from the GRS library.
+ *
+ * \return !0 MSB 2 bytes major version, LSB 2 bytes minor version.
+ * 0 failure
+*/
+
+extern uint32_t sn_grs_get_version(void)
+{
+ return SN_GRS_VERSION;
+}
+
+/**
+ * \fn extern int8_t sn_grs_send_coap_message(sn_nsdl_addr_s * address_ptr, sn_coap_hdr_s *coap_hdr_ptr)
+ *
+ * \brief Sends CoAP message
+ *
+ * Sends CoAP message
+ *
+ * \param *coap_hdr_ptr Pointer to CoAP message to be sent
+ *
+ * \param *address_ptr Pointer to source address struct
+ *
+ * \return 0 = success, -1 = failed
+ *
+*/
+extern int8_t sn_grs_send_coap_message(sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr)
+{
+ uint8_t *message_ptr = NULL;
+ uint16_t message_len = 0;
+ uint8_t ret_val = 0;
+
+ /* Calculate message length */
+ message_len = sn_coap_builder_calc_needed_packet_data_size(coap_hdr_ptr);
+
+ /* Allocate memory for message and check was allocating successfully */
+ message_ptr = sn_grs_alloc(message_len);
+ if(message_ptr == NULL)
+ return SN_NSDL_FAILURE;
+
+ /* Build CoAP message */
+ if(sn_coap_protocol_build(address_ptr, message_ptr, coap_hdr_ptr) < 0)
+ {
+ sn_grs_free(message_ptr);
+ message_ptr = 0;
+ return SN_NSDL_FAILURE;
+ }
+
+ /* Call tx callback function to send message */
+ ret_val = sn_grs_tx_callback(SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address_ptr);
+
+ /* Free allocated memory */
+ sn_grs_free(message_ptr);
+ message_ptr = 0;
+
+ if(ret_val == 0)
+ return SN_NSDL_FAILURE;
+ else
+ return SN_NSDL_SUCCESS;
+}
+
+/**
+ * \fn static sn_grs_resource_info_s *sn_grs_search_resource(uint16_t pathlen, uint8_t *path, uint8_t search_method)
+ *
+ * \brief Searches given resource from linked list
+ *
+ * Search either precise path, or subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc...
+ *
+ * \param pathlen Length of the path to be search
+ *
+ * \param *path Pointer to the path string to be search
+ *
+ * \param search_method Search method, SEARCH or DELETE
+ *
+ * \return Pointer to the resource. If resource not found, return value is NULL
+ *
+*/
+
+static sn_nsdl_resource_info_s *sn_grs_search_resource(uint16_t pathlen, uint8_t *path, uint8_t search_method)
+{
+ /* Local variables */
+ sn_nsdl_resource_info_s *resource_search_temp = NULL;
+ uint8_t i = 0;
+ uint8_t *path_temp_ptr = NULL;
+
+ /* Check parameters */
+ if(!pathlen || !path)
+ {
+ return (sn_nsdl_resource_info_s *)NULL;;
+ }
+
+ /* Remove '/' - marks from the end and beginning */
+ path_temp_ptr = sn_grs_convert_uri(&pathlen, path);
+
+ resource_search_temp = sn_linked_list_get_first_node(resource_root_list);
+
+ /* Searchs exact path */
+ if(search_method == SN_GRS_SEARCH_METHOD)
+ {
+ /* Scan all nodes on list */
+ while(resource_search_temp)
+ {
+ /* If length equals.. */
+ if(resource_search_temp->pathlen == pathlen)
+ {
+ /* Compare paths */
+ i = memcmp(resource_search_temp->path, path_temp_ptr, pathlen);
+
+ /* If same, return node pointer */
+ if(!i)
+ return resource_search_temp;
+ }
+ /* If that was not what we needed, get next node.. */
+ resource_search_temp = sn_linked_list_get_next_node(resource_root_list);
+ }
+ }
+
+ /* Search also subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... */
+ else if(search_method == SN_GRS_DELETE_METHOD)
+ {
+ /* Scan all nodes on list */
+ while(resource_search_temp)
+ {
+ uint8_t *temp_ptr = resource_search_temp->path;
+
+ i = memcmp(resource_search_temp->path, path_temp_ptr, pathlen);
+
+ /* If found, return pointer */
+ if((*(temp_ptr+(uint8_t)pathlen) == '/') && !i)
+ return resource_search_temp;
+
+ /* else get next node */
+ resource_search_temp = sn_linked_list_get_next_node(resource_root_list);
+ }
+ }
+
+ /* If there was not nodes we wanted, return NULL */
+ return (sn_nsdl_resource_info_s *)NULL;
+}
+
+
+/**
+ * \fn static int8_t sn_grs_add_resource_to_list(sn_linked_list_t *list_ptr, sn_grs_resource_info_s *resource_ptr)
+ *
+ * \brief Adds given resource to resource list
+ *
+ * \param *list_ptr Length of the path to be search
+ *
+ * \param *resource_ptr Pointer to the path string to be search
+ *
+ * \return 0 = SN_NSDL_SUCCESS, -1 = SN_NSDL_FAILURE
+ *
+*/
+
+static int8_t sn_grs_add_resource_to_list(sn_linked_list_t *list_ptr, sn_nsdl_resource_info_s *resource_ptr)
+{
+ /* Local variables */
+ int8_t status = 0;
+ uint8_t *path_start_ptr = NULL;
+ uint16_t path_len = 0;
+ sn_nsdl_resource_info_s *resource_copy_ptr = NULL;
+
+ /* Allocate memory for the resource info copy */
+ if(!resource_ptr->pathlen)
+ {
+ return SN_NSDL_FAILURE;
+ }
+ resource_copy_ptr = sn_grs_alloc(sizeof(sn_nsdl_resource_info_s));
+ if(resource_copy_ptr == (sn_nsdl_resource_info_s*)NULL)
+ {
+ return SN_NSDL_FAILURE;
+ }
+
+ /* Set everything to zero */
+ memset(resource_copy_ptr, 0, sizeof(sn_nsdl_resource_info_s));
+
+ resource_copy_ptr->mode = resource_ptr->mode;
+ 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;
+
+ /* Remove '/' - chars from the beginning and from the end */
+
+ path_len = resource_ptr->pathlen;
+ path_start_ptr = sn_grs_convert_uri(&path_len, resource_ptr->path);
+
+ /* Allocate memory for the path */
+ resource_copy_ptr->path = sn_grs_alloc(path_len);
+ if(!resource_copy_ptr->path)
+ {
+ sn_grs_resource_info_free(resource_copy_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ /* Update pathlen */
+ resource_copy_ptr->pathlen = path_len;
+
+ /* Copy path string to the copy */
+#ifdef CC8051_PLAT
+ copy_code_nsdl(resource_copy_ptr->path, (prog_uint8_t*)path_start_ptr, resource_copy_ptr->pathlen);
+#else
+ memcpy(resource_copy_ptr->path, path_start_ptr, resource_copy_ptr->pathlen);
+#endif
+ /* Allocate memory for the resource, and copy it to copy */
+ if(resource_ptr->resource)
+ {
+ resource_copy_ptr->resource = sn_grs_alloc(resource_ptr->resourcelen);
+ if(!resource_copy_ptr->resource)
+ {
+ sn_grs_resource_info_free(resource_copy_ptr);
+ return SN_NSDL_FAILURE;
+ }
+ memcpy(resource_copy_ptr->resource, resource_ptr->resource, resource_ptr->resourcelen);
+ }
+
+
+
+ /* If resource parameters exists, copy them */
+ if(resource_ptr->resource_parameters_ptr)
+ {
+ resource_copy_ptr->resource_parameters_ptr = sn_grs_alloc(sizeof(sn_nsdl_resource_parameters_s));
+ if(!resource_copy_ptr->resource_parameters_ptr)
+ {
+ sn_grs_resource_info_free(resource_copy_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ memset(resource_copy_ptr->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s));
+
+
+ resource_copy_ptr->resource_parameters_ptr->resource_type_len = resource_ptr->resource_parameters_ptr->resource_type_len;
+
+ resource_copy_ptr->resource_parameters_ptr->interface_description_len = resource_ptr->resource_parameters_ptr->interface_description_len;
+
+ resource_copy_ptr->resource_parameters_ptr->mime_content_type = resource_ptr->resource_parameters_ptr->mime_content_type;
+
+ resource_copy_ptr->resource_parameters_ptr->observable = resource_ptr->resource_parameters_ptr->observable;
+
+ if(resource_ptr->resource_parameters_ptr->resource_type_ptr)
+ {
+ resource_copy_ptr->resource_parameters_ptr->resource_type_ptr = sn_grs_alloc(resource_ptr->resource_parameters_ptr->resource_type_len);
+ if(!resource_copy_ptr->resource_parameters_ptr->resource_type_ptr)
+ {
+ sn_grs_resource_info_free(resource_copy_ptr);
+ return SN_NSDL_FAILURE;
+ }
+#ifdef CC8051_PLAT
+ copy_code_nsdl(resource_copy_ptr->resource_parameters_ptr->resource_type_ptr,(prog_uint8_t*) resource_ptr->resource_parameters_ptr->resource_type_ptr, resource_ptr->resource_parameters_ptr->resource_type_len);
+#else
+ memcpy(resource_copy_ptr->resource_parameters_ptr->resource_type_ptr, resource_ptr->resource_parameters_ptr->resource_type_ptr, resource_ptr->resource_parameters_ptr->resource_type_len);
+#endif
+ }
+
+ if(resource_ptr->resource_parameters_ptr->interface_description_ptr)
+ {
+ resource_copy_ptr->resource_parameters_ptr->interface_description_ptr = sn_grs_alloc(resource_ptr->resource_parameters_ptr->interface_description_len);
+ if(!resource_copy_ptr->resource_parameters_ptr->interface_description_ptr)
+ {
+ sn_grs_resource_info_free(resource_copy_ptr);
+ return SN_NSDL_FAILURE;
+ }
+ memcpy(resource_copy_ptr->resource_parameters_ptr->interface_description_ptr, resource_ptr->resource_parameters_ptr->interface_description_ptr, resource_ptr->resource_parameters_ptr->interface_description_len);
+ }
+
+ /* Copy auto observation parameter */
+ /* todo: aobs not supported ATM - needs fixing */
+/* if(resource_ptr->resource_parameters_ptr->auto_obs_ptr && resource_ptr->resource_parameters_ptr->auto_obs_len)
+ {
+ resource_copy_ptr->resource_parameters_ptr->auto_obs_ptr = sn_grs_alloc(resource_ptr->resource_parameters_ptr->auto_obs_len);
+ if(!resource_copy_ptr->resource_parameters_ptr->auto_obs_ptr)
+ {
+ sn_grs_resource_info_free(resource_copy_ptr);
+ return SN_NSDL_FAILURE;
+ }
+ memcpy(resource_copy_ptr->resource_parameters_ptr->auto_obs_ptr, resource_ptr->resource_parameters_ptr->auto_obs_ptr, resource_ptr->resource_parameters_ptr->auto_obs_len);
+ resource_copy_ptr->resource_parameters_ptr->auto_obs_len = resource_ptr->resource_parameters_ptr->auto_obs_len;
+ }
+
+ resource_copy_ptr->resource_parameters_ptr->coap_content_type = resource_ptr->resource_parameters_ptr->coap_content_type;
+ */
+ }
+
+ /* Add copied resource to the linked list */
+ status = sn_linked_list_add_node(list_ptr, resource_copy_ptr);
+
+ /* Was adding ok? */
+ if(status == SN_LINKED_LIST_ERROR_NO_ERROR)
+ {
+ return SN_NSDL_SUCCESS;
+ }
+ else
+ {
+ sn_grs_resource_info_free(resource_copy_ptr);
+ return SN_NSDL_FAILURE;//DONE?: Free memory
+ }
+}
+
+
+/**
+ * \fn static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr)
+ *
+ * \brief Removes '/' from the beginning and from the end of uri string
+ *
+ * \param *uri_len Pointer to the length of the path string
+ *
+ * \param *uri_ptr Pointer to the path string
+ *
+ * \return start pointer of the uri
+ *
+*/
+
+static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr)
+{
+ /* Local variables */
+ uint8_t *uri_start_ptr = uri_ptr;
+
+ /* If '/' in the beginning, update uri start pointer and uri len */
+ if(*uri_ptr == '/')
+ {
+ uri_start_ptr = uri_ptr+1;
+ *uri_len = *uri_len-1;
+ }
+
+ /* If '/' at the end, update uri len */
+ if(*(uri_start_ptr+*uri_len-1) == '/')
+ {
+ *uri_len = *uri_len-1;
+ }
+
+ /* Return start pointer */
+ return uri_start_ptr;
+}
+
+/**
+ * \fn static int8_t sn_grs_resource_info_free(sn_grs_resource_info_s *resource_ptr)
+ *
+ * \brief Frees resource info structure
+ *
+ * \param *resource_ptr Pointer to the resource
+ *
+ * \return 0 if success, -1 if failed
+ *
+*/
+
+static int8_t sn_grs_resource_info_free(sn_nsdl_resource_info_s *resource_ptr)
+{
+ if(resource_ptr)
+ {
+ if(resource_ptr->resource_parameters_ptr)
+ {
+ if(resource_ptr->resource_parameters_ptr->interface_description_ptr)
+ {
+ sn_grs_free(resource_ptr->resource_parameters_ptr->interface_description_ptr);
+ resource_ptr->resource_parameters_ptr->interface_description_ptr = 0;
+ }
+
+ if(resource_ptr->resource_parameters_ptr->resource_type_ptr)
+ {
+ sn_grs_free(resource_ptr->resource_parameters_ptr->resource_type_ptr);
+ resource_ptr->resource_parameters_ptr->resource_type_ptr = 0;
+ }
+
+ /* Todo: aobs not supported ATM - needs fixing */
+ /*
+ if(resource_ptr->resource_parameters_ptr->auto_obs_ptr)
+ {
+ sn_grs_free(resource_ptr->resource_parameters_ptr->auto_obs_ptr);
+ resource_ptr->resource_parameters_ptr->auto_obs_ptr = 0;
+ }
+ */
+
+ sn_grs_free(resource_ptr->resource_parameters_ptr);
+ resource_ptr->resource_parameters_ptr = 0;
+ }
+
+ if(resource_ptr->path)
+ {
+ sn_grs_free(resource_ptr->path);
+ resource_ptr->path = 0;
+ }
+ if(resource_ptr->resource)
+ {
+ sn_grs_free(resource_ptr->resource);
+ resource_ptr->resource = 0;
+ }
+ sn_grs_free(resource_ptr);
+ resource_ptr = 0;
+ return SN_NSDL_SUCCESS;
+ }
+ return SN_NSDL_FAILURE;
+}
+
+#ifdef CC8051_PLAT
+void copy_code_nsdl(uint8_t * ptr, prog_uint8_t * code_ptr, uint16_t len)
+{
+ uint16_t i;
+ for(i=0; i<len; i++)
+ {
+ ptr[i] = code_ptr[i];
+ }
+}
+#endif
+
+static uint8_t sn_grs_compare_code(uint8_t * ptr, prog_uint8_t * code_ptr, uint8_t len)
+{
+ uint8_t i=0;
+ while(len)
+ {
+ if(ptr[i] != code_ptr[i])
+ {
+ break;
+ }
+ len--;
+ i++;
+ }
+ return len;
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sn_grs.h Tue Feb 18 01:10:07 2014 +0000
@@ -0,0 +1,117 @@
+/*
+ * GRS.h
+ *
+ * Created on: 2.8.2011
+ * Author: Tero
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GRS_H_
+#define GRS_H_
+
+
+#endif /* GRS_H_ */
+
+#define SN_GRS_VERSION 0x0101
+
+#ifndef SN_NSDL_HAVE_HTTP_CAPABILITY
+#define SN_NSDL_HAVE_HTTP_CAPABILITY 0
+#endif
+
+#ifndef SN_NSDL_HAVE_HTTPS_CAPABILITY
+#define SN_NSDL_HAVE_HTTPS_CAPABILITY 0
+#endif
+
+#ifndef SN_NSDL_HAVE_COAP_CAPABILITY
+#define SN_NSDL_HAVE_COAP_CAPABILITY 1
+#endif
+
+#define SN_GRS_RESOURCE_ALREADY_EXISTS -2
+#define SN_GRS_INVALID_PATH -3
+#define SN_GRS_LIST_ADDING_FAILURE -4
+#define SN_GRS_RESOURCE_UPDATED -5
+
+#define ACCESS_DENIED -6
+
+#define SN_GRS_DELETE_METHOD 0
+#define SN_GRS_SEARCH_METHOD 1
+
+#define SN_GRS_DEFAULT_ACCESS 0x0F
+
+#define SN_NDSL_RESOURCE_NOT_REGISTERED 0
+#define SN_NDSL_RESOURCE_REGISTERING 1
+#define SN_NDSL_RESOURCE_REGISTERED 2
+
+/***** Structs *****/
+
+typedef struct sn_grs_version_
+{
+ uint8_t major_version;
+ uint8_t minor_version;
+ uint8_t build;
+}sn_grs_version_s;
+
+
+
+/***** Function prototypes *****/
+/**
+ * \fn extern int8_t sn_grs_init (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t,
+ * sn_nsdl_addr_s *), uint8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *),
+ * sn_grs_mem_s *sn_memory)
+ *
+ * \brief GRS library initialize function.
+ *
+ * This function initializes GRS, CoAP and HTTP libraries.
+ *
+ * \param sn_grs_tx_callback A function pointer to a transmit callback function. Should return 1 when succeed, 0 when failed
+ * \param *sn_grs_rx_callback_ptr A function pointer to a receiving callback function. If received packet is not for GRS, it will be passed to
+ * upper level (NSDL) to be proceed.
+ * \param sn_memory A pointer to a structure containing the platform specific functions for memory allocation and free.
+ *
+ * \return success = 0, failure = -1
+ *
+*/
+extern int8_t sn_grs_init (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t,
+ sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *), sn_nsdl_mem_s *sn_memory);
+extern int8_t sn_grs_exec(uint32_t time);
+extern sn_grs_resource_list_s *sn_grs_list_resource(uint16_t pathlen, uint8_t *path);
+extern sn_nsdl_resource_info_s *sn_grs_get_first_resource(void);
+extern sn_nsdl_resource_info_s *sn_grs_get_next_resource(void);
+extern sn_nsdl_resource_info_s *sn_grs_get_resource(uint16_t pathlen, uint8_t *path);
+extern int8_t sn_grs_delete_resource(uint16_t pathlen, uint8_t *path);
+extern int8_t sn_grs_update_resource(sn_nsdl_resource_info_s *res);
+/**
+ * \fn extern int8_t sn_grs_create_resource(sn_grs_resource_info_t *res)
+ *
+ * \brief Resource creating function.
+ *
+ * Used to create a static or dynamic HTTP(S) or CoAP resource.
+ *
+ * \param *res Pointer to a structure of type sn_grs_resource_info_t that contains the information
+ * about the resource.
+ *
+ * \return 0 success
+ * -1 Resource already exists
+ * -2 Invalid path
+ * -3 List adding failure
+*/
+extern int8_t sn_grs_create_resource(sn_nsdl_resource_info_s *res);
+extern int8_t sn_grs_process_http(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src);
+extern int8_t sn_grs_process_coap(uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src);
+extern int16_t sn_grs_get_capability(void);
+extern uint32_t sn_grs_get_version(void);
+extern int8_t sn_grs_send_coap_message(sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr);
+
+extern int8_t sn_grs_destroy(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sn_nsdl.c Tue Feb 18 01:10:07 2014 +0000
@@ -0,0 +1,1555 @@
+/**
+ * \file sn_nsdl.c
+ *
+ * \brief Nano service device library
+ *
+ * Application interface to CoAP, GRS and NSP handling.
+ *
+ */
+
+#include <string.h>
+
+#include "nsdl_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"
+#include "sn_linked_list.h"
+
+/* Defines */
+#define RESOURCE_DIR_LEN 2
+#define RESOURCE_DIR_PATH {'r','d'}
+
+#define EP_NAME_PARAMETERS_LEN 2
+#define EP_NAME_PARAMETERS {'h','='}
+
+#define RT_PARAMETER_LEN 3
+#define RT_PARAMETER {'r','t','='}
+
+#define IF_PARAMETER_LEN 3
+#define IF_PARAMETER {'i','f','='}
+
+#define CON_PARAMETER_LEN 4
+#define CON_PARAMETER {'c','o','n','='}
+
+#define LT_PARAMETER_LEN 3
+#define LT_PARAMETER {'l','t','='}
+
+#define OBS_PARAMETER_LEN 3
+#define OBS_PARAMETER {'o','b','s'}
+
+#define AOBS_PARAMETER_LEN 8
+#define AOBS_PARAMETER {'a','o','b','s',';','i','d','='}
+
+#define COAP_CON_PARAMETER_LEN 3
+#define COAP_CON_PARAMETER {'c','t','='}
+
+#define EVENT_PATH_LEN 6
+#define EVENT_PATH {'e','v','e','n','t','/'}
+
+#define SN_NSDL_EP_REGISTER_MESSAGE 1
+#define SN_NSDL_EP_UPDATE_MESSAGE 2
+
+#define SN_NSDL_MSG_NO_TYPE 0
+#define SN_NSDL_MSG_REGISTER 1
+#define SN_NSDL_MSG_UNREGISTER 2
+#define SN_NSDL_MSG_UPDATE 3
+#define SN_NSDL_MSG_EVENT 4
+
+#define SN_NSDL_MAX_MESSAGE_COUNT 1
+
+/* Constants */
+SN_NSDL_CONST_MEMORY_ATTRIBUTE
+static uint8_t ep_name_parameter_string[] = EP_NAME_PARAMETERS;
+
+SN_NSDL_CONST_MEMORY_ATTRIBUTE
+static uint8_t resource_path_ptr[] = RESOURCE_DIR_PATH;
+
+SN_NSDL_CONST_MEMORY_ATTRIBUTE
+static uint8_t resource_type_parameter[] = RT_PARAMETER;
+
+SN_NSDL_CONST_MEMORY_ATTRIBUTE
+static uint8_t obs_parameter[] = OBS_PARAMETER;
+
+//SN_NSDL_CONST_MEMORY_ATTRIBUTE
+//static uint8_t aobs_parameter[] = AOBS_PARAMETER;
+
+SN_NSDL_CONST_MEMORY_ATTRIBUTE
+static uint8_t if_description_parameter[] = IF_PARAMETER;
+
+SN_NSDL_CONST_MEMORY_ATTRIBUTE
+static uint8_t ep_lifetime_parameter[] = LT_PARAMETER;
+
+SN_NSDL_CONST_MEMORY_ATTRIBUTE
+static uint8_t coap_con_type_parameter[] = COAP_CON_PARAMETER;
+
+SN_NSDL_CONST_MEMORY_ATTRIBUTE
+static uint8_t event_path_parameter[] = EVENT_PATH;
+
+/* Global function pointers */
+static void *(*sn_nsdl_alloc)(uint16_t) = 0;
+static void (*sn_nsdl_free)(void*) = 0;
+static uint8_t (*sn_nsdl_tx_callback)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *) = 0;
+static uint8_t (*sn_nsdl_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *) = 0;
+
+/* Global variables */
+static sn_nsdl_ep_parameters_s *ep_information_ptr = 0; // Endpoint parameters, Name, Domain etc..
+static sn_nsdl_addr_s *nsp_address_ptr = 0; // NSP server address information
+static sn_linked_list_t *message_list_ptr = 0; //
+static uint8_t sn_nsdl_endpoint_registered = 0;
+
+/* Function prototypes */
+static int8_t sn_nsdl_internal_coap_send (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 (void);
+int8_t sn_nsdl_build_registration_body (sn_coap_hdr_s *message_ptr, uint8_t updating_registeration);
+static uint16_t sn_nsdl_calculate_registration_body_size (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 (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 (sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr);
+static int8_t sn_nsdl_resolve_ep_information (sn_coap_hdr_s *coap_packet_ptr);
+static void sn_nsdl_mark_resources_as_registered (void);
+static uint8_t sn_nsdl_itoa_len (uint8_t value);
+static uint8_t *sn_nsdl_itoa (uint8_t *ptr, uint8_t value);
+
+
+int8_t sn_nsdl_destroy(void)
+{
+ if(message_list_ptr)
+ {
+ uint16_t size = sn_linked_list_count_nodes(message_list_ptr);
+ uint16_t i = 0;
+ sn_nsdl_sent_messages_s*tmp;
+
+
+ for(i=0;i<size;i++)
+ {
+ tmp = sn_linked_list_get_first_node(message_list_ptr);
+
+ if(tmp)
+ {
+ sn_linked_list_remove_current_node(message_list_ptr);
+ sn_nsdl_free(tmp);
+ tmp = 0;
+ }
+ }
+
+ if(!sn_linked_list_count_nodes(message_list_ptr))
+ {
+ sn_linked_list_free(message_list_ptr);
+ message_list_ptr = 0;
+ }
+ }
+
+ if(ep_information_ptr)
+ {
+ if(ep_information_ptr->endpoint_name_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->endpoint_name_ptr);
+ ep_information_ptr->endpoint_name_ptr = 0;
+ }
+ if(ep_information_ptr->domain_name_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->domain_name_ptr);
+ ep_information_ptr->domain_name_ptr = 0;
+ ep_information_ptr->domain_name_len = 0;
+ }
+ if(ep_information_ptr->type_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->type_ptr);
+ ep_information_ptr->type_ptr = 0;
+ }
+
+ if(ep_information_ptr->lifetime_ptr)
+
+ {
+ sn_nsdl_free(ep_information_ptr->lifetime_ptr);
+ ep_information_ptr->lifetime_ptr = 0;
+ }
+
+ sn_nsdl_free(ep_information_ptr);
+ ep_information_ptr = 0;
+ }
+
+ if(nsp_address_ptr)
+ {
+ if(nsp_address_ptr->socket_information)
+ {
+ sn_nsdl_free(nsp_address_ptr->socket_information);
+ nsp_address_ptr->socket_information= 0;
+ }
+
+ if(nsp_address_ptr->addr_ptr)
+ {
+ sn_nsdl_free(nsp_address_ptr->addr_ptr);
+ nsp_address_ptr->addr_ptr = 0;
+ }
+ sn_nsdl_free(nsp_address_ptr);
+ nsp_address_ptr = 0;
+ }
+
+ /* Destroy also libCoap and grs part of libNsdl */
+ sn_grs_destroy();
+ sn_coap_protocol_destroy();
+
+ return 0;
+}
+
+int8_t 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)
+{
+ /* Check pointers and define function pointers */
+ if(!sn_memory || !sn_memory->sn_nsdl_alloc || !sn_memory->sn_nsdl_free || !sn_nsdl_tx_cb || !sn_nsdl_rx_cb)
+ return SN_NSDL_FAILURE;
+
+ /* Define function pointers */
+ sn_nsdl_alloc = sn_memory->sn_nsdl_alloc;
+ sn_nsdl_free = sn_memory->sn_nsdl_free;
+
+ sn_nsdl_tx_callback = sn_nsdl_tx_cb;
+ sn_nsdl_rx_callback = sn_nsdl_rx_cb;
+
+ sn_linked_list_init(sn_nsdl_alloc, sn_nsdl_free);
+
+ message_list_ptr = sn_linked_list_create();
+ if(!message_list_ptr)
+ return SN_NSDL_FAILURE;
+
+ /* Initialize ep parameters struct */
+ if(!ep_information_ptr)
+ {
+ ep_information_ptr = sn_nsdl_alloc(sizeof(sn_nsdl_ep_parameters_s));
+ if(!ep_information_ptr)
+ {
+ sn_linked_list_free(message_list_ptr);
+ return SN_NSDL_FAILURE;
+ }
+ memset(ep_information_ptr, 0, sizeof(sn_nsdl_ep_parameters_s));
+ }
+
+ /* Initialize GRS */
+ if(sn_grs_init(sn_nsdl_tx_cb,&sn_nsdl_local_rx_function, sn_memory))
+ {
+
+ sn_nsdl_free(ep_information_ptr);
+ ep_information_ptr = 0;
+ sn_linked_list_free(message_list_ptr);
+ return SN_NSDL_FAILURE;
+
+ }
+
+ // todo: Resolve NS server address -> v0.5 = hardcoded address
+ sn_nsdl_resolve_nsp_address();
+
+ sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED;
+
+ return SN_NSDL_SUCCESS;
+}
+
+int8_t sn_nsdl_GET_with_QUERY(char * uri, uint16_t urilen, uint8_t*destination, uint16_t port, char *query, uint8_t query_len)
+{
+ sn_coap_hdr_s *message_ptr;
+ sn_nsdl_addr_s *dst = 0;
+
+ message_ptr = sn_nsdl_alloc(sizeof(sn_coap_hdr_s));
+ if(message_ptr == NULL)
+ return SN_NSDL_FAILURE;
+
+ memset(message_ptr, 0, sizeof(sn_coap_hdr_s));
+
+ /* Fill message fields -> confirmable post to specified NSP path */
+ message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+ message_ptr->msg_code = COAP_MSG_CODE_REQUEST_GET;
+ /* Allocate memory for the extended options list */
+ message_ptr->options_list_ptr = sn_nsdl_alloc(sizeof(sn_coap_options_list_s));
+ if(message_ptr->options_list_ptr == NULL)
+ {
+ sn_nsdl_free(message_ptr);
+ message_ptr = 0;
+ return SN_NSDL_FAILURE;
+ }
+
+
+ memset(message_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s));
+ message_ptr->options_list_ptr->uri_query_len =query_len;
+ message_ptr->options_list_ptr->uri_query_ptr = (uint8_t *)query;
+ message_ptr->uri_path_len = urilen;
+ message_ptr->uri_path_ptr = (uint8_t *)uri;
+
+ /* Build and send coap message to NSP */
+ /* Local variables */
+ if(!dst)
+ {
+ //allocate only if previously not allocated
+ dst = sn_nsdl_alloc(sizeof(sn_nsdl_addr_s));
+ }
+
+ if(dst)
+ {
+ /* This is only for version 0.5 */
+ dst->type = SN_NSDL_ADDRESS_TYPE_IPV6;
+ dst->port = port;
+ dst->addr_len = 16;
+ if(!dst->addr_ptr)
+ {
+ dst->addr_ptr = sn_nsdl_alloc(dst->addr_len);
+ memcpy(dst->addr_ptr, destination, 16);
+ }
+ }
+
+ sn_grs_send_coap_message(dst, message_ptr);
+
+ if(dst->addr_ptr)
+ sn_nsdl_free(dst->addr_ptr);
+
+ if(dst)
+ sn_nsdl_free(dst);
+ message_ptr->uri_path_ptr = NULL;
+ message_ptr->options_list_ptr->uri_host_ptr = NULL;
+ message_ptr->options_list_ptr->uri_query_ptr = NULL;
+
+ sn_coap_parser_release_allocated_coap_msg_mem(message_ptr);
+ return SN_NSDL_SUCCESS;
+}
+
+int8_t sn_nsdl_GET(char * uri, uint16_t urilen, uint8_t*destination, uint16_t port)
+{
+ sn_coap_hdr_s *message_ptr;
+ sn_nsdl_addr_s *dst = 0;
+
+
+ message_ptr = sn_nsdl_alloc(sizeof(sn_coap_hdr_s));
+ if(message_ptr == NULL)
+ return SN_NSDL_FAILURE;
+
+ memset(message_ptr, 0, sizeof(sn_coap_hdr_s));
+
+ /* Fill message fields -> confirmable post to specified NSP path */
+ message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+ message_ptr->msg_code = COAP_MSG_CODE_REQUEST_GET;
+ /* Allocate memory for the extended options list */
+ message_ptr->options_list_ptr = sn_nsdl_alloc(sizeof(sn_coap_options_list_s));
+ if(message_ptr->options_list_ptr == NULL)
+ {
+ sn_nsdl_free(message_ptr);
+ message_ptr = 0;
+ return SN_NSDL_FAILURE;
+ }
+
+
+ memset(message_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s));
+
+ message_ptr->uri_path_len = urilen;
+ message_ptr->uri_path_ptr = (uint8_t *)uri;
+
+ /* Build and send coap message to NSP */
+ /* Local variables */
+ if(!dst)
+ {
+ //allocate only if previously not allocated
+ dst = sn_nsdl_alloc(sizeof(sn_nsdl_addr_s));
+ memset(dst, 0, sizeof(sn_nsdl_addr_s));
+ }
+
+ if(dst)
+ {
+ /* This is only for version 0.5 */
+ dst->type = SN_NSDL_ADDRESS_TYPE_IPV6;
+ dst->port = port;
+ dst->addr_len = 16;
+ if(!dst->addr_ptr)
+ {
+ dst->addr_ptr = sn_nsdl_alloc(dst->addr_len);
+ memcpy(dst->addr_ptr, destination, 16);
+ }
+ }
+ sn_grs_send_coap_message(dst, message_ptr);
+
+ if(dst->addr_ptr)
+ sn_nsdl_free(dst->addr_ptr);
+ if(dst)
+ sn_nsdl_free(dst);
+ message_ptr->uri_path_ptr = NULL;
+ message_ptr->options_list_ptr->uri_host_ptr = NULL;
+
+ sn_coap_parser_release_allocated_coap_msg_mem(message_ptr);
+ return SN_NSDL_SUCCESS;
+}
+
+
+
+int8_t sn_nsdl_register_endpoint(sn_nsdl_ep_parameters_s *endpoint_info_ptr)
+{
+ /* Local variables */
+ sn_coap_hdr_s *register_message_ptr;
+ int8_t status = 0;
+
+ if(!endpoint_info_ptr)
+ return SN_NSDL_FAILURE;
+
+ /*** Build endpoint register message ***/
+
+ /* Allocate memory for header struct */
+ register_message_ptr = sn_nsdl_alloc(sizeof(sn_coap_hdr_s));
+ if(register_message_ptr == NULL)
+ return SN_NSDL_FAILURE;
+
+ 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 = sn_nsdl_alloc(sizeof(sn_coap_options_list_s));
+ if(register_message_ptr->options_list_ptr == NULL)
+ {
+ sn_nsdl_free(register_message_ptr);
+ register_message_ptr = 0;
+ return SN_NSDL_FAILURE;
+ }
+
+ 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;
+
+ /* If domain name is configured, fill needed fields */
+ if(endpoint_info_ptr->domain_name_len)
+ {
+ register_message_ptr->options_list_ptr->uri_host_len = endpoint_info_ptr->domain_name_len;
+ register_message_ptr->options_list_ptr->uri_host_ptr = endpoint_info_ptr->domain_name_ptr;
+ }
+
+ /* Fill Uri-query options */
+ sn_nsdl_fill_uri_query_options(endpoint_info_ptr, register_message_ptr, SN_NSDL_EP_REGISTER_MESSAGE);
+#ifndef REG_TEMPLATE
+ /* Built body for message */
+ status = sn_nsdl_build_registration_body(register_message_ptr, 0);
+ if(status == 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(register_message_ptr);
+ return SN_NSDL_FAILURE;
+ }
+#endif
+ /* Build and send coap message to NSP */
+ status = sn_nsdl_internal_coap_send(register_message_ptr, nsp_address_ptr, SN_NSDL_MSG_REGISTER);
+
+ if(register_message_ptr->payload_ptr)
+ {
+ 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(register_message_ptr);
+
+ if(ep_information_ptr)
+ {
+ if(ep_information_ptr->domain_name_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->domain_name_ptr);
+ ep_information_ptr->domain_name_ptr = 0;
+ ep_information_ptr->domain_name_len = 0;
+ }
+
+ if(ep_information_ptr->endpoint_name_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->endpoint_name_ptr);
+ ep_information_ptr->endpoint_name_ptr = 0;
+ ep_information_ptr->endpoint_name_len = 0;
+ }
+
+ if(endpoint_info_ptr->domain_name_ptr)
+ {
+
+ if(!ep_information_ptr->domain_name_ptr)
+ {
+ ep_information_ptr->domain_name_ptr = sn_nsdl_alloc(endpoint_info_ptr->domain_name_len);
+ }
+ if(!ep_information_ptr->domain_name_ptr)
+ {
+ return SN_NSDL_FAILURE;
+ }
+
+ memcpy(ep_information_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_len);
+ ep_information_ptr->domain_name_len = endpoint_info_ptr->domain_name_len;
+
+ }
+
+ if(endpoint_info_ptr->endpoint_name_ptr)
+ {
+
+ if(!ep_information_ptr->endpoint_name_ptr)
+ {
+ ep_information_ptr->endpoint_name_ptr = sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len);
+ }
+ if(!ep_information_ptr->endpoint_name_ptr)
+ {
+ if(ep_information_ptr->domain_name_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->domain_name_ptr);
+ ep_information_ptr->domain_name_ptr = 0;
+ ep_information_ptr->domain_name_len = 0;
+ }
+ return SN_NSDL_FAILURE;
+ }
+
+ memcpy(ep_information_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len);
+ ep_information_ptr->endpoint_name_len = endpoint_info_ptr->endpoint_name_len;
+
+ }
+ }
+
+ return status;
+}
+
+int8_t sn_nsdl_unregister_endpoint(void)
+{
+ /* Local variables */
+ sn_coap_hdr_s *unregister_message_ptr;
+ uint8_t *temp_ptr = 0;
+
+ /* Check that EP have been registered */
+ if(sn_nsdl_is_ep_registered())
+ {
+
+ /* Memory allocation for unregister message */
+ unregister_message_ptr = sn_nsdl_alloc(sizeof(sn_coap_hdr_s));
+ if(!unregister_message_ptr)
+ return SN_NSDL_FAILURE;
+
+ 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;
+
+ unregister_message_ptr->uri_path_len = (RESOURCE_DIR_LEN + 1 + ep_information_ptr->domain_name_len + 1 + ep_information_ptr->endpoint_name_len);
+ unregister_message_ptr->uri_path_ptr = sn_nsdl_alloc(unregister_message_ptr->uri_path_len);
+ if (!unregister_message_ptr->uri_path_ptr)
+ {
+ sn_coap_parser_release_allocated_coap_msg_mem(unregister_message_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ 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 ,ep_information_ptr->domain_name_ptr, ep_information_ptr->domain_name_len);
+ temp_ptr += ep_information_ptr->domain_name_len;
+
+ *temp_ptr++ = '/';
+
+ memcpy(temp_ptr ,ep_information_ptr->endpoint_name_ptr, ep_information_ptr->endpoint_name_len);
+
+ /* Send message */
+ sn_nsdl_internal_coap_send(unregister_message_ptr, nsp_address_ptr, SN_NSDL_MSG_UNREGISTER);
+
+ /* Free memory */
+ sn_coap_parser_release_allocated_coap_msg_mem(unregister_message_ptr);
+
+ }
+
+ return SN_NSDL_SUCCESS;
+}
+
+int8_t sn_nsdl_update_registration (sn_nsdl_ep_parameters_s *endpoint_info_ptr)
+{
+ /* Local variables */
+ sn_coap_hdr_s *register_message_ptr;
+ uint8_t *temp_ptr;
+
+ /*** Build endpoint register update message ***/
+
+ /* Allocate memory for header struct */
+ register_message_ptr = sn_nsdl_alloc(sizeof(sn_coap_hdr_s));
+ if(register_message_ptr == NULL)
+ return SN_NSDL_FAILURE;
+
+ 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_PUT;
+
+ register_message_ptr->uri_path_len = sizeof(resource_path_ptr) + ep_information_ptr->domain_name_len + ep_information_ptr->endpoint_name_len + 2; // = rd/domain/endpoint
+
+ register_message_ptr->uri_path_ptr = sn_nsdl_alloc(register_message_ptr->uri_path_len);
+ if(!register_message_ptr->uri_path_ptr)
+ {
+ sn_coap_parser_release_allocated_coap_msg_mem(register_message_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ 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, ep_information_ptr->domain_name_ptr, ep_information_ptr->domain_name_len);
+ temp_ptr += ep_information_ptr->domain_name_len;
+ *temp_ptr++ = '/';
+
+ /* rd/domain/ENDPOINT */
+ memcpy(temp_ptr, ep_information_ptr->endpoint_name_ptr, ep_information_ptr->endpoint_name_len);
+
+
+ /* Allocate memory for the extended options list */
+ register_message_ptr->options_list_ptr = 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(register_message_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ memset(register_message_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s));
+
+ /* Fill Uri-query options */
+ sn_nsdl_fill_uri_query_options(endpoint_info_ptr, register_message_ptr, SN_NSDL_EP_UPDATE_MESSAGE);
+
+ /* Build and send coap message to NSP */
+ sn_nsdl_internal_coap_send(register_message_ptr, nsp_address_ptr, SN_NSDL_MSG_UPDATE);
+
+ if(register_message_ptr->payload_ptr)
+ sn_nsdl_free(register_message_ptr->payload_ptr);
+ sn_coap_parser_release_allocated_coap_msg_mem(register_message_ptr);
+
+ return SN_NSDL_SUCCESS;
+}
+
+int8_t sn_nsdl_send_eventing_message (uint8_t *event_name_ptr, uint16_t event_name_len, uint8_t *message_body_ptr, uint16_t message_body_len)
+{
+ sn_coap_hdr_s *eventing_message_ptr;
+ int8_t status = 0;
+
+ /* Allocate and initialize memory for header struct */
+ eventing_message_ptr = sn_nsdl_alloc(sizeof(sn_coap_hdr_s));
+ if(eventing_message_ptr == NULL)
+ return SN_NSDL_FAILURE;
+
+ memset(eventing_message_ptr, 0, sizeof(sn_coap_hdr_s));
+
+ /* Fill header */
+ eventing_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+ eventing_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST;
+
+ /* Fill uri path option */
+ eventing_message_ptr->uri_path_len = sizeof(event_path_parameter) + event_name_len;
+ eventing_message_ptr->uri_path_ptr = sn_nsdl_alloc(eventing_message_ptr->uri_path_len);
+
+ if(!eventing_message_ptr->uri_path_ptr)
+ {
+ sn_coap_parser_release_allocated_coap_msg_mem(eventing_message_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ memcpy(eventing_message_ptr->uri_path_ptr, event_path_parameter, sizeof(event_path_parameter));
+ memcpy(eventing_message_ptr->uri_path_ptr + sizeof(event_path_parameter), event_name_ptr, event_name_len);
+
+ /* Fill payload */
+ eventing_message_ptr->payload_len = message_body_len;
+ eventing_message_ptr->payload_ptr = message_body_ptr;
+
+ /* Send coap message */
+ status = sn_nsdl_internal_coap_send(eventing_message_ptr, nsp_address_ptr, SN_NSDL_MSG_EVENT);
+
+ eventing_message_ptr->payload_ptr = NULL;
+
+ sn_coap_parser_release_allocated_coap_msg_mem(eventing_message_ptr);
+
+ return status;
+}
+
+void sn_nsdl_nsp_lost(void)
+{
+ sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED;
+ return;
+}
+
+int8_t sn_nsdl_is_ep_registered(void)
+{
+
+ return sn_nsdl_endpoint_registered;
+}
+
+uint16_t sn_nsdl_send_observation_notification(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;
+
+ /* Allocate and initialize memory for header struct */
+ notification_message_ptr = 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 = sn_nsdl_alloc(sizeof(sn_coap_options_list_s));
+ if(notification_message_ptr->options_list_ptr == NULL)
+ {
+ 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_grs_send_coap_message(nsp_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(notification_message_ptr);
+
+ return return_msg_id;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * */
+/* GRS Wrapper */
+/* These are documented in sn_grs.c - file */
+/* * * * * * * * * * * * * * * * * * * * * */
+
+int16_t sn_nsdl_get_capability(void)
+{
+ return sn_grs_get_capability();
+}
+
+
+uint32_t sn_nsdl_get_version(void)
+{
+ return sn_grs_get_version();
+}
+
+
+int8_t sn_nsdl_process_http(uint8_t *packet_ptr, uint16_t *packet_len_ptr, sn_nsdl_addr_s *src_ptr)
+{
+ return sn_grs_process_http(packet_ptr, packet_len_ptr, src_ptr);
+}
+
+
+int8_t sn_nsdl_process_coap(uint8_t *packet_ptr, uint16_t packet_len_ptr, sn_nsdl_addr_s *src_ptr)
+{
+ return sn_grs_process_coap(packet_ptr, packet_len_ptr, src_ptr);
+}
+
+int8_t sn_nsdl_exec(uint32_t time)
+{
+ return sn_grs_exec(time);
+}
+
+int8_t sn_nsdl_create_resource(sn_nsdl_resource_info_s *res_ptr)
+{
+ return sn_grs_create_resource(res_ptr);
+}
+
+int8_t sn_nsdl_update_resource(sn_nsdl_resource_info_s *res_ptr)
+{
+ return sn_grs_update_resource(res_ptr);
+}
+
+int8_t sn_nsdl_delete_resource(uint8_t pathlen, uint8_t *path_ptr)
+{
+ return sn_grs_delete_resource(pathlen, path_ptr);
+}
+
+sn_nsdl_resource_info_s *sn_nsdl_get_resource(uint16_t pathlen, uint8_t *path_ptr)
+{
+ return sn_grs_get_resource(pathlen, path_ptr);
+}
+
+sn_grs_resource_list_s *sn_nsdl_list_resource(uint16_t pathlen, uint8_t *path_ptr)
+{
+ return sn_grs_list_resource(pathlen, path_ptr);
+}
+
+int8_t sn_nsdl_send_coap_message(sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr)
+{
+ return sn_grs_send_coap_message(address_ptr, coap_hdr_ptr);
+}
+
+/********************/
+/* Static functions */
+/********************/
+
+
+/**
+ * \fn static int8_t sn_nsdl_send_coap_message(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 *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 SN_NSDL_SUCCESS = 0, Failed = -1
+ */
+static int8_t sn_nsdl_internal_coap_send(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;
+ int16_t status = 0;
+
+ coap_message_len = sn_coap_builder_calc_needed_packet_data_size(coap_header_ptr);
+
+ if(coap_message_len == 0)
+ return SN_NSDL_FAILURE;
+
+ coap_message_ptr = sn_nsdl_alloc(coap_message_len);
+ if(!coap_message_ptr)
+ return SN_NSDL_FAILURE;
+
+ /* Build message */
+ status = sn_coap_protocol_build(dst_addr_ptr,coap_message_ptr, coap_header_ptr);
+
+ /* If message building failed */
+ if(status < 0)
+ {
+ sn_nsdl_free(coap_message_ptr);
+ return SN_NSDL_FAILURE;
+ }
+
+ /* If mesage type is confirmable, save it to list to wait for reply */
+ if(coap_header_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE)
+ {
+ sn_nsdl_sent_messages_s *message_ptr = sn_nsdl_alloc(sizeof(sn_nsdl_sent_messages_s));
+ if(message_ptr)
+ {
+ if(sn_linked_list_count_nodes(message_list_ptr) >= SN_NSDL_MAX_MESSAGE_COUNT)
+ {
+ sn_nsdl_sent_messages_s *message_temp_ptr = sn_linked_list_get_last_node(message_list_ptr);
+ if(message_temp_ptr)
+ sn_nsdl_free(message_temp_ptr);
+ sn_linked_list_remove_current_node(message_list_ptr);
+ }
+
+ message_ptr->message_type = message_description;
+ message_ptr->msg_id_number = coap_header_ptr->msg_id;
+ sn_linked_list_add_node(message_list_ptr, (void*)message_ptr);
+
+ status = SN_NSDL_SUCCESS;
+ }
+ else
+ {
+ status = SN_NSDL_FAILURE;
+ }
+
+ }
+
+ sn_nsdl_tx_callback(SN_NSDL_PROTOCOL_COAP, coap_message_ptr, coap_message_len, dst_addr_ptr);
+ sn_nsdl_free(coap_message_ptr);
+
+ return status;
+}
+
+/**
+ * \fn static void sn_nsdl_resolve_nsp_address(void)
+ *
+ * \brief Resolves NSP server address.
+ *
+ * \note Application must set NSP address with set_nsp_address
+ */
+static void sn_nsdl_resolve_nsp_address(void)
+{
+ /* Local variables */
+ if(!nsp_address_ptr)
+ {
+ //allocate only if previously not allocated
+ nsp_address_ptr = sn_nsdl_alloc(sizeof(sn_nsdl_addr_s));
+ }
+
+ if(nsp_address_ptr)
+ {
+ memset(nsp_address_ptr, 0, sizeof(sn_nsdl_addr_s));
+ /* This is only for version 0.5 */
+ nsp_address_ptr->type = SN_NSDL_ADDRESS_TYPE_NONE;
+ }
+
+ /* Todo: get NSP address */
+}
+
+/**
+ * \fn static int8_t sn_nsdl_build_registration_body(sn_coap_hdr_s *message_ptr)
+ *
+ * \brief To build GRS resources to registration message payload
+ *
+ * \param *message_ptr Pointer to CoAP message header
+ *
+ * \return SN_NSDL_SUCCESS = 0, Failed = -1
+ */
+int8_t sn_nsdl_build_registration_body(sn_coap_hdr_s *message_ptr, uint8_t updating_registeration)
+{
+ /* Local variables */
+ uint8_t *temp_ptr;
+ sn_nsdl_resource_info_s *resource_temp_ptr;
+
+
+ /* Get list of resources */
+
+
+ /* Calculate needed memory and allocate */
+ message_ptr->payload_len = sn_nsdl_calculate_registration_body_size(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 = 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();
+
+ /* 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();
+ continue;
+ }
+ else
+ {
+ resource_temp_ptr->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERING;
+ }
+
+ /* 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 - needs fixing */
+ /*
+ 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();
+
+ }
+
+ return SN_NSDL_SUCCESS;
+}
+
+/**
+ * \fn static uint16_t sn_nsdl_calculate_registration_body_size(sn_grs_resource_list_s *grs_resources_list_ptr)
+ *
+ *
+ * \brief Calculates registration message payload size
+ *
+ * \param *grs_resources_list_ptr Pointer to list of GRS resources
+ *
+ * \return Needed payload size
+ */
+static uint16_t sn_nsdl_calculate_registration_body_size(uint8_t updating_registeration)
+{
+ /* Local variables */
+ uint16_t return_value = 0;
+ sn_nsdl_resource_info_s *resource_temp_ptr;
+
+ /* check pointer */
+
+ resource_temp_ptr = sn_grs_get_first_resource();
+
+ 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();
+ 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 - needs fixing*/
+ /*
+ 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();
+
+ }
+
+ 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 SN_NSDL_SUCCESS = 0, Failed = -1
+ */
+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 += 2; //h=
+ number_of_parameters++;
+ }
+
+ if((endpoint_info_ptr->type_len != 0) && (endpoint_info_ptr->type_ptr != 0))
+ {
+ return_value+=endpoint_info_ptr->type_len;
+ return_value += 3;
+ 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 += 3;
+ 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(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 *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(sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type)
+{
+ uint8_t *temp_ptr = NULL;
+ 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 = 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;
+
+ 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 ?h=, 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))
+ {
+ if(temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr)
+ *temp_ptr++ = '&';
+
+ memcpy(temp_ptr, resource_type_parameter, sizeof(resource_type_parameter));
+ temp_ptr += RT_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;
+ }
+
+ return SN_NSDL_SUCCESS;
+}
+
+/**
+ * \fn static uint8_t sn_nsdl_local_rx_function(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 *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(sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr)
+{
+ int8_t status = 0;
+ uint16_t number_of_messages;
+ sn_nsdl_sent_messages_s *sent_message_temp_ptr;
+
+ if((coap_packet_ptr == 0) || (address_ptr == 0))
+ return -1;
+
+ /* If we wait for a response to some message.. */
+ number_of_messages = sn_linked_list_count_nodes(message_list_ptr);
+
+ if(number_of_messages)
+ {
+ while(number_of_messages--)
+ {
+ sent_message_temp_ptr = sn_linked_list_get_last_node(message_list_ptr);
+
+ if(sent_message_temp_ptr)
+ {
+ if(sent_message_temp_ptr->msg_id_number == coap_packet_ptr->msg_id)
+ {
+ switch(sent_message_temp_ptr->message_type)
+ {
+ case SN_NSDL_MSG_REGISTER:
+ if(coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CREATED)
+ {
+ sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_IS_REGISTERED;
+ sn_nsdl_mark_resources_as_registered();
+ status = sn_nsdl_resolve_ep_information(coap_packet_ptr);
+ if(status != SN_NSDL_SUCCESS)
+ {
+ /* Node can be removed */
+ sn_nsdl_free(sent_message_temp_ptr);
+ sn_linked_list_remove_current_node(message_list_ptr);
+ return status;
+ }
+ }
+ break;
+ case SN_NSDL_MSG_UNREGISTER:
+ if(coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_DELETED)
+ {
+ if(ep_information_ptr->endpoint_name_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->endpoint_name_ptr);
+ ep_information_ptr->endpoint_name_ptr = 0;
+ ep_information_ptr->endpoint_name_len = 0;
+ }
+
+ if(ep_information_ptr->domain_name_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->domain_name_ptr);
+ ep_information_ptr->domain_name_ptr = 0;
+ ep_information_ptr->domain_name_len = 0;
+ }
+
+ }
+ break;
+ case SN_NSDL_MSG_EVENT:
+ case SN_NSDL_MSG_UPDATE:
+ break;
+ }
+ /* Node can be removed */
+ sn_nsdl_free(sent_message_temp_ptr);
+ sn_linked_list_remove_current_node(message_list_ptr);
+
+ sn_nsdl_rx_callback(coap_packet_ptr, address_ptr);
+ return SN_NSDL_SUCCESS;
+ }
+ }
+ sent_message_temp_ptr = sn_linked_list_get_previous_node(message_list_ptr);
+ }
+ }
+
+ /* No messages to wait for, or message was not response to our request */
+ status = sn_nsdl_rx_callback(coap_packet_ptr, address_ptr);
+
+ return status;
+}
+
+void sn_nsdl_mark_resources_as_registered(void)
+{
+
+ sn_nsdl_resource_info_s *temp_resource;
+
+ temp_resource = sn_grs_get_first_resource();
+
+ while(temp_resource)
+ {
+
+ if(temp_resource->resource_parameters_ptr->registered == SN_NDSL_RESOURCE_REGISTERING)
+ {
+
+ temp_resource->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERED;
+
+ }
+
+ temp_resource = sn_grs_get_next_resource();
+
+ }
+
+
+}
+
+/**
+ * \fn static int8_t sn_nsdl_resolve_ep_information(sn_coap_hdr_s *coap_packet_ptr)
+ *
+ *
+ * \brief Resolves endpoint information from received CoAP message
+ *
+ * \param *coap_packet_ptr Pointer to received CoAP message
+ *
+ * \return SN_NSDL_SUCCESS = 0, Failed = -1
+ */
+static int8_t sn_nsdl_resolve_ep_information(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)
+ return SN_NSDL_FAILURE;
+ if(!coap_packet_ptr->options_list_ptr)
+ return SN_NSDL_FAILURE;
+ if(!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(!ep_information_ptr->domain_name_ptr)
+ {
+ ep_information_ptr->domain_name_len = parameter_len - 1;
+ ep_information_ptr->domain_name_ptr = sn_nsdl_alloc(ep_information_ptr->domain_name_len);
+ if(!ep_information_ptr->domain_name_ptr)
+ return SN_NSDL_FAILURE;
+ memcpy(ep_information_ptr->domain_name_ptr, temp_ptr - ep_information_ptr->domain_name_len, ep_information_ptr->domain_name_len);
+ }
+
+ }
+ if(parameter_count == 3)
+ {
+ if(!ep_information_ptr->endpoint_name_ptr)
+ {
+ ep_information_ptr->endpoint_name_len = parameter_len - 1;
+ ep_information_ptr->endpoint_name_ptr = sn_nsdl_alloc(ep_information_ptr->endpoint_name_len);
+ if(!ep_information_ptr->endpoint_name_ptr)
+ {
+ if(ep_information_ptr->domain_name_ptr)
+ {
+ sn_nsdl_free(ep_information_ptr->domain_name_ptr);
+ ep_information_ptr->domain_name_ptr = NULL;
+ ep_information_ptr->domain_name_len = 0;
+ }
+
+ return SN_NSDL_FAILURE;
+
+ }
+ memcpy(ep_information_ptr->endpoint_name_ptr, temp_ptr - ep_information_ptr->endpoint_name_len, ep_information_ptr->endpoint_name_len);
+ }
+ }
+ parameter_len = 0;
+ }
+ parameter_len++;
+ temp_ptr++;
+ }
+
+
+ return SN_NSDL_SUCCESS;
+}
+
+/**
+ * \fn int8_t set_NSP_address(uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type)
+ * \brief This function is used to set the NSP address given by an application.
+ * \param uint8_t *NSP_address Pointer to NSP address Note! IPv6 address must always be 16 bytes long and IPv4 address must always be 4 bytes long!
+ * \param uint16_t port NSP port
+ * \param sn_nsdl_addr_type_e address_type NSP address type (SN_NSDL_ADDRESS_TYPE_IPV6 or SN_NSDL_ADDRESS_TYPE_IPV4)
+ * \return 0 on success, -1 on false to indicate that NSDL internal address pointer is not allocated (call nsdl_init() first).
+ *
+ */
+int8_t set_NSP_address(uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type)
+{
+
+ /* Check parameters and source pointers */
+ if(!nsp_address_ptr || !NSP_address)
+ {
+ return -1;
+ }
+
+ nsp_address_ptr->type = address_type;
+
+ if(address_type == SN_NSDL_ADDRESS_TYPE_IPV4)
+ {
+ if(nsp_address_ptr->addr_ptr)
+ {
+ sn_nsdl_free(nsp_address_ptr->addr_ptr);
+ }
+
+ nsp_address_ptr->addr_len = 4;
+
+ nsp_address_ptr->addr_ptr = sn_nsdl_alloc(nsp_address_ptr->addr_len);
+ if(!nsp_address_ptr->addr_ptr)
+ return -1;
+
+ memcpy(nsp_address_ptr->addr_ptr, NSP_address, nsp_address_ptr->addr_len);
+ nsp_address_ptr->port = port;
+ }
+
+ else if(address_type == SN_NSDL_ADDRESS_TYPE_IPV6)
+ {
+ if(nsp_address_ptr->addr_ptr)
+ {
+ sn_nsdl_free(nsp_address_ptr->addr_ptr);
+ }
+
+ nsp_address_ptr->addr_len = 16;
+
+ nsp_address_ptr->addr_ptr = sn_nsdl_alloc(nsp_address_ptr->addr_len);
+ if(!nsp_address_ptr->addr_ptr)
+ return -1;
+
+ memcpy(nsp_address_ptr->addr_ptr, NSP_address, nsp_address_ptr->addr_len);
+ nsp_address_ptr->port = port;
+ }
+ return 0;
+}
+
+
+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);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sn_nsdl_lib.h Tue Feb 18 01:10:07 2014 +0000
@@ -0,0 +1,431 @@
+/**
+ * \file sn_nsdl_lib.h
+ *
+ * \brief NanoService Devices Library header file
+ *
+ * Created on: Aug 23, 2011
+ * Author: tero
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SN_NSDL_CONST_MEMORY_ATTRIBUTE
+
+#define SN_NSDL_ENDPOINT_NOT_REGISTERED 0
+#define SN_NSDL_ENDPOINT_IS_REGISTERED 1
+
+/**
+ * \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_ep_parameters_s;
+
+/**
+ * \brief For internal use
+ */
+typedef struct sn_nsdl_sent_messages_
+{
+ uint16_t msg_id_number;
+ uint8_t message_type;
+} sn_nsdl_sent_messages_s;
+
+/**
+ * \brief Function pointers used for memory allocation and freeing
+ */
+typedef struct sn_nsdl_mem_
+{
+ void *(*sn_nsdl_alloc)(uint16_t);
+ void (*sn_nsdl_free)(void *);
+} sn_nsdl_mem_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;
+
+/**
+ * \brief Used protocol
+ */
+typedef struct sn_proto_info_
+{
+ sn_nsdl_capab_e proto; /**< Only COAP is supported */
+} sn_proto_info_s;
+
+/**
+ * \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)(sn_coap_hdr_s *, sn_nsdl_addr_s *, sn_proto_info_s *);
+
+} sn_nsdl_resource_info_s;
+
+/**
+ * \fn extern int8_t 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 NSDL message (register message etc.), rx callback will be called.
+ *
+ * \param *sn_memory Memory structure which includes function pointers to the allocation and free functions.
+ *
+ * \return 0 Success
+ * \return -1 Failure
+ */
+extern int8_t 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);
+
+/**
+ * \fn extern uint8_t sn_nsdl_register_endpoint(sn_nsdl_ep_parameters_s *endpoint_info_ptr)
+ *
+ * \brief Registers endpoint to NSP server.
+ *
+ * \param *endpoint_info_ptr Contains endpoint information.
+ *
+ * \return 0 Success
+ * \return -1 Failure
+ */
+extern int8_t sn_nsdl_register_endpoint(sn_nsdl_ep_parameters_s *endpoint_info_ptr);
+
+/**
+ * \fn extern int8_t sn_nsdl_unregister_endpoint(void)
+ *
+ * \brief Sends unregister-message to NSP server.
+ *
+ * \return 0 Success
+ * \return -1 Failure
+ */
+extern int8_t sn_nsdl_unregister_endpoint(void);
+
+/**
+ * \fn extern int8_t sn_nsdl_update_registration(sn_nsdl_ep_parameters_s *endpoint_parameters_ptr);
+ *
+ * \brief Update the registration with NSP.
+ *
+ * \param *endpoint_info_ptr Contains endpoint information.
+ *
+ * \return 0 Success
+ * \return -1 Failure
+ */
+extern int8_t sn_nsdl_update_registration(sn_nsdl_ep_parameters_s *endpoint_parameters_ptr);
+
+/**
+ * \fn extern int8_t sn_nsdl_is_ep_registered(void)
+ *
+ * \brief Checks if endpoint is registered.
+ *
+ * \return 1 Endpoint registration is done successfully
+ * \return 0 Endpoint is not registered
+ */
+extern int8_t sn_nsdl_is_ep_registered(void);
+
+/**
+ * \fn extern void sn_nsdl_nsp_lost(void);
+ *
+ * \brief A function to inform NSDL-C library if application detects a fault in NSP registration.
+ *
+ * After calling this function sn_nsdl_is_ep_registered() will return "not registered".
+ */
+extern void sn_nsdl_nsp_lost(void);
+
+/**
+ * \fn extern uint16_t sn_nsdl_send_observation_notification(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 NSP server
+ *
+ * \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(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 int16_t sn_nsdl_get_capability(void)
+ *
+ * \brief Capability query function.
+ *
+ * Used to retrieve the list of supported protocols from the NSDL module.
+ *
+ * \return >0 Success, supported capabilities reported using bitmask with definitions from sn_nsdl_capab_t
+ * \return 0 Success, no supported capabilities
+ */
+extern int16_t sn_nsdl_get_capability(void);
+
+/**
+ * \fn extern uint32_t sn_nsdl_get_version(void)
+ *
+ * \brief Version query function.
+ *
+ * Used to retrieve the version information structure from the NSDL library.
+ *
+ * \return !0 MSB 2 bytes major version, LSB 2 bytes minor version.
+ * \return 0 Failure
+*/
+extern uint32_t sn_nsdl_get_version(void);
+
+/**
+ * \fn extern int8_t sn_nsdl_process_http(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src)
+ *
+ * \brief Currently HTTP is not supported
+ *
+ * \return -1 Failure
+ */
+extern int8_t sn_nsdl_process_http(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src);
+
+/**
+ * \fn extern int8_t sn_nsdl_process_coap(uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src)
+ *
+ * \brief To push CoAP packet to NSDL library
+ *
+ * Used to push an CoAP packet to NSDL library for processing.
+ *
+ * \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(uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src);
+
+/**
+ * \fn extern int8_t sn_nsdl_exec(uint32_t time);
+ *
+ * \brief CoAP retransmission function.
+ *
+ * Used to give execution time for the NSDL (CoAP) library for retransmissions. The NSDL library
+ * will call the exec functions of all enabled protocol modules.
+ *
+ * \param time Time in seconds.
+ *
+ * \return 0 Success
+ * \return -1 Failure
+ */
+extern int8_t sn_nsdl_exec(uint32_t time);
+
+/**
+ * \fn extern int8_t sn_nsdl_create_resource(sn_nsdl_resource_info_s *res)
+ *
+ * \brief Resource creating function.
+ *
+ * Used to create a static or dynamic HTTP(S) or 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(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 *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(sn_nsdl_resource_info_s *res);
+
+/**
+ * \fn extern int8_t sn_nsdl_delete_resource(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 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(uint8_t pathlen, uint8_t *path);
+
+/**
+ * \fn extern sn_nsdl_resource_info_s *sn_nsdl_get_resource(uint16_t pathlen, uint8_t *path)
+ *
+ * \brief Resource get function.
+ *
+ * Used to get a resource.
+ *
+ * \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(uint16_t pathlen, uint8_t *path);
+
+/**
+ * \fn extern sn_grs_resource_list_s *sn_nsdl_list_resource(uint16_t pathlen, uint8_t *path)
+ *
+ * \brief Resource list function.
+ *
+ * \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
+ */
+extern sn_grs_resource_list_s *sn_nsdl_list_resource(uint16_t pathlen, uint8_t *path);
+
+/**
+ * \fn extern int8_t sn_nsdl_send_coap_message(sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr);
+ *
+ * \brief Send an outgoing CoAP request.
+ *
+ * \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(sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr);
+
+/**
+ * \fn extern int8_t set_NSP_address(uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type);
+ *
+ * \brief This function is used to set the NSP address given by an application.
+ *
+ * \return 0 Success
+ * \return -1 Failed to indicate that NSDL internal address pointer is not allocated (call nsdl_init() first).
+ */
+extern int8_t set_NSP_address(uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type);
+
+/**
+ * \fn extern int8_t sn_nsdl_destroy(void);
+ *
+ * \brief This function releases all allocated memory in nsdl and grs modules.
+ */
+extern int8_t sn_nsdl_destroy(void);
+
+#ifdef __cplusplus
+}
+#endif
+