diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index 06d70a918a..929ff50980 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -558,6 +558,13 @@ ssize_t coap_build_reply_header(coap_pkt_t *pkt, unsigned code, ? COAP_TYPE_ACK : COAP_TYPE_NON; + if (IS_USED(MODULE_NANOCOAP_TOKEN_EXT)) { + /* Worst case: 2 byte extended token length field. + * See https://www.rfc-editor.org/rfc/rfc8974#name-extended-token-length-tkl-f + */ + hdr_len += 2; + } + if (hdr_len > len) { return -ENOBUFS; } @@ -585,6 +592,13 @@ ssize_t coap_build_reply_header(coap_pkt_t *pkt, unsigned code, } } + if (IS_USED(MODULE_NANOCOAP_TOKEN_EXT)) { + /* we need to update the header length with the actual one, as we may + * have used less bytes for the extended token length fields as our + * worst case assumption */ + hdr_len = bufpos - (uint8_t *)buf; + } + if (payload) { if (ct >= 0) { bufpos += coap_put_option_ct(bufpos, 0, ct); diff --git a/tests/unittests/tests-nanocoap/tests-nanocoap.c b/tests/unittests/tests-nanocoap/tests-nanocoap.c index b76ebeb035..098e243251 100644 --- a/tests/unittests/tests-nanocoap/tests-nanocoap.c +++ b/tests/unittests/tests-nanocoap/tests-nanocoap.c @@ -1099,15 +1099,35 @@ static void test_nanocoap__token_length_ext_16(void) uint8_t buf[32]; coap_hdr_t *hdr = (void *)buf; + /* build a request with an overlong token (that mandates the use of + * an 8 bit extended token length field) */ TEST_ASSERT_EQUAL_INT(21, coap_build_hdr(hdr, COAP_TYPE_CON, (void *)token, strlen(token), - COAP_CODE_204, 23)); + COAP_METHOD_DELETE, 23)); + + /* parse the packet build, and verify it parses back as expected */ coap_pkt_t pkt; int res = coap_parse(&pkt, buf, 21); TEST_ASSERT_EQUAL_INT(0, res); TEST_ASSERT_EQUAL_INT(21, coap_get_total_hdr_len(&pkt)); - TEST_ASSERT_EQUAL_INT(204, coap_get_code_decimal(&pkt)); + TEST_ASSERT_EQUAL_INT(COAP_METHOD_DELETE, coap_get_code_raw(&pkt)); + TEST_ASSERT_EQUAL_INT(23, coap_get_id(&pkt)); + TEST_ASSERT_EQUAL_INT(strlen(token), coap_get_token_len(&pkt)); + TEST_ASSERT_EQUAL_INT(0, memcmp(coap_get_token(&pkt), token, strlen(token))); + TEST_ASSERT_EQUAL_INT(0, pkt.payload_len); + TEST_ASSERT_EQUAL_INT(13, hdr->ver_t_tkl & 0xf); + + /* now build the corresponding reply and check that it parses back as + * expected */ + uint8_t rbuf[sizeof(buf)]; + ssize_t len = coap_build_reply_header(&pkt, COAP_CODE_DELETED, rbuf, + sizeof(rbuf), 0, NULL, NULL); + TEST_ASSERT_EQUAL_INT(21, len); + res = coap_parse(&pkt, rbuf, 21); + TEST_ASSERT_EQUAL_INT(0, res); + TEST_ASSERT_EQUAL_INT(21, coap_get_total_hdr_len(&pkt)); + TEST_ASSERT_EQUAL_INT(COAP_CODE_DELETED, coap_get_code_raw(&pkt)); TEST_ASSERT_EQUAL_INT(23, coap_get_id(&pkt)); TEST_ASSERT_EQUAL_INT(strlen(token), coap_get_token_len(&pkt)); TEST_ASSERT_EQUAL_INT(0, memcmp(coap_get_token(&pkt), token, strlen(token))); @@ -1128,15 +1148,36 @@ static void test_nanocoap__token_length_ext_269(void) uint8_t buf[280]; coap_hdr_t *hdr = (void *)buf; + /* build a request with an overlong token (that mandates the use of + * an 16 bit extended token length field) */ TEST_ASSERT_EQUAL_INT(275, coap_build_hdr(hdr, COAP_TYPE_CON, (void *)token, strlen(token), - COAP_CODE_204, 23)); + COAP_METHOD_DELETE, 23)); + + /* parse the packet build, and verify it parses back as expected */ coap_pkt_t pkt; int res = coap_parse(&pkt, buf, 275); TEST_ASSERT_EQUAL_INT(0, res); TEST_ASSERT_EQUAL_INT(275, coap_get_total_hdr_len(&pkt)); - TEST_ASSERT_EQUAL_INT(204, coap_get_code_decimal(&pkt)); + TEST_ASSERT_EQUAL_INT(COAP_METHOD_DELETE, coap_get_code_raw(&pkt)); + TEST_ASSERT_EQUAL_INT(23, coap_get_id(&pkt)); + TEST_ASSERT_EQUAL_INT(strlen(token), coap_get_token_len(&pkt)); + TEST_ASSERT_EQUAL_INT(0, memcmp(coap_get_token(&pkt), token, strlen(token))); + TEST_ASSERT_EQUAL_INT(0, pkt.payload_len); + TEST_ASSERT_EQUAL_INT(14, hdr->ver_t_tkl & 0xf); + + /* now build the corresponding reply and check that it parses back as + * expected */ + uint8_t rbuf[sizeof(buf)]; + ssize_t len = coap_build_reply_header(&pkt, COAP_CODE_DELETED, rbuf, + sizeof(rbuf), 0, NULL, NULL); + + TEST_ASSERT_EQUAL_INT(275, len); + res = coap_parse(&pkt, rbuf, 275); + TEST_ASSERT_EQUAL_INT(0, res); + TEST_ASSERT_EQUAL_INT(275, coap_get_total_hdr_len(&pkt)); + TEST_ASSERT_EQUAL_INT(COAP_CODE_DELETED, coap_get_code_raw(&pkt)); TEST_ASSERT_EQUAL_INT(23, coap_get_id(&pkt)); TEST_ASSERT_EQUAL_INT(strlen(token), coap_get_token_len(&pkt)); TEST_ASSERT_EQUAL_INT(0, memcmp(coap_get_token(&pkt), token, strlen(token)));