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