import { WebSocket, WebSocketServer } from 'ws'; import { ulid } from 'ulid'; const wss = new WebSocketServer({ port: 8080 }); const rooms = new Map>(); const sockets = new Map(); wss.on('connection', (ws) => { let peerId = ulid(); const join = (room: string) => { if (!rooms.has(room)) { rooms.set(room, new Set([peerId])); } else { rooms.get(room)!.add(peerId); } }; const unjoinAll = () => { rooms.entries().forEach(([room, peers]) => { peers.delete(peerId); if (!peers.size) rooms.delete(room); }); }; ws.on('message', (message) => { try { const text = message.toString('utf8'); const data = JSON.parse(text); if (data.type === 'self') { ws.send(JSON.stringify({ type: 'self', id: peerId.toString(), })); return; } if (data.type === 'join' && typeof data.room === 'string') { unjoinAll(); join(data.room); const peers = rooms.get(data.room) ?? []; peers.forEach((peer) => { sockets.get(peer)!.send(JSON.stringify({ type: 'peers', peers: peers, })); }); return; } if (data.type === 'offer' && typeof data.peer === 'string' && typeof data.offer === 'object') { const otherWS = sockets.get(data.peer); if (!otherWS) return; otherWS.send(JSON.stringify({ type: 'offer', from: peerId, offer: data.offer, })); return; } if (data.type === 'accept' && typeof data.peer === 'string' && typeof data.counterOffer === 'object') { const otherWS = sockets.get(data.peer); if (!otherWS) return; otherWS.send(JSON.stringify({ type: 'accept', from: peerId, counterOffer: data.counterOffer, })); return; } throw 0; } catch (e) { ws.send(JSON.stringify({ type: 'error', message: 'Bad Request', })); } }); ws.on('close', () => { unjoinAll(); sockets.delete(peerId); }); });