diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index 083815af59..6d3b17ca9e 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -1364,6 +1364,25 @@ static inline size_t coap_opt_put_uri_query(uint8_t *buf, uint16_t lastonum, return coap_opt_put_string(buf, lastonum, COAP_OPT_URI_QUERY, uri, '&'); } +/** + * @brief Convenience function for inserting URI_PATH and URI_QUERY into buffer + * This function will automatically split path and query parameters. + * + * @param[out] buf buffer to write to + * @param[in,out] lastonum number of previous option (for delta calculation), + * or 0 if first option + * @param[in] uri ptr into a source URI, to the first character after + * the authority component + * + * @returns amount of bytes written to @p buf + * + * This function may produce two different options (Uri-Path and Uri-Query). + * Users that need to insert Content-Format, Max-Age or the currently + * unassigned option 13 need to split their URI themselves and call the + * respective helper functions. + */ +size_t coap_opt_put_uri_pathquery(uint8_t *buf, uint16_t *lastonum, const char *uri); + /** * @brief Convenience function for inserting PROXY_URI option into buffer * diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index bdb4a6bfd3..3905e8a320 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -787,6 +787,26 @@ size_t coap_opt_put_string_with_len(uint8_t *buf, uint16_t lastonum, uint16_t op return bufpos - buf; } +size_t coap_opt_put_uri_pathquery(uint8_t *buf, uint16_t *lastonum, const char *uri) +{ + const char *query = strchr(uri, '?'); + size_t len = query ? (size_t)(query - uri - 1) : strlen(uri); + size_t bytes_out = coap_opt_put_string_with_len(buf, *lastonum, + COAP_OPT_URI_PATH, + uri, len, '/'); + + if (query) { + buf += bytes_out; + bytes_out += coap_opt_put_uri_query(buf, COAP_OPT_URI_PATH, query + 1); + *lastonum = COAP_OPT_URI_QUERY; + } + else { + *lastonum = COAP_OPT_URI_PATH; + } + + return bytes_out; +} + size_t coap_opt_put_uint(uint8_t *buf, uint16_t lastonum, uint16_t onum, uint32_t value) { diff --git a/tests/unittests/tests-nanocoap/tests-nanocoap.c b/tests/unittests/tests-nanocoap/tests-nanocoap.c index 00d5c85147..09ccdf1109 100644 --- a/tests/unittests/tests-nanocoap/tests-nanocoap.c +++ b/tests/unittests/tests-nanocoap/tests-nanocoap.c @@ -58,6 +58,37 @@ static void test_nanocoap__hdr(void) TEST_ASSERT_EQUAL_STRING((char *)loc_path, (char *)path_tmp); } +/* + * Validates encoded message ID byte order and put/get URI & Query option. + */ +static void test_nanocoap__hdr_2(void) +{ + uint8_t buf[_BUF_SIZE]; + uint16_t msgid = 0xABCD; + char path[] = "/test/abcd/efgh?foo=bar&baz=blub"; + unsigned char path_tmp[64] = {0}; + unsigned char query_tmp[64] = {0}; + + uint8_t *pktpos = &buf[0]; + uint16_t lastonum = 0; + pktpos += coap_build_hdr((coap_hdr_t *)pktpos, COAP_TYPE_CON, NULL, 0, + COAP_METHOD_GET, msgid); + pktpos += coap_opt_put_uri_pathquery(pktpos, &lastonum, path); + + coap_pkt_t pkt; + coap_parse(&pkt, &buf[0], pktpos - &buf[0]); + + TEST_ASSERT_EQUAL_INT(msgid, coap_get_id(&pkt)); + + int res = coap_get_uri_path(&pkt, path_tmp); + TEST_ASSERT_EQUAL_INT(sizeof("/test/abcd/efgh"), res); + TEST_ASSERT_EQUAL_STRING("/test/abcd/efgh", (char *)path_tmp); + + res = coap_get_uri_query(&pkt, query_tmp); + TEST_ASSERT_EQUAL_INT(sizeof("&foo=bar&baz=blub"), res); + TEST_ASSERT_EQUAL_STRING("&foo=bar&baz=blub", (char *)query_tmp); +} + /* * Client GET request with simple path. Test request generation. * Request /time resource from libcoap example @@ -840,6 +871,7 @@ Test *tests_nanocoap_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { new_TestFixture(test_nanocoap__hdr), + new_TestFixture(test_nanocoap__hdr_2), new_TestFixture(test_nanocoap__get_req), new_TestFixture(test_nanocoap__put_req), new_TestFixture(test_nanocoap__get_multi_path),