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