@sanctumterra/raknet 1.3.70 → 1.3.71
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/client/client-events.d.ts +2 -1
- package/dist/client/client-events.d.ts.map +1 -1
- package/dist/client/client.d.ts +2 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +58 -10
- package/dist/client/framer.d.ts +5 -3
- package/dist/client/framer.d.ts.map +1 -1
- package/dist/client/framer.js +79 -62
- package/dist/tests/server.js +1 -1
- package/dist/utils/Logger.d.ts +1 -1
- package/dist/utils/Logger.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Ack, Advertisement, ConnectedPing, ConnectionRequest, ConnectionRequestAccepted, NewIncomingConnection, OpenConnectionReplyOne, OpenConnectionReplyTwo, OpenConnectionRequestOne, OpenConnectionRequestTwo, UnconnectedPing, UnconnectedPong } from "../proto";
|
|
1
|
+
import type { Ack, Advertisement, ConnectedPing, ConnectedPong, ConnectionRequest, ConnectionRequestAccepted, NewIncomingConnection, OpenConnectionReplyOne, OpenConnectionReplyTwo, OpenConnectionRequestOne, OpenConnectionRequestTwo, UnconnectedPing, UnconnectedPong } from "../proto";
|
|
2
2
|
import type { Frameset } from "../proto/packets/frameset";
|
|
3
3
|
export interface ClientEvents {
|
|
4
4
|
"open-connection-reply-one": [OpenConnectionReplyOne];
|
|
@@ -9,6 +9,7 @@ export interface ClientEvents {
|
|
|
9
9
|
"unconnected-pong": [UnconnectedPong];
|
|
10
10
|
frameset: [Frameset];
|
|
11
11
|
"connected-ping": [ConnectedPing];
|
|
12
|
+
"connected-pong": [ConnectedPong];
|
|
12
13
|
"connection-request": [ConnectionRequest];
|
|
13
14
|
"connection-request-accepted": [ConnectionRequestAccepted];
|
|
14
15
|
"new-incoming-connection": [NewIncomingConnection];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-events.d.ts","sourceRoot":"","sources":["../../src/client/client-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC5B,2BAA2B,EAAE,CAAC,sBAAsB,CAAC,CAAC;IACtD,2BAA2B,EAAE,CAAC,sBAAsB,CAAC,CAAC;IACtD,6BAA6B,EAAE,CAAC,wBAAwB,CAAC,CAAC;IAC1D,6BAA6B,EAAE,CAAC,wBAAwB,CAAC,CAAC;IAC1D,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;IACtC,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;IACtC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;IACrB,gBAAgB,EAAE,CAAC,aAAa,CAAC,CAAC;IAClC,oBAAoB,EAAE,CAAC,iBAAiB,CAAC,CAAC;IAC1C,6BAA6B,EAAE,CAAC,yBAAyB,CAAC,CAAC;IAC3D,yBAAyB,EAAE,CAAC,qBAAqB,CAAC,CAAC;IACnD,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC;IACvB,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACX,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;IACf,KAAK,EAAE,EAAE,CAAC;IACV,OAAO,EAAE,CAAC,aAAa,CAAC,CAAC;IACzB,IAAI,EAAE,EAAE,CAAC;CACT"}
|
|
1
|
+
{"version":3,"file":"client-events.d.ts","sourceRoot":"","sources":["../../src/client/client-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,aAAa,EACb,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC5B,2BAA2B,EAAE,CAAC,sBAAsB,CAAC,CAAC;IACtD,2BAA2B,EAAE,CAAC,sBAAsB,CAAC,CAAC;IACtD,6BAA6B,EAAE,CAAC,wBAAwB,CAAC,CAAC;IAC1D,6BAA6B,EAAE,CAAC,wBAAwB,CAAC,CAAC;IAC1D,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;IACtC,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;IACtC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;IACrB,gBAAgB,EAAE,CAAC,aAAa,CAAC,CAAC;IAClC,gBAAgB,EAAE,CAAC,aAAa,CAAC,CAAC;IAClC,oBAAoB,EAAE,CAAC,iBAAiB,CAAC,CAAC;IAC1C,6BAA6B,EAAE,CAAC,yBAAyB,CAAC,CAAC;IAC3D,yBAAyB,EAAE,CAAC,qBAAqB,CAAC,CAAC;IACnD,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC;IACvB,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACX,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;IACf,KAAK,EAAE,EAAE,CAAC;IACV,OAAO,EAAE,CAAC,aAAa,CAAC,CAAC;IACzB,IAAI,EAAE,EAAE,CAAC;CACT"}
|
package/dist/client/client.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Emitter } from "@serenityjs/emitter";
|
|
|
2
2
|
import type { ClientEvents } from "./client-events";
|
|
3
3
|
import { type Socket } from "node:dgram";
|
|
4
4
|
import { Framer } from "./framer";
|
|
5
|
-
import { type Address, type Advertisement,
|
|
5
|
+
import { type Address, type Advertisement, Frame, type Priority, Status } from "../proto";
|
|
6
6
|
import { type ClientOptions } from "./client-options";
|
|
7
7
|
export declare class Client extends Emitter<ClientEvents> {
|
|
8
8
|
socket: Socket;
|
|
@@ -17,6 +17,7 @@ export declare class Client extends Emitter<ClientEvents> {
|
|
|
17
17
|
ping(): Promise<Advertisement | null>;
|
|
18
18
|
connect(): Promise<Advertisement>;
|
|
19
19
|
sendFrame(frame: Frame, priority: Priority): void;
|
|
20
|
+
frameAndSend(payload: Buffer, priority: Priority): void;
|
|
20
21
|
send(buffer: Buffer): void;
|
|
21
22
|
cleanup(): void;
|
|
22
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAmB,KAAK,MAAM,EAAgB,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAEN,KAAK,OAAO,EACZ,KAAK,aAAa,EAElB,KAAK,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAmB,KAAK,MAAM,EAAgB,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAEN,KAAK,OAAO,EACZ,KAAK,aAAa,EAElB,KAAK,EAOL,KAAK,QAAQ,EAEb,MAAM,EAGN,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,kBAAkB,CAAC;AAI5E,qBAAa,MAAO,SAAQ,OAAO,CAAC,YAAY,CAAC;IACzC,MAAM,EAAG,MAAM,CAAC;IAChB,MAAM,EAAG,MAAM,CAAC;IAChB,OAAO,EAAE,aAAa,CAAC;IAC9B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,OAAO,CAAkB;IAC1B,aAAa,EAAG,OAAO,CAAC;IAExB,MAAM,SAAuB;gBAExB,OAAO,GAAE,OAAO,CAAC,aAAa,CAAwB;IAO3D,UAAU;IAgBJ,IAAI,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAkBrC,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;IA8EvC,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAQjD,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAQvD,IAAI,CAAC,MAAM,EAAE,MAAM;IAyBnB,OAAO,IAAI,IAAI;CA4BtB"}
|
package/dist/client/client.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Client = void 0;
|
|
4
7
|
const emitter_1 = require("@serenityjs/emitter");
|
|
5
8
|
const node_dgram_1 = require("node:dgram");
|
|
6
9
|
const framer_1 = require("./framer");
|
|
7
10
|
const proto_1 = require("../proto");
|
|
11
|
+
const disconnect_1 = __importDefault(require("../proto/packets/disconnect"));
|
|
8
12
|
const client_options_1 = require("./client-options");
|
|
9
13
|
const utils_1 = require("../utils");
|
|
10
14
|
class Client extends emitter_1.Emitter {
|
|
@@ -56,6 +60,9 @@ class Client extends emitter_1.Emitter {
|
|
|
56
60
|
if (this.status === proto_1.Status.Connecting) {
|
|
57
61
|
throw new Error("Connection attempt already in progress");
|
|
58
62
|
}
|
|
63
|
+
if (this.status === proto_1.Status.Connected) {
|
|
64
|
+
throw new Error("Already connected");
|
|
65
|
+
}
|
|
59
66
|
this.status = proto_1.Status.Connecting;
|
|
60
67
|
this.initSocket();
|
|
61
68
|
this.timer = setInterval(() => this.emit("tick"), 50);
|
|
@@ -118,20 +125,61 @@ class Client extends emitter_1.Emitter {
|
|
|
118
125
|
}
|
|
119
126
|
}
|
|
120
127
|
sendFrame(frame, priority) {
|
|
121
|
-
|
|
128
|
+
try {
|
|
129
|
+
this.framer.sendFrame(frame, priority);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
utils_1.Logger.error("[Raknet] Failed to send frame", error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
frameAndSend(payload, priority) {
|
|
136
|
+
const frame = new proto_1.Frame();
|
|
137
|
+
frame.reliability = proto_1.Reliability.ReliableOrdered;
|
|
138
|
+
frame.payload = payload;
|
|
139
|
+
frame.orderChannel = 0;
|
|
140
|
+
this.sendFrame(frame, priority);
|
|
122
141
|
}
|
|
123
142
|
send(buffer) {
|
|
124
|
-
if (this.
|
|
125
|
-
utils_1.Logger.
|
|
126
|
-
|
|
143
|
+
if (this.status === proto_1.Status.Disconnected) {
|
|
144
|
+
utils_1.Logger.warn("[Client] Attempting to send packet while disconnected");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
utils_1.Logger.debug(`[Client] Sending packet ${buffer[0]}, ${buffer.length} bytes to ${this.options.address}:${this.options.port}`);
|
|
148
|
+
utils_1.Logger.debug(`[Client] Current connection status: ${proto_1.Status[this.status]}`);
|
|
149
|
+
try {
|
|
150
|
+
this.socket.send(buffer, 0, buffer.length, this.options.port, this.options.address);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
utils_1.Logger.error("[Client] Failed to send packet", error);
|
|
154
|
+
this.cleanup();
|
|
155
|
+
}
|
|
127
156
|
}
|
|
128
157
|
cleanup() {
|
|
129
|
-
this.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
this.status = proto_1.Status.
|
|
158
|
+
if (this.status === proto_1.Status.Disconnected) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
utils_1.Logger.info("[Client] Cleaning up connection and resources");
|
|
162
|
+
const wasConnected = this.status === proto_1.Status.Connected;
|
|
163
|
+
this.status = proto_1.Status.Disconnecting;
|
|
164
|
+
try {
|
|
165
|
+
// Send disconnect notification if we were connected
|
|
166
|
+
if (wasConnected) {
|
|
167
|
+
const disconnect = new disconnect_1.default();
|
|
168
|
+
this.send(disconnect.serialize());
|
|
169
|
+
}
|
|
170
|
+
this.removeAll();
|
|
171
|
+
this.socket.removeAllListeners();
|
|
172
|
+
this.socket.close();
|
|
173
|
+
clearInterval(this.timer);
|
|
174
|
+
clearTimeout(this.timeout);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
utils_1.Logger.error("[Client] Error during cleanup", error);
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
this.status = proto_1.Status.Disconnected;
|
|
181
|
+
utils_1.Logger.info("[Client] Cleanup complete, status set to Disconnected");
|
|
182
|
+
}
|
|
135
183
|
}
|
|
136
184
|
}
|
|
137
185
|
exports.Client = Client;
|
package/dist/client/framer.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare class Framer {
|
|
|
9
9
|
private lostFrameSequences;
|
|
10
10
|
private inputHighestSequenceIndex;
|
|
11
11
|
private inputOrderIndex;
|
|
12
|
-
protected inputOrderingQueue:
|
|
12
|
+
protected inputOrderingQueue: Array<Map<number, Frame>>;
|
|
13
13
|
protected readonly fragmentsQueue: Map<number, Map<number, Frame>>;
|
|
14
14
|
outputOrderIndex: number[];
|
|
15
15
|
outputSequenceIndex: number[];
|
|
@@ -17,9 +17,12 @@ export declare class Framer {
|
|
|
17
17
|
protected outputSequence: number;
|
|
18
18
|
protected outputSplitIndex: number;
|
|
19
19
|
protected outputReliableIndex: number;
|
|
20
|
-
|
|
20
|
+
outputFrames: Frame[];
|
|
21
|
+
private outputFramesByteLength;
|
|
21
22
|
outputBackup: Map<number, Frame[]>;
|
|
22
23
|
_tickCount: number;
|
|
24
|
+
private lastPingSent;
|
|
25
|
+
private lastPongReceived;
|
|
23
26
|
constructor(client: Client);
|
|
24
27
|
tick(): void;
|
|
25
28
|
incommingMessage(payload: Buffer, rinfo: RemoteInfo): void;
|
|
@@ -33,7 +36,6 @@ export declare class Framer {
|
|
|
33
36
|
private reassembleAndProcessFragment;
|
|
34
37
|
frameAndSend(payload: Buffer, priority?: Priority): void;
|
|
35
38
|
sendFrame(frame: Frame, priority: Priority): void;
|
|
36
|
-
private handleLargePayload;
|
|
37
39
|
private createSplitFrame;
|
|
38
40
|
private queueFrame;
|
|
39
41
|
sendQueue(amount: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framer.d.ts","sourceRoot":"","sources":["../../src/client/framer.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,EAGL,QAAQ,EAWR,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,qBAAa,MAAM;IAClB,OAAO,CAAC,MAAM,CAAS;
|
|
1
|
+
{"version":3,"file":"framer.d.ts","sourceRoot":"","sources":["../../src/client/framer.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,EAGL,QAAQ,EAWR,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,qBAAa,MAAM;IAClB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,sBAAsB,CAA0B;IACxD,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,yBAAyB,CAAmC;IACpE,OAAO,CAAC,eAAe,CAAmC;IAC1D,SAAS,CAAC,kBAAkB,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAGrD;IACF,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CACvD;IAEJ,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,gBAAgB,EAAE,QAAQ,CAAC;IAClC,SAAS,CAAC,cAAc,SAAK;IAC7B,SAAS,CAAC,gBAAgB,SAAK;IAC/B,SAAS,CAAC,mBAAmB,SAAK;IAC3B,YAAY,EAAE,KAAK,EAAE,CAAM;IAClC,OAAO,CAAC,sBAAsB,CAAK;IAC5B,YAAY,uBAA8B;IAC1C,UAAU,SAAK;IACtB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,gBAAgB,CAAK;gBAEjB,MAAM,EAAE,MAAM;IASnB,IAAI;IA2DJ,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU;IAgF1D,OAAO,CAAC,YAAY;IAsEb,MAAM,CAAC,QAAQ,EAAE,QAAQ;IAoDhC,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,4BAA4B;IA6B7B,YAAY,CAClB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,QAA0B,GAClC,IAAI;IAQA,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAiCxD,OAAO,CAAC,gBAAgB;IAwBxB,OAAO,CAAC,UAAU;IAgBX,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CA2BtC"}
|
package/dist/client/framer.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.Framer = void 0;
|
|
7
4
|
const proto_1 = require("../proto");
|
|
@@ -9,7 +6,6 @@ const proto_2 = require("../proto");
|
|
|
9
6
|
const utils_1 = require("../utils");
|
|
10
7
|
const binarystream_1 = require("@serenityjs/binarystream");
|
|
11
8
|
const connection_request_accepted_1 = require("../proto/packets/connection-request-accepted");
|
|
12
|
-
const disconnect_1 = __importDefault(require("../proto/packets/disconnect"));
|
|
13
9
|
class Framer {
|
|
14
10
|
client;
|
|
15
11
|
lastInputSequence = -1;
|
|
@@ -17,7 +13,7 @@ class Framer {
|
|
|
17
13
|
lostFrameSequences = new Set();
|
|
18
14
|
inputHighestSequenceIndex = new Array(64).fill(0);
|
|
19
15
|
inputOrderIndex = new Array(64).fill(0);
|
|
20
|
-
inputOrderingQueue = new Map();
|
|
16
|
+
inputOrderingQueue = Array.from({ length: 64 }, () => new Map());
|
|
21
17
|
fragmentsQueue = new Map();
|
|
22
18
|
outputOrderIndex;
|
|
23
19
|
outputSequenceIndex;
|
|
@@ -25,56 +21,69 @@ class Framer {
|
|
|
25
21
|
outputSequence = 0;
|
|
26
22
|
outputSplitIndex = 0;
|
|
27
23
|
outputReliableIndex = 0;
|
|
28
|
-
outputFrames =
|
|
24
|
+
outputFrames = [];
|
|
25
|
+
outputFramesByteLength = 0;
|
|
29
26
|
outputBackup = new Map();
|
|
30
27
|
_tickCount = 0;
|
|
28
|
+
lastPingSent = 0;
|
|
29
|
+
lastPongReceived = 0;
|
|
31
30
|
constructor(client) {
|
|
32
31
|
this.client = client;
|
|
33
32
|
this.outputFrameQueue = new proto_2.Frameset();
|
|
34
33
|
this.outputFrameQueue.frames = [];
|
|
35
34
|
this.outputOrderIndex = Array.from({ length: 32 }).fill(0);
|
|
36
35
|
this.outputSequenceIndex = Array.from({ length: 32 }).fill(0);
|
|
37
|
-
|
|
38
|
-
this.inputOrderingQueue.set(index, new Map());
|
|
39
|
-
}
|
|
36
|
+
this.lastPongReceived = Date.now();
|
|
40
37
|
}
|
|
41
38
|
tick() {
|
|
42
39
|
this._tickCount++;
|
|
43
40
|
if (this.client.status === proto_1.Status.Disconnected ||
|
|
44
|
-
this.client.status === proto_1.Status.Disconnecting)
|
|
41
|
+
this.client.status === proto_1.Status.Disconnecting) {
|
|
42
|
+
utils_1.Logger.debug(`[Framer] Skipping tick - client status: ${proto_1.Status[this.client.status]}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
if (now - this.lastPongReceived > 30000 &&
|
|
47
|
+
this.client.status === proto_1.Status.Connected) {
|
|
48
|
+
utils_1.Logger.warn("[Framer] No pong received in last 30 seconds, disconnecting");
|
|
49
|
+
this.client.cleanup();
|
|
45
50
|
return;
|
|
46
|
-
|
|
51
|
+
}
|
|
52
|
+
if (this._tickCount % 50 === 0) {
|
|
53
|
+
this.lastPingSent = now;
|
|
54
|
+
const ping = new proto_1.ConnectedPing();
|
|
55
|
+
ping.timestamp = BigInt(now);
|
|
56
|
+
this.frameAndSend(ping.serialize(), proto_1.Priority.Immediate);
|
|
57
|
+
utils_1.Logger.debug(`[Framer] Sent ping at ${now}, last pong received: ${this.lastPongReceived}`);
|
|
58
|
+
}
|
|
59
|
+
const ackSeqs = this.receivedFrameSequences;
|
|
60
|
+
if (ackSeqs.size > 0) {
|
|
61
|
+
this.receivedFrameSequences = new Set();
|
|
62
|
+
utils_1.Logger.debug(`[Framer] Sending ACK for ${ackSeqs.size} sequences`);
|
|
47
63
|
const ack = new proto_1.Ack();
|
|
48
|
-
ack.sequences = Array.from(
|
|
49
|
-
this.receivedFrameSequences.delete(seq);
|
|
50
|
-
return seq;
|
|
51
|
-
});
|
|
64
|
+
ack.sequences = Array.from(ackSeqs);
|
|
52
65
|
this.client.send(ack.serialize());
|
|
53
66
|
}
|
|
54
|
-
|
|
67
|
+
const nackSeqs = this.lostFrameSequences;
|
|
68
|
+
if (nackSeqs.size > 0) {
|
|
69
|
+
this.lostFrameSequences = new Set();
|
|
70
|
+
utils_1.Logger.debug(`[Framer] Sending NACK for ${nackSeqs.size} sequences`);
|
|
55
71
|
const pk = new proto_1.Nack();
|
|
56
|
-
pk.sequences = Array.from(
|
|
57
|
-
this.lostFrameSequences.delete(seq);
|
|
58
|
-
return seq;
|
|
59
|
-
});
|
|
72
|
+
pk.sequences = Array.from(nackSeqs);
|
|
60
73
|
this.client.send(pk.serialize());
|
|
61
74
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
ping.timestamp = BigInt(Date.now());
|
|
65
|
-
this.frameAndSend(ping.serialize(), proto_1.Priority.Normal);
|
|
66
|
-
}
|
|
67
|
-
this.sendQueue(this.outputFrames.size);
|
|
75
|
+
utils_1.Logger.debug(`[Framer] Queue state - Frames: ${this.outputFrames.length}, Backup: ${this.outputBackup.size}`);
|
|
76
|
+
this.sendQueue(this.outputFrames.length);
|
|
68
77
|
}
|
|
69
78
|
incommingMessage(payload, rinfo) {
|
|
70
79
|
let header = payload.readUint8();
|
|
71
80
|
if ((header & 0xf0) === 0x80)
|
|
72
81
|
header = 0x80;
|
|
73
|
-
|
|
74
|
-
utils_1.Logger.debug(`Received packet ${header} from ${rinfo.address}:${rinfo.port}`);
|
|
82
|
+
utils_1.Logger.debug(`[Framer] Received packet ${header} from ${rinfo.address}:${rinfo.port}`);
|
|
75
83
|
switch (header) {
|
|
76
84
|
case proto_1.Packet.Ack: {
|
|
77
85
|
const ack = new proto_1.Ack(payload).deserialize();
|
|
86
|
+
utils_1.Logger.debug(`[Framer] Processing ACK with ${ack.sequences.length} sequences`);
|
|
78
87
|
for (const seq of ack.sequences) {
|
|
79
88
|
this.outputBackup.delete(seq);
|
|
80
89
|
}
|
|
@@ -82,12 +91,13 @@ class Framer {
|
|
|
82
91
|
}
|
|
83
92
|
case proto_1.Packet.Nack: {
|
|
84
93
|
const nack = new proto_1.Nack(payload).deserialize();
|
|
94
|
+
utils_1.Logger.debug(`[Framer] Processing NACK with ${nack.sequences.length} sequences`);
|
|
85
95
|
for (const seq of nack.sequences) {
|
|
86
96
|
const lostFrames = this.outputBackup.get(seq) ?? [];
|
|
97
|
+
utils_1.Logger.debug(`[Framer] Resending ${lostFrames.length} lost frames for sequence ${seq}`);
|
|
87
98
|
for (const lostFrame of lostFrames) {
|
|
88
99
|
this.sendFrame(lostFrame, proto_1.Priority.Immediate);
|
|
89
100
|
}
|
|
90
|
-
// this.outputBackup.delete(seq);
|
|
91
101
|
}
|
|
92
102
|
break;
|
|
93
103
|
}
|
|
@@ -133,8 +143,7 @@ class Framer {
|
|
|
133
143
|
}
|
|
134
144
|
processFrame(frame) {
|
|
135
145
|
const header = frame.payload[0];
|
|
136
|
-
|
|
137
|
-
utils_1.Logger.debug(`Received FrameSet Packet ${header}`);
|
|
146
|
+
utils_1.Logger.debug(`[Framer] Processing frame with header ${header}`);
|
|
138
147
|
if (this.client.status === proto_1.Status.Connecting) {
|
|
139
148
|
switch (header) {
|
|
140
149
|
case proto_1.Packet.ConnectionRequest: {
|
|
@@ -155,7 +164,7 @@ class Framer {
|
|
|
155
164
|
break;
|
|
156
165
|
}
|
|
157
166
|
case proto_1.Packet.DisconnectionNotification: {
|
|
158
|
-
|
|
167
|
+
utils_1.Logger.info("[Framer] Received disconnection notification while connecting");
|
|
159
168
|
this.client.cleanup();
|
|
160
169
|
break;
|
|
161
170
|
}
|
|
@@ -172,12 +181,19 @@ class Framer {
|
|
|
172
181
|
this.frameAndSend(pong.serialize(), proto_1.Priority.Immediate);
|
|
173
182
|
break;
|
|
174
183
|
}
|
|
184
|
+
case proto_1.Packet.ConnectedPong: {
|
|
185
|
+
const packet = new proto_1.ConnectedPong(frame.payload).deserialize();
|
|
186
|
+
this.lastPongReceived = Date.now();
|
|
187
|
+
utils_1.Logger.debug(`[Framer] Received pong, latency: ${Date.now() - Number(packet.pingTime)}ms`);
|
|
188
|
+
this.client.emit("connected-pong", packet);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
175
191
|
case 0xfe: {
|
|
176
192
|
this.client.emit("encapsulated", frame.payload);
|
|
177
193
|
break;
|
|
178
194
|
}
|
|
179
195
|
case proto_1.Packet.DisconnectionNotification: {
|
|
180
|
-
|
|
196
|
+
utils_1.Logger.info("[Framer] Received disconnection notification");
|
|
181
197
|
this.client.cleanup();
|
|
182
198
|
break;
|
|
183
199
|
}
|
|
@@ -187,20 +203,19 @@ class Framer {
|
|
|
187
203
|
handle(frameSet) {
|
|
188
204
|
try {
|
|
189
205
|
if (this.receivedFrameSequences.has(frameSet.sequence)) {
|
|
190
|
-
|
|
191
|
-
utils_1.Logger.debug(`Received duplicate frameset ${frameSet.sequence}`);
|
|
206
|
+
utils_1.Logger.debug(`[Framer] Received duplicate frameset ${frameSet.sequence}`);
|
|
192
207
|
return;
|
|
193
208
|
}
|
|
194
209
|
this.lostFrameSequences.delete(frameSet.sequence);
|
|
195
210
|
if (frameSet.sequence < this.lastInputSequence ||
|
|
196
211
|
frameSet.sequence === this.lastInputSequence) {
|
|
197
|
-
|
|
198
|
-
utils_1.Logger.debug(`Received out of order frameset ${frameSet.sequence}!`);
|
|
212
|
+
utils_1.Logger.debug(`[Framer] Received out of order frameset ${frameSet.sequence}!`);
|
|
199
213
|
return;
|
|
200
214
|
}
|
|
201
215
|
this.receivedFrameSequences.add(frameSet.sequence);
|
|
202
216
|
const diff = frameSet.sequence - this.lastInputSequence;
|
|
203
217
|
if (diff > 1) {
|
|
218
|
+
utils_1.Logger.debug(`[Framer] Detected ${diff - 1} missing sequences between ${this.lastInputSequence} and ${frameSet.sequence}`);
|
|
204
219
|
for (let index = this.lastInputSequence + 1; index < frameSet.sequence; index++) {
|
|
205
220
|
this.lostFrameSequences.add(index);
|
|
206
221
|
}
|
|
@@ -211,15 +226,18 @@ class Framer {
|
|
|
211
226
|
this.handleFrame(frame);
|
|
212
227
|
}
|
|
213
228
|
catch (err) {
|
|
214
|
-
utils_1.Logger.error("Error handling frame", err);
|
|
229
|
+
utils_1.Logger.error("[Framer] Error handling frame", err);
|
|
215
230
|
}
|
|
216
231
|
}
|
|
217
232
|
}
|
|
218
233
|
catch (err) {
|
|
219
|
-
utils_1.Logger.error("Error handling frameset", err);
|
|
234
|
+
utils_1.Logger.error("[Framer] Error handling frameset", err);
|
|
220
235
|
}
|
|
221
236
|
}
|
|
222
237
|
handleFrame(frame) {
|
|
238
|
+
if (this.client.options.debug) {
|
|
239
|
+
utils_1.Logger.debug(`[Framer] Handling frame - Split: ${frame.isSplit}, Sequenced: ${frame.isSequenced}, Ordered: ${frame.isOrdered}`);
|
|
240
|
+
}
|
|
223
241
|
if (frame.isSplit) {
|
|
224
242
|
this.handleSplit(frame);
|
|
225
243
|
}
|
|
@@ -241,7 +259,7 @@ class Framer {
|
|
|
241
259
|
else if (frame.orderedFrameIndex > expectedOrderIndex) {
|
|
242
260
|
if (this.client.options.debug)
|
|
243
261
|
utils_1.Logger.debug(`Queuing out-of-order frame: ${frame.orderedFrameIndex}`);
|
|
244
|
-
const unorderedQueue = this.inputOrderingQueue
|
|
262
|
+
const unorderedQueue = this.inputOrderingQueue[frame.orderChannel];
|
|
245
263
|
if (!unorderedQueue)
|
|
246
264
|
return;
|
|
247
265
|
unorderedQueue.set(frame.orderedFrameIndex, frame);
|
|
@@ -255,7 +273,7 @@ class Framer {
|
|
|
255
273
|
this.inputOrderIndex[frame.orderChannel] = frame.orderedFrameIndex + 1;
|
|
256
274
|
this.inputHighestSequenceIndex[frame.orderChannel] = 0;
|
|
257
275
|
this.processFrame(frame);
|
|
258
|
-
const outOfOrderQueue = this.inputOrderingQueue
|
|
276
|
+
const outOfOrderQueue = this.inputOrderingQueue[frame.orderChannel];
|
|
259
277
|
let nextOrderIndex = this.inputOrderIndex[frame.orderChannel];
|
|
260
278
|
for (; outOfOrderQueue.has(nextOrderIndex); nextOrderIndex++) {
|
|
261
279
|
const nextFrame = outOfOrderQueue.get(nextOrderIndex);
|
|
@@ -264,7 +282,6 @@ class Framer {
|
|
|
264
282
|
outOfOrderQueue.delete(nextOrderIndex);
|
|
265
283
|
}
|
|
266
284
|
}
|
|
267
|
-
this.inputOrderingQueue.set(frame.orderChannel, outOfOrderQueue);
|
|
268
285
|
this.inputOrderIndex[frame.orderChannel] = nextOrderIndex;
|
|
269
286
|
}
|
|
270
287
|
handleSequenced(frame) {
|
|
@@ -335,7 +352,11 @@ class Framer {
|
|
|
335
352
|
const maxSize = this.client.options.mtuSize - 36;
|
|
336
353
|
const splitSize = Math.ceil(frame.payload.byteLength / maxSize);
|
|
337
354
|
if (frame.payload.byteLength > maxSize) {
|
|
338
|
-
this.
|
|
355
|
+
const splitId = this.outputSplitIndex++ & 0xffff;
|
|
356
|
+
for (let index = 0; index < frame.payload.byteLength; index += maxSize) {
|
|
357
|
+
const nframe = this.createSplitFrame(frame, index, maxSize, splitId, splitSize);
|
|
358
|
+
this.queueFrame(nframe, proto_1.Priority.Immediate);
|
|
359
|
+
}
|
|
339
360
|
}
|
|
340
361
|
else {
|
|
341
362
|
if (frame.isReliable)
|
|
@@ -343,13 +364,6 @@ class Framer {
|
|
|
343
364
|
this.queueFrame(frame, priority);
|
|
344
365
|
}
|
|
345
366
|
}
|
|
346
|
-
handleLargePayload(frame, maxSize, splitSize) {
|
|
347
|
-
const splitId = this.outputSplitIndex++ % 65_536;
|
|
348
|
-
for (let index = 0; index < frame.payload.byteLength; index += maxSize) {
|
|
349
|
-
const nframe = this.createSplitFrame(frame, index, maxSize, splitId, splitSize);
|
|
350
|
-
this.queueFrame(nframe, proto_1.Priority.Immediate);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
367
|
createSplitFrame(originalFrame, index, maxSize, splitId, splitSize) {
|
|
354
368
|
const nframe = new proto_1.Frame();
|
|
355
369
|
nframe.reliableFrameIndex = this.outputReliableIndex++;
|
|
@@ -367,27 +381,30 @@ class Framer {
|
|
|
367
381
|
return nframe;
|
|
368
382
|
}
|
|
369
383
|
queueFrame(frame, priority) {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if (length + frame.getByteLength() > this.client.options.mtuSize - 36) {
|
|
375
|
-
this.sendQueue(this.outputFrames.size);
|
|
384
|
+
const frameLength = frame.getByteLength();
|
|
385
|
+
const totalLength = 4 + this.outputFramesByteLength + frameLength;
|
|
386
|
+
if (totalLength > this.client.options.mtuSize - 36) {
|
|
387
|
+
this.sendQueue(this.outputFrames.length);
|
|
376
388
|
}
|
|
377
|
-
this.outputFrames.
|
|
389
|
+
this.outputFrames.push(frame);
|
|
390
|
+
this.outputFramesByteLength += frameLength;
|
|
378
391
|
if (priority === proto_1.Priority.Immediate) {
|
|
379
392
|
this.sendQueue(1);
|
|
380
393
|
}
|
|
381
394
|
}
|
|
382
395
|
sendQueue(amount) {
|
|
383
|
-
if (this.outputFrames.
|
|
396
|
+
if (this.outputFrames.length === 0)
|
|
384
397
|
return;
|
|
398
|
+
utils_1.Logger.debug(`[Framer] Sending queue with ${amount} frames, total queued: ${this.outputFrames.length}`);
|
|
385
399
|
const frameset = new proto_2.Frameset();
|
|
386
400
|
frameset.sequence = this.outputSequence++;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
401
|
+
const framesToSend = this.outputFrames.slice(0, amount);
|
|
402
|
+
frameset.frames = framesToSend;
|
|
403
|
+
this.outputFrames = this.outputFrames.slice(amount);
|
|
404
|
+
const sentLength = framesToSend.reduce((sum, f) => sum + f.getByteLength(), 0);
|
|
405
|
+
this.outputFramesByteLength -= sentLength;
|
|
406
|
+
this.outputBackup.set(frameset.sequence, framesToSend);
|
|
407
|
+
utils_1.Logger.debug(`[Framer] Frameset sequence: ${frameset.sequence}, remaining in queue: ${this.outputFrames.length}`);
|
|
391
408
|
this.client.send(frameset.serialize());
|
|
392
409
|
}
|
|
393
410
|
}
|
package/dist/tests/server.js
CHANGED
|
@@ -11,7 +11,7 @@ const server = new server_1.Server({
|
|
|
11
11
|
});
|
|
12
12
|
server.start();
|
|
13
13
|
server.on("connect", (connection) => {
|
|
14
|
-
utils_1.Logger.info(`Connection from ${connection.remoteInfo.address}:${connection.remoteInfo.port} established in
|
|
14
|
+
utils_1.Logger.info(`Connection from ${connection.remoteInfo.address}:${connection.remoteInfo.port} established in unknown ms`);
|
|
15
15
|
connection.on("encapsulated", (packet) => {
|
|
16
16
|
utils_1.Logger.info(`Received Encapsulated packet: ${packet.toString("hex")}`);
|
|
17
17
|
});
|
package/dist/utils/Logger.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../src/utils/Logger.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../src/utils/Logger.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAuC/E,QAAA,MAAM,MAAM;;;kBAIG,OAAO,EAAE,GAAG,IAAI;mBAIf,OAAO,EAAE,GAAG,IAAI;kBAIjB,OAAO,EAAE,GAAG,IAAI;mBAIf,OAAO,EAAE,GAAG,IAAI;kBAKjB,OAAO,EAAE,GAAG,IAAI;YAItB,MAAM;iBAOD,OAAO,EAAE,GAAG,IAAI;kBAKf,OAAO,EAAE,GAAG,IAAI;sBAIZ,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE;CAkClD,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
|