Rtos API example

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