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

[WIP] sys/net/*coap: Make APIs (more) transport agnostic #20900

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

maribu
Copy link
Member

@maribu maribu commented Oct 9, 2024

Contribution description

This changes the API of nanocoap with the goal to reduce the expose of UDP specifics in the API. The plan is to eventually support transports such as CoAP over TCP and CoAP over WebSocket directly in nanocoap while sharing most of the code, as e.g. the CoAP Option processing remains identical. Specifically, the plan is to unlock a transport with modules and introduce overhead for dispatching to specific transport only when multiple transports are actually in use.

Support for OSCORE directly in nanocoap is probably not sensible, as the serialization is very much unlike the other transports. A unified CoAP API for multiple transports including OSCORE is probably best implemented on top. But when limited to the boring set of CoAP transports, we probably can support them well with nanocoap with less overhead.

API Changes:

Breaking Changes without Deprecation

  • coap_pkt_t now contains a uint8_t *buf pointer instead of a
    coap_hdr_t * pointer to the beginning of the buffer
    • This will also work when the buffer is used by non-UDP
      transports

Application developers often have little need to touch this, so
hopefully this will not cause to many breakage. The breakage it causes
is easy to fix and spotted at compile time.

Breaking Changes with Deprecation

  • coap_hdr_t has been renamed to coap_udp_hdr_t
    • A deprecated alias was created for deprecation
  • coap_hdr*() functions have been deprecated
    • Equivalent coap_pkt*() functions have been created that work on coap_pkt_t * instead of coap_hdr_t *
  • coap_build_hdr() has been renamed to coap_build_udp_hdr() and that works on an uint8_t * buffer with a given length, rather than on a coap_hdr_t * with a figers crossed length
    • a deprecated coap_build_hdr() function was added that calls to coap_build_udp_hdr() and has the same signature, so that users have time to update

Internal users have been updated, except for tests.

The deprecated functions will probably exposed only when nanocoap is used with only UDP as transport, as those will wreak havoc on non-UDP CoAP packets. That should be fine, as existing apps hardly will make use of other transports anyway.

Testing procedure

Existing apps and tests should work as before. I will do some limited testing soon and do more rigorous testing once an implementation of nanocoap using TCP as transport is ready. Otherwise there are likely still UDP specifics in the API that I have overlooked.

Issues/PRs references

See also #20792

@github-actions github-actions bot added Area: network Area: Networking Area: tests Area: tests and testing framework Area: CoAP Area: Constrained Application Protocol implementations Area: sys Area: System Area: examples Area: Example Applications labels Oct 9, 2024
@maribu
Copy link
Member Author

maribu commented Oct 9, 2024

This PR is not ready for review yet, I just want to make the work more transparent.

@maribu maribu marked this pull request as draft October 9, 2024 11:45
@mguetschow
Copy link
Contributor

Cross-referencing @carl-tud's ongoing work with a superset of the goals of this one: #20792

@maribu maribu force-pushed the sys/net/nanocoap/transport-agnostic-api branch 4 times, most recently from 99877b3 to d832957 Compare October 14, 2024 11:12
@maribu maribu added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Oct 14, 2024
@riot-ci
Copy link

riot-ci commented Oct 14, 2024

Murdock results

✔️ PASSED

84cbedc examples/gcoap: upgrade users of deprecated nanocoap APIs

Success Failures Total Runtime
10214 0 10215 13m:15s

Artifacts

@maribu maribu force-pushed the sys/net/nanocoap/transport-agnostic-api branch 2 times, most recently from c13f6d0 to 34b0d34 Compare October 14, 2024 11:41
@chrysn
Copy link
Member

chrysn commented Oct 14, 2024

Could the .hdr pointer stay there unused and deprecated if none of the non-UDP gcoap modules are enabled?

Then users who just upgrade their applications would see a deprecation rather than breakage, and would just need to follow that deprecation's pointers ("use the setters and getters") before either they go to the next release or they enable any of the new modules. The Rust wrappers (affected in RIOT-OS/rust-riot-wrappers#129) could then do the same: use the old ways unless a new module is enabled, and after the next release they can go all-in with the new accessor, and thus always work with the current release and with the mai^Wmaster branch.

@chrysn
Copy link
Member

chrysn commented Oct 14, 2024

To clarify: If it's only the Rust wrappers affected, workarounds are possible (but necessary) to make things work there by detecting whether any code getter/setter is present. But if making it easier for riot-wrappers also eases other users' transitions, maybe we should do that. I can work with either outcome.

@maribu
Copy link
Member Author

maribu commented Oct 14, 2024

Could the .hdr pointer stay there unused and deprecated if none of the non-UDP gcoap modules are enabled?

I think adding an unnamed union containing .hdr and .buf if - and only if - only UDP is used would be a compromise. Having a .hdr when there is (possibly) no UDP header present is quite a footgun, as .hdr is tied towards a UDP header. We should also not have the union there when the CI is run, so that users of coap_pkt_t::hdr don't sneak back in.

@chrysn
Copy link
Member

chrysn commented Oct 14, 2024

Yes, an unnamed union .buf ∪ .hdr that only has the old item if that is legal (ie. UDP is the only transport) would be good.

CI should probably not interfere here because that'd also impede the Rust side -- but after the next release, the old item can go away anyway, and then we're enforcing the deprecation. Until then I think we'll have to rely on people following the deprecation.

@maribu maribu force-pushed the sys/net/nanocoap/transport-agnostic-api branch 2 times, most recently from 6cc1b64 to 061ca01 Compare October 15, 2024 19:45
@maribu maribu force-pushed the sys/net/nanocoap/transport-agnostic-api branch from 061ca01 to 104919c Compare October 16, 2024 21:18
@maribu
Copy link
Member Author

maribu commented Oct 16, 2024

@chrysn: The trick with the unnamed union to make hdr and buf aliases does not work for the Rust side:

error[E0609]: no field `hdr` on type `riot_sys::coap_pkt_t`
   --> /data/riotbuild/.cargo/git/checkouts/rust-riot-wrappers-155be8faf0b21fa1/d7858f5/src/gcoap.rs:383:32
    |
383 |         unsafe { (*(*self.pkt).hdr).code = code };
    |                                ^^^ unknown field
    |
help: one of the expressions' fields has a field of the same name
    |
383 |         unsafe { (*(*self.pkt).__bindgen_anon_1.hdr).code = code };
    |                                +++++++++++++++++

For more information about this error, try `rustc --explain E0609`.

@maribu maribu added CI: run tests If set, CI server will run tests on hardware for the labeled PR CI: full build disable CI build filter 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 CI: run tests If set, CI server will run tests on hardware for the labeled PR CI: full build disable CI build filter labels Oct 16, 2024
@maribu
Copy link
Member Author

maribu commented Oct 17, 2024

A full CI run witj tests enabled just passed. So regressions that our tests would catch are no longer present.

Remaining ToDos:

  • find out how to move forward on the rust side
  • prove, that this change actually allows other transports to be implemented

@chrysn
Copy link
Member

chrysn commented Oct 17, 2024

On the Rust side, there is no immediate action needed while the .hdr field is unconditional. Before that becomes conditional, #129 can be adjusted to only do its changes under the same conditions (because the modules are only available in the next release).

Didn't notice #20900 (comment), revisiting…

chrysn added a commit to RIOT-OS/rust-riot-wrappers that referenced this pull request Oct 17, 2024
While [PR20900] provides a compatibility .hdr accessor through a union,
that trick is not available through bindgen or c2rust, which all
introduce a dummy-named field for the anonymous union. Instead, we
follow the path set out by [PR79] and introspect the source file.

[PR20900]: RIOT-OS/RIOT#20900
[PR79]: #79

Co-Authored-By: Marian Buschsieweke <[email protected]>
chrysn added a commit to RIOT-OS/rust-riot-wrappers that referenced this pull request Oct 17, 2024
While [PR20900] provides a compatibility .hdr accessor through a union,
that trick is not available through bindgen or c2rust, which all
introduce a dummy-named field for the anonymous union. Instead, we
follow the path set out by [PR79] and introspect the source file.

[PR20900]: RIOT-OS/RIOT#20900
[PR79]: #79

Co-Authored-By: Marian Buschsieweke <[email protected]>
@maribu maribu force-pushed the sys/net/nanocoap/transport-agnostic-api branch from 03cbfb4 to 7720e62 Compare October 17, 2024 12:48
@maribu
Copy link
Member Author

maribu commented Oct 17, 2024

I rebased on top of #20917 and changed the latest commit to use RIOT-OS/rust-riot-wrappers#130 for the RIOT wrappers.

This changes the API of nanocoap with the goal to reduce the expose of
UDP specifics in the API. The plan is to eventually support transports
such as CoAP over TCP and CoAP over WebSocket directly in nanocoap
while sharing most of the code, as e.g. the CoAP Option processing
remains identical. Specifically, the plan is to unlock a transport with
modules and introduce overhead for dispatching to specific transport
only when multiple transports are actually in use.

Support for OSCORE directly in nanocoap is probably not sensible, as
the serialization is very much unlike the other transports. A unified
CoAP API for multiple transports including OSCORE is probably best
implemented on top. But when limited to the boring set of CoAP
transports, we probably can support them well with nanocoap with less
overhead.

API Changes:
============

- `coap_pkt_t` now contains a `uint8_t *buf` pointer instead of a
  `coap_hdr_t *hdr` pointer to the beginning of the buffer
    - This will also work when the buffer is used by non-UDP
      transports
    - A deprecated `coap_udp_hdr_t *hdr` has been crammed into
      an unnamed `union` with `uint8_t *buf`. For architectures
      where pointers have the same memory layout regardless of type
      (e.g. all of the supported ones), this will make `hdr` an
      alias for `buf`.
    - The alias will only be provided if no transport besides UDP is
      used in nanocoap. So existing apps will continue to work, new
      apps that want to support other transports need to move to
      adapt.
- `coap_hdr_t` has been renamed to `coap_udp_hdr_t`
    - A deprecated alias was created for deprecation
- `coap_hdr*()` functions have been deprecated
    - Equivalent `coap_pkt*()` functions have been created that work
      on `coap_pkt_t *` instead of `coap_hdr_t *`
    - If non-UDP transports are used, the deprecated `coap_hdr*()`
      will probably not be exposed to avoid footguns.
- `coap_build_hdr()` has been renamed to `coap_build_udp_hdr()` and
  that works on an `uint8_t *` buffer with a given length, rather than
  on a `coap_hdr_t *` with a *figers crossed* length
    - a deprecated `coap_build_hdr()` function was added that calls
      to `coap_build_udp_hdr()` and has the same signature, so that
      users have time to update
@maribu maribu force-pushed the sys/net/nanocoap/transport-agnostic-api branch from 7720e62 to 84cbedc Compare October 18, 2024 20:05
@maribu
Copy link
Member Author

maribu commented Oct 18, 2024

Rebased on master. If I still fine issues with the API when implementing CoAP over TCP as proof of concept, I may still adapt this PR. Once confirmed that this is a sane base for adding other transports, I'll mark this PR as ready.

I think the PR will now be more stable and reviewers could take an early look now.

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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants