UNPKG

muweb-socket

Version:

WebSocket communication for mudb

214 lines 8.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var ws = require("uws"); var socket_1 = require("mudb/socket"); function noop() { } var MuWebSocketConnection = (function () { function MuWebSocketConnection(sessionId, reliableSocket, serverClose) { var _this = this; this.started = false; this.closed = false; this.unreliableSockets = []; this._nextSocketSend = 0; this.pendingMessages = []; this.onMessage = noop; this.onClose = noop; this.sessionId = sessionId; this.reliableSocket = reliableSocket; this.serverClose = serverClose; this.reliableSocket.onmessage = function (_a) { var data = _a.data; if (_this.started) { if (typeof data === 'string') { _this.onMessage(data, false); } else { _this.onMessage(new Uint8Array(data), false); } } else { if (typeof data === 'string') { _this.pendingMessages.push(data); } else { _this.pendingMessages.push(new Uint8Array(data).slice(0)); } } }; this.reliableSocket.onclose = function () { _this.closed = true; for (var i = 0; i < _this.unreliableSockets.length; ++i) { _this.unreliableSockets[i].close(); } _this.onClose(); _this.serverClose(); }; } MuWebSocketConnection.prototype.addUnreliableSocket = function (socket) { var _this = this; if (this.closed) { return; } this.unreliableSockets.push(socket); socket.onmessage = function (_a) { var data = _a.data; if (typeof data === 'string') { _this.onMessage(data, true); } else { _this.onMessage(new Uint8Array(data), true); } }; socket.onclose = function () { _this.unreliableSockets.splice(_this.unreliableSockets.indexOf(socket), 1); }; }; MuWebSocketConnection.prototype.send = function (data, unreliable) { if (this.closed) { return; } if (unreliable) { if (this.unreliableSockets.length > 0) { this.unreliableSockets[this._nextSocketSend++ % this.unreliableSockets.length].send(data); } } else { this.reliableSocket.send(data); } }; MuWebSocketConnection.prototype.close = function () { this.reliableSocket.close(); }; return MuWebSocketConnection; }()); exports.MuWebSocketConnection = MuWebSocketConnection; var MuWebSocketClient = (function () { function MuWebSocketClient(connection) { this.state = socket_1.MuSocketState.INIT; this.sessionId = connection.sessionId; this._connection = connection; } MuWebSocketClient.prototype.open = function (spec) { var _this = this; if (this.state === socket_1.MuSocketState.OPEN) { throw new Error('mudb/web-socket: socket already open'); } if (this.state === socket_1.MuSocketState.CLOSED) { throw new Error('mudb/web-socket: cannot reopen closed socket'); } setTimeout(function () { _this._connection.started = true; _this._connection.onMessage = spec.message; _this._connection.onClose = function () { _this.state = socket_1.MuSocketState.CLOSED; spec.close(); }; _this.state = socket_1.MuSocketState.OPEN; spec.ready(); for (var i = 0; i < _this._connection.pendingMessages.length; ++i) { spec.message(_this._connection.pendingMessages[i], false); } _this._connection.pendingMessages.length = 0; if (_this._connection.closed) { _this.state = socket_1.MuSocketState.CLOSED; spec.close(); } }, 0); }; MuWebSocketClient.prototype.send = function (data, unreliable) { this._connection.send(data, !!unreliable); }; MuWebSocketClient.prototype.close = function () { this._connection.close(); }; return MuWebSocketClient; }()); exports.MuWebSocketClient = MuWebSocketClient; var MuWebSocketServer = (function () { function MuWebSocketServer(spec) { this._connections = []; this.clients = []; this.state = socket_1.MuSocketServerState.INIT; this._httpServer = spec.server; } MuWebSocketServer.prototype._findConnection = function (sessionId) { for (var i = 0; i < this._connections.length; ++i) { if (this._connections[i].sessionId === sessionId) { return this._connections[i]; } } return null; }; MuWebSocketServer.prototype.start = function (spec) { var _this = this; if (this.state === socket_1.MuSocketServerState.RUNNING) { throw new Error('mudb/web-socket: server already running'); } if (this.state === socket_1.MuSocketServerState.SHUTDOWN) { throw new Error('mudb/web-socket: server already shut down, cannot restart'); } setTimeout(function () { _this._websocketServer = new ws.Server({ server: _this._httpServer, }) .on('connection', function (socket) { socket.onmessage = function (_a) { var data = _a.data; try { var sessionId = JSON.parse(data).sessionId; if (typeof sessionId !== 'string') { throw new Error('bad session ID'); } var connection_1 = _this._findConnection(sessionId); if (connection_1) { socket.send(JSON.stringify({ reliable: false, })); connection_1.addUnreliableSocket(socket); return; } else { socket.send(JSON.stringify({ reliable: true, })); connection_1 = new MuWebSocketConnection(sessionId, socket, function () { if (connection_1) { _this._connections.splice(_this._connections.indexOf(connection_1), 1); for (var i = _this.clients.length - 1; i >= 0; --i) { if (_this.clients[i].sessionId === connection_1.sessionId) { _this.clients.splice(i, 1); } } } }); _this._connections.push(connection_1); var client = new MuWebSocketClient(connection_1); _this.clients.push(client); spec.connection(client); return; } } catch (e) { console.error("mudb/web-socket: terminating socket due to " + e); socket.terminate(); } }; }); _this._onClose = spec.close; _this.state = socket_1.MuSocketServerState.RUNNING; spec.ready(); }, 0); }; MuWebSocketServer.prototype.close = function () { if (this.state === socket_1.MuSocketServerState.SHUTDOWN) { return; } this.state = socket_1.MuSocketServerState.SHUTDOWN; if (this._websocketServer) { this._websocketServer.close(this._onClose); } }; return MuWebSocketServer; }()); exports.MuWebSocketServer = MuWebSocketServer; //# sourceMappingURL=server.js.map