diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index abdf2409fd8f..d239a6a4f1fe 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -573,6 +573,23 @@ static inline ssize_t coap_get_uri_query(const coap_pkt_t *pkt, uint8_t *target) */ ssize_t coap_opt_get_next(const coap_pkt_t *pkt, coap_optpos_t *opt, uint8_t **value, bool init_opt); + +/** + * @brief Retrieve the value for an option as an opaque array of bytes + * + * Retrieves the location and length of the option value of any type. Useful for + * an opaque option, which essentially is an array of bytes. If more than one + * option for a given option number, retrieves the first option. To retrieve + * subsequent options, see coap_opt_get_next(). + * + * @param[in] pkt packet to read from + * @param[in] opt_num option number to retrieve + * @param[out] value start of the option value + * + * @return length of option; 0 if the option exists but is empty + * @return -ENOENT if option not found + */ +ssize_t coap_opt_get_opaque(coap_pkt_t *pkt, unsigned opt_num, uint8_t **value); /**@}*/ diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index 0759f11f410e..cfae4cffeb02 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -205,6 +205,20 @@ static uint8_t *_parse_option(const coap_pkt_t *pkt, return pkt_pos; } +ssize_t coap_opt_get_opaque(coap_pkt_t *pkt, unsigned opt_num, uint8_t **value) +{ + uint8_t *start = coap_find_option(pkt, opt_num); + if (!start) { + return -ENOENT; + } + + uint16_t delta; + int len; + + *value = _parse_option(pkt, start, &delta, &len); + return len; +} + int coap_get_option_uint(coap_pkt_t *pkt, unsigned opt_num, uint32_t *target) { assert(target); diff --git a/tests/unittests/tests-nanocoap/tests-nanocoap.c b/tests/unittests/tests-nanocoap/tests-nanocoap.c index c5d630b9d4a2..ce6888df8828 100644 --- a/tests/unittests/tests-nanocoap/tests-nanocoap.c +++ b/tests/unittests/tests-nanocoap/tests-nanocoap.c @@ -620,6 +620,31 @@ static void test_nanocoap__options_iterate(void) } } +/* + * Tests use of coap_opt_get_opaque() to find an option as a byte array, and + * coap_opt_get_next() to find a second option with the same option number. + */ +static void test_nanocoap__options_get_opaque(void) +{ + coap_pkt_t pkt; + int res = _read_rd_post_req(&pkt, true); + TEST_ASSERT_EQUAL_INT(0, res); + + /* read Uri-Query options */ + uint8_t *value; + ssize_t optlen = coap_opt_get_opaque(&pkt, COAP_OPT_URI_QUERY, &value); + TEST_ASSERT_EQUAL_INT(24, optlen); + + coap_optpos_t opt = {0, value + optlen - (uint8_t *)pkt.hdr}; + + optlen = coap_opt_get_next(&pkt, &opt, &value, false); + TEST_ASSERT_EQUAL_INT(0, opt.opt_num); + TEST_ASSERT_EQUAL_INT(5, optlen); + + optlen = coap_opt_get_next(&pkt, &opt, &value, false); + TEST_ASSERT_EQUAL_INT(-ENOENT, optlen); +} + Test *tests_nanocoap_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { @@ -634,6 +659,7 @@ Test *tests_nanocoap_tests(void) new_TestFixture(test_nanocoap__get_query), new_TestFixture(test_nanocoap__get_multi_query), new_TestFixture(test_nanocoap__option_add_buffer_max), + new_TestFixture(test_nanocoap__options_get_opaque), new_TestFixture(test_nanocoap__options_iterate), new_TestFixture(test_nanocoap__server_get_req), new_TestFixture(test_nanocoap__server_reply_simple),