What you need
The release archives are
offline-protocol-0.30.0-linux-x86_64.tar.gz, offline-protocol-0.30.0-linux-aarch64.tar.gz, offline-protocol-0.30.0-macos-arm64.tar.gz and offline-protocol-0.30.0-windows-x86_64.zip. The iOS XCFramework in the same release carries the same C functions, and the same header applies. The Android libraries do not: the C binding is off in the Android builds.
To build the library yourself, including the static archive the releases do not ship, use Rust 1.91 or newer:
Quick start
This program creates an engine, sets up storage, starts it and sends a message. It is the SDK’s own quick start, which the release compiles and runs against each desktop library before publishing.Call methods
Method names, parameter names and the JSON form of every type are the local API’s, so its method table is the reference for what you can call.- Engine methods are bare (
send_message).MeshServicesmethods carryservices.(services.register_service) andDataStoremethods carrydata.(data.create_doc). - Parameters are a JSON object keyed by the definition’s parameter names.
NULLmeans no parameters. - Bytes are padded standard base64. Enums are spelled as the definition spells them (
"WiFiDirect","Medium"). An omitted dictionary field takes the definition’s default. An unknown key is refused. - A method that returns nothing returns
null. - An engine refusal sets
err.variantto theProtocolErrorvariant name anderr.codeto its position, the same number as the local API’s-32000 - n. See error codes.
ble_, internet_, wifi_direct_, reticulum_, nostr_) and the platform operations such as send_file_from_path, because your process is the platform here and owns the radios, sockets and files.
The declarations that take a callback have their own functions: events, the four transport notifications, initialize_mls with your own storage providers, and the storage conformance suite. The header documents each.
Ownership and threads
- Free every
char *the library returns withoffline_protocol_string_free, and nothing else with it. Clear anOfflineProtocolErrorwithoffline_protocol_error_clearafter every failure. - The library writes a result only when a call succeeds. Free a result only after
OfflineProtocolStatus_Ok. - A callback runs synchronously on whichever thread is inside the engine. It must be safe from any thread, must not call back into the engine and must not unwind. Copy the event, queue it and return.
- Every function that takes a callback also takes a
dropfunction and actx. The library callsdrop(ctx)exactly once, including when it refuses the registration, so never freectxyourself. - Every entry point catches a panic and answers
OfflineProtocolStatus_Internalinstead of aborting your process.
Events
Install a callback withoffline_protocol_set_event_callback, or poll with offline_protocol_poll_event. Every event is queued either way; the queue keeps the newest 1,000. Event payloads are the engine’s JSON, the same as the event reference describes.
What your host provides
The C binding provides nothing beyond the engine:- Transports. Drain each transport’s outbound queue, perform the I/O, report the outcome and inject what you receive. The transport callbacks say when a queue has frames; the Internet transport has none and is polled.
- Storage. Two storage providers written in C, or the built-in file stores through
initialize_mls_with_file_stores. Prove a provider withoffline_protocol_run_storage_conformance. - Lifecycle.
start,stopandprocesson a timer. For telemetry, the binding fillsos; passos_majoryourself and report backgrounding withnotify_app_state. - One engine per handle, freed once, with no call in flight when it is.
Reference
- C binding README and its consumer check, two complete C programs CI compiles and runs.
- C binding contract: ownership, threading, storage providers and which builds carry the binding.
- Local API specification: method names, encodings and errors.

