2020-10-24 00:43:24 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2023-10-30 15:32:01 +01:00
|
|
|
* @defgroup net_nanocoap_fileserver CoAP file server
|
|
|
|
* @ingroup net_nanocoap
|
2020-10-24 00:43:24 +02:00
|
|
|
* @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.
|
|
|
|
*
|
2022-05-20 23:49:10 +02:00
|
|
|
* As usual, GET operations are used to read files and PUT writes to files.
|
2020-10-24 00:43:24 +02:00
|
|
|
* In the current implementation, PUTs are expressed as random-access, meaning
|
2022-05-20 23:49:10 +02:00
|
|
|
* that files are not updated atomically, although files are created atomically.
|
|
|
|
* The Content-Format option is not checked in the current implementation.
|
|
|
|
* Conditional file modification and deletion is supported using the If-Match
|
|
|
|
* option. The If-Match option carries a previously received Etag or in case of
|
|
|
|
* zero length, requires a request to be processed only if the resource exists.
|
|
|
|
* In opposite, the If-None-Match option requires a request to be processed,
|
|
|
|
* only if the resource does not yet exist, and is most useful for file creation.
|
2020-10-24 00:43:24 +02:00
|
|
|
*
|
2022-07-26 00:24:39 +02:00
|
|
|
* Directories are expressed to URIs with trailing slashes. Directories and
|
|
|
|
* their content are deleted as if one would do an `$rm -r`. If you only would
|
|
|
|
* like to delete a directory if it is empty, you must supply an If-Match option
|
|
|
|
* with the special value @ref COAPFILESERVER_DIR_DELETE_ETAG.
|
2020-10-24 00:43:24 +02:00
|
|
|
*
|
|
|
|
* @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
|
|
|
|
*
|
2023-10-30 15:32:01 +01:00
|
|
|
* * ``USEMODULE += nanocoap_fileserver``
|
2020-10-24 00:43:24 +02:00
|
|
|
*
|
2023-10-30 15:32:01 +01:00
|
|
|
* * Enter a @ref nanocoap_fileserver_handler handler into your CoAP server's
|
2020-10-24 00:43:24 +02:00
|
|
|
* resource list like this:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* static const coap_resource_t _resources[] = {
|
|
|
|
* ...
|
2022-05-23 22:57:42 +02:00
|
|
|
* {
|
|
|
|
* .path = "/files/sd",
|
|
|
|
* .methods = COAP_GET | COAP_MATCH_SUBTREE,
|
2023-10-30 15:32:01 +01:00
|
|
|
* .handler = nanocoap_fileserver_handler,
|
2022-05-23 22:57:42 +02:00
|
|
|
* .context = "/sd0"
|
|
|
|
* },
|
2020-10-24 00:43:24 +02:00
|
|
|
* ...
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*
|
2022-05-23 22:57:42 +02:00
|
|
|
* The path argument specifies under which path the folder is served via CoAP while
|
|
|
|
* the context argument contains the path on the local filesystem that will be served.
|
|
|
|
*
|
2022-05-20 23:49:10 +02:00
|
|
|
* The allowed methods dictate whether it's read-only (``COAP_GET``) or
|
|
|
|
* read-write (``COAP_GET | COAP_PUT | COAP_DELETE``).
|
2022-08-01 13:51:52 +02:00
|
|
|
* If you want to support ``PUT`` and `DELETE`, you need to enable the modules
|
2023-10-30 15:32:01 +01:00
|
|
|
* ``nanocoap_fileserver_put`` and ``nanocoap_fileserver_delete``.
|
2020-10-24 00:43:24 +02:00
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Resource handler for the CoAP file system server
|
|
|
|
*
|
|
|
|
* @author chrysn <chrysn@fsfe.org>
|
|
|
|
*/
|
|
|
|
|
2023-10-30 15:32:01 +01:00
|
|
|
#ifndef NET_NANOCOAP_FILESERVER_H
|
|
|
|
#define NET_NANOCOAP_FILESERVER_H
|
2020-10-24 00:43:24 +02:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "net/nanocoap.h"
|
|
|
|
|
2022-07-26 00:24:39 +02:00
|
|
|
/**
|
|
|
|
* @brief Randomly generated Etag, used by a client when a directory should only be
|
|
|
|
* deleted, if it is empty
|
|
|
|
*/
|
|
|
|
#define COAPFILESERVER_DIR_DELETE_ETAG (0x6ce88b56u)
|
|
|
|
|
2022-08-05 22:07:51 +02:00
|
|
|
/**
|
|
|
|
* @brief GCoAP fileserver event types
|
|
|
|
*
|
2023-10-30 15:32:01 +01:00
|
|
|
* @note This requires the nanocoap_fileserver_callback module.
|
2022-08-05 22:07:51 +02:00
|
|
|
*/
|
|
|
|
typedef enum {
|
2023-10-30 15:32:01 +01:00
|
|
|
NANOCOAP_FILESERVER_GET_FILE_START, /**< file download started */
|
|
|
|
NANOCOAP_FILESERVER_GET_FILE_END, /**< file download finished */
|
|
|
|
NANOCOAP_FILESERVER_PUT_FILE_START, /**< file upload started */
|
|
|
|
NANOCOAP_FILESERVER_PUT_FILE_END, /**< file upload finished */
|
|
|
|
NANOCOAP_FILESERVER_DELETE_FILE, /**< file deletion requested
|
2022-08-05 22:07:51 +02:00
|
|
|
(called before file is deleted) */
|
2023-10-30 15:32:01 +01:00
|
|
|
} nanocoap_fileserver_event_t;
|
2022-08-05 22:07:51 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief GCoAP fileserver event context
|
|
|
|
*/
|
|
|
|
typedef struct {
|
|
|
|
const char *path; /**< VFS path of the affected file */
|
|
|
|
void *user_ctx; /**< Optional user supplied context */
|
2023-10-30 15:32:01 +01:00
|
|
|
} nanocoap_fileserver_event_ctx_t;
|
2022-08-05 22:07:51 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief GCoAP fileserver event callback type
|
|
|
|
*
|
|
|
|
* @param[in] event Type of the event
|
|
|
|
* @param[in] ctx Event context information
|
|
|
|
*
|
|
|
|
*/
|
2023-10-30 15:32:01 +01:00
|
|
|
typedef void (*nanocoap_fileserver_event_handler_t)(nanocoap_fileserver_event_t event,
|
|
|
|
nanocoap_fileserver_event_ctx_t *ctx);
|
2022-08-05 22:07:51 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Register a consumer for GCoAP fileserver events
|
2023-10-30 15:32:01 +01:00
|
|
|
* Requires the `nanocoap_fileserver_callback` module
|
2022-08-05 22:07:51 +02:00
|
|
|
*
|
|
|
|
* The Callback is called on each fileserver event and executed
|
|
|
|
* within the GCoAP thread.
|
|
|
|
*
|
|
|
|
* @param[in] cb The callback function to be called on events
|
|
|
|
* @param[in] arg Custom callback function context
|
|
|
|
*
|
|
|
|
*/
|
2023-10-30 15:32:01 +01:00
|
|
|
void nanocoap_fileserver_set_event_cb(nanocoap_fileserver_event_handler_t cb, void *arg);
|
2022-08-05 22:07:51 +02:00
|
|
|
|
2020-10-24 00:43:24 +02:00
|
|
|
/**
|
|
|
|
* @brief File server handler
|
|
|
|
*
|
|
|
|
* Serve a directory from the VFS as a CoAP resource tree.
|
2023-10-30 15:32:01 +01:00
|
|
|
* @see net_nanocoap_fileserver
|
2020-10-24 00:43:24 +02:00
|
|
|
*
|
|
|
|
* @param[in] pdu CoAP request package
|
|
|
|
* @param[out] buf Buffer for the response
|
|
|
|
* @param[in] len Response buffer length
|
2022-05-23 22:57:42 +02:00
|
|
|
* @param[in] ctx pointer to a @ref coap_request_ctx_t
|
2020-10-24 00:43:24 +02:00
|
|
|
*
|
|
|
|
* @return size of the response on success
|
|
|
|
* negative error
|
|
|
|
*/
|
2023-10-30 15:32:01 +01:00
|
|
|
ssize_t nanocoap_fileserver_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|
|
|
coap_request_ctx_t *ctx);
|
2020-10-24 00:43:24 +02:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-10-30 15:32:01 +01:00
|
|
|
#endif /* NET_NANOCOAP_FILESERVER_H */
|
2020-10-24 00:43:24 +02:00
|
|
|
|
|
|
|
/** @} */
|