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-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
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 "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 }
Generated on Tue Jul 12 2022 11:02:51 by
