From fc9149fe749ce02e55c1ed64ed0d63ea43f86987 Mon Sep 17 00:00:00 2001 From: chrysn Date: Thu, 30 Jan 2025 11:03:38 +0100 Subject: [PATCH] feat(coap): auto-start CoAP server as needed --- Cargo.lock | 1 + examples/coap-client/src/main.rs | 9 --------- laze-project.yml | 4 ++++ src/ariel-os-coap/Cargo.toml | 13 ++++++++++++- src/ariel-os-coap/src/lib.rs | 22 ++++++++++++++++++++++ src/ariel-os/Cargo.toml | 7 +++++++ 6 files changed, 46 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a415be0c7..24a0ed74b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,6 +158,7 @@ version = "0.1.0" dependencies = [ "ariel-os-debug", "ariel-os-embassy", + "ariel-os-macros", "ariel-os-random", "cbor-macro", "cboritem", diff --git a/examples/coap-client/src/main.rs b/examples/coap-client/src/main.rs index 97ed5682d..43a92c134 100644 --- a/examples/coap-client/src/main.rs +++ b/examples/coap-client/src/main.rs @@ -5,15 +5,6 @@ use ariel_os::debug::log::info; -/// Run a CoAP stack without serving any actual resources. -#[ariel_os::task(autostart)] -async fn coap_run() { - use coap_handler_implementations::new_dispatcher; - - let handler = new_dispatcher(); - ariel_os::coap::coap_run(handler).await; -} - #[ariel_os::task(autostart)] async fn run_client_operations() { use coap_request::Stack; diff --git a/laze-project.yml b/laze-project.yml index 3a4695fbb..a25dd883e 100644 --- a/laze-project.yml +++ b/laze-project.yml @@ -785,6 +785,10 @@ modules: # will have their own entry point when they exist. depends: - coap + env: + global: + FEATURES: + - ariel-os/coap-server - name: coap-client help: Support for CoAP client functionality. diff --git a/src/ariel-os-coap/Cargo.toml b/src/ariel-os-coap/Cargo.toml index 8c9db6480..ba7b031bb 100644 --- a/src/ariel-os-coap/Cargo.toml +++ b/src/ariel-os-coap/Cargo.toml @@ -29,6 +29,7 @@ lakers = { version = "0.7.2", default-features = false } ariel-os-debug.workspace = true ariel-os-embassy = { workspace = true, features = ["net"] } ariel-os-random = { workspace = true, features = ["csprng"] } +ariel-os-macros = { path = "../ariel-os-macros" } static_cell = "2.1.0" # FIXME: Should go out eventually @@ -43,9 +44,19 @@ embedded-io-async = "0.6.1" workspace = true [features] +# Enables the coap_run function through which an own server is passed in. The +# crate setting this must call `ariel_os{_,::}coap::coap_run()`; if not set, +# that function is run with a default minimal server automatically (as is +# required by the implementation to have client functionality). +# +# At the feature level, this is a bit of a misnomer, could also be +# called "manual-server-start"; the name is chosen to align with +# laze's name for this (where coap-server makes more sense). +coap-server = [] + ## Enables an arbitrary set of features in dependencies where dependencies fail ## if no features are configured at all. -doc = ["embassy-net/proto-ipv6", "embassy-net/medium-ip"] +doc = ["embassy-net/proto-ipv6", "embassy-net/medium-ip", "coap-server"] ## Enables defmt logging of coapcore defmt = ["coapcore/defmt"] diff --git a/src/ariel-os-coap/src/lib.rs b/src/ariel-os-coap/src/lib.rs index 773d50b14..ac3f7cb3b 100644 --- a/src/ariel-os-coap/src/lib.rs +++ b/src/ariel-os-coap/src/lib.rs @@ -8,6 +8,8 @@ #![no_std] #![deny(missing_docs)] #![deny(clippy::pedantic)] +// for #[ariel_os_macros::task(autostart)] +#![feature(impl_trait_in_assoc_type, used_with_arg)] // Moving work from https://github.com/embassy-rs/embassy/pull/2519 in here for the time being mod udp_nal; @@ -63,7 +65,12 @@ mod demo_setup { /// # Panics /// /// This can only be run once, as it sets up a system wide CoAP handler. +#[cfg(feature = "coap-server")] pub async fn coap_run(handler: impl coap_handler::Handler + coap_handler::Reporting) -> ! { + coap_run_impl(handler).await +} + +async fn coap_run_impl(handler: impl coap_handler::Handler + coap_handler::Reporting) -> ! { static COAP: StaticCell> = StaticCell::new(); let stack = ariel_os_embassy::net::network_stack().await.unwrap(); @@ -155,3 +162,18 @@ pub async fn coap_client( .await // Not an actual await, just a convenient way to see which executor is running .expect("CoAP client can currently only be used from the thread the network is bound to") } + +/// Auto-started CoAP server that serves two purposes: +/// +/// * It provides the backend for the CoAP client operation (which leaves message sending to that +/// task). +/// * It runs any CoAP server components provided by the OS (none yet). +#[cfg(not(feature = "coap-server"))] +#[ariel_os_macros::task(autostart)] +async fn coap_run() { + use coap_handler_implementations::new_dispatcher; + + // FIXME: Provide an "all system components" constructor in this crate. + let handler = new_dispatcher(); + coap_run_impl(handler).await; +} diff --git a/src/ariel-os/Cargo.toml b/src/ariel-os/Cargo.toml index 56d64c9fe..13b9b5703 100644 --- a/src/ariel-os/Cargo.toml +++ b/src/ariel-os/Cargo.toml @@ -59,6 +59,13 @@ dns = ["ariel-os-embassy/dns"] mdns = ["ariel-os-embassy/mdns"] ## Enables support for [CoAP](https://ariel-os.github.io/ariel-os/dev/docs/book/tooling/coap.html). coap = ["dep:ariel-os-coap", "random"] +## Support for applications to set up own CoAP server handlers. +## +## When an application selects this, it needs to run `ariel_os::coap_run()` +## in a task; otherwise, other components (eg. system components that also +## run on the CoAP server, or the CoAP client that depends on the server +## loop to run) get stalled. +coap-server = ["coap", "ariel-os-coap/coap-server"] ## Selects static IP configuration. network-config-static = ["ariel-os-embassy/network-config-static"]