Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_coap_protocol.c Source File

sn_coap_protocol.c

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