net: coap_client: allow application to add block2 option to requests

Allow an application to add a Block2 option to an initial request for a
resource. For any subsequent requests as part of a blockwise transfer,
drop the application-added Block2 option since the coap_client must
append a Block2 option with updated NUM and SZX fields based on the
server response.

Signed-off-by: Matt Rodgers <mrodgers@witekio.com>
This commit is contained in:
Matt Rodgers 2024-07-29 11:55:27 +01:00 committed by Fabio Baltieri
commit 47fbb8512f
3 changed files with 60 additions and 0 deletions

View file

@ -79,6 +79,34 @@ The following is an example of a very simple response handling function:
} }
} }
CoAP options may also be added to the request by the application. The following is an example of
the application adding a Block2 option to the initial request, to suggest a maximum block size to
the server for a resource that it expects to be large enough to require a blockwise transfer (see
RFC7959 Figure 3: Block-Wise GET with Early Negotiation).
.. code-block:: c
static struct coap_client;
struct coap_client_request req = { 0 };
/* static, since options must remain valid throughout the whole execution of the request */
static struct coap_client_option block2_option;
coap_client_init(&client, NULL);
block2_option = coap_client_option_initial_block2();
req.method = COAP_METHOD_GET;
req.confirmable = true;
req.path = "test";
req.fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN;
req.cb = response_cb;
req.options = &block2_option;
req.num_options = 1;
req.payload = NULL;
req.len = 0;
ret = coap_client_req(&client, sock, &address, &req, -1);
API Reference API Reference
************* *************

View file

@ -159,6 +159,28 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr
*/ */
void coap_client_cancel_requests(struct coap_client *client); void coap_client_cancel_requests(struct coap_client *client);
/**
* @brief Initialise a Block2 option to be added to a request
*
* If the application expects a request to require a blockwise transfer, it may pre-emptively
* suggest a maximum block size to the server - see RFC7959 Figure 3: Block-Wise GET with Early
* Negotiation.
*
* This helper function returns a Block2 option to send with the initial request.
*
* @return CoAP client initial Block2 option structure
*/
static inline struct coap_client_option coap_client_option_initial_block2(void)
{
struct coap_client_option block2 = {
.code = COAP_OPTION_BLOCK2,
.len = 1,
.value[0] = coap_bytes_to_block_size(CONFIG_COAP_CLIENT_BLOCK_SIZE),
};
return block2;
}
/** /**
* @} * @}
*/ */

View file

@ -148,6 +148,7 @@ static int coap_client_init_request(struct coap_client *client,
{ {
int ret = 0; int ret = 0;
int i; int i;
bool block2 = false;
memset(client->send_buf, 0, sizeof(client->send_buf)); memset(client->send_buf, 0, sizeof(client->send_buf));
@ -189,6 +190,7 @@ static int coap_client_init_request(struct coap_client *client,
/* Blockwise receive ongoing, request next block. */ /* Blockwise receive ongoing, request next block. */
if (internal_req->recv_blk_ctx.current > 0) { if (internal_req->recv_blk_ctx.current > 0) {
block2 = true;
ret = coap_append_block2_option(&internal_req->request, ret = coap_append_block2_option(&internal_req->request,
&internal_req->recv_blk_ctx); &internal_req->recv_blk_ctx);
@ -200,6 +202,14 @@ static int coap_client_init_request(struct coap_client *client,
/* Add extra options if any */ /* Add extra options if any */
for (i = 0; i < req->num_options; i++) { for (i = 0; i < req->num_options; i++) {
if (COAP_OPTION_BLOCK2 == req->options[i].code && block2) {
/* After the first request, ignore any block2 option added by the
* application, since NUM (and possibly SZX) must be updated based on the
* server response.
*/
continue;
}
ret = coap_packet_append_option(&internal_req->request, req->options[i].code, ret = coap_packet_append_option(&internal_req->request, req->options[i].code,
req->options[i].value, req->options[i].len); req->options[i].value, req->options[i].len);