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