@sanctumterra/raknet 1.3.61 → 1.3.64
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 -4
- package/dist/client/client-events.d.ts.map +1 -1
- package/dist/client/client-options.d.ts +23 -0
- package/dist/client/client-options.d.ts.map +1 -0
- package/dist/client/client-options.js +24 -0
- package/dist/client/client.d.ts +26 -11
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +222 -102
- package/dist/client/framer.d.ts +49 -0
- package/dist/client/framer.d.ts.map +1 -0
- package/dist/client/framer.js +368 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/proto/packets/index.d.ts +0 -1
- package/dist/proto/packets/index.d.ts.map +1 -1
- package/dist/proto/packets/index.js +0 -1
- package/dist/proto/types/valid.d.ts +1 -2
- package/dist/proto/types/valid.d.ts.map +1 -1
- package/dist/tests/benchmark.d.ts +2 -0
- package/dist/tests/benchmark.d.ts.map +1 -0
- package/dist/tests/benchmark.js +71 -0
- package/dist/tests/localhost.js +3 -1
- package/dist/tests/test.d.ts +2 -0
- package/dist/tests/test.d.ts.map +1 -0
- package/dist/tests/test.js +49 -0
- package/dist/utils/Logger.d.ts +14 -0
- package/dist/utils/Logger.d.ts.map +1 -0
- package/dist/utils/Logger.js +98 -0
- package/dist/utils/buffer-pool.d.ts +5 -0
- package/dist/utils/buffer-pool.d.ts.map +1 -0
- package/dist/utils/buffer-pool.js +22 -0
- package/dist/utils/decorators.d.ts +3 -0
- package/dist/utils/decorators.d.ts.map +1 -0
- package/dist/utils/decorators.js +62 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/package.json +4 -7
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Ack, ConnectedPing, ConnectionRequest, NewIncomingConnection, OpenConnectionReplyOne, OpenConnectionReplyTwo, OpenConnectionRequestOne, OpenConnectionRequestTwo, UnconnectedPing, UnconnectedPong
|
|
1
|
+
import type { Ack, ConnectedPing, ConnectionRequest, NewIncomingConnection, OpenConnectionReplyOne, OpenConnectionReplyTwo, OpenConnectionRequestOne, OpenConnectionRequestTwo, UnconnectedPing, UnconnectedPong } from "../proto";
|
|
2
|
+
import type { Frameset } from "../proto/packets/frameset";
|
|
2
3
|
export interface ClientEvents {
|
|
3
4
|
"open-connection-reply-one": [OpenConnectionReplyOne];
|
|
4
5
|
"open-connection-reply-two": [OpenConnectionReplyTwo];
|
|
@@ -10,11 +11,8 @@ export interface ClientEvents {
|
|
|
10
11
|
"connected-ping": [ConnectedPing];
|
|
11
12
|
"connection-request": [ConnectionRequest];
|
|
12
13
|
"new-incoming-connection": [NewIncomingConnection];
|
|
13
|
-
"connection-request-accepted": [ConnectionRequestAccepted];
|
|
14
|
-
"connected-pong": [ConnectedPong];
|
|
15
14
|
encapsulated: [Buffer];
|
|
16
15
|
ack: [Ack];
|
|
17
|
-
nack: [Nack];
|
|
18
16
|
error: [Error];
|
|
19
17
|
close: [];
|
|
20
18
|
connect: [];
|
|
@@ -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,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,
|
|
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,iBAAiB,EACjB,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,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,EAAE,CAAC;IACZ,IAAI,EAAE,EAAE,CAAC;CACT"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type ClientOptions = {
|
|
2
|
+
address: string;
|
|
3
|
+
port: number;
|
|
4
|
+
protocolVersion: number;
|
|
5
|
+
mtuSize: number;
|
|
6
|
+
clientId: bigint;
|
|
7
|
+
debug: boolean;
|
|
8
|
+
timeout: number;
|
|
9
|
+
maxFrameQueueSize: number;
|
|
10
|
+
fragmentTimeout: number;
|
|
11
|
+
enableBufferPooling: boolean;
|
|
12
|
+
gcInterval: number;
|
|
13
|
+
socketBufferMultiplier: number;
|
|
14
|
+
tickInterval: number;
|
|
15
|
+
connectionRetryInterval: number;
|
|
16
|
+
initialConnectionTimeout: number;
|
|
17
|
+
batchSize: number;
|
|
18
|
+
maxPipelineStages: number;
|
|
19
|
+
fastPathEnabled: boolean;
|
|
20
|
+
};
|
|
21
|
+
declare const defaultClientOptions: ClientOptions;
|
|
22
|
+
export { type ClientOptions, defaultClientOptions };
|
|
23
|
+
//# sourceMappingURL=client-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-options.d.ts","sourceRoot":"","sources":["../../src/client/client-options.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,EAAE,MAAM,CAAC;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,QAAA,MAAM,oBAAoB,EAAE,aAmB3B,CAAC;AAEF,OAAO,EAAE,KAAK,aAAa,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultClientOptions = void 0;
|
|
4
|
+
const defaultClientOptions = {
|
|
5
|
+
address: "127.0.0.1",
|
|
6
|
+
port: 19132,
|
|
7
|
+
protocolVersion: 11,
|
|
8
|
+
mtuSize: 1492,
|
|
9
|
+
clientId: BigInt(Math.floor(Math.random() * 1000000000000000000)),
|
|
10
|
+
debug: false,
|
|
11
|
+
timeout: 3000,
|
|
12
|
+
maxFrameQueueSize: 1000,
|
|
13
|
+
fragmentTimeout: 10000,
|
|
14
|
+
enableBufferPooling: true,
|
|
15
|
+
gcInterval: 60000,
|
|
16
|
+
socketBufferMultiplier: 2048,
|
|
17
|
+
tickInterval: 8,
|
|
18
|
+
connectionRetryInterval: 100,
|
|
19
|
+
initialConnectionTimeout: 800,
|
|
20
|
+
batchSize: 16,
|
|
21
|
+
maxPipelineStages: 2,
|
|
22
|
+
fastPathEnabled: true,
|
|
23
|
+
};
|
|
24
|
+
exports.defaultClientOptions = defaultClientOptions;
|
package/dist/client/client.d.ts
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
|
-
import Emitter from "@serenityjs/emitter";
|
|
2
|
-
import { type ClientOptions } from "./client_options";
|
|
1
|
+
import { Emitter } from "@serenityjs/emitter";
|
|
3
2
|
import type { ClientEvents } from "./client-events";
|
|
4
|
-
import { type
|
|
3
|
+
import { type Socket } from "node:dgram";
|
|
4
|
+
import { Framer } from "./framer";
|
|
5
|
+
import { Address, type Advertisement, type Frame, Priority } from "../proto";
|
|
6
|
+
import { type ClientOptions } from "./client-options";
|
|
5
7
|
export declare class Client extends Emitter<ClientEvents> {
|
|
6
|
-
|
|
8
|
+
socket: Socket;
|
|
9
|
+
framer: Framer;
|
|
7
10
|
options: ClientOptions;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
private timer;
|
|
12
|
+
private timeout;
|
|
13
|
+
serverAddress: Address;
|
|
14
|
+
private isConnecting;
|
|
15
|
+
private packetHandlers;
|
|
16
|
+
private fastPathPackets;
|
|
17
|
+
constructor(options?: Partial<ClientOptions>);
|
|
18
|
+
initSocket(): void;
|
|
19
|
+
ping(): Promise<Advertisement | null>;
|
|
12
20
|
connect(): Promise<Advertisement>;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
private setupConnection;
|
|
22
|
+
sendFrame(frame: Frame, priority: Priority): void;
|
|
23
|
+
send(buffer: Buffer): void;
|
|
24
|
+
private onMessage;
|
|
25
|
+
private cleanup;
|
|
26
|
+
private handleAck;
|
|
27
|
+
private handleUnconnectedPong;
|
|
28
|
+
private handleOpenConnectionReplyOne;
|
|
29
|
+
private handleOpenConnectionReplyTwo;
|
|
30
|
+
private handleFrameSet;
|
|
16
31
|
}
|
|
17
32
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,qBAAqB,CAAC;
|
|
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,OAAO,EACP,KAAK,aAAa,EAElB,KAAK,KAAK,EAOV,QAAQ,EAGR,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,kBAAkB,CAAC;AAK5E,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;IAC/B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAwD;IAC9E,OAAO,CAAC,eAAe,CAKpB;gBAES,OAAO,GAAE,OAAO,CAAC,aAAa,CAAwB;IAmB3D,UAAU;IAaJ,IAAI,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IA2BrC,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;YAmBhC,eAAe;IAyDtB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIjD,IAAI,CAAC,MAAM,EAAE,MAAM;IAe1B,OAAO,CAAC,SAAS;IAyBjB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,4BAA4B;IAkBpC,OAAO,CAAC,4BAA4B;IAuCpC,OAAO,CAAC,cAAc;CAKtB"}
|
package/dist/client/client.js
CHANGED
|
@@ -1,129 +1,249 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4
10
|
};
|
|
5
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
12
|
exports.Client = void 0;
|
|
7
|
-
const emitter_1 =
|
|
8
|
-
const
|
|
9
|
-
const
|
|
13
|
+
const emitter_1 = require("@serenityjs/emitter");
|
|
14
|
+
const node_dgram_1 = require("node:dgram");
|
|
15
|
+
const framer_1 = require("./framer");
|
|
10
16
|
const proto_1 = require("../proto");
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
const client_options_1 = require("./client-options");
|
|
18
|
+
const utils_1 = require("../utils");
|
|
19
|
+
const frameset_1 = require("../proto/packets/frameset");
|
|
20
|
+
const decorators_1 = require("../utils/decorators");
|
|
21
|
+
class Client extends emitter_1.Emitter {
|
|
22
|
+
socket;
|
|
23
|
+
framer;
|
|
13
24
|
options;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
timer;
|
|
26
|
+
timeout;
|
|
27
|
+
serverAddress;
|
|
28
|
+
isConnecting = false;
|
|
29
|
+
packetHandlers;
|
|
30
|
+
fastPathPackets = new Set([
|
|
31
|
+
proto_1.Packet.Ack,
|
|
32
|
+
proto_1.Packet.Nack,
|
|
33
|
+
proto_1.Packet.ConnectedPing,
|
|
34
|
+
proto_1.Packet.ConnectedPong,
|
|
35
|
+
]);
|
|
36
|
+
constructor(options = client_options_1.defaultClientOptions) {
|
|
18
37
|
super();
|
|
19
38
|
this.options = { ...client_options_1.defaultClientOptions, ...options };
|
|
20
|
-
this.
|
|
39
|
+
this.maxListeners = 20;
|
|
40
|
+
this.packetHandlers = new Map([
|
|
41
|
+
[proto_1.Packet.Ack, this.handleAck.bind(this)],
|
|
42
|
+
[proto_1.Packet.UnconnectedPong, this.handleUnconnectedPong.bind(this)],
|
|
43
|
+
[
|
|
44
|
+
proto_1.Packet.OpenConnectionReplyOne,
|
|
45
|
+
this.handleOpenConnectionReplyOne.bind(this),
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
proto_1.Packet.OpenConnectionReplyTwo,
|
|
49
|
+
this.handleOpenConnectionReplyTwo.bind(this),
|
|
50
|
+
],
|
|
51
|
+
[proto_1.Packet.FrameSet, this.handleFrameSet.bind(this)],
|
|
52
|
+
]);
|
|
21
53
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
54
|
+
initSocket() {
|
|
55
|
+
try {
|
|
56
|
+
this.socket = (0, node_dgram_1.createSocket)("udp4");
|
|
57
|
+
this.framer = new framer_1.Framer(this);
|
|
58
|
+
this.remove("tick", () => this.framer.tick());
|
|
59
|
+
this.on("tick", () => this.framer.tick());
|
|
60
|
+
this.socket.removeAllListeners("message");
|
|
61
|
+
this.socket.on("message", this.onMessage.bind(this));
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
utils_1.Logger.error(`Failed to create socket: ${error}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async ping() {
|
|
34
68
|
return new Promise((resolve, reject) => {
|
|
35
|
-
|
|
36
|
-
this.
|
|
37
|
-
|
|
69
|
+
const timeoutId = setTimeout(() => {
|
|
70
|
+
this.removeAll("unconnected-pong");
|
|
71
|
+
reject(new Error("Ping timed out"));
|
|
72
|
+
}, this.options.initialConnectionTimeout);
|
|
73
|
+
const sendPing = () => {
|
|
74
|
+
const unconnectedPing = new proto_1.UnconnectedPing();
|
|
75
|
+
unconnectedPing.guid = this.options.clientId;
|
|
76
|
+
unconnectedPing.clientTimestamp = BigInt(Date.now());
|
|
77
|
+
this.send(unconnectedPing.serialize());
|
|
78
|
+
};
|
|
79
|
+
sendPing();
|
|
80
|
+
const pingInterval = setInterval(sendPing, 50);
|
|
81
|
+
this.once("unconnected-pong", (packet) => {
|
|
82
|
+
clearTimeout(timeoutId);
|
|
83
|
+
clearInterval(pingInterval);
|
|
84
|
+
resolve((0, proto_1.fromString)(packet.message));
|
|
38
85
|
});
|
|
39
86
|
});
|
|
40
87
|
}
|
|
41
|
-
async
|
|
88
|
+
async connect() {
|
|
89
|
+
if (this.isConnecting)
|
|
90
|
+
throw new Error("Connection attempt already in progress");
|
|
91
|
+
try {
|
|
92
|
+
this.isConnecting = true;
|
|
93
|
+
this.initSocket();
|
|
94
|
+
const [advertisement] = await Promise.all([
|
|
95
|
+
this.ping(),
|
|
96
|
+
this.setupConnection(),
|
|
97
|
+
]);
|
|
98
|
+
if (!advertisement)
|
|
99
|
+
throw new Error("Failed to get server advertisement");
|
|
100
|
+
return advertisement;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
this.isConnecting = false;
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async setupConnection() {
|
|
108
|
+
this.timer = setInterval(() => this.emit("tick"), this.options.tickInterval);
|
|
109
|
+
const request = new proto_1.OpenConnectionRequestOne();
|
|
110
|
+
request.mtu = this.options.mtuSize;
|
|
111
|
+
request.protocol = this.options.protocolVersion;
|
|
42
112
|
return new Promise((resolve, reject) => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const pongHandler = (pong) => {
|
|
48
|
-
this.advertisement = (0, proto_1.fromString)(pong.message);
|
|
49
|
-
cleanup();
|
|
50
|
-
resolve((0, proto_1.fromString)(pong.message));
|
|
51
|
-
};
|
|
113
|
+
let connectionAttempts = 0;
|
|
114
|
+
const maxAttempts = 3;
|
|
115
|
+
let isResolved = false;
|
|
116
|
+
let timeoutId;
|
|
52
117
|
const cleanup = () => {
|
|
53
|
-
clearTimeout(
|
|
54
|
-
this.
|
|
118
|
+
clearTimeout(timeoutId);
|
|
119
|
+
this.removeAll("open-connection-reply-one");
|
|
120
|
+
this.removeAll("new-incoming-connection");
|
|
121
|
+
};
|
|
122
|
+
const attemptConnection = () => {
|
|
123
|
+
if (isResolved)
|
|
124
|
+
return;
|
|
125
|
+
if (connectionAttempts >= maxAttempts) {
|
|
126
|
+
cleanup();
|
|
127
|
+
reject(new Error("Connection timed out"));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
connectionAttempts++;
|
|
131
|
+
this.emit("open-connection-request-one", request);
|
|
132
|
+
this.send(request.serialize());
|
|
133
|
+
const delay = connectionAttempts === 1
|
|
134
|
+
? 50
|
|
135
|
+
: Math.min(75 * 1.5 ** (connectionAttempts - 1), 200);
|
|
136
|
+
timeoutId = setTimeout(attemptConnection, delay);
|
|
55
137
|
};
|
|
56
|
-
|
|
57
|
-
this.once("
|
|
138
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
|
139
|
+
this.once("open-connection-reply-one", () => (connectionAttempts = 0));
|
|
140
|
+
this.onceAfter("new-incoming-connection", () => {
|
|
141
|
+
if (!isResolved) {
|
|
142
|
+
isResolved = true;
|
|
143
|
+
cleanup();
|
|
144
|
+
this.emit("connect");
|
|
145
|
+
this.isConnecting = false;
|
|
146
|
+
resolve();
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
attemptConnection();
|
|
58
150
|
});
|
|
59
151
|
}
|
|
60
|
-
|
|
61
|
-
this.
|
|
152
|
+
sendFrame(frame, priority) {
|
|
153
|
+
this.framer.sendFrame(frame, priority);
|
|
62
154
|
}
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
return;
|
|
155
|
+
send(buffer) {
|
|
156
|
+
if (this.options.debug) {
|
|
157
|
+
utils_1.Logger.debug(`Sending ${buffer[0]}, ${buffer.length} bytes to ${this.options.address}:${this.options.port}`);
|
|
67
158
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
case proto_1.Packet.Ack: {
|
|
77
|
-
const ack = new proto_1.Ack(data).deserialize();
|
|
78
|
-
this.emit("ack", ack);
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
case proto_1.Packet.FrameSet: {
|
|
82
|
-
const frameset = new proto_1.Frameset(data).deserialize();
|
|
83
|
-
this.emit("frameset", frameset);
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
case proto_1.Packet.ConnectedPing: {
|
|
87
|
-
const connectedPing = new proto_1.ConnectedPing(data).deserialize();
|
|
88
|
-
this.emit("connected-ping", connectedPing);
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
case proto_1.Packet.ConnectionRequest: {
|
|
92
|
-
const connectionRequest = new proto_1.ConnectionRequest(data).deserialize();
|
|
93
|
-
this.emit("connection-request", connectionRequest);
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
case proto_1.Packet.NewIncomingConnection: {
|
|
97
|
-
const newIncomingConnection = new proto_1.NewIncomingConnection(data).deserialize();
|
|
98
|
-
this.emit("new-incoming-connection", newIncomingConnection);
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
case proto_1.Packet.UnconnectedPing: {
|
|
102
|
-
const unconnectedPing = new proto_1.UnconnectedPing(data).deserialize();
|
|
103
|
-
this.emit("unconnected-ping", unconnectedPing);
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
case proto_1.Packet.UnconnectedPong: {
|
|
107
|
-
const unconnectedPong = new proto_1.UnconnectedPong(data).deserialize();
|
|
108
|
-
this.emit("unconnected-pong", unconnectedPong);
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
case proto_1.Packet.Nack: {
|
|
112
|
-
const nack = new proto_1.Nack(data).deserialize();
|
|
113
|
-
this.emit("nack", nack);
|
|
114
|
-
break;
|
|
159
|
+
this.socket.send(buffer, 0, buffer.length, this.options.port, this.options.address);
|
|
160
|
+
}
|
|
161
|
+
onMessage(msg, rinfo) {
|
|
162
|
+
try {
|
|
163
|
+
const packetId = (msg[0] & 0xf0) === 0x80 ? 0x80 : msg[0];
|
|
164
|
+
if (this.fastPathPackets.has(packetId)) {
|
|
165
|
+
this.packetHandlers.get(packetId)?.(msg, rinfo);
|
|
166
|
+
return;
|
|
115
167
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
168
|
+
const handler = this.packetHandlers.get(packetId);
|
|
169
|
+
if (handler) {
|
|
170
|
+
handler(msg, rinfo);
|
|
171
|
+
return;
|
|
120
172
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.emit("connection-request-accepted", connectionRequestAccepted);
|
|
124
|
-
break;
|
|
173
|
+
if (this.options.debug) {
|
|
174
|
+
utils_1.Logger.debug(`Unhandled packet ${packetId} from ${rinfo.address}:${rinfo.port}`);
|
|
125
175
|
}
|
|
126
176
|
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
utils_1.Logger.error("Failed to handle packet", { error: error });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
cleanup() {
|
|
182
|
+
this.removeAll();
|
|
183
|
+
this.socket.removeAllListeners();
|
|
184
|
+
this.socket.close();
|
|
185
|
+
clearInterval(this.timer);
|
|
186
|
+
clearTimeout(this.timeout);
|
|
187
|
+
this.isConnecting = false;
|
|
188
|
+
}
|
|
189
|
+
handleAck(msg, _rinfo) {
|
|
190
|
+
this.emit("ack", new proto_1.Ack(msg).deserialize());
|
|
191
|
+
}
|
|
192
|
+
handleUnconnectedPong(msg, _rinfo) {
|
|
193
|
+
this.emit("unconnected-pong", new proto_1.UnconnectedPong(msg).deserialize());
|
|
194
|
+
}
|
|
195
|
+
handleOpenConnectionReplyOne(msg, rinfo) {
|
|
196
|
+
const packet = new proto_1.OpenConnectionReplyOne(msg).deserialize();
|
|
197
|
+
this.emit("open-connection-reply-one", packet);
|
|
198
|
+
this.serverAddress = new proto_1.Address(rinfo.address, rinfo.port, rinfo.family === "IPv4" ? 4 : 6);
|
|
199
|
+
const request = new proto_1.OpenConnectionRequestTwo();
|
|
200
|
+
request.mtu = packet.mtu;
|
|
201
|
+
request.address = this.serverAddress;
|
|
202
|
+
request.clientGuid = this.options.clientId;
|
|
203
|
+
this.emit("open-connection-request-two", request);
|
|
204
|
+
this.send(request.serialize());
|
|
205
|
+
}
|
|
206
|
+
handleOpenConnectionReplyTwo(msg, _rinfo) {
|
|
207
|
+
const packet = new proto_1.OpenConnectionReplyTwo(msg).deserialize();
|
|
208
|
+
this.emit("open-connection-reply-two", packet);
|
|
209
|
+
this.options.mtuSize = packet.mtu;
|
|
210
|
+
const conReq = new proto_1.ConnectionRequest();
|
|
211
|
+
conReq.clientGuid = this.options.clientId;
|
|
212
|
+
conReq.timestamp = BigInt(Date.now());
|
|
213
|
+
conReq.useSecurity = false;
|
|
214
|
+
let connectionAttempts = 0;
|
|
215
|
+
let lastAttemptTime = 0;
|
|
216
|
+
this.emit("connection-request", conReq);
|
|
217
|
+
this.framer.frameAndSend(conReq.serialize(), proto_1.Priority.Immediate);
|
|
218
|
+
lastAttemptTime = Date.now();
|
|
219
|
+
const connectionInterval = setInterval(() => {
|
|
220
|
+
const now = Date.now();
|
|
221
|
+
if (now - lastAttemptTime < 100)
|
|
222
|
+
return;
|
|
223
|
+
if (connectionAttempts >= 3) {
|
|
224
|
+
clearInterval(connectionInterval);
|
|
225
|
+
this.cleanup();
|
|
226
|
+
this.emit("error", new Error("Connection request timed out"));
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
lastAttemptTime = now;
|
|
230
|
+
connectionAttempts++;
|
|
231
|
+
this.emit("connection-request", conReq);
|
|
232
|
+
this.framer.frameAndSend(conReq.serialize(), proto_1.Priority.Immediate);
|
|
233
|
+
}, 100);
|
|
234
|
+
this.once("new-incoming-connection", () => clearInterval(connectionInterval));
|
|
235
|
+
}
|
|
236
|
+
handleFrameSet(msg, _rinfo) {
|
|
237
|
+
const frameset = new frameset_1.Frameset(msg).deserialize();
|
|
238
|
+
this.emit("frameset", frameset);
|
|
239
|
+
this.framer.handle(frameset);
|
|
127
240
|
}
|
|
128
241
|
}
|
|
129
242
|
exports.Client = Client;
|
|
243
|
+
__decorate([
|
|
244
|
+
decorators_1.measureExecutionTime,
|
|
245
|
+
decorators_1.optimizeConnection,
|
|
246
|
+
__metadata("design:type", Function),
|
|
247
|
+
__metadata("design:paramtypes", []),
|
|
248
|
+
__metadata("design:returntype", Promise)
|
|
249
|
+
], Client.prototype, "connect", null);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Frame, Priority } from "../proto";
|
|
2
|
+
import { Frameset } from "../proto";
|
|
3
|
+
import type { Client } from "./client";
|
|
4
|
+
interface FragmentInfo {
|
|
5
|
+
frame: Frame;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class Framer {
|
|
9
|
+
private static readonly BUFFER_SIZES;
|
|
10
|
+
private bufferPools;
|
|
11
|
+
private client;
|
|
12
|
+
private lastInputSequence;
|
|
13
|
+
private receivedFrameSequences;
|
|
14
|
+
private lostFrameSequences;
|
|
15
|
+
private inputHighestSequenceIndex;
|
|
16
|
+
private inputOrderIndex;
|
|
17
|
+
protected inputOrderingQueue: Map<number, Map<number, Frame>>;
|
|
18
|
+
protected readonly fragmentsQueue: Map<number, Map<number, FragmentInfo>>;
|
|
19
|
+
outputOrderIndex: number[];
|
|
20
|
+
outputSequenceIndex: number[];
|
|
21
|
+
outputFrameQueue: Frameset;
|
|
22
|
+
protected outputSequence: number;
|
|
23
|
+
protected outputSplitIndex: number;
|
|
24
|
+
protected outputReliableIndex: number;
|
|
25
|
+
protected outputFrames: Frame[];
|
|
26
|
+
outputBackup: Map<number, Frame[]>;
|
|
27
|
+
constructor(client: Client);
|
|
28
|
+
tick(): void;
|
|
29
|
+
private processFrame;
|
|
30
|
+
private processBatch;
|
|
31
|
+
handle(frameSet: Frameset): void;
|
|
32
|
+
private handleFrame;
|
|
33
|
+
private handleOrdered;
|
|
34
|
+
private processOrderedFrames;
|
|
35
|
+
private handleSequenced;
|
|
36
|
+
private handleSplit;
|
|
37
|
+
private reassembleAndProcessFragment;
|
|
38
|
+
frameAndSend(payload: Buffer, priority?: Priority): void;
|
|
39
|
+
sendFrame(frame: Frame, priority: Priority): void;
|
|
40
|
+
private handleLargePayload;
|
|
41
|
+
private createSplitFrame;
|
|
42
|
+
private queueFrame;
|
|
43
|
+
sendQueue(amount: number): void;
|
|
44
|
+
private cleanupStaleFragments;
|
|
45
|
+
private getOptimalBuffer;
|
|
46
|
+
private releaseBuffer;
|
|
47
|
+
}
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=framer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framer.d.ts","sourceRoot":"","sources":["../../src/client/framer.ts"],"names":[],"mappings":"AACA,OAAO,EAIN,KAAK,EAGL,QAAQ,EAIR,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,UAAU,YAAY;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,MAAM;IAClB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAA4B;IAChE,OAAO,CAAC,WAAW,CAAoC;IAEvD,OAAO,CAAC,MAAM,CAAS;IAEvB,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,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAa;IAC1E,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAC9D;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;IAClC,SAAS,CAAC,YAAY,EAAE,KAAK,EAAE,CAAM;IAC9B,YAAY,uBAA8B;gBAErC,MAAM,EAAE,MAAM;IAmBnB,IAAI;IAqBX,OAAO,CAAC,YAAY;IAuDpB,OAAO,CAAC,YAAY;IAcb,MAAM,CAAC,QAAQ,EAAE,QAAQ;IAyChC,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,4BAA4B;IA8C7B,YAAY,CAClB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,QAA0B,GAClC,IAAI;IAQA,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAuBxD,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,gBAAgB;IAwBxB,OAAO,CAAC,UAAU;IAuBX,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAatC,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,aAAa;CAUrB"}
|