P2P

node-datachannel

DataChannels WebRTC sin media — solo datos

Key Concept: DataChannels ≠ Media

En Arq. 6, node-datachannel no transporta audio ni vídeo. El audio va por Mumble y el vídeo por µStreamer MJPEG. node-datachannel se usa solo para datos: mensajes de texto (chat P2P), transferencia de archivos, y señalización entre peers SSB.
Tipo de datosTransporteComponente
VídeoHTTP MJPEG (µStreamer)µStreamer → Oasis proxy
AudioMumble protocol + HTTP OGG bridgemurmurd → bridge
Texto/chatWebRTC DataChannel (P2P)node-datachannel
ArchivosWebRTC DataChannel (P2P)node-datachannel
SeñalizaciónWebRTC DataChannel o SSB feednode-datachannel / SSB

Identidad del Componente

CampoValor
npmnode-datachannel
Repomurat-dogan/node-datachannel
Binding delibdatachannel (C/C++)
Autor libdatachannelPaul-Louis Ageneau
LicenciaMPL-2.0 (libdatachannel) + MIT (bindings)
Incluye media✘ No — solo DataChannels + signaling
RAM típica~5–10 MB (integrado en proceso Node.js de Oasis)
Installnpm install node-datachannel

Flujo de Señalización (SDP via SSB)

  PEER A (SNH)                                    PEER B (remote)
      │                                               │
      │  1. createPeerConnection()                     │
      │  2. createDataChannel('chat')                  │
      │  3. createOffer() → SDP offer                  │
      │                                               │
      │ ──── SDP offer via SSB msg ──────────────────▷│
      │                                               │
      │                     4. setRemoteDescription()  │
      │                     5. createAnswer() → SDP    │
      │                                               │
      │◁──── SDP answer via SSB msg ──────────────────│
      │                                               │
      │  6. setRemoteDescription()                     │
      │                                               │
      │ ◀═══ ICE candidates (trickle via SSB) ═══════▷│
      │                                               │
      │ ◀══════ DataChannel OPEN ═══════════════════▷ │
      │           texto · archivos · señalización      │
La señalización (SDP offer/answer + ICE candidates) viaja por SSB feed messages: cada peer publica su SDP como un mensaje SSB privado. No hace falta un signaling server WebSocket.

API Patterns — node-datachannel

Crear peer connection + datachannel
const nodeDataChannel = require('node-datachannel'); const peer = new nodeDataChannel.PeerConnection( 'PeerA', { iceServers: [] } // sin STUN: solo LAN ); const dc = peer.createDataChannel('chat'); dc.onOpen(() => { dc.sendMessage('hello from SNH'); }); dc.onMessage((msg) => { console.log('received:', msg); });
Generar SDP y publicar en SSB
peer.onLocalDescription((sdp, type) => { // Publicar en SSB como mensaje privado al peer ssbClient.publish({ type: 'webrtc-sdp', sdpType: type, // 'offer' | 'answer' sdp: sdp, recps: [peerBId] // privado }); }); peer.onLocalCandidate((candidate, mid) => { ssbClient.publish({ type: 'webrtc-ice', candidate, mid, recps: [peerBId] }); });
Recibir SDP del otro peer (listener SSB)
ssbClient.on('webrtc-sdp', (msg) => { if (msg.value.content.sdpType === 'offer') { peer.setRemoteDescription( msg.value.content.sdp, 'offer' ); } else { peer.setRemoteDescription( msg.value.content.sdp, 'answer' ); } }); ssbClient.on('webrtc-ice', (msg) => { peer.addRemoteCandidate( msg.value.content.candidate, msg.value.content.mid ); });

File Transfer via DataChannel

DataChannels soportan datos binarios. Para archivos grandes: chunk en bloques de ~16 KB (límite SCTP), enviar secuencialmente, reassemblar en destino.
// Enviar fichero en chunks const CHUNK = 16384; // 16 KB const buf = fs.readFileSync(filePath); dc.sendMessage(JSON.stringify({ type: 'file-meta', name: path.basename(filePath), size: buf.length })); for (let i = 0; i < buf.length; i += CHUNK) { dc.sendMessageBinary(buf.slice(i, i + CHUNK)); } dc.sendMessage(JSON.stringify({ type: 'file-end' }));
Alternativa: Los archivos pueden viajar como SSB blobs (inmutables, content-addressed). DataChannel para archivos pequeños/urgentes; SSB blobs para archivos que deben persistir en el log.

LAN vs Remoto — ICE Config

EscenarioiceServersFuncionaNota
LAN directa[] (vacío)mDNS / IP local directa
LAN con NAT simple[STUN público]Reflexive candidates
Internet (simétric NAT)[STUN + TURN]⚠️Necesita TURN relay
TorICE no funciona sobre Tor (UDP bloqueado)
DataChannels P2P no funcionan sobre Tor. Para datos entre peers en Tor: usar SSB replication (TCP, compatible Tor). DataChannels solo para LAN o con STUN/TURN en clearnet.
En Arq. 6 (solo LAN), iceServers: [] es suficiente. Los peers están en la misma red, se ven directamente por IP.

Formato de Mensajes — Convención

// Todos los mensajes DataChannel son JSON con campo 'type' { "type": "chat", "text": "hola", "ts": 1711612800 } { "type": "file-meta", "name": "foto.jpg", "size": 48230 } { "type": "file-end" } { "type": "ping" } { "type": "pong", "rtt": 12 } { "type": "status", "video": true, "audio": true }
DRY rule: siempre JSON con campo type. Permite extensibilidad futura sin romper parsers existentes. Los chunks binarios de file-transfer son la única excepción (raw ArrayBuffer).

Keywords

DataChannel SCTP SDP ICE libdatachannel SSB feed recps offer/answer trickle ICE 16 KB chunk P2P mDNS