UNPKG

19 kBJavaScriptView Raw
1"use strict";
2/*---------------------------------------------------------------------------------------------
3 * Copyright (c) Microsoft Corporation. All rights reserved.
4 * Licensed under the MIT License. See License.txt in the project root for license information.
5 *--------------------------------------------------------------------------------------------*/
6Object.defineProperty(exports, "__esModule", { value: true });
7const ee = require("events");
8const messages_1 = require("./messages");
9class ProtocolServer extends ee.EventEmitter {
10 constructor() {
11 super();
12 this._pendingRequests = new Map();
13 }
14 start(inStream, outStream) {
15 this._sequence = 1;
16 this._writableStream = outStream;
17 this._rawData = new Buffer(0);
18 inStream.on('data', (data) => this._handleData(data));
19 inStream.on('close', () => {
20 this._emitEvent(new messages_1.Event('close'));
21 });
22 inStream.on('error', (error) => {
23 this._emitEvent(new messages_1.Event('error', 'inStream error: ' + (error && error.message)));
24 });
25 outStream.on('error', (error) => {
26 this._emitEvent(new messages_1.Event('error', 'outStream error: ' + (error && error.message)));
27 });
28 inStream.resume();
29 }
30 stop() {
31 if (this._writableStream) {
32 this._writableStream.end();
33 }
34 }
35 sendEvent(event) {
36 this._send('event', event);
37 }
38 sendResponse(response) {
39 if (response.seq > 0) {
40 console.error(`attempt to send more than one response for command ${response.command}`);
41 }
42 else {
43 this._send('response', response);
44 }
45 }
46 sendRequest(command, args, timeout, cb) {
47 const request = {
48 command: command
49 };
50 if (args && Object.keys(args).length > 0) {
51 request.arguments = args;
52 }
53 if (!this._writableStream) {
54 this._emitEvent(new messages_1.Event('error', 'sendRequest: No writableStream'));
55 return;
56 }
57 this._send('request', request);
58 if (cb) {
59 this._pendingRequests.set(request.seq, cb);
60 const timer = setTimeout(() => {
61 clearTimeout(timer);
62 const clb = this._pendingRequests.get(request.seq);
63 if (clb) {
64 this._pendingRequests.delete(request.seq);
65 clb(new messages_1.Response(request, 'timeout'));
66 }
67 }, timeout);
68 }
69 }
70 // ---- protected ----------------------------------------------------------
71 dispatchRequest(request) {
72 }
73 // ---- private ------------------------------------------------------------
74 _emitEvent(event) {
75 this.emit(event.event, event);
76 }
77 _send(typ, message) {
78 message.type = typ;
79 message.seq = this._sequence++;
80 if (this._writableStream) {
81 const json = JSON.stringify(message);
82 this._writableStream.write(`Content-Length: ${Buffer.byteLength(json, 'utf8')}\r\n\r\n${json}`, 'utf8');
83 }
84 }
85 _handleData(data) {
86 this._rawData = Buffer.concat([this._rawData, data]);
87 while (true) {
88 if (this._contentLength >= 0) {
89 if (this._rawData.length >= this._contentLength) {
90 const message = this._rawData.toString('utf8', 0, this._contentLength);
91 this._rawData = this._rawData.slice(this._contentLength);
92 this._contentLength = -1;
93 if (message.length > 0) {
94 try {
95 let msg = JSON.parse(message);
96 if (msg.type === 'request') {
97 this.dispatchRequest(msg);
98 }
99 else if (msg.type === 'response') {
100 const response = msg;
101 const clb = this._pendingRequests.get(response.request_seq);
102 if (clb) {
103 this._pendingRequests.delete(response.request_seq);
104 clb(response);
105 }
106 }
107 }
108 catch (e) {
109 this._emitEvent(new messages_1.Event('error', 'Error handling data: ' + (e && e.message)));
110 }
111 }
112 continue; // there may be more complete messages to process
113 }
114 }
115 else {
116 const idx = this._rawData.indexOf(ProtocolServer.TWO_CRLF);
117 if (idx !== -1) {
118 const header = this._rawData.toString('utf8', 0, idx);
119 const lines = header.split('\r\n');
120 for (let i = 0; i < lines.length; i++) {
121 const pair = lines[i].split(/: +/);
122 if (pair[0] == 'Content-Length') {
123 this._contentLength = +pair[1];
124 }
125 }
126 this._rawData = this._rawData.slice(idx + ProtocolServer.TWO_CRLF.length);
127 continue;
128 }
129 }
130 break;
131 }
132 }
133}
134ProtocolServer.TWO_CRLF = '\r\n\r\n';
135exports.ProtocolServer = ProtocolServer;
136//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvdG9jb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOztBQUVoRyw2QkFBNkI7QUFFN0IseUNBQTZDO0FBRzdDLG9CQUE0QixTQUFRLEVBQUUsQ0FBQyxZQUFZO0lBVWxEO1FBQ0MsS0FBSyxFQUFFLENBQUM7UUFIRCxxQkFBZ0IsR0FBRyxJQUFJLEdBQUcsRUFBc0QsQ0FBQztJQUl6RixDQUFDO0lBRU0sS0FBSyxDQUFDLFFBQStCLEVBQUUsU0FBZ0M7UUFDN0UsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLGVBQWUsR0FBRyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUU5QixRQUFRLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQVksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBRTlELFFBQVEsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRTtZQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksZ0JBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3JDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsUUFBUSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUM5QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksZ0JBQUssQ0FBQyxPQUFPLEVBQUUsa0JBQWtCLEdBQUcsQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRixDQUFDLENBQUMsQ0FBQztRQUVILFNBQVMsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDL0IsSUFB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LEdBQUcsR0FBRyxjQUFjLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUMxRSxTQUFTO2lCQUNUO2FBQ0Q7WUFDRCxNQUFNO1NBQ047SUFDRixDQUFDOztBQXRKYyx1QkFBUSxHQUFHLFVBQVUsQ0FBQztBQUZ0Qyx3Q0F5SkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuaW1wb3J0ICogYXMgZWUgZnJvbSAnZXZlbnRzJztcbmltcG9ydCB7IERlYnVnUHJvdG9jb2wgfSBmcm9tICd2c2NvZGUtZGVidWdwcm90b2NvbCc7XG5pbXBvcnQgeyBSZXNwb25zZSwgRXZlbnQgfSBmcm9tICcuL21lc3NhZ2VzJztcblxuXG5leHBvcnQgY2xhc3MgUHJvdG9jb2xTZXJ2ZXIgZXh0ZW5kcyBlZS5FdmVudEVtaXR0ZXIge1xuXG5cdHByaXZhdGUgc3RhdGljIFRXT19DUkxGID0gJ1xcclxcblxcclxcbic7XG5cblx0cHJpdmF0ZSBfcmF3RGF0YTogQnVmZmVyO1xuXHRwcml2YXRlIF9jb250ZW50TGVuZ3RoOiBudW1iZXI7XG5cdHByaXZhdGUgX3NlcXVlbmNlOiBudW1iZXI7XG5cdHByaXZhdGUgX3dyaXRhYmxlU3RyZWFtOiBOb2RlSlMuV3JpdGFibGVTdHJlYW07XG5cdHByaXZhdGUgX3BlbmRpbmdSZXF1ZXN0cyA9IG5ldyBNYXA8bnVtYmVyLCAocmVzcG9uc2U6IERlYnVnUHJvdG9jb2wuUmVzcG9uc2UpID0+IHZvaWQ+KCk7XG5cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblx0fVxuXG5cdHB1YmxpYyBzdGFydChpblN0cmVhbTogTm9kZUpTLlJlYWRhYmxlU3RyZWFtLCBvdXRTdHJlYW06IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSk6IHZvaWQge1xuXHRcdHRoaXMuX3NlcXVlbmNlID0gMTtcblx0XHR0aGlzLl93cml0YWJsZVN0cmVhbSA9IG91dFN0cmVhbTtcblx0XHR0aGlzLl9yYXdEYXRhID0gbmV3IEJ1ZmZlcigwKTtcblxuXHRcdGluU3RyZWFtLm9uKCdkYXRhJywgKGRhdGE6IEJ1ZmZlcikgPT4gdGhpcy5faGFuZGxlRGF0YShkYXRhKSk7XG5cblx0XHRpblN0cmVhbS5vbignY2xvc2UnLCAoKSA9PiB7XG5cdFx0XHR0aGlzLl9lbWl0RXZlbnQobmV3IEV2ZW50KCdjbG9zZScpKTtcblx0XHR9KTtcblx0XHRpblN0cmVhbS5vbignZXJyb3InLCAoZXJyb3IpID0+IHtcblx0XHRcdHRoaXMuX2VtaXRFdmVudChuZXcgRXZlbnQoJ2Vycm9yJywgJ2luU3RyZWFtIGVycm9yOiAnICsgKGVycm9yICYmIGVycm9yLm1lc3NhZ2UpKSk7XG5cdFx0fSk7XG5cblx0XHRvdXRTdHJlYW0ub24oJ2Vycm9yJywgKGVycm9yKSA9PiB7XG5cdFx0XHR0aGlzLl9lbWl0RXZlbnQobmV3IEV2ZW50KCdlcnJvcicsICdvdXRTdHJlYW0gZXJyb3I6ICcgKyAoZXJyb3IgJiYgZXJyb3IubWVzc2FnZSkpKTtcblx0XHR9KTtcblxuXHRcdGluU3RyZWFtLnJlc3VtZSgpO1xuXHR9XG5cblx0cHVibGljIHN0b3AoKTogdm9pZCB7XG5cdFx0aWYgKHRoaXMuX3dyaXRhYmxlU3RyZWFtKSB7XG5cdFx0XHR0aGlzLl93cml0YWJsZVN0cmVhbS5lbmQoKTtcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgc2VuZEV2ZW50KGV2ZW50OiBEZWJ1Z1Byb3RvY29sLkV2ZW50KTogdm9pZCB7XG5cdFx0dGhpcy5fc2VuZCgnZXZlbnQnLCBldmVudCk7XG5cdH1cblxuXHRwdWJsaWMgc2VuZFJlc3BvbnNlKHJlc3BvbnNlOiBEZWJ1Z1Byb3RvY29sLlJlc3BvbnNlKTogdm9pZCB7XG5cdFx0aWYgKHJlc3BvbnNlLnNlcSA+IDApIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoYGF0dGVtcHQgdG8gc2VuZCBtb3JlIHRoYW4gb25lIHJlc3BvbnNlIGZvciBjb21tYW5kICR7cmVzcG9uc2UuY29tbWFuZH1gKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fc2VuZCgncmVzcG9uc2UnLCByZXNwb25zZSk7XG5cdFx0fVxuXHR9XG5cblx0cHVibGljIHNlbmRSZXF1ZXN0KGNvbW1hbmQ6IHN0cmluZywgYXJnczogYW55LCB0aW1lb3V0OiBudW1iZXIsIGNiOiAocmVzcG9uc2U6IERlYnVnUHJvdG9jb2wuUmVzcG9uc2UpID0+IHZvaWQpIDogdm9pZCB7XG5cblx0XHRjb25zdCByZXF1ZXN0OiBhbnkgPSB7XG5cdFx0XHRjb21tYW5kOiBjb21tYW5kXG5cdFx0fTtcblx0XHRpZiAoYXJncyAmJiBPYmplY3Qua2V5cyhhcmdzKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRyZXF1ZXN0LmFyZ3VtZW50cyA9IGFyZ3M7XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLl93cml0YWJsZVN0cmVhbSkge1xuXHRcdFx0dGhpcy5fZW1pdEV2ZW50KG5ldyBFdmVudCgnZXJyb3InLCAnc2VuZFJlcXVlc3Q6IE5vIHdyaXRhYmxlU3RyZWFtJykpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMuX3NlbmQoJ3JlcXVlc3QnLCByZXF1ZXN0KTtcblxuXHRcdGlmIChjYikge1xuXHRcdFx0dGhpcy5fcGVuZGluZ1JlcXVlc3RzLnNldChyZXF1ZXN0LnNlcSwgY2IpO1xuXG5cdFx0XHRjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRjbGVhclRpbWVvdXQodGltZXIpO1xuXHRcdFx0XHRjb25zdCBjbGIgPSB0aGlzLl9wZW5kaW5nUmVxdWVzdHMuZ2V0KHJlcXVlc3Quc2VxKTtcblx0XHRcdFx0aWYgKGNsYikge1xuXHRcdFx0XHRcdHRoaXMuX3BlbmRpbmdSZXF1ZXN0cy5kZWxldGUocmVxdWVzdC5zZXEpO1xuXHRcdFx0XHRcdGNsYihuZXcgUmVzcG9uc2UocmVxdWVzdCwgJ3RpbWVvdXQnKSk7XG5cdFx0XHRcdH1cblx0XHRcdH0sIHRpbWVvdXQpO1xuXHRcdH1cblx0fVxuXG5cdC8vIC0tLS0gcHJvdGVjdGVkIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcm90ZWN0ZWQgZGlzcGF0Y2hSZXF1ZXN0KHJlcXVlc3Q6IERlYnVnUHJvdG9jb2wuUmVxdWVzdCk6IHZvaWQge1xuXHR9XG5cblx0Ly8gLS0tLSBwcml2YXRlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgX2VtaXRFdmVudChldmVudDogRGVidWdQcm90b2NvbC5FdmVudCkge1xuXHRcdHRoaXMuZW1pdChldmVudC5ldmVudCwgZXZlbnQpO1xuXHR9XG5cblx0cHJpdmF0ZSBfc2VuZCh0eXA6ICdyZXF1ZXN0JyB8ICdyZXNwb25zZScgfCAnZXZlbnQnLCBtZXNzYWdlOiBEZWJ1Z1Byb3RvY29sLlByb3RvY29sTWVzc2FnZSk6IHZvaWQge1xuXG5cdFx0bWVzc2FnZS50eXBlID0gdHlwO1xuXHRcdG1lc3NhZ2Uuc2VxID0gdGhpcy5fc2VxdWVuY2UrKztcblxuXHRcdGlmICh0aGlzLl93cml0YWJsZVN0cmVhbSkge1xuXHRcdFx0Y29uc3QganNvbiA9IEpTT04uc3RyaW5naWZ5KG1lc3NhZ2UpO1xuXHRcdFx0dGhpcy5fd3JpdGFibGVTdHJlYW0ud3JpdGUoYENvbnRlbnQtTGVuZ3RoOiAke0J1ZmZlci5ieXRlTGVuZ3RoKGpzb24sICd1dGY4Jyl9XFxyXFxuXFxyXFxuJHtqc29ufWAsICd1dGY4Jyk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBfaGFuZGxlRGF0YShkYXRhOiBCdWZmZXIpOiB2b2lkIHtcblxuXHRcdHRoaXMuX3Jhd0RhdGEgPSBCdWZmZXIuY29uY2F0KFt0aGlzLl9yYXdEYXRhLCBkYXRhXSk7XG5cblx0XHR3aGlsZSAodHJ1ZSkge1xuXHRcdFx0aWYgKHRoaXMuX2NvbnRlbnRMZW5ndGggPj0gMCkge1xuXHRcdFx0XHRpZiAodGhpcy5fcmF3RGF0YS5sZW5ndGggPj0gdGhpcy5fY29udGVudExlbmd0aCkge1xuXHRcdFx0XHRcdGNvbnN0IG1lc3NhZ2UgPSB0aGlzLl9yYXdEYXRhLnRvU3RyaW5nKCd1dGY4JywgMCwgdGhpcy5fY29udGVudExlbmd0aCk7XG5cdFx0XHRcdFx0dGhpcy5fcmF3RGF0YSA9IHRoaXMuX3Jhd0RhdGEuc2xpY2UodGhpcy5fY29udGVudExlbmd0aCk7XG5cdFx0XHRcdFx0dGhpcy5fY29udGVudExlbmd0aCA9IC0xO1xuXHRcdFx0XHRcdGlmIChtZXNzYWdlLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdGxldCBtc2c6IERlYnVnUHJvdG9jb2wuUHJvdG9jb2xNZXNzYWdlID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcblx0XHRcdFx0XHRcdFx0aWYgKG1zZy50eXBlID09PSAncmVxdWVzdCcpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmRpc3BhdGNoUmVxdWVzdCg8RGVidWdQcm90b2NvbC5SZXF1ZXN0PiBtc2cpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKG1zZy50eXBlID09PSAncmVzcG9uc2UnKSB7XG5cdFx0XHRcdFx0XHRcdFx0Y29uc3QgcmVzcG9uc2UgPSA8RGVidWdQcm90b2NvbC5SZXNwb25zZT4gbXNnO1xuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IGNsYiA9IHRoaXMuX3BlbmRpbmdSZXF1ZXN0cy5nZXQocmVzcG9uc2UucmVxdWVzdF9zZXEpO1xuXHRcdFx0XHRcdFx0XHRcdGlmIChjbGIpIHtcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMuX3BlbmRpbmdSZXF1ZXN0cy5kZWxldGUocmVzcG9uc2UucmVxdWVzdF9zZXEpO1xuXHRcdFx0XHRcdFx0XHRcdFx0Y2xiKHJlc3BvbnNlKTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuX2VtaXRFdmVudChuZXcgRXZlbnQoJ2Vycm9yJywgJ0Vycm9yIGhhbmRsaW5nIGRhdGE6ICcgKyAoZSAmJiBlLm1lc3NhZ2UpKSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGNvbnRpbnVlO1x0Ly8gdGhlcmUgbWF5IGJlIG1vcmUgY29tcGxldGUgbWVzc2FnZXMgdG8gcHJvY2Vzc1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb25zdCBpZHggPSB0aGlzLl9yYXdEYXRhLmluZGV4T2YoUHJvdG9jb2xTZXJ2ZXIuVFdPX0NSTEYpO1xuXHRcdFx0XHRpZiAoaWR4ICE9PSAtMSkge1xuXHRcdFx0XHRcdGNvbnN0IGhlYWRlciA9IHRoaXMuX3Jhd0RhdGEudG9TdHJpbmcoJ3V0ZjgnLCAwLCBpZHgpO1xuXHRcdFx0XHRcdGNvbnN0IGxpbmVzID0gaGVhZGVyLnNwbGl0KCdcXHJcXG4nKTtcblx0XHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBwYWlyID0gbGluZXNbaV0uc3BsaXQoLzogKy8pO1xuXHRcdFx0XHRcdFx0aWYgKHBhaXJbMF0gPT0gJ0NvbnRlbnQtTGVuZ3RoJykge1xuXHRcdFx0XHRcdFx0XHR0aGlzLl9jb250ZW50TGVuZ3RoID0gK3BhaXJbMV07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHRoaXMuX3Jhd0RhdGEgPSB0aGlzLl9yYXdEYXRhLnNsaWNlKGlkeCArIFByb3RvY29sU2VydmVyLlRXT19DUkxGLmxlbmd0aCk7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxufVxuIl19
\No newline at end of file