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