Skip to content

net/gcoap: add context struct for request handler#13819

Closed
kb2ma wants to merge 1 commit intoRIOT-OS:masterfrom
kb2ma:gcoap/recv_ctx
Closed

net/gcoap: add context struct for request handler#13819
kb2ma wants to merge 1 commit intoRIOT-OS:masterfrom
kb2ma:gcoap/recv_ctx

Conversation

@kb2ma
Copy link
Copy Markdown
Member

@kb2ma kb2ma commented Apr 5, 2020

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_t struct 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:

   printf("Resource path: %s\n", ((gcoap_req_ctx_t *)ctx)->resource->path);

Also review the documentation update in the first paragraph of the Creating a response section.

Issues/PRs references

Alternative to #13621

@kb2ma kb2ma added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: CoAP Area: Constrained Application Protocol implementations labels Apr 5, 2020
@kb2ma kb2ma requested a review from kaspar030 April 5, 2020 13:13
@kb2ma
Copy link
Copy Markdown
Member Author

kb2ma commented Apr 5, 2020

@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. :-)

@haukepetersen
Copy link
Copy Markdown
Contributor

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.

@haukepetersen haukepetersen added Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines labels May 19, 2020
@haukepetersen haukepetersen added the Reviewed: 3-testing The PR was tested according to the maintainer guidelines label May 19, 2020
@haukepetersen
Copy link
Copy Markdown
Contributor

done, works flawless as far as I can tell.

Copy link
Copy Markdown
Contributor

@haukepetersen haukepetersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK from my side.

@miri64 miri64 added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label May 19, 2020
@kb2ma
Copy link
Copy Markdown
Member Author

kb2ma commented May 19, 2020

Let's please delay the merge. I plan to review later today. It looks like there is a spurious build issue also.

@kb2ma
Copy link
Copy Markdown
Member Author

kb2ma commented May 20, 2020

@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.

@haukepetersen
Copy link
Copy Markdown
Contributor

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 slicer struct is used when sending out data, correct? And the gcoap_req_ctx_t struct is used when handling incoming CoAP packets. So I take it, that all/most? of the additional fields are valid in one or the other direction?! Maybe we can decouple nanocoap and gcoap by doing the following:

  • in nanocoap: add an additional, generic void * pointer to coap_pkt_t, possibly '#ifdef'd for gcoap and potentially other high-level 'users' of nanocoaop. Let's call it ext for now
  • in gcoap: add three separate structs:
    1. one for holding data that is of interested for incoming packets, e.g. the remote endpoint, a pointer to the ressource itself, etc (like gcoap_req_ctx_t in this PR). Also the observe_value that is now part of coap_pkt_t could be a candidate field for this.
    2. one for holding data that is useful when preparing data that is send (gcoap_tx_txt_t?). This struct could hold context data for preparing packets that are to be send, e.g. a reference to the slicer struct?
    3. one to rule them all, ähm, one to tie them together, e.g. gcoap_ctx_t. This struct holds a union that opts for one of the two structs above, and in addition it could have a bitmap style field so that the implementation can check at runtime which of the contexts is active.

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 nanocoap (coap_pkt_t) anymore, subsequently decoupling nanocoap and gcoap better.

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!

@benpicco benpicco added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels May 25, 2020
@kb2ma kb2ma closed this Jun 16, 2020
@miri64 miri64 added the State: archived State: The PR has been archived for possible future re-adaptation label Jun 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: CoAP Area: Constrained Application Protocol implementations CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines State: archived State: The PR has been archived for possible future re-adaptation Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants