1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

nanocoap_sock: add nanocoap_sock_get_block()

This commit is contained in:
Benjamin Valentin 2024-05-21 19:18:29 +02:00
parent 4a431c8d1a
commit 994211d955
2 changed files with 120 additions and 0 deletions

View File

@ -589,6 +589,25 @@ int nanocoap_sock_get_blockwise(nanocoap_sock_t *sock, const char *path,
coap_blksize_t blksize,
coap_blockwise_cb_t callback, void *arg);
/**
* @brief Performs a blockwise coap get request to the specified url, store
* the response in a buffer.
*
* @param[in] sock socket to use for the request
* @param[in] path Absolute URL pointer to source path
* @param[in] blksize sender suggested SZX for the COAP block request
* @param[in] offset Offset in bytes from the start of the resource
* @param[in] dst Target buffer
* @param[in] len Target buffer length
*
* @returns <0 on error
* @returns -EINVAL if an invalid url is provided
* @returns size of the response payload on success
*/
int nanocoap_sock_get_slice(nanocoap_sock_t *sock, const char *path,
coap_blksize_t blksize, size_t offset,
void *dst, size_t len);
/**
* @brief Performs a blockwise coap get request to the specified url.
*

View File

@ -707,6 +707,107 @@ int nanocoap_sock_get_blockwise(nanocoap_sock_t *sock, const char *path,
return 0;
}
typedef struct {
uint8_t *ptr;
size_t len;
size_t offset;
size_t res;
} _buf_slice_t;
static int _2buf_slice(void *arg, size_t offset, uint8_t *buf, size_t len, int more)
{
_buf_slice_t *ctx = arg;
if (offset + len < ctx->offset) {
return 0;
}
if (offset > ctx->offset + ctx->len) {
return 0;
}
if (!ctx->len) {
return 0;
}
offset = ctx->offset - offset;
len = MIN(len - offset, ctx->len);
memcpy(ctx->ptr, buf + offset, len);
ctx->len -= len;
ctx->ptr += len;
ctx->offset += len;
ctx->res += len;
DEBUG("nanocoap: got %"PRIuSIZE" bytes, %"PRIuSIZE" bytes left (offset: %"PRIuSIZE")\n",
len, ctx->len, offset);
if (!more) {
ctx->len = 0;
}
return 0;
}
static unsigned _num_blks(size_t offset, size_t len, coap_blksize_t szx)
{
uint16_t mask = coap_szx2size(szx) - 1;
uint8_t shift = szx + 4;
size_t end = offset + len;
unsigned num_blks = ((end >> shift) + !!(end & mask))
- ((offset >> shift) + !!(offset & mask));
return num_blks;
}
int nanocoap_sock_get_slice(nanocoap_sock_t *sock, const char *path,
coap_blksize_t blksize, size_t offset,
void *dst, size_t len)
{
uint8_t buf[CONFIG_NANOCOAP_BLOCK_HEADER_MAX];
/* try to find optimal blocksize */
unsigned num_blocks = _num_blks(offset, len, blksize);
for (uint8_t szx = 0; szx < blksize; ++szx) {
if (_num_blks(offset, len, szx) <= num_blocks) {
blksize = szx;
break;
}
}
_buf_slice_t dst_ctx = {
.ptr = dst,
.len = len,
.offset = offset,
};
_block_ctx_t ctx = {
.callback = _2buf_slice,
.arg = &dst_ctx,
.more = true,
};
#if CONFIG_NANOCOAP_SOCK_BLOCK_TOKEN
random_bytes(ctx.token, sizeof(ctx.token));
#endif
unsigned num = offset >> (blksize + 4);
while (dst_ctx.len) {
DEBUG("nanocoap: fetching block %u\n", num);
int res = _fetch_block(sock, buf, sizeof(buf), path, blksize, num, &ctx);
if (res < 0) {
DEBUG("nanocoap: error fetching block %u: %d\n", num, res);
return res;
}
num += 1;
}
return dst_ctx.res;
}
int nanocoap_sock_url_connect(const char *url, nanocoap_sock_t *sock)
{
char hostport[CONFIG_SOCK_HOSTPORT_MAXLEN];