sandbox / mbed-client-c

Fork of mbed-client-c by Christopher Haster

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