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

sys: Add stdio_coap #19289

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

Conversation

chrysn
Copy link
Member

@chrysn chrysn commented Feb 20, 2023

Contribution description

This adds a new stdio through CoAP, roughly following the proposed interface.

It consists of largely independent channels for data out (effectively implemented in the scroll-ring crate), and one for data in (backed by the same kind of ring buffer, but different in its overwrite and blocking behaviors).

The behavior of stdout is that writes never block and happily overwrite the ring buffer -- if data is not obtained fast enough1, it is lost. Still, a byte counter is kept (overflowing at 32bit), so that not only the presence but also the size of holes in the readout can be determined. Right now, the CoAP handler can only be polled. Future versions will hopefully support observe, in which case the hole indication becomes even more important: The fetch can then report the latest slice, and if the client is interested it can still fetch the missed data if it's around by then.

The behavior of stdin is much easier: Data is POSTed there, stored in a buffer, and POSTs are rejected if there's not enough space in the buffer. (It could be way easier if users of stdin asked for data in chunks and not byte-wise, for then we could save the buffer and deliver data right from the request in there -- but even the shell that has a line-sized buffer pulls data bytewise).

Testing procedure

So far, this only works on applications that do not start gcoap on their own, for (at least the simple version of) the discovery procedure relies on .well-known/core being handled by this module. [edit: More precisely, the stdio_coap module currently makes all other gcoap resources indiscoverable.]

  • USEMODULE+=stdio_coap make -C examples/saul all term -- this won't print anything on its own.

  • In a separate terminal,

    $ git clone https://gitlab.com/chrysn/scroll-ring
    $ cd coap-scroll-ring-server/tools
    $ python3 -m venv ./venv
    $ source ./venv/bin/activate
    $ pip install -r requirements.txt
    $ ./coap-console 'coap://[ff02::1%tapbr0]'
    

    This uses multicast CoAP to discover the precise address of the device; if there are multiple ones around, it picks the one that responds fastest (so in that case, please give the unicast address).

    The autodiscovery process also finds the precise paths; applications that set up gcoap manually may need that.

Open issues

  • How strongly should this pull in gcoap and the network stack? Am I depending on the right modules?

  • Right now this registers all own resources in a single Rust CoAP handler that's registered as a Gcoap listener. This is not transparent to the resource enumeration process.

  • There is no sensible make term helper -- do we need one? (That'd require passing information at least about the network interface around, like PORT=[fe80::...%tapbr0], which we don't have so far)

  • I don't want this merged without a usable security model. I haven't tried going through DTLS -- can our DTLS by now use different keys to gain different levels of authorization?

    My goal here is to make things work with OSCORE. That won't be too tricky as long as we're in a all-resources-from-Rust ecosystem, but there's no clear roadmap for integration with on-Rust CoAP resources.

    A minimal viable solution could be that OSCORE is available only for these resources, discovery is compatible with other resources, and for the time being, this module negotiates the key between build system and device.

Footnotes

  1. precisely: if more data is written in one go than fits in the ring buffer, or if data is not fetched frequently enough, or the task reading the ring buffer is doing that too slowly, or there are writers that are so low in their priority that that the rest of the ring buffer gets filled before the low priority task completes

@chrysn chrysn marked this pull request as draft February 20, 2023 12:54
@github-actions github-actions bot added Area: build system Area: Build system Area: sys Area: System labels Feb 20, 2023
@chrysn chrysn added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Area: CoAP Area: Constrained Application Protocol implementations Area: Rust Area: Rust wrapper labels Feb 20, 2023
@riot-ci
Copy link

riot-ci commented Feb 20, 2023

Murdock results

FAILED

8596269 Merge branch 'tinydtls-defaults' into stdio-coap

Success Failures Total Runtime
67 0 5731 14m:57s

Artifacts

@github-actions github-actions bot removed the Area: CoAP Area: Constrained Application Protocol implementations label Feb 20, 2023
@github-actions github-actions bot added the Area: examples Area: Example Applications label Feb 22, 2023
@chrysn
Copy link
Member Author

chrysn commented Feb 22, 2023

With the latest updates, this collaborates well with other gcoap resources, so it can also be used together with the gcoap example. (It doesn't work with the rust-gcoap example: That still usurps the full CoAP tree).

It suffers a bit from the lack of the built-in .well-known/core's block-wise transfer or filtering, but that's a topic of its own. (More concretely, with the default buffer sizes and the gcoap example, only one of two resources is listed, making stdout work but stdin not).

bors bot added a commit that referenced this pull request Feb 27, 2023
19329: MAINTAINING.md: add some notes on Bors r=benpicco a=benpicco



19330: native/stdio: Explicitly provide getchar r=chrysn a=chrysn

### Contribution description

This ensures that even when libc does not implement getchar through getc, any custom stdio is still in the loop when getchar is used.

Frankly, I don't know when this broke -- I'm pretty sure custom stdio worked just a few days ago -- but either way, without this patch RIOT on native currently bypasses a configured stdio for me.

### Testing procedure

* `make -C examples/saul all debug`
* `break stdio_read`
* `run`

Without this patch, observe how the shell runs w/o ever breaking. After, lots of breakpoint hits.

This is the way it behaves for me (Debian sid, libc6:i386 2.36-8). If it works for you before this patch, we might start bisecting the differences between the systems, but we may also accept that libcs may imlpement getchar in different ways, and not all of them pass by the getc which we're patching.

### Issues/PRs references

This is needed for testing #19289.

The implementation stems from the `fgetc(3)` man page, which states that "getchar() is equivalent to getc(stdin)".

Co-authored-by: Benjamin Valentin <[email protected]>
Co-authored-by: chrysn <[email protected]>
@github-actions github-actions bot added Area: Kconfig Area: Kconfig integration Area: network Area: Networking Area: pkg Area: External package ports labels Feb 28, 2023
@chrysn
Copy link
Member Author

chrysn commented Feb 28, 2023

Now updated to also work over DTLS.

There's no checking of which credentials are used -- stdio is even accepted over unprotected CoAP -- but how we'd establish actual DTLS credentials that are not just "secretPSK" is something that'll need a bit of thought anyway. (Possibly together with considering RFC9202 and a corresponding update to credman). So

$ USEMODULE+='stdio_coap' make -C examples/gcoap_dtls all term CARGO_CHANNEL=nightly

bors bot added a commit that referenced this pull request Feb 28, 2023
16158: gnrc_sixlowpan_frag_sfr_congure_sfr: initial import r=miri64 a=miri64



19331: pkg/tinydtls: Adjust defaults r=miri64 a=chrysn

### Contribution description

This adjusts two defaults in tinydtls:

* Default verbosity is set to warning. At the info level, this module produces way more output (several lines per new connection, and even per message) than is common in RIOT.
* If gcoap is used, the buffer size is adjusted to the gcoap buffer size plus overhead. Otherwise, CoAP-over-DTLS works fine until one happens to request larger resources.

### Testing procedure

* Run examples/gcoap_dtls
* Send a CoAP request from outside, eg. with `aiocoap-client 'coaps://[fe80::3c63:beff:fe85:ca96%tapbr0]/.well-known/core' --credentials testserver.json` (where testserver.json is `{"coaps://[fe80::3c63:beff:fe85:ca96%tapbr0]/*": {"dtls": {"psk": {"ascii": "secretPSK"}, "client-identity": {"ascii": "Client_identity"}}}}`).

Before, there are messages shown for every request; now there are none.

Modify `examples/gcoap/server.c` as follows:

```patch
diff --git a/examples/gcoap/server.c b/examples/gcoap/server.c
index bf2315cd01..28e1faac27 100644
--- a/examples/gcoap/server.c
+++ b/examples/gcoap/server.c
`@@` -68,7 +68,7 `@@` static const coap_resource_t _resources[] = {
 };
 
 static const char *_link_params[] = {
-    ";ct=0;rt=\"count\";obs",
+    ";ct=0;rt=\"count\";obs;looooooooooooooooooooooong-attribute=\"loooooooooooooooooooooooooooooong\"",
     NULL
 };
```

The request passes; without this patch, it is stuck in retransmissions until "Network error: Retransmissions exceeded".

### Issues/PRs references

This contributes to making #19289 usable with a minimum level of security. (That module fills up the gcoap buffer to the brim). While the module handles the verbosity as well as it can (occasionally admitting that it lost bytes of output), the previous verbosity produces an infinite stream of stdout data. (But the default should be quiet immaterial of that particular PR).

Co-authored-by: Martine Lenders <[email protected]>
Co-authored-by: chrysn <[email protected]>
bors bot added a commit that referenced this pull request Mar 2, 2023
19331: pkg/tinydtls: Adjust defaults r=benpicco a=chrysn

### Contribution description

This adjusts two defaults in tinydtls:

* Default verbosity is set to warning. At the info level, this module produces way more output (several lines per new connection, and even per message) than is common in RIOT.
* If gcoap is used, the buffer size is adjusted to the gcoap buffer size plus overhead. Otherwise, CoAP-over-DTLS works fine until one happens to request larger resources.

### Testing procedure

* Run examples/gcoap_dtls
* Send a CoAP request from outside, eg. with `aiocoap-client 'coaps://[fe80::3c63:beff:fe85:ca96%tapbr0]/.well-known/core' --credentials testserver.json` (where testserver.json is `{"coaps://[fe80::3c63:beff:fe85:ca96%tapbr0]/*": {"dtls": {"psk": {"ascii": "secretPSK"}, "client-identity": {"ascii": "Client_identity"}}}}`).

Before, there are messages shown for every request; now there are none.

Modify `examples/gcoap/server.c` as follows:

```patch
diff --git a/examples/gcoap/server.c b/examples/gcoap/server.c
index bf2315cd01..28e1faac27 100644
--- a/examples/gcoap/server.c
+++ b/examples/gcoap/server.c
`@@` -68,7 +68,7 `@@` static const coap_resource_t _resources[] = {
 };
 
 static const char *_link_params[] = {
-    ";ct=0;rt=\"count\";obs",
+    ";ct=0;rt=\"count\";obs;looooooooooooooooooooooong-attribute=\"loooooooooooooooooooooooooooooong\"",
     NULL
 };
```

The request passes; without this patch, it is stuck in retransmissions until "Network error: Retransmissions exceeded".

### Issues/PRs references

This contributes to making #19289 usable with a minimum level of security. (That module fills up the gcoap buffer to the brim). While the module handles the verbosity as well as it can (occasionally admitting that it lost bytes of output), the previous verbosity produces an infinite stream of stdout data. (But the default should be quiet immaterial of that particular PR).

Co-authored-by: chrysn <[email protected]>
bors bot added a commit that referenced this pull request Mar 2, 2023
18515: libschc: initial import as package r=miri64 a=miri64



19331: pkg/tinydtls: Adjust defaults r=miri64 a=chrysn

### Contribution description

This adjusts two defaults in tinydtls:

* Default verbosity is set to warning. At the info level, this module produces way more output (several lines per new connection, and even per message) than is common in RIOT.
* If gcoap is used, the buffer size is adjusted to the gcoap buffer size plus overhead. Otherwise, CoAP-over-DTLS works fine until one happens to request larger resources.

### Testing procedure

* Run examples/gcoap_dtls
* Send a CoAP request from outside, eg. with `aiocoap-client 'coaps://[fe80::3c63:beff:fe85:ca96%tapbr0]/.well-known/core' --credentials testserver.json` (where testserver.json is `{"coaps://[fe80::3c63:beff:fe85:ca96%tapbr0]/*": {"dtls": {"psk": {"ascii": "secretPSK"}, "client-identity": {"ascii": "Client_identity"}}}}`).

Before, there are messages shown for every request; now there are none.

Modify `examples/gcoap/server.c` as follows:

```patch
diff --git a/examples/gcoap/server.c b/examples/gcoap/server.c
index bf2315cd01..28e1faac27 100644
--- a/examples/gcoap/server.c
+++ b/examples/gcoap/server.c
`@@` -68,7 +68,7 `@@` static const coap_resource_t _resources[] = {
 };
 
 static const char *_link_params[] = {
-    ";ct=0;rt=\"count\";obs",
+    ";ct=0;rt=\"count\";obs;looooooooooooooooooooooong-attribute=\"loooooooooooooooooooooooooooooong\"",
     NULL
 };
```

The request passes; without this patch, it is stuck in retransmissions until "Network error: Retransmissions exceeded".

### Issues/PRs references

This contributes to making #19289 usable with a minimum level of security. (That module fills up the gcoap buffer to the brim). While the module handles the verbosity as well as it can (occasionally admitting that it lost bytes of output), the previous verbosity produces an infinite stream of stdout data. (But the default should be quiet immaterial of that particular PR).

Co-authored-by: Martine Lenders <[email protected]>
Co-authored-by: chrysn <[email protected]>
bors bot added a commit that referenced this pull request Mar 2, 2023
19331: pkg/tinydtls: Adjust defaults r=miri64 a=chrysn

### Contribution description

This adjusts two defaults in tinydtls:

* Default verbosity is set to warning. At the info level, this module produces way more output (several lines per new connection, and even per message) than is common in RIOT.
* If gcoap is used, the buffer size is adjusted to the gcoap buffer size plus overhead. Otherwise, CoAP-over-DTLS works fine until one happens to request larger resources.

### Testing procedure

* Run examples/gcoap_dtls
* Send a CoAP request from outside, eg. with `aiocoap-client 'coaps://[fe80::3c63:beff:fe85:ca96%tapbr0]/.well-known/core' --credentials testserver.json` (where testserver.json is `{"coaps://[fe80::3c63:beff:fe85:ca96%tapbr0]/*": {"dtls": {"psk": {"ascii": "secretPSK"}, "client-identity": {"ascii": "Client_identity"}}}}`).

Before, there are messages shown for every request; now there are none.

Modify `examples/gcoap/server.c` as follows:

```patch
diff --git a/examples/gcoap/server.c b/examples/gcoap/server.c
index bf2315cd01..28e1faac27 100644
--- a/examples/gcoap/server.c
+++ b/examples/gcoap/server.c
`@@` -68,7 +68,7 `@@` static const coap_resource_t _resources[] = {
 };
 
 static const char *_link_params[] = {
-    ";ct=0;rt=\"count\";obs",
+    ";ct=0;rt=\"count\";obs;looooooooooooooooooooooong-attribute=\"loooooooooooooooooooooooooooooong\"",
     NULL
 };
```

The request passes; without this patch, it is stuck in retransmissions until "Network error: Retransmissions exceeded".

### Issues/PRs references

This contributes to making #19289 usable with a minimum level of security. (That module fills up the gcoap buffer to the brim). While the module handles the verbosity as well as it can (occasionally admitting that it lost bytes of output), the previous verbosity produces an infinite stream of stdout data. (But the default should be quiet immaterial of that particular PR).

Co-authored-by: chrysn <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: build system Area: Build system Area: examples Area: Example Applications Area: Kconfig Area: Kconfig integration Area: network Area: Networking Area: pkg Area: External package ports Area: Rust Area: Rust wrapper Area: sys Area: System 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.

2 participants