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 OmniWheels 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 "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 Fri Jul 22 2022 04:54:00 by
1.7.2
