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_builder.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_builder.c 00019 * 00020 * \brief CoAP Message builder 00021 * 00022 * Functionality: Builds CoAP message 00023 * 00024 */ 00025 00026 /* * * * * * * * * * * * * * */ 00027 /* * * * INCLUDE FILES * * * */ 00028 /* * * * * * * * * * * * * * */ 00029 00030 #include <string.h> /* For memset() and memcpy() */ 00031 00032 #include "ns_types.h" 00033 #include "sn_nsdl.h" 00034 #include "sn_coap_header.h" 00035 #include "sn_coap_header_internal.h" 00036 #include "sn_coap_protocol_internal.h" 00037 00038 /* * * * LOCAL FUNCTION PROTOTYPES * * * */ 00039 static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); 00040 static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); 00041 static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option); 00042 static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number); 00043 static int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number); 00044 static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number); 00045 static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option); 00046 static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option); 00047 static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option); 00048 static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); 00049 static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option); 00050 00051 sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) 00052 { 00053 sn_coap_hdr_s *coap_res_ptr; 00054 00055 if (!coap_packet_ptr || !handle) { 00056 return NULL; 00057 } 00058 00059 coap_res_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_hdr_s)); 00060 if (!coap_res_ptr) { 00061 return NULL; 00062 } 00063 00064 memset(coap_res_ptr, 0x00, sizeof(sn_coap_hdr_s)); 00065 00066 if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 00067 coap_res_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; 00068 coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code; 00069 coap_res_ptr->msg_id = coap_packet_ptr->msg_id; 00070 } 00071 00072 else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) { 00073 coap_res_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; 00074 coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code; 00075 /* msg_id needs to be set by the caller in this case */ 00076 } 00077 00078 else { 00079 handle->sn_coap_protocol_free( coap_res_ptr ); 00080 return NULL; 00081 } 00082 00083 if (coap_packet_ptr->token_ptr) { 00084 coap_res_ptr->token_len = coap_packet_ptr->token_len; 00085 coap_res_ptr->token_ptr = handle->sn_coap_protocol_malloc(coap_res_ptr->token_len); 00086 if (!coap_res_ptr->token_ptr) { 00087 handle->sn_coap_protocol_free(coap_res_ptr); 00088 return NULL; 00089 } 00090 memcpy(coap_res_ptr->token_ptr, coap_packet_ptr->token_ptr, coap_res_ptr->token_len); 00091 } 00092 return coap_res_ptr; 00093 } 00094 00095 int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr) 00096 { 00097 return sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); 00098 } 00099 00100 int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) 00101 { 00102 uint8_t *base_packet_data_ptr = NULL; 00103 00104 /* * * * Check given pointers * * * */ 00105 if (dst_packet_data_ptr == NULL || src_coap_msg_ptr == NULL) { 00106 return -2; 00107 } 00108 00109 /* Initialize given Packet data memory area with zero values */ 00110 uint16_t dst_byte_count_to_be_built = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, blockwise_payload_size); 00111 00112 if (!dst_byte_count_to_be_built) { 00113 return -1; 00114 } 00115 00116 memset(dst_packet_data_ptr, 0, dst_byte_count_to_be_built); 00117 00118 /* * * * Store base (= original) destination Packet data pointer for later usage * * * */ 00119 base_packet_data_ptr = dst_packet_data_ptr; 00120 00121 /* * * * * * * * * * * * * * * * * * */ 00122 /* * * * Header part building * * * */ 00123 /* * * * * * * * * * * * * * * * * * */ 00124 if (sn_coap_builder_header_build(&dst_packet_data_ptr, src_coap_msg_ptr) != 0) { 00125 /* Header building failed */ 00126 return -1; 00127 } 00128 00129 /* If else than Reset message because Reset message must be empty */ 00130 if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) { 00131 /* * * * * * * * * * * * * * * * * * */ 00132 /* * * * Options part building * * * */ 00133 /* * * * * * * * * * * * * * * * * * */ 00134 sn_coap_builder_options_build(&dst_packet_data_ptr, src_coap_msg_ptr); 00135 00136 /* * * * * * * * * * * * * * * * * * */ 00137 /* * * * Payload part building * * * */ 00138 /* * * * * * * * * * * * * * * * * * */ 00139 sn_coap_builder_payload_build(&dst_packet_data_ptr, src_coap_msg_ptr); 00140 } 00141 00142 /* * * * Return built Packet data length * * * */ 00143 return (dst_packet_data_ptr - base_packet_data_ptr); 00144 } 00145 uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr) 00146 { 00147 return sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); 00148 } 00149 00150 uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) 00151 { 00152 uint16_t returned_byte_count = 0; 00153 00154 if (!src_coap_msg_ptr) { 00155 return 0; 00156 } 00157 00158 /* * * * * HEADER * * * * */ 00159 00160 /* Header size is fixed */ 00161 returned_byte_count = COAP_HEADER_LENGTH; 00162 00163 /* * * * * OPTIONS * * * * */ 00164 00165 /* If else than Reset message because Reset message must be empty */ 00166 if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) { 00167 uint16_t repeatable_option_size = 0; 00168 00169 /* TOKEN - Length is 1-8 bytes */ 00170 if (src_coap_msg_ptr->token_ptr != NULL) { 00171 if (src_coap_msg_ptr->token_len > 8 || src_coap_msg_ptr->token_len < 1) { /* Check that option is not longer than defined */ 00172 return 0; 00173 } 00174 00175 returned_byte_count += src_coap_msg_ptr->token_len; 00176 } 00177 00178 /* URI PATH - Repeatable option. Length of one option is 0-255 */ 00179 /* Do not add uri-path for notification message. 00180 * Uri-path is needed for cancelling observation with RESET message */ 00181 if (!src_coap_msg_ptr->options_list_ptr || 00182 (src_coap_msg_ptr->options_list_ptr && !src_coap_msg_ptr->options_list_ptr->observe_len && !src_coap_msg_ptr->options_list_ptr->observe_ptr)) { 00183 if (src_coap_msg_ptr->uri_path_ptr != NULL) { 00184 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->uri_path_len, 00185 src_coap_msg_ptr->uri_path_ptr, COAP_OPTION_URI_PATH); 00186 if (repeatable_option_size) { 00187 returned_byte_count += repeatable_option_size; 00188 } else { 00189 return 0; 00190 } 00191 } 00192 } 00193 /* CONTENT TYPE - Length of this option is 0-2 bytes */ 00194 if (src_coap_msg_ptr->content_type_ptr != NULL) { 00195 returned_byte_count++; 00196 if (src_coap_msg_ptr->content_type_len > 2) { 00197 return 0; 00198 } 00199 00200 returned_byte_count += src_coap_msg_ptr->content_type_len; 00201 } 00202 00203 /* If options list pointer exists */ 00204 if (src_coap_msg_ptr->options_list_ptr != NULL) { 00205 /* ACCEPT - Repeatable option. Length of this option is 0-2 bytes */ 00206 if (src_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) { 00207 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->accept_len, 00208 src_coap_msg_ptr->options_list_ptr->accept_ptr, COAP_OPTION_ACCEPT); 00209 if (repeatable_option_size) { 00210 returned_byte_count += repeatable_option_size; 00211 } else { 00212 return 0; 00213 } 00214 } 00215 00216 /* MAX AGE - Length of this option is 0-4 bytes */ 00217 if (src_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) { 00218 returned_byte_count++; 00219 if (src_coap_msg_ptr->options_list_ptr->max_age_len > 4) { 00220 return 0; 00221 } 00222 00223 returned_byte_count += src_coap_msg_ptr->options_list_ptr->max_age_len; 00224 } 00225 00226 /* PROXY URI - Length of this option is 1-1034 bytes */ 00227 if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) { 00228 if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 1 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 12) { /* Add option header byte(s) - depending of option length */ 00229 returned_byte_count++; 00230 } 00231 00232 else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 13 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 269) { 00233 returned_byte_count += 2; 00234 } 00235 00236 else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 270 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 1034) { 00237 returned_byte_count += 3; 00238 } 00239 00240 else { 00241 return 0; 00242 } 00243 00244 /* Add needed memory for Option value */ 00245 returned_byte_count += src_coap_msg_ptr->options_list_ptr->proxy_uri_len; 00246 } 00247 00248 /* ETAG - Repeatable option. Length of this option is 1-8 bytes*/ 00249 if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) { 00250 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->etag_len, 00251 src_coap_msg_ptr->options_list_ptr->etag_ptr, COAP_OPTION_ETAG); 00252 if (repeatable_option_size) { 00253 returned_byte_count += repeatable_option_size; 00254 } else { 00255 return 0; 00256 } 00257 } 00258 00259 /* URI HOST - Length of this option is 1-255 bytes */ 00260 if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) { 00261 if (src_coap_msg_ptr->options_list_ptr->uri_host_len > 0 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 12) { 00262 returned_byte_count++; 00263 } 00264 00265 else if (src_coap_msg_ptr->options_list_ptr->uri_host_len >= 13 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 255) { 00266 returned_byte_count += 2; 00267 } 00268 00269 else { 00270 return 0; 00271 } 00272 00273 returned_byte_count += src_coap_msg_ptr->options_list_ptr->uri_host_len; 00274 } 00275 00276 /* LOCATION PATH - Repeatable option. Length of this option is 0-255 bytes*/ 00277 if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) { 00278 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_path_len, 00279 src_coap_msg_ptr->options_list_ptr->location_path_ptr, COAP_OPTION_LOCATION_PATH); 00280 if (repeatable_option_size) { 00281 returned_byte_count += repeatable_option_size; 00282 } else { 00283 return 0; 00284 } 00285 } 00286 00287 /* URI PORT - Length of this option is 0-2 bytes */ 00288 if (src_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) { 00289 returned_byte_count++; 00290 if (src_coap_msg_ptr->options_list_ptr->uri_port_len > 2) { 00291 return 0; 00292 } 00293 00294 returned_byte_count += src_coap_msg_ptr->options_list_ptr->uri_port_len; 00295 } 00296 00297 /* lOCATION QUERY - Repeatable option. Length of this option is 0-255 bytes */ 00298 if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) { 00299 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_query_len, 00300 src_coap_msg_ptr->options_list_ptr->location_query_ptr, COAP_OPTION_LOCATION_QUERY); 00301 if (repeatable_option_size) { 00302 returned_byte_count += repeatable_option_size; 00303 } else { 00304 return 0; 00305 } 00306 } 00307 00308 /* OBSERVE - Length of this option is 0-3 bytes */ 00309 if (src_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) { 00310 returned_byte_count++; 00311 if (src_coap_msg_ptr->options_list_ptr->observe_len > 3) { 00312 return 0; 00313 } 00314 00315 returned_byte_count += src_coap_msg_ptr->options_list_ptr->observe_len; 00316 } else if (src_coap_msg_ptr->options_list_ptr->observe) { 00317 returned_byte_count++; 00318 } 00319 00320 /* URI QUERY - Repeatable option. Length of this option is 1-255 */ 00321 if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) { 00322 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->uri_query_len, 00323 src_coap_msg_ptr->options_list_ptr->uri_query_ptr, COAP_OPTION_URI_QUERY); 00324 if (repeatable_option_size) { 00325 returned_byte_count += repeatable_option_size; 00326 } else { 00327 return 0; 00328 } 00329 } 00330 00331 /* BLOCK 1 - Length of this option is 1-3 bytes*/ 00332 if (src_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) { 00333 returned_byte_count++; 00334 if (src_coap_msg_ptr->options_list_ptr->block2_len > 3 || src_coap_msg_ptr->options_list_ptr->block2_len < 1) { 00335 return 0; 00336 } 00337 00338 returned_byte_count += src_coap_msg_ptr->options_list_ptr->block2_len; 00339 } 00340 00341 /* BLOCK 2 - Length of this option is 1-3 bytes*/ 00342 if (src_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) { 00343 returned_byte_count++; 00344 00345 if (src_coap_msg_ptr->options_list_ptr->block1_len > 3 || src_coap_msg_ptr->options_list_ptr->block1_len < 1) { 00346 return 0; 00347 } 00348 00349 returned_byte_count += src_coap_msg_ptr->options_list_ptr->block1_len; 00350 } 00351 } 00352 00353 /* * * * * PAYLOAD * * * * */ 00354 #if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ 00355 if ((src_coap_msg_ptr->payload_len > blockwise_payload_size) && (blockwise_payload_size > 0)) { 00356 /* Two bytes for Block option */ 00357 returned_byte_count += 2; 00358 00359 if (src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED) { 00360 returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 1); 00361 } else { /* Response message */ 00362 returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 2); 00363 } 00364 /* Add maximum payload at one Blockwise message */ 00365 returned_byte_count += blockwise_payload_size; 00366 returned_byte_count ++; /* For payload marker */ 00367 } else { 00368 returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 0); 00369 /* Add wanted payload */ 00370 00371 returned_byte_count += src_coap_msg_ptr->payload_len; 00372 00373 if (src_coap_msg_ptr->payload_len) { 00374 returned_byte_count ++; /* For payload marker */ 00375 } 00376 00377 } 00378 #else 00379 returned_byte_count += src_coap_msg_ptr->payload_len; 00380 if (src_coap_msg_ptr->payload_len) { 00381 returned_byte_count ++; /* For payload marker */ 00382 } 00383 returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 0); 00384 #endif 00385 } 00386 00387 return returned_byte_count; 00388 } 00389 00390 /** 00391 * \fn static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option) 00392 * 00393 * \brief Checks if there is need for option jump 00394 * 00395 * \param *src_coap_msg_ptr is source of checked CoAP message 00396 * 00397 * \param block option marks if block option is to be added to message later. 0 = no block option, 1 = block1 and 2 = block2 00398 * 00399 * \return Returns bytes needed for jumping 00400 */ 00401 00402 static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option) 00403 { 00404 uint8_t previous_option_number = 0; 00405 uint8_t needed_space = 0; 00406 00407 if (src_coap_msg_ptr->options_list_ptr != NULL) { 00408 /* If option numbers greater than 12 is not used, then jumping is not needed */ 00409 if (!src_coap_msg_ptr->options_list_ptr->uri_query_ptr && 00410 !src_coap_msg_ptr->options_list_ptr->accept_ptr && 00411 !src_coap_msg_ptr->options_list_ptr->location_query_ptr && 00412 !src_coap_msg_ptr->options_list_ptr->block2_ptr && 00413 !src_coap_msg_ptr->options_list_ptr->block1_ptr && 00414 !src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr && 00415 !block_option && 00416 !src_coap_msg_ptr->options_list_ptr->max_age_ptr) { 00417 return 0; 00418 } 00419 00420 if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) { 00421 previous_option_number = (COAP_OPTION_URI_HOST); 00422 } 00423 00424 if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) { 00425 previous_option_number = (COAP_OPTION_ETAG); 00426 } 00427 00428 if ((src_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) || (src_coap_msg_ptr->options_list_ptr->observe)) { 00429 previous_option_number = (COAP_OPTION_OBSERVE); 00430 } 00431 00432 if (src_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) { 00433 previous_option_number = (COAP_OPTION_URI_PORT); 00434 } 00435 00436 if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) { 00437 previous_option_number = (COAP_OPTION_LOCATION_PATH); 00438 } 00439 00440 if (src_coap_msg_ptr->uri_path_ptr != NULL) { 00441 previous_option_number = (COAP_OPTION_URI_PATH); 00442 } 00443 if (src_coap_msg_ptr->content_type_ptr != NULL) { 00444 previous_option_number = (COAP_OPTION_CONTENT_FORMAT); 00445 } 00446 if (src_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) { 00447 if ((COAP_OPTION_MAX_AGE - previous_option_number) > 12) { 00448 needed_space += 1; 00449 } 00450 previous_option_number = (COAP_OPTION_MAX_AGE); 00451 } 00452 00453 if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) { 00454 if ((COAP_OPTION_URI_QUERY - previous_option_number) > 12) { 00455 needed_space += 1; 00456 } 00457 previous_option_number = (COAP_OPTION_URI_QUERY); 00458 } 00459 if (src_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) { 00460 if ((COAP_OPTION_ACCEPT - previous_option_number) > 12) { 00461 needed_space += 1; 00462 } 00463 previous_option_number = (COAP_OPTION_ACCEPT); 00464 } 00465 if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) { 00466 if ((COAP_OPTION_LOCATION_QUERY - previous_option_number) > 12) { 00467 needed_space += 1; 00468 } 00469 previous_option_number = (COAP_OPTION_LOCATION_QUERY); 00470 } 00471 if (src_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) { 00472 if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12 || (block_option == 2 && (COAP_OPTION_BLOCK2 - previous_option_number) > 12)) { 00473 needed_space += 1; 00474 } 00475 previous_option_number = (COAP_OPTION_BLOCK2); 00476 } 00477 if (src_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) { 00478 if ((COAP_OPTION_BLOCK1 - previous_option_number) > 12 || (block_option == 1 && (COAP_OPTION_BLOCK1 - previous_option_number) > 12)) { 00479 needed_space += 1; 00480 } 00481 previous_option_number = (COAP_OPTION_BLOCK1); 00482 } 00483 if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) { 00484 if ((COAP_OPTION_PROXY_URI - previous_option_number) > 12) { 00485 needed_space += 1; 00486 } 00487 if ((COAP_OPTION_PROXY_URI - previous_option_number) > 269) { //Can not happen 00488 needed_space += 1; 00489 } 00490 previous_option_number = (COAP_OPTION_PROXY_URI); 00491 } 00492 } 00493 00494 else { 00495 if (src_coap_msg_ptr->uri_path_ptr != 0) { 00496 previous_option_number = (COAP_OPTION_URI_PATH); 00497 } 00498 00499 if (src_coap_msg_ptr->content_type_ptr != 0) { 00500 previous_option_number = (COAP_OPTION_CONTENT_FORMAT); 00501 } 00502 00503 #if YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE //block_option 1 & 2 only used if this maro is defined 00504 if (block_option == 2) { 00505 if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12) { 00506 needed_space += 1; 00507 } 00508 previous_option_number = (COAP_OPTION_BLOCK2); 00509 } 00510 if (block_option == 1) { 00511 if ((COAP_OPTION_BLOCK1 - previous_option_number) > 12) { 00512 needed_space += 1; 00513 } 00514 previous_option_number = (COAP_OPTION_BLOCK1); 00515 } 00516 #endif 00517 } 00518 return needed_space; 00519 } 00520 00521 /** 00522 * \fn static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) 00523 * 00524 * \brief Builds Header part of Packet data 00525 * 00526 * \param **dst_packet_data_pptr is destination for built Packet data 00527 * 00528 * \param *src_coap_msg_ptr is source for building Packet data 00529 * 00530 * \return Return value is 0 in ok case and -1 in failure case 00531 **************************************************************************** */ 00532 static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) 00533 { 00534 /* * * * Check validity of Header values * * * */ 00535 if (sn_coap_header_validity_check(src_coap_msg_ptr, COAP_VERSION) != 0) { 00536 return -1; 00537 } 00538 00539 /* * * Add CoAP Version * * */ 00540 **dst_packet_data_pptr += COAP_VERSION; 00541 00542 /* * * Add Message type * * */ 00543 **dst_packet_data_pptr += src_coap_msg_ptr->msg_type; 00544 00545 /* * * Add Token length * * */ 00546 **dst_packet_data_pptr += (src_coap_msg_ptr->token_len); 00547 00548 (*dst_packet_data_pptr) ++; 00549 /* * * Add Message code * * */ 00550 **dst_packet_data_pptr = src_coap_msg_ptr->msg_code; 00551 (*dst_packet_data_pptr) ++; 00552 00553 /* * * Add Message ID * * */ 00554 **dst_packet_data_pptr = (uint8_t)(src_coap_msg_ptr->msg_id >> COAP_HEADER_MSG_ID_MSB_SHIFT); /* MSB part */ 00555 (*dst_packet_data_pptr) ++; 00556 **dst_packet_data_pptr = (uint8_t)src_coap_msg_ptr->msg_id; /* LSB part */ 00557 (*dst_packet_data_pptr) ++; 00558 00559 /* Success */ 00560 return 0; 00561 } 00562 00563 /** 00564 * \fn static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) 00565 * 00566 * \brief Builds Options part of Packet data 00567 * 00568 * \param **dst_packet_data_pptr is destination for built Packet data 00569 * 00570 * \param *src_coap_msg_ptr is source for building Packet data 00571 * 00572 * \return Return value is 0 in every case 00573 */ 00574 static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) 00575 { 00576 int16_t ret_status = 0; 00577 00578 /* * * * Check if Options are used at all * * * */ 00579 if (src_coap_msg_ptr->uri_path_ptr == NULL && src_coap_msg_ptr->token_ptr == NULL && 00580 src_coap_msg_ptr->content_type_ptr == NULL && src_coap_msg_ptr->options_list_ptr == NULL) { 00581 return 0; 00582 } 00583 00584 /* * * * First add Token option * * * */ 00585 if (src_coap_msg_ptr->token_len && src_coap_msg_ptr->token_ptr) { 00586 memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->token_ptr, src_coap_msg_ptr->token_len); 00587 } 00588 (*dst_packet_data_pptr) += src_coap_msg_ptr->token_len; 00589 00590 /* Then build rest of the options */ 00591 00592 /* * * * Initialize previous Option number for new built message * * * */ 00593 uint16_t previous_option_number = 0; 00594 00595 //missing: COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH, COAP_OPTION_SIZE 00596 00597 /* Check if less used options are used at all */ 00598 if (src_coap_msg_ptr->options_list_ptr != NULL) { 00599 /* * * * Build Uri-Host option * * * */ 00600 sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_host_len, 00601 src_coap_msg_ptr->options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST, &previous_option_number); 00602 00603 /* * * * Build ETag option * * * */ 00604 sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->etag_ptr, 00605 (uint16_t *)&src_coap_msg_ptr->options_list_ptr->etag_len, COAP_OPTION_ETAG, &previous_option_number); 00606 00607 /* * * * Build Observe option * * * * */ 00608 ret_status = sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->observe_len, 00609 src_coap_msg_ptr->options_list_ptr->observe_ptr, COAP_OPTION_OBSERVE, &previous_option_number); 00610 if (ret_status == 0) { 00611 sn_coap_builder_options_build_add_zero_length_option(dst_packet_data_pptr, 00612 src_coap_msg_ptr->options_list_ptr->observe_len, 00613 src_coap_msg_ptr->options_list_ptr->observe, 00614 COAP_OPTION_OBSERVE, 00615 &previous_option_number); 00616 } 00617 00618 /* * * * Build Uri-Port option * * * */ 00619 sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_port_len, 00620 src_coap_msg_ptr->options_list_ptr->uri_port_ptr, COAP_OPTION_URI_PORT, &previous_option_number); 00621 00622 /* * * * Build Location-Path option * * * */ 00623 sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_path_ptr, 00624 &src_coap_msg_ptr->options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH, &previous_option_number); 00625 } 00626 /* * * * Build Uri-Path option * * * */ 00627 /* Do not add uri-path for notification message. 00628 * Uri-path is needed for cancelling observation with RESET message */ 00629 if (!src_coap_msg_ptr->options_list_ptr || 00630 (src_coap_msg_ptr->options_list_ptr && !src_coap_msg_ptr->options_list_ptr->observe_len && !src_coap_msg_ptr->options_list_ptr->observe_ptr)) 00631 sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->uri_path_ptr, 00632 &src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH, &previous_option_number); 00633 00634 /* * * * Build Content-Type option * * * */ 00635 sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->content_type_len, 00636 src_coap_msg_ptr->content_type_ptr, COAP_OPTION_CONTENT_FORMAT, &previous_option_number); 00637 00638 if (src_coap_msg_ptr->options_list_ptr != NULL) { 00639 /* * * * Build Max-Age option * * * */ 00640 sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->max_age_len, 00641 src_coap_msg_ptr->options_list_ptr->max_age_ptr, COAP_OPTION_MAX_AGE, &previous_option_number); 00642 00643 /* * * * Build Uri-Query option * * * * */ 00644 sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->uri_query_ptr, 00645 &src_coap_msg_ptr->options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY, &previous_option_number); 00646 00647 /* * * * Build Accept option * * * * */ 00648 sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->accept_ptr, 00649 (uint16_t *)&src_coap_msg_ptr->options_list_ptr->accept_len, COAP_OPTION_ACCEPT, &previous_option_number); 00650 } 00651 00652 if (src_coap_msg_ptr->options_list_ptr != NULL) { 00653 /* * * * Build Location-Query option * * * */ 00654 sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_query_ptr, 00655 &src_coap_msg_ptr->options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY, &previous_option_number); 00656 00657 /* * * * Build Block2 option * * * * */ 00658 sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block2_len, 00659 src_coap_msg_ptr->options_list_ptr->block2_ptr, COAP_OPTION_BLOCK2, &previous_option_number); 00660 00661 /* * * * Build Block1 option * * * * */ 00662 sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block1_len, 00663 src_coap_msg_ptr->options_list_ptr->block1_ptr, COAP_OPTION_BLOCK1, &previous_option_number); 00664 00665 /* * * * Build Proxy-Uri option * * * */ 00666 sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->proxy_uri_len, 00667 src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI, &previous_option_number); 00668 } 00669 00670 /* Success */ 00671 return 0; 00672 } 00673 00674 /** 00675 * \fn static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_value_len, uint8_t *option_value_ptr, sn_coap_option_numbers_e option_number) 00676 * 00677 * \brief Adds Options part of Packet data 00678 * 00679 * \param **dst_packet_data_pptr is destination for built Packet data 00680 * 00681 * \param option_value_len is Option value length to be added 00682 * 00683 * \param *option_value_ptr is pointer to Option value data to be added 00684 * 00685 * \param option_number is Option number to be added 00686 * 00687 * \return Return value is 0 if option was not added, 1 if added 00688 */ 00689 static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, 00690 uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number) 00691 { 00692 /* Check if there is option at all */ 00693 if (option_ptr != NULL) { 00694 uint16_t option_delta; 00695 00696 option_delta = (option_number - *previous_option_number); 00697 00698 /* * * Build option header * * */ 00699 00700 /* First option length without extended part */ 00701 if (option_len <= 12) { 00702 **dst_packet_data_pptr = option_len; 00703 } 00704 00705 else if (option_len > 12 && option_len < 269) { 00706 **dst_packet_data_pptr = 0x0D; 00707 } 00708 00709 else if (option_len >= 269) { 00710 **dst_packet_data_pptr = 0x0E; 00711 } 00712 00713 /* Then option delta with extensions, and move pointer */ 00714 if (option_delta <= 12) { 00715 **dst_packet_data_pptr += (option_delta << 4); 00716 *dst_packet_data_pptr += 1; 00717 } 00718 00719 else if (option_delta > 12 && option_delta < 269) { 00720 **dst_packet_data_pptr += 0xD0; 00721 option_delta -= 13; 00722 00723 *(*dst_packet_data_pptr + 1) = (uint8_t)option_delta; 00724 *dst_packet_data_pptr += 2; 00725 } 00726 //This is currently dead code (but possibly needed in future) 00727 else if (option_delta >= 269) { 00728 **dst_packet_data_pptr += 0xE0; 00729 option_delta -= 269; 00730 00731 *(*dst_packet_data_pptr + 2) = (uint8_t)option_delta; 00732 *(*dst_packet_data_pptr + 1) = (option_delta >> 8); 00733 *dst_packet_data_pptr += 3; 00734 } 00735 00736 /* Now option length extensions, if needed */ 00737 if (option_len > 12 && option_len < 269) { 00738 **dst_packet_data_pptr = (uint8_t)(option_len - 13); 00739 *dst_packet_data_pptr += 1; 00740 } 00741 00742 else if (option_len >= 269) { 00743 *(*dst_packet_data_pptr + 1) = (uint8_t)(option_len - 269); 00744 **dst_packet_data_pptr = ((option_len - 269) >> 8); 00745 *dst_packet_data_pptr += 2; 00746 } 00747 00748 *previous_option_number = option_number; 00749 00750 /* Write Option value */ 00751 memcpy(*dst_packet_data_pptr, option_ptr, option_len); 00752 00753 /* Increase destination Packet data pointer */ 00754 (*dst_packet_data_pptr) += option_len; 00755 00756 return 1; 00757 } 00758 00759 /* Success */ 00760 return 0; 00761 } 00762 00763 /* 00764 * @return 1 if was added 0 otherwise 00765 */ 00766 int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, 00767 uint8_t option_length, 00768 uint8_t option_exist, 00769 sn_coap_option_numbers_e option_number, 00770 uint16_t *previous_option_number) 00771 { 00772 if ((option_exist != 0) && (option_length == 0)) { 00773 uint16_t option_delta; 00774 00775 option_delta = (option_number - *previous_option_number); 00776 00777 /* * * Build option header * * */ 00778 00779 /* First option length without extended part */ 00780 **dst_packet_data_pptr = 0; 00781 00782 /* Then option delta with extensions, and move pointer */ 00783 if (option_delta <= 12) { 00784 **dst_packet_data_pptr += (option_delta << 4); 00785 *dst_packet_data_pptr += 1; 00786 } 00787 //Cannot happen currently --> 00788 else if (option_delta > 12 && option_delta < 269) { 00789 **dst_packet_data_pptr += 0xD0; 00790 option_delta -= 13; 00791 00792 *(*dst_packet_data_pptr + 1) = (uint8_t)option_delta; 00793 *dst_packet_data_pptr += 2; 00794 } 00795 00796 else if (option_delta >= 269) { 00797 **dst_packet_data_pptr += 0xE0; 00798 option_delta -= 269; 00799 00800 *(*dst_packet_data_pptr + 2) = (uint8_t)option_delta; 00801 *(*dst_packet_data_pptr + 1) = (option_delta >> 8); 00802 *dst_packet_data_pptr += 3; 00803 } 00804 //<-- Cannot happen currently 00805 00806 *previous_option_number = option_number; 00807 00808 return 1; 00809 } 00810 return 0; 00811 } 00812 00813 /** 00814 * \fn static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option) 00815 * 00816 * \brief Builds Option Uri-Query from given CoAP Header structure to Packet data 00817 * 00818 * \param **dst_packet_data_pptr is destination for built Packet data 00819 * 00820 * \param uint8_t **src_pptr 00821 * 00822 * \param uint16_t *src_len_ptr 00823 * 00824 * \paramsn_coap_option_numbers_e option option to be added 00825 * 00826 * \return Return value is 0 always 00827 */ 00828 static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number) 00829 { 00830 /* Check if there is option at all */ 00831 if (*src_pptr != NULL) { 00832 uint8_t *query_ptr = *src_pptr; 00833 uint8_t query_part_count = 0; 00834 uint16_t query_len = *src_len_ptr; 00835 uint8_t i = 0; 00836 uint16_t query_part_offset = 0; 00837 00838 /* Get query part count */ 00839 query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option); 00840 00841 /* * * * Options by adding all parts to option * * * */ 00842 for (i = 0; i < query_part_count; i++) { 00843 /* Get length of query part */ 00844 uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option); 00845 00846 /* Get position of query part */ 00847 query_part_offset = sn_coap_builder_options_get_option_part_position(query_len, query_ptr, i, option); 00848 00849 /* Add Uri-query's one part to Options */ 00850 sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, *src_pptr + query_part_offset, option, previous_option_number); 00851 } 00852 } 00853 /* Success */ 00854 return 0; 00855 } 00856 00857 00858 /** 00859 * \fn static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option) 00860 * 00861 * \brief Calculates needed Packet data memory size for option 00862 * 00863 * \param path_len is length of calculated strting(s) 00864 * 00865 * \param *path_ptr is pointer to calculated options 00866 * 00867 * \return Return value is count of needed memory as bytes for Uri-query option 00868 */ 00869 static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option) 00870 { 00871 uint8_t query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option); 00872 uint8_t i = 0; 00873 uint16_t ret_value = 0; 00874 00875 /* * * * * * * * * * * * * * * * * * * * * * * * */ 00876 /* * * * Calculate Uri-query options length * * */ 00877 /* * * * * * * * * * * * * * * * * * * * * * * * */ 00878 for (i = 0; i < query_part_count; i++) { 00879 /* * * Length of Option number and Option value length * * */ 00880 00881 /* Get length of Query part */ 00882 uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option); 00883 00884 /* Check option length */ 00885 switch (option) { 00886 case (COAP_OPTION_ETAG): /* Length 1-8 */ 00887 if (one_query_part_len < 1 || one_query_part_len > 8) { 00888 return 0; 00889 } 00890 break; 00891 case (COAP_OPTION_LOCATION_PATH): /* Length 0-255 */ 00892 case (COAP_OPTION_URI_PATH): /* Length 0-255 */ 00893 case (COAP_OPTION_LOCATION_QUERY): /* Length 0-255 */ 00894 if (one_query_part_len > 255) { 00895 return 0; 00896 } 00897 break; 00898 case (COAP_OPTION_URI_QUERY): /* Length 1-255 */ 00899 if (one_query_part_len < 1 || one_query_part_len > 255) { 00900 return 0; 00901 } 00902 break; 00903 case (COAP_OPTION_ACCEPT): /* Length 0-2 */ 00904 if (one_query_part_len > 2) { 00905 return 0; 00906 } 00907 break; 00908 default: 00909 break; //impossible scenario currently 00910 } 00911 00912 /* Check if 4 bits are enough for writing Option value length */ 00913 if (one_query_part_len <= 12) { 00914 /* 4 bits are enough for Option value length */ 00915 ret_value++; 00916 } else if (one_query_part_len >= 13 && one_query_part_len < 269) { 00917 /* Extra byte for Option value length is needed */ 00918 ret_value += 2; 00919 } 00920 //This can only happen if we are in default case above, currently is not happening 00921 else if (one_query_part_len >= 270 && one_query_part_len < 1034) { 00922 /* Extra bytes for Option value length is needed */ 00923 ret_value += 3; 00924 } 00925 00926 00927 /* * * Length of Option value * * */ 00928 00929 /* Increase options length */ 00930 ret_value += one_query_part_len; 00931 } 00932 00933 /* Success */ 00934 return ret_value; 00935 } 00936 00937 00938 00939 /** 00940 * \fn static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option) 00941 * 00942 * \brief Gets query part count from whole option string 00943 * 00944 * \param query_len is length of whole Path 00945 * 00946 * \param *query_ptr is pointer to the start of whole Path 00947 * 00948 * \return Return value is count of query parts 00949 */ 00950 static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option) 00951 { 00952 uint8_t returned_query_count = 0; 00953 uint16_t query_len_index = 0; 00954 uint8_t char_to_search = '&'; 00955 00956 if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { 00957 char_to_search = '/'; 00958 } 00959 00960 /* Loop whole query and search '\0' characters (not first and last char) */ 00961 for (query_len_index = 1; query_len_index < query_len - 1; query_len_index++) { 00962 /* If new query part starts */ 00963 if (*(query_ptr + query_len_index) == char_to_search) { /* If match */ 00964 returned_query_count++; 00965 } 00966 } 00967 00968 returned_query_count++; 00969 00970 return returned_query_count; 00971 } 00972 00973 /** 00974 * \fn static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, 00975 uint8_t *query_ptr, 00976 uint8_t query_index, sn_coap_option_numbers_e option) 00977 * 00978 * \brief Gets one's query part length from whole query string 00979 * 00980 * \param query_len is length of whole string 00981 * 00982 * \param *query_ptr is pointer to the start of whole string 00983 * 00984 * \param query_index is query part index to be found 00985 * 00986 * \param sn_coap_option_numbers_e option is option number of the option 00987 * 00988 * \return Return value is length of query part 00989 */ 00990 static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr, 00991 uint8_t query_index, sn_coap_option_numbers_e option) 00992 { 00993 uint16_t returned_query_part_len = 0; 00994 uint8_t temp_query_index = 0; 00995 uint16_t query_len_index = 0; 00996 uint8_t char_to_search = '&'; 00997 00998 if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { 00999 char_to_search = '/'; 01000 } 01001 01002 /* Loop whole query and search '\0' characters */ 01003 for (query_len_index = 0; query_len_index < query_len; query_len_index++) { 01004 /* Store character to temp_char for helping debugging */ 01005 uint8_t temp_char = *query_ptr; 01006 01007 /* If new query part starts */ 01008 if (temp_char == char_to_search && returned_query_part_len > 0) { /* returned_query_part_len > 0 is for querys which start with "\0" */ 01009 /* If query part index is wanted */ 01010 if (temp_query_index == query_index) { 01011 /* Return length of query part */ 01012 return returned_query_part_len; 01013 } else { 01014 /* Reset length of query part because wanted query part finding continues*/ 01015 returned_query_part_len = 0; 01016 } 01017 01018 /* Next query part is looped */ 01019 temp_query_index++; 01020 } else if (temp_char != char_to_search) { /* Else if query part continues */ 01021 /* Increase query part length */ 01022 returned_query_part_len++; 01023 } 01024 01025 query_ptr++; 01026 } 01027 01028 /* Return length of query part in cases that query part does not finish to '\0' character (last query part can be like that) */ 01029 return returned_query_part_len; 01030 } 01031 01032 /** 01033 * \fn static uint16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, 01034 uint8_t *query_ptr, 01035 uint8_t query_index, sn_coap_option_numbers_e option) 01036 * 01037 * \brief Gets query part position in whole query 01038 * 01039 * \param query_len is length of whole query 01040 * 01041 * \param *query_ptr is pointer to the start of whole query 01042 * 01043 * \param query_index is query part index to be found 01044 * 01045 * \return Return value is position (= offset) of query part in whole query. In 01046 * fail cases -1 is returned. 01047 */ 01048 static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr, 01049 uint8_t query_index, sn_coap_option_numbers_e option) 01050 { 01051 uint16_t returned_query_part_offset = 0; 01052 uint8_t temp_query_index = 0; 01053 uint16_t query_len_index = 0; 01054 uint8_t char_to_search = '&'; 01055 01056 if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { 01057 char_to_search = '/'; 01058 } 01059 01060 if (query_index == 0) { 01061 if (*query_ptr == 0 || *query_ptr == char_to_search) { 01062 return 1; 01063 } else { 01064 return 0; 01065 } 01066 } 01067 01068 /* Loop whole query and search separator characters */ 01069 for (query_len_index = 0; query_len_index < query_len; query_len_index++) { 01070 /* Store character to temp_char for helping debugging */ 01071 uint8_t temp_char = *query_ptr; 01072 01073 /* If new query part starts */ 01074 if (temp_char == char_to_search && returned_query_part_offset > 0) { /* returned_query_part_offset > 0 is for querys which start with searched char */ 01075 /* If query part index is wanted */ 01076 if (temp_query_index == (query_index - 1)) { 01077 /* Return offset of query part */ 01078 return (returned_query_part_offset + 1); /* Plus one is for passing separator */ 01079 } 01080 01081 /* Next query part is looped */ 01082 temp_query_index++; 01083 } 01084 01085 returned_query_part_offset++; 01086 01087 query_ptr++; 01088 } 01089 01090 return -1; //Dead code? 01091 } 01092 01093 01094 /** 01095 * \fn static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) 01096 * 01097 * \brief Builds Options part of Packet data 01098 * 01099 * \param **dst_packet_data_pptr is destination for built Packet data 01100 * 01101 * \param *src_coap_msg_ptr is source for building Packet data 01102 */ 01103 static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) 01104 { 01105 /* Check if Payload is used at all */ 01106 if (src_coap_msg_ptr->payload_len && src_coap_msg_ptr->payload_ptr != NULL) { 01107 /* Write Payload marker */ 01108 01109 **dst_packet_data_pptr = 0xff; 01110 (*dst_packet_data_pptr)++; 01111 01112 /* Write Payload */ 01113 memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->payload_ptr, src_coap_msg_ptr->payload_len); 01114 01115 /* Increase destination Packet data pointer */ 01116 (*dst_packet_data_pptr) += src_coap_msg_ptr->payload_len; 01117 } 01118 }
Generated on Wed Jul 13 2022 17:43:56 by
