joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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