@jonathanyee/devtunnel-ctl 0.0.0-stage → 0.1.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 +281 -2
- package/dist/auth.d.ts +23 -0
- package/dist/auth.js +150 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +206 -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 +112 -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/launchd.d.ts +10 -0
- package/dist/launchd.js +131 -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 +29 -0
- package/dist/sdk-transport.js +239 -0
- package/dist/sdk-transport.js.map +1 -0
- package/npm-shrinkwrap.json +809 -0
- package/package.json +31 -4
package/dist/rpc.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import net from 'node:net';
|
|
2
|
+
import { lstat, chmod, unlink } from 'node:fs/promises';
|
|
3
|
+
import { bounded, Fault, record, safeFault, isFaultCode, redact } from "./core.js";
|
|
4
|
+
import { validateConfig } from "./config.js";
|
|
5
|
+
function parseRequest(value) {
|
|
6
|
+
if (!record(value) || value.v !== 1)
|
|
7
|
+
throw new Fault('protocol');
|
|
8
|
+
const allowed = new Set(['v', 'command', 'profile', 'name']);
|
|
9
|
+
if (Object.keys(value).some(key => !allowed.has(key)))
|
|
10
|
+
throw new Fault('protocol');
|
|
11
|
+
if (value.command === 'status' || value.command === 'logs')
|
|
12
|
+
return { v: 1, command: value.command };
|
|
13
|
+
if (value.command === 'add') {
|
|
14
|
+
const config = validateConfig({ version: 1, helperPath: '/unused', profiles: [value.profile] });
|
|
15
|
+
return { v: 1, command: 'add', profile: config.profiles[0] };
|
|
16
|
+
}
|
|
17
|
+
if (['pause', 'resume', 'reconnect'].includes(String(value.command)) &&
|
|
18
|
+
typeof value.name === 'string' && /^(all|[a-z][a-z0-9-]{0,31})$/.test(value.name)) {
|
|
19
|
+
if (value.command === 'pause' || value.command === 'resume' || value.command === 'reconnect') {
|
|
20
|
+
return { v: 1, command: value.command, name: value.name };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
throw new Fault('protocol');
|
|
24
|
+
}
|
|
25
|
+
function parseFrame(text) {
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(text);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw new Fault('protocol');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class RpcServer {
|
|
34
|
+
path;
|
|
35
|
+
handler;
|
|
36
|
+
log;
|
|
37
|
+
server;
|
|
38
|
+
inode;
|
|
39
|
+
sockets = new Set();
|
|
40
|
+
constructor(path, handler, log) {
|
|
41
|
+
this.path = path;
|
|
42
|
+
this.handler = handler;
|
|
43
|
+
this.log = log;
|
|
44
|
+
}
|
|
45
|
+
async listen() {
|
|
46
|
+
if (Buffer.byteLength(this.path) > 100)
|
|
47
|
+
throw new Fault('invalid-config', 'State directory path is too long for a Unix socket (limit 100 bytes including control.sock).');
|
|
48
|
+
try {
|
|
49
|
+
const info = await lstat(this.path);
|
|
50
|
+
if (!info.isSocket() || info.uid !== process.getuid?.())
|
|
51
|
+
throw new Fault('invalid-config', 'Control socket path is not an owned Unix socket.');
|
|
52
|
+
const live = await bounded(signal => new Promise((resolve, reject) => {
|
|
53
|
+
const socket = net.connect(this.path);
|
|
54
|
+
const abort = () => { socket.destroy(); reject(new Fault('daemon-unavailable', 'Existing control socket is unresponsive; refusing to unlink it.')); };
|
|
55
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
56
|
+
const done = (result) => { signal.removeEventListener('abort', abort); socket.destroy(); resolve(result); };
|
|
57
|
+
socket.once('connect', () => done(true));
|
|
58
|
+
socket.once('error', error => {
|
|
59
|
+
if ('code' in error && error.code === 'ECONNREFUSED')
|
|
60
|
+
done(false);
|
|
61
|
+
else {
|
|
62
|
+
signal.removeEventListener('abort', abort);
|
|
63
|
+
socket.destroy();
|
|
64
|
+
reject(new Fault('daemon-unavailable'));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}), 500);
|
|
68
|
+
if (live)
|
|
69
|
+
throw new Fault('daemon-unavailable', 'A daemon already owns the control socket.');
|
|
70
|
+
const current = await lstat(this.path);
|
|
71
|
+
if (current.ino !== info.ino)
|
|
72
|
+
throw new Fault('daemon-unavailable', 'Control socket ownership changed; refusing cleanup.');
|
|
73
|
+
await unlink(this.path);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
const server = net.createServer(socket => this.accept(socket));
|
|
80
|
+
server.maxConnections = 32;
|
|
81
|
+
this.server = server;
|
|
82
|
+
await new Promise((resolve, reject) => {
|
|
83
|
+
server.once('error', reject);
|
|
84
|
+
server.listen(this.path, () => { server.off('error', reject); resolve(); });
|
|
85
|
+
});
|
|
86
|
+
this.inode = (await lstat(this.path)).ino;
|
|
87
|
+
await chmod(this.path, 0o600);
|
|
88
|
+
server.on('error', () => this.log(new Fault('internal', 'Control listener failed.')));
|
|
89
|
+
}
|
|
90
|
+
accept(socket) {
|
|
91
|
+
this.sockets.add(socket);
|
|
92
|
+
const timeout = setTimeout(() => socket.destroy(), 5000);
|
|
93
|
+
socket.on('error', () => socket.destroy());
|
|
94
|
+
socket.once('close', () => { clearTimeout(timeout); this.sockets.delete(socket); });
|
|
95
|
+
let bytes = 0, text = '', handled = false;
|
|
96
|
+
socket.on('data', (chunk) => {
|
|
97
|
+
if (handled) {
|
|
98
|
+
socket.destroy();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
bytes += chunk.length;
|
|
102
|
+
if (bytes > 32768) {
|
|
103
|
+
this.log(new Fault('protocol'));
|
|
104
|
+
socket.destroy();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
text += chunk.toString('utf8');
|
|
108
|
+
const end = text.indexOf('\n');
|
|
109
|
+
if (end < 0)
|
|
110
|
+
return;
|
|
111
|
+
handled = true;
|
|
112
|
+
if (text.slice(end + 1).trim()) {
|
|
113
|
+
socket.destroy();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const send = (value) => {
|
|
117
|
+
const frame = JSON.stringify(value) + '\n';
|
|
118
|
+
if (Buffer.byteLength(frame) > 131072) {
|
|
119
|
+
this.log(new Fault('protocol'));
|
|
120
|
+
socket.destroy();
|
|
121
|
+
}
|
|
122
|
+
else
|
|
123
|
+
socket.end(frame);
|
|
124
|
+
};
|
|
125
|
+
void Promise.resolve().then(() => this.handler(parseRequest(parseFrame(text.slice(0, end))))).then(result => send({ ok: true, result }), error => {
|
|
126
|
+
const fault = safeFault(error);
|
|
127
|
+
this.log(fault);
|
|
128
|
+
send({ ok: false, error: { code: fault.code, message: fault.message } });
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async close() {
|
|
133
|
+
for (const socket of this.sockets)
|
|
134
|
+
socket.destroy();
|
|
135
|
+
if (this.server?.listening) {
|
|
136
|
+
await bounded(() => new Promise((resolve, reject) => this.server.close(error => error ? reject(error) : resolve())), 1000);
|
|
137
|
+
}
|
|
138
|
+
if (this.inode !== undefined) {
|
|
139
|
+
try {
|
|
140
|
+
const info = await lstat(this.path);
|
|
141
|
+
if (info.ino === this.inode && info.isSocket())
|
|
142
|
+
await unlink(this.path);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
export function request(path, value, timeoutMs = 4500) {
|
|
152
|
+
const frame = JSON.stringify(value) + '\n';
|
|
153
|
+
if (Buffer.byteLength(frame) > 32768)
|
|
154
|
+
return Promise.reject(new Fault('protocol'));
|
|
155
|
+
return bounded(signal => new Promise((resolve, reject) => {
|
|
156
|
+
const socket = net.connect(path);
|
|
157
|
+
let bytes = 0, text = '', done = false;
|
|
158
|
+
const finish = (error, result) => {
|
|
159
|
+
if (done)
|
|
160
|
+
return;
|
|
161
|
+
done = true;
|
|
162
|
+
signal.removeEventListener('abort', abort);
|
|
163
|
+
socket.destroy();
|
|
164
|
+
if (error)
|
|
165
|
+
reject(error);
|
|
166
|
+
else
|
|
167
|
+
resolve(result);
|
|
168
|
+
};
|
|
169
|
+
const abort = () => finish(new Fault('daemon-unavailable', 'Daemon did not respond before the deadline. State changes may have completed; check status before retrying.'));
|
|
170
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
171
|
+
socket.once('connect', () => socket.write(frame));
|
|
172
|
+
socket.on('error', () => finish(new Fault('daemon-unavailable')));
|
|
173
|
+
socket.once('close', () => { if (!done)
|
|
174
|
+
finish(new Fault('daemon-unavailable')); });
|
|
175
|
+
socket.on('data', (chunk) => {
|
|
176
|
+
bytes += chunk.length;
|
|
177
|
+
if (bytes > 131072) {
|
|
178
|
+
finish(new Fault('protocol'));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
text += chunk.toString('utf8');
|
|
182
|
+
const end = text.indexOf('\n');
|
|
183
|
+
if (end < 0)
|
|
184
|
+
return;
|
|
185
|
+
try {
|
|
186
|
+
const response = parseFrame(text.slice(0, end));
|
|
187
|
+
if (!record(response) || typeof response.ok !== 'boolean')
|
|
188
|
+
throw new Fault('protocol');
|
|
189
|
+
if (response.ok)
|
|
190
|
+
finish(undefined, response.result);
|
|
191
|
+
else if (record(response.error) && typeof response.error.message === 'string' && isFaultCode(response.error.code)) {
|
|
192
|
+
finish(new Fault(response.error.code, redact(response.error.message)));
|
|
193
|
+
}
|
|
194
|
+
else
|
|
195
|
+
throw new Fault('protocol');
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
finish(new Fault('protocol'));
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}), timeoutMs).catch(error => {
|
|
202
|
+
if (error instanceof Fault && error.code === 'timeout') {
|
|
203
|
+
throw new Fault('daemon-unavailable', 'Daemon did not respond before the deadline. State changes may have completed; check status before retrying.');
|
|
204
|
+
}
|
|
205
|
+
throw error;
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=rpc.js.map
|
package/dist/rpc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.js","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { TunnelRelayTunnelClient } from '@microsoft/dev-tunnels-connections';
|
|
2
|
+
import { TunnelManagementHttpClient } from '@microsoft/dev-tunnels-management';
|
|
3
|
+
import type { Tunnel } from '@microsoft/dev-tunnels-contracts';
|
|
4
|
+
import { Agent } from 'node:https';
|
|
5
|
+
import type { Duplex } from 'node:stream';
|
|
6
|
+
import type { Profile } from './config.ts';
|
|
7
|
+
import { TokenProvider } from './auth.ts';
|
|
8
|
+
import { Fault } from './core.ts';
|
|
9
|
+
export interface TransportEvent {
|
|
10
|
+
kind: 'relay' | 'keepalive-failed' | 'keepalive-succeeded' | 'retry';
|
|
11
|
+
connected?: boolean;
|
|
12
|
+
fault?: Fault;
|
|
13
|
+
}
|
|
14
|
+
export interface Session {
|
|
15
|
+
readonly connected: boolean;
|
|
16
|
+
open(signal: AbortSignal): Promise<Duplex>;
|
|
17
|
+
dispose(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export interface Transport {
|
|
20
|
+
connect(profile: Profile, signal: AbortSignal, event: (event: TransportEvent) => void): Promise<Session>;
|
|
21
|
+
}
|
|
22
|
+
export declare function resolveTunnel(profile: Profile, tokens: TokenProvider, management: TunnelManagementHttpClient, signal: AbortSignal): Promise<Tunnel>;
|
|
23
|
+
export declare class SdkTransport implements Transport {
|
|
24
|
+
private readonly tokens;
|
|
25
|
+
private readonly managementFactory;
|
|
26
|
+
private readonly clientFactory;
|
|
27
|
+
constructor(tokens: TokenProvider, managementFactory?: (agent: Agent) => TunnelManagementHttpClient, clientFactory?: () => TunnelRelayTunnelClient);
|
|
28
|
+
connect(profile: Profile, signal: AbortSignal, event: (e: TransportEvent) => void): Promise<Session>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { TunnelRelayTunnelClient, ConnectionStatus, RelayConnectionError } from '@microsoft/dev-tunnels-connections';
|
|
2
|
+
import { TunnelManagementHttpClient, ManagementApiVersions } from '@microsoft/dev-tunnels-management';
|
|
3
|
+
import { CancellationTokenSource, SecureStream } from '@microsoft/dev-tunnels-ssh';
|
|
4
|
+
import { TunnelConnectionMode } from '@microsoft/dev-tunnels-contracts';
|
|
5
|
+
import { Agent } from 'node:https';
|
|
6
|
+
import { TokenProvider } from "./auth.js";
|
|
7
|
+
import { bounded, Fault, safeFault } from "./core.js";
|
|
8
|
+
async function sdkCall(signal, action) {
|
|
9
|
+
const source = new CancellationTokenSource();
|
|
10
|
+
const abort = () => source.cancel();
|
|
11
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
12
|
+
if (signal.aborted)
|
|
13
|
+
source.cancel();
|
|
14
|
+
try {
|
|
15
|
+
return await action(source.token);
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
signal.removeEventListener('abort', abort);
|
|
19
|
+
source.dispose();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function sdkRefresh(signal, cancellation, timeoutMs, action) {
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
const subscription = cancellation?.onCancellationRequested(() => controller.abort());
|
|
25
|
+
if (cancellation?.isCancellationRequested)
|
|
26
|
+
controller.abort();
|
|
27
|
+
try {
|
|
28
|
+
return await bounded(action, timeoutMs, AbortSignal.any([signal, controller.signal]));
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
subscription?.dispose();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function resolveTunnel(profile, tokens, management, signal) {
|
|
35
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
36
|
+
const token = await tokens.get(profile, signal, attempt > 0);
|
|
37
|
+
const clusterId = profile.clusterId ?? token.clusterId;
|
|
38
|
+
if (!clusterId)
|
|
39
|
+
throw new Fault('invalid-config', 'Specify --cluster: the token has no SDK routing hint.');
|
|
40
|
+
try {
|
|
41
|
+
const tunnel = await bounded(inner => sdkCall(inner, cancellation => management.getTunnel({ tunnelId: profile.tunnelId, clusterId }, { accessToken: token.value, includePorts: true, followRedirects: true }, cancellation)), 8000, signal);
|
|
42
|
+
if (!tunnel)
|
|
43
|
+
throw new Fault('remote-unavailable');
|
|
44
|
+
return { ...tunnel, accessTokens: { connect: token.value } };
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const fault = safeFault(error);
|
|
48
|
+
if (fault.code === 'login-required' && attempt === 0)
|
|
49
|
+
continue;
|
|
50
|
+
throw fault;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
throw new Fault('login-required');
|
|
54
|
+
}
|
|
55
|
+
export class SdkTransport {
|
|
56
|
+
tokens;
|
|
57
|
+
managementFactory;
|
|
58
|
+
clientFactory;
|
|
59
|
+
constructor(tokens, managementFactory = (agent) => new TunnelManagementHttpClient({ name: 'devtunnel-ctl', version: '0.1.0' }, ManagementApiVersions.Version20230927preview, undefined, undefined, agent), clientFactory = () => new TunnelRelayTunnelClient(undefined, () => { })) {
|
|
60
|
+
this.tokens = tokens;
|
|
61
|
+
this.managementFactory = managementFactory;
|
|
62
|
+
this.clientFactory = clientFactory;
|
|
63
|
+
}
|
|
64
|
+
async connect(profile, signal, event) {
|
|
65
|
+
const agent = new Agent({ keepAlive: false, maxSockets: 8, timeout: 10000 });
|
|
66
|
+
const management = this.managementFactory(agent);
|
|
67
|
+
management.trace = () => { };
|
|
68
|
+
management.enableEventsReporting = false;
|
|
69
|
+
const client = this.clientFactory();
|
|
70
|
+
client.trace = () => { };
|
|
71
|
+
client.acceptLocalConnectionsForForwardedPorts = false;
|
|
72
|
+
const lifetime = new AbortController();
|
|
73
|
+
const streams = new Set();
|
|
74
|
+
const destroyStream = (stream) => {
|
|
75
|
+
if (stream instanceof SecureStream)
|
|
76
|
+
stream.dispose();
|
|
77
|
+
stream.destroy();
|
|
78
|
+
};
|
|
79
|
+
const metadata = async (signal) => {
|
|
80
|
+
const tunnel = await resolveTunnel(profile, this.tokens, management, signal);
|
|
81
|
+
const endpoints = tunnel.endpoints?.filter(e => e.connectionMode === TunnelConnectionMode.TunnelRelay);
|
|
82
|
+
if (!endpoints?.length)
|
|
83
|
+
throw new Fault('remote-unavailable');
|
|
84
|
+
if (endpoints.some(e => !e.hostPublicKeys?.length)) {
|
|
85
|
+
throw new Fault('remote-unavailable', 'Tunnel host has not published public keys; refusing unverified host identity.');
|
|
86
|
+
}
|
|
87
|
+
return tunnel;
|
|
88
|
+
};
|
|
89
|
+
const subscriptions = [];
|
|
90
|
+
let disposed = false, established = false, refreshes = 0, authRetried = false, graceUntil = 0;
|
|
91
|
+
let refreshEpoch = 0;
|
|
92
|
+
let refreshFailure;
|
|
93
|
+
const clearRefreshEvidence = () => { refreshEpoch++; refreshFailure = undefined; };
|
|
94
|
+
const connectionFault = (error) => {
|
|
95
|
+
// The SDK can rethrow the original relay 401 after its refresh handler fails.
|
|
96
|
+
if (error instanceof RelayConnectionError && error.errorContext.statusCode === 401 && refreshFailure) {
|
|
97
|
+
return refreshFailure;
|
|
98
|
+
}
|
|
99
|
+
return safeFault(error);
|
|
100
|
+
};
|
|
101
|
+
let disposal;
|
|
102
|
+
const emit = (e) => { if (!disposed && !lifetime.signal.aborted)
|
|
103
|
+
event(e); };
|
|
104
|
+
const dispose = () => {
|
|
105
|
+
if (disposal)
|
|
106
|
+
return disposal;
|
|
107
|
+
disposed = true;
|
|
108
|
+
clearRefreshEvidence();
|
|
109
|
+
lifetime.abort();
|
|
110
|
+
agent.destroy();
|
|
111
|
+
for (const stream of streams)
|
|
112
|
+
destroyStream(stream);
|
|
113
|
+
streams.clear();
|
|
114
|
+
signal.removeEventListener('abort', abort);
|
|
115
|
+
for (const subscription of subscriptions)
|
|
116
|
+
subscription.dispose();
|
|
117
|
+
disposal = bounded(() => Promise.all([client.dispose(), management.dispose()]).then(() => { }), 2000);
|
|
118
|
+
return disposal;
|
|
119
|
+
};
|
|
120
|
+
const abort = () => { void dispose().catch(error => event({ kind: 'retry', fault: safeFault(error) })); };
|
|
121
|
+
const relayFactory = client.streamFactory;
|
|
122
|
+
client.streamFactory = {
|
|
123
|
+
createRelayStream: async (...args) => {
|
|
124
|
+
if (!args[0].startsWith('wss://'))
|
|
125
|
+
throw new Fault('remote-unavailable', 'Relay endpoint must use authenticated TLS.');
|
|
126
|
+
try {
|
|
127
|
+
return await bounded(() => relayFactory.createRelayStream(args[0], args[1], args[2], { ...args[3], tlsOptions: { ...args[3]?.tlsOptions, agent } }, args[4]), 10000, lifetime.signal, late => bounded(() => late.stream.close(), 1000));
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
agent.destroy();
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
136
|
+
if (signal.aborted) {
|
|
137
|
+
await dispose();
|
|
138
|
+
throw new Fault('aborted');
|
|
139
|
+
}
|
|
140
|
+
subscriptions.push(client.portForwarding(e => { e.cancel = e.portNumber !== profile.remotePort; }));
|
|
141
|
+
subscriptions.push(client.connectionStatusChanged(e => {
|
|
142
|
+
const connected = e.status === ConnectionStatus.Connected;
|
|
143
|
+
const fault = e.disconnectError ? connectionFault(e.disconnectError) : undefined;
|
|
144
|
+
if (connected) {
|
|
145
|
+
established = true;
|
|
146
|
+
graceUntil = 0;
|
|
147
|
+
refreshes = 0;
|
|
148
|
+
authRetried = false;
|
|
149
|
+
clearRefreshEvidence();
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
if (e.status === ConnectionStatus.Connecting &&
|
|
153
|
+
(e.previousStatus === ConnectionStatus.Connected || e.previousStatus === ConnectionStatus.Disconnected)) {
|
|
154
|
+
refreshes = 0;
|
|
155
|
+
authRetried = false;
|
|
156
|
+
clearRefreshEvidence();
|
|
157
|
+
}
|
|
158
|
+
if (established && !graceUntil)
|
|
159
|
+
graceUntil = Date.now() + 8000;
|
|
160
|
+
}
|
|
161
|
+
emit({ kind: 'relay', connected, ...(fault ? { fault } : {}) });
|
|
162
|
+
}));
|
|
163
|
+
subscriptions.push(client.keepAliveFailed(() => emit({ kind: 'keepalive-failed' })));
|
|
164
|
+
subscriptions.push(client.keepAliveSucceeded(() => emit({ kind: 'keepalive-succeeded' })));
|
|
165
|
+
subscriptions.push(client.retryingTunnelConnection(e => {
|
|
166
|
+
const fault = connectionFault(e.error);
|
|
167
|
+
const initialAuthRetry = !established && refreshes === 1 && !authRetried;
|
|
168
|
+
if (initialAuthRetry)
|
|
169
|
+
authRetried = true;
|
|
170
|
+
// The outer controller owns retry scheduling; the SDK only owns a short resumable grace.
|
|
171
|
+
e.retry = (initialAuthRetry || (established && Date.now() < graceUntil)) &&
|
|
172
|
+
fault.code !== 'access-denied' && fault.code !== 'throttled' && !refreshFailure && !disposed;
|
|
173
|
+
emit({ kind: 'retry', fault });
|
|
174
|
+
}));
|
|
175
|
+
subscriptions.push(client.refreshingTunnelAccessToken(e => {
|
|
176
|
+
clearRefreshEvidence();
|
|
177
|
+
const epoch = refreshEpoch;
|
|
178
|
+
const current = () => epoch === refreshEpoch && !disposed && !lifetime.signal.aborted;
|
|
179
|
+
e.tunnelAccessToken = sdkRefresh(lifetime.signal, e.cancellation, 12000, inner => {
|
|
180
|
+
if (!current())
|
|
181
|
+
throw new Fault('aborted');
|
|
182
|
+
if (++refreshes > 1)
|
|
183
|
+
throw new Fault('login-required');
|
|
184
|
+
return this.tokens.get(profile, inner, true).then(token => token.value);
|
|
185
|
+
}).then(token => {
|
|
186
|
+
if (!current())
|
|
187
|
+
throw new Fault('aborted');
|
|
188
|
+
return token;
|
|
189
|
+
}).catch(error => {
|
|
190
|
+
if (!current())
|
|
191
|
+
throw new Fault('aborted');
|
|
192
|
+
const fault = safeFault(error);
|
|
193
|
+
const sanitized = new Fault(fault.code, undefined, fault.retryAfterMs);
|
|
194
|
+
refreshFailure = sanitized;
|
|
195
|
+
throw sanitized;
|
|
196
|
+
});
|
|
197
|
+
}));
|
|
198
|
+
subscriptions.push(client.refreshingTunnel(e => {
|
|
199
|
+
e.tunnelPromise = sdkRefresh(lifetime.signal, e.cancellation, 20000, metadata);
|
|
200
|
+
}));
|
|
201
|
+
try {
|
|
202
|
+
const tunnel = await metadata(lifetime.signal);
|
|
203
|
+
await bounded(inner => sdkCall(inner, cancellation => client.connect(tunnel, {
|
|
204
|
+
enableRetry: true, enableReconnect: true, keepAliveIntervalInSeconds: 10, httpAgent: agent,
|
|
205
|
+
}, cancellation)), 15000, lifetime.signal);
|
|
206
|
+
await bounded(inner => sdkCall(inner, cancellation => client.waitForForwardedPort(profile.remotePort, cancellation)), 5000, lifetime.signal);
|
|
207
|
+
if (disposed || signal.aborted)
|
|
208
|
+
throw new Fault('aborted');
|
|
209
|
+
return {
|
|
210
|
+
get connected() { return !disposed && client.connectionStatus === ConnectionStatus.Connected; },
|
|
211
|
+
open: async (openSignal) => {
|
|
212
|
+
if (disposed)
|
|
213
|
+
throw new Fault('aborted');
|
|
214
|
+
const stream = await bounded(inner => sdkCall(inner, cancellation => client.connectToForwardedPort(profile.remotePort, cancellation)), 3000, AbortSignal.any([openSignal, lifetime.signal]), destroyStream);
|
|
215
|
+
if (disposed || openSignal.aborted || stream.destroyed) {
|
|
216
|
+
destroyStream(stream);
|
|
217
|
+
throw new Fault('aborted');
|
|
218
|
+
}
|
|
219
|
+
streams.add(stream);
|
|
220
|
+
stream.on('error', () => destroyStream(stream));
|
|
221
|
+
stream.once('close', () => {
|
|
222
|
+
streams.delete(stream);
|
|
223
|
+
// SecureStream.destroy() alone does not close its separate SDK SSH session.
|
|
224
|
+
if (stream instanceof SecureStream)
|
|
225
|
+
stream.dispose();
|
|
226
|
+
});
|
|
227
|
+
return stream;
|
|
228
|
+
},
|
|
229
|
+
dispose,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
const fault = signal.aborted || lifetime.signal.aborted ? new Fault('aborted') : connectionFault(error);
|
|
234
|
+
await dispose().catch(disposeError => event({ kind: 'retry', fault: safeFault(disposeError) }));
|
|
235
|
+
throw fault;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=sdk-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-transport.js","sourceRoot":"","sources":["../src/sdk-transport.ts"],"names":[],"mappings":"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"}
|