Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

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