zigmeshcore is a Zig implementation of the core MeshCore packet protocol. It provides packet encoding and decoding, cryptographic primitives, identity and group messaging, packet scheduling, radio integration, and a high-level mesh node API.
The library is designed for embedded and native applications. Protocol data uses fixed-capacity storage, and platform-specific behavior is supplied through small type-erased interfaces.
Current version: 0.1.0
- Zig 0.16.0 or newer
- A radio implementation when using the dispatcher or high-level mesh API
The package has no external Zig dependencies.
Add zigmeshcore to your project's build.zig.zon. For a local checkout:
.dependencies = .{
.zigmeshcore = .{
.path = "../zigmeshcore",
},
},Then import the module in build.zig:
const zigmeshcore = b.dependency("zigmeshcore", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("zigmeshcore", zigmeshcore.module("zigmeshcore"));In application code:
const mesh = @import("zigmeshcore");The Packet type stores decoded packet fields and serializes them into the
MeshCore wire format.
const std = @import("std");
const mesh = @import("zigmeshcore");
pub fn main() !void {
var packet: mesh.Packet = .init();
packet.header =
(mesh.constants.PAYLOAD_TYPE_ACK << mesh.constants.PH_TYPE_SHIFT) |
mesh.constants.ROUTE_TYPE_DIRECT;
packet.payload[0..4].* = .{ 1, 2, 3, 4 };
packet.payload_len = 4;
var encoded: [mesh.constants.MAX_TRANS_UNIT]u8 = undefined;
const encoded_len = packet.writeTo(&encoded) orelse
return error.InvalidPacket;
var decoded: mesh.Packet = .init();
if (!decoded.readFrom(encoded[0..encoded_len]))
return error.InvalidPacket;
std.debug.assert(
decoded.getPayloadType() == mesh.constants.PAYLOAD_TYPE_ACK,
);
}Packet.writeTo returns null if the packet is invalid or the destination is
too small. Packet.readFrom returns false for malformed or unsupported input.
Mesh connects the protocol implementation to application-owned platform
services:
Radiohandles raw frame transmission and reception.PacketManagerowns packets and the inbound and outbound queues.Clockprovides monotonic time.RealtimeClockprovides Unix time for advertisements.RNGsupplies random bytes.Tablestracks packets used for duplicate detection.Handlerreceives mesh events and supplies peer and channel lookups.LocalIdentitysupplies Ed25519 signing and X25519 agreement operations.
Create concrete implementations, wrap them with each interface's init
function, and pass the resulting interfaces to Mesh.init. Call begin once,
then call loop regularly from the application's event loop.
var node: mesh.Mesh = .init(
mesh.Radio.init(&radio_impl),
packet_pool.interface(),
mesh.Clock.init(&clock_impl),
rng_impl.rng(),
mesh.RealtimeClock.init(&realtime_impl),
mesh.Tables.init(&tables_impl),
local_identity,
mesh.Handler.init(&handler_impl),
);
try node.begin();
while (true) {
try node.loop();
}The exact method requirements for each platform interface are documented in the generated API reference and enforced at compile time.
- MeshCore packet parsing, validation, hashing, and serialization
- Flood, transport flood, direct, and zero-hop routing
- Advertisements, peer datagrams, anonymous datagrams, and group datagrams
- Acknowledgements, path returns, trace packets, and custom data packets
- Fixed-capacity packet pools and scheduled inbound and outbound queues
- Type-erased radio, clock, entropy, RNG, handler, and storage interfaces
- SHA-256, SHA-512, HMAC, AES-128, X25519, and Ed25519 support
- Software crypto implementations with replaceable backends
- Dispatcher statistics, fault tracking, airtime budgeting, and radio recovery
The package exports commonly used types and functions at its root. It also exposes focused modules for lower-level access:
packet,path, andconstantsmesh,dispatcher,radio, andpacket_manageridentity,group_channel,mesh_handler, andmesh_tableshash,cipher,ecdh, andsignaturerng,entropy,clock,instant, andhex
See src/root.zig for the complete public surface.
Run all library and downstream import tests:
zig build testGenerate the API documentation:
zig build docsThe generated documentation is written to zig-out/docs/index.html.
Packets obtained from a Mesh or PacketManager belong to the caller until
they are queued or released. A successful send operation transfers the packet
to the outbound queue. If packet creation or sending fails, release any packet
still owned by the caller. Do not free or reuse a queued packet.
For simple fixed-capacity storage, use StaticPoolPacketManager(N) or
FixedPacketManager(pool_size, outbound_size, inbound_size).
zigmeshcore is available under the MIT License. See LICENSE.