Skip to content
Snippets Groups Projects
Commit 43db2715 authored by Ken Bannister's avatar Ken Bannister
Browse files

net/nanocoap: create pkt-based request

Includes string and uint options.
parent fd1a987b
No related branches found
No related tags found
No related merge requests found
......@@ -17,6 +17,7 @@
* @brief nanocoap API
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Ken Bannister <kb2ma@runbox.com>
*/
#ifndef NET_NANOCOAP_H
......@@ -224,6 +225,18 @@ extern "C" {
#define COAP_BLOCKWISE_SZX_MAX (7)
/** @} */
/**
* @name coap_opt_finish() flag parameter values
*
* Directs packet/buffer updates when user finishes adding options
* @{
*/
/** @brief no special handling required */
#define COAP_OPT_FINISH_NONE (0x0000)
/** @brief expect a payload to follow */
#define COAP_OPT_FINISH_PAYLOAD (0x0001)
/** @} */
/**
* @brief Raw CoAP PDU header structure
*/
......@@ -390,6 +403,22 @@ ssize_t coap_handle_req(coap_pkt_t *pkt, uint8_t *resp_buf, unsigned resp_buf_le
ssize_t coap_build_hdr(coap_hdr_t *hdr, unsigned type, uint8_t *token,
size_t token_len, unsigned code, uint16_t id);
/**
* @brief Initialize a packet struct, to build a message buffer
*
* @pre buf CoAP header already initialized
* @post pkt.flags all zeroed
* @post pkt.payload points to first byte after header
* @post pkt.payload_len set to maximum space available for options + payload
*
* @param[out] pkt pkt to initialize
* @param[in] buf buffer to write for pkt, with CoAP header already
* initialized
* @param[in] len length of buf
* @param[in] header_len length of header in buf, including token
*/
void coap_pkt_init(coap_pkt_t *pkt, uint8_t *buf, size_t len, size_t header_len);
/**
* @brief Insert a CoAP option into buffer
*
......@@ -499,6 +528,52 @@ size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum,
*/
size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t lastonum);
/**
* @brief Encode the given string as option(s) into pkt
*
* Use separator to split string into multiple options.
*
* @post pkt.payload advanced to first byte after option(s)
* @post pkt.payload_len reduced by option(s) length
*
* @param[in,out] pkt pkt referencing target buffer
* @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 buffer
* @return -ENOSPC if no available options
*/
ssize_t coap_opt_add_string(coap_pkt_t *pkt, uint16_t optnum, const char *string, char separator);
/**
* @brief Encode the given uint option into pkt
*
* @post pkt.payload advanced to first byte after option
* @post pkt.payload_len reduced by option length
*
* @param[in,out] pkt pkt referencing target buffer
* @param[in] optnum option number to use
* @param[in] value uint to encode
*
* @return number of bytes written to buffer
* @return <0 reserved for error but not implemented yet
*/
ssize_t coap_opt_add_uint(coap_pkt_t *pkt, uint16_t optnum, uint32_t value);
/**
* @brief Finalizes options as required and prepares for payload
*
* @post pkt.payload advanced to first available byte after options
* @post pkt.payload_len is maximum bytes available for payload
*
* @param[in,out] pkt pkt to update
* @param[in] flags see COAP_OPT_FINISH... macros
*
* @return total number of bytes written to buffer
*/
ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags);
/**
* @brief Get content type from packet
*
......
......@@ -383,6 +383,15 @@ ssize_t coap_build_hdr(coap_hdr_t *hdr, unsigned type, uint8_t *token, size_t to
return sizeof(coap_hdr_t) + token_len;
}
void coap_pkt_init(coap_pkt_t *pkt, uint8_t *buf, size_t len, size_t header_len)
{
memset(pkt, 0, sizeof(coap_pkt_t));
pkt->hdr = (coap_hdr_t *)buf;
pkt->token = buf + sizeof(coap_hdr_t);
pkt->payload = buf + header_len;
pkt->payload_len = len - header_len;
}
static int _decode_value(unsigned val, uint8_t **pkt_pos_ptr, uint8_t *pkt_end)
{
uint8_t *pkt_pos = *pkt_pos_ptr;
......@@ -595,6 +604,85 @@ size_t coap_put_option_uri(uint8_t *buf, uint16_t lastonum, const char *uri, uin
return bufpos - buf;
}
/* Common functionality for addition of an option */
static ssize_t _add_opt_pkt(coap_pkt_t *pkt, uint16_t optnum, uint8_t *val,
size_t val_len)
{
assert(pkt->options_len < NANOCOAP_NOPTS_MAX);
uint16_t lastonum = (pkt->options_len)
? pkt->options[pkt->options_len - 1].opt_num : 0;
assert(optnum >= lastonum);
size_t optlen = coap_put_option(pkt->payload, lastonum, optnum, val, val_len);
assert(pkt->payload_len > optlen);
pkt->options[pkt->options_len].opt_num = optnum;
pkt->options[pkt->options_len].offset = pkt->payload - (uint8_t *)pkt->hdr;
pkt->options_len++;
pkt->payload += optlen;
pkt->payload_len -= optlen;
return optlen;
}
ssize_t coap_opt_add_string(coap_pkt_t *pkt, uint16_t optnum, const char *string,
char separator)
{
size_t unread_len = strlen(string);
if (!unread_len) {
return 0;
}
char *uripos = (char *)string;
size_t write_len = 0;
while (unread_len) {
size_t part_len;
uripos++;
uint8_t *part_start = (uint8_t *)uripos;
while (unread_len--) {
if ((*uripos == separator) || (*uripos == '\0')) {
break;
}
uripos++;
}
part_len = (uint8_t *)uripos - part_start;
if (part_len) {
if (pkt->options_len == NANOCOAP_NOPTS_MAX) {
return -ENOSPC;
}
write_len += _add_opt_pkt(pkt, optnum, part_start, part_len);
}
}
return write_len;
}
ssize_t coap_opt_add_uint(coap_pkt_t *pkt, uint16_t optnum, uint32_t value)
{
uint32_t tmp = value;
unsigned tmp_len = _encode_uint(&tmp);
return _add_opt_pkt(pkt, optnum, (uint8_t *)&tmp, tmp_len);
}
ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags)
{
if (flags & COAP_OPT_FINISH_PAYLOAD) {
assert(pkt->payload_len > 1);
*pkt->payload++ = 0xFF;
pkt->payload_len--;
}
else {
pkt->payload_len = 0;
}
return pkt->payload - (uint8_t *)pkt->hdr;
}
ssize_t coap_well_known_core_default_handler(coap_pkt_t *pkt, uint8_t *buf, \
size_t len, void *context)
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment