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.
Fork of mbed-os by
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 13:16:06 by
1.7.2
