Backend daemon for Xynq.
The daemon manages peer discovery, secure networking, and communication between devices. Native applications communicate with the daemon over IPC, while daemons communicate over QUIC.
| Channel | Format |
|---|---|
| Native App ↔ Daemon | Protocol Buffers |
| Daemon ↔ Daemon | Postcard (Serde binary format) |
Protocol definitions are available in xynq-proto.
Status
- ✅ IPC service
- ✅ QUIC networking
- ✅ LAN discovery
- ✅ Relay discovery
- ✅ Mutual authentication
- 🚧 Native applications
Native Application
│
IPC (Protobuf)
│
┌──────────────┐
│ Xynq Daemon │
├──────────────┤
│ IPC Service │
│ Network Svc │
└──────┬───────┘
│
┌────────────┴────────────┐
│ │
LAN Transport Relay Transport
┌──────────┐ ┌──────────┐
│ mDNS │ │ Relay │
│ QUIC │ │ QUIC │
└────┬─────┘ └────┬─────┘
│ │
└──────────┬─────────────┘
│
Remote Daemon
The daemon consists of two services:
- IPC Service — Receives commands and streams events to native applications.
- Network Service — Discovers peers, establishes QUIC sessions, authenticates devices, and transports daemon messages.
Each synchronization group is called a cluster.
A cluster consists of:
- Cluster ID (UUID v4)
- Device ID (UUID v7)
- Shared cluster secret
These values are generated by the native application and provisioned to the daemon through IPC.
A new device joins using:
- QR code
- Human-readable pairing code
Xynq supports both LAN and Relay discovery.
LAN discovery uses mDNS.
Every daemon continuously advertises its presence.
When another daemon is discovered:
- Cluster IDs must match.
- Device IDs must differ.
The daemon with the smaller UUID v7 initiates the QUIC connection. The other daemon accepts it. This prevents duplicate simultaneous connections.
Each daemon establishes a persistent QUIC connection to the relay server.
The relay organizes connected daemons into cluster groups.
- If a cluster does not exist, the relay creates it.
- Otherwise, the daemon joins the existing cluster group.
Daemons in the same relay group can discover each other regardless of their network.
Authentication is completely mutual.
Once a QUIC connection is established, both peers simultaneously send:
- nonce
- timestamp
- HMAC-SHA256 signature
signature =
HMAC_SHA256(
shared_cluster_secret,
nonce || timestamp
)
Both peers verify:
- HMAC signature
- Timestamp validity
- Nonce freshness
The connection is accepted only if every check succeeds.
Since QUIC provides independent bidirectional streams, authentication happens concurrently without client/server roles.
All daemon-to-daemon communication uses QUIC bidirectional streams.
Payloads are serialized using Postcard.
Typical messages include:
- Authentication
- Peer metadata
- Cluster events
- Control messages
- Heartbeats
Each logical operation uses its own QUIC stream, allowing multiple concurrent operations over a single connection.
src/
├── ipc/
│ ├── command.rs # IPC request definitions
│ └── event.rs # IPC event definitions
│
├── network/
│ ├── lan/
│ │ ├── crypto.rs # QUIC TLS certificates & credentials
│ │ └── discovery.rs # mDNS discovery
│ │
│ ├── relay/
│ │ └── crypto.rs # QUIC TLS certificates & credentials
│ │
│ ├── session/
│ │ ├── message.rs # Daemon protocol messages
│ │ └── sign.rs # HMAC authentication
│ │
│ ├── lan.rs # LAN transport
│ ├── relay.rs # Relay transport
│ └── session.rs # QUIC session management
│
├── config.rs # Configuration
├── id.rs # Cluster & device identifiers
├── ipc.rs # IPC service
├── logging.rs # Logging initialization
├── network.rs # Network service
├── service.rs # Shared service abstractions
├── transport.rs # Common transport interface
└── main.rs # Entry point