Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
sn_coap_parser.c
00001 /* 00002 * Copyright (c) 2011-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 /** 00018 *\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
Generated on Tue Jul 12 2022 11:02:31 by
1.7.2