Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_coap_protocol.c Source File

sn_coap_protocol.c

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