File size: 22,587 Bytes
f9f1a35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
"use strict";
/*
 * Copyright 2020 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DapServer = void 0;
var childProcess = require("child_process");
var crypto = require("crypto");
var net = require("net");
var ws_1 = require("ws");
var jsonRpc = require("./json_rpc");
var logging = require("./logging");
var sockets_1 = require("./sockets");
var sessionCounter = 0;
/** Socket<->debug adapter. */
var Session = /** @class */ (function () {
    function Session(clientSocket, domainSocketPath) {
        var _this = this;
        this.clientSocket = clientSocket;
        this.id = sessionCounter++;
        this.clientSocket.onClose(function (reason) {
            logging.getLogger().debug('DAP socket disconnected for session %d reason: %s', _this.id, reason);
            // Handle client disconnects to close sockets, so as to free up resources.
            _this.close();
        });
        this.connect(domainSocketPath);
    }
    Session.prototype.close = function () {
        if (this.dapSocket) {
            this.dapSocket.destroy();
        }
        this.clientSocket.close(true);
    };
    Session.prototype.connect = function (domainSocketPath) {
        return __awaiter(this, void 0, Promise, function () {
            var rpc_1, dapSocket_1, message, error_1;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _a.trys.push([0, 2, , 3]);
                        logging.getLogger().info('DAP creating Socket to %s for session %d', domainSocketPath, this.id);
                        rpc_1 = new jsonRpc.JsonRpcReader(function (dapMessage) {
                            var message = { data: jsonRpc.encodeJsonRpc(dapMessage.content) };
                            _this.clientSocket.sendString(JSON.stringify(message));
                        });
                        dapSocket_1 = new net.Socket();
                        this.dapSocket = dapSocket_1;
                        dapSocket_1.on('data', function (data) {
                            rpc_1.append(data);
                        });
                        dapSocket_1.on('close', function () {
                            _this.close();
                        });
                        return [4 /*yield*/, new Promise(function (resolve, reject) {
                                dapSocket_1.on('error', reject);
                                dapSocket_1.connect(domainSocketPath, resolve);
                            })];
                    case 1:
                        _a.sent();
                        message = { open: true };
                        this.clientSocket.sendString(JSON.stringify(message));
                        this.clientSocket.onBinaryMessage(function (data) {
                            dapSocket_1.write(Uint8Array.from(data));
                        });
                        this.clientSocket.onStringMessage(function (data) {
                            dapSocket_1.write(data);
                        });
                        return [3 /*break*/, 3];
                    case 2:
                        error_1 = _a.sent();
                        logging.getLogger().error('Error connecting to Debug Adapter: %s', error_1);
                        this.close();
                        return [3 /*break*/, 3];
                    case 3: return [2 /*return*/];
                }
            });
        });
    };
    return Session;
}());
/** Debug Adapter Protocol server. */
var DapServer = /** @class */ (function () {
    function DapServer(muxBinary, server) {
        var _this = this;
        this.portPromise = this.spawnMultiplexer(muxBinary);
        server === null || server === void 0 ? void 0 : server.of('/debugger').on('connection', function (socket) {
            _this.portPromise.then(function (domainSocketPath) {
                // Session manages its own lifetime.
                // tslint:disable-next-line:no-unused-expression
                new Session(new sockets_1.SocketIOAdapter(socket), domainSocketPath);
            });
        });
    }
    DapServer.prototype.handleUpgrade = function (request, sock, head) {
        var _this = this;
        new ws_1.Server({ noServer: true }).handleUpgrade(request, sock, head, function (ws) {
            _this.portPromise.then(function (domainSocketPath) {
                // Session manages its own lifetime.
                // tslint:disable-next-line:no-unused-expression
                new Session(new sockets_1.WebSocketAdapter(ws), domainSocketPath);
            });
        });
    };
    DapServer.prototype.spawnMultiplexer = function (muxBinary) {
        return __awaiter(this, void 0, Promise, function () {
            var filename, muxProcess, muxOutput;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        filename = "/tmp/debugger_".concat(crypto.randomBytes(6).readUIntLE(0, 6).toString(36));
                        muxProcess = childProcess.spawn(muxBinary, [
                            "--domain_socket_path=".concat(filename),
                        ]);
                        muxProcess.stdout.on('data', function (data) {
                            logging.getLogger().info('%s: %s', muxBinary, data);
                        });
                        muxProcess.stdout.on('error', function (data) {
                            logging.getLogger().info('%s: %s', muxBinary, data);
                        });
                        muxOutput = '';
                        return [4 /*yield*/, new Promise(function (resolve, reject) {
                                var connectionHandler = function (data) {
                                    muxOutput += data;
                                    // Wait for the process to indicate that it is listening.
                                    if (muxOutput.match(/Listening on /)) {
                                        muxProcess.stdout.off('data', connectionHandler);
                                        resolve();
                                    }
                                };
                                muxProcess.stdout.on('data', connectionHandler);
                                muxProcess.stdout.on('error', reject);
                            })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, filename];
                }
            });
        });
    };
    return DapServer;
}());
exports.DapServer = DapServer;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja2V0aW9fdG9fZGFwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGhpcmRfcGFydHkvY29sYWIvc291cmNlcy9zb2NrZXRpb190b19kYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFSCw0Q0FBOEM7QUFDOUMsK0JBQWlDO0FBRWpDLHlCQUEyQjtBQUkzQix5QkFBMEI7QUFFMUIsb0NBQXNDO0FBQ3RDLG1DQUFxQztBQUNyQyxxQ0FBb0U7QUFFcEUsSUFBSSxjQUFjLEdBQUcsQ0FBQyxDQUFDO0FBRXZCLDhCQUE4QjtBQUM5QjtJQUlFLGlCQUE2QixZQUFvQixFQUFFLGdCQUF3QjtRQUEzRSxpQkFZQztRQVo0QixpQkFBWSxHQUFaLFlBQVksQ0FBUTtRQUMvQyxJQUFJLENBQUMsRUFBRSxHQUFHLGNBQWMsRUFBRSxDQUFDO1FBRTNCLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLFVBQUMsTUFBTTtZQUMvQixPQUFPLENBQUMsU0FBUyxFQUFFLENBQUMsS0FBSyxDQUNyQixtREFBbUQsRUFBRSxLQUFJLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBRTFFLDBFQUEwRTtZQUMxRSxLQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDZixDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRU8sdUJBQUssR0FBYjtRQUNFLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDM0IsQ0FBQztRQUNELElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFYSx5QkFBTyxHQUFy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QUFDO3dCQUNuQixxQkFBTSxJQUFJLE9BQU8sQ0FBTyxVQUFDLE9BQU8sRUFBRSxNQUFNO2dDQUN0QyxJQUFNLGlCQUFpQixHQUFHLFVBQUMsSUFBWTtvQ0FDckMsU0FBUyxJQUFJLElBQUksQ0FBQztvQ0FDbEIseURBQXlEO29DQUN6RCxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQzt3Q0FDckMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLGlCQUFpQixDQUFDLENBQUM7d0NBQ2pELE9BQU8sRUFBRSxDQUFDO29DQUNaLENBQUM7Z0NBQ0gsQ0FBQyxDQUFDO2dDQUNGLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO2dDQUNoRCxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7NEJBQ3hDLENBQUMsQ0FBQyxFQUFBOzt3QkFYRixTQVdFLENBQUM7d0JBQ0gsc0JBQU8sUUFBUSxFQUFDOzs7O0tBQ2pCO0lBQ0gsZ0JBQUM7QUFBRCxDQUFDLEFBckRELElBcURDO0FBckRZLDhCQUFTIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3RcbiAqIHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mXG4gKiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVFxuICogV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlXG4gKiBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9ucyB1bmRlclxuICogdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0ICogYXMgY2hpbGRQcm9jZXNzIGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgKiBhcyBodHRwIGZyb20gJ2h0dHAnO1xuaW1wb3J0ICogYXMgbmV0IGZyb20gJ25ldCc7XG4vLyBUaGUgdW51c3VhbCBjYXNpbmcgaXMgZnJvbSB1cHN0cmVhbSBTb2NrZXRJTy5cbi8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTplbmZvcmNlLW5hbWUtY2FzaW5nXG5pbXBvcnQgKiBhcyBTb2NrZXRJTyBmcm9tICdzb2NrZXQuaW8nO1xuaW1wb3J0IHtTZXJ2ZXJ9IGZyb20gJ3dzJztcblxuaW1wb3J0ICogYXMganNvblJwYyBmcm9tICcuL2pzb25fcnBjJztcbmltcG9ydCAqIGFzIGxvZ2dpbmcgZnJvbSAnLi9sb2dnaW5nJztcbmltcG9ydCB7U29ja2V0LCBTb2NrZXRJT0FkYXB0ZXIsIFdlYlNvY2tldEFkYXB0ZXJ9IGZyb20gJy4vc29ja2V0cyc7XG5cbmxldCBzZXNzaW9uQ291bnRlciA9IDA7XG5cbi8qKiBTb2NrZXQ8LT5kZWJ1ZyBhZGFwdGVyLiAqL1xuY2xhc3MgU2Vzc2lvbiB7XG4gIHByaXZhdGUgcmVhZG9ubHkgaWQ6IG51bWJlcjtcbiAgcHJpdmF0ZSBkYXBTb2NrZXQ/OiBuZXQuU29ja2V0O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgY2xpZW50U29ja2V0OiBTb2NrZXQsIGRvbWFpblNvY2tldFBhdGg6IHN0cmluZykge1xuICAgIHRoaXMuaWQgPSBzZXNzaW9uQ291bnRlcisrO1xuXG4gICAgdGhpcy5jbGllbnRTb2NrZXQub25DbG9zZSgocmVhc29uKSA9PiB7XG4gICAgICBsb2dnaW5nLmdldExvZ2dlcigpLmRlYnVnKFxuICAgICAgICAgICdEQVAgc29ja2V0IGRpc2Nvbm5lY3RlZCBmb3Igc2Vzc2lvbiAlZCByZWFzb246ICVzJywgdGhpcy5pZCwgcmVhc29uKTtcblxuICAgICAgLy8gSGFuZGxlIGNsaWVudCBkaXNjb25uZWN0cyB0byBjbG9zZSBzb2NrZXRzLCBzbyBhcyB0byBmcmVlIHVwIHJlc291cmNlcy5cbiAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuY29ubmVjdChkb21haW5Tb2NrZXRQYXRoKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xvc2UoKSB7XG4gICAgaWYgKHRoaXMuZGFwU29ja2V0KSB7XG4gICAgICB0aGlzLmRhcFNvY2tldC5kZXN0cm95KCk7XG4gICAgfVxuICAgIHRoaXMuY2xpZW50U29ja2V0LmNsb3NlKHRydWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjb25uZWN0KGRvbWFpblNvY2tldFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBsb2dnaW5nLmdldExvZ2dlcigpLmluZm8oXG4gICAgICAgICAgJ0RBUCBjcmVhdGluZyBTb2NrZXQgdG8gJXMgZm9yIHNlc3Npb24gJWQnLCBkb21haW5Tb2NrZXRQYXRoLFxuICAgICAgICAgIHRoaXMuaWQpO1xuXG4gICAgICBjb25zdCBycGMgPSBuZXcganNvblJwYy5Kc29uUnBjUmVhZGVyKChkYXBNZXNzYWdlKSA9PiB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2U6XG4gICAgICAgICAgICBPdXRnb2luZ01lc3NhZ2UgPSB7ZGF0YToganNvblJwYy5lbmNvZGVKc29uUnBjKGRhcE1lc3NhZ2UuY29udGVudCl9O1xuICAgICAgICB0aGlzLmNsaWVudFNvY2tldC5zZW5kU3RyaW5nKEpTT04uc3RyaW5naWZ5KG1lc3NhZ2UpKTtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBkYXBTb2NrZXQgPSBuZXcgbmV0LlNvY2tldCgpO1xuICAgICAgdGhpcy5kYXBTb2NrZXQgPSBkYXBTb2NrZXQ7XG4gICAgICBkYXBTb2NrZXQub24oJ2RhdGEnLCAoZGF0YTogQnVmZmVyKSA9PiB7XG4gICAgICAgIHJwYy5hcHBlbmQoZGF0YSk7XG4gICAgICB9KTtcbiAgICAgIGRhcFNvY2tldC5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBkYXBTb2NrZXQub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgICAgZGFwU29ja2V0LmNvbm5lY3QoZG9tYWluU29ja2V0UGF0aCwgcmVzb2x2ZSk7XG4gICAgICB9KTtcblxuICAgICAgLy8gTm90aWZ5IHRoZSBjbGllbnQgdGhhdCB0aGUgY29ubmVjdGlvbi5pcyBub3cgb3Blbi5cbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE91dGdvaW5nTWVzc2FnZSA9IHtvcGVuOiB0cnVlfTtcbiAgICAgIHRoaXMuY2xpZW50U29ja2V0LnNlbmRTdHJpbmcoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSkpO1xuICAgICAgdGhpcy5jbGllbnRTb2NrZXQub25CaW5hcnlNZXNzYWdlKChkYXRhOiBCdWZmZXIpID0+IHtcbiAgICAgICAgZGFwU29ja2V0LndyaXRlKFVpbnQ4QXJyYXkuZnJvbShkYXRhKSk7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuY2xpZW50U29ja2V0Lm9uU3RyaW5nTWVzc2FnZSgoZGF0YTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGRhcFNvY2tldC53cml0ZShkYXRhKTtcbiAgICAgIH0pO1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGxvZ2dpbmcuZ2V0TG9nZ2VyKCkuZXJyb3IoJ0Vycm9yIGNvbm5lY3RpbmcgdG8gRGVidWcgQWRhcHRlcjogJXMnLCBlcnJvcik7XG4gICAgICB0aGlzLmNsb3NlKCk7XG4gICAgfVxuICB9XG59XG5cbi8qKiBEZWJ1ZyBBZGFwdGVyIFByb3RvY29sIHNlcnZlci4gKi9cbmV4cG9ydCBjbGFzcyBEYXBTZXJ2ZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IHBvcnRQcm9taXNlOiBQcm9taXNlPHN0cmluZz47XG4gIGNvbnN0cnVjdG9yKG11eEJpbmFyeTogc3RyaW5nLCBzZXJ2ZXI/OiBTb2NrZXRJTy5TZXJ2ZXIpIHtcbiAgICB0aGlzLnBvcnRQcm9taXNlID0gdGhpcy5zcGF3bk11bHRpcGxleGVyKG11eEJpbmFyeSk7XG5cbiAgICBzZXJ2ZXI/Lm9mKCcvZGVidWdnZXInKS5vbignY29ubmVjdGlvbicsIChzb2NrZXQ6IFNvY2tldElPLlNvY2tldCkgPT4ge1xuICAgICAgdGhpcy5wb3J0UHJvbWlzZS50aGVuKChkb21haW5Tb2NrZXRQYXRoKSA9PiB7XG4gICAgICAgIC8vIFNlc3Npb24gbWFuYWdlcyBpdHMgb3duIGxpZmV0aW1lLlxuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tdW51c2VkLWV4cHJlc3Npb25cbiAgICAgICAgbmV3IFNlc3Npb24obmV3IFNvY2tldElPQWRhcHRlcihzb2NrZXQpLCBkb21haW5Tb2NrZXRQYXRoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgaGFuZGxlVXBncmFkZShyZXF1ZXN0OiBodHRwLkluY29taW5nTWVzc2FnZSwgc29jazogbmV0LlNvY2tldCwgaGVhZDogQnVmZmVyKSB7XG4gICAgbmV3IFNlcnZlcih7bm9TZXJ2ZXI6IHRydWV9KS5oYW5kbGVVcGdyYWRlKHJlcXVlc3QsIHNvY2ssIGhlYWQsICh3cykgPT4ge1xuICAgICAgdGhpcy5wb3J0UHJvbWlzZS50aGVuKChkb21haW5Tb2NrZXRQYXRoKSA9PiB7XG4gICAgICAgIC8vIFNlc3Npb24gbWFuYWdlcyBpdHMgb3duIGxpZmV0aW1lLlxuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tdW51c2VkLWV4cHJlc3Npb25cbiAgICAgICAgbmV3IFNlc3Npb24obmV3IFdlYlNvY2tldEFkYXB0ZXIod3MpLCBkb21haW5Tb2NrZXRQYXRoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzcGF3bk11bHRpcGxleGVyKG11eEJpbmFyeTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBmaWxlbmFtZSA9XG4gICAgICAgIGAvdG1wL2RlYnVnZ2VyXyR7Y3J5cHRvLnJhbmRvbUJ5dGVzKDYpLnJlYWRVSW50TEUoMCwgNikudG9TdHJpbmcoMzYpfWA7XG4gICAgY29uc3QgbXV4UHJvY2VzcyA9IGNoaWxkUHJvY2Vzcy5zcGF3bihtdXhCaW5hcnksIFtcbiAgICAgIGAtLWRvbWFpbl9zb2NrZXRfcGF0aD0ke2ZpbGVuYW1lfWAsXG4gICAgXSk7XG5cbiAgICBtdXhQcm9jZXNzLnN0ZG91dC5vbignZGF0YScsIChkYXRhOiBzdHJpbmcpID0+IHtcbiAgICAgIGxvZ2dpbmcuZ2V0TG9nZ2VyKCkuaW5mbygnJXM6ICVzJywgbXV4QmluYXJ5LCBkYXRhKTtcbiAgICB9KTtcbiAgICBtdXhQcm9jZXNzLnN0ZG91dC5vbignZXJyb3InLCAoZGF0YTogc3RyaW5nKSA9PiB7XG4gICAgICBsb2dnaW5nLmdldExvZ2dlcigpLmluZm8oJyVzOiAlcycsIG11eEJpbmFyeSwgZGF0YSk7XG4gICAgfSk7XG5cbiAgICBsZXQgbXV4T3V0cHV0ID0gJyc7XG4gICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgY29ubmVjdGlvbkhhbmRsZXIgPSAoZGF0YTogc3RyaW5nKSA9PiB7XG4gICAgICAgIG11eE91dHB1dCArPSBkYXRhO1xuICAgICAgICAvLyBXYWl0IGZvciB0aGUgcHJvY2VzcyB0byBpbmRpY2F0ZSB0aGF0IGl0IGlzIGxpc3RlbmluZy5cbiAgICAgICAgaWYgKG11eE91dHB1dC5tYXRjaCgvTGlzdGVuaW5nIG9uIC8pKSB7XG4gICAgICAgICAgbXV4UHJvY2Vzcy5zdGRvdXQub2ZmKCdkYXRhJywgY29ubmVjdGlvbkhhbmRsZXIpO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIG11eFByb2Nlc3Muc3Rkb3V0Lm9uKCdkYXRhJywgY29ubmVjdGlvbkhhbmRsZXIpO1xuICAgICAgbXV4UHJvY2Vzcy5zdGRvdXQub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICB9KTtcbiAgICByZXR1cm4gZmlsZW5hbWU7XG4gIH1cbn1cblxuZGVjbGFyZSBpbnRlcmZhY2UgT3V0Z29pbmdNZXNzYWdlIHtcbiAgcmVhZG9ubHkgZGF0YT86IHN0cmluZztcbiAgcmVhZG9ubHkgb3Blbj86IGJvb2xlYW47XG59XG4iXX0=