Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_grs.c Source File

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_nsdl_dynamic_resource_parameters_s *sn_grs_get_first_resource(struct grs_s *handle)
00143 {
00144     if( !handle ){
00145         return NULL;
00146     }
00147     return ns_list_get_first(&handle->resource_root_list);
00148 }
00149 
00150 extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_next_resource(struct grs_s *handle,
00151                                                                              const sn_nsdl_dynamic_resource_parameters_s *sn_grs_current_resource)
00152 {
00153     if( !handle || !sn_grs_current_resource ){
00154         return NULL;
00155     }
00156     return ns_list_get_next(&handle->resource_root_list, sn_grs_current_resource);
00157 }
00158 
00159 extern int8_t sn_grs_delete_resource(struct grs_s *handle, const char *path)
00160 {
00161     /* Local variables */
00162     sn_nsdl_dynamic_resource_parameters_s     *resource_temp  = NULL;
00163 
00164     /* Search if resource found */
00165     resource_temp = sn_grs_search_resource(handle, path, SN_GRS_SEARCH_METHOD);
00166 
00167     /* If not found */
00168     if (resource_temp == NULL) {
00169         return SN_NSDL_FAILURE;
00170     }
00171 
00172     /* If found, delete it and delete also subresources, if there is any */
00173     do {
00174         /* Remove from list */
00175         ns_list_remove(&handle->resource_root_list, resource_temp);
00176         --handle->resource_root_count;
00177 
00178         /* Free */
00179         sn_grs_resource_info_free(handle, resource_temp);
00180 
00181         /* Search for subresources */
00182         resource_temp = sn_grs_search_resource(handle, path, SN_GRS_DELETE_METHOD);
00183     } while (resource_temp != NULL);
00184 
00185     return SN_NSDL_SUCCESS;
00186 }
00187 
00188 int8_t sn_grs_put_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
00189 {
00190     if (!res || !handle) {
00191         return SN_NSDL_FAILURE;
00192     }
00193 
00194     /* Check path validity */
00195     if (!res->static_resource_parameters->path || res->static_resource_parameters->path[0] == '\0') {
00196         return SN_GRS_INVALID_PATH;
00197     }
00198 
00199     /* Check if resource already exists */
00200     if (sn_grs_search_resource(handle,
00201                                res->static_resource_parameters->path, SN_GRS_SEARCH_METHOD) != (sn_nsdl_dynamic_resource_parameters_s *)NULL) {
00202         return SN_GRS_RESOURCE_ALREADY_EXISTS;
00203     }
00204 
00205     res->registered = SN_NDSL_RESOURCE_NOT_REGISTERED;
00206 
00207     ns_list_add_to_start(&handle->resource_root_list, res);
00208     ++handle->resource_root_count;
00209 
00210     return SN_NSDL_SUCCESS;
00211 }
00212 
00213 int8_t sn_grs_pop_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
00214 {
00215     if (!res || !handle) {
00216         return SN_NSDL_FAILURE;
00217     }
00218 
00219     /* Check path validity */
00220     if (!res->static_resource_parameters->path || res->static_resource_parameters->path[0] == '\0') {
00221         return SN_GRS_INVALID_PATH;
00222     }
00223 
00224     /* Check if resource exists on list. */
00225     if (sn_grs_search_resource(handle,
00226                                res->static_resource_parameters->path, SN_GRS_SEARCH_METHOD) == (sn_nsdl_dynamic_resource_parameters_s *)NULL) {
00227         return SN_NSDL_FAILURE;
00228     }
00229 
00230     ns_list_remove(&handle->resource_root_list, res);
00231     --handle->resource_root_count;
00232 
00233     return SN_NSDL_SUCCESS;
00234 }
00235 
00236 /**
00237  * \fn  extern int8_t sn_grs_process_coap(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src)
00238  *
00239  * \brief To push CoAP packet to GRS library
00240  *
00241  *  Used to push an CoAP packet to GRS library for processing.
00242  *
00243  *  \param  *packet     Pointer to a uint8_t array containing the packet (including the CoAP headers).
00244  *                      After successful execution this array may contain the response packet.
00245  *
00246  *  \param  *packet_len Pointer to length of the packet. After successful execution this array may contain the length
00247  *                      of the response packet.
00248  *
00249  *  \param  *src        Pointer to packet source address information. After successful execution this array may contain
00250  *                      the destination address of the response packet.
00251  *
00252  *  \return             0 = success, -1 = failure
00253 */
00254 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)
00255 {
00256     if( !coap_packet_ptr || !nsdl_handle){
00257         return SN_NSDL_FAILURE;
00258     }
00259 
00260     sn_nsdl_dynamic_resource_parameters_s *resource_temp_ptr  = NULL;
00261     sn_coap_msg_code_e      status              = COAP_MSG_CODE_EMPTY;
00262     sn_coap_hdr_s           *response_message_hdr_ptr = NULL;
00263     struct grs_s            *handle = nsdl_handle->grs;
00264     bool                    static_get_request = false;
00265 
00266     if (coap_packet_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE) {
00267         /* Check if .well-known/core */
00268         if (coap_packet_ptr->uri_path_len == WELLKNOWN_PATH_LEN && memcmp(coap_packet_ptr->uri_path_ptr, WELLKNOWN_PATH, WELLKNOWN_PATH_LEN) == 0) {
00269             return sn_grs_core_request(nsdl_handle, src_addr_ptr, coap_packet_ptr);
00270         }
00271 
00272         /* Get resource */
00273         char* path = nsdl_handle->grs->sn_grs_alloc(coap_packet_ptr->uri_path_len + 1);
00274         if (!path) {
00275             return SN_NSDL_FAILURE;
00276         }
00277 
00278         memcpy(path,
00279                coap_packet_ptr->uri_path_ptr,
00280                coap_packet_ptr->uri_path_len);
00281         path[coap_packet_ptr->uri_path_len] = '\0';
00282 
00283         resource_temp_ptr = sn_grs_search_resource(handle, path, SN_GRS_SEARCH_METHOD);
00284         nsdl_handle->grs->sn_grs_free(path);
00285 
00286         /* * * * * * * * * * * */
00287         /* If resource exists  */
00288         /* * * * * * * * * * * */
00289         if (resource_temp_ptr) {
00290             /* If dynamic resource, go to callback */
00291             if (resource_temp_ptr->static_resource_parameters->mode == SN_GRS_DYNAMIC) {
00292                 /* Check accesses */
00293                 if (((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) && !(resource_temp_ptr->access & SN_GRS_GET_ALLOWED))          ||
00294                         ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) && !(resource_temp_ptr->access & SN_GRS_POST_ALLOWED))   ||
00295                         ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) && !(resource_temp_ptr->access & SN_GRS_PUT_ALLOWED))     ||
00296                         ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) && !(resource_temp_ptr->access & SN_GRS_DELETE_ALLOWED))) {
00297                     status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00298                 } else {
00299                     /* Do not call null pointer.. */
00300                     if (resource_temp_ptr->sn_grs_dyn_res_callback != NULL) {
00301                         resource_temp_ptr->sn_grs_dyn_res_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr, SN_NSDL_PROTOCOL_COAP);
00302                     } else {
00303                         if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00304                             handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00305                             coap_packet_ptr->payload_ptr = 0;
00306                         }
00307                         sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00308                     }
00309 
00310                     return SN_NSDL_SUCCESS;
00311                 }
00312             } else {
00313                 /* Static resource handling */
00314                 switch (coap_packet_ptr->msg_code) {
00315                     case COAP_MSG_CODE_REQUEST_GET:
00316                         if (resource_temp_ptr->access & SN_GRS_GET_ALLOWED) {
00317                             status = COAP_MSG_CODE_RESPONSE_CONTENT;
00318                             static_get_request = true;
00319                         } else {
00320                             status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00321                         }
00322                         break;
00323 
00324                     case COAP_MSG_CODE_REQUEST_POST:
00325                     case COAP_MSG_CODE_REQUEST_PUT:
00326                     case COAP_MSG_CODE_REQUEST_DELETE:
00327                         status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00328                         break;
00329 
00330                     default:
00331                         status = COAP_MSG_CODE_RESPONSE_FORBIDDEN;
00332                         break;
00333                 }
00334             }
00335         }
00336 
00337         /* * * * * * * * * * * * * * */
00338         /* If resource was not found */
00339         /* * * * * * * * * * * * * * */
00340 
00341         else {
00342             if (coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) {
00343                 handle->sn_grs_rx_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr);
00344 
00345                 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00346                     handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00347                     coap_packet_ptr->payload_ptr = 0;
00348                 }
00349 
00350                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00351                 return SN_NSDL_SUCCESS;
00352             } else {
00353                 status = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00354             }
00355         }
00356     }
00357 
00358     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00359     /* If received packed was other than reset, create response  */
00360     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00361     if (coap_packet_ptr->msg_type != COAP_MSG_TYPE_RESET && coap_packet_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT) {
00362 
00363         /* Allocate resopnse message  */
00364         response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->coap);
00365         if (!response_message_hdr_ptr) {
00366             if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00367                 handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00368                 coap_packet_ptr->payload_ptr = 0;
00369             }
00370             sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00371             return SN_NSDL_FAILURE;
00372         }
00373 
00374         /* If status has not been defined, response internal server error */
00375         if (status == COAP_MSG_CODE_EMPTY) {
00376             status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
00377         }
00378 
00379         /* Fill header */
00380         response_message_hdr_ptr->msg_code = status;
00381 
00382         if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
00383             response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
00384         } else {
00385             response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
00386         }
00387 
00388         response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
00389 
00390         if (coap_packet_ptr->token_ptr) {
00391             response_message_hdr_ptr->token_len = coap_packet_ptr->token_len;
00392             response_message_hdr_ptr->token_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->token_len);
00393             if (!response_message_hdr_ptr->token_ptr) {
00394                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00395 
00396                 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00397                     handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00398                     coap_packet_ptr->payload_ptr = 0;
00399                 }
00400 
00401                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00402                 return SN_NSDL_FAILURE;
00403             }
00404             memcpy(response_message_hdr_ptr->token_ptr, coap_packet_ptr->token_ptr, response_message_hdr_ptr->token_len);
00405         }
00406 
00407         if (status == COAP_MSG_CODE_RESPONSE_CONTENT) {
00408             /* Add content type if other than default */
00409             if (resource_temp_ptr->static_resource_parameters) {
00410                 response_message_hdr_ptr->content_format =
00411                     (sn_coap_content_format_e) resource_temp_ptr->coap_content_type;
00412              }
00413 
00414             /* Add payload */
00415             if (resource_temp_ptr->resource_len != 0) {
00416                 response_message_hdr_ptr->payload_len = resource_temp_ptr->resource_len;
00417                 response_message_hdr_ptr->payload_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->payload_len);
00418 
00419                 if (!response_message_hdr_ptr->payload_ptr) {
00420                     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00421 
00422                     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00423                         handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00424                         coap_packet_ptr->payload_ptr = 0;
00425                     }
00426 
00427                     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00428                     return SN_NSDL_FAILURE;
00429                 }
00430 
00431                 memcpy(response_message_hdr_ptr->payload_ptr,
00432                        resource_temp_ptr->resource,
00433                        response_message_hdr_ptr->payload_len);
00434             }
00435             // Add max-age attribute for static resources.
00436             // Not a mandatory parameter, no need to return in case of memory allocation fails.
00437             if (static_get_request) {
00438                 if (sn_coap_parser_alloc_options(handle->coap, response_message_hdr_ptr)) {
00439                     response_message_hdr_ptr->options_list_ptr->max_age = 0;
00440                 }
00441             }
00442         }
00443         sn_grs_send_coap_message(nsdl_handle, src_addr_ptr, response_message_hdr_ptr);
00444 
00445         if (response_message_hdr_ptr->payload_ptr) {
00446             handle->sn_grs_free(response_message_hdr_ptr->payload_ptr);
00447             response_message_hdr_ptr->payload_ptr = 0;
00448         }
00449         sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00450     }
00451 
00452     /* Free parsed CoAP message */
00453     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00454         handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00455         coap_packet_ptr->payload_ptr = 0;
00456     }
00457     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00458 
00459     return SN_NSDL_SUCCESS;
00460 }
00461 
00462 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)
00463 {
00464     uint8_t *message_ptr = NULL;
00465     uint16_t message_len = 0;
00466     int16_t ret_val = 0;
00467 
00468     if( !handle ){
00469         return SN_NSDL_FAILURE;
00470     }
00471 
00472 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */
00473     ret_val = prepare_blockwise_message(handle->grs->coap, coap_hdr_ptr);
00474     if( 0 != ret_val ) {
00475         return SN_NSDL_FAILURE;
00476     }
00477 #endif
00478 
00479     /* Calculate message length */
00480     message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_hdr_ptr, handle->grs->coap->sn_coap_block_data_size);
00481 
00482     /* Allocate memory for message and check was allocating successfully */
00483     message_ptr = handle->grs->sn_grs_alloc(message_len);
00484     if (message_ptr == NULL) {
00485         return SN_NSDL_FAILURE;
00486     }
00487 
00488     /* Build CoAP message */
00489     ret_val = sn_coap_protocol_build(handle->grs->coap, address_ptr, message_ptr, coap_hdr_ptr, (void *)handle);
00490     if (ret_val < 0) {
00491         handle->grs->sn_grs_free(message_ptr);
00492         message_ptr = 0;
00493         if (ret_val == -4) {
00494             return SN_NSDL_RESEND_QUEUE_FULL;
00495         } else {
00496             return SN_NSDL_FAILURE;
00497         }
00498     }
00499 
00500     /* Call tx callback function to send message */
00501     ret_val = handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address_ptr);
00502 
00503     /* Free allocated memory */
00504     handle->grs->sn_grs_free(message_ptr);
00505     message_ptr = 0;
00506 
00507     if (ret_val == 0) {
00508         return SN_NSDL_FAILURE;
00509     } else {
00510         return SN_NSDL_SUCCESS;
00511     }
00512 }
00513 
00514 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)
00515 {
00516     sn_coap_hdr_s           *response_message_hdr_ptr = NULL;
00517     sn_coap_content_format_e wellknown_content_format = COAP_CT_LINK_FORMAT;
00518 
00519     /* Allocate response message  */
00520     response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
00521     if (response_message_hdr_ptr == NULL) {
00522         if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00523             handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr);
00524             coap_packet_ptr->payload_ptr = 0;
00525         }
00526         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00527         return SN_NSDL_FAILURE;
00528     }
00529 
00530     /* Build response */
00531     response_message_hdr_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00532     response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
00533     response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
00534     response_message_hdr_ptr->content_format = wellknown_content_format;
00535 
00536     sn_nsdl_build_registration_body(handle, response_message_hdr_ptr, 0);
00537 
00538     /* Send and free */
00539     sn_grs_send_coap_message(handle, src_addr_ptr, response_message_hdr_ptr);
00540 
00541     if (response_message_hdr_ptr->payload_ptr) {
00542         handle->grs->sn_grs_free(response_message_hdr_ptr->payload_ptr);
00543         response_message_hdr_ptr->payload_ptr = 0;
00544     }
00545     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, response_message_hdr_ptr);
00546 
00547     /* Free parsed CoAP message */
00548     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00549         handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr);
00550         coap_packet_ptr->payload_ptr = 0;
00551     }
00552     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00553 
00554     return SN_NSDL_SUCCESS;
00555 }
00556 
00557 /**
00558  * \fn  static sn_grs_resource_info_s *sn_grs_search_resource(struct grs_s *handle, const char *path, uint8_t search_method)
00559  *
00560  * \brief Searches given resource from linked list
00561  *
00562  *  Search either precise path, or subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc...
00563  *
00564  *  \param  pathlen         Length of the path to be search
00565  *
00566  *  \param  *path           Pointer to the path string to be search
00567  *
00568  *  \param  search_method   Search method, SEARCH or DELETE
00569  *
00570  *  \return                 Pointer to the resource. If resource not found, return value is NULL
00571  *
00572 */
00573 
00574 sn_nsdl_dynamic_resource_parameters_s *sn_grs_search_resource(struct grs_s *handle, const char *path, uint8_t search_method)
00575 {
00576     /* Local variables */
00577     char                     *path_temp_ptr          = NULL;
00578     /* Check parameters */
00579     if (!handle || !path) {
00580         return NULL;
00581     }
00582     uint16_t pathlen = strlen(path);
00583     /* Remove '/' - marks from the end and beginning */
00584     path_temp_ptr = sn_grs_convert_uri(&pathlen, path);
00585 
00586     /* Searchs exact path */
00587     if (search_method == SN_GRS_SEARCH_METHOD) {
00588         /* Scan all nodes on list */
00589         ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) {
00590             /* If length equals.. */
00591             size_t len = 0;
00592             if(resource_search_temp &&
00593                     resource_search_temp->static_resource_parameters &&
00594                     resource_search_temp->static_resource_parameters->path) {
00595                 len = strlen(resource_search_temp->static_resource_parameters->path);
00596             }
00597 
00598             if (len == pathlen) {
00599                 /* Compare paths, If same return node pointer*/
00600                 if (0 == memcmp(resource_search_temp->static_resource_parameters->path,
00601                                 path_temp_ptr,
00602                                 pathlen)) {
00603                     return resource_search_temp;
00604                 }
00605             }
00606         }
00607     }
00608     /* Search also subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... */
00609     else if (search_method == SN_GRS_DELETE_METHOD) {
00610         /* Scan all nodes on list */
00611         ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) {
00612             char *temp_path = resource_search_temp->static_resource_parameters->path;
00613             if (strlen(resource_search_temp->static_resource_parameters->path) > pathlen &&
00614                     (*(temp_path + (uint8_t)pathlen) == '/') &&
00615                     0 == memcmp(resource_search_temp->static_resource_parameters->path,
00616                                 path_temp_ptr,
00617                                 pathlen)) {
00618                 return resource_search_temp;
00619             }
00620         }
00621     }
00622 
00623     /* If there was not nodes we wanted, return NULL */
00624     return NULL;
00625 }
00626 
00627 /**
00628  * \fn  static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr)
00629  *
00630  * \brief Removes '/' from the beginning and from the end of uri string
00631  *
00632  *  \param  *uri_len            Pointer to the length of the path string
00633  *
00634  *  \param  *uri_ptr            Pointer to the path string
00635  *
00636  *  \return start pointer of the uri
00637  *
00638 */
00639 
00640 static char *sn_grs_convert_uri(uint16_t *uri_len, const char *uri_ptr)
00641 {
00642     /* Local variables */
00643     char *uri_start_ptr = (char *) uri_ptr;
00644 
00645     /* If '/' in the beginning, update uri start pointer and uri len */
00646     if (*uri_ptr == '/') {
00647         uri_start_ptr = (char *) uri_ptr + 1;
00648         *uri_len = *uri_len - 1;
00649     }
00650 
00651     /* If '/' at the end, update uri len */
00652     if (*(uri_start_ptr + *uri_len - 1) == '/') {
00653         *uri_len = *uri_len - 1;
00654     }
00655 
00656     /* Return start pointer */
00657     return uri_start_ptr;
00658 }
00659 
00660 /**
00661  * \fn  static int8_t sn_grs_resource_info_free(sn_grs_resource_info_s *resource_ptr)
00662  *
00663  * \brief Frees resource info structure
00664  *
00665  *  \param *resource_ptr    Pointer to the resource
00666  *
00667  *  \return 0 if success, -1 if failed
00668  *
00669 */
00670 static int8_t sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr)
00671 {
00672     if (resource_ptr) {
00673 #ifdef MEMORY_OPTIMIZED_API
00674         if (resource_ptr->free_on_delete) {
00675             handle->sn_grs_free(resource_ptr);
00676         }
00677         return SN_NSDL_FAILURE;
00678 #else
00679         if (resource_ptr->static_resource_parameters &&
00680                 resource_ptr->static_resource_parameters->free_on_delete) {
00681 #ifndef RESOURCE_ATTRIBUTES_LIST
00682 #ifndef DISABLE_INTERFACE_DESCRIPTION
00683             if (resource_ptr->static_resource_parameters->interface_description_ptr) {
00684                 handle->sn_grs_free(resource_ptr->static_resource_parameters->interface_description_ptr);
00685                 resource_ptr->static_resource_parameters->interface_description_ptr = 0;
00686             }
00687 #endif
00688 #ifndef DISABLE_RESOURCE_TYPE
00689             if (resource_ptr->static_resource_parameters->resource_type_ptr) {
00690                 handle->sn_grs_free(resource_ptr->static_resource_parameters->resource_type_ptr);
00691                 resource_ptr->static_resource_parameters->resource_type_ptr = 0;
00692             }
00693 #endif
00694 #else
00695             sn_nsdl_free_resource_attributes_list(resource_ptr->static_resource_parameters);
00696 #endif
00697             if (resource_ptr->static_resource_parameters->path) {
00698                 handle->sn_grs_free(resource_ptr->static_resource_parameters->path);
00699                 resource_ptr->static_resource_parameters->path = 0;
00700             }
00701 
00702             if (resource_ptr->resource) {
00703                 handle->sn_grs_free(resource_ptr->resource);
00704                 resource_ptr->resource = 0;
00705             }
00706 
00707             handle->sn_grs_free(resource_ptr->static_resource_parameters);
00708             resource_ptr->static_resource_parameters = 0;
00709         }
00710         if (resource_ptr->free_on_delete) {
00711             handle->sn_grs_free(resource_ptr);
00712         }
00713         return SN_NSDL_SUCCESS;
00714 #endif
00715     }
00716     return SN_NSDL_FAILURE; //Dead code?
00717 }
00718 
00719 void sn_grs_mark_resources_as_registered(struct nsdl_s *handle)
00720 {
00721     if( !handle ){
00722         return;
00723     }
00724 
00725     sn_nsdl_dynamic_resource_parameters_s *temp_resource;
00726 
00727     temp_resource = sn_grs_get_first_resource(handle->grs);
00728 
00729     while (temp_resource) {
00730         if (temp_resource->registered == SN_NDSL_RESOURCE_REGISTERING) {
00731             temp_resource->registered = SN_NDSL_RESOURCE_REGISTERED;
00732         }
00733         temp_resource = sn_grs_get_next_resource(handle->grs, temp_resource);
00734     }
00735 }