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