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