emailjs-tcp-socket
Version:
This shim brings the W3C Raw Socket API to node.js and Chromium. Its purpose is to enable apps to use the same api in Firefox OS, Chrome OS, and on the server.
248 lines (200 loc) • 23.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _ramda = require('ramda');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var TCPSocket = function () {
_createClass(TCPSocket, null, [{
key: 'open',
value: function open(host, port) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return new TCPSocket({ host: host, port: port, options: options });
}
}]);
function TCPSocket(_ref) {
var _this = this;
var host = _ref.host,
port = _ref.port,
options = _ref.options;
_classCallCheck(this, TCPSocket);
this.host = new Windows.Networking.HostName(host); // NB! HostName constructor will throw on invalid input
this.port = port;
this.ssl = (0, _ramda.propOr)(false, 'useSecureTransport')(options);
this.bufferedAmount = 0;
this.readyState = 'connecting';
this.binaryType = (0, _ramda.propOr)('arraybuffer', 'binaryType')(options);
if (this.binaryType !== 'arraybuffer') {
throw new Error('Only arraybuffers are supported!');
}
this._socket = new Windows.Networking.Sockets.StreamSocket();
this._socket.control.keepAlive = true;
this._socket.control.noDelay = true;
this._dataReader = null;
this._dataWriter = null;
// set to true if upgrading with STARTTLS
this._upgrading = false;
// cache all client.send calls to this array if currently upgrading
this._upgradeCache = [];
// initial socket type. default is 'plainSocket' (no encryption applied)
// 'tls12' supports the TLS 1.2, TLS 1.1 and TLS 1.0 protocols but no SSL
this._protectionLevel = Windows.Networking.Sockets.SocketProtectionLevel[this.ssl ? 'tls12' : 'plainSocket'];
// Initiate connection to destination
this._socket.connectAsync(this.host, this.port, this._protectionLevel).done(function () {
_this._setStreamHandlers();
_this._emit('open');
}, function (e) {
return _this._emit('error', e);
});
}
/**
* Initiate Reader and Writer interfaces for the socket
*/
_createClass(TCPSocket, [{
key: '_setStreamHandlers',
value: function _setStreamHandlers() {
this._dataReader = new Windows.Storage.Streams.DataReader(this._socket.inputStream);
this._dataReader.inputStreamOptions = Windows.Storage.Streams.InputStreamOptions.partial;
// setup writer
this._dataWriter = new Windows.Storage.Streams.DataWriter(this._socket.outputStream);
// start byte reader loop
this._read();
}
/**
* Emit an error and close socket
*
* @param {Error} error Error object
*/
}, {
key: '_errorHandler',
value: function _errorHandler(error) {
// we ignore errors after close has been called, since all aborted operations
// will emit their error handlers
// this will also apply to starttls as a read call is aborted before upgrading the socket
if (this._upgrading || this.readyState !== 'closing' && this.readyState !== 'closed') {
this._emit('error', error);
this.close();
}
}
/**
* Read available bytes from the socket. This method is recursive once it ends, it restarts itthis
*/
}, {
key: '_read',
value: function _read() {
var _this2 = this;
if (this._upgrading || this.readyState !== 'open' && this.readyState !== 'connecting') {
return; // do nothing if socket not open
}
// Read up to 4096 bytes from the socket. This is not a fixed number (the mode was set
// with inputStreamOptions.partial property), so it might return with a smaller
// amount of bytes.
this._dataReader.loadAsync(4096).done(function (availableByteCount) {
if (!availableByteCount) {
// no bytes available for reading, restart the reading process
return setImmediate(_this2._read.bind(_this2));
}
// we need an Uint8Array that gets filled with the bytes from the buffer
var data = new Uint8Array(availableByteCount);
_this2._dataReader.readBytes(data); // data argument gets filled with the bytes
_this2._emit('data', data.buffer);
// restart reading process
return setImmediate(_this2._read.bind(_this2));
}, function (e) {
return _this2._errorHandler(e);
});
}
//
// API
//
}, {
key: 'close',
value: function close() {
this.readyState = 'closing';
try {
this._socket.close();
} catch (E) {
this._emit('error', E);
}
setImmediate(this._emit.bind(this, 'close'));
}
}, {
key: 'send',
value: function send(data) {
var _this3 = this;
if (this.readyState !== 'open') {
return;
}
if (this._upgrading) {
this._upgradeCache.push(data);
return;
}
// Write bytes to buffer
this._dataWriter.writeBytes(data);
// Emit buffer contents
this._dataWriter.storeAsync().done(function () {
return _this3._emit('drain');
}, function (e) {
return _this3._errorHandler(e);
});
}
}, {
key: 'upgradeToSecure',
value: function upgradeToSecure() {
var _this4 = this;
if (this.ssl || this._upgrading) return;
this._upgrading = true;
try {
// release current input stream. this is required to allow socket upgrade
// write stream is not released as all send calls are cached from this point onwards
// and not passed to socket until the socket is upgraded
this._dataReader.detachStream();
} catch (E) {}
// update protection level
this._protectionLevel = Windows.Networking.Sockets.SocketProtectionLevel.tls12;
this._socket.upgradeToSslAsync(this._protectionLevel, this.host).done(function () {
_this4._upgrading = false;
_this4.ssl = true; // secured connection from now on
_this4._dataReader = new Windows.Storage.Streams.DataReader(_this4._socket.inputStream);
_this4._dataReader.inputStreamOptions = Windows.Storage.Streams.InputStreamOptions.partial;
_this4._read();
// emit all cached requests
while (_this4._upgradeCache.length) {
var data = _this4._upgradeCache.shift();
_this4.send(data);
}
}, function (e) {
_this4._upgrading = false;
_this4._errorHandler(e);
});
}
}, {
key: '_emit',
value: function _emit(type, data) {
var target = this;
switch (type) {
case 'open':
this.readyState = 'open';
this.onopen && this.onopen({ target: target, type: type, data: data });
break;
case 'error':
this.onerror && this.onerror({ target: target, type: type, data: data });
break;
case 'data':
this.ondata && this.ondata({ target: target, type: type, data: data });
break;
case 'drain':
this.ondrain && this.ondrain({ target: target, type: type, data: data });
break;
case 'close':
this.readyState = 'closed';
this.onclose && this.onclose({ target: target, type: type, data: data });
break;
}
}
}]);
return TCPSocket;
}();
exports.default = TCPSocket;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy93aW5kb3dzLXNvY2tldC5qcyJdLCJuYW1lcyI6WyJUQ1BTb2NrZXQiLCJob3N0IiwicG9ydCIsIm9wdGlvbnMiLCJXaW5kb3dzIiwiTmV0d29ya2luZyIsIkhvc3ROYW1lIiwic3NsIiwiYnVmZmVyZWRBbW91bnQiLCJyZWFkeVN0YXRlIiwiYmluYXJ5VHlwZSIsIkVycm9yIiwiX3NvY2tldCIsIlNvY2tldHMiLCJTdHJlYW1Tb2NrZXQiLCJjb250cm9sIiwia2VlcEFsaXZlIiwibm9EZWxheSIsIl9kYXRhUmVhZGVyIiwiX2RhdGFXcml0ZXIiLCJfdXBncmFkaW5nIiwiX3VwZ3JhZGVDYWNoZSIsIl9wcm90ZWN0aW9uTGV2ZWwiLCJTb2NrZXRQcm90ZWN0aW9uTGV2ZWwiLCJjb25uZWN0QXN5bmMiLCJkb25lIiwiX3NldFN0cmVhbUhhbmRsZXJzIiwiX2VtaXQiLCJlIiwiU3RvcmFnZSIsIlN0cmVhbXMiLCJEYXRhUmVhZGVyIiwiaW5wdXRTdHJlYW0iLCJpbnB1dFN0cmVhbU9wdGlvbnMiLCJJbnB1dFN0cmVhbU9wdGlvbnMiLCJwYXJ0aWFsIiwiRGF0YVdyaXRlciIsIm91dHB1dFN0cmVhbSIsIl9yZWFkIiwiZXJyb3IiLCJjbG9zZSIsImxvYWRBc3luYyIsImF2YWlsYWJsZUJ5dGVDb3VudCIsInNldEltbWVkaWF0ZSIsImJpbmQiLCJkYXRhIiwiVWludDhBcnJheSIsInJlYWRCeXRlcyIsImJ1ZmZlciIsIl9lcnJvckhhbmRsZXIiLCJFIiwicHVzaCIsIndyaXRlQnl0ZXMiLCJzdG9yZUFzeW5jIiwiZGV0YWNoU3RyZWFtIiwidGxzMTIiLCJ1cGdyYWRlVG9Tc2xBc3luYyIsImxlbmd0aCIsInNoaWZ0Iiwic2VuZCIsInR5cGUiLCJ0YXJnZXQiLCJvbm9wZW4iLCJvbmVycm9yIiwib25kYXRhIiwib25kcmFpbiIsIm9uY2xvc2UiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7Ozs7SUFFcUJBLFM7Ozt5QkFDTkMsSSxFQUFNQyxJLEVB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QUFoQixFQUFiLENBQWhCO0FBQ0E7QUFqQko7QUFtQkQ7Ozs7OztrQkEvTGtCN0MsUyIsImZpbGUiOiJ3aW5kb3dzLXNvY2tldC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHByb3BPciB9IGZyb20gJ3JhbWRhJ1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUQ1BTb2NrZXQge1xuICBzdGF0aWMgb3BlbiAoaG9zdCwgcG9ydCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgcmV0dXJuIG5ldyBUQ1BTb2NrZXQoeyBob3N0LCBwb3J0LCBvcHRpb25zIH0pXG4gIH1cblxuICBjb25zdHJ1Y3RvciAoeyBob3N0LCBwb3J0LCBvcHRpb25zIH0pIHtcbiAgICB0aGlzLmhvc3QgPSBuZXcgV2luZG93cy5OZXR3b3JraW5nLkhvc3ROYW1lKGhvc3QpIC8vIE5CISBIb3N0TmFtZSBjb25zdHJ1Y3RvciB3aWxsIHRocm93IG9uIGludmFsaWQgaW5wdXRcbiAgICB0aGlzLnBvcnQgPSBwb3J0XG4gICAgdGhpcy5zc2wgPSBwcm9wT3IoZmFsc2UsICd1c2VTZWN1cmVUcmFuc3BvcnQnKShvcHRpb25zKVxuICAgIHRoaXMuYnVmZmVyZWRBbW91bnQgPSAwXG4gICAgdGhpcy5yZWFkeVN0YXRlID0gJ2Nvbm5lY3RpbmcnXG4gICAgdGhpcy5iaW5hcnlUeXBlID0gcHJvcE9yKCdhcnJheWJ1ZmZlcicsICdiaW5hcnlUeXBlJykob3B0aW9ucylcblxuICAgIGlmICh0aGlzLmJpbmFyeVR5cGUgIT09ICdhcnJheWJ1ZmZlcicpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25seSBhcnJheWJ1ZmZlcnMgYXJlIHN1cHBvcnRlZCEnKVxuICAgIH1cblxuICAgIHRoaXMuX3NvY2tldCA9IG5ldyBXaW5kb3dzLk5ldHdvcmtpbmcuU29ja2V0cy5TdHJlYW1Tb2NrZXQoKVxuXG4gICAgdGhpcy5fc29ja2V0LmNvbnRyb2wua2VlcEFsaXZlID0gdHJ1ZVxuICAgIHRoaXMuX3NvY2tldC5jb250cm9sLm5vRGVsYXkgPSB0cnVlXG5cbiAgICB0aGlzLl9kYXRhUmVhZGVyID0gbnVsbFxuICAgIHRoaXMuX2RhdGFXcml0ZXIgPSBudWxsXG5cbiAgICAvLyBzZXQgdG8gdHJ1ZSBpZiB1cGdyYWRpbmcgd2l0aCBTVEFSVFRMU1xuICAgIHRoaXMuX3VwZ3JhZGluZyA9IGZhbHNlXG5cbiAgICAvLyBjYWNoZSBhbGwgY2xpZW50LnNlbmQgY2FsbHMgdG8gdGhpcyBhcnJheSBpZiBjdXJyZW50bHkgdXBncmFkaW5nXG4gICAgdGhpcy5fdXBncmFkZUNhY2hlID0gW11cblxuICAgIC8vIGluaXRpYWwgc29ja2V0IHR5cGUuIGRlZmF1bHQgaXMgJ3BsYWluU29ja2V0JyAobm8gZW5jcnlwdGlvbiBhcHBsaWVkKVxuICAgIC8vICd0bHMxMicgc3VwcG9ydHMgdGhlIFRMUyAxLjIsIFRMUyAxLjEgYW5kIFRMUyAxLjAgcHJvdG9jb2xzIGJ1dCBubyBTU0xcbiAgICB0aGlzLl9wcm90ZWN0aW9uTGV2ZWwgPSBXaW5kb3dzLk5ldHdvcmtpbmcuU29ja2V0cy5Tb2NrZXRQcm90ZWN0aW9uTGV2ZWxbdGhpcy5zc2wgPyAndGxzMTInIDogJ3BsYWluU29ja2V0J11cblxuICAgIC8vIEluaXRpYXRlIGNvbm5lY3Rpb24gdG8gZGVzdGluYXRpb25cbiAgICB0aGlzLl9zb2NrZXRcbiAgICAgIC5jb25uZWN0QXN5bmModGhpcy5ob3N0LCB0aGlzLnBvcnQsIHRoaXMuX3Byb3RlY3Rpb25MZXZlbClcbiAgICAgIC5kb25lKCgpID0+IHtcbiAgICAgICAgdGhpcy5fc2V0U3RyZWFtSGFuZGxlcnMoKVxuICAgICAgICB0aGlzLl9lbWl0KCdvcGVuJylcbiAgICAgIH0sIGUgPT4gdGhpcy5fZW1pdCgnZXJyb3InLCBlKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWF0ZSBSZWFkZXIgYW5kIFdyaXRlciBpbnRlcmZhY2VzIGZvciB0aGUgc29ja2V0XG4gICAqL1xuICBfc2V0U3RyZWFtSGFuZGxlcnMgKCkge1xuICAgIHRoaXMuX2RhdGFSZWFkZXIgPSBuZXcgV2luZG93cy5TdG9yYWdlLlN0cmVhbXMuRGF0YVJlYWRlcih0aGlzLl9zb2NrZXQuaW5wdXRTdHJlYW0pXG4gICAgdGhpcy5fZGF0YVJlYWRlci5pbnB1dFN0cmVhbU9wdGlvbnMgPSBXaW5kb3dzLlN0b3JhZ2UuU3RyZWFtcy5JbnB1dFN0cmVhbU9wdGlvbnMucGFydGlhbFxuXG4gICAgLy8gc2V0dXAgd3JpdGVyXG4gICAgdGhpcy5fZGF0YVdyaXRlciA9IG5ldyBXaW5kb3dzLlN0b3JhZ2UuU3RyZWFtcy5EYXRhV3JpdGVyKHRoaXMuX3NvY2tldC5vdXRwdXRTdHJlYW0pXG5cbiAgICAvLyBzdGFydCBieXRlIHJlYWRlciBsb29wXG4gICAgdGhpcy5fcmVhZCgpXG4gIH1cblxuICAvKipcbiAgICogRW1pdCBhbiBlcnJvciBhbmQgY2xvc2Ugc29ja2V0XG4gICAqXG4gICAqIEBwYXJhbSB7RXJyb3J9IGVycm9yIEVycm9yIG9iamVjdFxuICAgKi9cbiAgX2Vycm9ySGFuZGxlciAoZXJyb3IpIHtcbiAgICAvLyB3ZSBpZ25vcmUgZXJyb3JzIGFmdGVyIGNsb3NlIGhhcyBiZWVuIGNhbGxlZCwgc2luY2UgYWxsIGFib3J0ZWQgb3BlcmF0aW9uc1xuICAgIC8vIHdpbGwgZW1pdCB0aGVpciBlcnJvciBoYW5kbGVyc1xuICAgIC8vIHRoaXMgd2lsbCBhbHNvIGFwcGx5IHRvIHN0YXJ0dGxzIGFzIGEgcmVhZCBjYWxsIGlzIGFib3J0ZWQgYmVmb3JlIHVwZ3JhZGluZyB0aGUgc29ja2V0XG4gICAgaWYgKHRoaXMuX3VwZ3JhZGluZyB8fCAodGhpcy5yZWFkeVN0YXRlICE9PSAnY2xvc2luZycgJiYgdGhpcy5yZWFkeVN0YXRlICE9PSAnY2xvc2VkJykpIHtcbiAgICAgIHRoaXMuX2VtaXQoJ2Vycm9yJywgZXJyb3IpXG4gICAgICB0aGlzLmNsb3NlKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVhZCBhdmFpbGFibGUgYnl0ZXMgZnJvbSB0aGUgc29ja2V0LiBUaGlzIG1ldGhvZCBpcyByZWN1cnNpdmUgIG9uY2UgaXQgZW5kcywgaXQgcmVzdGFydHMgaXR0aGlzXG4gICAqL1xuICBfcmVhZCAoKSB7XG4gICAgaWYgKHRoaXMuX3VwZ3JhZGluZyB8fCAodGhpcy5yZWFkeVN0YXRlICE9PSAnb3BlbicgJiYgdGhpcy5yZWFkeVN0YXRlICE9PSAnY29ubmVjdGluZycpKSB7XG4gICAgICByZXR1cm4gLy8gZG8gbm90aGluZyBpZiBzb2NrZXQgbm90IG9wZW5cbiAgICB9XG5cbiAgICAvLyBSZWFkIHVwIHRvIDQwOTYgYnl0ZXMgZnJvbSB0aGUgc29ja2V0LiBUaGlzIGlzIG5vdCBhIGZpeGVkIG51bWJlciAodGhlIG1vZGUgd2FzIHNldFxuICAgIC8vIHdpdGggaW5wdXRTdHJlYW1PcHRpb25zLnBhcnRpYWwgcHJvcGVydHkpLCBzbyBpdCBtaWdodCByZXR1cm4gd2l0aCBhIHNtYWxsZXJcbiAgICAvLyBhbW91bnQgb2YgYnl0ZXMuXG4gICAgdGhpcy5fZGF0YVJlYWRlci5sb2FkQXN5bmMoNDA5NikuZG9uZShhdmFpbGFibGVCeXRlQ291bnQgPT4ge1xuICAgICAgaWYgKCFhdmFpbGFibGVCeXRlQ291bnQpIHtcbiAgICAgICAgLy8gbm8gYnl0ZXMgYXZhaWxhYmxlIGZvciByZWFkaW5nLCByZXN0YXJ0IHRoZSByZWFkaW5nIHByb2Nlc3NcbiAgICAgICAgcmV0dXJuIHNldEltbWVkaWF0ZSh0aGlzLl9yZWFkLmJpbmQodGhpcykpXG4gICAgICB9XG5cbiAgICAgIC8vIHdlIG5lZWQgYW4gVWludDhBcnJheSB0aGF0IGdldHMgZmlsbGVkIHdpdGggdGhlIGJ5dGVzIGZyb20gdGhlIGJ1ZmZlclxuICAgICAgdmFyIGRhdGEgPSBuZXcgVWludDhBcnJheShhdmFpbGFibGVCeXRlQ291bnQpXG4gICAgICB0aGlzLl9kYXRhUmVhZGVyLnJlYWRCeXRlcyhkYXRhKSAvLyBkYXRhIGFyZ3VtZW50IGdldHMgZmlsbGVkIHdpdGggdGhlIGJ5dGVzXG5cbiAgICAgIHRoaXMuX2VtaXQoJ2RhdGEnLCBkYXRhLmJ1ZmZlcilcblxuICAgICAgLy8gcmVzdGFydCByZWFkaW5nIHByb2Nlc3NcbiAgICAgIHJldHVybiBzZXRJbW1lZGlhdGUodGhpcy5fcmVhZC5iaW5kKHRoaXMpKVxuICAgIH0sIGUgPT4gdGhpcy5fZXJyb3JIYW5kbGVyKGUpKVxuICB9XG5cbiAgLy9cbiAgLy8gQVBJXG4gIC8vXG5cbiAgY2xvc2UgKCkge1xuICAgIHRoaXMucmVhZHlTdGF0ZSA9ICdjbG9zaW5nJ1xuXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuX3NvY2tldC5jbG9zZSgpXG4gICAgfSBjYXRjaCAoRSkge1xuICAgICAgdGhpcy5fZW1pdCgnZXJyb3InLCBFKVxuICAgIH1cblxuICAgIHNldEltbWVkaWF0ZSh0aGlzLl9lbWl0LmJpbmQodGhpcywgJ2Nsb3NlJykpXG4gIH1cblxuICBzZW5kIChkYXRhKSB7XG4gICAgaWYgKHRoaXMucmVhZHlTdGF0ZSAhPT0gJ29wZW4nKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAodGhpcy5fdXBncmFkaW5nKSB7XG4gICAgICB0aGlzLl91cGdyYWRlQ2FjaGUucHVzaChkYXRhKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gV3JpdGUgYnl0ZXMgdG8gYnVmZmVyXG4gICAgdGhpcy5fZGF0YVdyaXRlci53cml0ZUJ5dGVzKGRhdGEpXG5cbiAgICAvLyBFbWl0IGJ1ZmZlciBjb250ZW50c1xuICAgIHRoaXMuX2RhdGFXcml0ZXIuc3RvcmVBc3luYygpLmRvbmUoKCkgPT4gdGhpcy5fZW1pdCgnZHJhaW4nKSwgKGUpID0+IHRoaXMuX2Vycm9ySGFuZGxlcihlKSlcbiAgfVxuXG4gIHVwZ3JhZGVUb1NlY3VyZSAoKSB7XG4gICAgaWYgKHRoaXMuc3NsIHx8IHRoaXMuX3VwZ3JhZGluZykgcmV0dXJuXG5cbiAgICB0aGlzLl91cGdyYWRpbmcgPSB0cnVlXG4gICAgdHJ5IHtcbiAgICAgIC8vIHJlbGVhc2UgY3VycmVudCBpbnB1dCBzdHJlYW0uIHRoaXMgaXMgcmVxdWlyZWQgdG8gYWxsb3cgc29ja2V0IHVwZ3JhZGVcbiAgICAgIC8vIHdyaXRlIHN0cmVhbSBpcyBub3QgcmVsZWFzZWQgYXMgYWxsIHNlbmQgY2FsbHMgYXJlIGNhY2hlZCBmcm9tIHRoaXMgcG9pbnQgb253YXJkc1xuICAgICAgLy8gYW5kIG5vdCBwYXNzZWQgdG8gc29ja2V0IHVudGlsIHRoZSBzb2NrZXQgaXMgdXBncmFkZWRcbiAgICAgIHRoaXMuX2RhdGFSZWFkZXIuZGV0YWNoU3RyZWFtKClcbiAgICB9IGNhdGNoIChFKSB7IH1cblxuICAgIC8vIHVwZGF0ZSBwcm90ZWN0aW9uIGxldmVsXG4gICAgdGhpcy5fcHJvdGVjdGlvbkxldmVsID0gV2luZG93cy5OZXR3b3JraW5nLlNvY2tldHMuU29ja2V0UHJvdGVjdGlvbkxldmVsLnRsczEyXG5cbiAgICB0aGlzLl9zb2NrZXQudXBncmFkZVRvU3NsQXN5bmModGhpcy5fcHJvdGVjdGlvbkxldmVsLCB0aGlzLmhvc3QpLmRvbmUoXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHRoaXMuX3VwZ3JhZGluZyA9IGZhbHNlXG4gICAgICAgIHRoaXMuc3NsID0gdHJ1ZSAvLyBzZWN1cmVkIGNvbm5lY3Rpb24gZnJvbSBub3cgb25cblxuICAgICAgICB0aGlzLl9kYXRhUmVhZGVyID0gbmV3IFdpbmRvd3MuU3RvcmFnZS5TdHJlYW1zLkRhdGFSZWFkZXIodGhpcy5fc29ja2V0LmlucHV0U3RyZWFtKVxuICAgICAgICB0aGlzLl9kYXRhUmVhZGVyLmlucHV0U3RyZWFtT3B0aW9ucyA9IFdpbmRvd3MuU3RvcmFnZS5TdHJlYW1zLklucHV0U3RyZWFtT3B0aW9ucy5wYXJ0aWFsXG4gICAgICAgIHRoaXMuX3JlYWQoKVxuXG4gICAgICAgIC8vIGVtaXQgYWxsIGNhY2hlZCByZXF1ZXN0c1xuICAgICAgICB3aGlsZSAodGhpcy5fdXBncmFkZUNhY2hlLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLl91cGdyYWRlQ2FjaGUuc2hpZnQoKVxuICAgICAgICAgIHRoaXMuc2VuZChkYXRhKVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgKGUpID0+IHtcbiAgICAgICAgdGhpcy5fdXBncmFkaW5nID0gZmFsc2VcbiAgICAgICAgdGhpcy5fZXJyb3JIYW5kbGVyKGUpXG4gICAgICB9XG4gICAgKVxuICB9XG5cbiAgX2VtaXQgKHR5cGUsIGRhdGEpIHtcbiAgICBjb25zdCB0YXJnZXQgPSB0aGlzXG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlICdvcGVuJzpcbiAgICAgICAgdGhpcy5yZWFkeVN0YXRlID0gJ29wZW4nXG4gICAgICAgIHRoaXMub25vcGVuICYmIHRoaXMub25vcGVuKHsgdGFyZ2V0LCB0eXBlLCBkYXRhIH0pXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlICdlcnJvcic6XG4gICAgICAgIHRoaXMub25lcnJvciAmJiB0aGlzLm9uZXJyb3IoeyB0YXJnZXQsIHR5cGUsIGRhdGEgfSlcbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgJ2RhdGEnOlxuICAgICAgICB0aGlzLm9uZGF0YSAmJiB0aGlzLm9uZGF0YSh7IHRhcmdldCwgdHlwZSwgZGF0YSB9KVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSAnZHJhaW4nOlxuICAgICAgICB0aGlzLm9uZHJhaW4gJiYgdGhpcy5vbmRyYWluKHsgdGFyZ2V0LCB0eXBlLCBkYXRhIH0pXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlICdjbG9zZSc6XG4gICAgICAgIHRoaXMucmVhZHlTdGF0ZSA9ICdjbG9zZWQnXG4gICAgICAgIHRoaXMub25jbG9zZSAmJiB0aGlzLm9uY2xvc2UoeyB0YXJnZXQsIHR5cGUsIGRhdGEgfSlcbiAgICAgICAgYnJlYWtcbiAgICB9XG4gIH1cbn1cbiJdfQ==