@andersbakken/fisk 3.5.7 → 3.6.1
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/dist/VM_runtime.js +3914 -0
- package/dist/VM_runtime.js.map +1 -0
- package/dist/fisk-builder.js +55239 -0
- package/dist/fisk-builder.js.map +1 -0
- package/dist/fisk-daemon.js +4223 -0
- package/dist/fisk-daemon.js.map +1 -0
- package/dist/fisk-scheduler.js +54045 -0
- package/dist/fisk-scheduler.js.map +1 -0
- package/package.json +71 -34
- package/builder/VM.js +0 -156
- package/builder/VM_runtime.js +0 -171
- package/builder/client.js +0 -181
- package/builder/compile.js +0 -269
- package/builder/fisk-builder.js +0 -899
- package/builder/load.js +0 -85
- package/builder/objectcache.js +0 -301
- package/builder/quit-on-error.js +0 -9
- package/builder/server.js +0 -214
- package/common/index.js +0 -45
- package/daemon/client.js +0 -100
- package/daemon/clientbuffer.js +0 -73
- package/daemon/compile.js +0 -140
- package/daemon/constants.js +0 -13
- package/daemon/fisk-daemon.js +0 -166
- package/daemon/server.js +0 -81
- package/daemon/slots.js +0 -69
- package/monitor/fisk-monitor.js +0 -767
- package/proxy/fisk-proxy.js +0 -150
- package/scheduler/database.js +0 -144
- package/scheduler/environments.js +0 -386
- package/scheduler/fisk-scheduler.js +0 -1411
- package/scheduler/objectcachemanager.js +0 -306
- package/scheduler/peak.js +0 -112
- package/scheduler/public/index.html +0 -37
- package/scheduler/server.js +0 -432
- package/scheduler/usertester.js +0 -60
package/builder/load.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
const EventEmitter = require("events");
|
|
2
|
-
const os = require("os");
|
|
3
|
-
|
|
4
|
-
// some code taken from https://gist.github.com/bag-man/5570809
|
|
5
|
-
|
|
6
|
-
//Create function to get CPU information
|
|
7
|
-
function cpuAverage() {
|
|
8
|
-
|
|
9
|
-
//Initialise sum of idle and time of cores and fetch CPU info
|
|
10
|
-
let totalIdle = 0, totalTick = 0;
|
|
11
|
-
const cpus = os.cpus();
|
|
12
|
-
|
|
13
|
-
if (!(cpus instanceof Array))
|
|
14
|
-
return undefined;
|
|
15
|
-
|
|
16
|
-
//Loop through CPU cores
|
|
17
|
-
for(let i = 0, len = cpus.length; i < len; i++) {
|
|
18
|
-
|
|
19
|
-
//Select CPU core
|
|
20
|
-
let cpu = cpus[i];
|
|
21
|
-
|
|
22
|
-
//Total up the time in the cores tick
|
|
23
|
-
for(let type in cpu.times) {
|
|
24
|
-
totalTick += cpu.times[type];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
//Total up the idle time of the core
|
|
28
|
-
totalIdle += cpu.times.idle;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
//Return the average Idle and Tick times
|
|
32
|
-
return {idle: totalIdle / cpus.length, total: totalTick / cpus.length};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
//Grab first CPU Measure
|
|
36
|
-
let startMeasure = cpuAverage();
|
|
37
|
-
|
|
38
|
-
function measure() {
|
|
39
|
-
//Grab second Measure
|
|
40
|
-
const endMeasure = cpuAverage();
|
|
41
|
-
|
|
42
|
-
let percentageCPU;
|
|
43
|
-
if (endMeasure && startMeasure) {
|
|
44
|
-
//Calculate the difference in idle and total time between the measures
|
|
45
|
-
const idleDifference = endMeasure.idle - startMeasure.idle;
|
|
46
|
-
const totalDifference = endMeasure.total - startMeasure.total;
|
|
47
|
-
//Calculate the average percentage CPU usage
|
|
48
|
-
percentageCPU = 100 - ~~(100 * idleDifference / totalDifference);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
//Next measure will diff against this measure
|
|
52
|
-
startMeasure = endMeasure;
|
|
53
|
-
|
|
54
|
-
return percentageCPU ? percentageCPU / 100 : undefined;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
class Load extends EventEmitter {
|
|
58
|
-
constructor() {
|
|
59
|
-
super();
|
|
60
|
-
this._interval = undefined;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
get running() {
|
|
64
|
-
return this._interval !== undefined;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
start(interval) {
|
|
68
|
-
if (this._interval !== undefined)
|
|
69
|
-
throw new Error("Interval already running");
|
|
70
|
-
this._interval = setInterval(() => {
|
|
71
|
-
let m = measure();
|
|
72
|
-
if (m)
|
|
73
|
-
this.emit("data", m);
|
|
74
|
-
}, interval);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
stop() {
|
|
78
|
-
if (!this._interval)
|
|
79
|
-
throw new Error("No interval running");
|
|
80
|
-
clearInterval(this._interval);
|
|
81
|
-
this._interval = undefined;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
module.exports = new Load();
|
package/builder/objectcache.js
DELETED
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
const fs = require("fs-extra");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const EventEmitter = require("events");
|
|
4
|
-
|
|
5
|
-
function prettysize(bytes)
|
|
6
|
-
{
|
|
7
|
-
const prettysize = require("prettysize");
|
|
8
|
-
return prettysize(bytes, bytes >= 1024); // don't want 0Bytes
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
class ObjectCacheItem
|
|
12
|
-
{
|
|
13
|
-
constructor(response, headerSize)
|
|
14
|
-
{
|
|
15
|
-
this.headerSize = headerSize;
|
|
16
|
-
this.response = response;
|
|
17
|
-
this.cacheHits = 0;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get contentsSize() { return this.response.index.reduce((total, item) => { return total + item.bytes; }, 0); }
|
|
21
|
-
get fileSize() { return 4 + this.headerSize + this.contentsSize; }
|
|
22
|
-
// get headerSize
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
class PendingItem
|
|
26
|
-
{
|
|
27
|
-
constructor(response, path, dataBytes) // not including the metadata
|
|
28
|
-
{
|
|
29
|
-
this.response = response;
|
|
30
|
-
this.path = path;
|
|
31
|
-
this.remaining = dataBytes;
|
|
32
|
-
this.endCB = undefined;
|
|
33
|
-
this.file = fs.createWriteStream(path);
|
|
34
|
-
this.file.on("drain", () => {
|
|
35
|
-
// console.log("Got drain", this.buffer.length);
|
|
36
|
-
let buf = this.buffer;
|
|
37
|
-
this.buffer = undefined;
|
|
38
|
-
buf.forEach(b => this.write(b));
|
|
39
|
-
if (!this.buffer && this.endCB) {
|
|
40
|
-
this.file.end();
|
|
41
|
-
this.endCB();
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
this.buffer = undefined;
|
|
45
|
-
|
|
46
|
-
const json = Buffer.from(JSON.stringify(response));
|
|
47
|
-
const headerSizeBuffer = Buffer.allocUnsafe(4);
|
|
48
|
-
headerSizeBuffer.writeUInt32LE(json.length);
|
|
49
|
-
this.write(headerSizeBuffer);
|
|
50
|
-
this.write(json);
|
|
51
|
-
this.jsonLength = json.length;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
write(data) {
|
|
55
|
-
// console.log("GOT DATA", this.path, data.length, this.buffer);
|
|
56
|
-
if (this.buffer) {
|
|
57
|
-
this.buffer.push(data);
|
|
58
|
-
} else if (!this.file.write(data)) {
|
|
59
|
-
// console.log("Failed to write", data.length);
|
|
60
|
-
this.buffer = [];
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
end(cb)
|
|
64
|
-
{
|
|
65
|
-
if (this.buffer) {
|
|
66
|
-
this.endCB = cb;
|
|
67
|
-
} else {
|
|
68
|
-
this.file.end(cb);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
class ObjectCache extends EventEmitter
|
|
74
|
-
{
|
|
75
|
-
constructor(dir, maxSize, purgeSize)
|
|
76
|
-
{
|
|
77
|
-
super();
|
|
78
|
-
this.dir = dir;
|
|
79
|
-
fs.mkdirpSync(dir);
|
|
80
|
-
this.maxSize = maxSize;
|
|
81
|
-
this.purgeSize = purgeSize;
|
|
82
|
-
this.cache = {};
|
|
83
|
-
this.pending = {};
|
|
84
|
-
this.size = 0;
|
|
85
|
-
// console.log(fs.readdirSync(this.dir, { withFileTypes: true }));
|
|
86
|
-
try {
|
|
87
|
-
fs.readdirSync(this.dir).map(fileName => {
|
|
88
|
-
let ret = { path: path.join(this.dir, fileName) };
|
|
89
|
-
if (fileName.length == 32) {
|
|
90
|
-
try {
|
|
91
|
-
let stat = fs.statSync(ret.path);
|
|
92
|
-
if (stat.isFile()) {
|
|
93
|
-
ret.size = stat.size;
|
|
94
|
-
ret.atime = stat.atimeMs;
|
|
95
|
-
}
|
|
96
|
-
} catch (err) {
|
|
97
|
-
console.error("Got error stating", ret.path, err);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return ret;
|
|
101
|
-
}).sort((a, b) => a.atime - b.atime).forEach(item => {
|
|
102
|
-
this.loadFile(item.path, item.size);
|
|
103
|
-
});
|
|
104
|
-
} catch (err) {
|
|
105
|
-
console.error(`Got error reading directory ${dir}:`, err);
|
|
106
|
-
}
|
|
107
|
-
console.log("initializing object cache with", this.dir, "maxSize", prettysize(maxSize), "size", prettysize(this.size));
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
loadFile(filePath, fileSize)
|
|
111
|
-
{
|
|
112
|
-
let fileName = path.basename(filePath);
|
|
113
|
-
// console.log("got file", file);
|
|
114
|
-
let fd;
|
|
115
|
-
let jsonBuffer;
|
|
116
|
-
try {
|
|
117
|
-
if (fileName.length == 32) {
|
|
118
|
-
const headerSizeBuffer = Buffer.allocUnsafe(4);
|
|
119
|
-
fd = fs.openSync(filePath, "r");
|
|
120
|
-
const stat = fs.statSync(filePath);
|
|
121
|
-
fs.readSync(fd, headerSizeBuffer, 0, 4);
|
|
122
|
-
const headerSize = headerSizeBuffer.readUInt32LE(0);
|
|
123
|
-
// console.log("got headerSize", headerSize);
|
|
124
|
-
if (headerSize < 10 || headerSize > 1024 * 16)
|
|
125
|
-
throw new Error(`Got bad header size for ${fileName}: ${headerSize}`);
|
|
126
|
-
jsonBuffer = Buffer.allocUnsafe(headerSize);
|
|
127
|
-
fs.readSync(fd, jsonBuffer, 0, headerSize);
|
|
128
|
-
const response = JSON.parse(jsonBuffer.toString());
|
|
129
|
-
if (response.sha1 != fileName)
|
|
130
|
-
throw new Error(`Got bad filename: ${fileName} vs ${response.sha1}`);
|
|
131
|
-
let item = new ObjectCacheItem(response, headerSize);
|
|
132
|
-
if (item.fileSize != fileSize)
|
|
133
|
-
throw new Error(`Got bad size for ${fileName} expected ${item.fileSize} got ${fileSize}`);
|
|
134
|
-
fs.closeSync(fd);
|
|
135
|
-
this.size += item.fileSize;
|
|
136
|
-
this.cache[fileName] = item;
|
|
137
|
-
this.emit("added", { sha1: response.sha1, sourceFile: response.sourceFile, fileSize: stat.size });
|
|
138
|
-
} else {
|
|
139
|
-
throw new Error("Unexpected file " + fileName);
|
|
140
|
-
}
|
|
141
|
-
} catch (err) {
|
|
142
|
-
if (fd)
|
|
143
|
-
fs.closeSync(fd);
|
|
144
|
-
console.error("got failure", filePath, err, jsonBuffer ? jsonBuffer.toString().substr(0, 100) : undefined);
|
|
145
|
-
try {
|
|
146
|
-
fs.removeSync(filePath);
|
|
147
|
-
} catch (doubleError) {
|
|
148
|
-
console.error("Can't even delete this one", doubleError);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return undefined;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
state(sha1)
|
|
155
|
-
{
|
|
156
|
-
if (sha1 in this.cache) {
|
|
157
|
-
return "exists";
|
|
158
|
-
} else if (sha1 in this.pending) {
|
|
159
|
-
return "pending";
|
|
160
|
-
}
|
|
161
|
-
return "none";
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
get keys()
|
|
165
|
-
{
|
|
166
|
-
return Object.keys(this.cache);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
clear() {
|
|
170
|
-
this.purge(0);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
add(response, contents) {
|
|
174
|
-
if (response.sha1 in this.pending) {
|
|
175
|
-
console.log("Already writing this, I suppose this is possible", response);
|
|
176
|
-
return;
|
|
177
|
-
} else if (response.sha1 in this.cache) {
|
|
178
|
-
throw new Error("This should not happen. We already have " + response.sha1 + " in the cache");
|
|
179
|
-
}
|
|
180
|
-
let absolutePath = path.join(this.dir, response.sha1);
|
|
181
|
-
try {
|
|
182
|
-
fs.mkdirpSync(this.dir);
|
|
183
|
-
} catch (err) {
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
let remaining = 0;
|
|
187
|
-
response.index.forEach(file => { remaining += file.bytes; });
|
|
188
|
-
|
|
189
|
-
let pendingItem = new PendingItem(response, absolutePath, remaining);
|
|
190
|
-
pendingItem.file.on("error", err => {
|
|
191
|
-
console.error("Failed to write pendingItem", response, err);
|
|
192
|
-
delete this.pending[response.sha1];
|
|
193
|
-
});
|
|
194
|
-
this.pending[response.sha1] = pendingItem;
|
|
195
|
-
contents.forEach(c => pendingItem.write(c.contents));
|
|
196
|
-
pendingItem.end(() => {
|
|
197
|
-
if (this.pending[response.sha1] == pendingItem) {
|
|
198
|
-
let cacheItem = new ObjectCacheItem(response, pendingItem.jsonLength);
|
|
199
|
-
try {
|
|
200
|
-
let stat = fs.statSync(path.join(this.dir, response.sha1));
|
|
201
|
-
// console.log("stat is", stat.size, "for", path.join(this.dir, response.sha1));
|
|
202
|
-
// console.log("shit", cacheItem);
|
|
203
|
-
// console.log("ass", pendingItem);
|
|
204
|
-
if (cacheItem.fileSize != stat.size) {
|
|
205
|
-
throw new Error(`Wrong file size for ${path.join(this.dir, response.sha1)}, should have been ${cacheItem.fileSize} but ended up being ${stat.size}`);
|
|
206
|
-
}
|
|
207
|
-
this.cache[response.sha1] = cacheItem;
|
|
208
|
-
// console.log(response);
|
|
209
|
-
this.emit("added", { sha1: response.sha1, sourceFile: response.sourceFile, fileSize: cacheItem.fileSize });
|
|
210
|
-
|
|
211
|
-
this.size += cacheItem.fileSize;
|
|
212
|
-
if (this.size > this.maxSize)
|
|
213
|
-
this.purge(this.purgeSize);
|
|
214
|
-
console.log("Finished writing", response.sha1);
|
|
215
|
-
} catch (err) {
|
|
216
|
-
console.error("Something wrong", err);
|
|
217
|
-
try {
|
|
218
|
-
fs.unlinkSync(pendingItem.path);
|
|
219
|
-
} catch (err) {
|
|
220
|
-
if (err.code != "ENOENT")
|
|
221
|
-
console.error(`Failed to unlink ${pendingItem.path} ${err}`);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
delete this.pending[response.sha1];
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
get cacheHits()
|
|
231
|
-
{
|
|
232
|
-
let ret = 0;
|
|
233
|
-
for (let sha1 in this.cache) {
|
|
234
|
-
ret += this.cache[sha1].cacheHits;
|
|
235
|
-
}
|
|
236
|
-
return ret;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
info(query)
|
|
240
|
-
{
|
|
241
|
-
if (!query)
|
|
242
|
-
query = {};
|
|
243
|
-
const ret = Object.assign({ cacheHits: this.cacheHits, usage: ((this.size / this.maxSize) * 100).toFixed(1) }, this);
|
|
244
|
-
ret.count = Object.keys(ret.cache).length;
|
|
245
|
-
delete ret._events;
|
|
246
|
-
delete ret._eventsCount;
|
|
247
|
-
if (!("objects" in query))
|
|
248
|
-
delete ret.cache;
|
|
249
|
-
if (!("pending" in query))
|
|
250
|
-
delete ret.pending;
|
|
251
|
-
[ "maxSize", "size", "purgeSize" ].forEach(key => {
|
|
252
|
-
ret[key] = prettysize(ret[key]);
|
|
253
|
-
});
|
|
254
|
-
return ret;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
remove(sha1)
|
|
258
|
-
{
|
|
259
|
-
try {
|
|
260
|
-
const info = this.cache[sha1];
|
|
261
|
-
this.size -= info.fileSize;
|
|
262
|
-
delete this.cache[sha1];
|
|
263
|
-
this.emit("removed", { sha1: sha1, sourceFile: info.response.sourceFile, fileSize: info.fileSize });
|
|
264
|
-
fs.unlinkSync(path.join(this.dir, sha1));
|
|
265
|
-
} catch (err) {
|
|
266
|
-
console.error("Can't remove file", path.join(this.dir, sha1), err.toString());
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
purge(targetSize)
|
|
271
|
-
{
|
|
272
|
-
for (let sha1 in this.cache) {
|
|
273
|
-
if (this.size <= targetSize) {
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
console.log(`purging ${sha1} because ${this.size} >= ${targetSize}`);
|
|
277
|
-
this.remove(sha1);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
get(sha1, dontTouch)
|
|
282
|
-
{
|
|
283
|
-
let ret = this.cache[sha1];
|
|
284
|
-
if (!dontTouch && ret) {
|
|
285
|
-
delete this.cache[sha1];
|
|
286
|
-
this.cache[sha1] = ret;
|
|
287
|
-
}
|
|
288
|
-
return ret;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
syncData()
|
|
292
|
-
{
|
|
293
|
-
let ret = [];
|
|
294
|
-
for (let key in this.cache) {
|
|
295
|
-
ret.push({ sha1: key, fileSize: this.cache[key].fileSize });
|
|
296
|
-
}
|
|
297
|
-
return ret;
|
|
298
|
-
}
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
module.exports = ObjectCache;
|
package/builder/quit-on-error.js
DELETED
package/builder/server.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
const EventEmitter = require("events");
|
|
2
|
-
const WebSocket = require("ws");
|
|
3
|
-
const Url = require("url");
|
|
4
|
-
const http = require("http");
|
|
5
|
-
const express = require("express");
|
|
6
|
-
const zlib = require("zlib");
|
|
7
|
-
|
|
8
|
-
class Job extends EventEmitter {
|
|
9
|
-
constructor(data) {
|
|
10
|
-
super();
|
|
11
|
-
Object.assign(this, data);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
send(type, msg) {
|
|
15
|
-
if (this.ws.readyState !== WebSocket.OPEN)
|
|
16
|
-
return;
|
|
17
|
-
try {
|
|
18
|
-
if (msg === undefined) {
|
|
19
|
-
if (type instanceof Buffer) {
|
|
20
|
-
this.ws.send(type);
|
|
21
|
-
} else {
|
|
22
|
-
this.ws.send(JSON.stringify(type));
|
|
23
|
-
}
|
|
24
|
-
} else {
|
|
25
|
-
let tosend;
|
|
26
|
-
if (typeof msg === "object") {
|
|
27
|
-
tosend = msg;
|
|
28
|
-
tosend.type = type;
|
|
29
|
-
} else {
|
|
30
|
-
tosend = { type: type, message: msg };
|
|
31
|
-
}
|
|
32
|
-
this.ws.send(JSON.stringify(tosend));
|
|
33
|
-
}
|
|
34
|
-
} catch (err) {
|
|
35
|
-
console.error("got send error", this.id, type, err);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
get readyState() {
|
|
40
|
-
return this.ws.readyState;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
close() {
|
|
44
|
-
this.closed = true;
|
|
45
|
-
this.ws.close();
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
class Server extends EventEmitter {
|
|
50
|
-
constructor(option, configVersion) {
|
|
51
|
-
super();
|
|
52
|
-
this.option = option;
|
|
53
|
-
this.id = 0;
|
|
54
|
-
this.configVersion = configVersion;
|
|
55
|
-
this.app = undefined;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
listen() {
|
|
59
|
-
this.app = express();
|
|
60
|
-
this.emit("listen", this.app);
|
|
61
|
-
this.port = this.option.int("port", 8096);
|
|
62
|
-
|
|
63
|
-
this.server = http.createServer(this.app);
|
|
64
|
-
this.ws = new WebSocket.Server({ noServer: true, backlog: this.option.int("backlog", 50) });
|
|
65
|
-
this.server.listen({ port: this.port, backlog: this.option.int("backlog", 50), host: "0.0.0.0" });
|
|
66
|
-
|
|
67
|
-
this.server.on("upgrade", (req, socket, head) => {
|
|
68
|
-
this.ws.handleUpgrade(req, socket, head, (ws) => {
|
|
69
|
-
this._handleConnection(ws, req);
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
console.log("listening on", this.port);
|
|
74
|
-
this.ws.on("headers", (headers, request) => {
|
|
75
|
-
this.emit("headers", headers, request);
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
_handleConnection(ws, req) {
|
|
80
|
-
const connectTime = Date.now();
|
|
81
|
-
let client = undefined;
|
|
82
|
-
let bytes = undefined;
|
|
83
|
-
let ip = req.connection.remoteAddress;
|
|
84
|
-
let clientEmitted = false;
|
|
85
|
-
const error = msg => {
|
|
86
|
-
ws.send(`{"error": "${msg}"}`);
|
|
87
|
-
ws.close();
|
|
88
|
-
if (client && clientEmitted) {
|
|
89
|
-
client.emit("error", msg);
|
|
90
|
-
} else {
|
|
91
|
-
this.emit("error", { ip: ip, message: msg });
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
if (!ip) { // already closed
|
|
96
|
-
// console.log(req.connection, ws.readyState);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
if (ip.substr(0, 7) == "::ffff:") {
|
|
100
|
-
ip = ip.substr(7);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const url = Url.parse(req.url);
|
|
104
|
-
switch (url.pathname) {
|
|
105
|
-
case "/compile":
|
|
106
|
-
const hash = req.headers["x-fisk-environments"];
|
|
107
|
-
if (!hash) {
|
|
108
|
-
error("Bad ws request, no environments");
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const name = req.headers["x-fisk-client-name"];
|
|
112
|
-
const configVersion = req.headers["x-fisk-config-version"];
|
|
113
|
-
if (configVersion != this.configVersion) {
|
|
114
|
-
error(`Bad config version, expected ${this.configVersion}, got ${configVersion}`);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// console.log("GOT HEADERS", req.headers);
|
|
119
|
-
client = new Job({ ws: ws,
|
|
120
|
-
ip: ip,
|
|
121
|
-
hash: hash,
|
|
122
|
-
name: name,
|
|
123
|
-
hostname: req.headers["x-fisk-client-hostname"],
|
|
124
|
-
user: req.headers["x-fisk-user"],
|
|
125
|
-
sourceFile: req.headers["x-fisk-sourcefile"],
|
|
126
|
-
priority: parseInt(req.headers["x-fisk-priority"]) || 0,
|
|
127
|
-
sha1: req.headers["x-fisk-sha1"],
|
|
128
|
-
id: parseInt(req.headers["x-fisk-job-id"]),
|
|
129
|
-
builderIp: req.headers["x-fisk-builder-ip"] });
|
|
130
|
-
|
|
131
|
-
break;
|
|
132
|
-
default:
|
|
133
|
-
error(`Invalid pathname ${url.pathname}`);
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
ws.on("message", msg => {
|
|
138
|
-
switch (typeof msg) {
|
|
139
|
-
case "string":
|
|
140
|
-
// console.log("Got message", msg);
|
|
141
|
-
if (bytes) {
|
|
142
|
-
// bad, client have to send all the data in a binary message before sending JSON
|
|
143
|
-
error(`Got JSON message while ${bytes} bytes remained of a binary message`);
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
// assume JSON
|
|
147
|
-
let json;
|
|
148
|
-
try {
|
|
149
|
-
json = JSON.parse(msg);
|
|
150
|
-
} catch (e) {
|
|
151
|
-
}
|
|
152
|
-
if (json === undefined) {
|
|
153
|
-
error("Unable to parse string message as JSON");
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
bytes = json.bytes;
|
|
157
|
-
client.compressed = json.compressed;
|
|
158
|
-
client.commandLine = json.commandLine;
|
|
159
|
-
client.argv0 = json.argv0;
|
|
160
|
-
client.connectTime = connectTime;
|
|
161
|
-
client.wait = json.wait;
|
|
162
|
-
this.emit("job", client);
|
|
163
|
-
clientEmitted = true;
|
|
164
|
-
break;
|
|
165
|
-
case "object":
|
|
166
|
-
if (msg instanceof Buffer) {
|
|
167
|
-
// console.log("Got binary", msg.length, bytes);
|
|
168
|
-
if (!msg.length) {
|
|
169
|
-
// no data?
|
|
170
|
-
error("No data in buffer");
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
if (!bytes) {
|
|
174
|
-
error("Got binary message without a preceeding json message describing the data");
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
if (msg.length !== bytes) {
|
|
178
|
-
// woops
|
|
179
|
-
error(`length ${msg.length} !== ${bytes}`);
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
bytes = 0;
|
|
183
|
-
// console.log("GOT DATA", client.compressed, msg.length);
|
|
184
|
-
if (client.compressed) {
|
|
185
|
-
zlib.gunzip(msg, (err, data) => {
|
|
186
|
-
if (err) {
|
|
187
|
-
error(`Got error inflating data ${err}`);
|
|
188
|
-
} else {
|
|
189
|
-
client.emit("data", { data });
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
} else {
|
|
193
|
-
client.emit("data", { data: msg });
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
break;
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
ws.on("close", () => {
|
|
200
|
-
if (client && clientEmitted) {
|
|
201
|
-
// console.error("GOT WS CLOSE", bytes, client.objectcache);
|
|
202
|
-
client.emit("close");
|
|
203
|
-
}
|
|
204
|
-
ws.removeAllListeners();
|
|
205
|
-
});
|
|
206
|
-
ws.on("error", (error) => {
|
|
207
|
-
console.log("GOT WS ERROR", error);
|
|
208
|
-
if (client && clientEmitted)
|
|
209
|
-
client.emit("error", error);
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
module.exports = Server;
|
package/common/index.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
|
|
5
|
-
const Version = 5;
|
|
6
|
-
|
|
7
|
-
function cacheDir(option)
|
|
8
|
-
{
|
|
9
|
-
let dir = option("cache-dir");
|
|
10
|
-
if (!dir) {
|
|
11
|
-
dir = path.join(os.homedir(), ".cache", "fisk", path.basename(option.prefix));
|
|
12
|
-
}
|
|
13
|
-
return dir;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function validateCache(option)
|
|
17
|
-
{
|
|
18
|
-
const dir = cacheDir(option);
|
|
19
|
-
const file = path.join(dir, 'version');
|
|
20
|
-
// console.log(dir);
|
|
21
|
-
let version;
|
|
22
|
-
try {
|
|
23
|
-
version = fs.readFileSync(file);
|
|
24
|
-
if (version.readUInt32BE() == Version) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
} catch (err) {
|
|
28
|
-
}
|
|
29
|
-
if (version)
|
|
30
|
-
console.log(`Wrong version. Destroying cache ${dir}`);
|
|
31
|
-
fs.removeSync(dir);
|
|
32
|
-
fs.mkdirpSync(dir);
|
|
33
|
-
let buf = Buffer.allocUnsafe(4);
|
|
34
|
-
buf.writeUInt32BE(Version);
|
|
35
|
-
fs.writeFileSync(file, buf);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
module.exports = function(option) {
|
|
40
|
-
validateCache(option);
|
|
41
|
-
return {
|
|
42
|
-
cacheDir: cacheDir.bind(this, option),
|
|
43
|
-
Version: Version
|
|
44
|
-
};
|
|
45
|
-
};
|