UNPKG

24.2 kBJavaScriptView Raw
1'use strict';
2
3var _regenerator = require('babel-runtime/regenerator');
4
5var _regenerator2 = _interopRequireDefault(_regenerator);
6
7var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
8
9var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
10
11var _getIterator2 = require('babel-runtime/core-js/get-iterator');
12
13var _getIterator3 = _interopRequireDefault(_getIterator2);
14
15var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
16
17var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
18
19var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
20
21var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
22
23var _createClass2 = require('babel-runtime/helpers/createClass');
24
25var _createClass3 = _interopRequireDefault(_createClass2);
26
27function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
28
29var ChatServiceError = require('./ChatServiceError');
30var Promise = require('bluebird');
31var RedisAdapter = require('socket.io-redis');
32var SocketIOClusterBus = require('./SocketIOClusterBus');
33var SocketServer = require('socket.io');
34var _ = require('lodash');
35
36var _require = require('./utils');
37
38var run = _require.run;
39
40// Socket.io transport.
41
42var SocketIOTransport = function () {
43 function SocketIOTransport(server, options, adapterConstructor, adapterOptions) {
44 var _this = this;
45
46 (0, _classCallCheck3.default)(this, SocketIOTransport);
47
48 this.server = server;
49 this.options = options;
50 this.adapterConstructor = adapterConstructor;
51 this.adapterOptions = adapterOptions;
52 this.port = this.server.port;
53 this.io = this.options.io;
54 this.middleware = options.middleware;
55 this.namespace = this.options.namespace || '/chat-service';
56 var Adapter = function () {
57 switch (true) {
58 case _this.adapterConstructor === 'memory':
59 return null;
60 case _this.adapterConstructor === 'redis':
61 return RedisAdapter;
62 case _.isFunction(_this.adapterConstructor):
63 return _this.adapterConstructor;
64 default:
65 var c = _this.adapterConstructor;
66 throw new Error('Invalid transport adapter: ' + c);
67 }
68 }();
69 if (!this.io) {
70 this.ioOptions = this.options.ioOptions;
71 this.http = this.options.http;
72 if (this.http) {
73 this.dontCloseIO = true;
74 this.io = new SocketServer(this.options.http, this.ioOptions);
75 } else {
76 this.io = new SocketServer(this.port, this.ioOptions);
77 }
78 if (Adapter) {
79 this.adapter = new (Function.prototype.bind.apply(Adapter, [null].concat((0, _toConsumableArray3.default)(this.adapterOptions))))();
80 this.io.adapter(this.adapter);
81 }
82 } else {
83 this.dontCloseIO = true;
84 }
85 this.nsp = this.io.of(this.namespace);
86 this.server.io = this.io;
87 this.server.nsp = this.nsp;
88 this.clusterBus = new SocketIOClusterBus(this.server, this.nsp.adapter);
89 this.closed = false;
90 }
91
92 (0, _createClass3.default)(SocketIOTransport, [{
93 key: 'rejectLogin',
94 value: function rejectLogin(socket, error) {
95 error = this.server.convertError(error);
96 socket.emit('loginRejected', error);
97 socket.disconnect();
98 }
99 }, {
100 key: 'confirmLogin',
101 value: function confirmLogin(socket, userName, authData) {
102 authData.id = socket.id;
103 socket.emit('loginConfirmed', userName, authData);
104 }
105 }, {
106 key: 'ensureUserName',
107 value: function ensureUserName(socket, userName) {
108 return Promise.try(function () {
109 if (!userName) {
110 var query = socket.handshake.query;
111
112 userName = query && query.user;
113 if (!userName) {
114 return Promise.reject(new ChatServiceError('noLogin'));
115 }
116 }
117 return Promise.resolve(userName);
118 });
119 }
120 }, {
121 key: 'setEvents',
122 value: function setEvents() {
123 var _this2 = this;
124
125 if (this.middleware) {
126 var middleware = _.castArray(this.middleware);
127 var _iteratorNormalCompletion = true;
128 var _didIteratorError = false;
129 var _iteratorError = undefined;
130
131 try {
132 for (var _iterator = (0, _getIterator3.default)(middleware), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
133 var fn = _step.value;
134
135 this.nsp.use(fn);
136 }
137 } catch (err) {
138 _didIteratorError = true;
139 _iteratorError = err;
140 } finally {
141 try {
142 if (!_iteratorNormalCompletion && _iterator.return) {
143 _iterator.return();
144 }
145 } finally {
146 if (_didIteratorError) {
147 throw _iteratorError;
148 }
149 }
150 }
151 }
152 this.nsp.on('connection', function (socket) {
153 return run(_this2, _regenerator2.default.mark(function _callee() {
154 var id, _ref, _ref2, userName, _ref2$, authData;
155
156 return _regenerator2.default.wrap(function _callee$(_context) {
157 while (1) {
158 switch (_context.prev = _context.next) {
159 case 0:
160 id = socket.id;
161 _context.next = 3;
162 return this.server.onConnect(id);
163
164 case 3:
165 _ref = _context.sent;
166 _ref2 = (0, _slicedToArray3.default)(_ref, 2);
167 userName = _ref2[0];
168 _ref2$ = _ref2[1];
169 authData = _ref2$ === undefined ? {} : _ref2$;
170 _context.next = 10;
171 return this.ensureUserName(socket, userName);
172
173 case 10:
174 userName = _context.sent;
175 _context.next = 13;
176 return this.server.registerClient(userName, id);
177
178 case 13:
179 this.confirmLogin(socket, userName, authData);
180
181 case 14:
182 case 'end':
183 return _context.stop();
184 }
185 }
186 }, _callee, this);
187 })).catch(function (error) {
188 return _this2.rejectLogin(socket, error);
189 });
190 });
191 }
192 }, {
193 key: 'close',
194 value: function close() {
195 var _this3 = this;
196
197 this.closed = true;
198 this.nsp.removeAllListeners('connection');
199 this.clusterBus.removeAllListeners();
200 return Promise.try(function () {
201 if (!_this3.dontCloseIO) {
202 _this3.io.close();
203 } else if (_this3.http) {
204 _this3.io.engine.close();
205 } else {
206 var _iteratorNormalCompletion2 = true;
207 var _didIteratorError2 = false;
208 var _iteratorError2 = undefined;
209
210 try {
211 for (var _iterator2 = (0, _getIterator3.default)(_.toPairs(_this3.nsp.connected)), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
212 var _step2$value = (0, _slicedToArray3.default)(_step2.value, 2);
213
214 var socket = _step2$value[1];
215
216 socket.disconnect();
217 }
218 } catch (err) {
219 _didIteratorError2 = true;
220 _iteratorError2 = err;
221 } finally {
222 try {
223 if (!_iteratorNormalCompletion2 && _iterator2.return) {
224 _iterator2.return();
225 }
226 } finally {
227 if (_didIteratorError2) {
228 throw _iteratorError2;
229 }
230 }
231 }
232 }
233 return Promise.resolve();
234 });
235 }
236 }, {
237 key: 'bindHandler',
238 value: function bindHandler(id, name, fn) {
239 var socket = this.getSocket(id);
240 if (socket) {
241 socket.on(name, fn);
242 }
243 }
244 }, {
245 key: 'getServer',
246 value: function getServer() {
247 return this.io;
248 }
249 }, {
250 key: 'getSocket',
251 value: function getSocket(id) {
252 return this.nsp.connected[id];
253 }
254 }, {
255 key: 'emitToChannel',
256 value: function emitToChannel(channel, eventName) {
257 var _nsp$to;
258
259 for (var _len = arguments.length, eventData = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
260 eventData[_key - 2] = arguments[_key];
261 }
262
263 (_nsp$to = this.nsp.to(channel)).emit.apply(_nsp$to, [eventName].concat(eventData));
264 }
265 }, {
266 key: 'sendToChannel',
267 value: function sendToChannel(id, channel, eventName) {
268 var socket = this.getSocket(id);
269
270 for (var _len2 = arguments.length, eventData = Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) {
271 eventData[_key2 - 3] = arguments[_key2];
272 }
273
274 if (!socket) {
275 this.emitToChannel.apply(this, [channel, eventName].concat(eventData));
276 } else {
277 var _socket$to;
278
279 (_socket$to = socket.to(channel)).emit.apply(_socket$to, [eventName].concat(eventData));
280 }
281 }
282 }, {
283 key: 'getHandshakeData',
284 value: function getHandshakeData(id) {
285 var res = { isConnected: false, query: {}, headers: {} };
286 var socket = this.getSocket(id);
287 if (!socket) {
288 return res;
289 }
290 res.isConnected = true;
291 res.query = socket.handshake.query;
292 res.headers = socket.handshake.headers;
293 return res;
294 }
295 }, {
296 key: 'joinChannel',
297 value: function joinChannel(id, channel) {
298 var socket = this.getSocket(id);
299 if (!socket) {
300 return Promise.reject(new ChatServiceError('invalidSocket', id));
301 } else {
302 return Promise.fromCallback(function (fn) {
303 return socket.join(channel, fn);
304 });
305 }
306 }
307 }, {
308 key: 'leaveChannel',
309 value: function leaveChannel(id, channel) {
310 var socket = this.getSocket(id);
311 if (!socket) {
312 return Promise.resolve();
313 }
314 return Promise.fromCallback(function (fn) {
315 return socket.leave(channel, fn);
316 });
317 }
318 }, {
319 key: 'disconnectSocket',
320 value: function disconnectSocket(id) {
321 var socket = this.getSocket(id);
322 if (socket) {
323 socket.disconnect();
324 }
325 return Promise.resolve();
326 }
327 }]);
328 return SocketIOTransport;
329}();
330
331module.exports = SocketIOTransport;
332//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Tb2NrZXRJT1RyYW5zcG9ydC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLElBQU0sbUJBQW1CLFFBQVEsb0JBQVIsQ0FBekI7QUFDQSxJQUFNLFVBQVUsUUFBUSxVQUFSLENBQWhCO0FBQ0EsSUFBTSxlQUFlLFFBQVEsaUJBQVIsQ0FBckI7QUFDQSxJQUFNLHFCQUFxQixRQUFRLHNCQUFSLENBQTNCO0FBQ0EsSUFBTSxlQUFlLFFBQVEsV0FBUixDQUFyQjtBQUNBLElBQU0sSUFBSSxRQUFRLFFBQVIsQ0FBVjs7ZUFDZ0IsUUFBUSxTQUFSLEM7O0lBQVIsRyxZQUFBLEc7O0FBRVI7O0lBQ00saUI7QUFFSiw2QkFBYSxNQUFiLEVBQXFCLE9BQXJCLEVBQThCLGtCQUE5QixFQUFrRCxjQUFsRCxFQUFrRTtBQUFBOztBQUFBOztBQUNoRSxTQUFLLE1BQUwsR0FBYyxNQUFkO0FBQ0EsU0FBSyxPQUFMLEdBQWUsT0FBZjtBQUNBLFNBQUssa0JBQUwsR0FBMEIsa0JBQTFCO0FBQ0EsU0FBSyxjQUFMLEdBQXNCLGNBQXRCO0FBQ0EsU0FBSyxJQUFMLEdBQVksS0FBSyxNQUFMLENBQVksSUFBeEI7QUFDQSxTQUFLLEVBQUwsR0FBVSxLQUFLLE9BQUwsQ0FBYSxFQUF2QjtBQUNBLFNBQUssVUFBTCxHQUFrQixRQUFRLFVBQTFCO0FBQ0EsU0FBSyxTQUFMLEdBQWlCLEtBQUssT0FBTCxDQUFhLFNBQWIsSUFBMEIsZUFBM0M7QUFDQSxRQUFJLFVBQVcsWUFBTTtBQUNuQixjQUFRLElBQVI7QUFDRSxhQUFLLE1BQUssa0JBQUwsS0FBNEIsUUFBakM7QUFDRSxpQkFBTyxJQUFQO0FBQ0YsYUFBSyxNQUFLLGtCQUFMLEtBQTRCLE9BQWpDO0FBQ0UsaUJBQU8sWUFBUDtBQUNGLGFBQUssRUFBRSxVQUFGLENBQWEsTUFBSyxrQkFBbEIsQ0FBTDtBQUNFLGlCQUFPLE1BQUssa0JBQVo7QUFDRjtB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QUosR0FBWSxPQUFPLFNBQVAsQ0FBaUIsS0FBN0I7QUFDQSxVQUFJLE9BQUosR0FBYyxPQUFPLFNBQVAsQ0FBaUIsT0FBL0I7QUFDQSxhQUFPLEdBQVA7QUFDRDs7O2dDQUVZLEUsRUFBSSxPLEVBQVM7QUFDeEIsVUFBSSxTQUFTLEtBQUssU0FBTCxDQUFlLEVBQWYsQ0FBYjtBQUNBLFVBQUksQ0FBQyxNQUFMLEVBQWE7QUFDWCxlQUFPLFFBQVEsTUFBUixDQUFlLElBQUksZ0JBQUosQ0FBcUIsZUFBckIsRUFBc0MsRUFBdEMsQ0FBZixDQUFQO0FBQ0QsT0FGRCxNQUVPO0FBQ0wsZUFBTyxRQUFRLFlBQVIsQ0FBcUI7QUFBQSxpQkFBTSxPQUFPLElBQVAsQ0FBWSxPQUFaLEVBQXFCLEVBQXJCLENBQU47QUFBQSxTQUFyQixDQUFQO0FBQ0Q7QUFDRjs7O2lDQUVhLEUsRUFBSSxPLEVBQVM7QUFDekIsVUFBSSxTQUFTLEtBQUssU0FBTCxDQUFlLEVBQWYsQ0FBYjtBQUNBLFVBQUksQ0FBQyxNQUFMLEVBQWE7QUFBRSxlQUFPLFFBQVEsT0FBUixFQUFQO0FBQTBCO0FBQ3pDLGFBQU8sUUFBUSxZQUFSLENBQXFCO0FBQUEsZUFBTSxPQUFPLEtBQVAsQ0FBYSxPQUFiLEVBQXNCLEVBQXRCLENBQU47QUFBQSxPQUFyQixDQUFQO0FBQ0Q7OztxQ0FFaUIsRSxFQUFJO0FBQ3BCLFVBQUksU0FBUyxLQUFLLFNBQUwsQ0FBZSxFQUFmLENBQWI7QUFDQSxVQUFJLE1BQUosRUFBWTtBQUNWLGVBQU8sVUFBUDtBQUNEO0FBQ0QsYUFBTyxRQUFRLE9BQVIsRUFBUDtBQUNEOzs7OztBQUlILE9BQU8sT0FBUCxHQUFpQixpQkFBakIiLCJmaWxlIjoiU29ja2V0SU9UcmFuc3BvcnQuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCdcblxuY29uc3QgQ2hhdFNlcnZpY2VFcnJvciA9IHJlcXVpcmUoJy4vQ2hhdFNlcnZpY2VFcnJvcicpXG5jb25zdCBQcm9taXNlID0gcmVxdWlyZSgnYmx1ZWJpcmQnKVxuY29uc3QgUmVkaXNBZGFwdGVyID0gcmVxdWlyZSgnc29ja2V0LmlvLXJlZGlzJylcbmNvbnN0IFNvY2tldElPQ2x1c3RlckJ1cyA9IHJlcXVpcmUoJy4vU29ja2V0SU9DbHVzdGVyQnVzJylcbmNvbnN0IFNvY2tldFNlcnZlciA9IHJlcXVpcmUoJ3NvY2tldC5pbycpXG5jb25zdCBfID0gcmVxdWlyZSgnbG9kYXNoJylcbmNvbnN0IHsgcnVuIH0gPSByZXF1aXJlKCcuL3V0aWxzJylcblxuLy8gU29ja2V0LmlvIHRyYW5zcG9ydC5cbmNsYXNzIFNvY2tldElPVHJhbnNwb3J0IHtcblxuICBjb25zdHJ1Y3RvciAoc2VydmVyLCBvcHRpb25zLCBhZGFwdGVyQ29uc3RydWN0b3IsIGFkYXB0ZXJPcHRpb25zKSB7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXJcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zXG4gICAgdGhpcy5hZGFwdGVyQ29uc3RydWN0b3IgPSBhZGFwdGVyQ29uc3RydWN0b3JcbiAgICB0aGlzLmFkYXB0ZXJPcHRpb25zID0gYWRhcHRlck9wdGlvbnNcbiAgICB0aGlzLnBvcnQgPSB0aGlzLnNlcnZlci5wb3J0XG4gICAgdGhpcy5pbyA9IHRoaXMub3B0aW9ucy5pb1xuICAgIHRoaXMubWlkZGxld2FyZSA9IG9wdGlvbnMubWlkZGxld2FyZVxuICAgIHRoaXMubmFtZXNwYWNlID0gdGhpcy5vcHRpb25zLm5hbWVzcGFjZSB8fCAnL2NoYXQtc2VydmljZSdcbiAgICBsZXQgQWRhcHRlciA9ICgoKSA9PiB7XG4gICAgICBzd2l0Y2ggKHRydWUpIHtcbiAgICAgICAgY2FzZSB0aGlzLmFkYXB0ZXJDb25zdHJ1Y3RvciA9PT0gJ21lbW9yeSc6XG4gICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgY2FzZSB0aGlzLmFkYXB0ZXJDb25zdHJ1Y3RvciA9PT0gJ3JlZGlzJzpcbiAgICAgICAgICByZXR1cm4gUmVkaXNBZGFwdGVyXG4gICAgICAgIGNhc2UgXy5pc0Z1bmN0aW9uKHRoaXMuYWRhcHRlckNvbnN0cnVjdG9yKTpcbiAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyQ29uc3RydWN0b3JcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBsZXQgYyA9IHRoaXMuYWRhcHRlckNvbnN0cnVjdG9yXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHRyYW5zcG9ydCBhZGFwdGVyOiAke2N9YClcbiAgICAgIH1cbiAgICB9KSgpXG4gICAgaWYgKCF0aGlzLmlvKSB7XG4gICAgICB0aGlzLmlvT3B0aW9ucyA9IHRoaXMub3B0aW9ucy5pb09wdGlvbnNcbiAgICAgIHRoaXMuaHR0cCA9IHRoaXMub3B0aW9ucy5odHRwXG4gICAgICBpZiAodGhpcy5odHRwKSB7XG4gICAgICAgIHRoaXMuZG9udENsb3NlSU8gPSB0cnVlXG4gICAgICAgIHRoaXMuaW8gPSBuZXcgU29ja2V0U2VydmVyKHRoaXMub3B0aW9ucy5odHRwLCB0aGlzLmlvT3B0aW9ucylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaW8gPSBuZXcgU29ja2V0U2VydmVyKHRoaXMucG9ydCwgdGhpcy5pb09wdGlvbnMpXG4gICAgICB9XG4gICAgICBpZiAoQWRhcHRlcikge1xuICAgICAgICB0aGlzLmFkYXB0ZXIgPSBuZXcgQWRhcHRlciguLi50aGlzLmFkYXB0ZXJPcHRpb25zKVxuICAgICAgICB0aGlzLmlvLmFkYXB0ZXIodGhpcy5hZGFwdGVyKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmRvbnRDbG9zZUlPID0gdHJ1ZVxuICAgIH1cbiAgICB0aGlzLm5zcCA9IHRoaXMuaW8ub2YodGhpcy5uYW1lc3BhY2UpXG4gICAgdGhpcy5zZXJ2ZXIuaW8gPSB0aGlzLmlvXG4gICAgdGhpcy5zZXJ2ZXIubnNwID0gdGhpcy5uc3BcbiAgICB0aGlzLmNsdXN0ZXJCdXMgPSBuZXcgU29ja2V0SU9DbHVzdGVyQnVzKHRoaXMuc2VydmVyLCB0aGlzLm5zcC5hZGFwdGVyKVxuICAgIHRoaXMuY2xvc2VkID0gZmFsc2VcbiAgfVxuXG4gIHJlamVjdExvZ2luIChzb2NrZXQsIGVycm9yKSB7XG4gICAgZXJyb3IgPSB0aGlzLnNlcnZlci5jb252ZXJ0RXJyb3IoZXJyb3IpXG4gICAgc29ja2V0LmVtaXQoJ2xvZ2luUmVqZWN0ZWQnLCBlcnJvcilcbiAgICBzb2NrZXQuZGlzY29ubmVjdCgpXG4gIH1cblxuICBjb25maXJtTG9naW4gKHNvY2tldCwgdXNlck5hbWUsIGF1dGhEYXRhKSB7XG4gICAgYXV0aERhdGEuaWQgPSBzb2NrZXQuaWRcbiAgICBzb2NrZXQuZW1pdCgnbG9naW5Db25maXJtZWQnLCB1c2VyTmFtZSwgYXV0aERhdGEpXG4gIH1cblxuICBlbnN1cmVVc2VyTmFtZSAoc29ja2V0LCB1c2VyTmFtZSkge1xuICAgIHJldHVybiBQcm9taXNlLnRyeSgoKSA9PiB7XG4gICAgICBpZiAoIXVzZXJOYW1lKSB7XG4gICAgICAgIGxldCB7IHF1ZXJ5IH0gPSBzb2NrZXQuaGFuZHNoYWtlXG4gICAgICAgIHVzZXJOYW1lID0gcXVlcnkgJiYgcXVlcnkudXNlclxuICAgICAgICBpZiAoIXVzZXJOYW1lKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBDaGF0U2VydmljZUVycm9yKCdub0xvZ2luJykpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodXNlck5hbWUpXG4gICAgfSlcbiAgfVxuXG4gIHNldEV2ZW50cyAoKSB7XG4gICAgaWYgKHRoaXMubWlkZGxld2FyZSkge1xuICAgICAgbGV0IG1pZGRsZXdhcmUgPSBfLmNhc3RBcnJheSh0aGlzLm1pZGRsZXdhcmUpXG4gICAgICBmb3IgKGxldCBmbiBvZiBtaWRkbGV3YXJlKSB7XG4gICAgICAgIHRoaXMubnNwLnVzZShmbilcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5uc3Aub24oJ2Nvbm5lY3Rpb24nLCBzb2NrZXQgPT4ge1xuICAgICAgcmV0dXJuIHJ1bih0aGlzLCBmdW5jdGlvbiAqICgpIHtcbiAgICAgICAgbGV0IGlkID0gc29ja2V0LmlkXG4gICAgICAgIGxldCBbdXNlck5hbWUsIGF1dGhEYXRhID0ge31dID0geWllbGQgdGhpcy5zZXJ2ZXIub25Db25uZWN0KGlkKVxuICAgICAgICB1c2VyTmFtZSA9IHlpZWxkIHRoaXMuZW5zdXJlVXNlck5hbWUoc29ja2V0LCB1c2VyTmFtZSlcbiAgICAgICAgeWllbGQgdGhpcy5zZXJ2ZXIucmVnaXN0ZXJDbGllbnQodXNlck5hbWUsIGlkKVxuICAgICAgICB0aGlzLmNvbmZpcm1Mb2dpbihzb2NrZXQsIHVzZXJOYW1lLCBhdXRoRGF0YSlcbiAgICAgIH0pLmNhdGNoKGVycm9yID0+IHRoaXMucmVqZWN0TG9naW4oc29ja2V0LCBlcnJvcikpXG4gICAgfSlcbiAgfVxuXG4gIGNsb3NlICgpIHtcbiAgICB0aGlzLmNsb3NlZCA9IHRydWVcbiAgICB0aGlzLm5zcC5yZW1vdmVBbGxMaXN0ZW5lcnMoJ2Nvbm5lY3Rpb24nKVxuICAgIHRoaXMuY2x1c3RlckJ1cy5yZW1vdmVBbGxMaXN0ZW5lcnMoKVxuICAgIHJldHVybiBQcm9taXNlLnRyeSgoKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuZG9udENsb3NlSU8pIHtcbiAgICAgICAgdGhpcy5pby5jbG9zZSgpXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuaHR0cCkge1xuICAgICAgICB0aGlzLmlvLmVuZ2luZS5jbG9zZSgpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3IgKGxldCBbLCBzb2NrZXRdIG9mIF8udG9QYWlycyh0aGlzLm5zcC5jb25uZWN0ZWQpKSB7XG4gICAgICAgICAgc29ja2V0LmRpc2Nvbm5lY3QoKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICB9KVxuICB9XG5cbiAgYmluZEhhbmRsZXIgKGlkLCBuYW1lLCBmbikge1xuICAgIGxldCBzb2NrZXQgPSB0aGlzLmdldFNvY2tldChpZClcbiAgICBpZiAoc29ja2V0KSB7XG4gICAgICBzb2NrZXQub24obmFtZSwgZm4pXG4gICAgfVxuICB9XG5cbiAgZ2V0U2VydmVyICgpIHtcbiAgICByZXR1cm4gdGhpcy5pb1xuICB9XG5cbiAgZ2V0U29ja2V0IChpZCkge1xuICAgIHJldHVybiB0aGlzLm5zcC5jb25uZWN0ZWRbaWRdXG4gIH1cblxuICBlbWl0VG9DaGFubmVsIChjaGFubmVsLCBldmVudE5hbWUsIC4uLmV2ZW50RGF0YSkge1xuICAgIHRoaXMubnNwLnRvKGNoYW5uZWwpLmVtaXQoZXZlbnROYW1lLCAuLi5ldmVudERhdGEpXG4gIH1cblxuICBzZW5kVG9DaGFubmVsIChpZCwgY2hhbm5lbCwgZXZlbnROYW1lLCAuLi5ldmVudERhdGEpIHtcbiAgICBsZXQgc29ja2V0ID0gdGhpcy5nZXRTb2NrZXQoaWQpXG4gICAgaWYgKCFzb2NrZXQpIHtcbiAgICAgIHRoaXMuZW1pdFRvQ2hhbm5lbChjaGFubmVsLCBldmVudE5hbWUsIC4uLmV2ZW50RGF0YSlcbiAgICB9IGVsc2Uge1xuICAgICAgc29ja2V0LnRvKGNoYW5uZWwpLmVtaXQoZXZlbnROYW1lLCAuLi5ldmVudERhdGEpXG4gICAgfVxuICB9XG5cbiAgZ2V0SGFuZHNoYWtlRGF0YSAoaWQpIHtcbiAgICBsZXQgcmVzID0geyBpc0Nvbm5lY3RlZDogZmFsc2UsIHF1ZXJ5OiB7fSwgaGVhZGVyczoge30gfVxuICAgIGxldCBzb2NrZXQgPSB0aGlzLmdldFNvY2tldChpZClcbiAgICBpZiAoIXNvY2tldCkgeyByZXR1cm4gcmVzIH1cbiAgICByZXMuaXNDb25uZWN0ZWQgPSB0cnVlXG4gICAgcmVzLnF1ZXJ5ID0gc29ja2V0LmhhbmRzaGFrZS5xdWVyeVxuICAgIHJlcy5oZWFkZXJzID0gc29ja2V0LmhhbmRzaGFrZS5oZWFkZXJzXG4gICAgcmV0dXJuIHJlc1xuICB9XG5cbiAgam9pbkNoYW5uZWwgKGlkLCBjaGFubmVsKSB7XG4gICAgbGV0IHNvY2tldCA9IHRoaXMuZ2V0U29ja2V0KGlkKVxuICAgIGlmICghc29ja2V0KSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IENoYXRTZXJ2aWNlRXJyb3IoJ2ludmFsaWRTb2NrZXQnLCBpZCkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBQcm9taXNlLmZyb21DYWxsYmFjayhmbiA9PiBzb2NrZXQuam9pbihjaGFubmVsLCBmbikpXG4gICAgfVxuICB9XG5cbiAgbGVhdmVDaGFubmVsIChpZCwgY2hhbm5lbCkge1xuICAgIGxldCBzb2NrZXQgPSB0aGlzLmdldFNvY2tldChpZClcbiAgICBpZiAoIXNvY2tldCkgeyByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkgfVxuICAgIHJldHVybiBQcm9taXNlLmZyb21DYWxsYmFjayhmbiA9PiBzb2NrZXQubGVhdmUoY2hhbm5lbCwgZm4pKVxuICB9XG5cbiAgZGlzY29ubmVjdFNvY2tldCAoaWQpIHtcbiAgICBsZXQgc29ja2V0ID0gdGhpcy5nZXRTb2NrZXQoaWQpXG4gICAgaWYgKHNvY2tldCkge1xuICAgICAgc29ja2V0LmRpc2Nvbm5lY3QoKVxuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgfVxuXG59XG5cbm1vZHVsZS5leHBvcnRzID0gU29ja2V0SU9UcmFuc3BvcnRcbiJdfQ==
\No newline at end of file