1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 06:23:53 +01:00

Merge pull request #17962 from benpicco/nanocoap_vfs-put

nanocoap_vfs: add nanocoap_vfs_put()
This commit is contained in:
benpicco 2022-06-16 11:53:36 +02:00 committed by GitHub
commit 0a16f8266a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 154 additions and 2 deletions

View File

@ -86,6 +86,7 @@
#include <unistd.h>
#ifdef RIOT_VERSION
#include "bitarithm.h"
#include "bitfield.h"
#include "byteorder.h"
#include "iolist.h"
@ -988,6 +989,19 @@ static inline unsigned coap_szx2size(unsigned szx)
{
return (1 << (szx + 4));
}
/**
* @brief Helper to encode byte size into next equal or smaller SZX value
*
* @param[in] len Size in bytes
*
* @returns closest SZX value that fits into a buffer of @p len
*/
static inline unsigned coap_size2szx(unsigned len)
{
assert(len >= 16);
return bitarithm_msb(len >> 4);
}
/**@}*/
/**

View File

@ -51,6 +51,37 @@ int nanocoap_vfs_get_url(const char *url, const char *dst);
*/
int nanocoap_vfs_get(nanocoap_sock_t *sock, const char *path, const char *dst);
/**
* @brief Uploads the @p file to @p url via blockwise PUT.
*
* @param[in] url URL to the resource
* @param[in] src Path to the source file
* @param[in] work_buf Buffer to read file blocks into
* @param[in] work_buf_len Size of the buffer. Should be 1 byte more
* than the desired CoAP blocksize.
*
* @returns 0 on success
* @returns <0 on error
*/
int nanocoap_vfs_put_url(const char *url, const char *src,
void *work_buf, size_t work_buf_len);
/**
* @brief Uploads the @p file to @p path via blockwise PUT.
*
* @param[in] sock Connection to the server
* @param[in] path Remote query path to the resource
* @param[in] src Path to the source file
* @param[in] work_buf Buffer to read file blocks into
* @param[in] work_buf_len Size of the buffer. Should be 1 byte more
* than the desired CoAP blocksize.
*
* @returns 0 on success
* @returns <0 on error
*/
int nanocoap_vfs_put(nanocoap_sock_t *sock, const char *path, const char *src,
void *work_buf, size_t work_buf_len);
#ifdef __cplusplus
}
#endif

View File

@ -19,7 +19,7 @@
*/
#include <fcntl.h>
#include "net/nanocoap_sock.h"
#include "net/nanocoap_vfs.h"
#include "net/sock/util.h"
#include "vfs.h"
@ -92,3 +92,68 @@ int nanocoap_vfs_get_url(const char *url, const char *dst)
_2file, &fd);
return _finalize_file(fd, res, dst, dst_tmp);
}
static int _vfs_put(coap_block_request_t *ctx, const char *file, void *buffer)
{
int res, fd = vfs_open(file, O_RDONLY, 0644);
if (fd < 0) {
return fd;
}
/* buffer is at least one larger than SZX value */
int buffer_len = coap_szx2size(ctx->blksize) + 1;
bool more = true;
while (more && (res = vfs_read(fd, buffer, buffer_len)) > 0) {
more = res == buffer_len;
res = nanocoap_sock_block_request(ctx, buffer,
res, more, NULL, NULL);
if (res < 0) {
break;
}
vfs_lseek(fd, -1, SEEK_CUR);
}
nanocoap_block_request_done(ctx);
vfs_close(fd);
return res;
}
int nanocoap_vfs_put(nanocoap_sock_t *sock, const char *path, const char *src,
void *work_buf, size_t work_buf_len)
{
DEBUG("nanocoap: uploading %s to %s\n", src, path);
if (work_buf_len < coap_szx2size(0) + 1) {
return -ENOBUFS;
}
coap_block_request_t ctx = {
.path = path,
.method = COAP_METHOD_PUT,
.blksize = coap_size2szx(work_buf_len - 1),
.sock = *sock,
};
return _vfs_put(&ctx, src, work_buf);
}
int nanocoap_vfs_put_url(const char *url, const char *src,
void *work_buf, size_t work_buf_len)
{
DEBUG("nanocoap: uploading %s to %s\n", src, url);
if (work_buf_len < coap_szx2size(0) + 1) {
return -ENOBUFS;
}
coap_block_request_t ctx;
int res = nanocoap_block_request_init_url(&ctx, url, COAP_METHOD_PUT,
coap_size2szx(work_buf_len - 1));
if (res) {
return res;
}
return _vfs_put(&ctx, src, work_buf);
}

View File

@ -91,7 +91,7 @@ static int _print_dir(const char *url, char *buf, size_t len)
static int _nanocoap_get_handler(int argc, char **argv)
{
int res;
char buffer[CONFIG_NANOCOAP_QS_MAX];
char buffer[CONFIG_NANOCOAP_URI_MAX];
char *dst, *url = argv[1];
if (argc < 2) {
@ -139,4 +139,43 @@ static int _nanocoap_get_handler(int argc, char **argv)
return res;
}
static int _nanocoap_put_handler(int argc, char **argv)
{
int res;
char *file, *url;
char buffer[CONFIG_NANOCOAP_URI_MAX];
char work_buf[coap_szx2size(CONFIG_NANOCOAP_BLOCKSIZE_DEFAULT) + 1];
if (argc < 3) {
printf("Usage: %s <file> <url>\n", argv[0]);
return -EINVAL;
}
file = argv[1];
url = argv[2];
if (_is_dir(url)) {
const char *basename = strrchr(file, '/');
if (basename == NULL) {
return -EINVAL;
}
if (snprintf(buffer, sizeof(buffer), "%s%s",
url, basename + 1) >= (int)sizeof(buffer)) {
puts("Constructed URI too long");
return -ENOBUFS;
}
url = buffer;
}
res = nanocoap_vfs_put_url(url, file, work_buf, sizeof(work_buf));
if (res < 0) {
printf("Upload failed: %s\n", strerror(-res));
}
else {
printf("Saved to %s\n", url);
}
return res;
}
SHELL_COMMAND(ncget, "download a file from a CoAP server", _nanocoap_get_handler);
SHELL_COMMAND(ncput, "upload a file to a CoAP server", _nanocoap_put_handler);

View File

@ -27,6 +27,9 @@ ifeq (,$(filter $(BOARD),$(LOW_MEMORY_BOARDS)))
# USEMODULE += vfs_auto_format
USEMODULE += shell_commands
# VFS operations require more stack on the main thread
CFLAGS += -DTHREAD_STACKSIZE_MAIN=THREAD_STACKSIZE_LARGE
# always enable auto-format for native
ifeq ($(BOARD),native)
USEMODULE += vfs_auto_format