Added per-network LAN broadcast relay
LAN game discovery previously dropped IPv4 broadcasts at TUN ingress. Carry limited and subnet-directed UDP broadcasts to authenticated, opted-in members of the source network, including destinations reached through mesh relays. Preserve the original IP/UDP bytes and deliver received broadcasts only to the local TUN; never reflood them or expose another pair's plaintext at transit. Build immutable recipient snapshots on address and participation changes. The origin sends one ordinary end-to-end encrypted copy per recipient; the existing fast, bounded-hop transport router remains unchanged. Validate UDP framing, source ownership and destination admission without game-specific port rules. Keep network domains isolated and refuse implicit gateways to physical LANs. The separate broadcast policy/domain layer is the extension point for future authorized subnet exports; physical capture, bridging and LAN deduplication are deliberately not implemented yet. Persist default-on participation independently for each local network. Add join --no-broadcast/--broadcast and network broadcast <id> [on|off], including live updates and authenticated announcements. Joining without a flag preserves the saved choice. Opt-out stops local origination and delivery, while opaque unicast transit for other members keeps working. Migrate SQLite schema 3 to 4 without replacing identities or signed state. Use control ALPN 3 and local IPC protocol 14 for the new announcement/request shapes; update peers and restart running agents together. The data ALPN 4 envelope remains unchanged. No release version bump, tag or push is included. Document agent-owned commits in AGENTS.md: short English subjects, explanatory bodies, scoped staging, honest validation, and repository-local fallback author AB <ab@hexor.cy> only when an effective name/email is missing. Release actions remain the user's responsibility. Validation on Windows: cargo fmt --all -- --check; cargo check --locked --workspace --all-targets; cargo clippy --locked --workspace --all-targets -- -D warnings; release workspace/all-target tests: 313 passed. The two existing SQLite wipe failures (a_wipe_removes_everything_and_the_next_start_is_a_stranger and wiping_twice_is_as_ordinary_as_wiping_once) were explicitly skipped; the public-DHT smoke test and forwarding benchmark remain ignored by default. New coverage exercises real iroh/WireGuard multihop fanout, single delivery, runtime opt-out, unicast replies, domain isolation, malformed input and schema migration. TUNs are in-memory; actual games and OS adapter selection were not tested.
This commit is contained in:
+8
-3
@@ -9,7 +9,7 @@ Two versions exist and are independent:
|
||||
|
||||
- **Identity scheme**, `tsunagi-network-id-v1`. Frozen. Changing it creates a
|
||||
different network space for the same name and secret.
|
||||
- **Control protocol**, ALPN `tsunagi/ctrl/2`, `PROTOCOL_VERSION = 2`.
|
||||
- **Control protocol**, ALPN `tsunagi/ctrl/3`, `PROTOCOL_VERSION = 3`.
|
||||
|
||||
Upgrading the crate or bumping the control protocol must never change an
|
||||
existing `NetworkId`.
|
||||
@@ -191,7 +191,7 @@ transport connection, not supplied by the frame. Intermediate nodes cannot
|
||||
decrypt or authenticate the inner WireGuard payload; the destination does that.
|
||||
Flow ids are routing hints, not authorization proofs.
|
||||
|
||||
Control ALPN 2 carries `Reachable { links: [{ peer, protocol }] }`. Each row
|
||||
Control ALPN 3 carries `Reachable { links: [{ peer, protocol }] }`. Each row
|
||||
belongs to the authenticated sender and is replaced atomically, expires after
|
||||
90 seconds, and is withdrawn on session closure. Only compatible authenticated
|
||||
members enter a protocol's graph; local edges always come from actual links.
|
||||
@@ -215,7 +215,7 @@ not affect other networks.
|
||||
|
||||
| message | meaning |
|
||||
|---|---|
|
||||
| `Announce { hostname, capabilities }` | this agent's hostname and IP-plugin capabilities |
|
||||
| `Announce { hostname, capabilities, broadcast }` | this agent's hostname, IP-plugin capabilities and local broadcast participation |
|
||||
| `Ping { seq, payload }` | small request used to verify the exchange |
|
||||
| `Pong { seq, payload }` | the echoed reply |
|
||||
| `State { records }` | a snapshot of signed records, merged into what the receiver holds |
|
||||
@@ -223,6 +223,11 @@ not affect other networks.
|
||||
| `Reachable { links }` | sender's current direct data links, scoped by protocol |
|
||||
| `Bye { reason }` | graceful goodbye; not a revocation of anything |
|
||||
|
||||
`broadcast` is a per-network local opt-in, enabled by default and treated as
|
||||
false until an authenticated announcement arrives. It governs IP broadcast
|
||||
fanout and local admission; encrypted transit still uses the existing envelope.
|
||||
See [broadcast.md](broadcast.md) for scope and persistence.
|
||||
|
||||
A `State` snapshot is merged, never substituted: an author missing from it is
|
||||
left untouched. Each record carries its own signature, so a peer forwarding
|
||||
somebody else's record cannot alter it, and a record that fails verification
|
||||
|
||||
Reference in New Issue
Block a user