@scrypted/server 0.123.8 → 0.123.10

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 (49) hide show
  1. package/dist/cluster/cluster-labels.d.ts +3 -0
  2. package/dist/cluster/cluster-labels.js +39 -0
  3. package/dist/cluster/cluster-labels.js.map +1 -0
  4. package/dist/{scrypted-cluster-common.d.ts → cluster/cluster-setup.d.ts} +8 -6
  5. package/dist/{scrypted-cluster-common.js → cluster/cluster-setup.js} +52 -11
  6. package/dist/cluster/cluster-setup.js.map +1 -0
  7. package/dist/plugin/plugin-console.js +2 -2
  8. package/dist/plugin/plugin-console.js.map +1 -1
  9. package/dist/plugin/plugin-host.js +3 -3
  10. package/dist/plugin/plugin-host.js.map +1 -1
  11. package/dist/plugin/plugin-remote-worker.js +2 -2
  12. package/dist/plugin/plugin-remote-worker.js.map +1 -1
  13. package/dist/plugin/runtime/cluster-fork.worker.d.ts +1 -1
  14. package/dist/plugin/runtime/cluster-fork.worker.js +4 -3
  15. package/dist/plugin/runtime/cluster-fork.worker.js.map +1 -1
  16. package/dist/plugin/runtime/node-fork-worker.js +2 -2
  17. package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
  18. package/dist/runtime.d.ts +1 -1
  19. package/dist/runtime.js +2 -2
  20. package/dist/runtime.js.map +1 -1
  21. package/dist/scrypted-cluster-main.d.ts +31 -0
  22. package/dist/scrypted-cluster-main.js +232 -2
  23. package/dist/scrypted-cluster-main.js.map +1 -1
  24. package/dist/scrypted-main-exports.js +2 -2
  25. package/dist/scrypted-main-exports.js.map +1 -1
  26. package/dist/scrypted-server-main.js +4 -3
  27. package/dist/scrypted-server-main.js.map +1 -1
  28. package/dist/services/cluster-fork.d.ts +2 -2
  29. package/dist/services/cluster-fork.js +2 -2
  30. package/dist/services/cluster-fork.js.map +1 -1
  31. package/package.json +2 -2
  32. package/python/plugin_remote.py +100 -141
  33. package/src/cluster/cluster-labels.ts +36 -0
  34. package/src/{scrypted-cluster-common.ts → cluster/cluster-setup.ts} +65 -13
  35. package/src/plugin/plugin-console.ts +1 -1
  36. package/src/plugin/plugin-host.ts +4 -4
  37. package/src/plugin/plugin-remote-worker.ts +2 -7
  38. package/src/plugin/runtime/cluster-fork.worker.ts +2 -2
  39. package/src/plugin/runtime/node-fork-worker.ts +1 -1
  40. package/src/runtime.ts +2 -2
  41. package/src/scrypted-cluster-main.ts +280 -1
  42. package/src/scrypted-main-exports.ts +1 -1
  43. package/src/scrypted-server-main.ts +2 -1
  44. package/src/services/cluster-fork.ts +2 -1
  45. package/dist/scrypted-cluster-common.js.map +0 -1
  46. package/dist/scrypted-cluster.d.ts +0 -38
  47. package/dist/scrypted-cluster.js +0 -290
  48. package/dist/scrypted-cluster.js.map +0 -1
  49. package/src/scrypted-cluster.ts +0 -344
@@ -1,5 +1,21 @@
1
+ import type { ForkOptions } from '@scrypted/types';
2
+ import { once } from 'events';
1
3
  import { install as installSourceMapSupport } from 'source-map-support';
2
- import { startClusterClient } from './scrypted-cluster';
4
+ import type { Readable } from 'stream';
5
+ import tls from 'tls';
6
+ import type { createSelfSignedCertificate } from './cert';
7
+ import { computeClusterObjectHash } from './cluster/cluster-hash';
8
+ import { getClusterLabels } from './cluster/cluster-labels';
9
+ import { getScryptedClusterMode, InitializeCluster, setupCluster } from './cluster/cluster-setup';
10
+ import type { ClusterObject } from './cluster/connect-rpc-object';
11
+ import { getPluginVolume, getScryptedVolume } from './plugin/plugin-volume';
12
+ import { prepareZip } from './plugin/runtime/node-worker-common';
13
+ import { getBuiltinRuntimeHosts } from './plugin/runtime/runtime-host';
14
+ import { RuntimeWorker } from './plugin/runtime/runtime-worker';
15
+ import { RpcPeer } from './rpc';
16
+ import { createRpcDuplexSerializer } from './rpc-serializer';
17
+ import type { ScryptedRuntime } from './runtime';
18
+ import { sleep } from './sleep';
3
19
 
4
20
  installSourceMapSupport({
5
21
  environment: 'node',
@@ -10,3 +26,266 @@ async function start(mainFilename: string) {
10
26
  }
11
27
 
12
28
  export default start;
29
+
30
+ function peerLifecycle(serializer: ReturnType<typeof createRpcDuplexSerializer>, peer: RpcPeer, socket: tls.TLSSocket, type: 'server' | 'client') {
31
+ serializer.setupRpcPeer(peer);
32
+
33
+ socket.on('data', data => serializer.onData(data));
34
+
35
+ socket.on('error', e => {
36
+ peer.kill(e.message);
37
+ });
38
+ socket.on('close', () => {
39
+ peer.kill(`cluster ${type} closed`);
40
+ });
41
+ peer.killed.then(() => {
42
+ socket.destroy();
43
+ });
44
+ }
45
+
46
+ function preparePeer(socket: tls.TLSSocket, type: 'server' | 'client') {
47
+ const serializer = createRpcDuplexSerializer(socket);
48
+ const peer = new RpcPeer(`cluster-remote:${socket.remoteAddress}:${socket.remotePort}`, 'cluster-host', (message, reject, serializationContext) => {
49
+ serializer.sendMessage(message, reject, serializationContext);
50
+ });
51
+
52
+ peerLifecycle(serializer, peer, socket, type);
53
+
54
+ return peer;
55
+ }
56
+
57
+ export interface ClusterForkOptions {
58
+ runtime?: ForkOptions['runtime'];
59
+ labels?: ForkOptions['labels'];
60
+ }
61
+
62
+ type ConnectForkWorker = (auth: ClusterObject, properties: ClusterWorkerProperties) => Promise<{ clusterId: string }>;
63
+
64
+ export interface ClusterWorkerProperties {
65
+ labels: string[];
66
+ }
67
+
68
+ export interface ClusterWorker extends ClusterWorkerProperties {
69
+ peer: RpcPeer;
70
+ }
71
+
72
+ export class PeerLiveness {
73
+ __proxy_oneway_methods = ['kill'];
74
+ constructor(private killed: Promise<any>) {
75
+ }
76
+ async waitKilled() {
77
+ return this.killed;
78
+ }
79
+ }
80
+
81
+ export class ClusterForkResult extends PeerLiveness {
82
+ constructor(private peer: RpcPeer, killed: Promise<any>, private result: any) {
83
+ super(killed);
84
+ }
85
+
86
+ async kill() {
87
+ this.peer.kill('killed');
88
+ }
89
+
90
+ async getResult() {
91
+ return this.result;
92
+ }
93
+ }
94
+
95
+ export type ClusterForkParam = (peerLiveness: PeerLiveness, runtime: string, packageJson: any, zipHash: string, getZip: () => Promise<Buffer>) => Promise<ClusterForkResult>;
96
+
97
+ export function startClusterClient(mainFilename: string) {
98
+ const labels = getClusterLabels();
99
+
100
+ const clusterSecret = process.env.SCRYPTED_CLUSTER_SECRET;
101
+ const clusterMode = getScryptedClusterMode();
102
+ const [, host, port] = clusterMode;
103
+ (async () => {
104
+ while (true) {
105
+ const backoff = sleep(10000);
106
+ const socket = tls.connect({
107
+ host,
108
+ port,
109
+ rejectUnauthorized: false,
110
+ });
111
+
112
+ await once(socket, 'secureConnect');
113
+ const { localAddress, localPort } = socket;
114
+ console.log('Cluster server connected.', localAddress, localPort);
115
+ socket.on('close', () => {
116
+ console.log('Cluster server disconnected.', localAddress, localPort);
117
+ });
118
+
119
+ const peer = preparePeer(socket, 'client');
120
+
121
+ try {
122
+ const connectForkWorker: ConnectForkWorker = await peer.getParam('connectForkWorker');
123
+ const auth: ClusterObject = {
124
+ address: socket.localAddress,
125
+ port: socket.localPort,
126
+ id: undefined,
127
+ proxyId: undefined,
128
+ sourceKey: undefined,
129
+ sha256: undefined,
130
+ };
131
+ auth.sha256 = computeClusterObjectHash(auth, clusterSecret);
132
+
133
+ const properties: ClusterWorkerProperties = {
134
+ labels,
135
+ };
136
+
137
+ const { clusterId } = await connectForkWorker(auth, properties);
138
+ const clusterPeerSetup = setupCluster(peer);
139
+ await clusterPeerSetup.initializeCluster({ clusterId, clusterSecret });
140
+
141
+ const clusterForkParam: ClusterForkParam = async (
142
+ peerLiveness: PeerLiveness,
143
+ runtime: string,
144
+ packageJson: any,
145
+ zipHash: string,
146
+ getZip: () => Promise<Buffer>) => {
147
+ let runtimeWorker: RuntimeWorker;
148
+
149
+ const builtins = getBuiltinRuntimeHosts();
150
+ const rt = builtins.get(runtime);
151
+ if (!rt)
152
+ throw new Error('unknown runtime ' + runtime);
153
+
154
+ const pluginId: string = packageJson.name;
155
+ const { zipFile, unzippedPath } = await prepareZip(getPluginVolume(pluginId), zipHash, getZip);
156
+
157
+ const volume = getScryptedVolume();
158
+ const pluginVolume = getPluginVolume(pluginId);
159
+
160
+ runtimeWorker = rt(mainFilename, pluginId, {
161
+ packageJson,
162
+ env: {
163
+ SCRYPTED_VOLUME: volume,
164
+ SCRYPTED_PLUGIN_VOLUME: pluginVolume,
165
+ },
166
+ pluginDebug: undefined,
167
+ zipFile,
168
+ unzippedPath,
169
+ zipHash,
170
+ }, undefined);
171
+
172
+ const threadPeer = new RpcPeer('main', 'thread', (message, reject, serializationContext) => runtimeWorker.send(message, reject, serializationContext));
173
+
174
+ let pongPromise: Promise<(time: number) => Promise<void>>
175
+ threadPeer.params.pong = async (time: number) => {
176
+ pongPromise = pongPromise || threadPeer.getParam('pong');
177
+ const pong = await pongPromise;
178
+ await pong(time);
179
+ };
180
+
181
+ runtimeWorker.setupRpcPeer(threadPeer);
182
+ runtimeWorker.on('exit', () => {
183
+ threadPeer.kill('worker exited');
184
+ });
185
+ runtimeWorker.on('error', e => {
186
+ threadPeer.kill('worker error ' + e);
187
+ });
188
+ threadPeer.killed.catch(() => { }).finally(() => {
189
+ runtimeWorker.kill();
190
+ });
191
+ peerLiveness.waitKilled().catch(() => { }).finally(() => {
192
+ threadPeer.kill('peer killed');
193
+ });
194
+ let getRemote: any;
195
+ try {
196
+ const initializeCluster: InitializeCluster = await threadPeer.getParam('initializeCluster');
197
+ await initializeCluster({ clusterId, clusterSecret });
198
+ getRemote = await threadPeer.getParam('getRemote');
199
+ }
200
+ catch (e) {
201
+ threadPeer.kill('cluster fork failed');
202
+ throw e;
203
+ }
204
+
205
+ const readStream = async function* (stream: Readable) {
206
+ for await (const buffer of stream) {
207
+ yield buffer;
208
+ }
209
+ }
210
+
211
+ const timeout = setTimeout(() => {
212
+ threadPeer.kill('cluster fork timeout');
213
+ }, 10000);
214
+ const clusterGetRemote = (...args: any[]) => {
215
+ clearTimeout(timeout);
216
+ return {
217
+ [RpcPeer.PROPERTY_JSON_COPY_SERIALIZE_CHILDREN]: true,
218
+ stdout: readStream(runtimeWorker.stdout),
219
+ stderr: readStream(runtimeWorker.stderr),
220
+ getRemote,
221
+ };
222
+ };
223
+
224
+ const result = new ClusterForkResult(threadPeer, threadPeer.killed, clusterGetRemote);
225
+ return result;
226
+ };
227
+
228
+ peer.params['fork'] = clusterForkParam;
229
+
230
+ await peer.killed;
231
+ }
232
+ catch (e) {
233
+ peer.kill(e.message);
234
+ socket.destroy();
235
+ console.warn('Cluster client error:', localAddress, localPort, e);
236
+ }
237
+ await backoff;
238
+ }
239
+ })();
240
+ }
241
+
242
+ export function createClusterServer(runtime: ScryptedRuntime, certificate: ReturnType<typeof createSelfSignedCertificate>) {
243
+ const server = tls.createServer({
244
+ key: certificate.serviceKey,
245
+ cert: certificate.certificate,
246
+ }, (socket) => {
247
+ console.log('Cluster client connected.', socket.remoteAddress, socket.remotePort);
248
+ socket.on('close', () => {
249
+ console.log('Cluster client disconnected.', socket.remoteAddress, socket.remotePort);
250
+ });
251
+
252
+ const peer = preparePeer(socket, 'server');
253
+
254
+ const connectForkWorker: ConnectForkWorker = async (auth: ClusterObject, properties: ClusterWorkerProperties) => {
255
+ try {
256
+ const sha256 = computeClusterObjectHash(auth, runtime.clusterSecret);
257
+ if (sha256 !== auth.sha256)
258
+ throw new Error('cluster object hash mismatch');
259
+ // the remote address may be ipv6 prefixed so use a fuzzy match.
260
+ // eg ::ffff:192.168.2.124
261
+ if (!process.env.SCRYPTED_DISABLE_CLUSTER_SERVER_TRUST) {
262
+ if (auth.port !== socket.remotePort || !socket.remoteAddress.endsWith(auth.address))
263
+ throw new Error('cluster object address mismatch');
264
+ }
265
+ const worker: ClusterWorker = {
266
+ ...properties,
267
+ peer,
268
+ };
269
+ runtime.clusterWorkers.add(worker);
270
+ peer.killed.then(() => {
271
+ runtime.clusterWorkers.delete(worker);
272
+ });
273
+ socket.on('close', () => {
274
+ runtime.clusterWorkers.delete(worker);
275
+ });
276
+ console.log('Cluster client authenticated.', socket.remoteAddress, socket.remotePort, properties);
277
+ }
278
+ catch (e) {
279
+ peer.kill(e);
280
+ socket.destroy();
281
+ }
282
+
283
+ return {
284
+ clusterId: runtime.clusterId,
285
+ }
286
+ }
287
+ peer.params['connectForkWorker'] = connectForkWorker;
288
+ });
289
+
290
+ return server;
291
+ }
@@ -11,7 +11,7 @@ import { getScryptedVolume } from './plugin/plugin-volume';
11
11
  import { isNodePluginWorkerProcess } from './plugin/runtime/node-fork-worker';
12
12
  import { RPCResultError, startPeriodicGarbageCollection } from './rpc';
13
13
  import type { Runtime } from './scrypted-server-main';
14
- import { getScryptedClusterMode } from './scrypted-cluster';
14
+ import { getScryptedClusterMode } from './cluster/cluster-setup';
15
15
 
16
16
  function start(mainFilename: string, options?: {
17
17
  onRuntimeCreated?: (runtime: Runtime) => Promise<void>,
@@ -23,7 +23,8 @@ import { getNpmPackageInfo } from './services/plugin';
23
23
  import { setScryptedUserPassword, UsersService } from './services/users';
24
24
  import { sleep } from './sleep';
25
25
  import { ONE_DAY_MILLISECONDS, UserToken } from './usertoken';
26
- import { createClusterServer, getScryptedClusterMode } from './scrypted-cluster';
26
+ import { createClusterServer } from './scrypted-cluster-main';
27
+ import { getScryptedClusterMode } from './cluster/cluster-setup';
27
28
 
28
29
  export type Runtime = ScryptedRuntime;
29
30
 
@@ -1,5 +1,6 @@
1
1
  import type { ScryptedRuntime } from "../runtime";
2
- import { ClusterForkOptions, ClusterForkParam, matchesClusterLabels, PeerLiveness } from "../scrypted-cluster";
2
+ import { matchesClusterLabels } from "../cluster/cluster-labels";
3
+ import { ClusterForkOptions, ClusterForkParam, PeerLiveness } from "../scrypted-cluster-main";
3
4
 
4
5
  export class ClusterFork {
5
6
  constructor(public runtime: ScryptedRuntime) { }
@@ -1 +0,0 @@
1
- {"version":3,"file":"scrypted-cluster-common.js","sourceRoot":"","sources":["../src/scrypted-cluster-common.ts"],"names":[],"mappings":"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"}
@@ -1,38 +0,0 @@
1
- import type { ForkOptions } from '@scrypted/types';
2
- import tls from 'tls';
3
- import type { createSelfSignedCertificate } from './cert';
4
- import { RpcPeer } from './rpc';
5
- import type { ScryptedRuntime } from './runtime';
6
- export declare class PeerLiveness {
7
- private killed;
8
- __proxy_oneway_methods: string[];
9
- constructor(killed: Promise<any>);
10
- waitKilled(): Promise<any>;
11
- }
12
- export declare class ClusterForkResult extends PeerLiveness {
13
- private peer;
14
- private result;
15
- constructor(peer: RpcPeer, killed: Promise<any>, result: any);
16
- kill(): Promise<void>;
17
- getResult(): Promise<any>;
18
- }
19
- export type ClusterForkParam = (peerLiveness: PeerLiveness, runtime: string, packageJson: any, zipHash: string, getZip: () => Promise<Buffer>) => Promise<ClusterForkResult>;
20
- export type InitializeCluster = (cluster: {
21
- clusterId: string;
22
- clusterSecret: string;
23
- }) => Promise<void>;
24
- export interface ClusterWorkerProperties {
25
- labels: string[];
26
- }
27
- export interface ClusterWorker extends ClusterWorkerProperties {
28
- peer: RpcPeer;
29
- }
30
- export declare function getScryptedClusterMode(): ['server' | 'client', string, number];
31
- export interface ClusterForkOptions {
32
- runtime?: ForkOptions['runtime'];
33
- labels?: ForkOptions['labels'];
34
- }
35
- export declare function matchesClusterLabels(options: ClusterForkOptions, labels: string[]): number;
36
- export declare function getClusterLabels(): string[];
37
- export declare function startClusterClient(mainFilename: string): void;
38
- export declare function createClusterServer(runtime: ScryptedRuntime, certificate: ReturnType<typeof createSelfSignedCertificate>): tls.Server;
@@ -1,290 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ClusterForkResult = exports.PeerLiveness = void 0;
7
- exports.getScryptedClusterMode = getScryptedClusterMode;
8
- exports.matchesClusterLabels = matchesClusterLabels;
9
- exports.getClusterLabels = getClusterLabels;
10
- exports.startClusterClient = startClusterClient;
11
- exports.createClusterServer = createClusterServer;
12
- const net_1 = __importDefault(require("net"));
13
- const os_1 = __importDefault(require("os"));
14
- const tls_1 = __importDefault(require("tls"));
15
- const cluster_hash_1 = require("./cluster/cluster-hash");
16
- const plugin_volume_1 = require("./plugin/plugin-volume");
17
- const node_worker_common_1 = require("./plugin/runtime/node-worker-common");
18
- const runtime_host_1 = require("./plugin/runtime/runtime-host");
19
- const rpc_1 = require("./rpc");
20
- const rpc_serializer_1 = require("./rpc-serializer");
21
- const scrypted_cluster_common_1 = require("./scrypted-cluster-common");
22
- const sleep_1 = require("./sleep");
23
- class PeerLiveness {
24
- killed;
25
- __proxy_oneway_methods = ['kill'];
26
- constructor(killed) {
27
- this.killed = killed;
28
- }
29
- async waitKilled() {
30
- return this.killed;
31
- }
32
- }
33
- exports.PeerLiveness = PeerLiveness;
34
- class ClusterForkResult extends PeerLiveness {
35
- peer;
36
- result;
37
- constructor(peer, killed, result) {
38
- super(killed);
39
- this.peer = peer;
40
- this.result = result;
41
- }
42
- async kill() {
43
- this.peer.kill('killed');
44
- }
45
- async getResult() {
46
- return this.result;
47
- }
48
- }
49
- exports.ClusterForkResult = ClusterForkResult;
50
- function getScryptedClusterMode() {
51
- const mode = process.env.SCRYPTED_CLUSTER_MODE;
52
- if (!mode)
53
- return;
54
- if (!['server', 'client'].includes(mode))
55
- throw new Error('SCRYPTED_CLUSTER_MODE must be set to either "server" or "client".');
56
- if (!process.env.SCRYPTED_CLUSTER_SECRET)
57
- throw new Error('SCRYPTED_CLUSTER_MODE is set but SCRYPTED_CLUSTER_SECRET is not set.');
58
- const [server, sport] = process.env.SCRYPTED_CLUSTER_SERVER?.split(':') || [];
59
- const port = parseInt(sport) || 10556;
60
- const address = process.env.SCRYPTED_CLUSTER_ADDRESS;
61
- if (mode === 'client') {
62
- if (!net_1.default.isIP(server))
63
- throw new Error('SCRYPTED_CLUSTER_SERVER is not a valid IP address:port.');
64
- if (!net_1.default.isIP(address))
65
- throw new Error('SCRYPTED_CLUSTER_ADDRESS is not set to a valid IP address.');
66
- }
67
- else {
68
- // the cluster address may come from the server:port combo or address variable but not both.
69
- if (address && server && server !== address)
70
- throw new Error('SCRYPTED_CLUSTER_ADDRESS and SCRYPTED_CLUSTER_SERVER must not both be used.');
71
- const serverAddress = address || server;
72
- if (!net_1.default.isIP(serverAddress))
73
- throw new Error('SCRYPTED_CLUSTER_ADDRESS is not set.');
74
- process.env.SCRYPTED_CLUSTER_ADDRESS = serverAddress;
75
- delete process.env.SCRYPTED_CLUSTER_SERVER;
76
- }
77
- return [mode, server, port];
78
- }
79
- function peerLifecycle(serializer, peer, socket, type) {
80
- serializer.setupRpcPeer(peer);
81
- socket.on('data', data => serializer.onData(data));
82
- socket.on('error', e => {
83
- peer.kill(e.message);
84
- });
85
- socket.on('close', () => {
86
- peer.kill(`cluster ${type} closed`);
87
- });
88
- peer.killed.then(() => {
89
- socket.destroy();
90
- });
91
- }
92
- function preparePeer(socket, type) {
93
- const serializer = (0, rpc_serializer_1.createRpcDuplexSerializer)(socket);
94
- const peer = new rpc_1.RpcPeer(`cluster-remote:${socket.remoteAddress}:${socket.remotePort}`, 'cluster-host', (message, reject, serializationContext) => {
95
- serializer.sendMessage(message, reject, serializationContext);
96
- });
97
- peerLifecycle(serializer, peer, socket, type);
98
- return peer;
99
- }
100
- function matchesClusterLabels(options, labels) {
101
- let matched = 0;
102
- for (const label of options?.labels?.require || []) {
103
- if (!labels.includes(label))
104
- return 0;
105
- }
106
- // if there is nothing in the any list, consider it matched
107
- let foundAny = !options?.labels?.any?.length;
108
- for (const label of options.labels?.any || []) {
109
- if (labels.includes(label)) {
110
- matched++;
111
- foundAny = true;
112
- }
113
- }
114
- if (!foundAny)
115
- return 0;
116
- for (const label of options?.labels?.prefer || []) {
117
- if (labels.includes(label))
118
- matched++;
119
- }
120
- // ensure non zero result.
121
- matched++;
122
- return matched;
123
- }
124
- function getClusterLabels() {
125
- let labels = process.env.SCRYPTED_CLUSTER_LABELS?.split(',') || [];
126
- labels.push(process.arch, process.platform, os_1.default.hostname());
127
- labels = [...new Set(labels)];
128
- return labels;
129
- }
130
- function startClusterClient(mainFilename) {
131
- const labels = getClusterLabels();
132
- const clusterSecret = process.env.SCRYPTED_CLUSTER_SECRET;
133
- const clusterMode = getScryptedClusterMode();
134
- const [, host, port] = clusterMode;
135
- (async () => {
136
- while (true) {
137
- const backoff = (0, sleep_1.sleep)(10000);
138
- const socket = tls_1.default.connect({
139
- host,
140
- port,
141
- rejectUnauthorized: false,
142
- });
143
- socket.on('secureConnect', () => {
144
- console.log('Cluster server connected.', socket.localAddress, socket.localPort);
145
- });
146
- socket.on('close', () => {
147
- console.log('Cluster server disconnected.', socket.localAddress, socket.localPort);
148
- });
149
- const peer = preparePeer(socket, 'client');
150
- try {
151
- const connectForkWorker = await peer.getParam('connectForkWorker');
152
- const auth = {
153
- address: socket.localAddress,
154
- port: socket.localPort,
155
- id: undefined,
156
- proxyId: undefined,
157
- sourceKey: undefined,
158
- sha256: undefined,
159
- };
160
- auth.sha256 = (0, cluster_hash_1.computeClusterObjectHash)(auth, clusterSecret);
161
- const properties = {
162
- labels,
163
- };
164
- const { clusterId } = await connectForkWorker(auth, properties);
165
- const clusterPeerSetup = (0, scrypted_cluster_common_1.prepareClusterPeer)(peer);
166
- await clusterPeerSetup.initializeCluster({ clusterId, clusterSecret });
167
- const clusterForkParam = async (peerLiveness, runtime, packageJson, zipHash, getZip) => {
168
- let runtimeWorker;
169
- const builtins = (0, runtime_host_1.getBuiltinRuntimeHosts)();
170
- const rt = builtins.get(runtime);
171
- if (!rt)
172
- throw new Error('unknown runtime ' + runtime);
173
- const pluginId = packageJson.name;
174
- const { zipFile, unzippedPath } = await (0, node_worker_common_1.prepareZip)((0, plugin_volume_1.getPluginVolume)(pluginId), zipHash, getZip);
175
- const volume = (0, plugin_volume_1.getScryptedVolume)();
176
- const pluginVolume = (0, plugin_volume_1.getPluginVolume)(pluginId);
177
- runtimeWorker = rt(mainFilename, pluginId, {
178
- packageJson,
179
- env: {
180
- SCRYPTED_VOLUME: volume,
181
- SCRYPTED_PLUGIN_VOLUME: pluginVolume,
182
- },
183
- pluginDebug: undefined,
184
- zipFile,
185
- unzippedPath,
186
- zipHash,
187
- }, undefined);
188
- const threadPeer = new rpc_1.RpcPeer('main', 'thread', (message, reject, serializationContext) => runtimeWorker.send(message, reject, serializationContext));
189
- runtimeWorker.setupRpcPeer(threadPeer);
190
- runtimeWorker.on('exit', () => {
191
- threadPeer.kill('worker exited');
192
- });
193
- runtimeWorker.on('error', e => {
194
- threadPeer.kill('worker error ' + e);
195
- });
196
- threadPeer.killed.catch(() => { }).finally(() => {
197
- runtimeWorker.kill();
198
- });
199
- peerLiveness.waitKilled().catch(() => { }).finally(() => {
200
- threadPeer.kill('peer killed');
201
- });
202
- let getRemote;
203
- try {
204
- const initializeCluster = await threadPeer.getParam('initializeCluster');
205
- await initializeCluster({ clusterId, clusterSecret });
206
- getRemote = await threadPeer.getParam('getRemote');
207
- }
208
- catch (e) {
209
- threadPeer.kill('cluster fork failed');
210
- throw e;
211
- }
212
- const readStream = async function* (stream) {
213
- for await (const buffer of stream) {
214
- yield buffer;
215
- }
216
- };
217
- const timeout = setTimeout(() => {
218
- threadPeer.kill('cluster fork timeout');
219
- }, 10000);
220
- const clusterGetRemote = (...args) => {
221
- clearTimeout(timeout);
222
- return {
223
- [rpc_1.RpcPeer.PROPERTY_JSON_COPY_SERIALIZE_CHILDREN]: true,
224
- stdout: readStream(runtimeWorker.stdout),
225
- stderr: readStream(runtimeWorker.stderr),
226
- getRemote,
227
- };
228
- };
229
- const result = new ClusterForkResult(threadPeer, threadPeer.killed, clusterGetRemote);
230
- return result;
231
- };
232
- peer.params['fork'] = clusterForkParam;
233
- await peer.killed;
234
- }
235
- catch (e) {
236
- peer.kill(e.message);
237
- socket.destroy();
238
- console.warn('Cluster client error:', e);
239
- }
240
- await backoff;
241
- }
242
- })();
243
- }
244
- function createClusterServer(runtime, certificate) {
245
- const server = tls_1.default.createServer({
246
- key: certificate.serviceKey,
247
- cert: certificate.certificate,
248
- }, (socket) => {
249
- console.log('Cluster client connected.', socket.remoteAddress, socket.remotePort);
250
- socket.on('close', () => {
251
- console.log('Cluster client disconnected.', socket.remoteAddress, socket.remotePort);
252
- });
253
- const peer = preparePeer(socket, 'server');
254
- const connectForkWorker = async (auth, properties) => {
255
- try {
256
- const sha256 = (0, cluster_hash_1.computeClusterObjectHash)(auth, runtime.clusterSecret);
257
- if (sha256 !== auth.sha256)
258
- throw new Error('cluster object hash mismatch');
259
- // the remote address may be ipv6 prefixed so use a fuzzy match.
260
- // eg ::ffff:192.168.2.124
261
- if (!process.env.SCRYPTED_DISABLE_CLUSTER_SERVER_TRUST) {
262
- if (auth.port !== socket.remotePort || !socket.remoteAddress.endsWith(auth.address))
263
- throw new Error('cluster object address mismatch');
264
- }
265
- const worker = {
266
- ...properties,
267
- peer,
268
- };
269
- runtime.clusterWorkers.add(worker);
270
- peer.killed.then(() => {
271
- runtime.clusterWorkers.delete(worker);
272
- });
273
- socket.on('close', () => {
274
- runtime.clusterWorkers.delete(worker);
275
- });
276
- console.log('Cluster client authenticated.', socket.remoteAddress, socket.remotePort, properties);
277
- }
278
- catch (e) {
279
- peer.kill(e);
280
- socket.destroy();
281
- }
282
- return {
283
- clusterId: runtime.clusterId,
284
- };
285
- };
286
- peer.params['connectForkWorker'] = connectForkWorker;
287
- });
288
- return server;
289
- }
290
- //# sourceMappingURL=scrypted-cluster.js.map