muweb-socket
Version:
WebSocket communication for mudb
214 lines • 8.37 kB
JavaScript
"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