# Arquitectura del servidor ## Estructura de carpetas ``` server/ room/ Dominio de salas P2P friends/ Dominio de amigos y MD calls/ Dominio de llamadas de voz/vídeo profile/ Dominio del perfil de usuario local identity/ Dominio de identidad criptográfica messages/ Dominio de mensajes de chat ``` Cada carpeta de dominio sigue el mismo patrón: | Archivo | Función | |---|---| | `store.ts` | Lee y escribe datos en disco | | `utils.ts` | Funciones de utilidad puras | | `handler.ts` | Manejadores de mensajes WebSocket | | `events.ts` | Manejadores de eventos P2P | | `watcher.ts` | Suscripciones P2P en vivo (solo salas) | | `tracker.ts` | Estado de ejecución en memoria (solo llamadas) | ## Responsabilidades de los dominios ### `room/` Todo lo relacionado con las salas P2P: persistir las salas a las que te has unido, observar actualizaciones en vivo, consultar el historial de la sala para conocer el estado de propiedad y moderación, y atender todos los mensajes WebSocket relacionados con salas (crear, unirse, salir, operaciones de administración). ### `friends/` El sistema de amigos: persistir la lista de amigos, utilidades puras de búsqueda, atender los mensajes WebSocket de solicitud/aceptación/eliminación de amistad, y atender los eventos P2P de amistad entrantes (unirse a salas de MD al aceptar). ### `calls/` Llamadas de voz/vídeo: seguir qué llamadas están activas en memoria y retransmitir los mensajes WebSocket de señalización de llamadas (iniciar, unirse, relevar señal, finalizar) a través del registro de la sala. PeerJS se ejecuta en el navegador; el servidor solo reenvía las cargas opacas `call-signal`, por lo que no necesita un broker PeerServer. ### `profile/` Los datos visibles del usuario local: persistir nombre, avatar y estado de presencia en disco, funciones de utilidad para normalizar la presencia y generar nombres de usuario anónimos, y atender los mensajes WebSocket de actualización de perfil. ### `identity/` Operaciones de identidad criptográfica: atender los mensajes WebSocket para la copia de seguridad de la frase semilla, la importación de la frase semilla y el reinicio de la base de datos local. La lógica central de identidad vive en `lib/identity.ts`. ### `messages/` Operaciones de mensajes de chat: atender todos los mensajes WebSocket relacionados con mensajes (enviar, editar, reaccionar, fijar, subir/descargar archivos, gestión de canales, emojis personalizados). ## Archivos a nivel de servidor | Archivo | Función | |---|---| | `server.ts` | Punto de entrada | | `ws-dispatch.ts` | Enruta los mensajes WebSocket entrantes al manejador correcto | | `context.ts` | Tipos compartidos: `SessionContext` y `PipelineContext` | | `broadcast.ts` | Envía mensajes a todos los clientes WebSocket conectados | | `http-handler.ts` | Sirve los archivos estáticos del cliente y atiende el endpoint de reinicio | | `quibble-init.ts` | Inicializa el nodo P2P con lógica de reintento para el bloqueo de almacenamiento | | `rtc.ts` | Resuelve la lista de servidores ICE enviada a los clientes (delega en `lib/rtc-config.ts`) | | `net.ts` | Busca un puerto TCP libre al arrancar | ## Servidores ICE Al conectarse, el servidor envía a cada cliente un mensaje `rtc-config` con la lista de servidores ICE. Los valores por defecto vienen de `lib/rtc-config.ts` (STUN de Cloudflare + TURN compartido de Metered). Se pueden sobrescribir con variables de entorno: - `QUIBBLE_ICE_SERVERS_JSON`: un array JSON completo de `{ urls, username?, credential? }`, usado tal cual. - `TURN_URL`, `TURN_USERNAME`, `TURN_CREDENTIAL`: apunta a todos los clientes a tu propio servidor TURN. Los usuarios también pueden configurar su propio servidor STUN/TURN en Ajustes, lo que sobrescribe localmente los valores por defecto del servidor. Consulta [stun-turn.md](stun-turn.md).