From e190ffe200b0d19daba98aebf57f87e58ec0ae65 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 9 Feb 2017 10:53:26 -0800 Subject: [PATCH] iot/zoap: Fix handling of 16-bytes block-wise transfers This fixes the case that a request for block number (NUM) 0, using a 16 byte block was considered invalid. This was because it is encoded as the value 0 (zero), which can be expressed as the BLOCK1 option present but without any value associated. The old code considered this the same as the option not existing. Change-Id: I0f3912803a88865e9f544a6d0078ed4231775a88 Signed-off-by: Vinicius Costa Gomes --- subsys/net/lib/zoap/zoap.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/subsys/net/lib/zoap/zoap.c b/subsys/net/lib/zoap/zoap.c index 6ff02b2f85f..94dab4a7c36 100644 --- a/subsys/net/lib/zoap/zoap.c +++ b/subsys/net/lib/zoap/zoap.c @@ -1210,15 +1210,16 @@ struct block_transfer { bool more; }; -static unsigned int get_block_option(struct zoap_packet *pkt, uint16_t code) +static int get_block_option(struct zoap_packet *pkt, uint16_t code) { struct zoap_option option; unsigned int val; int count = 1; count = zoap_find_options(pkt, code, &option, count); - if (count <= 0) - return 0; + if (count <= 0) { + return -ENOENT; + } val = zoap_option_value_to_int(&option); @@ -1230,15 +1231,15 @@ static int update_descriptive_block(struct zoap_block_context *ctx, { size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4); - if (block == 0) { - return -ENOENT; + if (block == -ENOENT) { + return 0; } if (size && ctx->total_size && ctx->total_size != size) { return -EINVAL; } - if (ctx->block_size > 0 && GET_BLOCK_SIZE(block) > ctx->block_size) { + if (ctx->current > 0 && GET_BLOCK_SIZE(block) > ctx->block_size) { return -EINVAL; } @@ -1250,7 +1251,7 @@ static int update_descriptive_block(struct zoap_block_context *ctx, ctx->total_size = size; } ctx->current = new_current; - ctx->block_size = GET_BLOCK_SIZE(block); + ctx->block_size = min(GET_BLOCK_SIZE(block), ctx->block_size); return 0; } @@ -1260,7 +1261,7 @@ static int update_control_block1(struct zoap_block_context *ctx, { size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4); - if (block == 0) { + if (block == -ENOENT) { return 0; } @@ -1283,7 +1284,7 @@ static int update_control_block2(struct zoap_block_context *ctx, { size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4); - if (block == 0) { + if (block == -ENOENT) { return 0; } @@ -1296,8 +1297,7 @@ static int update_control_block2(struct zoap_block_context *ctx, } ctx->current = new_current; - ctx->block_size = GET_BLOCK_SIZE(block); - ctx->total_size = size; + ctx->block_size = min(GET_BLOCK_SIZE(block), ctx->block_size); return 0; } @@ -1305,14 +1305,16 @@ static int update_control_block2(struct zoap_block_context *ctx, int zoap_update_from_block(struct zoap_packet *pkt, struct zoap_block_context *ctx) { - unsigned int block1, block2, size1, size2; - int r; + int r, block1, block2, size1, size2; block1 = get_block_option(pkt, ZOAP_OPTION_BLOCK1); block2 = get_block_option(pkt, ZOAP_OPTION_BLOCK2); size1 = get_block_option(pkt, ZOAP_OPTION_SIZE1); size2 = get_block_option(pkt, ZOAP_OPTION_SIZE2); + size1 = size1 == -ENOENT ? 0 : size1; + size2 = size2 == -ENOENT ? 0 : size2; + if (is_request(pkt)) { r = update_control_block2(ctx, block2, size2); if (r) {