ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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