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