Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_nsdl.c Source File

sn_nsdl.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 /**
00017  * \file sn_nsdl.c
00018  *
00019  * \brief Nano service device library
00020  *
00021  */
00022 
00023 // Needed for PRIu64 on FreeRTOS
00024 #include <stdio.h>
00025 // Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX
00026 #ifndef __STDC_LIMIT_MACROS
00027 #define __STDC_LIMIT_MACROS
00028 #endif
00029 
00030 // Note: this macro is needed on armcc to get the the PRI*32 macros
00031 // from inttypes.h in a C++ code.
00032 #ifndef __STDC_FORMAT_MACROS
00033 #define __STDC_FORMAT_MACROS
00034 #endif
00035 
00036 #include <string.h>
00037 
00038 #include "ns_types.h"
00039 #include "sn_nsdl.h"
00040 #include "sn_coap_header.h"
00041 #include "sn_coap_protocol.h"
00042 #include "source/include/sn_coap_protocol_internal.h"
00043 #include "sn_nsdl_lib.h"
00044 #include "sn_grs.h"
00045 #include "mbed-trace/mbed_trace.h"
00046 #include "common_functions.h"
00047 #include <stdlib.h>
00048 
00049 /* Defines */
00050 #define TRACE_GROUP "mClt"
00051 #define RESOURCE_DIR_LEN                2
00052 #define EP_NAME_PARAMETERS_LEN          3
00053 #define ET_PARAMETER_LEN                3
00054 #define LT_PARAMETER_LEN                3
00055 #define DOMAIN_PARAMETER_LEN            2
00056 #define RT_PARAMETER_LEN                3
00057 #define IF_PARAMETER_LEN                3
00058 #define NAME_PARAMETER_LEN              5
00059 #define OBS_PARAMETER_LEN               3
00060 #define AOBS_PARAMETER_LEN              5
00061 #define COAP_CON_PARAMETER_LEN          3
00062 #define BS_EP_PARAMETER_LEN             3
00063 #define BS_QUEUE_MODE_PARAMATER_LEN     2
00064 
00065 #define SN_NSDL_EP_REGISTER_MESSAGE     1
00066 #define SN_NSDL_EP_UPDATE_MESSAGE       2
00067 
00068 #define SN_NSDL_MSG_UNDEFINED           0
00069 #define SN_NSDL_MSG_REGISTER            1
00070 #define SN_NSDL_MSG_UNREGISTER          2
00071 #define SN_NSDL_MSG_UPDATE              3
00072 #define SN_NSDL_MSG_BOOTSTRAP           4
00073 
00074 #ifdef YOTTA_CFG_DISABLE_OBS_FEATURE
00075 #define COAP_DISABLE_OBS_FEATURE YOTTA_CFG_DISABLE_OBS_FEATURE
00076 #elif defined MBED_CONF_MBED_CLIENT_COAP_DISABLE_OBS_FEATURE
00077 #define COAP_DISABLE_OBS_FEATURE MBED_CONF_MBED_CLIENT_COAP_DISABLE_OBS_FEATURE
00078 #endif
00079 
00080 #ifdef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE
00081 #define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE
00082 #elif defined MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00083 #define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00084 #endif
00085 
00086 /* Constants */
00087 static uint8_t      ep_name_parameter_string[]  = {'e', 'p', '='};      /* Endpoint name. A unique name for the registering node in a domain.  */
00088 static uint8_t      resource_path_ptr[]         = {'r', 'd'};           /* For resource directory */
00089 static uint8_t      resource_type_parameter[]   = {'r', 't', '='};      /* Resource type. Only once for registration */
00090 #ifndef COAP_DISABLE_OBS_FEATURE
00091 static uint8_t      obs_parameter[]             = {'o', 'b', 's'};      /* Observable */
00092 static uint8_t      aobs_parameter[]            = {'a', 'o', 'b', 's', '='}; /* Auto observable */
00093 #endif
00094 static uint8_t      if_description_parameter[]  = {'i', 'f', '='};      /* Interface description. Only once */
00095 static uint8_t      ep_lifetime_parameter[]     = {'l', 't', '='};      /* Lifetime. Number of seconds that this registration will be valid for. Must be updated within this time, or will be removed. */
00096 static uint8_t      ep_domain_parameter[]       = {'d', '='};           /* Domain name. If this parameter is missing, a default domain is assumed. */
00097 static uint8_t      coap_con_type_parameter[]   = {'c', 't', '='};      /* CoAP content type */
00098 
00099 #ifdef RESOURCE_ATTRIBUTES_LIST
00100 static uint8_t      name_parameter[]            = {'n', 'a', 'm', 'e', '='};
00101 #endif
00102 
00103 /* * OMA BS parameters * */
00104 static uint8_t bs_uri[]                         = {'b', 's'};
00105 static uint8_t bs_ep_name[]                     = {'e', 'p', '='};
00106 static uint8_t et_parameter[]                   = {'e', 't', '='};      /* Endpoint type */
00107 static uint8_t bs_queue_mode[]                  = {'b', '='};
00108 
00109 /* Function prototypes */
00110 static int32_t          sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description);
00111 static void             sn_nsdl_resolve_nsp_address(struct nsdl_s *handle);
00112 int8_t                  sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration);
00113 static uint16_t         sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error);
00114 static uint8_t          sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type, const char *uri_query);
00115 static int8_t           sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type, const char *uri_query);
00116 static int8_t           sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr);
00117 static int8_t           sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr);
00118 static uint8_t          sn_nsdl_itoa_len(uint32_t value);
00119 static uint8_t          *sn_nsdl_itoa(uint8_t *ptr, uint32_t value);
00120 static int8_t           set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr);
00121 static bool             validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr);
00122 static bool             validate(uint8_t* ptr, uint32_t len, char illegalChar);
00123 static bool             sn_nsdl_check_uint_overflow(uint16_t resource_size, uint16_t param_a, uint16_t param_b);
00124 static void             remove_previous_block_data(struct nsdl_s *handle, sn_nsdl_addr_s *src_ptr, const uint32_t block_number);
00125 static bool             update_last_block_data(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, bool block1);
00126 static void             sn_nsdl_print_coap_data(sn_coap_hdr_s *coap_header_ptr, bool outgoing);
00127 #if defined(FEA_TRACE_SUPPORT) || MBED_CONF_MBED_TRACE_ENABLE || YOTTA_CFG_MBED_TRACE || (defined(YOTTA_CFG) && !defined(NDEBUG))
00128 static const char*      sn_nsdl_coap_status_description(sn_coap_status_e status);
00129 static const char*      sn_nsdl_coap_message_code_desc(int msg_code);
00130 static const char*      sn_nsdl_coap_message_type_desc(int msg_type);
00131 #endif
00132 
00133 int8_t sn_nsdl_destroy(struct nsdl_s *handle)
00134 {
00135     if (handle == NULL) {
00136         return SN_NSDL_FAILURE;
00137     }
00138 
00139     if (handle->ep_information_ptr) {
00140         handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr);
00141         handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
00142         handle->sn_nsdl_free(handle->ep_information_ptr->location_ptr);
00143         handle->sn_nsdl_free(handle->ep_information_ptr->type_ptr);
00144         handle->sn_nsdl_free(handle->ep_information_ptr->lifetime_ptr);
00145         handle->sn_nsdl_free(handle->ep_information_ptr);
00146     }
00147 
00148     if (handle->nsp_address_ptr) {
00149         if (handle->nsp_address_ptr->omalw_address_ptr) {
00150             handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr);
00151             handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr);
00152         }
00153 
00154         handle->sn_nsdl_free(handle->nsp_address_ptr);
00155     }
00156 
00157     handle->sn_nsdl_free(handle->oma_bs_address_ptr);
00158 
00159     /* Destroy also libCoap and grs part of libNsdl */
00160     sn_coap_protocol_destroy(handle->grs->coap);
00161     sn_grs_destroy(handle->grs);
00162     handle->sn_nsdl_free(handle);
00163 
00164     return SN_NSDL_SUCCESS;
00165 }
00166 
00167 struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *),
00168                             uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
00169                             void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *),
00170                             uint8_t (*sn_nsdl_auto_obs_token_cb)(struct nsdl_s *, const char *, uint8_t *))
00171 {
00172     /* Check pointers and define function pointers */
00173     if (!sn_nsdl_alloc || !sn_nsdl_free || !sn_nsdl_tx_cb || !sn_nsdl_rx_cb) {
00174         return NULL;
00175     }
00176 
00177     struct nsdl_s *handle = NULL;
00178 
00179     handle = sn_nsdl_alloc(sizeof(struct nsdl_s));
00180 
00181     if (handle == NULL) {
00182         return NULL;
00183     }
00184 
00185     memset(handle, 0, sizeof(struct nsdl_s));
00186 
00187     /* Define function pointers */
00188     handle->sn_nsdl_alloc = sn_nsdl_alloc;
00189     handle->sn_nsdl_free = sn_nsdl_free;
00190 
00191     handle->sn_nsdl_tx_callback = sn_nsdl_tx_cb;
00192     handle->sn_nsdl_rx_callback = sn_nsdl_rx_cb;
00193     handle->sn_nsdl_auto_obs_token_callback = sn_nsdl_auto_obs_token_cb;
00194 
00195     /* Initialize ep parameters struct */
00196     if (!handle->ep_information_ptr) {
00197         handle->ep_information_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_ep_parameters_s));
00198         if (!handle->ep_information_ptr) {
00199             sn_nsdl_free(handle);
00200             return NULL;
00201         }
00202         memset(handle->ep_information_ptr, 0, sizeof(sn_nsdl_ep_parameters_s));
00203     }
00204 
00205     handle->grs = sn_grs_init(sn_nsdl_tx_cb, &sn_nsdl_local_rx_function, sn_nsdl_alloc, sn_nsdl_free);
00206 
00207     /* Initialize GRS */
00208     if (handle->grs == NULL) {
00209         handle->sn_nsdl_free(handle->ep_information_ptr);
00210         handle->ep_information_ptr = 0;
00211         sn_nsdl_free(handle);
00212         return NULL;
00213     }
00214 
00215     sn_nsdl_resolve_nsp_address(handle);
00216 
00217     handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED;
00218     handle->context = NULL;
00219 
00220     return handle;
00221 }
00222 
00223 uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle,
00224                                    sn_nsdl_ep_parameters_s *endpoint_info_ptr,
00225                                    const char *uri_query_parameters)
00226 {
00227     /* Local variables */
00228     sn_coap_hdr_s   *register_message_ptr;
00229     uint16_t        message_id  = 0;
00230 
00231     if (endpoint_info_ptr == NULL || handle == NULL) {
00232         return 0;
00233     }
00234 
00235     /*** Build endpoint register message ***/
00236 
00237     /* Allocate memory for header struct */
00238     register_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
00239     if (register_message_ptr == NULL) {
00240         return 0;
00241     }
00242 
00243     /* Fill message fields -> confirmable post to specified NSP path */
00244     register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
00245     register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST;
00246 
00247     /* Allocate memory for the extended options list */
00248     if (sn_coap_parser_alloc_options(handle->grs->coap, register_message_ptr) == NULL) {
00249         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00250         register_message_ptr = 0;
00251         return 0;
00252     }
00253 
00254     register_message_ptr->uri_path_len = sizeof(resource_path_ptr);
00255     register_message_ptr->uri_path_ptr = resource_path_ptr;
00256 
00257     /* Fill Uri-query options */
00258     if( SN_NSDL_FAILURE == sn_nsdl_fill_uri_query_options(handle, endpoint_info_ptr,
00259                                                           register_message_ptr, SN_NSDL_EP_REGISTER_MESSAGE,
00260                                                           uri_query_parameters) ){
00261         register_message_ptr->uri_path_ptr = NULL;
00262         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00263         return 0;
00264     }
00265 
00266     if (endpoint_info_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) {
00267         /* Built body for message */
00268         if (sn_nsdl_build_registration_body(handle, register_message_ptr, 0) == SN_NSDL_FAILURE) {
00269             register_message_ptr->uri_path_ptr = NULL;
00270             register_message_ptr->options_list_ptr->uri_host_ptr = NULL;
00271             sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00272             return 0;
00273         }
00274     }
00275 
00276     /* Clean (possible) existing and save new endpoint info to handle */
00277     if (set_endpoint_info(handle, endpoint_info_ptr) == -1) {
00278 
00279         handle->sn_nsdl_free(register_message_ptr->payload_ptr);
00280         register_message_ptr->payload_ptr = NULL;
00281 
00282         register_message_ptr->uri_path_ptr = NULL;
00283         register_message_ptr->options_list_ptr->uri_host_ptr = NULL;
00284 
00285         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00286 
00287         return 0;
00288     }
00289 
00290     /* Build and send coap message to NSP */
00291     message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_REGISTER);
00292 
00293     handle->sn_nsdl_free(register_message_ptr->payload_ptr);
00294     register_message_ptr->payload_ptr = NULL;
00295 
00296     register_message_ptr->uri_path_ptr = NULL;
00297     register_message_ptr->options_list_ptr->uri_host_ptr = NULL;
00298 
00299     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00300 
00301     return message_id;
00302 }
00303 
00304 int32_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle)
00305 {
00306     /* Local variables */
00307     sn_coap_hdr_s   *unregister_message_ptr;
00308     uint8_t         *temp_ptr = 0;
00309     int32_t        message_id = 0;
00310 
00311     /* Check parameters */
00312     if (handle == NULL) {
00313         return 0;
00314     }
00315 
00316     /* Check that EP have been registered */
00317     if (sn_nsdl_is_ep_registered(handle)) {
00318 
00319         /* Memory allocation for unregister message */
00320         unregister_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
00321         if (!unregister_message_ptr) {
00322             return 0;
00323         }
00324 
00325         /* Fill unregister message */
00326         unregister_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
00327         unregister_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_DELETE;
00328 
00329         if(handle->ep_information_ptr->location_ptr) {
00330             unregister_message_ptr->uri_path_len = handle->ep_information_ptr->location_len;
00331             unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len);
00332             if (!unregister_message_ptr->uri_path_ptr) {
00333                 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr);
00334                 return 0;
00335             }
00336 
00337             temp_ptr = unregister_message_ptr->uri_path_ptr;
00338 
00339             memcpy(temp_ptr , handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len);
00340         } else {
00341             unregister_message_ptr->uri_path_len = (RESOURCE_DIR_LEN + 1 + handle->ep_information_ptr->domain_name_len + 1 + handle->ep_information_ptr->endpoint_name_len);
00342             unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len);
00343             if (!unregister_message_ptr->uri_path_ptr) {
00344                 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr);
00345                 return 0;
00346             }
00347 
00348             temp_ptr = unregister_message_ptr->uri_path_ptr;
00349 
00350             memcpy(temp_ptr, resource_path_ptr, RESOURCE_DIR_LEN);
00351             temp_ptr += RESOURCE_DIR_LEN;
00352 
00353             *temp_ptr++ = '/';
00354 
00355             memcpy(temp_ptr , handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len);
00356             temp_ptr += handle->ep_information_ptr->domain_name_len;
00357 
00358             *temp_ptr++ = '/';
00359 
00360             memcpy(temp_ptr , handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len);
00361         }
00362 
00363         /* Send message */
00364         message_id = sn_nsdl_internal_coap_send(handle, unregister_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UNREGISTER);
00365 
00366         /* Free memory */
00367         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr);
00368 
00369     }
00370 
00371     return message_id;
00372 }
00373 
00374 int32_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len)
00375 {
00376     /* Local variables */
00377     sn_coap_hdr_s   *register_message_ptr;
00378     uint8_t         *temp_ptr;
00379     sn_nsdl_ep_parameters_s temp_parameters;
00380     int32_t        message_id = 0;
00381 
00382     /* Check parameters */
00383     if (handle == NULL) {
00384         return 0;
00385     }
00386 
00387     if (!sn_nsdl_is_ep_registered(handle)){
00388         return 0;
00389     }
00390 
00391     memset(&temp_parameters, 0, sizeof(sn_nsdl_ep_parameters_s));
00392 
00393     temp_parameters.lifetime_len = lt_len;
00394     temp_parameters.lifetime_ptr = lt_ptr;
00395 
00396     /*** Build endpoint register update message ***/
00397 
00398     /* Allocate memory for header struct */
00399     register_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
00400     if (register_message_ptr == NULL) {
00401         return 0;
00402     }
00403 
00404     /* Fill message fields -> confirmable post to specified NSP path */
00405     register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
00406     register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST;
00407 
00408     if(handle->ep_information_ptr->location_ptr) {
00409         register_message_ptr->uri_path_len  =   handle->ep_information_ptr->location_len;    /* = Only location set by Device Server*/
00410 
00411         register_message_ptr->uri_path_ptr  =   handle->sn_nsdl_alloc(register_message_ptr->uri_path_len);
00412         if (!register_message_ptr->uri_path_ptr) {
00413             sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00414             return 0;
00415         }
00416 
00417         temp_ptr = register_message_ptr->uri_path_ptr;
00418 
00419         /* location */
00420         memcpy(temp_ptr, handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len);
00421     } else {
00422         register_message_ptr->uri_path_len  =   sizeof(resource_path_ptr) + handle->ep_information_ptr->domain_name_len + handle->ep_information_ptr->endpoint_name_len + 2;    /* = rd/domain/endpoint */
00423 
00424         register_message_ptr->uri_path_ptr  =   handle->sn_nsdl_alloc(register_message_ptr->uri_path_len);
00425         if (!register_message_ptr->uri_path_ptr) {
00426             sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00427             return 0;
00428         }
00429 
00430         temp_ptr = register_message_ptr->uri_path_ptr;
00431 
00432         /* rd/ */
00433         memcpy(temp_ptr, resource_path_ptr, sizeof(resource_path_ptr));
00434         temp_ptr += sizeof(resource_path_ptr);
00435         *temp_ptr++ = '/';
00436 
00437         /* rd/DOMAIN/ */
00438         memcpy(temp_ptr, handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len);
00439         temp_ptr += handle->ep_information_ptr->domain_name_len;
00440         *temp_ptr++ = '/';
00441 
00442         /* rd/domain/ENDPOINT */
00443         memcpy(temp_ptr, handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len);
00444     }
00445 
00446     /* Allocate memory for the extended options list */
00447     if (sn_coap_parser_alloc_options(handle->grs->coap, register_message_ptr) == NULL) {
00448         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00449         return 0;
00450     }
00451 
00452     /* Fill Uri-query options */
00453     sn_nsdl_fill_uri_query_options(handle, &temp_parameters, register_message_ptr, SN_NSDL_EP_UPDATE_MESSAGE, NULL);
00454 
00455     /* Build payload */
00456     if (handle->ep_information_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) {
00457 
00458         if (sn_nsdl_build_registration_body(handle, register_message_ptr, 1) == SN_NSDL_FAILURE) {
00459             sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00460             return 0;
00461         }
00462     }
00463 
00464     /* Build and send coap message to NSP */
00465     message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UPDATE);
00466 
00467     handle->sn_nsdl_free(register_message_ptr->payload_ptr);
00468 
00469     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
00470 
00471     return message_id;
00472 }
00473 
00474 int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len)
00475 {
00476     if(!handle || !location_ptr || (location_len == 0)) {
00477         return -1;
00478     }
00479 
00480     handle->sn_nsdl_free(handle->ep_information_ptr->location_ptr);
00481     handle->ep_information_ptr->location_ptr = handle->sn_nsdl_alloc(location_len);
00482     memcpy(handle->ep_information_ptr->location_ptr, location_ptr, location_len);
00483     handle->ep_information_ptr->location_len = location_len;
00484 
00485     return 0;
00486 }
00487 
00488 void sn_nsdl_nsp_lost(struct nsdl_s *handle)
00489 {
00490     /* Check parameters */
00491     if (handle == NULL) {
00492         return;
00493     }
00494 
00495     handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED;
00496 }
00497 
00498 int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle)
00499 {
00500     /* Check parameters */
00501     if (handle == NULL) {
00502         return SN_NSDL_FAILURE;
00503     }
00504 
00505     return handle->sn_nsdl_endpoint_registered;
00506 }
00507 
00508 int32_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len,
00509    uint8_t *payload_ptr, uint16_t payload_len, sn_coap_observe_e observe, sn_coap_msg_type_e message_type,
00510    sn_coap_content_format_e content_format,
00511    const int32_t message_id)
00512 {
00513     sn_coap_hdr_s   *notification_message_ptr;
00514     int32_t         return_msg_id = 0;
00515 
00516     /* Check parameters */
00517     if (handle == NULL || handle->grs == NULL) {
00518         return 0;
00519     }
00520 
00521     /* Allocate and initialize memory for header struct */
00522     notification_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
00523     if (notification_message_ptr == NULL) {
00524         return 0;
00525     }
00526 
00527     if (sn_coap_parser_alloc_options(handle->grs->coap, notification_message_ptr) == NULL) {
00528         handle->sn_nsdl_free(notification_message_ptr);
00529         return 0;
00530     }
00531 
00532     /* Fill header */
00533     notification_message_ptr->msg_type = message_type;
00534     notification_message_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00535 
00536     /* Fill token */
00537     notification_message_ptr->token_len = token_len;
00538     notification_message_ptr->token_ptr = token_ptr;
00539 
00540     /* Fill payload */
00541     notification_message_ptr->payload_len = payload_len;
00542     notification_message_ptr->payload_ptr = payload_ptr;
00543 
00544     /* Fill observe */
00545     notification_message_ptr->options_list_ptr->observe = observe;
00546 
00547     /* Fill content format */
00548     notification_message_ptr->content_format = content_format;
00549 
00550     if (message_id != -1) {
00551         notification_message_ptr->msg_id = message_id;
00552     }
00553 
00554     /* Send message */
00555     return_msg_id = sn_nsdl_send_coap_message(handle, handle->nsp_address_ptr->omalw_address_ptr, notification_message_ptr);
00556     if (return_msg_id >= SN_NSDL_SUCCESS) {
00557         return_msg_id = notification_message_ptr->msg_id;
00558     }
00559 
00560     /* Free memory */
00561     notification_message_ptr->payload_ptr = NULL;
00562     notification_message_ptr->token_ptr = NULL;
00563 
00564     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, notification_message_ptr);
00565 
00566     return return_msg_id;
00567 }
00568 
00569 /* * * * * * * * * * */
00570 /* ~ OMA functions ~ */
00571 /* * * * * * * * * * */
00572 
00573 uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr,
00574                                sn_nsdl_ep_parameters_s *endpoint_info_ptr,
00575                                sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr,
00576                                const char *uri_query_parameters)
00577 {
00578 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00579     /* Local variables */
00580     sn_coap_hdr_s bootstrap_coap_header;
00581     uint8_t *uri_query_tmp_ptr;
00582     uint16_t message_id = 0;
00583 
00584     /* Check parameters */
00585     if (!bootstrap_address_ptr || !bootstrap_endpoint_info_ptr || !endpoint_info_ptr || !handle) {
00586         return 0;
00587     }
00588 
00589     handle->sn_nsdl_oma_bs_done_cb = bootstrap_endpoint_info_ptr->oma_bs_status_cb;
00590     handle->sn_nsdl_oma_bs_done_cb_handle = bootstrap_endpoint_info_ptr->oma_bs_status_cb_handle;
00591 
00592     /* XXX FIX -- Init CoAP header struct */
00593     sn_coap_parser_init_message(&bootstrap_coap_header);
00594 
00595     if (!sn_coap_parser_alloc_options(handle->grs->coap, &bootstrap_coap_header)) {
00596         return 0;
00597     }
00598 
00599     /* Build bootstrap start message */
00600     bootstrap_coap_header.msg_code = COAP_MSG_CODE_REQUEST_POST;
00601     bootstrap_coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE;
00602 
00603     bootstrap_coap_header.uri_path_ptr = bs_uri;
00604     bootstrap_coap_header.uri_path_len = sizeof(bs_uri);
00605 
00606     size_t query_len = endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN;
00607     size_t optional_params_len = 0;
00608     if (uri_query_parameters) {
00609         optional_params_len = strlen(uri_query_parameters);
00610     }
00611 
00612     query_len += optional_params_len;
00613 
00614     if (query_len > MAX_URI_QUERY_LEN) {
00615         handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr);
00616         tr_error("sn_nsdl_oma_bootstrap - max param length reached (%d)", query_len);
00617         return 0;
00618     }
00619 
00620     uri_query_tmp_ptr = handle->sn_nsdl_alloc(query_len);
00621     if (!uri_query_tmp_ptr) {
00622         handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr);
00623         return 0;
00624     }
00625 
00626     memcpy(uri_query_tmp_ptr, bs_ep_name, BS_EP_PARAMETER_LEN);
00627     memcpy((uri_query_tmp_ptr + BS_EP_PARAMETER_LEN),
00628            endpoint_info_ptr->endpoint_name_ptr,
00629            endpoint_info_ptr->endpoint_name_len);
00630 
00631     if (optional_params_len > 0) {
00632         memcpy(uri_query_tmp_ptr + endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN,
00633                uri_query_parameters,
00634                optional_params_len);
00635     }
00636 
00637     bootstrap_coap_header.options_list_ptr->uri_query_len = query_len;
00638     bootstrap_coap_header.options_list_ptr->uri_query_ptr = uri_query_tmp_ptr;
00639 
00640     /* Save bootstrap server address */
00641     handle->oma_bs_address_len = bootstrap_address_ptr->addr_len;       /* Length.. */
00642     handle->oma_bs_address_ptr = handle->sn_nsdl_alloc(handle->oma_bs_address_len);     /* Address.. */
00643     if (!handle->oma_bs_address_ptr) {
00644         handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr);
00645         handle->sn_nsdl_free(uri_query_tmp_ptr);
00646         return 0;
00647     }
00648     memcpy(handle->oma_bs_address_ptr, bootstrap_address_ptr->addr_ptr, handle->oma_bs_address_len);
00649     handle->oma_bs_port = bootstrap_address_ptr->port;                  /* And port */
00650 
00651     /* Send message */
00652     message_id = sn_nsdl_internal_coap_send(handle, &bootstrap_coap_header, bootstrap_address_ptr, SN_NSDL_MSG_BOOTSTRAP);
00653 
00654     /* Free allocated memory */
00655     handle->sn_nsdl_free(uri_query_tmp_ptr);
00656     handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr);
00657 
00658     return message_id;
00659 #else
00660     return 0;
00661 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00662 
00663 }
00664 
00665 char *sn_nsdl_get_version(void)
00666 {
00667 #if defined(YOTTA_MBED_CLIENT_C_VERSION_STRING)
00668     return YOTTA_MBED_CLIENT_C_VERSION_STRING;
00669 #elif defined(VERSION)
00670     return VERSION;
00671 #else
00672     return "0.0.0";
00673 #endif
00674 }
00675 
00676 int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet_ptr, uint16_t packet_len, sn_nsdl_addr_s *src_ptr)
00677 {
00678     sn_coap_hdr_s           *coap_packet_ptr    = NULL;
00679     sn_coap_hdr_s           *coap_response_ptr  = NULL;
00680     sn_nsdl_dynamic_resource_parameters_s *resource = NULL;
00681     /* Check parameters */
00682     if (handle == NULL) {
00683         return SN_NSDL_FAILURE;
00684     }
00685 
00686     /* Parse CoAP packet */
00687     coap_packet_ptr = sn_coap_protocol_parse(handle->grs->coap, src_ptr, packet_len, packet_ptr, (void *)handle);
00688 
00689     /* Check if parsing was successfull */
00690     if (coap_packet_ptr == (sn_coap_hdr_s *)NULL) {
00691         return SN_NSDL_FAILURE;
00692     }
00693 
00694 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
00695     // Pass block to application if external_memory_block is set
00696     if((coap_packet_ptr->options_list_ptr &&
00697         coap_packet_ptr->options_list_ptr->block1 != -1) &&
00698         (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING ||
00699         coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED)) {
00700         // Block 1 handling
00701         /* Get resource */
00702         char* path = handle->sn_nsdl_alloc(coap_packet_ptr->uri_path_len + 1);
00703         if (!path) {
00704             return SN_NSDL_FAILURE;
00705         }
00706 
00707         memcpy(path,
00708                 coap_packet_ptr->uri_path_ptr,
00709                 coap_packet_ptr->uri_path_len);
00710         path[coap_packet_ptr->uri_path_len] = '\0';
00711 
00712 
00713         resource = sn_nsdl_get_resource(handle, path);
00714         handle->sn_nsdl_free(path);
00715 
00716         if (coap_packet_ptr->options_list_ptr) {
00717             if(resource &&
00718                resource->static_resource_parameters->external_memory_block &&
00719                coap_packet_ptr->options_list_ptr->block1) {
00720 
00721                 uint32_t block_number = coap_packet_ptr->options_list_ptr->block1 >> 4;
00722                 if (block_number) {
00723                     remove_previous_block_data(handle, src_ptr, block_number);
00724                 }
00725 
00726                 // Whole message received --> pass only the last block data to application
00727                 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) {
00728                     // Get the block size
00729                     uint8_t temp = (coap_packet_ptr->options_list_ptr->block1 & 0x07);
00730                     uint16_t block_size = 1u << (temp + 4);
00731 
00732                     uint32_t new_payload_len = coap_packet_ptr->payload_len - block_size;
00733                     uint8_t *temp_ptr =  handle->grs->coap->sn_coap_protocol_malloc(new_payload_len);
00734                     if (temp_ptr) {
00735                         // Skip the second last block data since it's still stored in mbed-coap list!
00736                         memcpy(temp_ptr, coap_packet_ptr->payload_ptr + block_size, new_payload_len);
00737                         handle->grs->coap->sn_coap_protocol_free(coap_packet_ptr->payload_ptr);
00738                         coap_packet_ptr->payload_ptr = NULL;
00739 
00740                         coap_packet_ptr->payload_ptr = handle->grs->coap->sn_coap_protocol_malloc(new_payload_len);
00741                         if (coap_packet_ptr->payload_ptr) {
00742                             memcpy(coap_packet_ptr->payload_ptr, temp_ptr, new_payload_len);
00743                             coap_packet_ptr->payload_len = new_payload_len;
00744                         }
00745 
00746                         handle->grs->coap->sn_coap_protocol_free(temp_ptr);
00747                     }
00748                 }
00749             } else {
00750                 resource = NULL;
00751             }
00752         } else {
00753             resource = NULL;
00754         }
00755     }
00756 #endif
00757 
00758     sn_nsdl_print_coap_data(coap_packet_ptr, false);
00759 
00760     // Handling of GET responses
00761     if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CONTENT) {
00762         bool data_updated = false;
00763         if (coap_packet_ptr->options_list_ptr && coap_packet_ptr->options_list_ptr->block2 != -1) {
00764             uint32_t block_number = coap_packet_ptr->options_list_ptr->block2 >> 4;
00765             if (block_number) {
00766                 remove_previous_block_data(handle, src_ptr, block_number);
00767             }
00768 
00769             // Modify payload to have only last received block data
00770             data_updated = update_last_block_data(handle, coap_packet_ptr, false);
00771         }
00772 
00773         handle->sn_nsdl_rx_callback(handle, coap_packet_ptr, src_ptr);
00774         if (data_updated) {
00775             handle->grs->coap->sn_coap_protocol_free(coap_packet_ptr->payload_ptr);
00776         }
00777 
00778         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00779         return SN_NSDL_SUCCESS;
00780     }
00781 
00782     /* Check, if coap itself sends response, or block receiving is ongoing... */
00783     if (coap_packet_ptr->coap_status != COAP_STATUS_OK &&
00784         coap_packet_ptr->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED &&
00785         coap_packet_ptr &&
00786         !resource) {
00787         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00788         return SN_NSDL_SUCCESS;
00789     }
00790 
00791     /* If proxy options added, return not supported */
00792     if (coap_packet_ptr->options_list_ptr) {
00793         if (coap_packet_ptr->options_list_ptr->proxy_uri_len) {
00794             coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED);
00795             if (coap_response_ptr) {
00796                 sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr);
00797                 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr);
00798                 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00799                 return SN_NSDL_SUCCESS;
00800             } else {
00801                 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00802                 return SN_NSDL_FAILURE;
00803             }
00804         }
00805     }
00806 
00807     /* * * * * * * * * * * * * * * * * * * * * * * * * * */
00808     /* If message is response message, call RX callback  */
00809     /* * * * * * * * * * * * * * * * * * * * * * * * * * */
00810 
00811     if (((coap_packet_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) ||
00812             (coap_packet_ptr->msg_type >= COAP_MSG_TYPE_ACKNOWLEDGEMENT))) {
00813         int8_t retval = sn_nsdl_local_rx_function(handle, coap_packet_ptr, src_ptr);
00814         if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED &&
00815                 coap_packet_ptr->payload_ptr) {
00816             handle->sn_nsdl_free(coap_packet_ptr->payload_ptr);
00817             coap_packet_ptr->payload_ptr = 0;
00818         }
00819         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00820         return retval;
00821     }
00822 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00823     /* * If OMA bootstrap message... * */
00824     bool bootstrap_msg = src_ptr && (handle->oma_bs_address_len == src_ptr->addr_len) &&
00825             (handle->oma_bs_port == src_ptr->port) &&
00826             !memcmp(handle->oma_bs_address_ptr, src_ptr->addr_ptr, handle->oma_bs_address_len);
00827 
00828     // Pass bootstrap data to application
00829     if (bootstrap_msg) {
00830         handle->sn_nsdl_rx_callback(handle, coap_packet_ptr,src_ptr);
00831         if (coap_packet_ptr &&
00832             coap_packet_ptr->options_list_ptr &&
00833             coap_packet_ptr->coap_status != COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED &&
00834             coap_packet_ptr->options_list_ptr->block1 != -1) {
00835                 handle->sn_nsdl_free(coap_packet_ptr->payload_ptr);
00836                 coap_packet_ptr->payload_ptr = NULL;
00837         }
00838         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00839         return SN_NSDL_SUCCESS;
00840     }
00841 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00842 
00843     /* * * * * * * * * * * * * * * */
00844     /* Other messages are for GRS  */
00845     /* * * * * * * * * * * * * * * */
00846     return sn_grs_process_coap(handle, coap_packet_ptr, src_ptr);
00847 }
00848 
00849 int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time)
00850 {
00851     if(!handle || !handle->grs){
00852         return SN_NSDL_FAILURE;
00853     }
00854     /* Call CoAP execution function */
00855     return sn_coap_protocol_exec(handle->grs->coap, time);
00856 }
00857 
00858 sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_resource(struct nsdl_s *handle, const char *path_ptr)
00859 {
00860     /* Check parameters */
00861     if (handle == NULL) {
00862         return NULL;
00863     }
00864 
00865     return sn_grs_search_resource(handle->grs, path_ptr, SN_GRS_SEARCH_METHOD);
00866 }
00867 
00868 
00869 /**
00870  * \fn static int32_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description)
00871  *
00872  *
00873  * \brief To send NSDL messages. Stores message id?s and message description to catch response from NSP server
00874  * \param   *handle             Pointer to nsdl-library handle
00875  * \param   *coap_header_ptr    Pointer to the CoAP message header to be sent
00876  * \param   *dst_addr_ptr       Pointer to the address structure that contains destination address information
00877  * \param   message_description Message description to be stored to list for waiting response
00878  *
00879  * \return  message id, <=0 if failed
00880  */
00881 static int32_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description)
00882 {
00883 
00884     tr_debug("sn_nsdl_internal_coap_send");
00885     uint8_t     *coap_message_ptr   = NULL;
00886     int32_t     coap_message_len    = 0;
00887     uint16_t    coap_header_len     = 0;
00888 
00889 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */
00890     int8_t ret_val = prepare_blockwise_message(handle->grs->coap, coap_header_ptr);
00891     if( 0 != ret_val ) {
00892         return 0;
00893     }
00894 #endif
00895 
00896     coap_message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_header_ptr, handle->grs->coap->sn_coap_block_data_size);
00897     tr_debug("sn_nsdl_internal_coap_send - msg len after calc: %" PRId32 "", coap_message_len);
00898     if (coap_message_len == 0) {
00899         return 0;
00900     }
00901 
00902     coap_message_ptr = handle->sn_nsdl_alloc(coap_message_len);
00903     if (!coap_message_ptr) {
00904         return 0;
00905     }
00906 
00907     coap_header_len = coap_header_ptr->payload_len;
00908 
00909     /* Build message */
00910     int16_t ret = sn_coap_protocol_build(handle->grs->coap, dst_addr_ptr, coap_message_ptr, coap_header_ptr, (void *)handle);
00911     if (ret < 0) {
00912         handle->sn_nsdl_free(coap_message_ptr);
00913         return ret;
00914     }
00915 
00916     /* If message type is confirmable, save it to list to wait for reply */
00917     if (coap_header_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
00918         if (message_description == SN_NSDL_MSG_REGISTER) {
00919             handle->register_msg_id = coap_header_ptr->msg_id;
00920             handle->register_msg_len = coap_header_len;
00921         }
00922         else if (message_description == SN_NSDL_MSG_UNREGISTER) {
00923             handle->unregister_msg_id = coap_header_ptr->msg_id;
00924         }
00925         else if (message_description == SN_NSDL_MSG_UPDATE) {
00926             handle->update_register_msg_id = coap_header_ptr->msg_id;
00927             handle->update_register_msg_len = coap_header_len;
00928         }
00929         else if (message_description == SN_NSDL_MSG_BOOTSTRAP) {
00930             handle->bootstrap_msg_id = coap_header_ptr->msg_id;
00931         }
00932     }
00933     sn_nsdl_print_coap_data(coap_header_ptr, true);
00934     handle->sn_nsdl_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, coap_message_ptr, coap_message_len, dst_addr_ptr);
00935     handle->sn_nsdl_free(coap_message_ptr);
00936 
00937     return coap_header_ptr->msg_id;
00938 }
00939 
00940 /**
00941  * \fn static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle)
00942  *
00943  * \brief Resolves NSP server address.
00944  *
00945  * \param *handle Pointer to nsdl-library handle
00946  * \note Application must set NSP address with set_nsp_address
00947  */
00948 static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle)
00949 {
00950     /* Local variables */
00951     if (!handle->nsp_address_ptr) {
00952         //allocate only if previously not allocated
00953         handle->nsp_address_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_oma_server_info_t));
00954     }
00955 
00956     if (handle->nsp_address_ptr) {
00957         handle->nsp_address_ptr->omalw_server_security = SEC_NOT_SET;
00958         handle->nsp_address_ptr->omalw_address_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_addr_s));
00959         if (handle->nsp_address_ptr->omalw_address_ptr) {
00960             memset(handle->nsp_address_ptr->omalw_address_ptr, 0, sizeof(sn_nsdl_addr_s));
00961             handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_NONE;
00962         }
00963     }
00964 }
00965 
00966 #ifdef RESOURCE_ATTRIBUTES_LIST
00967 static char *sn_nsdl_build_resource_attribute_str(char *dst, const sn_nsdl_attribute_item_s *attribute, const char *name, const size_t name_len)
00968 {
00969     if (attribute != NULL && name != NULL && name_len > 0 && attribute->value) {
00970         size_t attribute_len = strlen(attribute->value);
00971         *dst++ = ';';
00972         memcpy(dst, name, name_len);
00973         dst += name_len;
00974         *dst++ = '"';
00975         memcpy(dst,
00976                attribute->value,
00977                attribute_len);
00978         dst += attribute_len;
00979         *dst++ = '"';
00980     }
00981     return dst;
00982 }
00983 #endif
00984 
00985 /**
00986  * \fn int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration)
00987  *
00988  * \brief   To build GRS resources to registration message payload
00989  * \param *handle Pointer to nsdl-library handle
00990  * \param   *message_ptr Pointer to CoAP message header
00991  *
00992  * \return  SN_NSDL_SUCCESS = 0, Failed = -1
00993  */
00994 int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration)
00995 {
00996     tr_debug("sn_nsdl_build_registration_body");
00997     /* Local variables */
00998     uint8_t                 *temp_ptr;
00999     sn_nsdl_dynamic_resource_parameters_s   *resource_temp_ptr;
01000 
01001     /* Calculate needed memory and allocate */
01002     int8_t error = 0;
01003     uint16_t msg_len = sn_nsdl_calculate_registration_body_size(handle, updating_registeration, &error);
01004     if (SN_NSDL_FAILURE == error) {
01005         return error;
01006     }
01007 
01008     if (!msg_len) {
01009         return SN_NSDL_SUCCESS;
01010     } else {
01011         message_ptr->payload_len = msg_len;
01012     }
01013     tr_debug("sn_nsdl_build_registration_body - body size: [%d]", message_ptr->payload_len);
01014     message_ptr->payload_ptr = handle->sn_nsdl_alloc(message_ptr->payload_len);
01015     if (!message_ptr->payload_ptr) {
01016         return SN_NSDL_FAILURE;
01017     }
01018 
01019     /* Build message */
01020     temp_ptr = message_ptr->payload_ptr;
01021 
01022     resource_temp_ptr = sn_grs_get_first_resource(handle->grs);
01023 
01024     /* Loop trough all resources */
01025     while (resource_temp_ptr) {
01026         /* if resource needs to be registered */
01027         if (resource_temp_ptr->publish_uri) {
01028             if (updating_registeration && resource_temp_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) {
01029                 resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr);
01030                 continue;
01031             } else {
01032                 resource_temp_ptr->registered = SN_NDSL_RESOURCE_REGISTERED;
01033             }
01034 
01035             /* If not first resource, add '.' to separator */
01036             if (temp_ptr != message_ptr->payload_ptr) {
01037                 *temp_ptr++ = ',';
01038             }
01039 
01040             *temp_ptr++ = '<';
01041             *temp_ptr++ = '/';
01042             size_t path_len = 0;
01043             if (resource_temp_ptr->static_resource_parameters->path) {
01044                 path_len = strlen(resource_temp_ptr->static_resource_parameters->path);
01045             }
01046             memcpy(temp_ptr,
01047                    resource_temp_ptr->static_resource_parameters->path,
01048                    path_len);
01049             temp_ptr += path_len;
01050             *temp_ptr++ = '>';
01051 
01052             /* Resource attributes */
01053 #ifndef RESOURCE_ATTRIBUTES_LIST
01054 #ifndef DISABLE_RESOURCE_TYPE
01055             size_t resource_type_len = 0;
01056             if (resource_temp_ptr->static_resource_parameters->resource_type_ptr) {
01057                 resource_type_len = strlen(resource_temp_ptr->static_resource_parameters->resource_type_ptr);
01058             }
01059             if (resource_type_len) {
01060                 *temp_ptr++ = ';';
01061                 memcpy(temp_ptr, resource_type_parameter, RT_PARAMETER_LEN);
01062                 temp_ptr += RT_PARAMETER_LEN;
01063                 *temp_ptr++ = '"';
01064                 memcpy(temp_ptr,
01065                        resource_temp_ptr->static_resource_parameters->resource_type_ptr,
01066                        resource_type_len);
01067                 temp_ptr += resource_type_len;
01068                 *temp_ptr++ = '"';
01069             }
01070 #endif
01071 #ifndef DISABLE_INTERFACE_DESCRIPTION
01072             size_t interface_description_len = 0;
01073             if (resource_temp_ptr->static_resource_parameters->interface_description_ptr) {
01074                 interface_description_len = strlen(resource_temp_ptr->static_resource_parameters->interface_description_ptr);
01075             }
01076 
01077             if (interface_description_len) {
01078                 *temp_ptr++ = ';';
01079                 memcpy(temp_ptr, if_description_parameter, IF_PARAMETER_LEN);
01080                 temp_ptr += IF_PARAMETER_LEN;
01081                 *temp_ptr++ = '"';
01082                 memcpy(temp_ptr,
01083                        resource_temp_ptr->static_resource_parameters->interface_description_ptr,
01084                        interface_description_len);
01085                 temp_ptr += interface_description_len;
01086                 *temp_ptr++ = '"';
01087             }
01088 #endif
01089 #else
01090             size_t attribute_len = 0;
01091             if (resource_temp_ptr->static_resource_parameters->attributes_ptr) {
01092                 sn_nsdl_attribute_item_s *attribute = resource_temp_ptr->static_resource_parameters->attributes_ptr;
01093                 while (attribute->attribute_name != ATTR_END) {
01094                     switch (attribute->attribute_name) {
01095                     case ATTR_RESOURCE_TYPE:
01096                         temp_ptr = sn_nsdl_build_resource_attribute_str(temp_ptr, attribute, resource_type_parameter, RT_PARAMETER_LEN);
01097                         break;
01098                     case ATTR_INTERFACE_DESCRIPTION:
01099                         temp_ptr = sn_nsdl_build_resource_attribute_str(temp_ptr, attribute, if_description_parameter, IF_PARAMETER_LEN);
01100                         break;
01101                     case ATTR_ENDPOINT_NAME:
01102                         temp_ptr = sn_nsdl_build_resource_attribute_str(temp_ptr, attribute, name_parameter, NAME_PARAMETER_LEN);
01103                         break;
01104                     default:
01105                         break;
01106                     }
01107                     attribute++;
01108                 }
01109             }
01110 #endif
01111             if (resource_temp_ptr->coap_content_type != 0) {
01112                 *temp_ptr++ = ';';
01113                 memcpy(temp_ptr, coap_con_type_parameter, COAP_CON_PARAMETER_LEN);
01114                 temp_ptr += COAP_CON_PARAMETER_LEN;
01115                 *temp_ptr++ = '"';
01116                 temp_ptr = sn_nsdl_itoa(temp_ptr,
01117                                         resource_temp_ptr->coap_content_type);
01118                 *temp_ptr++ = '"';
01119             }
01120 
01121             /* ;aobs / ;obs */
01122             // This needs to be re-visited and may be need an API for maganging obs value for different server implementation
01123 #ifndef COAP_DISABLE_OBS_FEATURE
01124             if (resource_temp_ptr->auto_observable) {
01125                 uint8_t token[MAX_TOKEN_SIZE] = {0};
01126                 uint8_t len = handle->sn_nsdl_auto_obs_token_callback(handle,
01127                                                                       resource_temp_ptr->static_resource_parameters->path,
01128                                                                       (uint8_t*)token);
01129                 if (len > 0) {
01130                     *temp_ptr++ = ';';
01131                     memcpy(temp_ptr, aobs_parameter, AOBS_PARAMETER_LEN);
01132                     temp_ptr += AOBS_PARAMETER_LEN;
01133                     *temp_ptr++ = '"';
01134                     uint16_t temp = common_read_16_bit((uint8_t*)token);
01135                     temp_ptr = sn_nsdl_itoa(temp_ptr, temp);
01136                     *temp_ptr++ = '"';
01137                 } else {
01138                     return SN_NSDL_FAILURE;
01139                 }
01140             }
01141             else if (resource_temp_ptr->observable) {
01142                 *temp_ptr++ = ';';
01143                 memcpy(temp_ptr, obs_parameter, OBS_PARAMETER_LEN);
01144                 temp_ptr += OBS_PARAMETER_LEN;
01145             }
01146 #endif
01147         }
01148         resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr);
01149 
01150     }
01151     return SN_NSDL_SUCCESS;
01152 }
01153 
01154 /**
01155  * \fn static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error)
01156  *
01157  *
01158  * \brief   Calculates registration message payload size
01159  * \param   *handle                 Pointer to nsdl-library handle
01160  * \param   *updating_registeration Pointer to list of GRS resources
01161  * \param   *error                  Error code, SN_NSDL_SUCCESS or SN_NSDL_FAILURE
01162  *
01163  * \return  Needed payload size
01164  */
01165 static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error)
01166 {
01167     tr_debug("sn_nsdl_calculate_registration_body_size");
01168     /* Local variables */
01169     uint16_t return_value = 0;
01170     *error = SN_NSDL_SUCCESS;
01171     const sn_nsdl_dynamic_resource_parameters_s *resource_temp_ptr;
01172 
01173     /* check pointer */
01174     resource_temp_ptr = sn_grs_get_first_resource(handle->grs);
01175 
01176     while (resource_temp_ptr) {
01177         if (resource_temp_ptr->publish_uri) {
01178             if (updating_registeration && resource_temp_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) {
01179                 resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr);
01180                 continue;
01181             }
01182             /* If not first resource, then '.' will be added */
01183             if (return_value) {
01184                 if (sn_nsdl_check_uint_overflow(return_value, 1, 0)) {
01185                     return_value++;
01186                 } else {
01187                     *error = SN_NSDL_FAILURE;
01188                     break;
01189                 }
01190             }
01191 
01192             /* Count length for the resource path </path> */
01193             size_t path_len = 0;
01194             if (resource_temp_ptr->static_resource_parameters->path) {
01195                 path_len = strlen(resource_temp_ptr->static_resource_parameters->path);
01196             }
01197 
01198             if (sn_nsdl_check_uint_overflow(return_value, 3, path_len)) {
01199                 return_value += (3 + path_len);
01200             } else {
01201                 *error = SN_NSDL_FAILURE;
01202                 break;
01203             }
01204 
01205             /* Count lengths of the attributes */
01206 #ifndef RESOURCE_ATTRIBUTES_LIST
01207 #ifndef DISABLE_RESOURCE_TYPE
01208             /* Resource type parameter */
01209             size_t resource_type_len = 0;
01210             if (resource_temp_ptr->static_resource_parameters->resource_type_ptr) {
01211                 resource_type_len = strlen(resource_temp_ptr->static_resource_parameters->resource_type_ptr);
01212             }
01213 
01214             if (resource_type_len) {
01215                 /* ;rt="restype" */
01216                 if (sn_nsdl_check_uint_overflow(return_value,
01217                                                 6,
01218                                                 resource_type_len)) {
01219                     return_value += (6 + resource_type_len);
01220                 } else {
01221                     *error = SN_NSDL_FAILURE;
01222                     break;
01223                 }
01224             }
01225 #endif
01226 
01227 #ifndef DISABLE_INTERFACE_DESCRIPTION
01228             /* Interface description parameter */
01229             size_t interface_description_len = 0;
01230             if (resource_temp_ptr->static_resource_parameters->interface_description_ptr) {
01231                 interface_description_len = strlen(resource_temp_ptr->static_resource_parameters->interface_description_ptr);
01232             }
01233             if (interface_description_len) {
01234                 /* ;if="iftype" */
01235                 if (sn_nsdl_check_uint_overflow(return_value,
01236                                                 6,
01237                                                 interface_description_len)) {
01238                     return_value += (6 + interface_description_len);
01239                 } else {
01240                     *error = SN_NSDL_FAILURE;
01241                     break;
01242                 }
01243             }
01244 #endif
01245 #else
01246             /* All attributes */
01247             if (resource_temp_ptr->static_resource_parameters->attributes_ptr) {
01248                 size_t attribute_len = 0;
01249                 size_t attribute_desc_len = 0;
01250                 uint8_t success = 1;
01251                 sn_nsdl_attribute_item_s *item = resource_temp_ptr->static_resource_parameters->attributes_ptr;
01252                 while (item->attribute_name != ATTR_END) {
01253                     switch(item->attribute_name) {
01254                     case ATTR_RESOURCE_TYPE:
01255                         /* ;rt="restype" */
01256                         attribute_desc_len = 6;
01257                         attribute_len = strlen(item->value);
01258                         break;
01259                     case ATTR_INTERFACE_DESCRIPTION:
01260                         /* ;if="iftype" */
01261                         attribute_desc_len = 6;
01262                         attribute_len = strlen(item->value);
01263                         break;
01264                     case ATTR_ENDPOINT_NAME:
01265                         /* ;name="name" */
01266                         attribute_desc_len = 8;
01267                         attribute_len = strlen(item->value);
01268                         break;
01269                     default:
01270                         break;
01271                     }
01272                     if (sn_nsdl_check_uint_overflow(return_value,
01273                                                     attribute_desc_len,
01274                                                     attribute_len)) {
01275                         return_value += (attribute_desc_len + attribute_len);
01276                     } else {
01277                         success = 0;
01278                         break;
01279                     }
01280                     item++;
01281                 }
01282                 if (!success) {
01283                     *error = SN_NSDL_FAILURE;
01284                     break;
01285                 }
01286             }
01287 #endif
01288             if (resource_temp_ptr->coap_content_type != 0) {
01289                 /* ;if="content" */
01290                 uint8_t len = sn_nsdl_itoa_len(resource_temp_ptr->coap_content_type);
01291                 if (sn_nsdl_check_uint_overflow(return_value, 6, len)) {
01292                     return_value += (6 + len);
01293                 } else {
01294                     *error = SN_NSDL_FAILURE;
01295                     break;
01296                 }
01297             }
01298 #ifndef COAP_DISABLE_OBS_FEATURE
01299             // Auto obs will take higher priority
01300             // This needs to be re-visited and may be need an API for maganging obs value for different server implementation
01301             if (resource_temp_ptr->auto_observable) {
01302                 /* ;aobs="" */
01303                 uint8_t token[MAX_TOKEN_SIZE] = {0};
01304                 uint8_t len = handle->sn_nsdl_auto_obs_token_callback(handle,
01305                                                                       resource_temp_ptr->static_resource_parameters->path,
01306                                                                       (uint8_t*)token);
01307 
01308                 if (len > 0) {
01309                     uint16_t temp = common_read_16_bit((uint8_t*)token);
01310                     uint8_t token_len = sn_nsdl_itoa_len(temp);
01311                     if (sn_nsdl_check_uint_overflow(return_value, 8, token_len)) {
01312                         return_value += (8 + token_len);
01313                     } else {
01314                         *error = SN_NSDL_FAILURE;
01315                         break;
01316                     }
01317                 } else {
01318                     *error = SN_NSDL_FAILURE;
01319                     break;
01320                 }
01321             }
01322             else if (resource_temp_ptr->observable) {
01323                 if (sn_nsdl_check_uint_overflow(return_value, 4, 0)) {
01324                     return_value += 4;
01325                 } else {
01326                     *error = SN_NSDL_FAILURE;
01327                     break;
01328                 }
01329             }
01330 #endif
01331         }
01332         resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr);
01333     }
01334     return return_value;
01335 }
01336 
01337 /**
01338  * \fn static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type)
01339  *
01340  *
01341  * \brief Calculates needed uri query option length
01342  *
01343  * \param *endpoint_info_ptr    Pointer to endpoint info structure
01344  * \param msg_type              Message type
01345  *
01346  * \return  number of parameters in uri query
01347  */
01348 static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr,
01349                                                       uint8_t msg_type,
01350                                                       const char *uri_query)
01351 {
01352     uint16_t return_value = 0;
01353     uint8_t number_of_parameters = 0;
01354 
01355 
01356     if ((endpoint_info_ptr->endpoint_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && endpoint_info_ptr->endpoint_name_ptr != 0) {
01357         return_value += endpoint_info_ptr->endpoint_name_len;
01358         return_value += EP_NAME_PARAMETERS_LEN; //ep=
01359         number_of_parameters++;
01360     }
01361 
01362     if ((endpoint_info_ptr->type_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->type_ptr != 0)) {
01363         return_value += endpoint_info_ptr->type_len;
01364         return_value += ET_PARAMETER_LEN;       //et=
01365         number_of_parameters++;
01366     }
01367 
01368     if ((endpoint_info_ptr->lifetime_len != 0) && (endpoint_info_ptr->lifetime_ptr != 0)) {
01369         return_value += endpoint_info_ptr->lifetime_len;
01370         return_value += LT_PARAMETER_LEN;       //lt=
01371         number_of_parameters++;
01372     }
01373 
01374     if ((endpoint_info_ptr->domain_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->domain_name_ptr != 0)) {
01375         return_value += endpoint_info_ptr->domain_name_len;
01376         return_value += DOMAIN_PARAMETER_LEN;       //d=
01377         number_of_parameters++;
01378     }
01379 
01380     if (((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01)) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
01381         return_value += BS_QUEUE_MODE_PARAMATER_LEN;
01382 
01383         if (endpoint_info_ptr->binding_and_mode & 0x01) {
01384             return_value++;
01385         }
01386         if (endpoint_info_ptr->binding_and_mode & 0x04) {
01387             return_value++;
01388         }
01389         if ((endpoint_info_ptr->binding_and_mode & 0x02) && ((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01))) {
01390             return_value++;
01391         }
01392 
01393         number_of_parameters++;
01394     }
01395 
01396     if (number_of_parameters != 0) {
01397         return_value += (number_of_parameters - 1);
01398     }
01399 
01400     if (uri_query) {
01401         return_value += strlen(uri_query);
01402     }
01403 
01404     if (return_value > MAX_URI_QUERY_LEN) {
01405         tr_error("sn_nsdl_calculate_uri_query_option_len - max param length reached (%d)", return_value);
01406         return_value = 0;
01407     }
01408 
01409     return return_value;
01410 }
01411 
01412 /**
01413  * \fn static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type)
01414  *
01415  *
01416  * \brief Fills uri-query options to message header struct
01417  * \param *handle           Pointer to nsdl-library handle
01418  * \param *parameter_ptr    Pointer to endpoint parameters struct
01419  * \param *source_msg_ptr   Pointer to CoAP header struct
01420  * \param msg_type          Message type
01421  *
01422  * \return  SN_NSDL_SUCCESS = 0, Failed = -1
01423  */
01424 static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle,
01425                                              sn_nsdl_ep_parameters_s *parameter_ptr,
01426                                              sn_coap_hdr_s *source_msg_ptr,
01427                                              uint8_t msg_type,
01428                                              const char *uri_query)
01429 {
01430     uint8_t *temp_ptr = NULL;
01431     if( !validateParameters(parameter_ptr) ){
01432         return SN_NSDL_FAILURE;
01433     }
01434 
01435     size_t query_len = sn_nsdl_calculate_uri_query_option_len(parameter_ptr, msg_type, uri_query);
01436     if (query_len == 0) {
01437         return 0;
01438     }
01439 
01440     source_msg_ptr->options_list_ptr->uri_query_len = query_len;
01441     source_msg_ptr->options_list_ptr->uri_query_ptr = handle->sn_nsdl_alloc(query_len);
01442 
01443     if (source_msg_ptr->options_list_ptr->uri_query_ptr == NULL) {
01444         return SN_NSDL_FAILURE;
01445     }
01446     memset(source_msg_ptr->options_list_ptr->uri_query_ptr, 0, source_msg_ptr->options_list_ptr->uri_query_len);
01447 
01448     temp_ptr = source_msg_ptr->options_list_ptr->uri_query_ptr;
01449 
01450     /******************************************************/
01451     /* If endpoint name is configured, fill needed fields */
01452     /******************************************************/
01453 
01454     if ((parameter_ptr->endpoint_name_len != 0) &&
01455         (parameter_ptr->endpoint_name_ptr != 0) &&
01456         (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
01457         /* fill endpoint name, first ?ep=, then endpoint name */
01458         memcpy(temp_ptr, ep_name_parameter_string, sizeof(ep_name_parameter_string));
01459         temp_ptr += EP_NAME_PARAMETERS_LEN;
01460         memcpy(temp_ptr, parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len);
01461         temp_ptr += parameter_ptr->endpoint_name_len;
01462     }
01463 
01464     /******************************************************/
01465     /* If endpoint type is configured, fill needed fields */
01466     /******************************************************/
01467 
01468     if ((parameter_ptr->type_len != 0) &&
01469         (parameter_ptr->type_ptr != 0) &&
01470         (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
01471         if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) {
01472             *temp_ptr++ = '&';
01473         }
01474 
01475         memcpy(temp_ptr, et_parameter, sizeof(et_parameter));
01476         temp_ptr += ET_PARAMETER_LEN;
01477         memcpy(temp_ptr, parameter_ptr->type_ptr, parameter_ptr->type_len);
01478         temp_ptr += parameter_ptr->type_len;
01479     }
01480 
01481 
01482     /******************************************************/
01483     /* If lifetime is configured, fill needed fields */
01484     /******************************************************/
01485 
01486     if ((parameter_ptr->lifetime_len != 0) && (parameter_ptr->lifetime_ptr != 0)) {
01487         if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) {
01488             *temp_ptr++ = '&';
01489         }
01490 
01491         memcpy(temp_ptr, ep_lifetime_parameter, sizeof(ep_lifetime_parameter));
01492         temp_ptr += LT_PARAMETER_LEN;
01493         memcpy(temp_ptr, parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len);
01494         temp_ptr += parameter_ptr->lifetime_len;
01495     }
01496 
01497     /******************************************************/
01498     /* If domain is configured, fill needed fields */
01499     /******************************************************/
01500 
01501     if ((parameter_ptr->domain_name_len != 0) &&
01502         (parameter_ptr->domain_name_ptr != 0) &&
01503         (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
01504         if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) {
01505             *temp_ptr++ = '&';
01506         }
01507 
01508         memcpy(temp_ptr, ep_domain_parameter, sizeof(ep_domain_parameter));
01509         temp_ptr += DOMAIN_PARAMETER_LEN;
01510         memcpy(temp_ptr, parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len);
01511         temp_ptr += parameter_ptr->domain_name_len;
01512     }
01513 
01514     /******************************************************/
01515     /* If queue-mode is configured, fill needed fields    */
01516     /******************************************************/
01517 
01518     if (((parameter_ptr->binding_and_mode & 0x01) ||
01519          (parameter_ptr->binding_and_mode & 0x04)) &&
01520          (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
01521         if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) {
01522             *temp_ptr++ = '&';
01523         }
01524 
01525         memcpy(temp_ptr, bs_queue_mode, sizeof(bs_queue_mode));
01526         temp_ptr += BS_QUEUE_MODE_PARAMATER_LEN;
01527 
01528         if (parameter_ptr->binding_and_mode & 0x01) {
01529             *temp_ptr++ = 'U';
01530             if (parameter_ptr->binding_and_mode & 0x02) {
01531                 *temp_ptr++ = 'Q';
01532             }
01533         }
01534 
01535         if (parameter_ptr->binding_and_mode & 0x04) {
01536             *temp_ptr++ = 'S';
01537             if ((parameter_ptr->binding_and_mode & 0x02) && !(parameter_ptr->binding_and_mode & 0x01)) {
01538                 *temp_ptr++ = 'Q';
01539             }
01540         }
01541     }
01542 
01543     if (uri_query) {
01544         memcpy(temp_ptr, uri_query, strlen(uri_query));
01545     }
01546 
01547     return SN_NSDL_SUCCESS;
01548 }
01549 
01550 static bool validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr)
01551 {
01552     if( !validate( parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len, '&' ) ){
01553         return false;
01554     }
01555 
01556     if( !validate( parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len, '&' ) ){
01557         return false;
01558     }
01559 
01560     if( !validate( parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len, '&' ) ){
01561         return false;
01562     }
01563 
01564     if( !validate( parameter_ptr->type_ptr, parameter_ptr->type_len, '&' ) ){
01565         return false;
01566     }
01567     return true;
01568 }
01569 
01570 static bool validate(uint8_t* ptr, uint32_t len, char illegalChar)
01571 {
01572     if( ptr ){
01573         for( uint32_t i=0; i < len; i++ ){
01574             if( ptr[i] == illegalChar ){
01575                 return false;
01576             }
01577         }
01578     }
01579     return true;
01580 }
01581 
01582 /**
01583  * \fn static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr)
01584  *
01585  * \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.
01586  * \param *handle           Pointer to nsdl-library handle
01587  * \param *coap_packet_ptr  Pointer to received CoAP packet
01588  * \param *address_ptr      Pointer to source address struct
01589  *
01590  * \return      SN_NSDL_SUCCESS = 0, Failed = -1
01591  */
01592 static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr)
01593 {
01594     if ((coap_packet_ptr == 0) || (address_ptr == 0)) {
01595         return -1;
01596     }
01597 
01598     bool is_reg_msg = false;
01599     bool is_update_reg_msg = false;
01600     bool is_unreg_msg = false;
01601     if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CREATED) {
01602         if (handle->grs->coap->sn_coap_block_data_size > 0) {
01603             handle->register_msg_id += handle->register_msg_len / handle->grs->coap->sn_coap_block_data_size;
01604         }
01605         if (coap_packet_ptr->msg_id == handle->register_msg_id) {
01606             handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_IS_REGISTERED;
01607             is_reg_msg = true;
01608             sn_grs_mark_resources_as_registered(handle);
01609             if (sn_nsdl_resolve_ep_information(handle, coap_packet_ptr) != SN_NSDL_SUCCESS) {
01610                 return SN_NSDL_FAILURE;
01611             }
01612         }
01613     }
01614 
01615     else if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CHANGED) {
01616         if (handle->grs->coap->sn_coap_block_data_size > 0) {
01617             handle->update_register_msg_id += handle->update_register_msg_len / handle->grs->coap->sn_coap_block_data_size;
01618         }
01619         if (coap_packet_ptr->msg_id == handle->update_register_msg_id) {
01620             is_update_reg_msg = true;
01621         }
01622     }
01623 
01624     if (coap_packet_ptr->msg_id == handle->unregister_msg_id) {
01625         is_unreg_msg = true;
01626         if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_DELETED) {
01627 
01628             handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr);
01629             handle->ep_information_ptr->endpoint_name_ptr = 0;
01630             handle->ep_information_ptr->endpoint_name_len = 0;
01631 
01632             handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
01633             handle->ep_information_ptr->domain_name_ptr = 0;
01634             handle->ep_information_ptr->domain_name_len = 0;
01635         }
01636     }
01637 
01638     /* No messages to wait for, or message was not response to our request */
01639     int ret = handle->sn_nsdl_rx_callback(handle, coap_packet_ptr, address_ptr);
01640     if (is_reg_msg) {
01641         handle->register_msg_id = 0;
01642         handle->register_msg_len = 0;
01643     }
01644     else if (is_unreg_msg) {
01645         handle->unregister_msg_id = 0;
01646     }
01647     else if (is_update_reg_msg) {
01648         handle->update_register_msg_id = 0;
01649         handle->update_register_msg_len = 0;
01650     }
01651     else if (coap_packet_ptr->msg_id == handle->bootstrap_msg_id) {
01652         handle->bootstrap_msg_id = 0;
01653     }
01654     return ret;
01655 }
01656 
01657 /**
01658  * \fn static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr)
01659  *
01660  *
01661  * \brief Resolves endpoint information from received CoAP message
01662  * \param *handle           Pointer to nsdl-library handle
01663  * \param *coap_packet_ptr  Pointer to received CoAP message
01664  *
01665  * \return  SN_NSDL_SUCCESS = 0, Failed = -1
01666  */
01667 static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr)
01668 {
01669     uint8_t     *temp_ptr;
01670     uint8_t     parameter_count     = 0;
01671     uint16_t    parameter_len       = 0;
01672 
01673     if (!coap_packet_ptr || !coap_packet_ptr->options_list_ptr ||
01674         !coap_packet_ptr->options_list_ptr->location_path_ptr) {
01675         return SN_NSDL_FAILURE;
01676     }
01677 
01678     temp_ptr = coap_packet_ptr->options_list_ptr->location_path_ptr;
01679 
01680     while (temp_ptr <= (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) {
01681 
01682         if ((temp_ptr == (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) || (*temp_ptr == '/')) {
01683 
01684             parameter_count++;
01685             if (parameter_count == 2) {
01686                 if (!handle->ep_information_ptr->domain_name_ptr) {
01687                     handle->ep_information_ptr->domain_name_len = parameter_len - 1;
01688                     handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->domain_name_len);
01689                     if (!handle->ep_information_ptr->domain_name_ptr) {
01690                         return SN_NSDL_FAILURE;
01691                     }
01692                     memcpy(handle->ep_information_ptr->domain_name_ptr, temp_ptr - handle->ep_information_ptr->domain_name_len, handle->ep_information_ptr->domain_name_len);
01693                 }
01694 
01695             }
01696             if (parameter_count == 3) {
01697                 if (!handle->ep_information_ptr->endpoint_name_ptr) {
01698                     handle->ep_information_ptr->endpoint_name_len = parameter_len - 1;
01699                     handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->endpoint_name_len);
01700                     if (!handle->ep_information_ptr->endpoint_name_ptr) {
01701                         if (handle->ep_information_ptr->domain_name_ptr) {
01702                             handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
01703                             handle->ep_information_ptr->domain_name_ptr = NULL;
01704                             handle->ep_information_ptr->domain_name_len = 0;
01705                         }
01706 
01707                         return SN_NSDL_FAILURE;
01708 
01709                     }
01710                     memcpy(handle->ep_information_ptr->endpoint_name_ptr, temp_ptr - handle->ep_information_ptr->endpoint_name_len, handle->ep_information_ptr->endpoint_name_len);
01711                 }
01712             }
01713             parameter_len = 0;
01714         }
01715         parameter_len++;
01716         temp_ptr++;
01717     }
01718 
01719 
01720     return SN_NSDL_SUCCESS;
01721 }
01722 
01723 extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint8_t address_length, uint16_t port, sn_nsdl_addr_type_e address_type)
01724 {
01725     /* Check parameters and source pointers */
01726     if (!handle || !handle->nsp_address_ptr || !handle->nsp_address_ptr->omalw_address_ptr || !NSP_address) {
01727         return SN_NSDL_FAILURE;
01728     }
01729 
01730     handle->nsp_address_ptr->omalw_address_ptr->type = address_type;
01731     handle->nsp_address_ptr->omalw_server_security = SEC_NOT_SET;
01732 
01733     handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr);
01734 
01735     handle->nsp_address_ptr->omalw_address_ptr->addr_len = address_length;
01736 
01737     handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(handle->nsp_address_ptr->omalw_address_ptr->addr_len);
01738     if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) {
01739         return SN_NSDL_FAILURE;
01740     }
01741 
01742     memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, NSP_address, handle->nsp_address_ptr->omalw_address_ptr->addr_len);
01743     handle->nsp_address_ptr->omalw_address_ptr->port = port;
01744 
01745     return SN_NSDL_SUCCESS;
01746 }
01747 
01748 
01749 static uint8_t sn_nsdl_itoa_len(uint32_t value)
01750 {
01751     uint8_t i = 0;
01752 
01753     do {
01754         i++;
01755     } while ((value /= 10) > 0);
01756 
01757     return i;
01758 }
01759 
01760 static uint8_t *sn_nsdl_itoa(uint8_t *ptr, uint32_t value)
01761 {
01762 
01763     uint8_t start = 0;
01764     uint8_t end = 0;
01765     uint8_t i;
01766 
01767     i = 0;
01768 
01769     /* ITOA */
01770     do {
01771         ptr[i++] = (value % 10) + '0';
01772     } while ((value /= 10) > 0);
01773 
01774     end = i - 1;
01775 
01776     /* reverse (part of ITOA) */
01777     while (start < end) {
01778         uint8_t chr;
01779 
01780         chr = ptr[start];
01781         ptr[start] = ptr[end];
01782         ptr[end] = chr;
01783 
01784         start++;
01785         end--;
01786 
01787     }
01788     return (ptr + i);
01789 }
01790 
01791 static int8_t set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr)
01792 {
01793     handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
01794     handle->ep_information_ptr->domain_name_ptr = 0;
01795     handle->ep_information_ptr->domain_name_len = 0;
01796 
01797     handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr);
01798     handle->ep_information_ptr->endpoint_name_ptr = 0;
01799     handle->ep_information_ptr->endpoint_name_len = 0;
01800 
01801     if (endpoint_info_ptr->domain_name_ptr && endpoint_info_ptr->domain_name_len) {
01802         handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->domain_name_len);
01803 
01804         if (!handle->ep_information_ptr->domain_name_ptr) {
01805             return -1;
01806         }
01807 
01808         memcpy(handle->ep_information_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_len);
01809         handle->ep_information_ptr->domain_name_len = endpoint_info_ptr->domain_name_len;
01810     }
01811 
01812     if (endpoint_info_ptr->endpoint_name_ptr && endpoint_info_ptr->endpoint_name_len) {
01813         handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len);
01814 
01815         if (!handle->ep_information_ptr->endpoint_name_ptr) {
01816             handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
01817             handle->ep_information_ptr->domain_name_ptr = 0;
01818             handle->ep_information_ptr->domain_name_len = 0;
01819             return -1;
01820         }
01821 
01822         memcpy(handle->ep_information_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len);
01823         handle->ep_information_ptr->endpoint_name_len = endpoint_info_ptr->endpoint_name_len;
01824     }
01825 
01826     handle->ep_information_ptr->binding_and_mode = endpoint_info_ptr->binding_and_mode;
01827     handle->ep_information_ptr->ds_register_mode = endpoint_info_ptr->ds_register_mode;
01828 
01829     return 0;
01830 }
01831 
01832 /* Wrapper */
01833 sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, const char *path)
01834 {
01835     /* Check parameters */
01836     if (handle == NULL) {
01837         return NULL;
01838     }
01839 
01840     return sn_grs_list_resource(handle->grs, path);
01841 }
01842 
01843 void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list)
01844 {
01845     /* Check parameters */
01846     if (handle == NULL) {
01847         return;
01848     }
01849 
01850     sn_grs_free_resource_list(handle->grs, list);
01851 }
01852 
01853 extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr)
01854 {
01855     /* Check parameters */
01856     if (handle == NULL) {
01857         return SN_NSDL_FAILURE;
01858     }
01859 
01860     int8_t ret = sn_grs_send_coap_message(handle, address_ptr, coap_hdr_ptr);
01861 
01862     sn_nsdl_print_coap_data(coap_hdr_ptr, true);
01863 
01864     return ret;
01865 }
01866 
01867 extern int8_t sn_nsdl_handle_block2_response_internally(struct nsdl_s *handle, uint8_t build_response)
01868 {
01869     /* Check parameters */
01870     if (handle == NULL) {
01871         return SN_NSDL_FAILURE;
01872     }
01873 
01874     return sn_coap_protocol_handle_block2_response_internally(handle->grs->coap, build_response);
01875 }
01876 
01877 extern int8_t sn_nsdl_clear_coap_sent_blockwise_messages(struct nsdl_s *handle)
01878 {
01879     /* Check parameters */
01880     if (handle == NULL) {
01881         return SN_NSDL_FAILURE;
01882     }
01883 
01884     // Enable function once new CoAP API is released to mbed-os
01885     //sn_coap_protocol_clear_sent_blockwise_messages(handle->grs->coap);
01886 
01887 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
01888     // Workaround until CoAP API is released
01889     /* Loop all stored Blockwise messages in Linked list */
01890     ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->grs->coap->linked_list_blockwise_sent_msgs) {
01891         if (removed_blocwise_msg_ptr->coap == handle->grs->coap) {
01892             if (removed_blocwise_msg_ptr->coap_msg_ptr){
01893                 if (removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr) {
01894                     handle->grs->coap->sn_coap_protocol_free(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr);
01895                 }
01896                 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap,
01897                                                               removed_blocwise_msg_ptr->coap_msg_ptr);
01898 
01899             }
01900 
01901             ns_list_remove(&handle->grs->coap->linked_list_blockwise_sent_msgs, removed_blocwise_msg_ptr);
01902             handle->grs->coap->sn_coap_protocol_free(removed_blocwise_msg_ptr);
01903         }
01904     }
01905 #endif
01906     return SN_NSDL_SUCCESS;
01907 }
01908 
01909 extern int32_t sn_nsdl_send_get_data_request(struct nsdl_s *handle,
01910         const char *uri_path,
01911         const uint32_t token,
01912         const size_t offset)
01913 {
01914     sn_coap_hdr_s  req_message;
01915     int32_t        message_id;
01916 
01917     if (handle == NULL || uri_path == NULL || handle->grs->coap->sn_coap_block_data_size == 0) {
01918         return 0;
01919     }
01920 
01921     memset(&req_message, 0, sizeof(sn_coap_hdr_s));
01922 
01923     // Fill message fields
01924     req_message.msg_type = COAP_MSG_TYPE_CONFIRMABLE;
01925     req_message.msg_code = COAP_MSG_CODE_REQUEST_GET;
01926     req_message.uri_path_len = (uint16_t)strlen(uri_path);
01927     req_message.uri_path_ptr = (uint8_t*)uri_path;
01928     req_message.token_ptr = (uint8_t*)&token;
01929     req_message.token_len = sizeof(token);
01930 
01931 // Skip block options if feature is not enabled
01932 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
01933     if (sn_coap_parser_alloc_options(handle->grs->coap, &req_message) == NULL) {
01934         handle->grs->coap->sn_coap_protocol_free(req_message.options_list_ptr);
01935         return 0;
01936     }
01937 
01938     // Add block number
01939     req_message.options_list_ptr->block2 = 0;
01940     if (offset > 0) {
01941         req_message.options_list_ptr->block2 = ((offset / handle->grs->coap->sn_coap_block_data_size) << 4);
01942     }
01943     // Add block size
01944     req_message.options_list_ptr->block2 |= sn_coap_convert_block_size(handle->grs->coap->sn_coap_block_data_size);
01945 #endif
01946 
01947     // Build and send coap message
01948     message_id = sn_nsdl_internal_coap_send(handle, &req_message, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UNDEFINED);
01949     handle->grs->coap->sn_coap_protocol_free(req_message.options_list_ptr);
01950 
01951     return message_id;
01952 }
01953 
01954 extern int8_t sn_nsdl_put_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
01955 {
01956     if (!handle) {
01957         return SN_NSDL_FAILURE;
01958     }
01959 
01960     return sn_grs_put_resource(handle->grs, res);
01961 }
01962 
01963 extern int8_t sn_nsdl_pop_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
01964 {
01965     if (!handle) {
01966         return SN_NSDL_FAILURE;
01967     }
01968 
01969     return sn_grs_pop_resource(handle->grs, res);
01970 }
01971 
01972 extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, const char *path)
01973 {
01974     /* Check parameters */
01975     if (handle == NULL) {
01976         return SN_NSDL_FAILURE;
01977     }
01978 
01979     return sn_grs_delete_resource(handle->grs, path);
01980 }
01981 extern const sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_first_resource(struct nsdl_s *handle)
01982 {
01983     /* Check parameters */
01984     if (handle == NULL) {
01985         return NULL;
01986     }
01987 
01988     return sn_grs_get_first_resource(handle->grs);
01989 }
01990 extern const sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_next_resource(struct nsdl_s *handle, const sn_nsdl_dynamic_resource_parameters_s *resource)
01991 {
01992     /* Check parameters */
01993     if (handle == NULL) {
01994         return NULL;
01995     }
01996 
01997     return sn_grs_get_next_resource(handle->grs, resource);
01998 }
01999 
02000 extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
02001 {
02002     if (handle == NULL) {
02003         return NULL;
02004     }
02005 
02006     return sn_coap_build_response(handle->grs->coap, coap_packet_ptr, msg_code);
02007 }
02008 
02009 extern sn_coap_options_list_s *sn_nsdl_alloc_options_list(struct nsdl_s *handle, sn_coap_hdr_s *coap_msg_ptr)
02010 {
02011     if (handle == NULL || coap_msg_ptr == NULL) {
02012         return NULL;
02013     }
02014     return sn_coap_parser_alloc_options(handle->grs->coap, coap_msg_ptr);
02015 }
02016 
02017 extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
02018 {
02019     if (handle == NULL) {
02020         return;
02021     }
02022 
02023     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, freed_coap_msg_ptr);
02024 }
02025 
02026 extern int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle,
02027     uint8_t resending_count, uint8_t resending_interval)
02028 {
02029     if (handle == NULL) {
02030         return SN_NSDL_FAILURE;
02031     }
02032     return sn_coap_protocol_set_retransmission_parameters(handle->grs->coap,
02033                                                           resending_count,resending_interval);
02034 }
02035 
02036 extern int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle,
02037         uint8_t buffer_size_messages, uint16_t buffer_size_bytes)
02038 {
02039     if (handle == NULL) {
02040         return SN_NSDL_FAILURE;
02041     }
02042     return sn_coap_protocol_set_retransmission_buffer(handle->grs->coap,
02043                                                       buffer_size_messages, buffer_size_bytes);
02044 }
02045 
02046 extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size)
02047 {
02048     if (handle == NULL) {
02049         return SN_NSDL_FAILURE;
02050     }
02051     return sn_coap_protocol_set_block_size(handle->grs->coap, block_size);
02052 }
02053 
02054 extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count)
02055 {
02056     if (handle == NULL) {
02057         return SN_NSDL_FAILURE;
02058     }
02059     return sn_coap_protocol_set_duplicate_buffer_size(handle->grs->coap, message_count);
02060 }
02061 
02062 bool sn_nsdl_check_uint_overflow(uint16_t resource_size, uint16_t param_a, uint16_t param_b)
02063 {
02064     uint16_t first_check = param_a + param_b;
02065     if (first_check < param_b) {
02066         return false;
02067     } else {
02068         uint16_t total = resource_size + first_check;
02069         if (total < first_check) {
02070             return false;
02071         } else {
02072             return true;
02073         }
02074     }
02075 }
02076 
02077 extern int8_t sn_nsdl_set_context(struct nsdl_s * const handle, void * const context)
02078 {
02079     if (handle == NULL) {
02080         return SN_NSDL_FAILURE;
02081     }
02082     handle->context = context;
02083     return SN_NSDL_SUCCESS;
02084 }
02085 
02086 extern void *sn_nsdl_get_context(const struct nsdl_s * const handle)
02087 {
02088     if (handle == NULL) {
02089         return NULL;
02090     }
02091     return handle->context;
02092 }
02093 
02094 
02095 int8_t sn_nsdl_clear_coap_resending_queue(struct nsdl_s *handle)
02096 {
02097     if (handle == NULL || handle->grs == NULL) {
02098         tr_err("sn_nsdl_clear_coap_resending_queue failed.");
02099         return SN_NSDL_FAILURE;
02100     }
02101     sn_coap_protocol_clear_retransmission_buffer(handle->grs->coap);
02102     return SN_NSDL_SUCCESS;
02103 }
02104 
02105 #ifdef RESOURCE_ATTRIBUTES_LIST
02106 static void sn_nsdl_free_attribute_value(sn_nsdl_attribute_item_s *attribute)
02107 {
02108     switch (attribute->attribute_name) {
02109     case ATTR_RESOURCE_TYPE:
02110     case ATTR_INTERFACE_DESCRIPTION:
02111     case ATTR_ENDPOINT_NAME:
02112         free(attribute->value);
02113         attribute->value = NULL;
02114         break;
02115     case ATTR_NOP:
02116     case ATTR_END:
02117     default:
02118         break;
02119     }
02120 }
02121 
02122 void sn_nsdl_free_resource_attributes_list(sn_nsdl_static_resource_parameters_s *params)
02123 {
02124     if (params == NULL || params->free_on_delete == false) {
02125         return;
02126     }
02127     sn_nsdl_attribute_item_s *item = params->attributes_ptr;
02128     if (item) {
02129         while (item->attribute_name != ATTR_END) {
02130             sn_nsdl_free_attribute_value(item);
02131             item++;
02132         }
02133         free(params->attributes_ptr);
02134         params->attributes_ptr = NULL;
02135     }
02136 }
02137 
02138 bool sn_nsdl_set_resource_attribute(sn_nsdl_static_resource_parameters_s *params, const sn_nsdl_attribute_item_s *attribute)
02139 {
02140     if (params == NULL || params->free_on_delete == false) {
02141         return false;
02142     }
02143     unsigned int item_count = 0;
02144     sn_nsdl_attribute_item_s *item = params->attributes_ptr;
02145     // Count the number of attributes for reallocation, update in place though
02146     // if the attribute already existed
02147     while (item != NULL) {
02148         item_count++;
02149         if (item->attribute_name == ATTR_END) {
02150             break;
02151         }
02152         // Check if attribute already exists or if there is NOP we can overwrite
02153         if (item->attribute_name == attribute->attribute_name || item->attribute_name == ATTR_NOP) {
02154             // Found attribute or NOP, overwrite it
02155             sn_nsdl_free_attribute_value(item);
02156             item->attribute_name = attribute->attribute_name;
02157             item->value = attribute->value;
02158             return true;
02159         }
02160         item++;
02161     }
02162     // Attribute did not yet exist (ptr was null or ATTR_END was first one)
02163     if (item_count > 0) {
02164         // List already had some attributes, so reallocate
02165         size_t new_size = (item_count + 1) * sizeof(sn_nsdl_attribute_item_s);
02166         item = params->attributes_ptr;
02167         params->attributes_ptr = realloc(item, new_size);
02168         if (params->attributes_ptr == NULL) {
02169             // realloc failed, put back original pointer and return false
02170             params->attributes_ptr = item;
02171             return false;
02172         }
02173         // And move item ptr to ATTR_END to update that and last attribute
02174         item = &(params->attributes_ptr[item_count - 1]);
02175     }
02176     else {
02177         // No attributes, so allocate first time (1 struct for attribute and 1 struct for ATTR_END)
02178         params->attributes_ptr = (char*)malloc(2 * sizeof(sn_nsdl_attribute_item_s));
02179         if (params->attributes_ptr == NULL) {
02180             return false;
02181         }
02182         item = params->attributes_ptr;
02183     }
02184     item->attribute_name = attribute->attribute_name;
02185     item->value = attribute->value;
02186     item++;
02187     item->attribute_name = ATTR_END;
02188     item->value = NULL;
02189     return true;
02190 }
02191 
02192 const char *sn_nsdl_get_resource_attribute(const sn_nsdl_static_resource_parameters_s *params, sn_nsdl_resource_attribute_t attribute_name)
02193 {
02194     char *value = NULL;
02195     if (params != NULL) {
02196         sn_nsdl_attribute_item_s *item = params->attributes_ptr;
02197         while (item != NULL && item->attribute_name != ATTR_END) {
02198             if (item->attribute_name == attribute_name) {
02199                 value = item->value;
02200                 break;
02201             }
02202             item++;
02203         }
02204     }
02205     return value;
02206 }
02207 
02208 bool sn_nsdl_remove_resource_attribute(sn_nsdl_static_resource_parameters_s *params, sn_nsdl_resource_attribute_t attribute_name)
02209 {
02210     if (params == NULL || params->free_on_delete == false) {
02211         return false;
02212     }
02213 
02214     bool found = false;
02215     sn_nsdl_attribute_item_s *item = params->attributes_ptr;
02216     while (item != NULL) {
02217         if (item->attribute_name == ATTR_END) {
02218             break;
02219         }
02220         // Remove if attribute name matches
02221         if (item->attribute_name == attribute_name) {
02222             // Currently only pointer values, need to free and set as NOP
02223             sn_nsdl_free_attribute_value(item);
02224             item->attribute_name = ATTR_NOP;
02225             found = true;
02226             break;
02227         }
02228         item++;
02229     }
02230 
02231     return found;
02232 
02233 }
02234 
02235 #endif
02236 
02237 
02238 void sn_nsdl_print_coap_data(sn_coap_hdr_s *coap_header_ptr, bool outgoing)
02239 {
02240 #if defined(FEA_TRACE_SUPPORT) || MBED_CONF_MBED_TRACE_ENABLE || YOTTA_CFG_MBED_TRACE || (defined(YOTTA_CFG) && !defined(NDEBUG))
02241     if (!coap_header_ptr) {
02242         return;
02243     }
02244 
02245     if (outgoing) {
02246         tr_info("======== Outgoing CoAP package ========");
02247     } else {
02248         tr_info("======== Incoming CoAP package ========");
02249     }
02250 
02251     if (coap_header_ptr->uri_path_len > 0 && coap_header_ptr->uri_path_ptr) {
02252         tr_info("Uri-Path:\t\t%.*s", coap_header_ptr->uri_path_len, coap_header_ptr->uri_path_ptr);
02253     }
02254     tr_info("Status:\t\t%s", sn_nsdl_coap_status_description(coap_header_ptr->coap_status));
02255     tr_info("Code:\t\t%s", sn_nsdl_coap_message_code_desc(coap_header_ptr->msg_code));
02256     tr_info("Type:\t\t%s", sn_nsdl_coap_message_type_desc(coap_header_ptr->msg_type));
02257     tr_info("Id:\t\t%d", coap_header_ptr->msg_id);
02258     if (coap_header_ptr->token_ptr && coap_header_ptr->token_len > 0) {
02259         tr_info("Token:\t\t%s", tr_array(coap_header_ptr->token_ptr, coap_header_ptr->token_len));
02260     }
02261     if (coap_header_ptr->content_format != -1) {
02262         tr_info("Content-type:\t%d", coap_header_ptr->content_format);
02263     }
02264     tr_info("Payload len:\t%d", coap_header_ptr->payload_len);
02265 #ifdef MBED_CLIENT_PRINT_COAP_PAYLOAD
02266     if (coap_header_ptr->payload_ptr && coap_header_ptr->payload_len > 0) {
02267         int i = 0;
02268         int row_len = 40;
02269         int max_length = 2048;
02270         while (i < coap_header_ptr->payload_len && i < max_length) {
02271             if (i + row_len > coap_header_ptr->payload_len) {
02272                 row_len = coap_header_ptr->payload_len - i;
02273             }
02274             tr_info("Payload:\t\t%s", tr_array( coap_header_ptr->payload_ptr + i, row_len));
02275             i += row_len;
02276         }
02277         if (i >= max_length)
02278             tr_info("Payload:\t\t.....");
02279     }
02280 #endif
02281 
02282     if (coap_header_ptr->options_list_ptr) {
02283         if (coap_header_ptr->options_list_ptr->etag_ptr && coap_header_ptr->options_list_ptr->etag_len > 0) {
02284             tr_info("E-tag:\t%.*s", coap_header_ptr->options_list_ptr->etag_len, coap_header_ptr->options_list_ptr->etag_ptr);
02285         }
02286         if (coap_header_ptr->options_list_ptr->proxy_uri_ptr && coap_header_ptr->options_list_ptr->proxy_uri_len > 0) {
02287             tr_info("Proxy uri:\t%.*s", coap_header_ptr->options_list_ptr->proxy_uri_len, coap_header_ptr->options_list_ptr->proxy_uri_ptr);
02288         }
02289 
02290         if (coap_header_ptr->options_list_ptr->uri_host_ptr && coap_header_ptr->options_list_ptr->uri_host_len > 0) {
02291             tr_info("Uri host:\t%.*s", coap_header_ptr->options_list_ptr->uri_host_len, coap_header_ptr->options_list_ptr->uri_host_ptr);
02292         }
02293 
02294         if (coap_header_ptr->options_list_ptr->location_path_ptr && coap_header_ptr->options_list_ptr->location_path_len > 0) {
02295             tr_info("Location path:\t%.*s", coap_header_ptr->options_list_ptr->location_path_len, coap_header_ptr->options_list_ptr->location_path_ptr);
02296         }
02297 
02298         if (coap_header_ptr->options_list_ptr->location_query_ptr && coap_header_ptr->options_list_ptr->location_query_len > 0) {
02299             tr_info("Location query:\t%.*s", coap_header_ptr->options_list_ptr->location_query_len, coap_header_ptr->options_list_ptr->location_query_ptr);
02300         }
02301 
02302         if (coap_header_ptr->options_list_ptr->uri_query_ptr && coap_header_ptr->options_list_ptr->uri_query_len > 0) {
02303             tr_info("Uri query:\t%.*s", coap_header_ptr->options_list_ptr->uri_query_len, coap_header_ptr->options_list_ptr->uri_query_ptr);
02304         }
02305 
02306         tr_info("Max-age:\t\t%" PRIu32"", coap_header_ptr->options_list_ptr->max_age);
02307         if (coap_header_ptr->options_list_ptr->use_size1) {
02308             tr_info("Size 1:\t\t%" PRIu32"", coap_header_ptr->options_list_ptr->size1);
02309         }
02310         if (coap_header_ptr->options_list_ptr->use_size2) {
02311             tr_info("Size 2:\t\t%" PRIu32"", coap_header_ptr->options_list_ptr->size2);
02312         }
02313         if (coap_header_ptr->options_list_ptr->accept != -1) {
02314             tr_info("Accept:\t\t%d", coap_header_ptr->options_list_ptr->accept);
02315         }
02316         if (coap_header_ptr->options_list_ptr->uri_port != -1) {
02317             tr_info("Uri port:\t%" PRId32"", coap_header_ptr->options_list_ptr->uri_port);
02318         }
02319         if (coap_header_ptr->options_list_ptr->observe != -1) {
02320             tr_info("Observe:\t\t%" PRId32"", coap_header_ptr->options_list_ptr->observe);
02321         }
02322         if (coap_header_ptr->options_list_ptr->block1 != -1) {
02323             tr_info("Block1 number:\t%" PRId32"", coap_header_ptr->options_list_ptr->block1 >> 4);
02324             uint8_t temp = (coap_header_ptr->options_list_ptr->block1 & 0x07);
02325             uint16_t block_size = 1u << (temp + 4);
02326             tr_info("Block1 size:\t%d", block_size);
02327             tr_info("Block1 more:\t%d", (coap_header_ptr->options_list_ptr->block1) & 0x08 ? true : false);
02328         }
02329         if (coap_header_ptr->options_list_ptr->block2 != -1) {
02330             tr_info("Block2 number:\t%" PRId32"", coap_header_ptr->options_list_ptr->block2 >> 4);
02331             uint8_t temp = (coap_header_ptr->options_list_ptr->block2 & 0x07);
02332             uint16_t block_size = 1u << (temp + 4);
02333             tr_info("Block2 size:\t%d", block_size);
02334             tr_info("Block2 more:\t%d", (coap_header_ptr->options_list_ptr->block2) & 0x08 ? true : false);
02335         }
02336     }
02337     tr_info("======== End of CoAP package ========");
02338 #else
02339     (void) coap_header_ptr;
02340     (void) outgoing;
02341 #endif
02342 }
02343 
02344 #if defined(FEA_TRACE_SUPPORT) || MBED_CONF_MBED_TRACE_ENABLE || YOTTA_CFG_MBED_TRACE || (defined(YOTTA_CFG) && !defined(NDEBUG))
02345 const char *sn_nsdl_coap_status_description(sn_coap_status_e status)
02346 {
02347     switch(status) {
02348         case COAP_STATUS_OK:
02349             return "COAP_STATUS_OK";
02350         case COAP_STATUS_PARSER_ERROR_IN_HEADER:
02351             return "COAP_STATUS_PARSER_ERROR_IN_HEADER";
02352         case COAP_STATUS_PARSER_DUPLICATED_MSG:
02353             return "COAP_STATUS_PARSER_DUPLICATED_MSG";
02354         case COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING:
02355             return "COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING";
02356         case COAP_STATUS_PARSER_BLOCKWISE_ACK:
02357             return "COAP_STATUS_PARSER_BLOCKWISE_ACK";
02358         case COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED:
02359             return "COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED";
02360         case COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED:
02361             return "COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED";
02362         case COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED:
02363             return "COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED";
02364         default:
02365             return "";
02366     }
02367 }
02368 
02369 const char *sn_nsdl_coap_message_code_desc(int msg_code)
02370 {
02371     switch(msg_code) {
02372         case COAP_MSG_CODE_EMPTY:
02373             return "COAP_MSG_CODE_EMPTY";
02374         case COAP_MSG_CODE_REQUEST_GET:
02375             return "COAP_MSG_CODE_REQUEST_GET";
02376         case COAP_MSG_CODE_REQUEST_POST:
02377             return "COAP_MSG_CODE_REQUEST_POST";
02378         case COAP_MSG_CODE_REQUEST_PUT:
02379             return "COAP_MSG_CODE_REQUEST_PUT";
02380         case COAP_MSG_CODE_REQUEST_DELETE:
02381             return "COAP_MSG_CODE_REQUEST_DELETE";
02382         case COAP_MSG_CODE_RESPONSE_CREATED:
02383             return "COAP_MSG_CODE_RESPONSE_CREATED";
02384         case COAP_MSG_CODE_RESPONSE_DELETED:
02385             return "COAP_MSG_CODE_RESPONSE_DELETED";
02386         case COAP_MSG_CODE_RESPONSE_VALID:
02387             return "COAP_MSG_CODE_RESPONSE_VALID";
02388         case COAP_MSG_CODE_RESPONSE_CHANGED:
02389             return "COAP_MSG_CODE_RESPONSE_CHANGED";
02390         case COAP_MSG_CODE_RESPONSE_CONTENT:
02391             return "COAP_MSG_CODE_RESPONSE_CONTENT";
02392         case COAP_MSG_CODE_RESPONSE_CONTINUE:
02393             return "COAP_MSG_CODE_RESPONSE_CONTINUE";
02394         case COAP_MSG_CODE_RESPONSE_BAD_REQUEST:
02395             return "COAP_MSG_CODE_RESPONSE_BAD_REQUEST";
02396         case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED:
02397             return "COAP_MSG_CODE_RESPONSE_UNAUTHORIZED";
02398         case COAP_MSG_CODE_RESPONSE_BAD_OPTION:
02399             return "COAP_MSG_CODE_RESPONSE_BAD_OPTION";
02400         case COAP_MSG_CODE_RESPONSE_FORBIDDEN:
02401             return "COAP_MSG_CODE_RESPONSE_FORBIDDEN";
02402         case COAP_MSG_CODE_RESPONSE_NOT_FOUND:
02403             return "COAP_MSG_CODE_RESPONSE_NOT_FOUND";
02404         case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED:
02405             return "COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED";
02406         case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE:
02407             return "COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE";
02408         case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE:
02409             return "COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE";
02410         case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED:
02411             return "COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED";
02412         case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE:
02413             return "COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE";
02414         case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT:
02415             return "COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT";
02416         case COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR:
02417             return "COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR";
02418         case COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED:
02419             return "COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED";
02420         case COAP_MSG_CODE_RESPONSE_BAD_GATEWAY:
02421             return "COAP_MSG_CODE_RESPONSE_BAD_GATEWAY";
02422         case COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE:
02423             return "COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE";
02424         case COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT:
02425             return "COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT";
02426         case COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED:
02427             return "COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED";
02428         default:
02429             return "";
02430     }
02431 }
02432 
02433 const char *sn_nsdl_coap_message_type_desc(int msg_type)
02434 {
02435     switch(msg_type) {
02436         case COAP_MSG_TYPE_CONFIRMABLE:
02437             return "COAP_MSG_TYPE_CONFIRMABLE";
02438         case COAP_MSG_TYPE_NON_CONFIRMABLE:
02439             return "COAP_MSG_TYPE_NON_CONFIRMABLE";
02440         case COAP_MSG_TYPE_ACKNOWLEDGEMENT:
02441             return "COAP_MSG_TYPE_ACKNOWLEDGEMENT";
02442         case COAP_MSG_TYPE_RESET:
02443             return "COAP_MSG_TYPE_RESET";
02444         default:
02445             return "";
02446     }
02447 }
02448 #endif
02449 
02450 void remove_previous_block_data(struct nsdl_s *handle, sn_nsdl_addr_s *src_ptr, const uint32_t block_number)
02451 {
02452 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
02453     ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->grs->coap->linked_list_blockwise_received_payloads) {
02454         uint32_t stored_number = stored_payload_info_ptr->block_number;
02455         // Remove the previous block data
02456         if (block_number - 1 == stored_number) {
02457             sn_coap_protocol_block_remove(handle->grs->coap,
02458                     src_ptr,
02459                     stored_payload_info_ptr->payload_len,
02460                     stored_payload_info_ptr->payload_ptr);
02461             break;
02462         }
02463     }
02464 #endif
02465 }
02466 
02467 bool update_last_block_data(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, bool block1)
02468 {
02469     bool data_updated = false;
02470     // Whole message received --> pass only the last block data to application
02471     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) {
02472         // Get the block size
02473         uint8_t temp = 0;
02474         if (block1) {
02475             temp = (coap_packet_ptr->options_list_ptr->block1 & 0x07);
02476         } else {
02477             temp = (coap_packet_ptr->options_list_ptr->block2 & 0x07);
02478         }
02479         uint16_t block_size = 1u << (temp + 4);
02480 
02481         uint32_t new_payload_len = coap_packet_ptr->payload_len - block_size;
02482         uint8_t *temp_ptr =  handle->grs->coap->sn_coap_protocol_malloc(new_payload_len);
02483         if (temp_ptr) {
02484             // Skip the second last block data since it's still stored in mbed-coap list!
02485             memcpy(temp_ptr, coap_packet_ptr->payload_ptr + block_size, new_payload_len);
02486             handle->grs->coap->sn_coap_protocol_free(coap_packet_ptr->payload_ptr);
02487             coap_packet_ptr->payload_ptr = temp_ptr;
02488             coap_packet_ptr->payload_len = new_payload_len;
02489             data_updated = true;
02490         }
02491     }
02492 
02493     return data_updated;
02494 }