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