sonic-ws 1.0.0-beta.9 → 1.0.0-rc.0-patch
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 +4 -4
- package/dist/ws/client/core/ClientCore.d.ts +5 -1
- package/dist/ws/client/core/ClientCore.js +43 -10
- package/dist/ws/enums/EnumHandler.d.ts +5 -5
- package/dist/ws/enums/EnumHandler.js +1 -1
- package/dist/ws/enums/EnumType.d.ts +3 -8
- package/dist/ws/enums/EnumType.js +30 -11
- package/dist/ws/packets/PacketListener.d.ts +1 -1
- package/dist/ws/packets/PacketListener.js +2 -12
- package/dist/ws/packets/PacketProcessors.js +12 -9
- package/dist/ws/packets/PacketType.d.ts +2 -1
- package/dist/ws/packets/PacketType.js +3 -2
- package/dist/ws/packets/Packets.d.ts +16 -11
- package/dist/ws/packets/Packets.js +65 -32
- package/dist/ws/server/SonicWSConnection.d.ts +67 -6
- package/dist/ws/server/SonicWSConnection.js +204 -41
- package/dist/ws/server/SonicWSServer.d.ts +80 -1
- package/dist/ws/server/SonicWSServer.js +91 -6
- package/dist/ws/util/CodePointUtil.js +12 -11
- package/dist/ws/util/PacketHolder.d.ts +4 -1
- package/dist/ws/util/PacketHolder.js +11 -6
- package/dist/ws/util/PacketUtils.d.ts +59 -21
- package/dist/ws/util/PacketUtils.js +68 -41
- package/package.json +1 -1
|
@@ -5,23 +5,84 @@ export declare class SonicWSConnection {
|
|
|
5
5
|
private host;
|
|
6
6
|
private listeners;
|
|
7
7
|
private print;
|
|
8
|
-
|
|
8
|
+
private rateLimitInterval;
|
|
9
|
+
private rateLimit;
|
|
10
|
+
private received;
|
|
11
|
+
private timers;
|
|
12
|
+
private handshakePacket;
|
|
13
|
+
private handshakeLambda;
|
|
14
|
+
private messageLambda;
|
|
15
|
+
private handshakedMessageLambda;
|
|
16
|
+
/** If the packet handshake has been completed; `wss.requireHandshake(packet)` */
|
|
17
|
+
handshakeComplete: boolean;
|
|
18
|
+
/** The index of the connection. Alternatively, check `this.code` for a low bandwidth character. */
|
|
9
19
|
id: number;
|
|
10
20
|
/** The indexed character of the connection. Smaller data packet in strings. */
|
|
11
21
|
code: string;
|
|
12
|
-
constructor(socket: WS.WebSocket, host: SonicWSServer, id: number);
|
|
22
|
+
constructor(socket: WS.WebSocket, host: SonicWSServer, id: number, handshakePacket: string | null);
|
|
23
|
+
private parseData;
|
|
24
|
+
private handshakeHandler;
|
|
25
|
+
private messageHandler;
|
|
13
26
|
private hideNewLines;
|
|
14
|
-
|
|
27
|
+
/** Sends raw data to the user; will likely fail validity checks if used externally */
|
|
15
28
|
raw_send(data: string): void;
|
|
16
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Checks if the connection is closed
|
|
31
|
+
* @returns If it's closed or not
|
|
32
|
+
*/
|
|
33
|
+
isClosed(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Sets the rate limit of the client
|
|
36
|
+
* @param limit How many packets can be sent every second, 0 for no limit
|
|
37
|
+
*/
|
|
38
|
+
setRateLimit(limit: number): void;
|
|
39
|
+
/**
|
|
40
|
+
* Listens for when the connection closes
|
|
41
|
+
* @param listener Called when it closes
|
|
42
|
+
*/
|
|
43
|
+
on_close(listener: (code: number, reason: Buffer) => void): void;
|
|
17
44
|
/**
|
|
18
45
|
* Listens for a packet
|
|
19
46
|
* @param tag The tag of the key to listen for
|
|
20
47
|
* @param listener A function to listen for it
|
|
21
48
|
*/
|
|
22
49
|
on(tag: string, listener: (...values: any) => void): void;
|
|
50
|
+
/**
|
|
51
|
+
* Sends a packet with the tag and values
|
|
52
|
+
* @param tag The tag to send
|
|
53
|
+
* @param values The values to send
|
|
54
|
+
*/
|
|
23
55
|
send(tag: string, ...values: any[]): void;
|
|
24
|
-
/**
|
|
25
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Broadcasts a packet to all other users connected
|
|
58
|
+
* @param tag The tag to send
|
|
59
|
+
* @param values The values to send
|
|
60
|
+
*/
|
|
61
|
+
broadcastFiltered(tag: string, filter: (socket: SonicWSConnection) => boolean, ...values: any[]): void;
|
|
62
|
+
/**
|
|
63
|
+
* Broadcasts a packet to all other users connected
|
|
64
|
+
* @param tag The tag to send
|
|
65
|
+
* @param values The values to send
|
|
66
|
+
*/
|
|
26
67
|
broadcast(tag: string, ...values: any[]): void;
|
|
68
|
+
/**
|
|
69
|
+
* Toggles printing all sent and received messages
|
|
70
|
+
*/
|
|
71
|
+
togglePrint(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Closes the socket
|
|
74
|
+
*/
|
|
75
|
+
close(code?: number): void;
|
|
76
|
+
/**
|
|
77
|
+
* Sets a timeout that will automatically end when the socket closes
|
|
78
|
+
* @param call The function to call
|
|
79
|
+
* @param time The time between now and the call (ms)
|
|
80
|
+
*/
|
|
81
|
+
setTimeout(call: () => void, time: number): number;
|
|
82
|
+
/**
|
|
83
|
+
* Sets an interval that will automatically end when the socket closes
|
|
84
|
+
* @param call The function to call
|
|
85
|
+
* @param time The time between calls (ms)
|
|
86
|
+
*/
|
|
87
|
+
setInterval(call: () => void, time: number): number;
|
|
27
88
|
}
|
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
36
|
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
37
|
if (ar || !(i in from)) {
|
|
@@ -10,62 +43,140 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
10
43
|
};
|
|
11
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
45
|
exports.SonicWSConnection = void 0;
|
|
46
|
+
var WS = __importStar(require("ws"));
|
|
13
47
|
var PacketListener_1 = require("../packets/PacketListener");
|
|
14
48
|
var CodePointUtil_1 = require("../util/CodePointUtil");
|
|
15
49
|
var PacketUtils_1 = require("../util/PacketUtils");
|
|
16
50
|
var SonicWSConnection = /** @class */ (function () {
|
|
17
|
-
function SonicWSConnection(socket, host, id) {
|
|
51
|
+
function SonicWSConnection(socket, host, id, handshakePacket) {
|
|
18
52
|
var _this = this;
|
|
19
53
|
this.print = false;
|
|
54
|
+
this.rateLimit = 50;
|
|
55
|
+
this.received = 0;
|
|
56
|
+
this.timers = [];
|
|
57
|
+
this.messageLambda = function (data) { return _this.messageHandler(_this.parseData(data)); };
|
|
58
|
+
this.handshakedMessageLambda = function (data) {
|
|
59
|
+
var parsed = _this.parseData(data);
|
|
60
|
+
if (parsed == null)
|
|
61
|
+
return;
|
|
62
|
+
if (parsed[0] == _this.handshakePacket)
|
|
63
|
+
return _this.socket.close(4005);
|
|
64
|
+
_this.messageHandler(parsed);
|
|
65
|
+
};
|
|
66
|
+
/** If the packet handshake has been completed; `wss.requireHandshake(packet)` */
|
|
67
|
+
this.handshakeComplete = false;
|
|
20
68
|
this.socket = socket;
|
|
21
69
|
this.host = host;
|
|
22
70
|
this.id = id;
|
|
23
71
|
this.code = String.fromCharCode(id);
|
|
72
|
+
this.handshakePacket = handshakePacket;
|
|
24
73
|
this.listeners = {};
|
|
25
|
-
for (var _i = 0, _a = Object.values(host.clientPackets.
|
|
74
|
+
for (var _i = 0, _a = Object.values(host.clientPackets.getTags()); _i < _a.length; _i++) {
|
|
26
75
|
var key = _a[_i];
|
|
27
|
-
this.listeners[
|
|
76
|
+
this.listeners[key] = [];
|
|
28
77
|
}
|
|
29
|
-
this.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!_this.host.clientPackets.has(key)) {
|
|
41
|
-
_this.socket.close(4002);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
for (var _i = 0, _a = _this.listeners[key]; _i < _a.length; _i++) {
|
|
45
|
-
var listener = _a[_i];
|
|
46
|
-
var valid = listener.listen(value);
|
|
47
|
-
// if invalid then ignore it
|
|
48
|
-
if (!valid) {
|
|
49
|
-
socket.close(4003);
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
;
|
|
78
|
+
if (this.handshakePacket == null) {
|
|
79
|
+
this.socket.addEventListener('message', this.messageLambda);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.handshakeLambda = function (data) { return _this.handshakeHandler(data); };
|
|
83
|
+
this.socket.addEventListener('message', this.handshakeLambda);
|
|
84
|
+
}
|
|
85
|
+
this.socket.on('close', function () {
|
|
86
|
+
if (_this.rateLimit != 0)
|
|
87
|
+
clearInterval(_this.rateLimitInterval);
|
|
88
|
+
_this.timers.forEach(clearTimeout);
|
|
54
89
|
});
|
|
90
|
+
if (this.rateLimit != 0)
|
|
91
|
+
this.rateLimitInterval = setInterval(function () { return _this.received = 0; }, 1000);
|
|
55
92
|
}
|
|
93
|
+
SonicWSConnection.prototype.parseData = function (data) {
|
|
94
|
+
if (this.rateLimit != 0 && ++this.received > this.rateLimit) {
|
|
95
|
+
this.socket.close(4000);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
var message = data.data.toString();
|
|
99
|
+
if (this.print)
|
|
100
|
+
console.log("\u001B[31m\u2B07 \u001B[38;5;245m(".concat(this.id, ",").concat((0, CodePointUtil_1.getStringBytes)(message), ")\u001B[0m ").concat(this.hideNewLines(message)));
|
|
101
|
+
if (message.length < 1) {
|
|
102
|
+
this.socket.close(4001);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
var key = message[0];
|
|
106
|
+
var value = message.substring(1);
|
|
107
|
+
// not a key, bye bye
|
|
108
|
+
if (!this.host.clientPackets.has(key)) {
|
|
109
|
+
this.socket.close(4002);
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
return [this.host.clientPackets.getTag(key), value];
|
|
113
|
+
};
|
|
114
|
+
SonicWSConnection.prototype.handshakeHandler = function (data) {
|
|
115
|
+
var parsed = this.parseData(data);
|
|
116
|
+
if (parsed == null)
|
|
117
|
+
return;
|
|
118
|
+
if (parsed[0] != this.handshakePacket) {
|
|
119
|
+
this.socket.close(4004);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.messageHandler(parsed);
|
|
123
|
+
this.socket.removeEventListener('message', this.handshakeLambda);
|
|
124
|
+
this.socket.addEventListener('message', this.handshakedMessageLambda);
|
|
125
|
+
this.handshakeComplete = true;
|
|
126
|
+
};
|
|
127
|
+
SonicWSConnection.prototype.messageHandler = function (data) {
|
|
128
|
+
if (data == null)
|
|
129
|
+
return;
|
|
130
|
+
var tag = data[0], value = data[1];
|
|
131
|
+
var listened = this.host.clientPackets.getPacket(tag).listen(value);
|
|
132
|
+
// if invalid then ignore it
|
|
133
|
+
if (listened == null) {
|
|
134
|
+
this.socket.close(4003);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
var processed = listened[0], isArray = listened[1];
|
|
138
|
+
for (var _i = 0, _a = this.listeners[tag]; _i < _a.length; _i++) {
|
|
139
|
+
var listener = _a[_i];
|
|
140
|
+
listener.listen(processed, isArray);
|
|
141
|
+
}
|
|
142
|
+
;
|
|
143
|
+
};
|
|
56
144
|
SonicWSConnection.prototype.hideNewLines = function (str) {
|
|
57
145
|
return str.split("\n").join("☺");
|
|
58
146
|
};
|
|
59
|
-
|
|
60
|
-
this.socket.on('close', listener);
|
|
61
|
-
};
|
|
147
|
+
/** Sends raw data to the user; will likely fail validity checks if used externally */
|
|
62
148
|
SonicWSConnection.prototype.raw_send = function (data) {
|
|
149
|
+
if (this.isClosed())
|
|
150
|
+
throw new Error("Connection is already closed!");
|
|
63
151
|
if (this.print)
|
|
64
152
|
console.log("\u001B[32m\u2B06 \u001B[38;5;245m(".concat(this.id, ",").concat((0, CodePointUtil_1.getStringBytes)(data), ")\u001B[0m ").concat(this.hideNewLines(data)));
|
|
65
153
|
this.socket.send(data);
|
|
66
154
|
};
|
|
67
|
-
|
|
68
|
-
|
|
155
|
+
/**
|
|
156
|
+
* Checks if the connection is closed
|
|
157
|
+
* @returns If it's closed or not
|
|
158
|
+
*/
|
|
159
|
+
SonicWSConnection.prototype.isClosed = function () {
|
|
160
|
+
return this.socket.readyState == WS.CLOSED;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Sets the rate limit of the client
|
|
164
|
+
* @param limit How many packets can be sent every second, 0 for no limit
|
|
165
|
+
*/
|
|
166
|
+
SonicWSConnection.prototype.setRateLimit = function (limit) {
|
|
167
|
+
// so that i can store limits in 1 packet
|
|
168
|
+
if (limit > CodePointUtil_1.MAX_C) {
|
|
169
|
+
limit = 0;
|
|
170
|
+
console.warn("A rate limit above ".concat(CodePointUtil_1.MAX_C, " is considered infinite."));
|
|
171
|
+
}
|
|
172
|
+
this.rateLimit = limit;
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Listens for when the connection closes
|
|
176
|
+
* @param listener Called when it closes
|
|
177
|
+
*/
|
|
178
|
+
SonicWSConnection.prototype.on_close = function (listener) {
|
|
179
|
+
this.socket.on('close', listener);
|
|
69
180
|
};
|
|
70
181
|
/**
|
|
71
182
|
* Listens for a packet
|
|
@@ -77,10 +188,15 @@ var SonicWSConnection = /** @class */ (function () {
|
|
|
77
188
|
if (code == null)
|
|
78
189
|
throw new Error("Tag \"".concat(tag, "\" has not been created!"));
|
|
79
190
|
var packet = this.host.clientPackets.getPacket(tag);
|
|
80
|
-
if (!this.listeners[
|
|
81
|
-
this.listeners[
|
|
82
|
-
this.listeners[
|
|
191
|
+
if (!this.listeners[tag])
|
|
192
|
+
this.listeners[tag] = [];
|
|
193
|
+
this.listeners[tag].push(new PacketListener_1.PacketListener(packet, listener));
|
|
83
194
|
};
|
|
195
|
+
/**
|
|
196
|
+
* Sends a packet with the tag and values
|
|
197
|
+
* @param tag The tag to send
|
|
198
|
+
* @param values The values to send
|
|
199
|
+
*/
|
|
84
200
|
SonicWSConnection.prototype.send = function (tag) {
|
|
85
201
|
var _this = this;
|
|
86
202
|
var values = [];
|
|
@@ -89,17 +205,64 @@ var SonicWSConnection = /** @class */ (function () {
|
|
|
89
205
|
}
|
|
90
206
|
(0, PacketUtils_1.emitPacket)(this.host.serverPackets, function (d) { return _this.raw_send(d); }, tag, values);
|
|
91
207
|
};
|
|
92
|
-
/**
|
|
93
|
-
|
|
94
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Broadcasts a packet to all other users connected
|
|
210
|
+
* @param tag The tag to send
|
|
211
|
+
* @param values The values to send
|
|
212
|
+
*/
|
|
213
|
+
SonicWSConnection.prototype.broadcastFiltered = function (tag, filter) {
|
|
214
|
+
var _a;
|
|
215
|
+
var _this = this;
|
|
216
|
+
var values = [];
|
|
217
|
+
for (var _i = 2; _i < arguments.length; _i++) {
|
|
218
|
+
values[_i - 2] = arguments[_i];
|
|
219
|
+
}
|
|
220
|
+
(_a = this.host).broadcastFiltered.apply(_a, __spreadArray([tag, function (socket) { return socket != _this && filter(socket); }], values, false));
|
|
95
221
|
};
|
|
222
|
+
/**
|
|
223
|
+
* Broadcasts a packet to all other users connected
|
|
224
|
+
* @param tag The tag to send
|
|
225
|
+
* @param values The values to send
|
|
226
|
+
*/
|
|
96
227
|
SonicWSConnection.prototype.broadcast = function (tag) {
|
|
97
|
-
var _this = this;
|
|
98
228
|
var values = [];
|
|
99
229
|
for (var _i = 1; _i < arguments.length; _i++) {
|
|
100
230
|
values[_i - 1] = arguments[_i];
|
|
101
231
|
}
|
|
102
|
-
this.
|
|
232
|
+
this.broadcastFiltered.apply(this, __spreadArray([tag, function () { return true; }], values, false));
|
|
233
|
+
};
|
|
234
|
+
/**
|
|
235
|
+
* Toggles printing all sent and received messages
|
|
236
|
+
*/
|
|
237
|
+
SonicWSConnection.prototype.togglePrint = function () {
|
|
238
|
+
this.print = !this.print;
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
241
|
+
* Closes the socket
|
|
242
|
+
*/
|
|
243
|
+
SonicWSConnection.prototype.close = function (code) {
|
|
244
|
+
if (code === void 0) { code = 1000; }
|
|
245
|
+
this.socket.close(code);
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* Sets a timeout that will automatically end when the socket closes
|
|
249
|
+
* @param call The function to call
|
|
250
|
+
* @param time The time between now and the call (ms)
|
|
251
|
+
*/
|
|
252
|
+
SonicWSConnection.prototype.setTimeout = function (call, time) {
|
|
253
|
+
var timeout = setTimeout(call, time);
|
|
254
|
+
this.timers.push(timeout);
|
|
255
|
+
return timeout;
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* Sets an interval that will automatically end when the socket closes
|
|
259
|
+
* @param call The function to call
|
|
260
|
+
* @param time The time between calls (ms)
|
|
261
|
+
*/
|
|
262
|
+
SonicWSConnection.prototype.setInterval = function (call, time) {
|
|
263
|
+
var interval = setInterval(call, time);
|
|
264
|
+
this.timers.push(interval);
|
|
265
|
+
return interval;
|
|
103
266
|
};
|
|
104
267
|
return SonicWSConnection;
|
|
105
268
|
}());
|
|
@@ -2,6 +2,17 @@ import * as WS from 'ws';
|
|
|
2
2
|
import { SonicWSConnection } from './SonicWSConnection';
|
|
3
3
|
import { PacketHolder } from '../util/PacketHolder';
|
|
4
4
|
import { Packet } from '../packets/Packets';
|
|
5
|
+
/**
|
|
6
|
+
* Sonic WS Server Options
|
|
7
|
+
*/
|
|
8
|
+
export type SonicServerOptions = {
|
|
9
|
+
/** An array of packets the client can send and server can listen for; using CreatePacket(), CreateObjPacket(), and CreateEnumPacket() */
|
|
10
|
+
clientPackets?: Packet[];
|
|
11
|
+
/** An array of packets the server can send and client can listen for; using CreatePacket(), CreateObjPacket(), and CreateEnumPacket() */
|
|
12
|
+
serverPackets?: Packet[];
|
|
13
|
+
/** Default WS Options */
|
|
14
|
+
websocketOptions?: WS.ServerOptions;
|
|
15
|
+
};
|
|
5
16
|
export declare class SonicWSServer {
|
|
6
17
|
private wss;
|
|
7
18
|
private availableIds;
|
|
@@ -10,13 +21,81 @@ export declare class SonicWSServer {
|
|
|
10
21
|
serverPackets: PacketHolder;
|
|
11
22
|
private connections;
|
|
12
23
|
private connectionMap;
|
|
13
|
-
|
|
24
|
+
private rateLimit;
|
|
25
|
+
private handshakePacket;
|
|
26
|
+
/**
|
|
27
|
+
* Initializes and hosts a websocket with sonic protocol
|
|
28
|
+
* Rate limits can be set with wss.setRateLimit(x); it is defaulted at 50/second
|
|
29
|
+
* @param settings Sonic Server Options such as schema data for client and server packets, alongside websocket options
|
|
30
|
+
*/
|
|
31
|
+
constructor(settings: SonicServerOptions);
|
|
14
32
|
private generateSocketID;
|
|
33
|
+
/**
|
|
34
|
+
* Requires each client to send this packet upon initialization
|
|
35
|
+
*
|
|
36
|
+
* Recreates this:
|
|
37
|
+
* ```js
|
|
38
|
+
* let initiated = false;
|
|
39
|
+
* socket.on('init', () => {
|
|
40
|
+
* if(initiated) return socket.close();
|
|
41
|
+
* initiated = true;
|
|
42
|
+
* // process
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* socket.on('otherPacket', () => {
|
|
46
|
+
* if(!initiated) return socket.close();
|
|
47
|
+
* // process
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @param packet The tag of the packet to require as a handshake
|
|
52
|
+
*/
|
|
53
|
+
requireHandshake(packet: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Sets the rate limit for all clients
|
|
56
|
+
* @param limit Amount of packets the sockets can send every second, or 0 for infinite
|
|
57
|
+
*/
|
|
58
|
+
setRateLimit(limit: number): void;
|
|
59
|
+
/**
|
|
60
|
+
* Listens for whenever a client connects
|
|
61
|
+
* @param runner Called when ready
|
|
62
|
+
*/
|
|
15
63
|
on_connect(runner: (client: SonicWSConnection) => void): void;
|
|
64
|
+
/**
|
|
65
|
+
* Listens for whenever the server is ready
|
|
66
|
+
* @param runner Called when ready
|
|
67
|
+
*/
|
|
16
68
|
on_ready(runner: () => void): void;
|
|
69
|
+
/**
|
|
70
|
+
* Closes the server
|
|
71
|
+
* @param callback Called when server closes
|
|
72
|
+
*/
|
|
17
73
|
shutdown(callback: (err?: Error) => void): void;
|
|
74
|
+
/**
|
|
75
|
+
* Broadcasts a packet to all users connected, but with a filter
|
|
76
|
+
* @param tag The tag to send
|
|
77
|
+
* @param filter The filter for who to send to
|
|
78
|
+
* @param values The values to send
|
|
79
|
+
*/
|
|
80
|
+
broadcastFiltered(tag: string, filter: (socket: SonicWSConnection) => boolean, ...values: any): void;
|
|
81
|
+
/**
|
|
82
|
+
* Broadcasts a packet to all users connected
|
|
83
|
+
* @param tag The tag to send
|
|
84
|
+
* @param values The values to send
|
|
85
|
+
*/
|
|
18
86
|
broadcast(tag: string, ...values: any): void;
|
|
87
|
+
/**
|
|
88
|
+
* @returns All users connected to the socket
|
|
89
|
+
*/
|
|
19
90
|
getConnected(): SonicWSConnection[];
|
|
91
|
+
/**
|
|
92
|
+
* @param id The socket id
|
|
93
|
+
* @returns The socket
|
|
94
|
+
*/
|
|
20
95
|
getSocket(id: number): SonicWSConnection;
|
|
96
|
+
/**
|
|
97
|
+
* Closes a socket by id
|
|
98
|
+
* @param id The socket id
|
|
99
|
+
*/
|
|
21
100
|
closeSocket(id: number): void;
|
|
22
101
|
}
|
|
@@ -53,23 +53,30 @@ var PacketHolder_1 = require("../util/PacketHolder");
|
|
|
53
53
|
var CodePointUtil_1 = require("../util/CodePointUtil");
|
|
54
54
|
var version_1 = require("../../version");
|
|
55
55
|
var SonicWSServer = /** @class */ (function () {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Initializes and hosts a websocket with sonic protocol
|
|
58
|
+
* Rate limits can be set with wss.setRateLimit(x); it is defaulted at 50/second
|
|
59
|
+
* @param settings Sonic Server Options such as schema data for client and server packets, alongside websocket options
|
|
60
|
+
*/
|
|
61
|
+
function SonicWSServer(settings) {
|
|
58
62
|
var _this = this;
|
|
59
63
|
this.availableIds = Array.from({ length: 501 }, function (_, i) { return i; });
|
|
60
64
|
this.connectListeners = [];
|
|
61
65
|
this.connections = [];
|
|
62
66
|
this.connectionMap = {};
|
|
63
|
-
this.
|
|
67
|
+
this.rateLimit = 50;
|
|
68
|
+
this.handshakePacket = null;
|
|
69
|
+
var _a = settings.clientPackets, clientPackets = _a === void 0 ? [] : _a, _b = settings.serverPackets, serverPackets = _b === void 0 ? [] : _b, _c = settings.websocketOptions, websocketOptions = _c === void 0 ? {} : _c;
|
|
70
|
+
this.wss = new WS.WebSocketServer(websocketOptions);
|
|
64
71
|
this.clientPackets = new PacketHolder_1.PacketHolder(clientPackets);
|
|
65
72
|
this.serverPackets = new PacketHolder_1.PacketHolder(serverPackets);
|
|
66
73
|
var s_clientPackets = this.clientPackets.serialize();
|
|
67
74
|
var s_serverPackets = this.serverPackets.serialize();
|
|
68
75
|
var keyData = "SWS" + version_1.VERSION_CHAR + s_clientPackets + CodePointUtil_1.NULL + s_serverPackets;
|
|
69
76
|
this.wss.on('connection', function (socket) {
|
|
70
|
-
var sonicConnection = new SonicWSConnection_1.SonicWSConnection(socket, _this, _this.generateSocketID());
|
|
77
|
+
var sonicConnection = new SonicWSConnection_1.SonicWSConnection(socket, _this, _this.generateSocketID(), _this.handshakePacket);
|
|
71
78
|
// send tags to the client so it doesn't have to hard code them in
|
|
72
|
-
socket.send(keyData);
|
|
79
|
+
socket.send(keyData + CodePointUtil_1.NULL + String.fromCharCode(_this.rateLimit));
|
|
73
80
|
_this.connections.push(sonicConnection);
|
|
74
81
|
_this.connectionMap[sonicConnection.id] = sonicConnection;
|
|
75
82
|
_this.connectListeners.forEach(function (l) { return l(sonicConnection); });
|
|
@@ -94,28 +101,106 @@ var SonicWSServer = /** @class */ (function () {
|
|
|
94
101
|
SonicWSServer.prototype.generateSocketID = function () {
|
|
95
102
|
return this.availableIds.shift();
|
|
96
103
|
};
|
|
104
|
+
/**
|
|
105
|
+
* Requires each client to send this packet upon initialization
|
|
106
|
+
*
|
|
107
|
+
* Recreates this:
|
|
108
|
+
* ```js
|
|
109
|
+
* let initiated = false;
|
|
110
|
+
* socket.on('init', () => {
|
|
111
|
+
* if(initiated) return socket.close();
|
|
112
|
+
* initiated = true;
|
|
113
|
+
* // process
|
|
114
|
+
* });
|
|
115
|
+
*
|
|
116
|
+
* socket.on('otherPacket', () => {
|
|
117
|
+
* if(!initiated) return socket.close();
|
|
118
|
+
* // process
|
|
119
|
+
* })
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @param packet The tag of the packet to require as a handshake
|
|
123
|
+
*/
|
|
124
|
+
SonicWSServer.prototype.requireHandshake = function (packet) {
|
|
125
|
+
if (!this.clientPackets.hasTag(packet))
|
|
126
|
+
throw new Error("The client cannot send \"".concat(packet, "\" for handshake!"));
|
|
127
|
+
this.handshakePacket = packet;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Sets the rate limit for all clients
|
|
131
|
+
* @param limit Amount of packets the sockets can send every second, or 0 for infinite
|
|
132
|
+
*/
|
|
133
|
+
SonicWSServer.prototype.setRateLimit = function (limit) {
|
|
134
|
+
// so that i can store limits in 1 packet
|
|
135
|
+
if (limit > CodePointUtil_1.MAX_C) {
|
|
136
|
+
limit = 0;
|
|
137
|
+
console.warn("A rate limit above ".concat(CodePointUtil_1.MAX_C, " is considered infinite."));
|
|
138
|
+
}
|
|
139
|
+
this.rateLimit = limit;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Listens for whenever a client connects
|
|
143
|
+
* @param runner Called when ready
|
|
144
|
+
*/
|
|
97
145
|
SonicWSServer.prototype.on_connect = function (runner) {
|
|
98
146
|
this.connectListeners.push(runner);
|
|
99
147
|
};
|
|
148
|
+
/**
|
|
149
|
+
* Listens for whenever the server is ready
|
|
150
|
+
* @param runner Called when ready
|
|
151
|
+
*/
|
|
100
152
|
SonicWSServer.prototype.on_ready = function (runner) {
|
|
101
153
|
this.wss.on('listening', runner);
|
|
102
154
|
};
|
|
155
|
+
/**
|
|
156
|
+
* Closes the server
|
|
157
|
+
* @param callback Called when server closes
|
|
158
|
+
*/
|
|
103
159
|
SonicWSServer.prototype.shutdown = function (callback) {
|
|
104
160
|
this.wss.close(callback);
|
|
105
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* Broadcasts a packet to all users connected, but with a filter
|
|
164
|
+
* @param tag The tag to send
|
|
165
|
+
* @param filter The filter for who to send to
|
|
166
|
+
* @param values The values to send
|
|
167
|
+
*/
|
|
168
|
+
SonicWSServer.prototype.broadcastFiltered = function (tag, filter) {
|
|
169
|
+
var values = [];
|
|
170
|
+
for (var _i = 2; _i < arguments.length; _i++) {
|
|
171
|
+
values[_i - 2] = arguments[_i];
|
|
172
|
+
}
|
|
173
|
+
this.connections.filter(filter).forEach(function (conn) { return conn.send.apply(conn, __spreadArray([tag], values, false)); });
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Broadcasts a packet to all users connected
|
|
177
|
+
* @param tag The tag to send
|
|
178
|
+
* @param values The values to send
|
|
179
|
+
*/
|
|
106
180
|
SonicWSServer.prototype.broadcast = function (tag) {
|
|
107
181
|
var values = [];
|
|
108
182
|
for (var _i = 1; _i < arguments.length; _i++) {
|
|
109
183
|
values[_i - 1] = arguments[_i];
|
|
110
184
|
}
|
|
111
|
-
this.
|
|
185
|
+
this.broadcastFiltered.apply(this, __spreadArray([tag, function () { return true; }], values, false));
|
|
112
186
|
};
|
|
187
|
+
/**
|
|
188
|
+
* @returns All users connected to the socket
|
|
189
|
+
*/
|
|
113
190
|
SonicWSServer.prototype.getConnected = function () {
|
|
114
191
|
return this.connections;
|
|
115
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* @param id The socket id
|
|
195
|
+
* @returns The socket
|
|
196
|
+
*/
|
|
116
197
|
SonicWSServer.prototype.getSocket = function (id) {
|
|
117
198
|
return this.connectionMap[id];
|
|
118
199
|
};
|
|
200
|
+
/**
|
|
201
|
+
* Closes a socket by id
|
|
202
|
+
* @param id The socket id
|
|
203
|
+
*/
|
|
119
204
|
SonicWSServer.prototype.closeSocket = function (id) {
|
|
120
205
|
this.getSocket(id).close();
|
|
121
206
|
};
|