mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
net/nanocoap: improve option handling
- add generic string put and get functions - add location path and location query options - add dedicated functions for getting and setting URI query, URI path, location query, and location path options
This commit is contained in:
parent
daf2532c7d
commit
4c08e77d00
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2016-17 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* 2018 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -18,6 +19,7 @@
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @author Ken Bannister <kb2ma@runbox.com>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NET_NANOCOAP_H
|
||||
@ -63,9 +65,11 @@ extern "C" {
|
||||
*/
|
||||
#define COAP_OPT_URI_HOST (3)
|
||||
#define COAP_OPT_OBSERVE (6)
|
||||
#define COAP_OPT_LOCATION_PATH (8)
|
||||
#define COAP_OPT_URI_PATH (11)
|
||||
#define COAP_OPT_CONTENT_FORMAT (12)
|
||||
#define COAP_OPT_URI_QUERY (15)
|
||||
#define COAP_OPT_LOCATION_QUERY (20)
|
||||
#define COAP_OPT_BLOCK2 (23)
|
||||
#define COAP_OPT_BLOCK1 (27)
|
||||
/** @} */
|
||||
@ -450,17 +454,87 @@ size_t coap_put_option(uint8_t *buf, uint16_t lastonum, uint16_t onum, uint8_t *
|
||||
size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, uint16_t content_type);
|
||||
|
||||
/**
|
||||
* @brief Insert URI encoded option into buffer
|
||||
* @brief Encode the given string as multi-part option into buffer
|
||||
*
|
||||
* @param[out] buf buffer to write to
|
||||
* @param[in] lastonum number of previous option (for delta calculation),
|
||||
* or 0 if first option
|
||||
* @param[in] optnum option number to use
|
||||
* @param[in] string string to encode as option
|
||||
* @param[in] separator character used in @p string to separate parts
|
||||
*
|
||||
* @return number of bytes written to @p buf
|
||||
*/
|
||||
size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum,
|
||||
const char *string, char separator);
|
||||
|
||||
/**
|
||||
* @brief Convenience function for inserting URI_PATH option into buffer
|
||||
*
|
||||
* @param[out] buf buffer to write to
|
||||
* @param[in] lastonum number of previous option (for delta calculation),
|
||||
* or 0 if first option
|
||||
* @param[in] uri ptr to source URI
|
||||
* @param[in] optnum option number to use (e.g., COAP_OPT_URI_PATH)
|
||||
*
|
||||
* @returns amount of bytes written to @p buf
|
||||
*/
|
||||
size_t coap_put_option_uri(uint8_t *buf, uint16_t lastonum, const char *uri, uint16_t optnum);
|
||||
static inline size_t coap_opt_put_uri_path(uint8_t *buf, uint16_t lastonum,
|
||||
const char *uri)
|
||||
{
|
||||
return coap_opt_put_string(buf, lastonum, COAP_OPT_URI_PATH, uri, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convenience function for inserting URI_QUERY option into buffer
|
||||
*
|
||||
* @param[out] buf buffer to write to
|
||||
* @param[in] lastonum number of previous option (for delta calculation),
|
||||
* or 0 if first option
|
||||
* @param[in] uri ptr to source URI
|
||||
*
|
||||
* @returns amount of bytes written to @p buf
|
||||
*/
|
||||
static inline size_t coap_opt_put_uri_query(uint8_t *buf, uint16_t lastonum,
|
||||
const char *uri)
|
||||
{
|
||||
return coap_opt_put_string(buf, lastonum, COAP_OPT_URI_QUERY, uri, '&');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convenience function for inserting LOCATION_PATH option into buffer
|
||||
*
|
||||
* @param[out] buf buffer to write to
|
||||
* @param[in] lastonum number of previous option (for delta calculation),
|
||||
* or 0 if first option
|
||||
* @param[in] location ptr to string holding the location
|
||||
*
|
||||
* @returns amount of bytes written to @p buf
|
||||
*/
|
||||
static inline size_t coap_opt_put_location_path(uint8_t *buf,
|
||||
uint16_t lastonum,
|
||||
const char *location)
|
||||
{
|
||||
return coap_opt_put_string(buf, lastonum, COAP_OPT_LOCATION_PATH,
|
||||
location, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convenience function for inserting LOCATION_QUERY option into buffer
|
||||
*
|
||||
* @param[out] buf buffer to write to
|
||||
* @param[in] lastonum number of previous option (for delta calculation),
|
||||
* or 0 if first option
|
||||
* @param[in] location ptr to string holding the location
|
||||
*
|
||||
* @returns amount of bytes written to @p buf
|
||||
*/
|
||||
static inline size_t coap_opt_put_location_query(uint8_t *buf,
|
||||
uint16_t lastonum,
|
||||
const char *location)
|
||||
{
|
||||
return coap_opt_put_string(buf, lastonum, COAP_OPT_LOCATION_QUERY,
|
||||
location, '&');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generic block option getter
|
||||
@ -585,10 +659,30 @@ ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags);
|
||||
unsigned coap_get_content_type(coap_pkt_t *pkt);
|
||||
|
||||
/**
|
||||
* @brief Get the packet's request URI
|
||||
* @brief Read a full option as null terminated string into the target buffer
|
||||
*
|
||||
* This function decodes the pkt's URI option into a "/"-seperated and
|
||||
* NULL-terminated string.
|
||||
* This function is for reading and concatenating string based, multi-part CoAP
|
||||
* options like COAP_OPT_URI_PATH or COAP_OPT_LOCATION_PATH. It will write all
|
||||
* parts of the given option into the target buffer, separating the parts using
|
||||
* the given @p separator. The resulting string is `\0` terminated.
|
||||
*
|
||||
* @param[in] pkt packet to read from
|
||||
* @param[in] optnum absolute option number
|
||||
* @param[out] target target buffer
|
||||
* @param[in] max_len size of @p target
|
||||
* @param[in] separator character used for separating the option parts
|
||||
*
|
||||
* @return -ENOSPC if the complete option does not fit into @p target
|
||||
* @return nr of bytes written to @p target (including '\0')
|
||||
*/
|
||||
ssize_t coap_opt_get_string(const coap_pkt_t *pkt, uint16_t optnum,
|
||||
uint8_t *target, size_t max_len, char separator);
|
||||
|
||||
/**
|
||||
* @brief Convenience function for getting the packet's URI_PATH
|
||||
*
|
||||
* This function decodes the pkt's URI option into a "/"-separated and
|
||||
* '\0'-terminated string.
|
||||
*
|
||||
* Caller must ensure @p target can hold at least NANOCOAP_URI_MAX bytes!
|
||||
*
|
||||
@ -598,7 +692,75 @@ unsigned coap_get_content_type(coap_pkt_t *pkt);
|
||||
* @returns -ENOSPC if URI option is larger than NANOCOAP_URI_MAX
|
||||
* @returns nr of bytes written to @p target (including '\0')
|
||||
*/
|
||||
int coap_get_uri(coap_pkt_t *pkt, uint8_t *target);
|
||||
static inline ssize_t coap_get_uri_path(const coap_pkt_t *pkt, uint8_t *target)
|
||||
{
|
||||
return coap_opt_get_string(pkt, COAP_OPT_URI_PATH, target,
|
||||
NANOCOAP_URI_MAX, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convenience function for getting the packet's URI_QUERY option
|
||||
*
|
||||
* This function decodes the pkt's URI_QUERY option into a "&"-separated and
|
||||
* '\0'-terminated string.
|
||||
*
|
||||
* Caller must ensure @p target can hold at least NANOCOAP_URI_MAX bytes!
|
||||
*
|
||||
* @param[in] pkt pkt to work on
|
||||
* @param[out] target buffer for target URI
|
||||
*
|
||||
* @returns -ENOSPC if URI option is larger than NANOCOAP_URI_MAX
|
||||
* @returns nr of bytes written to @p target (including '\0')
|
||||
*/
|
||||
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 Convenience function for getting the packet's LOCATION_PATH option
|
||||
*
|
||||
* This function decodes the pkt's LOCATION_PATH option into a '/'-separated and
|
||||
* '\0'-terminated string.
|
||||
*
|
||||
* Caller must ensure @p target can hold at least 2 bytes!
|
||||
*
|
||||
* @param[in] pkt pkt to work on
|
||||
* @param[out] target buffer for location path
|
||||
* @param[in] max_len size of @p target in bytes
|
||||
*
|
||||
* @returns -ENOSPC if URI option is larger than @p max_len
|
||||
* @returns nr of bytes written to @p target (including '\0')
|
||||
*/
|
||||
static inline ssize_t coap_get_location_path(const coap_pkt_t *pkt,
|
||||
uint8_t *target, size_t max_len)
|
||||
{
|
||||
return coap_opt_get_string(pkt, COAP_OPT_LOCATION_PATH,
|
||||
target, max_len, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convenience function for getting the packet's LOCATION_QUERY option
|
||||
*
|
||||
* This function decodes the pkt's LOCATION_PATH option into a '&'-separated and
|
||||
* '\0'-terminated string.
|
||||
*
|
||||
* Caller must ensure @p target can hold at least 2 bytes!
|
||||
*
|
||||
* @param[in] pkt pkt to work on
|
||||
* @param[out] target buffer for location path
|
||||
* @param[in] max_len size of @p target in bytes
|
||||
*
|
||||
* @returns -ENOSPC if URI option is larger than @p max_len
|
||||
* @returns nr of bytes written to @p target (including '\0')
|
||||
*/
|
||||
static inline ssize_t coap_get_location_query(const coap_pkt_t *pkt,
|
||||
uint8_t *target, size_t max_len)
|
||||
{
|
||||
return coap_opt_get_string(pkt, COAP_OPT_LOCATION_QUERY,
|
||||
target, max_len, '&');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper to decode SZX value to size in bytes
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2016-18 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* 2018 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -14,6 +15,7 @@
|
||||
* @brief Nanocoap implementation
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -117,7 +119,7 @@ int coap_parse(coap_pkt_t *pkt, uint8_t *buf, size_t len)
|
||||
}
|
||||
|
||||
#ifdef MODULE_GCOAP
|
||||
coap_get_uri(pkt, pkt->url);
|
||||
coap_get_uri_path(pkt, pkt->url);
|
||||
pkt->content_type = coap_get_content_type(pkt);
|
||||
|
||||
if (coap_get_option_uint(pkt, COAP_OPT_OBSERVE, &pkt->observe_value) != 0) {
|
||||
@ -133,9 +135,9 @@ int coap_parse(coap_pkt_t *pkt, uint8_t *buf, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *coap_find_option(coap_pkt_t *pkt, unsigned opt_num)
|
||||
uint8_t *coap_find_option(const coap_pkt_t *pkt, unsigned opt_num)
|
||||
{
|
||||
coap_optpos_t *optpos = pkt->options;
|
||||
const coap_optpos_t *optpos = pkt->options;
|
||||
unsigned opt_count = pkt->options_len;
|
||||
|
||||
while (opt_count--) {
|
||||
@ -147,7 +149,8 @@ uint8_t *coap_find_option(coap_pkt_t *pkt, unsigned opt_num)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint8_t *_parse_option(coap_pkt_t *pkt, uint8_t *pkt_pos, uint16_t *delta, int *opt_len)
|
||||
static uint8_t *_parse_option(const coap_pkt_t *pkt,
|
||||
uint8_t *pkt_pos, uint16_t *delta, int *opt_len)
|
||||
{
|
||||
uint8_t *hdr_end = pkt->payload;
|
||||
|
||||
@ -188,7 +191,8 @@ int coap_get_option_uint(coap_pkt_t *pkt, unsigned opt_num, uint32_t *target)
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *coap_iterate_option(coap_pkt_t *pkt, uint8_t **optpos, int *opt_len, int first)
|
||||
uint8_t *coap_iterate_option(const coap_pkt_t *pkt, uint8_t **optpos,
|
||||
int *opt_len, int first)
|
||||
{
|
||||
uint8_t *data_start;
|
||||
|
||||
@ -226,25 +230,29 @@ unsigned coap_get_content_type(coap_pkt_t *pkt)
|
||||
return content_type;
|
||||
}
|
||||
|
||||
int coap_get_uri(coap_pkt_t *pkt, uint8_t *target)
|
||||
ssize_t coap_opt_get_string(const coap_pkt_t *pkt, uint16_t optnum,
|
||||
uint8_t *target, size_t max_len, char separator)
|
||||
{
|
||||
uint8_t *opt_pos = coap_find_option(pkt, COAP_OPT_URI_PATH);
|
||||
assert(pkt && target && (max_len > 1));
|
||||
|
||||
uint8_t *opt_pos = coap_find_option(pkt, optnum);
|
||||
if (!opt_pos) {
|
||||
*target++ = '/';
|
||||
*target++ = (uint8_t)separator;
|
||||
*target = '\0';
|
||||
return 2;
|
||||
}
|
||||
|
||||
unsigned left = NANOCOAP_URI_MAX - 1;
|
||||
unsigned left = max_len - 1;
|
||||
uint8_t *part_start = NULL;
|
||||
do {
|
||||
int opt_len;
|
||||
part_start = coap_iterate_option(pkt, &opt_pos, &opt_len, part_start==NULL);
|
||||
part_start = coap_iterate_option(pkt, &opt_pos, &opt_len,
|
||||
(part_start == NULL));
|
||||
if (part_start) {
|
||||
if (left < (unsigned)(opt_len + 1)) {
|
||||
return -ENOSPC;
|
||||
}
|
||||
*target++ = '/';
|
||||
*target++ = (uint8_t)separator;
|
||||
memcpy(target, part_start, opt_len);
|
||||
target += opt_len;
|
||||
left -= (opt_len + 1);
|
||||
@ -253,7 +261,7 @@ int coap_get_uri(coap_pkt_t *pkt, uint8_t *target)
|
||||
|
||||
*target = '\0';
|
||||
|
||||
return NANOCOAP_URI_MAX - left;
|
||||
return (int)(max_len - left);
|
||||
}
|
||||
|
||||
int coap_get_blockopt(coap_pkt_t *pkt, uint16_t option, uint32_t *blknum, unsigned *szx)
|
||||
@ -296,7 +304,7 @@ ssize_t coap_handle_req(coap_pkt_t *pkt, uint8_t *resp_buf, unsigned resp_buf_le
|
||||
uint8_t *uri = pkt->url;
|
||||
#else
|
||||
uint8_t uri[NANOCOAP_URI_MAX];
|
||||
if (coap_get_uri(pkt, uri) <= 0) {
|
||||
if (coap_get_uri_path(pkt, uri) <= 0) {
|
||||
return -EBADMSG;
|
||||
}
|
||||
#endif
|
||||
@ -569,24 +577,24 @@ size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t last
|
||||
}
|
||||
}
|
||||
|
||||
size_t coap_put_option_uri(uint8_t *buf, uint16_t lastonum, const char *uri, uint16_t optnum)
|
||||
size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum,
|
||||
const char *string, char separator)
|
||||
{
|
||||
char separator = (optnum == COAP_OPT_URI_PATH) ? '/' : '&';
|
||||
size_t uri_len = strlen(uri);
|
||||
size_t len = strlen(string);
|
||||
|
||||
if (uri_len == 0) {
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *bufpos = buf;
|
||||
char *uripos = (char *)uri;
|
||||
char *uripos = (char *)string;
|
||||
|
||||
while (uri_len) {
|
||||
while (len) {
|
||||
size_t part_len;
|
||||
uripos++;
|
||||
uint8_t *part_start = (uint8_t *)uripos;
|
||||
|
||||
while (uri_len--) {
|
||||
while (len--) {
|
||||
if ((*uripos == separator) || (*uripos == '\0')) {
|
||||
break;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ ssize_t nanocoap_get(sock_udp_ep_t *remote, const char *path, uint8_t *buf, size
|
||||
|
||||
pkt.hdr = (coap_hdr_t*)buf;
|
||||
pktpos += coap_build_hdr(pkt.hdr, COAP_REQ, NULL, 0, COAP_METHOD_GET, 1);
|
||||
pktpos += coap_put_option_uri(pktpos, 0, path, COAP_OPT_URI_PATH);
|
||||
pktpos += coap_opt_put_uri_path(pktpos, 0, path);
|
||||
pkt.payload = pktpos;
|
||||
pkt.payload_len = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user