@scrypted/server 0.144.1 → 0.144.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.
- package/dist/cert.js +1 -1
- package/dist/cert.js.map +1 -1
- package/dist/cluster/cluster-labels.d.ts +3 -3
- package/dist/cluster/cluster-labels.js +2 -2
- package/dist/cluster/cluster-labels.js.map +1 -1
- package/dist/cluster/cluster-setup.d.ts +3 -3
- package/dist/cluster/cluster-setup.js +3 -3
- package/dist/cluster/cluster-setup.js.map +1 -1
- package/dist/db-types.d.ts +4 -4
- package/dist/db-types.js.map +1 -1
- package/dist/event-registry.d.ts +2 -2
- package/dist/event-registry.js +9 -7
- package/dist/event-registry.js.map +1 -1
- package/dist/fetch/index.d.ts +2 -2
- package/dist/fetch/index.js +3 -6
- package/dist/fetch/index.js.map +1 -1
- package/dist/http-interfaces.js +1 -1
- package/dist/http-interfaces.js.map +1 -1
- package/dist/infer-defaults.d.ts +4 -4
- package/dist/infer-defaults.js +8 -4
- package/dist/infer-defaults.js.map +1 -1
- package/dist/ip.js +2 -1
- package/dist/ip.js.map +1 -1
- package/dist/level.d.ts +3 -3
- package/dist/level.js +1 -0
- package/dist/level.js.map +1 -1
- package/dist/listen-zero.js.map +1 -1
- package/dist/mixin/mixin-cycle.js +6 -6
- package/dist/mixin/mixin-cycle.js.map +1 -1
- package/dist/plugin/acl.js.map +1 -1
- package/dist/plugin/cluster.js.map +1 -1
- package/dist/plugin/descriptor.js +1 -1
- package/dist/plugin/descriptor.js.map +1 -1
- package/dist/plugin/device.d.ts +6 -6
- package/dist/plugin/device.js.map +1 -1
- package/dist/plugin/endpoint.js.map +1 -1
- package/dist/plugin/media.js.map +1 -1
- package/dist/plugin/mediaobject.d.ts +1 -1
- package/dist/plugin/mediaobject.js.map +1 -1
- package/dist/plugin/plugin-api.d.ts +6 -6
- package/dist/plugin/plugin-api.js +2 -2
- package/dist/plugin/plugin-api.js.map +1 -1
- package/dist/plugin/plugin-console.js +11 -10
- package/dist/plugin/plugin-console.js.map +1 -1
- package/dist/plugin/plugin-device.d.ts +3 -3
- package/dist/plugin/plugin-device.js +2 -0
- package/dist/plugin/plugin-device.js.map +1 -1
- package/dist/plugin/plugin-host-api.d.ts +1 -1
- package/dist/plugin/plugin-host-api.js +19 -5
- package/dist/plugin/plugin-host-api.js.map +1 -1
- package/dist/plugin/plugin-host.js +3 -2
- package/dist/plugin/plugin-host.js.map +1 -1
- package/dist/plugin/plugin-http.d.ts +1 -1
- package/dist/plugin/plugin-http.js +5 -1
- package/dist/plugin/plugin-http.js.map +1 -1
- package/dist/plugin/plugin-lazy-remote.js.map +1 -1
- package/dist/plugin/plugin-remote-websocket.js.map +1 -1
- package/dist/plugin/plugin-remote-worker.js +5 -2
- package/dist/plugin/plugin-remote-worker.js.map +1 -1
- package/dist/plugin/plugin-remote.js +1 -1
- package/dist/plugin/plugin-remote.js.map +1 -1
- package/dist/plugin/plugin-repl.js +6 -2
- package/dist/plugin/plugin-repl.js.map +1 -1
- package/dist/plugin/runtime/child-process-worker.d.ts +4 -4
- package/dist/plugin/runtime/child-process-worker.js +1 -2
- package/dist/plugin/runtime/child-process-worker.js.map +1 -1
- package/dist/plugin/runtime/cluster-fork-worker.d.ts +1 -1
- package/dist/plugin/runtime/cluster-fork-worker.js +2 -0
- package/dist/plugin/runtime/cluster-fork-worker.js.map +1 -1
- package/dist/plugin/runtime/custom-worker.js.map +1 -1
- package/dist/plugin/runtime/node-fork-worker.d.ts +1 -1
- package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
- package/dist/plugin/runtime/node-thread-worker.js.map +1 -1
- package/dist/plugin/runtime/python-worker.js +1 -1
- package/dist/plugin/runtime/python-worker.js.map +1 -1
- package/dist/plugin/runtime/runtime-worker.d.ts +1 -1
- package/dist/plugin/system.d.ts +1 -1
- package/dist/plugin/system.js +1 -0
- package/dist/plugin/system.js.map +1 -1
- package/dist/promise-utils.d.ts +1 -1
- package/dist/promise-utils.js.map +1 -1
- package/dist/rpc-buffer-serializer.d.ts +1 -1
- package/dist/rpc-serializer.js.map +1 -1
- package/dist/rpc.d.ts +10 -9
- package/dist/rpc.js +15 -8
- package/dist/rpc.js.map +1 -1
- package/dist/runtime.d.ts +11 -11
- package/dist/runtime.js +17 -18
- package/dist/runtime.js.map +1 -1
- package/dist/scrypted-cluster-main.js +3 -2
- package/dist/scrypted-cluster-main.js.map +1 -1
- package/dist/scrypted-plugin-main.js +1 -1
- package/dist/scrypted-plugin-main.js.map +1 -1
- package/dist/scrypted-server-main.js +8 -5
- package/dist/scrypted-server-main.js.map +1 -1
- package/dist/server-settings.d.ts +1 -1
- package/dist/server-settings.js +4 -4
- package/dist/server-settings.js.map +1 -1
- package/dist/services/addresses.d.ts +1 -1
- package/dist/services/addresses.js +2 -2
- package/dist/services/addresses.js.map +1 -1
- package/dist/services/alerts.js +2 -2
- package/dist/services/alerts.js.map +1 -1
- package/dist/services/cluster-fork.js.map +1 -1
- package/dist/services/plugin.d.ts +5 -5
- package/dist/services/plugin.js.map +1 -1
- package/dist/services/service-control.js.map +1 -1
- package/dist/services/users.d.ts +2 -2
- package/dist/services/users.js.map +1 -1
- package/dist/state.d.ts +7 -7
- package/dist/state.js +4 -4
- package/dist/state.js.map +1 -1
- package/dist/threading.js.map +1 -1
- package/dist/usertoken.d.ts +2 -2
- package/dist/usertoken.js.map +1 -1
- package/package.json +2 -2
- package/python/cluster_setup.py +13 -4
- package/python/plugin_remote.py +22 -18
- package/python/rpc_reader.py +3 -5
- package/src/cert.ts +2 -2
- package/src/cluster/cluster-labels.ts +4 -4
- package/src/cluster/cluster-setup.ts +20 -20
- package/src/db-types.ts +16 -16
- package/src/event-registry.ts +13 -11
- package/src/fetch/index.ts +4 -7
- package/src/http-interfaces.ts +2 -2
- package/src/infer-defaults.ts +12 -8
- package/src/ip.ts +2 -1
- package/src/level.ts +10 -9
- package/src/listen-zero.ts +1 -1
- package/src/mixin/mixin-cycle.ts +6 -6
- package/src/plugin/acl.ts +1 -1
- package/src/plugin/cluster.ts +2 -2
- package/src/plugin/descriptor.ts +2 -2
- package/src/plugin/device.ts +16 -16
- package/src/plugin/endpoint.ts +4 -4
- package/src/plugin/media.ts +15 -15
- package/src/plugin/mediaobject.ts +3 -3
- package/src/plugin/plugin-api.ts +7 -7
- package/src/plugin/plugin-console.ts +13 -12
- package/src/plugin/plugin-device.ts +20 -18
- package/src/plugin/plugin-host-api.ts +27 -13
- package/src/plugin/plugin-host.ts +26 -25
- package/src/plugin/plugin-http.ts +9 -5
- package/src/plugin/plugin-lazy-remote.ts +1 -1
- package/src/plugin/plugin-remote-websocket.ts +1 -1
- package/src/plugin/plugin-remote-worker.ts +22 -20
- package/src/plugin/plugin-remote.ts +14 -14
- package/src/plugin/plugin-repl.ts +6 -2
- package/src/plugin/runtime/child-process-worker.ts +11 -12
- package/src/plugin/runtime/cluster-fork-worker.ts +2 -0
- package/src/plugin/runtime/custom-worker.ts +6 -6
- package/src/plugin/runtime/node-fork-worker.ts +3 -3
- package/src/plugin/runtime/node-thread-worker.ts +3 -3
- package/src/plugin/runtime/python-worker.ts +14 -14
- package/src/plugin/runtime/runtime-worker.ts +1 -1
- package/src/plugin/system.ts +24 -23
- package/src/promise-utils.ts +4 -4
- package/src/rpc-serializer.ts +3 -3
- package/src/rpc.ts +25 -17
- package/src/runtime.ts +59 -60
- package/src/scrypted-cluster-main.ts +19 -18
- package/src/scrypted-plugin-main.ts +2 -2
- package/src/scrypted-server-main.ts +17 -14
- package/src/server-settings.ts +5 -5
- package/src/services/addresses.ts +3 -3
- package/src/services/alerts.ts +2 -2
- package/src/services/cluster-fork.ts +9 -9
- package/src/services/plugin.ts +15 -15
- package/src/services/service-control.ts +1 -1
- package/src/services/users.ts +3 -3
- package/src/state.ts +21 -21
- package/src/threading.ts +5 -5
- package/src/usertoken.ts +1 -1
|
@@ -84,8 +84,8 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
84
84
|
class PluginForkableAPI extends PluginAPIProxy {
|
|
85
85
|
[RpcPeer.PROPERTY_PROXY_ONEWAY_METHODS] = (_api as any)[RpcPeer.PROPERTY_PROXY_ONEWAY_METHODS];
|
|
86
86
|
|
|
87
|
-
setStorage(nativeId: string, storage: { [key: string]: any; }): Promise<void> {
|
|
88
|
-
const id = deviceManager.nativeIds.get(nativeId)
|
|
87
|
+
override setStorage(nativeId: string, storage: { [key: string]: any; }): Promise<void> {
|
|
88
|
+
const id = deviceManager.nativeIds.get(nativeId)!.id;
|
|
89
89
|
for (const r of forks) {
|
|
90
90
|
r.setNativeId(nativeId, id, storage);
|
|
91
91
|
}
|
|
@@ -104,7 +104,7 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
104
104
|
if (name === 'repl') {
|
|
105
105
|
if (!replPort)
|
|
106
106
|
throw new Error('REPL unavailable: Plugin not loaded.')
|
|
107
|
-
return [await replPort, process.env.SCRYPTED_CLUSTER_ADDRESS];
|
|
107
|
+
return [await replPort, process.env.SCRYPTED_CLUSTER_ADDRESS!] as [number, string];
|
|
108
108
|
}
|
|
109
109
|
throw new Error(`unknown service ${name}`);
|
|
110
110
|
},
|
|
@@ -183,11 +183,11 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
183
183
|
|
|
184
184
|
process.on('uncaughtException', e => {
|
|
185
185
|
getPluginConsole().error('uncaughtException', e);
|
|
186
|
-
scrypted.log
|
|
186
|
+
scrypted.log!.e('uncaughtException ' + (e.stack || e?.toString()));
|
|
187
187
|
});
|
|
188
188
|
process.on('unhandledRejection', e => {
|
|
189
189
|
getPluginConsole().error('unhandledRejection', e);
|
|
190
|
-
scrypted.log
|
|
190
|
+
scrypted.log!.e('unhandledRejection ' + ((e as Error).stack || e?.toString()));
|
|
191
191
|
});
|
|
192
192
|
|
|
193
193
|
installSourceMapSupport({
|
|
@@ -209,10 +209,10 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
209
209
|
await installOptionalDependencies(getPluginConsole(), packageJson);
|
|
210
210
|
|
|
211
211
|
const main = await pluginReader(mainNodejs);
|
|
212
|
-
const script = main
|
|
212
|
+
const script = main!.toString();
|
|
213
213
|
|
|
214
214
|
scrypted.connect = (socket, options) => {
|
|
215
|
-
process.send(options, socket);
|
|
215
|
+
process.send!(options, socket);
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
const pluginRemoteAPI: PluginRemote = scrypted.pluginRemoteAPI;
|
|
@@ -221,12 +221,12 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
221
221
|
let forkPeer: Promise<RpcPeer>;
|
|
222
222
|
let runtimeWorker: RuntimeWorker;
|
|
223
223
|
let nativeWorker: child_process.ChildProcess | worker_threads.Worker;
|
|
224
|
-
let clusterWorkerId: Promise<string
|
|
224
|
+
let clusterWorkerId: Promise<string> | undefined;
|
|
225
225
|
|
|
226
226
|
const runtimeWorkerOptions: RuntimeWorkerOptions = {
|
|
227
227
|
packageJson,
|
|
228
228
|
env: undefined,
|
|
229
|
-
pluginDebug: undefined
|
|
229
|
+
pluginDebug: undefined!,
|
|
230
230
|
zipFile,
|
|
231
231
|
unzippedPath,
|
|
232
232
|
zipHash,
|
|
@@ -234,13 +234,15 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
234
234
|
|
|
235
235
|
// if running in a cluster, fork to a matching cluster worker only if necessary.
|
|
236
236
|
if (utilizesClusterForkWorker(options)) {
|
|
237
|
-
|
|
237
|
+
const result = createClusterForkWorker(
|
|
238
238
|
runtimeWorkerOptions,
|
|
239
|
-
options
|
|
239
|
+
options!,
|
|
240
240
|
api.getComponent('cluster-fork'),
|
|
241
241
|
() => zipAPI.getZip(),
|
|
242
|
-
scrypted.connectRPCObject)
|
|
243
|
-
|
|
242
|
+
scrypted.connectRPCObject);
|
|
243
|
+
runtimeWorker = result.runtimeWorker;
|
|
244
|
+
forkPeer = result.forkPeer;
|
|
245
|
+
clusterWorkerId = result.clusterWorkerId as Promise<string>;
|
|
244
246
|
}
|
|
245
247
|
else {
|
|
246
248
|
if (options?.runtime) {
|
|
@@ -248,10 +250,10 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
248
250
|
const runtime = builtins.get(options.runtime);
|
|
249
251
|
if (!runtime)
|
|
250
252
|
throw new Error('unknown runtime ' + options.runtime);
|
|
251
|
-
runtimeWorker = runtime(mainFilename, runtimeWorkerOptions, undefined);
|
|
253
|
+
runtimeWorker = runtime(mainFilename, runtimeWorkerOptions, undefined!);
|
|
252
254
|
|
|
253
255
|
if (runtimeWorker instanceof ChildProcessWorker) {
|
|
254
|
-
nativeWorker = runtimeWorker.childProcess
|
|
256
|
+
nativeWorker = runtimeWorker.childProcess!;
|
|
255
257
|
}
|
|
256
258
|
}
|
|
257
259
|
else {
|
|
@@ -261,7 +263,7 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
261
263
|
const ntw = new NodeThreadWorker(mainFilename, pluginId, {
|
|
262
264
|
packageJson,
|
|
263
265
|
env: undefined,
|
|
264
|
-
pluginDebug: undefined
|
|
266
|
+
pluginDebug: undefined!,
|
|
265
267
|
zipFile,
|
|
266
268
|
unzippedPath,
|
|
267
269
|
zipHash,
|
|
@@ -316,8 +318,8 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
316
318
|
class PluginForkAPI extends PluginAPIProxy {
|
|
317
319
|
[RpcPeer.PROPERTY_PROXY_ONEWAY_METHODS] = (api as any)[RpcPeer.PROPERTY_PROXY_ONEWAY_METHODS];
|
|
318
320
|
|
|
319
|
-
setStorage(nativeId: string, storage: { [key: string]: any; }): Promise<void> {
|
|
320
|
-
const id = deviceManager.nativeIds.get(nativeId)
|
|
321
|
+
override setStorage(nativeId: string, storage: { [key: string]: any; }): Promise<void> {
|
|
322
|
+
const id = deviceManager.nativeIds.get(nativeId)!.id;
|
|
321
323
|
pluginRemoteAPI.setNativeId(nativeId, id, storage);
|
|
322
324
|
for (const r of forks) {
|
|
323
325
|
if (r === remote)
|
|
@@ -361,7 +363,7 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
361
363
|
removeListener(event, listener) {
|
|
362
364
|
return runtimeWorker.removeListener(event as any, listener);
|
|
363
365
|
},
|
|
364
|
-
nativeWorker
|
|
366
|
+
nativeWorker: nativeWorker!,
|
|
365
367
|
};
|
|
366
368
|
return {
|
|
367
369
|
[Symbol.dispose]() {
|
|
@@ -376,7 +378,7 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe
|
|
|
376
378
|
try {
|
|
377
379
|
const isModule = packageJson.type === 'module';
|
|
378
380
|
const filename = zipOptions?.debug ? pluginMainNodeJs : pluginIdMainNodeJs;
|
|
379
|
-
const sdkVersion = await pluginReader('sdk.json').then(b => JSON.parse(b
|
|
381
|
+
const sdkVersion = await pluginReader('sdk.json').then(b => JSON.parse(b!.toString()).version).catch(() => { });
|
|
380
382
|
const mainNodeJsOnFilesystem = path.join(unzippedPath, mainNodejs);
|
|
381
383
|
if (sdkVersion) {
|
|
382
384
|
// todo: remove this, only existed in prerelease versions
|
|
@@ -51,7 +51,7 @@ export async function setupPluginRemote(peer: RpcPeer, api: PluginAPI, pluginId:
|
|
|
51
51
|
delete state[id];
|
|
52
52
|
continue;
|
|
53
53
|
}
|
|
54
|
-
state[id] = getAccessControlDeviceState(id, state[id])
|
|
54
|
+
state[id] = getAccessControlDeviceState(id, state[id]!)!;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -67,11 +67,11 @@ export async function setupPluginRemote(peer: RpcPeer, api: PluginAPI, pluginId:
|
|
|
67
67
|
if (eventDetails.eventInterface === ScryptedInterface.ScryptedDevice) {
|
|
68
68
|
if (eventDetails.property === ScryptedInterfaceProperty.id) {
|
|
69
69
|
// a change on the id property means device was deleted
|
|
70
|
-
remote.updateDeviceState(eventData, undefined);
|
|
70
|
+
remote.updateDeviceState(eventData, undefined!);
|
|
71
71
|
}
|
|
72
72
|
else {
|
|
73
73
|
// a change on anything else is a descriptor update
|
|
74
|
-
remote.updateDeviceState(id, getAccessControlDeviceState(id));
|
|
74
|
+
remote.updateDeviceState(id, getAccessControlDeviceState(id)!);
|
|
75
75
|
}
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
@@ -127,7 +127,7 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp
|
|
|
127
127
|
|
|
128
128
|
ioSockets[id] = callbacks;
|
|
129
129
|
|
|
130
|
-
callbacks.connect(undefined
|
|
130
|
+
callbacks.connect(undefined!, {
|
|
131
131
|
close: (message) => connection.close(message),
|
|
132
132
|
send: (message) => connection.send(message),
|
|
133
133
|
});
|
|
@@ -140,14 +140,14 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp
|
|
|
140
140
|
api = await options?.onGetRemote?.(api, pluginId) || api;
|
|
141
141
|
|
|
142
142
|
const systemManager = new SystemManagerImpl();
|
|
143
|
-
const deviceManager = new DeviceManagerImpl(systemManager, getDeviceConsole
|
|
143
|
+
const deviceManager = new DeviceManagerImpl(systemManager, getDeviceConsole!, getMixinConsole!);
|
|
144
144
|
const endpointManager = new EndpointManagerImpl();
|
|
145
|
-
const clusterManager = new ClusterManagerImpl(undefined, api, undefined);
|
|
145
|
+
const clusterManager = new ClusterManagerImpl(undefined, api, undefined!);
|
|
146
146
|
const hostMediaManager = await api.getMediaManager();
|
|
147
147
|
if (!hostMediaManager) {
|
|
148
|
-
peer.params['createMediaManager'] = async () => createMediaManager(systemManager, deviceManager);
|
|
148
|
+
peer.params['createMediaManager'] = async () => createMediaManager!(systemManager, deviceManager);
|
|
149
149
|
}
|
|
150
|
-
const mediaManager = hostMediaManager || await createMediaManager(systemManager, deviceManager);
|
|
150
|
+
const mediaManager = hostMediaManager || await createMediaManager!(systemManager, deviceManager);
|
|
151
151
|
peer.params['mediaManager'] = mediaManager;
|
|
152
152
|
|
|
153
153
|
systemManager.api = api;
|
|
@@ -163,11 +163,11 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp
|
|
|
163
163
|
clusterManager,
|
|
164
164
|
log,
|
|
165
165
|
pluginHostAPI: api,
|
|
166
|
-
pluginRemoteAPI: undefined
|
|
166
|
+
pluginRemoteAPI: undefined!,
|
|
167
167
|
serverVersion: hostInfo?.serverVersion,
|
|
168
|
-
connect: undefined
|
|
169
|
-
fork: undefined
|
|
170
|
-
connectRPCObject: undefined
|
|
168
|
+
connect: undefined!,
|
|
169
|
+
fork: undefined!,
|
|
170
|
+
connectRPCObject: undefined!,
|
|
171
171
|
};
|
|
172
172
|
|
|
173
173
|
delete peer.params.getRemote;
|
|
@@ -188,7 +188,7 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp
|
|
|
188
188
|
'ioEvent',
|
|
189
189
|
'setNativeId',
|
|
190
190
|
],
|
|
191
|
-
getServicePort
|
|
191
|
+
getServicePort: getServicePort!,
|
|
192
192
|
async createDeviceState(id: string, setState: (property: string, value: any) => Promise<void>) {
|
|
193
193
|
return deviceManager.createDeviceState(id, setState);
|
|
194
194
|
},
|
|
@@ -300,7 +300,7 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp
|
|
|
300
300
|
params.pluginRuntimeAPI = ret;
|
|
301
301
|
|
|
302
302
|
try {
|
|
303
|
-
return await options
|
|
303
|
+
return await options!.onLoadZip!(ret, params, packageJson, zipAPI, zipOptions!);
|
|
304
304
|
}
|
|
305
305
|
catch (e) {
|
|
306
306
|
console.error('plugin start/fork failed', e)
|
|
@@ -19,9 +19,13 @@ export async function createREPLServer(scrypted: ScryptedStatic, params: any, pl
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
while (filter) {
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const entry = nativeIds.get(filter);
|
|
23
|
+
if (!entry)
|
|
24
|
+
break;
|
|
25
|
+
const d = await systemManager.getDeviceById(entry.id);
|
|
24
26
|
chain.push(filter);
|
|
27
|
+
if (!d?.providerId)
|
|
28
|
+
break;
|
|
25
29
|
filter = reversed.get(d.providerId);
|
|
26
30
|
}
|
|
27
31
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import child_process from 'child_process';
|
|
2
|
-
import { once } from 'events';
|
|
3
|
-
import { EventEmitter } from "ws";
|
|
2
|
+
import { EventEmitter, once } from 'events';
|
|
4
3
|
import { RpcMessage, RpcPeer } from "../../rpc";
|
|
5
4
|
import { RuntimeWorker, RuntimeWorkerOptions } from "./runtime-worker";
|
|
6
5
|
|
|
7
6
|
export abstract class ChildProcessWorker extends EventEmitter implements RuntimeWorker {
|
|
8
7
|
public pluginId: string;
|
|
9
|
-
protected worker: child_process.ChildProcess;
|
|
10
|
-
killPromise
|
|
8
|
+
protected worker: child_process.ChildProcess | undefined;
|
|
9
|
+
killPromise!: Promise<void>;
|
|
11
10
|
|
|
12
11
|
get childProcess() {
|
|
13
12
|
return this.worker;
|
|
@@ -20,18 +19,18 @@ export abstract class ChildProcessWorker extends EventEmitter implements Runtime
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
setupWorker() {
|
|
23
|
-
this.worker
|
|
24
|
-
this.worker
|
|
25
|
-
this.worker
|
|
26
|
-
this.worker
|
|
22
|
+
this.worker!.on('close', () => this.emit('error', new Error('close')));
|
|
23
|
+
this.worker!.on('disconnect', () => this.emit('error', new Error('disconnect')));
|
|
24
|
+
this.worker!.on('exit', (code, signal) => this.emit('exit', code, signal));
|
|
25
|
+
this.worker!.on('error', e => this.emit('error', e));
|
|
27
26
|
// aggressively catch errors
|
|
28
27
|
// ECONNRESET can be raised when the child process is killed
|
|
29
|
-
for (const stdio of this.worker
|
|
28
|
+
for (const stdio of this.worker!.stdio || []) {
|
|
30
29
|
if (stdio)
|
|
31
30
|
stdio.on('error', e => this.emit('error', e));
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
this.killPromise = once(this.worker
|
|
33
|
+
this.killPromise = once(this.worker!, 'exit').then(() => { }).catch(() => { });
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
get pid() {
|
|
@@ -39,11 +38,11 @@ export abstract class ChildProcessWorker extends EventEmitter implements Runtime
|
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
get stdout() {
|
|
42
|
-
return this.worker
|
|
41
|
+
return this.worker!.stdout!;
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
get stderr() {
|
|
46
|
-
return this.worker
|
|
45
|
+
return this.worker!.stderr!;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
kill(): void {
|
|
@@ -16,7 +16,9 @@ export function createClusterForkWorker(
|
|
|
16
16
|
|
|
17
17
|
// these are specific to the cluster worker host
|
|
18
18
|
// and will be set there.
|
|
19
|
+
// @ts-ignore these are optional at runtime
|
|
19
20
|
delete runtimeWorkerOptions.zipFile;
|
|
21
|
+
// @ts-ignore these are optional at runtime
|
|
20
22
|
delete runtimeWorkerOptions.unzippedPath;
|
|
21
23
|
|
|
22
24
|
const waitKilled = new Deferred<void>();
|
|
@@ -8,13 +8,13 @@ import { ChildProcessWorker } from "./child-process-worker";
|
|
|
8
8
|
import { RuntimeWorkerOptions } from "./runtime-worker";
|
|
9
9
|
|
|
10
10
|
export class CustomRuntimeWorker extends ChildProcessWorker {
|
|
11
|
-
serializer
|
|
12
|
-
fork
|
|
11
|
+
serializer!: ReturnType<typeof createRpcDuplexSerializer>;
|
|
12
|
+
fork!: boolean;
|
|
13
13
|
|
|
14
14
|
constructor(options: RuntimeWorkerOptions, runtime: ScryptedRuntime) {
|
|
15
15
|
super(options);
|
|
16
16
|
|
|
17
|
-
const pluginDevice = runtime.findPluginDevice(this.pluginId)
|
|
17
|
+
const pluginDevice = runtime.findPluginDevice(this.pluginId)!;
|
|
18
18
|
const scryptedRuntimeArguments: ScryptedRuntimeArguments = pluginDevice.state.scryptedRuntimeArguments?.value;
|
|
19
19
|
if (!scryptedRuntimeArguments)
|
|
20
20
|
throw new Error('custom runtime requires scryptedRuntimeArguments');
|
|
@@ -52,8 +52,8 @@ export class CustomRuntimeWorker extends ChildProcessWorker {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
setupRpcPeer(peer: RpcPeer): void {
|
|
55
|
-
const peerin = this.worker
|
|
56
|
-
const peerout = this.worker
|
|
55
|
+
const peerin = this.worker!.stdio[3]! as Writable;
|
|
56
|
+
const peerout = this.worker!.stdio[4]! as Readable;
|
|
57
57
|
|
|
58
58
|
const serializer = this.serializer = createRpcDuplexSerializer(peerin);
|
|
59
59
|
serializer.setupRpcPeer(peer);
|
|
@@ -75,7 +75,7 @@ export class CustomRuntimeWorker extends ChildProcessWorker {
|
|
|
75
75
|
this.serializer.sendMessage(message, reject, serializationContext);
|
|
76
76
|
}
|
|
77
77
|
catch (e) {
|
|
78
|
-
reject?.(e);
|
|
78
|
+
reject?.(e as Error);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -77,7 +77,7 @@ export class NodeForkWorker extends ChildProcessWorker {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
setupRpcPeer(peer: RpcPeer): void {
|
|
80
|
-
this.worker
|
|
80
|
+
this.worker!.on('message', (message, sendHandle) => {
|
|
81
81
|
if ((message as any).type && sendHandle) {
|
|
82
82
|
peer.handleMessage(message as any, {
|
|
83
83
|
sendHandle,
|
|
@@ -105,11 +105,11 @@ export class NodeForkWorker extends ChildProcessWorker {
|
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
catch (e) {
|
|
108
|
-
reject?.(e);
|
|
108
|
+
reject?.(e as Error);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
get pid() {
|
|
112
|
+
override get pid() {
|
|
113
113
|
return this.worker?.pid;
|
|
114
114
|
}
|
|
115
115
|
}
|
|
@@ -104,8 +104,8 @@ export class NodeThreadWorker extends EventEmitter implements RuntimeWorker {
|
|
|
104
104
|
return;
|
|
105
105
|
this.worker.terminate();
|
|
106
106
|
this.port.close();
|
|
107
|
-
this.port = undefined
|
|
108
|
-
this.worker = undefined
|
|
107
|
+
this.port = undefined!;
|
|
108
|
+
this.worker = undefined!;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
send(message: RpcMessage, reject?: (e: Error) => void, serializationContext?: any): void {
|
|
@@ -129,7 +129,7 @@ export class NodeThreadWorker extends EventEmitter implements RuntimeWorker {
|
|
|
129
129
|
port.postMessage(postMessage, transferList);
|
|
130
130
|
}
|
|
131
131
|
catch (e) {
|
|
132
|
-
reject?.(e);
|
|
132
|
+
reject?.(e as Error);
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -13,7 +13,7 @@ import { RuntimeWorkerOptions } from "./runtime-worker";
|
|
|
13
13
|
|
|
14
14
|
export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
15
15
|
static {
|
|
16
|
-
if (!fs.existsSync(process.env.SCRYPTED_PYTHON_PATH)) {
|
|
16
|
+
if (!process.env.SCRYPTED_PYTHON_PATH || !fs.existsSync(process.env.SCRYPTED_PYTHON_PATH)) {
|
|
17
17
|
try {
|
|
18
18
|
const py = new PortablePython(packagedPythonVersion);
|
|
19
19
|
const portablePython = py.executablePath;
|
|
@@ -26,18 +26,18 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
serializer
|
|
29
|
+
serializer!: ReturnType<typeof createRpcDuplexSerializer>;
|
|
30
30
|
peerin: Writable;
|
|
31
31
|
peerout: Readable;
|
|
32
32
|
_stdout = new PassThrough();
|
|
33
33
|
_stderr = new PassThrough();
|
|
34
34
|
pythonInstallationComplete = true;
|
|
35
35
|
|
|
36
|
-
get stdout() {
|
|
36
|
+
override get stdout() {
|
|
37
37
|
return this._stdout;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
get stderr() {
|
|
40
|
+
override get stderr() {
|
|
41
41
|
return this._stderr;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -99,7 +99,7 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
|
99
99
|
const setup = () => {
|
|
100
100
|
const types = require.resolve('@scrypted/types');
|
|
101
101
|
const PYTHONPATH = types.substring(0, types.indexOf('types') + 'types'.length);
|
|
102
|
-
this.worker = child_process.spawn(pythonPath, args, {
|
|
102
|
+
this.worker = child_process.spawn(pythonPath as string, args, {
|
|
103
103
|
cwd: options.unzippedPath,
|
|
104
104
|
// stdin, stdout, stderr, peer in, peer out
|
|
105
105
|
stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe'],
|
|
@@ -112,8 +112,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
|
112
112
|
});
|
|
113
113
|
this.setupWorker();
|
|
114
114
|
|
|
115
|
-
this.worker.stdout
|
|
116
|
-
this.worker.stderr
|
|
115
|
+
this.worker.stdout!.pipe(this.stdout);
|
|
116
|
+
this.worker.stderr!.pipe(this.stderr);
|
|
117
117
|
};
|
|
118
118
|
|
|
119
119
|
let pluginPythonVersion: string = options.packageJson.scrypted.pythonVersion?.[os.platform()]?.[os.arch()] || options.packageJson.scrypted.pythonVersion?.default;
|
|
@@ -125,8 +125,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
|
125
125
|
// if the plugin requests a specific python, then install it via portable python
|
|
126
126
|
if (!pluginPythonVersion) {
|
|
127
127
|
setup();
|
|
128
|
-
this.peerin = this.worker
|
|
129
|
-
this.peerout = this.worker
|
|
128
|
+
this.peerin = this.worker!.stdio[3]! as Writable;
|
|
129
|
+
this.peerout = this.worker!.stdio[4]! as Readable;
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
132
|
|
|
@@ -135,8 +135,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
|
135
135
|
if (envPython && fs.existsSync(envPython)) {
|
|
136
136
|
pythonPath = envPython;
|
|
137
137
|
setup();
|
|
138
|
-
this.peerin = this.worker
|
|
139
|
-
this.peerout = this.worker
|
|
138
|
+
this.peerin = this.worker!.stdio[3]! as Writable;
|
|
139
|
+
this.peerout = this.worker!.stdio[4]! as Readable;
|
|
140
140
|
return;
|
|
141
141
|
}
|
|
142
142
|
|
|
@@ -146,8 +146,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
|
146
146
|
const finishSetup = () => {
|
|
147
147
|
setup();
|
|
148
148
|
|
|
149
|
-
peerin.pipe(this.worker
|
|
150
|
-
(this.worker
|
|
149
|
+
peerin.pipe(this.worker!.stdio[3]! as Writable);
|
|
150
|
+
(this.worker!.stdio[4]! as Readable).pipe(peerout);
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
const pyVersion = require('py/package.json').version;
|
|
@@ -200,7 +200,7 @@ export class PythonRuntimeWorker extends ChildProcessWorker {
|
|
|
200
200
|
this.serializer.sendMessage(message, reject, serializationContext);
|
|
201
201
|
}
|
|
202
202
|
catch (e) {
|
|
203
|
-
reject?.(e);
|
|
203
|
+
reject?.(e as Error);
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
}
|
package/src/plugin/system.ts
CHANGED
|
@@ -10,8 +10,8 @@ function newDeviceProxy(id: string, systemManager: SystemManagerImpl) {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
class DeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
|
13
|
-
customProperties
|
|
14
|
-
device
|
|
13
|
+
customProperties!: Map<string | number | symbol, any>;
|
|
14
|
+
device!: Promise<ScryptedDevice | undefined>;
|
|
15
15
|
constructor(public id: string, public systemManager: SystemManagerImpl) {
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -20,14 +20,14 @@ class DeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
ownKeys(target: any): ArrayLike<string | symbol> {
|
|
23
|
-
const interfaces = new Set<string>(this.systemManager.state[this.id]
|
|
23
|
+
const interfaces = new Set<string>(this.systemManager.state[this.id]!.interfaces!.value);
|
|
24
24
|
const methods = getInterfaceMethods(this.systemManager.descriptors || ScryptedInterfaceDescriptors, interfaces);
|
|
25
25
|
const properties = getInterfaceProperties(this.systemManager.descriptors || ScryptedInterfaceDescriptors, interfaces);
|
|
26
26
|
return [...methods, ...properties];
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
getOwnPropertyDescriptor(target: any, p: string | symbol): PropertyDescriptor {
|
|
30
|
-
const interfaces = new Set<string>(this.systemManager.state[this.id]
|
|
29
|
+
getOwnPropertyDescriptor(target: any, p: string | symbol): PropertyDescriptor | undefined {
|
|
30
|
+
const interfaces = new Set<string>(this.systemManager.state[this.id]!.interfaces!.value);
|
|
31
31
|
const methods = getInterfaceMethods(this.systemManager.descriptors || ScryptedInterfaceDescriptors, interfaces);
|
|
32
32
|
const prop = p.toString();
|
|
33
33
|
if (methods.includes(prop)) {
|
|
@@ -39,9 +39,10 @@ class DeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
|
|
39
39
|
if (properties.includes(prop)) {
|
|
40
40
|
return {
|
|
41
41
|
configurable: true,
|
|
42
|
-
value: this.systemManager.state[this.id][prop]?.value
|
|
42
|
+
value: this.systemManager.state[this.id]![prop]?.value
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
return undefined;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
deleteProperty(target: any, p: string | symbol): boolean {
|
|
@@ -76,19 +77,19 @@ class DeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
|
|
76
77
|
if (handled)
|
|
77
78
|
return handled;
|
|
78
79
|
|
|
79
|
-
const interfaces = new Set<string>(this.systemManager.state[this.id]
|
|
80
|
+
const interfaces = new Set<string>(this.systemManager.state[this.id]!.interfaces?.value || []);
|
|
80
81
|
const prop = p.toString();
|
|
81
82
|
const isValidProperty = this.systemManager.propertyInterfaces?.[prop] || propertyInterfaces[prop];
|
|
82
83
|
|
|
83
84
|
// this will also return old properties that should not exist on a device. ie, a disabled mixin provider.
|
|
84
85
|
// should this change?
|
|
85
86
|
if (isValidProperty)
|
|
86
|
-
return (this.systemManager.state[this.id] as any)?.[p]?.value;
|
|
87
|
+
return (this.systemManager.state[this.id]! as any)?.[p]?.value;
|
|
87
88
|
|
|
88
89
|
if (!isValidInterfaceMethod(this.systemManager.descriptors || ScryptedInterfaceDescriptors, interfaces, prop))
|
|
89
90
|
return;
|
|
90
91
|
|
|
91
|
-
if (ScryptedInterfaceDescriptors[ScryptedInterface.ScryptedDevice]
|
|
92
|
+
if (ScryptedInterfaceDescriptors[ScryptedInterface.ScryptedDevice]!.methods.includes(prop))
|
|
92
93
|
return (this as any)[p].bind(this);
|
|
93
94
|
|
|
94
95
|
return new Proxy(() => p, this);
|
|
@@ -97,7 +98,7 @@ class DeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
|
|
97
98
|
ensureDevice() {
|
|
98
99
|
if (!this.device)
|
|
99
100
|
this.device = this.systemManager.api.getDeviceById(this.id);
|
|
100
|
-
return this.device
|
|
101
|
+
return this.device!;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
async apply(target: any, thisArg: any, argArray?: any) {
|
|
@@ -132,7 +133,7 @@ class DeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
|
|
132
133
|
|
|
133
134
|
|
|
134
135
|
class EventListenerRegisterImpl implements EventListenerRegister {
|
|
135
|
-
promise: Promise<EventListenerRegister
|
|
136
|
+
promise: Promise<EventListenerRegister> | undefined;
|
|
136
137
|
constructor(promise: Promise<EventListenerRegister>) {
|
|
137
138
|
this.promise = promise;
|
|
138
139
|
}
|
|
@@ -151,21 +152,21 @@ class EventListenerRegisterImpl implements EventListenerRegister {
|
|
|
151
152
|
function makeOneWayCallback<T>(input: T): T {
|
|
152
153
|
const f: any = input;
|
|
153
154
|
const oneways: string[] = f[RpcPeer.PROPERTY_PROXY_ONEWAY_METHODS] || [];
|
|
154
|
-
if (!oneways.includes(null))
|
|
155
|
-
oneways.push(null);
|
|
155
|
+
if (!oneways.includes(null!))
|
|
156
|
+
oneways.push(null!);
|
|
156
157
|
f[RpcPeer.PROPERTY_PROXY_ONEWAY_METHODS] = oneways;
|
|
157
158
|
return input;
|
|
158
159
|
}
|
|
159
160
|
|
|
160
161
|
export class SystemManagerImpl implements SystemManager {
|
|
161
|
-
api
|
|
162
|
-
state
|
|
162
|
+
api!: PluginAPI;
|
|
163
|
+
state!: { [id: string]: { [property: string]: SystemDeviceState } };
|
|
163
164
|
deviceProxies: { [id: string]: ScryptedDevice } = {};
|
|
164
|
-
log
|
|
165
|
+
log!: Logger;
|
|
165
166
|
events = new EventRegistry();
|
|
166
|
-
typesVersion
|
|
167
|
-
descriptors
|
|
168
|
-
propertyInterfaces
|
|
167
|
+
typesVersion!: string;
|
|
168
|
+
descriptors!: { [scryptedInterface: string]: ScryptedInterfaceDescriptor };
|
|
169
|
+
propertyInterfaces!: ReturnType<typeof getPropertyInterfaces>;
|
|
169
170
|
|
|
170
171
|
getDeviceState(id: string) {
|
|
171
172
|
return this.state[id];
|
|
@@ -196,9 +197,9 @@ export class SystemManagerImpl implements SystemManager {
|
|
|
196
197
|
}
|
|
197
198
|
}
|
|
198
199
|
}
|
|
199
|
-
if (!id)
|
|
200
|
+
if (!id!)
|
|
200
201
|
return;
|
|
201
|
-
let proxy = this.deviceProxies[id];
|
|
202
|
+
let proxy = this.deviceProxies[id!];
|
|
202
203
|
if (!proxy)
|
|
203
204
|
proxy = this.deviceProxies[id] = newDeviceProxy(id, this);
|
|
204
205
|
return proxy;
|
|
@@ -206,10 +207,10 @@ export class SystemManagerImpl implements SystemManager {
|
|
|
206
207
|
|
|
207
208
|
getDeviceByName(name: string): any {
|
|
208
209
|
for (const id of Object.keys(this.state)) {
|
|
209
|
-
const s = this.state[id]
|
|
210
|
+
const s = this.state[id]!;
|
|
210
211
|
if ((s.interfaces?.value as string[])?.includes(ScryptedInterface.ScryptedPlugin) && s.pluginId?.value === name)
|
|
211
212
|
return this.getDeviceById(id);
|
|
212
|
-
if (s.name
|
|
213
|
+
if (s.name!.value === name)
|
|
213
214
|
return this.getDeviceById(id);
|
|
214
215
|
}
|
|
215
216
|
}
|
package/src/promise-utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export interface RefreshPromise<T> {
|
|
2
|
-
promise: Promise<T
|
|
2
|
+
promise: Promise<T> | undefined;
|
|
3
3
|
cacheDuration: number;
|
|
4
4
|
}
|
|
5
5
|
|
|
@@ -66,12 +66,12 @@ export function timeoutFunction<T>(timeout: number, f: (isTimedOut: () => boolea
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
export function createPromiseDebouncer<T>() {
|
|
69
|
-
let current: Promise<T
|
|
69
|
+
let current: Promise<T> | undefined;
|
|
70
70
|
|
|
71
71
|
return (func: () => Promise<T>): Promise<T> => {
|
|
72
72
|
if (!current)
|
|
73
|
-
current = func().finally(() => current = undefined);
|
|
74
|
-
return current
|
|
73
|
+
current = func().finally(() => current = undefined as unknown as Promise<T>);
|
|
74
|
+
return current!;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
package/src/rpc-serializer.ts
CHANGED
|
@@ -109,8 +109,8 @@ export function createRpcDuplexSerializer(writable: {
|
|
|
109
109
|
sendMessageFinish: (message) => sendMessageFinish(Buffer.from(JSON.stringify(message))),
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
let header: Buffer;
|
|
113
|
-
let pending: Buffer;
|
|
112
|
+
let header: Buffer | undefined;
|
|
113
|
+
let pending: Buffer | undefined;
|
|
114
114
|
let offset: number;
|
|
115
115
|
let type: number;
|
|
116
116
|
|
|
@@ -183,7 +183,7 @@ export function createRpcDuplexSerializer(writable: {
|
|
|
183
183
|
|
|
184
184
|
export function createDataChannelSerializer(dc: { send: (data: Buffer) => void }) {
|
|
185
185
|
// Chunking and debouncing state
|
|
186
|
-
let pending: Buffer[];
|
|
186
|
+
let pending: Buffer[] | undefined;
|
|
187
187
|
|
|
188
188
|
// Max packet size for data channels is 16KB
|
|
189
189
|
const MAX_PACKET_SIZE = 16384;
|