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

gcoap: Add file server #14397

Closed
wants to merge 13 commits into from
Closed
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
8 changes: 8 additions & 0 deletions examples/filesystem/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += ps

ifeq (${NETWORK},1)
USEMODULE += gcoap
USEMODULE += coapfileserver
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_netdev_default
USEMODULE += auto_init_gnrc_netif
endif

# Use MTD (flash layer)
USEMODULE += mtd
# USEMODULE += mtd_sdcard
Expand Down
18 changes: 18 additions & 0 deletions examples/filesystem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,21 @@ Hello World!
cat /const/hello-riot
Hello RIOT!
```

## Network file server

If ``NETWORK=1`` is passed to make, the board's default network setup is
enabled, and a CoAP server is started that exports the file system at the path
``/vfs``.

You can access the file system from another board that runs the gcoap example:

```
> coap get fe80::3c63:beff:fe85:ca96%6 5683 /vfs/const/
<hello-world>,<hello-riot>
> coap get fe80::3c63:beff:fe85:ca96%6 5683 /vfs/const/hello-riot
--- blockwise start ---
gcoap: response Success, code 2.05, 13 bytes
00000000 48 65 6C 6C 6F 20 52 49 4F 54 21 0A 00
--- blockwise complete ---
```
30 changes: 30 additions & 0 deletions examples/filesystem/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
#include "shell.h"
#include "board.h" /* MTD_0 is defined in board.h */

#ifdef MODULE_COAPFILESERVER
#include <net/gcoap.h>
#include <net/coapfileserver.h>
#endif

/* Configure MTD device for SD card if none is provided */
#if !defined(MTD_0) && MODULE_MTD_SDCARD
#include "mtd_sdcard.h"
Expand Down Expand Up @@ -309,6 +314,26 @@ static const shell_command_t shell_commands[] = {
{ NULL, NULL, NULL }
};

#ifdef MODULE_COAPFILESERVER
/* Export all the file system */
static const struct coapfileserver_entry vfs = { "", 1 };

/* CoAP resources. Must be sorted by path (ASCII order). */
static const coap_resource_t _resources[] = {
{ "/vfs", COAP_GET | COAP_MATCH_SUBTREE, coapfileserver_handler, (void*)&vfs },
};

static gcoap_listener_t _listener = {
&_resources[0],
ARRAY_SIZE(_resources),
NULL,
NULL
};

Comment on lines +319 to +332
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to move this to an auto-init function? Is there a reason why this needs to be registered from the application?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only if it were to be made configurable as to the file system entry point and to the coap entry point -- we really shouldn't pick resource names on users' CoAP servers. (And there'd still need to allow manual management for things like ACLs, or when different mount points need different treatment on the CoAP side, eg. w/rt writability).

AFAIK we currently don't do any automatically inserted CoAP resources (other than /.well-known/core). Doing that efficiently would mean putting sorted entries into an array, AFAICT that can't be done even with XFA (#15002) and'd thus need pre-sorting by wherethroughever the configured paths are set. (For example, if coapfileserver did this and so did a hypothetical resourcedirectory, they'd need to be put as ["/.well-known/core", "/coapfileserver", "/rd"] with the one set of names but as ["/.well-known/core", "/cord-server", "/files"] with others).

I'll give it a try, but it may result in an "I'd rather do this as a next step".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only if it were to be made configurable as to the file system entry point and to the coap entry point -- we really shouldn't pick resource names on users' CoAP servers. (And there'd still need to allow manual management for things like ACLs, or when different mount points need different treatment on the CoAP side, eg. w/rt writability).

Agreed, I was thinking as well on making the entry point configurable.

Doing that efficiently would mean putting sorted entries into an array

Yeah, that's true. Maybe if we could adapt the path matching function on nanocoap we could get rid of the alphabetical ordering constraint? In any case, if that's needed it would be work for a follow up PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe if we could adapt the path matching function on nanocoap

Sorry, meant the gcoap matching, that's the one that enforces this.

#define MAIN_QUEUE_SIZE (4)
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
#endif

int main(void)
{
#if defined(MTD_0) && (defined(MODULE_SPIFFS) || defined(MODULE_LITTLEFS) || defined(MODULE_LITTLEFS2))
Expand All @@ -326,6 +351,11 @@ int main(void)
puts("constfs mounted successfully");
}

#ifdef MODULE_COAPFILESERVER
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
gcoap_register_listener(&_listener);
#endif

char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);

Expand Down
3 changes: 3 additions & 0 deletions sys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ endif
ifneq (,$(filter ztimer_xtimer_compat,$(USEMODULE)))
FILTER += xtimer
endif
ifneq (,$(filter coapfileserver,$(USEMODULE)))
DIRS += net/application_layer/coapfileserver
endif

DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(filter-out $(FILTER), $(USEMODULE)))))

Expand Down
4 changes: 4 additions & 0 deletions sys/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,10 @@ ifneq (,$(filter devfs,$(USEMODULE)))
USEMODULE += vfs
endif

ifneq (,$(filter coapfileserver,$(USEMODULE)))
USEMODULE += vfs
endif

ifneq (,$(filter vfs,$(USEMODULE)))
USEMODULE += posix_headers
ifeq (native, $(BOARD))
Expand Down
1 change: 1 addition & 0 deletions sys/include/net/coap.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ extern "C" {
* @{
*/
#define COAP_OPT_URI_HOST (3)
#define COAP_OPT_ETAG (4)
#define COAP_OPT_OBSERVE (6)
#define COAP_OPT_LOCATION_PATH (8)
#define COAP_OPT_URI_PATH (11)
Expand Down
71 changes: 71 additions & 0 deletions sys/include/net/coapfileserver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2020 chrysn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup net_coapfileserver
* @{
*
* @file
* @brief Resource handler for the CoAP file system server
*
* @author chrysn <chrysn@fsfe.org>
*
* @}
*/

#ifndef NET_COAPFILESERVER_H
#define NET_COAPFILESERVER_H

#ifdef __cplusplus
extern "C" {
#endif

#include <net/nanocoap.h>

/** File server starting point
*
* This struct needs to be present at the ctx of a coapfileserver_handler entry
* in a resource list.
*
*/
struct coapfileserver_entry {
/** Path in the VFS that should be served.
*
* This does not need a trailing slash. */
char *nameprefix;
/** Number of leading path components to ignore as they are the common prefix.
*
* If the file server is bound to the "/" resource, make this 0; if there
* is an entry
*
* ``{ "/files/sd", COAP_GET | COAP_MATCH_SUBTREE, coapfileserver_handler, files_sd }``
*
* then ``files_sd.strip_path`` needs to be 2.
*
* */
uint8_t strip_path;
};

/**
* File server handler
*
* Serve a directory from the VFS as a CoAP resource tree.
*
* @p ctx pointer to a @ref coapfileserver_entry
*
* @see net_coapfileserver
*/
ssize_t coapfileserver_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx);

#ifdef __cplusplus
}
#endif

#endif /* NET_COAPFILESERVER_H */

/** @} */
5 changes: 5 additions & 0 deletions sys/net/application_layer/coapfileserver/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MODULE = coapfileserver

SRC = coapfileserver.c

Comment on lines +2 to +4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed, the file should be included automatically:

Suggested change
SRC = coapfileserver.c

include $(RIOTBASE)/Makefile.base
Loading