UNPKG

socket-ipc

Version:

Message-based communications over UNIX sockets

117 lines (88 loc) 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } const PREAMBLE = 35; // '#' character const LENGTH_LEN = 4; // Length of the length? WTF? const HEADER_LEN = 1 + LENGTH_LEN; // 1 preamble byte + 4 length bytes var DecodeState; (function (DecodeState) { DecodeState[DecodeState["Initial"] = 0] = "Initial"; DecodeState[DecodeState["ReadLength"] = 1] = "ReadLength"; DecodeState[DecodeState["ReadData"] = 2] = "ReadData"; })(DecodeState || (DecodeState = {})); class MessageCodec { constructor(options) { _defineProperty(this, "binary", void 0); _defineProperty(this, "decodeState", DecodeState.Initial); _defineProperty(this, "lengthBuf", Buffer.alloc(LENGTH_LEN)); _defineProperty(this, "lengthBufPos", 0); _defineProperty(this, "decodeBuf", void 0); _defineProperty(this, "decodeBufPos", 0); this.binary = Boolean(options.binary); } encode(data) { const buffer = typeof data === 'string' ? Buffer.from(data) : data; const encoded = Buffer.alloc(buffer.length + HEADER_LEN); let pos = 0; encoded.writeUInt8(PREAMBLE, pos++); encoded.writeUInt32BE(buffer.length, pos); pos += LENGTH_LEN; buffer.copy(encoded, pos, 0, buffer.length); return encoded; } decode(srcBuffer, onMessage) { const messageComplete = buffer => onMessage(this.binary ? buffer : buffer.toString()); let srcPos = 0; while (srcPos < srcBuffer.length) { const srcRemain = srcBuffer.length - srcPos; let bytesRead = 0; switch (this.decodeState) { case DecodeState.Initial: const preamble = srcBuffer.readUInt8(srcPos); bytesRead = 1; if (PREAMBLE !== preamble) throw Error(`preamble did not match: expected ${PREAMBLE}, was ${preamble}`); this.decodeState = DecodeState.ReadLength; break; case DecodeState.ReadLength: bytesRead = Math.min(srcRemain, LENGTH_LEN - this.lengthBufPos); srcBuffer.copy(this.lengthBuf, this.lengthBufPos, srcPos, srcPos + bytesRead); this.lengthBufPos += bytesRead; if (this.lengthBufPos >= LENGTH_LEN) { const messageLength = this.lengthBuf.readUInt32BE(0); if (messageLength) { this.decodeBuf = Buffer.alloc(messageLength); this.decodeBufPos = 0; this.decodeState = DecodeState.ReadData; } else { // Empty message... messageComplete(Buffer.alloc(0)); this.decodeState = DecodeState.Initial; } this.lengthBufPos = 0; } break; case DecodeState.ReadData: { const decodeBuf = this.decodeBuf; if (!decodeBuf) throw Error('unexpected missing decodeBuf'); bytesRead = Math.min(srcRemain, decodeBuf.length - this.decodeBufPos); srcBuffer.copy(decodeBuf, this.decodeBufPos, srcPos, srcPos + bytesRead); this.decodeBufPos += bytesRead; if (this.decodeBufPos >= decodeBuf.length) { messageComplete(decodeBuf); this.decodeState = DecodeState.Initial; this.decodeBuf = undefined; } } break; } if (!bytesRead) throw Error('unexpected: bytesRead == 0'); srcPos += bytesRead; } } } exports.default = MessageCodec; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9NZXNzYWdlQ29kZWMudHMiXSwibmFtZXMiOlsiUFJFQU1CTEUiLCJMRU5HVEhfTEVOIiwiSEVBREVSX0xFTiIsIkRlY29kZVN0YXRlIiwiTWVzc2FnZUNvZGVjIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwiSW5pdGlhbCIsIkJ1ZmZlciIsImFsbG9jIiwiYmluYXJ5IiwiQm9vbGVhbiIsImVuY29kZSIsImRhdGEiLCJidWZmZXIiLCJmcm9tIiwiZW5jb2RlZCIsImxlbmd0aCIsInBvcyIsIndyaXRlVUludDgiLCJ3cml0ZVVJbnQzMkJFIiwiY29weSIsImRlY29kZSIsInNyY0J1ZmZlciIsIm9uTWVzc2FnZSIsIm1lc3NhZ2VDb21wbGV0ZSIsInRvU3RyaW5nIiwic3JjUG9zIiwic3JjUmVtYWluIiwiYnl0ZXNSZWFkIiwiZGVjb2RlU3RhdGUiLCJwcmVhbWJsZSIsInJlYWRVSW50OCIsIkVycm9yIiwiUmVhZExlbmd0aCIsIk1hdGgiLCJtaW4iLCJsZW5ndGhCdWZQb3MiLCJsZW5ndGhCdWYiLCJtZXNzYWdlTGVuZ3RoIiwicmVhZFVJbnQzMkJFIiwiZGVjb2RlQnVmIiwiZGVjb2RlQnVmUG9zIiwiUmVhZERhdGEiLCJ1bmRlZmluZWQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE1BQU1BLFFBQVEsR0FBRyxFQUFqQixDLENBQW9COztBQUNwQixNQUFNQyxVQUFVLEdBQUcsQ0FBbkIsQyxDQUFxQjs7QUFDckIsTUFBTUMsVUFBVSxHQUFHLElBQUlELFVBQXZCLEMsQ0FBa0M7O0lBRTdCRSxXOztXQUFBQSxXO0FBQUFBLEVBQUFBLFcsQ0FBQUEsVztBQUFBQSxFQUFBQSxXLENBQUFBLFc7QUFBQUEsRUFBQUEsVyxDQUFBQSxXO0dBQUFBLFcsS0FBQUEsVzs7QUFZVSxNQUFNQyxZQUFOLENBQW1CO0FBUWhDQyxFQUFBQSxXQUFXLENBQUNDLE9BQUQsRUFBK0I7QUFBQTs7QUFBQSx5Q0FOUEgsV0FBVyxDQUFDSSxPQU1MOztBQUFBLHVD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ZjtBQUNBLG1CQUFLcUIsV0FBTCxHQUFtQjNCLFdBQVcsQ0FBQ0ksT0FBL0I7QUFDRDs7QUFDRCxpQkFBSzhCLFlBQUwsR0FBb0IsQ0FBcEI7QUFDRDs7QUFDRDs7QUFDRixhQUFLbEMsV0FBVyxDQUFDd0MsUUFBakI7QUFDRTtBQUNFLGtCQUFNRixTQUFTLEdBQUcsS0FBS0EsU0FBdkI7QUFDQSxnQkFBSSxDQUFDQSxTQUFMLEVBQWdCLE1BQU1SLEtBQUssQ0FBQyw4QkFBRCxDQUFYO0FBQ2hCSixZQUFBQSxTQUFTLEdBQUdNLElBQUksQ0FBQ0MsR0FBTCxDQUNWUixTQURVLEVBRVZhLFNBQVMsQ0FBQ3hCLE1BQVYsR0FBbUIsS0FBS3lCLFlBRmQsQ0FBWjtBQUlBbkIsWUFBQUEsU0FBUyxDQUFDRixJQUFWLENBQ0VvQixTQURGLEVBRUUsS0FBS0MsWUFGUCxFQUdFZixNQUhGLEVBSUVBLE1BQU0sR0FBR0UsU0FKWDtBQU1BLGlCQUFLYSxZQUFMLElBQXFCYixTQUFyQjs7QUFDQSxnQkFBSSxLQUFLYSxZQUFMLElBQXFCRCxTQUFTLENBQUN4QixNQUFuQyxFQUEyQztBQUN6Q1EsY0FBQUEsZUFBZSxDQUFDZ0IsU0FBRCxDQUFmO0FBQ0EsbUJBQUtYLFdBQUwsR0FBbUIzQixXQUFXLENBQUNJLE9BQS9CO0FBQ0EsbUJBQUtrQyxTQUFMLEdBQWlCRyxTQUFqQjtBQUNEO0FBQ0Y7QUFDRDtBQXRESjs7QUF3REEsVUFBSSxDQUFDZixTQUFMLEVBQWdCLE1BQU1JLEtBQUssQ0FBQyw0QkFBRCxDQUFYO0FBQ2hCTixNQUFBQSxNQUFNLElBQUlFLFNBQVY7QUFDRDtBQUNGOztBQTFGK0IiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBQUkVBTUJMRSA9IDM1IC8vICcjJyBjaGFyYWN0ZXJcbmNvbnN0IExFTkdUSF9MRU4gPSA0IC8vIExlbmd0aCBvZiB0aGUgbGVuZ3RoPyBXVEY/XG5jb25zdCBIRUFERVJfTEVOID0gMSArIExFTkdUSF9MRU4gLy8gMSBwcmVhbWJsZSBieXRlICsgNCBsZW5ndGggYnl0ZXNcblxuZW51bSBEZWNvZGVTdGF0ZSB7XG4gIEluaXRpYWwsXG4gIFJlYWRMZW5ndGgsXG4gIFJlYWREYXRhLFxufVxuXG5leHBvcnQgdHlwZSBNZXNzYWdlQ29kZWNPcHRpb25zID0ge1xuICBiaW5hcnk/OiBib29sZWFuXG59XG5cbmV4cG9ydCB0eXBlIE1lc3NhZ2VEZWNvZGVkQ2FsbGJhY2sgPSAobWVzc2FnZTogQnVmZmVyIHwgc3RyaW5nKSA9PiB2b2lkXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1lc3NhZ2VDb2RlYyB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYmluYXJ5OiBib29sZWFuXG4gIHByaXZhdGUgZGVjb2RlU3RhdGU6IERlY29kZVN0YXRlID0gRGVjb2RlU3RhdGUuSW5pdGlhbFxuICBwcml2YXRlIHJlYWRvbmx5IGxlbmd0aEJ1ZjogQnVmZmVyID0gQnVmZmVyLmFsbG9jKExFTkdUSF9MRU4pXG4gIHByaXZhdGUgbGVuZ3RoQnVmUG9zID0gMFxuICBwcml2YXRlIGRlY29kZUJ1ZjogQnVmZmVyIHwgdW5kZWZpbmVkXG4gIHByaXZhdGUgZGVjb2RlQnVmUG9zID0gMFxuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IE1lc3NhZ2VDb2RlY09wdGlvbnMpIHtcbiAgICB0aGlzLmJpbmFyeSA9IEJvb2xlYW4ob3B0aW9ucy5iaW5hcnkpXG4gIH1cblxuICBlbmNvZGUoZGF0YTogc3RyaW5nIHwgQnVmZmVyKTogQnVmZmVyIHtcbiAgICBjb25zdCBidWZmZXI6IEJ1ZmZlciA9IHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJyA/IEJ1ZmZlci5mcm9tKGRhdGEpIDogZGF0YVxuICAgIGNvbnN0IGVuY29kZWQgPSBCdWZmZXIuYWxsb2MoYnVmZmVyLmxlbmd0aCArIEhFQURFUl9MRU4pXG4gICAgbGV0IHBvcyA9IDBcbiAgICBlbmNvZGVkLndyaXRlVUludDgoUFJFQU1CTEUsIHBvcysrKVxuICAgIGVuY29kZWQud3JpdGVVSW50MzJCRShidWZmZXIubGVuZ3RoLCBwb3MpXG4gICAgcG9zICs9IExFTkdUSF9MRU5cbiAgICBidWZmZXIuY29weShlbmNvZGVkLCBwb3MsIDAsIGJ1ZmZlci5sZW5ndGgpXG4gICAgcmV0dXJuIGVuY29kZWRcbiAgfVxuXG4gIGRlY29kZShzcmNCdWZmZXI6IEJ1ZmZlciwgb25NZXNzYWdlOiBNZXNzYWdlRGVjb2RlZENhbGxiYWNrKTogdm9pZCB7XG4gICAgY29uc3QgbWVzc2FnZUNvbXBsZXRlID0gKGJ1ZmZlcjogQnVmZmVyKTogdm9pZCA9PlxuICAgICAgb25NZXNzYWdlKHRoaXMuYmluYXJ5ID8gYnVmZmVyIDogYnVmZmVyLnRvU3RyaW5nKCkpXG5cbiAgICBsZXQgc3JjUG9zID0gMFxuICAgIHdoaWxlIChzcmNQb3MgPCBzcmNCdWZmZXIubGVuZ3RoKSB7XG4gICAgICBjb25zdCBzcmNSZW1haW4gPSBzcmNCdWZmZXIubGVuZ3RoIC0gc3JjUG9zXG4gICAgICBsZXQgYnl0ZXNSZWFkID0gMFxuICAgICAgc3dpdGNoICh0aGlzLmRlY29kZVN0YXRlKSB7XG4gICAgICAgIGNhc2UgRGVjb2RlU3RhdGUuSW5pdGlhbDpcbiAgICAgICAgICBjb25zdCBwcmVhbWJsZSA9IHNyY0J1ZmZlci5yZWFkVUludDgoc3JjUG9zKVxuICAgICAgICAgIGJ5dGVzUmVhZCA9IDFcbiAgICAgICAgICBpZiAoUFJFQU1CTEUgIT09IHByZWFtYmxlKVxuICAgICAgICAgICAgdGhyb3cgRXJyb3IoXG4gICAgICAgICAgICAgIGBwcmVhbWJsZSBkaWQgbm90IG1hdGNoOiBleHBlY3RlZCAke1BSRUFNQkxFfSwgd2FzICR7cHJlYW1ibGV9YFxuICAgICAgICAgICAgKVxuICAgICAgICAgIHRoaXMuZGVjb2RlU3RhdGUgPSBEZWNvZGVTdGF0ZS5SZWFkTGVuZ3RoXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSBEZWNvZGVTdGF0ZS5SZWFkTGVuZ3RoOlxuICAgICAgICAgIGJ5dGVzUmVhZCA9IE1hdGgubWluKHNyY1JlbWFpbiwgTEVOR1RIX0xFTiAtIHRoaXMubGVuZ3RoQnVmUG9zKVxuICAgICAgICAgIHNyY0J1ZmZlci5jb3B5KFxuICAgICAgICAgICAgdGhpcy5sZW5ndGhCdWYsXG4gICAgICAgICAgICB0aGlzLmxlbmd0aEJ1ZlBvcyxcbiAgICAgICAgICAgIHNyY1BvcyxcbiAgICAgICAgICAgIHNyY1BvcyArIGJ5dGVzUmVhZFxuICAgICAgICAgIClcbiAgICAgICAgICB0aGlzLmxlbmd0aEJ1ZlBvcyArPSBieXRlc1JlYWRcbiAgICAgICAgICBpZiAodGhpcy5sZW5ndGhCdWZQb3MgPj0gTEVOR1RIX0xFTikge1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZUxlbmd0aCA9IHRoaXMubGVuZ3RoQnVmLnJlYWRVSW50MzJCRSgwKVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2VMZW5ndGgpIHtcbiAgICAgICAgICAgICAgdGhpcy5kZWNvZGVCdWYgPSBCdWZmZXIuYWxsb2MobWVzc2FnZUxlbmd0aClcbiAgICAgICAgICAgICAgdGhpcy5kZWNvZGVCdWZQb3MgPSAwXG4gICAgICAgICAgICAgIHRoaXMuZGVjb2RlU3RhdGUgPSBEZWNvZGVTdGF0ZS5SZWFkRGF0YVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gRW1wdHkgbWVzc2FnZS4uLlxuICAgICAgICAgICAgICBtZXNzYWdlQ29tcGxldGUoQnVmZmVyLmFsbG9jKDApKVxuICAgICAgICAgICAgICB0aGlzLmRlY29kZVN0YXRlID0gRGVjb2RlU3RhdGUuSW5pdGlhbFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5sZW5ndGhCdWZQb3MgPSAwXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgRGVjb2RlU3RhdGUuUmVhZERhdGE6XG4gICAgICAgICAge1xuICAgICAgICAgICAgY29uc3QgZGVjb2RlQnVmID0gdGhpcy5kZWNvZGVCdWZcbiAgICAgICAgICAgIGlmICghZGVjb2RlQnVmKSB0aHJvdyBFcnJvcigndW5leHBlY3RlZCBtaXNzaW5nIGRlY29kZUJ1ZicpXG4gICAgICAgICAgICBieXRlc1JlYWQgPSBNYXRoLm1pbihcbiAgICAgICAgICAgICAgc3JjUmVtYWluLFxuICAgICAgICAgICAgICBkZWNvZGVCdWYubGVuZ3RoIC0gdGhpcy5kZWNvZGVCdWZQb3NcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIHNyY0J1ZmZlci5jb3B5KFxuICAgICAgICAgICAgICBkZWNvZGVCdWYsXG4gICAgICAgICAgICAgIHRoaXMuZGVjb2RlQnVmUG9zLFxuICAgICAgICAgICAgICBzcmNQb3MsXG4gICAgICAgICAgICAgIHNyY1BvcyArIGJ5dGVzUmVhZFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgdGhpcy5kZWNvZGVCdWZQb3MgKz0gYnl0ZXNSZWFkXG4gICAgICAgICAgICBpZiAodGhpcy5kZWNvZGVCdWZQb3MgPj0gZGVjb2RlQnVmLmxlbmd0aCkge1xuICAgICAgICAgICAgICBtZXNzYWdlQ29tcGxldGUoZGVjb2RlQnVmKVxuICAgICAgICAgICAgICB0aGlzLmRlY29kZVN0YXRlID0gRGVjb2RlU3RhdGUuSW5pdGlhbFxuICAgICAgICAgICAgICB0aGlzLmRlY29kZUJ1ZiA9IHVuZGVmaW5lZFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgaWYgKCFieXRlc1JlYWQpIHRocm93IEVycm9yKCd1bmV4cGVjdGVkOiBieXRlc1JlYWQgPT0gMCcpXG4gICAgICBzcmNQb3MgKz0gYnl0ZXNSZWFkXG4gICAgfVxuICB9XG59XG4iXX0=