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