@activeledger/activenetwork 2.15.6 → 4.3.3

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.
Files changed (79) hide show
  1. package/es/network/cpus.d.ts +1 -0
  2. package/es/network/cpus.d.ts.map +1 -1
  3. package/es/network/cpus.js +26 -15
  4. package/es/network/cpus.js.map +1 -1
  5. package/es/network/endpoints.d.ts +7 -3
  6. package/es/network/endpoints.d.ts.map +1 -1
  7. package/es/network/endpoints.js +685 -172
  8. package/es/network/endpoints.js.map +1 -1
  9. package/es/network/home.d.ts.map +1 -1
  10. package/es/network/home.js +41 -19
  11. package/es/network/home.js.map +1 -1
  12. package/es/network/host.d.ts +15 -7
  13. package/es/network/host.d.ts.map +1 -1
  14. package/es/network/host.js +631 -240
  15. package/es/network/host.js.map +1 -1
  16. package/es/network/locker.d.ts +10 -5
  17. package/es/network/locker.d.ts.map +1 -1
  18. package/es/network/locker.js +50 -17
  19. package/es/network/locker.js.map +1 -1
  20. package/es/network/maintain.d.ts.map +1 -1
  21. package/es/network/maintain.js +42 -42
  22. package/es/network/maintain.js.map +1 -1
  23. package/es/network/neighbour.d.ts +8 -4
  24. package/es/network/neighbour.d.ts.map +1 -1
  25. package/es/network/neighbour.js +82 -18
  26. package/es/network/neighbour.js.map +1 -1
  27. package/es/network/neighbourhood.d.ts +1 -1
  28. package/es/network/neighbourhood.d.ts.map +1 -1
  29. package/es/network/neighbourhood.js +39 -42
  30. package/es/network/neighbourhood.js.map +1 -1
  31. package/es/network/p2pClient.d.ts +20 -0
  32. package/es/network/p2pClient.d.ts.map +1 -0
  33. package/es/network/p2pClient.js +84 -0
  34. package/es/network/p2pClient.js.map +1 -0
  35. package/es/network/process.js +99 -65
  36. package/es/network/process.js.map +1 -1
  37. package/es/network/utils.d.ts.map +1 -1
  38. package/es/network/utils.js +17 -21
  39. package/es/network/utils.js.map +1 -1
  40. package/lib/network/cpus.d.ts +1 -0
  41. package/lib/network/cpus.d.ts.map +1 -1
  42. package/lib/network/cpus.js +26 -15
  43. package/lib/network/cpus.js.map +1 -1
  44. package/lib/network/endpoints.d.ts +7 -3
  45. package/lib/network/endpoints.d.ts.map +1 -1
  46. package/lib/network/endpoints.js +684 -171
  47. package/lib/network/endpoints.js.map +1 -1
  48. package/lib/network/home.d.ts.map +1 -1
  49. package/lib/network/home.js +41 -19
  50. package/lib/network/home.js.map +1 -1
  51. package/lib/network/host.d.ts +15 -7
  52. package/lib/network/host.d.ts.map +1 -1
  53. package/lib/network/host.js +630 -239
  54. package/lib/network/host.js.map +1 -1
  55. package/lib/network/locker.d.ts +10 -5
  56. package/lib/network/locker.d.ts.map +1 -1
  57. package/lib/network/locker.js +50 -17
  58. package/lib/network/locker.js.map +1 -1
  59. package/lib/network/maintain.d.ts.map +1 -1
  60. package/lib/network/maintain.js +42 -42
  61. package/lib/network/maintain.js.map +1 -1
  62. package/lib/network/neighbour.d.ts +8 -4
  63. package/lib/network/neighbour.d.ts.map +1 -1
  64. package/lib/network/neighbour.js +82 -18
  65. package/lib/network/neighbour.js.map +1 -1
  66. package/lib/network/neighbourhood.d.ts +1 -1
  67. package/lib/network/neighbourhood.d.ts.map +1 -1
  68. package/lib/network/neighbourhood.js +39 -42
  69. package/lib/network/neighbourhood.js.map +1 -1
  70. package/lib/network/p2pClient.d.ts +20 -0
  71. package/lib/network/p2pClient.d.ts.map +1 -0
  72. package/lib/network/p2pClient.js +88 -0
  73. package/lib/network/p2pClient.js.map +1 -0
  74. package/lib/network/process.js +98 -64
  75. package/lib/network/process.js.map +1 -1
  76. package/lib/network/utils.d.ts.map +1 -1
  77. package/lib/network/utils.js +17 -21
  78. package/lib/network/utils.js.map +1 -1
  79. package/package.json +10 -8
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Host = void 0;
4
- const http_1 = require("http");
5
4
  const child_process_1 = require("child_process");
6
5
  const fs_1 = require("fs");
7
6
  const path_1 = require("path");
7
+ const net = require("net");
8
8
  const activeoptions_1 = require("@activeledger/activeoptions");
9
9
  const activecrypto_1 = require("@activeledger/activecrypto");
10
10
  const activelogger_1 = require("@activeledger/activelogger");
@@ -15,80 +15,72 @@ const index_1 = require("./index");
15
15
  const locker_1 = require("./locker");
16
16
  const cpus_1 = require("./cpus");
17
17
  const process = require("process");
18
- const RELEASE_SHUTDOWN_TIMEOUT = 5 * 60 * 1000;
19
- const RELEASE_DELETE_TIMEOUT = 1 * 60 * 1000;
20
- const TIMER_QUEUE_INTERVAL = 10 * 1000;
18
+ const uWebSockets_js_1 = require("uWebSockets.js");
19
+ const RELEASE_SHUTDOWN_TIMEOUT = 1 * 60 * 1000;
20
+ const RELEASE_DELETE_TIMEOUT = 2 * 60 * 1000;
21
+ const TIMER_QUEUE_INTERVAL = 2 * 1000;
21
22
  const GRACEFUL_PROC_SHUTDOWN = 7 * 60 * 1000;
22
23
  const KILL_PROC_SHUTDOWN = 2.5 * 1000;
24
+ const MAX_RETRIES = 35;
25
+ function peekBytes(chunks, n) {
26
+ if (chunks.length > 0 && chunks[0].length >= n) {
27
+ return chunks[0];
28
+ }
29
+ let total = 0;
30
+ let end = 0;
31
+ while (end < chunks.length && total < n) {
32
+ total += chunks[end].length;
33
+ end++;
34
+ }
35
+ return Buffer.concat(chunks.slice(0, end));
36
+ }
23
37
  class Host extends home_1.Home {
24
- constructor() {
25
- super();
26
- this.processPending = {};
27
- this.cpuReady = 0;
28
- this.busyLocksQueue = [];
29
- let db = activeoptions_1.ActiveOptions.get("db", {});
30
- this.dbConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.database);
31
- this.dbConnection.info();
32
- this.dbErrorConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.error);
33
- this.dbErrorConnection.info();
34
- this.dbEventConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.event);
35
- this.dbEventConnection.info();
36
- this.hybridHosts = activeoptions_1.ActiveOptions.get("hybrid", []);
37
- if (this.hybridHosts.length) {
38
- for (let i = this.hybridHosts.length; i--;) {
39
- const hybrid = this.hybridHosts[i];
40
- hybrid.docName = activecrypto_1.ActiveCrypto.Hash.getHash(hybrid.url + hybrid.auth);
41
- }
38
+ p2pServer;
39
+ listenSocket;
40
+ api;
41
+ dbConnection;
42
+ dbErrorConnection;
43
+ dbEventConnection;
44
+ processPending = {};
45
+ cpuReady = 0;
46
+ hybridHosts;
47
+ busyLocksQueue = { internal: [], external: [] };
48
+ shutdown() {
49
+ if (this.listenSocket) {
50
+ (0, uWebSockets_js_1.us_listen_socket_close)(this.listenSocket);
51
+ this.listenSocket = null;
52
+ setTimeout(() => {
53
+ activelogger_1.ActiveLogger.info("Stopping HTTP Server");
54
+ this.api.close();
55
+ activelogger_1.ActiveLogger.info("Shutting down...");
56
+ process.exit(0);
57
+ }, 1300);
42
58
  }
43
- this.api = (0, http_1.createServer)((req, res) => {
44
- activelogger_1.ActiveLogger.debug(`Request - ${req.connection.remoteAddress} @ ${req.method}:${req.url}`);
45
- if (req.method == "POST") {
46
- const body = [];
47
- req.on("data", (chunk) => {
48
- body.push(chunk);
49
- });
50
- req.on("end", async () => {
51
- let data = Buffer.concat(body);
52
- if (req.headers["content-encoding"] == "gzip" ||
53
- (data[0] == 0x1f && data[1] == 0x8b)) {
54
- try {
55
- data = await activeoptions_1.ActiveGZip.ungzip(data);
56
- }
57
- catch (_a) {
59
+ }
60
+ pending(entry, remoteAddr, internal = false, forceRestart = false, isP2P = false) {
61
+ return new Promise(async (resolve, reject) => {
62
+ if (entry.$broadcast && entry.$nodes) {
63
+ const nodeSpoofCheck = Object.keys(entry.$nodes);
64
+ if (nodeSpoofCheck.length) {
65
+ for (let i = nodeSpoofCheck.length; i--;) {
66
+ const nodeCheck = nodeSpoofCheck[i];
67
+ if (!this.neighbourhood.checkFirewall(remoteAddr, nodeCheck)) {
68
+ return reject("Bad Neighbour Payload");
58
69
  }
59
70
  }
60
- index_1.Endpoints.postConvertor(this, data.toString(), req.headers["x-activeledger-encrypt"] ||
61
- false)
62
- .then((body) => {
63
- this.processEndpoints(req, res, body.body, body.from);
64
- })
65
- .catch((error) => {
66
- this.writeResponse(res, error.statusCode || 500, JSON.stringify(error.content || {}), req.headers["accept-encoding"]);
67
- });
68
- });
71
+ }
69
72
  }
70
- else {
71
- this.processEndpoints(req, res);
73
+ if (forceRestart && this.processPending[entry.$umid]) {
74
+ this.destroy(entry.$umid, true);
75
+ delete this.processPending[entry.$umid];
72
76
  }
73
- });
74
- const cpuTotal = cpus_1.PhysicalCores.count();
75
- const latestSetupMsg = this.getLatestSetup();
76
- for (let i = 0; i < cpuTotal; i++) {
77
- const processor = this.createProcessor(cpuTotal);
78
- this.processors.push(processor);
79
- processor.send(latestSetupMsg);
80
- }
81
- this.standbyProcess = this.createProcessor(cpuTotal);
82
- this.standbyProcess.send(latestSetupMsg);
83
- this.processorIterator = this.processors[Symbol.iterator]();
84
- this.timerQueue();
85
- }
86
- pending(entry, internal = false) {
87
- return new Promise((resolve, reject) => {
88
77
  if (entry.$broadcast) {
89
78
  if (this.processPending[entry.$umid]) {
90
- activelogger_1.ActiveLogger.debug("Broadcast Recieved : " + entry.$umid);
91
- if (this.processPending[entry.$umid].pid) {
79
+ if (!this.processPending[entry.$umid]?.finished &&
80
+ this.processPending[entry.$umid]?.pid &&
81
+ !this.processPending[entry.$umid]?.entry?.$nodes?.[this.reference]
82
+ ?.leader) {
83
+ activelogger_1.ActiveLogger.debug(`Broadcast Recieved [${isP2P ? "P2P" : "HTTP"}] : ` + entry.$umid);
92
84
  const processor = this.findProcessor(this.processPending[entry.$umid].pid);
93
85
  if (processor) {
94
86
  processor.send({
@@ -102,35 +94,327 @@ class Host extends home_1.Home {
102
94
  else {
103
95
  }
104
96
  }
97
+ else {
98
+ const pendingEntry = this.processPending[entry.$umid]?.entry;
99
+ if (pendingEntry) {
100
+ delete entry.$nodes[this.reference];
101
+ pendingEntry.$nodes = { ...pendingEntry.$nodes, ...entry.$nodes };
102
+ }
103
+ }
104
+ if (!entry.$$noreply) {
105
+ this.broadcast(entry.$umid, false, true);
106
+ }
105
107
  return resolve({
106
108
  status: 200,
107
109
  data: this.processPending[entry.$umid].entry,
110
+ dontRelease: true,
108
111
  });
109
112
  }
110
113
  }
111
114
  if (!this.processPending[entry.$umid]) {
112
115
  this.processPending[entry.$umid] = {
113
- entry: entry,
116
+ entry,
114
117
  resolve: (response) => {
115
- this.release({ entry, resolve: null, reject: null, pid: 0 });
116
- resolve(response);
118
+ if (internal && this.processPending[entry.$umid]?.responded) {
119
+ this.release(entry.$umid);
120
+ }
121
+ if (this.processPending[entry.$umid]) {
122
+ this.processPending[entry.$umid].finished = true;
123
+ }
124
+ if (!this.processPending[entry.$umid]?.responded) {
125
+ resolve(response);
126
+ try {
127
+ this.processPending[entry.$umid].responded = true;
128
+ activelogger_1.ActiveLogger.debug("Client Response TX : " + entry.$umid);
129
+ }
130
+ catch { }
131
+ }
117
132
  },
118
133
  reject: (response) => {
119
- this.release({ entry, resolve: null, reject: null, pid: 0 });
120
- reject(response);
134
+ if (this.processPending[entry.$umid]) {
135
+ this.processPending[entry.$umid].finished = true;
136
+ }
137
+ if (!this.processPending[entry.$umid]?.responded) {
138
+ reject(response);
139
+ try {
140
+ this.processPending[entry.$umid].responded = true;
141
+ }
142
+ catch { }
143
+ }
121
144
  },
122
145
  pid: 0,
146
+ finished: false,
147
+ responded: false,
123
148
  };
149
+ if (entry.$tx.$expire && remoteAddr !== this.host) {
150
+ if (await this.dbConnection.exists(`${entry.$umid}:umid`)) {
151
+ if (entry.$nodes) {
152
+ entry.$nodes[this.reference] = {
153
+ vote: false,
154
+ commit: false,
155
+ error: `Transaction Exists : ${entry.$umid}`,
156
+ };
157
+ }
158
+ else {
159
+ entry.$nodes = {
160
+ [this.reference]: {
161
+ vote: false,
162
+ commit: false,
163
+ error: `Transaction Exists : ${entry.$umid}`,
164
+ },
165
+ };
166
+ }
167
+ return this.processPending[entry.$umid].resolve({
168
+ status: 200,
169
+ data: entry,
170
+ });
171
+ }
172
+ }
124
173
  this.processQueue(entry, internal);
174
+ if (internal && entry.$broadcast) {
175
+ this.processPending[entry.$umid].responded = true;
176
+ return resolve({
177
+ status: 200,
178
+ data: { ok: true },
179
+ dontRelease: true,
180
+ });
181
+ }
125
182
  }
126
183
  else {
127
184
  return resolve({
128
185
  status: 200,
129
186
  data: this.processPending[entry.$umid].entry,
187
+ dontRelease: true,
130
188
  });
131
189
  }
132
190
  });
133
191
  }
192
+ constructor() {
193
+ super();
194
+ if (activeoptions_1.ActiveOptions.get("p2pStreamServer", false)) {
195
+ this.p2pServer = net.createServer((socket) => {
196
+ activelogger_1.ActiveLogger.info(`P2P TCP connection accepted from ${socket.remoteAddress}`);
197
+ let chunks = [];
198
+ let bufferLength = 0;
199
+ socket.on("data", async (data) => {
200
+ chunks.push(data);
201
+ bufferLength += data.length;
202
+ while (bufferLength >= 44) {
203
+ const header = peekBytes(chunks, 44);
204
+ const length = header.readUInt32BE(40);
205
+ if (bufferLength >= 44 + length) {
206
+ const fullBuffer = Buffer.concat(chunks);
207
+ const senderRef = fullBuffer.slice(0, 40).toString().trim();
208
+ const item = fullBuffer.slice(44, 44 + length);
209
+ const remaining = fullBuffer.slice(44 + length);
210
+ chunks = remaining.length > 0 ? [remaining] : [];
211
+ bufferLength = remaining.length;
212
+ const tx = await activeoptions_1.ActiveClone.deserialize(item);
213
+ this.processEndpoints({
214
+ headers: { "X-Activeledger": senderRef },
215
+ method: "POST",
216
+ url: "/a/init",
217
+ connection: { remoteAddress: socket.remoteAddress || "127.0.0.1" },
218
+ }, null, tx, senderRef, true);
219
+ }
220
+ else {
221
+ break;
222
+ }
223
+ }
224
+ });
225
+ socket.on("error", (err) => {
226
+ activelogger_1.ActiveLogger.error(err, "P2P socket error");
227
+ });
228
+ });
229
+ const p2pPort = parseInt(utils_1.ActiveInterfaces.getBindingDetails("port")) + 1;
230
+ this.p2pServer.listen(p2pPort, () => {
231
+ activelogger_1.ActiveLogger.info(`P2P TCP server listening on port ${p2pPort}`);
232
+ });
233
+ }
234
+ let db = activeoptions_1.ActiveOptions.get("db", {});
235
+ this.dbConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.database);
236
+ this.dbConnection.info();
237
+ this.dbErrorConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.error);
238
+ this.dbErrorConnection.info();
239
+ this.dbEventConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.event);
240
+ this.dbEventConnection.info();
241
+ this.hybridHosts = activeoptions_1.ActiveOptions.get("hybrid", []);
242
+ if (this.hybridHosts.length) {
243
+ for (let i = this.hybridHosts.length; i--;) {
244
+ const hybrid = this.hybridHosts[i];
245
+ hybrid.docName = activecrypto_1.ActiveCrypto.Hash.getHash(hybrid.url + hybrid.auth);
246
+ }
247
+ }
248
+ this.api = (0, uWebSockets_js_1.App)();
249
+ this.api.any("/*", async (res, req) => {
250
+ res.onAborted(() => {
251
+ res.writable = false;
252
+ });
253
+ res.writable = true;
254
+ const headers = {
255
+ "Accept-Encoding": req.getHeader("accept-encoding"),
256
+ "X-Activeledger": req.getHeader("x-activeledger"),
257
+ "x-activeledger-encrypt": req.getHeader("x-activeledger-encrypt"),
258
+ "content-encoding": req.getHeader("content-encoding"),
259
+ "X-Bundle": req.getHeader("x-bundle"),
260
+ };
261
+ const method = req.getMethod().toUpperCase();
262
+ const url = req.getUrl();
263
+ let ipFrom = Buffer.from(res.getProxiedRemoteAddressAsText().byteLength
264
+ ? res.getProxiedRemoteAddressAsText()
265
+ : res.getRemoteAddressAsText()).toString();
266
+ if (ipFrom.indexOf(":") !== -1) {
267
+ const ip6 = this.parseIp6(ipFrom);
268
+ ipFrom =
269
+ (ip6[6] >> 8) +
270
+ "." +
271
+ (ip6[6] & 0xff) +
272
+ "." +
273
+ (ip6[7] >> 8) +
274
+ "." +
275
+ (ip6[7] & 0xff);
276
+ }
277
+ if (method === "POST") {
278
+ let body = await this.readBuffer(res);
279
+ if (headers["content-encoding"] == "gzip" ||
280
+ (body[0] == 0x1f && body[1] == 0x8b)) {
281
+ try {
282
+ body = await activeoptions_1.ActiveGZip.ungzip(body);
283
+ }
284
+ catch (e) {
285
+ }
286
+ }
287
+ const bodyString = (await this.makeSureNotBuffer(body));
288
+ let bundles;
289
+ if (headers["X-Bundle"]) {
290
+ bundles = bodyString.split(":$ALB:");
291
+ res.cork(() => {
292
+ res.writeStatus("200");
293
+ res.writeHeader("Content-Type", "application/json");
294
+ res.end("{}");
295
+ });
296
+ res.writable = false;
297
+ }
298
+ else {
299
+ bundles = [bodyString];
300
+ }
301
+ for (let i = bundles.length; i--;) {
302
+ if (bundles[i]) {
303
+ index_1.Endpoints.postConvertor(this, bundles[i], headers["x-activeledger-encrypt"] || false)
304
+ .then((body) => {
305
+ this.processEndpoints({
306
+ headers,
307
+ method,
308
+ url,
309
+ connection: {
310
+ remoteAddress: ipFrom,
311
+ },
312
+ }, res, body.body, body.from);
313
+ })
314
+ .catch((error) => {
315
+ activelogger_1.ActiveLogger.error(error, "Server POST Parser 500");
316
+ this.writeResponse(res, error.statusCode || 500, JSON.stringify(error.content || { error: 1 }), headers["Accept-Encoding"]);
317
+ })
318
+ .finally(() => {
319
+ });
320
+ }
321
+ }
322
+ }
323
+ else {
324
+ if (method === "OPTIONS") {
325
+ await this.writeResponse(res, 200, "{}", "", true);
326
+ }
327
+ else {
328
+ await this.processEndpoints({
329
+ headers,
330
+ method,
331
+ url,
332
+ connection: {
333
+ remoteAddress: ipFrom,
334
+ },
335
+ }, res);
336
+ }
337
+ }
338
+ });
339
+ const cpuTotal = parseInt(activeoptions_1.ActiveOptions.get("cpus", "0")) || cpus_1.PhysicalCores.count();
340
+ const latestSetupMsg = this.getLatestSetup();
341
+ for (let i = 0; i < cpuTotal; i++) {
342
+ const processor = this.createProcessor(cpuTotal);
343
+ this.processors.push(processor);
344
+ processor.send(latestSetupMsg);
345
+ }
346
+ this.standbyProcess = this.createProcessor(cpuTotal);
347
+ this.standbyProcess.send(latestSetupMsg);
348
+ this.processorIterator = this.processors[Symbol.iterator]();
349
+ this.timerQueue();
350
+ }
351
+ readBuffer(res) {
352
+ return new Promise((resolve, reject) => {
353
+ const chunks = [];
354
+ res.onData((ab, isLast) => {
355
+ if (res.aborted) {
356
+ reject(new Error("Request aborted"));
357
+ return;
358
+ }
359
+ if (ab.byteLength > 0) {
360
+ const buffer = Buffer.allocUnsafe(ab.byteLength);
361
+ buffer.set(new Uint8Array(ab));
362
+ chunks.push(buffer);
363
+ }
364
+ if (isLast) {
365
+ resolve(chunks.length === 0
366
+ ? Buffer.alloc(0)
367
+ : chunks.length === 1
368
+ ? chunks[0]
369
+ : Buffer.concat(chunks));
370
+ }
371
+ });
372
+ });
373
+ }
374
+ parseIp6(str) {
375
+ var ar = new Array();
376
+ for (var i = 0; i < 8; i++)
377
+ ar[i] = 0;
378
+ if (str == "::")
379
+ return ar;
380
+ var sar = str.split(":");
381
+ var slen = sar.length;
382
+ if (slen > 8)
383
+ slen = 8;
384
+ var j = 0;
385
+ for (var i = 0; i < slen; i++) {
386
+ if (i && sar[i] == "") {
387
+ j = 9 - slen + i;
388
+ continue;
389
+ }
390
+ ar[j] = parseInt("0x0" + sar[i]);
391
+ j++;
392
+ }
393
+ return ar;
394
+ }
395
+ async makeSureNotBuffer(obj) {
396
+ if (obj.type === "Buffer" && obj.data?.length) {
397
+ if (obj.data[0] == 0x1f && obj.data[1] == 0x8b) {
398
+ return (await activeoptions_1.ActiveGZip.ungzip(Buffer.from(obj.data))).toString();
399
+ }
400
+ return Buffer.from(obj.data).toString();
401
+ }
402
+ if (Buffer.isBuffer(obj)) {
403
+ if (obj[0] == 0x1f && obj[1] == 0x8b) {
404
+ return (await activeoptions_1.ActiveGZip.ungzip(obj)).toString();
405
+ }
406
+ const tmp = obj.toString();
407
+ if (tmp.startsWith('{"type":"Buffer"')) {
408
+ const asBufferObj = JSON.parse(tmp);
409
+ if (asBufferObj.data[0] == 0x1f && asBufferObj.data[1] == 0x8b) {
410
+ return (await activeoptions_1.ActiveGZip.ungzip(Buffer.from(asBufferObj.data))).toString();
411
+ }
412
+ return Buffer.from(asBufferObj.data).toString();
413
+ }
414
+ return obj.toString();
415
+ }
416
+ return obj;
417
+ }
134
418
  getLatestSetup() {
135
419
  return {
136
420
  type: "setup",
@@ -154,29 +438,33 @@ class Host extends home_1.Home {
154
438
  pFork.stop = false;
155
439
  let unloadHandled = false;
156
440
  const unloadProcessorSafely = (...error) => {
157
- if (unloadHandled) {
158
- activelogger_1.ActiveLogger.fatal(error, "Processor Crashed - Already Shutting Down");
441
+ if (unloadHandled || !this.listenSocket) {
159
442
  }
160
443
  else {
161
444
  pFork.stop = unloadHandled = true;
162
445
  activelogger_1.ActiveLogger.fatal(error, "Processor Crashed");
163
446
  this.processors.push(this.standbyProcess);
164
447
  this.standbyProcess = this.createProcessor();
165
- this.standbyProcess.send(this.getLatestSetup());
448
+ setTimeout(() => {
449
+ this.standbyProcess.send(this.getLatestSetup(), (e) => {
450
+ if (e) {
451
+ activelogger_1.ActiveLogger.fatal(e, "Issue with new Standby Process");
452
+ }
453
+ });
454
+ }, 1000);
166
455
  activelogger_1.ActiveLogger.fatal(pFork, "Will Gracefully Shutdown in " + GRACEFUL_PROC_SHUTDOWN);
167
456
  setTimeout(() => {
168
457
  activelogger_1.ActiveLogger.fatal(pFork, "Starting Graceful Shutdown");
169
458
  const pendings = Object.keys(this.processPending);
170
459
  pendings.forEach((key) => {
171
460
  let pending = this.processPending[key];
172
- if ((pending === null || pending === void 0 ? void 0 : pending.pid) === pFork.pid) {
461
+ if (pending?.pid === pFork.pid) {
173
462
  pending.entry.$nodes[this.reference].error =
174
463
  "(Contract Thread Error) Unknown - Try Again";
175
464
  pending.resolve({
176
465
  status: 200,
177
466
  data: pending.entry,
178
467
  });
179
- this.release(pending);
180
468
  }
181
469
  });
182
470
  activelogger_1.ActiveLogger.fatal(pFork, "Will Kill in " + KILL_PROC_SHUTDOWN);
@@ -194,10 +482,9 @@ class Host extends home_1.Home {
194
482
  }
195
483
  };
196
484
  pFork.on("message", (m) => {
197
- var _a;
198
485
  const pending = this.processPending[m.data.umid];
199
486
  if (pending) {
200
- if (m.data.nodes) {
487
+ if (m.data.nodes && !m.data.early) {
201
488
  pending.entry.$nodes = {
202
489
  ...pending.entry.$nodes,
203
490
  ...m.data.nodes,
@@ -216,12 +503,10 @@ class Host extends home_1.Home {
216
503
  return;
217
504
  pending.resolve({
218
505
  status: 200,
219
- data: pending.entry,
506
+ data: m.data.entry
507
+ ? { ...pending.entry, ...m.data.entry }
508
+ : pending.entry,
220
509
  });
221
- this.release(pending);
222
- if (m.data && this.hybridHosts.length) {
223
- this.processHybridNodes(pending.entry);
224
- }
225
510
  break;
226
511
  case "commited":
227
512
  if (!pending)
@@ -230,9 +515,8 @@ class Host extends home_1.Home {
230
515
  status: 200,
231
516
  data: { ...pending.entry, ...m.data.entry },
232
517
  });
233
- this.release(pending);
234
518
  if (this.hybridHosts.length) {
235
- this.processHybridNodes(pending.entry, (_a = m.data.entry) === null || _a === void 0 ? void 0 : _a.$streams);
519
+ this.processHybridNodes(pending.entry, m.data.entry?.$streams);
236
520
  }
237
521
  break;
238
522
  case "broadcast":
@@ -244,8 +528,10 @@ class Host extends home_1.Home {
244
528
  case "ready":
245
529
  if (cpuTotal) {
246
530
  this.cpuReady++;
247
- if (!this.api.listening && this.cpuReady >= cpuTotal) {
248
- this.api.listen(utils_1.ActiveInterfaces.getBindingDetails("port"), () => {
531
+ if (!this.listeing && this.cpuReady >= cpuTotal) {
532
+ this.listeing = true;
533
+ this.api.listen(utils_1.ActiveInterfaces.getBindingDetails("port"), (token) => {
534
+ this.listenSocket = token;
249
535
  activelogger_1.ActiveLogger.info("Activeledger listening on port " +
250
536
  utils_1.ActiveInterfaces.getBindingDetails("port"));
251
537
  });
@@ -259,10 +545,12 @@ class Host extends home_1.Home {
259
545
  status: 200,
260
546
  data: { ...pending.entry, ...m.data.entry },
261
547
  });
262
- this.release(pending);
263
548
  }
264
- unloadProcessorSafely("unhandledrejection - Already Handled, Tidying up processes");
549
+ if (!m.data.recoverable) {
550
+ unloadProcessorSafely("unhandledrejection - Already Handled, Tidying up processes");
551
+ }
265
552
  break;
553
+ case "contractData":
266
554
  case "contractLatestVersion":
267
555
  this.processors.forEach((processor) => {
268
556
  processor.send(m);
@@ -279,6 +567,7 @@ class Host extends home_1.Home {
279
567
  pFork.on("error", unloadProcessorSafely);
280
568
  return pFork;
281
569
  }
570
+ listeing = false;
282
571
  reload() {
283
572
  activeoptions_1.ActiveOptions.extendConfig()
284
573
  .then((config) => {
@@ -307,57 +596,73 @@ class Host extends home_1.Home {
307
596
  activelogger_1.ActiveLogger.info(e, "Failed to reload Neighbourhood");
308
597
  });
309
598
  }
310
- destroy(umid) {
311
- var _a;
599
+ destroy(umid, skipTimeout = false) {
312
600
  if (this.processPending[umid]) {
313
601
  this.processPending[umid].shutdown = true;
314
- (_a = this.findProcessor(this.processPending[umid].pid)) === null || _a === void 0 ? void 0 : _a.send({
602
+ this.findProcessor(this.processPending[umid].pid)?.send({
315
603
  type: "destory",
316
604
  data: {
317
605
  umid,
606
+ skipTimeout,
318
607
  },
319
608
  });
320
- setTimeout(() => {
321
- delete this.processPending[umid];
322
- }, RELEASE_DELETE_TIMEOUT);
609
+ if (!skipTimeout) {
610
+ setTimeout(() => {
611
+ delete this.processPending[umid];
612
+ }, RELEASE_DELETE_TIMEOUT);
613
+ }
323
614
  }
324
615
  }
325
- broadcast(umid, early = false) {
326
- var _a;
327
- if (((_a = this.processPending[umid]) === null || _a === void 0 ? void 0 : _a.entry) &&
616
+ broadcast(umid, early = false, noreply = false) {
617
+ if (this.processPending[umid] && this.processPending[umid].broadcasting) {
618
+ return;
619
+ }
620
+ if (this.processPending[umid]?.entry &&
328
621
  this.processPending[umid].entry.$broadcast &&
329
622
  this.processPending[umid].entry.$nodes &&
330
- this.processPending[umid].entry.$nodes[this.reference]) {
331
- activelogger_1.ActiveLogger.debug("Broadcasting TX : " + umid);
623
+ (early ||
624
+ (this.processPending[umid].entry.$nodes[this.reference] &&
625
+ "vote" in this.processPending[umid].entry.$nodes[this.reference]))) {
626
+ this.processPending[umid].broadcasting = true;
627
+ activelogger_1.ActiveLogger.debug(`Broadcasting TX ($$NR ${noreply}) : ` + umid);
332
628
  let neighbourhood = this.neighbourhood.get();
333
629
  let nodes = this.neighbourhood.keys();
334
- let i = nodes.length;
335
630
  let promises = [];
336
- const data = !early
631
+ const selfEntry = this.processPending[umid].entry.$nodes[this.reference];
632
+ const data = selfEntry && !selfEntry.early
337
633
  ? Object.assign(this.processPending[umid].entry, {
338
634
  $nodes: {
339
- [this.reference]: this.processPending[umid].entry.$nodes[this.reference],
635
+ [this.reference]: selfEntry,
340
636
  },
341
637
  })
342
638
  : Object.assign(this.processPending[umid].entry, {
343
639
  $nodes: {},
344
640
  });
345
641
  if (data) {
346
- while (i--) {
642
+ data.$$noreply = noreply;
643
+ if (early) {
644
+ data.$$noreply = true;
645
+ }
646
+ for (let i = nodes.length; i--;) {
347
647
  let node = neighbourhood[nodes[i]];
348
- if (node.isHome && node.reference !== this.reference) {
349
- promises.push(node.knock("init", data));
648
+ if (node.isHome &&
649
+ node.reference !==
650
+ this
651
+ .reference) {
652
+ promises.push(node.knock("init", data, false, 0, true));
350
653
  }
351
654
  }
655
+ Promise.all(promises)
656
+ .then(() => {
657
+ this.processPending[umid].broadcasting = false;
658
+ })
659
+ .catch(() => {
660
+ this.processPending[umid].broadcasting = false;
661
+ setTimeout(() => {
662
+ this.broadcastResolver(umid);
663
+ }, 250);
664
+ });
352
665
  }
353
- Promise.all(promises)
354
- .then(() => {
355
- })
356
- .catch(() => {
357
- setTimeout(() => {
358
- this.broadcastResolver(umid);
359
- }, 500);
360
- });
361
666
  }
362
667
  }
363
668
  broadcastResolver(umid) {
@@ -377,14 +682,18 @@ class Host extends home_1.Home {
377
682
  },
378
683
  reason: "Failed to rebroadcast while in memory",
379
684
  };
380
- this.dbErrorConnection.post(doc);
685
+ this.dbErrorConnection.post(doc).catch((error) => {
686
+ activelogger_1.ActiveLogger.error(error, "Failed to write rebroadcast-failure error document");
687
+ });
381
688
  }
382
689
  }
383
690
  labelOrKey(txIO) {
384
691
  const keys = Object.keys(txIO || {});
385
692
  const out = [];
386
693
  for (let i = keys.length; i--;) {
387
- out.push(this.filterPrefix(txIO[keys[i]].$stream || keys[i]));
694
+ if (!txIO[keys[i]].$sigOnly) {
695
+ out.push(this.filterPrefix(txIO[keys[i]].$stream || keys[i]));
696
+ }
388
697
  }
389
698
  return out;
390
699
  }
@@ -395,19 +704,27 @@ class Host extends home_1.Home {
395
704
  return streamId;
396
705
  }
397
706
  hold(v, retries = 0) {
398
- if (v.$selfsign ||
399
- locker_1.Locker.hold([
400
- ...new Set([
401
- ...this.labelOrKey(v.$tx.$i),
402
- ...this.labelOrKey(v.$tx.$o),
403
- ]),
404
- ])) {
707
+ if (!v.$$labelOrKey) {
708
+ const outputs = this.labelOrKey(v.$tx.$o);
709
+ if (!v.$selfsign) {
710
+ v.$$labelOrKey = [
711
+ ...new Set([...this.labelOrKey(v.$tx.$i), ...outputs]),
712
+ ];
713
+ }
714
+ else {
715
+ v.$$labelOrKey = outputs;
716
+ }
717
+ }
718
+ if (locker_1.Locker.hold(v.$$labelOrKey, v.$umid)) {
405
719
  const robin = this.getRobin();
406
720
  if (!this.processPending[v.$umid].entry.$nodes)
407
- this.processPending[v.$umid].entry.$nodes = {};
721
+ if (!this.processPending[v.$umid].entry.$nodes) {
722
+ this.processPending[v.$umid].entry.$nodes = {};
723
+ }
408
724
  this.processPending[v.$umid].entry.$nodes[home_1.Home.reference] = {
409
725
  vote: false,
410
726
  commit: false,
727
+ early: true
411
728
  };
412
729
  this.processPending[v.$umid].pid = robin.pid || 0;
413
730
  robin.send({
@@ -417,60 +734,70 @@ class Host extends home_1.Home {
417
734
  return true;
418
735
  }
419
736
  else {
420
- if (retries === 0) {
421
- this.busyLocksQueue.push({
422
- entry: v,
423
- retry: 1,
424
- });
425
- }
426
- else {
427
- const internal = v.$revs ? true : false;
428
- const maxRetries = internal
429
- ? 2
430
- : activeoptions_1.ActiveOptions.get("queue_retry", 5);
431
- if (retries > maxRetries) {
432
- if (internal) {
433
- if (!v.$nodes) {
434
- v.$nodes = {};
435
- }
436
- v.$nodes[this.reference] = {
737
+ if (v.$nolock) {
738
+ if (v.$broadcast) {
739
+ this.processPending[v.$umid].entry.$nodes = {
740
+ [this.reference]: {
437
741
  vote: false,
438
742
  commit: false,
439
743
  error: "Busy Locks",
440
- };
441
- const doc = {
442
- code: 1100,
443
- processed: false,
444
- umid: v.$umid,
445
- transaction: v,
446
- locker: locker_1.Locker.getLocks(),
447
- reason: "Internal Busy Locks",
448
- };
449
- this.dbErrorConnection.post(doc);
450
- if (!v.$broadcast && home_1.Home.right.reference != v.$origin) {
451
- (async () => {
452
- const next = await home_1.Home.right.knock("init", v);
744
+ },
745
+ };
746
+ this.broadcast(v.$umid, false, true);
747
+ activelogger_1.ActiveLogger.warn(this.processPending[v.$umid], `${v.$umid} busy lock broadcasting that fact`);
748
+ }
749
+ this.processPending[v.$umid].reject({
750
+ status: 100,
751
+ error: "Busy Locks",
752
+ });
753
+ }
754
+ else {
755
+ if (retries === 0) {
756
+ (v.$revs
757
+ ? this.busyLocksQueue.internal
758
+ : this.busyLocksQueue.external).push({
759
+ running: false,
760
+ entry: v,
761
+ retry: 1,
762
+ });
763
+ }
764
+ else {
765
+ const internal = v.$revs ? true : false;
766
+ if (retries > activeoptions_1.ActiveOptions.get("queue_retry", MAX_RETRIES)) {
767
+ if (internal) {
768
+ if (!v.$nodes) {
769
+ v.$nodes = {};
770
+ }
771
+ v.$nodes[this.reference] = {
772
+ vote: false,
773
+ commit: false,
774
+ error: "IBL01",
775
+ };
776
+ if (!v.$broadcast && home_1.Home.right.reference != v.$origin) {
777
+ (async () => {
778
+ const next = await home_1.Home.right.knock("init", v);
779
+ this.processPending[v.$umid].resolve({
780
+ status: 200,
781
+ data: { ...v, ...next.data },
782
+ });
783
+ })();
784
+ }
785
+ else {
786
+ this.broadcast(v.$umid, false, true);
453
787
  this.processPending[v.$umid].resolve({
454
788
  status: 200,
455
- data: { ...v, ...next.data },
789
+ data: v,
456
790
  });
457
- })();
791
+ }
458
792
  }
459
793
  else {
460
- this.processPending[v.$umid].resolve({
461
- status: 200,
462
- data: v,
794
+ this.processPending[v.$umid].reject({
795
+ status: 100,
796
+ error: "Busy Locks",
463
797
  });
464
798
  }
799
+ return true;
465
800
  }
466
- else {
467
- this.processPending[v.$umid].reject({
468
- status: 100,
469
- error: "Busy Locks",
470
- });
471
- }
472
- this.release(this.processPending[v.$umid]);
473
- return true;
474
801
  }
475
802
  }
476
803
  return false;
@@ -487,36 +814,68 @@ class Host extends home_1.Home {
487
814
  }
488
815
  return robin;
489
816
  }
490
- release(pending) {
491
- locker_1.Locker.release([
492
- ...this.labelOrKey(pending.entry.$tx.$i),
493
- ...this.labelOrKey(pending.entry.$tx.$o),
494
- ]);
495
- setTimeout(() => {
496
- if (pending.entry) {
497
- this.destroy(pending.entry.$umid);
498
- }
499
- }, RELEASE_SHUTDOWN_TIMEOUT);
500
- setTimeout(() => {
501
- this.processQueue();
502
- }, 100);
817
+ release(umid) {
818
+ if (this.processPending[umid]) {
819
+ const entry = this.processPending[umid].entry;
820
+ locker_1.Locker.release(entry.$$labelOrKey || [
821
+ ...this.labelOrKey(entry.$tx.$i),
822
+ ...this.labelOrKey(entry.$tx.$o),
823
+ ], entry.$umid);
824
+ setTimeout(() => {
825
+ if (entry) {
826
+ this.destroy(entry.$umid);
827
+ }
828
+ }, RELEASE_SHUTDOWN_TIMEOUT);
829
+ setTimeout(() => {
830
+ this.processQueue();
831
+ }, 200);
832
+ }
833
+ else {
834
+ activelogger_1.ActiveLogger.warn(umid, "Trying to release unknown umid");
835
+ }
503
836
  }
837
+ processingBLQ = false;
504
838
  processQueue(next, internal = false) {
505
- let skipped = false;
506
- if (next && internal && !next.$broadcast) {
507
- this.hold(next);
508
- skipped = true;
509
- }
510
- if (this.busyLocksQueue.length) {
511
- for (let i = 0; i < this.busyLocksQueue.length; i++) {
512
- if (this.hold(this.busyLocksQueue[i].entry, this.busyLocksQueue[i].retry++)) {
513
- delete this.busyLocksQueue[i];
839
+ if (!this.processingBLQ) {
840
+ this.processingBLQ = true;
841
+ const checked = new Set();
842
+ if (this.busyLocksQueue.internal.length) {
843
+ const stillPending = [];
844
+ busyQueueInternal: for (let i = 0; i < this.busyLocksQueue.internal.length; i++) {
845
+ const labelOrKey = this.busyLocksQueue.internal[i].entry.$$labelOrKey;
846
+ if (labelOrKey?.length) {
847
+ if (labelOrKey.some((io) => checked.has(io))) {
848
+ continue busyQueueInternal;
849
+ }
850
+ labelOrKey.forEach((io) => checked.add(io));
851
+ }
852
+ if (!this.hold(this.busyLocksQueue.internal[i].entry, this.busyLocksQueue.internal[i].retry++)) {
853
+ stillPending.push(this.busyLocksQueue.internal[i]);
854
+ }
514
855
  }
856
+ this.busyLocksQueue.internal = stillPending;
857
+ }
858
+ if (next && internal) {
859
+ this.hold(next);
515
860
  }
516
- this.busyLocksQueue = this.busyLocksQueue.filter((n) => n);
861
+ if (this.busyLocksQueue.external.length) {
862
+ const stillPending = [];
863
+ for (let i = 0; i < this.busyLocksQueue.external.length; i++) {
864
+ if (!this.hold(this.busyLocksQueue.external[i].entry, this.busyLocksQueue.external[i].retry++)) {
865
+ stillPending.push(this.busyLocksQueue.external[i]);
866
+ }
867
+ }
868
+ this.busyLocksQueue.external = stillPending;
869
+ }
870
+ if (next && !internal) {
871
+ this.hold(next);
872
+ }
873
+ this.processingBLQ = false;
517
874
  }
518
- if (next && !skipped) {
519
- this.hold(next);
875
+ else {
876
+ if (next) {
877
+ this.hold(next);
878
+ }
520
879
  }
521
880
  }
522
881
  timerQueue() {
@@ -550,12 +909,12 @@ class Host extends home_1.Home {
550
909
  const data = response.data;
551
910
  if (data.status !== "ok") {
552
911
  const updated = [
553
- ...((activityStreams === null || activityStreams === void 0 ? void 0 : activityStreams.new) || []),
554
- ...((activityStreams === null || activityStreams === void 0 ? void 0 : activityStreams.updated) || []),
912
+ ...(activityStreams?.new || []),
913
+ ...(activityStreams?.updated || []),
555
914
  ].map((stream) => stream.id);
556
- const input = tx.$tx.$i
557
- ? this.hybridLabelKeyId(tx.$tx.$i)
558
- : [];
915
+ const input = tx.$tx.$i ?
916
+ this.hybridLabelKeyId(tx.$tx.$i) :
917
+ [];
559
918
  const output = tx.$tx.$o
560
919
  ? this.hybridLabelKeyId(tx.$tx.$o)
561
920
  : [];
@@ -570,8 +929,8 @@ class Host extends home_1.Home {
570
929
  }
571
930
  }
572
931
  const tmp = [];
573
- for (let i = keys.length; i--;) {
574
- tmp.push(keys[i] + ":stream");
932
+ for (const key of keys) {
933
+ tmp.push(key + ":stream");
575
934
  }
576
935
  keys.push(...tmp);
577
936
  return this.dbConnection
@@ -623,15 +982,16 @@ class Host extends home_1.Home {
623
982
  return streams;
624
983
  }
625
984
  }
626
- processEndpoints(req, res, body, from) {
627
- let requester = req.headers["x-activeledger"] || "NA";
985
+ processEndpoints(req, res, body, from, isP2P = false) {
986
+ let requester = req.headers["X-Activeledger"] || "NA";
628
987
  let response;
629
- let gzipAccepted = req.headers["accept-encoding"];
988
+ const started = Date.now();
989
+ let gzipAccepted = req.headers["Accept-Encoding"];
630
990
  switch (req.method) {
631
991
  case "GET":
632
992
  switch (req.url) {
633
993
  case "/a/locks":
634
- return this.writeResponse(res, 200, JSON.stringify(locker_1.Locker.getLocks()), gzipAccepted);
994
+ return this.writeResponse(res, 200, JSON.stringify({ L: locker_1.Locker.getLocks(), Q: this.busyLocksQueue }), gzipAccepted);
635
995
  case "/a/locks/check":
636
996
  locker_1.Locker.checkLocks();
637
997
  return this.writeResponse(res, 200, JSON.stringify({ checked: true }), gzipAccepted);
@@ -639,15 +999,39 @@ class Host extends home_1.Home {
639
999
  response = index_1.Endpoints.status(this, requester);
640
1000
  break;
641
1001
  case "/a/all":
642
- if (this.firewallCheck(requester, req)) {
1002
+ if (this.firewallCheck(requester, req.connection.remoteAddress)) {
643
1003
  response = index_1.Endpoints.all(this.dbConnection);
644
1004
  }
645
1005
  else {
646
1006
  return this.writeResponse(res, 403, "Forbidden", gzipAccepted);
647
1007
  }
648
1008
  break;
1009
+ case "/a/admin-reload":
1010
+ if (!activeoptions_1.ActiveOptions.get("remote", false)) {
1011
+ return this.writeResponse(res, 200, JSON.stringify({
1012
+ status: "failed",
1013
+ message: "remote disabled"
1014
+ }), gzipAccepted);
1015
+ }
1016
+ try {
1017
+ activeoptions_1.ActiveOptions.parseConfig();
1018
+ activelogger_1.ActiveLogger.enableDebug = activeoptions_1.ActiveOptions.get("debug", false);
1019
+ this.reload();
1020
+ activelogger_1.ActiveLogger.info("Host and child processes config.json reloaded successfully via admin API");
1021
+ return this.writeResponse(res, 200, JSON.stringify({
1022
+ status: "success",
1023
+ build: activeoptions_1.ActiveOptions.get("build", 0),
1024
+ }), gzipAccepted);
1025
+ }
1026
+ catch (error) {
1027
+ activelogger_1.ActiveLogger.error(error, "Admin reload error");
1028
+ return this.writeResponse(res, 200, JSON.stringify({
1029
+ status: "failed",
1030
+ message: error.message || "Internal Error"
1031
+ }), gzipAccepted);
1032
+ }
649
1033
  default:
650
- if (this.firewallCheck(requester, req)) {
1034
+ if (this.firewallCheck(requester, req.connection.remoteAddress)) {
651
1035
  if (req.url) {
652
1036
  let match = req.url.substr(0, 7);
653
1037
  switch (match) {
@@ -673,41 +1057,27 @@ class Host extends home_1.Home {
673
1057
  case "POST":
674
1058
  switch (req.url) {
675
1059
  case "/":
676
- response = index_1.Endpoints.ExternalInitalise(this, body, req.connection.remoteAddress || "unknown");
1060
+ response = index_1.Endpoints.ExternalInitalise(this, body, req.connection.remoteAddress || "unknown", this.dbConnection);
677
1061
  break;
678
1062
  case "/a/encrypt":
679
1063
  response = index_1.Endpoints.ExternalEncrypt(this, body, req.headers["x-activeledger-encrypt"] ||
680
1064
  false, this.dbConnection);
681
1065
  break;
682
1066
  case "/a/init":
683
- if (this.firewallCheck(requester, req)) {
684
- response = index_1.Endpoints.InternalInitalise(this, body);
1067
+ if (this.firewallCheck(requester, req.connection.remoteAddress)) {
1068
+ response = index_1.Endpoints.InternalInitalise(this, body, req.connection.remoteAddress, false, isP2P);
685
1069
  }
686
1070
  else {
687
1071
  return this.writeResponse(res, 403, "Forbidden", gzipAccepted);
688
1072
  }
689
1073
  break;
690
1074
  case "/a/stream":
691
- if (this.firewallCheck(requester, req)) {
692
- response = index_1.Endpoints.streams(this.dbConnection, body);
693
- }
694
- else {
695
- return this.writeResponse(res, 403, "Forbidden", gzipAccepted);
696
- }
1075
+ response = index_1.Endpoints.streams(this.dbConnection, body);
697
1076
  break;
698
1077
  default:
699
1078
  return this.writeResponse(res, 404, "Not Found", gzipAccepted);
700
1079
  }
701
1080
  break;
702
- case "OPTIONS":
703
- res.writeHead(200, {
704
- "Access-Control-Allow-Origin": "*",
705
- "Access-Control-Allow-Methods": "GET, POST",
706
- "Access-Control-Allow-Headers": req.headers["access-control-request-headers"] || "*",
707
- "X-Powered-By": "Activeledger",
708
- });
709
- res.end();
710
- return;
711
1081
  default:
712
1082
  return this.writeResponse(res, 404, "Not Found", gzipAccepted);
713
1083
  }
@@ -722,31 +1092,52 @@ class Host extends home_1.Home {
722
1092
  $enc: true,
723
1093
  };
724
1094
  }
1095
+ if (data.$umid) {
1096
+ const TT = Date.now() - started;
1097
+ if (TT > 5) {
1098
+ activelogger_1.ActiveLogger.info(`[RR] ${data.$umid ? data.$umid : "No Umid"} : S=${started}, TT=${TT}ms ${TT > 30000 ? "TTLR" : " OK"}`);
1099
+ }
1100
+ }
725
1101
  this.writeResponse(res, response.statusCode, JSON.stringify(data), gzipAccepted);
726
1102
  })
727
1103
  .catch((error) => {
1104
+ activelogger_1.ActiveLogger.error(error, "Failed to send response back");
1105
+ activelogger_1.ActiveLogger.info(`[RR] ERROR : S=${started}, TT=${Date.now() - started}ms`);
728
1106
  this.writeResponse(res, error.statusCode || 500, JSON.stringify(error.content || "Something has gone wrong"), gzipAccepted);
729
1107
  });
730
1108
  }
731
- async writeResponse(res, statusCode, content, encoding) {
732
- let headers = {
733
- "Content-Type": "application/json",
734
- "Content-Encoding": "none",
735
- "Access-Control-Allow-Origin": "*",
736
- "X-Powered-By": "Activeledger",
737
- };
738
- if (encoding == "gzip") {
739
- headers["Content-Encoding"] = "gzip";
740
- content = await activeoptions_1.ActiveGZip.gzip(content);
1109
+ async writeResponse(res, statusCode, content, encoding, cors = false) {
1110
+ if (!res || !res.writable) {
1111
+ return;
741
1112
  }
742
- res.writeHead(statusCode, headers);
743
- res.write(content);
744
- res.end();
1113
+ if (content) {
1114
+ if (encoding == "gzip") {
1115
+ content = await activeoptions_1.ActiveGZip.gzip(content);
1116
+ }
1117
+ }
1118
+ res.cork(() => {
1119
+ res.writeStatus(`${statusCode}`);
1120
+ res.writeHeader("Access-Control-Allow-Origin", "*");
1121
+ res.writeHeader("X-Content-Type-Options", "nosniff");
1122
+ res.writeHeader("X-Frame-Options", "DENY");
1123
+ res.writeHeader("Strict-Transport-Security", "max-age=63072000; includeSubDomains; preload");
1124
+ res.writeHeader("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none';");
1125
+ if (cors) {
1126
+ res.writeHeader("Access-Control-Allow-Methods", "GET, POST");
1127
+ res.writeHeader("Access-Control-Allow-Headers", "*");
1128
+ }
1129
+ if (content) {
1130
+ res.writeHeader("Content-Type", "application/json");
1131
+ if (encoding == "gzip") {
1132
+ res.writeHeader("Content-Encoding", "gzip");
1133
+ }
1134
+ res.end(content);
1135
+ res.writable = false;
1136
+ }
1137
+ });
745
1138
  }
746
- firewallCheck(requester, req) {
747
- return (requester !== "NA" &&
748
- this.neighbourhood.checkFirewall(req.headers["x-forwarded-for"] ||
749
- req.connection.remoteAddress));
1139
+ firewallCheck(requester, remoteAddr) {
1140
+ return this.neighbourhood.checkFirewall(remoteAddr, requester);
750
1141
  }
751
1142
  }
752
1143
  exports.Host = Host;