Skip to main content
From v0.30.0 the SDK has a C API over the same native library the other bindings load. It is the local API called in process: you create an engine from a JSON configuration, call any method of the interface definition by name with JSON parameters, and receive events as JSON. Any language that calls C uses it the same way, including C++, Go through cgo, C# through P/Invoke and Zig. The header declares about a dozen functions, and it does not change when a method is added to the interface definition, so a wrapper in another language keeps working across releases.

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). MeshServices methods carry services. (services.register_service) and DataStore methods carry data. (data.create_doc).
  • Parameters are a JSON object keyed by the definition’s parameter names. NULL means 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.variant to the ProtocolError variant name and err.code to its position, the same number as the local API’s -32000 - n. See error codes.
Unlike the local API service, the C binding reaches the transport methods (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 with offline_protocol_string_free, and nothing else with it. Clear an OfflineProtocolError with offline_protocol_error_clear after 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 drop function and a ctx. The library calls drop(ctx) exactly once, including when it refuses the registration, so never free ctx yourself.
  • Every entry point catches a panic and answers OfflineProtocolStatus_Internal instead of aborting your process.

Events

Install a callback with offline_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 with offline_protocol_run_storage_conformance.
  • Lifecycle. start, stop and process on a timer. For telemetry, the binding fills os; pass os_major yourself and report backgrounding with notify_app_state.
  • One engine per handle, freed once, with no call in flight when it is.

Reference

The SDK is AGPL-3.0-only with a commercial license available; see licensing.