dcp-worker 4.3.7 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dcp-evaluator-manager +15 -1
- package/bin/dcp-evaluator-start +9 -2
- package/bin/dcp-worker +197 -101
- package/lib/default-ui-events.js +3 -3
- package/lib/pidfile.js +7 -3
- package/lib/show.js +7 -16
- package/lib/telnetd.js +1 -1
- package/lib/utils.js +219 -9
- package/lib/web-iface.js +495 -91
- package/lib/worker-consoles/dashboard-console.js +8 -1
- package/lib/worker-consoles/stdio-console.js +9 -2
- package/package.json +6 -5
- package/www/admin/index.html +22 -0
- package/www/admin/manage-worker.html +19 -0
- package/www/admin/register-worker.html +334 -0
- package/www/hud/dark.css +10 -0
- package/www/hud/hud-common.css +19 -0
- package/www/hud/hud-common.mjs +69 -0
- package/www/hud/index.html +46 -0
- package/www/hud/small-dark.html +346 -0
- package/lib/web-console.js +0 -178
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<!--
|
|
3
|
+
- @file small-dark.html - small, dark status screen for the worker
|
|
4
|
+
- @author Wes Garland, wes@distributive.network
|
|
5
|
+
- @date Feb 2026
|
|
6
|
+
-
|
|
7
|
+
- DCP logo is hidden by default; use ?show-logo to reveal
|
|
8
|
+
-
|
|
9
|
+
-->
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="UTF-8">
|
|
13
|
+
<title>DCP Worker - HUD</title>
|
|
14
|
+
<link rel="stylesheet" type="text/css" href="./hud-common.css">
|
|
15
|
+
<script src="/etc/dcp-config.js"></script>
|
|
16
|
+
<script src="/dcp-client/dcp-client.js"></script>
|
|
17
|
+
<link rel="stylesheet" type="text/css" dcp-cdn-href="/css/dcp-style.css">
|
|
18
|
+
<link rel="stylesheet" type="text/css" href="./dark.css">
|
|
19
|
+
<script cdn-src="/dom-tk.js?dcp-worker-version=4.3.7"></script>
|
|
20
|
+
<script type="module">
|
|
21
|
+
import * as hud from "./hud-common.mjs";
|
|
22
|
+
window.addEventListener('error', ev => dcp['dom-tk'].modals.alert(ev));
|
|
23
|
+
window.addEventListener('unhandledrejection', ev => dcp['dom-tk'].modals.alert(ev.reason));
|
|
24
|
+
</script>
|
|
25
|
+
<style type="text/css">
|
|
26
|
+
HTML, BODY {
|
|
27
|
+
height: 100%;
|
|
28
|
+
width: 100%;
|
|
29
|
+
min-height: 100%; /* opera */
|
|
30
|
+
margin: 0;
|
|
31
|
+
padding: 0;
|
|
32
|
+
overflow: hidden;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
DIV#dcp-logo {
|
|
36
|
+
background-image: url(/dcp-client/assets/dcp-logo.png);
|
|
37
|
+
background-position: center;
|
|
38
|
+
background-repeat: no-repeat;
|
|
39
|
+
background-size: contain;
|
|
40
|
+
height: 20vh;
|
|
41
|
+
max-height: 60px;
|
|
42
|
+
margin-top: 1em;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
BODY[show-logo="false"] DIV#dcp-logo-header {
|
|
46
|
+
display: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#logBlocker {
|
|
50
|
+
width: 100%;
|
|
51
|
+
background-color: black;
|
|
52
|
+
position: relative;
|
|
53
|
+
z-index: 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#loggerText {
|
|
57
|
+
white-space: pre-wrap;
|
|
58
|
+
position: absolute;
|
|
59
|
+
bottom: 0;
|
|
60
|
+
max-height: 100%;
|
|
61
|
+
width: 100%;
|
|
62
|
+
overflow-x: hidden;
|
|
63
|
+
overflow-y: scroll;
|
|
64
|
+
text-overflow: ellipsis;
|
|
65
|
+
text-wrap: nowrap;
|
|
66
|
+
padding: 5px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
TABLE
|
|
70
|
+
{
|
|
71
|
+
align: left;
|
|
72
|
+
width: 100%;
|
|
73
|
+
border-bottom: 1px dotted #ccc;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
TD {
|
|
77
|
+
min-width: 20ch;
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
text-overflow: ellipsis;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
TH {
|
|
83
|
+
text-align: left;
|
|
84
|
+
text-wrap: nowrap;
|
|
85
|
+
}
|
|
86
|
+
</style>
|
|
87
|
+
<script src="/worker/run-info"></script>
|
|
88
|
+
<script>
|
|
89
|
+
'use strict';
|
|
90
|
+
if (!runInfo)
|
|
91
|
+
setTimeout(() => window.location.reload(), 1500);
|
|
92
|
+
</script>
|
|
93
|
+
<script>
|
|
94
|
+
'use strict';
|
|
95
|
+
const $ = document.querySelector.bind(document);
|
|
96
|
+
const $$ = document.querySelectorAll.bind(document);
|
|
97
|
+
function displayRunInfo(newRunInfo)
|
|
98
|
+
{
|
|
99
|
+
if (newRunInfo)
|
|
100
|
+
Object.assign(runInfo, newRunInfo);
|
|
101
|
+
|
|
102
|
+
runInfo.startTime = new Date(runInfo.startTime).toLocaleString();
|
|
103
|
+
runInfo.totalEarnings = new dcp.types.BigNumber(runInfo.totalEarnings.toFixed(3));
|
|
104
|
+
$$('[run-info]').forEach(element => {
|
|
105
|
+
const prop = element.getAttribute('run-info');
|
|
106
|
+
element.textContent = String(runInfo[prop]);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function init()
|
|
111
|
+
{
|
|
112
|
+
displayRunInfo();
|
|
113
|
+
const worker = new DistributiveWorkerLink(window.location.origin);
|
|
114
|
+
worker.on('payment', (amount) => {
|
|
115
|
+
const el = $('[run-info="totalEarnings"]');
|
|
116
|
+
const bnTotal = new dcp.types.BigNumber(el.textContent);
|
|
117
|
+
const bnAmount = new dcp.types.BigNumber(amount);
|
|
118
|
+
el.textContent = String(bnTotal.plus(bnAmount));
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
worker.on('job', job => logger(`New job: ${job.name} ${job.id.slice(0,8)} ${job.description || ''} ${job.link || ''}`));
|
|
122
|
+
worker.on('sandbox', sandbox => logger('sbox', sandbox));
|
|
123
|
+
worker.on('connect', (runInfo, taskInfo) => {
|
|
124
|
+
displayRunInfo(runInfo);
|
|
125
|
+
logger(`Worker currently has ${Object.keys(taskInfo.jobs).length} jobs loaded`);
|
|
126
|
+
});
|
|
127
|
+
worker.on('stop', () => logger('Worker is preparing to shut down'));
|
|
128
|
+
worker.on('end', () => logger('Worker has stopped'));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const logLines = [];
|
|
132
|
+
const logSize = 100;
|
|
133
|
+
function logger(...args)
|
|
134
|
+
{
|
|
135
|
+
const logEl = $('#loggerText');
|
|
136
|
+
const msg = args.map(arg => String(arg)).join(' ');
|
|
137
|
+
logLines.push(msg);
|
|
138
|
+
if (logLines.length === logSize)
|
|
139
|
+
logLines.shift();
|
|
140
|
+
logEl.textContent = logLines.join('\n');
|
|
141
|
+
logEl.scrollTo({top: logEl.scrollHeight, behavior: 'smooth'});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
class DistributiveWorkerLinkEvent
|
|
145
|
+
{
|
|
146
|
+
#cancelled = false;
|
|
147
|
+
#args;
|
|
148
|
+
|
|
149
|
+
constructor(args)
|
|
150
|
+
{
|
|
151
|
+
this.#args = args || [];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
preventDefault()
|
|
155
|
+
{
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
stopPropagation()
|
|
159
|
+
{
|
|
160
|
+
this.#cancelled = true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
dispatch(callback)
|
|
164
|
+
{
|
|
165
|
+
var wev;
|
|
166
|
+
if (globalThis.window === globalThis)
|
|
167
|
+
{
|
|
168
|
+
wev = window.event;
|
|
169
|
+
window.event = this;
|
|
170
|
+
}
|
|
171
|
+
callback(...this.#args);
|
|
172
|
+
if (globalThis.window === globalThis)
|
|
173
|
+
window.event = wev;
|
|
174
|
+
return !this.#cancelled;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
class DistributiveWorkerLink
|
|
179
|
+
{
|
|
180
|
+
#connectType = 'normal';
|
|
181
|
+
#location;
|
|
182
|
+
static #KVIN = (() => {
|
|
183
|
+
const KVIN = new dcp.kvin.KVIN();
|
|
184
|
+
KVIN.userCtors.BigNumber = dcp.types.BigNumber;
|
|
185
|
+
KVIN.userCtors.JobHandle = Object;
|
|
186
|
+
KVIN.userCtors.SanboxHandle = Object;
|
|
187
|
+
return KVIN;
|
|
188
|
+
})(/*iife*/);
|
|
189
|
+
|
|
190
|
+
constructor(location)
|
|
191
|
+
{
|
|
192
|
+
this.events = {};
|
|
193
|
+
this.#location = new URL(origin + '/dcp/');
|
|
194
|
+
this.#connect();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
#connect()
|
|
198
|
+
{
|
|
199
|
+
var reqs = [];
|
|
200
|
+
var queue = []; /* queue up notifications that arrive during Promise.allSettled */
|
|
201
|
+
|
|
202
|
+
this.conn = new dcp.protocol.Connection({ location: this.#location });
|
|
203
|
+
this.conn.on('end', (ev) => {
|
|
204
|
+
if (this.conn.closeErrorCode === 'ECONNRESET') /* Worker went down and came back up */
|
|
205
|
+
window.location.reload();
|
|
206
|
+
});
|
|
207
|
+
this.conn.on('connect', async () => {
|
|
208
|
+
var taskInfo, runInfo;
|
|
209
|
+
const p$res = [
|
|
210
|
+
this.conn.request('task-info').then(res => taskInfo = res.payload),
|
|
211
|
+
this.conn.request('run-info') .then(res => runInfo = res.payload)
|
|
212
|
+
];
|
|
213
|
+
try
|
|
214
|
+
{
|
|
215
|
+
await Promise.all(p$res);
|
|
216
|
+
this.#dispatchEvent('connect', [ runInfo, taskInfo ]);
|
|
217
|
+
this.#connectType = 'normal';
|
|
218
|
+
}
|
|
219
|
+
catch(error)
|
|
220
|
+
{
|
|
221
|
+
if (error.code === 'EADDRCHANGE')
|
|
222
|
+
this.#connectType = 'never';
|
|
223
|
+
else
|
|
224
|
+
this.#connectType = 'slow';
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
this.conn.on('end', async () => {
|
|
229
|
+
switch(this.#connectType)
|
|
230
|
+
{
|
|
231
|
+
case 'never':
|
|
232
|
+
console.log('ignore connect request, reload document to reconnect');
|
|
233
|
+
return;
|
|
234
|
+
case 'slow':
|
|
235
|
+
await dcp.utils.a$sleep(10);
|
|
236
|
+
/* fallthrough */
|
|
237
|
+
case 'normal':
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
this.#connect();
|
|
241
|
+
});
|
|
242
|
+
this.conn.on('notification', notification => {
|
|
243
|
+
if (reqs.length === 0)
|
|
244
|
+
this.#processNotification(notification);
|
|
245
|
+
else
|
|
246
|
+
queue.push(notification);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
for (let eventName of Object.keys(this.events))
|
|
250
|
+
reqs.push(this.conn.request('event-on', eventName));
|
|
251
|
+
Promise.allSettled(reqs).then(async () => {
|
|
252
|
+
for (let eventName of Object.keys(this.events))
|
|
253
|
+
this.events[eventName].eventHandlerId = await reqs.shift();
|
|
254
|
+
for (let notification of queue)
|
|
255
|
+
this.#processNotification(notification);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
#dispatchEvent(eventName, args)
|
|
260
|
+
{
|
|
261
|
+
if (!this.events[eventName])
|
|
262
|
+
return;
|
|
263
|
+
for (let event of this.events[eventName])
|
|
264
|
+
{
|
|
265
|
+
const ev = new DistributiveWorkerLinkEvent(args)
|
|
266
|
+
if (ev.dispatch(event.eventHandler) === false)
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
#processNotification(notification)
|
|
272
|
+
{
|
|
273
|
+
if (notification.payload.data.type !== 'event')
|
|
274
|
+
throw new Error('invalid notification type: ' + notification.payload.data.type);
|
|
275
|
+
const eventName = notification.payload.data.name;
|
|
276
|
+
this.#dispatchEvent(eventName, this.constructor.#KVIN.parse(notification.payload.data.kvinArgs));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
async on(eventName, eventHandler)
|
|
280
|
+
{
|
|
281
|
+
var eventHandlerId;
|
|
282
|
+
|
|
283
|
+
if (!this.events[eventName])
|
|
284
|
+
this.events[eventName] = [];
|
|
285
|
+
if (eventName === 'connect') /* internal event */
|
|
286
|
+
eventHandlerId = Math.random().toFixed(36) + Date.now();
|
|
287
|
+
else
|
|
288
|
+
{
|
|
289
|
+
try
|
|
290
|
+
{
|
|
291
|
+
const res = await this.conn.request('event-on', eventName);
|
|
292
|
+
eventHandlerId = res.payload.eventHandlerId;
|
|
293
|
+
}
|
|
294
|
+
catch(error)
|
|
295
|
+
{
|
|
296
|
+
if (error.code === 'EPIPE')
|
|
297
|
+
this.on(eventName, eventHandler); /* try again on new connection */
|
|
298
|
+
else
|
|
299
|
+
throw error;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
this.events[eventName].push({ eventHandler, eventHandlerId });
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
off(eventName, eventHandler)
|
|
306
|
+
{
|
|
307
|
+
for (let i=0; i < this.events[eventName].length; i++)
|
|
308
|
+
{
|
|
309
|
+
event = this.events[eventName][i];
|
|
310
|
+
if (event.eventHandler === eventHandler)
|
|
311
|
+
{
|
|
312
|
+
conn.request('event-off', { eventName, eventHandlerId: event.eventHandlerId });
|
|
313
|
+
this.events[eventName].splice(i, 1);
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
addEventListener = this.on;
|
|
320
|
+
removeEventListener = this.off;
|
|
321
|
+
}
|
|
322
|
+
</script>
|
|
323
|
+
</head>
|
|
324
|
+
<body onload="init();" show-logo="false">
|
|
325
|
+
<div id="logBlocker">
|
|
326
|
+
<div id="dcp-logo-header">
|
|
327
|
+
<div id="dcp-logo"></div>
|
|
328
|
+
<center><h3>DCP Worker</h3></center>
|
|
329
|
+
</div>
|
|
330
|
+
<table>
|
|
331
|
+
<tr><th>Running Since:</th> <td run-info="startTime"></td></tr>
|
|
332
|
+
<tr><th>Earnings Since Start:</th> <td run-info="totalEarnings" class="dcp-amount"></td></tr>
|
|
333
|
+
<tr><th>Earnings Account:</th> <td run-info="earningsAccount" class="dcp-fixed-font"></td></tr>
|
|
334
|
+
</table>
|
|
335
|
+
</div>
|
|
336
|
+
<div id="loggerText" class="dcp-fixed-font">connecting to worker...</div>
|
|
337
|
+
</body>
|
|
338
|
+
<script>
|
|
339
|
+
'use strict';
|
|
340
|
+
{
|
|
341
|
+
const searchParams = new URL(window.location.href).searchParams;
|
|
342
|
+
if (searchParams.has('show-logo'))
|
|
343
|
+
document.body.setAttribute('show-logo', searchParams.get('show-logo') || 'true');
|
|
344
|
+
}
|
|
345
|
+
</script>
|
|
346
|
+
</html>
|
package/lib/web-console.js
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* https://stackoverflow.com/questions/52843900/blessed-server-node-js-over-websocket-to-xterm-js-client-in-browser
|
|
3
|
-
*/
|
|
4
|
-
const blessed = require('blessed');
|
|
5
|
-
const contrib = require('blessed-contrib');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const http = require('http');
|
|
9
|
-
|
|
10
|
-
const progDir = path.dirname(require.main.filename);
|
|
11
|
-
const wwwDir = path.resolve(progDir, '../www');
|
|
12
|
-
const nmDir = path.resolve(progDir, '../node_modules');
|
|
13
|
-
|
|
14
|
-
const magic = {
|
|
15
|
-
html: 'text/html',
|
|
16
|
-
txt: 'text/plain',
|
|
17
|
-
js: 'application/javascript',
|
|
18
|
-
css: 'text/css',
|
|
19
|
-
gif: 'image/gif',
|
|
20
|
-
jpeg: 'image/jpeg',
|
|
21
|
-
jpg: 'image/jpeg',
|
|
22
|
-
png: 'image/png',
|
|
23
|
-
svg: 'image/svg+xml',
|
|
24
|
-
kvin: 'application/x-kvin',
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const clients = [ ];
|
|
28
|
-
var worker; /* instance of DistributiveWorker, null (stopped), or undefined (not started) */
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Return a copy of the local dcp config, with the current worker's config at dcpConfig.worker, but with
|
|
32
|
-
* with sensitive information (eg compute group credentials) stripped.
|
|
33
|
-
*/
|
|
34
|
-
function makeSafeConfig()
|
|
35
|
-
{
|
|
36
|
-
const conf = Object.assign({}, dcpConfig);
|
|
37
|
-
conf.worker = Object.assign({}, worker.config || dcpConfig.worker?.config);
|
|
38
|
-
|
|
39
|
-
/* Sanitize worker.computeGroups credentials */
|
|
40
|
-
if (conf.worker?.computeGroups)
|
|
41
|
-
{
|
|
42
|
-
conf.worker.computeGroups = Object.assign({}, conf.worker.computeGroups);
|
|
43
|
-
for (let key in conf.worker.computeGroups)
|
|
44
|
-
{
|
|
45
|
-
const group = conf.worker.computeGroups[key];
|
|
46
|
-
if (group.joinKey)
|
|
47
|
-
group = { joinKey: group.joinKey };
|
|
48
|
-
else
|
|
49
|
-
group = {};
|
|
50
|
-
conf.worker.computeGroups[key] = group;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return conf;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* HTTP server
|
|
59
|
-
*/
|
|
60
|
-
function handleHttpRequest(request, response)
|
|
61
|
-
{
|
|
62
|
-
if (request.url === '/etc/dcp-config.js')
|
|
63
|
-
{
|
|
64
|
-
response.setHeader('Content-Type', magic.js);
|
|
65
|
-
response.end(makeSkeletonConfig());
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (request.url === '/etc/dcp-config.kvin')
|
|
70
|
-
{
|
|
71
|
-
response.setHeader('Content-Type', magic.kvin);
|
|
72
|
-
response.end('(' + JSON.stringify(dcpConfig) + ')');
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
var filename = (request.url.slice(1) || 'index.html');
|
|
77
|
-
const contentType = magic[path.extname(filename).slice(1)] || 'text/plain';
|
|
78
|
-
var errorStatus, contentDir;
|
|
79
|
-
|
|
80
|
-
if (!filename.startsWith('node_modules/'))
|
|
81
|
-
contentDir = wwwDir;
|
|
82
|
-
else
|
|
83
|
-
{
|
|
84
|
-
contentDir = nmDir;
|
|
85
|
-
filename = filename.slice(13);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
filename = path.resolve(contentDir, filename);
|
|
89
|
-
console.log({contentDir,filename,requestUrl:request.url});
|
|
90
|
-
if (!filename.startsWith(contentDir) || filename[0] !== '/')
|
|
91
|
-
errorStatus = 401;
|
|
92
|
-
else if (!fs.existsSync(filename))
|
|
93
|
-
errorStatus = 404;
|
|
94
|
-
|
|
95
|
-
if (errorStatus)
|
|
96
|
-
{
|
|
97
|
-
response.setHeader('Content-Type', 'text/plain');
|
|
98
|
-
response.statusCode = errorStatus;
|
|
99
|
-
response.end(`${errorStatus} accessing ${filename}`);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
response.setHeader('Content-Type', contentType);
|
|
104
|
-
response.end(fs.readFileSync(filename));
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
exports.getConfig = function webConsole$$getConfig()
|
|
108
|
-
{
|
|
109
|
-
var config = { host: 'localhost', port: 9080 };
|
|
110
|
-
|
|
111
|
-
if (dcpConfig.worker?.webConsole?.listen)
|
|
112
|
-
{
|
|
113
|
-
config.host = dcpConfig.worker.webConsole.listen.host;
|
|
114
|
-
config.port = dcpConfig.worker.webConsole.listen.port || 80;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return config;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
exports.a$init = function webConsole$$init()
|
|
121
|
-
{
|
|
122
|
-
var server = http.createServer(handleHttpRequest).unref();
|
|
123
|
-
var resolve, reject;
|
|
124
|
-
var a$Promise = new Promise((_resolve, _reject) => {
|
|
125
|
-
resolve = _resolve;
|
|
126
|
-
reject = _reject;
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
server.on('error', error => {
|
|
130
|
-
console.error(` ! Web console not started; ${error.message}`);
|
|
131
|
-
reject(error);
|
|
132
|
-
});
|
|
133
|
-
server.listen(exports.getConfig(), function webConsole$$ready() {
|
|
134
|
-
resolve();
|
|
135
|
-
console.log(` * httpd listening on ${server._connectionKey}`);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* WebSocket server
|
|
140
|
-
*/
|
|
141
|
-
const WebSocketServer = require('websocket').server;
|
|
142
|
-
const wsServer = new WebSocketServer({
|
|
143
|
-
httpServer: server,
|
|
144
|
-
autoAcceptConnections: false
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
wsServer.on('request', handleWssRequest);
|
|
148
|
-
function handleWssRequest(request)
|
|
149
|
-
{
|
|
150
|
-
const connection = request.accept(null, request.origin);
|
|
151
|
-
connection.socket.unref();
|
|
152
|
-
clients.push(connection);
|
|
153
|
-
|
|
154
|
-
const write = connection.send;
|
|
155
|
-
const read = connection.socket.read;
|
|
156
|
-
|
|
157
|
-
connection.send(JSON.stringify({ type: 'log', facility: 'debug', message: 'hello, world' }));
|
|
158
|
-
connection.on('message', messageHandler);
|
|
159
|
-
connection.on('close', closeHandler);
|
|
160
|
-
|
|
161
|
-
function messageHandler(message)
|
|
162
|
-
{
|
|
163
|
-
console.log('message:', message)
|
|
164
|
-
console.log('this:', this);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function closeHandler()
|
|
168
|
-
{
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return a$Promise;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
exports.setWorker = function webConsole$$setWorker(dw)
|
|
176
|
-
{
|
|
177
|
-
worker = dw;
|
|
178
|
-
}
|