Files
quicproquo/docs/src/getting-started/mesh-networking.md
Christian Nennemann 2e081ead8e chore: rename quicproquo → quicprochat in docs, Docker, CI, and packaging
Rename all project references from quicproquo/qpq to quicprochat/qpc
across documentation, Docker configuration, CI workflows, packaging
scripts, operational configs, and build tooling.

- Docker: crate paths, binary names, user/group, data dirs, env vars
- CI: workflow crate references, binary names, artifact names
- Docs: all markdown files under docs/, SDK READMEs, book.toml
- Packaging: OpenWrt Makefile, init script, UCI config (file renames)
- Scripts: justfile, dev-shell, screenshot, cross-compile, ai_team
- Operations: Prometheus config, alert rules, Grafana dashboard
- Config: .env.example (QPQ_* → QPC_*), CODEOWNERS paths
- Top-level: README, CONTRIBUTING, ROADMAP, CLAUDE.md
2026-03-21 19:14:06 +01:00

4.7 KiB

Mesh Networking

quicprochat includes a mesh networking layer for decentralised, peer-to-peer messaging without central infrastructure. It is designed for community networks (Freifunk, BATMAN-adv, Babel routing) and offline-capable environments.

Mesh features are feature-gated — build the client with:

cargo build -p quicprochat-client --features mesh

Architecture

Client A ── mDNS discovery ──► nearby qpc node (LAN / mesh)
                                      │
                             Cap'n Proto federation
                                      │
                             remote qpc node (across mesh)

Client B ── iroh P2P ──────► Client C (direct, NAT-traversed)

Three layers work together:

  1. Server federation — servers relay messages across mesh via Cap'n Proto RPC over QUIC with mTLS
  2. mDNS discovery — servers announce themselves, clients find nearby nodes
  3. iroh P2P — direct peer-to-peer QUIC connections with NAT traversal

Self-sovereign mesh identity

In mesh mode, identity is based on an Ed25519 keypair — independent of server registration. No OPAQUE password auth or Authentication Service is required.

/mesh identity

Shows your mesh public key and known peers. The keypair and peer directory are persisted in a local JSON file.

mDNS discovery

Servers announce _quicprochat._udp.local. via mDNS on startup with TXT records:

ver=1
server=<host:port>
domain=<local_domain>

Clients browse for nearby nodes:

/mesh peers

Note a discovered server for connection:

/mesh server 192.168.1.42:7000

Direct P2P messaging

Send messages directly to a peer via iroh transport (QUIC with NAT traversal):

/mesh send <peer_id> Hello from the mesh!

Messages are signed with your mesh identity key. The iroh relay server is used as fallback when direct connections fail.

Store-and-forward

Messages for offline peers are buffered with TTL-based expiry:

  • MeshEnvelope — signed message with TTL, hop count, and max hops
  • Deduplication — SHA-256 message ID prevents relay loops
  • MeshStore — in-memory queue with per-recipient capacity limits
  • Garbage collection — expired messages are automatically purged

Forward stored messages to a newly-discovered peer:

/mesh store       # show queue statistics

The routing table shows known paths:

/mesh route

Broadcast channels

Lightweight pub/sub channels using symmetric ChaCha20-Poly1305 encryption (no MLS overhead). Suitable for community bulletin boards, announcements, and emergency broadcasts.

/mesh subscribe announcements        # join a channel
/mesh broadcast announcements Hello! # publish to a channel

Channels are created automatically on first subscription. The symmetric key is derived from the topic name (for open channels) or distributed out-of-band (for private channels).

Federation

Servers relay messages for recipients on remote nodes:

  • handle_enqueue and handle_batch_enqueue call federation::routing::resolve_destination()
  • Remote recipients are forwarded via FederationClient::relay_enqueue()
  • mTLS mutual authentication between federation peers

Configuration

# Environment variables
QPC_FEDERATION_LISTEN=0.0.0.0:7001
QPC_LOCAL_DOMAIN=node1.mesh.local
QPC_FEDERATION_CERT=/path/to/cert.der
QPC_FEDERATION_KEY=/path/to/key.der
QPC_FEDERATION_CA=/path/to/ca.der

Or in qpc-server.toml:

federation_enabled = true
federation_domain = "node1.mesh.local"
federation_listen = "0.0.0.0:7001"

ALPN tokens

Protocol ALPN
Client ↔ Server b"capnp"
P2P transport b"quicprochat/p2p/1"
Federation b"quicprochat/federation/1"

REPL command summary

Command Description
/mesh peers Scan for nearby nodes via mDNS
/mesh server <host:port> Note a discovered server
/mesh send <peer_id> <msg> Direct P2P message
/mesh broadcast <topic> <msg> Publish to broadcast channel
/mesh subscribe <topic> Join a broadcast channel
/mesh route Show routing table
/mesh identity Show mesh identity info
/mesh store Show store-and-forward stats

Implementation

  • P2P node: crates/quicprochat-p2p/src/lib.rsP2pNode with iroh transport
  • Mesh identity: crates/quicprochat-p2p/src/identity.rs
  • Store-and-forward: crates/quicprochat-p2p/src/store.rs + envelope.rs
  • Broadcast: crates/quicprochat-p2p/src/broadcast.rs
  • mDNS discovery: crates/quicprochat-client/src/client/mesh_discovery.rs
  • Federation routing: crates/quicprochat-server/src/node_service/delivery.rs
  • REPL commands: mesh handlers in crates/quicprochat-client/src/client/repl.rs