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