Repository navigation
v0.24.0+ciris.1 — transfers of any size arrive as one delivery
A transfer of any size is one delivery (leviculum#62)
A payload past RESOURCE_MAX_EFFICIENT_SIZE (1 MiB − 1) is split into segments, and core delivers one ResourceCompleted per segment carrying that slice. That is right for leviculum-core — no_std, running on boards that cannot hold a multi-megabyte transfer in RAM — and wrong for a consumer: the reference fires its resource callback once per transfer, so code written to reference semantics decoded our first event as the whole message and got a body cut at the ceiling minus the metadata size.
leviculum-std now reassembles. Intermediate segments are absorbed; the final segment becomes one ResourceCompleted carrying the whole payload and segment 1's metadata. Measured end to end: a 2,109,497-byte payload that previously arrived as (1,3,1048575) (2,3,1048575) (3,3,12347) now arrives as (3,3,2109497).
- No new wire or event field. A link carries at most one incoming resource at a time, so
LinkIdis an exact correlation key. - Free when unused. Single-segment transfers and every sender-side event pass through untouched; a batch with nothing segmented does no extra work.
- Bounded, because the segment count is peer-supplied — per transfer (default 64 MiB,
ReticulumNodeBuilder::max_assembled_resource_size) and in aggregate across links at four times that. A transfer past the ceilings is neither dropped nor truncated: it degrades to per-segment delivery with an error naming the ceiling and the knob. A link that dies mid-transfer releases its partial. - Assembly runs before observation and emission, so the completion registry, the event tap and the consumer all see the same whole-transfer event.
The efficient-size ceiling was reported as a typo; the comment was (leviculum#61)
RESOURCE_MAX_EFFICIENT_SIZE = 1_048_575 is correct and must not change: reference RNS is 1 * 1024 * 1024 - 1 (Resource.py:116). Raising it to 16 MiB as reported would emit segments a reference receiver cannot accept — trading a consumer-side bug for a wire-compatibility break. What was wrong is the comment beside it, claiming a "3-byte length encoding (0xFFFFFF)", which made a correct value look like an off-by-one-hex-digit typo. It is now an expression with the reference cited, and NodeEvent::ResourceCompleted documents the per-segment contract where a consumer actually reads it.
Catch-up to upstream master @ 50388fc6 (+57)
The largest catch-up since the 0.8.1 line, almost all LNode firmware and radio work: boosted receiver gain rather than an unchosen default, a reception no longer abandoned for a transmission, the radio listening again before handing a packet upward, a settable inter-packet gap, register read-back at bring-up, airtime and listen-window reporting, and a plain reader for the LNode debug port. leviculum-std movement is mostly rnsd-interop coverage. Nothing touched the fork's carry.
Also fixed: a latent race in this fork's own conformance suite, which read the responder's live-link gauge immediately after the initiator's await returned. The two sides establish at different moments by design, so it was a race the test happened to keep winning until upstream timing shifted.
Gate: core 1,743 / std 605 / multi-segment 2/2 / destination-lifecycle 4/4 / scoped-transit 6/6 / request-response 3/3; clippy -D warnings; fmt; thumbv6m; full CI green.