Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
sn_grs.c
Go to the documentation of this file.
00001 /* 00002 * Copyright (c) 2011-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 /** 00018 * 00019 * \file sn_grs.c 00020 * 00021 * \brief General resource server. 00022 * 00023 */ 00024 #include <string.h> 00025 #include <stdlib.h> 00026 #include "ns_list.h" 00027 #include "ns_types.h" 00028 #include "sn_nsdl.h" 00029 #include "sn_coap_header.h" 00030 #include "sn_coap_protocol.h" 00031 #include "source/include/sn_coap_protocol_internal.h" 00032 #include "sn_nsdl_lib.h" 00033 #include "sn_grs.h" 00034 00035 /* Defines */ 00036 #define WELLKNOWN_PATH_LEN 16 00037 #define WELLKNOWN_PATH (".well-known/core") 00038 00039 /* Local static function prototypes */ 00040 static int8_t sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr); 00041 static char *sn_grs_convert_uri(uint16_t *uri_len, const char *uri_ptr); 00042 static int8_t sn_grs_core_request(struct nsdl_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *coap_packet_ptr); 00043 static uint8_t coap_tx_callback(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *); 00044 static int8_t coap_rx_callback(sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address_ptr, void *param); 00045 00046 /* Extern function prototypes */ 00047 extern int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration); 00048 00049 /** 00050 * \fn int8_t sn_grs_destroy(void) 00051 * \brief This function may be used to flush GRS related stuff when a program exits. 00052 * @return always 0. 00053 */ 00054 extern int8_t sn_grs_destroy(struct grs_s *handle) 00055 { 00056 if( handle == NULL ){ 00057 return 0; 00058 } 00059 ns_list_foreach_safe(sn_nsdl_dynamic_resource_parameters_s, tmp, &handle->resource_root_list) { 00060 ns_list_remove(&handle->resource_root_list, tmp); 00061 --handle->resource_root_count; 00062 sn_grs_resource_info_free(handle, tmp); 00063 } 00064 handle->sn_grs_free(handle); 00065 00066 return 0; 00067 } 00068 00069 static uint8_t coap_tx_callback(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr, void *param) 00070 { 00071 struct nsdl_s *handle = (struct nsdl_s *)param; 00072 00073 if (handle == NULL) { 00074 return 0; 00075 } 00076 00077 return handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, data_ptr, data_len, address_ptr); 00078 } 00079 00080 static int8_t coap_rx_callback(sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address_ptr, void *param) 00081 { 00082 struct nsdl_s *handle = (struct nsdl_s *)param; 00083 00084 if (handle == NULL) { 00085 return 0; 00086 } 00087 00088 return handle->sn_nsdl_rx_callback(handle, coap_ptr, address_ptr); 00089 } 00090 00091 /** 00092 * \fn int8_t sn_grs_init (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t, 00093 * sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *), sn_nsdl_mem_s *sn_memory) 00094 * 00095 * \brief GRS library initialize function. 00096 * 00097 * This function initializes GRS and CoAP libraries. 00098 * 00099 * \param sn_grs_tx_callback A function pointer to a transmit callback function. 00100 * \param *sn_grs_rx_callback_ptr A function pointer to a receiving callback function. If received packet is not for GRS, it will be passed to 00101 * upper level (NSDL) to be proceed. 00102 * \param sn_memory A pointer to a structure containing the platform specific functions for memory allocation and free. 00103 * 00104 * \return success = 0, failure = -1 00105 * 00106 */ 00107 extern struct grs_s *sn_grs_init(uint8_t (*sn_grs_tx_callback_ptr)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, 00108 sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), 00109 void *(*sn_grs_alloc)(uint16_t), void (*sn_grs_free)(void *)) 00110 { 00111 00112 struct grs_s *handle_ptr = NULL; 00113 00114 /* Check parameters */ 00115 if (sn_grs_alloc == NULL || sn_grs_free == NULL || 00116 sn_grs_tx_callback_ptr == NULL || sn_grs_rx_callback_ptr == NULL) { 00117 return NULL; 00118 } 00119 00120 handle_ptr = sn_grs_alloc(sizeof(struct grs_s)); 00121 00122 if (handle_ptr == NULL) { 00123 return NULL; 00124 } 00125 00126 memset(handle_ptr, 0, sizeof(struct grs_s)); 00127 00128 /* Allocation and free - function pointers */ 00129 handle_ptr->sn_grs_alloc = sn_grs_alloc; 00130 handle_ptr->sn_grs_free = sn_grs_free; 00131 00132 /* TX callback function pointer */ 00133 handle_ptr->sn_grs_tx_callback = sn_grs_tx_callback_ptr; 00134 handle_ptr->sn_grs_rx_callback = sn_grs_rx_callback_ptr; 00135 00136 /* Initialize CoAP protocol library */ 00137 handle_ptr->coap = sn_coap_protocol_init(sn_grs_alloc, sn_grs_free, coap_tx_callback, coap_rx_callback); 00138 00139 return handle_ptr; 00140 } 00141 00142 extern sn_grs_resource_list_s *sn_grs_list_resource(struct grs_s *handle, const char *path) 00143 { 00144 (void) (path); 00145 sn_grs_resource_list_s *grs_resource_list_ptr = NULL; 00146 00147 if(handle == NULL){ 00148 return NULL; 00149 } 00150 00151 /* Allocate memory for the resource list to be filled */ 00152 grs_resource_list_ptr = handle->sn_grs_alloc(sizeof(sn_grs_resource_list_s)); 00153 if (!grs_resource_list_ptr) { 00154 goto fail; 00155 } 00156 00157 /* Count resources to the resource list struct */ 00158 grs_resource_list_ptr->res_count = handle->resource_root_count; 00159 grs_resource_list_ptr->res = NULL; 00160 00161 /**************************************/ 00162 /* Fill resource structs to the table */ 00163 /**************************************/ 00164 00165 /* If resources in list */ 00166 if (grs_resource_list_ptr->res_count) { 00167 int i; 00168 00169 /* Allocate memory for resources */ 00170 grs_resource_list_ptr->res = handle->sn_grs_alloc(grs_resource_list_ptr->res_count * sizeof(sn_grs_resource_s)); 00171 if (!grs_resource_list_ptr->res) { 00172 goto fail; 00173 } 00174 00175 /* Initialise the pointers to NULL to permit easy cleanup */ 00176 for (i = 0; i < grs_resource_list_ptr->res_count; i++) { 00177 grs_resource_list_ptr->res[i].path = NULL; 00178 } 00179 00180 i = 0; 00181 size_t len = 0; 00182 ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, grs_resource_ptr, &handle->resource_root_list) { 00183 /* Copy pathlen to resource list */ 00184 len = strlen(grs_resource_ptr->static_resource_parameters->path); 00185 00186 /* Allocate memory for path string */ 00187 grs_resource_list_ptr->res[i].path = handle->sn_grs_alloc(len); 00188 if (!grs_resource_list_ptr->res[i].path) { 00189 goto fail; 00190 } 00191 00192 /* Copy pathstring to resource list */ 00193 memcpy(grs_resource_list_ptr->res[i].path, 00194 grs_resource_ptr->static_resource_parameters->path, 00195 len); 00196 00197 i++; 00198 } 00199 } 00200 return grs_resource_list_ptr; 00201 00202 fail: 00203 sn_grs_free_resource_list(handle, grs_resource_list_ptr); 00204 return NULL; 00205 } 00206 00207 extern void sn_grs_free_resource_list(struct grs_s *handle, sn_grs_resource_list_s *list) 00208 { 00209 if (!list || !handle) { 00210 return; 00211 } 00212 00213 if (list->res) { 00214 for (int i = 0; i < list->res_count; i++) { 00215 if (list->res[i].path) { 00216 handle->sn_grs_free(list->res[i].path); 00217 list->res[i].path = NULL; 00218 } 00219 } 00220 handle->sn_grs_free(list->res); 00221 list->res = NULL; 00222 } 00223 00224 handle->sn_grs_free(list); 00225 } 00226 00227 extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_first_resource(struct grs_s *handle) 00228 { 00229 if( !handle ){ 00230 return NULL; 00231 } 00232 return ns_list_get_first(&handle->resource_root_list); 00233 } 00234 00235 extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_next_resource(struct grs_s *handle, 00236 const sn_nsdl_dynamic_resource_parameters_s *sn_grs_current_resource) 00237 { 00238 if( !handle || !sn_grs_current_resource ){ 00239 return NULL; 00240 } 00241 return ns_list_get_next(&handle->resource_root_list, sn_grs_current_resource); 00242 } 00243 00244 extern int8_t sn_grs_delete_resource(struct grs_s *handle, const char *path) 00245 { 00246 /* Local variables */ 00247 sn_nsdl_dynamic_resource_parameters_s *resource_temp = NULL; 00248 00249 /* Search if resource found */ 00250 resource_temp = sn_grs_search_resource(handle, path, SN_GRS_SEARCH_METHOD); 00251 00252 /* If not found */ 00253 if (resource_temp == NULL) { 00254 return SN_NSDL_FAILURE; 00255 } 00256 00257 /* If found, delete it and delete also subresources, if there is any */ 00258 do { 00259 /* Remove from list */ 00260 ns_list_remove(&handle->resource_root_list, resource_temp); 00261 --handle->resource_root_count; 00262 00263 /* Free */ 00264 sn_grs_resource_info_free(handle, resource_temp); 00265 00266 /* Search for subresources */ 00267 resource_temp = sn_grs_search_resource(handle, path, SN_GRS_DELETE_METHOD); 00268 } while (resource_temp != NULL); 00269 00270 return SN_NSDL_SUCCESS; 00271 } 00272 00273 int8_t sn_grs_put_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res) 00274 { 00275 if (!res || !handle) { 00276 return SN_NSDL_FAILURE; 00277 } 00278 00279 /* Check path validity */ 00280 if (!res->static_resource_parameters->path || res->static_resource_parameters->path[0] == '\0') { 00281 return SN_GRS_INVALID_PATH; 00282 } 00283 00284 /* Check if resource already exists */ 00285 if (sn_grs_search_resource(handle, 00286 res->static_resource_parameters->path, SN_GRS_SEARCH_METHOD) != (sn_nsdl_dynamic_resource_parameters_s *)NULL) { 00287 return SN_GRS_RESOURCE_ALREADY_EXISTS; 00288 } 00289 00290 res->registered = SN_NDSL_RESOURCE_NOT_REGISTERED; 00291 00292 ns_list_add_to_start(&handle->resource_root_list, res); 00293 ++handle->resource_root_count; 00294 00295 return SN_NSDL_SUCCESS; 00296 } 00297 00298 int8_t sn_grs_pop_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res) 00299 { 00300 if (!res || !handle) { 00301 return SN_NSDL_FAILURE; 00302 } 00303 00304 /* Check path validity */ 00305 if (!res->static_resource_parameters->path || res->static_resource_parameters->path[0] == '\0') { 00306 return SN_GRS_INVALID_PATH; 00307 } 00308 00309 /* Check if resource exists on list. */ 00310 if (sn_grs_search_resource(handle, 00311 res->static_resource_parameters->path, SN_GRS_SEARCH_METHOD) == (sn_nsdl_dynamic_resource_parameters_s *)NULL) { 00312 return SN_NSDL_FAILURE; 00313 } 00314 00315 ns_list_remove(&handle->resource_root_list, res); 00316 --handle->resource_root_count; 00317 00318 return SN_NSDL_SUCCESS; 00319 } 00320 00321 /** 00322 * \fn extern int8_t sn_grs_process_coap(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src) 00323 * 00324 * \brief To push CoAP packet to GRS library 00325 * 00326 * Used to push an CoAP packet to GRS library for processing. 00327 * 00328 * \param *packet Pointer to a uint8_t array containing the packet (including the CoAP headers). 00329 * After successful execution this array may contain the response packet. 00330 * 00331 * \param *packet_len Pointer to length of the packet. After successful execution this array may contain the length 00332 * of the response packet. 00333 * 00334 * \param *src Pointer to packet source address information. After successful execution this array may contain 00335 * the destination address of the response packet. 00336 * 00337 * \return 0 = success, -1 = failure 00338 */ 00339 extern int8_t sn_grs_process_coap(struct nsdl_s *nsdl_handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *src_addr_ptr) 00340 { 00341 if( !coap_packet_ptr || !nsdl_handle){ 00342 return SN_NSDL_FAILURE; 00343 } 00344 00345 sn_nsdl_dynamic_resource_parameters_s *resource_temp_ptr = NULL; 00346 sn_coap_msg_code_e status = COAP_MSG_CODE_EMPTY; 00347 sn_coap_hdr_s *response_message_hdr_ptr = NULL; 00348 struct grs_s *handle = nsdl_handle->grs; 00349 bool static_get_request = false; 00350 00351 if (coap_packet_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE) { 00352 /* Check if .well-known/core */ 00353 if (coap_packet_ptr->uri_path_len == WELLKNOWN_PATH_LEN && memcmp(coap_packet_ptr->uri_path_ptr, WELLKNOWN_PATH, WELLKNOWN_PATH_LEN) == 0) { 00354 return sn_grs_core_request(nsdl_handle, src_addr_ptr, coap_packet_ptr); 00355 } 00356 00357 /* Get resource */ 00358 char* path = nsdl_handle->grs->sn_grs_alloc(coap_packet_ptr->uri_path_len + 1); 00359 if (!path) { 00360 return SN_NSDL_FAILURE; 00361 } 00362 00363 memcpy(path, 00364 coap_packet_ptr->uri_path_ptr, 00365 coap_packet_ptr->uri_path_len); 00366 path[coap_packet_ptr->uri_path_len] = '\0'; 00367 00368 resource_temp_ptr = sn_grs_search_resource(handle, path, SN_GRS_SEARCH_METHOD); 00369 nsdl_handle->grs->sn_grs_free(path); 00370 00371 /* * * * * * * * * * * */ 00372 /* If resource exists */ 00373 /* * * * * * * * * * * */ 00374 if (resource_temp_ptr) { 00375 /* If dynamic resource, go to callback */ 00376 if (resource_temp_ptr->static_resource_parameters->mode == SN_GRS_DYNAMIC) { 00377 /* Check accesses */ 00378 if (((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) && !(resource_temp_ptr->access & SN_GRS_GET_ALLOWED)) || 00379 ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) && !(resource_temp_ptr->access & SN_GRS_POST_ALLOWED)) || 00380 ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) && !(resource_temp_ptr->access & SN_GRS_PUT_ALLOWED)) || 00381 ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) && !(resource_temp_ptr->access & SN_GRS_DELETE_ALLOWED))) { 00382 status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00383 } else { 00384 /* Do not call null pointer.. */ 00385 if (resource_temp_ptr->sn_grs_dyn_res_callback != NULL) { 00386 resource_temp_ptr->sn_grs_dyn_res_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr, SN_NSDL_PROTOCOL_COAP); 00387 } else { 00388 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { 00389 handle->sn_grs_free(coap_packet_ptr->payload_ptr); 00390 coap_packet_ptr->payload_ptr = 0; 00391 } 00392 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); 00393 } 00394 00395 return SN_NSDL_SUCCESS; 00396 } 00397 } else { 00398 /* Static resource handling */ 00399 switch (coap_packet_ptr->msg_code) { 00400 case COAP_MSG_CODE_REQUEST_GET: 00401 if (resource_temp_ptr->access & SN_GRS_GET_ALLOWED) { 00402 status = COAP_MSG_CODE_RESPONSE_CONTENT; 00403 static_get_request = true; 00404 } else { 00405 status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00406 } 00407 break; 00408 00409 case COAP_MSG_CODE_REQUEST_POST: 00410 case COAP_MSG_CODE_REQUEST_PUT: 00411 case COAP_MSG_CODE_REQUEST_DELETE: 00412 status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00413 break; 00414 00415 default: 00416 status = COAP_MSG_CODE_RESPONSE_FORBIDDEN; 00417 break; 00418 } 00419 } 00420 } 00421 00422 /* * * * * * * * * * * * * * */ 00423 /* If resource was not found */ 00424 /* * * * * * * * * * * * * * */ 00425 00426 else { 00427 if (coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) { 00428 handle->sn_grs_rx_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr); 00429 00430 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { 00431 handle->sn_grs_free(coap_packet_ptr->payload_ptr); 00432 coap_packet_ptr->payload_ptr = 0; 00433 } 00434 00435 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); 00436 return SN_NSDL_SUCCESS; 00437 } else { 00438 status = COAP_MSG_CODE_RESPONSE_NOT_FOUND; 00439 } 00440 } 00441 } 00442 00443 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00444 /* If received packed was other than reset, create response */ 00445 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00446 if (coap_packet_ptr->msg_type != COAP_MSG_TYPE_RESET && coap_packet_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT) { 00447 00448 /* Allocate resopnse message */ 00449 response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->coap); 00450 if (!response_message_hdr_ptr) { 00451 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { 00452 handle->sn_grs_free(coap_packet_ptr->payload_ptr); 00453 coap_packet_ptr->payload_ptr = 0; 00454 } 00455 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); 00456 return SN_NSDL_FAILURE; 00457 } 00458 00459 /* If status has not been defined, response internal server error */ 00460 if (status == COAP_MSG_CODE_EMPTY) { 00461 status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00462 } 00463 00464 /* Fill header */ 00465 response_message_hdr_ptr->msg_code = status; 00466 00467 if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 00468 response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; 00469 } else { 00470 response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; 00471 } 00472 00473 response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id; 00474 00475 if (coap_packet_ptr->token_ptr) { 00476 response_message_hdr_ptr->token_len = coap_packet_ptr->token_len; 00477 response_message_hdr_ptr->token_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->token_len); 00478 if (!response_message_hdr_ptr->token_ptr) { 00479 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr); 00480 00481 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { 00482 handle->sn_grs_free(coap_packet_ptr->payload_ptr); 00483 coap_packet_ptr->payload_ptr = 0; 00484 } 00485 00486 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); 00487 return SN_NSDL_FAILURE; 00488 } 00489 memcpy(response_message_hdr_ptr->token_ptr, coap_packet_ptr->token_ptr, response_message_hdr_ptr->token_len); 00490 } 00491 00492 if (status == COAP_MSG_CODE_RESPONSE_CONTENT) { 00493 /* Add content type if other than default */ 00494 if (resource_temp_ptr->static_resource_parameters) { 00495 response_message_hdr_ptr->content_format = 00496 (sn_coap_content_format_e) resource_temp_ptr->coap_content_type; 00497 } 00498 00499 /* Add payload */ 00500 if (resource_temp_ptr->resourcelen != 0) { 00501 response_message_hdr_ptr->payload_len = resource_temp_ptr->resourcelen; 00502 response_message_hdr_ptr->payload_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->payload_len); 00503 00504 if (!response_message_hdr_ptr->payload_ptr) { 00505 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr); 00506 00507 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { 00508 handle->sn_grs_free(coap_packet_ptr->payload_ptr); 00509 coap_packet_ptr->payload_ptr = 0; 00510 } 00511 00512 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); 00513 return SN_NSDL_FAILURE; 00514 } 00515 00516 memcpy(response_message_hdr_ptr->payload_ptr, 00517 resource_temp_ptr->resource, 00518 response_message_hdr_ptr->payload_len); 00519 } 00520 // Add max-age attribute for static resources. 00521 // Not a mandatory parameter, no need to return in case of memory allocation fails. 00522 if (static_get_request) { 00523 if (sn_coap_parser_alloc_options(handle->coap, response_message_hdr_ptr)) { 00524 response_message_hdr_ptr->options_list_ptr->max_age = 0; 00525 } 00526 } 00527 } 00528 sn_grs_send_coap_message(nsdl_handle, src_addr_ptr, response_message_hdr_ptr); 00529 00530 if (response_message_hdr_ptr->payload_ptr) { 00531 handle->sn_grs_free(response_message_hdr_ptr->payload_ptr); 00532 response_message_hdr_ptr->payload_ptr = 0; 00533 } 00534 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr); 00535 } 00536 00537 /* Free parsed CoAP message */ 00538 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { 00539 handle->sn_grs_free(coap_packet_ptr->payload_ptr); 00540 coap_packet_ptr->payload_ptr = 0; 00541 } 00542 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); 00543 00544 return SN_NSDL_SUCCESS; 00545 } 00546 00547 extern int8_t sn_grs_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr) 00548 { 00549 uint8_t *message_ptr = NULL; 00550 uint16_t message_len = 0; 00551 int16_t ret_val = 0; 00552 00553 if( !handle ){ 00554 return SN_NSDL_FAILURE; 00555 } 00556 00557 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ 00558 ret_val = prepare_blockwise_message(handle->grs->coap, coap_hdr_ptr); 00559 if( 0 != ret_val ) { 00560 return SN_NSDL_FAILURE; 00561 } 00562 #endif 00563 00564 /* Calculate message length */ 00565 message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_hdr_ptr, handle->grs->coap->sn_coap_block_data_size); 00566 00567 /* Allocate memory for message and check was allocating successfully */ 00568 message_ptr = handle->grs->sn_grs_alloc(message_len); 00569 if (message_ptr == NULL) { 00570 return SN_NSDL_FAILURE; 00571 } 00572 00573 /* Build CoAP message */ 00574 ret_val = sn_coap_protocol_build(handle->grs->coap, address_ptr, message_ptr, coap_hdr_ptr, (void *)handle); 00575 if (ret_val < 0) { 00576 handle->grs->sn_grs_free(message_ptr); 00577 message_ptr = 0; 00578 if (ret_val == -4) { 00579 return SN_NSDL_RESEND_QUEUE_FULL; 00580 } else { 00581 return SN_NSDL_FAILURE; 00582 } 00583 } 00584 00585 /* Call tx callback function to send message */ 00586 ret_val = handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address_ptr); 00587 00588 /* Free allocated memory */ 00589 handle->grs->sn_grs_free(message_ptr); 00590 message_ptr = 0; 00591 00592 if (ret_val == 0) { 00593 return SN_NSDL_FAILURE; 00594 } else { 00595 return SN_NSDL_SUCCESS; 00596 } 00597 } 00598 00599 static int8_t sn_grs_core_request(struct nsdl_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *coap_packet_ptr) 00600 { 00601 sn_coap_hdr_s *response_message_hdr_ptr = NULL; 00602 sn_coap_content_format_e wellknown_content_format = COAP_CT_LINK_FORMAT; 00603 00604 /* Allocate response message */ 00605 response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->grs->coap); 00606 if (response_message_hdr_ptr == NULL) { 00607 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { 00608 handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr); 00609 coap_packet_ptr->payload_ptr = 0; 00610 } 00611 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); 00612 return SN_NSDL_FAILURE; 00613 } 00614 00615 /* Build response */ 00616 response_message_hdr_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; 00617 response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; 00618 response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id; 00619 response_message_hdr_ptr->content_format = wellknown_content_format; 00620 00621 sn_nsdl_build_registration_body(handle, response_message_hdr_ptr, 0); 00622 00623 /* Send and free */ 00624 sn_grs_send_coap_message(handle, src_addr_ptr, response_message_hdr_ptr); 00625 00626 if (response_message_hdr_ptr->payload_ptr) { 00627 handle->grs->sn_grs_free(response_message_hdr_ptr->payload_ptr); 00628 response_message_hdr_ptr->payload_ptr = 0; 00629 } 00630 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, response_message_hdr_ptr); 00631 00632 /* Free parsed CoAP message */ 00633 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { 00634 handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr); 00635 coap_packet_ptr->payload_ptr = 0; 00636 } 00637 sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); 00638 00639 return SN_NSDL_SUCCESS; 00640 } 00641 00642 /** 00643 * \fn static sn_grs_resource_info_s *sn_grs_search_resource(struct grs_s *handle, const char *path, uint8_t search_method) 00644 * 00645 * \brief Searches given resource from linked list 00646 * 00647 * Search either precise path, or subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... 00648 * 00649 * \param pathlen Length of the path to be search 00650 * 00651 * \param *path Pointer to the path string to be search 00652 * 00653 * \param search_method Search method, SEARCH or DELETE 00654 * 00655 * \return Pointer to the resource. If resource not found, return value is NULL 00656 * 00657 */ 00658 00659 sn_nsdl_dynamic_resource_parameters_s *sn_grs_search_resource(struct grs_s *handle, const char *path, uint8_t search_method) 00660 { 00661 /* Local variables */ 00662 char *path_temp_ptr = NULL; 00663 /* Check parameters */ 00664 if (!handle || !path) { 00665 return NULL; 00666 } 00667 uint16_t pathlen = strlen(path); 00668 /* Remove '/' - marks from the end and beginning */ 00669 path_temp_ptr = sn_grs_convert_uri(&pathlen, path); 00670 00671 /* Searchs exact path */ 00672 if (search_method == SN_GRS_SEARCH_METHOD) { 00673 /* Scan all nodes on list */ 00674 ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) { 00675 /* If length equals.. */ 00676 size_t len = 0; 00677 if(resource_search_temp && 00678 resource_search_temp->static_resource_parameters && 00679 resource_search_temp->static_resource_parameters->path) { 00680 len = strlen(resource_search_temp->static_resource_parameters->path); 00681 } 00682 00683 if (len == pathlen) { 00684 /* Compare paths, If same return node pointer*/ 00685 if (0 == memcmp(resource_search_temp->static_resource_parameters->path, 00686 path_temp_ptr, 00687 pathlen)) { 00688 return resource_search_temp; 00689 } 00690 } 00691 } 00692 } 00693 /* Search also subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... */ 00694 else if (search_method == SN_GRS_DELETE_METHOD) { 00695 /* Scan all nodes on list */ 00696 ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) { 00697 char *temp_path = resource_search_temp->static_resource_parameters->path; 00698 if (strlen(resource_search_temp->static_resource_parameters->path) > pathlen && 00699 (*(temp_path + (uint8_t)pathlen) == '/') && 00700 0 == memcmp(resource_search_temp->static_resource_parameters->path, 00701 path_temp_ptr, 00702 pathlen)) { 00703 return resource_search_temp; 00704 } 00705 } 00706 } 00707 00708 /* If there was not nodes we wanted, return NULL */ 00709 return NULL; 00710 } 00711 00712 /** 00713 * \fn static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr) 00714 * 00715 * \brief Removes '/' from the beginning and from the end of uri string 00716 * 00717 * \param *uri_len Pointer to the length of the path string 00718 * 00719 * \param *uri_ptr Pointer to the path string 00720 * 00721 * \return start pointer of the uri 00722 * 00723 */ 00724 00725 static char *sn_grs_convert_uri(uint16_t *uri_len, const char *uri_ptr) 00726 { 00727 /* Local variables */ 00728 char *uri_start_ptr = (char *) uri_ptr; 00729 00730 /* If '/' in the beginning, update uri start pointer and uri len */ 00731 if (*uri_ptr == '/') { 00732 uri_start_ptr = (char *) uri_ptr + 1; 00733 *uri_len = *uri_len - 1; 00734 } 00735 00736 /* If '/' at the end, update uri len */ 00737 if (*(uri_start_ptr + *uri_len - 1) == '/') { 00738 *uri_len = *uri_len - 1; 00739 } 00740 00741 /* Return start pointer */ 00742 return uri_start_ptr; 00743 } 00744 00745 /** 00746 * \fn static int8_t sn_grs_resource_info_free(sn_grs_resource_info_s *resource_ptr) 00747 * 00748 * \brief Frees resource info structure 00749 * 00750 * \param *resource_ptr Pointer to the resource 00751 * 00752 * \return 0 if success, -1 if failed 00753 * 00754 */ 00755 static int8_t sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr) 00756 { 00757 if (resource_ptr) { 00758 #ifdef MEMORY_OPTIMIZED_API 00759 if (resource_ptr->free_on_delete) { 00760 handle->sn_grs_free(resource_ptr); 00761 } 00762 return SN_NSDL_FAILURE; 00763 #else 00764 if (resource_ptr->static_resource_parameters && 00765 resource_ptr->static_resource_parameters->free_on_delete) { 00766 #ifndef RESOURCE_ATTRIBUTES_LIST 00767 #ifndef DISABLE_INTERFACE_DESCRIPTION 00768 if (resource_ptr->static_resource_parameters->interface_description_ptr) { 00769 handle->sn_grs_free(resource_ptr->static_resource_parameters->interface_description_ptr); 00770 resource_ptr->static_resource_parameters->interface_description_ptr = 0; 00771 } 00772 #endif 00773 #ifndef DISABLE_RESOURCE_TYPE 00774 if (resource_ptr->static_resource_parameters->resource_type_ptr) { 00775 handle->sn_grs_free(resource_ptr->static_resource_parameters->resource_type_ptr); 00776 resource_ptr->static_resource_parameters->resource_type_ptr = 0; 00777 } 00778 #endif 00779 #else 00780 sn_nsdl_free_resource_attributes_list(resource_ptr->static_resource_parameters); 00781 #endif 00782 if (resource_ptr->static_resource_parameters->path) { 00783 handle->sn_grs_free(resource_ptr->static_resource_parameters->path); 00784 resource_ptr->static_resource_parameters->path = 0; 00785 } 00786 00787 if (resource_ptr->resource) { 00788 handle->sn_grs_free(resource_ptr->resource); 00789 resource_ptr->resource = 0; 00790 } 00791 00792 handle->sn_grs_free(resource_ptr->static_resource_parameters); 00793 resource_ptr->static_resource_parameters = 0; 00794 } 00795 if (resource_ptr->free_on_delete) { 00796 handle->sn_grs_free(resource_ptr); 00797 } 00798 return SN_NSDL_SUCCESS; 00799 #endif 00800 } 00801 return SN_NSDL_FAILURE; //Dead code? 00802 } 00803 00804 void sn_grs_mark_resources_as_registered(struct nsdl_s *handle) 00805 { 00806 if( !handle ){ 00807 return; 00808 } 00809 00810 sn_nsdl_dynamic_resource_parameters_s *temp_resource; 00811 00812 temp_resource = sn_grs_get_first_resource(handle->grs); 00813 00814 while (temp_resource) { 00815 if (temp_resource->registered == SN_NDSL_RESOURCE_REGISTERING) { 00816 temp_resource->registered = SN_NDSL_RESOURCE_REGISTERED; 00817 } 00818 temp_resource = sn_grs_get_next_resource(handle->grs, temp_resource); 00819 } 00820 }
Generated on Tue Jul 12 2022 19:01:37 by 1.7.2