ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_grs2.c Source File

sn_grs2.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 /**
00018  *
00019  * \file sn_grs.c
00020  *
00021  * \brief General resource server.
00022  *
00023  */
00024 #ifdef MBED_CLIENT_C_NEW_API
00025 #include <string.h>
00026 #include <stdlib.h>
00027 #include "ns_list.h"
00028 #include "ns_types.h"
00029 #include "sn_nsdl.h"
00030 #include "sn_coap_header.h"
00031 #include "sn_coap_protocol.h"
00032 #include "sn_coap_protocol_internal.h"
00033 #include "sn_nsdl_lib.h"
00034 #include "sn_grs.h"
00035 #include "mbed-trace/mbed_trace.h"
00036 
00037 /* Defines */
00038 #define TRACE_GROUP "coap"
00039 #define WELLKNOWN_PATH_LEN              16
00040 #define WELLKNOWN_PATH                  (".well-known/core")
00041 
00042 /* Local static function prototypes */
00043 static int8_t                       sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr);
00044 static uint8_t                     *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr);
00045 #ifndef MEMORY_OPTIMIZED_API
00046 static int8_t                       sn_grs_add_resource_to_list(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr);
00047 #endif
00048 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);
00049 static uint8_t                      coap_tx_callback(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *);
00050 static int8_t                       coap_rx_callback(sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address_ptr, void *param);
00051 
00052 /* Extern function prototypes */
00053 extern int8_t                       sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration);
00054 
00055 /**
00056  * \fn int8_t sn_grs_destroy(void)
00057  * \brief This function may be used to flush GRS related stuff when a program exits.
00058  * @return always 0.
00059  */
00060 extern int8_t sn_grs_destroy(struct grs_s *handle)
00061 {
00062     if( handle == NULL ){
00063         return 0;
00064     }
00065     ns_list_foreach_safe(sn_nsdl_dynamic_resource_parameters_s, tmp, &handle->resource_root_list) {
00066         ns_list_remove(&handle->resource_root_list, tmp);
00067         --handle->resource_root_count;
00068         sn_grs_resource_info_free(handle, tmp);
00069     }
00070     handle->sn_grs_free(handle);
00071 
00072     return 0;
00073 }
00074 
00075 static uint8_t coap_tx_callback(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr, void *param)
00076 {
00077     struct nsdl_s *handle = (struct nsdl_s *)param;
00078 
00079     if (handle == NULL) {
00080         return 0;
00081     }
00082 
00083     return handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, data_ptr, data_len, address_ptr);
00084 }
00085 
00086 static int8_t coap_rx_callback(sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address_ptr, void *param)
00087 {
00088     struct nsdl_s *handle = (struct nsdl_s *)param;
00089 
00090     if (handle == NULL) {
00091         return 0;
00092     }
00093 
00094     return handle->sn_nsdl_rx_callback(handle, coap_ptr, address_ptr);
00095 }
00096 
00097 /**
00098  * \fn int8_t sn_grs_init   (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t,
00099  *      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)
00100  *
00101  * \brief GRS library initialize function.
00102  *
00103  * This function initializes GRS and CoAP libraries.
00104  *
00105  * \param   sn_grs_tx_callback      A function pointer to a transmit callback function.
00106  * \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
00107  *                                  upper level (NSDL) to be proceed.
00108  * \param   sn_memory               A pointer to a structure containing the platform specific functions for memory allocation and free.
00109  *
00110  * \return success = 0, failure = -1
00111  *
00112 */
00113 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,
00114                                  sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
00115                                  void *(*sn_grs_alloc)(uint16_t), void (*sn_grs_free)(void *))
00116 {
00117 
00118     struct grs_s *handle_ptr = NULL;
00119 
00120     /* Check parameters */
00121     if (sn_grs_alloc == NULL || sn_grs_free == NULL ||
00122         sn_grs_tx_callback_ptr == NULL || sn_grs_rx_callback_ptr == NULL) {
00123         return NULL;
00124     }
00125 
00126     handle_ptr = sn_grs_alloc(sizeof(struct grs_s));
00127 
00128     if (handle_ptr == NULL) {
00129         return NULL;
00130     }
00131 
00132     memset(handle_ptr, 0, sizeof(struct grs_s));
00133 
00134     /* Allocation and free - function pointers  */
00135     handle_ptr->sn_grs_alloc = sn_grs_alloc;
00136     handle_ptr->sn_grs_free = sn_grs_free;
00137 
00138     /* TX callback function pointer */
00139     handle_ptr->sn_grs_tx_callback = sn_grs_tx_callback_ptr;
00140     handle_ptr->sn_grs_rx_callback = sn_grs_rx_callback_ptr;
00141 
00142     /* Initialize CoAP protocol library */
00143     handle_ptr->coap = sn_coap_protocol_init(sn_grs_alloc, sn_grs_free, coap_tx_callback, coap_rx_callback);
00144 
00145     return handle_ptr;
00146 }
00147 
00148 extern sn_grs_resource_list_s *sn_grs_list_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path)
00149 {
00150     (void) pathlen;
00151     sn_grs_resource_list_s *grs_resource_list_ptr = NULL;
00152 
00153     if( handle == NULL || path == NULL){
00154         return NULL;
00155     }
00156 
00157     /* Allocate memory for the resource list to be filled */
00158     grs_resource_list_ptr = handle->sn_grs_alloc(sizeof(sn_grs_resource_list_s));
00159     if (!grs_resource_list_ptr) {
00160         goto fail;
00161     }
00162 
00163     /* Count resources to the resource list struct */
00164     grs_resource_list_ptr->res_count = handle->resource_root_count;
00165     grs_resource_list_ptr->res = NULL;
00166 
00167     /**************************************/
00168     /* Fill resource structs to the table */
00169     /**************************************/
00170 
00171     /* If resources in list */
00172     if (grs_resource_list_ptr->res_count) {
00173         int i;
00174 
00175         /* Allocate memory for resources */
00176         grs_resource_list_ptr->res = handle->sn_grs_alloc(grs_resource_list_ptr->res_count * sizeof(sn_grs_resource_s));
00177         if (!grs_resource_list_ptr->res) {
00178             goto fail;
00179         }
00180 
00181         /* Initialise the pointers to NULL to permit easy cleanup */
00182         for (i = 0; i < grs_resource_list_ptr->res_count; i++) {
00183             grs_resource_list_ptr->res[i].path = NULL;
00184             grs_resource_list_ptr->res[i].pathlen = 0;
00185         }
00186 
00187         i = 0;
00188         ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, grs_resource_ptr, &handle->resource_root_list) {
00189             /* Copy pathlen to resource list */
00190             grs_resource_list_ptr->res[i].pathlen = grs_resource_ptr->static_resource_parameters->pathlen;
00191 
00192             /* Allocate memory for path string */
00193             grs_resource_list_ptr->res[i].path = handle->sn_grs_alloc(grs_resource_list_ptr->res[i].pathlen);
00194             if (!grs_resource_list_ptr->res[i].path) {
00195                 goto fail;
00196             }
00197 
00198             /* Copy pathstring to resource list */
00199             memcpy(grs_resource_list_ptr->res[i].path,
00200                    grs_resource_ptr->static_resource_parameters->path,
00201                    grs_resource_ptr->static_resource_parameters->pathlen);
00202 
00203             i++;
00204         }
00205     }
00206     return grs_resource_list_ptr;
00207 
00208 fail:
00209     sn_grs_free_resource_list(handle, grs_resource_list_ptr);
00210     return NULL;
00211 }
00212 
00213 extern void sn_grs_free_resource_list(struct grs_s *handle, sn_grs_resource_list_s *list)
00214 {
00215     if (!list || !handle) {
00216         return;
00217     }
00218 
00219     if (list->res) {
00220         for (int i = 0; i < list->res_count; i++) {
00221             if (list->res[i].path) {
00222                 handle->sn_grs_free(list->res[i].path);
00223                 list->res[i].path = NULL;
00224             }
00225         }
00226         handle->sn_grs_free(list->res);
00227         list->res = NULL;
00228     }
00229 
00230     handle->sn_grs_free(list);
00231 }
00232 
00233 extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_first_resource(struct grs_s *handle)
00234 {
00235     if( !handle ){
00236         return NULL;
00237     }
00238     return ns_list_get_first(&handle->resource_root_list);
00239 }
00240 
00241 extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_next_resource(struct grs_s *handle,
00242                                                                              const sn_nsdl_dynamic_resource_parameters_s *sn_grs_current_resource)
00243 {
00244     if( !handle || !sn_grs_current_resource ){
00245         return NULL;
00246     }
00247     return ns_list_get_next(&handle->resource_root_list, sn_grs_current_resource);
00248 }
00249 
00250 extern int8_t sn_grs_delete_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path)
00251 {
00252     /* Local variables */
00253     sn_nsdl_dynamic_resource_parameters_s     *resource_temp  = NULL;
00254 
00255     /* Search if resource found */
00256     resource_temp = sn_grs_search_resource(handle, pathlen, path, SN_GRS_SEARCH_METHOD);
00257 
00258     /* If not found */
00259     if (resource_temp == NULL) {
00260         return SN_NSDL_FAILURE;
00261     }
00262 
00263     /* If found, delete it and delete also subresources, if there is any */
00264     do {
00265         /* Remove from list */
00266         ns_list_remove(&handle->resource_root_list, resource_temp);
00267         --handle->resource_root_count;
00268 
00269         /* Free */
00270         sn_grs_resource_info_free(handle, resource_temp);
00271 
00272         /* Search for subresources */
00273         resource_temp = sn_grs_search_resource(handle, pathlen, path, SN_GRS_DELETE_METHOD);
00274     } while (resource_temp != NULL);
00275 
00276     return SN_NSDL_SUCCESS;
00277 }
00278 
00279 #ifndef MEMORY_OPTIMIZED_API
00280 extern int8_t sn_grs_update_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
00281 {
00282     /* Local variables */
00283     sn_nsdl_dynamic_resource_parameters_s     *resource_temp  = NULL;
00284 
00285     if( !res || !handle ){
00286         return SN_NSDL_FAILURE;
00287     }
00288 
00289     /* Search resource */
00290     resource_temp = sn_grs_search_resource(handle,
00291                                            res->static_resource_parameters->pathlen,
00292                                            res->static_resource_parameters->path,
00293                                            SN_GRS_SEARCH_METHOD);
00294     if (!resource_temp) {
00295         return SN_NSDL_FAILURE;
00296     }
00297 
00298     /* If there is payload on resource, free it */
00299     if (resource_temp->static_resource_parameters->resource != NULL) {
00300         handle->sn_grs_free(resource_temp->static_resource_parameters->resource);
00301         resource_temp->static_resource_parameters->resource = 0;
00302     }
00303     /* Update resource len */
00304     resource_temp->static_resource_parameters->resourcelen =
00305             res->static_resource_parameters->resourcelen;
00306 
00307     /* If resource len >0, allocate memory and copy payload */
00308     if (res->static_resource_parameters->resourcelen) {
00309         resource_temp->static_resource_parameters->resource =
00310                 handle->sn_grs_alloc(res->static_resource_parameters->resourcelen);
00311         if (resource_temp->static_resource_parameters->resource == NULL) {
00312             resource_temp->static_resource_parameters->resourcelen = 0;
00313             return SN_NSDL_FAILURE;
00314         }
00315 
00316         memcpy(resource_temp->static_resource_parameters->resource,
00317                res->static_resource_parameters->resource,
00318                resource_temp->static_resource_parameters->resourcelen);
00319     }
00320 
00321     /* Update access rights and callback address */
00322     resource_temp->access = res->access;
00323     resource_temp->sn_grs_dyn_res_callback = res->sn_grs_dyn_res_callback;
00324 
00325     /* TODO: resource_parameters_ptr not copied */
00326 
00327     return SN_NSDL_SUCCESS;
00328 }
00329 
00330 extern int8_t sn_grs_create_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
00331 {
00332     if (!res || !handle) {
00333         return SN_NSDL_FAILURE;
00334     }
00335 
00336     /* Check path validity */
00337     if (!res->static_resource_parameters->pathlen || !res->static_resource_parameters->path) {
00338         return SN_GRS_INVALID_PATH;
00339     }
00340 
00341     /* Check if resource already exists */
00342     if (sn_grs_search_resource(handle,
00343                                res->static_resource_parameters->pathlen,
00344                                res->static_resource_parameters->path,
00345                                SN_GRS_SEARCH_METHOD) !=
00346             (sn_nsdl_dynamic_resource_parameters_s *)NULL) {
00347         return SN_GRS_RESOURCE_ALREADY_EXISTS;
00348     }
00349 
00350     if (res) {
00351         res->registered = SN_NDSL_RESOURCE_NOT_REGISTERED;
00352     }
00353 
00354     /* Create resource */
00355     if (sn_grs_add_resource_to_list(handle, res) == SN_NSDL_SUCCESS) {
00356         return SN_NSDL_SUCCESS;
00357     }
00358     return SN_GRS_LIST_ADDING_FAILURE;
00359 }
00360 
00361 /**
00362  * \fn  static int8_t sn_grs_add_resource_to_list(sn_nsdl_dynamic_resource_parameters_s *resource_ptr)
00363  *
00364  * \brief Adds given resource to resource list
00365  *
00366  *  \param  *resource_ptr           Pointer to the path string to be search
00367  *
00368  *  \return 0 = SN_NSDL_SUCCESS, -1 = SN_NSDL_FAILURE
00369  *
00370 */
00371 static int8_t sn_grs_add_resource_to_list(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr)
00372 {
00373     /* Local variables */
00374 
00375     uint8_t *path_start_ptr = NULL;
00376     uint16_t path_len = 0;
00377     sn_nsdl_dynamic_resource_parameters_s *resource_copy_ptr = NULL;
00378 
00379     /* Allocate memory for the resource info copy */
00380     if (!resource_ptr->static_resource_parameters->pathlen) { //Dead code
00381         return SN_NSDL_FAILURE;
00382     }
00383 
00384     resource_copy_ptr = handle->sn_grs_alloc(sizeof(sn_nsdl_dynamic_resource_parameters_s));
00385     if (resource_copy_ptr == NULL) {
00386         return SN_NSDL_FAILURE;
00387     }
00388 
00389     /* Set everything to zero  */
00390     memset(resource_copy_ptr, 0, sizeof(sn_nsdl_dynamic_resource_parameters_s));
00391     resource_copy_ptr->sn_grs_dyn_res_callback = resource_ptr->sn_grs_dyn_res_callback;
00392     resource_copy_ptr->publish_uri = resource_ptr->publish_uri;
00393     resource_copy_ptr->free_on_delete = resource_ptr->free_on_delete;
00394     resource_copy_ptr->coap_content_type = resource_ptr->coap_content_type;
00395     resource_copy_ptr->observable = resource_ptr->observable;
00396     resource_copy_ptr->access = resource_ptr->access;
00397     /* If resource parameters exists, copy them */
00398     if (resource_ptr->static_resource_parameters) {
00399         resource_copy_ptr->static_resource_parameters = handle->sn_grs_alloc(sizeof(sn_nsdl_static_resource_parameters_s));
00400         if (!resource_copy_ptr->static_resource_parameters) {
00401             sn_grs_resource_info_free(handle, resource_copy_ptr);
00402             return SN_NSDL_FAILURE;
00403         }
00404 
00405         memset(resource_copy_ptr->static_resource_parameters, 0, sizeof(sn_nsdl_static_resource_parameters_s));
00406         resource_copy_ptr->static_resource_parameters->mode =
00407                 resource_ptr->static_resource_parameters->mode;
00408         resource_copy_ptr->static_resource_parameters->external_memory_block =
00409                 resource_ptr->static_resource_parameters->external_memory_block;
00410         resource_copy_ptr->static_resource_parameters->free_on_delete =
00411                 resource_ptr->static_resource_parameters->free_on_delete;
00412 
00413         resource_copy_ptr->static_resource_parameters->pathlen =
00414                 resource_ptr->static_resource_parameters->pathlen;
00415         resource_copy_ptr->static_resource_parameters->resourcelen =
00416                 resource_ptr->static_resource_parameters->resourcelen;
00417 
00418         if (resource_ptr->static_resource_parameters->resource_type_ptr) {
00419             // alloc space for terminating zero too
00420             const size_t resource_type_len = strlen(resource_ptr->static_resource_parameters->resource_type_ptr) + 1;
00421             resource_copy_ptr->static_resource_parameters->resource_type_ptr =
00422                     handle->sn_grs_alloc(resource_type_len);
00423             if (!resource_copy_ptr->static_resource_parameters->resource_type_ptr) {
00424                 sn_grs_resource_info_free(handle, resource_copy_ptr);
00425                 return SN_NSDL_FAILURE;
00426             }
00427             memcpy(resource_copy_ptr->static_resource_parameters->resource_type_ptr,
00428                    resource_ptr->static_resource_parameters->resource_type_ptr,
00429                    resource_type_len);
00430         }
00431 
00432         if (resource_ptr->static_resource_parameters->interface_description_ptr) {
00433             // todo: a sn_grs_strdup() or similar helper to avoid this copy-paste pattern.
00434             const size_t interface_description_len = strlen(resource_ptr->static_resource_parameters->interface_description_ptr) + 1;
00435             resource_copy_ptr->static_resource_parameters->interface_description_ptr =
00436                     handle->sn_grs_alloc(interface_description_len);
00437             if (!resource_copy_ptr->static_resource_parameters->interface_description_ptr) {
00438                 sn_grs_resource_info_free(handle, resource_copy_ptr);
00439                 return SN_NSDL_FAILURE;
00440             }
00441             memcpy(resource_copy_ptr->static_resource_parameters->interface_description_ptr,
00442                    resource_ptr->static_resource_parameters->interface_description_ptr,
00443                    interface_description_len);
00444         }
00445 
00446         /* Remove '/' - chars from the beginning and from the end */
00447 
00448         path_len = resource_ptr->static_resource_parameters->pathlen;
00449         path_start_ptr = sn_grs_convert_uri(&path_len, resource_ptr->static_resource_parameters->path);
00450 
00451         /* Allocate memory for the path */
00452         resource_copy_ptr->static_resource_parameters->path = handle->sn_grs_alloc(path_len);
00453         if (!resource_copy_ptr->static_resource_parameters->path) {
00454             sn_grs_resource_info_free(handle, resource_copy_ptr);
00455             return SN_NSDL_FAILURE;
00456         }
00457 
00458         /* Update pathlen */
00459         resource_copy_ptr->static_resource_parameters->pathlen = path_len;
00460 
00461         /* Copy path string to the copy */
00462         memcpy(resource_copy_ptr->static_resource_parameters->path,
00463                path_start_ptr,
00464                resource_copy_ptr->static_resource_parameters->pathlen);
00465 
00466         /* Allocate memory for the resource, and copy it to copy */
00467         if (resource_ptr->static_resource_parameters->resource) {
00468             resource_copy_ptr->static_resource_parameters->resource =
00469                     handle->sn_grs_alloc(resource_ptr->static_resource_parameters->resourcelen);
00470             if (!resource_copy_ptr->static_resource_parameters->resource) {
00471                 sn_grs_resource_info_free(handle, resource_copy_ptr);
00472                 return SN_NSDL_FAILURE;
00473             }
00474             memcpy(resource_copy_ptr->static_resource_parameters->resource,
00475                    resource_ptr->static_resource_parameters->resource,
00476                    resource_ptr->static_resource_parameters->resourcelen);
00477         }
00478     }
00479 
00480     /* Add copied resource to the linked list */
00481     ns_list_add_to_start(&handle->resource_root_list, resource_copy_ptr);
00482     ++handle->resource_root_count;
00483 
00484     return SN_NSDL_SUCCESS;
00485 }
00486 #endif
00487 
00488 int8_t sn_grs_put_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
00489 {
00490     if (!res || !handle) {
00491         return SN_NSDL_FAILURE;
00492     }
00493 
00494     /* Check path validity */
00495     if (!res->static_resource_parameters->pathlen || !res->static_resource_parameters->path) {
00496         return SN_GRS_INVALID_PATH;
00497     }
00498 
00499     /* Check if resource already exists */
00500     if (sn_grs_search_resource(handle,
00501                                res->static_resource_parameters->pathlen,
00502                                res->static_resource_parameters->path, SN_GRS_SEARCH_METHOD) != (sn_nsdl_dynamic_resource_parameters_s *)NULL) {
00503         return SN_GRS_RESOURCE_ALREADY_EXISTS;
00504     }
00505 
00506     res->registered = SN_NDSL_RESOURCE_NOT_REGISTERED;
00507 
00508     ns_list_add_to_start(&handle->resource_root_list, res);
00509     ++handle->resource_root_count;
00510 
00511     return SN_NSDL_SUCCESS;
00512 }
00513 
00514 int8_t sn_grs_pop_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
00515 {
00516     if (!res || !handle) {
00517         return SN_NSDL_FAILURE;
00518     }
00519 
00520     /* Check path validity */
00521     if (!res->static_resource_parameters->pathlen || !res->static_resource_parameters->path) {
00522         return SN_GRS_INVALID_PATH;
00523     }
00524 
00525     /* Check if resource exists on list. */
00526     if (sn_grs_search_resource(handle,
00527                                res->static_resource_parameters->pathlen,
00528                                res->static_resource_parameters->path, SN_GRS_SEARCH_METHOD) == (sn_nsdl_dynamic_resource_parameters_s *)NULL) {
00529         return SN_NSDL_FAILURE;
00530     }
00531 
00532     ns_list_remove(&handle->resource_root_list, res);
00533     --handle->resource_root_count;
00534 
00535     return SN_NSDL_SUCCESS;
00536 }
00537 
00538 /**
00539  * \fn  extern int8_t sn_grs_process_coap(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src)
00540  *
00541  * \brief To push CoAP packet to GRS library
00542  *
00543  *  Used to push an CoAP packet to GRS library for processing.
00544  *
00545  *  \param  *packet     Pointer to a uint8_t array containing the packet (including the CoAP headers).
00546  *                      After successful execution this array may contain the response packet.
00547  *
00548  *  \param  *packet_len Pointer to length of the packet. After successful execution this array may contain the length
00549  *                      of the response packet.
00550  *
00551  *  \param  *src        Pointer to packet source address information. After successful execution this array may contain
00552  *                      the destination address of the response packet.
00553  *
00554  *  \return             0 = success, -1 = failure
00555 */
00556 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)
00557 {
00558     tr_debug("sn_grs_process_coap");
00559     if( !coap_packet_ptr || !nsdl_handle){
00560         return SN_NSDL_FAILURE;
00561     }
00562 
00563     tr_debug("sn_grs_process_coap - coap params:");
00564     tr_debug("msg code: (%d), msg type: (%d), msg id: (%d), path: (%.*s)",
00565              coap_packet_ptr->msg_code, coap_packet_ptr->msg_type, coap_packet_ptr->msg_id,
00566              coap_packet_ptr->uri_path_len, coap_packet_ptr->uri_path_ptr);
00567 
00568     sn_nsdl_dynamic_resource_parameters_s *resource_temp_ptr  = NULL;
00569     sn_coap_msg_code_e      status              = COAP_MSG_CODE_EMPTY;
00570     sn_coap_hdr_s           *response_message_hdr_ptr = NULL;
00571     struct grs_s            *handle = nsdl_handle->grs;
00572     bool                    static_get_request = false;
00573 
00574     if (coap_packet_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE) {
00575         /* Check if .well-known/core */
00576         if (coap_packet_ptr->uri_path_len == WELLKNOWN_PATH_LEN && memcmp(coap_packet_ptr->uri_path_ptr, WELLKNOWN_PATH, WELLKNOWN_PATH_LEN) == 0) {
00577             return sn_grs_core_request(nsdl_handle, src_addr_ptr, coap_packet_ptr);
00578         }
00579 
00580         /* Get resource */
00581         resource_temp_ptr = sn_grs_search_resource(handle, coap_packet_ptr->uri_path_len, coap_packet_ptr->uri_path_ptr, SN_GRS_SEARCH_METHOD);
00582 
00583 
00584         /* * * * * * * * * * * */
00585         /* If resource exists  */
00586         /* * * * * * * * * * * */
00587         if (resource_temp_ptr) {
00588             tr_debug("sn_grs_process_coap - found (%.*s)", resource_temp_ptr->static_resource_parameters->pathlen,
00589                      resource_temp_ptr->static_resource_parameters->path);
00590             /* If dynamic resource, go to callback */
00591             if (resource_temp_ptr->static_resource_parameters->mode == SN_GRS_DYNAMIC) {
00592                 /* Check accesses */
00593                 if (((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) && !(resource_temp_ptr->access & SN_GRS_GET_ALLOWED))          ||
00594                         ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) && !(resource_temp_ptr->access & SN_GRS_POST_ALLOWED))   ||
00595                         ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) && !(resource_temp_ptr->access & SN_GRS_PUT_ALLOWED))     ||
00596                         ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) && !(resource_temp_ptr->access & SN_GRS_DELETE_ALLOWED))) {
00597                     status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00598                 } else {
00599                     /* Do not call null pointer.. */
00600                     if (resource_temp_ptr->sn_grs_dyn_res_callback != NULL) {
00601                         resource_temp_ptr->sn_grs_dyn_res_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr, SN_NSDL_PROTOCOL_COAP);
00602                     }
00603 
00604                     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00605                         handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00606                         coap_packet_ptr->payload_ptr = 0;
00607                     }
00608                     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00609                     return SN_NSDL_SUCCESS;
00610                 }
00611             } else {
00612                 /* Static resource handling */
00613                 switch (coap_packet_ptr->msg_code) {
00614                     case COAP_MSG_CODE_REQUEST_GET:
00615                         if (resource_temp_ptr->access & SN_GRS_GET_ALLOWED) {
00616                             status = COAP_MSG_CODE_RESPONSE_CONTENT;
00617                             static_get_request = true;
00618                         } else {
00619                             status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00620                         }
00621                         break;
00622 
00623                     case COAP_MSG_CODE_REQUEST_POST:
00624                     case COAP_MSG_CODE_REQUEST_PUT:
00625                     case COAP_MSG_CODE_REQUEST_DELETE:
00626                         status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00627                         break;
00628 
00629                     default:
00630                         status = COAP_MSG_CODE_RESPONSE_FORBIDDEN;
00631                         break;
00632                 }
00633             }
00634         }
00635 
00636         /* * * * * * * * * * * * * * */
00637         /* If resource was not found */
00638         /* * * * * * * * * * * * * * */
00639 
00640         else {
00641             if (coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) {
00642                 handle->sn_grs_rx_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr);
00643 
00644                 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00645                     handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00646                     coap_packet_ptr->payload_ptr = 0;
00647                 }
00648 
00649                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00650                 return SN_NSDL_SUCCESS;
00651             } else {
00652                 status = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00653             }
00654         }
00655     }
00656 
00657     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00658     /* If received packed was other than reset, create response  */
00659     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00660     if (coap_packet_ptr->msg_type != COAP_MSG_TYPE_RESET && coap_packet_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT) {
00661 
00662         /* Allocate resopnse message  */
00663         response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->coap);
00664         if (!response_message_hdr_ptr) {
00665             if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00666                 handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00667                 coap_packet_ptr->payload_ptr = 0;
00668             }
00669             sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00670             return SN_NSDL_FAILURE;
00671         }
00672 
00673         /* If status has not been defined, response internal server error */
00674         if (status == COAP_MSG_CODE_EMPTY) {
00675             status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
00676         }
00677 
00678         /* Fill header */
00679         response_message_hdr_ptr->msg_code = status;
00680 
00681         if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
00682             response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
00683         } else {
00684             response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
00685         }
00686 
00687         response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
00688 
00689         if (coap_packet_ptr->token_ptr) {
00690             response_message_hdr_ptr->token_len = coap_packet_ptr->token_len;
00691             response_message_hdr_ptr->token_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->token_len);
00692             if (!response_message_hdr_ptr->token_ptr) {
00693                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00694 
00695                 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00696                     handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00697                     coap_packet_ptr->payload_ptr = 0;
00698                 }
00699 
00700                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00701                 return SN_NSDL_FAILURE;
00702             }
00703             memcpy(response_message_hdr_ptr->token_ptr, coap_packet_ptr->token_ptr, response_message_hdr_ptr->token_len);
00704         }
00705 
00706         if (status == COAP_MSG_CODE_RESPONSE_CONTENT) {
00707             /* Add content type if other than default */
00708             if (resource_temp_ptr->static_resource_parameters) {
00709                 /* XXXX Why "if != 0"? 0 means text/plain, and is not the default for CoAP - this prevents setting text/plain? */
00710                 if (resource_temp_ptr->coap_content_type != 0) {
00711                     response_message_hdr_ptr->content_format =
00712                             (sn_coap_content_format_e) resource_temp_ptr->coap_content_type;
00713                 }
00714             }
00715 
00716             /* Add payload */
00717             if (resource_temp_ptr->static_resource_parameters->resourcelen != 0) {
00718                 response_message_hdr_ptr->payload_len = resource_temp_ptr->static_resource_parameters->resourcelen;
00719                 response_message_hdr_ptr->payload_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->payload_len);
00720 
00721                 if (!response_message_hdr_ptr->payload_ptr) {
00722                     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00723 
00724                     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00725                         handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00726                         coap_packet_ptr->payload_ptr = 0;
00727                     }
00728 
00729                     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00730                     return SN_NSDL_FAILURE;
00731                 }
00732 
00733                 memcpy(response_message_hdr_ptr->payload_ptr,
00734                        resource_temp_ptr->static_resource_parameters->resource,
00735                        response_message_hdr_ptr->payload_len);
00736             }
00737             // Add max-age attribute for static resources.
00738             // Not a mandatory parameter, no need to return in case of memory allocation fails.
00739             if (static_get_request) {
00740                 if (sn_coap_parser_alloc_options(handle->coap, response_message_hdr_ptr)) {
00741                     response_message_hdr_ptr->options_list_ptr->max_age = 0;
00742                 }
00743             }
00744         }
00745         sn_grs_send_coap_message(nsdl_handle, src_addr_ptr, response_message_hdr_ptr);
00746 
00747         if (response_message_hdr_ptr->payload_ptr) {
00748             handle->sn_grs_free(response_message_hdr_ptr->payload_ptr);
00749             response_message_hdr_ptr->payload_ptr = 0;
00750         }
00751         sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00752     }
00753 
00754     /* Free parsed CoAP message */
00755     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00756         handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00757         coap_packet_ptr->payload_ptr = 0;
00758     }
00759     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00760 
00761     return SN_NSDL_SUCCESS;
00762 }
00763 
00764 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)
00765 {
00766     tr_debug("sn_grs_send_coap_message");
00767     uint8_t     *message_ptr = NULL;
00768     uint16_t    message_len = 0;
00769     uint8_t     ret_val = 0;
00770 
00771     if( !handle ){
00772         return SN_NSDL_FAILURE;
00773     }
00774 
00775 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */
00776     ret_val = prepare_blockwise_message(handle->grs->coap, coap_hdr_ptr);
00777     if( 0 != ret_val ) {
00778         return SN_NSDL_FAILURE;
00779     }
00780 #endif
00781 
00782     /* Calculate message length */
00783     message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_hdr_ptr, handle->grs->coap->sn_coap_block_data_size);
00784     tr_debug("sn_grs_send_coap_message - msg len after calc: [%d]", message_len);
00785     tr_debug("sn_grs_send_coap_message - msg id: [%d]", coap_hdr_ptr->msg_id);
00786 
00787     /* Allocate memory for message and check was allocating successfully */
00788     message_ptr = handle->grs->sn_grs_alloc(message_len);
00789     if (message_ptr == NULL) {
00790         return SN_NSDL_FAILURE;
00791     }
00792 
00793     /* Build CoAP message */
00794     if (sn_coap_protocol_build(handle->grs->coap, address_ptr, message_ptr, coap_hdr_ptr, (void *)handle) < 0) {
00795         handle->grs->sn_grs_free(message_ptr);
00796         message_ptr = 0;
00797         return SN_NSDL_FAILURE;
00798     }
00799 
00800     /* Call tx callback function to send message */
00801     ret_val = handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address_ptr);
00802 
00803     /* Free allocated memory */
00804     handle->grs->sn_grs_free(message_ptr);
00805     message_ptr = 0;
00806 
00807     if (ret_val == 0) {
00808         return SN_NSDL_FAILURE;
00809     } else {
00810         return SN_NSDL_SUCCESS;
00811     }
00812 }
00813 
00814 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)
00815 {
00816     sn_coap_hdr_s           *response_message_hdr_ptr = NULL;
00817     sn_coap_content_format_e wellknown_content_format = COAP_CT_LINK_FORMAT;
00818 
00819     /* Allocate response message  */
00820     response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
00821     if (response_message_hdr_ptr == NULL) {
00822         if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00823             handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr);
00824             coap_packet_ptr->payload_ptr = 0;
00825         }
00826         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00827         return SN_NSDL_FAILURE;
00828     }
00829 
00830     /* Build response */
00831     response_message_hdr_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00832     response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
00833     response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
00834     response_message_hdr_ptr->content_format = wellknown_content_format;
00835 
00836     sn_nsdl_build_registration_body(handle, response_message_hdr_ptr, 0);
00837 
00838     /* Send and free */
00839     sn_grs_send_coap_message(handle, src_addr_ptr, response_message_hdr_ptr);
00840 
00841     if (response_message_hdr_ptr->payload_ptr) {
00842         handle->grs->sn_grs_free(response_message_hdr_ptr->payload_ptr);
00843         response_message_hdr_ptr->payload_ptr = 0;
00844     }
00845     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, response_message_hdr_ptr);
00846 
00847     /* Free parsed CoAP message */
00848     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00849         handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr);
00850         coap_packet_ptr->payload_ptr = 0;
00851     }
00852     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00853 
00854     return SN_NSDL_SUCCESS;
00855 }
00856 
00857 /**
00858  * \fn  static sn_grs_resource_info_s *sn_grs_search_resource(uint16_t pathlen, uint8_t *path, uint8_t search_method)
00859  *
00860  * \brief Searches given resource from linked list
00861  *
00862  *  Search either precise path, or subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc...
00863  *
00864  *  \param  pathlen         Length of the path to be search
00865  *
00866  *  \param  *path           Pointer to the path string to be search
00867  *
00868  *  \param  search_method   Search method, SEARCH or DELETE
00869  *
00870  *  \return                 Pointer to the resource. If resource not found, return value is NULL
00871  *
00872 */
00873 
00874 sn_nsdl_dynamic_resource_parameters_s *sn_grs_search_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path, uint8_t search_method)
00875 {
00876     /* Local variables */
00877     uint8_t                     *path_temp_ptr          = NULL;
00878     /* Check parameters */
00879     if (!handle || !pathlen || !path) {
00880         return NULL;
00881     }
00882 
00883     /* Remove '/' - marks from the end and beginning */
00884     path_temp_ptr = sn_grs_convert_uri(&pathlen, path);
00885 
00886     /* Searchs exact path */
00887     if (search_method == SN_GRS_SEARCH_METHOD) {
00888         /* Scan all nodes on list */
00889         ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) {
00890             /* If length equals.. */
00891             if (resource_search_temp->static_resource_parameters->pathlen == pathlen) {
00892                 /* Compare paths, If same return node pointer*/
00893                 if (0 == memcmp(resource_search_temp->static_resource_parameters->path,
00894                                 path_temp_ptr,
00895                                 pathlen)) {
00896                     return resource_search_temp;
00897                 }
00898             }
00899         }
00900     }
00901     /* Search also subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... */
00902     else if (search_method == SN_GRS_DELETE_METHOD) {
00903         /* Scan all nodes on list */
00904         ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) {
00905             uint8_t *temp_path = resource_search_temp->static_resource_parameters->path;
00906             if (resource_search_temp->static_resource_parameters->pathlen > pathlen &&
00907                     (*(temp_path + (uint8_t)pathlen) == '/') &&
00908                     0 == memcmp(resource_search_temp->static_resource_parameters->path,
00909                                 path_temp_ptr,
00910                                 pathlen)) {
00911                 return resource_search_temp;
00912             }
00913         }
00914     }
00915 
00916     /* If there was not nodes we wanted, return NULL */
00917     return NULL;
00918 }
00919 
00920 /**
00921  * \fn  static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr)
00922  *
00923  * \brief Removes '/' from the beginning and from the end of uri string
00924  *
00925  *  \param  *uri_len            Pointer to the length of the path string
00926  *
00927  *  \param  *uri_ptr            Pointer to the path string
00928  *
00929  *  \return start pointer of the uri
00930  *
00931 */
00932 
00933 static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr)
00934 {
00935     /* Local variables */
00936     uint8_t *uri_start_ptr = uri_ptr;
00937 
00938     /* If '/' in the beginning, update uri start pointer and uri len */
00939     if (*uri_ptr == '/') {
00940         uri_start_ptr = uri_ptr + 1;
00941         *uri_len = *uri_len - 1;
00942     }
00943 
00944     /* If '/' at the end, update uri len */
00945     if (*(uri_start_ptr + *uri_len - 1) == '/') {
00946         *uri_len = *uri_len - 1;
00947     }
00948 
00949     /* Return start pointer */
00950     return uri_start_ptr;
00951 }
00952 
00953 /**
00954  * \fn  static int8_t sn_grs_resource_info_free(sn_grs_resource_info_s *resource_ptr)
00955  *
00956  * \brief Frees resource info structure
00957  *
00958  *  \param *resource_ptr    Pointer to the resource
00959  *
00960  *  \return 0 if success, -1 if failed
00961  *
00962 */
00963 static int8_t sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr)
00964 {
00965     if (resource_ptr) {
00966 #ifdef MEMORY_OPTIMIZED_API
00967         if (resource_ptr->free_on_delete) {
00968             handle->sn_grs_free(resource_ptr);
00969         }
00970         return SN_NSDL_FAILURE;
00971 #else
00972         if (resource_ptr->static_resource_parameters &&
00973                 resource_ptr->static_resource_parameters->free_on_delete) {
00974             if (resource_ptr->static_resource_parameters->interface_description_ptr) {
00975                 handle->sn_grs_free(resource_ptr->static_resource_parameters->interface_description_ptr);
00976                 resource_ptr->static_resource_parameters->interface_description_ptr = 0;
00977             }
00978 
00979             if (resource_ptr->static_resource_parameters->resource_type_ptr) {
00980                 handle->sn_grs_free(resource_ptr->static_resource_parameters->resource_type_ptr);
00981                 resource_ptr->static_resource_parameters->resource_type_ptr = 0;
00982             }
00983 
00984             if (resource_ptr->static_resource_parameters->path) {
00985                 handle->sn_grs_free(resource_ptr->static_resource_parameters->path);
00986                 resource_ptr->static_resource_parameters->path = 0;
00987             }
00988 
00989             if (resource_ptr->static_resource_parameters->resource) {
00990                 handle->sn_grs_free(resource_ptr->static_resource_parameters->resource);
00991                 resource_ptr->static_resource_parameters->resource = 0;
00992             }
00993 
00994             handle->sn_grs_free(resource_ptr->static_resource_parameters);
00995             resource_ptr->static_resource_parameters = 0;
00996         }
00997         if (resource_ptr->free_on_delete) {
00998             handle->sn_grs_free(resource_ptr);
00999         }
01000         return SN_NSDL_SUCCESS;
01001 #endif
01002     }
01003     return SN_NSDL_FAILURE; //Dead code?
01004 }
01005 
01006 void sn_grs_mark_resources_as_registered(struct nsdl_s *handle)
01007 {
01008     if( !handle ){
01009         return;
01010     }
01011 
01012     sn_nsdl_dynamic_resource_parameters_s *temp_resource;
01013 
01014     temp_resource = sn_grs_get_first_resource(handle->grs);
01015 
01016     while (temp_resource) {
01017         if (temp_resource->registered == SN_NDSL_RESOURCE_REGISTERING) {
01018             temp_resource->registered = SN_NDSL_RESOURCE_REGISTERED;
01019         }
01020         temp_resource = sn_grs_get_next_resource(handle->grs, temp_resource);
01021     }
01022 }
01023 #endif