6.9 KiB
RNS Link API
MeshChatX exposes a generic Reticulum Link transport on the main WebSocket (/ws). External apps and plugins can open links, run request/response exchanges, send packets, and tear links down without going through NomadNet helpers.
When to use it
Your app or plugin needs a live RNS Link
|
--> Not NomadNet page browsing
--> Not LXMF messaging
|
--> Use rns.link.* over /ws
or plugin managers rnsLink.*
Address peers by destination hash and aspect. Do not invent IP or hostname shortcuts.
Auth
When password auth is enabled, every rns.link.* client message needs an authenticated session. Same rule as other WebSocket mutators.
Link lifecycle
Client sends rns.link.open
|
--> MeshChatX finds or opens path to destination
|
--> Link cached under (aspect, destination_hash)
|
--> Optional auto_identify
|
--> success / failure reply on same type + request_id
|
+--> rns.link.request / rns.link.send on the cached link
|
+--> rns.link.close tears down and uncaches
|
+--> disconnect cancels in-flight open / request for that client
Cache notes:
- Key is
(aspect, destination_hash) - Cap is 64 active links
- Idle links expire after about 30 minutes
- Repeated request failures recycle the cached link so the next call re-opens
Client to server
All messages need a unique request_id so replies can be matched.
type |
Required fields | Optional | Behaviour |
|---|---|---|---|
rns.link.open |
destination_hash, aspect, request_id |
auto_identify |
Open or reuse a cached link. Streams phase then success / failure. |
rns.link.identify |
destination_hash, aspect, request_id |
Call link.identify(local_identity) on the cached link. |
|
rns.link.request |
destination_hash, aspect, path, request_id |
data_b64, timeout |
Ensure the link is open, then link.request(path, data=…). |
rns.link.send |
destination_hash, aspect, payload_b64, request_id |
Send a raw packet on the cached link. | |
rns.link.close |
destination_hash, aspect, request_id |
Teardown and uncache the link. |
Field details:
destination_hash: hex string of the peer destinationaspect: dot-separated RNS app name + sub-aspects, for examplemicrorn.mgmtdata_b64/payload_b64/ replybody_b64: msgpack payloads, base64-encodedpath: request path string on the remote link endpointtimeout: seconds for the request wait
Example open:
{
"type": "rns.link.open",
"destination_hash": "aabbccddeeff00112233445566778899aabbccdd",
"aspect": "microrn.mgmt",
"request_id": "req-1",
"auto_identify": true
}
Example request:
{
"type": "rns.link.request",
"destination_hash": "aabbccddeeff00112233445566778899aabbccdd",
"aspect": "microrn.mgmt",
"path": "/status",
"request_id": "req-2",
"data_b64": null,
"timeout": 15
}
Server to client
Per-request_id replies reuse the same type with a status:
status |
Meaning |
|---|---|
phase |
Progress step while opening or requesting |
progress |
Additional progress detail when available |
success |
Operation finished |
failure |
Operation failed (includes an error message) |
Broadcast events (not tied to one request_id):
type |
event |
Notes |
|---|---|---|
rns.link.event |
packet_received |
Includes payload_b64 |
rns.link.event |
link_closed |
Cached link removed |
Inbound packet on a cached link
|
--> Broadcast rns.link.event / packet_received
|
Link torn down or evicted
|
--> Broadcast rns.link.event / link_closed
Plugins
Plugins call the same transport through HTTP invoke instead of speaking WebSocket types directly.
Plugin Worker
|
--> POST /api/v1/plugins/{id}/invoke
method: "callManager"
|
--> PluginManager checks granted managers
|
--> RnsLinkManager open / identify / request / send / close
Declare managers in plugin.json:
| Manager | Maps to |
|---|---|
rnsLink.open |
Open or reuse link |
rnsLink.identify |
Identify on cached link |
rnsLink.request |
Request/response |
rnsLink.send |
Raw packet send |
rnsLink.close |
Teardown |
Subscribe to async traffic with:
{
"permissions": {
"hooks": ["rns.link.event"],
"managers": ["rnsLink.open", "rnsLink.identify", "rnsLink.request", "rnsLink.send", "rnsLink.close"],
"storage": "isolated",
"network": "none"
}
}
Hook delivery:
RnsLinkManager event
|
--> PluginManager.dispatch_hook("rns.link.event", …)
|
--> WebSocket plugin.event to the UI
|
--> Plugin Worker on_hook / event handler
External app pattern
Connect to MeshChatX /ws (auth cookie / session as required)
|
--> Send rns.link.open with request_id
|
--> Wait for matching success
|
--> Send rns.link.request or rns.link.send
|
--> Listen for rns.link.event broadcasts
|
--> Send rns.link.close when finished
Keep one request_id per outstanding call. Cancel or ignore replies after you disconnect. MeshChatX cancels in-flight open/request work for that WebSocket client on disconnect.
Limits and failure behaviour
- Missing path or unreachable peer returns
failureon the open/request reply - After repeated request failures on one cached link, MeshChatX recycles that link
- Idle unused links are swept after about 30 minutes
- Over-cap eviction drops the oldest unused links first
Implementation map
/ws rns.link.*
|
--> meshchat.py WebSocket dispatch + per-client task tracking
|
--> rns_link_manager.py cache, open, identify, request, send, close
|
--> plugin_manager.py capability wrappers + hook fan-out
See also
- Plugins for install, grants, and invoke flow
- Architecture and design for WebSocket and plugin runtime overview
- Identities, privacy, and security for auth and session rules