BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_coap_protocol.c Source File

sn_coap_protocol.c

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