mulocal-socket
Version:
Local socket emulation for mudb
175 lines • 6.31 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var socket_1 = require("mudb/socket");
var mustreams_1 = require("mustreams");
function noop() { }
var BufferWrapper = (function () {
function BufferWrapper(data) {
this._buffer = mustreams_1.allocBuffer(data.length);
this.bytes = this._buffer.uint8.subarray(0, data.length);
this.bytes.set(data);
}
BufferWrapper.prototype.free = function () {
mustreams_1.freeBuffer(this._buffer);
};
return BufferWrapper;
}());
var MuLocalSocket = (function () {
function MuLocalSocket(sessionId, server) {
var _this = this;
this._onMessage = noop;
this._onUnreliableMessage = noop;
this._onClose = noop;
this.state = socket_1.MuSocketState.INIT;
this._pendingUnreliableMessages = [];
this._drainUnreliable = function () {
if (_this.state !== socket_1.MuSocketState.OPEN) {
return;
}
var message = _this._pendingUnreliableMessages.pop();
if (typeof message === 'string') {
_this._duplex._onMessage(message, true);
}
else if (message) {
_this._duplex._onMessage(message.bytes, true);
message.free();
}
};
this._pendingMessages = [];
this._drain = function () {
_this._drainTimeout = 0;
if (_this.state !== socket_1.MuSocketState.OPEN) {
return;
}
for (var i = 0; i < _this._pendingMessages.length; ++i) {
var message = _this._pendingMessages[i];
if (typeof message === 'string') {
_this._duplex._onMessage(message, false);
}
else {
_this._duplex._onMessage(message.bytes, false);
message.free();
}
}
_this._pendingMessages.length = 0;
};
this.sessionId = sessionId;
this._server = server;
}
MuLocalSocket.prototype.open = function (spec) {
var _this = this;
setTimeout(function () {
if (_this.state === socket_1.MuSocketState.OPEN) {
_this._onClose('socket already open');
return;
}
if (_this.state === socket_1.MuSocketState.CLOSED) {
_this._onClose('cannot reopen closed socket');
return;
}
_this.state = socket_1.MuSocketState.OPEN;
_this._onMessage = spec.message;
_this._onClose = spec.close;
_this._drain();
while (_this._pendingUnreliableMessages.length) {
_this._drainUnreliable();
}
spec.ready();
}, 0);
};
MuLocalSocket.prototype.send = function (data_, unreliable) {
if (this.state === socket_1.MuSocketState.CLOSED) {
return;
}
var data = typeof data_ === 'string' ? data_ : new BufferWrapper(data_);
if (unreliable) {
this._pendingUnreliableMessages.push(data);
setTimeout(this._drainUnreliable, 0);
}
else {
this._pendingMessages.push(data);
if (!this._drainTimeout) {
this._drainTimeout = setTimeout(this._drain, 0);
}
}
};
MuLocalSocket.prototype.close = function () {
if (this.state === socket_1.MuSocketState.CLOSED) {
return;
}
this.state = socket_1.MuSocketState.CLOSED;
this._server._removeSocket(this);
this._onClose();
this._duplex.close();
};
return MuLocalSocket;
}());
exports.MuLocalSocket = MuLocalSocket;
function removeIfExists(array, element) {
var idx = array.indexOf(element);
if (idx >= 0) {
array[idx] = array[array.length - 1];
array.pop();
}
}
var MuLocalSocketServer = (function () {
function MuLocalSocketServer() {
this.clients = [];
this._pendingSockets = [];
this.state = socket_1.MuSocketServerState.INIT;
}
MuLocalSocketServer.prototype._handleConnection = function (socket) {
switch (this.state) {
case socket_1.MuSocketServerState.RUNNING:
this.clients.push(socket);
this._onConnection(socket);
break;
case socket_1.MuSocketServerState.SHUTDOWN:
socket.close();
break;
default:
this._pendingSockets.push(socket);
}
};
MuLocalSocketServer.prototype._removeSocket = function (socket) {
removeIfExists(this.clients, socket);
removeIfExists(this._pendingSockets, socket);
};
MuLocalSocketServer.prototype.start = function (spec) {
var _this = this;
setTimeout(function () {
if (_this.state === socket_1.MuSocketServerState.RUNNING) {
_this._onClose('local socket server already running');
return;
}
if (_this.state === socket_1.MuSocketServerState.SHUTDOWN) {
_this._onClose('local socket server already shut down, cannot restart');
return;
}
_this.state = socket_1.MuSocketServerState.RUNNING;
_this._onConnection = spec.connection;
_this._onClose = spec.close;
while (_this._pendingSockets.length > 0) {
_this._handleConnection(_this._pendingSockets.pop());
}
spec.ready();
}, 0);
};
MuLocalSocketServer.prototype.close = function () {
if (this.state === socket_1.MuSocketServerState.SHUTDOWN) {
return;
}
if (this.state === socket_1.MuSocketServerState.INIT) {
this.state = socket_1.MuSocketServerState.SHUTDOWN;
return;
}
this.state = socket_1.MuSocketServerState.SHUTDOWN;
for (var i = this.clients.length - 1; i >= 0; --i) {
this.clients[i].close();
}
this._onClose();
};
return MuLocalSocketServer;
}());
exports.MuLocalSocketServer = MuLocalSocketServer;
//# sourceMappingURL=server-socket.js.map