Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

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_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, 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, uint8_t *token_ptr, uint8_t token_len, 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, uint8_t *token_ptr, uint8_t token_len);
00060 static bool                  sn_coap_protocol_linked_list_blockwise_payload_compare_block_number(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint8_t *token_ptr, uint8_t token_len, 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, uint8_t *token_ptr, uint8_t token_len);
00063 static uint32_t              sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint8_t *token_ptr, uint8_t token_len);
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_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not enabled, 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_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, 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_BLOCKWISE_ENABLED || 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_BLOCKWISE_ENABLED || 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 
00367 int8_t prepare_blockwise_message(struct coap_s *handle, sn_coap_hdr_s *src_coap_msg_ptr)
00368 {
00369 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
00370     if ((src_coap_msg_ptr->payload_len > SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE) &&
00371         (src_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) &&
00372         (handle->sn_coap_block_data_size > 0)) {
00373         /* * * * Add Blockwise option to send CoAP message * * */
00374 
00375         /* Allocate memory for less used options */
00376         if (sn_coap_parser_alloc_options(handle, src_coap_msg_ptr) == NULL) {
00377             tr_error("prepare_blockwise_message - failed to allocate options!");
00378             return -2;
00379         }
00380 
00381         /* Check if Request message */
00382         if (src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED) {
00383             /* Add Blockwise option, use Block1 because Request payload */
00384             src_coap_msg_ptr->options_list_ptr->block1 = 0x08;      /* First block  (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */
00385             src_coap_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
00386 
00387             /* Add size1 parameter */
00388 
00389             src_coap_msg_ptr->options_list_ptr->use_size1 = true;
00390             src_coap_msg_ptr->options_list_ptr->use_size2 = false;
00391             src_coap_msg_ptr->options_list_ptr->size1 = src_coap_msg_ptr->payload_len;
00392         } else { /* Response message */
00393             /* Add Blockwise option, use Block2 because Response payload */
00394             src_coap_msg_ptr->options_list_ptr->block2 = 0x08;      /* First block  (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */
00395             src_coap_msg_ptr->options_list_ptr->block2 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
00396 
00397             src_coap_msg_ptr->options_list_ptr->use_size1 = false;
00398             src_coap_msg_ptr->options_list_ptr->use_size2 = true;
00399             src_coap_msg_ptr->options_list_ptr->size2 = src_coap_msg_ptr->payload_len;
00400         }
00401     }
00402 #endif
00403     return 0;
00404 }
00405 
00406 
00407 int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr,
00408                                uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param)
00409 {
00410     int16_t  byte_count_built     = 0;
00411 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
00412     uint16_t original_payload_len = 0;
00413 #endif
00414     /* * * * Check given pointers  * * * */
00415     if ((dst_addr_ptr == NULL) || (dst_packet_data_ptr == NULL) || (src_coap_msg_ptr == NULL) || handle == NULL) {
00416         return -2;
00417     }
00418 
00419     if (dst_addr_ptr->addr_ptr == NULL) {
00420         return -2;
00421     }
00422 
00423     /* Check if built Message type is else than Acknowledgement or Reset i.e. message type is Confirmable or Non-confirmable */
00424     /* (for Acknowledgement and  Reset messages is written same Message ID than was in the Request message) */
00425     if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT &&
00426             src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET &&
00427             src_coap_msg_ptr->msg_id == 0) {
00428         /* * * * Generate new Message ID and increase it by one  * * * */
00429         src_coap_msg_ptr->msg_id = message_id;
00430         message_id++;
00431         if (message_id == 0) {
00432             message_id = 1;
00433         }
00434     }
00435 
00436 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
00437     /* If blockwising needed */
00438     if ((src_coap_msg_ptr->payload_len > SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE) &&
00439         (src_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) &&
00440         (handle->sn_coap_block_data_size > 0)) {
00441         /* Store original Payload length */
00442         original_payload_len = src_coap_msg_ptr->payload_len;
00443         /* Change Payload length of send message because Payload is blockwised */
00444         src_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size;
00445     }
00446 #endif
00447     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00448     /* * * * Build Packet data from CoAP message by using CoAP Header builder  * * * */
00449     /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00450 
00451     byte_count_built = sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, handle->sn_coap_block_data_size);
00452 
00453     if (byte_count_built < 0) {
00454         tr_error("sn_coap_protocol_build - failed to build message!");
00455         return byte_count_built;
00456     }
00457 
00458 #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
00459 
00460     /* Check if built Message type was confirmable, only these messages are resent */
00461     if (src_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
00462         /* Store message to Linked list for resending purposes */
00463         uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
00464         if (sn_coap_protocol_linked_list_send_msg_store(handle, dst_addr_ptr, byte_count_built, dst_packet_data_ptr,
00465                 resend_time,
00466                 param) == 0) {
00467             return -4;
00468         }
00469     }
00470 
00471 #endif /* ENABLE_RESENDINGS */
00472 
00473 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT
00474     if (src_coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT &&
00475             handle->sn_coap_duplication_buffer_size != 0) {
00476         coap_duplication_info_s* info = sn_coap_protocol_linked_list_duplication_info_search(handle,
00477                                                                                              dst_addr_ptr,
00478                                                                                              src_coap_msg_ptr->msg_id);
00479         /* Update package data to duplication info struct if it's not there yet */
00480         if (info && info->packet_ptr == NULL) {
00481             info->packet_ptr = handle->sn_coap_protocol_malloc(byte_count_built);
00482             if (info->packet_ptr) {
00483                 memcpy(info->packet_ptr, dst_packet_data_ptr, byte_count_built);
00484                 info->packet_len = byte_count_built;
00485             } else {
00486                 tr_error("sn_coap_protocol_build - failed to allocate duplication info!");
00487                 return -4;
00488             }
00489         }
00490     }
00491 #endif
00492 
00493 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
00494 
00495     /* If blockwising needed */
00496     if ((original_payload_len > handle->sn_coap_block_data_size) && (handle->sn_coap_block_data_size > 0)) {
00497 
00498         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00499         /* * * * Manage rest blockwise messages sending by storing them to Linked list * * * */
00500         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00501 
00502         coap_blockwise_msg_s *stored_blockwise_msg_ptr;
00503 
00504         stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
00505         if (!stored_blockwise_msg_ptr) {
00506             //block paylaod save failed, only first block can be build. Perhaps we should return error.
00507             tr_error("sn_coap_protocol_build - blockwise message allocation failed!");
00508             return byte_count_built;
00509         }
00510         memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
00511 
00512         /* Fill struct */
00513         stored_blockwise_msg_ptr->timestamp = handle->system_time;
00514 
00515         stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr);
00516         if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){
00517             handle->sn_coap_protocol_free(stored_blockwise_msg_ptr);
00518             stored_blockwise_msg_ptr = 0;
00519             tr_error("sn_coap_protocol_build - block header copy failed!");
00520             return -2;
00521         }
00522 
00523         stored_blockwise_msg_ptr->coap_msg_ptr->payload_len = original_payload_len;
00524         stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = handle->sn_coap_protocol_malloc(stored_blockwise_msg_ptr->coap_msg_ptr->payload_len);
00525 
00526         if (!stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) {
00527             //block payload save failed, only first block can be build. Perhaps we should return error.
00528             sn_coap_parser_release_allocated_coap_msg_mem(handle, stored_blockwise_msg_ptr->coap_msg_ptr);
00529             handle->sn_coap_protocol_free(stored_blockwise_msg_ptr);
00530             stored_blockwise_msg_ptr = 0;
00531             tr_error("sn_coap_protocol_build - block payload allocation failed!");
00532             return byte_count_built;
00533         }
00534         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);
00535 
00536         stored_blockwise_msg_ptr->coap = handle;
00537         stored_blockwise_msg_ptr->param = param;
00538         stored_blockwise_msg_ptr->msg_id = stored_blockwise_msg_ptr->coap_msg_ptr->msg_id;
00539         ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
00540     } else if (src_coap_msg_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE) {
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_BLOCKWISE_ENABLED || 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_BLOCKWISE_ENABLED && !SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is enabled, 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_BLOCKWISE_ENABLED && !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_BLOCKWISE_ENABLED || 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_BLOCKWISE_ENABLED || 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 
01052 uint16_t sn_coap_protocol_get_configured_blockwise_size(struct coap_s *handle)
01053 {
01054     return handle->sn_coap_block_data_size;
01055 }
01056 
01057 #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */
01058 
01059 /**************************************************************************//**
01060  * \fn static void sn_coap_protocol_linked_list_duplication_info_store(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id)
01061  *
01062  * \brief Stores Duplication info to Linked list
01063  *
01064  * \param msg_id is Message ID to be stored
01065  * \param *addr_ptr is pointer to Address information to be stored
01066  *****************************************************************************/
01067 
01068 static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr,
01069         uint16_t msg_id, void *param)
01070 {
01071     coap_duplication_info_s *stored_duplication_info_ptr = NULL;
01072 
01073     /* * * * Allocating memory for stored Duplication info * * * */
01074 
01075     /* Allocate memory for stored Duplication info's structure */
01076     stored_duplication_info_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_duplication_info_s));
01077 
01078     if (stored_duplication_info_ptr == NULL) {
01079         tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate duplication info!");
01080         return;
01081     }
01082     memset(stored_duplication_info_ptr, 0, sizeof(coap_duplication_info_s));
01083 
01084     /* Allocate memory for stored Duplication info's address */
01085     stored_duplication_info_ptr->address = handle->sn_coap_protocol_malloc(sizeof(sn_nsdl_addr_s));
01086     if (stored_duplication_info_ptr->address == NULL) {
01087         tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate address!");
01088         handle->sn_coap_protocol_free(stored_duplication_info_ptr);
01089         stored_duplication_info_ptr = 0;
01090         return;
01091     }
01092     memset(stored_duplication_info_ptr->address, 0, sizeof(sn_nsdl_addr_s));
01093 
01094     stored_duplication_info_ptr->address->addr_ptr = handle->sn_coap_protocol_malloc(addr_ptr->addr_len);
01095 
01096     if (stored_duplication_info_ptr->address->addr_ptr == NULL) {
01097         tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate address pointer!");
01098         handle->sn_coap_protocol_free(stored_duplication_info_ptr->address);
01099         stored_duplication_info_ptr->address = 0;
01100         handle->sn_coap_protocol_free(stored_duplication_info_ptr);
01101         stored_duplication_info_ptr = 0;
01102         return;
01103     }
01104 
01105     /* * * * Filling fields of stored Duplication info * * * */
01106     stored_duplication_info_ptr->timestamp = handle->system_time;
01107     stored_duplication_info_ptr->address->addr_len = addr_ptr->addr_len;
01108     memcpy(stored_duplication_info_ptr->address->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len);
01109     stored_duplication_info_ptr->address->port = addr_ptr->port;
01110     stored_duplication_info_ptr->msg_id = msg_id;
01111 
01112     stored_duplication_info_ptr->coap = handle;
01113 
01114     stored_duplication_info_ptr->param = param;
01115     /* * * * Storing Duplication info to Linked list * * * */
01116 
01117     ns_list_add_to_end(&handle->linked_list_duplication_msgs, stored_duplication_info_ptr);
01118     ++handle->count_duplication_msgs;
01119 }
01120 
01121 /**************************************************************************//**
01122  * \fn static int8_t sn_coap_protocol_linked_list_duplication_info_search(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id)
01123  *
01124  * \brief Searches stored message from Linked list (Address and Message ID as key)
01125  *
01126  * \param *addr_ptr is pointer to Address key to be searched
01127  * \param msg_id is Message ID key to be searched
01128  *
01129  * \return Return value is 0 when message found and -1 if not found
01130  *****************************************************************************/
01131 
01132 static coap_duplication_info_s* sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle,
01133         sn_nsdl_addr_s *addr_ptr, uint16_t msg_id)
01134 {
01135     /* Loop all nodes in Linked list for searching Message ID */
01136     ns_list_foreach(coap_duplication_info_s, stored_duplication_info_ptr, &handle->linked_list_duplication_msgs) {
01137         /* If message's Message ID is same than is searched */
01138         if (stored_duplication_info_ptr->msg_id == msg_id) {
01139             /* If message's Source address is same than is searched */
01140             if (0 == memcmp(addr_ptr->addr_ptr, stored_duplication_info_ptr->address->addr_ptr, addr_ptr->addr_len)) {
01141                 /* If message's Source address port is same than is searched */
01142                 if (stored_duplication_info_ptr->address->port == addr_ptr->port) {
01143                     /* * * Correct Duplication info found * * * */
01144                     return stored_duplication_info_ptr;
01145                 }
01146             }
01147         }
01148     }
01149     return NULL;
01150 }
01151 
01152 /**************************************************************************//**
01153  * \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)
01154  *
01155  * \brief Removes stored Duplication info from Linked list
01156  *
01157  * \param *addr_ptr is pointer to Address key to be removed
01158  *
01159  * \param port is Port key to be removed
01160  *
01161  * \param msg_id is Message ID key to be removed
01162  *****************************************************************************/
01163 
01164 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)
01165 {
01166     /* Loop all stored duplication messages in Linked list */
01167     ns_list_foreach(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) {
01168         /* If message's Address is same than is searched */
01169         if (handle == removed_duplication_info_ptr->coap && 0 == memcmp(addr_ptr,
01170                                                                         removed_duplication_info_ptr->address->addr_ptr,
01171                                                                         removed_duplication_info_ptr->address->addr_len)) {
01172             /* If message's Address prt is same than is searched */
01173             if (removed_duplication_info_ptr->address->port == port) {
01174                 /* If Message ID is same than is searched */
01175                 if (removed_duplication_info_ptr->msg_id == msg_id) {
01176                     /* * * * Correct Duplication info found, remove it from Linked list * * * */
01177                     ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr);
01178                     --handle->count_duplication_msgs;
01179 
01180                     /* Free memory of stored Duplication info */
01181                     handle->sn_coap_protocol_free(removed_duplication_info_ptr->address->addr_ptr);
01182                     removed_duplication_info_ptr->address->addr_ptr = 0;
01183                     handle->sn_coap_protocol_free(removed_duplication_info_ptr->address);
01184                     removed_duplication_info_ptr->address = 0;
01185                     handle->sn_coap_protocol_free(removed_duplication_info_ptr->packet_ptr);
01186                     removed_duplication_info_ptr->packet_ptr = 0;
01187                     handle->sn_coap_protocol_free(removed_duplication_info_ptr);
01188                     removed_duplication_info_ptr = 0;
01189                     return;
01190                 }
01191             }
01192         }
01193     }
01194 }
01195 
01196 /**************************************************************************//**
01197  * \fn static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle)
01198  *
01199  * \brief Removes old stored Duplication detection infos from Linked list
01200  *****************************************************************************/
01201 
01202 static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle)
01203 {
01204     /* Loop all stored duplication messages in Linked list */
01205     ns_list_foreach_safe(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) {
01206         if ((handle->system_time - removed_duplication_info_ptr->timestamp)  > SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED) {
01207             /* * * * Old Duplication info found, remove it from Linked list * * * */
01208             ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr);
01209             --handle->count_duplication_msgs;
01210 
01211             /* Free memory of stored Duplication info */
01212             handle->sn_coap_protocol_free(removed_duplication_info_ptr->address->addr_ptr);
01213             removed_duplication_info_ptr->address->addr_ptr = 0;
01214             handle->sn_coap_protocol_free(removed_duplication_info_ptr->address);
01215             removed_duplication_info_ptr->address = 0;
01216             handle->sn_coap_protocol_free(removed_duplication_info_ptr->packet_ptr);
01217             removed_duplication_info_ptr->packet_ptr = 0;
01218             handle->sn_coap_protocol_free(removed_duplication_info_ptr);
01219             removed_duplication_info_ptr = 0;
01220         }
01221     }
01222 }
01223 
01224 #endif /* SN_COAP_DUPLICATION_MAX_MSGS_COUNT */
01225 
01226 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
01227 /**************************************************************************//**
01228  * \fn static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr)
01229  *
01230  * \brief Removes stored blockwise message from Linked list
01231  *
01232  * \param removed_msg_ptr is message to be removed
01233  *****************************************************************************/
01234 
01235 static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr)
01236 {
01237     if( removed_msg_ptr->coap == handle ){
01238         ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_msg_ptr);
01239 
01240         if( removed_msg_ptr->coap_msg_ptr ){
01241             if (removed_msg_ptr->coap_msg_ptr->payload_ptr) {
01242                 handle->sn_coap_protocol_free(removed_msg_ptr->coap_msg_ptr->payload_ptr);
01243                 removed_msg_ptr->coap_msg_ptr->payload_ptr = 0;
01244             }
01245 
01246             sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_msg_ptr->coap_msg_ptr);
01247         }
01248 
01249         handle->sn_coap_protocol_free(removed_msg_ptr);
01250         removed_msg_ptr = 0;
01251     }
01252 }
01253 
01254 /**************************************************************************//**
01255  * \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)
01256  *
01257  * \brief Stores blockwise payload to Linked list
01258  *
01259  * \param *addr_ptr is pointer to Address information to be stored
01260  * \param stored_payload_len is length of stored Payload
01261  * \param *stored_payload_ptr is pointer to stored Payload
01262  *****************************************************************************/
01263 
01264 static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr,
01265         uint16_t stored_payload_len,
01266         uint8_t *stored_payload_ptr,
01267         uint8_t *token_ptr,
01268         uint8_t token_len,
01269         uint32_t block_number)
01270 {
01271     if (!addr_ptr || !stored_payload_len || !stored_payload_ptr) {
01272         return;
01273     }
01274 
01275     // Do not add duplicates to list, this could happen if server needs to retransmit block message again
01276     ns_list_foreach(coap_blockwise_payload_s, payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
01277         if ((0 == memcmp(addr_ptr->addr_ptr, payload_info_ptr->addr_ptr, addr_ptr->addr_len)) && (payload_info_ptr->port == addr_ptr->port)) {
01278             if (token_ptr) {
01279                 if (!payload_info_ptr->token_ptr || (payload_info_ptr->token_len != token_len) || (memcmp(payload_info_ptr->token_ptr, token_ptr, token_len))) {
01280                     continue;
01281                 }
01282             } else if (payload_info_ptr->token_ptr) {
01283                 continue;
01284             }
01285             if (payload_info_ptr->block_number == block_number) {
01286                 return;
01287             }
01288         }
01289     }
01290 
01291     coap_blockwise_payload_s *stored_blockwise_payload_ptr = NULL;
01292 
01293     /* * * * Allocating memory for stored Payload  * * * */
01294 
01295     /* Allocate memory for stored Payload's structure */
01296     stored_blockwise_payload_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_payload_s));
01297 
01298     if (stored_blockwise_payload_ptr == NULL) {
01299         tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate blockwise!");
01300         return;
01301     }
01302 
01303 
01304     /* Allocate memory for stored Payload's data */
01305     stored_blockwise_payload_ptr->payload_ptr = handle->sn_coap_protocol_malloc(stored_payload_len);
01306 
01307     if (stored_blockwise_payload_ptr->payload_ptr == NULL) {
01308         tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate payload!");
01309         handle->sn_coap_protocol_free(stored_blockwise_payload_ptr);
01310         stored_blockwise_payload_ptr = 0;
01311         return;
01312     }
01313 
01314     /* Allocate memory for stored Payload's address */
01315     stored_blockwise_payload_ptr->addr_ptr = handle->sn_coap_protocol_malloc(addr_ptr->addr_len);
01316 
01317     if (stored_blockwise_payload_ptr->addr_ptr == NULL) {
01318         tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate address pointer!");
01319         handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->payload_ptr);
01320         stored_blockwise_payload_ptr->payload_ptr = 0;
01321         handle->sn_coap_protocol_free(stored_blockwise_payload_ptr);
01322         stored_blockwise_payload_ptr = 0;
01323 
01324         return;
01325     }
01326 
01327     /* Allocate & copy token number */
01328     if (token_ptr && token_len) {
01329         stored_blockwise_payload_ptr->token_ptr = handle->sn_coap_protocol_malloc(token_len);
01330 
01331         if(!stored_blockwise_payload_ptr->token_ptr) {
01332             tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate token pointer!");
01333             handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->addr_ptr);
01334             handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->payload_ptr);
01335             handle->sn_coap_protocol_free(stored_blockwise_payload_ptr);
01336             return;
01337         }
01338 
01339         memcpy(stored_blockwise_payload_ptr->token_ptr, token_ptr, token_len);
01340         stored_blockwise_payload_ptr->token_len = token_len;
01341     } else {
01342         stored_blockwise_payload_ptr->token_ptr = NULL;
01343         stored_blockwise_payload_ptr->token_len = 0;
01344     }
01345 
01346     /* * * * Filling fields of stored Payload  * * * */
01347 
01348     stored_blockwise_payload_ptr->timestamp = handle->system_time;
01349 
01350     memcpy(stored_blockwise_payload_ptr->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len);
01351     stored_blockwise_payload_ptr->port = addr_ptr->port;
01352     memcpy(stored_blockwise_payload_ptr->payload_ptr, stored_payload_ptr, stored_payload_len);
01353     stored_blockwise_payload_ptr->payload_len = stored_payload_len;
01354 
01355     stored_blockwise_payload_ptr->coap = handle;
01356 
01357     stored_blockwise_payload_ptr->block_number = block_number;
01358 
01359     /* * * * Storing Payload to Linked list  * * * */
01360     ns_list_add_to_end(&handle->linked_list_blockwise_received_payloads, stored_blockwise_payload_ptr);
01361 }
01362 
01363 /**************************************************************************//**
01364  * \fn static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length)
01365  *
01366  * \brief Searches stored blockwise payload from Linked list (Address as key)
01367  *
01368  * \param *addr_ptr is pointer to Address key to be searched
01369  * \param *payload_length is pointer to returned Payload length
01370  *
01371  * \return Return value is pointer to found stored blockwise payload in Linked
01372  *         list or NULL if payload not found
01373  *****************************************************************************/
01374 
01375 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, uint8_t *token_ptr, uint8_t token_len)
01376 {
01377     /* Loop all stored blockwise payloads in Linked list */
01378     ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
01379         /* If payload's Source address and port is same than is searched */
01380         if ((0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (stored_payload_info_ptr->port == src_addr_ptr->port)) {
01381             /* Check token */
01382             if (token_ptr) {
01383                 if (!stored_payload_info_ptr->token_ptr || (token_len != stored_payload_info_ptr->token_len) || (memcmp(stored_payload_info_ptr->token_ptr, token_ptr, token_len))) {
01384                     continue;
01385                 }
01386             } else if (stored_payload_info_ptr->token_ptr) {
01387                 continue;
01388             }
01389             /* * * Correct Payload found * * * */
01390             *payload_length = stored_payload_info_ptr->payload_len;
01391             return stored_payload_info_ptr->payload_ptr;
01392         }
01393     }
01394 
01395     return NULL;
01396 }
01397 
01398 static bool sn_coap_protocol_linked_list_blockwise_payload_compare_block_number(struct coap_s *handle,
01399                                                                                    sn_nsdl_addr_s *src_addr_ptr,
01400                                                                                    uint8_t *token_ptr,
01401                                                                                    uint8_t token_len,
01402                                                                                    uint32_t block_number)
01403 {
01404     /* Loop all stored blockwise payloads in Linked list */
01405     ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
01406         /* If payload's Source address and port is same than is searched */
01407         if ((0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (stored_payload_info_ptr->port == src_addr_ptr->port)) {
01408             /* Check token number */
01409             if (token_ptr) {
01410                 if (!stored_payload_info_ptr->token_ptr || (token_len != stored_payload_info_ptr->token_len) || (memcmp(stored_payload_info_ptr->token_ptr, token_ptr, token_len))) {
01411                     continue;
01412                 }
01413             } else if (stored_payload_info_ptr->token_ptr) {
01414                 continue;
01415             }
01416             // Check that incoming block number matches to last received one
01417             if (block_number - 1 == stored_payload_info_ptr->block_number) {
01418                 return true;
01419             }
01420         }
01421     }
01422 
01423     return false;
01424 }
01425 
01426 /**************************************************************************//**
01427  * \fn static void sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle)
01428  *
01429  * \brief Removes current stored blockwise paylod from Linked list
01430  *****************************************************************************/
01431 
01432 static void sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle, uint8_t *token_ptr, uint8_t token_len)
01433 {
01434     /* Remove oldest node in Linked list*/
01435     if (token_ptr) {
01436         ns_list_foreach(coap_blockwise_payload_s, removed_payload_ptr, &handle->linked_list_blockwise_received_payloads) {
01437             if ((token_len == removed_payload_ptr->token_len) && !memcmp(removed_payload_ptr->token_ptr, token_ptr, token_len)) {
01438                 sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_payload_ptr);
01439                 return;
01440             }
01441         }
01442     } else {
01443         ns_list_foreach(coap_blockwise_payload_s, removed_payload_ptr, &handle->linked_list_blockwise_received_payloads) {
01444             if (!removed_payload_ptr->token_ptr) {
01445                 sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_payload_ptr);
01446                 return;
01447             }
01448         }
01449     }
01450 }
01451 
01452 /**************************************************************************//**
01453  * \fn static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle,
01454  *                                                      coap_blockwise_msg_s *removed_msg_ptr)
01455  *
01456  * \brief Removes stored blockwise payload from Linked list
01457  *
01458  * \param removed_payload_ptr is payload to be removed
01459  *****************************************************************************/
01460 
01461 static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle,
01462                                                                   coap_blockwise_payload_s *removed_payload_ptr)
01463 {
01464     ns_list_remove(&handle->linked_list_blockwise_received_payloads, removed_payload_ptr);
01465     /* Free memory of stored payload */
01466     if (removed_payload_ptr->addr_ptr != NULL) {
01467         handle->sn_coap_protocol_free(removed_payload_ptr->addr_ptr);
01468         removed_payload_ptr->addr_ptr = 0;
01469     }
01470 
01471     if (removed_payload_ptr->payload_ptr != NULL) {
01472         handle->sn_coap_protocol_free(removed_payload_ptr->payload_ptr);
01473         removed_payload_ptr->payload_ptr = 0;
01474     }
01475 
01476     if (removed_payload_ptr->token_ptr != NULL) {
01477         handle->sn_coap_protocol_free(removed_payload_ptr->token_ptr);
01478         removed_payload_ptr->token_ptr = 0;
01479     }
01480 
01481     handle->sn_coap_protocol_free(removed_payload_ptr);
01482     removed_payload_ptr = 0;
01483 }
01484 
01485 /**************************************************************************//**
01486  * \fn static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(sn_nsdl_addr_s *src_addr_ptr)
01487  *
01488  * \brief Counts length of Payloads in Linked list (Address as key)
01489  *
01490  * \param *addr_ptr is pointer to Address key
01491  *
01492  * \return Return value is length of Payloads as bytes
01493  *****************************************************************************/
01494 
01495 static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint8_t *token_ptr, uint8_t token_len)
01496 {
01497     uint32_t ret_whole_payload_len = 0;
01498     /* Loop all stored blockwise payloads in Linked list */
01499     ns_list_foreach(coap_blockwise_payload_s, searched_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
01500         /* If payload's Source address and port is same than is searched */
01501         if ((0 == memcmp(src_addr_ptr->addr_ptr, searched_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (searched_payload_info_ptr->port == src_addr_ptr->port)) {
01502             /* Check token */
01503             if (token_ptr) {
01504                 if(!searched_payload_info_ptr->token_ptr || (token_len != searched_payload_info_ptr->token_len) || (memcmp(searched_payload_info_ptr->token_ptr, token_ptr, token_len))) {
01505                     continue;
01506                 }
01507             } else if (searched_payload_info_ptr->token_ptr) {
01508                 continue;
01509             }
01510             /* * * Correct Payload found * * * */
01511             ret_whole_payload_len += searched_payload_info_ptr->payload_len;
01512         }
01513     }
01514 
01515     return ret_whole_payload_len;
01516 }
01517 
01518 /**************************************************************************//**
01519  * \fn static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle)
01520  *
01521  * \brief Check incoming and outgoing blockwise messages for time out.
01522  *        Remove timed out messages from lists. Notify application if
01523  *        outgoing message times out.
01524  *****************************************************************************/
01525 
01526 static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle)
01527 {
01528     /* Loop all outgoing blockwise messages */
01529     ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) {
01530         if ((handle->system_time - removed_blocwise_msg_ptr->timestamp)  > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) {
01531 
01532             // Item must be removed from the list before calling the rx_callback function.
01533             // Callback could actually clear the list and free the item and cause a use after free when callback returns.
01534             ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_blocwise_msg_ptr);
01535 
01536             /* * * * This messages has timed out, remove it from Linked list * * * */
01537             if( removed_blocwise_msg_ptr->coap_msg_ptr ){
01538                 if (handle->sn_coap_rx_callback) {
01539                     /* Notify the application about the time out */
01540                     removed_blocwise_msg_ptr->coap_msg_ptr->coap_status = COAP_STATUS_BUILDER_BLOCK_SENDING_FAILED;
01541                     removed_blocwise_msg_ptr->coap_msg_ptr->msg_id = removed_blocwise_msg_ptr->msg_id;
01542                     handle->sn_coap_rx_callback(removed_blocwise_msg_ptr->coap_msg_ptr, NULL, removed_blocwise_msg_ptr->param);
01543                 }
01544 
01545                 handle->sn_coap_protocol_free(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr);
01546                 sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_blocwise_msg_ptr->coap_msg_ptr);
01547             }
01548 
01549             handle->sn_coap_protocol_free(removed_blocwise_msg_ptr);
01550         }
01551     }
01552 
01553 
01554     /* Loop all incoming Blockwise messages */
01555     ns_list_foreach_safe(coap_blockwise_payload_s, removed_blocwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) {
01556         if ((handle->system_time - removed_blocwise_payload_ptr->timestamp)  > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) {
01557             /* * * * This messages has timed out, remove it from Linked list * * * */
01558             sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_blocwise_payload_ptr);
01559         }
01560     }
01561 }
01562 
01563 #endif /* SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */
01564 
01565 
01566 #if ENABLE_RESENDINGS  /* If Message resending is not used at all, this part of code will not be compiled */
01567 /***************************************************************************//**
01568  * \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)
01569  *
01570  * \brief Allocates memory for given message (send or blockwise message)
01571  *
01572  * \param *dst_addr_ptr is pointer to destination address where message will be sent
01573  * \param packet_data_len is length of allocated Packet data
01574  * \param uri_path_len is length of messages path url
01575  *
01576  * \return pointer to allocated struct
01577  *****************************************************************************/
01578 
01579 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)
01580 {
01581 
01582     coap_send_msg_s *msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_send_msg_s));
01583 
01584     if (msg_ptr == NULL) {
01585         return NULL;
01586     }
01587 
01588     //Locall structure for 1 malloc for send msg
01589     struct
01590     {
01591         sn_nsdl_transmit_s transmit;
01592         sn_nsdl_addr_s addr;
01593         uint8_t trail_data[];
01594     } *m;
01595     int trail_size = dst_addr_ptr->addr_len + packet_data_len;
01596 
01597     m = handle->sn_coap_protocol_malloc(sizeof *m + trail_size);
01598     if (!m) {
01599         handle->sn_coap_protocol_free(msg_ptr);
01600         return NULL;
01601     }
01602     //Init data
01603     memset(m, 0, sizeof(*m) + trail_size);
01604     memset(msg_ptr, 0, sizeof(coap_send_msg_s));
01605 
01606     msg_ptr->send_msg_ptr = &m->transmit;
01607     msg_ptr->send_msg_ptr->dst_addr_ptr = &m->addr;
01608 
01609     msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr = m->trail_data;
01610     if (packet_data_len) {
01611         msg_ptr->send_msg_ptr->packet_ptr = m->trail_data + dst_addr_ptr->addr_len;
01612     }
01613 
01614     return msg_ptr;
01615 }
01616 
01617 
01618 /**************************************************************************//**
01619  * \fn static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr)
01620  *
01621  * \brief Releases memory of given Sending message (coap_send_msg_s)
01622  *
01623  * \param *freed_send_msg_ptr is pointer to released Sending message
01624  *****************************************************************************/
01625 
01626 static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr)
01627 {
01628     if (freed_send_msg_ptr != NULL) {
01629         handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr);
01630         freed_send_msg_ptr->send_msg_ptr = NULL;
01631         handle->sn_coap_protocol_free(freed_send_msg_ptr);
01632         freed_send_msg_ptr = NULL;
01633     }
01634 }
01635 
01636 /**************************************************************************//**
01637  * \fn static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr)
01638  *
01639  * \brief Counts total message size of all messages in linked list
01640  *
01641  * \param const coap_send_msg_list_t *linked_list_ptr pointer to linked list
01642  *****************************************************************************/
01643 static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr)
01644 {
01645     uint16_t total_size = 0;
01646 
01647     ns_list_foreach(coap_send_msg_s, stored_msg_ptr, linked_list_ptr) {
01648         if (stored_msg_ptr->send_msg_ptr) {
01649             total_size += stored_msg_ptr->send_msg_ptr->packet_len;
01650         }
01651     }
01652 
01653     return total_size;
01654 }
01655 
01656 #endif
01657 
01658 #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
01659 void sn_coap_protocol_remove_sent_blockwise_message(struct coap_s *handle, uint16_t msg_id)
01660 {
01661     if (!handle) {
01662         return;
01663     }
01664 
01665     ns_list_foreach_safe(coap_blockwise_msg_s, tmp, &handle->linked_list_blockwise_sent_msgs) {
01666         if (tmp->coap == handle && tmp->coap_msg_ptr && tmp->coap_msg_ptr->msg_id == msg_id) {
01667             handle->sn_coap_protocol_free(tmp->coap_msg_ptr->payload_ptr);
01668             sn_coap_parser_release_allocated_coap_msg_mem(tmp->coap, tmp->coap_msg_ptr);
01669             ns_list_remove(&handle->linked_list_blockwise_sent_msgs, tmp);
01670             handle->sn_coap_protocol_free(tmp);
01671             break;
01672         }
01673     }
01674 }
01675 
01676 void sn_coap_protocol_block_remove(struct coap_s *handle, sn_nsdl_addr_s *source_address, uint16_t payload_length, void *payload)
01677 {
01678     if (!handle || !source_address || !payload) {
01679         return;
01680     }
01681 
01682     /* Loop all stored blockwise payloads in Linked list */
01683     ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
01684         /* If payload's Source address is not the same than is searched */
01685         if (memcmp(source_address->addr_ptr, stored_payload_info_ptr->addr_ptr, source_address->addr_len)) {
01686             continue;
01687         }
01688 
01689         /* If payload's Source address port is not the same than is searched */
01690         if (stored_payload_info_ptr->port != source_address->port) {
01691             continue;
01692         }
01693 
01694         /* Check the payload */
01695         if(payload_length != stored_payload_info_ptr->payload_len){
01696             continue;
01697         }
01698 
01699         if(!memcmp(stored_payload_info_ptr->payload_ptr, payload, stored_payload_info_ptr->payload_len))
01700         {
01701             /* Everything matches, remove and return. */
01702             sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_payload_info_ptr);
01703             return;
01704         }
01705     }
01706 }
01707 
01708 /****************************************************************************
01709  * \fn coap_blockwise_msg_s *sn_coap_stored_blockwise_msg_get(struct coap_s *handle, sn_coap_hdr_s *received_coap_msg_ptr)
01710  *
01711  * \brief Get blockwise message from list
01712  *
01713  * \param *handle Pointer to the coap handle structure
01714  * \param *received_coap_msg_ptr Pointer to parsed CoAP message structure
01715  *****************************************************************************/
01716 static coap_blockwise_msg_s *sn_coap_stored_blockwise_msg_get(struct coap_s *handle, sn_coap_hdr_s *received_coap_msg_ptr)
01717 {
01718     ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
01719         if (!received_coap_msg_ptr->token_ptr && !msg->coap_msg_ptr->token_ptr) {
01720             return msg;
01721         } else if ((received_coap_msg_ptr->token_len == msg->coap_msg_ptr->token_len) && (!memcmp(received_coap_msg_ptr->token_ptr, msg->coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len))) {
01722             return msg;
01723         }
01724     }
01725 
01726     return NULL;
01727 }
01728 
01729 /**************************************************************************//**
01730  * \fn static int8_t sn_coap_handle_blockwise_message(void)
01731  *
01732  * \brief Handles all received blockwise messages
01733  *
01734  * \param *src_addr_ptr pointer to source address information struct
01735  * \param *received_coap_msg_ptr pointer to parsed CoAP message structure
01736  *****************************************************************************/
01737 
01738 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)
01739 {
01740     sn_coap_hdr_s *src_coap_blockwise_ack_msg_ptr = NULL;
01741     uint16_t dst_packed_data_needed_mem = 0;
01742     uint8_t *dst_ack_packet_data_ptr = NULL;
01743     uint8_t block_temp = 0;
01744 
01745     uint16_t original_payload_len = 0;
01746     uint8_t *original_payload_ptr = NULL;
01747 
01748     /* Block1 Option in a request (e.g., PUT or POST) */
01749     // Blocked request sending, received ACK, sending next block..
01750     if (received_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
01751         if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) {
01752             if (received_coap_msg_ptr->options_list_ptr->block1 & 0x08) {
01753                 coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = NULL;
01754 
01755                 /* Get  */
01756                 ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
01757                     if (msg->coap_msg_ptr && received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
01758                         stored_blockwise_msg_temp_ptr = msg;
01759                         break;
01760                     }
01761                 }
01762 
01763                 if (stored_blockwise_msg_temp_ptr) {
01764                     /* Build response message */
01765 
01766                     uint16_t block_size;
01767                     uint32_t block_number;
01768 
01769                     /* Get block option parameters from received message */
01770                     block_number = received_coap_msg_ptr->options_list_ptr->block1 >> 4;
01771                     block_temp = received_coap_msg_ptr->options_list_ptr->block1 & 0x07;
01772                     block_size = 1u << (block_temp + 4);
01773 
01774                     /* Build next block message */
01775                     src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr;
01776 
01777                     if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) {
01778                         src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
01779                         src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
01780                     } else {
01781                         if (!sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr)) {
01782                             tr_error("sn_coap_handle_blockwise_message - (send block1) failed to allocate ack message!");
01783                             sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
01784                             return 0;
01785                         }
01786                     }
01787 
01788                     block_number++;
01789                     src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = (block_number << 4) | block_temp;
01790 
01791                     original_payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len;
01792                     original_payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr;
01793 
01794                     if ((block_size * (block_number + 1)) > stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) {
01795                         src_coap_blockwise_ack_msg_ptr->payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len - (block_size * (block_number));
01796                         src_coap_blockwise_ack_msg_ptr->payload_ptr = src_coap_blockwise_ack_msg_ptr->payload_ptr + (block_size * block_number);
01797                     }
01798 
01799                     /* Not last block */
01800                     else {
01801                         /* set more - bit */
01802                         src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= 0x08;
01803                         src_coap_blockwise_ack_msg_ptr->payload_len = block_size;
01804                         src_coap_blockwise_ack_msg_ptr->payload_ptr = src_coap_blockwise_ack_msg_ptr->payload_ptr + (block_size * block_number);
01805                     }
01806                     /* Build and send block message */
01807                     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);
01808 
01809                     dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
01810                     if (!dst_ack_packet_data_ptr) {
01811                         tr_error("sn_coap_handle_blockwise_message - (send block1) failed to allocate ack message!");
01812                         handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
01813                         src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
01814                         handle->sn_coap_protocol_free(original_payload_ptr);
01815                         original_payload_ptr = 0;
01816                         handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
01817                         src_coap_blockwise_ack_msg_ptr = 0;
01818                         stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL;
01819                         sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
01820                         return NULL;
01821                     }
01822                     src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
01823                     if (message_id == 0) {
01824                         message_id = 1;
01825                     }
01826 
01827                     sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
01828 
01829                     handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param);
01830 
01831 #if ENABLE_RESENDINGS
01832                     uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
01833                     if (src_coap_blockwise_ack_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
01834                         sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
01835                                 dst_packed_data_needed_mem,
01836                                 dst_ack_packet_data_ptr,
01837                                 resend_time, param);
01838                     }
01839 #endif
01840 
01841                     handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
01842                     dst_ack_packet_data_ptr = 0;
01843 
01844                     stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len;
01845                     stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr;
01846 
01847                     received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK;
01848 
01849                     // Remove original message from the list when last block has been sent.
01850                     if (!((src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1) & 0x08)) {
01851                         sn_coap_protocol_remove_sent_blockwise_message(handle, stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id);
01852                     }
01853                 }
01854             } else {
01855                 // XXX what was this trying to free?
01856                 received_coap_msg_ptr->coap_status = COAP_STATUS_OK;
01857 
01858             }
01859         }
01860 
01861         // Blocked request receiving
01862         else {
01863             if (received_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) {
01864                 received_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size;
01865             }
01866 
01867             // Check that incoming block number is in order.
01868             uint32_t block_number = received_coap_msg_ptr->options_list_ptr->block1 >> 4;
01869             bool blocks_in_order = true;
01870 
01871             if (block_number > 0 &&
01872                 !sn_coap_protocol_linked_list_blockwise_payload_compare_block_number(handle,
01873                                                                                      src_addr_ptr,
01874                                                                                      received_coap_msg_ptr->token_ptr,
01875                                                                                      received_coap_msg_ptr->token_len,
01876                                                                                      block_number)) {
01877                 blocks_in_order = false;
01878             }
01879 
01880             sn_coap_protocol_linked_list_blockwise_payload_store(handle,
01881                                                                  src_addr_ptr,
01882                                                                  received_coap_msg_ptr->payload_len,
01883                                                                  received_coap_msg_ptr->payload_ptr,
01884                                                                  received_coap_msg_ptr->token_ptr,
01885                                                                  received_coap_msg_ptr->token_len,
01886                                                                  block_number);
01887 
01888             /* If not last block (more value is set) */
01889             /* 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. */
01890             if (received_coap_msg_ptr->options_list_ptr->block1 & 0x08) {
01891                 src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle);
01892                 if (src_coap_blockwise_ack_msg_ptr == NULL) {
01893                     tr_error("sn_coap_handle_blockwise_message - (recv block1) failed to allocate ack message!");
01894                     sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
01895                     return NULL;
01896                 }
01897 
01898                 if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
01899                    tr_error("sn_coap_handle_blockwise_message - (recv block1) failed to allocate options!");
01900                     handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
01901                     src_coap_blockwise_ack_msg_ptr = 0;
01902                     sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
01903                     return NULL;
01904                 }
01905 
01906                 if (!blocks_in_order) {
01907                     tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE!");
01908                     src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE;
01909                 } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) {
01910                     src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
01911                 } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) {
01912                     src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTINUE;
01913                 } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) {
01914                     src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTINUE;
01915                 } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) {
01916                     src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_DELETED;
01917                 }
01918 
01919                 // Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle
01920                 if (received_coap_msg_ptr->options_list_ptr->size1 > SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE) {
01921                     // Include maximum size that stack can handle into response
01922                     tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
01923                     src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
01924                 }
01925                 else {
01926                     src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1;
01927                     src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
01928 
01929                     /* Check block size */
01930                     block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07);
01931                     uint16_t block_size = 1u << (block_temp + 4);
01932                     if (block_size >  handle->sn_coap_block_data_size) {
01933                          // Include maximum size that stack can handle into response
01934                          tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
01935                          src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
01936                          src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1 = handle->sn_coap_block_data_size;
01937                          sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
01938                     }
01939 
01940                     if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) {
01941                         src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8;
01942                         src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
01943                     }
01944                 }
01945 
01946                 src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id;
01947 
01948                 // Copy token to response
01949                 src_coap_blockwise_ack_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(received_coap_msg_ptr->token_len);
01950                 if (src_coap_blockwise_ack_msg_ptr->token_ptr) {
01951                     memcpy(src_coap_blockwise_ack_msg_ptr->token_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
01952                     src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len;
01953                 }
01954 
01955                 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);
01956 
01957                 dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
01958                 if (!dst_ack_packet_data_ptr) {
01959                     tr_error("sn_coap_handle_blockwise_message - (recv block1) message allocation failed!");
01960                     sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
01961                     handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
01962                     src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
01963                     handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
01964                     src_coap_blockwise_ack_msg_ptr = 0;
01965                     return NULL;
01966                 }
01967 
01968                 sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
01969                 handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param);
01970 
01971                 sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
01972                 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
01973                 dst_ack_packet_data_ptr = 0;
01974 
01975                 received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
01976 
01977             } else {
01978                 /* * * This is the last block when whole Blockwise payload from received * * */
01979                 /* * * blockwise messages is gathered and returned to User               * * */
01980 
01981                 /* Store last Blockwise payload to Linked list */
01982                 uint16_t payload_len            = 0;
01983                 uint8_t *payload_ptr            = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
01984                 uint32_t whole_payload_len      = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
01985                 uint8_t *temp_whole_payload_ptr = NULL;
01986 
01987                 temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
01988                 if (temp_whole_payload_ptr == NULL || whole_payload_len > UINT16_MAX) {
01989                     tr_error("sn_coap_handle_blockwise_message - (recv block1) failed to allocate all blocks!");
01990                     sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
01991                     handle->sn_coap_protocol_free(temp_whole_payload_ptr);
01992                     return 0;
01993                 }
01994 
01995                 // In block message case, payload_ptr freeing must be done in application level
01996                 received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr;
01997                 received_coap_msg_ptr->payload_len = whole_payload_len;
01998 
01999                 /* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */
02000                 while (payload_ptr != NULL) {
02001                     memcpy(temp_whole_payload_ptr, payload_ptr, payload_len);
02002                     temp_whole_payload_ptr += payload_len;
02003                     sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
02004                     payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
02005                 }
02006                 received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
02007             }
02008         }
02009     }
02010 
02011 
02012     /* Block2 Option in a response (e.g., a 2.05 response for GET) */
02013     /* Message ID must be same than in received message */
02014     else {
02015         //This is response to request we made
02016         if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) {
02017             if (handle->sn_coap_internal_block2_resp_handling) {
02018                 uint32_t block_number = 0;
02019 
02020                 /* Store blockwise payload to Linked list */
02021                 //todo: add block number to stored values - just to make sure all packets are in order
02022                 sn_coap_protocol_linked_list_blockwise_payload_store(handle,
02023                                                                      src_addr_ptr,
02024                                                                      received_coap_msg_ptr->payload_len,
02025                                                                      received_coap_msg_ptr->payload_ptr,
02026                                                                      received_coap_msg_ptr->token_ptr,
02027                                                                      received_coap_msg_ptr->token_len,
02028                                                                      received_coap_msg_ptr->options_list_ptr->block2 >> 4);
02029                 /* If not last block (more value is set) */
02030                 if (received_coap_msg_ptr->options_list_ptr->block2 & 0x08) {
02031                     coap_blockwise_msg_s *previous_blockwise_msg_ptr = NULL;
02032                     //build and send ack
02033                     received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
02034 
02035                     ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
02036                         if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
02037                             previous_blockwise_msg_ptr = msg;
02038                             break;
02039                         }
02040                     }
02041 
02042                     if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) {
02043                         tr_error("sn_coap_handle_blockwise_message - (send block2) previous message null!");
02044                         sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
02045                         return 0;
02046                     }
02047 
02048                     src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle);
02049                     if (src_coap_blockwise_ack_msg_ptr == NULL) {
02050                         tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate message!");
02051                         return 0;
02052                     }
02053 
02054                     /* * * Then build CoAP Acknowledgement message * * */
02055 
02056                     if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
02057                         tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate options!");
02058                         handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
02059                         src_coap_blockwise_ack_msg_ptr = 0;
02060                         sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
02061                         return NULL;
02062                     }
02063 
02064                     src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
02065                     if (message_id == 0) {
02066                         message_id = 1;
02067                     }
02068 
02069                     /* Update block option */
02070                     block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
02071 
02072                     block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
02073                     block_number ++;
02074 
02075                     src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = (block_number << 4) | block_temp;
02076 
02077 
02078                     /* Set BLOCK2 (subsequent) GET msg code and copy uri path from previous msg*/
02079                     src_coap_blockwise_ack_msg_ptr->msg_code = previous_blockwise_msg_ptr->coap_msg_ptr->msg_code;
02080                     if (previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr) {
02081                         src_coap_blockwise_ack_msg_ptr->uri_path_len = previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len;
02082                         src_coap_blockwise_ack_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len);
02083                         if (!src_coap_blockwise_ack_msg_ptr->uri_path_ptr) {
02084                             sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
02085                             tr_error("sn_coap_handle_blockwise_message - failed to allocate for uri path ptr!");
02086                             return NULL;
02087                         }
02088                         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);
02089                     }
02090                     if (previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr) {
02091                         src_coap_blockwise_ack_msg_ptr->token_len = previous_blockwise_msg_ptr->coap_msg_ptr->token_len;
02092                         src_coap_blockwise_ack_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->token_len);
02093                         if (!src_coap_blockwise_ack_msg_ptr->token_ptr) {
02094                             sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
02095                             tr_error("sn_coap_handle_blockwise_message - failed to allocate for token ptr!");
02096                             return NULL;
02097                         }
02098                         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);
02099                     }
02100 
02101                     ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr);
02102                     if (previous_blockwise_msg_ptr->coap_msg_ptr) {
02103                         if (previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) {
02104                             handle->sn_coap_protocol_free(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr);
02105                             previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = 0;
02106                         }
02107                         sn_coap_parser_release_allocated_coap_msg_mem(handle, previous_blockwise_msg_ptr->coap_msg_ptr);
02108                         previous_blockwise_msg_ptr->coap_msg_ptr = 0;
02109                     }
02110                     handle->sn_coap_protocol_free(previous_blockwise_msg_ptr);
02111                     previous_blockwise_msg_ptr = 0;
02112 
02113                     /* Then get needed memory count for Packet data */
02114                     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);
02115 
02116                     /* Then allocate memory for Packet data */
02117                     dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
02118 
02119                     if (dst_ack_packet_data_ptr == NULL) {
02120                         tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate packet!");
02121                         sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
02122                         sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
02123                         return NULL;
02124                     }
02125                     memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem);
02126 
02127                     /* * * Then build Acknowledgement message to Packed data * * */
02128                     if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) {
02129                         tr_error("sn_coap_handle_blockwise_message - (send block2) builder failed!");
02130                         handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
02131                         dst_ack_packet_data_ptr = 0;
02132                         sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
02133                         sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
02134                         return NULL;
02135                     }
02136 
02137                     /* * * Save to linked list * * */
02138                     coap_blockwise_msg_s *stored_blockwise_msg_ptr;
02139 
02140                     stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
02141                     if (!stored_blockwise_msg_ptr) {
02142                         tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate blockwise message!");
02143                         handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
02144                         dst_ack_packet_data_ptr = 0;
02145                         sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
02146                         sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
02147                         return 0;
02148                     }
02149                     memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
02150 
02151                     stored_blockwise_msg_ptr->timestamp = handle->system_time;
02152 
02153                     stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr;
02154                     stored_blockwise_msg_ptr->coap = handle;
02155                     stored_blockwise_msg_ptr->param = param;
02156                     stored_blockwise_msg_ptr->msg_id = stored_blockwise_msg_ptr->coap_msg_ptr->msg_id;
02157                     ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
02158 
02159                     /* * * Then release memory of CoAP Acknowledgement message * * */
02160                     handle->sn_coap_tx_callback(dst_ack_packet_data_ptr,
02161                                                 dst_packed_data_needed_mem, src_addr_ptr, param);
02162 
02163 #if ENABLE_RESENDINGS
02164                     uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
02165                     sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
02166                             dst_packed_data_needed_mem,
02167                             dst_ack_packet_data_ptr,
02168                             resend_time, param);
02169 #endif
02170                     handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
02171                     dst_ack_packet_data_ptr = 0;
02172                 }
02173 
02174                 //Last block received
02175                 else {
02176                     /* * * This is the last block when whole Blockwise payload from received * * */
02177                     /* * * blockwise messages is gathered and returned to User               * * */
02178 
02179                     /* Store last Blockwise payload to Linked list */
02180                     uint16_t payload_len            = 0;
02181                     uint8_t *payload_ptr            = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
02182                     uint16_t whole_payload_len      = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
02183                     uint8_t *temp_whole_payload_ptr = NULL;
02184 
02185                     temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
02186                     if (!temp_whole_payload_ptr) {
02187                         tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate whole payload!");
02188                         return 0;
02189                     }
02190 
02191                     received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr;
02192                     received_coap_msg_ptr->payload_len = whole_payload_len;
02193 
02194                     /* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */
02195                     while (payload_ptr != NULL) {
02196                         memcpy(temp_whole_payload_ptr, payload_ptr, payload_len);
02197 
02198                         temp_whole_payload_ptr += payload_len;
02199 
02200                         sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
02201                         payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
02202                     }
02203                     received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
02204 
02205                     //todo: remove previous msg from list
02206                 }
02207             }
02208         }
02209 
02210         //Now we send data to request
02211         else {
02212             //Get message by using block number
02213             //NOTE: Getting the first from list might not be correct one
02214             coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = sn_coap_stored_blockwise_msg_get(handle, received_coap_msg_ptr);
02215             if (stored_blockwise_msg_temp_ptr) {
02216                 uint16_t block_size;
02217                 uint32_t block_number;
02218 
02219                 /* Resolve block parameters */
02220                 block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
02221                 block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
02222                 block_size = 1u << (block_temp + 4);
02223                 /* Build response message */
02224                 src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr;
02225 
02226                 if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) {
02227                     src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
02228                     src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
02229                 } else {
02230                     if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
02231                         tr_error("sn_coap_handle_blockwise_message - (recv block2) failed to allocate options!");
02232                         return 0;
02233                     }
02234                 }
02235 
02236                 src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id;
02237 
02238                 src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = received_coap_msg_ptr->options_list_ptr->block2;
02239 
02240                 /* * Payload part * */
02241 
02242                 /* Check if last block */
02243 
02244                 original_payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len;
02245                 original_payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr;
02246 
02247                 if ((block_size * (block_number + 1)) >= stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) {
02248                     src_coap_blockwise_ack_msg_ptr->payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len - (block_size * block_number);
02249                     src_coap_blockwise_ack_msg_ptr->payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr + (block_size * block_number);
02250                 }
02251                 /* Not last block */
02252                 else {
02253                     /* set more - bit */
02254                     src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 |= 0x08;
02255                     src_coap_blockwise_ack_msg_ptr->payload_len = block_size;
02256                     src_coap_blockwise_ack_msg_ptr->payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr + (block_size * block_number);
02257                 }
02258 
02259                 /* Update token to match one which is in GET request.
02260                  * This is needed only in case of notification message.
02261                 */
02262                 if (src_coap_blockwise_ack_msg_ptr->options_list_ptr &&
02263                     src_coap_blockwise_ack_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
02264                     if (received_coap_msg_ptr->token_len && src_coap_blockwise_ack_msg_ptr->token_ptr) {
02265                         handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->token_ptr);
02266                         src_coap_blockwise_ack_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(received_coap_msg_ptr->token_len);
02267                         if (src_coap_blockwise_ack_msg_ptr->token_ptr) {
02268                             memcpy(src_coap_blockwise_ack_msg_ptr->token_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
02269                             src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len;
02270                         }
02271                     }
02272                 }
02273 
02274                 /* Build and send block message */
02275                 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);
02276 
02277                 dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
02278                 if (!dst_ack_packet_data_ptr) {
02279                     tr_error("sn_coap_handle_blockwise_message - (recv block2) failed to allocate packet!");
02280                     if(original_payload_ptr){
02281                         handle->sn_coap_protocol_free(original_payload_ptr);
02282                         original_payload_ptr = NULL;
02283                     }
02284                     sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
02285                     stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL;
02286                     return NULL;
02287                 }
02288 
02289                 sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
02290                 handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param);
02291 
02292                 handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
02293                 dst_ack_packet_data_ptr = 0;
02294 
02295                 stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len;
02296                 stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr;
02297 
02298                 if ((block_size * (block_number + 1)) >= stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) {
02299 
02300                     if (handle->sn_coap_rx_callback) {
02301                         stored_blockwise_msg_temp_ptr->coap_msg_ptr->coap_status = COAP_STATUS_BUILDER_BLOCK_SENDING_DONE;
02302                         stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id = stored_blockwise_msg_temp_ptr->msg_id;
02303                         handle->sn_coap_rx_callback(stored_blockwise_msg_temp_ptr->coap_msg_ptr, NULL, stored_blockwise_msg_temp_ptr->param);
02304                     }
02305 
02306                     sn_coap_protocol_linked_list_blockwise_msg_remove(handle, stored_blockwise_msg_temp_ptr);
02307                 }
02308 
02309                 received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK;
02310             }
02311         }
02312     }
02313     return received_coap_msg_ptr;
02314 }
02315 
02316 int8_t sn_coap_convert_block_size(uint16_t block_size)
02317 {
02318     if (block_size == 16) {
02319         return 0;
02320     } else if (block_size == 32) {
02321         return 1;
02322     } else if (block_size == 64) {
02323         return 2;
02324     } else if (block_size == 128) {
02325         return 3;
02326     } else if (block_size == 256) {
02327         return 4;
02328     } else if (block_size == 512) {
02329         return 5;
02330     } else if (block_size == 1024) {
02331         return 6;
02332     }
02333 
02334     return 0;
02335 }
02336 
02337 static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr)
02338 {
02339     sn_coap_hdr_s *destination_header_ptr;
02340 
02341     destination_header_ptr = sn_coap_parser_alloc_message(handle);
02342     if (!destination_header_ptr) {
02343         tr_error("sn_coap_protocol_copy_header - failed to allocate message!");
02344         return 0;
02345     }
02346 
02347     destination_header_ptr->coap_status = source_header_ptr->coap_status;
02348     destination_header_ptr->msg_type = source_header_ptr->msg_type;
02349     destination_header_ptr->msg_code = source_header_ptr->msg_code;
02350     destination_header_ptr->msg_id = source_header_ptr->msg_id;
02351 
02352     if (source_header_ptr->uri_path_ptr) {
02353         destination_header_ptr->uri_path_len = source_header_ptr->uri_path_len;
02354         destination_header_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->uri_path_len);
02355         if (!destination_header_ptr->uri_path_ptr) {
02356             tr_error("sn_coap_protocol_copy_header - failed to allocate uri path!");
02357             sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02358             return 0;
02359         }
02360         memcpy(destination_header_ptr->uri_path_ptr, source_header_ptr->uri_path_ptr, source_header_ptr->uri_path_len);
02361     }
02362 
02363     if (source_header_ptr->token_ptr) {
02364         destination_header_ptr->token_len = source_header_ptr->token_len;
02365         destination_header_ptr->token_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->token_len);
02366         if (!destination_header_ptr->token_ptr) {
02367             sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02368             tr_error("sn_coap_protocol_copy_header - failed to allocate token!");
02369             return 0;
02370         }
02371         memcpy(destination_header_ptr->token_ptr, source_header_ptr->token_ptr, source_header_ptr->token_len);
02372     }
02373 
02374     destination_header_ptr->content_format = source_header_ptr->content_format;
02375 
02376     /* Options list */
02377     if (source_header_ptr->options_list_ptr) {
02378         if (sn_coap_parser_alloc_options(handle, destination_header_ptr) == NULL) {
02379             sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02380             tr_error("sn_coap_protocol_copy_header - failed to allocate options!");
02381             return 0;
02382         }
02383 
02384         destination_header_ptr->options_list_ptr->max_age = source_header_ptr->options_list_ptr->max_age;
02385 
02386         if (source_header_ptr->options_list_ptr->proxy_uri_ptr) {
02387             destination_header_ptr->options_list_ptr->proxy_uri_len = source_header_ptr->options_list_ptr->proxy_uri_len;
02388             destination_header_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->proxy_uri_len);
02389             if (!destination_header_ptr->options_list_ptr->proxy_uri_ptr) {
02390                 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02391                 tr_error("sn_coap_protocol_copy_header - failed to allocate proxy uri!");
02392                 return 0;
02393             }
02394             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);
02395         }
02396 
02397         if (source_header_ptr->options_list_ptr->etag_ptr) {
02398             destination_header_ptr->options_list_ptr->etag_len = source_header_ptr->options_list_ptr->etag_len;
02399             destination_header_ptr->options_list_ptr->etag_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->etag_len);
02400             if (!destination_header_ptr->options_list_ptr->etag_ptr) {
02401                 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02402                 tr_error("sn_coap_protocol_copy_header - failed to allocate etag!");
02403                 return 0;
02404             }
02405             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);
02406         }
02407 
02408         if (source_header_ptr->options_list_ptr->uri_host_ptr) {
02409             destination_header_ptr->options_list_ptr->uri_host_len = source_header_ptr->options_list_ptr->uri_host_len;
02410             destination_header_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->uri_host_len);
02411             if (!destination_header_ptr->options_list_ptr->uri_host_ptr) {
02412                 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02413                 tr_error("sn_coap_protocol_copy_header - failed to allocate uri host!");
02414                 return 0;
02415             }
02416             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);
02417         }
02418 
02419         if (source_header_ptr->options_list_ptr->location_path_ptr) {
02420             destination_header_ptr->options_list_ptr->location_path_len = source_header_ptr->options_list_ptr->location_path_len;
02421             destination_header_ptr->options_list_ptr->location_path_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->location_path_len);
02422             if (!destination_header_ptr->options_list_ptr->location_path_ptr) {
02423                 tr_error("sn_coap_protocol_copy_header - failed to allocate location path!");
02424                 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02425                 return 0;
02426             }
02427             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);
02428         }
02429 
02430         destination_header_ptr->options_list_ptr->uri_port = source_header_ptr->options_list_ptr->uri_port;
02431 
02432         if (source_header_ptr->options_list_ptr->location_query_ptr) {
02433             destination_header_ptr->options_list_ptr->location_query_len = source_header_ptr->options_list_ptr->location_query_len;
02434             destination_header_ptr->options_list_ptr->location_query_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->location_query_len);
02435             if (!destination_header_ptr->options_list_ptr->location_query_ptr) {
02436                 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02437                 tr_error("sn_coap_protocol_copy_header - failed to allocate location query!");
02438                 return 0;
02439             }
02440             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);
02441         }
02442 
02443         destination_header_ptr->options_list_ptr->observe = source_header_ptr->options_list_ptr->observe;
02444         destination_header_ptr->options_list_ptr->accept = source_header_ptr->options_list_ptr->accept;
02445 
02446         if (source_header_ptr->options_list_ptr->uri_query_ptr) {
02447             destination_header_ptr->options_list_ptr->uri_query_len = source_header_ptr->options_list_ptr->uri_query_len;
02448             destination_header_ptr->options_list_ptr->uri_query_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->uri_query_len);
02449             if (!destination_header_ptr->options_list_ptr->uri_query_ptr) {
02450                 sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
02451                 tr_error("sn_coap_protocol_copy_header - failed to allocate uri query!");
02452                 return 0;
02453             }
02454             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);
02455         }
02456 
02457         destination_header_ptr->options_list_ptr->block1 = source_header_ptr->options_list_ptr->block1;
02458         destination_header_ptr->options_list_ptr->block2 = source_header_ptr->options_list_ptr->block2;
02459     }
02460 
02461     return destination_header_ptr;
02462 }
02463 #endif