diff --git a/block.c b/block.c index 0c7027cd..847fe9cc 100644 --- a/block.c +++ b/block.c @@ -18,6 +18,25 @@ #define min(a,b) ((a) < (b) ? (a) : (b)) #ifndef WITHOUT_BLOCK +unsigned int +coap_opt_block_num(const coap_opt_t *block_opt) { + unsigned int num = 0; + unsigned short len; + + len = coap_opt_length(block_opt); + + if (len == 0) { + return 0; + } + + if (len > 1) { + num = coap_decode_var_bytes(COAP_OPT_VALUE(block_opt), + COAP_OPT_LENGTH(block_opt) - 1); + } + + return (num << 4) | ((*COAP_OPT_BLOCK_LAST(block_opt) & 0xF0) >> 4); +} + int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block) { coap_opt_iterator_t opt_iter; @@ -30,8 +49,7 @@ coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block) { block->szx = COAP_OPT_BLOCK_SZX(option); if (COAP_OPT_BLOCK_MORE(option)) block->m = 1; - block->num = COAP_OPT_BLOCK_NUM(option); - + block->num = coap_opt_block_num(option); return 1; } diff --git a/block.h b/block.h index 73c3656f..283ba69b 100644 --- a/block.h +++ b/block.h @@ -40,29 +40,27 @@ typedef struct { unsigned int szx:3; /**< block size */ } coap_block_t; -/** Returns the value of the least significant byte of a Block option @p opt. */ -#define COAP_OPT_BLOCK_LAST(opt) ( COAP_OPT_VALUE(opt) + (COAP_OPT_LENGTH(opt) - 1) ) +/** + * Returns the value of the least significant byte of a Block option @p opt. + * For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST + * returns @c NULL. + */ +#define COAP_OPT_BLOCK_LAST(opt) \ + (COAP_OPT_LENGTH(opt) ? (COAP_OPT_VALUE(opt) + (COAP_OPT_LENGTH(opt)-1)) : 0) /** Returns the value of the More-bit of a Block option @p opt. */ -#define COAP_OPT_BLOCK_MORE(opt) ( *COAP_OPT_BLOCK_LAST(opt) & 0x08 ) +#define COAP_OPT_BLOCK_MORE(opt) \ + (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x08) : 0) /** Returns the value of the SZX-field of a Block option @p opt. */ -#define COAP_OPT_BLOCK_SZX(opt) ( *COAP_OPT_BLOCK_LAST(opt) & 0x07 ) +#define COAP_OPT_BLOCK_SZX(opt) \ + (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x07) : 0) -/** Implementation of COAP_OPT_BLOCK_NUM */ -static inline unsigned int -_coap_block_num_impl(const coap_opt_t *block_opt) { - unsigned int num = 0; - - if (COAP_OPT_LENGTH(block_opt) > 1) - num = coap_decode_var_bytes(COAP_OPT_VALUE(block_opt), - COAP_OPT_LENGTH(block_opt) - 1); - - return (num << 4) | ((*COAP_OPT_BLOCK_LAST(block_opt) & 0xF0) >> 4); -} - -/** Returns the value of field @c num in the given block option @p Block. */ -#define COAP_OPT_BLOCK_NUM(Block) _coap_block_num_impl(Block) +/** + * Returns the value of field @c num in the given block option @p + * block_opt. + */ +unsigned int coap_opt_block_num(const coap_opt_t *block_opt); /** * Checks if more than @p num blocks are required to deliver @p data_len