Survival LLM
인터넷 없이도 동작하는 무료 AI 어시스턴트와 150만 건 오프라인 자료를 제공, 답변 출처 표시, Mac·Windows 지원
Pure-Rust no_std OpenWrt ubus protocol: client and object provider (alloc), fixed-buffer blob/blobmsg codecs without alloc, plus a Linux broker and CLI.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗ubus-zero is a no_std Rust implementation of the
OpenWrt ubus wire protocol: a
synchronous client, an object provider, and blob/blobmsg codecs. All I/O goes
through a small Transport trait, so the protocol core has no dependency on
Linux, sockets, executors or logging. The default alloc feature provides the
client and provider. Disable it for borrowed parsing and fixed-buffer encoding
without an allocator; see the bounded I/O guide.
The workspace also includes a Linux broker,
ubusd,
and a CLI,
ubus-client.
On supported protocol paths, the Rust ubusd matches pinned OpenWrt
reference behavior (ubus 24864e7, libubox 17f527f) byte for byte.
A shared canonicalizer replaces broker-assigned object, peer and type IDs
with placeholders in order of first appearance. Headers, attribute order,
padding, lengths, names, payloads and status codes must match exactly.
Scenarios without broker-assigned IDs are compared as raw bytes.
| Evidence | What it covers |
|---|---|
| 187 checked-in golden transcripts | 109 ACL and 78 protocol scenarios recorded from the pinned C broker; replayed against Rust without OpenWrt fixtures |
| Live differential matrix | The same scenarios run against both brokers. Live runs also check that the goldens still match the pinned binaries. |
| Real OpenWrt consumers | The ubus CLI, libubus callers and providers, rpcd sessions, UCI and the rpcd file plugin |
| Fault profiles | Fragmented client streams and injected EINTR across the strict suite, plus file-descriptor passing at framing boundaries |
| Differential fuzzing | Both brokers must stay alive and keep answering. Fixed bugs and strict-close cases are kept as a regression corpus. |
| CI | Formatting, Clippy with -D warnings, the workspace tests and the strict pinned-reference suite on every PR. A weekly, non-blocking job runs the suite against upstream master to catch drift. |
Arbitrary malformed input is outside the byte-parity contract: the Rust broker
may close a connection where upstream returns an error status. The Rust API is
independent of the C libubus API and remains pre-1.0. See
Compatibility testing
for the full contract and test procedures.
Performance comparisons measure verified workloads against both brokers, with latency percentiles, throughput and raw samples.
The Cargo package is ubus-zero; the library crate is ubus.
[dependencies]
ubus = { package = "ubus-zero", git = "https://github.com/no-std-rs/ubus-zero", default-features = false, features = ["alloc"] }
| Feature | Provides |
|---|---|
alloc (default) | Client, provider and owned codecs over your own Transport. Opens no sockets. |
| (no default features) | Borrowed wire/blob/blobmsg readers and fixed-buffer builders; no allocator required |
signal | Linux bounded submission queue and resumable stream sender; works without alloc |
json (implies alloc) | ubus::json::{json_to_blobmsg, blobmsg_to_json}, still alloc without std |
unix (implies alloc) | ubus::unix::UnixUbusTransport for Linux Unix sockets via rustix, with monotonic deadlines |
portable-atomic | Shared-buffer helpers and the spin mutex on targets without pointer-width atomics (e.g. ESP32-C3) |
Given a connected transport and a service providing system.board:
extern crate alloc;
use alloc::vec::Vec;
use ubus::client::UbusClient;
use ubus::{BlobMsgTable, Transport};
fn board<T: Transport>(transport: T) -> ubus::Result<Vec<u8>> {
let mut client = UbusClient::connect(transport)?;
let system = client.lookup("system")?;
client.invoke(system, "board", &BlobMsgTable::empty())
}
invoke returns the last DATA reply as blobmsg table contents. invoke_many
returns every DATA reply. request and the methods built on it buffer
unrelated frames for recv_frame. lookup and invoke do not, so use the
request-based methods when you mix calls with events or subscriptions.
Provide an object:
use ubus::server::UbusConnection;
use ubus::{BlobMsgTable, Transport, UbusObject};
fn register_echo<T: Transport>(transport: T) -> ubus::Result<UbusConnection<T>> {
let object = UbusObject::new("example.echo").method("ping", |_request| {
Ok(BlobMsgTable::build(|reply| {
reply.put_str(Some("message"), "pong");
}))
});
UbusConnection::connect_and_register(transport, object)
}
Registering an object does not dispatch requests on its own. Keep the
connection alive and call poll_one() from your event loop. Each call handles
at most one frame. DispatchOutcome::Idle means no complete frame is
available, so wait or yield before polling again.
With unix enabled, UnixUbusTransport::connect("/tmp/ubus.sock") gives you a
ready transport. Call set_deadline before each request on a reused connection.
On targets without pointer-width atomics, configure portable-atomic's
appropriate fallback; the ESP32 example demonstrates a single-core setup.
Some APIs were adapted from Cellctl; see the
Cellctl imports.
cargo install --git https://github.com/no-std-rs/ubus-zero ubusd
cargo install --git https://github.com/no-std-rs/ubus-zero ubus-client
ubusd --socket /tmp/ubus.sock # terminal 1
ubus-client -s /tmp/ubus.sock list # terminal 2
A fresh standalone broker has no services. It only routes requests between
connected clients, so list starts empty and system is not available. To
register a provider, use ubus-client serve.
Non-root clients need ACL grants to register named objects, call methods,
subscribe, or send and listen for events. Without --acl-dir, all of these are
denied. Root bypasses ACLs, and monitoring requires root. The
daemon guide
has a working ACL and provider example. The
CLI guide
covers calls, events, subscriptions, JSON Lines batches and program-backed
providers.
A no_std firmware example
turns the GUITION ESP32-2424S012 round display into a live OpenWrt dashboard.
It shows traffic, load, memory, Wi-Fi and router identity, read through
uhttpd's /ubus bridge with a read-only rpcd account. The
browser USB installer can flash the
firmware from a desktop browser with Web Serial.
On Linux, with the pinned Rust toolchain and a C compiler:
cargo build -p ubusd --features testing # broker for the test harness
cargo test --workspace --all-features # Rust tests + golden replay
tools/ubusd-builder/build.sh # pinned OpenWrt fixtures (Docker Buildx)
python3 tools/ubus-compat-check.py # strict live suite
Without the fixtures, reference-backed tests print SKIP. The strict runner
fails instead. See
CONTRIBUTING.md
for the full checklist and the
security policy
for reporting vulnerabilities.