diff --git a/Cargo.lock b/Cargo.lock index 5c2ecc546..08a03b8c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,20 +447,16 @@ dependencies = [ "coap-request", "coap-request-implementations", "coap-scroll-ring-server", - "coapcore", "embassy-executor", "embassy-futures", "embassy-net", + "embassy-sync 0.6.0", "embassy-time", - "embedded-io-async", - "embedded-nal-async", "embedded-nal-coap", "heapless 0.8.0", - "hexlit", - "lakers", - "lakers-crypto-rustcrypto", "riot-rs", "riot-rs-boards", + "riot-rs-coap", "scroll-ring", "static-alloc", ] @@ -3650,10 +3646,23 @@ dependencies = [ name = "riot-rs-coap" version = "0.1.0" dependencies = [ + "coap-handler", + "coap-handler-implementations", "coapcore", + "critical-section", + "embassy-futures", "embassy-net", + "embassy-sync 0.6.0", + "embedded-io-async", + "embedded-nal-async", + "embedded-nal-coap", + "hexlit", + "lakers", "lakers-crypto-rustcrypto", + "riot-rs-debug", + "riot-rs-embassy", "riot-rs-random", + "static_cell", ] [[package]] diff --git a/examples/coap/Cargo.toml b/examples/coap/Cargo.toml index 4241012be..a9b06d184 100644 --- a/examples/coap/Cargo.toml +++ b/examples/coap/Cargo.toml @@ -12,8 +12,8 @@ workspace = true [dependencies] embassy-executor = { workspace = true, default-features = false } embassy-net = { workspace = true, features = ["udp"] } +embassy-sync.workspace = true embassy-time = { workspace = true, default-features = false } -embedded-io-async = "0.6.1" heapless = { workspace = true } riot-rs = { path = "../../src/riot-rs", features = [ "override-network-config", @@ -23,29 +23,18 @@ riot-rs = { path = "../../src/riot-rs", features = [ "csprng", ] } riot-rs-boards = { path = "../../src/riot-rs-boards" } - -coapcore.path = "../../src/lib/coapcore/" - -# for the udp_nal mod -embedded-nal-async = "0.7" +embassy-futures = "0.1.1" embedded-nal-coap = "0.1.0-alpha.2" coap-request = "0.2.0-alpha.2" coap-message = "0.3.2" -embassy-futures = "0.1.1" coap-message-demos = { version = "0.4.0", default-features = false } coap-request-implementations = "0.1.0-alpha.4" -lakers = { version = "0.6.0", default-features = false } -lakers-crypto-rustcrypto = "0.6.0" coap-handler = "0.2.0" coap-handler-implementations = "0.5.0" -hexlit = "0.5.5" static-alloc = { version = "0.2.5", features = ["polyfill"] } coap-scroll-ring-server = "0.2.0" scroll-ring = "0.1.1" -[features] -default = ["proto-ipv4"] # shame -# actually embedded-nal features, we have to match them here while developing udp_nal in here -proto-ipv4 = ["embassy-net/proto-ipv4"] -proto-ipv6 = ["embassy-net/proto-ipv6"] +# FIXME: Where should this be pulled through? +riot-rs-coap = { workspace = true, features = ["proto-ipv4"] } diff --git a/examples/coap/src/main.rs b/examples/coap/src/main.rs index 9d7fb89af..8ede488ed 100644 --- a/examples/coap/src/main.rs +++ b/examples/coap/src/main.rs @@ -5,13 +5,6 @@ use riot_rs::{debug::log::*, network}; -use embassy_net::udp::{PacketMetadata, UdpSocket}; - -// Moving work from https://github.com/embassy-rs/embassy/pull/2519 in here for the time being -mod udp_nal; - -use coapcore::seccontext; - // because coapcore depends on it temporarily extern crate alloc; use static_alloc::Bump; @@ -21,55 +14,6 @@ static A: Bump<[u8; 1 << 16]> = Bump::uninit(); #[riot_rs::task(autostart)] async fn coap_run() { - let stack = network::network_stack().await.unwrap(); - - // FIXME trim to CoAP requirements - let mut rx_meta = [PacketMetadata::EMPTY; 16]; - let mut rx_buffer = [0; 4096]; - let mut tx_meta = [PacketMetadata::EMPTY; 16]; - let mut tx_buffer = [0; 4096]; - - let socket = UdpSocket::new( - stack, - &mut rx_meta, - &mut rx_buffer, - &mut tx_meta, - &mut tx_buffer, - ); - - info!("Starting up CoAP server"); - - // Can't that even bind to the Any address?? - // let local_any = "0.0.0.0:5683".parse().unwrap(); // shame - let local_any = "10.42.0.61:5683".parse().unwrap(); // shame - let unconnected = udp_nal::UnconnectedUdp::bind_multiple(socket, local_any) - .await - .unwrap(); - - run(unconnected).await; -} - -// FIXME: So far, this is necessary boiler plate; see ../README.md#networking for details -#[riot_rs::config(network)] -fn network_config() -> embassy_net::Config { - use embassy_net::Ipv4Address; - - embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { - address: embassy_net::Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), - dns_servers: heapless::Vec::new(), - gateway: Some(Ipv4Address::new(10, 42, 0, 1)), - }) -} - -// Rest is from coap-message-demos/examples/std_embedded_nal_coap.rs - -/// This function works on *any* UdpFullStack, including embedded ones -- only main() is what makes -/// this use POSIX sockets. (It does make use of a std based RNG, but that could be passed in just -/// as well for no_std operation). -async fn run(mut sock: S) -where - S: embedded_nal_async::UnconnectedUdp, -{ use coap_handler_implementations::{HandlerBuilder, ReportingHandlerBuilder}; let log = None; @@ -87,39 +31,17 @@ where writeln!(stdout, "We have our own stdout now.").unwrap(); writeln!(stdout, "With rings and atomics.").unwrap(); - use hexlit::hex; - const R: &[u8] = &hex!("72cc4761dbd4c78f758931aa589d348d1ef874a7e303ede2f140dcf3e6aa4aac"); - let own_identity = ( - &lakers::CredentialRPK::new(lakers::EdhocMessageBuffer::new_from_slice(&hex!("A2026008A101A5010202410A2001215820BBC34960526EA4D32E940CAD2A234148DDC21791A12AFBCBAC93622046DD44F02258204519E257236B2A0CE2023F0931F1F386CA7AFDA64FCDE0108C224C51EABF6072")).expect("Credential should be small enough")).expect("Credential should be processable"), - R, - ); - - let handler = coap_message_demos::full_application_tree(log) - .at( - &["stdout"], - coap_scroll_ring_server::BufferHandler::new(&buffer), - ) - .with_wkc(); - - let mut handler = seccontext::OscoreEdhocHandler::new(own_identity, handler, stdout, || { - lakers_crypto_rustcrypto::Crypto::new(riot_rs::random::crypto_rng()) - }); - - info!("Server is ready."); + let handler = coap_message_demos::full_application_tree(log).at( + &["stdout"], + coap_scroll_ring_server::BufferHandler::new(&buffer), + ); - let coap = embedded_nal_coap::CoAPShared::<3>::new(); - let (client, server) = coap.split(); + let client_signal = embassy_sync::signal::Signal::new(); - // going with an embassy_futures join instead of an async_std::task::spawn b/c CoAPShared is not - // Sync, and async_std expects to work in multiple threads + // going with an embassy_futures join instead of RIOT-rs's spawn b/c CoAPShared is not Sync. embassy_futures::join::join( - async { - server - .run(&mut sock, &mut handler, &mut riot_rs::random::fast_rng()) - .await - .expect("UDP error") - }, - run_client_operations(client), + riot_rs::coap::coap_run(handler, stdout, &client_signal), + run_client_operations(&client_signal), ) .await; } @@ -128,9 +50,14 @@ where /// /// This doubles as an experimentation ground for the client side of embedded_nal_coap and /// coap-request in general. -async fn run_client_operations( - client: embedded_nal_coap::CoAPRuntimeClient<'_, N>, +async fn run_client_operations( + client_in: &embassy_sync::signal::Signal< + embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex, + &'static embedded_nal_coap::CoAPRuntimeClient<'static, 3>, + >, ) { + let client = client_in.wait().await; + // shame let addr = "10.42.0.1:1234"; let demoserver = addr.clone().parse().unwrap(); @@ -162,3 +89,15 @@ async fn run_client_operations( let response = response.await; info!("Response {:?}", response.map_err(|_| "TransportError")); } + +// FIXME: So far, this is necessary boiler plate; see ../README.md#networking for details +#[riot_rs::config(network)] +fn network_config() -> embassy_net::Config { + use embassy_net::Ipv4Address; + + embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + address: embassy_net::Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), + dns_servers: heapless::Vec::new(), + gateway: Some(Ipv4Address::new(10, 42, 0, 1)), + }) +} diff --git a/src/riot-rs-coap/Cargo.toml b/src/riot-rs-coap/Cargo.toml index 66265d0ce..c751bafd0 100644 --- a/src/riot-rs-coap/Cargo.toml +++ b/src/riot-rs-coap/Cargo.toml @@ -8,9 +8,26 @@ repository.workspace = true [dependencies] coapcore.path = "../lib/coapcore" +coap-handler = "0.2.0" +coap-handler-implementations = "0.5.0" +critical-section.workspace = true +embassy-futures = "0.1.1" embassy-net = { workspace = true, features = ["udp"] } +embassy-sync.workspace = true +embedded-nal-async = "0.7" +embedded-nal-coap = "0.1.0-alpha.2" lakers-crypto-rustcrypto = "0.6.0" +lakers = { version = "0.6.0", default-features = false } +riot-rs-debug.workspace = true +riot-rs-embassy.workspace = true riot-rs-random.workspace = true +static_cell = "2.1.0" + +# FIXME: Should go out eventually +hexlit = "0.5.5" + +# For the udp_nal +embedded-io-async = "0.6.1" [lints] workspace = true diff --git a/src/riot-rs-coap/src/lib.rs b/src/riot-rs-coap/src/lib.rs index 20f3d1891..aabcb0eae 100644 --- a/src/riot-rs-coap/src/lib.rs +++ b/src/riot-rs-coap/src/lib.rs @@ -7,3 +7,89 @@ #![no_std] #![deny(missing_docs)] #![deny(clippy::pedantic)] + +// Moving work from https://github.com/embassy-rs/embassy/pull/2519 in here for the time being +mod udp_nal; + +use coap_handler_implementations::{HandlerBuilder, ReportingHandlerBuilder}; +use coapcore::seccontext; +use critical_section::Mutex; +use embassy_net::udp::{PacketMetadata, UdpSocket}; +use riot_rs_debug::log::*; +use static_cell::StaticCell; + +const CONCURRENT_REQUESTS: usize = 3; + +// FIXME: log_stdout is not something we want to have here +// FIXME: I'd rather have the client_out available anywhere, but at least the way CoAPRuntimeClient +// is set up right now, server and client have to run in the same thread. +/// Run a CoAP server with the given handler on the system's CoAP transports. +pub async fn coap_run( + handler: impl coap_handler::Handler + coap_handler::Reporting, + log_stdout: impl core::fmt::Write, + client_out: &embassy_sync::signal::Signal< + embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex, + &'static embedded_nal_coap::CoAPRuntimeClient<'static, CONCURRENT_REQUESTS>, + >, +) { + let stack = riot_rs_embassy::network::network_stack().await.unwrap(); + + // FIXME trim to CoAP requirements + let mut rx_meta = [PacketMetadata::EMPTY; 16]; + let mut rx_buffer = [0; 4096]; + let mut tx_meta = [PacketMetadata::EMPTY; 16]; + let mut tx_buffer = [0; 4096]; + + let socket = UdpSocket::new( + stack, + &mut rx_meta, + &mut rx_buffer, + &mut tx_meta, + &mut tx_buffer, + ); + use embedded_nal_async::UnconnectedUdp; + + info!("Starting up CoAP server"); + + // Can't that even bind to the Any address?? + // let local_any = "0.0.0.0:5683".parse().unwrap(); // shame + let local_any = "10.42.0.61:5683".parse().unwrap(); // shame + let mut unconnected = udp_nal::UnconnectedUdp::bind_multiple(socket, local_any) + .await + .unwrap(); + + use hexlit::hex; + const R: &[u8] = &hex!("72cc4761dbd4c78f758931aa589d348d1ef874a7e303ede2f140dcf3e6aa4aac"); + let own_identity = ( + &lakers::CredentialRPK::new(lakers::EdhocMessageBuffer::new_from_slice(&hex!("A2026008A101A5010202410A2001215820BBC34960526EA4D32E940CAD2A234148DDC21791A12AFBCBAC93622046DD44F02258204519E257236B2A0CE2023F0931F1F386CA7AFDA64FCDE0108C224C51EABF6072")).expect("Credential should be small enough")).expect("Credential should be processable"), + R, + ); + + // FIXME: Should we allow users to override that? After all, this is just convenience and may + // be limiting in special applications. + let handler = handler.with_wkc(); + let mut handler = + seccontext::OscoreEdhocHandler::new(own_identity, handler, log_stdout, || { + lakers_crypto_rustcrypto::Crypto::new(riot_rs_random::crypto_rng()) + }); + + info!("Server is ready."); + + static COAP: StaticCell> = StaticCell::new(); + let coap = COAP.init_with(|| embedded_nal_coap::CoAPShared::new()); + static CLIENT: StaticCell> = + StaticCell::new(); + let (client, server) = coap.split(); + let client = CLIENT.init_with(|| client); + + client_out.signal(client); + + server + .run( + &mut unconnected, + &mut handler, + &mut riot_rs_random::fast_rng(), + ) + .await + .expect("UDP error") +} diff --git a/examples/coap/src/udp_nal/mod.rs b/src/riot-rs-coap/src/udp_nal/mod.rs similarity index 100% rename from examples/coap/src/udp_nal/mod.rs rename to src/riot-rs-coap/src/udp_nal/mod.rs diff --git a/examples/coap/src/udp_nal/util.rs b/src/riot-rs-coap/src/udp_nal/util.rs similarity index 100% rename from examples/coap/src/udp_nal/util.rs rename to src/riot-rs-coap/src/udp_nal/util.rs