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