Repository navigation
Conversation
This was referenced Oct 30, 2026
feat(swarm): share records with other readers of a file, in every client
WithAutonomi/ant-client#244
Draft
grumbach
marked this pull request as ready for review
November 2, 2026 19:27
Clients reading the same file can share its records with each other over WebRTC data channels, with nodes introducing them and staying the last seed. This adds the wire types for that introduction. - `swarm` module: `RoomKey`, `MemberId`, `OfferId`, `NodeId` and `Membership`, and the announce, answer and leave requests with their replies. An announce joins or refreshes a room, hands the node offers for other members and collects the signals waiting for this member, optionally waiting for one. - Every request names the rendezvous node it is for, so a request one node saw cannot be replayed at another. - A membership number in announce and leave lets a node keep each connection's newest membership of a room: a newer one replaces the old, an ended or older one is refused (`SwarmRefusal::Superseded`), and a leave ends only the membership it names. A node browsers cannot reach refuses with `SwarmRefusal::NotHosting`, which a client takes as "pass this node over now". - Shared limits both sides enforce: offers per announce, SDP size, inbox size, reply size, wait time, ICE servers, offers counted as delivered, the request size a node refuses before decoding, and the length of a reply's error. The `validate` methods of the requests and of all three replies check them; the offers, inbox and STUN server lists are refused while decoding once past their limit, so nothing longer is ever built. - `SWARM_SIGNAL_TTL_MS` (70 s): how long a node keeps a delivered offer for its answer and a signal for its member, which a client checks its own answering time against. - `constrain_swarm_sdp`: the ICE candidates an SDP from another client may keep (UDP, an IP that is not unspecified, multicast or broadcast, or an mDNS name, at most 16), with a caller's rule on top. A node relaying an SDP and a client applying one both use it, so readers' connectivity checks cannot be pointed at a third party. Receivers read SDP leniently (webrtc-rs trims an attribute's value, Chrome takes a name followed by a space, Firefox names attributes in any case, webrtc-ice splits fields on any Unicode whitespace), so a line any of them may read as a candidate or a DTLS fingerprint stays only in its standard form (printable ASCII words separated by single spaces; a candidate's component 1 to 256 and its priority a 32-bit number, so no ICE agent's ranking of it overflows), and a line with a carriage return anywhere but before its line feed goes: what a receiver reads is exactly what was checked, and a link's binding covers every fingerprint a receiver uses. The result holds no more memory than its length needs. `is_global_ip` and `canonical_ip` help both apply their rules. - Six `ChunkMessageBody` variants appended as discriminants 14 to 19, so existing messages keep their encoding. Tests pin every new tag.
`ChunkMessage::decode` took the message postcard decodes from the front of the input and ignored whatever followed. A sender could therefore pad a small message, such as a valid reply, out to the 5 MiB wire limit and still have it taken, so a receiver's bound on a reply was really the wire limit. Decoding now refuses any bytes after the message's end, as `DeserializationFailed`. Every sender encodes a message exactly, so nothing well formed changes; `test_decode_rejects_bytes_after_the_message` pins it.
The `RoomKey` doc said a public file's room is its address. A client derives the room from the file's root DataMap, once a shrunk map is resolved to its root, as ADR-0026 says: a public file published with a shrunk map has a room other than its address, and a client that followed the doc would wait in a room no other reader joins. The doc now says so.
grumbach
marked this pull request as draft
November 5, 2026 04:11
grumbach
force-pushed
the
feat/peer-swarm
branch
from
November 5, 2026 04:12
5c5a1f1 to
ffbed67
Compare
grumbach
added a commit
to grumbach/ant-node
that referenced
this pull request
Nov 5, 2026
Patch ant-protocol, saorsa-core and saorsa-transport to their feat/peer-swarm branches, which this change needs: the swarm messages (WithAutonomi/ant-protocol#50), the send on one named channel (WithAutonomi/saorsa-core#183) and the plain STUN answers (WithAutonomi/saorsa-transport#231). Once those merge, these point at their main branches, or at the released versions at the release train.
grumbach
added a commit
to grumbach/ant-client
that referenced
this pull request
Nov 5, 2026
Patch ant-protocol, saorsa-core, saorsa-transport and ant-node to their feat/peer-swarm branches, which this change needs: the swarm messages (WithAutonomi/ant-protocol#50), the send on one named channel (WithAutonomi/saorsa-core#183), the plain STUN answers (WithAutonomi/saorsa-transport#231) and the rendezvous on every node (WithAutonomi/ant-node#262). Once those merge, these point at their main branches, or at the released versions at the release train. Cargo.lock starts from main's lock and differs from it only where those branches need it: the swarm's WebRTC and STUN crates, saorsa-transport's main dropping its CLI (and its clap and reqwest dependencies), and ant-node's main adding winapi-util on Windows. iana-time-zone keeps the windows-core 0.62.2 main's lock has.
grumbach
added a commit
to grumbach/ant-node
that referenced
this pull request
Nov 5, 2026
Patch ant-protocol, saorsa-core and saorsa-transport to their feat/peer-swarm branches, which this change needs: the swarm messages (WithAutonomi/ant-protocol#50), the send on one named channel (WithAutonomi/saorsa-core#183) and the plain STUN answers (WithAutonomi/saorsa-transport#231). Once those merge, these point at their main branches, or at the released versions at the release train.
grumbach
added a commit
to grumbach/ant-client
that referenced
this pull request
Nov 5, 2026
Patch ant-protocol, saorsa-core, saorsa-transport and ant-node to their feat/peer-swarm branches, which this change needs: the swarm messages (WithAutonomi/ant-protocol#50), the send on one named channel (WithAutonomi/saorsa-core#183), the plain STUN answers (WithAutonomi/saorsa-transport#231) and the rendezvous on every node (WithAutonomi/ant-node#262). Once those merge, these point at their main branches, or at the released versions at the release train. Cargo.lock starts from main's lock and differs from it only where those branches need it: the swarm's WebRTC and STUN crates, saorsa-transport's main dropping its CLI (and its clap and reqwest dependencies), and ant-node's main adding winapi-util on Windows. iana-time-zone keeps the windows-core 0.62.2 main's lock has.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wire types for clients that read the same file sharing its records over WebRTC, with nodes introducing them and staying the last seed (ADR-0026): the announce, answer and leave messages of a file's swarm room, their shared limits, and the SDP rule both a relaying node and an applying client use so a stranger cannot point readers' connectivity checks anywhere. A second commit makes
ChunkMessage::decoderefuse bytes after a message. The branch is rebased onto main as three commits, the swarm messages following its get-or-closer request (ant-node ADR-0020).One change across six repositories. Merge order:
This PR depends on: none.
Linear issue
Closes V2-1892
Risk tier
Proposed; a human confirms at review.
Compatibility
ChunkMessageBodyvariants appended (tags 16 to 21, after main's get-or-closer pair); released nodes (v0.23.1) cannot decode them, log a warning and leave them unanswered (no panic or ERROR line in the rollout lab), and clients pass those nodes over.ChunkMessage::decoderefuses bytes after a message, which no sender writes.swarmmodule, limits andconstrain_swarm_sdp;ChunkMessageBodyis#[non_exhaustive].Semver impact
Test evidence
cargo test --lib: 130 passed atffbed67, rebased onto main5dc5537(ADR-0020's get-or-closer request) as three commits with the same code as the reviewed5c5a1f1.cargo fmt --check,cargo clippy --all-targets --all-features -- -D warnings,cargo clippy -- -D warningsandRUSTDOCFLAGS="-D warnings" cargo doc --no-deps: clean (Rust 1.99).constrain_swarm_sdp: only the standard form of a candidate or fingerprint line stays (other spellings, Unicode whitespace, stray carriage returns, out-of-range components and priorities go), a mostly dropped SDP holds only what it keeps, and the address classification, which is stricter than the IANA special-purpose registries: all of192.0.0.0/24and2001::/23, and IPv6 outside2000::/3, count as not public. The SDP tests fail with each fix reverted.d39c393f1307 lib tests; ant-core2f925d0989 lib tests,e2e_swarmand 261 WASM tests, all passing.ffbed67: every build, test and lint job passes; Security Audit fails. It fails only on RUSTSEC-2026-0387 (crypto-bigint0.5.5, throughelliptic-curve0.13), whichcargo auditreports on this repository's main lockfile too, with the same dependents; its fixes wait on alloy and webrtc-rs releases.linear-linkandpr-template, which check this description, pass.New dependency
none
ADR
https://github.com/grumbach/ant-node/blob/feat/peer-swarm/docs/adr/ADR-0026-clients-share-records-nodes-introduce-them.md (new in the ant-node PR, status Proposed)
Mitigation / rollback
Revert: nothing sends the new messages until the node and client PRs land.