anydrop/docs/architecture.md
ordinarthur 9d6e4da4ae
Some checks failed
Build & Deploy / build-and-deploy (push) Failing after 8s
feat: initial commit with full deployment setup
Includes React PWA frontend, WebSocket signaling server, shared types,
K8s manifests, Gitea CI/CD workflow, nginx config, and Dockerfiles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 10:30:45 +02:00

88 lines
4.3 KiB
Markdown

# Architecture AnyDrop
## Vue d'ensemble
AnyDrop repose sur trois briques :
1. **Client** (web, extension, desktop, mobile) — interface utilisateur + moteur WebRTC
2. **Serveur de signaling** — met en relation les pairs, ne voit jamais les fichiers
3. **Serveurs STUN/TURN** — aident à établir la connexion P2P à travers les NAT/firewalls
```
┌──────────┐ WebSocket ┌────────────────┐ WebSocket ┌──────────┐
│ Client A │ ────────────────────▶ │ Signaling │ ◀──────────────────── │ Client B │
└──────────┘ │ Server │ └──────────┘
│ └────────────────┘ │
│ │
│ ═══════ WebRTC DataChannel (P2P chiffré DTLS) ═══════ │
└─────────────────────────────────────────────────────────────────────────────┘
(les fichiers transitent uniquement ici)
```
## Le serveur de signaling
### Responsabilités
- Accepter les connexions WebSocket entrantes
- Attribuer un `peerId` unique et un `displayName` (nom animal aléatoire) à chaque client
- Placer le client dans la ou les rooms appropriées :
- Room **LAN** : hash de l'IP publique de la connexion
- Room **publique** : code court fourni dans l'URL (ex: `/x7k`)
- Relayer les messages de signaling (`offer`, `answer`, `ice-candidate`) entre pairs d'une même room
- Notifier `peer-joined` / `peer-left`
- Expirer les rooms publiques inactives (10 min)
### Ce que le serveur ne fait PAS
- ❌ Ne stocke aucun fichier ni contenu échangé
- ❌ Ne log pas les IPs dans des fichiers persistants
- ❌ N'a pas de base de données
- ❌ N'a pas d'authentification
## Les clients
Tous les clients (web, extensions, desktop, mobile) implémentent le **même protocole de signaling** et la même logique WebRTC. Le code `shared/` exporte les types de messages communs pour garantir la cohérence.
### Couche abstraction P2P
On utilise `simple-peer` pour masquer la complexité de l'API WebRTC native :
```ts
const peer = new SimplePeer({ initiator: true, trickle: true });
peer.on('signal', data => sendViaWebSocket(data)); // envoyer offer/ICE
peer.on('connect', () => sendFile(file)); // connexion établie
peer.on('data', chunk => reassemble(chunk)); // chunks reçus
```
### Découpage des fichiers
- Chunk size : **16 Ko** (compromis débit/mémoire)
- Header JSON initial : `{ name, size, mime, id }`
- Puis envoi séquentiel avec backpressure (`peer._channel.bufferedAmount < 1MB`)
- Fin de fichier : chunk spécial `{ eof: true, id }`
- Récepteur : accumule dans un `Blob[]` puis `new Blob(chunks, { type })`
## STUN et TURN
### STUN (Session Traversal Utilities for NAT)
Gratuit, quasi-gratuit en bande passante (quelques paquets). Sert uniquement à ce que le client découvre sa propre IP publique + port NAT, pour l'inclure dans les ICE candidates.
Serveurs utilisés : `stun.l.google.com:19302`, `stun1.l.google.com:19302`.
### TURN (Traversal Using Relays around NAT)
Fallback quand le P2P direct échoue (~10-20% des cas, surtout en entreprise / 4G). Le trafic est alors **relayé** par le serveur TURN → coût bande passante réel.
- V1 : Open Relay (gratuit, 500 Go/mois) — suffisant pour un lancement
- Plus tard : coturn auto-hébergé sur un VPS
## Déploiement cible
| Composant | Hébergement | URL |
|----------------|----------------------|-----------------------------------|
| Front web (PWA)| Vercel / Netlify | `anydrop.arthurbarre.fr` |
| Signaling | Railway / Fly.io | `ws.anydrop.arthurbarre.fr` |
| STUN | Google (gratuit) | `stun.l.google.com:19302` |
| TURN | Open Relay → coturn | `turn.anydrop.arthurbarre.fr` |