socket-function 1.2.14 → 1.2.16
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/SocketFunction.d.ts +2 -0
- package/SocketFunction.ts +5 -0
- package/index.d.ts +16 -0
- package/package.json +1 -1
- package/require/RequireController.d.ts +1 -0
- package/require/extMapper.d.ts +1 -0
- package/src/CallFactory.d.ts +1 -0
- package/src/CallFactory.ts +19 -8
- package/src/JSONLACKS/JSONLACKS.d.ts +1 -0
- package/src/Zip.d.ts +1 -0
- package/src/bits.d.ts +1 -0
- package/src/buffers.d.ts +1 -0
- package/src/callHTTPHandler.d.ts +1 -0
- package/src/callManager.ts +7 -4
- package/src/certStore.d.ts +1 -0
- package/src/https.d.ts +1 -0
- package/src/lz4/LZ4.d.ts +1 -0
- package/src/misc.d.ts +1 -0
- package/src/protocolNegotiation.ts +2 -1
- package/src/tlsParsing.d.ts +1 -0
- package/src/webSocketServer.d.ts +1 -0
- package/src/webSocketServer.ts +1 -1
package/SocketFunction.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference path="require/RequireController.d.ts" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
3
4
|
import { SocketExposedInterface, SocketFunctionHook, SocketFunctionClientHook, SocketExposedShape, SocketRegistered, CallerContext, FullCallType, SocketRegisterType } from "./SocketFunctionTypes";
|
|
4
5
|
import { SocketServerConfig } from "./src/webSocketServer";
|
|
5
6
|
import { Args, MaybePromise } from "./src/types";
|
|
@@ -36,6 +37,7 @@ export declare class SocketFunction {
|
|
|
36
37
|
*/
|
|
37
38
|
static GET_ALTERNATE_NODE_IDS: (nodeId: string) => MaybePromise<string[] | undefined>;
|
|
38
39
|
static WIRE_WARN_TIME: number;
|
|
40
|
+
static DISABLE_COMPRESSION: boolean;
|
|
39
41
|
private static onMountCallbacks;
|
|
40
42
|
private static exposedClassesSingleton;
|
|
41
43
|
static get exposedClasses(): Set<string>;
|
package/SocketFunction.ts
CHANGED
|
@@ -98,6 +98,9 @@ export class SocketFunction {
|
|
|
98
98
|
|
|
99
99
|
public static WIRE_WARN_TIME = 100;
|
|
100
100
|
|
|
101
|
+
// Process-wide compression kill switch. When set before connections are established, LZ4 is left out of the protocol negotiation entirely (both for connections we initiate and ones we accept), so NEITHER side compresses — the wire format stays the plain backwards-compatible one. Overrides per-function `compress` flags.
|
|
102
|
+
public static DISABLE_COMPRESSION = false;
|
|
103
|
+
|
|
101
104
|
// Shared across copies of this package, so onMount callbacks registered through one copy still
|
|
102
105
|
// fire when another copy mounts. See createSingleton.
|
|
103
106
|
private static onMountCallbacks = createSingleton("SocketFunction.onMountCallbacks", 1, () => new Map<string, (() => MaybePromise<void>)[]>()).get();
|
|
@@ -197,6 +200,8 @@ export class SocketFunction {
|
|
|
197
200
|
|
|
198
201
|
for (let value of Object.values(shape)) {
|
|
199
202
|
if (!value) continue;
|
|
203
|
+
value.noClientHooks = value.noClientHooks ?? defaultHooks?.noClientHooks;
|
|
204
|
+
value.noDefaultHooks = value.noDefaultHooks ?? defaultHooks?.noDefaultHooks;
|
|
200
205
|
if (!value.noClientHooks) {
|
|
201
206
|
value.clientHooks = [...(defaultHooks?.clientHooks || []), ...(value.clientHooks || [])];
|
|
202
207
|
}
|
package/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ declare module "socket-function/SetProcessVariables" {
|
|
|
9
9
|
declare module "socket-function/SocketFunction" {
|
|
10
10
|
/// <reference path="require/RequireController.d.ts" />
|
|
11
11
|
/// <reference types="node" />
|
|
12
|
+
/// <reference types="node" />
|
|
12
13
|
import { SocketExposedInterface, SocketFunctionHook, SocketFunctionClientHook, SocketExposedShape, SocketRegistered, CallerContext, FullCallType, SocketRegisterType } from "socket-function/SocketFunctionTypes";
|
|
13
14
|
import { SocketServerConfig } from "socket-function/src/webSocketServer";
|
|
14
15
|
import { Args, MaybePromise } from "socket-function/src/types";
|
|
@@ -45,6 +46,7 @@ declare module "socket-function/SocketFunction" {
|
|
|
45
46
|
*/
|
|
46
47
|
static GET_ALTERNATE_NODE_IDS: (nodeId: string) => MaybePromise<string[] | undefined>;
|
|
47
48
|
static WIRE_WARN_TIME: number;
|
|
49
|
+
static DISABLE_COMPRESSION: boolean;
|
|
48
50
|
private static onMountCallbacks;
|
|
49
51
|
private static exposedClassesSingleton;
|
|
50
52
|
static get exposedClasses(): Set<string>;
|
|
@@ -315,6 +317,7 @@ declare module "socket-function/require/CSSShim" {
|
|
|
315
317
|
declare module "socket-function/require/RequireController" {
|
|
316
318
|
/// <reference path="../../typenode/index.d.ts" />
|
|
317
319
|
/// <reference types="node" />
|
|
320
|
+
/// <reference types="node" />
|
|
318
321
|
declare global {
|
|
319
322
|
namespace NodeJS {
|
|
320
323
|
interface Module {
|
|
@@ -444,6 +447,7 @@ declare module "socket-function/require/compileFlags" {
|
|
|
444
447
|
}
|
|
445
448
|
|
|
446
449
|
declare module "socket-function/require/extMapper" {
|
|
450
|
+
/// <reference types="node" />
|
|
447
451
|
/// <reference types="node" />
|
|
448
452
|
export declare function getExtContentType(ext: string): string;
|
|
449
453
|
export declare function getContentTypeFromBuffer(buffer: Buffer): string | undefined;
|
|
@@ -469,6 +473,7 @@ declare module "socket-function/require/require" {
|
|
|
469
473
|
}
|
|
470
474
|
|
|
471
475
|
declare module "socket-function/src/CallFactory" {
|
|
476
|
+
/// <reference types="node" />
|
|
472
477
|
/// <reference types="node" />
|
|
473
478
|
/// <reference types="node" />
|
|
474
479
|
import { CallType } from "socket-function/SocketFunctionTypes";
|
|
@@ -527,6 +532,7 @@ declare module "socket-function/src/CallFactory" {
|
|
|
527
532
|
}
|
|
528
533
|
|
|
529
534
|
declare module "socket-function/src/JSONLACKS/JSONLACKS" {
|
|
535
|
+
/// <reference types="node" />
|
|
530
536
|
/// <reference types="node" />
|
|
531
537
|
export interface JSONLACKS_ParseConfig {
|
|
532
538
|
extended?: boolean;
|
|
@@ -562,6 +568,7 @@ declare module "socket-function/src/JSONLACKS/JSONLACKS.generated.js" {
|
|
|
562
568
|
}
|
|
563
569
|
|
|
564
570
|
declare module "socket-function/src/Zip" {
|
|
571
|
+
/// <reference types="node" />
|
|
565
572
|
/// <reference types="node" />
|
|
566
573
|
import { MaybePromise } from "socket-function/src/types";
|
|
567
574
|
export declare class Zip {
|
|
@@ -649,6 +656,7 @@ declare module "socket-function/src/batching" {
|
|
|
649
656
|
}
|
|
650
657
|
|
|
651
658
|
declare module "socket-function/src/bits" {
|
|
659
|
+
/// <reference types="node" />
|
|
652
660
|
/// <reference types="node" />
|
|
653
661
|
/** Subtracts the smallest possible value from a number (a double). This makes it possible to convert an exclusive range end
|
|
654
662
|
* to an inclusive range end, which is sometimes required (as in, < x is the same as <= minusEpsilon(x)).
|
|
@@ -675,6 +683,7 @@ declare module "socket-function/src/bits" {
|
|
|
675
683
|
}
|
|
676
684
|
|
|
677
685
|
declare module "socket-function/src/buffers" {
|
|
686
|
+
/// <reference types="node" />
|
|
678
687
|
/// <reference types="node" />
|
|
679
688
|
export type ArrayBufferViewTypes = Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | BigUint64Array | BigInt64Array | Float64Array | Float32Array | Uint8ClampedArray;
|
|
680
689
|
export type BufferType = ArrayBuffer | SharedArrayBuffer | ArrayBufferViewTypes;
|
|
@@ -752,6 +761,7 @@ declare module "socket-function/src/caching" {
|
|
|
752
761
|
}
|
|
753
762
|
|
|
754
763
|
declare module "socket-function/src/callHTTPHandler" {
|
|
764
|
+
/// <reference types="node" />
|
|
755
765
|
/// <reference types="node" />
|
|
756
766
|
/// <reference types="node" />
|
|
757
767
|
import http from "http";
|
|
@@ -806,6 +816,7 @@ declare module "socket-function/src/callManager" {
|
|
|
806
816
|
}
|
|
807
817
|
|
|
808
818
|
declare module "socket-function/src/certStore" {
|
|
819
|
+
/// <reference types="node" />
|
|
809
820
|
/// <reference types="node" />
|
|
810
821
|
/** Must be populated before the server starts */
|
|
811
822
|
export declare function trustCertificate(cert: string | Buffer): void;
|
|
@@ -971,6 +982,7 @@ declare module "socket-function/src/getUniqueTime" {
|
|
|
971
982
|
}
|
|
972
983
|
|
|
973
984
|
declare module "socket-function/src/https" {
|
|
985
|
+
/// <reference types="node" />
|
|
974
986
|
/// <reference types="node" />
|
|
975
987
|
export declare function httpsRequest(url: string, payload?: Buffer | Buffer[], method?: string, sendSessionCookies?: boolean, config?: {
|
|
976
988
|
headers?: {
|
|
@@ -982,6 +994,7 @@ declare module "socket-function/src/https" {
|
|
|
982
994
|
}
|
|
983
995
|
|
|
984
996
|
declare module "socket-function/src/lz4/LZ4" {
|
|
997
|
+
/// <reference types="node" />
|
|
985
998
|
/// <reference types="node" />
|
|
986
999
|
export declare class LZ4 {
|
|
987
1000
|
static compress(data: Buffer): Buffer;
|
|
@@ -1049,6 +1062,7 @@ declare module "socket-function/src/lz4/lz4_wasm_nodejs_bg.wasm" {
|
|
|
1049
1062
|
}
|
|
1050
1063
|
|
|
1051
1064
|
declare module "socket-function/src/misc" {
|
|
1065
|
+
/// <reference types="node" />
|
|
1052
1066
|
/// <reference types="node" />
|
|
1053
1067
|
import { MaybePromise } from "socket-function/src/types";
|
|
1054
1068
|
export declare const timeInSecond = 1000;
|
|
@@ -1479,6 +1493,7 @@ declare module "socket-function/src/storagePath" {
|
|
|
1479
1493
|
}
|
|
1480
1494
|
|
|
1481
1495
|
declare module "socket-function/src/tlsParsing" {
|
|
1496
|
+
/// <reference types="node" />
|
|
1482
1497
|
/// <reference types="node" />
|
|
1483
1498
|
export declare function parseTLSHello(buffer: Buffer): {
|
|
1484
1499
|
extensions: {
|
|
@@ -1508,6 +1523,7 @@ declare module "socket-function/src/upreal" {
|
|
|
1508
1523
|
}
|
|
1509
1524
|
|
|
1510
1525
|
declare module "socket-function/src/webSocketServer" {
|
|
1526
|
+
/// <reference types="node" />
|
|
1511
1527
|
/// <reference types="node" />
|
|
1512
1528
|
/// <reference types="node" />
|
|
1513
1529
|
import https from "https";
|
package/package.json
CHANGED
package/require/extMapper.d.ts
CHANGED
package/src/CallFactory.d.ts
CHANGED
package/src/CallFactory.ts
CHANGED
|
@@ -21,6 +21,13 @@ import { Zip } from "./Zip";
|
|
|
21
21
|
import { decodeProtocol, proposeProtocols } from "./protocolNegotiation";
|
|
22
22
|
setImmediate(() => import("./lz4/LZ4"));
|
|
23
23
|
|
|
24
|
+
// Cached in a plain variable because even though require/import caches modules, the lookup is still measurably slow on a hot path — and once cached the caller doesn't even need to await.
|
|
25
|
+
let lz4Cached: typeof import("./lz4/LZ4").LZ4 | undefined;
|
|
26
|
+
function getLZ4(): MaybePromise<typeof import("./lz4/LZ4").LZ4> {
|
|
27
|
+
if (lz4Cached) return lz4Cached;
|
|
28
|
+
return import("./lz4/LZ4").then(module => lz4Cached = module.LZ4);
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
setFlag(require, "pako", "allowclient", true);
|
|
25
32
|
|
|
26
33
|
// NOTE: If it is too low, and too many servers disconnect, we can easily spend 100% of our time
|
|
@@ -192,9 +199,10 @@ export async function createCallFactory(
|
|
|
192
199
|
compressedSize: 0,
|
|
193
200
|
};
|
|
194
201
|
try {
|
|
195
|
-
if (
|
|
202
|
+
if (SocketFunction.DISABLE_COMPRESSION) {
|
|
203
|
+
} else if (callFactory.receivedInitializeState?.supportsLZ4) {
|
|
196
204
|
let compressMode = shouldCompressCall(fullCall);
|
|
197
|
-
// If it's undefined, then we compress it. We basically always want to compress from now on, because LZ4 is so fast.
|
|
205
|
+
// If it's undefined, then we compress it. We basically always want to compress from now on, because LZ4 is so fast.
|
|
198
206
|
if (compressMode !== false) {
|
|
199
207
|
fullCall.args = await compressObjLZ4(fullCall.args, sendStats) as any;
|
|
200
208
|
fullCall.isArgsCompressed = "LZ4";
|
|
@@ -488,7 +496,7 @@ export async function createCallFactory(
|
|
|
488
496
|
let alternates = await SocketFunction.GET_ALTERNATE_NODE_IDS(nodeId);
|
|
489
497
|
if (alternates) {
|
|
490
498
|
for (let alternateNodeId of alternates) {
|
|
491
|
-
let newWebSocket = createWebsocket(alternateNodeId, proposeProtocols(nodeId, { lz4:
|
|
499
|
+
let newWebSocket = createWebsocket(alternateNodeId, proposeProtocols(nodeId, { lz4: !SocketFunction.DISABLE_COMPRESSION }));
|
|
492
500
|
await initializeWebsocket(newWebSocket, true);
|
|
493
501
|
|
|
494
502
|
if (callFactory.isConnected) {
|
|
@@ -500,7 +508,7 @@ export async function createCallFactory(
|
|
|
500
508
|
console.error("Error getting alternate node IDs", e);
|
|
501
509
|
}
|
|
502
510
|
|
|
503
|
-
let newWebSocket = createWebsocket(nodeId, proposeProtocols(nodeId, { lz4:
|
|
511
|
+
let newWebSocket = createWebsocket(nodeId, proposeProtocols(nodeId, { lz4: !SocketFunction.DISABLE_COMPRESSION }));
|
|
504
512
|
await initializeWebsocket(newWebSocket);
|
|
505
513
|
|
|
506
514
|
return newWebSocket;
|
|
@@ -635,7 +643,8 @@ export async function createCallFactory(
|
|
|
635
643
|
let timeTaken = Date.now() - time;
|
|
636
644
|
console.log(`DUR\t${(formatTime(timeTaken)).padEnd(6, " ")}\tFINISH\t${call.classGuid}.${call.functionName} at ${Date.now()}, (${nodeId} / ${localNodeId})`);
|
|
637
645
|
}
|
|
638
|
-
if (
|
|
646
|
+
if (SocketFunction.DISABLE_COMPRESSION) {
|
|
647
|
+
} else if (callFactory.receivedInitializeState?.supportsLZ4) {
|
|
639
648
|
let compressMode = shouldCompressCall(call);
|
|
640
649
|
if (compressMode !== false) {
|
|
641
650
|
response.result = await compressObjLZ4(response.result, sendStats);
|
|
@@ -865,7 +874,7 @@ const decompressObj = measureWrap(async function wireCallDecompress(obj: Buffer,
|
|
|
865
874
|
});
|
|
866
875
|
|
|
867
876
|
const compressObjLZ4 = measureWrap(async function wireCallCompressLZ4(obj: unknown, stats: CompressionStats): Promise<Buffer[]> {
|
|
868
|
-
const
|
|
877
|
+
const LZ4 = await getLZ4();
|
|
869
878
|
let headerParts: number[];
|
|
870
879
|
let dataBuffers: Buffer[];
|
|
871
880
|
|
|
@@ -968,8 +977,10 @@ const compressObjLZ4 = measureWrap(async function wireCallCompressLZ4(obj: unkno
|
|
|
968
977
|
});
|
|
969
978
|
|
|
970
979
|
const decompressObjLZ4 = measureWrap(async function wireCallDecompressLZ4(obj: Buffer[], stats: CompressionStats): Promise<unknown> {
|
|
971
|
-
|
|
972
|
-
|
|
980
|
+
let LZ4 = getLZ4();
|
|
981
|
+
if (LZ4 instanceof Promise) {
|
|
982
|
+
LZ4 = await LZ4;
|
|
983
|
+
}
|
|
973
984
|
stats.compressedSize += obj.reduce((sum, buf) => sum + buf.length, 0);
|
|
974
985
|
|
|
975
986
|
let decompressed: Buffer[] = [];
|
package/src/Zip.d.ts
CHANGED
package/src/bits.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
/** Subtracts the smallest possible value from a number (a double). This makes it possible to convert an exclusive range end
|
|
3
4
|
* to an inclusive range end, which is sometimes required (as in, < x is the same as <= minusEpsilon(x)).
|
|
4
5
|
*/
|
package/src/buffers.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
export type ArrayBufferViewTypes = Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | BigUint64Array | BigInt64Array | Float64Array | Float32Array | Uint8ClampedArray;
|
|
3
4
|
export type BufferType = ArrayBuffer | SharedArrayBuffer | ArrayBufferViewTypes;
|
|
4
5
|
export declare function cloneBuffer(data: Buffer): Buffer;
|
package/src/callHTTPHandler.d.ts
CHANGED
package/src/callManager.ts
CHANGED
|
@@ -128,6 +128,7 @@ export function unregisterGlobalClientHook(hook: SocketFunctionClientHook) {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
let startupTime = Date.now();
|
|
131
132
|
export const runClientHooks = measureWrap(async function runClientHooks(
|
|
132
133
|
callType: FullCallType,
|
|
133
134
|
hooks: Exclude<SocketExposedShape[""], undefined>,
|
|
@@ -149,8 +150,9 @@ export const runClientHooks = measureWrap(async function runClientHooks(
|
|
|
149
150
|
await measureBlock(async () => {
|
|
150
151
|
await hook(context);
|
|
151
152
|
}, `clientHook|${hook.name || hook.toString().slice(0, 100)}`);
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
let now = Date.now();
|
|
154
|
+
time = now - time;
|
|
155
|
+
if (time > 500 && now - startupTime > 60_000) {
|
|
154
156
|
console.warn(`Slow (${formatTime(time)}) client hook: ${JSON.stringify(hook.name || hook.toString().slice(0, 100))} for ${callType.classGuid}.${callType.functionName}(...)`);
|
|
155
157
|
}
|
|
156
158
|
// NOTE: See ClientHookContext.overrideResult for why we break here
|
|
@@ -171,8 +173,9 @@ export const runServerHooks = measureWrap(async function runServerHooks(
|
|
|
171
173
|
for (let hook of globalHooks.concat(hooks.hooks || [])) {
|
|
172
174
|
let time = Date.now();
|
|
173
175
|
await _setSocketContext(caller, () => hook(hookContext));
|
|
174
|
-
|
|
175
|
-
|
|
176
|
+
let now = Date.now();
|
|
177
|
+
time = now - time;
|
|
178
|
+
if (time > 500 && now - startupTime > 60_000) {
|
|
176
179
|
console.warn(`Slow (${formatTime(time)}) server hook: ${JSON.stringify(hook.name || hook.toString().slice(0, 100))} for ${callType.classGuid}.${callType.functionName}(...)`);
|
|
177
180
|
}
|
|
178
181
|
// NOTE: See HookContext.overrideResult for why we don't break here
|
package/src/certStore.d.ts
CHANGED
package/src/https.d.ts
CHANGED
package/src/lz4/LZ4.d.ts
CHANGED
package/src/misc.d.ts
CHANGED
|
@@ -78,7 +78,8 @@ export function proposeProtocols(target: string | undefined, clientCapabilities:
|
|
|
78
78
|
}
|
|
79
79
|
let out: string[] = [];
|
|
80
80
|
let clientLZ4Options = clientCapabilities.lz4 ? [true, false] : [false];
|
|
81
|
-
|
|
81
|
+
// When we don't want LZ4 we must not propose serverLZ4=1 at all — the server picks the first proposal it can serve, and the echoed serverLZ4 bit is what BOTH sides read as "this connection uses LZ4".
|
|
82
|
+
let serverLZ4Options = clientCapabilities.lz4 ? [true, false] : [false];
|
|
82
83
|
let encodedTarget = target ?? WILDCARD_TARGET;
|
|
83
84
|
for (let clientLZ4 of clientLZ4Options) {
|
|
84
85
|
for (let serverLZ4 of serverLZ4Options) {
|
package/src/tlsParsing.d.ts
CHANGED
package/src/webSocketServer.d.ts
CHANGED
package/src/webSocketServer.ts
CHANGED
|
@@ -82,7 +82,7 @@ export async function startSocketServer(
|
|
|
82
82
|
handleProtocols: (protocols, request) => {
|
|
83
83
|
const ourNodeId = SocketFunction.mountedNodeId;
|
|
84
84
|
const proposed = Array.from(protocols);
|
|
85
|
-
const chosen = chooseProtocol(proposed, ourNodeId, { lz4:
|
|
85
|
+
const chosen = chooseProtocol(proposed, ourNodeId, { lz4: !SocketFunction.DISABLE_COMPRESSION });
|
|
86
86
|
if (!chosen) {
|
|
87
87
|
const proposedDecoded = proposed.map(p => decodeProtocol(p));
|
|
88
88
|
let target = proposedDecoded[0]?.target;
|