Daiki Kato / mbed-os-lychee

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

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