From 6fe31c4396bdc681e6c5e4bf59fbfa16243151f3 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Wed, 11 Dec 2024 15:22:23 +0100 Subject: [PATCH] lib: nrf_cloud: use BLOCK2 for resumption offset Fix an issue where resumption wasn't requesting the correct offset of the FOTA file to download using COAP. This patch uses the standard offset option instead of a custom one. Signed-off-by: Maximilian Deubel --- .../releases/release-notes-changelog.rst | 6 +- .../lib/nrf_cloud/src/nrf_cloud_download.c | 58 ++++++++++++++----- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index e0a092e2028b..aadc6f829f50 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -450,7 +450,11 @@ Multiprotocol Service Layer libraries Libraries for networking ------------------------ -|no_changes_yet_note| +* :ref:`lib_nrf_cloud` library: + + * Fixed: + + * An issue that would cause resumption to fail when FOTA images are downloaded using the CoAP backend. Libraries for NFC ----------------- diff --git a/subsys/net/lib/nrf_cloud/src/nrf_cloud_download.c b/subsys/net/lib/nrf_cloud/src/nrf_cloud_download.c index 35e34c350714..0ccd5e079e0f 100644 --- a/subsys/net/lib/nrf_cloud/src/nrf_cloud_download.c +++ b/subsys/net/lib/nrf_cloud/src/nrf_cloud_download.c @@ -36,7 +36,8 @@ static struct nrf_cloud_download_data active_dl = { .type = NRF_CLOUD_DL_TYPE_NO #if defined(CONFIG_NRF_CLOUD_COAP_DOWNLOADS) #define ACPT_IDX 0 #define PRXY_IDX 1 -#define OPT_CNT 2 +#define BLOCK2_IDX 2 +#define OPT_CNT 3 /* CoAP option array */ static struct coap_client_option cc_opts[OPT_CNT] = {0}; /* CoAP client to be used for file downloads */ @@ -197,15 +198,43 @@ static void coap_dl_cb(int16_t result_code, size_t offset, const uint8_t *payloa } #define MAX_RETRIES 5 -#define PROXY_RSC_OFFSET_TMPLT NRF_CLOUD_COAP_PROXY_RSC "?offset=%u" -#define PROXY_RSC_BUF_SZ sizeof(PROXY_RSC_OFFSET_TMPLT) + 10 -static int coap_dl_start(struct nrf_cloud_download_data *const dl, const size_t offset) +/* COAP_OPTION_BLOCK2: set block size */ +#define SET_BLOCK_SIZE(v, b) (v |= ((b) & 0x07)) +/* COAP_OPTION_BLOCK2: set block number */ +#define SET_NUM(v, n) ((v) |= ((n) << 4)) + +/* convert integer into CoAP option */ +static uint8_t coap_option_write_int_val(uint8_t *data, uint16_t val) { - static char rsc_path_offset[PROXY_RSC_BUF_SZ]; + uint8_t len; + + if (val == 0U) { + data[0] = 0U; + len = 0U; + } else if (val < 0xFF) { + data[0] = (uint8_t) val; + len = 1U; + } else if (val < 0xFFFF) { + sys_put_be16(val, data); + len = 2U; + } else if (val < 0xFFFFFF) { + sys_put_be16(val, &data[1]); + data[0] = val >> 16; + len = 3U; + } else { + sys_put_be32(val, data); + len = 4U; + } + + return len; +} +static int coap_dl_start(struct nrf_cloud_download_data *const dl, const size_t offset) +{ int err; int retry = 0; struct coap_client *cc = &coap_client.cc; + int block2_val = 0; struct coap_client_request request = { .method = COAP_METHOD_GET, @@ -221,14 +250,11 @@ static int coap_dl_start(struct nrf_cloud_download_data *const dl, const size_t }; if (offset > 0) { - /* Use the offset parameter in the resource path */ - err = snprintk(rsc_path_offset, sizeof(rsc_path_offset), - PROXY_RSC_OFFSET_TMPLT, offset); - if ((err < 0) || (err >= sizeof(rsc_path_offset))) { - LOG_ERR("Could not format CoAP proxy download resource"); - return -EIO; - } - request.path = rsc_path_offset; + SET_NUM(block2_val, (offset/1024)); + SET_BLOCK_SIZE(block2_val, COAP_BLOCK_1024); + cc_opts[BLOCK2_IDX].code = COAP_OPTION_BLOCK2; + cc_opts[BLOCK2_IDX].len = + coap_option_write_int_val(cc_opts[BLOCK2_IDX].value, block2_val); } while ((err = coap_client_req(cc, cc->fd, NULL, &request, NULL)) == -EAGAIN) { @@ -287,6 +313,12 @@ static int coap_dl(struct nrf_cloud_download_data *const dl) ret = nrf_cloud_coap_transport_proxy_dl_opts_get(&cc_opts[ACPT_IDX], &cc_opts[PRXY_IDX], dl->host, file_path); + cc_opts[BLOCK2_IDX].code = COAP_OPTION_BLOCK2; + cc_opts[BLOCK2_IDX].len = 1; + cc_opts[BLOCK2_IDX].value[0] = 0; + SET_BLOCK_SIZE(cc_opts[BLOCK2_IDX].value[0], COAP_BLOCK_1024); + SET_NUM(cc_opts[BLOCK2_IDX].value[0], 0); + if (ret) { LOG_ERR("Failed to set CoAP options, error: %d", ret); return ret;