diff --git a/examples/nanocoap_server/Makefile b/examples/nanocoap_server/Makefile index 9f8b91f201b8d..e25633df92ec3 100644 --- a/examples/nanocoap_server/Makefile +++ b/examples/nanocoap_server/Makefile @@ -47,6 +47,13 @@ endif HIGH_MEMORY_BOARDS := native same54-xpro mcb2388 ifneq (,$(filter $(BOARD),$(HIGH_MEMORY_BOARDS))) + # enable separate response + USEMODULE += sock_aux_local + USEMODULE += event_callback + USEMODULE += event_thread + USEMODULE += event_timeout_ztimer + + # enable fileserver USEMODULE += nanocoap_fileserver USEMODULE += vfs_default diff --git a/examples/nanocoap_server/coap_handler.c b/examples/nanocoap_server/coap_handler.c index 2a04452b9fdfd..f1f0a98bedd08 100644 --- a/examples/nanocoap_server/coap_handler.c +++ b/examples/nanocoap_server/coap_handler.c @@ -10,8 +10,12 @@ #include #include +#include "event/callback.h" +#include "event/timeout.h" +#include "event/thread.h" #include "fmt.h" #include "net/nanocoap.h" +#include "net/nanocoap_sock.h" #include "hashes/sha256.h" #include "kernel_defines.h" @@ -182,6 +186,48 @@ NANOCOAP_RESOURCE(sha256) { .path = "/sha256", .methods = COAP_POST, .handler = _sha256_handler }; +/* separate response requires an event thread to execute it */ +#ifdef MODULE_EVENT_THREAD +static nanocoap_sock_response_ctx_t _separate_ctx; +static bool _separate_in_progress; + +static void _send_response(void *ctx) +{ + const char response[] = "This is a delayed response."; + + puts("_separate_handler(): send delayed response"); + nanocoap_sock_send_separate(ctx, COAP_CODE_CONTENT, COAP_TYPE_NON, + response, sizeof(response)); + _separate_in_progress = false; +} + +static ssize_t _separate_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, coap_request_ctx_t *context) +{ + static event_timeout_t event_timeout; + static event_callback_t event_timed = EVENT_CALLBACK_INIT(_send_response, &_separate_ctx); + + if (_separate_in_progress) { + puts("_separate_handler(): response already scheduled"); + return coap_build_reply(pkt, COAP_CODE_SERVICE_UNAVAILABLE, buf, len, 0); + } + + puts("_separate_handler(): send ACK, schedule response"); + + nanocoap_sock_prepare_separate(&_separate_ctx, pkt, context); + _separate_in_progress = true; + + event_timeout_ztimer_init(&event_timeout, ZTIMER_MSEC, EVENT_PRIO_MEDIUM, + &event_timed.super); + event_timeout_set(&event_timeout, 1 * MS_PER_SEC); + + return coap_build_empty_ack(pkt, buf, len); +} + +NANOCOAP_RESOURCE(separate) { + .path = "/separate", .methods = COAP_GET, .handler = _separate_handler, +}; +#endif /* MODULE_EVENT_THREAD */ + /* we can also include the fileserver module */ #ifdef MODULE_NANOCOAP_FILESERVER #include "net/nanocoap/fileserver.h"