joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_coap_parser.c Source File

sn_coap_parser.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  *\file sn_coap_parser.c
00019  *
00020  * \brief CoAP Header parser
00021  *
00022  * Functionality: Parses CoAP Header
00023  *
00024  */
00025 
00026 /* * * * * * * * * * * * * * */
00027 /* * * * INCLUDE FILES * * * */
00028 /* * * * * * * * * * * * * * */
00029 
00030 #include <stdio.h>
00031 #include <string.h> /* For memset() and memcpy() */
00032 
00033 #include "ns_types.h"
00034 #include "sn_nsdl.h"
00035 #include "sn_coap_header.h"
00036 #include "sn_coap_protocol.h"
00037 #include "sn_coap_header_internal.h"
00038 #include "sn_coap_protocol_internal.h"
00039 
00040 /* * * * * * * * * * * * * * * * * * * * */
00041 /* * * * LOCAL FUNCTION PROTOTYPES * * * */
00042 /* * * * * * * * * * * * * * * * * * * * */
00043 
00044 static void     sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr);
00045 static int8_t   sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len);
00046 static int8_t   sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len,  uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len);
00047 static int16_t  sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len);
00048 static int8_t   sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr);
00049 
00050 sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr)
00051 {
00052     /* * * * Check given pointer * * * */
00053     if (coap_msg_ptr == NULL) {
00054         return NULL;
00055     }
00056 
00057     /* XXX not technically legal to memset pointers to 0 */
00058     memset(coap_msg_ptr, 0x00, sizeof(sn_coap_hdr_s));
00059 
00060     return coap_msg_ptr;
00061 }
00062 
00063 sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle)
00064 {
00065     sn_coap_hdr_s *returned_coap_msg_ptr;
00066 
00067     /* * * * Check given pointer * * * */
00068     if (handle == NULL) {
00069         return NULL;
00070     }
00071 
00072     /* * * * Allocate memory for returned CoAP message and initialize allocated memory with with default values  * * * */
00073     returned_coap_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_hdr_s));
00074 
00075     return sn_coap_parser_init_message(returned_coap_msg_ptr);
00076 }
00077 
00078 sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr)
00079 {
00080     /* * * * Check given pointers * * * */
00081     if (handle == NULL || coap_msg_ptr == NULL) {
00082         return NULL;
00083     }
00084 
00085     /* * * * If the message already has options, return them * * * */
00086     if (coap_msg_ptr->options_list_ptr) {
00087         return coap_msg_ptr->options_list_ptr;
00088     }
00089 
00090     /* * * * Allocate memory for options and initialize allocated memory with with default values  * * * */
00091     coap_msg_ptr->options_list_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_options_list_s));
00092 
00093     if (coap_msg_ptr->options_list_ptr == NULL) {
00094         return NULL;
00095     }
00096 
00097     /* XXX not technically legal to memset pointers to 0 */
00098     memset(coap_msg_ptr->options_list_ptr, 0x00, sizeof(sn_coap_options_list_s));
00099 
00100     return coap_msg_ptr->options_list_ptr;
00101 }
00102 
00103 sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr)
00104 {
00105     uint8_t       *data_temp_ptr                    = packet_data_ptr;
00106     sn_coap_hdr_s *parsed_and_returned_coap_msg_ptr = NULL;
00107 
00108     /* * * * Check given pointer * * * */
00109     if (packet_data_ptr == NULL || packet_data_len < 4 || handle == NULL) {
00110         return NULL;
00111     }
00112 
00113     /* * * * Allocate and initialize CoAP message  * * * */
00114     parsed_and_returned_coap_msg_ptr = sn_coap_parser_alloc_message(handle);
00115 
00116     if (parsed_and_returned_coap_msg_ptr == NULL) {
00117         return NULL;
00118     }
00119 
00120     /* * * * Header parsing, move pointer over the header...  * * * */
00121     sn_coap_parser_header_parse(&data_temp_ptr, parsed_and_returned_coap_msg_ptr, coap_version_ptr);
00122 
00123     /* * * * Options parsing, move pointer over the options... * * * */
00124     if (sn_coap_parser_options_parse(handle, &data_temp_ptr, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len) != 0) {        
00125         parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
00126         return parsed_and_returned_coap_msg_ptr;
00127     }
00128 
00129     /* * * * Payload parsing * * * */
00130     if (sn_coap_parser_payload_parse(packet_data_len, packet_data_ptr, &data_temp_ptr, parsed_and_returned_coap_msg_ptr) == -1) {
00131         parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
00132         return parsed_and_returned_coap_msg_ptr;
00133     }
00134 
00135     /* * * * Return parsed CoAP message  * * * * */
00136     return parsed_and_returned_coap_msg_ptr;
00137 }
00138 
00139 void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
00140 {
00141     if (handle == NULL) {
00142         return;
00143     }
00144 
00145     if (freed_coap_msg_ptr != NULL) {
00146         if (freed_coap_msg_ptr->uri_path_ptr != NULL) {
00147             handle->sn_coap_protocol_free(freed_coap_msg_ptr->uri_path_ptr);
00148         }
00149 
00150         if (freed_coap_msg_ptr->token_ptr != NULL) {
00151             handle->sn_coap_protocol_free(freed_coap_msg_ptr->token_ptr);
00152         }
00153 
00154         if (freed_coap_msg_ptr->content_type_ptr != NULL) {
00155             handle->sn_coap_protocol_free(freed_coap_msg_ptr->content_type_ptr);
00156         }
00157 
00158         if (freed_coap_msg_ptr->options_list_ptr != NULL) {
00159             if (freed_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) {
00160                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->max_age_ptr);
00161             }
00162 
00163             if (freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
00164                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr);
00165             }
00166 
00167             if (freed_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
00168                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->etag_ptr);
00169             }
00170 
00171             if (freed_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
00172                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_host_ptr);
00173             }
00174 
00175             if (freed_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
00176                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_path_ptr);
00177             }
00178 
00179             if (freed_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) {
00180                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_port_ptr);
00181             }
00182 
00183             if (freed_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
00184                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_query_ptr);
00185             }
00186 
00187             if (freed_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) {
00188                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->observe_ptr);
00189             }
00190 
00191             if (freed_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
00192                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_query_ptr);
00193             }
00194 
00195             if (freed_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) {
00196                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->block2_ptr);
00197             }
00198 
00199             if (freed_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) {
00200                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->block1_ptr);
00201             }
00202             if (freed_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) {
00203                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->accept_ptr);
00204             }
00205 
00206             if (freed_coap_msg_ptr->options_list_ptr->size1_ptr != NULL) {
00207                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->size1_ptr);
00208             }
00209 
00210             if (freed_coap_msg_ptr->options_list_ptr->size2_ptr != NULL) {
00211                 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->size2_ptr);
00212             }
00213 
00214             handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr);
00215         }
00216 
00217         handle->sn_coap_protocol_free(freed_coap_msg_ptr);
00218     }
00219 }
00220 
00221 /**
00222  * \fn static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr)
00223  *
00224  * \brief Parses CoAP message's Header part from given Packet data
00225  *
00226  * \param **packet_data_ptr is source for Packet data to be parsed to CoAP message
00227  *
00228  * \param *dst_coap_msg_ptr is destination for parsed CoAP message
00229  *
00230  * \param *coap_version_ptr is destination for parsed CoAP specification version
00231  */
00232 static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr)
00233 {
00234     /* Parse CoAP Version and message type*/
00235     *coap_version_ptr = (coap_version_e)(**packet_data_pptr & COAP_HEADER_VERSION_MASK);
00236     dst_coap_msg_ptr->msg_type = (sn_coap_msg_type_e)(**packet_data_pptr & COAP_HEADER_MSG_TYPE_MASK);
00237     (*packet_data_pptr) += 1;
00238 
00239     /* Parse Message code */
00240     dst_coap_msg_ptr->msg_code = (sn_coap_msg_code_e) **packet_data_pptr;
00241     (*packet_data_pptr) += 1;
00242 
00243     /* Parse Message ID */
00244     dst_coap_msg_ptr->msg_id = *(*packet_data_pptr + 1);
00245     dst_coap_msg_ptr->msg_id += **packet_data_pptr << COAP_HEADER_MSG_ID_MSB_SHIFT;
00246     (*packet_data_pptr) += 2;
00247 
00248 }
00249 
00250 /**
00251  * \fn static uint8_t sn_coap_parser_options_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
00252  *
00253  * \brief Parses CoAP message's Options part from given Packet data
00254  *
00255  * \param **packet_data_pptr is source of Packet data to be parsed to CoAP message
00256  * \param *dst_coap_msg_ptr is destination for parsed CoAP message
00257  *
00258  * \return Return value is 0 in ok case and -1 in failure case
00259  */
00260 static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len)
00261 {
00262     uint8_t previous_option_number = 0;
00263     uint8_t i                      = 0;
00264     int8_t  ret_status             = 0;
00265     uint16_t message_left          = 0;
00266 
00267     /*  Parse token, if exists  */
00268     dst_coap_msg_ptr->token_len = *packet_data_start_ptr & COAP_HEADER_TOKEN_LENGTH_MASK;
00269 
00270     if (dst_coap_msg_ptr->token_len) {
00271         if ((dst_coap_msg_ptr->token_len > 8) || dst_coap_msg_ptr->token_ptr) {
00272             return -1;
00273         }
00274 
00275         dst_coap_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(dst_coap_msg_ptr->token_len);
00276 
00277         if (dst_coap_msg_ptr->token_ptr == NULL) {
00278             return -1;
00279         }
00280 
00281         memcpy(dst_coap_msg_ptr->token_ptr, *packet_data_pptr, dst_coap_msg_ptr->token_len);
00282         (*packet_data_pptr) += dst_coap_msg_ptr->token_len;
00283     }
00284 
00285     message_left = packet_len - ((*packet_data_pptr) - packet_data_start_ptr);
00286 
00287     /* Loop all Options */
00288     while (message_left && (**packet_data_pptr != 0xff)) {
00289 
00290         /* Get option length WITHOUT extensions */
00291         uint16_t option_len = (**packet_data_pptr & 0x0F);
00292 
00293         /* Option number length 15 is reserved for the future use - ERROR */
00294         if (option_len == 15) {
00295             return -1;
00296         }
00297 
00298         /* Resolve option delta */
00299         uint16_t  option_number = (**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT);
00300 
00301         if (option_number == 13) {
00302             option_number = *(*packet_data_pptr + 1) + 13;
00303             (*packet_data_pptr)++;
00304         } else if (option_number == 14) {
00305             option_number = *(*packet_data_pptr + 2);
00306             option_number += (*(*packet_data_pptr + 1) << 8) + 269;
00307             (*packet_data_pptr) += 2;
00308         }
00309         /* Option number 15 reserved for payload marker. This is handled as a error! */
00310         else if (option_number == 15) {
00311             return -1;
00312         }
00313 
00314         /* Add previous option to option delta and get option number */
00315         option_number += previous_option_number;
00316 
00317         /* Add possible option length extension to resolve full length of the option */
00318         if (option_len == 13) {
00319             option_len = *(*packet_data_pptr + 1) + 13;
00320             (*packet_data_pptr)++;
00321         } else if (option_len == 14) {
00322             option_len = *(*packet_data_pptr + 2);
00323             option_len += (*(*packet_data_pptr + 1) << 8) + 269;
00324             (*packet_data_pptr) += 2;
00325         }
00326 
00327 
00328         /* * * Parse option itself * * */
00329         /* Some options are handled independently in own functions */
00330         previous_option_number = option_number;
00331         /* Allocate options_list_ptr if needed */
00332         switch (option_number) {
00333             case COAP_OPTION_MAX_AGE:
00334             case COAP_OPTION_PROXY_URI:
00335             case COAP_OPTION_ETAG:
00336             case COAP_OPTION_URI_HOST:
00337             case COAP_OPTION_LOCATION_PATH:
00338             case COAP_OPTION_URI_PORT:
00339             case COAP_OPTION_LOCATION_QUERY:
00340             case COAP_OPTION_OBSERVE:
00341             case COAP_OPTION_URI_QUERY:
00342             case COAP_OPTION_BLOCK2:
00343             case COAP_OPTION_BLOCK1:
00344             case COAP_OPTION_ACCEPT:
00345             case COAP_OPTION_SIZE1:
00346             case COAP_OPTION_SIZE2:
00347                 if (sn_coap_parser_alloc_options(handle, dst_coap_msg_ptr) == NULL) {
00348                     return -1;
00349                 }
00350                 break;
00351         }
00352 
00353         /* Parse option */
00354         switch (option_number) {
00355             case COAP_OPTION_CONTENT_FORMAT:
00356                 if ((option_len > 2) || (dst_coap_msg_ptr->content_type_ptr)) {
00357                     return -1;
00358                 }
00359                 dst_coap_msg_ptr->content_type_len = option_len;
00360                 (*packet_data_pptr)++;
00361 
00362                 if (option_len) {
00363                     dst_coap_msg_ptr->content_type_ptr = handle->sn_coap_protocol_malloc(option_len);
00364 
00365                     if (dst_coap_msg_ptr->content_type_ptr == NULL) {
00366                         return -1;
00367                     }
00368 
00369                     memcpy(dst_coap_msg_ptr->content_type_ptr, *packet_data_pptr, option_len);
00370                     (*packet_data_pptr) += option_len;
00371                 }
00372                 break;
00373 
00374             case COAP_OPTION_MAX_AGE:
00375                 if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->max_age_ptr) {
00376                     return -1;
00377                 }
00378                 dst_coap_msg_ptr->options_list_ptr->max_age_len = option_len;
00379                 (*packet_data_pptr)++;
00380 
00381                 if (option_len) {
00382                     dst_coap_msg_ptr->options_list_ptr->max_age_ptr = handle->sn_coap_protocol_malloc(option_len);
00383 
00384                     if (dst_coap_msg_ptr->options_list_ptr->max_age_ptr == NULL) {
00385                         return -1;
00386                     }
00387 
00388                     memcpy(dst_coap_msg_ptr->options_list_ptr->max_age_ptr, *packet_data_pptr, option_len);
00389                     (*packet_data_pptr) += option_len;
00390                 }
00391                 break;
00392 
00393             case COAP_OPTION_PROXY_URI:
00394                 if ((option_len > 1034) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr) {
00395                     return -1;
00396                 }
00397                 dst_coap_msg_ptr->options_list_ptr->proxy_uri_len = option_len;
00398                 (*packet_data_pptr)++;
00399 
00400                 dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(option_len);
00401 
00402                 if (dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr == NULL) {
00403                     return -1;
00404                 }
00405                 memcpy(dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, *packet_data_pptr, option_len);
00406                 (*packet_data_pptr) += option_len;
00407 
00408                 break;
00409 
00410             case COAP_OPTION_ETAG:
00411                 /* This is managed independently because User gives this option in one character table */
00412 
00413                 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr,
00414                              message_left,
00415                              &dst_coap_msg_ptr->options_list_ptr->etag_ptr,
00416                              (uint16_t *)&dst_coap_msg_ptr->options_list_ptr->etag_len,
00417                              COAP_OPTION_ETAG, option_len);
00418                 if (ret_status >= 0) {
00419                     i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
00420                 } else {
00421                     return -1;
00422                 }
00423                 break;
00424 
00425             case COAP_OPTION_URI_HOST:
00426                 if ((option_len > 255) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->uri_host_ptr) {
00427                     return -1;
00428                 }
00429                 dst_coap_msg_ptr->options_list_ptr->uri_host_len = option_len;
00430                 (*packet_data_pptr)++;
00431 
00432                 dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(option_len);
00433 
00434                 if (dst_coap_msg_ptr->options_list_ptr->uri_host_ptr == NULL) {
00435                     return -1;
00436                 }
00437                 memcpy(dst_coap_msg_ptr->options_list_ptr->uri_host_ptr, *packet_data_pptr, option_len);
00438                 (*packet_data_pptr) += option_len;
00439 
00440                 break;
00441 
00442             case COAP_OPTION_LOCATION_PATH:
00443                 if (dst_coap_msg_ptr->options_list_ptr->location_path_ptr) {
00444                     return -1;
00445                 }
00446                 /* This is managed independently because User gives this option in one character table */
00447                 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
00448                              &dst_coap_msg_ptr->options_list_ptr->location_path_ptr, &dst_coap_msg_ptr->options_list_ptr->location_path_len,
00449                              COAP_OPTION_LOCATION_PATH, option_len);
00450                 if (ret_status >= 0) {
00451                     i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
00452                 } else {
00453                     return -1;
00454                 }
00455 
00456                 break;
00457 
00458 
00459             case COAP_OPTION_URI_PORT:
00460                 if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->uri_port_ptr) {
00461                     return -1;
00462                 }
00463                 dst_coap_msg_ptr->options_list_ptr->uri_port_len = option_len;
00464                 (*packet_data_pptr)++;
00465 
00466                 if (option_len) {
00467                     dst_coap_msg_ptr->options_list_ptr->uri_port_ptr = handle->sn_coap_protocol_malloc(option_len);
00468 
00469                     if (dst_coap_msg_ptr->options_list_ptr->uri_port_ptr == NULL) {
00470                         return -1;
00471                     }
00472                     memcpy(dst_coap_msg_ptr->options_list_ptr->uri_port_ptr, *packet_data_pptr, option_len);
00473                     (*packet_data_pptr) += option_len;
00474                 }
00475                 break;
00476 
00477             case COAP_OPTION_LOCATION_QUERY:
00478                 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
00479                              &dst_coap_msg_ptr->options_list_ptr->location_query_ptr, &dst_coap_msg_ptr->options_list_ptr->location_query_len,
00480                              COAP_OPTION_LOCATION_QUERY, option_len);
00481                 if (ret_status >= 0) {
00482                     i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
00483                 } else {
00484                     return -1;
00485                 }
00486 
00487                 break;
00488 
00489             case COAP_OPTION_URI_PATH:
00490                 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
00491                              &dst_coap_msg_ptr->uri_path_ptr, &dst_coap_msg_ptr->uri_path_len,
00492                              COAP_OPTION_URI_PATH, option_len);
00493                 if (ret_status >= 0) {
00494                     i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
00495                 } else {
00496                     return -1;
00497                 }
00498 
00499                 break;
00500 
00501             case COAP_OPTION_OBSERVE:
00502                 if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->observe_ptr) {
00503                     return -1;
00504                 }
00505 
00506                 dst_coap_msg_ptr->options_list_ptr->observe = 1;
00507                 (*packet_data_pptr)++;
00508 
00509                 if (option_len) {
00510 
00511                     dst_coap_msg_ptr->options_list_ptr->observe_len = option_len;
00512 
00513                     dst_coap_msg_ptr->options_list_ptr->observe_ptr = handle->sn_coap_protocol_malloc(option_len);
00514 
00515                     if (dst_coap_msg_ptr->options_list_ptr->observe_ptr == NULL) {
00516                         return -1;
00517                     }
00518 
00519                     memcpy(dst_coap_msg_ptr->options_list_ptr->observe_ptr, *packet_data_pptr, option_len);
00520                     (*packet_data_pptr) += option_len;
00521                 }
00522 
00523                 break;
00524 
00525             case COAP_OPTION_URI_QUERY:
00526                 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
00527                              &dst_coap_msg_ptr->options_list_ptr->uri_query_ptr, &dst_coap_msg_ptr->options_list_ptr->uri_query_len,
00528                              COAP_OPTION_URI_QUERY, option_len);
00529                 if (ret_status >= 0) {
00530                     i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
00531                 } else {
00532                     return -1;
00533                 }
00534 
00535                 break;
00536 
00537             case COAP_OPTION_BLOCK2:
00538                 if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->block2_ptr) {
00539                     return -1;
00540                 }
00541                 dst_coap_msg_ptr->options_list_ptr->block2_len = option_len;
00542                 (*packet_data_pptr)++;
00543 
00544                 dst_coap_msg_ptr->options_list_ptr->block2_ptr = handle->sn_coap_protocol_malloc(option_len);
00545 
00546                 if (dst_coap_msg_ptr->options_list_ptr->block2_ptr == NULL) {
00547                     return -1;
00548                 }
00549 
00550                 memcpy(dst_coap_msg_ptr->options_list_ptr->block2_ptr, *packet_data_pptr, option_len);
00551                 (*packet_data_pptr) += option_len;
00552 
00553                 break;
00554 
00555             case COAP_OPTION_BLOCK1:
00556                 if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->block1_ptr) {
00557                     return -1;
00558                 }
00559                 dst_coap_msg_ptr->options_list_ptr->block1_len = option_len;
00560                 (*packet_data_pptr)++;
00561 
00562                 dst_coap_msg_ptr->options_list_ptr->block1_ptr = handle->sn_coap_protocol_malloc(option_len);
00563 
00564                 if (dst_coap_msg_ptr->options_list_ptr->block1_ptr == NULL) {
00565                     return -1;
00566                 }
00567 
00568                 memcpy(dst_coap_msg_ptr->options_list_ptr->block1_ptr, *packet_data_pptr, option_len);
00569                 (*packet_data_pptr) += option_len;
00570 
00571                 break;
00572 
00573             case COAP_OPTION_ACCEPT:
00574                 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
00575                              &dst_coap_msg_ptr->options_list_ptr->accept_ptr, (uint16_t *)&dst_coap_msg_ptr->options_list_ptr->accept_len,
00576                              COAP_OPTION_ACCEPT, option_len);
00577                 if (ret_status >= 0) {
00578                     i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
00579                 } else {
00580                     return -1;
00581                 }
00582 
00583                 break;
00584 
00585             case COAP_OPTION_SIZE1:
00586                 if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->size1_ptr) {
00587                     return -1;
00588                 }
00589                 dst_coap_msg_ptr->options_list_ptr->size1_len = option_len;
00590                 (*packet_data_pptr)++;
00591 
00592                 if (option_len) {
00593                     dst_coap_msg_ptr->options_list_ptr->size1_ptr = handle->sn_coap_protocol_malloc(option_len);
00594 
00595                     if (dst_coap_msg_ptr->options_list_ptr->size1_ptr == NULL) {
00596                         return -1;
00597                     }
00598 
00599                     memcpy(dst_coap_msg_ptr->options_list_ptr->size1_ptr, *packet_data_pptr, option_len);
00600                     (*packet_data_pptr) += option_len;
00601                 }
00602                 break;
00603 
00604         case COAP_OPTION_SIZE2:
00605             if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->size2_ptr) {
00606                 return -1;
00607             }
00608             dst_coap_msg_ptr->options_list_ptr->size2_len = option_len;
00609             (*packet_data_pptr)++;
00610 
00611             if (option_len) {
00612                 dst_coap_msg_ptr->options_list_ptr->size2_ptr = handle->sn_coap_protocol_malloc(option_len);
00613 
00614                 if (dst_coap_msg_ptr->options_list_ptr->size2_ptr == NULL) {
00615                     return -1;
00616                 }
00617 
00618                 memcpy(dst_coap_msg_ptr->options_list_ptr->size2_ptr, *packet_data_pptr, option_len);
00619                 (*packet_data_pptr) += option_len;
00620             }
00621             break;
00622 
00623             default:
00624                 return -1;
00625         }
00626 
00627         /* Check for overflow */
00628         if ((*packet_data_pptr - packet_data_start_ptr) > packet_len) {
00629             return -1;
00630         }
00631 
00632         message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr);
00633 
00634 
00635     }
00636 
00637     return 0;
00638 }
00639 
00640 
00641 /**
00642  * \fn static int8_t sn_coap_parser_options_parse_multiple_options(uint8_t **packet_data_pptr, uint8_t options_count_left, uint8_t *previous_option_number_ptr, uint8_t **dst_pptr,
00643  *                                                                  uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
00644  *
00645  * \brief Parses CoAP message's Uri-query options
00646  *
00647  * \param **packet_data_pptr is source for Packet data to be parsed to CoAP message
00648  *
00649  * \param *dst_coap_msg_ptr is destination for parsed CoAP message
00650  *
00651  * \param options_count_left tells how many options are unhandled in Packet data
00652  *
00653  * \param *previous_option_number_ptr is pointer to used and returned previous Option number
00654  *
00655  * \return Return value is count of Uri-query optios parsed. In failure case -1 is returned.
00656 */
00657 static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len,  uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
00658 {
00659     int16_t     uri_query_needed_heap       = sn_coap_parser_options_count_needed_memory_multiple_option(*packet_data_pptr, packet_left_len, option, option_number_len);
00660     uint8_t    *temp_parsed_uri_query_ptr   = NULL;
00661     uint8_t     returned_option_counter     = 0;
00662 
00663     if (uri_query_needed_heap == -1) {
00664         return -1;
00665     }
00666 
00667     if (uri_query_needed_heap) {
00668         *dst_pptr = (uint8_t *) handle->sn_coap_protocol_malloc(uri_query_needed_heap);
00669 
00670         if (*dst_pptr == NULL) {
00671             return -1;
00672         }
00673     }
00674 
00675     *dst_len_ptr = uri_query_needed_heap;
00676 
00677     temp_parsed_uri_query_ptr = *dst_pptr;
00678 
00679     /* Loop all Uri-Query options */
00680     while ((temp_parsed_uri_query_ptr - *dst_pptr) < uri_query_needed_heap) {
00681         /* Check if this is first Uri-Query option */
00682         if (returned_option_counter > 0) {
00683             /* Uri-Query is modified to following format: temp1'\0'temp2'\0'temp3 i.e.  */
00684             /* Uri-Path is modified to following format: temp1\temp2\temp3 i.e.  */
00685             if (option == COAP_OPTION_URI_QUERY || option == COAP_OPTION_LOCATION_QUERY || option == COAP_OPTION_ETAG || option == COAP_OPTION_ACCEPT) {
00686                 memset(temp_parsed_uri_query_ptr, '&', 1);
00687             } else if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
00688                 memset(temp_parsed_uri_query_ptr, '/', 1);
00689             }
00690 
00691             temp_parsed_uri_query_ptr++;
00692         }
00693 
00694         returned_option_counter++;
00695 
00696         (*packet_data_pptr)++;
00697 
00698         if (((temp_parsed_uri_query_ptr - *dst_pptr) + option_number_len) > uri_query_needed_heap) {
00699             return -1;
00700         }
00701 
00702         memcpy(temp_parsed_uri_query_ptr, *packet_data_pptr, option_number_len);
00703 
00704         (*packet_data_pptr) += option_number_len;
00705         temp_parsed_uri_query_ptr += option_number_len;
00706 
00707         if ((temp_parsed_uri_query_ptr - *dst_pptr) >= uri_query_needed_heap || ((**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0)) {
00708             return returned_option_counter;
00709         }
00710 
00711         option_number_len = (**packet_data_pptr & 0x0F);
00712         if (option_number_len == 13) {
00713             option_number_len = *(*packet_data_pptr + 1) + 13;
00714             (*packet_data_pptr)++;
00715         } else if (option_number_len == 14) {
00716             option_number_len = *(*packet_data_pptr + 2);
00717             option_number_len += (*(*packet_data_pptr + 1) << 8) + 269;
00718             (*packet_data_pptr) += 2;
00719         }
00720     }
00721 
00722     return returned_option_counter;
00723 }
00724 
00725 
00726 
00727 
00728 /**
00729  * \fn static uint16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint8_t options_count_left, uint8_t previous_option_number, sn_coap_option_numbers_e option, uint16_t option_number_len)
00730  *
00731  * \brief Counts needed memory for uri query option
00732  *
00733  * \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message
00734  *
00735  * \param options_count_left tells how many options are unhandled in Packet data
00736  *
00737  * \param previous_option_number is previous Option number
00738  *
00739  * \param sn_coap_option_numbers_e option option number to be calculated
00740  *
00741  * \param uint16_t option_number_len length of the first option part
00742  */
00743 static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len)
00744 {
00745     uint16_t ret_value              = 0;
00746     uint16_t i                      = 1;
00747 
00748     /* Loop all Uri-Query options */
00749     while (i < packet_left_len) {
00750         if (option == COAP_OPTION_LOCATION_PATH && option_number_len > 255) {
00751             return -1;
00752         }
00753         if (option == COAP_OPTION_URI_PATH && option_number_len > 255) {
00754             return -1;
00755         }
00756         if (option == COAP_OPTION_URI_QUERY && option_number_len > 255) {
00757             return -1;
00758         }
00759         if (option == COAP_OPTION_LOCATION_QUERY && option_number_len > 255) {
00760             return -1;
00761         }
00762         if (option == COAP_OPTION_ACCEPT && option_number_len > 2) {
00763             return -1;
00764         }
00765         if (option == COAP_OPTION_ETAG && option_number_len > 8) {
00766             return -1;
00767         }
00768 
00769         i += option_number_len;
00770         ret_value += option_number_len + 1; /* + 1 is for separator */
00771         if(ret_value >= packet_left_len)
00772             break;
00773 
00774         if(ret_value >= packet_left_len)
00775             break;
00776 
00777         if( i == packet_left_len )
00778             break;
00779 
00780         if ((*(packet_data_ptr + i) >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0) {
00781             return (ret_value - 1);    /* -1 because last Part path does not include separator */
00782         }
00783 
00784         option_number_len = (*(packet_data_ptr + i) & 0x0F);
00785 
00786         if (option_number_len == 13) {
00787             i++;
00788             option_number_len = *(packet_data_ptr + i) + 13;
00789         } else if (option_number_len == 14) {
00790             option_number_len = *(packet_data_ptr + i + 2);
00791             option_number_len += (*(packet_data_ptr + i + 1) << 8) + 269;
00792             i += 2;
00793         } else if (option_number_len == 15) {
00794             return -1;
00795         }
00796         i++;
00797 
00798     }
00799 
00800     if (ret_value != 0) {
00801         return (ret_value - 1);    /* -1 because last Part path does not include separator */
00802     } else {
00803         return 0;
00804     }
00805 }
00806 
00807 /**
00808  * \fn static void sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
00809  *
00810  * \brief Parses CoAP message's Payload part from given Packet data
00811  *
00812  * \param packet_data_len is length of given Packet data to be parsed to CoAP message
00813  *
00814  * \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message
00815  *
00816  * \param **packet_data_pptr is source for Packet data to be parsed to CoAP message
00817  *
00818  * \param *dst_coap_msg_ptr is destination for parsed CoAP message
00819  *****************************************************************************/
00820 static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
00821 {
00822     /* If there is payload */
00823     if ((*packet_data_pptr - packet_data_start_ptr) < packet_data_len) {
00824         if (**packet_data_pptr == 0xff) {
00825             (*packet_data_pptr)++;
00826             /* Parse Payload length */
00827             dst_coap_msg_ptr->payload_len = packet_data_len - (*packet_data_pptr - packet_data_start_ptr);
00828 
00829             /* The presence of a marker followed by a zero-length payload MUST be processed as a message format error */
00830             if (dst_coap_msg_ptr->payload_len == 0) {
00831                 return -1;
00832             }
00833 
00834             /* Parse Payload by setting CoAP message's payload_ptr to point Payload in Packet data */
00835             dst_coap_msg_ptr->payload_ptr = *packet_data_pptr;
00836         }
00837         /* No payload marker.. */
00838         else {
00839             return -1;
00840         }
00841     }
00842     return 0;
00843 }