Merge pull request #8932 from bergzand/pr/nanocoap/block2
nanocoap: add server-side block2 support
This commit is contained in:
commit
14c9b3062b
@ -11,7 +11,7 @@ BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-mega2560 arduino-uno \
|
|||||||
chronos msb-430 msb-430h nucleo-f031k6 \
|
chronos msb-430 msb-430h nucleo-f031k6 \
|
||||||
nucleo-f042k6 nucleo-l031k6 nucleo-f030r8 \
|
nucleo-f042k6 nucleo-l031k6 nucleo-f030r8 \
|
||||||
nucleo-f303k8 nucleo-l053r8 stm32f0discovery \
|
nucleo-f303k8 nucleo-l053r8 stm32f0discovery \
|
||||||
telosb waspmote-pro z1
|
telosb waspmote-pro wsn430-v1_3b wsn430-v1_4 z1
|
||||||
|
|
||||||
# Include packages that pull up and auto-init the link layer.
|
# Include packages that pull up and auto-init the link layer.
|
||||||
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
|
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
|
||||||
|
|||||||
@ -17,6 +17,10 @@
|
|||||||
/* internal value that can be read/written via CoAP */
|
/* internal value that can be read/written via CoAP */
|
||||||
static uint8_t internal_value = 0;
|
static uint8_t internal_value = 0;
|
||||||
|
|
||||||
|
static const uint8_t block2_intro[] = "This is RIOT (Version: ";
|
||||||
|
static const uint8_t block2_board[] = " running on a ";
|
||||||
|
static const uint8_t block2_mcu[] = " board with a ";
|
||||||
|
|
||||||
static ssize_t _riot_board_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
|
static ssize_t _riot_board_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
|
||||||
{
|
{
|
||||||
(void)context;
|
(void)context;
|
||||||
@ -24,6 +28,40 @@ static ssize_t _riot_board_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, vo
|
|||||||
COAP_FORMAT_TEXT, (uint8_t*)RIOT_BOARD, strlen(RIOT_BOARD));
|
COAP_FORMAT_TEXT, (uint8_t*)RIOT_BOARD, strlen(RIOT_BOARD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t _riot_block2_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
|
||||||
|
{
|
||||||
|
(void)context;
|
||||||
|
coap_block_slicer_t slicer;
|
||||||
|
coap_block2_init(pkt, &slicer);
|
||||||
|
uint8_t *payload = buf + coap_get_total_hdr_len(pkt);
|
||||||
|
|
||||||
|
uint8_t *bufpos = payload;
|
||||||
|
|
||||||
|
bufpos += coap_put_option_ct(bufpos, 0, COAP_FORMAT_TEXT);
|
||||||
|
bufpos += coap_opt_put_block2(bufpos, COAP_OPT_CONTENT_FORMAT, &slicer, 1);
|
||||||
|
*bufpos++ = 0xff;
|
||||||
|
|
||||||
|
/* Add actual content */
|
||||||
|
bufpos += coap_blockwise_put_bytes(&slicer, bufpos, block2_intro, sizeof(block2_intro));
|
||||||
|
bufpos += coap_blockwise_put_bytes(&slicer, bufpos, (uint8_t*)RIOT_VERSION, sizeof(RIOT_VERSION));
|
||||||
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, ')');
|
||||||
|
bufpos += coap_blockwise_put_bytes(&slicer, bufpos, block2_board, sizeof(block2_board));
|
||||||
|
bufpos += coap_blockwise_put_bytes(&slicer, bufpos, (uint8_t*)RIOT_BOARD, sizeof(RIOT_BOARD));
|
||||||
|
bufpos += coap_blockwise_put_bytes(&slicer, bufpos, block2_mcu, sizeof(block2_mcu));
|
||||||
|
bufpos += coap_blockwise_put_bytes(&slicer, bufpos, (uint8_t*)RIOT_MCU, sizeof(RIOT_MCU));
|
||||||
|
/* To demonstrate individual chars */
|
||||||
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, ' ');
|
||||||
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, 'M');
|
||||||
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, 'C');
|
||||||
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, 'U');
|
||||||
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, '.');
|
||||||
|
|
||||||
|
|
||||||
|
unsigned payload_len = bufpos - payload;
|
||||||
|
return coap_block2_build_reply(pkt, COAP_CODE_205,
|
||||||
|
buf, len, payload_len, &slicer);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t _riot_value_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
|
static ssize_t _riot_value_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
|
||||||
{
|
{
|
||||||
(void) context;
|
(void) context;
|
||||||
@ -109,6 +147,7 @@ const coap_resource_t coap_resources[] = {
|
|||||||
COAP_WELL_KNOWN_CORE_DEFAULT_HANDLER,
|
COAP_WELL_KNOWN_CORE_DEFAULT_HANDLER,
|
||||||
{ "/riot/board", COAP_GET, _riot_board_handler, NULL },
|
{ "/riot/board", COAP_GET, _riot_board_handler, NULL },
|
||||||
{ "/riot/value", COAP_GET | COAP_PUT | COAP_POST, _riot_value_handler, NULL },
|
{ "/riot/value", COAP_GET | COAP_PUT | COAP_POST, _riot_value_handler, NULL },
|
||||||
|
{ "/riot/ver", COAP_GET, _riot_block2_handler, NULL },
|
||||||
{ "/sha256", COAP_POST, _sha256_handler, NULL },
|
{ "/sha256", COAP_POST, _sha256_handler, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,31 @@
|
|||||||
* @ingroup net
|
* @ingroup net
|
||||||
* @brief Provides CoAP functionality optimized for minimal resource usage
|
* @brief Provides CoAP functionality optimized for minimal resource usage
|
||||||
*
|
*
|
||||||
|
* # Create a Block-wise Response (Block2)
|
||||||
|
*
|
||||||
|
* Block-wise is a CoAP extension (RFC 7959) to divide a large payload across
|
||||||
|
* multiple physical packets. This section describes how to write a block-wise
|
||||||
|
* payload for a response, and is known as Block2. (Block1 is for a block-wise
|
||||||
|
* payload in a request.) See _riot_board_handler() in the nanocoap_server
|
||||||
|
* example for an example handler implementation.
|
||||||
|
*
|
||||||
|
* Start with coap_block2_init() to read the client request and initialize a
|
||||||
|
* coap_slicer_t struct with the size and location for this slice of the
|
||||||
|
* overall payload. Then write the block2 option in the response with
|
||||||
|
* coap_opt_put_block2(). The option includes an indicator ("more") that a
|
||||||
|
* slice completes the overall payload transfer. You may not know the value for
|
||||||
|
* _more_ at this point, but you must initialize the space in the packet for
|
||||||
|
* the option before writing the payload. The option is rewritten later.
|
||||||
|
*
|
||||||
|
* Next, use the coap_blockwise_put_xxx() functions to write the payload
|
||||||
|
* content. These functions use the coap_block_slicer_t to enable or disable
|
||||||
|
* actually writing the content, depending on the current position within the
|
||||||
|
* overall payload transfer.
|
||||||
|
*
|
||||||
|
* Finally, use the convenience function coap_block2_build_reply(), which
|
||||||
|
* finalizes the packet and calls coap_block2_finish() internally to update
|
||||||
|
* the block2 option.
|
||||||
|
*
|
||||||
* @{
|
* @{
|
||||||
*
|
*
|
||||||
* @file
|
* @file
|
||||||
@ -64,6 +89,8 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define NANOCOAP_NOPTS_MAX (16)
|
#define NANOCOAP_NOPTS_MAX (16)
|
||||||
#define NANOCOAP_URI_MAX (64)
|
#define NANOCOAP_URI_MAX (64)
|
||||||
|
#define NANOCOAP_BLOCK_SIZE_EXP_MAX (6) /**< Maximum size for a blockwise
|
||||||
|
* transfer as power of 2 */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#ifdef MODULE_GCOAP
|
#ifdef MODULE_GCOAP
|
||||||
@ -145,6 +172,16 @@ typedef struct {
|
|||||||
1 for more blocks coming */
|
1 for more blocks coming */
|
||||||
} coap_block1_t;
|
} coap_block1_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Blockwise transfer helper struct
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
size_t start; /**< Start offset of the current block */
|
||||||
|
size_t end; /**< End offset of the current block */
|
||||||
|
size_t cur; /**< Offset of the generated content */
|
||||||
|
uint8_t *opt; /**< Pointer to the placed option */
|
||||||
|
} coap_block_slicer_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Global CoAP resource list
|
* @brief Global CoAP resource list
|
||||||
*/
|
*/
|
||||||
@ -411,6 +448,17 @@ int coap_get_blockopt(coap_pkt_t *pkt, uint16_t option, uint32_t *blknum, unsign
|
|||||||
*/
|
*/
|
||||||
int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1);
|
int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Block2 option getter
|
||||||
|
*
|
||||||
|
* @param[in] pkt pkt to work on
|
||||||
|
* @param[out] block2 ptr to preallocated coap_block1_t structure
|
||||||
|
*
|
||||||
|
* @returns 0 if block2 option not present
|
||||||
|
* @returns 1 if structure has been filled
|
||||||
|
*/
|
||||||
|
int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Insert block1 option into buffer
|
* @brief Insert block1 option into buffer
|
||||||
*
|
*
|
||||||
@ -490,6 +538,23 @@ ssize_t coap_opt_add_uint(coap_pkt_t *pkt, uint16_t optnum, uint32_t value);
|
|||||||
*/
|
*/
|
||||||
ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags);
|
ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Insert block2 option into buffer
|
||||||
|
*
|
||||||
|
* When calling this function to initialize a packet with a block2 option, the
|
||||||
|
* more flag must be set to prevent the creation of an option with a length too
|
||||||
|
* small to contain the size bit.
|
||||||
|
*
|
||||||
|
* @param[out] buf buffer to write to
|
||||||
|
* @param[in] lastonum number of previous option (for delta calculation),
|
||||||
|
* must be < 23
|
||||||
|
* @param[in] slicer coap blockwise slicer helper struct
|
||||||
|
* @param[in] more more flag (1 or 0)
|
||||||
|
*
|
||||||
|
* @returns amount of bytes written to @p buf
|
||||||
|
*/
|
||||||
|
size_t coap_opt_put_block2(uint8_t *buf, uint16_t lastonum, coap_block_slicer_t *slicer, bool more);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get content type from packet
|
* @brief Get content type from packet
|
||||||
*
|
*
|
||||||
@ -604,6 +669,83 @@ static inline ssize_t coap_get_location_query(const coap_pkt_t *pkt,
|
|||||||
target, max_len, '&');
|
target, max_len, '&');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a block2 slicer struct for writing the payload
|
||||||
|
*
|
||||||
|
* This function determines the size of the response payload based on the
|
||||||
|
* size requested by the client in @p pkt.
|
||||||
|
*
|
||||||
|
* @param[in] pkt packet to work on
|
||||||
|
* @param[out] slicer Preallocated slicer struct to fill
|
||||||
|
*/
|
||||||
|
void coap_block2_init(coap_pkt_t *pkt, coap_block_slicer_t *slicer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finish a block2 response
|
||||||
|
*
|
||||||
|
* This function finalizes the block2 response header
|
||||||
|
*
|
||||||
|
* Checks whether the `more` bit should be set in the block2 option and
|
||||||
|
* sets/clears it if required. Doesn't return the number of bytes as this
|
||||||
|
* overwrites bytes in the packet, it doesn't add new bytes to the packet.
|
||||||
|
*
|
||||||
|
* @param[inout] slicer Preallocated slicer struct to use
|
||||||
|
*/
|
||||||
|
void coap_block2_finish(coap_block_slicer_t *slicer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Build reply to CoAP block2 request
|
||||||
|
*
|
||||||
|
* This function can be used to create a reply to a CoAP block2 request
|
||||||
|
* packet. In addition to @ref coap_build_reply, this function checks the
|
||||||
|
* block2 option and returns an error message to the client if necessary.
|
||||||
|
*
|
||||||
|
* @param[in] pkt packet to reply to
|
||||||
|
* @param[in] code reply code (e.g., COAP_CODE_204)
|
||||||
|
* @param[out] rbuf buffer to write reply to
|
||||||
|
* @param[in] rlen size of @p rbuf
|
||||||
|
* @param[in] payload_len length of payload
|
||||||
|
* @param[in] slicer slicer to use
|
||||||
|
*
|
||||||
|
* @returns size of reply packet on success
|
||||||
|
* @returns <0 on error
|
||||||
|
*/
|
||||||
|
ssize_t coap_block2_build_reply(coap_pkt_t *pkt, unsigned code,
|
||||||
|
uint8_t *rbuf, unsigned rlen, unsigned payload_len,
|
||||||
|
coap_block_slicer_t *slicer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a single character to a block2 reply.
|
||||||
|
*
|
||||||
|
* This function is used to add single characters to a CoAP block2 reply. It
|
||||||
|
* checks whether the character should be added to the buffer and ignores it
|
||||||
|
* when the character is outside the current block2 request.
|
||||||
|
*
|
||||||
|
* @param[in] slicer slicer to use
|
||||||
|
* @param[in] bufpos pointer to the current payload buffer position
|
||||||
|
* @param[in] c character to write
|
||||||
|
*
|
||||||
|
* @returns Number of bytes writen to @p bufpos
|
||||||
|
*/
|
||||||
|
size_t coap_blockwise_put_char(coap_block_slicer_t *slicer, uint8_t *bufpos, char c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a byte array to a block2 reply.
|
||||||
|
*
|
||||||
|
* This function is used to add an array of bytes to a CoAP block2 reply. it
|
||||||
|
* checks which parts of the string should be added to the reply and ignores
|
||||||
|
* parts that are outside the current block2 request.
|
||||||
|
*
|
||||||
|
* @param[in] slicer slicer to use
|
||||||
|
* @param[in] bufpos pointer to the current payload buffer position
|
||||||
|
* @param[in] c byte array to copy
|
||||||
|
* @param[in] len length of the byte array
|
||||||
|
*
|
||||||
|
* @returns Number of bytes writen to @p bufpos
|
||||||
|
*/
|
||||||
|
size_t coap_blockwise_put_bytes(coap_block_slicer_t *slicer, uint8_t *bufpos,
|
||||||
|
const uint8_t *c, size_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper to decode SZX value to size in bytes
|
* @brief Helper to decode SZX value to size in bytes
|
||||||
*
|
*
|
||||||
|
|||||||
@ -546,11 +546,39 @@ size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, uint16_t content_type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned _size2szx(size_t size)
|
||||||
|
{
|
||||||
|
unsigned szx = 0;
|
||||||
|
assert(size <= 1024);
|
||||||
|
|
||||||
|
while (size) {
|
||||||
|
size = size >> 1;
|
||||||
|
szx++;
|
||||||
|
}
|
||||||
|
/* Size exponent + 1 */
|
||||||
|
assert(szx >= 5);
|
||||||
|
return szx - 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned _slicer_blknum(coap_block_slicer_t *slicer)
|
||||||
|
{
|
||||||
|
size_t blksize = slicer->end - slicer->start;
|
||||||
|
size_t start = slicer->start;
|
||||||
|
unsigned blknum = 0;
|
||||||
|
|
||||||
|
while (start > 0) {
|
||||||
|
start -= blksize;
|
||||||
|
blknum++;
|
||||||
|
}
|
||||||
|
return blknum;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t coap_put_option_block(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more, uint16_t option)
|
static size_t coap_put_option_block(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more, uint16_t option)
|
||||||
{
|
{
|
||||||
uint32_t blkopt = (blknum << 4) | szx | (more ? 0x8 : 0);
|
uint32_t blkopt = (blknum << 4) | szx | (more ? 0x8 : 0);
|
||||||
size_t olen = _encode_uint(&blkopt);
|
size_t olen = _encode_uint(&blkopt);
|
||||||
return coap_put_option(buf, lastonum, option, (uint8_t*)&blkopt, olen);
|
|
||||||
|
return coap_put_option(buf, lastonum, option, (uint8_t *)&blkopt, olen);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more)
|
size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more)
|
||||||
@ -562,6 +590,7 @@ int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1)
|
|||||||
{
|
{
|
||||||
uint32_t blknum;
|
uint32_t blknum;
|
||||||
unsigned szx;
|
unsigned szx;
|
||||||
|
|
||||||
block1->more = coap_get_blockopt(pkt, COAP_OPT_BLOCK1, &blknum, &szx);
|
block1->more = coap_get_blockopt(pkt, COAP_OPT_BLOCK1, &blknum, &szx);
|
||||||
if (block1->more >= 0) {
|
if (block1->more >= 0) {
|
||||||
block1->offset = blknum << (szx + 4);
|
block1->offset = blknum << (szx + 4);
|
||||||
@ -576,6 +605,13 @@ int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1)
|
|||||||
return (block1->more >= 0);
|
return (block1->more >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block2)
|
||||||
|
{
|
||||||
|
block2->more = coap_get_blockopt(pkt, COAP_OPT_BLOCK2, &block2->blknum,
|
||||||
|
&block2->szx);
|
||||||
|
return (block2->more >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t lastonum)
|
size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t lastonum)
|
||||||
{
|
{
|
||||||
if (block1->more >= 1) {
|
if (block1->more >= 1) {
|
||||||
@ -586,6 +622,15 @@ size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t last
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t coap_opt_put_block2(uint8_t *buf, uint16_t lastonum, coap_block_slicer_t *slicer, bool more)
|
||||||
|
{
|
||||||
|
unsigned szx = _size2szx(slicer->end - slicer->start);
|
||||||
|
unsigned blknum = _slicer_blknum(slicer);
|
||||||
|
|
||||||
|
slicer->opt = buf;
|
||||||
|
return coap_put_option_block(buf, lastonum, blknum, szx, more, COAP_OPT_BLOCK2);
|
||||||
|
}
|
||||||
|
|
||||||
size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum,
|
size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum,
|
||||||
const char *string, char separator)
|
const char *string, char separator)
|
||||||
{
|
{
|
||||||
@ -704,32 +749,118 @@ ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags)
|
|||||||
return pkt->payload - (uint8_t *)pkt->hdr;
|
return pkt->payload - (uint8_t *)pkt->hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void coap_block2_init(coap_pkt_t *pkt, coap_block_slicer_t *slicer)
|
||||||
|
{
|
||||||
|
uint32_t blknum;
|
||||||
|
unsigned szx;
|
||||||
|
|
||||||
|
/* Retrieve the block2 option from the client request */
|
||||||
|
if (coap_get_blockopt(pkt, COAP_OPT_BLOCK2, &blknum, &szx) >= 0) {
|
||||||
|
/* Use the client requested block size if it is smaller than our own
|
||||||
|
* maximum block size */
|
||||||
|
if (NANOCOAP_BLOCK_SIZE_EXP_MAX - 4 < szx) {
|
||||||
|
szx = NANOCOAP_BLOCK_SIZE_EXP_MAX - 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slicer->start = blknum * coap_szx2size(szx);
|
||||||
|
slicer->end = slicer->start + coap_szx2size(szx);
|
||||||
|
slicer->cur = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void coap_block2_finish(coap_block_slicer_t *slicer)
|
||||||
|
{
|
||||||
|
assert(slicer->opt);
|
||||||
|
|
||||||
|
/* The third parameter for _decode_value() points to the end of the header.
|
||||||
|
* We don't know this position, but we know we can read the option because
|
||||||
|
* it's already in the buffer. So just point past the option. */
|
||||||
|
uint8_t *pos = slicer->opt + 1;
|
||||||
|
uint16_t delta = _decode_value(*slicer->opt >> 4, &pos, slicer->opt + 3);
|
||||||
|
int more = (slicer->cur > slicer->end) ? 1 : 0;
|
||||||
|
|
||||||
|
coap_opt_put_block2(slicer->opt, COAP_OPT_BLOCK2 - delta, slicer, more);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t coap_block2_build_reply(coap_pkt_t *pkt, unsigned code,
|
||||||
|
uint8_t *rbuf, unsigned rlen, unsigned payload_len,
|
||||||
|
coap_block_slicer_t *slicer)
|
||||||
|
{
|
||||||
|
/* Check if the generated data filled the requested block */
|
||||||
|
if (slicer->cur < slicer->start) {
|
||||||
|
return coap_build_reply(pkt, COAP_CODE_BAD_OPTION, rbuf, rlen, 0);
|
||||||
|
}
|
||||||
|
coap_block2_finish(slicer);
|
||||||
|
return coap_build_reply(pkt, code, rbuf, rlen, payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t coap_blockwise_put_char(coap_block_slicer_t *slicer, uint8_t *bufpos, char c)
|
||||||
|
{
|
||||||
|
/* Only copy the char if it is within the window */
|
||||||
|
if ((slicer->start <= slicer->cur) && (slicer->cur < slicer->end)) {
|
||||||
|
*bufpos = c;
|
||||||
|
slicer->cur++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
slicer->cur++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t coap_blockwise_put_bytes(coap_block_slicer_t *slicer, uint8_t *bufpos,
|
||||||
|
const uint8_t *c, size_t len)
|
||||||
|
{
|
||||||
|
size_t str_len = 0; /* Length of the string to copy */
|
||||||
|
|
||||||
|
/* Calculate start offset of the supplied string */
|
||||||
|
size_t str_offset = (slicer->start > slicer->cur)
|
||||||
|
? slicer->start - slicer->cur
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
/* Check for string before or beyond window */
|
||||||
|
if ((slicer->cur >= slicer->end) || (str_offset > len)) {
|
||||||
|
slicer->cur += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Check if string is over the end of the window */
|
||||||
|
if ((slicer->cur + len) >= slicer->end) {
|
||||||
|
str_len = slicer->end - (slicer->cur + str_offset);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str_len = len - str_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only copy the relevant part of the string to the buffer */
|
||||||
|
memcpy(bufpos, c + str_offset, str_len);
|
||||||
|
slicer->cur += len;
|
||||||
|
return str_len;
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t coap_well_known_core_default_handler(coap_pkt_t *pkt, uint8_t *buf, \
|
ssize_t coap_well_known_core_default_handler(coap_pkt_t *pkt, uint8_t *buf, \
|
||||||
size_t len, void *context)
|
size_t len, void *context)
|
||||||
{
|
{
|
||||||
(void)context;
|
(void)context;
|
||||||
|
coap_block_slicer_t slicer;
|
||||||
|
coap_block2_init(pkt, &slicer);
|
||||||
uint8_t *payload = buf + coap_get_total_hdr_len(pkt);
|
uint8_t *payload = buf + coap_get_total_hdr_len(pkt);
|
||||||
|
|
||||||
uint8_t *bufpos = payload;
|
uint8_t *bufpos = payload;
|
||||||
|
|
||||||
bufpos += coap_put_option_ct(bufpos, 0, COAP_CT_LINK_FORMAT);
|
bufpos += coap_put_option_ct(bufpos, 0, COAP_CT_LINK_FORMAT);
|
||||||
|
bufpos += coap_opt_put_block2(bufpos, COAP_OPT_CONTENT_FORMAT, &slicer, 1);
|
||||||
|
|
||||||
*bufpos++ = 0xff;
|
*bufpos++ = 0xff;
|
||||||
|
|
||||||
for (unsigned i = 0; i < coap_resources_numof; i++) {
|
for (unsigned i = 0; i < coap_resources_numof; i++) {
|
||||||
if (i) {
|
if (i) {
|
||||||
*bufpos++ = ',';
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, ',');
|
||||||
}
|
}
|
||||||
*bufpos++ = '<';
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, '<');
|
||||||
unsigned url_len = strlen(coap_resources[i].path);
|
unsigned url_len = strlen(coap_resources[i].path);
|
||||||
memcpy(bufpos, coap_resources[i].path, url_len);
|
bufpos += coap_blockwise_put_bytes(&slicer, bufpos,
|
||||||
bufpos += url_len;
|
(uint8_t*)coap_resources[i].path, url_len);
|
||||||
*bufpos++ = '>';
|
bufpos += coap_blockwise_put_char(&slicer, bufpos, '>');
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned payload_len = bufpos - payload;
|
unsigned payload_len = bufpos - payload;
|
||||||
|
return coap_block2_build_reply(pkt, COAP_CODE_205, buf, len, payload_len,
|
||||||
return coap_build_reply(pkt, COAP_CODE_205, buf, len, payload_len);
|
&slicer);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned coap_get_len(coap_pkt_t *pkt)
|
unsigned coap_get_len(coap_pkt_t *pkt)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user