markdown formatting
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user