UNPKG

rxdb

Version:

A local-first realtime NoSQL Database for JavaScript applications - https://rxdb.info/

151 lines (148 loc) 4.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PEER_ID_LENGTH = void 0; exports.startSignalingServerSimplePeer = startSignalingServerSimplePeer; var _index = require("../utils/index.js"); var _connectionHandlerSimplePeer = require("./connection-handler-simple-peer.js"); var PEER_ID_LENGTH = exports.PEER_ID_LENGTH = 12; /** * Starts a WebRTC signaling server * that can be used in tests. */ async function startSignalingServerSimplePeer(serverOptions) { var { WebSocketServer } = await import('ws'); var wss = new WebSocketServer(serverOptions); var peerById = new Map(); var peersByRoom = new Map(); var serverClosed = false; wss.on('close', () => { serverClosed = true; peerById.clear(); peersByRoom.clear(); }); /** * Clients can disconnect without telling that to the * server. Therefore we have to automatically disconnect clients that * have not send a ping message in the last 2 minutes. */ (async () => { var _loop = async function () { await (0, _index.promiseWait)(1000 * 5); var minTime = Date.now() - _connectionHandlerSimplePeer.SIMPLE_PEER_PING_INTERVAL; Array.from(peerById.values()).forEach(peer => { if (peer.lastPing < minTime) { disconnectSocket(peer.id, 'no ping for 2 minutes'); } }); }; while (!serverClosed) { await _loop(); } })(); function disconnectSocket(peerId, reason) { console.log('# disconnect peer ' + peerId + ' reason: ' + reason); var peer = peerById.get(peerId); if (peer) { peer.socket.close && peer.socket.close(undefined, reason); peer.rooms.forEach(roomId => { var room = peersByRoom.get(roomId); room?.delete(peerId); if (room && room.size === 0) { peersByRoom.delete(roomId); } }); } peerById.delete(peerId); } wss.on('connection', function (ws) { /** * PeerID is created by the server to prevent malicious * actors from falsy claiming other peoples ids. */ var peerId = (0, _index.randomToken)(PEER_ID_LENGTH); var peer = { id: peerId, socket: ws, rooms: new Set(), lastPing: Date.now() }; peerById.set(peerId, peer); sendMessage(ws, { type: 'init', yourPeerId: peerId }); ws.on('error', err => { console.error('SERVER ERROR:'); console.dir(err); disconnectSocket(peerId, 'socket errored'); }); ws.on('close', () => { disconnectSocket(peerId, 'socket disconnected'); }); ws.on('message', msgEvent => { peer.lastPing = Date.now(); var message = JSON.parse(msgEvent.toString()); var type = message.type; switch (type) { case 'join': var roomId = message.room; if (!validateIdString(roomId) || !validateIdString(peerId)) { disconnectSocket(peerId, 'invalid ids'); return; } if (peer.rooms.has(peerId)) { return; } peer.rooms.add(roomId); var room = (0, _index.getFromMapOrCreate)(peersByRoom, message.room, () => new Set()); room.add(peerId); // tell everyone about new room state room.forEach(otherPeerId => { var otherPeer = peerById.get(otherPeerId); if (otherPeer) { sendMessage(otherPeer.socket, { type: 'joined', otherPeerIds: Array.from(room) }); } }); break; case 'signal': if (message.senderPeerId !== peerId) { disconnectSocket(peerId, 'spoofed sender'); return; } var receiver = peerById.get(message.receiverPeerId); if (receiver) { sendMessage(receiver.socket, message); } break; case 'ping': break; default: disconnectSocket(peerId, 'unknown message type ' + type); } }); }); return { port: serverOptions.port, server: wss, localUrl: 'ws://localhost:' + serverOptions.port }; } function sendMessage(ws, message) { var msgString = JSON.stringify(message); ws.send(msgString); } function validateIdString(roomId) { if (typeof roomId === 'string' && roomId.length > 5 && roomId.length < 100) { return true; } else { return false; } } //# sourceMappingURL=signaling-server.js.map