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 all 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
28 changes: 27 additions & 1 deletion sys/include/net/nanocoap.h
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,32 @@ 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 Iterate over a packet's options
*
* This function is for accessing arbitrary options in a message in sequence.
* 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.
*
* The caller must provide a zeroed-out *opt to start iterating, and pass the
* same opt to subsequent calls. The function will, on each invocation, set
* *start to point to the beginning of the next option, and return the
* to-be-read length. The caller can read that option's number from
* opt.opt_num, and must ignore opt.offset.
*
* The end of the options is indicated by *start having a value of NULL; the
* return value is unspecified in that case.
*
* @param[in] pkt packet to read from
* @param[in,out] opt iteration counter
* @param[out] start pointer to the start of the option value
*
* @return number of bytes available at @p start
*/
size_t coap_opt_get_next(const coap_pkt_t *pkt, coap_optpos_t *opt,
uint8_t **start);

/**
* @brief Read a full option as null terminated string into the target buffer
*
Expand Down Expand Up @@ -975,7 +1001,7 @@ static inline unsigned coap_get_type(coap_pkt_t *pkt)
*
* @returns length of token in the given message (0-8 byte)
*/
static inline unsigned coap_get_token_len(coap_pkt_t *pkt)
static inline unsigned coap_get_token_len(const coap_pkt_t *pkt)
{
return (pkt->hdr->ver_t_tkl & 0xf);
}
Expand Down
22 changes: 22 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,28 @@ unsigned coap_get_content_type(coap_pkt_t *pkt)
return content_type;
}

size_t coap_opt_get_next(const coap_pkt_t *pkt, coap_optpos_t *opt,
uint8_t **start)
{
uint8_t *opt_pos = (uint8_t*)pkt->hdr + (opt->offset == 0 ? sizeof(coap_hdr_t) + coap_get_token_len(pkt) : opt->offset);
int opt_len = -1;
uint16_t delta;

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

if (opt_len >= 0) {
opt->opt_num += delta;
opt->offset = *start + opt_len - (uint8_t*)pkt->hdr;
return opt_len;
} else {
// Terminal condition that can either be caused by reaching the end of
// the options (if there is no payload marker), or by reaching the
// payload marker
*start = 0;
return 0;
}
}

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
40 changes: 40 additions & 0 deletions tests/nanocoap_cli/request_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,49 @@ 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];

uint8_t *start;
size_t length;
coap_optpos_t cursor = {0};
while (1) {
length = coap_opt_get_next(pkt, &cursor, &start);
if (start == NULL) {
break;
}

p += snprintf(&rsp[p], sizeof(rsp) - p, "%d: ", cursor.opt_num);
if ((size_t)p >= sizeof(rsp))
goto error;

for (size_t j = 0; j < length; ++j) {
p += snprintf(&rsp[p], sizeof(rsp) - p, "%02x", start[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 | COAP_POST, _reqopts_handler, NULL },
{ "/value", COAP_GET | COAP_PUT | COAP_POST, _value_handler, NULL },
};

Expand Down