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

4.3 KiB

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 :

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