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