Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_coap_protocol.c Source File

sn_coap_protocol.c

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