Rizky Ardi Maulana / mbed-os
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_coap_protocol.c Source File

sn_coap_protocol.c

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