Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

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_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                     }
00388 
00389                     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00390                         handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00391                         coap_packet_ptr->payload_ptr = 0;
00392                     }
00393                     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00394                     return SN_NSDL_SUCCESS;
00395                 }
00396             } else {
00397                 /* Static resource handling */
00398                 switch (coap_packet_ptr->msg_code) {
00399                     case COAP_MSG_CODE_REQUEST_GET:
00400                         if (resource_temp_ptr->access & SN_GRS_GET_ALLOWED) {
00401                             status = COAP_MSG_CODE_RESPONSE_CONTENT;
00402                             static_get_request = true;
00403                         } else {
00404                             status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00405                         }
00406                         break;
00407 
00408                     case COAP_MSG_CODE_REQUEST_POST:
00409                     case COAP_MSG_CODE_REQUEST_PUT:
00410                     case COAP_MSG_CODE_REQUEST_DELETE:
00411                         status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00412                         break;
00413 
00414                     default:
00415                         status = COAP_MSG_CODE_RESPONSE_FORBIDDEN;
00416                         break;
00417                 }
00418             }
00419         }
00420 
00421         /* * * * * * * * * * * * * * */
00422         /* If resource was not found */
00423         /* * * * * * * * * * * * * * */
00424 
00425         else {
00426             if (coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) {
00427                 handle->sn_grs_rx_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr);
00428 
00429                 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00430                     handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00431                     coap_packet_ptr->payload_ptr = 0;
00432                 }
00433 
00434                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00435                 return SN_NSDL_SUCCESS;
00436             } else {
00437                 status = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00438             }
00439         }
00440     }
00441 
00442     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00443     /* If received packed was other than reset, create response  */
00444     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00445     if (coap_packet_ptr->msg_type != COAP_MSG_TYPE_RESET && coap_packet_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT) {
00446 
00447         /* Allocate resopnse message  */
00448         response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->coap);
00449         if (!response_message_hdr_ptr) {
00450             if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00451                 handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00452                 coap_packet_ptr->payload_ptr = 0;
00453             }
00454             sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00455             return SN_NSDL_FAILURE;
00456         }
00457 
00458         /* If status has not been defined, response internal server error */
00459         if (status == COAP_MSG_CODE_EMPTY) {
00460             status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
00461         }
00462 
00463         /* Fill header */
00464         response_message_hdr_ptr->msg_code = status;
00465 
00466         if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
00467             response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
00468         } else {
00469             response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
00470         }
00471 
00472         response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
00473 
00474         if (coap_packet_ptr->token_ptr) {
00475             response_message_hdr_ptr->token_len = coap_packet_ptr->token_len;
00476             response_message_hdr_ptr->token_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->token_len);
00477             if (!response_message_hdr_ptr->token_ptr) {
00478                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00479 
00480                 if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00481                     handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00482                     coap_packet_ptr->payload_ptr = 0;
00483                 }
00484 
00485                 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00486                 return SN_NSDL_FAILURE;
00487             }
00488             memcpy(response_message_hdr_ptr->token_ptr, coap_packet_ptr->token_ptr, response_message_hdr_ptr->token_len);
00489         }
00490 
00491         if (status == COAP_MSG_CODE_RESPONSE_CONTENT) {
00492             /* Add content type if other than default */
00493             if (resource_temp_ptr->static_resource_parameters) {
00494                 response_message_hdr_ptr->content_format =
00495                     (sn_coap_content_format_e) resource_temp_ptr->coap_content_type;
00496              }
00497 
00498             /* Add payload */
00499             if (resource_temp_ptr->resourcelen != 0) {
00500                 response_message_hdr_ptr->payload_len = resource_temp_ptr->resourcelen;
00501                 response_message_hdr_ptr->payload_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->payload_len);
00502 
00503                 if (!response_message_hdr_ptr->payload_ptr) {
00504                     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00505 
00506                     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00507                         handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00508                         coap_packet_ptr->payload_ptr = 0;
00509                     }
00510 
00511                     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00512                     return SN_NSDL_FAILURE;
00513                 }
00514 
00515                 memcpy(response_message_hdr_ptr->payload_ptr,
00516                        resource_temp_ptr->resource,
00517                        response_message_hdr_ptr->payload_len);
00518             }
00519             // Add max-age attribute for static resources.
00520             // Not a mandatory parameter, no need to return in case of memory allocation fails.
00521             if (static_get_request) {
00522                 if (sn_coap_parser_alloc_options(handle->coap, response_message_hdr_ptr)) {
00523                     response_message_hdr_ptr->options_list_ptr->max_age = 0;
00524                 }
00525             }
00526         }
00527         sn_grs_send_coap_message(nsdl_handle, src_addr_ptr, response_message_hdr_ptr);
00528 
00529         if (response_message_hdr_ptr->payload_ptr) {
00530             handle->sn_grs_free(response_message_hdr_ptr->payload_ptr);
00531             response_message_hdr_ptr->payload_ptr = 0;
00532         }
00533         sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
00534     }
00535 
00536     /* Free parsed CoAP message */
00537     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00538         handle->sn_grs_free(coap_packet_ptr->payload_ptr);
00539         coap_packet_ptr->payload_ptr = 0;
00540     }
00541     sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
00542 
00543     return SN_NSDL_SUCCESS;
00544 }
00545 
00546 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)
00547 {
00548     uint8_t *message_ptr = NULL;
00549     uint16_t message_len = 0;
00550     int16_t ret_val = 0;
00551 
00552     if( !handle ){
00553         return SN_NSDL_FAILURE;
00554     }
00555 
00556 #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */
00557     ret_val = prepare_blockwise_message(handle->grs->coap, coap_hdr_ptr);
00558     if( 0 != ret_val ) {
00559         return SN_NSDL_FAILURE;
00560     }
00561 #endif
00562 
00563     /* Calculate message length */
00564     message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_hdr_ptr, handle->grs->coap->sn_coap_block_data_size);
00565 
00566     /* Allocate memory for message and check was allocating successfully */
00567     message_ptr = handle->grs->sn_grs_alloc(message_len);
00568     if (message_ptr == NULL) {
00569         return SN_NSDL_FAILURE;
00570     }
00571 
00572     /* Build CoAP message */
00573     ret_val = sn_coap_protocol_build(handle->grs->coap, address_ptr, message_ptr, coap_hdr_ptr, (void *)handle);
00574     if (ret_val < 0) {
00575         handle->grs->sn_grs_free(message_ptr);
00576         message_ptr = 0;
00577         if (ret_val == -4) {
00578             return SN_NSDL_RESEND_QUEUE_FULL;
00579         } else {
00580             return SN_NSDL_FAILURE;
00581         }
00582     }
00583 
00584     /* Call tx callback function to send message */
00585     ret_val = handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address_ptr);
00586 
00587     /* Free allocated memory */
00588     handle->grs->sn_grs_free(message_ptr);
00589     message_ptr = 0;
00590 
00591     if (ret_val == 0) {
00592         return SN_NSDL_FAILURE;
00593     } else {
00594         return SN_NSDL_SUCCESS;
00595     }
00596 }
00597 
00598 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)
00599 {
00600     sn_coap_hdr_s           *response_message_hdr_ptr = NULL;
00601     sn_coap_content_format_e wellknown_content_format = COAP_CT_LINK_FORMAT;
00602 
00603     /* Allocate response message  */
00604     response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
00605     if (response_message_hdr_ptr == NULL) {
00606         if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00607             handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr);
00608             coap_packet_ptr->payload_ptr = 0;
00609         }
00610         sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00611         return SN_NSDL_FAILURE;
00612     }
00613 
00614     /* Build response */
00615     response_message_hdr_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00616     response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
00617     response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
00618     response_message_hdr_ptr->content_format = wellknown_content_format;
00619 
00620     sn_nsdl_build_registration_body(handle, response_message_hdr_ptr, 0);
00621 
00622     /* Send and free */
00623     sn_grs_send_coap_message(handle, src_addr_ptr, response_message_hdr_ptr);
00624 
00625     if (response_message_hdr_ptr->payload_ptr) {
00626         handle->grs->sn_grs_free(response_message_hdr_ptr->payload_ptr);
00627         response_message_hdr_ptr->payload_ptr = 0;
00628     }
00629     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, response_message_hdr_ptr);
00630 
00631     /* Free parsed CoAP message */
00632     if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
00633         handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr);
00634         coap_packet_ptr->payload_ptr = 0;
00635     }
00636     sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
00637 
00638     return SN_NSDL_SUCCESS;
00639 }
00640 
00641 /**
00642  * \fn  static sn_grs_resource_info_s *sn_grs_search_resource(struct grs_s *handle, const char *path, uint8_t search_method)
00643  *
00644  * \brief Searches given resource from linked list
00645  *
00646  *  Search either precise path, or subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc...
00647  *
00648  *  \param  pathlen         Length of the path to be search
00649  *
00650  *  \param  *path           Pointer to the path string to be search
00651  *
00652  *  \param  search_method   Search method, SEARCH or DELETE
00653  *
00654  *  \return                 Pointer to the resource. If resource not found, return value is NULL
00655  *
00656 */
00657 
00658 sn_nsdl_dynamic_resource_parameters_s *sn_grs_search_resource(struct grs_s *handle, const char *path, uint8_t search_method)
00659 {
00660     /* Local variables */
00661     char                     *path_temp_ptr          = NULL;
00662     /* Check parameters */
00663     if (!handle || !path) {
00664         return NULL;
00665     }
00666     uint16_t pathlen = strlen(path);
00667     /* Remove '/' - marks from the end and beginning */
00668     path_temp_ptr = sn_grs_convert_uri(&pathlen, path);
00669 
00670     /* Searchs exact path */
00671     if (search_method == SN_GRS_SEARCH_METHOD) {
00672         /* Scan all nodes on list */
00673         ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) {
00674             /* If length equals.. */
00675             size_t len = 0;
00676             if(resource_search_temp &&
00677                     resource_search_temp->static_resource_parameters &&
00678                     resource_search_temp->static_resource_parameters->path) {
00679                 len = strlen(resource_search_temp->static_resource_parameters->path);
00680             }
00681 
00682             if (len == pathlen) {
00683                 /* Compare paths, If same return node pointer*/
00684                 if (0 == memcmp(resource_search_temp->static_resource_parameters->path,
00685                                 path_temp_ptr,
00686                                 pathlen)) {
00687                     return resource_search_temp;
00688                 }
00689             }
00690         }
00691     }
00692     /* Search also subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... */
00693     else if (search_method == SN_GRS_DELETE_METHOD) {
00694         /* Scan all nodes on list */
00695         ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) {
00696             char *temp_path = resource_search_temp->static_resource_parameters->path;
00697             if (strlen(resource_search_temp->static_resource_parameters->path) > pathlen &&
00698                     (*(temp_path + (uint8_t)pathlen) == '/') &&
00699                     0 == memcmp(resource_search_temp->static_resource_parameters->path,
00700                                 path_temp_ptr,
00701                                 pathlen)) {
00702                 return resource_search_temp;
00703             }
00704         }
00705     }
00706 
00707     /* If there was not nodes we wanted, return NULL */
00708     return NULL;
00709 }
00710 
00711 /**
00712  * \fn  static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr)
00713  *
00714  * \brief Removes '/' from the beginning and from the end of uri string
00715  *
00716  *  \param  *uri_len            Pointer to the length of the path string
00717  *
00718  *  \param  *uri_ptr            Pointer to the path string
00719  *
00720  *  \return start pointer of the uri
00721  *
00722 */
00723 
00724 static char *sn_grs_convert_uri(uint16_t *uri_len, const char *uri_ptr)
00725 {
00726     /* Local variables */
00727     char *uri_start_ptr = (char *) uri_ptr;
00728 
00729     /* If '/' in the beginning, update uri start pointer and uri len */
00730     if (*uri_ptr == '/') {
00731         uri_start_ptr = (char *) uri_ptr + 1;
00732         *uri_len = *uri_len - 1;
00733     }
00734 
00735     /* If '/' at the end, update uri len */
00736     if (*(uri_start_ptr + *uri_len - 1) == '/') {
00737         *uri_len = *uri_len - 1;
00738     }
00739 
00740     /* Return start pointer */
00741     return uri_start_ptr;
00742 }
00743 
00744 /**
00745  * \fn  static int8_t sn_grs_resource_info_free(sn_grs_resource_info_s *resource_ptr)
00746  *
00747  * \brief Frees resource info structure
00748  *
00749  *  \param *resource_ptr    Pointer to the resource
00750  *
00751  *  \return 0 if success, -1 if failed
00752  *
00753 */
00754 static int8_t sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr)
00755 {
00756     if (resource_ptr) {
00757 #ifdef MEMORY_OPTIMIZED_API
00758         if (resource_ptr->free_on_delete) {
00759             handle->sn_grs_free(resource_ptr);
00760         }
00761         return SN_NSDL_FAILURE;
00762 #else
00763         if (resource_ptr->static_resource_parameters &&
00764                 resource_ptr->static_resource_parameters->free_on_delete) {
00765 #ifndef RESOURCE_ATTRIBUTES_LIST
00766 #ifndef DISABLE_INTERFACE_DESCRIPTION
00767             if (resource_ptr->static_resource_parameters->interface_description_ptr) {
00768                 handle->sn_grs_free(resource_ptr->static_resource_parameters->interface_description_ptr);
00769                 resource_ptr->static_resource_parameters->interface_description_ptr = 0;
00770             }
00771 #endif
00772 #ifndef DISABLE_RESOURCE_TYPE
00773             if (resource_ptr->static_resource_parameters->resource_type_ptr) {
00774                 handle->sn_grs_free(resource_ptr->static_resource_parameters->resource_type_ptr);
00775                 resource_ptr->static_resource_parameters->resource_type_ptr = 0;
00776             }
00777 #endif
00778 #else
00779             sn_nsdl_free_resource_attributes_list(resource_ptr->static_resource_parameters);
00780 #endif
00781             if (resource_ptr->static_resource_parameters->path) {
00782                 handle->sn_grs_free(resource_ptr->static_resource_parameters->path);
00783                 resource_ptr->static_resource_parameters->path = 0;
00784             }
00785 
00786             if (resource_ptr->resource) {
00787                 handle->sn_grs_free(resource_ptr->resource);
00788                 resource_ptr->resource = 0;
00789             }
00790 
00791             handle->sn_grs_free(resource_ptr->static_resource_parameters);
00792             resource_ptr->static_resource_parameters = 0;
00793         }
00794         if (resource_ptr->free_on_delete) {
00795             handle->sn_grs_free(resource_ptr);
00796         }
00797         return SN_NSDL_SUCCESS;
00798 #endif
00799     }
00800     return SN_NSDL_FAILURE; //Dead code?
00801 }
00802 
00803 void sn_grs_mark_resources_as_registered(struct nsdl_s *handle)
00804 {
00805     if( !handle ){
00806         return;
00807     }
00808 
00809     sn_nsdl_dynamic_resource_parameters_s *temp_resource;
00810 
00811     temp_resource = sn_grs_get_first_resource(handle->grs);
00812 
00813     while (temp_resource) {
00814         if (temp_resource->registered == SN_NDSL_RESOURCE_REGISTERING) {
00815             temp_resource->registered = SN_NDSL_RESOURCE_REGISTERED;
00816         }
00817         temp_resource = sn_grs_get_next_resource(handle->grs, temp_resource);
00818     }
00819 }