markdown formatting

This commit is contained in:
2026-08-09 16:16:45 +02:00
parent f4a6259cf3
commit 18dd3b7e07
21 changed files with 1630 additions and 893 deletions
+35 -34
View File
@@ -1,8 +1,8 @@
# lanspread-peer proposed protocol and architecture
This document proposes a tighter, more fault-tolerant protocol while keeping
the current idea: mDNS discovery, QUIC transport, on-demand metadata, and
chunked file transfers.
This document proposes a tighter, more fault-tolerant protocol while keeping the
current idea: mDNS discovery, QUIC transport, on-demand metadata, and chunked
file transfers.
## Goals (unchanged)
@@ -26,14 +26,15 @@ chunked file transfers.
When a peer is discovered:
1. Connect and send `Hello { peer_id, proto_ver, listen_addr, library_rev,
library_digest, features }`. `listen_addr` is mandatory; the QUIC source port
is only a temporary transport port and must not be recorded as the peer's
listener.
2. Receive `HelloAck { peer_id, proto_ver, listen_addr, library_rev,
library_digest, features }`.
1. Connect and send
`Hello { peer_id, proto_ver, listen_addr, library_rev, library_digest, features }`.
`listen_addr` is mandatory; the QUIC source port is only a temporary
transport port and must not be recorded as the peer's listener.
2. Receive
`HelloAck { peer_id, proto_ver, listen_addr, library_rev, library_digest, features }`.
3. If the remote `peer_id` is already known but the address changed, update it.
4. If protocol versions are incompatible, drop the peer (and keep mDNS watching).
4. If protocol versions are incompatible, drop the peer (and keep mDNS
watching).
5. If library digests match, do nothing else.
6. If digests differ:
- If we have a known `library_rev` for that peer, request `LibraryDelta`.
@@ -50,16 +51,16 @@ When a peer is discovered:
Call to Play is transient peer-session state rather than database state. The
peer keeps a bounded event history, deduplicated by event ID. Every event and
chat message remains in the snapshot for the full lifetime of an active call,
so a peer joining mid-call receives the complete context. A creator's `Start`
or `Cancel` makes the call terminal and read-only, but its complete roster and
chat history remain in snapshots for 15 minutes so late joiners can see the
outcome. After that display window the history compacts to the Start or Cancel
tombstone for the rest of the peer session. Active and recently terminal calls
are never partially trimmed. If genuinely active history reaches the bound,
local publishes return an error to the caller instead of appearing to succeed;
terminal histories and tombstones do not consume that active-history capacity.
A call whose deadline elapses remains available for five minutes so the creator
chat message remains in the snapshot for the full lifetime of an active call, so
a peer joining mid-call receives the complete context. A creator's `Start` or
`Cancel` makes the call terminal and read-only, but its complete roster and chat
history remain in snapshots for 15 minutes so late joiners can see the outcome.
After that display window the history compacts to the Start or Cancel tombstone
for the rest of the peer session. Active and recently terminal calls are never
partially trimmed. If genuinely active history reaches the bound, local
publishes return an error to the caller instead of appearing to succeed;
terminal histories and tombstones do not consume that active-history capacity. A
call whose deadline elapses remains available for five minutes so the creator
can start or extend it, then its unresolved history is evicted as a unit. A
local action is applied to that history, sent to the UI, and broadcast to every
currently known peer. An incoming live event is applied once and sent to the UI
@@ -89,8 +90,8 @@ deterministically and derives deadlines and check-in phases from timestamps.
Those phases compare creator-supplied wall-clock timestamps with each viewer's
local wall clock, so LAN machines are assumed to be synchronized closely enough
for human-scale minute countdowns; clock skew shifts the displayed boundary by
the same amount.
There is deliberately no compatibility path for older protocol versions.
the same amount. There is deliberately no compatibility path for older protocol
versions.
### 4) Shutdown
@@ -137,8 +138,8 @@ There is deliberately no compatibility path for older protocol versions.
1. Maintain a persistent on-disk index (per game):
- `manifest_hash`, total size, file list (optional), and a fingerprint
(root-level `version.ini` mtime, root-level `.eti` mtime/size, and
`local/` directory presence).
(root-level `version.ini` mtime, root-level `.eti` mtime/size, and `local/`
directory presence).
2. Use filesystem watchers to update only changed games.
3. Keep a 300-second fallback scan to recover from missed events.
@@ -164,8 +165,8 @@ Downloaded and installed are independent predicates:
`local/` are user-owned and are skipped by manifests, fingerprints, and file
serving.
- Install and update transactions unpack into staging, then overwrite the first
discovered game-provided `account_name.txt` and `language.txt` files under
the staged tree from launcher settings before promoting it to `local/`.
discovered game-provided `account_name.txt` and `language.txt` files under the
staged tree from launcher settings before promoting it to `local/`.
Reserved per-game paths:
@@ -239,8 +240,8 @@ Most scans become O(number of game dirs), with full recursion only when needed.
1. Protocol updates in `lanspread-proto`:
- Define `Hello`, `HelloAck`, `LibrarySummary`, `LibrarySnapshot`,
`LibraryDelta`, and optional `Goodbye` messages.
- Thread `peer_id`, `library_rev`, and `manifest_hash` through all
library and manifest-bearing types.
- Thread `peer_id`, `library_rev`, and `manifest_hash` through all library
and manifest-bearing types.
- Make `Hello` and `HelloAck` carry the sender's `listen_addr`,
`library_rev`, and `library_digest` so both sides can record stable
listener addresses and immediately select `LibraryDelta` vs
@@ -248,11 +249,11 @@ Most scans become O(number of game dirs), with full recursion only when needed.
2. Peer identity:
- Persist a stable `peer_id` (UUID) in the peer config and inject it into
`PeerInfo` and `PeerGameDB` at startup.
- Track `peer_id -> SocketAddr` in the discovery table and update the
address on any incoming handshake or mDNS refresh.
- Track `peer_id -> SocketAddr` in the discovery table and update the address
on any incoming handshake or mDNS refresh.
3. Discovery handshake:
- Publish `peer_id` and `library_rev` in mDNS TXT records to avoid
immediate TCP/QUIC roundtrips when nothing changed.
- Publish `peer_id` and `library_rev` in mDNS TXT records to avoid immediate
TCP/QUIC roundtrips when nothing changed.
- Add a lightweight handshake in `run_peer_discovery` that exchanges
`Hello`/`HelloAck` before any library sync.
- Ignore peers that do not advertise the current protocol version.
@@ -261,8 +262,8 @@ Most scans become O(number of game dirs), with full recursion only when needed.
successful index refresh completes.
- Apply `LibraryDelta` when `library_rev` matches; reject stale or future
revisions and request `LibrarySnapshot` instead.
- Cache the last accepted `manifest_hash` per peer to short-circuit
manifest requests when unchanged.
- Cache the last accepted `manifest_hash` per peer to short-circuit manifest
requests when unchanged.
5. Local index + scan optimizations:
- Use the cached `local_library/index.json` file in the configured state
directory to store per-root fingerprints and computed manifests.