From 6246ab70d182fe563d98dc38a92c3a8317beaca0 Mon Sep 17 00:00:00 2001 From: chrysn Date: Thu, 26 Aug 2021 16:23:31 +0200 Subject: [PATCH] examples: Add second Rust example (gcoap) --- examples/rust-gcoap/Cargo.lock | Bin 0 -> 22635 bytes examples/rust-gcoap/Cargo.toml | 16 +++++++ examples/rust-gcoap/Makefile | 39 +++++++++++++++++ examples/rust-gcoap/Makefile.ci | 8 ++++ examples/rust-gcoap/README.md | 53 +++++++++++++++++++++++ examples/rust-gcoap/src/lib.rs | 57 +++++++++++++++++++++++++ examples/rust-gcoap/vfs.c | 72 ++++++++++++++++++++++++++++++++ 7 files changed, 245 insertions(+) create mode 100644 examples/rust-gcoap/Cargo.lock create mode 100644 examples/rust-gcoap/Cargo.toml create mode 100644 examples/rust-gcoap/Makefile create mode 100644 examples/rust-gcoap/Makefile.ci create mode 100644 examples/rust-gcoap/README.md create mode 100644 examples/rust-gcoap/src/lib.rs create mode 100644 examples/rust-gcoap/vfs.c diff --git a/examples/rust-gcoap/Cargo.lock b/examples/rust-gcoap/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..024687b93624eee957954e80972792fa30afad4c GIT binary patch literal 22635 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 literal 0 HcmV?d00001 diff --git a/examples/rust-gcoap/Cargo.toml b/examples/rust-gcoap/Cargo.toml new file mode 100644 index 0000000000..58d66cf76a --- /dev/null +++ b/examples/rust-gcoap/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rust-gcoap" +version = "0.1.0" +authors = ["Christian Amsüss "] +edition = "2018" +resolver = "2" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +riot-wrappers = { version = "^0.7", features = [ "with_coap_message", "with_coap_handler" ] } + +coap-message-demos = { git = "https://gitlab.com/chrysn/coap-message-demos/", default-features = false } +coap-handler-implementations = "0.1" +riot-coap-handler-demos = { git = "https://gitlab.com/etonomy/riot-module-examples/", features = [ "vfs" ] } diff --git a/examples/rust-gcoap/Makefile b/examples/rust-gcoap/Makefile new file mode 100644 index 0000000000..1cdf7b43c1 --- /dev/null +++ b/examples/rust-gcoap/Makefile @@ -0,0 +1,39 @@ +# name of your application +APPLICATION = rust_gcoap + +# If no BOARD is found in the environment, use this default: +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# Basic networking, and gcoap +USEMODULE += gcoap +USEMODULE += netdev_default +USEMODULE += auto_init_gnrc_netif +USEMODULE += gnrc_ipv6_default +USEMODULE += gnrc_icmpv6_echo + +USEMODULE += ztimer +USEMODULE += ztimer_usec +USEMODULE += ztimer_msec +USEMODULE += ztimer_sec + +USEMODULE += vfs +USEMODULE += constfs + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +# The name of crate (as per Cargo.toml package name, but with '-' replaced with '_') +APPLICATION_RUST_MODULE = rust_gcoap +BASELIBS += $(APPLICATION_RUST_MODULE).module + +FEATURES_REQUIRED += rust_target + +include $(RIOTBASE)/Makefile.include diff --git a/examples/rust-gcoap/Makefile.ci b/examples/rust-gcoap/Makefile.ci new file mode 100644 index 0000000000..2c83ca0bbb --- /dev/null +++ b/examples/rust-gcoap/Makefile.ci @@ -0,0 +1,8 @@ +BOARD_INSUFFICIENT_MEMORY := \ + blackpill \ + bluepill \ + nucleo-f302r8 \ + nucleo-f303k8 \ + nucleo-f334r8 \ + stm32mp157c-dk2 \ + # diff --git a/examples/rust-gcoap/README.md b/examples/rust-gcoap/README.md new file mode 100644 index 0000000000..5d8a5b42f1 --- /dev/null +++ b/examples/rust-gcoap/README.md @@ -0,0 +1,53 @@ +gcoap used with Rust +==================== + +This is the advanced Rust example; see ../rust-hello-world/ for the basics. + +In extension to the basic example, it shows: + +* C code can be mixed with Rust code easily; any C file is built and linked + as in applications without Rust. + + While it's technically possible to have header files for that code, + it is easier (and likewise often done in C applications) + to just translate the entry function's signature manually, + as is done with the `do_vfs_init()` function. + +* Code of Rust applications can be spread out into modules, + even if it builds on RIOT components. + + The CoAP handler built in the main function + combines generic CoAP components (from `coap_message_demos`) + with RIOT specific components (from `riot-coap-handler-demos`). + +* Many features of RIOT are exposed to Rust through the riot-wrappers crate, + which provides safe wrappers around RIOT structures. + + In this example, the abovementioned CoAP handler is run on the gcoap server, + for which the wrappers provide adaptation to the platform independent handler interface. + + Then, ztimer is used to sleep until the network interfaces are expected to be ready. + + Finally, the available network interfaces are iterated over + and queried for their IP addresses, + which makes it easier (in absence of an interactive shell) to find which address CoAP requests can be directed at. + +How to use +---------- + +``` +$ make all flash term +[...] +main(): This is RIOT! (Version: 2022.01-devel-560-g7f8ed-rust-application) +constfs mounted successfully +CoAP server ready; waiting for interfaces to settle before reporting addresses... +Active interface from PID KernelPID(6) ("gnrc_netdev_tap") + Address fe80:0000:0000:0000:1234:56ff:fe78:90ab + Address 2a02:0b18:c13b:8018:1234:56ff:fe78:90ab +``` + +Once that is ready, in a parallel shell, run: + +``` +$ aiocoap-client 'coap://[2a02:0b18:c13b:8018:1234:56ff:fe78:90ab]/.well-known/core' +``` diff --git a/examples/rust-gcoap/src/lib.rs b/examples/rust-gcoap/src/lib.rs new file mode 100644 index 0000000000..0059b4523c --- /dev/null +++ b/examples/rust-gcoap/src/lib.rs @@ -0,0 +1,57 @@ +// Copyright (C) 2020 Christian Amsüss +// +// This file is subject to the terms and conditions of the GNU Lesser +// General Public License v2.1. See the file LICENSE in the top level +// directory for more details. +#![no_std] + +use riot_wrappers::{riot_main, println}; +use riot_wrappers::{gcoap, thread, ztimer, gnrc}; + +use coap_handler_implementations::{ReportingHandlerBuilder, HandlerBuilder}; + +riot_main!(main); + +fn main() { + extern "C" { + fn do_vfs_init(); + } + + unsafe { do_vfs_init() }; + + let handler = coap_message_demos::full_application_tree(None) + .below(&["ps"], riot_coap_handler_demos::ps::ps_tree()) + .below(&["vfs"], riot_coap_handler_demos::vfs::vfs("/const")) + .with_wkc() + ; + let mut handler = riot_wrappers::coap_handler::GcoapHandler(handler); + + let mut listener = gcoap::SingleHandlerListener::new_catch_all(&mut handler); + + gcoap::scope(|greg| { + greg.register(&mut listener); + + println!("CoAP server ready; waiting for interfaces to settle before reporting addresses..."); + + let sectimer = ztimer::ZTimer::sec(); + sectimer.sleep_ticks(2); + + for netif in gnrc::Netif::all() { + println!("Active interface from PID {:?} ({:?})", netif.pid(), netif.pid().get_name().unwrap_or("unnamed")); + match netif.ipv6_addrs() { + Ok(addrs) => { + for a in addrs.addresses() { + println!(" Address {:?}", a); + } + } + _ => { + println!(" Does not support IPv6."); + } + } + } + + // Sending main thread to sleep; can't return or the Gcoap handler would need to be + // deregistered (which it can't). + loop { thread::sleep(); } + }) +} diff --git a/examples/rust-gcoap/vfs.c b/examples/rust-gcoap/vfs.c new file mode 100644 index 0000000000..ce25ee0c51 --- /dev/null +++ b/examples/rust-gcoap/vfs.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 OTA keys S.A. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * This file demonstrates how C code can be mixed with Rust code in an + * application in an ad-hoc fashion. + */ + +#include +#include "fs/constfs.h" +#include + +#define HELLO_WORLD_CONTENT "Hello World!\n" +#define HELLO_RIOT_CONTENT "Hello RIOT!\n" + +#define LARGE "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" \ + "1234567890---------\n" + +static constfs_file_t constfs_files[] = { + { + .path = "/hello-world", + .size = sizeof(HELLO_WORLD_CONTENT), + .data = (const uint8_t *)HELLO_WORLD_CONTENT, + }, + { + .path = "/hello-riot", + .size = sizeof(HELLO_RIOT_CONTENT), + .data = (const uint8_t *)HELLO_RIOT_CONTENT, + }, + { + .path = "/large", + .size = sizeof(LARGE), + .data = (const uint8_t *)LARGE, + } +}; + +static constfs_t constfs_desc = { + .nfiles = ARRAY_SIZE(constfs_files), + .files = constfs_files, +}; + +static vfs_mount_t const_mount = { + .fs = &constfs_file_system, + .mount_point = "/const", + .private_data = &constfs_desc, +}; + +void do_vfs_init(void) { + int res = vfs_mount(&const_mount); + if (res < 0) { + puts("Error while mounting constfs"); + } + else { + puts("constfs mounted successfully"); + } +}