sonic-ws 1.2.0 → 1.2.1
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/README.md +5 -2
- package/dist/ws/client/core/ClientCore.js +9 -2
- package/dist/ws/packets/PacketProcessors.d.ts +2 -2
- package/dist/ws/packets/PacketProcessors.js +6 -32
- package/dist/ws/packets/Packets.d.ts +2 -0
- package/dist/ws/packets/Packets.js +2 -0
- package/dist/ws/server/SonicWSConnection.js +12 -2
- package/dist/ws/server/SonicWSServer.js +2 -2
- package/dist/ws/util/packets/PacketUtils.d.ts +1 -1
- package/dist/ws/util/packets/PacketUtils.js +11 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,8 @@ Security:
|
|
|
23
23
|
- Built-in ability for handshake packets, preventing repetitive initiation checks in listeners (for example, removes if(!init) everywhere)
|
|
24
24
|
- Built-in rate limiting for packets; ability for global send & receive, alongside per-packet rate limiting
|
|
25
25
|
- Built-in disabling & enabling of packets to prevent abuse
|
|
26
|
-
- Prevents any race conditions; your callbacks will not be called until
|
|
26
|
+
- Prevents any race conditions; your callbacks will not be called until the last one finishes. (Alongside async options!)
|
|
27
|
+
- Prevents niche bugs found in other websocket libraries, such as functions calling after the socket already closed.
|
|
27
28
|
|
|
28
29
|
Performance & Scaling:
|
|
29
30
|
- Can handle very large packets in microseconds
|
|
@@ -119,4 +120,6 @@ Some weird error messages when invalid inputs are in like CreatePacket() and stu
|
|
|
119
120
|
|
|
120
121
|
Better error handling
|
|
121
122
|
|
|
122
|
-
Some middleware support
|
|
123
|
+
Some middleware support
|
|
124
|
+
|
|
125
|
+
Debug menus for client/server
|
|
@@ -166,8 +166,15 @@ class SonicWSCore {
|
|
|
166
166
|
const key = data[0];
|
|
167
167
|
const value = data.slice(1);
|
|
168
168
|
const packet = this.serverPackets.getPacket(this.serverPackets.getTag(key));
|
|
169
|
+
if (packet.rereference && value.length == 0) {
|
|
170
|
+
if (packet.lastReceived[0] === undefined)
|
|
171
|
+
return this.invalidPacket("No previous value to rereference");
|
|
172
|
+
this.listenPacket(packet.lastReceived[0], key);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
169
175
|
if (packet.dataBatching == 0) {
|
|
170
|
-
|
|
176
|
+
const res = packet.lastReceived[0] = await packet.listen(value, null);
|
|
177
|
+
this.listenPacket(res, key);
|
|
171
178
|
return;
|
|
172
179
|
}
|
|
173
180
|
const batchData = await BatchHelper_1.BatchHelper.unravelBatch(packet, value, null);
|
|
@@ -205,7 +212,7 @@ class SonicWSCore {
|
|
|
205
212
|
* @param values The values to send
|
|
206
213
|
*/
|
|
207
214
|
async send(tag, ...values) {
|
|
208
|
-
const [code, data, packet] = await (0, PacketUtils_1.processPacket)(this.clientPackets, tag, values);
|
|
215
|
+
const [code, data, packet] = await (0, PacketUtils_1.processPacket)(this.clientPackets, tag, values, 0);
|
|
209
216
|
if (packet.dataBatching == 0)
|
|
210
217
|
this.raw_send((0, BufferUtil_1.toPacketBuffer)(code, data));
|
|
211
218
|
else
|
|
@@ -4,10 +4,10 @@ import { PacketType } from "./PacketType";
|
|
|
4
4
|
export type PacketTypeValidator = (data: Uint8Array, index: number) => Promise<[Uint8Array, false | any]>;
|
|
5
5
|
export type PacketReceiveProcessor = (data: Uint8Array, validationResult: any, index: number) => any;
|
|
6
6
|
export type PacketSendProcessor = (ident: string, ...data: any[]) => Promise<Uint8Array>;
|
|
7
|
-
export declare function createValidator<T extends PacketType>(type: T, dataCap: number, dataMin: number, packet: Packet<T | T[]>, gzipCompression: boolean
|
|
7
|
+
export declare function createValidator<T extends PacketType>(type: T, dataCap: number, dataMin: number, packet: Packet<T | T[]>, gzipCompression: boolean): PacketTypeValidator;
|
|
8
8
|
export declare function createReceiveProcessor(type: PacketType, enumData: EnumPackage[], cap: number): PacketReceiveProcessor;
|
|
9
9
|
/** Creates a function that processes a packet type */
|
|
10
|
-
export declare function createSendProcessor(type: PacketType, gzipCompression: boolean
|
|
10
|
+
export declare function createSendProcessor(type: PacketType, gzipCompression: boolean): PacketSendProcessor;
|
|
11
11
|
export declare function createObjSendProcessor(packet: Packet<PacketType[]>): PacketSendProcessor;
|
|
12
12
|
export declare function createObjReceiveProcessor(packet: Packet<PacketType[]>): PacketReceiveProcessor;
|
|
13
13
|
export declare function createObjValidator(packet: Packet<PacketType[]>): PacketTypeValidator;
|
|
@@ -52,7 +52,7 @@ function VARINT_VERIF(cap, min) {
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
;
|
|
55
|
-
function createValidator(type, dataCap, dataMin, packet, gzipCompression
|
|
55
|
+
function createValidator(type, dataCap, dataMin, packet, gzipCompression) {
|
|
56
56
|
function genFunc() {
|
|
57
57
|
switch (type) {
|
|
58
58
|
case PacketType_1.PacketType.NONE: return (data) => data.length == 0;
|
|
@@ -149,29 +149,18 @@ function createValidator(type, dataCap, dataMin, packet, gzipCompression, rerefe
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
const fn = genFunc();
|
|
152
|
-
let parsed = null;
|
|
153
152
|
return gzipCompression
|
|
154
153
|
? async (data, index) => {
|
|
155
|
-
if (rereference && data.length == 0) {
|
|
156
|
-
if (parsed == null)
|
|
157
|
-
return [data, false];
|
|
158
|
-
return parsed;
|
|
159
|
-
}
|
|
160
154
|
try {
|
|
161
155
|
const dec = await (0, CompressionUtil_1.decompressGzip)(data);
|
|
162
|
-
return
|
|
156
|
+
return [dec, fn(dec, index)];
|
|
163
157
|
}
|
|
164
158
|
catch {
|
|
165
159
|
return [data, false];
|
|
166
160
|
}
|
|
167
161
|
}
|
|
168
162
|
: async (data, index) => {
|
|
169
|
-
|
|
170
|
-
if (parsed == null)
|
|
171
|
-
return [data, false];
|
|
172
|
-
return parsed;
|
|
173
|
-
}
|
|
174
|
-
return parsed = [data, fn(data, index)];
|
|
163
|
+
return [data, fn(data, index)];
|
|
175
164
|
};
|
|
176
165
|
}
|
|
177
166
|
function createReceiveProcessor(type, enumData, cap) {
|
|
@@ -215,7 +204,7 @@ function createReceiveProcessor(type, enumData, cap) {
|
|
|
215
204
|
}
|
|
216
205
|
}
|
|
217
206
|
/** Creates a function that processes a packet type */
|
|
218
|
-
function createSendProcessor(type, gzipCompression
|
|
207
|
+
function createSendProcessor(type, gzipCompression) {
|
|
219
208
|
function genFunc() {
|
|
220
209
|
switch (type) {
|
|
221
210
|
case PacketType_1.PacketType.NONE: return () => [];
|
|
@@ -263,34 +252,19 @@ function createSendProcessor(type, gzipCompression, rereference) {
|
|
|
263
252
|
}
|
|
264
253
|
}
|
|
265
254
|
const fn = genFunc();
|
|
266
|
-
let lastSent;
|
|
267
255
|
if (!gzipCompression) {
|
|
268
256
|
return async (_, data) => {
|
|
269
|
-
if (rereference) {
|
|
270
|
-
const jstr = JSON.stringify(data);
|
|
271
|
-
if (jstr == lastSent) {
|
|
272
|
-
return CompressionUtil_1.EMPTY_UINT8;
|
|
273
|
-
}
|
|
274
|
-
lastSent = jstr;
|
|
275
|
-
}
|
|
276
257
|
return new Uint8Array(fn(data));
|
|
277
258
|
};
|
|
278
259
|
}
|
|
279
260
|
return async (ident, data) => {
|
|
280
|
-
if (rereference) {
|
|
281
|
-
const jstr = JSON.stringify(data);
|
|
282
|
-
if (jstr == lastSent) {
|
|
283
|
-
return CompressionUtil_1.EMPTY_UINT8;
|
|
284
|
-
}
|
|
285
|
-
lastSent = jstr;
|
|
286
|
-
}
|
|
287
261
|
return (0, CompressionUtil_1.compressGzip)(new Uint8Array(fn(data)), ident);
|
|
288
262
|
};
|
|
289
263
|
}
|
|
290
264
|
function createObjSendProcessor(packet) {
|
|
291
265
|
const size = packet.type.length;
|
|
292
266
|
// TODO: Add compression and add rereferences[]
|
|
293
|
-
const processors = packet.type.map(t => createSendProcessor(t, false
|
|
267
|
+
const processors = packet.type.map(t => createSendProcessor(t, false));
|
|
294
268
|
return async (ident, data) => {
|
|
295
269
|
let result = [];
|
|
296
270
|
for (let i = 0; i < size; i++) {
|
|
@@ -321,7 +295,7 @@ function createObjReceiveProcessor(packet) {
|
|
|
321
295
|
};
|
|
322
296
|
}
|
|
323
297
|
function createObjValidator(packet) {
|
|
324
|
-
const validators = packet.type.map((t, i) => createValidator(t, packet.dataMax[i], packet.dataMin[i], packet, false
|
|
298
|
+
const validators = packet.type.map((t, i) => createValidator(t, packet.dataMax[i], packet.dataMin[i], packet, false));
|
|
325
299
|
return async (data) => {
|
|
326
300
|
let index = 0, enums = 0, computedData = [];
|
|
327
301
|
while (index < data.length) {
|
|
@@ -30,6 +30,8 @@ export declare class Packet<T extends (PacketType | readonly PacketType[])> {
|
|
|
30
30
|
processSend: (data: any[]) => Promise<Uint8Array>;
|
|
31
31
|
validate: (data: Uint8Array) => Promise<[Uint8Array, boolean]>;
|
|
32
32
|
customValidator: ((socket: SonicWSConnection, ...values: any[]) => boolean) | null;
|
|
33
|
+
lastReceived: Record<number, any>;
|
|
34
|
+
lastSent: Record<number, any>;
|
|
33
35
|
constructor(tag: string, schema: PacketSchema<T>, customValidator: ValidatorFunction, enabled: boolean, client: boolean);
|
|
34
36
|
listen(value: Uint8Array, socket: SonicWSConnection | null): Promise<[processed: any, flatten: boolean] | string>;
|
|
35
37
|
serialize(): number[];
|
|
@@ -92,6 +92,7 @@ class SonicWSConnection {
|
|
|
92
92
|
for (const tag of host.clientPackets.getTags()) {
|
|
93
93
|
this.listeners[tag] = [];
|
|
94
94
|
const pack = host.clientPackets.getPacket(tag);
|
|
95
|
+
pack.lastReceived[this.id] = undefined;
|
|
95
96
|
this.enabledPackets[tag] = pack.defaultEnabled;
|
|
96
97
|
this.asyncMap[tag] = pack.async;
|
|
97
98
|
if (pack.async)
|
|
@@ -121,6 +122,9 @@ class SonicWSConnection {
|
|
|
121
122
|
if (shouldCall)
|
|
122
123
|
callback(true);
|
|
123
124
|
}
|
|
125
|
+
for (const packet of host.clientPackets.getPackets()) {
|
|
126
|
+
delete packet.lastReceived[this.id];
|
|
127
|
+
}
|
|
124
128
|
});
|
|
125
129
|
}
|
|
126
130
|
parseData(event) {
|
|
@@ -214,8 +218,14 @@ class SonicWSConnection {
|
|
|
214
218
|
return;
|
|
215
219
|
const [tag, value] = data;
|
|
216
220
|
const packet = this.host.clientPackets.getPacket(tag);
|
|
221
|
+
if (packet.rereference && value.length == 0) {
|
|
222
|
+
if (packet.lastReceived[this.id] === undefined)
|
|
223
|
+
return this.invalidPacket("No previous value to rereference");
|
|
224
|
+
this.listenPacket(packet.lastReceived[this.id], tag);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
217
227
|
if (packet.dataBatching == 0) {
|
|
218
|
-
const res = await packet.listen(value, this);
|
|
228
|
+
const res = packet.lastReceived[this.id] = await packet.listen(value, this);
|
|
219
229
|
this.listenPacket(res, tag);
|
|
220
230
|
return;
|
|
221
231
|
}
|
|
@@ -282,7 +292,7 @@ class SonicWSConnection {
|
|
|
282
292
|
* @param values The values to send
|
|
283
293
|
*/
|
|
284
294
|
async send(tag, ...values) {
|
|
285
|
-
this.send_processed(...await (0, PacketUtils_1.processPacket)(this.host.serverPackets, tag, values));
|
|
295
|
+
this.send_processed(...await (0, PacketUtils_1.processPacket)(this.host.serverPackets, tag, values, this.id));
|
|
286
296
|
}
|
|
287
297
|
/**
|
|
288
298
|
* Broadcasts a packet to all other users connected
|
|
@@ -219,7 +219,7 @@ class SonicWSServer {
|
|
|
219
219
|
async broadcastTagged(tag, packetTag, ...values) {
|
|
220
220
|
if (!this.tagsInv.has(tag))
|
|
221
221
|
return;
|
|
222
|
-
const data = await (0, PacketUtils_1.processPacket)(this.serverPackets, packetTag, values);
|
|
222
|
+
const data = await (0, PacketUtils_1.processPacket)(this.serverPackets, packetTag, values, -1);
|
|
223
223
|
this.tagsInv.get(tag).forEach(conn => conn.send_processed(...data));
|
|
224
224
|
}
|
|
225
225
|
/**
|
|
@@ -229,7 +229,7 @@ class SonicWSServer {
|
|
|
229
229
|
* @param values The values to send
|
|
230
230
|
*/
|
|
231
231
|
async broadcastFiltered(tag, filter, ...values) {
|
|
232
|
-
const data = await (0, PacketUtils_1.processPacket)(this.serverPackets, tag, values);
|
|
232
|
+
const data = await (0, PacketUtils_1.processPacket)(this.serverPackets, tag, values, -1);
|
|
233
233
|
this.connections.filter(filter).forEach(conn => conn.send_processed(...data));
|
|
234
234
|
}
|
|
235
235
|
/**
|
|
@@ -9,7 +9,7 @@ import { EnumPackage } from "../enums/EnumType";
|
|
|
9
9
|
* @param values The values
|
|
10
10
|
* @returns The indexed code, the data, and the packet schema
|
|
11
11
|
*/
|
|
12
|
-
export declare function processPacket(packets: PacketHolder, tag: string, values: any[]): Promise<[code: number, data: Uint8Array, packet: Packet<any>]>;
|
|
12
|
+
export declare function processPacket(packets: PacketHolder, tag: string, values: any[], id: number): Promise<[code: number, data: Uint8Array, packet: Packet<any>]>;
|
|
13
13
|
/**
|
|
14
14
|
* Calls the listener for a packet with error callback
|
|
15
15
|
* @param listened The listened data
|
|
@@ -26,6 +26,7 @@ exports.UnFlattenData = UnFlattenData;
|
|
|
26
26
|
const Packets_1 = require("../../packets/Packets");
|
|
27
27
|
const PacketType_1 = require("../../packets/PacketType");
|
|
28
28
|
const EnumType_1 = require("../enums/EnumType");
|
|
29
|
+
const CompressionUtil_1 = require("./CompressionUtil");
|
|
29
30
|
/**
|
|
30
31
|
* Processes and verifies values into a sendable format
|
|
31
32
|
* @param packets Packet holder
|
|
@@ -33,7 +34,7 @@ const EnumType_1 = require("../enums/EnumType");
|
|
|
33
34
|
* @param values The values
|
|
34
35
|
* @returns The indexed code, the data, and the packet schema
|
|
35
36
|
*/
|
|
36
|
-
async function processPacket(packets, tag, values) {
|
|
37
|
+
async function processPacket(packets, tag, values, id) {
|
|
37
38
|
const code = packets.getKey(tag);
|
|
38
39
|
const packet = packets.getPacket(tag);
|
|
39
40
|
if (packet.autoFlatten) {
|
|
@@ -68,7 +69,15 @@ async function processPacket(packets, tag, values) {
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
|
-
|
|
72
|
+
const sendData = values.length > 0 ? await packet.processSend(values) : CompressionUtil_1.EMPTY_UINT8;
|
|
73
|
+
if (packet.rereference) {
|
|
74
|
+
if (id == -1)
|
|
75
|
+
throw new Error("Cannot broadcast a packet that is rereference-enabled");
|
|
76
|
+
if (packet.lastSent[id] == sendData)
|
|
77
|
+
return [code, CompressionUtil_1.EMPTY_UINT8, packet];
|
|
78
|
+
packet.lastSent[id] = sendData;
|
|
79
|
+
}
|
|
80
|
+
return [code, sendData, packet];
|
|
72
81
|
}
|
|
73
82
|
/**
|
|
74
83
|
* Calls the listener for a packet with error callback
|