Update mbed-coap to version 5.1.11

- Block-Wise request (block1) error handling improvements
- Fix regression from previous release concerning 1024 byte blocksize operations.
- Do not store ACK's into duplicate list.
- Code size optimizations
pull/14769/head
Antti Yli-Tokola 2021-06-14 09:42:13 +03:00
parent 9c6fe22ea2
commit 9f440a242f
9 changed files with 648 additions and 613 deletions

View File

@ -1,4 +1,18 @@
# Change Log # Change Log
## [v5.1.11](https://github.com/ARMmbed/mbed-coap/releases/tag/v5.1.11)
Block-Wise request (block1) error handling improvements:
* Removed SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED usage. Block-Wise requests will now follow normal retranmission rules.
* Process block1 responses only once. If response is coming in wrong order just ignore it wait next response to happen.
## [v5.1.10](https://github.com/ARMmbed/mbed-coap/releases/tag/v5.1.10)
- Fix regression from previous release concerning 1024 byte blocksize operations.
- Do not store ACK's into duplicate list.
## [v5.1.9](https://github.com/ARMmbed/mbed-coap/releases/tag/v5.1.9)
- Code size optimizations.
## [v5.1.8](https://github.com/ARMmbed/mbed-coap/releases/tag/v5.1.8) ## [v5.1.8](https://github.com/ARMmbed/mbed-coap/releases/tag/v5.1.8)

View File

@ -15,6 +15,9 @@ TEST_MODULES = ./test_modules
TEST_MODULE_MBED_TRACE = $(TEST_MODULES)/mbed-trace TEST_MODULE_MBED_TRACE = $(TEST_MODULES)/mbed-trace
TEST_MODULE_NANOSTACK = $(TEST_MODULES)/nanostack-libservice TEST_MODULE_NANOSTACK = $(TEST_MODULES)/nanostack-libservice
TEST_MODULE_RANDLIB = $(TEST_MODULES)/mbed-client-randlib TEST_MODULE_RANDLIB = $(TEST_MODULES)/mbed-client-randlib
TEST_MODULE_CCPUTEST_VERSION = "v3.8"
TEST_MODULE_CPPUTEST = $(TEST_MODULES)/cpputest
TEST_MODULE_CPPUTEST_LIB = $(TEST_MODULE_CPPUTEST)/lib/libCppUTest.a
.PHONY: clone .PHONY: clone
clone: clone:
@ -33,13 +36,20 @@ clone:
if [ ! -d $(TEST_MODULE_RANDLIB) ]; \ if [ ! -d $(TEST_MODULE_RANDLIB) ]; \
then git clone --depth 1 git@github.com:ARMmbed/mbed-client-randlib.git $(TEST_MODULE_RANDLIB); \ then git clone --depth 1 git@github.com:ARMmbed/mbed-client-randlib.git $(TEST_MODULE_RANDLIB); \
fi; fi;
if [ ! -d $(TEST_MODULE_CPPUTEST) ]; \
then git clone --single-branch -b $(TEST_MODULE_CCPUTEST_VERSION) https://github.com/cpputest/cpputest.git $(TEST_MODULE_CPPUTEST); \
fi;
.PHONY: test .PHONY: test
test: $(TESTDIRS) test: $(TEST_MODULE_CPPUTEST_LIB) $(TESTDIRS)
@rm -rf ./lcov @rm -rf ./lcov
@rm -rf ./coverage @rm -rf ./coverage
@rm -rf ./valgrind_logs
@mkdir -p lcov @mkdir -p lcov
@mkdir -p lcov/results @mkdir -p lcov/results
@mkdir coverage @mkdir coverage
@mkdir valgrind_logs
@find ./test -name '*.xml' | xargs cp -t ./lcov/results/ @find ./test -name '*.xml' | xargs cp -t ./lcov/results/
@rm -f lcov/index.xml @rm -f lcov/index.xml
@./xsl_script.sh @./xsl_script.sh
@ -47,16 +57,22 @@ test: $(TESTDIRS)
@xsltproc -o lcov/testresults.html lcov/junit_xsl.xslt lcov/index.xml @xsltproc -o lcov/testresults.html lcov/junit_xsl.xslt lcov/index.xml
@rm -f lcov/junit_xsl.xslt @rm -f lcov/junit_xsl.xslt
@rm -f lcov/index.xml @rm -f lcov/index.xml
@find ./ -name '*.gcno' | xargs cp --backup=numbered -t ./coverage/ @gcovr -r . --filter='.*/sn_coap_builder.c' --filter='.*/sn_coap_protocol.c' --filter='.*/sn_coap_parser.c' --filter='.*/sn_coap_header_check.c' -x -o ./lcov/gcovr.xml
@find ./ -name '*.gcda' | xargs cp --backup=numbered -t ./coverage/ @lcov -q -d test/. -c -o $(COVERAGEFILE)
@gcovr --object-directory ./coverage --exclude-unreachable-branches -e '.*/builds/.*' -e '.*/CppUTest/.*' -e '.*/mbed-client-libservice/.*' -e '.*/test/.*' -e '.*/stubs/.*' -e '.*/mbed-coap/.*' -x -o ./lcov/gcovr.xml
@lcov -d test/. -c -o $(COVERAGEFILE)
@lcov -q -r $(COVERAGEFILE) "/usr*" -o $(COVERAGEFILE) @lcov -q -r $(COVERAGEFILE) "/usr*" -o $(COVERAGEFILE)
@lcov -q -r $(COVERAGEFILE) "/test*" -o $(COVERAGEFILE) @lcov -q -r $(COVERAGEFILE) "*unittest*" -o $(COVERAGEFILE)
@lcov -q -r $(COVERAGEFILE) "/mbed-client-libservice*" -o $(COVERAGEFILE) @lcov -q -r $(COVERAGEFILE) "*test_modules*" -o $(COVERAGEFILE)
@genhtml -q $(COVERAGEFILE) --show-details --output-directory lcov/html @genhtml -q $(COVERAGEFILE) --show-details --output-directory lcov/html
@find ./test -name \valgrind*.xml -print0 | xargs -0 cp --target-directory=./valgrind_logs/
@echo mbed-coap module unit tests built @echo mbed-coap module unit tests built
$(TEST_MODULE_CPPUTEST_LIB):
cd $(TEST_MODULE_CPPUTEST) && \
./autogen.sh && \
./configure --disable-memory-leak-detection && \
make && \
cd $(CUR_DIR); \
$(TESTDIRS): $(TESTDIRS):
@make -C $(@:build-%=%) @make -C $(@:build-%=%)

View File

@ -23,6 +23,9 @@
#ifndef SN_COAP_HEADER_H_ #ifndef SN_COAP_HEADER_H_
#define SN_COAP_HEADER_H_ #define SN_COAP_HEADER_H_
#include "sn_config.h"
#include "ns_types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -180,8 +183,8 @@ typedef enum sn_coap_status_ {
*/ */
typedef struct sn_coap_options_list_ { typedef struct sn_coap_options_list_ {
uint8_t etag_len; /**< 1-8 bytes. Repeatable */ uint8_t etag_len; /**< 1-8 bytes. Repeatable */
unsigned int use_size1:1; bool use_size1;
unsigned int use_size2:1; bool use_size2;
uint16_t proxy_uri_len; /**< 1-1034 bytes. */ uint16_t proxy_uri_len; /**< 1-1034 bytes. */
uint16_t uri_host_len; /**< 1-255 bytes. */ uint16_t uri_host_len; /**< 1-255 bytes. */
@ -351,7 +354,10 @@ extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s
* \return Return value is count of needed memory as bytes for build Packet data * \return Return value is count of needed memory as bytes for build Packet data
* Null if failed * Null if failed
*/ */
extern uint16_t sn_coap_builder_calc_needed_packet_data_size(const sn_coap_hdr_s *src_coap_msg_ptr); extern uint16_t (sn_coap_builder_calc_needed_packet_data_size)(const sn_coap_hdr_s *src_coap_msg_ptr);
#ifdef SN_COAP_CONSTANT_NEEDED_SIZE
#define sn_coap_builder_calc_needed_packet_data_size(m) (SN_COAP_CONSTANT_NEEDED_SIZE)
#endif
/** /**
* \fn int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_size) * \fn int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_size)
@ -382,7 +388,10 @@ extern int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, const sn_coap_hdr
* \return Return value is count of needed memory as bytes for build Packet data * \return Return value is count of needed memory as bytes for build Packet data
* Null if failed * Null if failed
*/ */
extern uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size); extern uint16_t (sn_coap_builder_calc_needed_packet_data_size_2)(const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
#ifdef SN_COAP_CONSTANT_NEEDED_SIZE
#define sn_coap_builder_calc_needed_packet_data_size_2(m, p) (SN_COAP_CONSTANT_NEEDED_SIZE)
#endif
/** /**
* \fn sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) * \fn sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)

View File

@ -68,6 +68,23 @@
#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 0 /**< Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024 */ #define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 0 /**< Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024 */
#endif #endif
/**
* \def SN_COAP_CONSTANT_NEEDED_SIZE
* \brief Avoid needed size calculations
* If this is defined, sn_coap_builder_calc_needed_packet_data_size always returns that value,
* saving a lot of calculation code, at the cost of outgoing TX buffers being oversized, and
* with danger of them being undersized.
*
* sn_coap_builder_payload_build does not have any size input to limit its output, so it is
* always wise for users to assert that it has not output more than the size returned by
* sn_coap_builder_calc_needed_packet_size, whether this option is defined or not.
*/
#ifdef MBED_CONF_MBED_CLIENT_SN_COAP_CONSTANT_NEEDED_SIZE
#define SN_COAP_CONSTANT_NEEDED_SIZE MBED_CONF_MBED_CLIENT_SN_COAP_CONSTANT_NEEDED_SIZE
#endif
//#define SN_COAP_CONSTANT_NEEDED_SIZE 1024
/** /**
* \def SN_COAP_DISABLE_RESENDINGS * \def SN_COAP_DISABLE_RESENDINGS
* \brief Disables resending feature. Resending feature should not be needed * \brief Disables resending feature. Resending feature should not be needed

View File

@ -58,12 +58,12 @@ extern "C" {
* \brief This structure is returned by sn_coap_exec() for sending * \brief This structure is returned by sn_coap_exec() for sending
*/ */
typedef struct sn_nsdl_transmit_ { typedef struct sn_nsdl_transmit_ {
uint8_t *packet_ptr;
uint16_t packet_len;
sn_nsdl_addr_s dst_addr_ptr; sn_nsdl_addr_s dst_addr_ptr;
sn_nsdl_capab_e protocol; sn_nsdl_capab_e protocol;
uint16_t packet_len;
uint8_t *packet_ptr;
} sn_nsdl_transmit_s; } sn_nsdl_transmit_s;
/* * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * */

View File

@ -45,7 +45,7 @@ int8_t prepare_blockwise_message(struct coap_s *handle, struct sn_coap_hdr_ *coa
/* Structure which is stored to Linked list for message sending purposes */ /* Structure which is stored to Linked list for message sending purposes */
typedef struct coap_send_msg_ { typedef struct coap_send_msg_ {
uint8_t resending_counter; /* Tells how many times message is still tried to resend */ uint_fast8_t resending_counter; /* Tells how many times message is still tried to resend */
uint32_t resending_time; /* Tells next resending time */ uint32_t resending_time; /* Tells next resending time */
sn_nsdl_transmit_s send_msg_ptr; sn_nsdl_transmit_s send_msg_ptr;
@ -86,25 +86,35 @@ typedef NS_LIST_HEAD(coap_blockwise_msg_s, link) coap_blockwise_msg_list_t;
/* Structure which is stored to Linked list for blockwise messages receiving purposes */ /* Structure which is stored to Linked list for blockwise messages receiving purposes */
typedef struct coap_blockwise_payload_ { typedef struct coap_blockwise_payload_ {
uint32_t timestamp; /* Tells when Payload is stored to Linked list */
uint8_t addr_len; uint8_t addr_len;
uint8_t *addr_ptr; uint8_t token_len;
bool use_size1;
uint16_t port; uint16_t port;
uint16_t payload_len;
uint8_t *addr_ptr;
uint32_t block_number; uint32_t block_number;
uint8_t *token_ptr; uint8_t *token_ptr;
uint8_t token_len;
uint16_t payload_len;
uint8_t *payload_ptr; uint8_t *payload_ptr;
unsigned int use_size1:1; uint32_t timestamp; /* Tells when Payload is stored to Linked list */
ns_list_link_t link; ns_list_link_t link;
} coap_blockwise_payload_s; } coap_blockwise_payload_s;
typedef NS_LIST_HEAD(coap_blockwise_payload_s, link) coap_blockwise_payload_list_t; typedef NS_LIST_HEAD(coap_blockwise_payload_s, link) coap_blockwise_payload_list_t;
struct coap_s { struct coap_s {
uint8_t sn_coap_resending_queue_msgs;
uint8_t sn_coap_resending_count;
uint8_t sn_coap_resending_intervall;
uint8_t sn_coap_duplication_buffer_size;
uint8_t sn_coap_internal_block2_resp_handling; /* If this is set then coap itself sends a next GET request automatically */
uint16_t sn_coap_block_data_size;
#if ENABLE_RESENDINGS
uint16_t count_resent_msgs;
#endif
#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT
uint16_t count_duplication_msgs;
#endif
void *(*sn_coap_protocol_malloc)(uint16_t); void *(*sn_coap_protocol_malloc)(uint16_t);
void (*sn_coap_protocol_free)(void *); void (*sn_coap_protocol_free)(void *);
@ -113,12 +123,10 @@ struct coap_s {
#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
coap_send_msg_list_t linked_list_resent_msgs; /* Active resending messages are stored to this Linked list */ coap_send_msg_list_t linked_list_resent_msgs; /* Active resending messages are stored to this Linked list */
uint16_t count_resent_msgs;
#endif #endif
#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */
coap_duplication_info_list_t linked_list_duplication_msgs; /* Messages for duplicated messages detection is stored to this Linked list */ coap_duplication_info_list_t linked_list_duplication_msgs; /* Messages for duplicated messages detection is stored to this Linked list */
uint16_t count_duplication_msgs;
#endif #endif
#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not enabled, this part of code will not be compiled */ #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not enabled, this part of code will not be compiled */
@ -127,20 +135,14 @@ struct coap_s {
#endif #endif
uint32_t system_time; /* System time seconds */ uint32_t system_time; /* System time seconds */
uint16_t sn_coap_block_data_size;
uint8_t sn_coap_resending_queue_msgs;
uint32_t sn_coap_resending_queue_bytes; uint32_t sn_coap_resending_queue_bytes;
uint8_t sn_coap_resending_count;
uint8_t sn_coap_resending_intervall;
uint8_t sn_coap_duplication_buffer_size;
uint8_t sn_coap_internal_block2_resp_handling; /* If this is set then coap itself sends a next GET request automatically */
}; };
/* Utility function which performs a call to sn_coap_protocol_malloc() and memset's the result to zero. */ /* Utility function which performs a call to sn_coap_protocol_malloc() and memset's the result to zero. */
void *sn_coap_protocol_calloc(struct coap_s *handle, uint16_t length); void *sn_coap_protocol_calloc(struct coap_s *handle, uint_fast16_t length);
/* Utility function which performs a call to sn_coap_protocol_malloc() and memcopy's the source to result buffer. */ /* Utility function which performs a call to sn_coap_protocol_malloc() and memcopy's the source to result buffer. */
void *sn_coap_protocol_malloc_copy(struct coap_s *handle, const void *source, uint16_t length); void *sn_coap_protocol_malloc_copy(struct coap_s *handle, const void *source, uint_fast16_t length);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -37,17 +37,18 @@
#define TRACE_GROUP "coap" #define TRACE_GROUP "coap"
/* * * * LOCAL FUNCTION PROTOTYPES * * * */ /* * * * LOCAL FUNCTION PROTOTYPES * * * */
static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr); static uint8_t *sn_coap_builder_header_build(uint8_t *dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr);
static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr); static uint8_t *sn_coap_builder_options_build(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src_coap_msg_ptr);
static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option); static uint_fast16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option);
static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, const uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number); static uint8_t *sn_coap_builder_options_build_add_one_option(uint8_t *dst_packet_data_ptr, uint_fast16_t option_len, const uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number);
static void sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, const uint8_t *src_pptr, uint16_t src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number); static uint8_t *sn_coap_builder_options_build_add_multiple_option(uint8_t *dst_packet_data_pptr, const uint8_t *src_pptr, uint_fast16_t src_len, sn_coap_option_numbers_e option, uint16_t *previous_option_number);
static uint8_t sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packet_data_pptr, uint32_t value, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number); static uint_fast8_t sn_coap_builder_options_calc_uint_option_size(uint32_t option_value);
static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option); static uint8_t *sn_coap_builder_options_build_add_uint_option(uint8_t *dst_packet_data_ptr, uint32_t value, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number);
static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, const uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option); static uint_fast8_t sn_coap_builder_options_get_option_part_count(uint_fast16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option);
static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, const uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option); static uint_fast16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint_fast16_t query_len, const uint8_t *query_ptr, uint_fast8_t query_index, sn_coap_option_numbers_e option);
static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr); static int_fast16_t sn_coap_builder_options_get_option_part_position(uint_fast16_t query_len, const uint8_t *query_ptr, uint_fast8_t query_index, sn_coap_option_numbers_e option);
static uint8_t sn_coap_builder_options_calculate_jump_need(const sn_coap_hdr_s *src_coap_msg_ptr); static uint8_t *sn_coap_builder_payload_build(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src_coap_msg_ptr);
static uint_fast8_t sn_coap_builder_options_calculate_jump_need(const sn_coap_hdr_s *src_coap_msg_ptr);
sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, const sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, const sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
{ {
@ -101,7 +102,7 @@ int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src_c
return sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); return sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE);
} }
int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) int16_t sn_coap_builder_2(uint8_t * restrict dst_packet_data_ptr, const sn_coap_hdr_s * restrict src_coap_msg_ptr, uint16_t blockwise_payload_size)
{ {
uint8_t *base_packet_data_ptr; uint8_t *base_packet_data_ptr;
@ -110,23 +111,22 @@ int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src
return -2; return -2;
} }
/* Initialize given Packet data memory area with zero values */ /* This serves as a pre-validity check for various src_coap_msg_ptr fields */
/* (as long as SN_COAP_CONSTANT_NEEDED_SIZE is not set) */
uint16_t dst_byte_count_to_be_built = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, blockwise_payload_size); uint16_t dst_byte_count_to_be_built = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, blockwise_payload_size);
if (!dst_byte_count_to_be_built) { if (!dst_byte_count_to_be_built) {
tr_error("sn_coap_builder_2 - failed to allocate message!"); tr_error("sn_coap_builder_2 - failed to allocate message!");
return -1; return -1;
} }
// XXX: this should not be needed anymore but I have no courage to remove it yet.
memset(dst_packet_data_ptr, 0, dst_byte_count_to_be_built);
/* * * * Store base (= original) destination Packet data pointer for later usage * * * */ /* * * * Store base (= original) destination Packet data pointer for later usage * * * */
base_packet_data_ptr = dst_packet_data_ptr; base_packet_data_ptr = dst_packet_data_ptr;
/* * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * */
/* * * * Header part building * * * */ /* * * * Header part building * * * */
/* * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * */
if (sn_coap_builder_header_build(&dst_packet_data_ptr, src_coap_msg_ptr) != 0) { dst_packet_data_ptr = sn_coap_builder_header_build(dst_packet_data_ptr, src_coap_msg_ptr);
if (!dst_packet_data_ptr) {
/* Header building failed */ /* Header building failed */
tr_error("sn_coap_builder_2 - header building failed!"); tr_error("sn_coap_builder_2 - header building failed!");
return -1; return -1;
@ -137,23 +137,34 @@ int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, const sn_coap_hdr_s *src
/* * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * */
/* * * * Options part building * * * */ /* * * * Options part building * * * */
/* * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * */
sn_coap_builder_options_build(&dst_packet_data_ptr, src_coap_msg_ptr); dst_packet_data_ptr = sn_coap_builder_options_build(dst_packet_data_ptr, src_coap_msg_ptr);
/* * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * */
/* * * * Payload part building * * * */ /* * * * Payload part building * * * */
/* * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * */
sn_coap_builder_payload_build(&dst_packet_data_ptr, src_coap_msg_ptr); dst_packet_data_ptr = sn_coap_builder_payload_build(dst_packet_data_ptr, src_coap_msg_ptr);
} }
/* Shout as much as we can about overflow - if we exceed this, may have overrun user's buffer */
if (dst_packet_data_ptr - base_packet_data_ptr > dst_byte_count_to_be_built) {
tr_error("sn_coap_builder_2 - overflowed expected size!");
return -1;
}
/* * * * Return built Packet data length * * * */ /* * * * Return built Packet data length * * * */
return (dst_packet_data_ptr - base_packet_data_ptr); return (dst_packet_data_ptr - base_packet_data_ptr);
} }
uint16_t sn_coap_builder_calc_needed_packet_data_size(const sn_coap_hdr_s *src_coap_msg_ptr)
uint16_t (sn_coap_builder_calc_needed_packet_data_size)(const sn_coap_hdr_s *src_coap_msg_ptr)
{ {
return sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); return sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE);
} }
uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) uint16_t (sn_coap_builder_calc_needed_packet_data_size_2)(const sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
{ {
#ifdef SN_COAP_CONSTANT_NEEDED_SIZE
return SN_COAP_CONSTANT_NEEDED_SIZE;
#else
(void)blockwise_payload_size; (void)blockwise_payload_size;
uint_fast32_t returned_byte_count = 0; uint_fast32_t returned_byte_count = 0;
@ -169,7 +180,7 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
/* If else than Reset message because Reset message must be empty */ /* If else than Reset message because Reset message must be empty */
if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) { if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) {
uint16_t repeatable_option_size = 0; uint_fast16_t repeatable_option_size = 0;
/* TOKEN - Length is 1-8 bytes */ /* TOKEN - Length is 1-8 bytes */
if (src_coap_msg_ptr->token_ptr != NULL) { if (src_coap_msg_ptr->token_ptr != NULL) {
if (src_coap_msg_ptr->token_len > 8 || src_coap_msg_ptr->token_len < 1) { /* Check that option is not longer than defined */ if (src_coap_msg_ptr->token_len > 8 || src_coap_msg_ptr->token_len < 1) { /* Check that option is not longer than defined */
@ -190,19 +201,18 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
} }
} }
uint16_t tempInt = 0;
/* CONTENT FORMAT - An integer option, up to 2 bytes */ /* CONTENT FORMAT - An integer option, up to 2 bytes */
if (src_coap_msg_ptr->content_format != COAP_CT_NONE) { if (src_coap_msg_ptr->content_format != COAP_CT_NONE) {
if ((uint32_t) src_coap_msg_ptr->content_format > 0xffff) { if ((uint32_t) src_coap_msg_ptr->content_format > 0xffff) {
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - content format too large!"); tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - content format too large!");
return 0; return 0;
} }
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->content_format, COAP_OPTION_CONTENT_FORMAT, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_coap_msg_ptr->content_format);
} }
/* If options list pointer exists */ /* If options list pointer exists */
if (src_coap_msg_ptr->options_list_ptr != NULL) { if (src_coap_msg_ptr->options_list_ptr != NULL) {
const sn_coap_options_list_s *src_options_list_ptr = src_coap_msg_ptr->options_list_ptr; const sn_coap_options_list_s * restrict src_options_list_ptr = src_coap_msg_ptr->options_list_ptr;
/* ACCEPT - An integer option, up to 2 bytes */ /* ACCEPT - An integer option, up to 2 bytes */
if (src_options_list_ptr->accept != COAP_CT_NONE) { if (src_options_list_ptr->accept != COAP_CT_NONE) {
@ -210,11 +220,11 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - accept too large!"); tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - accept too large!");
return 0; return 0;
} }
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->accept, COAP_OPTION_ACCEPT, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_options_list_ptr->accept);
} }
/* MAX AGE - An integer option, omitted for default. Up to 4 bytes */ /* MAX AGE - An integer option, omitted for default. Up to 4 bytes */
if (src_options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) { if (src_options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->max_age, COAP_OPTION_MAX_AGE, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_options_list_ptr->max_age);
} }
/* PROXY URI - Length of this option is 1-1034 bytes */ /* PROXY URI - Length of this option is 1-1034 bytes */
if (src_options_list_ptr->proxy_uri_ptr != NULL) { if (src_options_list_ptr->proxy_uri_ptr != NULL) {
@ -282,7 +292,7 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - uri port too large!"); tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - uri port too large!");
return 0; return 0;
} }
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->uri_port, COAP_OPTION_URI_PORT, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_options_list_ptr->uri_port);
} }
/* lOCATION QUERY - Repeatable option. Length of this option is 0-255 bytes */ /* lOCATION QUERY - Repeatable option. Length of this option is 0-255 bytes */
if (src_options_list_ptr->location_query_ptr != NULL) { if (src_options_list_ptr->location_query_ptr != NULL) {
@ -300,7 +310,7 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
if ((uint32_t) src_options_list_ptr->observe > 0xffffff) { if ((uint32_t) src_options_list_ptr->observe > 0xffffff) {
return 0; return 0;
} }
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->observe, COAP_OPTION_OBSERVE, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_options_list_ptr->observe);
} }
/* URI QUERY - Repeatable option. Length of this option is 1-255 */ /* URI QUERY - Repeatable option. Length of this option is 1-255 */
if (src_options_list_ptr->uri_query_ptr != NULL) { if (src_options_list_ptr->uri_query_ptr != NULL) {
@ -320,11 +330,11 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - block1 too large!"); tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - block1 too large!");
return 0; return 0;
} }
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->block1, COAP_OPTION_BLOCK1, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_options_list_ptr->block1);
} }
/* SIZE1 - Length of this option is 0-4 bytes */ /* SIZE1 - Length of this option is 0-4 bytes */
if (src_options_list_ptr->use_size1) { if (src_options_list_ptr->use_size1) {
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->size1, COAP_OPTION_SIZE1, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_options_list_ptr->size1);
} }
/* BLOCK 2 - An integer option, up to 3 bytes */ /* BLOCK 2 - An integer option, up to 3 bytes */
if (src_options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) { if (src_options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
@ -332,11 +342,11 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - block2 too large!"); tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - block2 too large!");
return 0; return 0;
} }
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->block2, COAP_OPTION_BLOCK2, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_options_list_ptr->block2);
} }
/* SIZE2 - Length of this option is 0-4 bytes */ /* SIZE2 - Length of this option is 0-4 bytes */
if (src_coap_msg_ptr->options_list_ptr->use_size2) { if (src_coap_msg_ptr->options_list_ptr->use_size2) {
returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_options_list_ptr->size2, COAP_OPTION_SIZE2, &tempInt); returned_byte_count += sn_coap_builder_options_calc_uint_option_size(src_options_list_ptr->size2);
} }
} }
#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
@ -360,6 +370,7 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
return 0; return 0;
} }
return (uint16_t)returned_byte_count; return (uint16_t)returned_byte_count;
#endif
} }
/** /**
@ -374,10 +385,10 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size_2(const sn_coap_hdr_s *src
* \return Returns bytes needed for jumping * \return Returns bytes needed for jumping
*/ */
static uint8_t sn_coap_builder_options_calculate_jump_need(const sn_coap_hdr_s *src_coap_msg_ptr) static uint_fast8_t sn_coap_builder_options_calculate_jump_need(const sn_coap_hdr_s *src_coap_msg_ptr)
{ {
uint8_t previous_option_number = 0; uint8_t previous_option_number = 0;
uint8_t needed_space = 0; uint_fast8_t needed_space = 0;
const sn_coap_options_list_s* options_list_ptr = src_coap_msg_ptr->options_list_ptr; const sn_coap_options_list_s* options_list_ptr = src_coap_msg_ptr->options_list_ptr;
@ -489,54 +500,52 @@ static uint8_t sn_coap_builder_options_calculate_jump_need(const sn_coap_hdr_s *
} }
/** /**
* \fn static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) * \fn static int8_t sn_coap_builder_header_build(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr)
* *
* \brief Builds Header part of Packet data * \brief Builds Header part of Packet data
* *
* \param **dst_packet_data_pptr is destination for built Packet data * \param *dst_packet_data_ptr is destination for built Packet data
* *
* \param *src_coap_msg_ptr is source for building Packet data * \param *src_coap_msg_ptr is source for building Packet data
* *
* \return Return value is 0 in ok case and -1 in failure case * \return Return value is 0 in ok case and -1 in failure case
**************************************************************************** */ **************************************************************************** */
static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr) static uint8_t *sn_coap_builder_header_build(uint8_t * restrict dst_packet_data_ptr, const sn_coap_hdr_s * restrict src_coap_msg_ptr)
{ {
/* * * * Check validity of Header values * * * */ /* * * * Check validity of Header values * * * */
if (sn_coap_header_validity_check(src_coap_msg_ptr, COAP_VERSION) != 0) { if (sn_coap_header_validity_check(src_coap_msg_ptr, COAP_VERSION) != 0) {
tr_error("sn_coap_builder_header_build - header build failed!"); tr_error("sn_coap_builder_header_build - header build failed!");
return -1; return NULL;
} }
uint8_t* dest_packet = *dst_packet_data_pptr;
/* Set CoAP Version, Message type and Token length */ /* Set CoAP Version, Message type and Token length */
dest_packet[0] = COAP_VERSION | src_coap_msg_ptr->msg_type | src_coap_msg_ptr->token_len; dst_packet_data_ptr[0] = COAP_VERSION | src_coap_msg_ptr->msg_type | src_coap_msg_ptr->token_len;
/* * * Add Message code * * */ /* * * Add Message code * * */
dest_packet[1] = src_coap_msg_ptr->msg_code; dst_packet_data_ptr[1] = src_coap_msg_ptr->msg_code;
/* * * Add Message ID * * */ /* * * Add Message ID * * */
dest_packet[2] = (uint8_t)(src_coap_msg_ptr->msg_id >> COAP_HEADER_MSG_ID_MSB_SHIFT); /* MSB part */ dst_packet_data_ptr[2] = (uint8_t)(src_coap_msg_ptr->msg_id >> COAP_HEADER_MSG_ID_MSB_SHIFT); /* MSB part */
dest_packet[3] = (uint8_t)src_coap_msg_ptr->msg_id; /* LSB part */ dst_packet_data_ptr[3] = (uint8_t)src_coap_msg_ptr->msg_id; /* LSB part */
*dst_packet_data_pptr = dest_packet + 4; dst_packet_data_ptr += 4;
/* Success */ /* Success */
return 0; return dst_packet_data_ptr;
} }
/** /**
* \fn static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) * \fn static int8_t sn_coap_builder_options_build(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr)
* *
* \brief Builds Options part of Packet data * \brief Builds Options part of Packet data
* *
* \param **dst_packet_data_pptr is destination for built Packet data * \param *dst_packet_data_ptr is destination for built Packet data
* *
* \param *src_coap_msg_ptr is source for building Packet data * \param *src_coap_msg_ptr is source for building Packet data
* *
* \return Return value is 0 in every case * \return Returns updated output pointer
*/ */
static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr) static uint8_t *sn_coap_builder_options_build(uint8_t * restrict dst_packet_data_ptr, const sn_coap_hdr_s * restrict src_coap_msg_ptr)
{ {
/* * * * Check if Options are used at all * * * */ /* * * * Check if Options are used at all * * * */
if (src_coap_msg_ptr->uri_path_ptr == NULL && src_coap_msg_ptr->token_ptr == NULL && if (src_coap_msg_ptr->uri_path_ptr == NULL && src_coap_msg_ptr->token_ptr == NULL &&
@ -545,14 +554,14 @@ static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, cons
if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_CONFIRMABLE) { if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_CONFIRMABLE) {
tr_error("sn_coap_builder_options_build - options not used!"); tr_error("sn_coap_builder_options_build - options not used!");
} }
return 0; return dst_packet_data_ptr;
} }
/* * * * First add Token option * * * */ /* * * * First add Token option * * * */
if (src_coap_msg_ptr->token_len && src_coap_msg_ptr->token_ptr) { if (src_coap_msg_ptr->token_len && src_coap_msg_ptr->token_ptr) {
memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->token_ptr, src_coap_msg_ptr->token_len); memcpy(dst_packet_data_ptr, src_coap_msg_ptr->token_ptr, src_coap_msg_ptr->token_len);
} }
(*dst_packet_data_pptr) += src_coap_msg_ptr->token_len; dst_packet_data_ptr += src_coap_msg_ptr->token_len;
/* Then build rest of the options */ /* Then build rest of the options */
@ -561,105 +570,105 @@ static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, cons
//missing: COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH, COAP_OPTION_SIZE //missing: COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH, COAP_OPTION_SIZE
const sn_coap_options_list_s *src_options_list_ptr = src_coap_msg_ptr->options_list_ptr; const sn_coap_options_list_s * restrict src_options_list_ptr = src_coap_msg_ptr->options_list_ptr;
/* Check if less used options are used at all */ /* Check if less used options are used at all */
if (src_options_list_ptr != NULL) { if (src_options_list_ptr != NULL) {
/* * * * Build Uri-Host option * * * */ /* * * * Build Uri-Host option * * * */
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_options_list_ptr->uri_host_len, dst_packet_data_ptr = sn_coap_builder_options_build_add_one_option(dst_packet_data_ptr, src_options_list_ptr->uri_host_len,
src_options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST, &previous_option_number); src_options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST, &previous_option_number);
/* * * * Build ETag option * * * */ /* * * * Build ETag option * * * */
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_options_list_ptr->etag_ptr, dst_packet_data_ptr = sn_coap_builder_options_build_add_multiple_option(dst_packet_data_ptr, src_options_list_ptr->etag_ptr,
src_options_list_ptr->etag_len, COAP_OPTION_ETAG, &previous_option_number); src_options_list_ptr->etag_len, COAP_OPTION_ETAG, &previous_option_number);
/* * * * Build Observe option * * * * */ /* * * * Build Observe option * * * * */
if (src_options_list_ptr->observe != COAP_OBSERVE_NONE) { if (src_options_list_ptr->observe != COAP_OBSERVE_NONE) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->observe, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_options_list_ptr->observe,
COAP_OPTION_OBSERVE, &previous_option_number); COAP_OPTION_OBSERVE, &previous_option_number);
} }
/* * * * Build Uri-Port option * * * */ /* * * * Build Uri-Port option * * * */
if (src_options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) { if (src_options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->uri_port, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_options_list_ptr->uri_port,
COAP_OPTION_URI_PORT, &previous_option_number); COAP_OPTION_URI_PORT, &previous_option_number);
} }
/* * * * Build Location-Path option * * * */ /* * * * Build Location-Path option * * * */
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_options_list_ptr->location_path_ptr, dst_packet_data_ptr = sn_coap_builder_options_build_add_multiple_option(dst_packet_data_ptr, src_options_list_ptr->location_path_ptr,
src_options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH, &previous_option_number); src_options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH, &previous_option_number);
} }
/* * * * Build Uri-Path option * * * */ /* * * * Build Uri-Path option * * * */
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_coap_msg_ptr->uri_path_ptr, dst_packet_data_ptr = sn_coap_builder_options_build_add_multiple_option(dst_packet_data_ptr, src_coap_msg_ptr->uri_path_ptr,
src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH, &previous_option_number); src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH, &previous_option_number);
/* * * * Build Content-Type option * * * */ /* * * * Build Content-Type option * * * */
if (src_coap_msg_ptr->content_format != COAP_CT_NONE) { if (src_coap_msg_ptr->content_format != COAP_CT_NONE) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->content_format, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_coap_msg_ptr->content_format,
COAP_OPTION_CONTENT_FORMAT, &previous_option_number); COAP_OPTION_CONTENT_FORMAT, &previous_option_number);
} }
if (src_options_list_ptr != NULL) { if (src_options_list_ptr != NULL) {
/* * * * Build Max-Age option * * * */ /* * * * Build Max-Age option * * * */
if (src_options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) { if (src_options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->max_age, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_options_list_ptr->max_age,
COAP_OPTION_MAX_AGE, &previous_option_number); COAP_OPTION_MAX_AGE, &previous_option_number);
} }
/* * * * Build Uri-Query option * * * * */ /* * * * Build Uri-Query option * * * * */
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_options_list_ptr->uri_query_ptr, dst_packet_data_ptr = sn_coap_builder_options_build_add_multiple_option(dst_packet_data_ptr, src_options_list_ptr->uri_query_ptr,
src_options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY, &previous_option_number); src_options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY, &previous_option_number);
/* * * * Build Accept option * * * * */ /* * * * Build Accept option * * * * */
if (src_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE) { if (src_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->accept, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_options_list_ptr->accept,
COAP_OPTION_ACCEPT, &previous_option_number); COAP_OPTION_ACCEPT, &previous_option_number);
} }
/* * * * Build Location-Query option * * * */ /* * * * Build Location-Query option * * * */
sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, src_options_list_ptr->location_query_ptr, dst_packet_data_ptr = sn_coap_builder_options_build_add_multiple_option(dst_packet_data_ptr, src_options_list_ptr->location_query_ptr,
src_options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY, &previous_option_number); src_options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY, &previous_option_number);
/* * * * Build Block2 option * * * * */ /* * * * Build Block2 option * * * * */
if (src_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) { if (src_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->block2, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_options_list_ptr->block2,
COAP_OPTION_BLOCK2, &previous_option_number); COAP_OPTION_BLOCK2, &previous_option_number);
} }
/* * * * Build Block1 option * * * * */ /* * * * Build Block1 option * * * * */
if (src_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) { if (src_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->block1, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_options_list_ptr->block1,
COAP_OPTION_BLOCK1, &previous_option_number); COAP_OPTION_BLOCK1, &previous_option_number);
} }
/* * * * Build Size2 option * * * */ /* * * * Build Size2 option * * * */
if (src_coap_msg_ptr->options_list_ptr->use_size2) { if (src_coap_msg_ptr->options_list_ptr->use_size2) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->size2, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_options_list_ptr->size2,
COAP_OPTION_SIZE2, &previous_option_number); COAP_OPTION_SIZE2, &previous_option_number);
} }
/* * * * Build Proxy-Uri option * * * */ /* * * * Build Proxy-Uri option * * * */
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_options_list_ptr->proxy_uri_len, dst_packet_data_ptr = sn_coap_builder_options_build_add_one_option(dst_packet_data_ptr, src_options_list_ptr->proxy_uri_len,
src_options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI, &previous_option_number); src_options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI, &previous_option_number);
/* * * * Build Size1 option * * * */ /* * * * Build Size1 option * * * */
if (src_options_list_ptr->use_size1) { if (src_options_list_ptr->use_size1) {
sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_options_list_ptr->size1, dst_packet_data_ptr = sn_coap_builder_options_build_add_uint_option(dst_packet_data_ptr, src_options_list_ptr->size1,
COAP_OPTION_SIZE1, &previous_option_number); COAP_OPTION_SIZE1, &previous_option_number);
} }
} }
/* Success */ /* Success */
return 0; return dst_packet_data_ptr;
} }
/** /**
* \fn static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_value_len, uint8_t *option_value_ptr, sn_coap_option_numbers_e option_number) * \fn static uint8_t *sn_coap_builder_options_build_add_one_option(uint8_t *dst_packet_data_ptr, uint16_t option_value_len, uint8_t *option_value_ptr, sn_coap_option_numbers_e option_number)
* *
* \brief Adds Options part of Packet data * \brief Adds Options part of Packet data
* *
* \param **dst_packet_data_pptr is destination for built Packet data * \param *dst_packet_data_ptr is destination for built Packet data
* *
* \param option_value_len is Option value length to be added * \param option_value_len is Option value length to be added
* *
@ -667,20 +676,20 @@ static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, cons
* *
* \param option_number is Option number to be added * \param option_number is Option number to be added
* *
* \return Return value is 0 if option was not added, 1 if added * \return Advanced destination
*/ */
static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, static uint8_t *sn_coap_builder_options_build_add_one_option(uint8_t * restrict dst_packet_data_ptr, uint_fast16_t option_len,
const uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number) const uint8_t * restrict option_ptr, sn_coap_option_numbers_e option_number, uint16_t * restrict previous_option_number)
{ {
/* Check if there is option at all */ /* Check if there is option at all */
if (option_ptr != NULL) { if (option_ptr != NULL) {
uint16_t option_delta; uint_fast16_t option_delta;
option_delta = (option_number - *previous_option_number); option_delta = (option_number - *previous_option_number);
/* * * Build option header * * */ /* * * Build option header * * */
uint8_t first_byte; uint_fast8_t first_byte;
/* First option length without extended part */ /* First option length without extended part */
if (option_len <= 12) { if (option_len <= 12) {
@ -695,101 +704,97 @@ static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet
first_byte = 0x0E; first_byte = 0x0E;
} }
uint8_t *dest_packet = *dst_packet_data_pptr;
/* Then option delta with extensions, and move pointer */ /* Then option delta with extensions, and move pointer */
if (option_delta <= 12) { if (option_delta <= 12) {
dest_packet[0] = first_byte + (option_delta << 4); *dst_packet_data_ptr++ = first_byte + (option_delta << 4);
dest_packet += 1;
} }
else if (option_delta > 12 && option_delta < 269) { else if (option_delta > 12 && option_delta < 269) {
dest_packet[0] = first_byte + 0xD0; *dst_packet_data_ptr++ = first_byte + 0xD0;
option_delta -= 13; option_delta -= 13;
dest_packet[1] = (uint8_t)option_delta; *dst_packet_data_ptr++ = (uint8_t)option_delta;
dest_packet += 2;
} }
//This is currently dead code (but possibly needed in future) //This is currently dead code (but possibly needed in future)
else /*if (option_delta >= 269)*/ { else /*if (option_delta >= 269)*/ {
dest_packet[0] = first_byte + 0xE0; *dst_packet_data_ptr++ = first_byte + 0xE0;
option_delta -= 269; option_delta -= 269;
dest_packet[1] = (option_delta >> 8); *dst_packet_data_ptr++ = (option_delta >> 8);
dest_packet[2] = (uint8_t)option_delta; *dst_packet_data_ptr++ = (uint8_t)option_delta;
dest_packet += 3;
} }
/* Now option length extensions, if needed */ /* Now option length extensions, if needed */
if (option_len > 12 && option_len < 269) { if (option_len > 12 && option_len < 269) {
dest_packet[0] = (uint8_t)(option_len - 13); *dst_packet_data_ptr++ = (uint8_t)(option_len - 13);
dest_packet += 1;
} }
else if (option_len >= 269) { else if (option_len >= 269) {
dest_packet[0] = ((option_len - 269) >> 8); *dst_packet_data_ptr++ = ((option_len - 269) >> 8);
dest_packet[1] = (uint8_t)(option_len - 269); *dst_packet_data_ptr++ = (uint8_t)(option_len - 269);
dest_packet += 2;
} }
*previous_option_number = option_number; *previous_option_number = option_number;
/* Write Option value */ /* Write Option value */
memcpy(dest_packet, option_ptr, option_len); memcpy(dst_packet_data_ptr, option_ptr, option_len);
/* Increase destination Packet data pointer */ /* Increase destination Packet data pointer */
dest_packet += option_len; dst_packet_data_ptr += option_len;
*dst_packet_data_pptr = dest_packet;
return 1;
} }
/* Success */ /* Success */
return 0; return dst_packet_data_ptr;
}
static uint_fast8_t sn_coap_builder_options_calc_uint_option_size(uint32_t option_value)
{
// Calculation assumes option type/len is always 1 byte.
// Length certainly fits, and any extra for option type is accounted for
// separately by sn_coap_builder_options_calculate_jump_need.
uint_fast8_t len = 1;
while (option_value != 0) {
len++;
option_value >>= 8;
}
return len;
} }
/** /**
* \brief Constructs a uint Options part of Packet data * \brief Constructs a uint Options part of Packet data
* *
* \param **dst_packet_data_pptr is destination for built Packet data; NULL * \param *dst_packet_data_pptr is destination for built Packet data; NULL
* to compute size only. * to compute size only.
* *
* \param option_value is Option value to be added * \param option_value is Option value to be added
* *
* \param option_number is Option number to be added * \param option_number is Option number to be added
* *
* \return Return value is total option size, or -1 in write failure case * \return Updated destination pointer
*/ */
static uint8_t sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packet_data_pptr, uint32_t option_value, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number) static uint8_t *sn_coap_builder_options_build_add_uint_option(uint8_t * restrict dst_packet_data_ptr, uint32_t option_value, sn_coap_option_numbers_e option_number, uint16_t * restrict previous_option_number)
{ {
uint8_t payload[4]; uint8_t payload[4];
uint8_t len = 0; uint_fast8_t len = 0;
/* Construct the variable-length payload representing the value */ /* Construct the variable-length payload representing the value */
for (uint8_t i = 0; i < 4; i++) { for (uint_fast8_t i = 0; i < 4; i++) {
if (len > 0 || (option_value & 0xff000000)) { if (len > 0 || (option_value & 0xff000000)) {
payload[len++] = option_value >> 24; payload[len++] = option_value >> 24;
} }
option_value <<= 8; option_value <<= 8;
} }
/* If output pointer isn't NULL, write it out */ return sn_coap_builder_options_build_add_one_option(dst_packet_data_ptr, len, payload, option_number, previous_option_number);
if (dst_packet_data_pptr) {
// No need to check & handle return value, as the function returns failure only if the option pointer is zero
// and it is pointing to a local variable here.
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, len, payload, option_number, previous_option_number);
}
/* Return the total option size */
return 1 + len;
} }
/** /**
* \fn static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option) * \fn static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t *dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option)
* *
* \brief Builds Option Uri-Query from given CoAP Header structure to Packet data * \brief Builds Option Uri-Query from given CoAP Header structure to Packet data
* *
* \param **dst_packet_data_pptr is destination for built Packet data * \param *dst_packet_data_ptr is destination for built Packet data
* *
* \param uint8_t **src_ptr * \param uint8_t **src_ptr
* *
@ -797,17 +802,17 @@ static uint8_t sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packe
* *
* \paramsn_coap_option_numbers_e option option to be added * \paramsn_coap_option_numbers_e option option to be added
* *
* \return Return value is 0 always * \return Returns updated output pointer
*/ */
static void sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, const uint8_t *src_pptr, uint16_t src_len, sn_coap_option_numbers_e option, uint16_t *previous_option_number) static uint8_t *sn_coap_builder_options_build_add_multiple_option(uint8_t * restrict dst_packet_data_ptr, const uint8_t * restrict src_pptr, uint_fast16_t src_len, sn_coap_option_numbers_e option, uint16_t * restrict previous_option_number)
{ {
/* Check if there is option at all */ /* Check if there is option at all */
if (src_pptr != NULL) { if (src_pptr != NULL) {
const uint8_t *query_ptr = src_pptr; const uint8_t * restrict query_ptr = src_pptr;
uint8_t query_part_count = 0; uint_fast8_t query_part_count = 0;
uint16_t query_len = src_len; uint_fast16_t query_len = src_len;
uint8_t i = 0; uint_fast8_t i = 0;
uint16_t query_part_offset = 0; uint_fast16_t query_part_offset = 0;
/* Get query part count */ /* Get query part count */
query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option); query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option);
@ -815,16 +820,17 @@ static void sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_pack
/* * * * Options by adding all parts to option * * * */ /* * * * Options by adding all parts to option * * * */
for (i = 0; i < query_part_count; i++) { for (i = 0; i < query_part_count; i++) {
/* Get length of query part */ /* Get length of query part */
uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option); uint_fast16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option);
/* Get position of query part */ /* Get position of query part */
query_part_offset = sn_coap_builder_options_get_option_part_position(query_len, query_ptr, i, option); query_part_offset = sn_coap_builder_options_get_option_part_position(query_len, query_ptr, i, option);
/* Add Uri-query's one part to Options */ /* Add Uri-query's one part to Options */
sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, src_pptr + query_part_offset, option, previous_option_number); dst_packet_data_ptr = sn_coap_builder_options_build_add_one_option(dst_packet_data_ptr, one_query_part_len, src_pptr + query_part_offset, option, previous_option_number);
} }
} }
/* Success */ /* Success */
return dst_packet_data_ptr;
} }
@ -839,11 +845,11 @@ static void sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_pack
* *
* \return Return value is count of needed memory as bytes for Uri-query option * \return Return value is count of needed memory as bytes for Uri-query option
*/ */
static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option) static uint_fast16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option)
{ {
uint8_t query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option); uint_fast8_t query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option);
uint8_t i = 0; uint_fast8_t i = 0;
uint16_t ret_value = 0; uint_fast16_t ret_value = 0;
/* * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * Calculate Uri-query options length * * */ /* * * * Calculate Uri-query options length * * */
@ -852,7 +858,7 @@ static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, con
/* * * Length of Option number and Option value length * * */ /* * * Length of Option number and Option value length * * */
/* Get length of Query part */ /* Get length of Query part */
uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option); uint_fast16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option);
/* Check option length */ /* Check option length */
switch (option) { switch (option) {
@ -920,10 +926,13 @@ static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, con
* *
* \return Return value is count of query parts * \return Return value is count of query parts
*/ */
static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option) static uint_fast8_t sn_coap_builder_options_get_option_part_count(uint_fast16_t query_len, const uint8_t *query_ptr, sn_coap_option_numbers_e option)
{ {
uint8_t returned_query_count = 0; if (query_len <= 2) {
uint16_t query_len_index = 0; return 1;
}
const uint8_t *query_end = query_ptr + query_len - 1;
uint8_t char_to_search = '&'; uint8_t char_to_search = '&';
if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
@ -931,14 +940,13 @@ static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len,
} }
/* Loop whole query and search '\0' characters (not first and last char) */ /* Loop whole query and search '\0' characters (not first and last char) */
for (query_len_index = 1; query_len_index < query_len - 1; query_len_index++) { uint_fast8_t returned_query_count = 1;
/* If new query part starts */ query_ptr++;
if (*(query_ptr + query_len_index) == char_to_search) { /* If match */ do {
if (*query_ptr++ == char_to_search) { /* If match */
returned_query_count++; returned_query_count++;
} }
} } while (query_ptr < query_end);
returned_query_count++;
return returned_query_count; return returned_query_count;
} }
@ -960,13 +968,13 @@ static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len,
* *
* \return Return value is length of query part * \return Return value is length of query part
*/ */
static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, const uint8_t *query_ptr, static uint_fast16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint_fast16_t query_len, const uint8_t *query_ptr,
uint8_t query_index, sn_coap_option_numbers_e option) uint_fast8_t query_index, sn_coap_option_numbers_e option)
{ {
uint16_t returned_query_part_len = 0; uint_fast16_t returned_query_part_len = 0;
uint8_t temp_query_index = 0; uint_fast8_t temp_query_index = 0;
uint16_t query_len_index = 0; uint_fast16_t query_len_index = 0;
uint8_t char_to_search = '&'; uint_fast8_t char_to_search = '&';
if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
char_to_search = '/'; char_to_search = '/';
@ -975,7 +983,7 @@ static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option
/* Loop whole query and search '\0' characters */ /* Loop whole query and search '\0' characters */
for (query_len_index = 0; query_len_index < query_len; query_len_index++) { for (query_len_index = 0; query_len_index < query_len; query_len_index++) {
/* Store character to temp_char for helping debugging */ /* Store character to temp_char for helping debugging */
uint8_t temp_char = *query_ptr; uint_fast8_t temp_char = *query_ptr;
/* If new query part starts */ /* If new query part starts */
if (temp_char == char_to_search && returned_query_part_len > 0) { /* returned_query_part_len > 0 is for querys which start with "\0" */ if (temp_char == char_to_search && returned_query_part_len > 0) { /* returned_query_part_len > 0 is for querys which start with "\0" */
@ -1018,13 +1026,13 @@ static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option
* \return Return value is position (= offset) of query part in whole query. In * \return Return value is position (= offset) of query part in whole query. In
* fail cases -1 is returned. * fail cases -1 is returned.
*/ */
static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, const uint8_t *query_ptr, static int_fast16_t sn_coap_builder_options_get_option_part_position(uint_fast16_t query_len, const uint8_t *query_ptr,
uint8_t query_index, sn_coap_option_numbers_e option) uint_fast8_t query_index, sn_coap_option_numbers_e option)
{ {
uint16_t returned_query_part_offset = 0; uint_fast16_t returned_query_part_offset = 0;
uint8_t temp_query_index = 0; uint_fast8_t temp_query_index = 0;
uint16_t query_len_index = 0; uint_fast16_t query_len_index = 0;
uint8_t char_to_search = '&'; uint_fast8_t char_to_search = '&';
if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
char_to_search = '/'; char_to_search = '/';
@ -1041,7 +1049,7 @@ static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_l
/* Loop whole query and search separator characters */ /* Loop whole query and search separator characters */
for (query_len_index = 0; query_len_index < query_len; query_len_index++) { for (query_len_index = 0; query_len_index < query_len; query_len_index++) {
/* Store character to temp_char for helping debugging */ /* Store character to temp_char for helping debugging */
uint8_t temp_char = *query_ptr; uint_fast8_t temp_char = *query_ptr;
/* If new query part starts */ /* If new query part starts */
if (temp_char == char_to_search && returned_query_part_offset > 0) { /* returned_query_part_offset > 0 is for querys which start with searched char */ if (temp_char == char_to_search && returned_query_part_offset > 0) { /* returned_query_part_offset > 0 is for querys which start with searched char */
@ -1065,27 +1073,28 @@ static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_l
/** /**
* \fn static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) * \fn static void sn_coap_builder_payload_build(uint8_t *dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
* *
* \brief Builds Options part of Packet data * \brief Builds Options part of Packet data
* *
* \param **dst_packet_data_pptr is destination for built Packet data * \param *dst_packet_data_ptr is destination for built Packet data
* *
* \param *src_coap_msg_ptr is source for building Packet data * \param *src_coap_msg_ptr is source for building Packet data
*/ */
static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, const sn_coap_hdr_s *src_coap_msg_ptr) static uint8_t *sn_coap_builder_payload_build(uint8_t * restrict dst_packet_data_ptr, const sn_coap_hdr_s * restrict src_coap_msg_ptr)
{ {
/* Check if Payload is used at all */ /* Check if Payload is used at all */
if (src_coap_msg_ptr->payload_len && src_coap_msg_ptr->payload_ptr != NULL) { if (src_coap_msg_ptr->payload_len && src_coap_msg_ptr->payload_ptr != NULL) {
/* Write Payload marker */ /* Write Payload marker */
**dst_packet_data_pptr = 0xff; *dst_packet_data_ptr++ = 0xff;
(*dst_packet_data_pptr)++;
/* Write Payload */ /* Write Payload */
memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->payload_ptr, src_coap_msg_ptr->payload_len); memcpy(dst_packet_data_ptr, src_coap_msg_ptr->payload_ptr, src_coap_msg_ptr->payload_len);
/* Increase destination Packet data pointer */ /* Increase destination Packet data pointer */
(*dst_packet_data_pptr) += src_coap_msg_ptr->payload_len; dst_packet_data_ptr += src_coap_msg_ptr->payload_len;
} }
return dst_packet_data_ptr;
} }

View File

@ -42,11 +42,11 @@
/* * * * LOCAL FUNCTION PROTOTYPES * * * */ /* * * * LOCAL FUNCTION PROTOTYPES * * * */
/* * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * */
static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr); static const uint8_t *sn_coap_parser_header_parse(const uint8_t *packet_data_ptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr);
static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len); static const uint8_t *sn_coap_parser_options_parse(const uint8_t *packet_data_ptr, struct coap_s *handle, sn_coap_hdr_s *dst_coap_msg_ptr, const uint8_t *packet_data_start_ptr, uint_fast16_t packet_len);
static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len); static const uint8_t *sn_coap_parser_options_parse_multiple_options(const uint8_t *packet_data_ptr, struct coap_s *handle, uint_fast16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint_fast16_t option_number_len);
static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len); static int sn_coap_parser_options_count_needed_memory_multiple_option(const uint8_t *packet_data_ptr, uint_fast16_t packet_left_len, sn_coap_option_numbers_e option, uint_fast16_t option_number_len);
static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr); static const uint8_t *sn_coap_parser_payload_parse(const uint8_t *packet_data_ptr, uint16_t packet_data_len, uint8_t *packet_data_start_ptr, sn_coap_hdr_s *dst_coap_msg_ptr);
sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr) sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr)
{ {
@ -138,7 +138,7 @@ sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_c
sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr) sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr)
{ {
uint8_t *data_temp_ptr = packet_data_ptr; const uint8_t *data_temp_ptr = packet_data_ptr;
sn_coap_hdr_s *parsed_and_returned_coap_msg_ptr = NULL; sn_coap_hdr_s *parsed_and_returned_coap_msg_ptr = NULL;
/* * * * Check given pointer * * * */ /* * * * Check given pointer * * * */
@ -155,15 +155,18 @@ sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, u
} }
/* * * * Header parsing, move pointer over the header... * * * */ /* * * * Header parsing, move pointer over the header... * * * */
sn_coap_parser_header_parse(&data_temp_ptr, parsed_and_returned_coap_msg_ptr, coap_version_ptr); data_temp_ptr = sn_coap_parser_header_parse(data_temp_ptr, parsed_and_returned_coap_msg_ptr, coap_version_ptr);
/* * * * Options parsing, move pointer over the options... * * * */ /* * * * Options parsing, move pointer over the options... * * * */
if (sn_coap_parser_options_parse(handle, &data_temp_ptr, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len) != 0) { data_temp_ptr = sn_coap_parser_options_parse(data_temp_ptr, handle, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len);
if (!data_temp_ptr) {
parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
return parsed_and_returned_coap_msg_ptr; return parsed_and_returned_coap_msg_ptr;
} }
/* * * * Payload parsing * * * */ /* * * * Payload parsing * * * */
if (sn_coap_parser_payload_parse(packet_data_len, packet_data_ptr, &data_temp_ptr, parsed_and_returned_coap_msg_ptr) == -1) { data_temp_ptr = sn_coap_parser_payload_parse(data_temp_ptr, packet_data_len, packet_data_ptr, parsed_and_returned_coap_msg_ptr);
if (!data_temp_ptr) {
parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
return parsed_and_returned_coap_msg_ptr; return parsed_and_returned_coap_msg_ptr;
} }
@ -224,22 +227,20 @@ void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coa
* *
* \param *coap_version_ptr is destination for parsed CoAP specification version * \param *coap_version_ptr is destination for parsed CoAP specification version
*/ */
static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr) static const uint8_t *sn_coap_parser_header_parse(const uint8_t * restrict packet_data_ptr, sn_coap_hdr_s * restrict dst_coap_msg_ptr, coap_version_e * restrict coap_version_ptr)
{ {
/* Parse CoAP Version and message type*/ /* Parse CoAP Version and message type*/
*coap_version_ptr = (coap_version_e)(**packet_data_pptr & COAP_HEADER_VERSION_MASK); *coap_version_ptr = (coap_version_e)(*packet_data_ptr & COAP_HEADER_VERSION_MASK);
dst_coap_msg_ptr->msg_type = (sn_coap_msg_type_e)(**packet_data_pptr & COAP_HEADER_MSG_TYPE_MASK); dst_coap_msg_ptr->msg_type = (sn_coap_msg_type_e)(*packet_data_ptr++ & COAP_HEADER_MSG_TYPE_MASK);
(*packet_data_pptr) += 1;
/* Parse Message code */ /* Parse Message code */
dst_coap_msg_ptr->msg_code = (sn_coap_msg_code_e) **packet_data_pptr; dst_coap_msg_ptr->msg_code = (sn_coap_msg_code_e) *packet_data_ptr++;
(*packet_data_pptr) += 1;
/* Parse Message ID */ /* Parse Message ID */
dst_coap_msg_ptr->msg_id = *(*packet_data_pptr + 1); dst_coap_msg_ptr->msg_id = *packet_data_ptr++ << COAP_HEADER_MSG_ID_MSB_SHIFT;
dst_coap_msg_ptr->msg_id += **packet_data_pptr << COAP_HEADER_MSG_ID_MSB_SHIFT; dst_coap_msg_ptr->msg_id |= *packet_data_ptr++;
(*packet_data_pptr) += 2;
return packet_data_ptr;
} }
/** /**
@ -250,13 +251,15 @@ static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_
* *
* \return Return value is value of uint * \return Return value is value of uint
*/ */
static uint32_t sn_coap_parser_options_parse_uint(uint8_t **packet_data_pptr, uint8_t option_len) static uint32_t sn_coap_parser_options_parse_uint(const uint8_t * restrict * restrict packet_data_pptr, uint_fast8_t option_len)
{ {
uint32_t value = 0; uint32_t value = 0;
const uint8_t *packet_data_ptr = *packet_data_pptr;
while (option_len--) { while (option_len--) {
value <<= 8; value <<= 8;
value |= *(*packet_data_pptr)++; value |= *packet_data_ptr++;
} }
*packet_data_pptr = packet_data_ptr;
return value; return value;
} }
@ -267,15 +270,15 @@ static uint32_t sn_coap_parser_options_parse_uint(uint8_t **packet_data_pptr, ui
* \param b second term of addion * \param b second term of addion
* \param result pointer to the result variable * \param result pointer to the result variable
* *
* \return Return 0 if there was no overflow, -1 otherwise * \return Return 0 if there was no overflow, non-zero otherwise
*/ */
static int8_t sn_coap_parser_add_u16_limit(uint16_t a, uint16_t b, uint16_t *result) static int_fast8_t sn_coap_parser_add_u16_limit(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result)
{ {
uint16_t c; uint16_t c;
c = a + b; c = a + b;
if (c < a || c < b) { if (c < a || c < b) {
return -1; return 1;
} }
*result = c; *result = c;
@ -291,19 +294,19 @@ static int8_t sn_coap_parser_add_u16_limit(uint16_t a, uint16_t b, uint16_t *res
* \param packet_len total packet length * \param packet_len total packet length
* \param delta the number of bytes forward to check * \param delta the number of bytes forward to check
* *
* \return Return 0 if the data is within the bounds, -1 otherwise * \return Return 0 if the data is within the bounds, non-zero otherwise
*/ */
static int8_t sn_coap_parser_check_packet_ptr(uint8_t *packet_data_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len, uint16_t delta) static int_fast8_t sn_coap_parser_check_packet_ptr(const uint8_t *packet_data_ptr, const uint8_t *packet_data_start_ptr, uint_fast16_t packet_len, uint_fast16_t delta)
{ {
uint8_t *packet_end = packet_data_start_ptr + packet_len; const uint8_t *packet_end = packet_data_start_ptr + packet_len;
uint8_t *new_data_ptr = packet_data_ptr + delta; const uint8_t *new_data_ptr = packet_data_ptr + delta;
if (delta > packet_len) { if (delta > packet_len) {
return -1; return 1;
} }
if (new_data_ptr < packet_data_start_ptr || new_data_ptr > packet_end) { if (new_data_ptr < packet_data_start_ptr || new_data_ptr > packet_end) {
return -1; return 1;
} }
return 0; return 0;
@ -319,10 +322,10 @@ static int8_t sn_coap_parser_check_packet_ptr(uint8_t *packet_data_ptr, uint8_t
* *
* \return Return The remaining packet data length * \return Return The remaining packet data length
*/ */
static uint16_t sn_coap_parser_move_packet_ptr(uint8_t **packet_data_pptr, uint8_t *packet_data_start_ptr, uint16_t packet_len, uint16_t delta) static uint_fast16_t sn_coap_parser_move_packet_ptr(const uint8_t * restrict *packet_data_pptr, const uint8_t *packet_data_start_ptr, uint_fast16_t packet_len, uint_fast16_t delta)
{ {
uint8_t *packet_end = packet_data_start_ptr + packet_len; const uint8_t *packet_end = packet_data_start_ptr + packet_len;
uint8_t *new_data_ptr = *packet_data_pptr + delta; const uint8_t *new_data_ptr = *packet_data_pptr + delta;
if (new_data_ptr < packet_data_start_ptr) { if (new_data_ptr < packet_data_start_ptr) {
return 0; return 0;
@ -333,7 +336,7 @@ static uint16_t sn_coap_parser_move_packet_ptr(uint8_t **packet_data_pptr, uint8
*packet_data_pptr = new_data_ptr; *packet_data_pptr = new_data_ptr;
return (uint16_t)(packet_end - new_data_ptr); return (uint_fast16_t)(packet_end - new_data_ptr);
} }
/** /**
@ -344,11 +347,11 @@ static uint16_t sn_coap_parser_move_packet_ptr(uint8_t **packet_data_pptr, uint8
* \param packet_data_start_ptr pointer to data packet start * \param packet_data_start_ptr pointer to data packet start
* \param packet_len total packet length * \param packet_len total packet length
* *
* \return Return 0 if the data is within the bounds, -1 otherwise * \return Return 0 if the data is within the bounds, non-zero otherwise
*/ */
static int8_t sn_coap_parser_read_packet_u8(uint8_t *dst, uint8_t *packet_data_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len) static int8_t sn_coap_parser_read_packet_u8(uint8_t *dst, const uint8_t *packet_data_ptr, const uint8_t *packet_data_start_ptr, uint_fast16_t packet_len)
{ {
int8_t ptr_check_result; int_fast8_t ptr_check_result;
ptr_check_result = sn_coap_parser_check_packet_ptr(packet_data_ptr, packet_data_start_ptr, packet_len, 1); ptr_check_result = sn_coap_parser_check_packet_ptr(packet_data_ptr, packet_data_start_ptr, packet_len, 1);
@ -371,12 +374,12 @@ static int8_t sn_coap_parser_read_packet_u8(uint8_t *dst, uint8_t *packet_data_p
* \param packet_data_start_ptr pointer to data packet start * \param packet_data_start_ptr pointer to data packet start
* \param packet_len total packet length * \param packet_len total packet length
* *
* \return Return 0 if the data is within the bounds, -1 otherwise * \return Return 0 if the data is within the bounds, non-zero otherwise
*/ */
static int8_t sn_coap_parser_read_packet_u16(uint16_t *dst, uint8_t *packet_data_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len) static int_fast8_t sn_coap_parser_read_packet_u16(uint_fast16_t *dst, const uint8_t *packet_data_ptr, const uint8_t *packet_data_start_ptr, uint16_t packet_len)
{ {
int8_t ptr_check_result; int_fast8_t ptr_check_result;
uint16_t value; uint_fast16_t value;
ptr_check_result = sn_coap_parser_check_packet_ptr(packet_data_ptr, packet_data_start_ptr, packet_len, 2); ptr_check_result = sn_coap_parser_check_packet_ptr(packet_data_ptr, packet_data_start_ptr, packet_len, 2);
@ -402,9 +405,9 @@ static int8_t sn_coap_parser_read_packet_u16(uint16_t *dst, uint8_t *packet_data
* *
* \return Return 0 if the read was successful, -1 otherwise * \return Return 0 if the read was successful, -1 otherwise
*/ */
static int8_t parse_ext_option(uint16_t *dst, uint8_t **packet_data_pptr, uint8_t *packet_data_start_ptr, uint16_t packet_len, uint16_t *message_left) static int_fast8_t parse_ext_option(uint_fast16_t *dst, const uint8_t * restrict *packet_data_pptr, const uint8_t *packet_data_start_ptr, uint_fast16_t packet_len, uint_fast16_t *message_left)
{ {
uint16_t option_number = *dst; uint_fast16_t option_number = *dst;
if (option_number == 13) { if (option_number == 13) {
uint8_t option_ext; uint8_t option_ext;
@ -421,7 +424,7 @@ static int8_t parse_ext_option(uint16_t *dst, uint8_t **packet_data_pptr, uint8_
*message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, packet_data_start_ptr, packet_len, 1); *message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, packet_data_start_ptr, packet_len, 1);
} }
} else if (option_number == 14) { } else if (option_number == 14) {
int8_t read_result = sn_coap_parser_read_packet_u16(&option_number, *packet_data_pptr, packet_data_start_ptr, packet_len); int_fast8_t read_result = sn_coap_parser_read_packet_u16(&option_number, *packet_data_pptr, packet_data_start_ptr, packet_len);
if (read_result != 0) { if (read_result != 0) {
/* packet_data_pptr would overflow! */ /* packet_data_pptr would overflow! */
tr_error("sn_coap_parser_options_parse - **packet_data_pptr overflow !"); tr_error("sn_coap_parser_options_parse - **packet_data_pptr overflow !");
@ -449,67 +452,68 @@ static int8_t parse_ext_option(uint16_t *dst, uint8_t **packet_data_pptr, uint8_
* *
* \brief Parses CoAP message's Options part from given Packet data * \brief Parses CoAP message's Options part from given Packet data
* *
* \param **packet_data_pptr is source of Packet data to be parsed to CoAP message * \param *packet_data_ptr is source of Packet data to be parsed to CoAP message
* \param *dst_coap_msg_ptr is destination for parsed CoAP message * \param *dst_coap_msg_ptr is destination for parsed CoAP message
* *
* \return Return value is 0 in ok case and -1 in failure case * \return Return value is advanced input pointer in ok case and NULL in failure case
*/ */
static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len) static const uint8_t * sn_coap_parser_options_parse(const uint8_t * restrict packet_data_ptr, struct coap_s * restrict handle, sn_coap_hdr_s * restrict dst_coap_msg_ptr, const uint8_t *packet_data_start_ptr, uint_fast16_t packet_len)
{ {
uint8_t previous_option_number = 0; uint_fast16_t previous_option_number = 0;
int8_t ret_status = 0; uint_fast16_t message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, packet_data_start_ptr, packet_len, 0);
uint16_t message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, packet_data_start_ptr, packet_len, 0);
/* Parse token, if exists */ /* Parse token, if exists */
dst_coap_msg_ptr->token_len = *packet_data_start_ptr & COAP_HEADER_TOKEN_LENGTH_MASK; dst_coap_msg_ptr->token_len = *packet_data_start_ptr & COAP_HEADER_TOKEN_LENGTH_MASK;
if (dst_coap_msg_ptr->token_len) { if (dst_coap_msg_ptr->token_len) {
int8_t ptr_check_result; int_fast8_t ptr_check_result;
if ((dst_coap_msg_ptr->token_len > 8) || dst_coap_msg_ptr->token_ptr) { if ((dst_coap_msg_ptr->token_len > 8) || dst_coap_msg_ptr->token_ptr) {
tr_error("sn_coap_parser_options_parse - token not valid!"); tr_error("sn_coap_parser_options_parse - token not valid!");
return -1; return NULL;
} }
ptr_check_result = sn_coap_parser_check_packet_ptr(*packet_data_pptr, packet_data_start_ptr, packet_len, dst_coap_msg_ptr->token_len); ptr_check_result = sn_coap_parser_check_packet_ptr(packet_data_ptr, packet_data_start_ptr, packet_len, dst_coap_msg_ptr->token_len);
if (0 != ptr_check_result) { if (0 != ptr_check_result) {
tr_error("sn_coap_parser_options_parse - **packet_data_pptr overflow !"); tr_error("sn_coap_parser_options_parse - *packet_data_ptr overflow !");
return -1; return NULL;
} }
dst_coap_msg_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, *packet_data_pptr, dst_coap_msg_ptr->token_len); dst_coap_msg_ptr->token_ptr = sn_coap_protocol_malloc_copy(handle, packet_data_ptr, dst_coap_msg_ptr->token_len);
if (dst_coap_msg_ptr->token_ptr == NULL) { if (dst_coap_msg_ptr->token_ptr == NULL) {
tr_error("sn_coap_parser_options_parse - failed to allocate token!"); tr_error("sn_coap_parser_options_parse - failed to allocate token!");
return -1; return NULL;
} }
message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, packet_data_start_ptr, packet_len, dst_coap_msg_ptr->token_len); message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, packet_data_start_ptr, packet_len, dst_coap_msg_ptr->token_len);
} }
message_left = packet_len - (packet_data_ptr - packet_data_start_ptr);
/* Loop all Options */ /* Loop all Options */
while (message_left && (**packet_data_pptr != 0xff)) { uint_fast8_t option_byte;
while (message_left && ((option_byte = *packet_data_ptr) != 0xff)) {
/* Get option length WITHOUT extensions */ /* Get option length WITHOUT extensions */
uint16_t option_len = (**packet_data_pptr & 0x0F); uint_fast16_t option_len = (option_byte & 0x0F);
/* Get option number WITHOUT extensions */ /* Get option number WITHOUT extensions */
uint16_t option_number = (**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT); uint_fast16_t option_number = (option_byte >> COAP_OPTIONS_OPTION_NUMBER_SHIFT);
message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, packet_data_start_ptr, packet_len, 1); message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, packet_data_start_ptr, packet_len, 1);
int_fast8_t option_parse_result;
int8_t option_parse_result;
/* Add possible option delta extension */ /* Add possible option delta extension */
option_parse_result = parse_ext_option(&option_number, packet_data_pptr, packet_data_start_ptr, packet_len, &message_left); option_parse_result = parse_ext_option(&option_number, &packet_data_ptr, packet_data_start_ptr, packet_len, &message_left);
if (option_parse_result != 0) { if (option_parse_result != 0) {
return -1; return NULL;
} }
/* Add previous option to option delta and get option number */ /* Add previous option to option delta and get option number */
if (sn_coap_parser_add_u16_limit(option_number, previous_option_number, &option_number) != 0) { if (sn_coap_parser_add_u16_limit(option_number, previous_option_number, &option_number) != 0) {
return -1; return NULL;
} }
/* Add possible option length extension to resolve full length of the option */ /* Add possible option length extension to resolve full length of the option */
option_parse_result = parse_ext_option(&option_len, packet_data_pptr, packet_data_start_ptr, packet_len, &message_left); option_parse_result = parse_ext_option(&option_len, &packet_data_ptr, packet_data_start_ptr, packet_len, &message_left);
if (option_parse_result != 0) { if (option_parse_result != 0) {
return -1; return NULL;
} }
/* * * Parse option itself * * */ /* * * Parse option itself * * */
@ -533,15 +537,15 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack
case COAP_OPTION_SIZE2: case COAP_OPTION_SIZE2:
if (sn_coap_parser_alloc_options(handle, dst_coap_msg_ptr) == NULL) { if (sn_coap_parser_alloc_options(handle, dst_coap_msg_ptr) == NULL) {
tr_error("sn_coap_parser_options_parse - failed to allocate options!"); tr_error("sn_coap_parser_options_parse - failed to allocate options!");
return -1; return NULL;
} }
break; break;
} }
if (message_left < option_len){ if (message_left < option_len){
/* packet_data_pptr would overflow! */ /* packet_data_ptr would overflow! */
tr_error("sn_coap_parser_options_parse - **packet_data_pptr would overflow when parsing options!"); tr_error("sn_coap_parser_options_parse - *packet_data_ptr would overflow when parsing options!");
return -1; return NULL;
} }
/* Parse option */ /* Parse option */
@ -549,100 +553,102 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack
case COAP_OPTION_CONTENT_FORMAT: case COAP_OPTION_CONTENT_FORMAT:
if ((option_len > 2) || (dst_coap_msg_ptr->content_format != COAP_CT_NONE)) { if ((option_len > 2) || (dst_coap_msg_ptr->content_format != COAP_CT_NONE)) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_CONTENT_FORMAT not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_CONTENT_FORMAT not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->content_format = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->content_format = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
case COAP_OPTION_MAX_AGE: case COAP_OPTION_MAX_AGE:
if (option_len > 4) { if (option_len > 4) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_MAX_AGE not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_MAX_AGE not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->max_age = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->max_age = sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
case COAP_OPTION_PROXY_URI: case COAP_OPTION_PROXY_URI:
if ((option_len > 1034) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr) { if ((option_len > 1034) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->proxy_uri_len = option_len; dst_coap_msg_ptr->options_list_ptr->proxy_uri_len = option_len;
dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = sn_coap_protocol_malloc_copy(handle, *packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = sn_coap_protocol_malloc_copy(handle, packet_data_ptr, option_len);
if (dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr == NULL) { if (dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr == NULL) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI allocation failed!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI allocation failed!");
return -1; return NULL;
} }
message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, packet_data_start_ptr, packet_len, option_len); message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, packet_data_start_ptr, packet_len, option_len);
break; break;
case COAP_OPTION_ETAG: case COAP_OPTION_ETAG:
if (dst_coap_msg_ptr->options_list_ptr->etag_ptr) { if (dst_coap_msg_ptr->options_list_ptr->etag_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_ETAG exists!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_ETAG exists!");
return -1; return NULL;
} }
/* This is managed independently because User gives this option in one character table */ /* This is managed independently because User gives this option in one character table */
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, uint16_t len;
packet_data_ptr = sn_coap_parser_options_parse_multiple_options(packet_data_ptr, handle,
message_left, message_left,
&dst_coap_msg_ptr->options_list_ptr->etag_ptr, &dst_coap_msg_ptr->options_list_ptr->etag_ptr,
(uint16_t *)&dst_coap_msg_ptr->options_list_ptr->etag_len, &len,
COAP_OPTION_ETAG, option_len); COAP_OPTION_ETAG, option_len);
if (ret_status < 0) { if (!packet_data_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_ETAG not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_ETAG not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->etag_len = (uint8_t) len;
break; break;
case COAP_OPTION_URI_HOST: case COAP_OPTION_URI_HOST:
if ((option_len > 255) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->uri_host_ptr) { if ((option_len > 255) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->uri_host_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->uri_host_len = option_len; dst_coap_msg_ptr->options_list_ptr->uri_host_len = option_len;
dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = sn_coap_protocol_malloc_copy(handle, *packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = sn_coap_protocol_malloc_copy(handle, packet_data_ptr, option_len);
if (dst_coap_msg_ptr->options_list_ptr->uri_host_ptr == NULL) { if (dst_coap_msg_ptr->options_list_ptr->uri_host_ptr == NULL) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST allocation failed!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST allocation failed!");
return -1; return NULL;
} }
message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, packet_data_start_ptr, packet_len, option_len); message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, packet_data_start_ptr, packet_len, option_len);
break; break;
case COAP_OPTION_LOCATION_PATH: case COAP_OPTION_LOCATION_PATH:
if (dst_coap_msg_ptr->options_list_ptr->location_path_ptr) { if (dst_coap_msg_ptr->options_list_ptr->location_path_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_PATH exists!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_PATH exists!");
return -1; return NULL;
} }
/* This is managed independently because User gives this option in one character table */ /* This is managed independently because User gives this option in one character table */
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, packet_data_ptr = sn_coap_parser_options_parse_multiple_options(packet_data_ptr, handle, message_left,
&dst_coap_msg_ptr->options_list_ptr->location_path_ptr, &dst_coap_msg_ptr->options_list_ptr->location_path_len, &dst_coap_msg_ptr->options_list_ptr->location_path_ptr, &dst_coap_msg_ptr->options_list_ptr->location_path_len,
COAP_OPTION_LOCATION_PATH, option_len); COAP_OPTION_LOCATION_PATH, option_len);
if (ret_status < 0) { if (!packet_data_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_PATH not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_PATH not valid!");
return -1; return NULL;
} }
break; break;
case COAP_OPTION_URI_PORT: case COAP_OPTION_URI_PORT:
if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) { if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PORT not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PORT not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->uri_port = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->uri_port = sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
case COAP_OPTION_LOCATION_QUERY: case COAP_OPTION_LOCATION_QUERY:
if (dst_coap_msg_ptr->options_list_ptr->location_query_ptr) { if (dst_coap_msg_ptr->options_list_ptr->location_query_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_QUERY exists!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_QUERY exists!");
return -1; return NULL;
} }
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, packet_data_ptr = sn_coap_parser_options_parse_multiple_options(packet_data_ptr, handle, message_left,
&dst_coap_msg_ptr->options_list_ptr->location_query_ptr, &dst_coap_msg_ptr->options_list_ptr->location_query_len, &dst_coap_msg_ptr->options_list_ptr->location_query_ptr, &dst_coap_msg_ptr->options_list_ptr->location_query_len,
COAP_OPTION_LOCATION_QUERY, option_len); COAP_OPTION_LOCATION_QUERY, option_len);
if (ret_status < 0) { if (!packet_data_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_QUERY not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_QUERY not valid!");
return -1; return NULL;
} }
break; break;
@ -650,99 +656,99 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack
case COAP_OPTION_URI_PATH: case COAP_OPTION_URI_PATH:
if (dst_coap_msg_ptr->uri_path_ptr) { if (dst_coap_msg_ptr->uri_path_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PATH exists!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PATH exists!");
return -1; return NULL;
} }
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, packet_data_ptr = sn_coap_parser_options_parse_multiple_options(packet_data_ptr, handle, message_left,
&dst_coap_msg_ptr->uri_path_ptr, &dst_coap_msg_ptr->uri_path_len, &dst_coap_msg_ptr->uri_path_ptr, &dst_coap_msg_ptr->uri_path_len,
COAP_OPTION_URI_PATH, option_len); COAP_OPTION_URI_PATH, option_len);
if (ret_status < 0) { if (!packet_data_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PATH not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PATH not valid!");
return -1; return NULL;
} }
break; break;
case COAP_OPTION_OBSERVE: case COAP_OPTION_OBSERVE:
if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) { if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_OBSERVE not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_OBSERVE not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->observe = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->observe = sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
case COAP_OPTION_URI_QUERY: case COAP_OPTION_URI_QUERY:
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, packet_data_ptr = sn_coap_parser_options_parse_multiple_options(packet_data_ptr, handle, message_left,
&dst_coap_msg_ptr->options_list_ptr->uri_query_ptr, &dst_coap_msg_ptr->options_list_ptr->uri_query_len, &dst_coap_msg_ptr->options_list_ptr->uri_query_ptr, &dst_coap_msg_ptr->options_list_ptr->uri_query_len,
COAP_OPTION_URI_QUERY, option_len); COAP_OPTION_URI_QUERY, option_len);
if (ret_status < 0) { if (!packet_data_ptr) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_QUERY not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_QUERY not valid!");
return -1; return NULL;
} }
break; break;
case COAP_OPTION_BLOCK2: case COAP_OPTION_BLOCK2:
if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) { if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_BLOCK2 not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_BLOCK2 not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->block2 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->block2 = sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
case COAP_OPTION_BLOCK1: case COAP_OPTION_BLOCK1:
if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) { if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_BLOCK1 not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_BLOCK1 not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->block1 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->block1 = sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
case COAP_OPTION_ACCEPT: case COAP_OPTION_ACCEPT:
if ((option_len > 2) || (dst_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE)) { if ((option_len > 2) || (dst_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE)) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_ACCEPT not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_ACCEPT not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->accept = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->accept = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
case COAP_OPTION_SIZE1: case COAP_OPTION_SIZE1:
if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size1) { if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size1) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_SIZE1 not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_SIZE1 not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->use_size1 = true; dst_coap_msg_ptr->options_list_ptr->use_size1 = true;
dst_coap_msg_ptr->options_list_ptr->size1 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->size1 = sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
case COAP_OPTION_SIZE2: case COAP_OPTION_SIZE2:
if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size2) { if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size2) {
tr_error("sn_coap_parser_options_parse - COAP_OPTION_SIZE2 not valid!"); tr_error("sn_coap_parser_options_parse - COAP_OPTION_SIZE2 not valid!");
return -1; return NULL;
} }
dst_coap_msg_ptr->options_list_ptr->use_size2 = true; dst_coap_msg_ptr->options_list_ptr->use_size2 = true;
dst_coap_msg_ptr->options_list_ptr->size2 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len); dst_coap_msg_ptr->options_list_ptr->size2 = sn_coap_parser_options_parse_uint(&packet_data_ptr, option_len);
break; break;
default: default:
tr_error("sn_coap_parser_options_parse - unknown option!"); tr_error("sn_coap_parser_options_parse - unknown option!");
return -1; return NULL;
} }
/* Check for overflow */ /* Check for overflow */
if ((*packet_data_pptr - packet_data_start_ptr) > packet_len) { if ((packet_data_ptr - packet_data_start_ptr) > packet_len) {
return -1; return NULL;
} }
message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, packet_data_start_ptr, packet_len, 0); message_left = packet_len - (packet_data_ptr - packet_data_start_ptr);
} }
return 0; return packet_data_ptr;
} }
/** /**
* \fn static int8_t sn_coap_parser_options_parse_multiple_options(uint8_t **packet_data_pptr, uint8_t options_count_left, uint8_t *previous_option_number_ptr, uint8_t **dst_pptr, * \fn static int8_t sn_coap_parser_options_parse_multiple_options(uint8_t *packet_data_pptr, uint8_t options_count_left, uint8_t *previous_option_number_ptr, uint8_t **dst_pptr,
* uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len) * uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
* *
* \brief Parses CoAP message's Uri-query options * \brief Parses CoAP message's Uri-query options
* *
* \param **packet_data_pptr is source for Packet data to be parsed to CoAP message * \param *packet_data_ptr is source for Packet data to be parsed to CoAP message
* *
* \param *dst_coap_msg_ptr is destination for parsed CoAP message * \param *dst_coap_msg_ptr is destination for parsed CoAP message
* *
@ -750,26 +756,27 @@ static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **pack
* *
* \param *previous_option_number_ptr is pointer to used and returned previous Option number * \param *previous_option_number_ptr is pointer to used and returned previous Option number
* *
* \return Return value is count of Uri-query optios parsed. In failure case -1 is returned. * \return Return value is advanced input pointer. In failure case NULL is returned.
*/ */
static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len) static const uint8_t *sn_coap_parser_options_parse_multiple_options(const uint8_t * restrict packet_data_ptr, struct coap_s * restrict handle, uint_fast16_t packet_left_len, uint8_t ** restrict dst_pptr, uint16_t * restrict dst_len_ptr, sn_coap_option_numbers_e option, uint_fast16_t option_number_len)
{ {
int16_t uri_query_needed_heap = sn_coap_parser_options_count_needed_memory_multiple_option(*packet_data_pptr, packet_left_len, option, option_number_len);
uint8_t *temp_parsed_uri_query_ptr = NULL; int uri_query_needed_heap = sn_coap_parser_options_count_needed_memory_multiple_option(packet_data_ptr, packet_left_len, option, option_number_len);
uint8_t returned_option_counter = 0; uint8_t * restrict temp_parsed_uri_query_ptr = NULL;
uint8_t *start_ptr = *packet_data_pptr; const uint8_t *start_ptr = packet_data_ptr;
uint16_t message_left = packet_left_len; uint_fast16_t message_left = packet_left_len;
bool first_option = true;
if (uri_query_needed_heap == -1) { if (uri_query_needed_heap == -1) {
return -1; return NULL;
} }
if (uri_query_needed_heap) { if (uri_query_needed_heap) {
*dst_pptr = (uint8_t *) handle->sn_coap_protocol_malloc(uri_query_needed_heap); *dst_pptr = handle->sn_coap_protocol_malloc(uri_query_needed_heap);
if (*dst_pptr == NULL) { if (*dst_pptr == NULL) {
tr_error("sn_coap_parser_options_parse_multiple_options - failed to allocate options!"); tr_error("sn_coap_parser_options_parse_multiple_options - failed to allocate options!");
return -1; return NULL;
} }
} }
@ -779,7 +786,7 @@ static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handl
/* Loop all Uri-Query options */ /* Loop all Uri-Query options */
while ((temp_parsed_uri_query_ptr - *dst_pptr) < uri_query_needed_heap && message_left) { while ((temp_parsed_uri_query_ptr - *dst_pptr) < uri_query_needed_heap && message_left) {
/* Check if this is first Uri-Query option */ /* Check if this is first Uri-Query option */
if (returned_option_counter > 0) { if (!first_option) {
/* Uri-Query is modified to following format: temp1'\0'temp2'\0'temp3 i.e. */ /* Uri-Query is modified to following format: temp1'\0'temp2'\0'temp3 i.e. */
/* Uri-Path is modified to following format: temp1\temp2\temp3 i.e. */ /* Uri-Path is modified to following format: temp1\temp2\temp3 i.e. */
if (option == COAP_OPTION_URI_QUERY || option == COAP_OPTION_LOCATION_QUERY || option == COAP_OPTION_ETAG || option == COAP_OPTION_ACCEPT) { if (option == COAP_OPTION_URI_QUERY || option == COAP_OPTION_LOCATION_QUERY || option == COAP_OPTION_ETAG || option == COAP_OPTION_ACCEPT) {
@ -789,43 +796,42 @@ static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handl
} }
temp_parsed_uri_query_ptr++; temp_parsed_uri_query_ptr++;
} else {
first_option = false;
} }
returned_option_counter++;
if (((temp_parsed_uri_query_ptr - *dst_pptr) + option_number_len) > uri_query_needed_heap) { if (((temp_parsed_uri_query_ptr - *dst_pptr) + option_number_len) > uri_query_needed_heap) {
return -1; return NULL;
} }
if (0 != sn_coap_parser_check_packet_ptr(packet_data_ptr, start_ptr, packet_left_len, option_number_len)) {
if (0 != sn_coap_parser_check_packet_ptr(*packet_data_pptr, start_ptr, packet_left_len, option_number_len)) {
/* Buffer read overflow. */ /* Buffer read overflow. */
return -1; return NULL;
} }
/* Copy the option value to URI query buffer */ /* Copy the option value to URI query buffer */
memcpy(temp_parsed_uri_query_ptr, *packet_data_pptr, option_number_len); memcpy(temp_parsed_uri_query_ptr, packet_data_ptr, option_number_len);
message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, start_ptr, packet_left_len, option_number_len); message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, start_ptr, packet_left_len, option_number_len);
temp_parsed_uri_query_ptr += option_number_len; temp_parsed_uri_query_ptr += option_number_len;
/* Check if there is more input to process */ /* Check if there is more input to process */
if (message_left == 0 || ((**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0)) { if (message_left == 0 || ((*packet_data_ptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0)) {
return returned_option_counter; return packet_data_ptr;
} }
/* Process next option */ /* Process next option */
option_number_len = (**packet_data_pptr & 0x0F); option_number_len = (*packet_data_ptr & 0x0F);
message_left = sn_coap_parser_move_packet_ptr(packet_data_pptr, start_ptr, packet_left_len, 1); message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, start_ptr, packet_left_len, 1);
/* Add possible option length extension to resolve full length of the option */ /* Add possible option length extension to resolve full length of the option */
int8_t option_parse_result = parse_ext_option(&option_number_len, packet_data_pptr, start_ptr, packet_left_len, &message_left); int_fast8_t option_parse_result = parse_ext_option(&option_number_len, &packet_data_ptr, start_ptr, packet_left_len, &message_left);
if (option_parse_result != 0) { if (option_parse_result != 0) {
/* Extended option parsing failed. */ /* Extended option parsing failed. */
return -1; return NULL;
} }
} }
return returned_option_counter; return packet_data_ptr;
} }
/** /**
@ -843,11 +849,11 @@ static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handl
* *
* \param uint16_t option_number_len length of the first option part * \param uint16_t option_number_len length of the first option part
*/ */
static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len) static int sn_coap_parser_options_count_needed_memory_multiple_option(const uint8_t * restrict packet_data_ptr, uint_fast16_t packet_left_len, sn_coap_option_numbers_e option, uint_fast16_t option_number_len)
{ {
uint16_t ret_value = 0; int ret_value = 0;
uint16_t message_left = packet_left_len; uint_fast16_t message_left = packet_left_len;
uint8_t *start_ptr = packet_data_ptr; const uint8_t *start_ptr = packet_data_ptr;
/* Loop all Uri-Query options */ /* Loop all Uri-Query options */
while (message_left > 0) { while (message_left > 0) {
@ -871,7 +877,7 @@ static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_
} }
/* Check if the value length is within buffer limits */ /* Check if the value length is within buffer limits */
int8_t ptr_check_result = sn_coap_parser_check_packet_ptr(packet_data_ptr, start_ptr, packet_left_len, option_number_len); int_fast8_t ptr_check_result = sn_coap_parser_check_packet_ptr(packet_data_ptr, start_ptr, packet_left_len, option_number_len);
if (ptr_check_result != 0) { if (ptr_check_result != 0) {
return -1; return -1;
} }
@ -896,7 +902,7 @@ static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_
message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, start_ptr, packet_left_len, 1); message_left = sn_coap_parser_move_packet_ptr(&packet_data_ptr, start_ptr, packet_left_len, 1);
/* Add possible option length extension to resolve full length of the option */ /* Add possible option length extension to resolve full length of the option */
int8_t option_parse_result = parse_ext_option(&option_number_len, &packet_data_ptr, start_ptr, packet_left_len, &message_left); int_fast8_t option_parse_result = parse_ext_option(&option_number_len, &packet_data_ptr, start_ptr, packet_left_len, &message_left);
if (option_parse_result != 0) { if (option_parse_result != 0) {
return -1; return -1;
} }
@ -922,29 +928,29 @@ static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_
* *
* \param *dst_coap_msg_ptr is destination for parsed CoAP message * \param *dst_coap_msg_ptr is destination for parsed CoAP message
*****************************************************************************/ *****************************************************************************/
static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr) static const uint8_t *sn_coap_parser_payload_parse(const uint8_t * restrict packet_data_ptr, uint16_t packet_data_len, uint8_t *packet_data_start_ptr, sn_coap_hdr_s * restrict dst_coap_msg_ptr)
{ {
/* If there is payload */ /* If there is payload */
if ((*packet_data_pptr - packet_data_start_ptr) < packet_data_len) { if ((packet_data_ptr - packet_data_start_ptr) < packet_data_len) {
if (**packet_data_pptr == 0xff) { if (*packet_data_ptr == 0xff) {
(*packet_data_pptr)++; packet_data_ptr++;
/* Parse Payload length */ /* Parse Payload length */
dst_coap_msg_ptr->payload_len = packet_data_len - (*packet_data_pptr - packet_data_start_ptr); dst_coap_msg_ptr->payload_len = packet_data_len - (packet_data_ptr - packet_data_start_ptr);
/* The presence of a marker followed by a zero-length payload MUST be processed as a message format error */ /* The presence of a marker followed by a zero-length payload MUST be processed as a message format error */
if (dst_coap_msg_ptr->payload_len == 0) { if (dst_coap_msg_ptr->payload_len == 0) {
return -1; return NULL;
} }
/* Parse Payload by setting CoAP message's payload_ptr to point Payload in Packet data */ /* Parse Payload by setting CoAP message's payload_ptr to point Payload in Packet data */
dst_coap_msg_ptr->payload_ptr = *packet_data_pptr; dst_coap_msg_ptr->payload_ptr = (uint8_t *) packet_data_ptr;
} }
/* No payload marker.. */ /* No payload marker.. */
else { else {
tr_error("sn_coap_parser_payload_parse - payload marker not found!"); tr_error("sn_coap_parser_payload_parse - payload marker not found!");
return -1; return NULL;
} }
} }
return 0; return packet_data_ptr;
} }

View File

@ -52,8 +52,8 @@ static void sn_coap_protocol_linked_list_duplication_info_store
static coap_duplication_info_s *sn_coap_protocol_linked_list_duplication_info_search(const struct coap_s *handle, const sn_nsdl_addr_s *scr_addr_ptr, const uint16_t msg_id); static coap_duplication_info_s *sn_coap_protocol_linked_list_duplication_info_search(const struct coap_s *handle, const sn_nsdl_addr_s *scr_addr_ptr, const uint16_t msg_id);
static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle); static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle);
static void sn_coap_protocol_duplication_info_free(struct coap_s *handle, coap_duplication_info_s *duplication_info_ptr); static void sn_coap_protocol_duplication_info_free(struct coap_s *handle, coap_duplication_info_s *duplication_info_ptr);
static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *handle, const sn_nsdl_addr_s *dst_addr_ptr, const sn_coap_hdr_s *coap_msg_ptr, const int16_t data_size, const uint8_t *dst_packet_data_ptr); static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *handle, const sn_nsdl_addr_s *dst_addr_ptr, const sn_coap_hdr_s *coap_msg_ptr, const int_fast16_t data_size, const uint8_t *dst_packet_data_ptr);
static bool sn_coap_protocol_update_duplicate_package_data_all(const struct coap_s *handle, const sn_nsdl_addr_s *dst_addr_ptr, const sn_coap_hdr_s *coap_msg_ptr, const int16_t data_size, const uint8_t *dst_packet_data_ptr); static bool sn_coap_protocol_update_duplicate_package_data_all(const struct coap_s *handle, const sn_nsdl_addr_s *dst_addr_ptr, const sn_coap_hdr_s *coap_msg_ptr, const int_fast16_t data_size, const uint8_t *dst_packet_data_ptr);
#endif #endif
@ -65,8 +65,8 @@ static coap_blockwise_payload_s *sn_coap_protocol_linked_list_blockwise_search(s
static bool sn_coap_protocol_linked_list_blockwise_payload_search_compare_block_number(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len, uint32_t block_number); static bool sn_coap_protocol_linked_list_blockwise_payload_search_compare_block_number(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len, uint32_t block_number);
static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, coap_blockwise_payload_s *removed_payload_ptr); static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, coap_blockwise_payload_s *removed_payload_ptr);
static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len); static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, const uint8_t *token_ptr, uint8_t token_len);
static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle); static void sn_coap_protocol_handle_blockwise_timeout(struct coap_s *handle);
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); 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, bool *keep_in_resend_queue);
static bool sn_coap_handle_last_blockwise(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr); static bool sn_coap_handle_last_blockwise(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr);
static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, const sn_coap_hdr_s *source_header_ptr); static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, const sn_coap_hdr_s *source_header_ptr);
static coap_blockwise_msg_s *search_sent_blockwise_message(struct coap_s *handle, uint16_t msg_id); static coap_blockwise_msg_s *search_sent_blockwise_message(struct coap_s *handle, uint16_t msg_id);
@ -74,11 +74,11 @@ static int16_t store_blockwise_copy(struct coap_s *handle, cons
#endif #endif
#if ENABLE_RESENDINGS #if ENABLE_RESENDINGS
static uint8_t sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param); static uint8_t sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint_fast16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param);
static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id);
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); static coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint_fast16_t packet_data_len);
static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr); static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr);
static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr); static uint_fast16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr);
static uint32_t sn_coap_calculate_new_resend_time(const uint32_t current_time, const uint8_t interval, const uint8_t counter); static uint32_t sn_coap_calculate_new_resend_time(const uint32_t current_time, const uint8_t interval, const uint8_t counter);
#endif #endif
@ -202,19 +202,9 @@ int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_siz
if (handle == NULL) { if (handle == NULL) {
return -1; return -1;
} }
switch (block_size) { if (sn_coap_convert_block_size(block_size) >= 0) {
case 0:
case 16:
case 32:
case 64:
case 128:
case 256:
case 512:
case 1024:
handle->sn_coap_block_data_size = block_size; handle->sn_coap_block_data_size = block_size;
return 0; return 0;
default:
break;
} }
#endif #endif
return -1; return -1;
@ -317,8 +307,8 @@ void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle)
ns_list_foreach_safe(coap_send_msg_s, tmp, &handle->linked_list_resent_msgs) { ns_list_foreach_safe(coap_send_msg_s, tmp, &handle->linked_list_resent_msgs) {
ns_list_remove(&handle->linked_list_resent_msgs, tmp); ns_list_remove(&handle->linked_list_resent_msgs, tmp);
sn_coap_protocol_release_allocated_send_msg_mem(handle, tmp); sn_coap_protocol_release_allocated_send_msg_mem(handle, tmp);
--handle->count_resent_msgs;
} }
handle->count_resent_msgs = 0;
#endif #endif
} }
@ -523,7 +513,7 @@ int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_p
#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
static int16_t store_blockwise_copy(struct coap_s *handle, const sn_coap_hdr_s *src_coap_msg_ptr, void *param, uint16_t original_payload_len, bool copy_payload) static int16_t store_blockwise_copy(struct coap_s *handle, const sn_coap_hdr_s *src_coap_msg_ptr, void *param, uint16_t original_payload_len, bool copy_payload)
{ {
coap_blockwise_msg_s *stored_blockwise_msg_ptr; coap_blockwise_msg_s *restrict stored_blockwise_msg_ptr;
stored_blockwise_msg_ptr = sn_coap_protocol_calloc(handle, sizeof(coap_blockwise_msg_s)); stored_blockwise_msg_ptr = sn_coap_protocol_calloc(handle, sizeof(coap_blockwise_msg_s));
if (!stored_blockwise_msg_ptr) { if (!stored_blockwise_msg_ptr) {
@ -535,20 +525,21 @@ static int16_t store_blockwise_copy(struct coap_s *handle, const sn_coap_hdr_s *
/* Fill struct */ /* Fill struct */
stored_blockwise_msg_ptr->timestamp = handle->system_time; stored_blockwise_msg_ptr->timestamp = handle->system_time;
stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr); sn_coap_hdr_s *restrict copied_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr);
if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){ if (copied_msg_ptr == NULL) {
handle->sn_coap_protocol_free(stored_blockwise_msg_ptr); handle->sn_coap_protocol_free(stored_blockwise_msg_ptr);
tr_error("sn_coap_protocol_build - block header copy failed!"); tr_error("sn_coap_protocol_build - block header copy failed!");
return -2; return -2;
} }
stored_blockwise_msg_ptr->coap_msg_ptr = copied_msg_ptr;
if (copy_payload) { if (copy_payload) {
stored_blockwise_msg_ptr->coap_msg_ptr->payload_len = original_payload_len; copied_msg_ptr->payload_len = original_payload_len;
stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = sn_coap_protocol_malloc_copy(handle, src_coap_msg_ptr->payload_ptr, stored_blockwise_msg_ptr->coap_msg_ptr->payload_len); copied_msg_ptr->payload_ptr = sn_coap_protocol_malloc_copy(handle, src_coap_msg_ptr->payload_ptr, stored_blockwise_msg_ptr->coap_msg_ptr->payload_len);
if (!stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) { if (!copied_msg_ptr->payload_ptr) {
//block payload save failed, only first block can be build. Perhaps we should return error. //block payload save failed, only first block can be build. Perhaps we should return error.
sn_coap_parser_release_allocated_coap_msg_mem(handle, stored_blockwise_msg_ptr->coap_msg_ptr); sn_coap_parser_release_allocated_coap_msg_mem(handle, copied_msg_ptr);
handle->sn_coap_protocol_free(stored_blockwise_msg_ptr); handle->sn_coap_protocol_free(stored_blockwise_msg_ptr);
tr_error("sn_coap_protocol_build - block payload allocation failed!"); tr_error("sn_coap_protocol_build - block payload allocation failed!");
return -2; return -2;
@ -556,7 +547,7 @@ static int16_t store_blockwise_copy(struct coap_s *handle, const sn_coap_hdr_s *
} }
stored_blockwise_msg_ptr->param = param; stored_blockwise_msg_ptr->param = param;
stored_blockwise_msg_ptr->msg_id = stored_blockwise_msg_ptr->coap_msg_ptr->msg_id; stored_blockwise_msg_ptr->msg_id = copied_msg_ptr->msg_id;
ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
@ -564,9 +555,8 @@ static int16_t store_blockwise_copy(struct coap_s *handle, const sn_coap_hdr_s *
} }
#endif #endif
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) sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *restrict handle, sn_nsdl_addr_s *restrict src_addr_ptr, uint16_t packet_data_len, uint8_t *restrict packet_data_ptr, void *param)
{ {
sn_coap_hdr_s *returned_dst_coap_msg_ptr = NULL;
coap_version_e coap_version = COAP_VERSION_UNKNOWN; coap_version_e coap_version = COAP_VERSION_UNKNOWN;
/* * * * Check given pointer * * * */ /* * * * Check given pointer * * * */
@ -576,7 +566,7 @@ sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src
} }
/* * * * Parse Packet data to CoAP message by using CoAP Header parser * * * */ /* * * * Parse Packet data to CoAP message by using CoAP Header parser * * * */
returned_dst_coap_msg_ptr = sn_coap_parser(handle, packet_data_len, packet_data_ptr, &coap_version); sn_coap_hdr_s *restrict returned_dst_coap_msg_ptr = sn_coap_parser(handle, packet_data_len, packet_data_ptr, &coap_version);
/* Check status of returned pointer */ /* Check status of returned pointer */
if (returned_dst_coap_msg_ptr == NULL) { if (returned_dst_coap_msg_ptr == NULL) {
@ -651,9 +641,7 @@ sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src
// If no message duplication detected // If no message duplication detected
if ((returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE || if ((returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE ||
returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE || returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) &&
(returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT &&
returned_dst_coap_msg_ptr->msg_code != COAP_MSG_CODE_EMPTY)) &&
handle->sn_coap_duplication_buffer_size != 0) { handle->sn_coap_duplication_buffer_size != 0) {
coap_duplication_info_s *response = sn_coap_protocol_linked_list_duplication_info_search(handle, coap_duplication_info_s *response = sn_coap_protocol_linked_list_duplication_info_search(handle,
@ -686,7 +674,7 @@ sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src
returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_DUPLICATED_MSG; returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_DUPLICATED_MSG;
// Send ACK response // Send ACK response
if (response && returned_dst_coap_msg_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT) { if (response) {
// Check that response has been created // Check that response has been created
if (response->packet_ptr) { if (response->packet_ptr) {
tr_debug("sn_coap_protocol_parse - send ack for duplicate message"); tr_debug("sn_coap_protocol_parse - send ack for duplicate message");
@ -705,7 +693,7 @@ sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src
/*** And here we check if message was block message ***/ /*** And here we check if message was block message ***/
/*** If so, we call own block handling function and ***/ /*** If so, we call own block handling function and ***/
/*** return to caller. ***/ /*** return to caller. ***/
bool keep_in_resend_queue = false;
#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
if (returned_dst_coap_msg_ptr->options_list_ptr != NULL && if (returned_dst_coap_msg_ptr->options_list_ptr != NULL &&
@ -713,7 +701,7 @@ sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src
returned_dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE)) { returned_dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE)) {
// the sn_coap_handle_blockwise_message() will return the given message on success or NULL on error // the sn_coap_handle_blockwise_message() will return the given message on success or NULL on error
if (sn_coap_handle_blockwise_message(handle, src_addr_ptr, returned_dst_coap_msg_ptr, param) == NULL) { if (sn_coap_handle_blockwise_message(handle, src_addr_ptr, returned_dst_coap_msg_ptr, param, &keep_in_resend_queue) == NULL) {
tr_error("sn_coap_protocol_parse - handle blockwise returns null!"); tr_error("sn_coap_protocol_parse - handle blockwise returns null!");
@ -794,11 +782,11 @@ cleanup:
/* Get ... */ /* Get ... */
coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = search_sent_blockwise_message(handle, returned_dst_coap_msg_ptr->msg_id); coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = search_sent_blockwise_message(handle, returned_dst_coap_msg_ptr->msg_id);
/* Remove from the list if not an notification message. /* Remove from the list if not a notification message.
* Initial notification message is needed for sending rest of the blocks (GET request). * Initial notification message is needed for sending rest of the blocks (GET request).
*/ */
bool remove_from_the_list = false;
if (stored_blockwise_msg_temp_ptr) { if (stored_blockwise_msg_temp_ptr) {
bool remove_from_the_list;
if (stored_blockwise_msg_temp_ptr->coap_msg_ptr && if (stored_blockwise_msg_temp_ptr->coap_msg_ptr &&
stored_blockwise_msg_temp_ptr->coap_msg_ptr->options_list_ptr && stored_blockwise_msg_temp_ptr->coap_msg_ptr->options_list_ptr &&
stored_blockwise_msg_temp_ptr->coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) { stored_blockwise_msg_temp_ptr->coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
@ -806,12 +794,12 @@ cleanup:
} else { } else {
remove_from_the_list = true; remove_from_the_list = true;
} }
}
if (remove_from_the_list) {
if (remove_from_the_list) {
sn_coap_protocol_linked_list_blockwise_msg_remove(handle, stored_blockwise_msg_temp_ptr); sn_coap_protocol_linked_list_blockwise_msg_remove(handle, stored_blockwise_msg_temp_ptr);
} }
} }
}
if (!returned_dst_coap_msg_ptr) { if (!returned_dst_coap_msg_ptr) {
tr_error("sn_coap_protocol_parse - returned_dst_coap_msg_ptr null!"); tr_error("sn_coap_protocol_parse - returned_dst_coap_msg_ptr null!");
@ -830,7 +818,7 @@ cleanup:
/* Get node count i.e. count of active resending messages */ /* Get node count i.e. count of active resending messages */
uint16_t stored_resending_msgs_count = handle->count_resent_msgs; uint16_t stored_resending_msgs_count = handle->count_resent_msgs;
/* Check if there is ongoing active message resendings */ /* Check if there is ongoing active message resendings */
if (stored_resending_msgs_count > 0) { if (stored_resending_msgs_count > 0 && !keep_in_resend_queue) {
/* Remove resending message from active message resending Linked list, if any exists */ /* Remove resending message from active message resending Linked list, if any exists */
sn_coap_protocol_linked_list_send_msg_remove(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id); sn_coap_protocol_linked_list_send_msg_remove(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id);
} }
@ -853,7 +841,7 @@ int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time)
#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
/* * * * Handle block transfer timed outs * * * */ /* * * * Handle block transfer timed outs * * * */
sn_coap_protocol_handle_blockwise_timout(handle); sn_coap_protocol_handle_blockwise_timeout(handle);
#endif #endif
#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT
@ -888,6 +876,9 @@ rescan:
tmp_coap_hdr_ptr = sn_coap_parser(handle, stored_msg_ptr->send_msg_ptr.packet_len, stored_msg_ptr->send_msg_ptr.packet_ptr, &coap_version); tmp_coap_hdr_ptr = sn_coap_parser(handle, stored_msg_ptr->send_msg_ptr.packet_len, stored_msg_ptr->send_msg_ptr.packet_ptr, &coap_version);
if (tmp_coap_hdr_ptr != 0) { if (tmp_coap_hdr_ptr != 0) {
#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
sn_coap_protocol_remove_sent_blockwise_message(handle, tmp_coap_hdr_ptr->msg_id);
#endif // SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
tmp_coap_hdr_ptr->coap_status = COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED; tmp_coap_hdr_ptr->coap_status = COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED;
handle->sn_coap_rx_callback(tmp_coap_hdr_ptr, &stored_msg_ptr->send_msg_ptr.dst_addr_ptr, stored_msg_ptr->param); handle->sn_coap_rx_callback(tmp_coap_hdr_ptr, &stored_msg_ptr->send_msg_ptr.dst_addr_ptr, stored_msg_ptr->param);
@ -938,11 +929,11 @@ rescan:
* \return 1 Msg stored properly * \return 1 Msg stored properly
*****************************************************************************/ *****************************************************************************/
static uint8_t sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, static uint8_t sn_coap_protocol_linked_list_send_msg_store(struct coap_s *restrict handle, sn_nsdl_addr_s *restrict dst_addr_ptr, uint_fast16_t send_packet_data_len,
uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param) uint8_t *restrict send_packet_data_ptr, uint32_t sending_time, void *param)
{ {
coap_send_msg_s *stored_msg_ptr; coap_send_msg_s *restrict stored_msg_ptr;
/* If both queue parameters are "0" or resending count is "0", then re-sending is disabled */ /* If both queue parameters are "0" or resending count is "0", then re-sending is disabled */
if (((handle->sn_coap_resending_queue_msgs == 0) && (handle->sn_coap_resending_queue_bytes == 0)) || (handle->sn_coap_resending_count == 0)) { if (((handle->sn_coap_resending_queue_msgs == 0) && (handle->sn_coap_resending_queue_bytes == 0)) || (handle->sn_coap_resending_count == 0)) {
@ -1005,7 +996,7 @@ static uint8_t sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle
* \param msg_id is searching key for removed message * \param msg_id is searching key for removed message
*****************************************************************************/ *****************************************************************************/
static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, const sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *restrict handle, const sn_nsdl_addr_s *restrict src_addr_ptr, uint16_t msg_id)
{ {
/* Loop all stored resending messages in Linked list */ /* Loop all stored resending messages in Linked list */
ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) {
@ -1075,10 +1066,10 @@ uint16_t sn_coap_protocol_get_configured_blockwise_size(struct coap_s *handle)
* \param *addr_ptr is pointer to Address information to be stored * \param *addr_ptr is pointer to Address information to be stored
*****************************************************************************/ *****************************************************************************/
static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *restrict handle, sn_nsdl_addr_s *restrict addr_ptr,
uint16_t msg_id, void *param) uint16_t msg_id, void *param)
{ {
coap_duplication_info_s *stored_duplication_info_ptr = NULL; coap_duplication_info_s *restrict stored_duplication_info_ptr = NULL;
/* * * * Allocating memory for stored Duplication info * * * */ /* * * * Allocating memory for stored Duplication info * * * */
@ -1209,7 +1200,8 @@ void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle,
#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT
static void sn_coap_protocol_duplication_info_free(struct coap_s *handle, coap_duplication_info_s *duplication_info_ptr) static void sn_coap_protocol_duplication_info_free(struct coap_s *handle, coap_duplication_info_s *duplication_info_ptr)
{ {
if (duplication_info_ptr) { // General purpose free functions ignore null pointer inputs - this
// private one knows it never receives null.
if (duplication_info_ptr->address) { if (duplication_info_ptr->address) {
handle->sn_coap_protocol_free(duplication_info_ptr->address->addr_ptr); handle->sn_coap_protocol_free(duplication_info_ptr->address->addr_ptr);
handle->sn_coap_protocol_free(duplication_info_ptr->address); handle->sn_coap_protocol_free(duplication_info_ptr->address);
@ -1217,7 +1209,6 @@ static void sn_coap_protocol_duplication_info_free(struct coap_s *handle, coap_d
handle->sn_coap_protocol_free(duplication_info_ptr->packet_ptr); handle->sn_coap_protocol_free(duplication_info_ptr->packet_ptr);
handle->sn_coap_protocol_free(duplication_info_ptr); handle->sn_coap_protocol_free(duplication_info_ptr);
} }
}
#endif // SN_COAP_DUPLICATION_MAX_MSGS_COUNT #endif // SN_COAP_DUPLICATION_MAX_MSGS_COUNT
#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
@ -1257,10 +1248,10 @@ static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *han
* \param size1 Size of the whole incoming message * \param size1 Size of the whole incoming message
*****************************************************************************/ *****************************************************************************/
static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *restrict handle, sn_nsdl_addr_s *restrict addr_ptr,
uint16_t payload_len, uint16_t payload_len,
uint8_t *payload_ptr, uint8_t *restrict payload_ptr,
uint8_t *token_ptr, uint8_t *restrict token_ptr,
uint8_t token_len, uint8_t token_len,
uint32_t block_number, uint32_t block_number,
uint16_t block_size, uint16_t block_size,
@ -1279,7 +1270,7 @@ static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *
return; return;
} }
coap_blockwise_payload_s *stored_blockwise_payload_ptr = sn_coap_protocol_linked_list_blockwise_search(handle, addr_ptr, token_ptr, token_len); coap_blockwise_payload_s *restrict stored_blockwise_payload_ptr = sn_coap_protocol_linked_list_blockwise_search(handle, addr_ptr, token_ptr, token_len);
if (stored_blockwise_payload_ptr && stored_blockwise_payload_ptr->use_size1) { if (stored_blockwise_payload_ptr && stored_blockwise_payload_ptr->use_size1) {
memcpy(stored_blockwise_payload_ptr->payload_ptr + (block_number * block_size), payload_ptr, payload_len); memcpy(stored_blockwise_payload_ptr->payload_ptr + (block_number * block_size), payload_ptr, payload_len);
@ -1287,7 +1278,7 @@ static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *
uint16_t new_len = stored_blockwise_payload_ptr->payload_len + payload_len; uint16_t new_len = stored_blockwise_payload_ptr->payload_len + payload_len;
tr_debug("sn_coap_protocol_linked_list_blockwise_payload_store - reallocate from %d to %d", stored_blockwise_payload_ptr->payload_len, new_len); tr_debug("sn_coap_protocol_linked_list_blockwise_payload_store - reallocate from %d to %d", stored_blockwise_payload_ptr->payload_len, new_len);
uint8_t *temp_ptr = handle->sn_coap_protocol_malloc(stored_blockwise_payload_ptr->payload_len); uint8_t *restrict temp_ptr = handle->sn_coap_protocol_malloc(stored_blockwise_payload_ptr->payload_len);
if (temp_ptr == NULL) { if (temp_ptr == NULL) {
tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate temp buffer!"); tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate temp buffer!");
sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_blockwise_payload_ptr); sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_blockwise_payload_ptr);
@ -1530,50 +1521,15 @@ static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct c
} }
/**************************************************************************//** /**************************************************************************//**
* \fn static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) * \fn static void sn_coap_protocol_handle_blockwise_timeout(struct coap_s *handle)
* *
* \brief Check incoming and outgoing blockwise messages for time out. * \brief Check incoming and outgoing blockwise messages for time out.
* Remove timed out messages from lists. Notify application if * Remove timed out messages from lists. Notify application if
* outgoing message times out. * outgoing message times out.
*****************************************************************************/ *****************************************************************************/
static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) static void sn_coap_protocol_handle_blockwise_timeout(struct coap_s *handle)
{ {
/* Loop all outgoing blockwise messages */
/* foreach_safe isn't sufficient because callback routine could remove messages. */
rescan:
ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) {
if ((handle->system_time - removed_blocwise_msg_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) {
bool callback_called = false;
// Item must be removed from the list before calling the rx_callback function.
// Callback could actually clear the list and free the item and cause a use after free when callback returns.
ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_blocwise_msg_ptr);
/* * * * This messages has timed out, remove it from Linked list * * * */
if( removed_blocwise_msg_ptr->coap_msg_ptr ){
if (handle->sn_coap_rx_callback) {
/* Notify the application about the time out */
removed_blocwise_msg_ptr->coap_msg_ptr->coap_status = COAP_STATUS_BUILDER_BLOCK_SENDING_FAILED;
removed_blocwise_msg_ptr->coap_msg_ptr->msg_id = removed_blocwise_msg_ptr->msg_id;
sn_coap_protocol_delete_retransmission(handle, removed_blocwise_msg_ptr->msg_id);
handle->sn_coap_rx_callback(removed_blocwise_msg_ptr->coap_msg_ptr, NULL, removed_blocwise_msg_ptr->param);
callback_called = true;
}
handle->sn_coap_protocol_free(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr);
sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_blocwise_msg_ptr->coap_msg_ptr);
}
handle->sn_coap_protocol_free(removed_blocwise_msg_ptr);
if (callback_called) {
/* Callback routine could have wiped the list already */
/* Be super cautious and rescan from the start */
goto rescan;
}
}
}
/* Loop all incoming Blockwise messages */ /* Loop all incoming Blockwise messages */
ns_list_foreach_safe(coap_blockwise_payload_s, removed_blocwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) { ns_list_foreach_safe(coap_blockwise_payload_s, removed_blocwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) {
if ((handle->system_time - removed_blocwise_payload_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { if ((handle->system_time - removed_blocwise_payload_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) {
@ -1599,7 +1555,7 @@ rescan:
* \return pointer to allocated struct * \return pointer to allocated struct
*****************************************************************************/ *****************************************************************************/
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) coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint_fast16_t packet_data_len)
{ {
coap_send_msg_s *msg_ptr = sn_coap_protocol_calloc(handle, sizeof(coap_send_msg_s)); coap_send_msg_s *msg_ptr = sn_coap_protocol_calloc(handle, sizeof(coap_send_msg_s));
@ -1650,9 +1606,9 @@ static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handl
* *
* \param const coap_send_msg_list_t *linked_list_ptr pointer to linked list * \param const coap_send_msg_list_t *linked_list_ptr pointer to linked list
*****************************************************************************/ *****************************************************************************/
static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr) static uint_fast16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr)
{ {
uint16_t total_size = 0; uint_fast16_t total_size = 0;
ns_list_foreach(coap_send_msg_s, stored_msg_ptr, linked_list_ptr) { ns_list_foreach(coap_send_msg_s, stored_msg_ptr, linked_list_ptr) {
total_size += stored_msg_ptr->send_msg_ptr.packet_len; total_size += stored_msg_ptr->send_msg_ptr.packet_len;
@ -1715,8 +1671,7 @@ void sn_coap_protocol_block_remove(struct coap_s *handle, sn_nsdl_addr_s *source
continue; continue;
} }
if(!memcmp(stored_payload_info_ptr->payload_ptr, payload, stored_payload_info_ptr->payload_len)) if (!memcmp(stored_payload_info_ptr->payload_ptr, payload, stored_payload_info_ptr->payload_len)) {
{
/* Everything matches, remove and return. */ /* Everything matches, remove and return. */
sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_payload_info_ptr); sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_payload_info_ptr);
return; return;
@ -1754,11 +1709,11 @@ static coap_blockwise_msg_s *sn_coap_stored_blockwise_msg_get(struct coap_s *han
* \param *received_coap_msg_ptr pointer to parsed CoAP message structure * \param *received_coap_msg_ptr pointer to parsed CoAP message structure
*****************************************************************************/ *****************************************************************************/
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) 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, bool *keep_in_resend_queue)
{ {
sn_coap_hdr_s *src_coap_blockwise_ack_msg_ptr = NULL; sn_coap_hdr_s *src_coap_blockwise_ack_msg_ptr = NULL;
uint16_t dst_packed_data_needed_mem = 0; uint16_t dst_packed_data_needed_mem = 0;
uint8_t *dst_ack_packet_data_ptr = NULL; uint8_t *restrict dst_ack_packet_data_ptr = NULL;
uint8_t block_temp = 0; uint8_t block_temp = 0;
uint16_t original_payload_len = 0; uint16_t original_payload_len = 0;
@ -1768,27 +1723,29 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
// Blocked request sending, received ACK, sending next block.. // Blocked request sending, received ACK, sending next block..
if (received_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) { if (received_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) { if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) {
if (received_coap_msg_ptr->options_list_ptr->block1 & 0x08) {
coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr;
/* Get */ coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr;
stored_blockwise_msg_temp_ptr = search_sent_blockwise_message(handle, received_coap_msg_ptr->msg_id); stored_blockwise_msg_temp_ptr = search_sent_blockwise_message(handle, received_coap_msg_ptr->msg_id);
if (received_coap_msg_ptr->options_list_ptr->block1 & 0x08) {
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK;
if (stored_blockwise_msg_temp_ptr) { if (stored_blockwise_msg_temp_ptr) {
/* Build response message */ /* Build response message */
uint16_t block_size; uint_fast16_t block_size;
uint32_t block_number; uint32_t block_number;
uint32_t req_block_number;
src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr;
/* Get block option parameters from received message */ /* Get block option parameters from received message */
block_number = received_coap_msg_ptr->options_list_ptr->block1 >> 4; block_number = received_coap_msg_ptr->options_list_ptr->block1 >> 4;
block_temp = received_coap_msg_ptr->options_list_ptr->block1 & 0x07; block_temp = received_coap_msg_ptr->options_list_ptr->block1 & 0x07;
block_size = 1u << (block_temp + 4); block_size = 16u << block_temp;
/* Build next block message */
src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr;
if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) { if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) {
req_block_number = src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 >> 4;
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE; src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
// Do not clear block2 as it might have been set in the original request to request // Do not clear block2 as it might have been set in the original request to request
// specific size blocks // specific size blocks
@ -1797,8 +1754,15 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
tr_error("sn_coap_handle_blockwise_message - (send block1) failed to allocate ack message!"); tr_error("sn_coap_handle_blockwise_message - (send block1) failed to allocate ack message!");
return 0; return 0;
} }
// pass through to send a next request
req_block_number = block_number;
} }
// Make sure that block number is the one we requested. If it's the old one just ignore it and wait for next response.
if (req_block_number == block_number) {
/* Build next block message */
block_number++; block_number++;
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = (block_number << 4) | block_temp; src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = (block_number << 4) | block_temp;
@ -1838,6 +1802,7 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
#if ENABLE_RESENDINGS #if ENABLE_RESENDINGS
uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0); uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
if (src_coap_blockwise_ack_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { if (src_coap_blockwise_ack_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr, sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
dst_packed_data_needed_mem, dst_packed_data_needed_mem,
@ -1852,18 +1817,28 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len; stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len;
stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr; stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr;
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK;
// Remove original message from the list when last block has been sent. // Remove original message from the list when last block has been sent.
if (!((src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1) & 0x08)) { if (!((src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1) & 0x08)) {
sn_coap_protocol_remove_sent_blockwise_message(handle, stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id); sn_coap_protocol_remove_sent_blockwise_message(handle, stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id);
} }
} else {
tr_warn("sn_coap_handle_blockwise_message - blocks not in order, requested: %"PRIu32" received: %"PRIu32" --> ignore", req_block_number, block_number);
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = (req_block_number << 4) | block_temp;
*keep_in_resend_queue = true;
} }
}
} else {
if (stored_blockwise_msg_temp_ptr) {
// Last block received but some blocks are not yet sent. Ignore it and wait for next response.
tr_warn("sn_coap_handle_blockwise_message - last block received but some blocks are missing --> ignore");
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK;
*keep_in_resend_queue = true;
} else { } else {
// XXX what was this trying to free? // XXX what was this trying to free?
received_coap_msg_ptr->coap_status = COAP_STATUS_OK; received_coap_msg_ptr->coap_status = COAP_STATUS_OK;
} }
} }
}
// Blocked request receiving // Blocked request receiving
else { else {
@ -1912,14 +1887,13 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
// Include maximum size that stack can handle into response // Include maximum size that stack can handle into response
tr_info("sn_coap_handle_blockwise_message - (recv block1) entity too large"); tr_info("sn_coap_handle_blockwise_message - (recv block1) entity too large");
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE; src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
} } else {
else {
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1; src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1;
src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
/* Check block size */ /* Check block size */
block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07); block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07);
uint16_t block_size = 1u << (block_temp + 4); uint_fast16_t block_size = 16u << block_temp;
if (block_size > handle->sn_coap_block_data_size) { if (block_size > handle->sn_coap_block_data_size) {
// Include maximum size that stack can handle into response // Include maximum size that stack can handle into response
@ -1929,7 +1903,7 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
} }
if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) { if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) {
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8; src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFFFF8;
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
} }
} }
@ -2175,7 +2149,7 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07; block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
/* Resolve block parameters */ /* Resolve block parameters */
const uint16_t block_size = 1u << (block_temp + 4); const uint_fast16_t block_size = 16u << block_temp;
const uint32_t block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4; const uint32_t block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
@ -2228,8 +2202,7 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
if (src_coap_blockwise_ack_msg_ptr->token_ptr) { if (src_coap_blockwise_ack_msg_ptr->token_ptr) {
src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len; src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len;
} }
} } else {
else {
src_coap_blockwise_ack_msg_ptr->token_ptr = NULL; src_coap_blockwise_ack_msg_ptr->token_ptr = NULL;
src_coap_blockwise_ack_msg_ptr->token_len = 0; src_coap_blockwise_ack_msg_ptr->token_len = 0;
} }
@ -2318,28 +2291,17 @@ static bool sn_coap_handle_last_blockwise(struct coap_s *handle, const sn_nsdl_a
int8_t sn_coap_convert_block_size(uint16_t block_size) int8_t sn_coap_convert_block_size(uint16_t block_size)
{ {
if (block_size == 16) { for (int n = 0; n <= 6; n++) {
return 0; if (block_size == (16 << n)) {
} else if (block_size == 32) { return n;
return 1;
} else if (block_size == 64) {
return 2;
} else if (block_size == 128) {
return 3;
} else if (block_size == 256) {
return 4;
} else if (block_size == 512) {
return 5;
} else if (block_size == 1024) {
return 6;
} else {
return 0;
} }
} }
return -1;
}
static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, const sn_coap_hdr_s *source_header_ptr) static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *restrict handle, const sn_coap_hdr_s *restrict source_header_ptr)
{ {
sn_coap_hdr_s *destination_header_ptr; sn_coap_hdr_s *restrict destination_header_ptr;
destination_header_ptr = sn_coap_parser_alloc_message(handle); destination_header_ptr = sn_coap_parser_alloc_message(handle);
if (!destination_header_ptr) { if (!destination_header_ptr) {
@ -2382,8 +2344,8 @@ static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, const
return 0; return 0;
} }
const sn_coap_options_list_s *source_options_list_ptr = source_header_ptr->options_list_ptr; const sn_coap_options_list_s *restrict source_options_list_ptr = source_header_ptr->options_list_ptr;
sn_coap_options_list_s *destination_options_list_ptr = destination_header_ptr->options_list_ptr; sn_coap_options_list_s *restrict destination_options_list_ptr = destination_header_ptr->options_list_ptr;
destination_options_list_ptr->max_age = source_options_list_ptr->max_age; destination_options_list_ptr->max_age = source_options_list_ptr->max_age;
@ -2464,7 +2426,7 @@ static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, const
static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *handle, static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *handle,
const sn_nsdl_addr_s *dst_addr_ptr, const sn_nsdl_addr_s *dst_addr_ptr,
const sn_coap_hdr_s *coap_msg_ptr, const sn_coap_hdr_s *coap_msg_ptr,
const int16_t data_size, const int_fast16_t data_size,
const uint8_t *dst_packet_data_ptr) const uint8_t *dst_packet_data_ptr)
{ {
if (coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT && if (coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT &&
@ -2477,7 +2439,7 @@ static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *
static bool sn_coap_protocol_update_duplicate_package_data_all(const struct coap_s *handle, static bool sn_coap_protocol_update_duplicate_package_data_all(const struct coap_s *handle,
const sn_nsdl_addr_s *dst_addr_ptr, const sn_nsdl_addr_s *dst_addr_ptr,
const sn_coap_hdr_s *coap_msg_ptr, const sn_coap_hdr_s *coap_msg_ptr,
const int16_t data_size, const int_fast16_t data_size,
const uint8_t *dst_packet_data_ptr) const uint8_t *dst_packet_data_ptr)
{ {
coap_duplication_info_s *info = sn_coap_protocol_linked_list_duplication_info_search(handle, coap_duplication_info_s *info = sn_coap_protocol_linked_list_duplication_info_search(handle,
@ -2500,7 +2462,7 @@ static bool sn_coap_protocol_update_duplicate_package_data_all(const struct coap
} }
#endif #endif
void *sn_coap_protocol_malloc_copy(struct coap_s *handle, const void *source, uint16_t length) void *sn_coap_protocol_malloc_copy(struct coap_s *handle, const void *source, uint_fast16_t length)
{ {
void *dest = handle->sn_coap_protocol_malloc(length); void *dest = handle->sn_coap_protocol_malloc(length);
@ -2515,7 +2477,7 @@ void *sn_coap_protocol_malloc_copy(struct coap_s *handle, const void *source, ui
* are, but that would require the client to fill one up, as a wrapper filled from this * are, but that would require the client to fill one up, as a wrapper filled from this
* class would need access to the handle itself. * class would need access to the handle itself.
*/ */
void *sn_coap_protocol_calloc(struct coap_s *handle, uint16_t length) void *sn_coap_protocol_calloc(struct coap_s *handle, uint_fast16_t length)
{ {
void *result = handle->sn_coap_protocol_malloc(length); void *result = handle->sn_coap_protocol_malloc(length);