@baltica/raknet 0.0.5 → 0.0.7
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.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { ClientEvents, ClientOptions } from "./types";
|
|
|
4
4
|
export declare class Client extends Emitter<ClientEvents> {
|
|
5
5
|
private socket;
|
|
6
6
|
private network;
|
|
7
|
-
private tickInterval?;
|
|
8
7
|
private relay?;
|
|
9
8
|
options: ClientOptions;
|
|
10
9
|
constructor(options?: Partial<ClientOptions>);
|
package/dist/client/client.js
CHANGED
|
@@ -10,7 +10,6 @@ const types_1 = require("./types");
|
|
|
10
10
|
class Client extends utils_1.Emitter {
|
|
11
11
|
socket;
|
|
12
12
|
network;
|
|
13
|
-
tickInterval;
|
|
14
13
|
relay;
|
|
15
14
|
options;
|
|
16
15
|
constructor(options = {}) {
|
|
@@ -46,7 +45,6 @@ class Client extends utils_1.Emitter {
|
|
|
46
45
|
const targetPort = this.network.address.port;
|
|
47
46
|
this.network.send = (data) => this.relay.send(data, targetAddress, targetPort);
|
|
48
47
|
this.relay.onMessage((data) => this.network.receive(data));
|
|
49
|
-
this.tickInterval = setInterval(() => this.network.tick(), 50);
|
|
50
48
|
}
|
|
51
49
|
initDirect() {
|
|
52
50
|
this.socket = (0, node_dgram_1.createSocket)(this.options.family);
|
|
@@ -55,14 +53,12 @@ class Client extends utils_1.Emitter {
|
|
|
55
53
|
try {
|
|
56
54
|
this.socket.address();
|
|
57
55
|
this.socket.on("message", (buf) => this.network.receive(buf));
|
|
58
|
-
this.tickInterval = setInterval(() => this.network.tick(), 50);
|
|
59
56
|
resolve();
|
|
60
57
|
}
|
|
61
58
|
catch {
|
|
62
59
|
this.socket.bind();
|
|
63
60
|
this.socket.on("listening", () => {
|
|
64
61
|
this.socket.on("message", (buf) => this.network.receive(buf));
|
|
65
|
-
this.tickInterval = setInterval(() => this.network.tick(), 50);
|
|
66
62
|
resolve();
|
|
67
63
|
});
|
|
68
64
|
}
|
|
@@ -111,10 +107,7 @@ class Client extends utils_1.Emitter {
|
|
|
111
107
|
this.network.frameAndSend(data, priority);
|
|
112
108
|
}
|
|
113
109
|
close() {
|
|
114
|
-
|
|
115
|
-
clearInterval(this.tickInterval);
|
|
116
|
-
this.tickInterval = undefined;
|
|
117
|
-
}
|
|
110
|
+
this.network.destroy();
|
|
118
111
|
this.network.status = shared_1.Status.Disconnected;
|
|
119
112
|
this.network.send = () => { };
|
|
120
113
|
this.network.removeAllListeners();
|
package/dist/server/server.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { ServerEvents, ServerOptions } from "./types";
|
|
|
4
4
|
import { Connection } from "./connection";
|
|
5
5
|
export declare class Server extends Emitter<ServerEvents> {
|
|
6
6
|
private socket;
|
|
7
|
-
private tickInterval?;
|
|
8
7
|
private connections;
|
|
9
8
|
options: ServerOptions;
|
|
10
9
|
constructor(options?: Partial<ServerOptions>);
|
package/dist/server/server.js
CHANGED
|
@@ -10,7 +10,6 @@ const connection_1 = require("./connection");
|
|
|
10
10
|
const RAKNET_PROTOCOL = 11;
|
|
11
11
|
class Server extends utils_1.Emitter {
|
|
12
12
|
socket;
|
|
13
|
-
tickInterval;
|
|
14
13
|
connections = new Map();
|
|
15
14
|
options;
|
|
16
15
|
constructor(options = {}) {
|
|
@@ -26,14 +25,11 @@ class Server extends utils_1.Emitter {
|
|
|
26
25
|
this.socket.bind(this.options.port, this.options.address);
|
|
27
26
|
this.socket.on("listening", () => {
|
|
28
27
|
this.socket.on("message", (buffer, rinfo) => this.handleMessage(buffer, rinfo));
|
|
29
|
-
this.tickInterval = setInterval(() => this.tick(), 50);
|
|
30
28
|
resolve();
|
|
31
29
|
});
|
|
32
30
|
});
|
|
33
31
|
}
|
|
34
32
|
stop() {
|
|
35
|
-
if (this.tickInterval)
|
|
36
|
-
clearInterval(this.tickInterval);
|
|
37
33
|
for (const conn of this.connections.values())
|
|
38
34
|
conn.disconnect();
|
|
39
35
|
this.connections.clear();
|
|
@@ -40,9 +40,14 @@ export declare class NetworkSession extends Emitter<NetworkEvents> {
|
|
|
40
40
|
private highestReliableIndex;
|
|
41
41
|
private offlineRetry;
|
|
42
42
|
private outputBackupTimestamps;
|
|
43
|
+
private ackTimer?;
|
|
44
|
+
private retransmitTimer?;
|
|
45
|
+
private cleanupTimer?;
|
|
46
|
+
private lastCleanup;
|
|
43
47
|
constructor(mtu: number, client: boolean);
|
|
44
48
|
sendOfflineWithRetry(data: Buffer): void;
|
|
45
49
|
private clearOfflineRetry;
|
|
50
|
+
destroy(): void;
|
|
46
51
|
receive(buffer: Buffer): void;
|
|
47
52
|
private handleClientOffline;
|
|
48
53
|
private handleServerOffline;
|
|
@@ -8,8 +8,8 @@ const MTU_HEADER_SIZE = 36;
|
|
|
8
8
|
const RECEIVE_WINDOW = 2048;
|
|
9
9
|
const RELIABLE_WINDOW = 4096;
|
|
10
10
|
const FRAGMENT_TIMEOUT = 30_000;
|
|
11
|
-
const ORDER_QUEUE_MAX =
|
|
12
|
-
const ORDER_SKIP_THRESHOLD =
|
|
11
|
+
const ORDER_QUEUE_MAX = 4096;
|
|
12
|
+
const ORDER_SKIP_THRESHOLD = 8192;
|
|
13
13
|
const RAKNET_PROTOCOL = 11;
|
|
14
14
|
const GAME_PACKET_ID = 0xfe;
|
|
15
15
|
class NetworkSession extends utils_1.Emitter {
|
|
@@ -42,6 +42,10 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
42
42
|
highestReliableIndex = -1;
|
|
43
43
|
offlineRetry = null;
|
|
44
44
|
outputBackupTimestamps = new Map();
|
|
45
|
+
ackTimer;
|
|
46
|
+
retransmitTimer;
|
|
47
|
+
cleanupTimer;
|
|
48
|
+
lastCleanup = 0;
|
|
45
49
|
constructor(mtu, client) {
|
|
46
50
|
super();
|
|
47
51
|
this.mtu = mtu;
|
|
@@ -52,9 +56,25 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
52
56
|
sendOfflineWithRetry(data) {
|
|
53
57
|
this.offlineRetry = { data, attempts: 1, maxAttempts: this.maxRetransmit, lastSent: Date.now(), interval: this.retransmitInterval };
|
|
54
58
|
this.send(data);
|
|
59
|
+
if (!this.retransmitTimer) {
|
|
60
|
+
this.retransmitTimer = setTimeout(() => this.tick(), this.retransmitInterval);
|
|
61
|
+
}
|
|
55
62
|
}
|
|
56
63
|
clearOfflineRetry() {
|
|
57
64
|
this.offlineRetry = null;
|
|
65
|
+
if (this.retransmitTimer) {
|
|
66
|
+
clearTimeout(this.retransmitTimer);
|
|
67
|
+
this.retransmitTimer = undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
destroy() {
|
|
71
|
+
if (this.ackTimer)
|
|
72
|
+
clearTimeout(this.ackTimer);
|
|
73
|
+
if (this.retransmitTimer)
|
|
74
|
+
clearTimeout(this.retransmitTimer);
|
|
75
|
+
if (this.cleanupTimer)
|
|
76
|
+
clearTimeout(this.cleanupTimer);
|
|
77
|
+
this.removeAllListeners();
|
|
58
78
|
}
|
|
59
79
|
receive(buffer) {
|
|
60
80
|
const id = buffer[0];
|
|
@@ -231,48 +251,57 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
231
251
|
this.offlineRetry = null;
|
|
232
252
|
this.status = proto_1.Status.Disconnected;
|
|
233
253
|
this.emit("error", new Error("Connection timed out after " + r.maxAttempts + " attempts"));
|
|
254
|
+
return;
|
|
234
255
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
256
|
+
r.attempts++;
|
|
257
|
+
r.lastSent = now;
|
|
258
|
+
this.send(r.data);
|
|
259
|
+
if (this.retransmitTimer)
|
|
260
|
+
clearTimeout(this.retransmitTimer);
|
|
261
|
+
this.retransmitTimer = setTimeout(() => this.tick(), r.interval);
|
|
262
|
+
return;
|
|
240
263
|
}
|
|
241
264
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
ack.sequences = [...this.pendingAcks];
|
|
264
|
-
this.pendingAcks.clear();
|
|
265
|
-
this.send(ack.serialize());
|
|
265
|
+
if (now - this.lastCleanup > 5000) {
|
|
266
|
+
this.lastCleanup = now;
|
|
267
|
+
const windowStart = this.lastInputSequence - RECEIVE_WINDOW;
|
|
268
|
+
if (windowStart > 0) {
|
|
269
|
+
for (const s of this.receivedFrameSequences)
|
|
270
|
+
if (s < windowStart)
|
|
271
|
+
this.receivedFrameSequences.delete(s);
|
|
272
|
+
for (const s of this.lostFrameSequences)
|
|
273
|
+
if (s < windowStart)
|
|
274
|
+
this.lostFrameSequences.delete(s);
|
|
275
|
+
}
|
|
276
|
+
const relStart = this.highestReliableIndex - RELIABLE_WINDOW;
|
|
277
|
+
if (relStart > 0) {
|
|
278
|
+
for (const i of this.receivedReliableFrameIndices)
|
|
279
|
+
if (i < relStart)
|
|
280
|
+
this.receivedReliableFrameIndices.delete(i);
|
|
281
|
+
}
|
|
282
|
+
for (const [id, entry] of this.fragmentsQueue) {
|
|
283
|
+
if (now - entry.timestamp > FRAGMENT_TIMEOUT)
|
|
284
|
+
this.fragmentsQueue.delete(id);
|
|
285
|
+
}
|
|
266
286
|
}
|
|
267
|
-
if (this.lostFrameSequences.size > 0) {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
287
|
+
if (this.pendingAcks.size > 0 || this.lostFrameSequences.size > 0) {
|
|
288
|
+
if (this.pendingAcks.size > 0) {
|
|
289
|
+
const ack = new proto_1.Ack();
|
|
290
|
+
ack.sequences = [...this.pendingAcks];
|
|
291
|
+
this.pendingAcks.clear();
|
|
292
|
+
this.send(ack.serialize());
|
|
293
|
+
}
|
|
294
|
+
if (this.lostFrameSequences.size > 0) {
|
|
295
|
+
const nack = new proto_1.Nack();
|
|
296
|
+
nack.sequences = [...this.lostFrameSequences];
|
|
297
|
+
this.lostFrameSequences.clear();
|
|
298
|
+
this.send(nack.serialize());
|
|
299
|
+
}
|
|
272
300
|
}
|
|
273
|
-
|
|
301
|
+
let nextRetransmit = Infinity;
|
|
274
302
|
for (const [seq, sentAt] of this.outputBackupTimestamps) {
|
|
275
|
-
|
|
303
|
+
const age = now - sentAt;
|
|
304
|
+
if (age >= this.retransmitInterval) {
|
|
276
305
|
const frames = this.outputBackup.get(seq);
|
|
277
306
|
if (frames) {
|
|
278
307
|
const fs = new proto_1.FrameSet();
|
|
@@ -280,20 +309,33 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
280
309
|
fs.frames = frames;
|
|
281
310
|
this.send(fs.serialize());
|
|
282
311
|
this.outputBackupTimestamps.set(seq, now);
|
|
312
|
+
nextRetransmit = Math.min(nextRetransmit, this.retransmitInterval);
|
|
283
313
|
}
|
|
284
314
|
else {
|
|
285
315
|
this.outputBackupTimestamps.delete(seq);
|
|
286
316
|
}
|
|
287
317
|
}
|
|
318
|
+
else {
|
|
319
|
+
nextRetransmit = Math.min(nextRetransmit, this.retransmitInterval - age);
|
|
320
|
+
}
|
|
288
321
|
}
|
|
289
322
|
if (this.outputFrames.size > 0)
|
|
290
323
|
this.flush();
|
|
324
|
+
if (nextRetransmit < Infinity) {
|
|
325
|
+
if (this.retransmitTimer)
|
|
326
|
+
clearTimeout(this.retransmitTimer);
|
|
327
|
+
this.retransmitTimer = setTimeout(() => this.tick(), nextRetransmit);
|
|
328
|
+
}
|
|
291
329
|
}
|
|
292
330
|
onAck(ack) {
|
|
293
331
|
for (const seq of ack.sequences) {
|
|
294
332
|
this.outputBackup.delete(seq);
|
|
295
333
|
this.outputBackupTimestamps.delete(seq);
|
|
296
334
|
}
|
|
335
|
+
if (this.outputBackupTimestamps.size === 0 && this.retransmitTimer) {
|
|
336
|
+
clearTimeout(this.retransmitTimer);
|
|
337
|
+
this.retransmitTimer = undefined;
|
|
338
|
+
}
|
|
297
339
|
}
|
|
298
340
|
onNack(nack) {
|
|
299
341
|
for (const seq of nack.sequences) {
|
|
@@ -371,8 +413,10 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
371
413
|
this.outputBackup.set(fs.sequence, fs.frames);
|
|
372
414
|
this.outputBackupTimestamps.set(fs.sequence, Date.now());
|
|
373
415
|
this.outputFrames.clear();
|
|
374
|
-
|
|
375
|
-
this.
|
|
416
|
+
this.send(fs.serialize());
|
|
417
|
+
if (!this.retransmitTimer) {
|
|
418
|
+
this.retransmitTimer = setTimeout(() => this.tick(), this.retransmitInterval);
|
|
419
|
+
}
|
|
376
420
|
}
|
|
377
421
|
onFrameSet(fs) {
|
|
378
422
|
if (this.receivedFrameSequences.has(fs.sequence))
|
|
@@ -389,6 +433,12 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
389
433
|
}
|
|
390
434
|
for (const frame of fs.frames)
|
|
391
435
|
this.handleFrame(frame);
|
|
436
|
+
if (!this.ackTimer) {
|
|
437
|
+
this.ackTimer = setTimeout(() => {
|
|
438
|
+
this.ackTimer = undefined;
|
|
439
|
+
this.tick();
|
|
440
|
+
}, 10);
|
|
441
|
+
}
|
|
392
442
|
}
|
|
393
443
|
handleFrame(frame) {
|
|
394
444
|
if (frame.isReliable()) {
|