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