Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nanocoap_vfs: add nanocoap_vfs_put() #17962

Merged
merged 4 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions sys/include/net/nanocoap.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
#include <unistd.h>

#ifdef RIOT_VERSION
#include "bitarithm.h"
#include "bitfield.h"
#include "byteorder.h"
#include "iolist.h"
Expand Down Expand Up @@ -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);
}
/**@}*/

/**
Expand Down
31 changes: 31 additions & 0 deletions sys/include/net/nanocoap_vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 66 additions & 1 deletion sys/net/application_layer/nanocoap/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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);
}
43 changes: 41 additions & 2 deletions sys/shell/commands/sc_nanocoap_vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ static int _print_dir(const char *url, char *buf, size_t len)
_print_dir_cb, &ctx);
}

int _nanocoap_get_handler(int argc, char **argv)
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) {
Expand Down Expand Up @@ -139,4 +139,43 @@ 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];
fabian18 marked this conversation as resolved.
Show resolved Hide resolved

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);
3 changes: 3 additions & 0 deletions tests/nanocoap_cli/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down