@baltica/raknet 0.0.6 → 0.0.8
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,23 +45,21 @@ 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);
|
|
51
|
+
this.socket.ref();
|
|
53
52
|
this.network.send = (data) => this.socket.send(data, this.options.port, this.options.address);
|
|
54
53
|
return new Promise((resolve) => {
|
|
55
54
|
try {
|
|
56
55
|
this.socket.address();
|
|
57
56
|
this.socket.on("message", (buf) => this.network.receive(buf));
|
|
58
|
-
this.tickInterval = setInterval(() => this.network.tick(), 50);
|
|
59
57
|
resolve();
|
|
60
58
|
}
|
|
61
59
|
catch {
|
|
62
60
|
this.socket.bind();
|
|
63
61
|
this.socket.on("listening", () => {
|
|
64
62
|
this.socket.on("message", (buf) => this.network.receive(buf));
|
|
65
|
-
this.tickInterval = setInterval(() => this.network.tick(), 50);
|
|
66
63
|
resolve();
|
|
67
64
|
});
|
|
68
65
|
}
|
|
@@ -111,10 +108,7 @@ class Client extends utils_1.Emitter {
|
|
|
111
108
|
this.network.frameAndSend(data, priority);
|
|
112
109
|
}
|
|
113
110
|
close() {
|
|
114
|
-
|
|
115
|
-
clearInterval(this.tickInterval);
|
|
116
|
-
this.tickInterval = undefined;
|
|
117
|
-
}
|
|
111
|
+
this.network.destroy();
|
|
118
112
|
this.network.status = shared_1.Status.Disconnected;
|
|
119
113
|
this.network.send = () => { };
|
|
120
114
|
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,16 @@ 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;
|
|
47
|
+
private keepaliveTimer?;
|
|
43
48
|
constructor(mtu: number, client: boolean);
|
|
49
|
+
private startKeepalive;
|
|
44
50
|
sendOfflineWithRetry(data: Buffer): void;
|
|
45
51
|
private clearOfflineRetry;
|
|
52
|
+
destroy(): void;
|
|
46
53
|
receive(buffer: Buffer): void;
|
|
47
54
|
private handleClientOffline;
|
|
48
55
|
private handleServerOffline;
|
|
@@ -42,19 +42,56 @@ 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;
|
|
49
|
+
keepaliveTimer;
|
|
45
50
|
constructor(mtu, client) {
|
|
46
51
|
super();
|
|
47
52
|
this.mtu = mtu;
|
|
48
53
|
this.client = client;
|
|
49
54
|
for (let i = 0; i < 32; i++)
|
|
50
55
|
this.inputOrderingQueue.set(i, new Map());
|
|
56
|
+
this.startKeepalive();
|
|
57
|
+
}
|
|
58
|
+
startKeepalive() {
|
|
59
|
+
if (this.keepaliveTimer)
|
|
60
|
+
clearTimeout(this.keepaliveTimer);
|
|
61
|
+
const interval = this.status === proto_1.Status.Connected ? 10 :
|
|
62
|
+
this.status === proto_1.Status.Connecting ? 10 : 100;
|
|
63
|
+
this.keepaliveTimer = setTimeout(() => {
|
|
64
|
+
this.tick();
|
|
65
|
+
this.startKeepalive();
|
|
66
|
+
}, interval);
|
|
67
|
+
this.keepaliveTimer.ref();
|
|
51
68
|
}
|
|
52
69
|
sendOfflineWithRetry(data) {
|
|
53
70
|
this.offlineRetry = { data, attempts: 1, maxAttempts: this.maxRetransmit, lastSent: Date.now(), interval: this.retransmitInterval };
|
|
54
71
|
this.send(data);
|
|
72
|
+
if (!this.retransmitTimer) {
|
|
73
|
+
this.retransmitTimer = setTimeout(() => this.tick(), this.retransmitInterval);
|
|
74
|
+
this.retransmitTimer.ref();
|
|
75
|
+
}
|
|
55
76
|
}
|
|
56
77
|
clearOfflineRetry() {
|
|
57
78
|
this.offlineRetry = null;
|
|
79
|
+
if (this.retransmitTimer) {
|
|
80
|
+
clearTimeout(this.retransmitTimer);
|
|
81
|
+
this.retransmitTimer = undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
destroy() {
|
|
85
|
+
this.status = proto_1.Status.Disconnected;
|
|
86
|
+
if (this.ackTimer)
|
|
87
|
+
clearTimeout(this.ackTimer);
|
|
88
|
+
if (this.retransmitTimer)
|
|
89
|
+
clearTimeout(this.retransmitTimer);
|
|
90
|
+
if (this.cleanupTimer)
|
|
91
|
+
clearTimeout(this.cleanupTimer);
|
|
92
|
+
if (this.keepaliveTimer)
|
|
93
|
+
clearTimeout(this.keepaliveTimer);
|
|
94
|
+
this.removeAllListeners();
|
|
58
95
|
}
|
|
59
96
|
receive(buffer) {
|
|
60
97
|
const id = buffer[0];
|
|
@@ -221,7 +258,7 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
221
258
|
}
|
|
222
259
|
}
|
|
223
260
|
tick() {
|
|
224
|
-
if (this.status === proto_1.Status.Disconnected)
|
|
261
|
+
if (this.status === proto_1.Status.Disconnected || !this.send)
|
|
225
262
|
return;
|
|
226
263
|
const now = Date.now();
|
|
227
264
|
if (this.offlineRetry) {
|
|
@@ -231,48 +268,58 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
231
268
|
this.offlineRetry = null;
|
|
232
269
|
this.status = proto_1.Status.Disconnected;
|
|
233
270
|
this.emit("error", new Error("Connection timed out after " + r.maxAttempts + " attempts"));
|
|
271
|
+
return;
|
|
234
272
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
273
|
+
r.attempts++;
|
|
274
|
+
r.lastSent = now;
|
|
275
|
+
this.send(r.data);
|
|
276
|
+
if (this.retransmitTimer)
|
|
277
|
+
clearTimeout(this.retransmitTimer);
|
|
278
|
+
this.retransmitTimer = setTimeout(() => this.tick(), r.interval);
|
|
279
|
+
this.retransmitTimer.ref();
|
|
280
|
+
return;
|
|
240
281
|
}
|
|
241
282
|
}
|
|
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());
|
|
283
|
+
if (now - this.lastCleanup > 5000) {
|
|
284
|
+
this.lastCleanup = now;
|
|
285
|
+
const windowStart = this.lastInputSequence - RECEIVE_WINDOW;
|
|
286
|
+
if (windowStart > 0) {
|
|
287
|
+
for (const s of this.receivedFrameSequences)
|
|
288
|
+
if (s < windowStart)
|
|
289
|
+
this.receivedFrameSequences.delete(s);
|
|
290
|
+
for (const s of this.lostFrameSequences)
|
|
291
|
+
if (s < windowStart)
|
|
292
|
+
this.lostFrameSequences.delete(s);
|
|
293
|
+
}
|
|
294
|
+
const relStart = this.highestReliableIndex - RELIABLE_WINDOW;
|
|
295
|
+
if (relStart > 0) {
|
|
296
|
+
for (const i of this.receivedReliableFrameIndices)
|
|
297
|
+
if (i < relStart)
|
|
298
|
+
this.receivedReliableFrameIndices.delete(i);
|
|
299
|
+
}
|
|
300
|
+
for (const [id, entry] of this.fragmentsQueue) {
|
|
301
|
+
if (now - entry.timestamp > FRAGMENT_TIMEOUT)
|
|
302
|
+
this.fragmentsQueue.delete(id);
|
|
303
|
+
}
|
|
266
304
|
}
|
|
267
|
-
if (this.lostFrameSequences.size > 0) {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
305
|
+
if (this.pendingAcks.size > 0 || this.lostFrameSequences.size > 0) {
|
|
306
|
+
if (this.pendingAcks.size > 0) {
|
|
307
|
+
const ack = new proto_1.Ack();
|
|
308
|
+
ack.sequences = [...this.pendingAcks];
|
|
309
|
+
this.pendingAcks.clear();
|
|
310
|
+
this.send(ack.serialize());
|
|
311
|
+
}
|
|
312
|
+
if (this.lostFrameSequences.size > 0) {
|
|
313
|
+
const nack = new proto_1.Nack();
|
|
314
|
+
nack.sequences = [...this.lostFrameSequences];
|
|
315
|
+
this.lostFrameSequences.clear();
|
|
316
|
+
this.send(nack.serialize());
|
|
317
|
+
}
|
|
272
318
|
}
|
|
273
|
-
|
|
319
|
+
let nextRetransmit = Infinity;
|
|
274
320
|
for (const [seq, sentAt] of this.outputBackupTimestamps) {
|
|
275
|
-
|
|
321
|
+
const age = now - sentAt;
|
|
322
|
+
if (age >= this.retransmitInterval) {
|
|
276
323
|
const frames = this.outputBackup.get(seq);
|
|
277
324
|
if (frames) {
|
|
278
325
|
const fs = new proto_1.FrameSet();
|
|
@@ -280,20 +327,34 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
280
327
|
fs.frames = frames;
|
|
281
328
|
this.send(fs.serialize());
|
|
282
329
|
this.outputBackupTimestamps.set(seq, now);
|
|
330
|
+
nextRetransmit = Math.min(nextRetransmit, this.retransmitInterval);
|
|
283
331
|
}
|
|
284
332
|
else {
|
|
285
333
|
this.outputBackupTimestamps.delete(seq);
|
|
286
334
|
}
|
|
287
335
|
}
|
|
336
|
+
else {
|
|
337
|
+
nextRetransmit = Math.min(nextRetransmit, this.retransmitInterval - age);
|
|
338
|
+
}
|
|
288
339
|
}
|
|
289
340
|
if (this.outputFrames.size > 0)
|
|
290
341
|
this.flush();
|
|
342
|
+
if (nextRetransmit < Infinity) {
|
|
343
|
+
if (this.retransmitTimer)
|
|
344
|
+
clearTimeout(this.retransmitTimer);
|
|
345
|
+
this.retransmitTimer = setTimeout(() => this.tick(), nextRetransmit);
|
|
346
|
+
this.retransmitTimer.ref();
|
|
347
|
+
}
|
|
291
348
|
}
|
|
292
349
|
onAck(ack) {
|
|
293
350
|
for (const seq of ack.sequences) {
|
|
294
351
|
this.outputBackup.delete(seq);
|
|
295
352
|
this.outputBackupTimestamps.delete(seq);
|
|
296
353
|
}
|
|
354
|
+
if (this.outputBackupTimestamps.size === 0 && this.retransmitTimer) {
|
|
355
|
+
clearTimeout(this.retransmitTimer);
|
|
356
|
+
this.retransmitTimer = undefined;
|
|
357
|
+
}
|
|
297
358
|
}
|
|
298
359
|
onNack(nack) {
|
|
299
360
|
for (const seq of nack.sequences) {
|
|
@@ -363,7 +424,7 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
363
424
|
this.flush();
|
|
364
425
|
}
|
|
365
426
|
flush() {
|
|
366
|
-
if (this.outputFrames.size === 0)
|
|
427
|
+
if (this.outputFrames.size === 0 || !this.send)
|
|
367
428
|
return;
|
|
368
429
|
const fs = new proto_1.FrameSet();
|
|
369
430
|
fs.sequence = this.outputSequence++;
|
|
@@ -371,8 +432,11 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
371
432
|
this.outputBackup.set(fs.sequence, fs.frames);
|
|
372
433
|
this.outputBackupTimestamps.set(fs.sequence, Date.now());
|
|
373
434
|
this.outputFrames.clear();
|
|
374
|
-
|
|
375
|
-
this.
|
|
435
|
+
this.send(fs.serialize());
|
|
436
|
+
if (!this.retransmitTimer) {
|
|
437
|
+
this.retransmitTimer = setTimeout(() => this.tick(), this.retransmitInterval);
|
|
438
|
+
this.retransmitTimer.ref();
|
|
439
|
+
}
|
|
376
440
|
}
|
|
377
441
|
onFrameSet(fs) {
|
|
378
442
|
if (this.receivedFrameSequences.has(fs.sequence))
|
|
@@ -389,6 +453,13 @@ class NetworkSession extends utils_1.Emitter {
|
|
|
389
453
|
}
|
|
390
454
|
for (const frame of fs.frames)
|
|
391
455
|
this.handleFrame(frame);
|
|
456
|
+
if (!this.ackTimer) {
|
|
457
|
+
this.ackTimer = setTimeout(() => {
|
|
458
|
+
this.ackTimer = undefined;
|
|
459
|
+
this.tick();
|
|
460
|
+
}, 10);
|
|
461
|
+
this.ackTimer.ref();
|
|
462
|
+
}
|
|
392
463
|
}
|
|
393
464
|
handleFrame(frame) {
|
|
394
465
|
if (frame.isReliable()) {
|