Skip to content

Completing CoAP block

Ken Bannister edited this page Jan 6, 2019 · 23 revisions

Presently, RIOT includes server side implementations of block1 and block2. We would like to add client side implementations. At the same time, we are working to complete the struct-based API as described in #9309. So, this document documents how we plan to integrate the client side implementations, including the function names. We break down the approach based on how the option is used -- read or write; and within write, for descriptive or control use.

In this document, descriptive and control are used as described in section 2.1 of RFC 7959:

Where Block1 is present in a request or Block2 in a response (i.e.,
in that message to the payload of which it pertains) it indicates a
block-wise transfer and describes how this specific block-wise
payload forms part of the entire body being transferred ("descriptive
usage").  Where it is present in the opposite direction, it provides
additional control on how that payload will be formed or was
processed ("control usage").

Finally, the Implementation Notes section describes the sequence of PRs to implement this goal. See the project page for status.

Write Option for Descriptive Use

In this scenario, we slice up some large content into smaller blocks and send it to the remote endpoint. We have implemented a server GET response for block2, and we wish to add a client POST/PUT request for block1.

For a block2 server response, use coap_block2_init() to read the block option in the request. No new functions needed here. This function initializes the slicer struct from the block2 option in the request.

For a block1 client request, the slicer struct for the initial request is zeroed by the client, and it is up to the client to remember the next block to request. The client may reuse the same slicer struct or create a new one with each request. However, the block option in the previous response is not required to generate the next request.

Task Buffer Put API Option Add API
write option coap_opt_put_block() coap_opt_add_block()
finish options write 0xff coap_opt_finish()
write payload slice coap_blockwise_put_(bytes|char) -same-
finalize option (more blocks?) coap_block_finish() -same-

Write Option for Control Use

Block1 response

A server must write a block option in the response to a block1 request. The response does not include a blockwise payload, although the response to the final request may contain a payload for the overall response to the sequence. For example, /sha256 resource in the nanocoap_server example returns the digest in the final response.

In this scenario, the application will not have a slicer struct. Instead, the server simply will take the option from the request and put it in the response. The server may request smaller blocks from the client. Create coap_opt_put_block_control() and coap_opt_add_block_control().

Block2 request

A client must write a block2 option in the request to receive a particular block. The client initializes this option for the first request. The client likely retrieves the block option in responses, and increments the offset to request the next block. As with a Block1 response, the client uses a coap_block1_t, not a slicer struct. The client also can use the new coap_opt_put_block_control() and coap_opt_add_block_control().

Read Option

For either block1 or block2, client or server, the user simply wants to retrieve the block into a coap_block1_t struct. Note we need to rework so the existing coap_get_block1() and coap_get_block2() to be inline. They simply return the value of a new coap_get_block() function as currently implemented in coap_get_block1().

Implementation Notes

Each item below represents a PR.

  • Add coap_opt_put_block(). coap_opt_put_block2() already exists.

  • Add coap_opt_put_block_control(). Change _sha256_handler() to use coap_opt_put_block1_control() instead of coap_put_block1_ok(), which has a bug. Also deprecate coap_put_block1_ok() and coap_put_block1().

  • Create coap_opt_add_block(). Condense _slicer...() functions into _slicer2optval(). Use this new function in coap_opt_put_block() and coap_opt_add_block(). Create gcoap test app for /sha256 server.

  • Create coap_opt_add_block_control(). Create gcoap_test_app for /riot/ver server.

  • Create test app to POST /sha256. It uses coap_opt_put_block1(). Test against existing /sha256 handler. Create a second gcoap test app to use coap_opt_add_block1().

  • Create test app to GET /.well-known/core. It uses coap_opt_put_block2_control(). Test against existing /.well-known/core. Create a second gcoap test app to use coap_opt_add_block2_control().