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