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