Fix packet recovery support for BLOCK1 option in examples for lossy connections

examples/client.c
 examples/coap-server.c

For the client, the next block to transmit is always now the last acknowledged
block plus one.

If the client receives a duplicate BLOCK1 ACK, the duplicate ACK is ignored by
checking the message ids.

For the server, it no longer rejectes a duplicate BLOCK1 request, but does
still object if there is a gap in the provided data due to a missing block.
In otherwords, the blocks must arrive sequentially from the client.
This commit is contained in:
Jon Shallow committed 2018-11-11 13:30:42 +00:00
1 parent 3c75958f33
commit a1be686921
2 files changed
+26 -4

No files matched your search

+17 -2
View File
@@ -70,6 +70,8 @@ typedef unsigned char method_t;
method_t method = 1; /* the method we are using in our requests */
coap_block_t block = { .num = 0, .m = 0, .szx = 6 };
uint16_t last_block1_tid = 0;
unsigned int wait_seconds = 90; /* default timeout in seconds */
unsigned int wait_ms = 0;
@@ -421,7 +423,7 @@ message_handler(struct coap_context_t *ctx,
unsigned int bytes_sent = ((block.num + 1) << (block.szx + 4));
if (bytes_sent % (1 << (szx + 4)) == 0) {
/* Recompute the block number of the previous packet given the new block size */
block.num = (bytes_sent >> (szx + 4)) - 1;
num = block.num = (bytes_sent >> (szx + 4)) - 1;
block.szx = szx;
coap_log(LOG_DEBUG,
"new Block1 size is %u, block number %u completed\n",
@@ -440,6 +442,19 @@ message_handler(struct coap_context_t *ctx,
ready = 1;
return;
}
if (last_block1_tid == received->tid) {
/*
* Duplicate BLOCK1 ACK
*
* RFCs not clear here, but on a lossy connection, there could
* be multiple BLOCK1 ACKs, causing the client to retransmit the
* same block multiple times.
*
* Once a block has been ACKd, there is no need to retransmit it.
*/
return;
}
last_block1_tid = received->tid;
/* create pdu with request for next block */
pdu = coap_new_request(ctx, session, method, NULL, NULL, 0); /* first, create bare PDU w/o any option */
@@ -463,7 +478,7 @@ message_handler(struct coap_context_t *ctx,
/* finally add updated block option from response, clear M bit */
/* blocknr = (blocknr & 0xfffffff7) + 0x10; */
block.num++;
block.num = num + 1;
block.m = ((block.num+1) * (1 << (block.szx + 4)) < payload.length);
coap_log(LOG_DEBUG, "send block %d\n", block.num);
+9 -2
View File
@@ -479,12 +479,18 @@ hnd_put(coap_context_t *ctx UNUSED_PARAM,
value = NULL;
}
}
else if (offset !=
else if (offset >
(resource_entry->value ? resource_entry->value->length : 0)) {
/* Upload is not sequential */
/* Upload is not sequential - block missing */
response->code = COAP_RESPONSE_CODE(408);
return;
}
else if (offset <
(resource_entry->value ? resource_entry->value->length : 0)) {
/* Upload is not sequential - block duplicated */
goto just_respond;
}
/* Add in new block to end of current data */
resource_entry->value = coap_new_string(offset + size);
memcpy (&resource_entry->value->s[offset], data, size);
resource_entry->value->length = offset + size;
@@ -493,6 +499,7 @@ hnd_put(coap_context_t *ctx UNUSED_PARAM,
coap_delete_string(value);
}
}
just_respond:
if (block1.m) {
response->code = COAP_RESPONSE_CODE(231);
}