@jonathanyee/devtunnel-ctl 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +328 -2
- package/dist/auth.d.ts +24 -0
- package/dist/auth.js +151 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +246 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +94 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +16 -0
- package/dist/core.js +114 -0
- package/dist/core.js.map +1 -0
- package/dist/daemon.d.ts +31 -0
- package/dist/daemon.js +153 -0
- package/dist/daemon.js.map +1 -0
- package/dist/forwarding.d.ts +15 -0
- package/dist/forwarding.js +87 -0
- package/dist/forwarding.js.map +1 -0
- package/dist/host-process.d.ts +4 -0
- package/dist/host-process.js +110 -0
- package/dist/host-process.js.map +1 -0
- package/dist/host-sdk.d.ts +38 -0
- package/dist/host-sdk.js +327 -0
- package/dist/host-sdk.js.map +1 -0
- package/dist/host-service.d.ts +21 -0
- package/dist/host-service.js +193 -0
- package/dist/host-service.js.map +1 -0
- package/dist/host-worker.d.ts +1 -0
- package/dist/host-worker.js +80 -0
- package/dist/host-worker.js.map +1 -0
- package/dist/host.d.ts +43 -0
- package/dist/host.js +158 -0
- package/dist/host.js.map +1 -0
- package/dist/launchd.d.ts +15 -0
- package/dist/launchd.js +135 -0
- package/dist/launchd.js.map +1 -0
- package/dist/lock.d.ts +10 -0
- package/dist/lock.js +110 -0
- package/dist/lock.js.map +1 -0
- package/dist/log.d.ts +26 -0
- package/dist/log.js +67 -0
- package/dist/log.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +5 -0
- package/dist/main.js.map +1 -0
- package/dist/paths.d.ts +4 -0
- package/dist/paths.js +39 -0
- package/dist/paths.js.map +1 -0
- package/dist/probe.d.ts +1 -0
- package/dist/probe.js +45 -0
- package/dist/probe.js.map +1 -0
- package/dist/recovery.d.ts +77 -0
- package/dist/recovery.js +265 -0
- package/dist/recovery.js.map +1 -0
- package/dist/rpc.d.ts +30 -0
- package/dist/rpc.js +208 -0
- package/dist/rpc.js.map +1 -0
- package/dist/sdk-transport.d.ts +33 -0
- package/dist/sdk-transport.js +239 -0
- package/dist/sdk-transport.js.map +1 -0
- package/npm-shrinkwrap.json +810 -0
- package/package.json +31 -4
package/dist/log.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { open, rename, lstat } from 'node:fs/promises';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { Fault, redact } from "./core.js";
|
|
5
|
+
import { privateDir, privatePath } from "./paths.js";
|
|
6
|
+
export class Log {
|
|
7
|
+
dir;
|
|
8
|
+
maxBytes;
|
|
9
|
+
pending = 0;
|
|
10
|
+
tail = Promise.resolve();
|
|
11
|
+
sequence = 0;
|
|
12
|
+
recent = [];
|
|
13
|
+
constructor(dir, maxBytes = 262144) { this.dir = dir; this.maxBytes = maxBytes; }
|
|
14
|
+
async init() { await privateDir(this.dir); }
|
|
15
|
+
write(entry) {
|
|
16
|
+
if (this.pending >= 256)
|
|
17
|
+
return Promise.reject(new Fault('internal', 'Log backlog limit exceeded.'));
|
|
18
|
+
const line = JSON.stringify({ time: new Date().toISOString(), event: redact(entry.event),
|
|
19
|
+
...(entry.profile ? { profile: redact(entry.profile) } : {}),
|
|
20
|
+
...(entry.state ? { state: redact(entry.state) } : {}),
|
|
21
|
+
...(entry.message ? { message: redact(entry.message).slice(0, 256) } : {}),
|
|
22
|
+
...(entry.attempt !== undefined ? { attempt: entry.attempt } : {}),
|
|
23
|
+
...(entry.relayConnected !== undefined ? { relayConnected: entry.relayConnected } : {}),
|
|
24
|
+
...(entry.lastHealthyAt !== undefined ? { lastHealthyAt: entry.lastHealthyAt } : {}),
|
|
25
|
+
...(entry.nextRetryAt !== undefined ? { nextRetryAt: entry.nextRetryAt } : {}),
|
|
26
|
+
}) + '\n';
|
|
27
|
+
if (Buffer.byteLength(line) > this.maxBytes)
|
|
28
|
+
return Promise.reject(new Fault('internal', 'Log entry exceeds disk bound.'));
|
|
29
|
+
this.pending++;
|
|
30
|
+
this.tail = this.tail.then(async () => {
|
|
31
|
+
const path = join(this.dir, 'service.log'), previous = path + '.1';
|
|
32
|
+
let size = 0;
|
|
33
|
+
try {
|
|
34
|
+
await privatePath(path);
|
|
35
|
+
size = (await lstat(path)).size;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
if (size + Buffer.byteLength(line) > this.maxBytes) {
|
|
42
|
+
try {
|
|
43
|
+
await privatePath(previous);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
await rename(path, previous);
|
|
50
|
+
}
|
|
51
|
+
const file = await open(path, constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY | constants.O_NOFOLLOW, 0o600);
|
|
52
|
+
try {
|
|
53
|
+
await file.writeFile(line);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
await file.close();
|
|
57
|
+
}
|
|
58
|
+
this.recent.push({ sequence: ++this.sequence, line: line.trimEnd() });
|
|
59
|
+
if (this.recent.length > 128)
|
|
60
|
+
this.recent.shift();
|
|
61
|
+
}).finally(() => { this.pending--; });
|
|
62
|
+
return this.tail;
|
|
63
|
+
}
|
|
64
|
+
flush() { return this.tail; }
|
|
65
|
+
snapshot() { return this.recent.map(entry => ({ ...entry })); }
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=log.js.map
|
package/dist/log.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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"}
|
package/dist/main.d.ts
ADDED
package/dist/main.js
ADDED
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function stateDir(input?: string): string;
|
|
2
|
+
export declare function executable(path: string): Promise<string>;
|
|
3
|
+
export declare function privatePath(path: string, directory?: boolean): Promise<void>;
|
|
4
|
+
export declare function privateDir(path: string): Promise<void>;
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import { lstat, mkdir, chmod, realpath, access, stat } from 'node:fs/promises';
|
|
4
|
+
import { constants } from 'node:fs';
|
|
5
|
+
import { Fault } from "./core.js";
|
|
6
|
+
export function stateDir(input) {
|
|
7
|
+
return input ? resolve(input) : join(homedir(), '.devtunnel-ctl');
|
|
8
|
+
}
|
|
9
|
+
export async function executable(path) {
|
|
10
|
+
try {
|
|
11
|
+
const resolved = await realpath(path);
|
|
12
|
+
await access(resolved, constants.X_OK);
|
|
13
|
+
if (!(await stat(resolved)).isFile())
|
|
14
|
+
throw new Fault('invalid-config');
|
|
15
|
+
return resolved;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Fault('invalid-config', 'Configured executable is missing or not executable. Check its absolute path.');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function privatePath(path, directory = false) {
|
|
22
|
+
const info = await lstat(path);
|
|
23
|
+
if (info.isSymbolicLink() || (directory ? !info.isDirectory() : !info.isFile()) ||
|
|
24
|
+
info.uid !== process.getuid?.() || (info.mode & 0o077) !== 0) {
|
|
25
|
+
throw new Fault('invalid-config', 'State must be private, owned by this user, and not a symlink.');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function privateDir(path) {
|
|
29
|
+
try {
|
|
30
|
+
await mkdir(path, { mode: 0o700 });
|
|
31
|
+
await chmod(path, 0o700);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
await privatePath(path, true);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACxE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE,8EAA8E,CAAC,CAAC;IAAC,CAAC;AAChI,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,SAAS,GAAG,KAAK;IAC/D,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3E,IAAI,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE,+DAA+D,CAAC,CAAC;IACrG,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;YAAE,MAAM,KAAK,CAAC;IAC3F,CAAC;IACD,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC"}
|
package/dist/probe.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function probeSsh(port: number, signal?: AbortSignal, timeoutMs?: number): Promise<void>;
|
package/dist/probe.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import net from 'node:net';
|
|
2
|
+
import { bounded, Fault } from "./core.js";
|
|
3
|
+
export async function probeSsh(port, signal, timeoutMs = 3000) {
|
|
4
|
+
return bounded(inner => new Promise((resolve, reject) => {
|
|
5
|
+
const socket = net.connect({ port, host: '127.0.0.1' });
|
|
6
|
+
let text = '', done = false;
|
|
7
|
+
const abort = () => finish(new Fault('aborted'));
|
|
8
|
+
const finish = (error) => {
|
|
9
|
+
if (done)
|
|
10
|
+
return;
|
|
11
|
+
done = true;
|
|
12
|
+
inner.removeEventListener('abort', abort);
|
|
13
|
+
socket.destroy();
|
|
14
|
+
if (error)
|
|
15
|
+
reject(error);
|
|
16
|
+
else
|
|
17
|
+
resolve();
|
|
18
|
+
};
|
|
19
|
+
inner.addEventListener('abort', abort, { once: true });
|
|
20
|
+
if (inner.aborted) {
|
|
21
|
+
abort();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
socket.on('error', () => finish(new Fault('remote-unavailable')));
|
|
25
|
+
socket.on('close', () => { if (!done)
|
|
26
|
+
finish(new Fault('remote-unavailable')); });
|
|
27
|
+
socket.on('data', (chunk) => {
|
|
28
|
+
text += chunk.toString('ascii');
|
|
29
|
+
if (text.length > 4096) {
|
|
30
|
+
finish(new Fault('remote-unavailable'));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const lines = text.split('\n');
|
|
34
|
+
for (const line of lines.slice(0, -1)) {
|
|
35
|
+
if (/^SSH-(2\.0|1\.99)-[!-~]+(?: .*)?\r?$/.test(line) && line.length <= 255) {
|
|
36
|
+
finish();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (lines.length > 8)
|
|
41
|
+
finish(new Fault('remote-unavailable'));
|
|
42
|
+
});
|
|
43
|
+
}), timeoutMs, signal);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,MAAoB,EAAE,SAAS,GAAG,IAAI;IACjF,OAAO,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC5D,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACxD,IAAI,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,KAAK,CAAC;QAC5B,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,IAAI;gBAAE,OAAO;YACjB,IAAI,GAAG,IAAI,CAAC;YACZ,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,KAAK;gBAAE,MAAM,CAAC,KAAK,CAAC,CAAC;;gBAAM,OAAO,EAAE,CAAC;QAC3C,CAAC,CAAC;QACF,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAAC,KAAK,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QACvC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI;YAAE,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;gBAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;gBAAC,OAAO;YAAC,CAAC;YAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtC,IAAI,sCAAsC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;oBAAC,MAAM,EAAE,CAAC;oBAAC,OAAO;gBAAC,CAAC;YACpG,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Profile } from './config.ts';
|
|
2
|
+
import type { Transport } from './sdk-transport.ts';
|
|
3
|
+
import type { OpenStream } from './forwarding.ts';
|
|
4
|
+
import type { Clock, FaultCode } from './core.ts';
|
|
5
|
+
export type State = 'paused' | 'connecting' | 'healthy' | 'reconnecting' | FaultCode;
|
|
6
|
+
export interface Status {
|
|
7
|
+
name: string;
|
|
8
|
+
state: State;
|
|
9
|
+
localPort: number;
|
|
10
|
+
remotePort: number;
|
|
11
|
+
tunnelId: string;
|
|
12
|
+
clusterId?: string;
|
|
13
|
+
paused: boolean;
|
|
14
|
+
relayConnected: boolean;
|
|
15
|
+
attempt: number;
|
|
16
|
+
lastHealthyAt?: number;
|
|
17
|
+
nextRetryAt?: number;
|
|
18
|
+
cause?: {
|
|
19
|
+
code: FaultCode;
|
|
20
|
+
message: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
interface Listener {
|
|
24
|
+
listen(): Promise<void>;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
setTarget(target: OpenStream | undefined): void;
|
|
27
|
+
}
|
|
28
|
+
interface Dependencies {
|
|
29
|
+
transport: Transport;
|
|
30
|
+
forwarder: Listener;
|
|
31
|
+
probe(signal: AbortSignal): Promise<void>;
|
|
32
|
+
log(status: Status): void;
|
|
33
|
+
clock?: Clock;
|
|
34
|
+
random?: () => number;
|
|
35
|
+
}
|
|
36
|
+
export declare class Recovery {
|
|
37
|
+
readonly profile: Profile;
|
|
38
|
+
private readonly deps;
|
|
39
|
+
private readonly timer;
|
|
40
|
+
private readonly random;
|
|
41
|
+
private session;
|
|
42
|
+
private sessionLife;
|
|
43
|
+
private active;
|
|
44
|
+
private serial;
|
|
45
|
+
private generation;
|
|
46
|
+
private cancelTick;
|
|
47
|
+
private running;
|
|
48
|
+
private listening;
|
|
49
|
+
private state;
|
|
50
|
+
private attempts;
|
|
51
|
+
private remoteFailures;
|
|
52
|
+
private lastHealthyAt;
|
|
53
|
+
private nextCheck;
|
|
54
|
+
private nextRetry;
|
|
55
|
+
private lastTick;
|
|
56
|
+
private graceUntil;
|
|
57
|
+
private fault;
|
|
58
|
+
constructor(profile: Profile, deps: Dependencies);
|
|
59
|
+
status(): Status;
|
|
60
|
+
private transition;
|
|
61
|
+
start(): void;
|
|
62
|
+
private tick;
|
|
63
|
+
private begin;
|
|
64
|
+
private connect;
|
|
65
|
+
private check;
|
|
66
|
+
private probe;
|
|
67
|
+
private healthy;
|
|
68
|
+
private fail;
|
|
69
|
+
private onEvent;
|
|
70
|
+
private dispose;
|
|
71
|
+
private retire;
|
|
72
|
+
reconnect(): void;
|
|
73
|
+
pause(): Promise<void>;
|
|
74
|
+
resume(): void;
|
|
75
|
+
stop(): Promise<void>;
|
|
76
|
+
}
|
|
77
|
+
export {};
|
package/dist/recovery.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { clock as realClock, bounded, Fault, safeFault } from "./core.js";
|
|
2
|
+
export class Recovery {
|
|
3
|
+
profile;
|
|
4
|
+
deps;
|
|
5
|
+
timer;
|
|
6
|
+
random;
|
|
7
|
+
session;
|
|
8
|
+
sessionLife;
|
|
9
|
+
active;
|
|
10
|
+
serial = 0;
|
|
11
|
+
generation = 0;
|
|
12
|
+
cancelTick;
|
|
13
|
+
running = false;
|
|
14
|
+
listening = false;
|
|
15
|
+
state = 'connecting';
|
|
16
|
+
attempts = 0;
|
|
17
|
+
remoteFailures = 0;
|
|
18
|
+
lastHealthyAt;
|
|
19
|
+
nextCheck = 0;
|
|
20
|
+
nextRetry = 0;
|
|
21
|
+
lastTick = 0;
|
|
22
|
+
graceUntil = 0;
|
|
23
|
+
fault;
|
|
24
|
+
constructor(profile, deps) {
|
|
25
|
+
this.profile = { ...profile };
|
|
26
|
+
this.deps = deps;
|
|
27
|
+
this.timer = deps.clock ?? realClock;
|
|
28
|
+
this.random = deps.random ?? Math.random;
|
|
29
|
+
this.state = profile.paused ? 'paused' : 'connecting';
|
|
30
|
+
}
|
|
31
|
+
status() {
|
|
32
|
+
return { name: this.profile.name, tunnelId: this.profile.tunnelId,
|
|
33
|
+
...(this.profile.clusterId ? { clusterId: this.profile.clusterId } : {}),
|
|
34
|
+
localPort: this.profile.localPort, remotePort: this.profile.remotePort, state: this.state,
|
|
35
|
+
paused: this.profile.paused, relayConnected: this.session?.connected ?? false, attempt: this.attempts,
|
|
36
|
+
...(this.lastHealthyAt !== undefined ? { lastHealthyAt: this.lastHealthyAt } : {}),
|
|
37
|
+
...(this.nextRetry > 0 && Number.isFinite(this.nextRetry) ? { nextRetryAt: this.nextRetry } : {}),
|
|
38
|
+
...(this.fault ? { cause: { code: this.fault.code, message: this.fault.message } } : {}) };
|
|
39
|
+
}
|
|
40
|
+
transition(state, fault) {
|
|
41
|
+
const changed = state !== this.state || fault?.code !== this.fault?.code;
|
|
42
|
+
this.state = state;
|
|
43
|
+
this.fault = fault;
|
|
44
|
+
if (changed)
|
|
45
|
+
this.deps.log(this.status());
|
|
46
|
+
}
|
|
47
|
+
start() {
|
|
48
|
+
if (this.running)
|
|
49
|
+
return;
|
|
50
|
+
this.running = true;
|
|
51
|
+
this.lastTick = this.timer.now();
|
|
52
|
+
this.tick();
|
|
53
|
+
}
|
|
54
|
+
tick = () => {
|
|
55
|
+
if (!this.running)
|
|
56
|
+
return;
|
|
57
|
+
const now = this.timer.now(), gap = now - this.lastTick;
|
|
58
|
+
this.lastTick = now;
|
|
59
|
+
if (gap > 15000 && !this.profile.paused) {
|
|
60
|
+
this.nextCheck = now;
|
|
61
|
+
if (this.state !== 'login-required' && this.state !== 'access-denied' && this.state !== 'invalid-config' &&
|
|
62
|
+
this.state !== 'throttled')
|
|
63
|
+
this.nextRetry = Math.min(this.nextRetry, now);
|
|
64
|
+
}
|
|
65
|
+
if (!this.profile.paused && !this.active) {
|
|
66
|
+
if (this.session) {
|
|
67
|
+
if (this.graceUntil && now >= this.graceUntil && !this.session.connected) {
|
|
68
|
+
this.fail(new Fault('retrying'));
|
|
69
|
+
}
|
|
70
|
+
else if (now >= this.nextCheck && (!this.graceUntil || this.session.connected))
|
|
71
|
+
this.check();
|
|
72
|
+
}
|
|
73
|
+
else if (now >= this.nextRetry)
|
|
74
|
+
this.connect();
|
|
75
|
+
}
|
|
76
|
+
this.cancelTick = this.timer.later(1000, this.tick);
|
|
77
|
+
};
|
|
78
|
+
begin(action) {
|
|
79
|
+
this.active?.controller.abort();
|
|
80
|
+
const controller = new AbortController(), id = ++this.serial;
|
|
81
|
+
this.active = { id, controller };
|
|
82
|
+
const valid = () => this.active?.id === id && !controller.signal.aborted &&
|
|
83
|
+
this.running && !this.profile.paused;
|
|
84
|
+
void action(controller.signal, valid).catch(error => {
|
|
85
|
+
if (valid())
|
|
86
|
+
this.fail(safeFault(error));
|
|
87
|
+
}).finally(() => { if (this.active?.id === id)
|
|
88
|
+
this.active = undefined; });
|
|
89
|
+
}
|
|
90
|
+
connect() {
|
|
91
|
+
this.begin(async (signal, valid) => {
|
|
92
|
+
await this.retire();
|
|
93
|
+
if (!valid())
|
|
94
|
+
return;
|
|
95
|
+
if (!this.listening) {
|
|
96
|
+
await bounded(() => this.deps.forwarder.listen(), 1000, signal, () => this.deps.forwarder.close(), this.timer);
|
|
97
|
+
this.listening = true;
|
|
98
|
+
}
|
|
99
|
+
this.transition('connecting');
|
|
100
|
+
const life = new AbortController();
|
|
101
|
+
this.sessionLife = life;
|
|
102
|
+
const abort = () => life.abort();
|
|
103
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
104
|
+
const generation = ++this.generation;
|
|
105
|
+
let session;
|
|
106
|
+
try {
|
|
107
|
+
session = await bounded(inner => this.deps.transport.connect(this.profile, AbortSignal.any([inner, life.signal]), event => { if (generation === this.generation && !life.signal.aborted)
|
|
108
|
+
this.onEvent(event); }), 25000, signal, late => this.dispose(late), this.timer);
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
signal.removeEventListener('abort', abort);
|
|
112
|
+
}
|
|
113
|
+
if (!valid()) {
|
|
114
|
+
life.abort();
|
|
115
|
+
await this.dispose(session);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.session = session;
|
|
119
|
+
this.remoteFailures = 0;
|
|
120
|
+
this.deps.forwarder.setTarget(openSignal => {
|
|
121
|
+
if (!session.connected || generation !== this.generation || life.signal.aborted)
|
|
122
|
+
return Promise.reject(new Fault('retrying'));
|
|
123
|
+
return session.open(openSignal);
|
|
124
|
+
});
|
|
125
|
+
await this.probe(signal);
|
|
126
|
+
if (valid())
|
|
127
|
+
this.healthy();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
check() {
|
|
131
|
+
this.begin(async (signal, valid) => {
|
|
132
|
+
await this.probe(signal);
|
|
133
|
+
if (valid())
|
|
134
|
+
this.healthy();
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
probe(signal) {
|
|
138
|
+
return bounded(inner => this.deps.probe(inner), 3000, signal, undefined, this.timer);
|
|
139
|
+
}
|
|
140
|
+
healthy() {
|
|
141
|
+
this.lastHealthyAt = this.timer.now();
|
|
142
|
+
this.nextCheck = this.timer.now() + 10000;
|
|
143
|
+
this.nextRetry = 0;
|
|
144
|
+
this.attempts = 0;
|
|
145
|
+
this.remoteFailures = 0;
|
|
146
|
+
this.graceUntil = 0;
|
|
147
|
+
this.transition('healthy');
|
|
148
|
+
}
|
|
149
|
+
fail(fault) {
|
|
150
|
+
if (!this.running || this.profile.paused)
|
|
151
|
+
return;
|
|
152
|
+
const now = this.timer.now();
|
|
153
|
+
if (this.session && this.session.connected && ++this.remoteFailures < 2 &&
|
|
154
|
+
['remote-unavailable', 'timeout', 'retrying'].includes(fault.code)) {
|
|
155
|
+
this.nextCheck = now + 5000;
|
|
156
|
+
this.transition('remote-unavailable', new Fault('remote-unavailable', 'Tunnel: connected; SSH: no response. Check remote SSH/WSL.'));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
this.attempts++;
|
|
160
|
+
const backoff = Math.min(15000, 1000 * 2 ** Math.min(this.attempts - 1, 5));
|
|
161
|
+
this.nextRetry = now + Math.max(fault.retryAfterMs, Math.round(backoff * (0.5 + this.random() * 0.5)));
|
|
162
|
+
if (fault.code === 'login-required' || fault.code === 'access-denied' || fault.code === 'invalid-config') {
|
|
163
|
+
this.nextRetry = Infinity;
|
|
164
|
+
}
|
|
165
|
+
const state = fault.code === 'timeout' ? 'retrying' : fault.code;
|
|
166
|
+
this.transition(state, fault);
|
|
167
|
+
this.graceUntil = 0;
|
|
168
|
+
// Disposal is bounded and detached from the next generation's authority.
|
|
169
|
+
const old = this.session;
|
|
170
|
+
this.session = undefined;
|
|
171
|
+
this.generation++;
|
|
172
|
+
this.sessionLife?.abort();
|
|
173
|
+
this.sessionLife = undefined;
|
|
174
|
+
this.deps.forwarder.setTarget(undefined);
|
|
175
|
+
if (old)
|
|
176
|
+
void this.dispose(old).catch(error => this.deps.log({ ...this.status(),
|
|
177
|
+
cause: { code: safeFault(error).code, message: 'Client teardown exceeded its bound; its generation is cancelled.' } }));
|
|
178
|
+
}
|
|
179
|
+
onEvent(event) {
|
|
180
|
+
if (!this.running || this.profile.paused || !this.session)
|
|
181
|
+
return;
|
|
182
|
+
if (event.fault && ((event.kind === 'relay' && !event.connected &&
|
|
183
|
+
['access-denied', 'login-required', 'invalid-config', 'throttled'].includes(event.fault.code)) ||
|
|
184
|
+
(event.kind === 'retry' && event.fault.code === 'throttled'))) {
|
|
185
|
+
this.active?.controller.abort();
|
|
186
|
+
this.active = undefined;
|
|
187
|
+
this.fail(event.fault);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (event.kind === 'relay') {
|
|
191
|
+
if (event.connected) {
|
|
192
|
+
this.nextCheck = this.timer.now();
|
|
193
|
+
this.graceUntil = 0;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
if (!this.graceUntil)
|
|
197
|
+
this.graceUntil = this.timer.now() + 8000;
|
|
198
|
+
this.transition('reconnecting', event.fault);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else if (event.kind === 'keepalive-failed')
|
|
202
|
+
this.nextCheck = this.timer.now();
|
|
203
|
+
}
|
|
204
|
+
dispose(session) {
|
|
205
|
+
return bounded(() => session.dispose(), 1000, undefined, undefined, this.timer);
|
|
206
|
+
}
|
|
207
|
+
async retire() {
|
|
208
|
+
this.generation++;
|
|
209
|
+
this.sessionLife?.abort();
|
|
210
|
+
this.sessionLife = undefined;
|
|
211
|
+
const old = this.session;
|
|
212
|
+
this.session = undefined;
|
|
213
|
+
this.deps.forwarder.setTarget(undefined);
|
|
214
|
+
if (old) {
|
|
215
|
+
try {
|
|
216
|
+
await this.dispose(old);
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
this.deps.log({ ...this.status(), cause: { code: safeFault(error).code,
|
|
220
|
+
message: 'Client teardown exceeded its bound; its generation is cancelled.' } });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
reconnect() {
|
|
225
|
+
if (this.profile.paused || !this.running)
|
|
226
|
+
return;
|
|
227
|
+
if (this.state === 'throttled' && this.nextRetry > this.timer.now())
|
|
228
|
+
return;
|
|
229
|
+
this.active?.controller.abort();
|
|
230
|
+
this.active = undefined;
|
|
231
|
+
this.attempts = 0;
|
|
232
|
+
this.nextRetry = 0;
|
|
233
|
+
this.graceUntil = 0;
|
|
234
|
+
this.connect();
|
|
235
|
+
}
|
|
236
|
+
async pause() {
|
|
237
|
+
this.profile.paused = true;
|
|
238
|
+
this.active?.controller.abort();
|
|
239
|
+
this.active = undefined;
|
|
240
|
+
this.transition('paused');
|
|
241
|
+
await this.retire();
|
|
242
|
+
await bounded(() => this.deps.forwarder.close(), 1000, undefined, undefined, this.timer);
|
|
243
|
+
this.listening = false;
|
|
244
|
+
}
|
|
245
|
+
resume() {
|
|
246
|
+
if (!this.profile.paused)
|
|
247
|
+
return;
|
|
248
|
+
this.profile.paused = false;
|
|
249
|
+
this.nextRetry = 0;
|
|
250
|
+
this.nextCheck = 0;
|
|
251
|
+
this.graceUntil = 0;
|
|
252
|
+
this.attempts = 0;
|
|
253
|
+
if (!this.running)
|
|
254
|
+
this.start();
|
|
255
|
+
else
|
|
256
|
+
this.connect();
|
|
257
|
+
}
|
|
258
|
+
async stop() {
|
|
259
|
+
this.running = false;
|
|
260
|
+
this.cancelTick?.();
|
|
261
|
+
this.cancelTick = undefined;
|
|
262
|
+
await this.pause();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../src/recovery.ts"],"names":[],"mappings":"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"}
|
package/dist/rpc.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Fault } from './core.ts';
|
|
2
|
+
import type { Profile } from './config.ts';
|
|
3
|
+
export type Request = {
|
|
4
|
+
v: 1;
|
|
5
|
+
command: 'status';
|
|
6
|
+
} | {
|
|
7
|
+
v: 1;
|
|
8
|
+
command: 'logs';
|
|
9
|
+
} | {
|
|
10
|
+
v: 1;
|
|
11
|
+
command: 'add';
|
|
12
|
+
profile: Profile;
|
|
13
|
+
} | {
|
|
14
|
+
v: 1;
|
|
15
|
+
command: 'pause' | 'resume' | 'reconnect';
|
|
16
|
+
name: string;
|
|
17
|
+
};
|
|
18
|
+
export declare class RpcServer {
|
|
19
|
+
private readonly path;
|
|
20
|
+
private readonly handler;
|
|
21
|
+
private readonly log;
|
|
22
|
+
private server;
|
|
23
|
+
private inode;
|
|
24
|
+
private readonly sockets;
|
|
25
|
+
constructor(path: string, handler: (request: Request) => Promise<unknown>, log: (fault: Fault) => void);
|
|
26
|
+
listen(): Promise<void>;
|
|
27
|
+
private accept;
|
|
28
|
+
close(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export declare function request(path: string, value: unknown, timeoutMs?: number): Promise<unknown>;
|