From 68beb52f14ea26d7b5926f4e74f73b7bbbe40d01 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 5 Nov 2024 10:46:02 +0100 Subject: [PATCH] sys/net/nanocoap: add and use coap_get_response_hdr_len() Before, handlers writing blockwise transfer assumed that the response header length will match the request header length. This is true for UDP, but not for TCP: The CoAP over TCP header contains a Len field, that gets extended for larger messages. Since the reply often is indeed larger than the request, this is indeed often the case for CoAP over TCP. Note: Right now, no CoAP over TCP implementation is upstream. However, getting rid of incorrect assumptions now will make life easier later on. --- examples/nanocoap_server/coap_handler.c | 2 +- sys/include/net/nanocoap.h | 19 +++++++++++++++++++ sys/include/net/nanocoap_sock.h | 11 +++++++---- sys/net/application_layer/nanocoap/nanocoap.c | 2 +- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/examples/nanocoap_server/coap_handler.c b/examples/nanocoap_server/coap_handler.c index f777dab9c0..7b6b480f5a 100644 --- a/examples/nanocoap_server/coap_handler.c +++ b/examples/nanocoap_server/coap_handler.c @@ -53,7 +53,7 @@ static ssize_t _riot_block2_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, c (void)context; coap_block_slicer_t slicer; coap_block2_init(pkt, &slicer); - uint8_t *payload = buf + coap_get_total_hdr_len(pkt); + uint8_t *payload = buf + coap_get_response_hdr_len(pkt); uint8_t *bufpos = payload; diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index a663379868..ca09b27461 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -677,6 +677,22 @@ static inline unsigned coap_get_total_hdr_len(const coap_pkt_t *pkt) coap_get_token_len(pkt); } +/** + * @brief Get the header length a response to the given packet will have + * + * @param[in] pkt CoAP packet to reply to + * @return Length of the response header including token excluding + * CoAP options and any payload marker + * + * @note The main use case is the use of @ref coap_block2_build_reply, which + * is building the CoAP header of the response after options and + * payload have been added. + */ +static inline unsigned coap_get_response_hdr_len(const coap_pkt_t *pkt) +{ + return coap_get_total_hdr_len(pkt); +} + /** * @brief Write the given raw message code to given CoAP header * @@ -1939,6 +1955,9 @@ static inline size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, * @param[in] payload_len length of payload * @param[in] slicer slicer to use * + * @warning Use @ref coap_get_response_hdr_len to determine the size of the + * header this will write. + * * @returns size of reply packet on success * @returns <0 on error */ diff --git a/sys/include/net/nanocoap_sock.h b/sys/include/net/nanocoap_sock.h index d109dd8a36..fc1b2d70c2 100644 --- a/sys/include/net/nanocoap_sock.h +++ b/sys/include/net/nanocoap_sock.h @@ -110,10 +110,13 @@ * Start with coap_block2_init() to read the client request and initialize a * coap_slicer_t struct with the size and location for this slice of the * overall payload. Then write the block2 option in the response with - * coap_opt_put_block2(). The option includes an indicator ("more") that a - * slice completes the overall payload transfer. You may not know the value for - * _more_ at this point, but you must initialize the space in the packet for - * the option before writing the payload. The option is rewritten later. + * coap_opt_put_block2(). Use @ref coap_get_response_hdr_len to get the length + * of the response header: This will be the offset in the buffer where you + * should start adding options. The Block2 option includes an indicator + * ("more") that a slice completes the overall payload transfer. You may not + * know the value for _more_ at this point, but you must initialize the space + * in the packet for the option before writing the payload. The option is + * rewritten later. * * Next, use the coap_blockwise_put_xxx() functions to write the payload * content. These functions use the coap_block_slicer_t to enable or disable diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index 06d70a918a..97990932c1 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -1415,7 +1415,7 @@ ssize_t coap_well_known_core_default_handler(coap_pkt_t *pkt, uint8_t *buf, \ (void)context; coap_block_slicer_t slicer; coap_block2_init(pkt, &slicer); - uint8_t *payload = buf + coap_get_total_hdr_len(pkt); + uint8_t *payload = buf + coap_get_response_hdr_len(pkt); uint8_t *bufpos = payload; bufpos += coap_put_option_ct(bufpos, 0, COAP_FORMAT_LINK); bufpos += coap_opt_put_block2(bufpos, COAP_OPT_CONTENT_FORMAT, &slicer, 1);