From d69d4013d3c39b2b1c14522863364cfe3eb73b6c Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Tue, 7 Nov 2023 16:23:34 +0200 Subject: [PATCH] net: lwm2m: Fix blockwise response code In CoAP blockwise the client is supposed to respond with 2.31 Continue code on Ack. This was recently broken when Block1 parsing was moved after the initialization of reponse packet. We need separate CoAP API to modify the code of existing CoAP packet. Also Ack packet should contain the Block1 options, even the last one. Signed-off-by: Seppo Takalo --- include/zephyr/net/coap.h | 9 ++++++ subsys/net/lib/coap/coap.c | 10 +++++++ subsys/net/lib/lwm2m/lwm2m_message_handling.c | 30 +++++++++++++------ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/include/zephyr/net/coap.h b/include/zephyr/net/coap.h index 325ced2ebb..ebc7270975 100644 --- a/include/zephyr/net/coap.h +++ b/include/zephyr/net/coap.h @@ -373,6 +373,15 @@ uint8_t coap_header_get_token(const struct coap_packet *cpkt, uint8_t *token); */ uint8_t coap_header_get_code(const struct coap_packet *cpkt); +/** + * @brief Modifies the code of the CoAP packet. + * + * @param cpkt CoAP packet representation + * @param code CoAP code + * @return 0 on success, -EINVAL on failure + */ +int coap_header_set_code(const struct coap_packet *cpkt, uint8_t code); + /** * @brief Returns the message id associated with the CoAP packet. * diff --git a/subsys/net/lib/coap/coap.c b/subsys/net/lib/coap/coap.c index 429d3fd3d4..8ac8d73e78 100644 --- a/subsys/net/lib/coap/coap.c +++ b/subsys/net/lib/coap/coap.c @@ -950,6 +950,16 @@ static uint8_t __coap_header_get_code(const struct coap_packet *cpkt) return cpkt->data[1]; } +int coap_header_set_code(const struct coap_packet *cpkt, uint8_t code) +{ + if (!cpkt || !cpkt->data) { + return -EINVAL; + } + + cpkt->data[1] = code; + return 0; +} + uint8_t coap_header_get_token(const struct coap_packet *cpkt, uint8_t *token) { uint8_t tkl; diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index ed5f28aabd..6d006b4603 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -2065,6 +2065,13 @@ static int parse_write_op(struct lwm2m_message *msg, uint16_t format) if (block_num < block_ctx->expected) { LOG_WRN("Block already handled %d, expected %d", block_num, block_ctx->expected); + (void)coap_header_set_code(msg->out.out_cpkt, COAP_RESPONSE_CODE_CONTINUE); + /* Respond with the original Block1 header, original Ack migh have been + * lost, and this is a retry. We don't know the original response, but + * since it is handled, just assume we can continue. + */ + (void)coap_append_option_int(msg->out.out_cpkt, COAP_OPTION_BLOCK1, + block_opt); return 0; } if (block_num > block_ctx->expected) { @@ -2087,30 +2094,35 @@ static int parse_write_op(struct lwm2m_message *msg, uint16_t format) * number. */ block_ctx->expected += GET_BLOCK_SIZE(block_opt) - block_ctx->ctx.block_size + 1; - - /* Handle blockwise 1 (Part 1): Set response code */ - if (!last_block) { - msg->code = COAP_RESPONSE_CODE_CONTINUE; - } } r = do_write_op(msg, format); /* Handle blockwise 1 (Part 2): Append BLOCK1 option / free context */ if (block_ctx) { - if (r >= 0 && !last_block) { - /* More to come, ack with correspond block # */ + if (r >= 0) { + /* Add block1 option to response. + * As RFC7959 Section-2.3, More flag is off, because we have already + * written the data. + */ r = coap_append_block1_option(msg->out.out_cpkt, &block_ctx->ctx); if (r < 0) { /* report as internal server error */ - LOG_ERR("Fail adding block1 option: %d", r); + LOG_DBG("Fail adding block1 option: %d", r); r = -EINVAL; } + if (!last_block) { + r = coap_header_set_code(msg->out.out_cpkt, + COAP_RESPONSE_CODE_CONTINUE); + if (r < 0) { + LOG_DBG("Failed to modify response code"); + r = -EINVAL; + } + } } if (r < 0 || last_block) { /* Free context when finished or when there is error */ free_block_ctx(block_ctx); - } }