Skip to content

Commit

Permalink
Merge pull request #17956 from benpicco/coapfileserver
Browse files Browse the repository at this point in the history
gcoap: Add file server
  • Loading branch information
benpicco authored May 23, 2022
2 parents bbf0b3a + d4db82c commit 08e430b
Show file tree
Hide file tree
Showing 8 changed files with 645 additions and 1 deletion.
35 changes: 35 additions & 0 deletions examples/gcoap_fileserver/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# name of your application
APPLICATION = gcoap_fileserver

# If no BOARD is found in the environment, use this default:
BOARD ?= native

# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..

# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
DEVELHELP ?= 1

# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1

# Modules to include:
USEMODULE += shell
USEMODULE += shell_commands

# enable the fileserver module
USEMODULE += gcoap_fileserver

# select network modules
USEMODULE += gnrc_ipv6_default
USEMODULE += auto_init_gnrc_netif
USEMODULE += netdev_default
USEMODULE += gnrc_icmpv6_echo

# enable default file system mount points
USEMODULE += vfs_default
# USEMODULE += vfs_auto_format

include $(RIOTBASE)/Makefile.include
44 changes: 44 additions & 0 deletions examples/gcoap_fileserver/Makefile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
blackpill \
bluepill \
bluepill-stm32f030c8 \
derfmega128 \
i-nucleo-lrwan1 \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \
nucleo-f030r8 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-f302r8 \
nucleo-f303k8 \
nucleo-f334r8 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
samd10-xmini \
saml10-xpro \
saml11-xpro \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32f7508-dk \
stm32g0316-disco \
stm32l0538-disco \
stm32mp157c-dk2 \
telosb \
waspmote-pro \
z1 \
zigduino \
#
52 changes: 52 additions & 0 deletions examples/gcoap_fileserver/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2022 ML!PA Consulting GmbH
*
* 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 examples
* @{
*
* @file
* @brief Example application for demonstrating the GCoAP file server
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
* @}
*/

#include "net/gcoap.h"
#include "net/gcoap/fileserver.h"
#include "shell.h"
#include "vfs_default.h"

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

static const gcoap_fileserver_entry_t _vfs_entry = {
.root = VFS_DEFAULT_DATA,
.resource = "/vfs",
};

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

static gcoap_listener_t _listener = {
.resources = _resources,
.resources_len = ARRAY_SIZE(_resources),
};

int main(void)
{
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
gcoap_register_listener(&_listener);

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

return 0;
}
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ PSEUDOMODULES += evtimer_on_ztimer
PSEUDOMODULES += fatfs_vfs_format
PSEUDOMODULES += fmt_%
PSEUDOMODULES += gcoap_forward_proxy
PSEUDOMODULES += gcoap_fileserver
PSEUDOMODULES += gcoap_dtls
PSEUDOMODULES += fido2_tests
PSEUDOMODULES += gnrc_dhcpv6_%
Expand Down
6 changes: 6 additions & 0 deletions sys/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,12 @@ ifneq (,$(filter l2filter_%,$(USEMODULE)))
USEMODULE += l2filter
endif

ifneq (,$(filter gcoap_fileserver,$(USEMODULE)))
USEMODULE += gcoap
USEMODULE += checksum
USEMODULE += vfs
endif

ifneq (,$(filter gcoap_forward_proxy,$(USEMODULE)))
USEMODULE += gcoap
USEMODULE += uri_parser
Expand Down
13 changes: 12 additions & 1 deletion sys/include/net/gcoap.h
Original file line number Diff line number Diff line change
Expand Up @@ -627,8 +627,19 @@ extern "C" {
#define GCOAP_DTLS_EXTRA_STACKSIZE (0)
#endif

/**
* @brief Extra stack for VFS operations
*/
#if IS_USED(MODULE_GCOAP_FILESERVER)
#include "vfs.h"
#define GCOAP_VFS_EXTRA_STACKSIZE (VFS_DIR_BUFFER_SIZE + VFS_FILE_BUFFER_SIZE)
#else
#define GCOAP_VFS_EXTRA_STACKSIZE (0)
#endif

#define GCOAP_STACK_SIZE (THREAD_STACKSIZE_DEFAULT + DEBUG_EXTRA_STACKSIZE \
+ sizeof(coap_pkt_t) + GCOAP_DTLS_EXTRA_STACKSIZE)
+ sizeof(coap_pkt_t) + GCOAP_DTLS_EXTRA_STACKSIZE \
+ GCOAP_VFS_EXTRA_STACKSIZE)
#endif
/** @} */

Expand Down
122 changes: 122 additions & 0 deletions sys/include/net/gcoap/fileserver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* 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.
*/

/**
* @defgroup net_gcoap_fileserver GCoAP file server
* @ingroup net_gcoap
* @brief Library for serving files from the VFS to CoAP clients
*
* # About
*
* This maps files in the local file system onto a resources in CoAP. In that,
* it is what is called a static web server in the unconstrained web.
*
* As usual, GET operations are used to read files<!-- WRITESUPPORT, and PUT writes to files.
* In the current implementation, PUTs are expressed as random-access, meaning
* that files are not updated atomically -->.
*
* Directories are expressed to URIs with trailing slashes<!-- WRITESUPPORT, and are always
* created implicitly when files are PUT under them; they can be DELETEd when
* empty -->.
*
* @note The file server uses ETag for cache validation. The ETags are built
* from the file system stat values. As clients rely on the ETag to differ when
* the file changes, it is important that file modification times are set. The
* precise time values do not matter, but if a file is changed in place and
* neither its length nor its modification time is varied, then clients will
* not become aware of the change or may even mix up the versions half way
* through if they have a part of the old version cached.
*
* # Usage
*
* * ``USEMODULE += gcoap_fileserver``
*
* * Have a @ref gcoap_fileserver_entry_t populated with the path you want to serve,
* and the number of path components to strip from incoming requests:
*
* ```
* static const gcoap_fileserver_entry_t files_sd = {
* .root = "/sd0",
* .resource = "/files/sd"
* };
* ```
*
* * Enter a @ref gcoap_fileserver_handler handler into your CoAP server's
* resource list like this:
*
* ```
* static const coap_resource_t _resources[] = {
* ...
* { "/files/sd", COAP_GET | COAP_MATCH_SUBTREE, gcoap_fileserver_handler, (void*)&files_sd },
* ...
* }
* ```
*
* The allowed methods dictate whether it's read-only (``COAP_GET``) or (in the
* future<!-- WRITESUPPORT -->) read-write (``COAP_GET | COAP_PUT | COAP_DELETE``).
*
* @{
*
* @file
* @brief Resource handler for the CoAP file system server
*
* @author chrysn <chrysn@fsfe.org>
*/

#ifndef NET_GCOAP_FILESERVER_H
#define NET_GCOAP_FILESERVER_H

#ifdef __cplusplus
extern "C" {
#endif

#include "net/nanocoap.h"

/**
* @brief File server starting point
*
* This struct needs to be present at the ctx of a gcoap_fileserver_handler entry
* in a resource list.
*
*/
typedef struct {
/**
* @brief Path in the VFS that should be served.
*
* This does not need a trailing slash.
*/
const char *root;
/**
* @brief The associated CoAP resource path
*/
const char *resource;
} gcoap_fileserver_entry_t;

/**
* @brief File server handler
*
* Serve a directory from the VFS as a CoAP resource tree.
* @see net_gcoap_fileserver
*
* @param[in] pdu CoAP request package
* @param[out] buf Buffer for the response
* @param[in] len Response buffer length
* @param[in] ctx pointer to a @ref gcoap_fileserver_entry_t
*
* @return size of the response on success
* negative error
*/
ssize_t gcoap_fileserver_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx);

#ifdef __cplusplus
}
#endif

#endif /* NET_GCOAP_FILESERVER_H */

/** @} */
Loading

0 comments on commit 08e430b

Please sign in to comment.