mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 04:52:59 +01:00
Merge #18414
18414: gcoap/fileserver: add event callbacks r=benpicco a=benpicco Co-authored-by: Benjamin Valentin <benjamin.valentin@ml-pa.com>
This commit is contained in:
commit
d6f44f6206
@ -21,6 +21,7 @@ USEMODULE += shell_cmds_default
|
|||||||
|
|
||||||
# enable the fileserver module
|
# enable the fileserver module
|
||||||
USEMODULE += gcoap_fileserver
|
USEMODULE += gcoap_fileserver
|
||||||
|
USEMODULE += gcoap_fileserver_callback
|
||||||
USEMODULE += gcoap_fileserver_delete
|
USEMODULE += gcoap_fileserver_delete
|
||||||
USEMODULE += gcoap_fileserver_put
|
USEMODULE += gcoap_fileserver_put
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include "kernel_defines.h"
|
#include "kernel_defines.h"
|
||||||
#include "net/gcoap.h"
|
#include "net/gcoap.h"
|
||||||
#include "net/gcoap/fileserver.h"
|
#include "net/gcoap/fileserver.h"
|
||||||
@ -45,11 +46,36 @@ static gcoap_listener_t _listener = {
|
|||||||
.resources_len = ARRAY_SIZE(_resources),
|
.resources_len = ARRAY_SIZE(_resources),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void _event_cb(gcoap_fileserver_event_t event, gcoap_fileserver_event_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case GCOAP_FILESERVER_GET_FILE_START:
|
||||||
|
printf("gcoap fileserver: Download started: %s\n", ctx->path);
|
||||||
|
break;
|
||||||
|
case GCOAP_FILESERVER_GET_FILE_END:
|
||||||
|
printf("gcoap fileserver: Download finished: %s\n", ctx->path);
|
||||||
|
break;
|
||||||
|
case GCOAP_FILESERVER_PUT_FILE_START:
|
||||||
|
printf("gcoap fileserver: Upload started: %s\n", ctx->path);
|
||||||
|
break;
|
||||||
|
case GCOAP_FILESERVER_PUT_FILE_END:
|
||||||
|
printf("gcoap fileserver: Upload finished: %s\n", ctx->path);
|
||||||
|
break;
|
||||||
|
case GCOAP_FILESERVER_DELETE_FILE:
|
||||||
|
printf("gcoap fileserver: Delete %s\n", ctx->path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||||
gcoap_register_listener(&_listener);
|
gcoap_register_listener(&_listener);
|
||||||
|
|
||||||
|
if (IS_USED(MODULE_GCOAP_FILESERVER_CALLBACK)) {
|
||||||
|
gcoap_fileserver_set_event_cb(_event_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||||
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
|
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ PSEUDOMODULES += fatfs_vfs_format
|
|||||||
PSEUDOMODULES += fmt_%
|
PSEUDOMODULES += fmt_%
|
||||||
PSEUDOMODULES += gcoap_forward_proxy
|
PSEUDOMODULES += gcoap_forward_proxy
|
||||||
PSEUDOMODULES += gcoap_fileserver
|
PSEUDOMODULES += gcoap_fileserver
|
||||||
|
PSEUDOMODULES += gcoap_fileserver_callback
|
||||||
PSEUDOMODULES += gcoap_fileserver_delete
|
PSEUDOMODULES += gcoap_fileserver_delete
|
||||||
PSEUDOMODULES += gcoap_fileserver_put
|
PSEUDOMODULES += gcoap_fileserver_put
|
||||||
PSEUDOMODULES += gcoap_dtls
|
PSEUDOMODULES += gcoap_dtls
|
||||||
|
@ -90,6 +90,51 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define COAPFILESERVER_DIR_DELETE_ETAG (0x6ce88b56u)
|
#define COAPFILESERVER_DIR_DELETE_ETAG (0x6ce88b56u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GCoAP fileserver event types
|
||||||
|
*
|
||||||
|
* @note This requires the gcoap_fileserver_callback module.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
GCOAP_FILESERVER_GET_FILE_START, /**< file download started */
|
||||||
|
GCOAP_FILESERVER_GET_FILE_END, /**< file download finished */
|
||||||
|
GCOAP_FILESERVER_PUT_FILE_START, /**< file upload started */
|
||||||
|
GCOAP_FILESERVER_PUT_FILE_END, /**< file upload finished */
|
||||||
|
GCOAP_FILESERVER_DELETE_FILE, /**< file deletion requested
|
||||||
|
(called before file is deleted) */
|
||||||
|
} gcoap_fileserver_event_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GCoAP fileserver event context
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const char *path; /**< VFS path of the affected file */
|
||||||
|
void *user_ctx; /**< Optional user supplied context */
|
||||||
|
} gcoap_fileserver_event_ctx_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GCoAP fileserver event callback type
|
||||||
|
*
|
||||||
|
* @param[in] event Type of the event
|
||||||
|
* @param[in] ctx Event context information
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef void (*gcoap_fileserver_event_handler_t)(gcoap_fileserver_event_t event,
|
||||||
|
gcoap_fileserver_event_ctx_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a consumer for GCoAP fileserver events
|
||||||
|
* Requires the `gcoap_fileserver_callback` module
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void gcoap_fileserver_set_event_cb(gcoap_fileserver_event_handler_t cb, void *arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief File server handler
|
* @brief File server handler
|
||||||
*
|
*
|
||||||
|
@ -34,6 +34,21 @@
|
|||||||
/** Maximum length of an expressible path, including the trailing 0 character. */
|
/** Maximum length of an expressible path, including the trailing 0 character. */
|
||||||
#define COAPFILESERVER_PATH_MAX (64)
|
#define COAPFILESERVER_PATH_MAX (64)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fileserver event callback, only used with `gcoap_fileserver_callback`
|
||||||
|
*/
|
||||||
|
static gcoap_fileserver_event_handler_t _event_cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fileserver event callback context, only used with `gcoap_fileserver_callback`
|
||||||
|
*/
|
||||||
|
static void *_event_ctx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fileserver event mutex, protects event cb and event ctx from concurrent access
|
||||||
|
*/
|
||||||
|
static mutex_t _event_mtx;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure holding information about present options in a request
|
* @brief Structure holding information about present options in a request
|
||||||
*/
|
*/
|
||||||
@ -146,6 +161,26 @@ static void _calc_szx2(coap_pkt_t *pdu, size_t reserve, coap_block1_t *block2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void _event_file(gcoap_fileserver_event_t event, struct requestdata *request)
|
||||||
|
{
|
||||||
|
if (!IS_USED(MODULE_GCOAP_FILESERVER_CALLBACK)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&_event_mtx);
|
||||||
|
gcoap_fileserver_event_ctx_t ctx = {
|
||||||
|
.path = request->namebuf,
|
||||||
|
.user_ctx = _event_ctx,
|
||||||
|
};
|
||||||
|
|
||||||
|
gcoap_fileserver_event_handler_t cb = _event_cb;
|
||||||
|
mutex_unlock(&_event_mtx);
|
||||||
|
|
||||||
|
if (cb) {
|
||||||
|
cb(event, &ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t _get_file(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
static ssize_t _get_file(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
||||||
struct requestdata *request)
|
struct requestdata *request)
|
||||||
{
|
{
|
||||||
@ -193,6 +228,10 @@ static ssize_t _get_file(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
goto late_err;
|
goto late_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (block2.blknum == 0) {
|
||||||
|
_event_file(GCOAP_FILESERVER_GET_FILE_START, request);
|
||||||
|
}
|
||||||
|
|
||||||
/* That'd only happen if the buffer is too small for even a 16-byte block,
|
/* That'd only happen if the buffer is too small for even a 16-byte block,
|
||||||
* or if the above calculations were wrong.
|
* or if the above calculations were wrong.
|
||||||
*
|
*
|
||||||
@ -218,6 +257,10 @@ static ssize_t _get_file(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
read -= 1;
|
read -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!more) {
|
||||||
|
_event_file(GCOAP_FILESERVER_GET_FILE_END, request);
|
||||||
|
}
|
||||||
|
|
||||||
return resp_len + read;
|
return resp_len + read;
|
||||||
|
|
||||||
late_err:
|
late_err:
|
||||||
@ -257,6 +300,8 @@ static ssize_t _put_file(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
ret = COAP_CODE_PRECONDITION_FAILED;
|
ret = COAP_CODE_PRECONDITION_FAILED;
|
||||||
goto unlink_on_error;
|
goto unlink_on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_event_file(GCOAP_FILESERVER_PUT_FILE_START, request);
|
||||||
}
|
}
|
||||||
if (request->options.exists.if_match) {
|
if (request->options.exists.if_match) {
|
||||||
stat_etag(&stat, &etag); /* Etag before write */
|
stat_etag(&stat, &etag); /* Etag before write */
|
||||||
@ -316,6 +361,9 @@ static ssize_t _put_file(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
goto unlink_on_error;
|
goto unlink_on_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_event_file(GCOAP_FILESERVER_PUT_FILE_END, request);
|
||||||
|
|
||||||
stat_etag(&stat, &etag); /* Etag after write */
|
stat_etag(&stat, &etag); /* Etag after write */
|
||||||
gcoap_resp_init(pdu, buf, len, create ? COAP_CODE_CREATED : COAP_CODE_CHANGED);
|
gcoap_resp_init(pdu, buf, len, create ? COAP_CODE_CREATED : COAP_CODE_CHANGED);
|
||||||
coap_opt_add_opaque(pdu, COAP_OPT_ETAG, &etag, sizeof(etag));
|
coap_opt_add_opaque(pdu, COAP_OPT_ETAG, &etag, sizeof(etag));
|
||||||
@ -353,6 +401,9 @@ static ssize_t _delete_file(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
return gcoap_fileserver_error_handler(pdu, buf, len, COAP_CODE_PRECONDITION_FAILED);
|
return gcoap_fileserver_error_handler(pdu, buf, len, COAP_CODE_PRECONDITION_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_event_file(GCOAP_FILESERVER_DELETE_FILE, request);
|
||||||
|
|
||||||
if ((ret = vfs_unlink(request->namebuf)) < 0) {
|
if ((ret = vfs_unlink(request->namebuf)) < 0) {
|
||||||
return gcoap_fileserver_error_handler(pdu, buf, len, ret);
|
return gcoap_fileserver_error_handler(pdu, buf, len, ret);
|
||||||
}
|
}
|
||||||
@ -650,4 +701,16 @@ error:
|
|||||||
return gcoap_response(pdu, buf, len, errorcode);
|
return gcoap_response(pdu, buf, len, errorcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_GCOAP_FILESERVER_CALLBACK
|
||||||
|
void gcoap_fileserver_set_event_cb(gcoap_fileserver_event_handler_t cb, void *ctx)
|
||||||
|
{
|
||||||
|
mutex_lock(&_event_mtx);
|
||||||
|
|
||||||
|
_event_cb = cb;
|
||||||
|
_event_ctx = ctx;
|
||||||
|
|
||||||
|
mutex_unlock(&_event_mtx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
Loading…
Reference in New Issue
Block a user