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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
sn_coap_protocol.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_protocol.c 00019 * 00020 * \brief CoAP Protocol implementation 00021 * 00022 * Functionality: CoAP Protocol 00023 * 00024 */ 00025 00026 00027 /* * * * * * * * * * * * * * */ 00028 /* * * * INCLUDE FILES * * * */ 00029 /* * * * * * * * * * * * * * */ 00030 00031 #include <stdio.h> 00032 #include <stdlib.h> /* For libary malloc() */ 00033 #include <string.h> /* For memset() and memcpy() */ 00034 #if defined __linux__ || defined TARGET_LIKE_MBED 00035 #include <time.h> 00036 #endif 00037 00038 #include "ns_types.h" 00039 #include "mbed-coap/sn_coap_protocol.h" 00040 #include "sn_coap_header_internal.h" 00041 #include "sn_coap_protocol_internal.h" 00042 #include "randLIB.h" 00043 #include "mbed-trace/mbed_trace.h" 00044 00045 #define TRACE_GROUP "coap" 00046 /* * * * * * * * * * * * * * * * * * * * */ 00047 /* * * * LOCAL FUNCTION PROTOTYPES * * * */ 00048 /* * * * * * * * * * * * * * * * * * * * */ 00049 00050 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT/* If Message duplication detection is not used at all, this part of code will not be compiled */ 00051 static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id, void *param); 00052 static coap_duplication_info_s *sn_coap_protocol_linked_list_duplication_info_search(const struct coap_s *handle, const sn_nsdl_addr_s *scr_addr_ptr, const uint16_t msg_id); 00053 static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle); 00054 static void sn_coap_protocol_duplication_info_free(struct coap_s *handle, coap_duplication_info_s *duplication_info_ptr); 00055 static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *handle, const sn_nsdl_addr_s *dst_addr_ptr, const sn_coap_hdr_s *coap_msg_ptr, const int16_t data_size, const uint8_t *dst_packet_data_ptr); 00056 #endif 00057 00058 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */ 00059 static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr); 00060 static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, uint16_t payload_len, uint8_t *payload_ptr, uint8_t *token_ptr, uint8_t token_len, uint32_t block_number, uint32_t size1); 00061 static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length, const uint8_t *token_ptr, uint8_t token_len); 00062 static coap_blockwise_payload_s *sn_coap_protocol_linked_list_blockwise_search(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len); 00063 static bool sn_coap_protocol_linked_list_blockwise_payload_search_compare_block_number(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len, uint32_t block_number); 00064 static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, coap_blockwise_payload_s *removed_payload_ptr); 00065 static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len); 00066 static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle); 00067 static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param); 00068 static bool sn_coap_handle_last_blockwise(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr); 00069 static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, const sn_coap_hdr_s *source_header_ptr); 00070 static coap_blockwise_msg_s *search_sent_blockwise_message(struct coap_s *handle, uint16_t msg_id); 00071 static int16_t store_blockwise_copy(struct coap_s *handle, const sn_coap_hdr_s *src_coap_msg_ptr, void *param, uint16_t original_payload_len, bool copy_payload); 00072 #endif 00073 00074 #if ENABLE_RESENDINGS 00075 static uint8_t sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param); 00076 static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); 00077 static coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len); 00078 static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr); 00079 static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr); 00080 static uint32_t sn_coap_calculate_new_resend_time(const uint32_t current_time, const uint8_t interval, const uint8_t counter); 00081 #endif 00082 00083 static uint16_t read_packet_msg_id(const coap_send_msg_s *stored_msg); 00084 static uint16_t get_new_message_id(void); 00085 00086 static bool compare_address_and_port(const sn_nsdl_addr_s* left, const sn_nsdl_addr_s* right); 00087 00088 /* * * * * * * * * * * * * * * * * */ 00089 /* * * * GLOBAL DECLARATIONS * * * */ 00090 /* * * * * * * * * * * * * * * * * */ 00091 static uint16_t message_id; 00092 00093 int8_t sn_coap_protocol_destroy(struct coap_s *handle) 00094 { 00095 if (handle == NULL) { 00096 return -1; 00097 } 00098 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 00099 00100 sn_coap_protocol_clear_retransmission_buffer(handle); 00101 00102 #endif 00103 00104 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ 00105 ns_list_foreach_safe(coap_duplication_info_s, tmp, &handle->linked_list_duplication_msgs) { 00106 00107 ns_list_remove(&handle->linked_list_duplication_msgs, tmp); 00108 00109 sn_coap_protocol_duplication_info_free(handle, tmp); 00110 } 00111 00112 #endif 00113 00114 00115 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not enabled, this part of code will not be compiled */ 00116 00117 sn_coap_protocol_clear_sent_blockwise_messages(handle); 00118 00119 sn_coap_protocol_clear_received_blockwise_messages(handle); 00120 #endif 00121 00122 handle->sn_coap_protocol_free(handle); 00123 return 0; 00124 } 00125 00126 struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), 00127 uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *), 00128 int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *param)) 00129 { 00130 /* Check paramters */ 00131 if ((used_malloc_func_ptr == NULL) || (used_free_func_ptr == NULL) || (used_tx_callback_ptr == NULL)) { 00132 return NULL; 00133 } 00134 00135 struct coap_s *handle; 00136 handle = used_malloc_func_ptr(sizeof(struct coap_s)); 00137 if (handle == NULL) { 00138 return NULL; 00139 } 00140 00141 memset(handle, 0, sizeof(struct coap_s)); 00142 00143 /* * * Handle tx callback * * */ 00144 handle->sn_coap_tx_callback = used_tx_callback_ptr; 00145 00146 handle->sn_coap_protocol_free = used_free_func_ptr; 00147 handle->sn_coap_protocol_malloc = used_malloc_func_ptr; 00148 00149 /* * * Handle rx callback * * */ 00150 /* If pointer = 0, then re-sending does not return error when failed */ 00151 handle->sn_coap_rx_callback = used_rx_callback_ptr; 00152 00153 // Handles internally all GET req responses 00154 handle->sn_coap_internal_block2_resp_handling = true; 00155 00156 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 00157 /* * * * Create Linked list for storing active resending messages * * * */ 00158 ns_list_init(&handle->linked_list_resent_msgs); 00159 handle->sn_coap_resending_queue_msgs = SN_COAP_RESENDING_QUEUE_SIZE_MSGS; 00160 handle->sn_coap_resending_queue_bytes = SN_COAP_RESENDING_QUEUE_SIZE_BYTES; 00161 handle->sn_coap_resending_intervall = DEFAULT_RESPONSE_TIMEOUT; 00162 handle->sn_coap_resending_count = SN_COAP_RESENDING_MAX_COUNT; 00163 00164 00165 #endif /* ENABLE_RESENDINGS */ 00166 00167 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ 00168 /* * * * Create Linked list for storing Duplication info * * * */ 00169 ns_list_init(&handle->linked_list_duplication_msgs); 00170 handle->sn_coap_duplication_buffer_size = SN_COAP_DUPLICATION_MAX_MSGS_COUNT; 00171 #endif 00172 00173 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */ 00174 00175 ns_list_init(&handle->linked_list_blockwise_sent_msgs); 00176 ns_list_init(&handle->linked_list_blockwise_received_payloads); 00177 handle->sn_coap_block_data_size = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE; 00178 00179 #endif /* ENABLE_RESENDINGS */ 00180 00181 message_id = 0; 00182 return handle; 00183 } 00184 00185 int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t build_response) 00186 { 00187 if (handle == NULL) { 00188 return -1; 00189 } 00190 00191 handle->sn_coap_internal_block2_resp_handling = build_response; 00192 return 0; 00193 } 00194 00195 int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size) 00196 { 00197 (void) handle; 00198 (void) block_size; 00199 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 00200 if (handle == NULL) { 00201 return -1; 00202 } 00203 switch (block_size) { 00204 case 0: 00205 case 16: 00206 case 32: 00207 case 64: 00208 case 128: 00209 case 256: 00210 case 512: 00211 case 1024: 00212 handle->sn_coap_block_data_size = block_size; 00213 return 0; 00214 default: 00215 break; 00216 } 00217 #endif 00218 return -1; 00219 00220 } 00221 00222 void sn_coap_protocol_clear_sent_blockwise_messages(struct coap_s *handle) 00223 { 00224 (void) handle; 00225 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 00226 if (handle == NULL) { 00227 return; 00228 } 00229 00230 /* Loop all stored Blockwise messages in Linked list */ 00231 ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) { 00232 sn_coap_protocol_linked_list_blockwise_msg_remove(handle, removed_blocwise_msg_ptr); 00233 } 00234 #endif 00235 } 00236 00237 void sn_coap_protocol_clear_received_blockwise_messages(struct coap_s *handle) 00238 { 00239 (void) handle; 00240 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 00241 if (handle == NULL) { 00242 return; 00243 } 00244 00245 /* Loop all stored Blockwise messages in Linked list */ 00246 ns_list_foreach_safe(coap_blockwise_payload_s, removed_blockwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) { 00247 sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_blockwise_payload_ptr); 00248 } 00249 #endif 00250 } 00251 00252 int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count) 00253 { 00254 (void) handle; 00255 (void) message_count; 00256 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT 00257 if (handle == NULL) { 00258 return -1; 00259 } 00260 if (message_count <= SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT) { 00261 handle->sn_coap_duplication_buffer_size = message_count; 00262 return 0; 00263 } 00264 #endif 00265 return -1; 00266 } 00267 00268 int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle, 00269 uint8_t resending_count, uint8_t resending_intervall) 00270 { 00271 #if ENABLE_RESENDINGS 00272 if (handle == NULL) { 00273 return -1; 00274 } 00275 if (resending_count <= SN_COAP_MAX_ALLOWED_RESENDING_COUNT && 00276 resending_intervall <= SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT) { 00277 handle->sn_coap_resending_count = resending_count; 00278 00279 if (resending_intervall == 0) { 00280 handle->sn_coap_resending_intervall = 1; 00281 } else { 00282 handle->sn_coap_resending_intervall = resending_intervall; 00283 } 00284 return 0; 00285 } 00286 #endif 00287 return -1; 00288 } 00289 00290 int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle, 00291 uint8_t buffer_size_messages, uint16_t buffer_size_bytes) 00292 { 00293 #if ENABLE_RESENDINGS 00294 if (handle == NULL) { 00295 return -1; 00296 } 00297 if (buffer_size_bytes <= SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES && 00298 buffer_size_messages <= SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS ) { 00299 handle->sn_coap_resending_queue_bytes = buffer_size_bytes; 00300 handle->sn_coap_resending_queue_msgs = buffer_size_messages; 00301 return 0; 00302 } 00303 00304 #endif 00305 return -1; 00306 00307 } 00308 00309 void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle) 00310 { 00311 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 00312 if (handle == NULL) { 00313 return; 00314 } 00315 ns_list_foreach_safe(coap_send_msg_s, tmp, &handle->linked_list_resent_msgs) { 00316 ns_list_remove(&handle->linked_list_resent_msgs, tmp); 00317 sn_coap_protocol_release_allocated_send_msg_mem(handle, tmp); 00318 --handle->count_resent_msgs; 00319 } 00320 #endif 00321 } 00322 00323 int8_t sn_coap_protocol_delete_retransmission(struct coap_s *handle, uint16_t msg_id) 00324 { 00325 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 00326 if (handle == NULL) { 00327 return -1; 00328 } 00329 ns_list_foreach_safe(coap_send_msg_s, tmp, &handle->linked_list_resent_msgs) { 00330 if (tmp->send_msg_ptr.packet_ptr) { 00331 uint16_t temp_msg_id = read_packet_msg_id(tmp); 00332 if (temp_msg_id == msg_id) { 00333 ns_list_remove(&handle->linked_list_resent_msgs, tmp); 00334 --handle->count_resent_msgs; 00335 sn_coap_protocol_release_allocated_send_msg_mem(handle, tmp); 00336 return 0; 00337 } 00338 } 00339 } 00340 #endif 00341 return -2; 00342 } 00343 00344 int8_t sn_coap_protocol_delete_retransmission_by_token(struct coap_s *handle, const uint8_t *token, uint8_t token_len) 00345 { 00346 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 00347 if (handle == NULL || token == NULL || token_len == 0) { 00348 tr_error("sn_coap_protocol_delete_retransmission_by_token NULL"); 00349 return -1; 00350 } 00351 00352 ns_list_foreach(coap_send_msg_s, stored_msg, &handle->linked_list_resent_msgs) { 00353 uint8_t stored_token_len = (stored_msg->send_msg_ptr.packet_ptr[0] & 0x0F); 00354 if (stored_token_len == token_len) { 00355 if (memcmp(&stored_msg->send_msg_ptr.packet_ptr[4], token, stored_token_len) == 0) { 00356 00357 tr_debug("sn_coap_protocol_delete_retransmission_by_token - removed msg_id: %" PRIu16, read_packet_msg_id(stored_msg)); 00358 ns_list_remove(&handle->linked_list_resent_msgs, stored_msg); 00359 --handle->count_resent_msgs; 00360 00361 /* Free memory of stored message */ 00362 sn_coap_protocol_release_allocated_send_msg_mem(handle, stored_msg); 00363 return 0; 00364 } 00365 } 00366 } 00367 #endif 00368 return -2; 00369 } 00370 00371 static uint16_t read_packet_msg_id(const coap_send_msg_s *stored_msg) 00372 { 00373 uint16_t msg_id = (stored_msg->send_msg_ptr.packet_ptr[2] << 8); 00374 msg_id += (uint16_t)stored_msg->send_msg_ptr.packet_ptr[3]; 00375 return msg_id; 00376 } 00377 00378 int8_t prepare_blockwise_message(struct coap_s *handle, sn_coap_hdr_s *src_coap_msg_ptr) 00379 { 00380 (void) handle; 00381 (void) src_coap_msg_ptr; 00382 00383 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */ 00384 if ((src_coap_msg_ptr->payload_len > SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE) && 00385 (src_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) && 00386 (handle->sn_coap_block_data_size > 0)) { 00387 /* * * * Add Blockwise option to send CoAP message * * */ 00388 00389 /* Allocate memory for less used options */ 00390 if (sn_coap_parser_alloc_options(handle, src_coap_msg_ptr) == NULL) { 00391 tr_error("prepare_blockwise_message - failed to allocate options!"); 00392 return -2; 00393 } 00394 00395 /* Check if Request message */ 00396 if (src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED) { 00397 /* Add Blockwise option, use Block1 because Request payload */ 00398 src_coap_msg_ptr->options_list_ptr->block1 = 0x08; /* First block (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */ 00399 src_coap_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); 00400 00401 /* Add size1 parameter */ 00402 00403 src_coap_msg_ptr->options_list_ptr->use_size1 = true; 00404 src_coap_msg_ptr->options_list_ptr->use_size2 = false; 00405 src_coap_msg_ptr->options_list_ptr->size1 = src_coap_msg_ptr->payload_len; 00406 } else { /* Response message */ 00407 /* Add Blockwise option, use Block2 because Response payload */ 00408 src_coap_msg_ptr->options_list_ptr->block2 = 0x08; /* First block (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */ 00409 src_coap_msg_ptr->options_list_ptr->block2 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); 00410 00411 src_coap_msg_ptr->options_list_ptr->use_size1 = false; 00412 src_coap_msg_ptr->options_list_ptr->use_size2 = true; 00413 src_coap_msg_ptr->options_list_ptr->size2 = src_coap_msg_ptr->payload_len; 00414 } 00415 } 00416 #endif 00417 return 0; 00418 } 00419 00420 int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, 00421 uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param) 00422 { 00423 int16_t byte_count_built = 0; 00424 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */ 00425 uint16_t original_payload_len = 0; 00426 #endif 00427 /* * * * Check given pointers * * * */ 00428 if ((dst_addr_ptr == NULL) || (dst_packet_data_ptr == NULL) || (src_coap_msg_ptr == NULL) || handle == NULL) { 00429 return -2; 00430 } 00431 00432 if (dst_addr_ptr->addr_ptr == NULL) { 00433 return -2; 00434 } 00435 00436 /* Check if built Message type is else than Acknowledgement or Reset i.e. message type is Confirmable or Non-confirmable */ 00437 /* (for Acknowledgement and Reset messages is written same Message ID than was in the Request message) */ 00438 if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT && 00439 src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET && 00440 src_coap_msg_ptr->msg_id == 0) { 00441 00442 /* * * * Generate new Message ID * * * */ 00443 src_coap_msg_ptr->msg_id = get_new_message_id(); 00444 } 00445 00446 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */ 00447 /* If blockwising needed */ 00448 if ((src_coap_msg_ptr->payload_len > SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE) && 00449 (src_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) && 00450 (handle->sn_coap_block_data_size > 0)) { 00451 /* Store original Payload length */ 00452 original_payload_len = src_coap_msg_ptr->payload_len; 00453 /* Change Payload length of send message because Payload is blockwised */ 00454 src_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size; 00455 } 00456 #endif 00457 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00458 /* * * * Build Packet data from CoAP message by using CoAP Header builder * * * */ 00459 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00460 00461 byte_count_built = sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, handle->sn_coap_block_data_size); 00462 00463 if (byte_count_built < 0) { 00464 tr_error("sn_coap_protocol_build - failed to build message!"); 00465 return byte_count_built; 00466 } 00467 00468 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 00469 00470 /* Check if built Message type was confirmable, only these messages are resent */ 00471 if (src_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 00472 /* Store message to Linked list for resending purposes */ 00473 uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0); 00474 if (sn_coap_protocol_linked_list_send_msg_store(handle, dst_addr_ptr, byte_count_built, dst_packet_data_ptr, 00475 resend_time, 00476 param) == 0) { 00477 return -4; 00478 } 00479 } 00480 00481 #endif /* ENABLE_RESENDINGS */ 00482 00483 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT 00484 00485 // copy coap data buffer to duplicate list for resending purposes 00486 if (!sn_coap_protocol_update_duplicate_package_data(handle, dst_addr_ptr, src_coap_msg_ptr, byte_count_built, dst_packet_data_ptr)) { 00487 return -4; 00488 } 00489 00490 #endif 00491 00492 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */ 00493 00494 /* If blockwising needed */ 00495 if ((original_payload_len > handle->sn_coap_block_data_size) && (handle->sn_coap_block_data_size > 0)) { 00496 00497 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00498 /* * * * Manage rest blockwise messages sending by storing them to Linked list * * * */ 00499 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00500 00501 int status = store_blockwise_copy(handle, src_coap_msg_ptr, param, original_payload_len, true); 00502 if (status < 0) { 00503 return status; 00504 } 00505 00506 } else if (src_coap_msg_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE && 00507 src_coap_msg_ptr->msg_code != COAP_MSG_CODE_EMPTY) { 00508 00509 int status = store_blockwise_copy(handle, src_coap_msg_ptr, param, original_payload_len, false); 00510 if (status < 0) { 00511 return status; 00512 } 00513 } 00514 00515 #endif /* SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ 00516 00517 /* * * * Return built CoAP message Packet data length * * * */ 00518 return byte_count_built; 00519 } 00520 00521 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 00522 static int16_t store_blockwise_copy(struct coap_s *handle, const sn_coap_hdr_s *src_coap_msg_ptr, void *param, uint16_t original_payload_len, bool copy_payload) 00523 { 00524 coap_blockwise_msg_s *stored_blockwise_msg_ptr; 00525 00526 stored_blockwise_msg_ptr = sn_coap_protocol_calloc(handle, sizeof(coap_blockwise_msg_s)); 00527 if (!stored_blockwise_msg_ptr) { 00528 //block payload save failed, only first block can be build. Perhaps we should return error. 00529 tr_error("sn_coap_protocol_build - blockwise message allocation failed!"); 00530 return -2; 00531 } 00532 00533 /* Fill struct */ 00534 stored_blockwise_msg_ptr->timestamp = handle->system_time; 00535 00536 stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr); 00537 if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){ 00538 handle->sn_coap_protocol_free(stored_blockwise_msg_ptr); 00539 tr_error("sn_coap_protocol_build - block header copy failed!"); 00540 return -2; 00541 } 00542 00543 if (copy_payload) { 00544 stored_blockwise_msg_ptr->coap_msg_ptr->payload_len = original_payload_len; 00545 stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = sn_coap_protocol_malloc_copy(handle, src_coap_msg_ptr->payload_ptr, stored_blockwise_msg_ptr->coap_msg_ptr->payload_len); 00546 00547 if (!stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) { 00548 //block payload save failed, only first block can be build. Perhaps we should return error. 00549 sn_coap_parser_release_allocated_coap_msg_mem(handle, stored_blockwise_msg_ptr->coap_msg_ptr); 00550 handle->sn_coap_protocol_free(stored_blockwise_msg_ptr); 00551 tr_error("sn_coap_protocol_build - block payload allocation failed!"); 00552 return -2; 00553 } 00554 } 00555 00556 stored_blockwise_msg_ptr->param = param; 00557 stored_blockwise_msg_ptr->msg_id = stored_blockwise_msg_ptr->coap_msg_ptr->msg_id; 00558 00559 ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); 00560 00561 return 0; 00562 } 00563 #endif 00564 00565 sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *param) 00566 { 00567 sn_coap_hdr_s *returned_dst_coap_msg_ptr = NULL; 00568 coap_version_e coap_version = COAP_VERSION_UNKNOWN; 00569 00570 /* * * * Check given pointer * * * */ 00571 if (src_addr_ptr == NULL || src_addr_ptr->addr_ptr == NULL || 00572 packet_data_ptr == NULL || handle == NULL) { 00573 return NULL; 00574 } 00575 00576 /* * * * Parse Packet data to CoAP message by using CoAP Header parser * * * */ 00577 returned_dst_coap_msg_ptr = sn_coap_parser(handle, packet_data_len, packet_data_ptr, &coap_version); 00578 00579 /* Check status of returned pointer */ 00580 if (returned_dst_coap_msg_ptr == NULL) { 00581 /* Memory allocation error in parser */ 00582 tr_error("sn_coap_protocol_parse - allocation fail in parser!"); 00583 return NULL; 00584 } 00585 /* * * * Send bad request response if parsing fails * * * */ 00586 if (returned_dst_coap_msg_ptr->coap_status == COAP_STATUS_PARSER_ERROR_IN_HEADER) { 00587 sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param); 00588 sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); 00589 tr_error("sn_coap_protocol_parse - COAP_STATUS_PARSER_ERROR_IN_HEADER"); 00590 return NULL; 00591 } 00592 00593 /* * * * Check validity of parsed Header values * * * */ 00594 if (sn_coap_header_validity_check(returned_dst_coap_msg_ptr, coap_version) != 0) { 00595 /* If message code is in a reserved class (1, 6 or 7), send reset. Message code class is 3 MSB of the message code byte */ 00596 00597 const uint8_t msg_code_class = returned_dst_coap_msg_ptr->msg_code >> 5; 00598 if ((msg_code_class == 1) || // if class == 1 00599 (msg_code_class == 6) || // if class == 6 00600 (msg_code_class == 7)) { // if class == 7 00601 tr_error("sn_coap_protocol_parse - message code not valid!"); 00602 sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param); 00603 } 00604 00605 /* Release memory of CoAP message */ 00606 sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); 00607 00608 /* Return NULL because Header validity check failed */ 00609 return NULL; 00610 } 00611 00612 /* Check if we need to send reset message */ 00613 /* A recipient MUST acknowledge a Confirmable message with an Acknowledgement 00614 message or, if it lacks context to process the message properly 00615 (including the case where the message is Empty, uses a code with a 00616 reserved class (1, 6 or 7), or has a message format error), MUST 00617 reject it; rejecting a Confirmable message is effected by sending a 00618 matching Reset message and otherwise ignoring it. */ 00619 if (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 00620 /* CoAP ping */ 00621 if (returned_dst_coap_msg_ptr->msg_code == COAP_MSG_CODE_EMPTY) { 00622 sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param); 00623 00624 /* Release memory of CoAP message */ 00625 sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); 00626 00627 /* Return NULL because Header validity check failed */ 00628 return NULL; 00629 } 00630 } 00631 00632 00633 #if !SN_COAP_BLOCKWISE_ENABLED && !SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is enabled, this part of code will not be compiled */ 00634 /* If blockwising used in received message */ 00635 if (returned_dst_coap_msg_ptr->options_list_ptr != NULL && 00636 (returned_dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE || 00637 returned_dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE)) { 00638 /* Set returned status to User */ 00639 returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED; 00640 tr_error("sn_coap_protocol_parse - COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED!"); 00641 //todo: send response -> not implemented 00642 return returned_dst_coap_msg_ptr; 00643 } 00644 #endif /* !SN_COAP_BLOCKWISE_ENABLED && !SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ 00645 00646 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT/* If Message duplication is used, this part of code will not be compiled */ 00647 00648 // Manage received CoAP message duplicate detection 00649 00650 // If no message duplication detected 00651 if ((returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE || 00652 returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE || 00653 (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT && 00654 returned_dst_coap_msg_ptr->msg_code != COAP_MSG_CODE_EMPTY)) && 00655 handle->sn_coap_duplication_buffer_size != 0) { 00656 00657 coap_duplication_info_s* response = sn_coap_protocol_linked_list_duplication_info_search(handle, 00658 src_addr_ptr, 00659 returned_dst_coap_msg_ptr->msg_id); 00660 if (response == NULL) { 00661 // No Message duplication: Store received message for detecting later duplication 00662 00663 // Get count of stored duplication messages 00664 uint16_t stored_duplication_msgs_count = handle->count_duplication_msgs; 00665 00666 // Check if there is no room to store message for duplication detection purposes 00667 if (stored_duplication_msgs_count >= handle->sn_coap_duplication_buffer_size) { 00668 tr_debug("sn_coap_protocol_parse - duplicate list full, dropping oldest"); 00669 00670 // Get oldest stored duplication message 00671 coap_duplication_info_s *stored_duplication_info_ptr = ns_list_get_first(&handle->linked_list_duplication_msgs); 00672 00673 // Remove oldest stored duplication message for getting room for new duplication message 00674 sn_coap_protocol_linked_list_duplication_info_remove(handle, 00675 stored_duplication_info_ptr->address->addr_ptr, 00676 stored_duplication_info_ptr->address->port, 00677 stored_duplication_info_ptr->msg_id); 00678 } 00679 00680 // Store Duplication info to Linked list 00681 sn_coap_protocol_linked_list_duplication_info_store(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id, param); 00682 } else { // Message duplication detected 00683 // Set returned status to User 00684 returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_DUPLICATED_MSG; 00685 00686 // Send ACK response 00687 if (response && returned_dst_coap_msg_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT) { 00688 // Check that response has been created 00689 if (response->packet_ptr) { 00690 tr_debug("sn_coap_protocol_parse - send ack for duplicate message"); 00691 handle->sn_coap_tx_callback(response->packet_ptr, 00692 response->packet_len, response->address, response->param); 00693 } 00694 } 00695 00696 return returned_dst_coap_msg_ptr; 00697 } 00698 } 00699 #endif 00700 00701 /*** And here we check if message was block message ***/ 00702 /*** If so, we call own block handling function and ***/ 00703 /*** return to caller. ***/ 00704 00705 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 00706 00707 if (returned_dst_coap_msg_ptr->options_list_ptr != NULL && 00708 (returned_dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE || 00709 returned_dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE)) { 00710 00711 // the sn_coap_handle_blockwise_message() will return the given message on success or NULL on error 00712 if (sn_coap_handle_blockwise_message(handle, src_addr_ptr, returned_dst_coap_msg_ptr, param) == NULL) { 00713 00714 tr_error("sn_coap_protocol_parse - handle blockwise returns null!"); 00715 00716 // the message is freed just here, not in every other path in sn_coap_handle_blockwise_message(). 00717 sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); 00718 returned_dst_coap_msg_ptr = NULL; 00719 } 00720 00721 } else if (returned_dst_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) { 00722 00723 // If message comes without block1 information and payload length is too large to handle. 00724 // Send hint response to the server to start a blockwise transfer. 00725 00726 tr_info("sn_coap_protocol_parse - payload too large, request blockwise transfer"); 00727 00728 uint8_t *packet_data_ptr = NULL; 00729 uint16_t packet_data_size = 0; 00730 sn_coap_hdr_s *resp = sn_coap_build_response(handle, 00731 returned_dst_coap_msg_ptr, 00732 COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE); 00733 00734 if (resp == NULL) { 00735 tr_error("sn_coap_protocol_parse - payload too large, failed to build response!"); 00736 goto cleanup; 00737 } 00738 00739 if (sn_coap_parser_alloc_options(handle, resp) == NULL) { 00740 tr_error("sn_coap_protocol_parse - payload too large, failed to allocate options!"); 00741 goto cleanup; 00742 } 00743 00744 // set block1 size into response 00745 resp->options_list_ptr->block1 &= 0x08; 00746 resp->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); 00747 00748 packet_data_size = sn_coap_builder_calc_needed_packet_data_size_2(resp, handle->sn_coap_block_data_size); 00749 00750 packet_data_ptr = handle->sn_coap_protocol_malloc(packet_data_size); 00751 00752 if (packet_data_ptr == NULL) { 00753 tr_error("sn_coap_protocol_parse - payload too large, failed to allocate buffer!"); 00754 goto cleanup; 00755 } 00756 00757 if (sn_coap_builder_2(packet_data_ptr, resp, handle->sn_coap_block_data_size) < 0) { 00758 tr_error("sn_coap_protocol_parse - payload too large, builder failed!"); 00759 goto cleanup; 00760 } 00761 00762 sn_coap_parser_release_allocated_coap_msg_mem(handle, resp); 00763 00764 handle->sn_coap_tx_callback(packet_data_ptr, packet_data_size, src_addr_ptr, param); 00765 00766 handle->sn_coap_protocol_free(packet_data_ptr); 00767 00768 returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING; 00769 00770 return returned_dst_coap_msg_ptr; 00771 00772 cleanup: 00773 sn_coap_parser_release_allocated_coap_msg_mem(handle, resp); 00774 sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); 00775 handle->sn_coap_protocol_free(packet_data_ptr); 00776 return NULL; 00777 00778 } else if (returned_dst_coap_msg_ptr->msg_code != COAP_MSG_CODE_EMPTY) { 00779 // Do not clean stored blockwise message when empty ack is received. 00780 // Stored message is mandatory when building a next (GET) blockwise message. 00781 // This will happen when non piggybacked response mode is selected. 00782 /* Get ... */ 00783 coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = search_sent_blockwise_message(handle, returned_dst_coap_msg_ptr->msg_id); 00784 00785 /* Remove from the list if not an notification message. 00786 * Initial notification message is needed for sending rest of the blocks (GET request). 00787 */ 00788 bool remove_from_the_list = false; 00789 if (stored_blockwise_msg_temp_ptr) { 00790 if (stored_blockwise_msg_temp_ptr->coap_msg_ptr && 00791 stored_blockwise_msg_temp_ptr->coap_msg_ptr->options_list_ptr && 00792 stored_blockwise_msg_temp_ptr->coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) { 00793 remove_from_the_list = false; 00794 } else { 00795 remove_from_the_list = true; 00796 } 00797 } 00798 if (remove_from_the_list) { 00799 00800 sn_coap_protocol_linked_list_blockwise_msg_remove(handle, stored_blockwise_msg_temp_ptr); 00801 } 00802 } 00803 00804 if (!returned_dst_coap_msg_ptr) { 00805 tr_error("sn_coap_protocol_parse - returned_dst_coap_msg_ptr null!"); 00806 return NULL; 00807 } 00808 00809 #endif 00810 00811 00812 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 00813 00814 /* Check if received Message type was acknowledgement */ 00815 if ((returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT) || (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_RESET)) { 00816 /* * * * Manage CoAP message resending by removing active resending message from Linked list * * */ 00817 00818 /* Get node count i.e. count of active resending messages */ 00819 uint16_t stored_resending_msgs_count = handle->count_resent_msgs; 00820 00821 /* Check if there is ongoing active message resendings */ 00822 if (stored_resending_msgs_count > 0) { 00823 00824 /* Remove resending message from active message resending Linked list, if any exists */ 00825 sn_coap_protocol_linked_list_send_msg_remove(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id); 00826 } 00827 } 00828 #endif /* ENABLE_RESENDINGS */ 00829 00830 /* * * * Return parsed CoAP message * * * */ 00831 return returned_dst_coap_msg_ptr; 00832 } 00833 00834 00835 int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time) 00836 { 00837 if( !handle ){ 00838 return -1; 00839 } 00840 00841 /* * * * Store current System time * * * */ 00842 handle->system_time = current_time; 00843 00844 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 00845 /* * * * Handle block transfer timed outs * * * */ 00846 sn_coap_protocol_handle_blockwise_timout(handle); 00847 #endif 00848 00849 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT 00850 /* * * * Remove old duplication messages * * * */ 00851 sn_coap_protocol_linked_list_duplication_info_remove_old_ones(handle); 00852 #endif 00853 00854 #if ENABLE_RESENDINGS 00855 /* Check if there is ongoing active message sendings */ 00856 /* foreach_safe isn't sufficient because callback routine could cancel messages. */ 00857 rescan: 00858 ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { 00859 // First check that msg belongs to handle 00860 /* Check if it is time to send this message */ 00861 if (current_time >= stored_msg_ptr->resending_time) { 00862 /* * * Increase Resending counter * * */ 00863 stored_msg_ptr->resending_counter++; 00864 00865 /* Check if all re-sendings have been done */ 00866 if (stored_msg_ptr->resending_counter > handle->sn_coap_resending_count) { 00867 coap_version_e coap_version = COAP_VERSION_UNKNOWN; 00868 00869 00870 /* Remove message from Linked list */ 00871 ns_list_remove(&handle->linked_list_resent_msgs, stored_msg_ptr); 00872 --handle->count_resent_msgs; 00873 00874 /* If RX callback have been defined.. */ 00875 if (handle->sn_coap_rx_callback != 0) { 00876 sn_coap_hdr_s *tmp_coap_hdr_ptr; 00877 /* Parse CoAP message, set status and call RX callback */ 00878 tmp_coap_hdr_ptr = sn_coap_parser(handle, stored_msg_ptr->send_msg_ptr.packet_len, stored_msg_ptr->send_msg_ptr.packet_ptr, &coap_version); 00879 00880 if (tmp_coap_hdr_ptr != 0) { 00881 tmp_coap_hdr_ptr->coap_status = COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED; 00882 handle->sn_coap_rx_callback(tmp_coap_hdr_ptr, &stored_msg_ptr->send_msg_ptr.dst_addr_ptr, stored_msg_ptr->param); 00883 00884 sn_coap_parser_release_allocated_coap_msg_mem(handle, tmp_coap_hdr_ptr); 00885 } 00886 } 00887 00888 /* Free memory of stored message */ 00889 sn_coap_protocol_release_allocated_send_msg_mem(handle, stored_msg_ptr); 00890 } else { 00891 /* Send message */ 00892 handle->sn_coap_tx_callback(stored_msg_ptr->send_msg_ptr.packet_ptr, 00893 stored_msg_ptr->send_msg_ptr.packet_len, &stored_msg_ptr->send_msg_ptr.dst_addr_ptr, stored_msg_ptr->param); 00894 00895 /* * * Count new Resending time * * */ 00896 stored_msg_ptr->resending_time = sn_coap_calculate_new_resend_time(current_time, 00897 handle->sn_coap_resending_intervall, 00898 stored_msg_ptr->resending_counter); 00899 } 00900 /* Callback routine could have wiped the list (eg as a response to sending failed) */ 00901 /* Be super cautious and rescan from the start */ 00902 goto rescan; 00903 } 00904 } 00905 00906 #endif /* ENABLE_RESENDINGS */ 00907 00908 return 0; 00909 } 00910 00911 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 00912 00913 /**************************************************************************//** 00914 * \fn static uint8_t sn_coap_protocol_linked_list_send_msg_store(sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time) 00915 * 00916 * \brief Stores message to Linked list for sending purposes. 00917 00918 * \param *dst_addr_ptr is pointer to destination address where CoAP message will be sent 00919 * 00920 * \param send_packet_data_len is length of Packet data to be stored 00921 * 00922 * \param *send_packet_data_ptr is Packet data to be stored 00923 * 00924 * \param sending_time is stored sending time 00925 * 00926 * \return 0 Allocation or buffer limit reached 00927 * 00928 * \return 1 Msg stored properly 00929 *****************************************************************************/ 00930 00931 static uint8_t sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, 00932 uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param) 00933 { 00934 00935 coap_send_msg_s *stored_msg_ptr; 00936 00937 /* If both queue parameters are "0" or resending count is "0", then re-sending is disabled */ 00938 if (((handle->sn_coap_resending_queue_msgs == 0) && (handle->sn_coap_resending_queue_bytes == 0)) || (handle->sn_coap_resending_count == 0)) { 00939 return 1; 00940 } 00941 00942 if (handle->sn_coap_resending_queue_msgs > 0) { 00943 if (handle->count_resent_msgs >= handle->sn_coap_resending_queue_msgs) { 00944 tr_error("sn_coap_protocol_linked_list_send_msg_store - resend queue full!"); 00945 return 0; 00946 } 00947 } 00948 00949 /* Count resending queue size, if buffer size is defined */ 00950 if (handle->sn_coap_resending_queue_bytes > 0) { 00951 if ((sn_coap_count_linked_list_size(&handle->linked_list_resent_msgs) + send_packet_data_len) > handle->sn_coap_resending_queue_bytes) { 00952 tr_error("sn_coap_protocol_linked_list_send_msg_store - resend buffer size reached!"); 00953 return 0; 00954 } 00955 } 00956 00957 /* Allocating memory for stored message */ 00958 stored_msg_ptr = sn_coap_protocol_allocate_mem_for_msg(handle, dst_addr_ptr, send_packet_data_len); 00959 00960 if (stored_msg_ptr == 0) { 00961 tr_error("sn_coap_protocol_linked_list_send_msg_store - failed to allocate message!"); 00962 return 0; 00963 } 00964 00965 /* Filling of coap_send_msg_s with initialization values */ 00966 stored_msg_ptr->resending_counter = 0; 00967 stored_msg_ptr->resending_time = sending_time; 00968 00969 /* Filling of sn_nsdl_transmit_s */ 00970 stored_msg_ptr->send_msg_ptr.protocol = SN_NSDL_PROTOCOL_COAP; 00971 stored_msg_ptr->send_msg_ptr.packet_len = send_packet_data_len; 00972 memcpy(stored_msg_ptr->send_msg_ptr.packet_ptr, send_packet_data_ptr, send_packet_data_len); 00973 00974 /* Filling of sn_nsdl_addr_s */ 00975 stored_msg_ptr->send_msg_ptr.dst_addr_ptr.type = dst_addr_ptr->type; 00976 stored_msg_ptr->send_msg_ptr.dst_addr_ptr.addr_len = dst_addr_ptr->addr_len; 00977 memcpy(stored_msg_ptr->send_msg_ptr.dst_addr_ptr.addr_ptr, dst_addr_ptr->addr_ptr, dst_addr_ptr->addr_len); 00978 stored_msg_ptr->send_msg_ptr.dst_addr_ptr.port = dst_addr_ptr->port; 00979 00980 stored_msg_ptr->param = param; 00981 00982 /* Storing Resending message to Linked list */ 00983 ns_list_add_to_end(&handle->linked_list_resent_msgs, stored_msg_ptr); 00984 ++handle->count_resent_msgs; 00985 return 1; 00986 } 00987 00988 00989 /**************************************************************************//** 00990 * \fn static void sn_coap_protocol_linked_list_send_msg_remove(sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) 00991 * 00992 * \brief Removes stored resending message from Linked list 00993 * 00994 * \param *src_addr_ptr is searching key for searched message 00995 * \param msg_id is searching key for removed message 00996 *****************************************************************************/ 00997 00998 static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) 00999 { 01000 /* Loop all stored resending messages in Linked list */ 01001 ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { 01002 /* Get message ID from stored resending message */ 01003 uint16_t temp_msg_id = read_packet_msg_id(stored_msg_ptr); 01004 01005 /* If message's Message ID is same than is searched */ 01006 if (temp_msg_id == msg_id) { 01007 /* If message's Source address and port is same than is searched */ 01008 if (compare_address_and_port(src_addr_ptr, &stored_msg_ptr->send_msg_ptr.dst_addr_ptr)) { 01009 /* * * Message found * * */ 01010 01011 /* Remove message from Linked list */ 01012 ns_list_remove(&handle->linked_list_resent_msgs, stored_msg_ptr); 01013 --handle->count_resent_msgs; 01014 01015 /* Free memory of stored message */ 01016 sn_coap_protocol_release_allocated_send_msg_mem(handle, stored_msg_ptr); 01017 01018 return; 01019 } 01020 } 01021 } 01022 } 01023 01024 uint32_t sn_coap_calculate_new_resend_time(const uint32_t current_time, const uint8_t interval, const uint8_t counter) 01025 { 01026 uint32_t resend_time = interval << counter; 01027 uint16_t random_factor = randLIB_get_random_in_range(100, RESPONSE_RANDOM_FACTOR * 100); 01028 return current_time + ((resend_time * random_factor) / 100); 01029 } 01030 01031 #endif /* ENABLE_RESENDINGS */ 01032 01033 void sn_coap_protocol_send_rst(struct coap_s *handle, uint16_t msg_id, sn_nsdl_addr_s *addr_ptr, void *param) 01034 { 01035 uint8_t packet_ptr[4]; 01036 01037 /* Add CoAP version and message type */ 01038 packet_ptr[0] = COAP_VERSION_1; 01039 packet_ptr[0] |= COAP_MSG_TYPE_RESET; 01040 01041 /* Add message code */ 01042 packet_ptr[1] = COAP_MSG_CODE_EMPTY; 01043 01044 /* Add message ID */ 01045 packet_ptr[2] = msg_id >> 8; 01046 packet_ptr[3] = (uint8_t)msg_id; 01047 01048 /* Send RST */ 01049 handle->sn_coap_tx_callback(packet_ptr, 4, addr_ptr, param); 01050 01051 } 01052 01053 uint16_t sn_coap_protocol_get_configured_blockwise_size(struct coap_s *handle) 01054 { 01055 return handle->sn_coap_block_data_size; 01056 } 01057 01058 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ 01059 01060 /**************************************************************************//** 01061 * \fn static void sn_coap_protocol_linked_list_duplication_info_store(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id) 01062 * 01063 * \brief Stores Duplication info to Linked list 01064 * 01065 * \param msg_id is Message ID to be stored 01066 * \param *addr_ptr is pointer to Address information to be stored 01067 *****************************************************************************/ 01068 01069 static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, 01070 uint16_t msg_id, void *param) 01071 { 01072 coap_duplication_info_s *stored_duplication_info_ptr = NULL; 01073 01074 /* * * * Allocating memory for stored Duplication info * * * */ 01075 01076 /* Allocate memory for stored Duplication info's structure */ 01077 stored_duplication_info_ptr = sn_coap_protocol_calloc(handle, sizeof(coap_duplication_info_s)); 01078 01079 if (stored_duplication_info_ptr == NULL) { 01080 tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate duplication info!"); 01081 return; 01082 } 01083 01084 /* Allocate memory for stored Duplication info's address */ 01085 stored_duplication_info_ptr->address = sn_coap_protocol_calloc(handle, sizeof(sn_nsdl_addr_s)); 01086 if (stored_duplication_info_ptr->address == NULL) { 01087 tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate address!"); 01088 sn_coap_protocol_duplication_info_free(handle, stored_duplication_info_ptr); 01089 return; 01090 } 01091 01092 stored_duplication_info_ptr->address->addr_ptr = handle->sn_coap_protocol_malloc(addr_ptr->addr_len); 01093 01094 if (stored_duplication_info_ptr->address->addr_ptr == NULL) { 01095 tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate address pointer!"); 01096 sn_coap_protocol_duplication_info_free(handle, stored_duplication_info_ptr); 01097 return; 01098 } 01099 01100 /* * * * Filling fields of stored Duplication info * * * */ 01101 stored_duplication_info_ptr->timestamp = handle->system_time; 01102 stored_duplication_info_ptr->address->addr_len = addr_ptr->addr_len; 01103 memcpy(stored_duplication_info_ptr->address->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len); 01104 stored_duplication_info_ptr->address->port = addr_ptr->port; 01105 stored_duplication_info_ptr->msg_id = msg_id; 01106 01107 stored_duplication_info_ptr->param = param; 01108 /* * * * Storing Duplication info to Linked list * * * */ 01109 01110 ns_list_add_to_end(&handle->linked_list_duplication_msgs, stored_duplication_info_ptr); 01111 ++handle->count_duplication_msgs; 01112 } 01113 01114 /**************************************************************************//** 01115 * \fn static coap_duplication_info_s *sn_coap_protocol_linked_list_duplication_info_search(const struct coap_s *handle, const sn_nsdl_addr_s *scr_addr_ptr, const uint16_t msg_id) 01116 * 01117 * \brief Searches stored message from Linked list (Address and Message ID as key) 01118 * 01119 * \param *addr_ptr is pointer to Address key to be searched 01120 * \param msg_id is Message ID key to be searched 01121 * 01122 * \return Return value is 0 when message found and -1 if not found 01123 *****************************************************************************/ 01124 01125 static coap_duplication_info_s* sn_coap_protocol_linked_list_duplication_info_search(const struct coap_s *handle, 01126 const sn_nsdl_addr_s *addr_ptr, const uint16_t msg_id) 01127 { 01128 /* Loop all nodes in Linked list for searching Message ID */ 01129 ns_list_foreach(coap_duplication_info_s, stored_duplication_info_ptr, &handle->linked_list_duplication_msgs) { 01130 /* If message's Message ID is same than is searched */ 01131 if (stored_duplication_info_ptr->msg_id == msg_id) { 01132 /* If message's Source address & port is same than is searched */ 01133 if (compare_address_and_port(addr_ptr, stored_duplication_info_ptr->address)) { 01134 /* * * Correct Duplication info found * * * */ 01135 return stored_duplication_info_ptr; 01136 } 01137 } 01138 } 01139 return NULL; 01140 } 01141 01142 01143 01144 /**************************************************************************//** 01145 * \fn static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle) 01146 * 01147 * \brief Removes old stored Duplication detection infos from Linked list 01148 *****************************************************************************/ 01149 01150 static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle) 01151 { 01152 01153 ns_list_foreach_safe(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) { 01154 if ((handle->system_time - removed_duplication_info_ptr->timestamp) > SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED) { 01155 /* * * * Old Duplication info found, remove it from Linked list * * * */ 01156 ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr); 01157 --handle->count_duplication_msgs; 01158 01159 /* Free memory of stored Duplication info */ 01160 sn_coap_protocol_duplication_info_free(handle, removed_duplication_info_ptr); 01161 } 01162 } 01163 } 01164 01165 #endif /* SN_COAP_DUPLICATION_MAX_MSGS_COUNT */ 01166 01167 void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, const uint8_t *scr_addr_ptr, const uint16_t port, const uint16_t msg_id) 01168 { 01169 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT 01170 /* Loop all stored duplication messages in Linked list */ 01171 ns_list_foreach(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) { 01172 /* If message's Address is same than is searched */ 01173 if (0 == memcmp(scr_addr_ptr, 01174 removed_duplication_info_ptr->address->addr_ptr, 01175 removed_duplication_info_ptr->address->addr_len)) { 01176 /* If message's Address prt is same than is searched */ 01177 if (removed_duplication_info_ptr->address->port == port) { 01178 /* If Message ID is same than is searched */ 01179 if (removed_duplication_info_ptr->msg_id == msg_id) { 01180 /* * * * Correct Duplication info found, remove it from Linked list * * * */ 01181 tr_info("sn_coap_protocol_linked_list_duplication_info_remove - message id %d removed", msg_id); 01182 ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr); 01183 --handle->count_duplication_msgs; 01184 01185 /* Free memory of stored Duplication info */ 01186 sn_coap_protocol_duplication_info_free(handle, removed_duplication_info_ptr); 01187 return; 01188 } 01189 } 01190 } 01191 } 01192 #else 01193 (void)handle; 01194 (void)scr_addr_ptr; 01195 (void)port; 01196 (void)msg_id; 01197 #endif //SN_COAP_DUPLICATION_MAX_MSGS_COUNT 01198 } 01199 01200 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT 01201 static void sn_coap_protocol_duplication_info_free(struct coap_s *handle, coap_duplication_info_s *duplication_info_ptr) 01202 { 01203 if (duplication_info_ptr) { 01204 if (duplication_info_ptr->address) { 01205 handle->sn_coap_protocol_free(duplication_info_ptr->address->addr_ptr); 01206 handle->sn_coap_protocol_free(duplication_info_ptr->address); 01207 } 01208 handle->sn_coap_protocol_free(duplication_info_ptr->packet_ptr); 01209 handle->sn_coap_protocol_free(duplication_info_ptr); 01210 } 01211 } 01212 #endif // SN_COAP_DUPLICATION_MAX_MSGS_COUNT 01213 01214 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 01215 /**************************************************************************//** 01216 * \fn static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr) 01217 * 01218 * \brief Removes stored blockwise message from Linked list 01219 * 01220 * \param removed_msg_ptr is message to be removed 01221 *****************************************************************************/ 01222 01223 static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr) 01224 { 01225 ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_msg_ptr); 01226 01227 if (removed_msg_ptr->coap_msg_ptr) { 01228 handle->sn_coap_protocol_free(removed_msg_ptr->coap_msg_ptr->payload_ptr); 01229 01230 sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_msg_ptr->coap_msg_ptr); 01231 } 01232 01233 handle->sn_coap_protocol_free(removed_msg_ptr); 01234 } 01235 01236 /**************************************************************************//** 01237 * \fn static void sn_coap_protocol_linked_list_blockwise_payload_store(sn_nsdl_addr_s *addr_ptr, uint16_t payload_len, uint8_t *payload_ptr) 01238 * 01239 * \brief Stores blockwise payload to Linked list 01240 * 01241 * \param *addr_ptr is pointer to Address information to be stored 01242 * \param payload_len is length of incoming payload 01243 * \param *payload_ptr is pointer to stored incoming payload 01244 * \param *token_ptr is pointer to stored token 01245 * \param token_len is length of the stored token 01246 * \param block_number Block number to be stored 01247 * \param size1 Size of the whole incoming message 01248 *****************************************************************************/ 01249 01250 static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, 01251 uint16_t payload_len, 01252 uint8_t *payload_ptr, 01253 uint8_t *token_ptr, 01254 uint8_t token_len, 01255 uint32_t block_number, 01256 uint32_t size1) 01257 { 01258 if (!addr_ptr || !payload_len || !payload_ptr) { 01259 return; 01260 } 01261 01262 // Do not add duplicates to list, this could happen if server needs to retransmit block message again 01263 if (sn_coap_protocol_linked_list_blockwise_payload_search_compare_block_number(handle, 01264 addr_ptr, 01265 token_ptr, 01266 token_len, 01267 block_number)) { 01268 return; 01269 } 01270 01271 coap_blockwise_payload_s *stored_blockwise_payload_ptr = sn_coap_protocol_linked_list_blockwise_search(handle, addr_ptr, token_ptr, token_len); 01272 01273 if (stored_blockwise_payload_ptr && stored_blockwise_payload_ptr->use_size1) { 01274 memcpy(stored_blockwise_payload_ptr->payload_ptr + (block_number * handle->sn_coap_block_data_size), payload_ptr, payload_len); 01275 } else if (stored_blockwise_payload_ptr) { 01276 uint16_t new_len = stored_blockwise_payload_ptr->payload_len + payload_len; 01277 tr_debug("sn_coap_protocol_linked_list_blockwise_payload_store - reallocate from %d to %d", stored_blockwise_payload_ptr->payload_len, new_len); 01278 01279 uint8_t *temp_ptr = handle->sn_coap_protocol_malloc(stored_blockwise_payload_ptr->payload_len); 01280 if (temp_ptr == NULL) { 01281 tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate temp buffer!"); 01282 sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_blockwise_payload_ptr); 01283 return; 01284 } 01285 01286 memcpy(temp_ptr, stored_blockwise_payload_ptr->payload_ptr, stored_blockwise_payload_ptr->payload_len); 01287 01288 handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->payload_ptr); 01289 stored_blockwise_payload_ptr->payload_ptr = handle->sn_coap_protocol_malloc(new_len); 01290 01291 if (stored_blockwise_payload_ptr->payload_ptr == NULL) { 01292 tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to reallocate payload!"); 01293 handle->sn_coap_protocol_free(temp_ptr); 01294 sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_blockwise_payload_ptr); 01295 return; 01296 } 01297 01298 memcpy(stored_blockwise_payload_ptr->payload_ptr, temp_ptr, stored_blockwise_payload_ptr->payload_len); 01299 memcpy(stored_blockwise_payload_ptr->payload_ptr + stored_blockwise_payload_ptr->payload_len, payload_ptr, payload_len); 01300 stored_blockwise_payload_ptr->payload_len = new_len; 01301 handle->sn_coap_protocol_free(temp_ptr); 01302 01303 } else { 01304 stored_blockwise_payload_ptr = NULL; 01305 stored_blockwise_payload_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_payload_s)); 01306 01307 if (stored_blockwise_payload_ptr == NULL) { 01308 tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate blockwise!"); 01309 return; 01310 } 01311 01312 // If size1 option present then we can allocate the whole payload before hand. 01313 stored_blockwise_payload_ptr->use_size1 = size1 ? 1 : 0; 01314 01315 /* Allocate memory for stored Payload's data */ 01316 if (stored_blockwise_payload_ptr->use_size1) { 01317 stored_blockwise_payload_ptr->payload_ptr = handle->sn_coap_protocol_malloc(size1); 01318 if (stored_blockwise_payload_ptr->payload_ptr) { 01319 memcpy(stored_blockwise_payload_ptr->payload_ptr, payload_ptr, payload_len); 01320 stored_blockwise_payload_ptr->payload_len = size1; 01321 } 01322 } else { 01323 stored_blockwise_payload_ptr->payload_ptr = sn_coap_protocol_malloc_copy(handle, payload_ptr, payload_len); 01324 stored_blockwise_payload_ptr->payload_len = payload_len; 01325 } 01326 01327 if (stored_blockwise_payload_ptr->payload_ptr == NULL) { 01328 tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate payload!"); 01329 handle->sn_coap_protocol_free(stored_blockwise_payload_ptr); 01330 return; 01331 } 01332 01333 /* Allocate memory for stored Payload's address */ 01334 stored_blockwise_payload_ptr->addr_ptr = sn_coap_protocol_malloc_copy(handle, addr_ptr->addr_ptr, addr_ptr->addr_len); 01335 01336 if (stored_blockwise_payload_ptr->addr_ptr == NULL) { 01337 tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate address pointer!"); 01338 handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->payload_ptr); 01339 handle->sn_coap_protocol_free(stored_blockwise_payload_ptr); 01340 return; 01341 } 01342 01343 /* Allocate & copy token number */ 01344 if (token_ptr && token_len) { 01345 stored_blockwise_payload_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, token_ptr, token_len); 01346 01347 if (!stored_blockwise_payload_ptr->token_ptr) { 01348 tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate token pointer!"); 01349 handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->addr_ptr); 01350 handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->payload_ptr); 01351 handle->sn_coap_protocol_free(stored_blockwise_payload_ptr); 01352 return; 01353 } 01354 01355 stored_blockwise_payload_ptr->token_len = token_len; 01356 } else { 01357 stored_blockwise_payload_ptr->token_ptr = NULL; 01358 stored_blockwise_payload_ptr->token_len = 0; 01359 } 01360 01361 /* * * * Filling fields of stored Payload * * * */ 01362 stored_blockwise_payload_ptr->port = addr_ptr->port; 01363 01364 /* * * * Storing Payload to Linked list * * * */ 01365 ns_list_add_to_end(&handle->linked_list_blockwise_received_payloads, stored_blockwise_payload_ptr); 01366 } 01367 01368 stored_blockwise_payload_ptr->block_number = block_number; 01369 stored_blockwise_payload_ptr->timestamp = handle->system_time; 01370 } 01371 01372 /**************************************************************************//** 01373 * \fn static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length) 01374 * 01375 * \brief Searches stored blockwise payload from Linked list (Address as key) 01376 * 01377 * \param *addr_ptr is pointer to Address key to be searched 01378 * \param *payload_length is pointer to returned Payload length 01379 * 01380 * \return Return value is pointer to found stored blockwise payload in Linked 01381 * list or NULL if payload not found 01382 *****************************************************************************/ 01383 01384 static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length, const uint8_t *token_ptr, uint8_t token_len) 01385 { 01386 /* Loop all stored blockwise payloads in Linked list */ 01387 ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { 01388 /* If payload's Source address and port is same than is searched */ 01389 if ((0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (stored_payload_info_ptr->port == src_addr_ptr->port)) { 01390 /* Check token */ 01391 if (token_ptr) { 01392 if (!stored_payload_info_ptr->token_ptr || (token_len != stored_payload_info_ptr->token_len) || (memcmp(stored_payload_info_ptr->token_ptr, token_ptr, token_len))) { 01393 continue; 01394 } 01395 } else if (stored_payload_info_ptr->token_ptr) { 01396 continue; 01397 } 01398 /* * * Correct Payload found * * * */ 01399 *payload_length = stored_payload_info_ptr->payload_len; 01400 return stored_payload_info_ptr->payload_ptr; 01401 } 01402 } 01403 01404 return NULL; 01405 } 01406 01407 /**************************************************************************//** 01408 * \fn static uint8_t *sn_coap_protocol_linked_list_blockwise_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length) 01409 * 01410 * \brief Searches stored blockwise message from Linked list (Address as key) 01411 * 01412 * \param *addr_ptr is pointer to Address key to be searched 01413 * \param *payload_length is pointer to returned Payload length 01414 * 01415 * \return Return value is pointer to found stored blockwise message in Linked 01416 * list or NULL if message not found 01417 *****************************************************************************/ 01418 static coap_blockwise_payload_s *sn_coap_protocol_linked_list_blockwise_search(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len) 01419 { 01420 /* Loop all stored blockwise payloads in Linked list */ 01421 ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { 01422 /* If payload's Source address and port is same than is searched */ 01423 if ((0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (stored_payload_info_ptr->port == src_addr_ptr->port)) { 01424 /* Check token */ 01425 if (token_ptr) { 01426 if (!stored_payload_info_ptr->token_ptr || (token_len != stored_payload_info_ptr->token_len) || (memcmp(stored_payload_info_ptr->token_ptr, token_ptr, token_len))) { 01427 continue; 01428 } 01429 } else if (stored_payload_info_ptr->token_ptr) { 01430 continue; 01431 } 01432 return stored_payload_info_ptr; 01433 } 01434 } 01435 01436 return NULL; 01437 } 01438 01439 static bool sn_coap_protocol_linked_list_blockwise_payload_search_compare_block_number(struct coap_s *handle, 01440 const sn_nsdl_addr_s *src_addr_ptr, 01441 const uint8_t *token_ptr, 01442 uint8_t token_len, 01443 uint32_t block_number) 01444 { 01445 /* Loop all stored blockwise payloads in Linked list */ 01446 ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { 01447 /* If payload's Source address and port is same than is searched */ 01448 if ((0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (stored_payload_info_ptr->port == src_addr_ptr->port)) { 01449 /* Check token number */ 01450 if (token_ptr) { 01451 if (!stored_payload_info_ptr->token_ptr || (token_len != stored_payload_info_ptr->token_len) || (memcmp(stored_payload_info_ptr->token_ptr, token_ptr, token_len))) { 01452 continue; 01453 } 01454 } else if (stored_payload_info_ptr->token_ptr) { 01455 continue; 01456 } 01457 // Check that stored block number matches to given one 01458 if (block_number == stored_payload_info_ptr->block_number) { 01459 return true; 01460 } 01461 } 01462 } 01463 01464 return false; 01465 } 01466 01467 /**************************************************************************//** 01468 * \fn static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, 01469 * coap_blockwise_msg_s *removed_msg_ptr) 01470 * 01471 * \brief Removes stored blockwise payload from Linked list 01472 * 01473 * \param removed_payload_ptr is payload to be removed 01474 *****************************************************************************/ 01475 01476 static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, 01477 coap_blockwise_payload_s *removed_payload_ptr) 01478 { 01479 ns_list_remove(&handle->linked_list_blockwise_received_payloads, removed_payload_ptr); 01480 /* Free memory of stored payload */ 01481 handle->sn_coap_protocol_free(removed_payload_ptr->addr_ptr); 01482 handle->sn_coap_protocol_free(removed_payload_ptr->payload_ptr); 01483 handle->sn_coap_protocol_free(removed_payload_ptr->token_ptr); 01484 01485 handle->sn_coap_protocol_free(removed_payload_ptr); 01486 } 01487 01488 /**************************************************************************//** 01489 * \fn static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(sn_nsdl_addr_s *src_addr_ptr) 01490 * 01491 * \brief Counts length of Payloads in Linked list (Address as key) 01492 * 01493 * \param *addr_ptr is pointer to Address key 01494 * 01495 * \return Return value is length of Payloads as bytes 01496 *****************************************************************************/ 01497 01498 static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len) 01499 { 01500 uint32_t ret_whole_payload_len = 0; 01501 /* Loop all stored blockwise payloads in Linked list */ 01502 ns_list_foreach(coap_blockwise_payload_s, searched_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { 01503 /* If payload's Source address and port is same than is searched */ 01504 if ((0 == memcmp(src_addr_ptr->addr_ptr, searched_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (searched_payload_info_ptr->port == src_addr_ptr->port)) { 01505 /* Check token */ 01506 if (token_ptr) { 01507 if(!searched_payload_info_ptr->token_ptr || (token_len != searched_payload_info_ptr->token_len) || (memcmp(searched_payload_info_ptr->token_ptr, token_ptr, token_len))) { 01508 continue; 01509 } 01510 } else if (searched_payload_info_ptr->token_ptr) { 01511 continue; 01512 } 01513 /* * * Correct Payload found * * * */ 01514 ret_whole_payload_len += searched_payload_info_ptr->payload_len; 01515 } 01516 } 01517 01518 return ret_whole_payload_len; 01519 } 01520 01521 /**************************************************************************//** 01522 * \fn static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) 01523 * 01524 * \brief Check incoming and outgoing blockwise messages for time out. 01525 * Remove timed out messages from lists. Notify application if 01526 * outgoing message times out. 01527 *****************************************************************************/ 01528 01529 static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) 01530 { 01531 /* Loop all outgoing blockwise messages */ 01532 /* foreach_safe isn't sufficient because callback routine could remove messages. */ 01533 rescan: 01534 ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) { 01535 if ((handle->system_time - removed_blocwise_msg_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { 01536 bool callback_called = false; 01537 // Item must be removed from the list before calling the rx_callback function. 01538 // Callback could actually clear the list and free the item and cause a use after free when callback returns. 01539 ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_blocwise_msg_ptr); 01540 01541 /* * * * This messages has timed out, remove it from Linked list * * * */ 01542 if( removed_blocwise_msg_ptr->coap_msg_ptr ){ 01543 if (handle->sn_coap_rx_callback) { 01544 /* Notify the application about the time out */ 01545 removed_blocwise_msg_ptr->coap_msg_ptr->coap_status = COAP_STATUS_BUILDER_BLOCK_SENDING_FAILED; 01546 removed_blocwise_msg_ptr->coap_msg_ptr->msg_id = removed_blocwise_msg_ptr->msg_id; 01547 sn_coap_protocol_delete_retransmission(handle, removed_blocwise_msg_ptr->msg_id); 01548 handle->sn_coap_rx_callback(removed_blocwise_msg_ptr->coap_msg_ptr, NULL, removed_blocwise_msg_ptr->param); 01549 callback_called = true; 01550 } 01551 handle->sn_coap_protocol_free(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr); 01552 sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_blocwise_msg_ptr->coap_msg_ptr); 01553 } 01554 01555 handle->sn_coap_protocol_free(removed_blocwise_msg_ptr); 01556 01557 if (callback_called) { 01558 /* Callback routine could have wiped the list already */ 01559 /* Be super cautious and rescan from the start */ 01560 goto rescan; 01561 } 01562 } 01563 } 01564 01565 01566 /* Loop all incoming Blockwise messages */ 01567 ns_list_foreach_safe(coap_blockwise_payload_s, removed_blocwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) { 01568 if ((handle->system_time - removed_blocwise_payload_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { 01569 /* * * * This messages has timed out, remove it from Linked list * * * */ 01570 sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_blocwise_payload_ptr); 01571 } 01572 } 01573 } 01574 01575 #endif /* SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ 01576 01577 01578 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ 01579 /***************************************************************************//** 01580 * \fn int8_t sn_coap_protocol_allocate_mem_for_msg(sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len, coap_send_msg_s *msg_ptr) 01581 * 01582 * \brief Allocates memory for given message (send or blockwise message) 01583 * 01584 * \param *dst_addr_ptr is pointer to destination address where message will be sent 01585 * \param packet_data_len is length of allocated Packet data 01586 * \param uri_path_len is length of messages path url 01587 * 01588 * \return pointer to allocated struct 01589 *****************************************************************************/ 01590 01591 coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len) 01592 { 01593 01594 coap_send_msg_s *msg_ptr = sn_coap_protocol_calloc(handle, sizeof(coap_send_msg_s)); 01595 01596 if (msg_ptr == NULL) { 01597 return 0; 01598 } 01599 01600 msg_ptr->send_msg_ptr.packet_ptr = handle->sn_coap_protocol_malloc(packet_data_len); 01601 01602 msg_ptr->send_msg_ptr.dst_addr_ptr.addr_ptr = sn_coap_protocol_calloc(handle, dst_addr_ptr->addr_len); 01603 01604 if ((msg_ptr->send_msg_ptr.dst_addr_ptr.addr_ptr == NULL) || 01605 (msg_ptr->send_msg_ptr.packet_ptr == NULL)) { 01606 01607 sn_coap_protocol_release_allocated_send_msg_mem(handle, msg_ptr); 01608 return 0; 01609 } 01610 01611 return msg_ptr; 01612 } 01613 01614 01615 /**************************************************************************//** 01616 * \fn static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr) 01617 * 01618 * \brief Releases memory of given Sending message (coap_send_msg_s) 01619 * 01620 * \param *freed_send_msg_ptr is pointer to released Sending message 01621 *****************************************************************************/ 01622 01623 static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr) 01624 { 01625 if (freed_send_msg_ptr != NULL) { 01626 01627 handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr.dst_addr_ptr.addr_ptr); 01628 01629 handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr.packet_ptr); 01630 01631 handle->sn_coap_protocol_free(freed_send_msg_ptr); 01632 } 01633 } 01634 01635 /**************************************************************************//** 01636 * \fn static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr) 01637 * 01638 * \brief Counts total message size of all messages in linked list 01639 * 01640 * \param const coap_send_msg_list_t *linked_list_ptr pointer to linked list 01641 *****************************************************************************/ 01642 static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr) 01643 { 01644 uint16_t total_size = 0; 01645 01646 ns_list_foreach(coap_send_msg_s, stored_msg_ptr, linked_list_ptr) { 01647 total_size += stored_msg_ptr->send_msg_ptr.packet_len; 01648 } 01649 01650 return total_size; 01651 } 01652 01653 #endif 01654 01655 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 01656 01657 static coap_blockwise_msg_s* search_sent_blockwise_message(struct coap_s *handle, uint16_t msg_id) 01658 { 01659 ns_list_foreach(coap_blockwise_msg_s, tmp, &handle->linked_list_blockwise_sent_msgs) { 01660 if (tmp->coap_msg_ptr && tmp->coap_msg_ptr->msg_id == msg_id) { 01661 return tmp; 01662 } 01663 } 01664 01665 return NULL; 01666 } 01667 01668 void sn_coap_protocol_remove_sent_blockwise_message(struct coap_s *handle, uint16_t msg_id) 01669 { 01670 if (!handle) { 01671 return; 01672 } 01673 01674 coap_blockwise_msg_s *tmp = search_sent_blockwise_message(handle, msg_id); 01675 01676 if (tmp) { 01677 handle->sn_coap_protocol_free(tmp->coap_msg_ptr->payload_ptr); 01678 sn_coap_parser_release_allocated_coap_msg_mem(handle, tmp->coap_msg_ptr); 01679 ns_list_remove(&handle->linked_list_blockwise_sent_msgs, tmp); 01680 handle->sn_coap_protocol_free(tmp); 01681 } 01682 } 01683 01684 void sn_coap_protocol_block_remove(struct coap_s *handle, sn_nsdl_addr_s *source_address, uint16_t payload_length, void *payload) 01685 { 01686 if (!handle || !source_address || !payload) { 01687 return; 01688 } 01689 01690 /* Loop all stored blockwise payloads in Linked list */ 01691 ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { 01692 /* If payload's Source address is not the same than is searched */ 01693 if (memcmp(source_address->addr_ptr, stored_payload_info_ptr->addr_ptr, source_address->addr_len)) { 01694 continue; 01695 } 01696 01697 /* If payload's Source address port is not the same than is searched */ 01698 if (stored_payload_info_ptr->port != source_address->port) { 01699 continue; 01700 } 01701 01702 /* Check the payload */ 01703 if(payload_length != stored_payload_info_ptr->payload_len){ 01704 continue; 01705 } 01706 01707 if(!memcmp(stored_payload_info_ptr->payload_ptr, payload, stored_payload_info_ptr->payload_len)) 01708 { 01709 /* Everything matches, remove and return. */ 01710 sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_payload_info_ptr); 01711 return; 01712 } 01713 } 01714 } 01715 01716 /**************************************************************************** 01717 * \fn coap_blockwise_msg_s *sn_coap_stored_blockwise_msg_get(struct coap_s *handle, sn_coap_hdr_s *received_coap_msg_ptr) 01718 * 01719 * \brief Get blockwise message from list 01720 * 01721 * \param *handle Pointer to the coap handle structure 01722 * \param *received_coap_msg_ptr Pointer to parsed CoAP message structure 01723 *****************************************************************************/ 01724 static coap_blockwise_msg_s *sn_coap_stored_blockwise_msg_get(struct coap_s *handle, sn_coap_hdr_s *received_coap_msg_ptr) 01725 { 01726 ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) { 01727 if (!received_coap_msg_ptr->token_ptr && !msg->coap_msg_ptr->token_ptr) { 01728 return msg; 01729 } else if ((received_coap_msg_ptr->token_len == msg->coap_msg_ptr->token_len) && (!memcmp(received_coap_msg_ptr->token_ptr, msg->coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len))) { 01730 return msg; 01731 } 01732 } 01733 01734 return ns_list_get_first(&handle->linked_list_blockwise_sent_msgs); 01735 } 01736 01737 /**************************************************************************//** 01738 * \fn static int8_t sn_coap_handle_blockwise_message(void) 01739 * 01740 * \brief Handles all received blockwise messages 01741 * 01742 * \param *src_addr_ptr pointer to source address information struct 01743 * \param *received_coap_msg_ptr pointer to parsed CoAP message structure 01744 *****************************************************************************/ 01745 01746 static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param) 01747 { 01748 sn_coap_hdr_s *src_coap_blockwise_ack_msg_ptr = NULL; 01749 uint16_t dst_packed_data_needed_mem = 0; 01750 uint8_t *dst_ack_packet_data_ptr = NULL; 01751 uint8_t block_temp = 0; 01752 01753 uint16_t original_payload_len = 0; 01754 uint8_t *original_payload_ptr = NULL; 01755 01756 /* Block1 Option in a request (e.g., PUT or POST) */ 01757 // Blocked request sending, received ACK, sending next block.. 01758 if (received_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) { 01759 if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) { 01760 if (received_coap_msg_ptr->options_list_ptr->block1 & 0x08) { 01761 coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr; 01762 01763 /* Get */ 01764 stored_blockwise_msg_temp_ptr = search_sent_blockwise_message(handle, received_coap_msg_ptr->msg_id); 01765 01766 if (stored_blockwise_msg_temp_ptr) { 01767 /* Build response message */ 01768 01769 uint16_t block_size; 01770 uint32_t block_number; 01771 01772 /* Get block option parameters from received message */ 01773 block_number = received_coap_msg_ptr->options_list_ptr->block1 >> 4; 01774 block_temp = received_coap_msg_ptr->options_list_ptr->block1 & 0x07; 01775 block_size = 1u << (block_temp + 4); 01776 01777 /* Build next block message */ 01778 src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr; 01779 01780 if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) { 01781 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE; 01782 // Do not clear block2 as it might have been set in the original request to request 01783 // specific size blocks 01784 } else { 01785 if (!sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr)) { 01786 tr_error("sn_coap_handle_blockwise_message - (send block1) failed to allocate ack message!"); 01787 return 0; 01788 } 01789 } 01790 01791 block_number++; 01792 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = (block_number << 4) | block_temp; 01793 01794 original_payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len; 01795 original_payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr; 01796 01797 if ((block_size * (block_number + 1)) > stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) { 01798 src_coap_blockwise_ack_msg_ptr->payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len - (block_size * (block_number)); 01799 src_coap_blockwise_ack_msg_ptr->payload_ptr = src_coap_blockwise_ack_msg_ptr->payload_ptr + (block_size * block_number); 01800 } 01801 01802 /* Not last block */ 01803 else { 01804 /* set more - bit */ 01805 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= 0x08; 01806 src_coap_blockwise_ack_msg_ptr->payload_len = block_size; 01807 src_coap_blockwise_ack_msg_ptr->payload_ptr = src_coap_blockwise_ack_msg_ptr->payload_ptr + (block_size * block_number); 01808 } 01809 01810 /* Build and send block message */ 01811 dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); 01812 01813 dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); 01814 if (!dst_ack_packet_data_ptr) { 01815 tr_error("sn_coap_handle_blockwise_message - (send block1) failed to allocate ack message!"); 01816 handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); 01817 handle->sn_coap_protocol_free(original_payload_ptr); 01818 handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); 01819 stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL; 01820 return NULL; 01821 } 01822 src_coap_blockwise_ack_msg_ptr->msg_id = get_new_message_id(); 01823 01824 sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); 01825 01826 handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); 01827 01828 #if ENABLE_RESENDINGS 01829 uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0); 01830 if (src_coap_blockwise_ack_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 01831 sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr, 01832 dst_packed_data_needed_mem, 01833 dst_ack_packet_data_ptr, 01834 resend_time, param); 01835 } 01836 #endif 01837 01838 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); 01839 dst_ack_packet_data_ptr = 0; 01840 01841 stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len; 01842 stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr; 01843 01844 received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK; 01845 01846 // Remove original message from the list when last block has been sent. 01847 if (!((src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1) & 0x08)) { 01848 sn_coap_protocol_remove_sent_blockwise_message(handle, stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id); 01849 } 01850 } 01851 } else { 01852 // XXX what was this trying to free? 01853 received_coap_msg_ptr->coap_status = COAP_STATUS_OK; 01854 } 01855 } 01856 01857 // Blocked request receiving 01858 else { 01859 if (received_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) { 01860 received_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size; 01861 } 01862 01863 // Check that incoming block number is in order. 01864 const uint32_t block_number = received_coap_msg_ptr->options_list_ptr->block1 >> 4; 01865 bool blocks_in_order = true; 01866 01867 if (block_number > 0 && 01868 !sn_coap_protocol_linked_list_blockwise_payload_search_compare_block_number(handle, 01869 src_addr_ptr, 01870 received_coap_msg_ptr->token_ptr, 01871 received_coap_msg_ptr->token_len, 01872 block_number - 1)) { 01873 blocks_in_order = false; 01874 } 01875 01876 /* If not last block (more value is set) */ 01877 /* Block option length can be 1-3 bytes. First 4-20 bits are for block number. Last 4 bits are ALWAYS more bit + block size. */ 01878 if (received_coap_msg_ptr->options_list_ptr->block1 & 0x08) { 01879 01880 src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message_with_options(handle); 01881 if (src_coap_blockwise_ack_msg_ptr == NULL) { 01882 tr_error("sn_coap_handle_blockwise_message - (recv block1) failed to allocate ack message!"); 01883 return NULL; 01884 } 01885 01886 if (!blocks_in_order) { 01887 tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE!"); 01888 src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE; 01889 } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) { 01890 src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; 01891 } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) { 01892 src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTINUE; 01893 } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) { 01894 src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTINUE; 01895 } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) { 01896 src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_DELETED; 01897 } 01898 01899 // Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle 01900 if (received_coap_msg_ptr->options_list_ptr->size1 > SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE) { 01901 // Include maximum size that stack can handle into response 01902 tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!"); 01903 src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE; 01904 } 01905 else { 01906 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1; 01907 src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; 01908 01909 /* Check block size */ 01910 block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07); 01911 uint16_t block_size = 1u << (block_temp + 4); 01912 01913 if (block_size > handle->sn_coap_block_data_size) { 01914 // Include maximum size that stack can handle into response 01915 tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!"); 01916 src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE; 01917 src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1 = handle->sn_coap_block_data_size; 01918 } 01919 01920 if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) { 01921 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8; 01922 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); 01923 } 01924 } 01925 01926 src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id; 01927 01928 // Copy token to response 01929 src_coap_blockwise_ack_msg_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len); 01930 if (src_coap_blockwise_ack_msg_ptr->token_ptr) { 01931 src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len; 01932 } 01933 01934 dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); 01935 01936 dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); 01937 if (!dst_ack_packet_data_ptr) { 01938 tr_error("sn_coap_handle_blockwise_message - (recv block1) message allocation failed!"); 01939 handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); 01940 handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); 01941 return NULL; 01942 } 01943 01944 sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); 01945 01946 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT 01947 // copy coap data buffer to duplicate list for resending purposes 01948 if (!sn_coap_protocol_update_duplicate_package_data(handle, 01949 src_addr_ptr, 01950 src_coap_blockwise_ack_msg_ptr, 01951 dst_packed_data_needed_mem, 01952 dst_ack_packet_data_ptr)) { 01953 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); 01954 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); 01955 return NULL; 01956 } 01957 #endif 01958 // Store only in success case 01959 if (src_coap_blockwise_ack_msg_ptr->msg_code != COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE && 01960 src_coap_blockwise_ack_msg_ptr->msg_code != COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE) { 01961 sn_coap_protocol_linked_list_blockwise_payload_store(handle, 01962 src_addr_ptr, 01963 received_coap_msg_ptr->payload_len, 01964 received_coap_msg_ptr->payload_ptr, 01965 received_coap_msg_ptr->token_ptr, 01966 received_coap_msg_ptr->token_len, 01967 block_number, 01968 received_coap_msg_ptr->options_list_ptr->size1); 01969 } 01970 01971 handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); 01972 01973 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); 01974 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); 01975 dst_ack_packet_data_ptr = 0; 01976 01977 received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING; 01978 01979 } else { 01980 01981 /* * * This is the last block when whole Blockwise payload from received * * */ 01982 /* * * blockwise messages is gathered and returned to User * * */ 01983 01984 sn_coap_protocol_linked_list_blockwise_payload_store(handle, 01985 src_addr_ptr, 01986 received_coap_msg_ptr->payload_len, 01987 received_coap_msg_ptr->payload_ptr, 01988 received_coap_msg_ptr->token_ptr, 01989 received_coap_msg_ptr->token_len, 01990 block_number, 01991 received_coap_msg_ptr->options_list_ptr->size1); 01992 01993 if (!sn_coap_handle_last_blockwise(handle, src_addr_ptr, received_coap_msg_ptr)) { 01994 01995 return NULL; 01996 } 01997 } 01998 } 01999 } 02000 02001 02002 /* Block2 Option in a response (e.g., a 2.05 response for GET) */ 02003 /* Message ID must be same than in received message */ 02004 else { 02005 //This is response to request we made 02006 if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) { 02007 #if SN_COAP_BLOCKWISE_INTERNAL_BLOCK_2_HANDLING_ENABLED 02008 if (handle->sn_coap_internal_block2_resp_handling) { 02009 uint32_t block_number = 0; 02010 /* Store blockwise payload to Linked list */ 02011 //todo: add block number to stored values - just to make sure all packets are in order 02012 sn_coap_protocol_linked_list_blockwise_payload_store(handle, 02013 src_addr_ptr, 02014 received_coap_msg_ptr->payload_len, 02015 received_coap_msg_ptr->payload_ptr, 02016 received_coap_msg_ptr->token_ptr, 02017 received_coap_msg_ptr->token_len, 02018 received_coap_msg_ptr->options_list_ptr->block2 >> 4, 02019 received_coap_msg_ptr->options_list_ptr->size1); 02020 /* If not last block (more value is set) */ 02021 if (received_coap_msg_ptr->options_list_ptr->block2 & 0x08) { 02022 coap_blockwise_msg_s *previous_blockwise_msg_ptr; 02023 //build and send ack 02024 received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING; 02025 02026 previous_blockwise_msg_ptr = search_sent_blockwise_message(handle, received_coap_msg_ptr->msg_id); 02027 02028 if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) { 02029 tr_error("sn_coap_handle_blockwise_message - (send block2) previous message null!"); 02030 return 0; 02031 } 02032 02033 /* * * Then build CoAP Acknowledgement message * * */ 02034 src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message_with_options(handle); 02035 if (src_coap_blockwise_ack_msg_ptr == NULL) { 02036 tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate message!"); 02037 return NULL; 02038 } 02039 02040 src_coap_blockwise_ack_msg_ptr->msg_id = get_new_message_id(); 02041 02042 /* Update block option */ 02043 block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07; 02044 02045 block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4; 02046 block_number ++; 02047 02048 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = (block_number << 4) | block_temp; 02049 02050 02051 /* Set BLOCK2 (subsequent) GET msg code and copy uri path from previous msg*/ 02052 src_coap_blockwise_ack_msg_ptr->msg_code = previous_blockwise_msg_ptr->coap_msg_ptr->msg_code; 02053 if (previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr) { 02054 src_coap_blockwise_ack_msg_ptr->uri_path_ptr = sn_coap_protocol_malloc_copy(handle, previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len); 02055 02056 if (!src_coap_blockwise_ack_msg_ptr->uri_path_ptr) { 02057 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); 02058 tr_error("sn_coap_handle_blockwise_message - failed to allocate for uri path ptr!"); 02059 return NULL; 02060 } 02061 src_coap_blockwise_ack_msg_ptr->uri_path_len = previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len; 02062 } 02063 if (previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr) { 02064 02065 src_coap_blockwise_ack_msg_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->token_len); 02066 if (!src_coap_blockwise_ack_msg_ptr->token_ptr) { 02067 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); 02068 tr_error("sn_coap_handle_blockwise_message - failed to allocate for token ptr!"); 02069 return NULL; 02070 } 02071 src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len; 02072 } 02073 02074 sn_coap_protocol_linked_list_blockwise_msg_remove(handle, previous_blockwise_msg_ptr); 02075 02076 previous_blockwise_msg_ptr = 0; 02077 02078 /* Then get needed memory count for Packet data */ 02079 dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); 02080 02081 /* Then allocate memory for Packet data */ 02082 dst_ack_packet_data_ptr = sn_coap_protocol_calloc(handle, dst_packed_data_needed_mem); 02083 02084 if (dst_ack_packet_data_ptr == NULL) { 02085 tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate packet!"); 02086 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); 02087 return NULL; 02088 } 02089 02090 /* * * Then build Acknowledgement message to Packed data * * */ 02091 if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) { 02092 tr_error("sn_coap_handle_blockwise_message - (send block2) builder failed!"); 02093 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); 02094 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); 02095 return NULL; 02096 } 02097 02098 /* * * Save to linked list * * */ 02099 coap_blockwise_msg_s *stored_blockwise_msg_ptr; 02100 02101 stored_blockwise_msg_ptr = sn_coap_protocol_calloc(handle, sizeof(coap_blockwise_msg_s)); 02102 if (!stored_blockwise_msg_ptr) { 02103 tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate blockwise message!"); 02104 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); 02105 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); 02106 return 0; 02107 } 02108 02109 stored_blockwise_msg_ptr->timestamp = handle->system_time; 02110 02111 stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr; 02112 stored_blockwise_msg_ptr->param = param; 02113 stored_blockwise_msg_ptr->msg_id = stored_blockwise_msg_ptr->coap_msg_ptr->msg_id; 02114 ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); 02115 02116 /* * * Then release memory of CoAP Acknowledgement message * * */ 02117 handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, 02118 dst_packed_data_needed_mem, src_addr_ptr, param); 02119 02120 #if ENABLE_RESENDINGS 02121 uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0); 02122 sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr, 02123 dst_packed_data_needed_mem, 02124 dst_ack_packet_data_ptr, 02125 resend_time, param); 02126 #endif 02127 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); 02128 dst_ack_packet_data_ptr = 0; 02129 } 02130 02131 //Last block received 02132 else { 02133 /* * * This is the last block when whole Blockwise payload from received * * */ 02134 /* * * blockwise messages is gathered and returned to User * * */ 02135 02136 if (!sn_coap_handle_last_blockwise(handle, src_addr_ptr, received_coap_msg_ptr)) { 02137 02138 return NULL; 02139 } 02140 02141 //todo: remove previous msg from list 02142 } 02143 } 02144 #else 02145 // If the internal handling is disabled, this code should not be ran unless 02146 // the client messed up in its own handler. 02147 tr_error("sn_coap_handle_blockwise_message - (send block2) - callback not set"); 02148 return NULL; 02149 #endif 02150 } 02151 02152 //Now we send data to request 02153 else { 02154 //Get message by using block number 02155 //NOTE: Getting the first from list might not be correct one 02156 coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = sn_coap_stored_blockwise_msg_get(handle, received_coap_msg_ptr); 02157 if (stored_blockwise_msg_temp_ptr) { 02158 02159 block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07; 02160 02161 /* Resolve block parameters */ 02162 const uint16_t block_size = 1u << (block_temp + 4); 02163 const uint32_t block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4; 02164 02165 02166 /* Build response message */ 02167 src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr; 02168 02169 if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) { 02170 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE; 02171 // Do not clear block2 as it might have been set in the original request to request 02172 // specific size blocks 02173 } else { 02174 if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) { 02175 tr_error("sn_coap_handle_blockwise_message - (recv block2) failed to allocate options!"); 02176 return 0; 02177 } 02178 } 02179 02180 src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id; 02181 02182 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = received_coap_msg_ptr->options_list_ptr->block2; 02183 02184 /* * Payload part * */ 02185 02186 /* Check if last block */ 02187 02188 original_payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len; 02189 original_payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr; 02190 02191 if ((block_size * (block_number + 1)) >= stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) { 02192 src_coap_blockwise_ack_msg_ptr->payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len - (block_size * block_number); 02193 src_coap_blockwise_ack_msg_ptr->payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr + (block_size * block_number); 02194 } 02195 /* Not last block */ 02196 else { 02197 /* set more - bit */ 02198 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 |= 0x08; 02199 src_coap_blockwise_ack_msg_ptr->payload_len = block_size; 02200 src_coap_blockwise_ack_msg_ptr->payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr + (block_size * block_number); 02201 } 02202 02203 /* Update token to match one which is in GET request. 02204 * This is needed only in case of notification message. 02205 */ 02206 if (src_coap_blockwise_ack_msg_ptr->options_list_ptr && 02207 src_coap_blockwise_ack_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) { 02208 if (received_coap_msg_ptr->token_len && src_coap_blockwise_ack_msg_ptr->token_ptr) { 02209 handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->token_ptr); 02210 src_coap_blockwise_ack_msg_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len); 02211 if (src_coap_blockwise_ack_msg_ptr->token_ptr) { 02212 src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len; 02213 } 02214 } 02215 } 02216 02217 /* Build and send block message */ 02218 dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); 02219 02220 dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); 02221 if (!dst_ack_packet_data_ptr) { 02222 tr_error("sn_coap_handle_blockwise_message - (recv block2) failed to allocate packet!"); 02223 handle->sn_coap_protocol_free(original_payload_ptr); 02224 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); 02225 stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL; 02226 return NULL; 02227 } 02228 02229 sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); 02230 handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); 02231 02232 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); 02233 dst_ack_packet_data_ptr = 0; 02234 02235 stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len; 02236 stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr; 02237 02238 if ((block_size * (block_number + 1)) >= stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) { 02239 02240 if (handle->sn_coap_rx_callback) { 02241 stored_blockwise_msg_temp_ptr->coap_msg_ptr->coap_status = COAP_STATUS_BUILDER_BLOCK_SENDING_DONE; 02242 stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id = stored_blockwise_msg_temp_ptr->msg_id; 02243 handle->sn_coap_rx_callback(stored_blockwise_msg_temp_ptr->coap_msg_ptr, NULL, stored_blockwise_msg_temp_ptr->param); 02244 } 02245 02246 sn_coap_protocol_linked_list_blockwise_msg_remove(handle, stored_blockwise_msg_temp_ptr); 02247 } 02248 02249 received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK; 02250 } 02251 } 02252 } 02253 return received_coap_msg_ptr; 02254 } 02255 02256 static bool sn_coap_handle_last_blockwise(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr) 02257 { 02258 uint16_t payload_len = 0; 02259 uint32_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len); 02260 uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len); 02261 02262 tr_debug("sn_coap_handle_last_blockwise - whole len %" PRIu32, whole_payload_len); 02263 if (!whole_payload_len) { 02264 return false; 02265 } 02266 02267 #if SN_COAP_REDUCE_BLOCKWISE_HEAP_FOOTPRINT 02268 received_coap_msg_ptr->payload_ptr = payload_ptr; 02269 received_coap_msg_ptr->payload_len = whole_payload_len; 02270 #else 02271 received_coap_msg_ptr->payload_ptr = sn_coap_protocol_malloc_copy(handle, payload_ptr, whole_payload_len); 02272 if (received_coap_msg_ptr->payload_ptr == NULL) { 02273 tr_error("sn_coap_handle_last_blockwise - failed to allocate whole package!"); 02274 return false; 02275 } 02276 received_coap_msg_ptr->payload_len = whole_payload_len; 02277 #endif 02278 received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; 02279 02280 return true; 02281 } 02282 02283 int8_t sn_coap_convert_block_size(uint16_t block_size) 02284 { 02285 if (block_size == 16) { 02286 return 0; 02287 } else if (block_size == 32) { 02288 return 1; 02289 } else if (block_size == 64) { 02290 return 2; 02291 } else if (block_size == 128) { 02292 return 3; 02293 } else if (block_size == 256) { 02294 return 4; 02295 } else if (block_size == 512) { 02296 return 5; 02297 } else if (block_size == 1024) { 02298 return 6; 02299 } else { 02300 return 0; 02301 } 02302 } 02303 02304 static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, const sn_coap_hdr_s *source_header_ptr) 02305 { 02306 sn_coap_hdr_s *destination_header_ptr; 02307 02308 destination_header_ptr = sn_coap_parser_alloc_message(handle); 02309 if (!destination_header_ptr) { 02310 tr_error("sn_coap_protocol_copy_header - failed to allocate message!"); 02311 return 0; 02312 } 02313 02314 destination_header_ptr->coap_status = source_header_ptr->coap_status; 02315 destination_header_ptr->msg_type = source_header_ptr->msg_type; 02316 destination_header_ptr->msg_code = source_header_ptr->msg_code; 02317 destination_header_ptr->msg_id = source_header_ptr->msg_id; 02318 02319 if (source_header_ptr->uri_path_ptr) { 02320 destination_header_ptr->uri_path_len = source_header_ptr->uri_path_len; 02321 destination_header_ptr->uri_path_ptr = sn_coap_protocol_malloc_copy(handle, source_header_ptr->uri_path_ptr, source_header_ptr->uri_path_len); 02322 if (!destination_header_ptr->uri_path_ptr) { 02323 tr_error("sn_coap_protocol_copy_header - failed to allocate uri path!"); 02324 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02325 return 0; 02326 } 02327 } 02328 02329 if (source_header_ptr->token_ptr) { 02330 destination_header_ptr->token_len = source_header_ptr->token_len; 02331 destination_header_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, source_header_ptr->token_ptr, source_header_ptr->token_len); 02332 if (!destination_header_ptr->token_ptr) { 02333 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02334 tr_error("sn_coap_protocol_copy_header - failed to allocate token!"); 02335 return 0; 02336 } 02337 } 02338 02339 destination_header_ptr->content_format = source_header_ptr->content_format; 02340 02341 /* Options list */ 02342 if (source_header_ptr->options_list_ptr) { 02343 if (sn_coap_parser_alloc_options(handle, destination_header_ptr) == NULL) { 02344 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02345 tr_error("sn_coap_protocol_copy_header - failed to allocate options!"); 02346 return 0; 02347 } 02348 02349 const sn_coap_options_list_s *source_options_list_ptr = source_header_ptr->options_list_ptr; 02350 sn_coap_options_list_s *destination_options_list_ptr = destination_header_ptr->options_list_ptr; 02351 02352 destination_options_list_ptr->max_age = source_options_list_ptr->max_age; 02353 02354 if (source_options_list_ptr->proxy_uri_ptr) { 02355 destination_options_list_ptr->proxy_uri_len = source_options_list_ptr->proxy_uri_len; 02356 destination_options_list_ptr->proxy_uri_ptr = sn_coap_protocol_malloc_copy(handle, source_options_list_ptr->proxy_uri_ptr, source_options_list_ptr->proxy_uri_len); 02357 if (!destination_options_list_ptr->proxy_uri_ptr) { 02358 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02359 tr_error("sn_coap_protocol_copy_header - failed to allocate proxy uri!"); 02360 return 0; 02361 } 02362 } 02363 02364 if (source_options_list_ptr->etag_ptr) { 02365 destination_options_list_ptr->etag_len = source_options_list_ptr->etag_len; 02366 destination_options_list_ptr->etag_ptr = sn_coap_protocol_malloc_copy(handle, source_options_list_ptr->etag_ptr, source_options_list_ptr->etag_len); 02367 if (!destination_options_list_ptr->etag_ptr) { 02368 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02369 tr_error("sn_coap_protocol_copy_header - failed to allocate etag!"); 02370 return 0; 02371 } 02372 } 02373 02374 if (source_options_list_ptr->uri_host_ptr) { 02375 destination_options_list_ptr->uri_host_len = source_options_list_ptr->uri_host_len; 02376 destination_options_list_ptr->uri_host_ptr = sn_coap_protocol_malloc_copy(handle, source_options_list_ptr->uri_host_ptr, source_options_list_ptr->uri_host_len); 02377 if (!destination_options_list_ptr->uri_host_ptr) { 02378 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02379 tr_error("sn_coap_protocol_copy_header - failed to allocate uri host!"); 02380 return 0; 02381 } 02382 } 02383 02384 if (source_options_list_ptr->location_path_ptr) { 02385 destination_options_list_ptr->location_path_len = source_options_list_ptr->location_path_len; 02386 destination_options_list_ptr->location_path_ptr = sn_coap_protocol_malloc_copy(handle, source_options_list_ptr->location_path_ptr, source_options_list_ptr->location_path_len); 02387 if (!destination_options_list_ptr->location_path_ptr) { 02388 tr_error("sn_coap_protocol_copy_header - failed to allocate location path!"); 02389 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02390 return 0; 02391 } 02392 } 02393 02394 destination_options_list_ptr->uri_port = source_options_list_ptr->uri_port; 02395 02396 if (source_options_list_ptr->location_query_ptr) { 02397 destination_options_list_ptr->location_query_len = source_options_list_ptr->location_query_len; 02398 destination_options_list_ptr->location_query_ptr = sn_coap_protocol_malloc_copy(handle, source_options_list_ptr->location_query_ptr, source_options_list_ptr->location_query_len); 02399 if (!destination_options_list_ptr->location_query_ptr) { 02400 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02401 tr_error("sn_coap_protocol_copy_header - failed to allocate location query!"); 02402 return 0; 02403 } 02404 } 02405 02406 destination_options_list_ptr->observe = source_options_list_ptr->observe; 02407 destination_options_list_ptr->accept = source_options_list_ptr->accept; 02408 02409 if (source_options_list_ptr->uri_query_ptr) { 02410 destination_options_list_ptr->uri_query_len = source_options_list_ptr->uri_query_len; 02411 destination_options_list_ptr->uri_query_ptr = sn_coap_protocol_malloc_copy(handle, source_options_list_ptr->uri_query_ptr, source_options_list_ptr->uri_query_len); 02412 if (!destination_options_list_ptr->uri_query_ptr) { 02413 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); 02414 tr_error("sn_coap_protocol_copy_header - failed to allocate uri query!"); 02415 return 0; 02416 } 02417 } 02418 02419 destination_options_list_ptr->block1 = source_options_list_ptr->block1; 02420 destination_options_list_ptr->block2 = source_options_list_ptr->block2; 02421 } 02422 02423 return destination_header_ptr; 02424 } 02425 #endif 02426 02427 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT 02428 static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *handle, 02429 const sn_nsdl_addr_s *dst_addr_ptr, 02430 const sn_coap_hdr_s *coap_msg_ptr, 02431 const int16_t data_size, 02432 const uint8_t *dst_packet_data_ptr) 02433 { 02434 if (coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT && 02435 handle->sn_coap_duplication_buffer_size != 0) { 02436 coap_duplication_info_s* info = sn_coap_protocol_linked_list_duplication_info_search(handle, 02437 dst_addr_ptr, 02438 coap_msg_ptr->msg_id); 02439 02440 /* Update package data to duplication info struct if it's not there yet */ 02441 if (info && info->packet_ptr == NULL) { 02442 info->packet_ptr = handle->sn_coap_protocol_malloc(data_size); 02443 if (info->packet_ptr) { 02444 memcpy(info->packet_ptr, dst_packet_data_ptr, data_size); 02445 info->packet_len = data_size; 02446 } else { 02447 tr_error("sn_coap_protocol_update_duplication_package_data - failed to allocate duplication info!"); 02448 return false; 02449 } 02450 } 02451 } 02452 return true; 02453 } 02454 #endif 02455 02456 void *sn_coap_protocol_malloc_copy(struct coap_s *handle, const void *source, uint16_t length) 02457 { 02458 void *dest = handle->sn_coap_protocol_malloc(length); 02459 02460 if ((dest) && (source)) { 02461 memcpy(dest, source, length); 02462 } 02463 return dest; 02464 } 02465 02466 /* 02467 * This should logically be part and accessed via of the coap_s just as malloc() & free() 02468 * are, but that would require the client to fill one up, as a wrapper filled from this 02469 * class would need access to the handle itself. 02470 */ 02471 void *sn_coap_protocol_calloc(struct coap_s *handle, uint16_t length) 02472 { 02473 void *result = handle->sn_coap_protocol_malloc(length); 02474 02475 if (result) { 02476 memset(result, 0, length); 02477 } 02478 return result; 02479 } 02480 02481 static bool compare_address_and_port(const sn_nsdl_addr_s* left, const sn_nsdl_addr_s* right) 02482 { 02483 bool match = false; 02484 02485 if (left->port == right->port) { 02486 if (0 == memcmp(left->addr_ptr, right->addr_ptr, left->addr_len)) { 02487 match = true; 02488 } 02489 } 02490 02491 return match; 02492 } 02493 02494 static uint16_t get_new_message_id(void) 02495 { 02496 if (message_id == 0) { 02497 /* Randomize global message ID */ 02498 randLIB_seed_random(); 02499 message_id = randLIB_get_16bit(); 02500 } 02501 message_id++; 02502 if (message_id == 0) { 02503 message_id = 1; 02504 } 02505 return message_id; 02506 }
Generated on Tue Jul 12 2022 13:54:50 by
