diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index 415df82314..9078d1a504 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -530,6 +530,38 @@ static inline ssize_t coap_get_uri_query(const coap_pkt_t *pkt, uint8_t *target) return coap_opt_get_string(pkt, COAP_OPT_URI_QUERY, target, NANOCOAP_URI_MAX, '&'); } + +/** + * @brief Iterate over a packet's options + * + * To start iteration from the first option, set @p init_opt to true. To start + * iteration from a specific option, set @p init_opt to false, set + * @p opt->offset to the offset of the desired option from pkt->hdr, and + * @p opt->opt_num as required. See below for how @p opt->opt_num is modified. + * + * With each invocation, this function returns the length of the option value + * and sets @p value to point to the start of the value. The value for + * @p opt->opt_num is increased by the delta in the option number value over + * the preceding option in the packet. So, @p opt->opt_num is accurate if + * iteration started with the first option. Otherwise, it is useful for + * identification of repeated options. Finally, @p opt->offset is set to the + * offset for any following option, to prepare for the next iteration. + * + * The end of the options is indicated by a -ENOENT return value. In this case + * @p value and @p opt are unchanged from their input values. + * + * @param[in] pkt packet to read from + * @param[in,out] opt option attributes; read on input if @p init_opt + * is false + * @param[out] value start of the option value + * @param[in] init_opt true to retrieve first option; false to retrieve + * option at opt->offset + * + * @return length of option value + * @return -ENOENT if option not found + */ +ssize_t coap_opt_get_next(const coap_pkt_t *pkt, coap_optpos_t *opt, + uint8_t **value, bool init_opt); /**@}*/ diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index 46c5e3bbcb..aa5bf1fe86 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -269,6 +269,30 @@ unsigned coap_get_content_type(coap_pkt_t *pkt) return content_type; } +ssize_t coap_opt_get_next(const coap_pkt_t *pkt, coap_optpos_t *opt, + uint8_t **value, bool init_opt) +{ + if (init_opt) { + opt->opt_num = 0; + opt->offset = coap_get_total_hdr_len(pkt); + } + uint8_t *start = (uint8_t*)pkt->hdr + opt->offset; + + /* Find start of option value and value length. */ + uint16_t delta; + int len; + + start = _parse_option(pkt, start, &delta, &len); + if (!start) { + return -ENOENT; + } + + *value = start; + opt->opt_num += delta; + opt->offset = start + len - (uint8_t*)pkt->hdr; + return len; +} + ssize_t coap_opt_get_string(const coap_pkt_t *pkt, uint16_t optnum, uint8_t *target, size_t max_len, char separator) {