socket-function 1.1.37 → 1.1.38

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/index.d.ts CHANGED
@@ -642,6 +642,48 @@ declare module "socket-function/src/batching" {
642
642
 
643
643
  }
644
644
 
645
+ declare module "socket-function/src/bits" {
646
+ /// <reference types="node" />
647
+ /// <reference types="node" />
648
+ /** Subtracts the smallest possible value from a number (a double). This makes it possible to convert an exclusive range end
649
+ * to an inclusive range end, which is sometimes required (as in, < x is the same as <= minusEpsilon(x)).
650
+ */
651
+ export declare function minusEpsilon(value: number): number;
652
+ export declare function addEpsilons(value: number, count: number): number;
653
+ export declare function getHighUint32(num: number): number;
654
+ export declare function getLowUint32(num: number): number;
655
+ /** IMPORTANT! Beware of comparisons with 64 bit numbers. getFloat64_fromBytes(4294136438, 168) !== getFloat64_fromBytes(4294136438, 168).
656
+ * USE is64BitEqual instead, OR, ensure the 2 highest bits are always 0.
657
+ */
658
+ export declare function setLowHighUint32(low: number, high: number): number;
659
+ /** Adds protection against NaN values, changing the result if it would be NaN. This is because NaN values will compare to be not equal even if they are equal in certain cases, and in other cases, they'll always be equal, even if their bits are not equal.
660
+ - This means this is not a reversible operation. However, in a lot of cases, that doesn't matter.
661
+ */
662
+ export declare function setLowHighUint32Safe(low: number, high: number): number;
663
+ export declare function xor64BitsSafe(a: number, b: number): number;
664
+ export declare function getShortNumber(buffer: Buffer): number;
665
+ export declare function getBufferInt(buffer: Buffer): number;
666
+ /** Returns a number between 0 (inclusive) and 1 (exclusive) */
667
+ export declare function getBufferFraction(buffer: Buffer): number;
668
+ export declare function getTimeUnique(): number;
669
+
670
+ }
671
+
672
+ declare module "socket-function/src/buffers" {
673
+ /// <reference types="node" />
674
+ /// <reference types="node" />
675
+ export type ArrayBufferViewTypes = Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | BigUint64Array | BigInt64Array | Float64Array | Float32Array | Uint8ClampedArray;
676
+ export type BufferType = ArrayBuffer | SharedArrayBuffer | ArrayBufferViewTypes;
677
+ export declare function cloneBuffer(data: Buffer): Buffer;
678
+ export declare function asBuffer(data: BufferType): Buffer;
679
+ export declare function asFloat64(data: Buffer): Float64Array;
680
+ export declare function asFloat32(data: Buffer): Float32Array;
681
+ export declare function asUint32(data: Buffer): Uint32Array;
682
+ export declare function asInt32(data: Buffer): Int32Array;
683
+ export declare function asFloat64MaybeCopy(data: Buffer): Float64Array;
684
+
685
+ }
686
+
645
687
  declare module "socket-function/src/caching" {
646
688
  import { AnyFunction, Args } from "socket-function/src/types";
647
689
  export declare function lazy<T>(factory: () => T): {
@@ -874,6 +916,10 @@ declare module "socket-function/src/forwardPort" {
874
916
 
875
917
  }
876
918
 
919
+ declare module "socket-function/src/getUniqueTime" {
920
+
921
+ }
922
+
877
923
  declare module "socket-function/src/https" {
878
924
  /// <reference types="node" />
879
925
  /// <reference types="node" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "socket-function",
3
- "version": "1.1.37",
3
+ "version": "1.1.38",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "dependencies": {
package/src/bits.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /** Subtracts the smallest possible value from a number (a double). This makes it possible to convert an exclusive range end
4
+ * to an inclusive range end, which is sometimes required (as in, < x is the same as <= minusEpsilon(x)).
5
+ */
6
+ export declare function minusEpsilon(value: number): number;
7
+ export declare function addEpsilons(value: number, count: number): number;
8
+ export declare function getHighUint32(num: number): number;
9
+ export declare function getLowUint32(num: number): number;
10
+ /** IMPORTANT! Beware of comparisons with 64 bit numbers. getFloat64_fromBytes(4294136438, 168) !== getFloat64_fromBytes(4294136438, 168).
11
+ * USE is64BitEqual instead, OR, ensure the 2 highest bits are always 0.
12
+ */
13
+ export declare function setLowHighUint32(low: number, high: number): number;
14
+ /** Adds protection against NaN values, changing the result if it would be NaN. This is because NaN values will compare to be not equal even if they are equal in certain cases, and in other cases, they'll always be equal, even if their bits are not equal.
15
+ - This means this is not a reversible operation. However, in a lot of cases, that doesn't matter.
16
+ */
17
+ export declare function setLowHighUint32Safe(low: number, high: number): number;
18
+ export declare function xor64BitsSafe(a: number, b: number): number;
19
+ export declare function getShortNumber(buffer: Buffer): number;
20
+ export declare function getBufferInt(buffer: Buffer): number;
21
+ /** Returns a number between 0 (inclusive) and 1 (exclusive) */
22
+ export declare function getBufferFraction(buffer: Buffer): number;
23
+ export declare function getTimeUnique(): number;
package/src/bits.ts ADDED
@@ -0,0 +1,116 @@
1
+
2
+ /** Subtracts the smallest possible value from a number (a double). This makes it possible to convert an exclusive range end
3
+ * to an inclusive range end, which is sometimes required (as in, < x is the same as <= minusEpsilon(x)).
4
+ */
5
+ export function minusEpsilon(value: number) {
6
+ let high = getHighUint32(value);
7
+ let low = getLowUint32(value);
8
+
9
+ if (low === 0) {
10
+ low = 2 ** 32 - 1;
11
+ high--;
12
+ } else {
13
+ low--;
14
+ }
15
+
16
+ return setLowHighUint32(low, high);
17
+ }
18
+ const maxUint32 = 2 ** 32 - 1;
19
+ export function addEpsilons(value: number, count: number) {
20
+ let high = getHighUint32(value);
21
+ let low = getLowUint32(value);
22
+
23
+ low += count;
24
+ if (low < 0) {
25
+ low += maxUint32;
26
+ high++;
27
+ } else if (low > maxUint32) {
28
+ low -= maxUint32;
29
+ high--;
30
+ }
31
+
32
+ return setLowHighUint32(low, high);
33
+ }
34
+
35
+ let conversionBuffer = new Float64Array(1);
36
+ let conversionUint8Buffer = new Uint8Array(conversionBuffer.buffer);
37
+ let conversionUint32Buffer = new Uint32Array(conversionBuffer.buffer);
38
+ export function getHighUint32(num: number): number {
39
+ conversionBuffer[0] = num;
40
+ return conversionUint32Buffer[1];
41
+ }
42
+ export function getLowUint32(num: number): number {
43
+ conversionBuffer[0] = num;
44
+ return conversionUint32Buffer[0];
45
+ }
46
+
47
+ /** IMPORTANT! Beware of comparisons with 64 bit numbers. getFloat64_fromBytes(4294136438, 168) !== getFloat64_fromBytes(4294136438, 168).
48
+ * USE is64BitEqual instead, OR, ensure the 2 highest bits are always 0.
49
+ */
50
+ export function setLowHighUint32(low: number, high: number): number {
51
+ conversionUint32Buffer[0] = low;
52
+ conversionUint32Buffer[1] = high;
53
+ return conversionBuffer[0];
54
+ }
55
+
56
+ /** Adds protection against NaN values, changing the result if it would be NaN. This is because NaN values will compare to be not equal even if they are equal in certain cases, and in other cases, they'll always be equal, even if their bits are not equal.
57
+ - This means this is not a reversible operation. However, in a lot of cases, that doesn't matter.
58
+ */
59
+ export function setLowHighUint32Safe(low: number, high: number): number {
60
+ conversionUint32Buffer[0] = low;
61
+ // Prevent NaN by not setting all the exponent bits to 1
62
+ conversionUint32Buffer[1] = high & 0xBFFFFFFF;
63
+ return conversionBuffer[0];
64
+ }
65
+
66
+ // NOTE: Not reversible, see setLowHighUint32Safe
67
+ export function xor64BitsSafe(a: number, b: number): number {
68
+ let high = getHighUint32(a);
69
+ let low = getLowUint32(a);
70
+ let high2 = getHighUint32(b);
71
+ let low2 = getLowUint32(b);
72
+ return setLowHighUint32Safe(low ^ low2, high ^ high2);
73
+ }
74
+
75
+ // Gets bits that can be stored in a number. Specifically, the first 62 bits,
76
+ // as 64 bits will not compare correctly when treated as a double.
77
+ export function getShortNumber(buffer: Buffer): number {
78
+ let high = buffer.readUInt32BE(0) & 0x3FFFFFFF;
79
+ let low = buffer.readUInt32BE(4);
80
+ return setLowHighUint32(low, high);
81
+ }
82
+ /* Returns a number between 0 and 2**48 */
83
+ export function getBufferInt(buffer: Buffer): number {
84
+ let num = 0;
85
+ for (let i = 0; i < Math.min(buffer.length, 6); i++) {
86
+ num = num * 256 + buffer[i];
87
+ }
88
+ return num;
89
+ }
90
+ const intMax = 2 ** 48;
91
+ /** Returns a number between 0 (inclusive) and 1 (exclusive) */
92
+ export function getBufferFraction(buffer: Buffer): number {
93
+ let int = getBufferInt(buffer);
94
+ return int / intMax;
95
+ }
96
+
97
+ /*
98
+ export function numberToBase64(num: number): string {
99
+ conversionBuffer[0] = num;
100
+ return Buffer.from(conversionBuffer.buffer).toString("base64");
101
+ }
102
+ export function numberFromBase64(base64: string) {
103
+ return new Float64Array(Buffer.from(base64, "base64"))[0];
104
+ }
105
+ */
106
+
107
+
108
+ let prevTime = 0;
109
+ export function getTimeUnique() {
110
+ let time = Date.now();
111
+ if (time <= prevTime) {
112
+ time = addEpsilons(prevTime, 1);
113
+ }
114
+ prevTime = time;
115
+ return time;
116
+ }
@@ -0,0 +1,11 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ export type ArrayBufferViewTypes = Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | BigUint64Array | BigInt64Array | Float64Array | Float32Array | Uint8ClampedArray;
4
+ export type BufferType = ArrayBuffer | SharedArrayBuffer | ArrayBufferViewTypes;
5
+ export declare function cloneBuffer(data: Buffer): Buffer;
6
+ export declare function asBuffer(data: BufferType): Buffer;
7
+ export declare function asFloat64(data: Buffer): Float64Array;
8
+ export declare function asFloat32(data: Buffer): Float32Array;
9
+ export declare function asUint32(data: Buffer): Uint32Array;
10
+ export declare function asInt32(data: Buffer): Int32Array;
11
+ export declare function asFloat64MaybeCopy(data: Buffer): Float64Array;
package/src/buffers.ts ADDED
@@ -0,0 +1,69 @@
1
+ import { canHaveChildren } from "socket-function/src/types";
2
+
3
+ export type ArrayBufferViewTypes = Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | BigUint64Array | BigInt64Array | Float64Array | Float32Array | Uint8ClampedArray;
4
+ export type BufferType = ArrayBuffer | SharedArrayBuffer | ArrayBufferViewTypes;
5
+
6
+ export function cloneBuffer(data: Buffer): Buffer {
7
+ let newBuffer = Buffer.alloc(data.length);
8
+ data.copy(newBuffer);
9
+ return newBuffer;
10
+ }
11
+
12
+
13
+ export function asBuffer(data: BufferType): Buffer {
14
+ if (!data) return data;
15
+ if (data instanceof Buffer) return data;
16
+ if (!canHaveChildren(data)) return data as any;
17
+ if (!("buffer" in data) || !("byteOffset" in data) || !("byteLength" in data)) {
18
+ return Buffer.from(data);
19
+ }
20
+ let result = Buffer.from((data as any).buffer, (data as any).byteOffset, (data as any).byteLength);
21
+ return result;
22
+ }
23
+ export function asFloat64(data: Buffer): Float64Array {
24
+ if (data.length % 8 !== 0) {
25
+ throw new Error(`Data is not 8 count aligned, received length of ${data.length}`);
26
+ }
27
+ if (data.byteOffset % 8 !== 0) {
28
+ throw new Error(`Data is not 8 byte aligned, received offset of ${data.byteOffset}`);
29
+ }
30
+ return new Float64Array(data.buffer, data.byteOffset, Math.floor(data.length / 8));
31
+ }
32
+ export function asFloat32(data: Buffer): Float32Array {
33
+ if (data.length % 4 !== 0) {
34
+ throw new Error(`Data is not 4 byte aligned, received length of ${data.length}`);
35
+ }
36
+ if (data.byteOffset % 4 !== 0) {
37
+ throw new Error(`Data is not 4 byte aligned, received offset of ${data.byteOffset}`);
38
+ }
39
+ return new Float32Array(data.buffer, data.byteOffset, Math.floor(data.length / 4));
40
+ }
41
+ export function asUint32(data: Buffer): Uint32Array {
42
+ if (data.length % 4 !== 0) {
43
+ throw new Error(`Data is not 4 byte aligned, received length of ${data.length}`);
44
+ }
45
+ if (data.byteOffset % 4 !== 0) {
46
+ throw new Error(`Data is not 4 byte aligned, received offset of ${data.byteOffset}`);
47
+ }
48
+ return new Uint32Array(data.buffer, data.byteOffset, Math.floor(data.length / 4));
49
+ }
50
+ export function asInt32(data: Buffer): Int32Array {
51
+ if (data.length % 4 !== 0) {
52
+ throw new Error(`Data is not 4 byte aligned, received length of ${data.length}`);
53
+ }
54
+ if (data.byteOffset % 4 !== 0) {
55
+ throw new Error(`Data is not 4 byte aligned, received offset of ${data.byteOffset}`);
56
+ }
57
+ return new Int32Array(data.buffer, data.byteOffset, Math.floor(data.length / 4));
58
+ }
59
+
60
+
61
+ export function asFloat64MaybeCopy(data: Buffer) {
62
+ if (data.length % 8 !== 0) {
63
+ throw new Error(`Data is not 8 count aligned, received length of ${data.length}`);
64
+ }
65
+ if (data.byteOffset % 8 !== 0) {
66
+ return asFloat64(cloneBuffer(data));
67
+ }
68
+ return new Float64Array(data.buffer, data.byteOffset, Math.floor(data.length / 8));
69
+ }
File without changes
File without changes
@@ -78,8 +78,14 @@ export async function startSocketServer(
78
78
  const proposed = Array.from(protocols);
79
79
  const chosen = chooseProtocol(proposed, ourNodeId, { lz4: true });
80
80
  if (!chosen) {
81
- const proposedDecoded = proposed.map(p => decodeProtocol(p) ?? `<undecodable: ${p}>`);
82
- console.log(`Rejecting handshake on ${ourNodeId}: none of the ${proposed.length} proposed protocols target us`, { ourNodeId, proposedDecoded });
81
+ const proposedDecoded = proposed.map(p => decodeProtocol(p));
82
+ let target = proposedDecoded[0]?.target;
83
+ let getMachineId = (x: string) => x.split(".").slice(-3).join(".");
84
+ if (target && getMachineId(target) === getMachineId(ourNodeId)) {
85
+ console.log(`Rejecting handshake from old thread, ${target} !== ${ourNodeId}`);
86
+ } else {
87
+ console.log(`Rejecting handshake on ${ourNodeId}: none of the ${proposed.length} proposed protocols target us`, { ourNodeId, proposedDecoded });
88
+ }
83
89
  return false;
84
90
  }
85
91
  return chosen;