Skip to content

net/unicoap: Unified and Modular CoAP Stack: Block-Wise Transfers - #22589

Draft
carl-tud wants to merge 12 commits into
RIOT-OS:pr/unicoap-clientfrom
carl-tud:unicoap-05-blockwise
Draft

net/unicoap: Unified and Modular CoAP Stack: Block-Wise Transfers#22589
carl-tud wants to merge 12 commits into
RIOT-OS:pr/unicoap-clientfrom
carl-tud:unicoap-05-blockwise

Conversation

@carl-tud

@carl-tud carl-tud commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

This PR implements block-wise transfers (RFC 7959) in unicoap, a unified and modular CoAP implementation for RIOT. An overview of all PRs related to unicoap is presented in #21389, including reasons why unicoap is needed and a performance analysis.

What does this PR include?

  • Support for automatic Block1 (chunked request) and Block2 (chunked responses) transfers
    • Client
    • Server
    • Requests and responses will be automatically handled, and only relevenat block-wise transfer implementations will only be linked, depending on whether you imported unicoap_client and/or unicoap_server.
    • Optimisations: Specify UNICOAP_[CLIENT|RESOURCE]_FLAG_DURABLE_MESSAGE in addition to the slice flag to avoid the message from being copied into an internal buffer if you can guarantee the pointer will stay alive throughout the transfer (e.g., for static allocations in your app). Internal buffers are only needed when this is not case, or when reassembling.
    • Configurability: Customise the number of state objects available for client transfers, server transfers, and buffers.
  • Manual tools: The underlying tools for block-wise transfers are available as part of the new net/unicoap/blockwise.h header and unicoap_blockwise_kit submodule, so users can easily manually implement block-wise transfer or tinker with specific APIs.
    • Unit tests for these tools, tests state machine logic
  • Integration into coap shell command: new --slice and --glue command line arguments
  • Added to unicoap_server example: Slicing and reassembling supported
  • Interop-testable with client.py and server.py scripts powered by aiocoap
  • Documentation throughout

Block-wise features at your fingertips

Compared to prior fiddling with block-wise APIs, this is how easy supporting block-wise transfer is now. No need to change response handlers or request handlers!

Add USEMODULE += unicoap_blockwise to your Makefile. Then:

unicoap_destination_t destination = unicoap_destination_uri("coap://example.invalid/stuff/bigggg");
 int res = unicoap_send_request_async(&request, &destination, handle_response, 
    // This is all you need: add two flags.
    UNICOAP_CLIENT_FLAG_SLICE | UNICOAP_CLIENT_FLAG_REASSEMBLE, 
    NULL);
UNICOAP_RESOURCE(biggg) {
    .path = UNICOAP_PATH("stuff", "biggg"),
    
    // Nothing more to do than adding two flags.
    .flags = UNICOAP_RESOURCE_FLAG_SLICE | UNICOAP_RESOURCE_FLAG_REASSEMBLE,
    
    .methods = UNICOAP_METHODS(UNICOAP_METHOD_GET, UNICOAP_METHOD_PUT),    
    .handler = handle_request,
};

I'll organise the monolithic commit into multiple structured commits once this has passed review, and rebase this PR onto #22266 once merged (PR stacks do not work).

Declaration of AI-Tools / LLMs usage:

AI-Tools / LLMs that were used are:

none

@github-actions github-actions Bot added Area: network Area: Networking Area: doc Area: Documentation Area: tests Area: tests and testing framework Area: build system Area: Build system Area: pkg Area: External package ports Area: CoAP Area: Constrained Application Protocol implementations Area: sys Area: System Area: examples Area: Example Applications Area: Kconfig Area: Kconfig integration labels Aug 16, 2026
@carl-tud carl-tud added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation and removed Area: network Area: Networking Area: doc Area: Documentation Area: tests Area: tests and testing framework Area: build system Area: Build system Area: pkg Area: External package ports Area: CoAP Area: Constrained Application Protocol implementations Area: sys Area: System Area: examples Area: Example Applications Area: Kconfig Area: Kconfig integration labels Aug 16, 2026
@carl-tud carl-tud added Type: new feature The issue requests / The PR implemements a new feature for RIOT AI: Not Used AI was stated to not be used in this PR/Issue labels Aug 16, 2026
@carl-tud carl-tud changed the title net/unicoap: Block-wise transfers net/unicoap: Unified and Modular CoAP Stack: Block-Wise Transfers Aug 16, 2026
@carl-tud
carl-tud changed the base branch from master to unicoap-p3 August 16, 2026 19:40
@carl-tud
carl-tud requested a review from mguetschow August 16, 2026 19:46
@carl-tud

Copy link
Copy Markdown
Contributor Author

I have yet to make the iterator support noncontiguous payloads... Only contiguous buffers at the moment...

@github-actions github-actions Bot added Area: network Area: Networking Area: doc Area: Documentation Area: tests Area: tests and testing framework Area: build system Area: Build system Area: CoAP Area: Constrained Application Protocol implementations Area: sys Area: System Area: examples Area: Example Applications labels Aug 19, 2026

@mguetschow mguetschow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First round of review, no testing yet. Great work as always!

" This is a demo of block-wise transfers in unicoap." \
" This very long response payload will be split into several chunks aka. blocks," \
" each sent in a separate Block2 response. The client needs to support block-wise transfer," \
" and sent subsequent Block2 requests to retrieve the remaining response blocks."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
" and sent subsequent Block2 requests to retrieve the remaining response blocks."
" and send subsequent Block2 requests to retrieve the remaining response blocks."

Comment on lines 90 to +97
* In this case, we don't want to loose our precious greeting along the way.
* To send confirmable messages (CON) over UDP or DTLS, we pass the
* @ref UNICOAP_RESOURCE_FLAG_RELIABLE flag. */
.flags = UNICOAP_RESOURCE_FLAG_RELIABLE,
#if IS_USED(MODULE_UNICOAP_BLOCKWISE)
.flags = UNICOAP_RESOURCE_FLAG_RELIABLE
| UNICOAP_RESOURCE_FLAG_REASSEMBLE
| UNICOAP_RESOURCE_FLAG_DURABLE_MESSAGE
| UNICOAP_RESOURCE_FLAG_SLICE,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing some comment on blockwise support. I would move the reliable discussion below into the else and add blockwise into the if

Comment on lines 622 to 628
PSEUDOMODULES += unicoap_server_resource_declarations

# Automatic block-wise transfers in server API
PSEUDOMODULES += unicoap_server_blockwise

# URI support in unicoap client API
PSEUDOMODULES += unicoap_client_uri

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh oh, those should be alphabetically sorted, but apparently already violated on the base PR...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... why are we alphabetically sorting them? as opposed to sensibly sorting them?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because "sensibly" is hard to tell across modules. Arguably easier among submodules with a common prefix, but I'd favor consistency here (and I'm sure @crasbe as well)

* @brief Instructs the stack to send a given message with block-wise fragmented
* payload.
*
* @warning The body you want to slice must not exceed `UINT32_MAX` bytes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this constraint come from?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no clue... I'll investigate what I did there

* If a response times out, the @p error parameter will be set to `-ETIMEDOUT`.
* Other failures are also communicated via the error parameter.
*
* Return a negative integer to abort the block-wise transfer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Return a negative integer to abort the block-wise transfer.
* Return zero to continue or a negative integer to abort the block-wise transfer.

Comment on lines +446 to +447
for (int i = 0; i < (int)ARRAY_SIZE(_state.server_memos); i += 1) {
memo = &_state.server_memos[i];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't this need a _lock as well?

Comment on lines +39 to +40
printf("TEST: %s\n", __func__);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
printf("TEST: %s\n", __func__);

unittests are usually not printing anything in RIOT. same in the other functions


unicoap_blockwise_iterator_init(&slicer, UNICOAP_BLOCK_SZX_32, (uint8_t*)body, strlen(body));
TEST_ASSERT_EQUAL_INT(slicer.offset, 0);
_TEST_ASSERT_EQUAL_BLOCK(slicer.block_option, 0, 32, true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_TEST_ASSERT_EQUAL_BLOCK(slicer.block_option, 0, 32, true);
_TEST_ASSERT_EQUAL_BLOCK(slicer._block_option, 0, 32, true);

otherwise the tests do not compile

res = unicoap_blockwise_collect_block1(&collector, block, chunk, chunk_size);
TEST_ASSERT_EQUAL_INT(res, 1);
_TEST_ASSERT_EQUAL_BYTES(body_buffer + 0, body + 0, chunk_size);
_TEST_ASSERT_EQUAL_BLOCK(collector.block_option, 0, 16, true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_TEST_ASSERT_EQUAL_BLOCK(collector.block_option, 0, 16, true);
_TEST_ASSERT_EQUAL_BLOCK(collector.block_option, 2, 16, true);

Would have expected this to be updated by unicoap_blockwise_collect_block1 - after all that's what you need to send to the client in control usage?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also this would match what you expect below for collect_block2.

Comment on lines +341 to +344
/* server */
/* test retransmissions */
for (unsigned int i = 0; i < 3; i += 1) {
chunk_size = unicoap_blockwise_slice_block2(&slicer, block, &chunk);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't we test retransmissions for block1?

@mguetschow

mguetschow commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

First test, after git merge unicoap-03-client-minimal (and sensible merge conflict resolution) (server: unicoap on native, client: client.py):

When requesting the same blockwise response a second time, before blockwise amnesia has completed, the server responds with the last block instead of the first, even if the client sent an ACK to the last block before:

2026-09-04 16:38:25,096 # RIOT native interrupts/signals initialized.
2026-09-04 16:38:25,097 # TZ not set, setting UTC
2026-09-04 16:38:25,097 # RIOT native64 board initialized.
2026-09-04 16:38:25,097 # RIOT native hardware initialization complete.
2026-09-04 16:38:25,097 # 
2026-09-04 16:38:25,098 # coap.server: registered 2 XFA resources
2026-09-04 16:38:25,098 # coap.transport.udp: zero_copy_guarantees=1 creating UDP sock, port=5683 if=0 family=inet6
2026-09-04 16:38:25,098 # coap.transport.dtls: creating DTLS sock, port=5684 if=0 family=inet6
2026-09-04 16:38:25,099 # main(): This is RIOT! (Version: 2026.10-devel-393-g930331-unicoap-05-blockwise)
2026-09-04 16:38:25,099 # app: listening at UDP <sock_tl_ep port=5683 netif=0 ipv6=::>
2026-09-04 16:38:25,099 # coap.transport.udp: zero_copy_guarantees=1 creating UDP sock, port=5682 if=0 family=inet6
2026-09-04 16:38:25,099 # app: also listening UDP <sock_tl_ep port=5682 netif=0 ipv6=::>
2026-09-04 16:38:25,100 # app: listening at DTLS <sock_tl_ep port=5684 netif=0 ipv6=::>
2026-09-04 16:38:25,100 # app: using credential: type=PSK id=Client_identity key=secretPSK
2026-09-04 16:38:25,100 # app: interfaces have ipv6=[ fe80::5c64:bbff:fe11:9231 ]
Welcome to pyterm!
Type '/exit' to exit.
2026-09-04 16:38:27,545 # coap.messaging.rfc7252: received <NON REQ mid=11944 token=4629 code=0.01 GET payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,545 # coap.messaging: received in channel:
2026-09-04 16:38:27,545 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,545 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,545 # coap.server: </>: found
2026-09-04 16:38:27,545 # coap.server: invoking handler
2026-09-04 16:38:27,545 # app: GET /, 0 bytes
2026-09-04 16:38:27,545 # coap.server: sending immediate response
2026-09-04 16:38:27,545 # coap.state: [server #0] alloc
2026-09-04 16:38:27,545 # coap.state: [block-wise buffer #0] alloc
2026-09-04 16:38:27,545 # coap.state: [block-wise transfer #0] alloc
2026-09-04 16:38:27,546 # coap.blockwise: setting up transfer
2026-09-04 16:38:27,546 # coap.blockwise: preparing transfer for SLICE stage: no_copy=1
2026-09-04 16:38:27,546 # coap.state: [block-wise buffer #0] free
2026-09-04 16:38:27,546 # coap.blockwise: slicing off block <#0, total=32B, M>
2026-09-04 16:38:27,546 # coap.messaging: sending in channel:
2026-09-04 16:38:27,546 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,546 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,546 # coap.messaging.rfc7252: sending <CON RESP mid=13146 token=4629 code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,546 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,546 # coap.state.sched: messaging.7252.ack-timeout in 2651ms
2026-09-04 16:38:27,546 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,546 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,546 # coap.messaging.rfc7252: received <ACK EMPTY mid=13146 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,547 # coap.messaging.rfc7252: [MID 13146] received ACK, stopping retransmission
2026-09-04 16:38:27,547 # coap.messaging.rfc7252: [MID 13146] transmission ended
2026-09-04 16:38:27,547 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,547 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,547 # coap.messaging.rfc7252: received <NON REQ mid=11945 token=462A code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,547 # coap.messaging: received in channel:
2026-09-04 16:38:27,547 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,547 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,547 # coap.server: </>: found
2026-09-04 16:38:27,547 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,547 # coap.blockwise: using block size 32 (we preferred 32, peer suggested 32)
2026-09-04 16:38:27,547 # coap.blockwise: slicing off block <#1, total=32B, M>
2026-09-04 16:38:27,547 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,548 # coap.messaging: sending in channel:
2026-09-04 16:38:27,548 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,548 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,548 # coap.messaging.rfc7252: sending <CON RESP mid=13147 token=462A code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,548 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,548 # coap.state.sched: messaging.7252.ack-timeout in 2277ms
2026-09-04 16:38:27,548 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,548 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,548 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,548 # coap.messaging.rfc7252: received <ACK EMPTY mid=13147 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,548 # coap.messaging.rfc7252: [MID 13147] received ACK, stopping retransmission
2026-09-04 16:38:27,548 # coap.messaging.rfc7252: [MID 13147] transmission ended
2026-09-04 16:38:27,548 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,549 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,549 # coap.messaging.rfc7252: received <NON REQ mid=11946 token=462B code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,549 # coap.messaging: received in channel:
2026-09-04 16:38:27,549 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,549 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,549 # coap.server: </>: found
2026-09-04 16:38:27,549 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:27,549 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,549 # coap.blockwise: slicing off block <#2, total=32B, M>
2026-09-04 16:38:27,549 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,549 # coap.messaging: sending in channel:
2026-09-04 16:38:27,549 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,549 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,550 # coap.messaging.rfc7252: sending <CON RESP mid=13148 token=462B code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,550 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,550 # coap.state.sched: messaging.7252.ack-timeout in 2179ms
2026-09-04 16:38:27,550 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,550 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,550 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,550 # coap.messaging.rfc7252: received <ACK EMPTY mid=13148 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,550 # coap.messaging.rfc7252: [MID 13148] received ACK, stopping retransmission
2026-09-04 16:38:27,550 # coap.messaging.rfc7252: [MID 13148] transmission ended
2026-09-04 16:38:27,550 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,550 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,550 # coap.messaging.rfc7252: received <NON REQ mid=11947 token=462C code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,551 # coap.messaging: received in channel:
2026-09-04 16:38:27,551 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,551 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,551 # coap.server: </>: found
2026-09-04 16:38:27,551 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:27,551 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,551 # coap.blockwise: using block size 32 (we preferred 32, peer suggested 32)
2026-09-04 16:38:27,551 # coap.blockwise: slicing off block <#3, total=32B, M>
2026-09-04 16:38:27,551 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,551 # coap.messaging: sending in channel:
2026-09-04 16:38:27,551 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,551 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,551 # coap.messaging.rfc7252: sending <CON RESP mid=13149 token=462C code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,552 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,552 # coap.state.sched: messaging.7252.ack-timeout in 2778ms
2026-09-04 16:38:27,552 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,552 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,552 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,552 # coap.messaging.rfc7252: received <ACK EMPTY mid=13149 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,552 # coap.messaging.rfc7252: [MID 13149] received ACK, stopping retransmission
2026-09-04 16:38:27,552 # coap.messaging.rfc7252: [MID 13149] transmission ended
2026-09-04 16:38:27,552 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,552 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,552 # coap.messaging.rfc7252: received <NON REQ mid=11948 token=462D code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,552 # coap.messaging: received in channel:
2026-09-04 16:38:27,552 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,553 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,553 # coap.server: </>: found
2026-09-04 16:38:27,553 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:27,553 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,553 # coap.blockwise: slicing off block <#4, total=32B, M>
2026-09-04 16:38:27,553 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,553 # coap.messaging: sending in channel:
2026-09-04 16:38:27,553 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,553 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,553 # coap.messaging.rfc7252: sending <CON RESP mid=13150 token=462D code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,553 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,553 # coap.state.sched: messaging.7252.ack-timeout in 2655ms
2026-09-04 16:38:27,553 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,554 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,554 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,554 # coap.messaging.rfc7252: received <ACK EMPTY mid=13150 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,554 # coap.messaging.rfc7252: [MID 13150] received ACK, stopping retransmission
2026-09-04 16:38:27,554 # coap.messaging.rfc7252: [MID 13150] transmission ended
2026-09-04 16:38:27,554 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,554 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,554 # coap.messaging.rfc7252: received <NON REQ mid=11949 token=462E code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,554 # coap.messaging: received in channel:
2026-09-04 16:38:27,554 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,554 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,554 # coap.server: </>: found
2026-09-04 16:38:27,554 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:27,555 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,555 # coap.blockwise: using block size 32 (we preferred 32, peer suggested 32)
2026-09-04 16:38:27,555 # coap.blockwise: slicing off block <#5, total=32B, M>
2026-09-04 16:38:27,555 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,555 # coap.messaging: sending in channel:
2026-09-04 16:38:27,555 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,555 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,555 # coap.messaging.rfc7252: sending <CON RESP mid=13151 token=462E code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,555 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,555 # coap.state.sched: messaging.7252.ack-timeout in 2138ms
2026-09-04 16:38:27,555 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,555 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,555 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,556 # coap.messaging.rfc7252: received <ACK EMPTY mid=13151 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,556 # coap.messaging.rfc7252: [MID 13151] received ACK, stopping retransmission
2026-09-04 16:38:27,556 # coap.messaging.rfc7252: [MID 13151] transmission ended
2026-09-04 16:38:27,556 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,556 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,556 # coap.messaging.rfc7252: received <NON REQ mid=11950 token=462F code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,556 # coap.messaging: received in channel:
2026-09-04 16:38:27,556 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,556 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,556 # coap.server: </>: found
2026-09-04 16:38:27,556 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:27,556 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,557 # coap.blockwise: slicing off block <#6, total=32B, M>
2026-09-04 16:38:27,557 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,557 # coap.messaging: sending in channel:
2026-09-04 16:38:27,557 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,557 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,557 # coap.messaging.rfc7252: sending <CON RESP mid=13152 token=462F code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,557 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,557 # coap.state.sched: messaging.7252.ack-timeout in 2621ms
2026-09-04 16:38:27,557 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,557 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,557 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,557 # coap.messaging.rfc7252: received <ACK EMPTY mid=13152 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,558 # coap.messaging.rfc7252: [MID 13152] received ACK, stopping retransmission
2026-09-04 16:38:27,558 # coap.messaging.rfc7252: [MID 13152] transmission ended
2026-09-04 16:38:27,558 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,558 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,558 # coap.messaging.rfc7252: received <NON REQ mid=11951 token=4630 code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,558 # coap.messaging: received in channel:
2026-09-04 16:38:27,558 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,558 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,558 # coap.server: </>: found
2026-09-04 16:38:27,558 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:27,558 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,558 # coap.blockwise: using block size 32 (we preferred 32, peer suggested 32)
2026-09-04 16:38:27,558 # coap.blockwise: slicing off block <#7, total=32B, M>
2026-09-04 16:38:27,559 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,559 # coap.messaging: sending in channel:
2026-09-04 16:38:27,559 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,559 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,559 # coap.messaging.rfc7252: sending <CON RESP mid=13153 token=4630 code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,559 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,559 # coap.state.sched: messaging.7252.ack-timeout in 2464ms
2026-09-04 16:38:27,559 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,559 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,559 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,559 # coap.messaging.rfc7252: received <ACK EMPTY mid=13153 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,559 # coap.messaging.rfc7252: [MID 13153] received ACK, stopping retransmission
2026-09-04 16:38:27,559 # coap.messaging.rfc7252: [MID 13153] transmission ended
2026-09-04 16:38:27,560 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,560 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,560 # coap.messaging.rfc7252: received <NON REQ mid=11952 token=4631 code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,560 # coap.messaging: received in channel:
2026-09-04 16:38:27,560 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,560 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,560 # coap.server: </>: found
2026-09-04 16:38:27,560 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:27,560 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,560 # coap.blockwise: slicing off block <#8, total=32B, M>
2026-09-04 16:38:27,560 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,560 # coap.messaging: sending in channel:
2026-09-04 16:38:27,560 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,560 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,561 # coap.messaging.rfc7252: sending <CON RESP mid=13154 token=4631 code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,561 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:27,561 # coap.state.sched: messaging.7252.ack-timeout in 2999ms
2026-09-04 16:38:27,561 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:27,561 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,561 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,561 # coap.messaging.rfc7252: received <ACK EMPTY mid=13154 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,561 # coap.messaging.rfc7252: [MID 13154] received ACK, stopping retransmission
2026-09-04 16:38:27,561 # coap.messaging.rfc7252: [MID 13154] transmission ended
2026-09-04 16:38:27,561 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,561 # coap.state.notif: messaging layer released state
2026-09-04 16:38:27,561 # coap.messaging.rfc7252: received <NON REQ mid=11953 token=4632 code=0.01 GET payload=(0 bytes) options=(1; 3 bytes)>
2026-09-04 16:38:27,562 # coap.messaging: received in channel:
2026-09-04 16:38:27,562 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,562 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,562 # coap.server: </>: found
2026-09-04 16:38:27,562 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:27,562 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:27,562 # coap.blockwise: using block size 32 (we preferred 32, peer suggested 32)
2026-09-04 16:38:27,562 # coap.blockwise: slicing off block <#9, total=24B, last>
2026-09-04 16:38:27,562 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:27,562 # coap.messaging: sending in channel:
2026-09-04 16:38:27,562 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:27,562 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:27,562 # coap.messaging.rfc7252: sending <CON RESP mid=13155 token=4632 code=2.05 Content payload=(24 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:27,563 # coap.transport.udp: sendv: 37 bytes
2026-09-04 16:38:27,563 # coap.state.sched: messaging.7252.ack-timeout in 2412ms
2026-09-04 16:38:27,563 # coap.messaging.rfc7252: created <carbon_copy size=37>
2026-09-04 16:38:27,563 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:27,563 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:27,563 # coap.messaging.rfc7252: received <ACK EMPTY mid=13155 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:27,563 # coap.messaging.rfc7252: [MID 13155] received ACK, stopping retransmission
2026-09-04 16:38:27,563 # coap.messaging.rfc7252: [MID 13155] transmission ended
2026-09-04 16:38:27,563 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:27,563 # coap.state.notif: messaging layer released state
2026-09-04 16:38:30,682 # coap.messaging.rfc7252: received <NON REQ mid=18113 token=203C code=0.01 GET payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:30,682 # coap.messaging: received in channel:
2026-09-04 16:38:30,682 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:30,682 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:30,682 # coap.server: </>: found
2026-09-04 16:38:30,682 # coap.state.sched: server.blockwise.amnesia cancelled
2026-09-04 16:38:30,682 # coap.server.blockwise: received request in SLICE stage
2026-09-04 16:38:30,682 # coap.blockwise: slicing off block <#9, total=32B, M>
2026-09-04 16:38:30,683 # coap.server.blockwise: slicing block-wise, sending more.
2026-09-04 16:38:30,683 # coap.messaging: sending in channel:
2026-09-04 16:38:30,683 #       remote=UDP <sock_tl_ep port=5600 netif=7 ipv6=fe80::5c64:bbff:fe11:9230>
2026-09-04 16:38:30,683 #       local=UDP <sock_tl_ep port=5683 netif=0 ipv6=fe80::5c64:bbff:fe11:9231>
2026-09-04 16:38:30,683 # coap.messaging.rfc7252: sending <CON RESP mid=13156 token=203C code=2.05 Content payload=(32 bytes) options=(2; 6 bytes)>
2026-09-04 16:38:30,683 # coap.transport.udp: sendv: 45 bytes
2026-09-04 16:38:30,683 # coap.state.sched: messaging.7252.ack-timeout in 2786ms
2026-09-04 16:38:30,683 # coap.messaging.rfc7252: created <carbon_copy size=45>
2026-09-04 16:38:30,683 # coap.state.notif: messaging layer allocated state
2026-09-04 16:38:30,683 # coap.state.sched: server.blockwise.amnesia in 60000ms
2026-09-04 16:38:30,683 # coap.messaging.rfc7252: received <ACK EMPTY mid=13156 token= code=0.00 Empty payload=(0 bytes) options=(0; 0 bytes)>
2026-09-04 16:38:30,683 # coap.messaging.rfc7252: [MID 13156] received ACK, stopping retransmission
2026-09-04 16:38:30,684 # coap.messaging.rfc7252: [MID 13156] transmission ended
2026-09-04 16:38:30,684 # coap.state.sched: messaging.7252.ack-timeout cancelled
2026-09-04 16:38:30,684 # coap.state.notif: messaging layer released state
image

@mguetschow

Copy link
Copy Markdown
Contributor

server: server.py, client: unicoap_client on native

requesting /.well-known/core, /other/separate, /other/block all work as expected

@crasbe crasbe added the State: needs rebase State: The codebase was changed since the creation of the PR, making a rebase necessary label Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Not Used AI was stated to not be used in this PR/Issue Area: build system Area: Build system Area: CoAP Area: Constrained Application Protocol implementations Area: doc Area: Documentation Area: examples Area: Example Applications Area: network Area: Networking Area: sys Area: System Area: tests Area: tests and testing framework State: needs rebase State: The codebase was changed since the creation of the PR, making a rebase necessary Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants