sonic-ws 1.2.2 → 1.3.0
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/index.d.ts +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/ws/Connection.d.ts +14 -13
- package/dist/ws/Connection.js +33 -1
- package/dist/ws/PacketProcessor.d.ts +124 -0
- package/dist/ws/PacketProcessor.js +19 -0
- package/dist/ws/client/core/ClientCore.d.ts +9 -6
- package/dist/ws/client/core/ClientCore.js +61 -52
- package/dist/ws/packets/Packets.d.ts +1 -1
- package/dist/ws/server/SonicWSConnection.d.ts +15 -5
- package/dist/ws/server/SonicWSConnection.js +63 -45
- package/dist/ws/server/SonicWSServer.d.ts +25 -21
- package/dist/ws/server/SonicWSServer.js +655 -27
- package/dist/ws/util/packets/CompressionUtil.js +1 -1
- package/dist/ws/util/packets/HashUtil.d.ts +2 -0
- package/dist/ws/util/packets/HashUtil.js +122 -0
- package/dist/ws/util/packets/PacketHolder.d.ts +2 -2
- package/dist/ws/util/packets/PacketHolder.js +2 -0
- package/dist/ws/util/packets/PacketUtils.d.ts +4 -2
- package/dist/ws/util/packets/PacketUtils.js +57 -38
- package/dist/ws/util/packets/RateHandler.js +2 -1
- package/package.json +3 -4
package/dist/index.d.ts
CHANGED
|
@@ -2,5 +2,6 @@ export { SonicWS } from './ws/client/node/ClientNode';
|
|
|
2
2
|
export { SonicWSConnection } from './ws/server/SonicWSConnection';
|
|
3
3
|
export { SonicWSServer } from './ws/server/SonicWSServer';
|
|
4
4
|
export { PacketType } from './ws/packets/PacketType';
|
|
5
|
+
export { BasicMiddleware, ConnectionMiddleware, ServerMiddleware, BCInfo } from './ws/PacketProcessor';
|
|
5
6
|
export { CreatePacket, CreateObjPacket, CreateEnumPacket, FlattenData, UnFlattenData } from './ws/util/packets/PacketUtils';
|
|
6
7
|
export { DefineEnum, WrapEnum } from './ws/util/enums/EnumHandler';
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -18,7 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
exports.SERVER_SUFFIX_NUMS = exports.SERVER_SUFFIX = exports.VERSION = void 0;
|
|
19
19
|
const StringUtil_1 = require("./ws/util/StringUtil");
|
|
20
20
|
/** Current protocol version */
|
|
21
|
-
exports.VERSION =
|
|
21
|
+
exports.VERSION = 19;
|
|
22
22
|
/** Server data suffix */
|
|
23
23
|
exports.SERVER_SUFFIX = "SWS";
|
|
24
24
|
/** Server data suffix in array */
|
package/dist/ws/Connection.d.ts
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
init?(conn: Connection): void;
|
|
3
|
-
onReceive_pre(tag: string, data: Uint8Array): boolean | void;
|
|
4
|
-
onSend_pre(tag: string, values: any[]): boolean | void;
|
|
5
|
-
onReceive_post(tag: string, values: any[]): boolean | void;
|
|
6
|
-
onSend_post(tag: string, data: Uint8Array): boolean | void;
|
|
7
|
-
onStatusChange(status: number): void;
|
|
8
|
-
}
|
|
1
|
+
import { ConnectionMiddleware, MiddlewareHolder } from "./PacketProcessor";
|
|
9
2
|
/**
|
|
10
3
|
* Holds shared connection values. Lets helper functions work on client and server.
|
|
11
4
|
*/
|
|
12
|
-
export interface Connection {
|
|
5
|
+
export interface Connection extends MiddlewareHolder<ConnectionMiddleware> {
|
|
13
6
|
/**
|
|
14
7
|
* List of timers.
|
|
15
8
|
* For internal use only.
|
|
@@ -50,8 +43,16 @@ export interface Connection {
|
|
|
50
43
|
* Closes the connection
|
|
51
44
|
*/
|
|
52
45
|
close(code?: number, reason?: string): void;
|
|
53
|
-
/**
|
|
54
|
-
* Adds a basic middleware which can interact with packets
|
|
55
|
-
*/
|
|
56
|
-
addBasicMiddleware(middleware: BasicMiddleware): void;
|
|
57
46
|
}
|
|
47
|
+
export declare enum CloseCodes {
|
|
48
|
+
RATELIMIT = 4000,
|
|
49
|
+
SMALL = 4001,
|
|
50
|
+
INVALID_KEY = 4002,
|
|
51
|
+
INVALID_PACKET = 4003,
|
|
52
|
+
INVALID_DATA = 4004,
|
|
53
|
+
REPEATED_HANDSHAKE = 4005,
|
|
54
|
+
DISABLED_PACKET = 4006,
|
|
55
|
+
MIDDLEWARE = 4007,
|
|
56
|
+
MANUAL_SHUTDOWN = 4008
|
|
57
|
+
}
|
|
58
|
+
export declare function getClosureCause(id: number): string;
|
package/dist/ws/Connection.js
CHANGED
|
@@ -15,4 +15,36 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
;
|
|
18
|
+
exports.CloseCodes = void 0;
|
|
19
|
+
exports.getClosureCause = getClosureCause;
|
|
20
|
+
var CloseCodes;
|
|
21
|
+
(function (CloseCodes) {
|
|
22
|
+
CloseCodes[CloseCodes["RATELIMIT"] = 4000] = "RATELIMIT";
|
|
23
|
+
CloseCodes[CloseCodes["SMALL"] = 4001] = "SMALL";
|
|
24
|
+
CloseCodes[CloseCodes["INVALID_KEY"] = 4002] = "INVALID_KEY";
|
|
25
|
+
CloseCodes[CloseCodes["INVALID_PACKET"] = 4003] = "INVALID_PACKET";
|
|
26
|
+
CloseCodes[CloseCodes["INVALID_DATA"] = 4004] = "INVALID_DATA";
|
|
27
|
+
CloseCodes[CloseCodes["REPEATED_HANDSHAKE"] = 4005] = "REPEATED_HANDSHAKE";
|
|
28
|
+
CloseCodes[CloseCodes["DISABLED_PACKET"] = 4006] = "DISABLED_PACKET";
|
|
29
|
+
CloseCodes[CloseCodes["MIDDLEWARE"] = 4007] = "MIDDLEWARE";
|
|
30
|
+
CloseCodes[CloseCodes["MANUAL_SHUTDOWN"] = 4008] = "MANUAL_SHUTDOWN";
|
|
31
|
+
})(CloseCodes || (exports.CloseCodes = CloseCodes = {}));
|
|
32
|
+
function getClosureCause(id) {
|
|
33
|
+
if (id >= 4000) {
|
|
34
|
+
return CloseCodes[id] ?? 'UNKNOWN';
|
|
35
|
+
}
|
|
36
|
+
switch (id) {
|
|
37
|
+
case 1000:
|
|
38
|
+
return 'NORMAL_CLOSURE';
|
|
39
|
+
case 1001:
|
|
40
|
+
return 'GOING_AWAY';
|
|
41
|
+
case 1002:
|
|
42
|
+
return 'PROTOCOL_ERROR';
|
|
43
|
+
case 1003:
|
|
44
|
+
return 'UNSUPPORTED_DATA';
|
|
45
|
+
case 1006:
|
|
46
|
+
return 'ABNORMAL_CLOSURE';
|
|
47
|
+
default:
|
|
48
|
+
return 'UNKNOWN';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Connection } from "./Connection";
|
|
2
|
+
import { SonicWSConnection } from "./server/SonicWSConnection";
|
|
3
|
+
/**
|
|
4
|
+
* A basic middleware interface; extended by other middleware types
|
|
5
|
+
*/
|
|
6
|
+
export interface BasicMiddleware {
|
|
7
|
+
/**
|
|
8
|
+
* Called when the middleware is initialized
|
|
9
|
+
* @param conn The connection instance
|
|
10
|
+
*/
|
|
11
|
+
init?(conn: Connection): void;
|
|
12
|
+
}
|
|
13
|
+
export type FuncKeys<T> = {
|
|
14
|
+
[K in keyof T]: NonNullable<T[K]> extends (...args: any[]) => any ? K : never;
|
|
15
|
+
}[keyof T];
|
|
16
|
+
export interface MiddlewareHolder<T extends BasicMiddleware> {
|
|
17
|
+
/**
|
|
18
|
+
* Adds middleware which can interact with packets and other events
|
|
19
|
+
*/
|
|
20
|
+
addMiddleware(middleware: T): void;
|
|
21
|
+
/**
|
|
22
|
+
* Calls a middleware method on all middlewares
|
|
23
|
+
* @param method The method to call
|
|
24
|
+
* @param values The values to pass to the method
|
|
25
|
+
*/
|
|
26
|
+
callMiddleware<K extends FuncKeys<T> & keyof T>(method: K, ...values: Parameters<NonNullable<Extract<T[K], (...args: any[]) => any>>>): Promise<boolean>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A connection middleware interface, used in SonicWSConnection and ClientCore
|
|
30
|
+
*/
|
|
31
|
+
export interface ConnectionMiddleware extends BasicMiddleware {
|
|
32
|
+
/**
|
|
33
|
+
* Called before a packet is received
|
|
34
|
+
* @param tag The packet tag
|
|
35
|
+
* @param data The raw packet data
|
|
36
|
+
* @param recvSize The size of the received packet
|
|
37
|
+
* @returns `true` to cancel processing, `false` or nothing to continue
|
|
38
|
+
*/
|
|
39
|
+
onReceive_pre?(tag: string, data: Uint8Array, recvSize: number): boolean | void;
|
|
40
|
+
/**
|
|
41
|
+
* Called before a packet is sent
|
|
42
|
+
* @param tag The packet tag
|
|
43
|
+
* @param values The packet values
|
|
44
|
+
* @param processedAt The time the packet was processed at; Date.now()
|
|
45
|
+
* @param perfTime The performance time the packet was processed at; performance.now()
|
|
46
|
+
* @returns `true` to cancel processing, `false` or nothing to continue
|
|
47
|
+
*/
|
|
48
|
+
onSend_pre?(tag: string, values: any[], processedAt: number, perfTime: number): boolean | void;
|
|
49
|
+
/**
|
|
50
|
+
* Called after a packet is received and listeners have been processed
|
|
51
|
+
* @param tag The packet tag
|
|
52
|
+
* @param values The packet values
|
|
53
|
+
*/
|
|
54
|
+
onReceive_post?(tag: string, values: any[]): void;
|
|
55
|
+
/**
|
|
56
|
+
* Called after a packet is sent
|
|
57
|
+
* @param tag The packet tag
|
|
58
|
+
* @param data The raw packet data
|
|
59
|
+
* @param sendSize The size of the sent packet
|
|
60
|
+
*/
|
|
61
|
+
onSend_post?(tag: string, data: Uint8Array, sendSize: number): void;
|
|
62
|
+
/**
|
|
63
|
+
* Called when the connection status changes
|
|
64
|
+
* @param status The new connection status
|
|
65
|
+
*/
|
|
66
|
+
onStatusChange?(status: number): void;
|
|
67
|
+
/**
|
|
68
|
+
* Called when the name of the connection changes; server-side only
|
|
69
|
+
* @param name The new name of the connection
|
|
70
|
+
* @returns `true` to cancel setting the name, `false` or nothing to continue
|
|
71
|
+
*/
|
|
72
|
+
onNameChange?(name: string): boolean | void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Different types of broadcast information
|
|
76
|
+
*/
|
|
77
|
+
export type BCInfo = {
|
|
78
|
+
recipients: SonicWSConnection[];
|
|
79
|
+
} & ({
|
|
80
|
+
type: "all";
|
|
81
|
+
} | {
|
|
82
|
+
type: "tagged";
|
|
83
|
+
tag: string;
|
|
84
|
+
} | {
|
|
85
|
+
type: "filter";
|
|
86
|
+
filter: (connection: SonicWSConnection) => boolean;
|
|
87
|
+
});
|
|
88
|
+
/**
|
|
89
|
+
* Server-sided middleware, used in SonicWSServer for a more broad range of events
|
|
90
|
+
* This does not include information for packets sent and received, as that is handled by ConnectionMiddleware
|
|
91
|
+
*/
|
|
92
|
+
export interface ServerMiddleware extends BasicMiddleware {
|
|
93
|
+
/**
|
|
94
|
+
* Called when a client connects
|
|
95
|
+
* @param connection The connection instance
|
|
96
|
+
*/
|
|
97
|
+
onClientConnect?(connection: SonicWSConnection): boolean | void;
|
|
98
|
+
/**
|
|
99
|
+
* Called when a client disconnects
|
|
100
|
+
* @param connection The connection instance
|
|
101
|
+
* @param code The disconnect code
|
|
102
|
+
* @param reason The disconnect reason
|
|
103
|
+
*/
|
|
104
|
+
onClientDisconnect?(connection: SonicWSConnection, code: number, reason?: Buffer<ArrayBufferLike>): void;
|
|
105
|
+
/**
|
|
106
|
+
* Called when a packet is broadcasted
|
|
107
|
+
* @param tag The packet tag
|
|
108
|
+
* @param info The broadcast information
|
|
109
|
+
* @param values The packet values
|
|
110
|
+
*/
|
|
111
|
+
onPacketBroadcast_pre?(tag: string, info: BCInfo, ...values: any[]): boolean | void;
|
|
112
|
+
/**
|
|
113
|
+
* Called when a packet is processed after being broadcasted
|
|
114
|
+
* @param tag The packet tag
|
|
115
|
+
* @param info The broadcast information
|
|
116
|
+
* @param values The packet values
|
|
117
|
+
*/
|
|
118
|
+
onPacketBroadcast_post?(tag: string, info: BCInfo, data: Uint8Array, sendSize: number): boolean | void;
|
|
119
|
+
}
|
|
120
|
+
export type ServerPQ = [tag: string, value: Uint8Array];
|
|
121
|
+
export type ClientPQ = Uint8Array;
|
|
122
|
+
export type PacketQueue<T> = (T | null)[];
|
|
123
|
+
export type AsyncPQ<T> = [boolean, PacketQueue<T>];
|
|
124
|
+
export type SendQueue = [boolean, [Function, string, any[]][], string?];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026 Lily (liwybloc)
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
;
|
|
19
|
+
;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PacketHolder } from '../../util/packets/PacketHolder';
|
|
2
|
-
import {
|
|
2
|
+
import { Connection } from '../../Connection';
|
|
3
|
+
import { AsyncPQ, ConnectionMiddleware, ClientPQ, PacketQueue, FuncKeys } from '../../PacketProcessor';
|
|
3
4
|
export declare abstract class SonicWSCore implements Connection {
|
|
4
5
|
/** Raw 'ws' library connection / webjs WebSocket class */
|
|
5
6
|
socket: WebSocket;
|
|
@@ -24,7 +25,6 @@ export declare abstract class SonicWSCore implements Connection {
|
|
|
24
25
|
_timers: Record<number, [number, (closed: boolean) => void, boolean]>;
|
|
25
26
|
private asyncData;
|
|
26
27
|
private asyncMap;
|
|
27
|
-
private _state;
|
|
28
28
|
constructor(ws: WebSocket, bufferHandler: (val: MessageEvent) => Promise<Uint8Array>);
|
|
29
29
|
private reading;
|
|
30
30
|
private readQueue;
|
|
@@ -32,12 +32,14 @@ export declare abstract class SonicWSCore implements Connection {
|
|
|
32
32
|
private invalidPacket;
|
|
33
33
|
private listenLock;
|
|
34
34
|
private packetQueue;
|
|
35
|
-
listenPacket(data: string | [any[], boolean], code: number): Promise<void>;
|
|
35
|
+
listenPacket(data: string | [any[], boolean], code: number, packetQueue: PacketQueue<ClientPQ>, isAsync: boolean, asyncData: AsyncPQ<ClientPQ>): Promise<void>;
|
|
36
36
|
private isAsync;
|
|
37
37
|
private enqueuePacket;
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
private triggerNextPacket;
|
|
39
|
+
private middlewares;
|
|
40
|
+
addMiddleware(middleware: ConnectionMiddleware): void;
|
|
41
|
+
callMiddleware<K extends FuncKeys<ConnectionMiddleware> & keyof ConnectionMiddleware>(method: K, ...values: Parameters<NonNullable<Extract<ConnectionMiddleware[K], (...args: any[]) => any>>>): Promise<boolean>;
|
|
42
|
+
private dataHandler;
|
|
41
43
|
private messageHandler;
|
|
42
44
|
protected listen(key: string, listener: (data: any[]) => void): void;
|
|
43
45
|
/**
|
|
@@ -50,6 +52,7 @@ export declare abstract class SonicWSCore implements Connection {
|
|
|
50
52
|
* @param listener Callback for when data is received
|
|
51
53
|
*/
|
|
52
54
|
raw_onsend(listener: (data: Uint8Array) => void): void;
|
|
55
|
+
private sendQueue;
|
|
53
56
|
/**
|
|
54
57
|
* Sends a packet to the server
|
|
55
58
|
* @param tag The tag of the packet
|
|
@@ -38,7 +38,6 @@ class SonicWSCore {
|
|
|
38
38
|
_timers = {};
|
|
39
39
|
asyncData = {};
|
|
40
40
|
asyncMap = {};
|
|
41
|
-
_state = WebSocket.OPEN;
|
|
42
41
|
constructor(ws, bufferHandler) {
|
|
43
42
|
this.socket = ws;
|
|
44
43
|
this.listeners = {
|
|
@@ -62,6 +61,12 @@ class SonicWSCore {
|
|
|
62
61
|
if (shouldCall)
|
|
63
62
|
callback(true);
|
|
64
63
|
}
|
|
64
|
+
for (const packet of this.clientPackets.getPackets()) {
|
|
65
|
+
delete packet.lastSent[0];
|
|
66
|
+
}
|
|
67
|
+
for (const packet of this.serverPackets.getPackets()) {
|
|
68
|
+
delete packet.lastReceived[0];
|
|
69
|
+
}
|
|
65
70
|
});
|
|
66
71
|
this.bufferHandler = bufferHandler;
|
|
67
72
|
}
|
|
@@ -118,54 +123,34 @@ class SonicWSCore {
|
|
|
118
123
|
}
|
|
119
124
|
listenLock = false;
|
|
120
125
|
packetQueue = [];
|
|
121
|
-
async listenPacket(data, code) {
|
|
122
|
-
|
|
123
|
-
return;
|
|
126
|
+
async listenPacket(data, code, packetQueue, isAsync, asyncData) {
|
|
127
|
+
const tag = this.serverPackets.getTag(code);
|
|
124
128
|
const listeners = this.listeners.event[code];
|
|
125
129
|
if (!listeners)
|
|
126
|
-
return console.warn("Warn: No listener for packet " +
|
|
127
|
-
this.enqueuePacket(data,
|
|
130
|
+
return console.warn("Warn: No listener for packet " + tag);
|
|
131
|
+
await this.enqueuePacket(data, listeners, packetQueue, isAsync, asyncData);
|
|
132
|
+
await this.callMiddleware('onReceive_post', tag, typeof data == 'string' ? [data] : data[0]);
|
|
128
133
|
}
|
|
129
134
|
isAsync(code) {
|
|
130
135
|
return this.asyncMap[code];
|
|
131
136
|
}
|
|
132
|
-
async enqueuePacket(data,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (isAsync) {
|
|
138
|
-
asyncData = this.asyncData[code];
|
|
139
|
-
locked = asyncData[0];
|
|
140
|
-
packetQueue = asyncData[1];
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
locked = this.listenLock;
|
|
144
|
-
packetQueue = this.packetQueue;
|
|
145
|
-
}
|
|
146
|
-
if (locked) {
|
|
147
|
-
packetQueue.push(data);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
if (isAsync)
|
|
151
|
-
asyncData[0] = true;
|
|
152
|
-
else
|
|
153
|
-
this.listenLock = true;
|
|
154
|
-
let currentData = data;
|
|
155
|
-
while (true) {
|
|
156
|
-
await (0, PacketUtils_1.listenPacket)(currentData, listeners, this.invalidPacket);
|
|
157
|
-
if (packetQueue.length === 0)
|
|
158
|
-
break;
|
|
159
|
-
currentData = packetQueue.shift();
|
|
160
|
-
}
|
|
137
|
+
async enqueuePacket(data, listeners, packetQueue, isAsync, asyncData) {
|
|
138
|
+
await (0, PacketUtils_1.listenPacket)(data, listeners, this.invalidPacket);
|
|
139
|
+
await this.triggerNextPacket(packetQueue, isAsync, asyncData);
|
|
140
|
+
}
|
|
141
|
+
async triggerNextPacket(packetQueue, isAsync, asyncData) {
|
|
161
142
|
if (isAsync)
|
|
162
143
|
asyncData[0] = false;
|
|
163
144
|
else
|
|
164
145
|
this.listenLock = false;
|
|
146
|
+
if (packetQueue.length > 0) {
|
|
147
|
+
this.dataHandler(packetQueue.shift());
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
165
150
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
this.
|
|
151
|
+
middlewares = [];
|
|
152
|
+
addMiddleware(middleware) {
|
|
153
|
+
this.middlewares.push(middleware);
|
|
169
154
|
const m = middleware;
|
|
170
155
|
try {
|
|
171
156
|
if (typeof m.init === 'function')
|
|
@@ -177,7 +162,7 @@ class SonicWSCore {
|
|
|
177
162
|
}
|
|
178
163
|
async callMiddleware(method, ...values) {
|
|
179
164
|
let cancelled = false;
|
|
180
|
-
for (const middleware of this.
|
|
165
|
+
for (const middleware of this.middlewares) {
|
|
181
166
|
const fn = middleware[method];
|
|
182
167
|
if (!fn)
|
|
183
168
|
continue;
|
|
@@ -192,31 +177,55 @@ class SonicWSCore {
|
|
|
192
177
|
}
|
|
193
178
|
return cancelled;
|
|
194
179
|
}
|
|
195
|
-
async
|
|
196
|
-
const data = await this.bufferHandler(event);
|
|
197
|
-
this.listeners.message.forEach(listener => listener(data));
|
|
198
|
-
if (data.length < 1)
|
|
199
|
-
return;
|
|
180
|
+
async dataHandler(data) {
|
|
200
181
|
const key = data[0];
|
|
201
182
|
const value = data.slice(1);
|
|
183
|
+
const isAsync = this.isAsync(key);
|
|
184
|
+
let locked;
|
|
185
|
+
let packetQueue;
|
|
186
|
+
let asyncData;
|
|
187
|
+
if (isAsync) {
|
|
188
|
+
asyncData = this.asyncData[key];
|
|
189
|
+
locked = asyncData[0];
|
|
190
|
+
packetQueue = asyncData[1];
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
locked = this.listenLock;
|
|
194
|
+
packetQueue = this.packetQueue;
|
|
195
|
+
}
|
|
196
|
+
if (locked) {
|
|
197
|
+
packetQueue.push(data);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (isAsync)
|
|
201
|
+
asyncData[0] = true;
|
|
202
|
+
else
|
|
203
|
+
this.listenLock = true;
|
|
202
204
|
const packet = this.serverPackets.getPacket(this.serverPackets.getTag(key));
|
|
203
|
-
if (await this.callMiddleware('onReceive_pre', packet.tag, data))
|
|
205
|
+
if (await this.callMiddleware('onReceive_pre', packet.tag, data, data.length))
|
|
204
206
|
return;
|
|
205
207
|
if (packet.rereference && value.length == 0) {
|
|
206
208
|
if (packet.lastReceived[0] === undefined)
|
|
207
209
|
return this.invalidPacket("No previous value to rereference");
|
|
208
|
-
this.listenPacket(packet.lastReceived[0], key);
|
|
210
|
+
this.listenPacket(packet.lastReceived[0], key, packetQueue, isAsync, asyncData);
|
|
209
211
|
return;
|
|
210
212
|
}
|
|
211
213
|
if (packet.dataBatching == 0) {
|
|
212
214
|
const res = packet.lastReceived[0] = await packet.listen(value, null);
|
|
213
|
-
this.listenPacket(res, key);
|
|
215
|
+
this.listenPacket(res, key, packetQueue, isAsync, asyncData);
|
|
214
216
|
return;
|
|
215
217
|
}
|
|
216
218
|
const batchData = await BatchHelper_1.BatchHelper.unravelBatch(packet, value, null);
|
|
217
219
|
if (typeof batchData == 'string')
|
|
218
220
|
return this.invalidPacket(batchData);
|
|
219
|
-
batchData.forEach(data => this.listenPacket(data, key));
|
|
221
|
+
batchData.forEach(data => this.listenPacket(data, key, packetQueue, isAsync, asyncData));
|
|
222
|
+
}
|
|
223
|
+
async messageHandler(event) {
|
|
224
|
+
const data = await this.bufferHandler(event);
|
|
225
|
+
this.listeners.message.forEach(listener => listener(data));
|
|
226
|
+
if (data.length < 1)
|
|
227
|
+
return;
|
|
228
|
+
await this.dataHandler(data);
|
|
220
229
|
}
|
|
221
230
|
listen(key, listener) {
|
|
222
231
|
const skey = this.serverPackets.getKey(key);
|
|
@@ -242,21 +251,21 @@ class SonicWSCore {
|
|
|
242
251
|
raw_onsend(listener) {
|
|
243
252
|
this.listeners.send.push(listener);
|
|
244
253
|
}
|
|
254
|
+
sendQueue = [false, [], undefined];
|
|
245
255
|
/**
|
|
246
256
|
* Sends a packet to the server
|
|
247
257
|
* @param tag The tag of the packet
|
|
248
258
|
* @param values The values to send
|
|
249
259
|
*/
|
|
250
260
|
async send(tag, ...values) {
|
|
251
|
-
if (await this.callMiddleware('onSend_pre', tag, values))
|
|
252
|
-
return;
|
|
253
|
-
const [code, data, packet] = await (0, PacketUtils_1.processPacket)(this.clientPackets, tag, values, 0);
|
|
254
|
-
if (await this.callMiddleware('onSend_post', tag, data))
|
|
261
|
+
if (await this.callMiddleware('onSend_pre', tag, values, Date.now(), performance.now()))
|
|
255
262
|
return;
|
|
263
|
+
const [code, data, packet] = await (0, PacketUtils_1.processPacket)(this.clientPackets, tag, values, this.sendQueue, 0);
|
|
256
264
|
if (packet.dataBatching == 0)
|
|
257
265
|
this.raw_send((0, BufferUtil_1.toPacketBuffer)(code, data));
|
|
258
266
|
else
|
|
259
267
|
this.batcher.batchPacket(code, data);
|
|
268
|
+
await this.callMiddleware('onSend_post', tag, data, data.length);
|
|
260
269
|
}
|
|
261
270
|
/**
|
|
262
271
|
* Listens for when the client connects
|
|
@@ -31,7 +31,7 @@ export declare class Packet<T extends (PacketType | readonly PacketType[])> {
|
|
|
31
31
|
validate: (data: Uint8Array) => Promise<[Uint8Array, boolean]>;
|
|
32
32
|
customValidator: ((socket: SonicWSConnection, ...values: any[]) => boolean) | null;
|
|
33
33
|
lastReceived: Record<number, any>;
|
|
34
|
-
lastSent: Record<number,
|
|
34
|
+
lastSent: Record<number, number | bigint>;
|
|
35
35
|
constructor(tag: string, schema: PacketSchema<T>, customValidator: ValidatorFunction, enabled: boolean, client: boolean);
|
|
36
36
|
listen(value: Uint8Array, socket: SonicWSConnection | null): Promise<[processed: any, flatten: boolean] | string>;
|
|
37
37
|
serialize(): number[];
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import * as WS from 'ws';
|
|
2
2
|
import { SonicWSServer } from './SonicWSServer';
|
|
3
3
|
import { Packet } from '../packets/Packets';
|
|
4
|
-
import {
|
|
4
|
+
import { Connection } from '../Connection';
|
|
5
|
+
import { ConnectionMiddleware, FuncKeys } from '../PacketProcessor';
|
|
5
6
|
export declare class SonicWSConnection implements Connection {
|
|
6
7
|
/** Raw 'ws' library socket */
|
|
7
8
|
socket: WS.WebSocket;
|
|
8
9
|
private host;
|
|
9
10
|
private listeners;
|
|
10
11
|
private print;
|
|
12
|
+
private name;
|
|
11
13
|
private handshakePacket;
|
|
12
14
|
private handshakeLambda;
|
|
13
15
|
private messageLambda;
|
|
@@ -23,7 +25,6 @@ export declare class SonicWSConnection implements Connection {
|
|
|
23
25
|
private asyncMap;
|
|
24
26
|
private asyncData;
|
|
25
27
|
private closed;
|
|
26
|
-
private _state;
|
|
27
28
|
constructor(socket: WS.WebSocket, host: SonicWSServer, id: number, handshakePacket: string | null, clientRateLimit: number, serverRateLimit: number);
|
|
28
29
|
private parseData;
|
|
29
30
|
private handshakeHandler;
|
|
@@ -33,9 +34,9 @@ export declare class SonicWSConnection implements Connection {
|
|
|
33
34
|
private packetQueue;
|
|
34
35
|
private listenPacket;
|
|
35
36
|
private messageHandler;
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
private middlewares;
|
|
38
|
+
addMiddleware(middleware: ConnectionMiddleware): void;
|
|
39
|
+
callMiddleware<K extends FuncKeys<ConnectionMiddleware> & keyof ConnectionMiddleware>(method: K, ...values: Parameters<NonNullable<Extract<ConnectionMiddleware[K], (...args: any[]) => any>>>): Promise<boolean>;
|
|
39
40
|
/**
|
|
40
41
|
* Enables a packet for the client.
|
|
41
42
|
* @param tag The tag of the packet
|
|
@@ -66,6 +67,7 @@ export declare class SonicWSConnection implements Connection {
|
|
|
66
67
|
* For internal use.
|
|
67
68
|
*/
|
|
68
69
|
send_processed(code: number, data: Uint8Array, packet: Packet<any>): void;
|
|
70
|
+
private sendQueue;
|
|
69
71
|
/**
|
|
70
72
|
* Sends a packet with the tag and values
|
|
71
73
|
* @param tag The tag to send
|
|
@@ -100,4 +102,12 @@ export declare class SonicWSConnection implements Connection {
|
|
|
100
102
|
* @param replace If it should replace a previous tag; defaults to true. If using false, you can add multiple tags.
|
|
101
103
|
*/
|
|
102
104
|
tag(tag: string, replace?: boolean): void;
|
|
105
|
+
/**
|
|
106
|
+
* Sets the name of this connection for the debug menu; good for setting e.g. usernames on games
|
|
107
|
+
*/
|
|
108
|
+
setName(name: string): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* @returns Name of the socket, defaults to Socket [ID] unless set with setName()
|
|
111
|
+
*/
|
|
112
|
+
getName(): string;
|
|
103
113
|
}
|