hello

Dependents:   nespresso_demo nespresso_endpoint EnvoyNespressoEndpointColorDetectorV2

Fork of nsdl by Robert Taylor

Revision:
0:f6e4e1bbb3fe
Child:
2:05e4cd1a1542
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sn_nsdl.c	Wed Jun 04 15:38:26 2014 +0000
@@ -0,0 +1,1575 @@
+/**
+ * \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			3
+#define EP_NAME_PARAMETERS				{'e','p','='}
+
+#define RT_PARAMETER_LEN				3
+#define RT_PARAMETER					{'r','t','='}
+
+#define DOMAIN_PARAMETER_LEN			2
+#define DOMAIN_PARAMETER				{'d','='}
+
+#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		ep_domain_parameter[]		= DOMAIN_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;
+
+	/* 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 += EP_NAME_PARAMETERS_LEN;	//ep=
+		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 += RT_PARAMETER_LEN; 		//et=
+		number_of_parameters++;
+	}
+
+	if((endpoint_info_ptr->lifetime_len != 0) && (endpoint_info_ptr->lifetime_ptr != 0))
+	{
+		return_value+=endpoint_info_ptr->lifetime_len;
+		return_value += LT_PARAMETER_LEN;		//lt=
+		number_of_parameters++;
+	}
+
+	if((endpoint_info_ptr->domain_name_len != 0) && (endpoint_info_ptr->domain_name_ptr != 0))
+	{
+		return_value+=endpoint_info_ptr->domain_name_len;
+		return_value += DOMAIN_PARAMETER_LEN;		//d=
+		number_of_parameters++;
+	}
+
+	if(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 ?ep=, then endpoint name */
+		memcpy(temp_ptr, ep_name_parameter_string, sizeof(ep_name_parameter_string));
+		temp_ptr += EP_NAME_PARAMETERS_LEN;
+		memcpy(temp_ptr, parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len);
+		temp_ptr += parameter_ptr->endpoint_name_len;
+	}
+
+	/******************************************************/
+	/* If endpoint type is configured, fill needed fields */
+	/******************************************************/
+
+	if((parameter_ptr->type_len != 0) && (parameter_ptr->type_ptr != 0))
+	{
+		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;
+	}
+
+	/******************************************************/
+	/* If domain is configured, fill needed fields */
+	/******************************************************/
+
+	if((parameter_ptr->domain_name_len != 0) && (parameter_ptr->domain_name_ptr != 0))
+	{
+		if(temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr)
+			*temp_ptr++ = '&';
+
+		memcpy(temp_ptr, ep_domain_parameter, sizeof(ep_domain_parameter));
+		temp_ptr += DOMAIN_PARAMETER_LEN;
+		memcpy(temp_ptr, parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len);
+		temp_ptr += parameter_ptr->domain_name_len;
+	}
+
+	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);
+}