@i14ks/ccv 0.7.0 → 0.7.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/bundle/ccv.mjs +64 -3
- package/package.json +1 -1
package/bundle/ccv.mjs
CHANGED
|
@@ -4229,6 +4229,9 @@ var RELAY_BROADCAST = "*";
|
|
|
4229
4229
|
// ../host/dist/relay-link.js
|
|
4230
4230
|
var RETRY_MIN_MS = 1e3;
|
|
4231
4231
|
var RETRY_MAX_MS = 6e4;
|
|
4232
|
+
var HANDSHAKE_TIMEOUT_MS = 15e3;
|
|
4233
|
+
var CONNECT_TIMEOUT_MS = 3e4;
|
|
4234
|
+
var SILENCE_TIMEOUT_MS = 95e3;
|
|
4232
4235
|
function jitter(delay) {
|
|
4233
4236
|
return Math.round(delay * (0.8 + Math.random() * 0.4));
|
|
4234
4237
|
}
|
|
@@ -4237,6 +4240,17 @@ var RelayLink = class extends EventEmitter3 {
|
|
|
4237
4240
|
#socket = null;
|
|
4238
4241
|
#retry = RETRY_MIN_MS;
|
|
4239
4242
|
#retryTimer = null;
|
|
4243
|
+
/**
|
|
4244
|
+
* Сторож живого соединения — один таймер на три фазы жизни сокета.
|
|
4245
|
+
*
|
|
4246
|
+
* До `open` он сторожит подключение, после — тишину, и переставляется каждым
|
|
4247
|
+
* пришедшим кадром. Один таймер, а не три: у сокета в каждый момент есть
|
|
4248
|
+
* ровно один способ подвести, и держать под него отдельные заводные механизмы
|
|
4249
|
+
* значило бы гасить их по очереди в каждой ветке.
|
|
4250
|
+
*/
|
|
4251
|
+
#watchdog = null;
|
|
4252
|
+
/** Сокет рвём мы сами — чтобы не подменить свою причину отказа причиной от `ws`. */
|
|
4253
|
+
#aborting = false;
|
|
4240
4254
|
#clients = /* @__PURE__ */ new Set();
|
|
4241
4255
|
#error = null;
|
|
4242
4256
|
#closed = false;
|
|
@@ -4422,10 +4436,13 @@ var RelayLink = class extends EventEmitter3 {
|
|
|
4422
4436
|
clearTimeout(this.#retryTimer);
|
|
4423
4437
|
this.#retryTimer = null;
|
|
4424
4438
|
}
|
|
4439
|
+
this.#disarm();
|
|
4425
4440
|
const socket = this.#socket;
|
|
4426
4441
|
this.#socket = null;
|
|
4427
4442
|
if (socket) {
|
|
4428
4443
|
socket.removeAllListeners();
|
|
4444
|
+
socket.on("error", () => {
|
|
4445
|
+
});
|
|
4429
4446
|
socket.close();
|
|
4430
4447
|
}
|
|
4431
4448
|
for (const clientId of this.#clients)
|
|
@@ -4437,9 +4454,12 @@ var RelayLink = class extends EventEmitter3 {
|
|
|
4437
4454
|
if (!credentials || this.#closed || this.#socket)
|
|
4438
4455
|
return;
|
|
4439
4456
|
const wsUrl = `${credentials.url.replace(/^http/, "ws")}/relay/host`;
|
|
4440
|
-
|
|
4457
|
+
this.#aborting = false;
|
|
4458
|
+
const socket = new WebSocket(wsUrl, { handshakeTimeout: HANDSHAKE_TIMEOUT_MS });
|
|
4441
4459
|
this.#socket = socket;
|
|
4460
|
+
this.#arm(socket, CONNECT_TIMEOUT_MS, "relay \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u043D\u0430 \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435");
|
|
4442
4461
|
socket.on("open", () => {
|
|
4462
|
+
this.#arm(socket, SILENCE_TIMEOUT_MS, "relay \u0437\u0430\u043C\u043E\u043B\u0447\u0430\u043B");
|
|
4443
4463
|
const hello = {
|
|
4444
4464
|
t: "host.hello",
|
|
4445
4465
|
protocol: RELAY_PROTOCOL_VERSION,
|
|
@@ -4449,13 +4469,19 @@ var RelayLink = class extends EventEmitter3 {
|
|
|
4449
4469
|
};
|
|
4450
4470
|
socket.send(JSON.stringify(hello));
|
|
4451
4471
|
});
|
|
4452
|
-
socket.on("message", (raw) =>
|
|
4472
|
+
socket.on("message", (raw) => {
|
|
4473
|
+
this.#arm(socket, SILENCE_TIMEOUT_MS, "relay \u0437\u0430\u043C\u043E\u043B\u0447\u0430\u043B");
|
|
4474
|
+
this.#onMessage(socket, String(raw));
|
|
4475
|
+
});
|
|
4453
4476
|
socket.on("error", (error) => {
|
|
4454
|
-
this.#
|
|
4477
|
+
if (this.#aborting)
|
|
4478
|
+
return;
|
|
4479
|
+
this.#error = humanize(error);
|
|
4455
4480
|
});
|
|
4456
4481
|
socket.on("close", (code, reason) => {
|
|
4457
4482
|
if (this.#socket !== socket)
|
|
4458
4483
|
return;
|
|
4484
|
+
this.#disarm();
|
|
4459
4485
|
this.#socket = null;
|
|
4460
4486
|
for (const clientId of this.#clients)
|
|
4461
4487
|
this.emit("detached", clientId);
|
|
@@ -4469,6 +4495,34 @@ var RelayLink = class extends EventEmitter3 {
|
|
|
4469
4495
|
this.#scheduleRetry(rejected);
|
|
4470
4496
|
});
|
|
4471
4497
|
}
|
|
4498
|
+
/**
|
|
4499
|
+
* Взвести сторожа: не дождались — рвём сокет и уходим на общий круг повтора.
|
|
4500
|
+
*
|
|
4501
|
+
* `terminate()`, а не `close()`: закрытие по правилам ждёт ответного кадра от
|
|
4502
|
+
* стороны, которая как раз и не отвечает, — а нам нужен `close` на своей
|
|
4503
|
+
* стороне здесь и сейчас, потому что именно он запускает переподключение.
|
|
4504
|
+
* Для сокета, застрявшего в CONNECTING, `ws` тем же вызовом обрывает
|
|
4505
|
+
* рукопожатие — и это тот самый случай, ради которого всё написано.
|
|
4506
|
+
*/
|
|
4507
|
+
#arm(socket, ms, reason) {
|
|
4508
|
+
this.#disarm();
|
|
4509
|
+
this.#watchdog = setTimeout(() => {
|
|
4510
|
+
this.#watchdog = null;
|
|
4511
|
+
if (this.#socket !== socket)
|
|
4512
|
+
return;
|
|
4513
|
+
this.#error = `${reason} \u0437\u0430 ${Math.round(ms / 1e3)} \u0441 \u2014 \u043F\u0440\u043E\u0431\u0443\u0435\u043C \u0441\u043D\u043E\u0432\u0430`;
|
|
4514
|
+
this.#log(this.#error);
|
|
4515
|
+
this.#aborting = true;
|
|
4516
|
+
socket.terminate();
|
|
4517
|
+
}, ms);
|
|
4518
|
+
this.#watchdog.unref();
|
|
4519
|
+
}
|
|
4520
|
+
#disarm() {
|
|
4521
|
+
if (!this.#watchdog)
|
|
4522
|
+
return;
|
|
4523
|
+
clearTimeout(this.#watchdog);
|
|
4524
|
+
this.#watchdog = null;
|
|
4525
|
+
}
|
|
4472
4526
|
#scheduleRetry(rejected) {
|
|
4473
4527
|
if (this.#closed || !this.#credentials || this.#retryTimer)
|
|
4474
4528
|
return;
|
|
@@ -4560,6 +4614,13 @@ var RelayLink = class extends EventEmitter3 {
|
|
|
4560
4614
|
function describe5(error) {
|
|
4561
4615
|
return error instanceof Error ? error.message : String(error);
|
|
4562
4616
|
}
|
|
4617
|
+
function humanize(error) {
|
|
4618
|
+
const message = describe5(error);
|
|
4619
|
+
if (/handshake has timed out/i.test(message)) {
|
|
4620
|
+
return `relay \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u043D\u0430 \u0440\u0443\u043A\u043E\u043F\u043E\u0436\u0430\u0442\u0438\u0435 \u0437\u0430 ${Math.round(HANDSHAKE_TIMEOUT_MS / 1e3)} \u0441 \u2014 \u043F\u0440\u043E\u0431\u0443\u0435\u043C \u0441\u043D\u043E\u0432\u0430`;
|
|
4621
|
+
}
|
|
4622
|
+
return message;
|
|
4623
|
+
}
|
|
4563
4624
|
|
|
4564
4625
|
// ../host/dist/terminal.js
|
|
4565
4626
|
import { EventEmitter as EventEmitter4 } from "node:events";
|
package/package.json
CHANGED