Low-level constructor. Prefer the Link.initiate / Link.accept factories.
OptionalephemeralEd25519Priv?: CryptoKeyInitiator's fresh ephemeral Ed25519 private key (link-proof signing).
This side's ephemeral X25519 private key.
OptionalephemeralX25519Pub?: Uint8Array<ArrayBufferLike>This side's ephemeral X25519 public key (raw 32 bytes).
Optionalmode?: numberOptionalmtu?: numberOptionalpeerEd25519Pub?: Uint8Array<ArrayBufferLike>Peer's ephemeral Ed25519 public key (raw 32 bytes). Responder-only: the initiator's link-proof signing pub, captured from the LINKREQUEST body so the responder can verify initiator-signed link proofs (§6.5).
OptionalpeerX25519Pub?: Uint8Array<ArrayBufferLike>Peer's ephemeral X25519 public key (raw 32 bytes).
Cached verify-only CryptoKey imported from peerEd25519Pub (responder).
Outbound CTX_NONE DATA packet hashes (hex → bytes) awaiting a link PROOF (§6.5).
The interface this link's traffic flows over — the interface the
LINKREQUEST arrived on (responder) or the LRPROOF arrived on
(initiator). Mirrors the Python reference's Link.attached_interface.
The transport's TransportCore.sendPacket routes LINK-destination packets (LRPROOF, link DATA, keepalives, teardown) over this interface when no routing-table entry exists for the link id — the link's return path is its arrival interface for the link's lifetime, independent of which interface happens to be the node's default.
Injected bz2 module (PROTOCOL-SPEC.md §10.2 step 2). The library never imports a compression dependency; the application assigns this if it wants Resource compression. When unset, compressed advertisements cannot be decompressed locally and sender-side compression is skipped.
Hop count the link was initiated expecting (Link.expected_hops). Set
from hopsTo(destination) on the initiator and from the LINKREQUEST hop
count on the responder. null until then. The terminus rebalance
corrects both this and the path table if the real hop count differs.
Original hashes of split resources that failed mid-transfer; late segments for these are rejected instead of restarting an assembler.
Incoming Resources (this side is the receiver) keyed by hex(resource.hash). Populated from RESOURCE_ADV; parts are routed by map_hash matching.
Wall-clock ms of the last keepalive sent on this link. Purely an egress-cadence guard: unlike Link#lastInboundTime it never counts toward liveness — a keepalive we sent proves nothing about the peer still being there. Gating pings on it also prevents a ping storm while a pong is in flight or lost.
The request window the most recently concluded incoming transfer on
this link had adapted to (Python Link.last_resource_window). New
incoming transfers seed their window from it, so repeated transfers
over one link — repeated peer syncs, repeated client fetches — resume
at the earned throughput instead of re-learning it from 4 parts per
round-trip every time.
Cap on advertised Resource size accepted inbound (§10.4 bomb defense).
Applications may lower this; null keeps the Resource default.
Outgoing Resources (this side is the sender) keyed by hex(resource.hash)
— PROTOCOL-SPEC.md §10. Driven by Resource.advertise and fulfilled by
inbound RESOURCE_REQ / RESOURCE_PRF / RESOURCE_RCL.
Initiator-side pending REQUESTs keyed by hex(request_id) (PROTOCOL-SPEC.md §11.5). Each entry resolves/rejects its returned Promise when the matching RESPONSE arrives or the timeout fires.
handedOut tracks whether request() has returned the response promise
to a caller yet. Between registering the entry and returning the promise,
request() is still awaiting the transmit — during that window nobody
holds the promise, so settling it with a rejection would surface as an
unhandled rejection and crash the process. Unheld entries are settled
quietly instead (see _failPendingRequest), and request() rethrows the
recorded error once the transmit settles.
Pending outgoing resource payloads keyed by hex hash (RESOURCE_ADV/REQ).
Epoch ms of the last path-rebalance, or null if none (Link.rebalanced).
Wall-clock time (ms) at which the LINKREQUEST was sent (initiator) or received (responder). Used to measure RTT.
Split-resource assemblers (§10.3) keyed by hex(originalHash) — the first segment's hash that ties all segments of one logical transfer together.
StaticALLOW_Whether the link terminus corrects its path-table hop estimate when a
link handshake's packets traverse a different hop count than expected
(RNS.Transport.ALLOW_LINK_PATH_REBALANCE). Default on, matching upstream.
StaticDEFAULT_Default Reticulum MTU when MTU discovery is disabled or unavailable.
StaticEC_Combined size of the two initiator ephemeral public keys (X25519 + Ed25519).
StaticKEEPALIVE_StaticKEEPALIVE_StaticKEEPALIVE_StaticMODE_Default link mode (the only enabled mode in upstream RNS).
StaticRESPONSE_Fixed multiplier on the response grace term (PROTOCOL-SPEC.md §11.5).
StaticRESPONSE_Response-side grace term for the default REQUEST timeout
(PROTOCOL-SPEC.md §11.5). Mirrors
RNS.Resource.RESPONSE_MAX_GRACE_TIME — the same caveat applies.
StaticSIGNALLING_Size of the optional MTU/mode signalling trailer on LINKREQUEST/LRPROOF.
StaticSTALE_StaticTRAFFIC_Multiplier on measured RTT used when computing the default REQUEST
response timeout (PROTOCOL-SPEC.md §11.5). Mirrors
RNS.Link.TRAFFIC_TIMEOUT_FACTOR — verify against upstream if precise
timeout parity matters.
Maximum plaintext bytes that fit in a single link DATA packet after Token encryption and the HEADER_1 framing are applied (PROTOCOL-SPEC.md §11.1, §5.2).
The on-wire form of a link DATA packet is:
flags(1) hops(1) dest_hash(16) context(1) iv(16) aes_ct hmac(32)
\---------------------- 19 ----------------/ \------ 48 ------/
PKCS#7 padding always adds 1–16 bytes (a full block when the plaintext is
itself a block multiple), so the largest plaintext P whose ciphertext
fits the remaining budget is the largest block-multiple ciphertext ≤
(mtu − 67) minus one byte. At the default mtu = 500 this yields the
spec-pinned MDU = 431 (wire packet 499 B, verified against RNS).
The current link status.
Transitions the link to a new status, emitting statuschange.
Internal
Registers an incoming Resource (receiver side) keyed by hex(resource.hash).
Internal
Registers an outgoing Resource (sender side) keyed by hex(resource.hash).
Internal
Removes an incoming Resource registration.
Internal
Removes an outgoing Resource registration (e.g. a split resource advancing to its next segment, keyed by the previous segment's hash).
The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.
Optionaloptions: boolean | AddEventListenerOptionsThe dispatchEvent() method of the EventTarget sends an Event to the object, (synchronously) invoking the affected event listeners in the appropriate order. The normal event processing rules (including the capturing and optional bubbling phase) also apply to events dispatched manually with dispatchEvent().
The reliable typed-message Channel for this link (the Python
reference's Link carries one lazily). Lazily created on first access (or on the first inbound
CHANNEL packet). Returns the same instance for the lifetime of the link.
Register message classes with channel.registerMessageType(...) and
receive with channel.addMessageHandler(cb); send with
channel.send(message).
Initiator: prove which long-term identity owns this link to the responder.
Must be called AFTER the link is ACTIVE and BEFORE sending any application DATA. This is load-bearing for Python-LXMF interop: the Python LXMRouter does not install its link-data listener until it has processed LINKIDENTIFY, so a DATA/RESOURCE sent before LINKIDENTIFY is silently dropped on the Python side. Wire body (link-encrypted):
public_key(64) || signature(64)
where signature = identity.sign(link_id || public_key), matching the
Python reference.
The initiator's long-term identity.
Queues and processes an inbound packet addressed to this link.
OptionalreceivingInterface: Interface | null = null
Interface the packet arrived on. On the initiator side the LRPROOF's
arrival interface becomes Link.attachedInterface (the reference
sets attached_interface at proof validation), pinning the return
path for the rest of the link's lifetime.
The removeEventListener() method of the EventTarget interface removes an event listener previously registered with EventTarget.addEventListener() from the target. The event listener to be removed is identified using a combination of the event type, the event listener function itself, and various optional options that may affect the matching process; see Matching event listeners for removal.
Optionaloptions: boolean | EventListenerOptionsInitiator: send a REQUEST over the link and await the RESPONSE (PROTOCOL-SPEC.md §11.1, §11.5).
Packs the msgpack envelope [timestamp, path_hash, data] (single pack —
data is encoded directly, NOT pre-msgpacked), dispatches by size, and
returns a Promise that resolves with the response value when the server's
matching RESPONSE arrives.
For a single-packet REQUEST the request_id the server echoes back is
SHA-256(packet.get_hashable_part())[:16] — the truncated hash of the
encrypted wire packet, computed identically on both sides. It is NOT
random and NOT a hash of the plaintext envelope.
Opaque path token (e.g. "/page/index.mu").
Optionaldata: any = null
Application value for envelope element [2]
(null for plain GETs, an object for NomadNet form posts, an array for
LXMF /get rounds, a Uint8Array for opaque blobs …). Passed to msgpack
directly — do NOT pre-pack it.
Optionaloptions: {OptionalonMetadata?: (metadata: any) => voidCalled with the
decoded response metadata when the responder answers with a
metadata-carrying Resource (§10.4 x flag). Invoked before the
returned Promise resolves, so callers observe it as soon as the
response is available.
OptionalonProgress?: (Transfer progress for Resource-backed request/response bodies
direction tells whether the bytes flow away from (request
upload) or towards (response download) the caller. loaded /
total are approximate logical byte counts for the current
segment; segmentIndex / segmentTotal let callers aggregate
split transfers.Optionaltimeout?: numberResponse timeout in ms (defaults to
rtt * TRAFFIC_TIMEOUT_FACTOR + RESPONSE_MAX_GRACE_TIME_SECS * 1.125).
The decoded RESPONSE value.
Cleanly tears down the link by sending a LINKCLOSE whose encrypted body is the link_id, then transitioning to CLOSED locally.
Resolves once the Link reaches ACTIVE status (immediately if it already
is). Callers that obtain a Link reference before the handshake finishes —
e.g. right after Destination.createLink() resolves — should await
this before sending application data, since the session token is only
derived once the handshake completes.
Mirrors the gating the LXMF router applies in its outbound processing before sending DIRECT messages.
OptionaltimeoutMs: number
How long to wait for the handshake. Defaults to the bitrate-adaptive establishment timeout (import("./transport.js").TransportCore.establishmentTimeout); falls back to 15 s when no transport/destination is available.
StaticacceptResponder side: accept an incoming LINKREQUEST and complete the handshake up to LRPROOF.
Derives the link_id, extracts the initiator's ephemeral keys, derives the session keys, builds and sends the LRPROOF signed with the destination's long-term identity key, registers the link with the transport, and transitions to HANDSHAKE. The link becomes ACTIVE once the initiator's LRRTT arrives.
IN destination whose identity is this node's.
The incoming LINKREQUEST (with raw populated).
OptionalreceivingInterface: Interface | null = null
The interface the LINKREQUEST arrived on. Captured as the link's return
path (Link.attachedInterface), so responder→initiator traffic
flows back over it regardless of the node's default interface. Matches
the reference's link.attached_interface = packet.receiving_interface.
StaticinitiateInitiator side: establish a new link to destination.
Generates fresh ephemeral X25519 + Ed25519 keypairs, builds and sends the LINKREQUEST (dest_type=SINGLE, addressed to the responder's destination hash), derives the link_id from the serialized packet, registers the link with the transport, and transitions to HANDSHAKE. The link becomes ACTIVE once the responder's LRPROOF is validated.
OUT destination whose identity is the responder's.
StaticsignallingPacks the 3-byte MTU/mode signalling trailer.
An ephemeral encrypted channel between two destinations.
A Link is established through a LINKREQUEST/LRPROOF handshake which derives shared session keys; once ACTIVE, application packets are Token-encrypted over the link. Provides inbound sequencing, keepalive/watchdog handling, link identification, and resource advertisement transport.
Construct via Link.initiate or Link.accept; do not call the constructor directly.