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