Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nanocoap: Allow accessing opaque and other written options #11437

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions sys/include/net/nanocoap.h
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,27 @@ size_t coap_opt_put_block2(uint8_t *buf, uint16_t lastonum, coap_block_slicer_t
*/
unsigned coap_get_content_type(coap_pkt_t *pkt);

/**
* @brief Access an option by its struct offset
*
* This function is for accessing arbitrary options in a message that was
* received, or was built using the struct-based API. It is useful for reading
* opaque options, updating values after they have been added (e.g. putting a
* value into a pre-allocated ETag after the payload was calculate), and when
* iterating over a message's options.
*
* It is up to the caller to ensure that optnum is valid, i.e. that `0 <= optnum
* < pkt->options_len`.
*
* @param[in] pkt packet to read from
* @param[in] index absolute option number
* @param[out] start pointer to the start of the option value
*
* @return number of bytes available at @p start
*/
size_t coap_opt_by_index(const coap_pkt_t *pkt, uint16_t index,
uint8_t **start);

/**
* @brief Read a full option as null terminated string into the target buffer
*
Expand Down
15 changes: 15 additions & 0 deletions sys/net/application_layer/nanocoap/nanocoap.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,21 @@ unsigned coap_get_content_type(coap_pkt_t *pkt)
return content_type;
}

size_t coap_opt_by_index(const coap_pkt_t *pkt, uint16_t index,
uint8_t **start)
{
assert(pkt && index < pkt->options_len);

const coap_optpos_t *optslot = &pkt->options[index];
uint8_t *opt_pos = (uint8_t*)pkt->hdr + optslot->offset;
int opt_len;
uint16_t delta;

*start = _parse_option(pkt, opt_pos, &delta, &opt_len);

return opt_len;
}

ssize_t coap_opt_get_string(const coap_pkt_t *pkt, uint16_t optnum,
uint8_t *target, size_t max_len, char separator)
{
Expand Down
3 changes: 3 additions & 0 deletions tests/nanocoap_cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ which to listen. Provides these resources:
`/value`<br>
Reads/Writes an unsigned 8-bit integer.

`/req-opts`<br>
Hex-dumps all options in the request message into a response.

`/.well-known/core`<br>
Reads the list of resources. Expects a block2 based request or else returns at
most the first 16 bytes of the list.
Expand Down
34 changes: 34 additions & 0 deletions tests/nanocoap_cli/request_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,43 @@ static ssize_t _value_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *c
COAP_FORMAT_TEXT, (uint8_t*)rsp, p);
}

static ssize_t _reqopts_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
{
(void) context;

ssize_t p = 0;
char rsp[128];

for (uint16_t i = 0; i < pkt->options_len; ++i) {
uint16_t optnum = pkt->options[i].opt_num;
p += snprintf(&rsp[p], sizeof(rsp) - p, "%d: ", optnum);
if ((size_t)p >= sizeof(rsp))
goto error;
uint8_t *optcursor;
size_t length = coap_opt_by_index(pkt, i, &optcursor);
for (size_t j = 0; j < length; ++j) {
p += snprintf(&rsp[p], sizeof(rsp) - p, "%02x", optcursor[j]);
if ((size_t)p >= sizeof(rsp))
goto error;
}
p += snprintf(&rsp[p], sizeof(rsp) - p, "\n");
if ((size_t)p >= sizeof(rsp))
goto error;
}

return coap_reply_simple(pkt, COAP_CODE_205, buf, len,
COAP_FORMAT_TEXT, (uint8_t*)rsp, p);

error:
rsp[sizeof(rsp) - 1] = '_';
return coap_reply_simple(pkt, COAP_CODE_205, buf, len,
COAP_FORMAT_TEXT, (uint8_t*)rsp, sizeof(rsp));
}

/* must be sorted by path (ASCII order) */
const coap_resource_t coap_resources[] = {
COAP_WELL_KNOWN_CORE_DEFAULT_HANDLER,
{ "/req-opts", COAP_GET, _reqopts_handler, NULL },
{ "/value", COAP_GET | COAP_PUT | COAP_POST, _value_handler, NULL },
};

Expand Down