Skip to content
Merged
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
178 changes: 170 additions & 8 deletions sys/include/net/nanocoap.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016-17 Kaspar Schleiser <[email protected]>
* 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
Expand All @@ -18,6 +19,7 @@
*
* @author Kaspar Schleiser <[email protected]>
* @author Ken Bannister <[email protected]>
* @author Hauke Petersen <[email protected]>
*/

#ifndef NET_NANOCOAP_H
Expand Down Expand Up @@ -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)
/** @} */
Expand Down Expand Up @@ -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
*
* @returns amount of bytes written to @p buf
*/
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
* @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_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
Expand Down Expand Up @@ -585,10 +659,50 @@ 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!
*
* @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_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!
*
Expand All @@ -598,10 +712,58 @@ 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_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
* @brief Helper to decode SZX value to size in bytes
*
* @param[in] szx SZX value to decode
*
Expand Down
8 changes: 4 additions & 4 deletions sys/net/application_layer/gcoap/gcoap.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,8 @@ static ssize_t _write_options(coap_pkt_t *pdu, uint8_t *buf, size_t len)
DEBUG("gcoap: _write_options: path does not start with '/'\n");
return -EINVAL;
}
bufpos += coap_put_option_uri(bufpos, last_optnum, (char *)pdu->url,
COAP_OPT_URI_PATH);
bufpos += coap_opt_put_uri_path(bufpos, last_optnum,
(char *)pdu->url);
last_optnum = COAP_OPT_URI_PATH;
}
}
Expand All @@ -578,8 +578,8 @@ static ssize_t _write_options(coap_pkt_t *pdu, uint8_t *buf, size_t len)

/* Uri-query for requests */
if (coap_get_code_class(pdu) == COAP_CLASS_REQ) {
bufpos += coap_put_option_uri(bufpos, last_optnum, (char *)pdu->qs,
COAP_OPT_URI_QUERY);
bufpos += coap_opt_put_uri_query(bufpos, last_optnum,
(char *)pdu->qs);
/* uncomment when further options are added below ... */
/* last_optnum = COAP_OPT_URI_QUERY; */
}
Expand Down
48 changes: 28 additions & 20 deletions sys/net/application_layer/nanocoap/nanocoap.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016-18 Kaspar Schleiser <[email protected]>
* 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
Expand All @@ -14,6 +15,7 @@
* @brief Nanocoap implementation
*
* @author Kaspar Schleiser <[email protected]>
* @author Hauke Petersen <[email protected]>
*
* @}
*/
Expand Down Expand Up @@ -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) {
Expand All @@ -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--) {
Expand All @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down
Loading