Runtime-agnostic mDNS / DNS-SD engine for bare metal — responder and querier
over smoltcp UDP, no_std + alloc, no OS and no async runtime required.
Introduction
hick-smoltcp drives the Sans-I/O core (mdns-proto) over a smoltcp UDP
socket through a small UdpIo transport seam. It owns no executor and performs
no blocking: you pump it from your own poll loop alongside the smoltcp
Interface, and it tells you when to wake next. This is the shared engine the
hick-embassy driver builds on — but it is usable standalone with any smoltcp
stack.
no_std + alloc: the protocol state lives in slab-backed pools, so there is
no per-packet heap traffic on the hot path.
Installation
[]
= "0.1"
Example
use ;
use ;
// The engine wires mdns-proto's alloc-tier state machines to any `UdpIo`. For
// smoltcp, use the family-aware `DualStack` over your v4 and/or v6 socket handles.
let mut engine = new;
let mut records = new;
records.add_a;
engine.register_service?;
// Pump from your own loop, handing it a `DualStack` view of your sockets and a
// scratch buffer. The engine fans each multicast to BOTH groups, so `DualStack`
// routes by family (leave a family `None` for a single-stack node). `pump` returns
// the next instant the engine wants to be polled.
loop
Feature flags
| Feature | Description |
|---|---|
atomic (default) |
The native-atomic alloc tier: SmolStr names + Bytes rdata. Needs pointer-width atomics. |
no-atomic |
For cores without native atomic CAS (Cortex-M0+ / thumbv6m / RP2040): swaps the refcounted Name / rdata onto portable-atomic's Arc (clone via a critical-section impl your binary provides), keeping the alloc-backed pools. Build with --no-default-features --features no-atomic. |
tracing |
Forward structured tracing events from mdns-proto (requires a std subscriber; a no-op on bare-metal without one). |
stats |
Enable no_std-safe atomic counters; read a snapshot via engine.stats(). Implies atomic. |
defmt |
Emit defmt log events — the idiomatic choice for bare-metal targets. |
Observability
For bare-metal targets the recommended logging path is defmt combined with
stats:
= { = "0.1", = ["defmt", "stats"] }
Enable defmt to have the engine emit structured log events through the
defmt framework at the level your firmware configures.
Enable stats and call engine.stats() to obtain a
hick_trace::stats::StatsSnapshot:
let snap = engine.stats;
// snap.packets_rx, snap.cache_size, etc.
The tracing feature is available but is a no-op in bare-metal builds that
do not set up a tracing subscriber.
The metrics feature (bridging counters to the metrics facade) requires
std and is not available on bare-metal targets. Use stats + defmt
instead for observability on embedded.
Design
no_std+alloc, panic-free hot path: slab-backed protocol pools, no per-packet allocation.UdpIotransport seam — a two-method, non-blocking trait (try_recv/try_send). The family-awareDualStackimplements it over smoltcp UDP sockets (routing each multicast to the socket of its own family); bring your own and the engine is transport-agnostic.- RFC 6762 §11 on-link gate — uses the received hop-limit (
== 255) when the transport surfaces it, else falls back to a source-subnet membership check. - RFC 6762 §10.1 goodbye — unregistering an announced service emits a TTL=0 goodbye, bursted a few times by the pump.
Pinned to a single smoltcp 0.13, unified with the version hick-embassy's
embassy-net pulls in.
The hick family
hick (facade) · mdns-proto (Sans-I/O core) · hick-udp (UDP) ·
hick-reactor (tokio / smol driver) · hick-compio (compio driver) ·
hick-smoltcp (this crate) · hick-embassy (embassy driver).
License
hick-smoltcp is under the terms of both the MIT license and the Apache License
(Version 2.0).
See LICENSE-APACHE, LICENSE-MIT for details.
Copyright (c) 2025 Al Liu.