This document describes the current public FFI surface exported by cmd/moss-ffi.
For packaging, lifecycle, callback/threading guidance, and JNI integration patterns, see docs/SHARED_INTEGRATION.md.
Build Moss as a C-shared library:
# Linux
go build -buildmode=c-shared -o libmoss.so ./cmd/moss-ffi
# Windows
go build -buildmode=c-shared -o moss.dll ./cmd/moss-ffi
# macOS
go build -buildmode=c-shared -o libmoss.dylib ./cmd/moss-ffiThe generated C header is emitted next to the library (moss.h or libmoss.h).
MossHandle Moss_Init(const char* mesh_id, const uint8_t* psk, const char* config);Creates a node instance and returns an opaque handle.
mesh_id: required UTF-8 mesh identifier.psk: optional 32-byte pre-shared key; passNULLfor an open mesh.config: optional JSON config; passNULLfor defaults.
Returns a positive handle on success or a negative error code on failure.
int32_t Moss_Start(MossHandle handle);Starts listeners, bootstrap, maintenance loops, NAT profiling, and mesh operations.
int32_t Moss_Stop(MossHandle handle);Stops the node, closes sessions, releases runtime resources, and invalidates the handle.
int32_t Moss_Connect(MossHandle handle, const char* addr);Attempts an explicit direct connection to host:port.
This is optional. The runtime can still bootstrap and discover peers autonomously.
int32_t Moss_Subscribe(MossHandle handle, const char* channel);Subscribes the local node to a channel.
int32_t Moss_Unsubscribe(MossHandle handle, const char* channel);Unsubscribes from a channel and sends PRUNE to current mesh peers.
int32_t Moss_Publish(MossHandle handle, const char* channel,
const uint8_t* data, uint32_t len);Publishes a binary payload to a channel.
The current runtime uses:
- local flood publish to eligible direct peers
- GossipSub-style mesh forwarding
IHAVE/IWANTreplay for recent messagesIDONTWANTsuppression for larger payloads
int32_t Moss_SetCallback(MossHandle handle, MossMessageCallback cb);Registers the per-message callback.
Callback signature:
typedef void (*MossMessageCallback)(const char* channel,
const uint8_t* sender_id,
const uint8_t* data,
uint32_t len);int32_t Moss_SetEventCallback(MossHandle handle, MossEventCallback cb);Registers the event callback.
Callback signature:
typedef void (*MossEventCallback)(int32_t event_type,
const char* detail_json);Current event IDs:
1EventPeerJoined2EventPeerLeft3EventSupernodePromoted4EventSupernodeRevoked5EventTrackerAnnounce6EventTrackerFailure7EventRelayMigrated
int32_t Moss_SetScoringCallback(MossHandle handle, MossScoringCallback cb);Allows the host application to override per-peer score decisions used by:
- mesh candidate selection
- pruning
- opportunistic grafting
- relay candidate ranking
Callback signature:
typedef double (*MossScoringCallback)(const uint8_t* peer_id,
double base_score);peer_id is the 32-byte public identity key.
int32_t Moss_SetKeyStore(MossKeyStoreLoadCallback load,
MossKeyStoreSaveCallback save);Registers global identity persistence callbacks used by subsequent Moss_Init calls.
Callback signatures:
typedef uint32_t (*MossKeyStoreLoadCallback)(uint8_t* buffer,
uint32_t capacity);
typedef void (*MossKeyStoreSaveCallback)(const uint8_t* data,
uint32_t len);Behavior:
- if
loadreturns a valid encoded identity, Moss reuses it - otherwise Moss generates a new identity and calls
save
const char* Moss_GetMeshInfo(MossHandle handle);Returns a JSON document describing the current node state. Current fields:
{
"mesh_id": "example",
"listen_port": 41030,
"peer_count": 3,
"peers": ["10.0.0.10:41031"],
"channels": ["alpha"],
"nat_type": "unknown",
"public_key": "hex-encoded-32-byte-key",
"supernode_ready": false
}const uint8_t* Moss_GetPublicKey(MossHandle handle);Returns a newly allocated 32-byte public key buffer.
const char* Moss_GetNATType(MossHandle handle);Returns the current NAT type string, for example:
unknownpublicfull_conerestricted_coneport_restricted_conesymmetric_natcgnat
void Moss_Free(void* ptr);Frees memory returned by:
Moss_GetMeshInfoMoss_GetPublicKeyMoss_GetNATType
Current error codes:
0MOSS_OK-1MOSS_ERR_INVALID_HANDLE-2MOSS_ERR_ALREADY_STARTED-3MOSS_ERR_NOT_STARTED-4MOSS_ERR_INVALID_CHANNEL-5MOSS_ERR_MESSAGE_TOO_LARGE-6MOSS_ERR_NO_PEERS-7MOSS_ERR_TRACKER_FAIL-8MOSS_ERR_CONFIG_INVALID-9MOSS_ERR_OUT_OF_MEMORY-10MOSS_ERR_CONNECT_FAILED
Top-level config schema:
{
"trackers": ["udp://tracker.opentrackr.org:1337/announce"],
"announce_interval_sec": 120,
"listen_port": 0,
"max_peers": 200,
"static_peers": ["10.0.0.10:41030"],
"bootstrap_timeout_sec": 3,
"gossipsub": {
"D": 6,
"D_lo": 4,
"D_high": 12,
"D_out": 2,
"D_lazy": 6,
"heartbeat_ms": 1000
},
"nat": {
"upnp_enabled": false,
"natpmp_enabled": false,
"pcp_enabled": false,
"supernode_min_uptime_sec": 300,
"relay_max_bandwidth_kbps": 256,
"relay_max_sessions": 50,
"relay_session_ttl_sec": 1800,
"hole_punch_attempts": 3,
"port_prediction_enabled": true
},
"security": {
"handshake_timeout_sec": 5,
"max_message_size_bytes": 65536,
"rate_limit_burst": 256000,
"rate_limit_sustained": 64000
},
"transport": {
"high_throughput": false,
"stream_buffer_size": 0,
"udp_buffer_size": 0
}
}Notes:
- omitting
trackersuses the built-in default tracker set - explicitly passing
"trackers": []disables tracker bootstrap - partial nested config objects are supported; unspecified fields fall back to defaults
The transport block controls per-session inbound queue sizes and
gossip overhead. Defaults (256-packet queues, full GossipSub control
traffic) suit chat- and discovery-style workloads where each peer
publishes at most a handful of messages per second.
For high-rate point-to-point streams (file transfer, game traffic,
media tunnels), set high_throughput: true. This applies the following
preset to the node, taking effect on the next Moss_Start:
- per-stream and per-UDP-session inbound queues grow from 256 to 65536 packets, eliminating silent drops during bursts
IHAVEandIDONTWANTgossip control broadcasts are skipped on publish, since they exist to amortize duplicate delivery in large meshes and add pure overhead in dense point-to-point topologies
stream_buffer_size and udp_buffer_size allow per-axis overrides when
the preset is too coarse — set them explicitly to choose the queue
capacity without enabling the full preset, or alongside
high_throughput to keep the gossip-overhead reduction while picking
custom queue sizes. Values <= 0 fall back to defaults / the preset.
Default is high_throughput: false so existing integrations keep
their original memory footprint.
Example integrations live in:
examples/c_exampleexamples/cpp_exampleexamples/csharp_exampleexamples/python_exampleexamples/python_chatexamples/rust_example
The CI-style smoke coverage in cmd/moss-ffi/main_test.go currently compile-and-run tests:
- C
- C++
- Python
- C#
Rust is run when a valid Rust toolchain is configured in the environment.