1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-15 17:43:51 +01:00

Merge pull request #20197 from benpicco/coap_iterate_uri_query

nanocoap: add coap_iterate_uri_query()
This commit is contained in:
benpicco 2025-07-24 11:35:51 +00:00 committed by GitHub
commit 4f9f755f99
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 114 additions and 4 deletions

View File

@ -987,6 +987,31 @@ static inline ssize_t coap_get_uri_query_string(coap_pkt_t *pkt, char *target,
bool coap_find_uri_query(coap_pkt_t *pkt, const char *key,
const char **value, size_t *len);
/**
* @brief Iterate over a packet's URI Query options
*
* This expects that the Uri-Query options follow the widespread format `key=value`
* or just `key`
*
* Key and Value will be copied into the supplied buffers as a NULL-terminated
* string.
*
* @param[in] pkt packet to read from
* @param[out] ctx opaque, must be set to `NULL` on first call
* @param[out] key Output buffer for the key
* @param[in] key_len_max Size of the key output buffer
* @param[out] value Output buffer for the value
* @param[in] value_len_max Size of the value output buffer
*
* @return 2 if key and value were found
* @return 1 if key was found
* @return 0 if no key was found
* @return -E2BIG if key or value does not fit the supplied space
*/
int coap_iterate_uri_query(coap_pkt_t *pkt, void **ctx,
char *key, size_t key_len_max,
char *value, size_t value_len_max);
/**
* @brief Iterate over a packet's options
*

View File

@ -407,6 +407,56 @@ ssize_t coap_opt_get_string(coap_pkt_t *pkt, uint16_t optnum,
return (int)(max_len - left);
}
int coap_iterate_uri_query(coap_pkt_t *pkt, void **opt_pos,
char *key, size_t key_len_max,
char *value, size_t value_len_max)
{
int len;
void *key_data = coap_iterate_option(pkt, COAP_OPT_URI_QUERY,
(uint8_t **)opt_pos, &len);
if (!key_data) {
return 0; /* No key found */
}
const char *value_data = memchr(key_data, '=', len);
size_t key_len, value_len;
if (value_data) {
key_len = (uintptr_t)value_data - (uintptr_t)key_data;
value_data += 1;
value_len = len - key_len - 1;
} else {
key_len = len;
value_data = NULL;
value_len = 0;
if (value && value_len_max) {
value[0] = 0;
}
}
if (key_len >= key_len_max) {
return -E2BIG;
}
memcpy(key, key_data, key_len);
key[key_len] = 0;
if (!value_data) {
return 1; /* Key was found but no values */
}
if (!value) {
return 2; /* Key and values found */
}
if (value_len >= value_len_max) {
return -E2BIG;
}
memcpy(value, value_data, value_len);
value[value_len] = 0;
return 2; /* Key and values found */
}
int coap_get_blockopt(coap_pkt_t *pkt, uint16_t option, uint32_t *blknum, uint8_t *szx)
{
uint8_t *optpos = coap_find_option(pkt, option);

View File

@ -67,6 +67,8 @@ static void test_nanocoap__hdr_2(void)
char path[] = "/test/abcd/efgh?foo=bar&baz=blub";
unsigned char path_tmp[64] = {0};
char query_tmp[64] = {0};
char key[8];
char value[8];
uint8_t *pktpos = &buf[0];
uint16_t lastonum = 0;
@ -86,6 +88,25 @@ static void test_nanocoap__hdr_2(void)
res = coap_get_uri_query_string(&pkt, query_tmp, sizeof(query_tmp));
TEST_ASSERT_EQUAL_INT(sizeof("&foo=bar&baz=blub"), res);
TEST_ASSERT_EQUAL_STRING("&foo=bar&baz=blub", (char *)query_tmp);
void *pos = NULL;
res = coap_iterate_uri_query(&pkt, &pos, key, sizeof(key), value, 3);
TEST_ASSERT_EQUAL_INT(-E2BIG, res);
res = coap_iterate_uri_query(&pkt, &pos, key, 3, value, sizeof(value));
TEST_ASSERT_EQUAL_INT(-E2BIG, res);
pos = NULL;
res = coap_iterate_uri_query(&pkt, &pos, key, sizeof(key), value, sizeof(value));
TEST_ASSERT_EQUAL_INT(2, res);
TEST_ASSERT_EQUAL_STRING("foo", key);
TEST_ASSERT_EQUAL_STRING("bar", value);
res = coap_iterate_uri_query(&pkt, &pos, key, sizeof(key), value, sizeof(value));
TEST_ASSERT_EQUAL_INT(2, res);
TEST_ASSERT_EQUAL_STRING("baz", key);
TEST_ASSERT_EQUAL_STRING("blub", value);
res = coap_iterate_uri_query(&pkt, &pos, key, sizeof(key), value, sizeof(value));
TEST_ASSERT_EQUAL_INT(0, res);
}
/*
@ -347,10 +368,12 @@ static void test_nanocoap__get_multi_query(void)
coap_pkt_t pkt;
uint16_t msgid = 0xABCD;
uint8_t token[2] = {0xDA, 0xEC};
char key1[] = "ab";
char val1[] = "cde";
char key2[] = "f";
char qs[] = "ab=cde&f";
const char key1[] = "ab";
const char val1[] = "cde";
const char key2[] = "f";
const char qs[] = "ab=cde&f";
char key[8];
char value[8];
size_t len = coap_build_hdr((coap_hdr_t *)&buf[0], COAP_TYPE_NON,
&token[0], 2, COAP_METHOD_GET, msgid);
@ -386,6 +409,18 @@ static void test_nanocoap__get_multi_query(void)
TEST_ASSERT_EQUAL_INT((uintptr_t)NULL, (uintptr_t)val);
TEST_ASSERT(!coap_find_uri_query(&pkt, "cde", &val, &val_len));
TEST_ASSERT(coap_find_uri_query(&pkt, "ab", NULL, 0));
void *pos = NULL;
int res = coap_iterate_uri_query(&pkt, &pos, key, sizeof(key), value, sizeof(value));
TEST_ASSERT_EQUAL_INT(2, res);
TEST_ASSERT_EQUAL_STRING("ab", key);
TEST_ASSERT_EQUAL_STRING("cde", value);
res = coap_iterate_uri_query(&pkt, &pos, key, sizeof(key), value, sizeof(value));
TEST_ASSERT_EQUAL_INT(1, res);
TEST_ASSERT_EQUAL_STRING("f", key);
TEST_ASSERT_EQUAL_STRING("", value);
res = coap_iterate_uri_query(&pkt, &pos, key, sizeof(key), value, sizeof(value));
TEST_ASSERT_EQUAL_INT(0, res);
}
/*