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