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.