From 233dd31e173a706c997d233acd9a44f79a52cf30 Mon Sep 17 00:00:00 2001 From: Ken Bannister Date: Sun, 24 Feb 2019 06:06:30 -0500 Subject: [PATCH 1/7] net/nanocoap: add generic uint block option --- sys/include/net/nanocoap.h | 14 ++++++++++++++ sys/net/application_layer/nanocoap/nanocoap.c | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index 6f4daa40f0cc..7eabe5689afd 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -1038,6 +1038,20 @@ static inline size_t coap_opt_put_block2(uint8_t *buf, uint16_t lastonum, return coap_opt_put_block(buf, lastonum, slicer, more, COAP_OPT_BLOCK2); } +/** + * @brief Encode the given uint option into buffer + * + * @param[out] buf buffer to write to + * @param[in] lastonum number of previous option (for delta calculation), + * or 0 for first option + * @param[in] onum number of option + * @param[in] value value to encode + * + * @returns amount of bytes written to @p buf + */ +size_t coap_opt_put_uint(uint8_t *buf, uint16_t lastonum, uint16_t onum, + uint32_t value); + /** * @brief Insert block option into buffer from block struct * diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index f5090e2a77e8..695165d52d4e 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -810,6 +810,14 @@ size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum, return bufpos - buf; } +size_t coap_opt_put_uint(uint8_t *buf, uint16_t lastonum, uint16_t onum, + uint32_t value) +{ + unsigned uint_len = _encode_uint(&value); + + return coap_put_option(buf, lastonum, onum, (uint8_t *)&value, uint_len); +} + /* Common functionality for addition of an option */ static ssize_t _add_opt_pkt(coap_pkt_t *pkt, uint16_t optnum, const uint8_t *val, size_t val_len) From dae9c4ab8927029f654fdc28145dbbe125cd586a Mon Sep 17 00:00:00 2001 From: Ken Bannister Date: Sun, 24 Feb 2019 06:31:58 -0500 Subject: [PATCH 2/7] net/nanocoap: use coap_opt_add_uint() and remove unused --- sys/include/net/nanocoap.h | 21 ++++++-- sys/net/application_layer/nanocoap/nanocoap.c | 54 +++++-------------- 2 files changed, 28 insertions(+), 47 deletions(-) diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index 7eabe5689afd..635399518e9f 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -1077,7 +1077,8 @@ size_t coap_opt_put_block_object(uint8_t *buf, uint16_t lastonum, static inline size_t coap_opt_put_block1_control(uint8_t *buf, uint16_t lastonum, coap_block1_t *block) { - return coap_opt_put_block_object(buf, lastonum, block, COAP_OPT_BLOCK1); + return coap_opt_put_uint(buf, lastonum, COAP_OPT_BLOCK1, + (block->blknum << 4) | block->szx | (block->more ? 0x8 : 0)); } /** @@ -1094,8 +1095,9 @@ static inline size_t coap_opt_put_block1_control(uint8_t *buf, uint16_t lastonum static inline size_t coap_opt_put_block2_control(uint8_t *buf, uint16_t lastonum, coap_block1_t *block) { - block->more = 0; - return coap_opt_put_block_object(buf, lastonum, block, COAP_OPT_BLOCK2); + /* block.more must be zero, so no need to 'or' it in */ + return coap_opt_put_uint(buf, lastonum, COAP_OPT_BLOCK2, + (block->blknum << 4) | block->szx); } /** @@ -1230,7 +1232,12 @@ size_t coap_put_option(uint8_t *buf, uint16_t lastonum, uint16_t onum, const uin * * @returns amount of bytes written to @p buf */ -size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more); +static inline size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, + unsigned blknum, unsigned szx, int more) +{ + return coap_opt_put_uint(buf, lastonum, COAP_OPT_BLOCK1, + (blknum << 4) | szx | (more ? 0x8 : 0)); +} /** * @brief Insert content type option into buffer @@ -1242,7 +1249,11 @@ size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum, * * @returns amount of bytes written to @p buf */ -size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, uint16_t content_type); +static inline size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, + uint16_t content_type) +{ + return coap_opt_put_uint(buf, lastonum, COAP_OPT_CONTENT_FORMAT, content_type); +} /**@}*/ diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index 695165d52d4e..c1ef9205b7be 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -653,20 +653,6 @@ size_t coap_put_option(uint8_t *buf, uint16_t lastonum, uint16_t onum, const uin return (size_t)n; } -size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, uint16_t content_type) -{ - if (content_type == 0) { - return coap_put_option(buf, lastonum, COAP_OPT_CONTENT_FORMAT, NULL, 0); - } - else if (content_type <= 255) { - uint8_t tmp = content_type; - return coap_put_option(buf, lastonum, COAP_OPT_CONTENT_FORMAT, &tmp, sizeof(tmp)); - } - else { - return coap_put_option(buf, lastonum, COAP_OPT_CONTENT_FORMAT, (uint8_t *)&content_type, sizeof(content_type)); - } -} - static unsigned _size2szx(size_t size) { unsigned szx = 0; @@ -694,46 +680,30 @@ static unsigned _slicer_blknum(coap_block_slicer_t *slicer) return blknum; } -static size_t coap_put_option_block(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more, uint16_t option) -{ - uint32_t blkopt = (blknum << 4) | szx | (more ? 0x8 : 0); - size_t olen = _encode_uint(&blkopt); - - return coap_put_option(buf, lastonum, option, (uint8_t *)&blkopt, olen); -} - -size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more) -{ - return coap_put_option_block(buf, lastonum, blknum, szx, more, COAP_OPT_BLOCK1); -} - -int coap_get_block(coap_pkt_t *pkt, coap_block1_t *block, uint16_t blkopt) +int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1) { uint32_t blknum; unsigned szx; - block->more = coap_get_blockopt(pkt, blkopt, &blknum, &szx); - if (block->more >= 0) { - block->offset = blknum << (szx + 4); + block1->more = coap_get_blockopt(pkt, COAP_OPT_BLOCK1, &blknum, &szx); + if (block1->more >= 0) { + block1->offset = blknum << (szx + 4); } else { - block->offset = 0; + block1->offset = 0; } - block->blknum = blknum; - block->szx = szx; + block1->blknum = blknum; + block1->szx = szx; - return (block->more >= 0); -} - -int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block) -{ - return coap_get_block(pkt, block, COAP_OPT_BLOCK1); + return (block1->more >= 0); } -int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block) +int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block2) { - return coap_get_block(pkt, block, COAP_OPT_BLOCK2); + block2->more = coap_get_blockopt(pkt, COAP_OPT_BLOCK2, &block2->blknum, + &block2->szx); + return (block2->more >= 0); } size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t lastonum) From efb75c5c4cc7c419582decc75a63750d40ebf02a Mon Sep 17 00:00:00 2001 From: Ken Bannister Date: Sun, 24 Feb 2019 06:41:09 -0500 Subject: [PATCH 3/7] net/coap: improve slicer to block helper --- sys/net/application_layer/nanocoap/nanocoap.c | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index c1ef9205b7be..3f8fb92ab200 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -667,7 +667,7 @@ static unsigned _size2szx(size_t size) return szx - 5; } -static unsigned _slicer_blknum(coap_block_slicer_t *slicer) +static unsigned _slicer2blkopt(coap_block_slicer_t *slicer, bool more) { size_t blksize = slicer->end - slicer->start; size_t start = slicer->start; @@ -677,7 +677,8 @@ static unsigned _slicer_blknum(coap_block_slicer_t *slicer) start -= blksize; blknum++; } - return blknum; + + return (blknum << 4) | _size2szx(blksize) | (more ? 0x8 : 0); } int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1) @@ -719,14 +720,9 @@ size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t last size_t coap_opt_put_block(uint8_t *buf, uint16_t lastonum, coap_block_slicer_t *slicer, bool more, uint16_t option) { - coap_block1_t block; - - coap_block_object_init(&block, _slicer_blknum(slicer), - slicer->end - slicer->start, more); - slicer->opt = buf; - return coap_opt_put_block_object(buf, lastonum, &block, option); + return coap_opt_put_uint(buf, lastonum, option, _slicer2blkopt(slicer, more)); } size_t coap_opt_put_block_object(uint8_t *buf, uint16_t lastonum, @@ -878,13 +874,9 @@ ssize_t coap_opt_add_uint(coap_pkt_t *pkt, uint16_t optnum, uint32_t value) ssize_t coap_opt_add_block(coap_pkt_t *pkt, coap_block_slicer_t *slicer, bool more, uint16_t option) { - uint32_t blkopt = (_slicer_blknum(slicer) << 4); - blkopt |= _size2szx(slicer->end - slicer->start); - blkopt |= (more ? 0x8 : 0); - slicer->opt = pkt->payload; - return coap_opt_add_uint(pkt, option, blkopt); + return coap_opt_add_uint(pkt, option, _slicer2blkopt(slicer, more)); } ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags) @@ -947,12 +939,7 @@ void coap_block_finish(coap_block_slicer_t *slicer, uint16_t option) uint8_t *pos = slicer->opt + 1; uint16_t delta = _decode_value(*slicer->opt >> 4, &pos, slicer->opt + 3); - /* Calculate the block uint value inline here rather than through - * coap_opt_put_block(). Conserves stack and avoids importing Buffer API - * functions when using Packet API. */ - uint32_t blkopt = (_slicer_blknum(slicer) << 4); - blkopt |= _size2szx(slicer->end - slicer->start); - blkopt |= ((slicer->cur > slicer->end) ? 0x8 : 0); + uint32_t blkopt = _slicer2blkopt(slicer, slicer->cur > slicer->end); size_t olen = _encode_uint(&blkopt); coap_put_option(slicer->opt, option - delta, option, (uint8_t *)&blkopt, olen); From 5eaa51e42661408d675102e40a31d6f691027234 Mon Sep 17 00:00:00 2001 From: Ken Bannister Date: Sun, 24 Feb 2019 06:43:09 -0500 Subject: [PATCH 4/7] net/nanocoap: remove unused function --- sys/include/net/nanocoap.h | 13 ------------- sys/net/application_layer/nanocoap/nanocoap.c | 9 --------- 2 files changed, 22 deletions(-) diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index 635399518e9f..0ade92629fac 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -1052,19 +1052,6 @@ static inline size_t coap_opt_put_block2(uint8_t *buf, uint16_t lastonum, size_t coap_opt_put_uint(uint8_t *buf, uint16_t lastonum, uint16_t onum, uint32_t value); -/** - * @brief Insert block option into buffer from block struct - * - * @param[in] buf buffer to write to - * @param[in] lastonum last option number (must be < @p option) - * @param[in] block block option attribute struct - * @param[in] option option number (block1 or block2) - * - * @returns amount of bytes written to @p buf - */ -size_t coap_opt_put_block_object(uint8_t *buf, uint16_t lastonum, - coap_block1_t *block, uint16_t option); - /** * @brief Insert block1 option into buffer in control usage * diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index 3f8fb92ab200..dbe2ce4b0c39 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -725,15 +725,6 @@ size_t coap_opt_put_block(uint8_t *buf, uint16_t lastonum, coap_block_slicer_t * return coap_opt_put_uint(buf, lastonum, option, _slicer2blkopt(slicer, more)); } -size_t coap_opt_put_block_object(uint8_t *buf, uint16_t lastonum, - coap_block1_t *block, uint16_t option) -{ - uint32_t blkopt = (block->blknum << 4) | block->szx | (block->more ? 0x8 : 0); - size_t olen = _encode_uint(&blkopt); - - return coap_put_option(buf, lastonum, option, (uint8_t *)&blkopt, olen); -} - size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum, const char *string, char separator) { From 2abcbc0d2047351dbc5aeb61bf4e623dddda6b86 Mon Sep 17 00:00:00 2001 From: Ken Bannister Date: Sun, 24 Feb 2019 06:57:00 -0500 Subject: [PATCH 5/7] net/coap: add generic get block function --- sys/include/net/nanocoap.h | 34 ++++++++++++++++--- sys/net/application_layer/nanocoap/nanocoap.c | 25 ++++---------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index 0ade92629fac..cf53564acca4 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -717,6 +717,26 @@ size_t coap_blockwise_put_bytes(coap_block_slicer_t *slicer, uint8_t *bufpos, */ size_t coap_blockwise_put_char(coap_block_slicer_t *slicer, uint8_t *bufpos, char c); +/** + * @brief Block option getter + * + * This function gets a CoAP packet's block option and parses it into a helper + * structure. + * + * If no block option is present in @p pkt, the values in @p block will be + * initialized with zero. That implies both block->offset and block->more are + * also valid in that case, as packet with offset==0 and more==0 means it contains + * all the payload for the corresponding request. + * + * @param[in] pkt pkt to work on + * @param[out] block ptr to preallocated coap_block1_t structure + * @param[in] option block1 or block2 + * + * @returns 0 if block option not present + * @returns 1 if structure has been filled + */ +int coap_get_block(coap_pkt_t *pkt, coap_block1_t *block, uint16_t option); + /** * @brief Block1 option getter * @@ -729,23 +749,29 @@ size_t coap_blockwise_put_char(coap_block_slicer_t *slicer, uint8_t *bufpos, cha * all the payload for the corresponding request. * * @param[in] pkt pkt to work on - * @param[out] block1 ptr to preallocated coap_block1_t structure + * @param[out] block ptr to preallocated coap_block1_t structure * * @returns 0 if block1 option not present * @returns 1 if structure has been filled */ -int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1); +static inline int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block) +{ + return coap_get_block(pkt, block, COAP_OPT_BLOCK1); +} /** * @brief Block2 option getter * * @param[in] pkt pkt to work on - * @param[out] block2 ptr to preallocated coap_block1_t structure + * @param[out] block ptr to preallocated coap_block1_t structure * * @returns 0 if block2 option not present * @returns 1 if structure has been filled */ -int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block2); +static inline int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block) +{ + return coap_get_block(pkt, block, COAP_OPT_BLOCK2); +} /** * @brief Generic block option getter diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index dbe2ce4b0c39..2b8eec228759 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -681,30 +681,17 @@ static unsigned _slicer2blkopt(coap_block_slicer_t *slicer, bool more) return (blknum << 4) | _size2szx(blksize) | (more ? 0x8 : 0); } -int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1) +int coap_get_block(coap_pkt_t *pkt, coap_block1_t *block, uint16_t option) { - uint32_t blknum; - unsigned szx; - - block1->more = coap_get_blockopt(pkt, COAP_OPT_BLOCK1, &blknum, &szx); - if (block1->more >= 0) { - block1->offset = blknum << (szx + 4); + block->more = coap_get_blockopt(pkt, option, &block->blknum, &block->szx); + if (block->more >= 0) { + block->offset = block->blknum << (block->szx + 4); } else { - block1->offset = 0; + block->offset = 0; } - block1->blknum = blknum; - block1->szx = szx; - - return (block1->more >= 0); -} - -int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block2) -{ - block2->more = coap_get_blockopt(pkt, COAP_OPT_BLOCK2, &block2->blknum, - &block2->szx); - return (block2->more >= 0); + return (block->more >= 0); } size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t lastonum) From e22d4729e13ecff0cae4e63e9cdde2b36ba38f28 Mon Sep 17 00:00:00 2001 From: Ken Bannister Date: Sun, 24 Feb 2019 07:02:53 -0500 Subject: [PATCH 6/7] net/nanocoap: initialize offset attribute --- sys/net/application_layer/nanocoap/nanocoap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index 2b8eec228759..b764441af041 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -880,6 +880,7 @@ void coap_block_object_init(coap_block1_t *block, size_t blknum, size_t blksize, block->szx = _size2szx(blksize); block->blknum = blknum; block->more = more; + block->offset = block->blknum << (block->szx + 4); } void coap_block_slicer_init(coap_block_slicer_t *slicer, size_t blknum, From 2dc4209c0e7df04cbf9746ec064ead2a5191ab3e Mon Sep 17 00:00:00 2001 From: Ken Bannister Date: Mon, 30 Sep 2019 08:15:21 -0400 Subject: [PATCH 7/7] net/nanocoap: optimize determination of exponent for block szx --- sys/net/application_layer/nanocoap/nanocoap.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index b764441af041..df0853c3497d 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -26,6 +26,7 @@ #include #include +#include "bitarithm.h" #include "net/nanocoap.h" #define ENABLE_DEBUG (0) @@ -655,16 +656,15 @@ size_t coap_put_option(uint8_t *buf, uint16_t lastonum, uint16_t onum, const uin static unsigned _size2szx(size_t size) { - unsigned szx = 0; assert(size <= 1024); - while (size) { - size = size >> 1; - szx++; - } - /* Size exponent + 1 */ - assert(szx >= 5); - return szx - 5; + /* We must wait to subract the szx offset of 4 until after the assert below. + * Input should be a power of two, but if not it may have a stray low order + * '1' bit that would invalidate the subtraction. */ + unsigned szx = bitarithm_lsb(size); + + assert(szx >= 4); + return szx - 4; } static unsigned _slicer2blkopt(coap_block_slicer_t *slicer, bool more)