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