net/gcoap: add context struct for request handler#13819
net/gcoap: add context struct for request handler#13819kb2ma wants to merge 1 commit intoRIOT-OS:masterfrom
Conversation
|
@haukepetersen, I assume from the RIOT tradition that absence of a response to my comment in #13621 means you are not violently opposed to the idea here. :-) |
|
Yes, your assumption is correct. I like this approach and agree that it is much cleaner then my quick hack in #13621. So lets take this path. Code wise this PR looks good to me, I will now rebase my experiment branch on top of this change to verify that it also works as expected. |
|
done, works flawless as far as I can tell. |
|
Let's please delay the merge. I plan to review later today. It looks like there is a spurious build issue also. |
|
@haukepetersen, I asked for delay here because I now think the approach here is too limiting. Since I wrote this PR, I also wrote an RFC for a generic payload writer in #13942 that supports both writing a self contained payload as well as a block payload. For that task, the simplest approach was to add a pointer to the slicer struct to the coap_pkt_t. I realized that the reason addition to the coap_pkt_t was compelling is that it is used essentially everywhere in gcoap. The issue with the solution there is that it directly attaches the slicer to the coap_pkt_t, similar to #13621 attachment of sock_udp_ep_t to the pkt struct. So I think a more comprehensive solution will serve us well. Rather than putting the context struct in the resource handler callback as proposed here, I am in favor of attaching some sort of generic context parameter directly to the PDU, maybe as a void pointer. Then we can add whatever we need in the future, as we need it, without breaking APIs. Maybe we also will need some sort of bitwise capabilities attribute to identify what is available in the context in any particular scenario. I'd appreciate your thoughts on this idea. |
|
Yapp, a more comprehensive solution is always most welcome - I kind of hate you for going this path :-) But seriously, I agree that we can probably do better here if we think about this some more. So when I understand #13942 correctly, the
All of these three structs can be extended at anytime, without any API braking, right? Also, any changes in these structs do not require any changes to Furthermore there is no (or at least less) wasted memory for fields that have only validity in send/receive direction. In terms of usability, we might then also provide some kind of user facing functions that accesses the given context. E.g. in a ressource handler implementation, instead of using something like ssize_t _some_ressource_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
{
// try to get the remote endpoint
sock_udp_ep_t *ep = pkt->ext->req_ctx->remote;
....
}we might want to do something like ssize_t _some_ressource_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
{
// try to get the remote endpoint
gcoap_req_ctx_t *rc = gcoap_get_req_ctx(pkt); // -> this would return NULL if called from the wrong context...
sock_udp_ep_t *ep = rc->remote;
....
}Does this make sense? And did I miss something here? Looking forward to advancing on this! |
Contribution description
The nanocoap request handler callback, coap_handler_t, limits context data to the user context parameter from the resource for the request. However, an application may need more context information. For example, #13621 adds a reference to the remote endpoint for the request in the coap_pkt_t struct. As I pointed out in a comment, addition of the remote reference in this struct is not a great fit.
So, the PR here proposes addition of a
gcoap_req_ctx_tstruct that is passed to the application as the void pointer for the request callback. This struct holds the remote endpoint from #13621 as well as the application resource for the request, which provides access to the resource's user context attribute. This approach solves the original problem and provides a mechanism for passing more context data to the handler in the future as needed.On the down side, it is possible that existing gcoap applications already use the user context parameter, and will break with this update. I think this risk is acceptable because the nature of the context parameter in the callback has not been explicitly stated in the gcoap or nanocoap documentation. This PR also updates the gcoap documentation to describe the contents of the context parameter.
Testing procedure
The gcoap example does not use the context parameter, but you can modify it to do so in one of the request handlers with code like:
Also review the documentation update in the first paragraph of the Creating a response section.
Issues/PRs references
Alternative to #13621