Manual NanoService C Client 1.11-RC2 import
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
diff -r aafd54b05111 -r 14a9b0f4b9d6 sn_grs.c --- /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; +} + +
diff -r aafd54b05111 -r 14a9b0f4b9d6 sn_grs.h --- /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 + + + + +
diff -r aafd54b05111 -r 14a9b0f4b9d6 sn_nsdl.c --- /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); +} +
diff -r aafd54b05111 -r 14a9b0f4b9d6 sn_nsdl_lib.h --- /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 +