takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

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