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