Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nanocoap: Add functions to handle etag options #19980

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

bergzand
Copy link
Member

Contribution description

This adds 3 functions for adding entity-tags to coap packets. The first
simply adds the option to the coap packet with the supplied etag value.
The second functionallow for adding a dummy etag value which is to be
replaced later by the last function. This allows for allocating space
for the option up front when the etag value itself is generated based on
the payload.

I also did a quick replace of coap_opt_add_opaque(pdu, COAP_OPT_ETAG…) in other sources.

Testing procedure

Added the option to one of the handlers of the gcoap_block_server example to test this.

The response result should look like this in wireshark:

image

Issues/PRs references

None

This adds 3 functions for adding entity-tags to coap packets. The first
simply adds the option to the coap packet with the supplied etag value.
The second functionallow for adding a dummy etag value which is to be
replaced later by the last function. This allows for allocating space
for the option up front when the etag value itself is generated based on
the payload
@bergzand bergzand added the Type: new feature The issue requests / The PR implemements a new feature for RIOT label Oct 17, 2023
@github-actions github-actions bot added Area: network Area: Networking Area: CoAP Area: Constrained Application Protocol implementations Area: sys Area: System Area: examples Area: Example Applications labels Oct 17, 2023
chrysn
chrysn previously approved these changes Oct 17, 2023
@chrysn
Copy link
Member

chrysn commented Oct 17, 2023 via email

Comment on lines 1546 to 1547
* @note The @p len supplied to this call must match the length supplied to the call to add the
* etag option
Copy link
Member

Choose a reason for hiding this comment

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

This makes this function basically unusable for cache re-validation at the client. Unless the user somehow looks up the cache entry and fetches the exact length the server supplied. But for that they need a somewhat complete request (ignoring questions which are not accounted for in cache key validation), which causes a bootstrapping problem. Its why I did the complicated dance of adding a full-length COAP_ETAG_LENGTH_MAX dummy ETag in 728c7d6 first only to use memmove later to reduce the size if necessary.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure what to do here. For me the use case here was limited to known etag lengths for generating server responses.
I think it would significantly increase complexity of replacing the etag if you want to relax this condition. It would also mean informing the user of the function with how many bytes were removed from the packet.

At this point it might be easier to have a generic coap_opt_insert_opaque()

Copy link
Member

Choose a reason for hiding this comment

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

Such applications can still use coap_opt_add_etag. When building a response from a cache or from a response received from the network, I'd expect that building the response only happens when the input is fully available, and thus the ETag can be calculated. Only when the ETag is calculated on the fly while populating the payload, then the two-part dummy steps are needed. (But to be fair, I don't quite understand what the nanocoap cache ETag tricks do in your linked commit in the first place).

Copy link
Member

Choose a reason for hiding this comment

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

(But to be fair, I don't quite understand what the nanocoap cache ETag tricks do in your linked commit in the first place).

It assumes that the client user does not need to know about the cache. So to allow for cache validation (i.e. get the ETag from the cache) it adds first a dummy ETag option of full length on request initialization and then populates it once it has a cache hit before send. Since that ETag comes from the server, it can be of any length, so the dummy option needs to be resized (after cache key calculation, so basically after the whole message is already constructed).

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I managed to rewrite this to allow for arbitrary etag sizes in the replace code, as long as the initial etag was larger than the new etag. The added complexity is not as much as I initially expected, but I'm rather curious whether I'm covering all edge cases. I'm also not very happy with the footgun that might be the return value

The example code does seem to still work though.

@github-actions github-actions bot added the Area: tests Area: tests and testing framework label Oct 18, 2023
@benpicco benpicco added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Oct 18, 2023
@riot-ci
Copy link

riot-ci commented Oct 18, 2023

Murdock results

✔️ PASSED

feaa274 fixup! fixup! fixup! fixup! fixup! fixup! nanocoap: Add functions to handle etag options

Success Failures Total Runtime
7937 0 7937 17m:26s

Artifacts

@bergzand bergzand requested a review from chrysn October 19, 2023 12:04
@bergzand bergzand dismissed chrysn’s stale review October 19, 2023 12:05

Code got changed sufficiently to warrant another look

@github-actions github-actions bot added the Area: pkg Area: External package ports label Oct 19, 2023
@bergzand bergzand force-pushed the pr/nanocoap/etag_handling branch from e3abe4d to 5e45fd7 Compare October 19, 2023 14:31
@github-actions github-actions bot removed the Area: pkg Area: External package ports label Oct 19, 2023
memmove(opt + new_len, rest_of_the_packet, end_of_the_packet - rest_of_the_packet);

/* Update the payload data */
pkt->payload += len_diff;
Copy link
Member

Choose a reason for hiding this comment

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

Could this move pkt->payload before the CoAP header or is there a sanity check for that beforehand?

Copy link
Member Author

Choose a reason for hiding this comment

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

The gut feeling says no, all pointer values here are grabbed from parse functions already in nanocoap.

The only way I see this happening is when the payload ptr is already incorrect or when the dummy etag value was shorter than the new one.

Copy link
Member

@miri64 miri64 Oct 20, 2023

Choose a reason for hiding this comment

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

[…] or when the dummy etag value was shorter than the new one.

Sounds like there should be a check at least a (pkt->payload + len_diff) < opt check, just to avoid stupidity ;-)

Copy link
Member Author

Choose a reason for hiding this comment

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

Sounds like there should be a check at least a (pkt->payload + len_diff) < opt check, just to avoid stupidity ;-)

API misuse should already be covered by the assert(opt_len >= len). I can add another assert, however I think this mostly results in sanity testing nanocoap internal functions.

But maybe a second look from somebody else well versed in pointer magic might help here as maybe I'm missing an edge case.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I think an assert would be enough in this case, just to make sure the pre-conditions are met.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added


/* Update the payload data */
pkt->payload += len_diff;
pkt->payload_len += len_diff;
Copy link
Member

Choose a reason for hiding this comment

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

The payload length should not be affected by the option shortening, so please remove this line ;-)

Copy link
Member Author

Choose a reason for hiding this comment

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

Well spotted, fixed!

@bergzand
Copy link
Member Author

@miri64 I don't really feel confident in patching the rest of the cache code to also use the coap_opt_replace_etag() there. Do you have a patch for me or do we leave that as is for now?

@miri64
Copy link
Member

miri64 commented Oct 20, 2023

@miri64 I don't really feel confident in patching the rest of the cache code to also use the coap_opt_replace_etag() there. Do you have a patch for me or do we leave that as is for now?

I don't have a patch, so let's leave it as is for now. Make very ephemeral mental note to fix this at some point.

@Teufelchen1
Copy link
Contributor

Cheekily taking that audacity to ping;
@chrysn is the unittest sufficient? Can your comment be resolved?
@miri64 You also have two unresolved comments that seem to be addressed?
@bergzand beside the unresolved comments; Is anything else blocking you here?

@chrysn
Copy link
Member

chrysn commented Jan 24, 2024 via email

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 Area: examples Area: Example Applications Area: network Area: Networking Area: sys Area: System Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants