# 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` |