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