RIOT icon indicating copy to clipboard operation
RIOT copied to clipboard

gcoap/fileserver: add event callbacks

Open benpicco opened this issue 3 years ago • 4 comments

Contribution description

When serving updates via GCoAP fileserver it turned out to be useful to know if a node started downloading the update and when it finished doing so.

But there are probably more use cases where some action might be taken or logged based on the events on the GCoAP fileserver.

This adds 5 event types:

  • GCOAP_FILESERVER_GET_START: file download started (block 0 requested)
  • GCOAP_FILESERVER_GET_END: file download finished (last block requested)
  • GCOAP_FILESERVER_PUT_START:file upload started (block 0 uploaded)
  • GCOAP_FILESERVER_PUT_END: file upload finished (last block uploaded)
  • GCOAP_FILESERVER_DELETE:file deletion requested

Testing procedure

To be a able to test this, the new callback module is enabled for examples/gcoap_fileserver to log file events:

> ls /nvm0
./
../
LICENSE	24310 B
hello.txt	15 B
main.c	27 B
total 3 files
          
> gcoap fileserver: Download started: /nvm0/hello.txt
gcoap fileserver: Download finished: /nvm0/hello.txt
aiocoap-client coap://[fe80::748f:e6ff:fed7:426d%tapbr0]/vfs/hello.txt

Issues/PRs references

benpicco avatar Aug 08 '22 07:08 benpicco

Just to get the architectural review side out -- making sure more generally useful alternatives have been considered:

  • This would hook into the specific interface between CoAP and the file service. Might it not make more sense to monitor things on the file system side, or on the CoAP side? (on the file system side it might behave like inotify, on the CoAP side like log hooks).

  • What are use cases and possible extensions of this? (An extension I could envision is that at some point one might need to know who sent the request, and thus extend gcoap_fileserver_event_ctx_t, so maybe that should be private).

On use cases, note that CoAP GET is supposed to be side effect free; now we don't, can't and won't generally enforce this in RIOT, but reacting to a GET event in any other facility than logging (at which point I'd go back whether this might not be just for logging generic CoAP requests or file system access) sounds like an invitation to do side effects, and might need a warning.

chrysn avatar Aug 08 '22 08:08 chrysn

My use case is: I have multiple sensors that I want to update, since communication happens over a bus I want to update one sensor at a time to avoid contention. (The sensor network might also only be turned on for the updates when it's otherwise in an OFF state. So I want to know when all sensors have received the update to return to the original state again)

Updates are sometimes unreliable, especially with the old firmware revision. So I want to know: Was the manifest accepted (GCOAP_FILESERVER_GET_START on the ".bin" file) and finally: Did the update download successfully (GCOAP_FILESERVER_GET_END on the ".bin" file).

You are right that it would probably be better to use a second channel to communicate those events (e.g. the sensors would send them explicitly). But that won't help with sensors already deployed that don't send those yet to be implemented status messages - so server side events were an easy solution to this problem.

If more context information is required for other use cases, gcoap_fileserver_event_ctx_t can be extended without changing the API.

benpicco avatar Aug 08 '22 08:08 benpicco

The first thing I asked myself, was whether _event_cb and _event_ctx should be protected in some way by a mutex or atomic accesses because they are static variables and are read in the gcoap thread and can be written by any other thread using gcoap_fileserver_set_event_cb(), or if we just assume that they are set once, before requests are being processed. But if they are set once, we could as well make _event_cb a classic __attribute__((weak)) hook and _event_ctx an extern variable, I guess. Any opinions on that?

fabian18 avatar Aug 08 '22 22:08 fabian18

I realized that I want to unsubscribe from those events, so I'll go with the mutex.

benpicco avatar Sep 14 '22 14:09 benpicco

Someone might be wondering why it is only implemented for files?

I didn't see the need for it yet - should I add it anyway?

benpicco avatar Jan 14 '23 22:01 benpicco

The msg_bus module just came to my mind. Have you considered this as an alternative to callbacks, since you already said that you would like to be able to "unsubscribe"? This may also be done in the future I guess.

fabian18 avatar Jan 15 '23 11:01 fabian18

This could be implemented on top, but I'd like to avoid IPC if not necessary.

benpicco avatar Jan 15 '23 11:01 benpicco

Ok please squash.

fabian18 avatar Jan 16 '23 09:01 fabian18

bors merge

benpicco avatar Jan 16 '23 22:01 benpicco

Build succeeded:

bors[bot] avatar Jan 17 '23 01:01 bors[bot]

Thank you for the review!

benpicco avatar Jan 17 '23 01:01 benpicco