Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_coap_protocol.c Source File

sn_coap_protocol.c

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