1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-24 22:13:52 +01:00

nanocoap_sock: add nanocoap_sock_block_request()

This commit is contained in:
Benjamin Valentin 2022-04-15 23:01:33 +02:00
parent f2279e43ae
commit b99d4b58bd
2 changed files with 139 additions and 0 deletions

View File

@ -134,6 +134,7 @@
#include "net/nanocoap.h"
#include "net/sock/udp.h"
#include "net/sock/util.h"
#ifdef __cplusplus
extern "C" {
@ -145,6 +146,17 @@ extern "C" {
*/
typedef sock_udp_t nanocoap_sock_t;
/**
* @brief Blockwise request helper struct
*/
typedef struct {
nanocoap_sock_t sock; /**< socket used for the request */
const char *path; /**< path on the server */
uint32_t blknum; /**< current block number */
uint8_t method; /**< request method (GET, POST, PUT) */
uint8_t blksize; /**< CoAP blocksize exponent */
} coap_block_request_t;
/**
* @brief Start a nanocoap server instance
*
@ -332,6 +344,87 @@ ssize_t nanocoap_request(coap_pkt_t *pkt, sock_udp_ep_t *local,
ssize_t nanocoap_get(sock_udp_ep_t *remote, const char *path, void *buf,
size_t len);
/**
* @brief Initialize block request context
*
* @param[out] ctx The block request context to initialize
* @param[in] remote Server endpoint
* @param[in] path Server path for request
* @param[in] method Request method (`COAP_METHOD_{GET|PUT|POST}`)
* @param[in] blksize Request blocksize exponent
*
* @retval 0 Success
* @retval <0 Error (see @ref nanocoap_sock_connect for details)
*/
static inline int nanocoap_block_request_init(coap_block_request_t *ctx,
sock_udp_ep_t *remote,
const char *path,
uint8_t method,
coap_blksize_t blksize)
{
ctx->path = path;
ctx->blknum = 0;
ctx->method = method;
ctx->blksize = blksize;
return nanocoap_sock_connect(&ctx->sock, NULL, remote);
}
/**
* @brief Initialize block request context by URL
*
* @param[out] ctx The block request context to initialize
* @param[in] url The request URL
* @param[in] method Request method (`COAP_METHOD_{GET|PUT|POST}`)
* @param[in] blksize Request blocksize exponent
*
* @retval 0 Success
* @retval <0 Error (see @ref nanocoap_sock_url_connect for details)
*/
static inline int nanocoap_block_request_init_url(coap_block_request_t *ctx,
const char *url,
uint8_t method,
coap_blksize_t blksize)
{
ctx->path = sock_urlpath(url);
ctx->blknum = 0;
ctx->method = method;
ctx->blksize = blksize;
return nanocoap_sock_url_connect(url, &ctx->sock);
}
/**
* @brief Free block request context
*
* @param[out] ctx The block request context to finalize
*/
static inline void nanocoap_block_request_done(coap_block_request_t *ctx)
{
nanocoap_sock_close(&ctx->sock);
}
/**
* @brief Do a block-wise request, send a single block.
*
* This method is expected to be called in a loop until all
* payload blocks have been transferred.
*
* @pre @p ctx was initialized with @ref nanocoap_block_request_init or
* @ref nanocoap_block_request_init_url
*
* @param[in] ctx blockwise request context
* @param[in] data payload to send
* @param[in] len payload length
* @param[in] more more blocks after this one
* (will be set automatically if @p len > block size)
* @param[in] cb callback for response
* @param[in] arg callback context
*
* @return Number of payload bytes written on success
* Negative error on failure
*/
int nanocoap_sock_block_request(coap_block_request_t *ctx,
const void *data, size_t len, bool more,
coap_request_cb_t cb, void *arg);
#ifdef __cplusplus
}
#endif

View File

@ -392,6 +392,52 @@ static int _fetch_block(nanocoap_sock_t *sock, uint8_t *buf, size_t len,
return nanocoap_sock_request_cb(sock, &pkt, _block_cb, ctx);
}
int nanocoap_sock_block_request(coap_block_request_t *req,
const void *data, size_t len, bool more,
coap_request_cb_t callback, void *arg)
{
/* clip the payload at the block size */
if (len > coap_szx2size(req->blksize)) {
len = coap_szx2size(req->blksize);
more = true;
}
int res;
uint8_t buf[CONFIG_NANOCOAP_BLOCK_HEADER_MAX];
iolist_t snip = {
.iol_base = (void *)data,
.iol_len = len,
};
coap_pkt_t pkt = {
.hdr = (void *)buf,
.snips = &snip,
};
uint8_t *pktpos = (void *)pkt.hdr;
uint16_t lastonum = 0;
pktpos += coap_build_hdr(pkt.hdr, COAP_TYPE_CON, NULL, 0, req->method, _get_id());
pktpos += coap_opt_put_uri_pathquery(pktpos, &lastonum, req->path);
pktpos += coap_opt_put_uint(pktpos, lastonum, COAP_OPT_BLOCK1,
(req->blknum << 4) | req->blksize | (more ? 0x8 : 0));
if (len) {
/* set payload marker */
*pktpos++ = 0xFF;
}
pkt.payload = pktpos;
pkt.payload_len = 0;
res = nanocoap_sock_request_cb(&req->sock, &pkt, callback, arg);
if (res < 0) {
return res;
}
++req->blknum;
return len;
}
int nanocoap_sock_get_blockwise(nanocoap_sock_t *sock, const char *path,
coap_blksize_t blksize,
coap_blockwise_cb_t callback, void *arg)