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