sonic-ws 1.3.3 → 2.0.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.
Files changed (78) hide show
  1. package/LICENSE +56 -196
  2. package/README.md +88 -17
  3. package/dist/{index.d.ts → ts/index.d.ts} +6 -0
  4. package/dist/{index.js → ts/index.js} +10 -11
  5. package/dist/ts/native/wrapper.d.ts +59 -0
  6. package/dist/ts/native/wrapper.js +7 -0
  7. package/dist/{version.d.ts → ts/version.d.ts} +5 -0
  8. package/dist/ts/version.js +7 -0
  9. package/dist/{ws → ts/ws}/Connection.d.ts +5 -0
  10. package/dist/ts/ws/Connection.js +7 -0
  11. package/dist/{ws → ts/ws}/PacketProcessor.d.ts +5 -0
  12. package/dist/ts/ws/PacketProcessor.js +7 -0
  13. package/dist/{ws → ts/ws}/client/core/ClientCore.d.ts +5 -0
  14. package/dist/ts/ws/client/core/ClientCore.js +7 -0
  15. package/dist/{ws → ts/ws}/client/node/ClientNode.d.ts +5 -0
  16. package/dist/ts/ws/client/node/ClientNode.js +7 -0
  17. package/dist/{ws → ts/ws}/debug/DebugServer.d.ts +5 -0
  18. package/dist/ts/ws/debug/DebugServer.js +7 -0
  19. package/dist/{ws → ts/ws}/packets/PacketType.d.ts +6 -1
  20. package/dist/ts/ws/packets/PacketType.js +7 -0
  21. package/dist/{ws → ts/ws}/packets/Packets.d.ts +5 -3
  22. package/dist/ts/ws/packets/Packets.js +7 -0
  23. package/dist/{ws → ts/ws}/server/SonicWSConnection.d.ts +5 -0
  24. package/dist/ts/ws/server/SonicWSConnection.js +7 -0
  25. package/dist/{ws → ts/ws}/server/SonicWSServer.d.ts +8 -0
  26. package/dist/ts/ws/server/SonicWSServer.js +7 -0
  27. package/dist/{ws → ts/ws}/util/BufferUtil.d.ts +5 -0
  28. package/dist/ts/ws/util/BufferUtil.js +7 -0
  29. package/dist/{ws → ts/ws}/util/StringUtil.d.ts +5 -2
  30. package/dist/ts/ws/util/StringUtil.js +7 -0
  31. package/dist/{ws → ts/ws}/util/enums/EnumHandler.d.ts +5 -0
  32. package/dist/ts/ws/util/enums/EnumHandler.js +7 -0
  33. package/dist/{ws → ts/ws}/util/enums/EnumType.d.ts +5 -0
  34. package/dist/ts/ws/util/enums/EnumType.js +7 -0
  35. package/dist/ts/ws/util/packets/BatchHelper.d.ts +6 -0
  36. package/dist/ts/ws/util/packets/BatchHelper.js +7 -0
  37. package/dist/ts/ws/util/packets/CompressionUtil.d.ts +13 -0
  38. package/dist/ts/ws/util/packets/CompressionUtil.js +7 -0
  39. package/dist/ts/ws/util/packets/HashUtil.d.ts +7 -0
  40. package/dist/ts/ws/util/packets/HashUtil.js +7 -0
  41. package/dist/ts/ws/util/packets/JSONUtil.d.ts +7 -0
  42. package/dist/ts/ws/util/packets/JSONUtil.js +7 -0
  43. package/dist/ts/ws/util/packets/PacketHolder.d.ts +6 -0
  44. package/dist/ts/ws/util/packets/PacketHolder.js +7 -0
  45. package/dist/{ws → ts/ws}/util/packets/PacketUtils.d.ts +5 -0
  46. package/dist/ts/ws/util/packets/PacketUtils.js +7 -0
  47. package/dist/ts/ws/util/packets/RateHandler.d.ts +6 -0
  48. package/dist/ts/ws/util/packets/RateHandler.js +7 -0
  49. package/package.json +14 -10
  50. package/dist/version.js +0 -25
  51. package/dist/ws/Connection.js +0 -126
  52. package/dist/ws/PacketProcessor.js +0 -52
  53. package/dist/ws/client/core/ClientCore.js +0 -251
  54. package/dist/ws/client/node/ClientNode.js +0 -36
  55. package/dist/ws/debug/DebugServer.js +0 -607
  56. package/dist/ws/packets/PacketProcessors.d.ts +0 -13
  57. package/dist/ws/packets/PacketProcessors.js +0 -317
  58. package/dist/ws/packets/PacketType.js +0 -61
  59. package/dist/ws/packets/Packets.js +0 -277
  60. package/dist/ws/server/SonicWSConnection.js +0 -298
  61. package/dist/ws/server/SonicWSServer.js +0 -307
  62. package/dist/ws/util/BufferUtil.js +0 -42
  63. package/dist/ws/util/StringUtil.js +0 -51
  64. package/dist/ws/util/enums/EnumHandler.js +0 -60
  65. package/dist/ws/util/enums/EnumType.js +0 -72
  66. package/dist/ws/util/packets/BatchHelper.d.ts +0 -1
  67. package/dist/ws/util/packets/BatchHelper.js +0 -85
  68. package/dist/ws/util/packets/CompressionUtil.d.ts +0 -35
  69. package/dist/ws/util/packets/CompressionUtil.js +0 -277
  70. package/dist/ws/util/packets/HashUtil.d.ts +0 -2
  71. package/dist/ws/util/packets/HashUtil.js +0 -122
  72. package/dist/ws/util/packets/JSONUtil.d.ts +0 -2
  73. package/dist/ws/util/packets/JSONUtil.js +0 -179
  74. package/dist/ws/util/packets/PacketHolder.d.ts +0 -1
  75. package/dist/ws/util/packets/PacketHolder.js +0 -126
  76. package/dist/ws/util/packets/PacketUtils.js +0 -283
  77. package/dist/ws/util/packets/RateHandler.d.ts +0 -1
  78. package/dist/ws/util/packets/RateHandler.js +0 -66
@@ -1,607 +0,0 @@
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
- var __importDefault = (this && this.__importDefault) || function (mod) {
18
- return (mod && mod.__esModule) ? mod : { "default": mod };
19
- };
20
- Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.DebugServer = void 0;
22
- const Connection_1 = require("../Connection");
23
- const PacketType_1 = require("../packets/PacketType");
24
- const SonicWSServer_1 = require("../server/SonicWSServer");
25
- const PacketUtils_1 = require("../util/packets/PacketUtils");
26
- const http_1 = __importDefault(require("http"));
27
- const open_1 = __importDefault(require("open"));
28
- const EnumHandler_1 = require("../util/enums/EnumHandler");
29
- class DebugServer {
30
- constructor(host, data) {
31
- data.port ??= 0;
32
- data.password ??= "";
33
- if (data.port < 0 || data.port >= 65536)
34
- throw new Error("Port out of range!");
35
- /*
36
- * `
37
- <!DOCTYPE html>
38
- <html>
39
- <head>
40
- <meta charset="UTF-8">
41
- <script src="https://cdn.jsdelivr.net/gh/liwybloc/sonic-ws/bundled/SonicWS_bundle"></script>
42
- <title>SonicWS Debug Menu</title>
43
- <style>
44
- body {
45
- margin: 0;
46
- font-family: Inter, Arial, sans-serif;
47
- background: #0f1115;
48
- color: #e6e6e6;
49
- height: 100vh;
50
- display: flex;
51
- }
52
-
53
- #sidebar {
54
- width: 260px;
55
- background: #141821;
56
- border-right: 1px solid #1f2533;
57
- display: flex;
58
- flex-direction: column;
59
- }
60
-
61
- #sidebar-header {
62
- padding: 16px;
63
- font-weight: 600;
64
- font-size: 18px;
65
- border-bottom: 1px solid #1f2533;
66
- cursor: pointer;
67
- transition: color 0.2s;
68
- }
69
- #sidebar-header:hover {
70
- color: #dddddd;
71
- }
72
-
73
- #socket-list {
74
- flex: 1;
75
- overflow-y: auto;
76
- }
77
-
78
- .socket-item {
79
- padding: 10px 14px;
80
- cursor: pointer;
81
- border-bottom: 1px solid #1f2533;
82
- }
83
-
84
- .socket-item:hover {
85
- background: #1b2030;
86
- }
87
-
88
- .socket-item.active {
89
- background: #22294a;
90
- }
91
-
92
- .socket-id {
93
- font-size: 12px;
94
- opacity: 0.7;
95
- }
96
-
97
- #main {
98
- flex: 1;
99
- display: flex;
100
- flex-direction: column;
101
- }
102
-
103
- #main-header {
104
- padding: 17px;
105
- border-bottom: 1px solid #1f2533;
106
- display: flex;
107
- justify-content: space-between;
108
- align-items: center;
109
- }
110
-
111
- #stats {
112
- display: flex;
113
- gap: 20px;
114
- font-size: 13px;
115
- }
116
-
117
- #packets {
118
- flex: 1;
119
- overflow-y: auto;
120
- padding: 12px;
121
- }
122
-
123
- .packet {
124
- background: #1a1f2e;
125
- border-radius: 6px;
126
- padding: 6px 8px;
127
- margin-bottom: 4px;
128
- font-size: 12px;
129
- cursor: pointer;
130
- }
131
-
132
- .packet.sent { border-left: 3px solid #3cff7a; }
133
- .packet.recv { border-left: 3px solid #ff5a5a; }
134
-
135
- .packet-details {
136
- display: none;
137
- margin-top: 4px;
138
- opacity: 0.75;
139
- font-size: 11px;
140
- }
141
-
142
- .packet.expanded .packet-details {
143
- display: block;
144
- }
145
-
146
- button {
147
- background: none;
148
- }
149
- </style>
150
- </head>
151
- <body>
152
- <div id="sidebar">
153
- <div id="sidebar-header">Sonic WS Debug Menu</div>
154
- <div id="socket-list"></div>
155
- </div>
156
-
157
- <div id="main">
158
- <div id="main-header">
159
- <button id="close-socket" style="display:none;">❌</button>
160
- <div id="socket-title">Server Home</div>
161
- <div id="stats"></div>
162
- </div>
163
- <div id="home" style="display: block; padding: 16px;">
164
- <h2>Server Dashboard</h2>
165
- <div id="global-stats" style="margin-bottom:16px;"></div>
166
- <h3>Connection Logs</h3>
167
- <ul id="connection-logs" style="max-height:200px; overflow-y:auto; padding-left:16px;"></ul>
168
- <div style="margin-top:16px;">
169
- <table style="width:100%; border-collapse:collapse;">
170
- <thead>
171
- <tr>
172
- <th style="border-bottom:1px solid #444; text-align:left;">Socket ID</th>
173
- <th style="border-bottom:1px solid #444; text-align:left;">Name</th>
174
- <th style="border-bottom:1px solid #444; text-align:left;">Status</th>
175
- </tr>
176
- </thead>
177
- <tbody id="connection-table"></tbody>
178
- </table>
179
- </div>
180
- </div>
181
- <div id="packets"></div>
182
- </div>
183
-
184
- <script>
185
- const socketList = document.getElementById('socket-list');
186
- const packetsDiv = document.getElementById('packets');
187
- const socketTitle = document.getElementById('socket-title');
188
- const debugTitle = document.getElementById('sidebar-header');
189
- const statsDiv = document.getElementById('stats');
190
- const home = document.getElementById('home');
191
- const closeSocketBtn = document.getElementById('close-socket');
192
-
193
- debugTitle.onclick = () => {
194
- if(activeId !== null) {
195
- activeId = null;
196
- packetsDiv.style.display = 'none';
197
- home.style.display = 'block';
198
- closeSocketBtn.style.display = 'none';
199
- renderGlobalStats();
200
- }
201
- };
202
-
203
- const globalStats = {
204
- totalSockets: 0,
205
- totalSent: 0,
206
- totalRecv: 0,
207
- totalSentBytes: 0,
208
- totalRecvBytes: 0,
209
- totalSaved: 0,
210
- startTime: 0,
211
- };
212
-
213
- function formatMilliseconds(ms) {
214
- if (ms < 1) return '0.0s';
215
-
216
- const units = [
217
- { label: 'week', value: 7 * 24 * 60 * 60 * 1000 },
218
- { label: 'day', value: 24 * 60 * 60 * 1000 },
219
- { label: 'hour', value: 60 * 60 * 1000 },
220
- { label: 'minute', value: 60 * 1000 },
221
- ];
222
-
223
- const parts = [];
224
-
225
- for (const { label, value } of units) {
226
- const amount = Math.floor(ms / value);
227
- if (amount > 0) {
228
- parts.push(amount + ' ' + label + (amount !== 1 ? 's' : ''));
229
- ms -= amount * value;
230
- }
231
- }
232
-
233
- if (ms > 0 || parts.length === 0) {
234
- const seconds = (ms / 1000).toFixed(1);
235
- parts.push(seconds + 's');
236
- }
237
-
238
- if (parts.length === 1) return parts[0];
239
- const last = parts.pop();
240
- return parts.join(', ') + ' and ' + last;
241
- }
242
-
243
-
244
- const globalStatsDiv = document.getElementById('global-stats');
245
- function renderGlobalStats() {
246
- const stats = globalStats;
247
- const uptime = Date.now() - stats.startTime;
248
- const formattedUptime = formatMilliseconds(uptime);
249
-
250
- globalStatsDiv.innerHTML = '<div><strong>Total Sockets:</strong> ' + stats.totalSockets + '</div><div><strong>Total Sent Packets:</strong> ' + stats.totalSent + '</div><div><strong>Total Received Packets:</strong> ' + stats.totalRecv + '</div><div><strong>Total Sent Bytes:</strong> ' + stats.totalSentBytes + ' B</div><div><strong>Total Received Bytes:</strong> ' + stats.totalRecvBytes + ' B</div><div><strong>Total Bandwidth Saved:</strong> ' + stats.totalSaved + ' B</div><div><strong>Uptime:</strong> ' + formattedUptime + '</div>';
251
- }
252
- setInterval(renderGlobalStats, 50);
253
-
254
- function updateConnectionTable() {
255
- const tbody = document.getElementById('connection-table');
256
- tbody.innerHTML = '';
257
- sockets.forEach(s => {
258
- const row = document.createElement('tr');
259
- row.innerHTML = '<td>' + s.id + '</td><td>' + s.name + '</td><td style="color:' + (s.el.style.color || '#0f0') + '">' + (s.el.style.color === '#f00' ? 'Disconnected' : 'Connected') + '</td>';
260
- tbody.appendChild(row);
261
- });
262
- }
263
- setInterval(updateConnectionTable, 1000);
264
-
265
- const sockets = new Map();
266
- let activeId = null;
267
-
268
- function selectSocket(id) {
269
- activeId = id;
270
- [...socketList.children].forEach(e => e.classList.toggle('active', e.dataset.id == id));
271
-
272
- const s = sockets.get(id);
273
- socketTitle.textContent = s.name;
274
- packetsDiv.innerHTML = '';
275
- s.packets.forEach(p => packetsDiv.appendChild(p.el));
276
- renderStats(s);
277
- home.style.display = 'none';
278
- packetsDiv.style.display = 'block';
279
- closeSocketBtn.style.display = 'block';
280
- }
281
-
282
- closeSocketBtn.onclick = () => {
283
- if(activeId === null) return;
284
- ws.send("close", Number(activeId));
285
- }
286
-
287
- function renderStats(s) {
288
- statsDiv.innerHTML = "<div>Sent: " + s.sent + "</div><div>Recv: " + s.recv + "</div><div>Sent bytes: " + s.sentBytes + "</div><div>Recv bytes: " + s.recvBytes + "</div><div>Saved: " + s.saved + "</div>";
289
- }
290
-
291
- function addSocket(id, name) {
292
- const el = document.createElement('div');
293
- el.className = 'socket-item';
294
- el.dataset.id = id;
295
- el.innerHTML = "<div>" + name + "</div><div class=\\"socket-id\\">#" + id + "</div>";
296
- el.onclick = () => selectSocket(id);
297
- socketList.appendChild(el);
298
-
299
- sockets.set(id, {
300
- id,
301
- name,
302
- el,
303
- packets: [],
304
- sent: 0,
305
- recv: 0,
306
- sentBytes: 0,
307
- recvBytes: 0,
308
- saved: 0
309
- });
310
- }
311
-
312
- function removeSocket(id, code, reason, codeReason) {
313
- const s = sockets.get(id);
314
- if (!s) return console.error("Unknown socket!!", id);
315
-
316
- s.el.dataset.id = id + "-closed";
317
- s.el.onclick = () => selectSocket(id + "-closed");
318
- sockets.set(id + "-closed", s);
319
- sockets.delete(id);
320
-
321
- if(activeId == id) activeId = id + "-closed";
322
-
323
- const nameNode = s.el.childNodes[0];
324
- nameNode.style.color = "#f00";
325
-
326
- let circle = document.createElement('span');
327
- circle.style.display = 'inline-block';
328
- circle.style.width = '10px';
329
- circle.style.height = '10px';
330
- circle.style.borderRadius = '50%';
331
- circle.style.background = '#ff5a5a';
332
- circle.style.marginLeft = '8px';
333
- nameNode.appendChild(circle);
334
-
335
- // add disconnection info to home page logs
336
- const logItem = document.createElement('li');
337
- logItem.textContent = 'Socket #' + id + ' disconnected — Code: ' + code + ', Reason: ' + reason + ', Closure Cause: ' + codeReason;
338
- document.getElementById('connection-logs').appendChild(logItem);
339
-
340
- requestAnimationFrame(() => circle.style.width = '100%');
341
- setTimeout(() => {
342
- circle.remove();
343
- s.el.remove();
344
- if(activeId == id + "-closed") {
345
- packetsDiv.style.display = 'none';
346
- home.style.display = 'block';
347
- closeSocketBtn.style.display = 'none';
348
- }
349
- }, 30000);
350
- }
351
-
352
- function addPacket(id, dir, tag, rawSize, saved, info, date, processTime) {
353
- const s = sockets.get(id);
354
- if (!s) return console.error("Unknown socket!!", id);
355
-
356
- const el = document.createElement('div');
357
- el.className = 'packet ' + (dir === 'sent' ? 'sent' : 'recv');
358
- el.innerHTML = '<div>' + tag + (info !== "undefined" ? ' — ' + info : '') + '</div><div class="packet-details">Raw Bytes: ' + rawSize + 'b (saved: ~' + saved + 'b)<br>Processed At: ' + new Date(date).toISOString() + '<br>Processing Time: ' + processTime.toFixed(2) + 'ms</div>';
359
-
360
- el.onclick = () => el.classList.toggle('expanded');
361
-
362
- s.packets.push({ el });
363
- if (dir === 'sent') {
364
- s.sent++;
365
- s.sentBytes += rawSize;
366
- } else {
367
- s.recv++;
368
- s.recvBytes += rawSize;
369
- }
370
- s.saved += saved;
371
-
372
- if (activeId === id) {
373
- packetsDiv.appendChild(el);
374
- renderStats(s);
375
- }
376
- }
377
-
378
- function setStat(i, v) {
379
- globalStats[Object.keys(globalStats)[i]] = v;
380
- if (activeId === null) renderGlobalStats();
381
- }
382
-
383
- const ws = new SonicWS('ws://' + location.host);
384
-
385
- ws.on("connection", id => addSocket(id, "Socket " + id));
386
- ws.on("disconnection", ([id, code], [reason, codeReason]) => removeSocket(id, code, reason, codeReason));
387
- ws.on("nameChange", ([id], [name]) => {
388
- const s = sockets.get(id);
389
- if (!s) return console.error("Unknown socket!!", id);
390
- s.name = name;
391
- s.el.firstChild.textContent = name;
392
- if (activeId === id) socketTitle.textContent = name;
393
- });
394
- ws.on("packet", ([id, size, saved], [dir], [tag], [values], [time, processTime]) => {
395
- console.log("Received packet", { id, size, saved, dir, tag, values, time, processTime });
396
- addPacket(id, dir, tag, size, saved, values, time, processTime);
397
- });
398
- ws.on("stats", (stats) => {
399
- console.log("Received stats", stats);
400
- stats.forEach((v, i) => setStat(i, v));
401
- });
402
- ws.on("stat", (i, v) => setStat(i, v));
403
-
404
- const lastKnownPassword = localStorage.getItem("password");
405
- const empty = !localStorage.getItem("req");
406
- let usedPass = "";
407
- ws.on_ready(() => {
408
- if(empty) ws.send("password", "");
409
- else ws.send("password", usedPass = (lastKnownPassword ?? prompt("Please enter password")));
410
- });
411
-
412
- ws.on_close(() => {
413
- window.location.reload();
414
- });
415
-
416
- ws.on("authenticated", (success) => {
417
- if(!success) {
418
- localStorage.setItem("req", true);
419
- localStorage.removeItem("password");
420
- window.location.reload();
421
- } else {
422
- localStorage.setItem("req", usedPass.length > 0);
423
- localStorage.setItem("password", usedPass);
424
- }
425
- })
426
- </script>
427
- </body>
428
- </html>
429
- `
430
- */
431
- const server = http_1.default.createServer((req, res) => {
432
- res.writeHead(200, { 'Content-Type': 'text/html' });
433
- res.end(`<!doctypehtml><meta charset=UTF-8><script src=https://cdn.jsdelivr.net/gh/liwybloc/sonic-ws/bundled/SonicWS_bundle.js></script><title>SonicWS Debug Menu</title><style>body{margin:0;font-family:Inter,Arial,sans-serif;background:#0f1115;color:#e6e6e6;height:100vh;display:flex}#sidebar{width:260px;background:#141821;border-right:1px solid #1f2533;display:flex;flex-direction:column}#sidebar-header{padding:16px;font-weight:600;font-size:18px;border-bottom:1px solid #1f2533;cursor:pointer;transition:color .2s}#sidebar-header:hover{color:#ddd}#socket-list{flex:1;overflow-y:auto}.socket-item{padding:10px 14px;cursor:pointer;border-bottom:1px solid #1f2533}.socket-item:hover{background:#1b2030}.socket-item.active{background:#22294a}.socket-id{font-size:12px;opacity:.7}#main{flex:1;display:flex;flex-direction:column}#main-header{padding:17px;border-bottom:1px solid #1f2533;display:flex;justify-content:space-between;align-items:center}#stats{display:flex;gap:20px;font-size:13px}#packets{flex:1;overflow-y:auto;padding:12px}.packet{background:#1a1f2e;border-radius:6px;padding:6px 8px;margin-bottom:4px;font-size:12px;cursor:pointer}.packet.sent{border-left:3px solid #3cff7a}.packet.recv{border-left:3px solid #ff5a5a}.packet-details{display:none;margin-top:4px;opacity:.75;font-size:11px}.packet.expanded .packet-details{display:block}button{background:0 0}</style><div id=sidebar><div id=sidebar-header>Sonic WS Debug Menu</div><div id=socket-list></div></div><div id=main><div id=main-header><button id=close-socket style=display:none>❌</button><div id=socket-title>Server Home</div><div id=stats></div></div><div id=home style=display:block;padding:16px><h2>Server Dashboard</h2><div id=global-stats style=margin-bottom:16px></div><h3>Connection Logs</h3><ul id=connection-logs style=max-height:200px;overflow-y:auto;padding-left:16px></ul><div style=margin-top:16px><table style=width:100%;border-collapse:collapse><thead><tr><th style="border-bottom:1px solid #444;text-align:left">Socket ID<th style="border-bottom:1px solid #444;text-align:left">Name<th style="border-bottom:1px solid #444;text-align:left">Status<tbody id=connection-table></table></div></div><div id=packets></div></div><script>const socketList=document.getElementById("socket-list"),packetsDiv=document.getElementById("packets"),socketTitle=document.getElementById("socket-title"),debugTitle=document.getElementById("sidebar-header"),statsDiv=document.getElementById("stats"),home=document.getElementById("home"),closeSocketBtn=document.getElementById("close-socket");debugTitle.onclick=()=>{null!==activeId&&(activeId=null,packetsDiv.style.display="none",home.style.display="block",closeSocketBtn.style.display="none",renderGlobalStats())};const globalStats={totalSockets:0,totalSent:0,totalRecv:0,totalSentBytes:0,totalRecvBytes:0,totalSaved:0,startTime:0};function formatMilliseconds(e){if(e<1)return"0.0s";const t=[{label:"week",value:6048e5},{label:"day",value:864e5},{label:"hour",value:36e5},{label:"minute",value:6e4}],s=[];for(const{label:o,value:n}of t){const t=Math.floor(e/n);t>0&&(s.push(t+" "+o+(1!==t?"s":"")),e-=t*n)}if(e>0||0===s.length){const t=(e/1e3).toFixed(1);s.push(t+"s")}if(1===s.length)return s[0];const o=s.pop();return s.join(", ")+" and "+o}const globalStatsDiv=document.getElementById("global-stats");function renderGlobalStats(){const e=globalStats,t=formatMilliseconds(Date.now()-e.startTime);globalStatsDiv.innerHTML="<div><strong>Total Sockets:</strong> "+e.totalSockets+"</div><div><strong>Total Sent Packets:</strong> "+e.totalSent+"</div><div><strong>Total Received Packets:</strong> "+e.totalRecv+"</div><div><strong>Total Sent Bytes:</strong> "+e.totalSentBytes+" B</div><div><strong>Total Received Bytes:</strong> "+e.totalRecvBytes+" B</div><div><strong>Total Bandwidth Saved:</strong> "+e.totalSaved+" B</div><div><strong>Uptime:</strong> "+t+"</div>"}function updateConnectionTable(){const e=document.getElementById("connection-table");e.innerHTML="",sockets.forEach((t=>{const s=document.createElement("tr");s.innerHTML="<td>"+t.id+"</td><td>"+t.name+'</td><td style="color:'+(t.el.style.color||"#0f0")+'">'+("#f00"===t.el.style.color?"Disconnected":"Connected")+"</td>",e.appendChild(s)}))}setInterval(renderGlobalStats,50),setInterval(updateConnectionTable,1e3);const sockets=new Map;let activeId=null;function selectSocket(e){activeId=e,[...socketList.children].forEach((t=>t.classList.toggle("active",t.dataset.id==e)));const t=sockets.get(e);socketTitle.textContent=t.name,packetsDiv.innerHTML="",t.packets.forEach((e=>packetsDiv.appendChild(e.el))),renderStats(t),home.style.display="none",packetsDiv.style.display="block",closeSocketBtn.style.display="block"}function renderStats(e){statsDiv.innerHTML="<div>Sent: "+e.sent+"</div><div>Recv: "+e.recv+"</div><div>Sent bytes: "+e.sentBytes+"</div><div>Recv bytes: "+e.recvBytes+"</div><div>Saved: "+e.saved+"</div>"}function addSocket(e,t){const s=document.createElement("div");s.className="socket-item",s.dataset.id=e,s.innerHTML="<div>"+t+'</div><div class="socket-id">#'+e+"</div>",s.onclick=()=>selectSocket(e),socketList.appendChild(s),sockets.set(e,{id:e,name:t,el:s,packets:[],sent:0,recv:0,sentBytes:0,recvBytes:0,saved:0})}function removeSocket(e,t,s,o){const n=sockets.get(e);if(!n)return console.error("Unknown socket!!",e);n.el.dataset.id=e+"-closed",n.el.onclick=()=>selectSocket(e+"-closed"),sockets.set(e+"-closed",n),sockets.delete(e),activeId==e&&(activeId=e+"-closed");const c=n.el.childNodes[0];c.style.color="#f00";let l=document.createElement("span");l.style.display="inline-block",l.style.width="10px",l.style.height="10px",l.style.borderRadius="50%",l.style.background="#ff5a5a",l.style.marginLeft="8px",c.appendChild(l);const a=document.createElement("li");a.textContent="Socket #"+e+" disconnected — Code: "+t+", Reason: "+s+", Closure Cause: "+o,document.getElementById("connection-logs").appendChild(a),requestAnimationFrame((()=>l.style.width="100%")),setTimeout((()=>{l.remove(),n.el.remove(),activeId==e+"-closed"&&(packetsDiv.style.display="none",home.style.display="block",closeSocketBtn.style.display="none")}),3e4)}function addPacket(e,t,s,o,n,c,l,a){const d=sockets.get(e);if(!d)return console.error("Unknown socket!!",e);const i=document.createElement("div");i.className="packet "+("sent"===t?"sent":"recv"),i.innerHTML="<div>"+s+("undefined"!==c?" — "+c:"")+'</div><div class="packet-details">Raw Bytes: '+o+"b (saved: ~"+n+"b)<br>Processed At: "+new Date(l).toISOString()+"<br>Processing Time: "+a.toFixed(2)+"ms</div>",i.onclick=()=>i.classList.toggle("expanded"),d.packets.push({el:i}),"sent"===t?(d.sent++,d.sentBytes+=o):(d.recv++,d.recvBytes+=o),d.saved+=n,activeId===e&&(packetsDiv.appendChild(i),renderStats(d))}function setStat(e,t){globalStats[Object.keys(globalStats)[e]]=t,null===activeId&&renderGlobalStats()}closeSocketBtn.onclick=()=>{null!==activeId&&ws.send("close",Number(activeId))};const ws=new SonicWS("ws://"+location.host);ws.on("connection",(e=>addSocket(e,"Socket "+e))),ws.on("disconnection",(([e,t],[s,o])=>removeSocket(e,t,s,o))),ws.on("nameChange",(([e],[t])=>{const s=sockets.get(e);if(!s)return console.error("Unknown socket!!",e);s.name=t,s.el.firstChild.textContent=t,activeId===e&&(socketTitle.textContent=t)})),ws.on("packet",(([e,t,s],[o],[n],[c],[l,a])=>{console.log("Received packet",{id:e,size:t,saved:s,dir:o,tag:n,values:c,time:l,processTime:a}),addPacket(e,o,n,t,s,c,l,a)})),ws.on("stats",(e=>{console.log("Received stats",e),e.forEach(((e,t)=>setStat(t,e)))})),ws.on("stat",((e,t)=>setStat(e,t)));const lastKnownPassword=localStorage.getItem("password"),empty=!localStorage.getItem("req");let usedPass="";ws.on_ready((()=>{empty?ws.send("password",""):ws.send("password",usedPass=lastKnownPassword??prompt("Please enter password"))})),ws.on_close((()=>{window.location.reload()})),ws.on("authenticated",(e=>{e?(localStorage.setItem("req",usedPass.length>0),localStorage.setItem("password",usedPass)):(localStorage.setItem("req",!0),localStorage.removeItem("password"),window.location.reload())}));</script>`);
434
- });
435
- const TYPE_ENUM = (0, EnumHandler_1.DefineEnum)("type", ["sent", "recv"]);
436
- const wss = new SonicWSServer_1.SonicWSServer({
437
- clientPackets: [
438
- (0, PacketUtils_1.CreatePacket)({ tag: "password", type: PacketType_1.PacketType.STRINGS_UTF16 }),
439
- (0, PacketUtils_1.CreatePacket)({ tag: "close", type: PacketType_1.PacketType.UVARINT }),
440
- ],
441
- serverPackets: [
442
- (0, PacketUtils_1.CreatePacket)({ tag: "authenticated", type: PacketType_1.PacketType.BOOLEANS }),
443
- (0, PacketUtils_1.CreatePacket)({ tag: "connection", type: PacketType_1.PacketType.UVARINT }),
444
- (0, PacketUtils_1.CreateObjPacket)({ tag: "disconnection", types: [PacketType_1.PacketType.UVARINT, PacketType_1.PacketType.STRINGS], noDataRange: true }),
445
- (0, PacketUtils_1.CreateObjPacket)({ tag: "nameChange", types: [PacketType_1.PacketType.UVARINT, PacketType_1.PacketType.STRINGS_UTF16], noDataRange: true }),
446
- (0, PacketUtils_1.CreateObjPacket)({
447
- tag: "packet",
448
- types: [
449
- PacketType_1.PacketType.VARINT,
450
- TYPE_ENUM,
451
- PacketType_1.PacketType.STRINGS_UTF16,
452
- PacketType_1.PacketType.STRINGS_UTF16,
453
- PacketType_1.PacketType.FLOATS,
454
- ],
455
- noDataRange: true,
456
- dataBatching: 50,
457
- maxBatchSize: 0,
458
- }),
459
- (0, PacketUtils_1.CreatePacket)({ tag: "stats", type: PacketType_1.PacketType.UVARINT, noDataRange: true, dontSpread: true }),
460
- (0, PacketUtils_1.CreatePacket)({ tag: "stat", type: PacketType_1.PacketType.UVARINT, dataMax: 2 }),
461
- ],
462
- websocketOptions: { server },
463
- });
464
- const globalStats = new Proxy({
465
- totalSockets: 0,
466
- totalSent: 0,
467
- totalRecv: 0,
468
- totalSentBytes: 0,
469
- totalRecvBytes: 0,
470
- totalSaved: 0,
471
- startTime: Date.now(),
472
- }, {
473
- set(target, prop, value) {
474
- const key = String(prop);
475
- if (target[key] !== value) {
476
- target[key] = value;
477
- wss.broadcast("stat", Object.keys(globalStats).indexOf(key), value);
478
- }
479
- return true;
480
- }
481
- });
482
- // TODO: i think this is fucked by async
483
- const storedPacketData = {};
484
- wss.on_connect(ws => {
485
- let authenticated = false;
486
- const ogs = ws.send.bind(ws);
487
- let queue = [];
488
- ws.send = async (tag, ...values) => {
489
- console.log(authenticated, tag, values);
490
- if (!authenticated)
491
- queue.push([tag, values]);
492
- else
493
- ogs(tag, ...values);
494
- };
495
- ws.send("stats", ...Object.values(globalStats));
496
- host.connections.forEach(conn => {
497
- ws.send("connection", conn.id);
498
- ws.send("nameChange", conn.id, conn.getName());
499
- storedPacketData[conn.id]?.forEach((data) => {
500
- ws.send("packet", ...data);
501
- });
502
- });
503
- ws.on("password", (pword) => {
504
- if (data.password != pword) {
505
- ogs("authenticated", false);
506
- setTimeout(() => ws.close(1008), 1000);
507
- }
508
- else {
509
- authenticated = true;
510
- ws.send("authenticated", true);
511
- queue.forEach(([tag, values]) => ogs(tag, ...values));
512
- }
513
- });
514
- ws.on("close", (id) => {
515
- if (!authenticated)
516
- return;
517
- host.connectionMap[id]?.close(Connection_1.CloseCodes.MANUAL_SHUTDOWN);
518
- });
519
- });
520
- const innerConns = [];
521
- const broadcastSends = {};
522
- const textEncoder = new TextEncoder();
523
- const length = (values) => textEncoder.encode(JSON.stringify(values) ?? "[]").length;
524
- host.addMiddleware(new (class {
525
- onClientConnect(connection) {
526
- globalStats.totalSockets++;
527
- storedPacketData[connection.id] = [];
528
- innerConns.push(connection);
529
- wss.broadcast("connection", connection.id);
530
- const packetsSend = {};
531
- const packetsRecv = {};
532
- connection.addMiddleware(new (class {
533
- onNameChange(name) {
534
- wss.broadcast("nameChange", connection.id, name);
535
- }
536
- onSend_pre(tag, values, date, perfTime) {
537
- packetsSend[tag] ??= [];
538
- packetsSend[tag].push([values, perfTime, date]);
539
- }
540
- onSend_post(tag, data, sendSize) {
541
- globalStats.totalSentBytes += sendSize;
542
- globalStats.totalSent++;
543
- const [values, perfTime, date] = packetsSend[tag].shift();
544
- const jsonLength = length(values);
545
- const saved = jsonLength - sendSize;
546
- globalStats.totalSaved += saved;
547
- const record = [
548
- [connection.id, sendSize + 1, saved],
549
- TYPE_ENUM.wrap("sent"),
550
- tag,
551
- JSON.stringify(values),
552
- [date, performance.now() - perfTime],
553
- ];
554
- storedPacketData[connection.id].push(record);
555
- wss.broadcast("packet", ...record);
556
- }
557
- onReceive_pre(tag, data, recvSize) {
558
- globalStats.totalRecvBytes += recvSize;
559
- globalStats.totalRecv++;
560
- packetsRecv[tag] ??= [];
561
- packetsRecv[tag].push([data, performance.now(), Date.now()]);
562
- }
563
- onReceive_post(tag, values) {
564
- const [data, time, date] = packetsRecv[tag].shift();
565
- const jsonLength = length(values);
566
- const saved = jsonLength - data.length;
567
- globalStats.totalSaved += saved;
568
- const record = [
569
- [connection.id, data.length + 1, saved],
570
- TYPE_ENUM.wrap("recv"),
571
- tag,
572
- JSON.stringify(values),
573
- [date, performance.now() - time],
574
- ];
575
- storedPacketData[connection.id].push(record);
576
- wss.broadcast("packet", ...record);
577
- }
578
- })());
579
- }
580
- onClientDisconnect(connection, code, reason) {
581
- globalStats.totalSockets--;
582
- wss.broadcast("disconnection", [connection.id, code], [reason?.toString() ?? "UNKNOWN", (0, Connection_1.getClosureCause)(code)]);
583
- delete storedPacketData[connection.id];
584
- innerConns.splice(innerConns.indexOf(connection), 1);
585
- }
586
- onPacketBroadcast_pre(tag, info, ...values) {
587
- broadcastSends[tag] ??= [];
588
- broadcastSends[tag].push([values, performance.now(), Date.now()]);
589
- }
590
- onPacketBroadcast_post(tag, info, data, sendSize) {
591
- const [values, time, date] = broadcastSends[tag].shift();
592
- info.recipients.forEach(k => {
593
- if (innerConns.includes(k)) {
594
- k.callMiddleware("onSend_pre", tag, values, date, time);
595
- k.callMiddleware("onSend_post", tag, data, sendSize);
596
- }
597
- });
598
- }
599
- })());
600
- server.listen(data.port, () => {
601
- const address = server.address();
602
- console.log(`SWS Debug server running at http://localhost:${address.port}`);
603
- (0, open_1.default)(`http://localhost:${address.port}`);
604
- });
605
- }
606
- }
607
- exports.DebugServer = DebugServer;
@@ -1,13 +0,0 @@
1
- import { EnumPackage } from "../util/enums/EnumType";
2
- import { Packet } from "./Packets";
3
- import { PacketType } from "./PacketType";
4
- export type PacketTypeValidator = (data: Uint8Array, index: number) => Promise<[Uint8Array, false | any]>;
5
- export type PacketReceiveProcessor = (data: Uint8Array, validationResult: any, index: number) => any;
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> | Packet<T[]>, gzipCompression: boolean): PacketTypeValidator;
8
- export declare function createReceiveProcessor(type: PacketType, enumData: EnumPackage[], cap: number): PacketReceiveProcessor;
9
- /** Creates a function that processes a packet type */
10
- export declare function createSendProcessor(type: PacketType, gzipCompression: boolean, batchedData: boolean): PacketSendProcessor;
11
- export declare function createObjSendProcessor(packet: Packet<PacketType[]>): PacketSendProcessor;
12
- export declare function createObjReceiveProcessor(packet: Packet<PacketType[]>): PacketReceiveProcessor;
13
- export declare function createObjValidator(packet: Packet<PacketType[]>): PacketTypeValidator;