Skip to content

Commit

Permalink
check session IDs in all UDP response packets
Browse files Browse the repository at this point in the history
  • Loading branch information
KurtThiemann committed Nov 28, 2024
1 parent 2bdf979 commit d3e583b
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "craftping",
"type": "module",
"version": "2.0.0",
"version": "2.0.1",
"main": "index.js",
"repository": "github:aternosorg/craftping",
"scripts": {
Expand Down
25 changes: 23 additions & 2 deletions src/BedrockPing/BedrockPing.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
import UDPClient from "../UDPSocket/UDPClient.js";
import UnconnectedPing from "../Packet/BedrockPing/UnconnectedPing.js";
import UnconnectedPong from "../Packet/BedrockPing/UnconnectedPong.js";
import * as crypto from "node:crypto";

export default class BedrockPing extends UDPClient {
/** @type {BigInt} */ sessionId;

/**
* @return {Promise<UnconnectedPong>}
*/
async ping() {
// Normally, the time field is used for the current ms timestamp, but we're using it as a session ID
// to identify which reply belongs to which request.
this.sessionId = crypto.randomBytes(8).readBigInt64BE();
let startTime = BigInt(Date.now());
await this.sendPacket(new UnconnectedPing().setTime(startTime).generateClientGUID());
await this.sendPacket(new UnconnectedPing().setTime(this.sessionId).generateClientGUID());
this.signal?.throwIfAborted();

return new UnconnectedPong().read(await this.readData());
// The time field in the response contains the session ID, but we replace it with the start time
// in case anyone relies on the time field containing an actual timestamp.
return new UnconnectedPong().read(await this.readData()).setTime(startTime);
}

/**
* @inheritDoc
*/
shouldAcceptPacket(packet) {
let data = packet.getData();
if (data.byteLength < 9) {
return false;
}

let timestamp = data.readBigInt64BE(1);
return timestamp === this.sessionId;
}
}
13 changes: 13 additions & 0 deletions src/Query/Query.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,17 @@ export default class Query extends UDPClient {
this.signal?.throwIfAborted();
return new FullStatResponse().read(await this.readData());
}

/**
* @inheritDoc
*/
shouldAcceptPacket(packet) {
let data = packet.getData();
if (data.byteLength < 5) {
return false;
}

let session = data.readUInt32BE(1);
return session === this.sessionId;
}
}
11 changes: 11 additions & 0 deletions src/UDPSocket/UDPSocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ export default class UDPSocket extends EventEmitter {

handleMessage(data, info) {
let message = new UDPMessage(data, info);
if (!this.shouldAcceptPacket(message)) {
return this;
}

if (this.readQueue.length > 0) {
this.readQueue.shift().resolve(message);
Expand Down Expand Up @@ -166,4 +169,12 @@ export default class UDPSocket extends EventEmitter {
});
});
}

/**
* @param {UDPMessage} packet
* @return {boolean}
*/
shouldAcceptPacket(packet) {
return true
}
}

0 comments on commit d3e583b

Please sign in to comment.