mirror of
https://github.com/obgm/libcoap.git
synced 2026-11-09 02:32:53 +03:00
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:
1 parent
3c75958f33
commit
a1be686921
2 files changed
+26
-4
No files matched your search
+17
-2
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user