Skip to content

Commit ee5c856

Browse files
committed
🐛 Add challenge retries for A2S_PLAYER requests
1 parent bccbdad commit ee5c856

File tree

3 files changed

+54
-35
lines changed

3 files changed

+54
-35
lines changed

package-lock.json

+17-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "steam-server-query",
3-
"version": "1.1.2",
3+
"version": "1.1.3",
44
"description": "Module which implements the Master Server Query Protocol and Game Server Queries.",
55
"main": "lib/index.js",
66
"types": "lib/index.d.ts",
@@ -26,7 +26,7 @@
2626
},
2727
"homepage": "https://github.com/GiyoMoon/steam-server-query#readme",
2828
"devDependencies": {
29-
"@types/node": "^17.0.5",
30-
"typescript": "^4.5.4"
29+
"@types/node": "^17.0.17",
30+
"typescript": "^4.5.5"
3131
}
3232
}

src/gameServer/gameServer.ts

+34-16
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class GameServerQuery {
7575
}
7676

7777
// If the server replied with a challenge, grab challenge number and send request again
78-
if (resultBuffer.compare(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0x41]), 0, 5, 0, 5) === 0) {
78+
if (this._isChallengeResponse(resultBuffer)) {
7979
resultBuffer = resultBuffer.slice(5);
8080
const challenge = resultBuffer;
8181
try {
@@ -93,26 +93,40 @@ class GameServerQuery {
9393
}
9494

9595
public async player(): Promise<PlayerResponse> {
96-
let challengeResultBuffer: Buffer;
97-
try {
98-
challengeResultBuffer = await this._promiseSocket.send(this._buildPacket(Buffer.from([0x55])), this._host, this._port);
99-
} catch (err: any) {
100-
this._promiseSocket.closeSocket();
101-
throw new Error(err);
102-
}
96+
let resultBuffer: Buffer;
97+
let gotPlayerResponse = false;
98+
let challengeTries = 0;
10399

104-
const challenge = challengeResultBuffer.slice(5);
100+
do {
101+
let challengeResultBuffer: Buffer;
102+
try {
103+
challengeResultBuffer = await this._promiseSocket.send(this._buildPacket(Buffer.from([0x55])), this._host, this._port);
104+
} catch (err: any) {
105+
this._promiseSocket.closeSocket();
106+
throw new Error(err);
107+
}
105108

106-
let resultBuffer: Buffer;
107-
try {
108-
resultBuffer = await this._promiseSocket.send(this._buildPacket(Buffer.from([0x55]), challenge), this._host, this._port);
109-
} catch (err: any) {
110-
this._promiseSocket.closeSocket();
111-
throw new Error(err);
112-
}
109+
const challenge = challengeResultBuffer.slice(5);
110+
try {
111+
resultBuffer = await this._promiseSocket.send(this._buildPacket(Buffer.from([0x55]), challenge), this._host, this._port);
112+
} catch (err: any) {
113+
this._promiseSocket.closeSocket();
114+
throw new Error(err);
115+
}
116+
117+
if (!this._isChallengeResponse(resultBuffer)) {
118+
gotPlayerResponse = true;
119+
}
120+
121+
challengeTries++;
122+
} while (!gotPlayerResponse && challengeTries < 5);
113123

114124
this._promiseSocket.closeSocket();
115125

126+
if (this._isChallengeResponse(resultBuffer)) {
127+
throw new Error('Server kept sending challenge responses.');
128+
}
129+
116130
const parsedPlayerBuffer = this._parsePlayerBuffer(resultBuffer);
117131
return parsedPlayerBuffer;
118132
}
@@ -177,6 +191,10 @@ class GameServerQuery {
177191
return packet;
178192
}
179193

194+
private _isChallengeResponse(buffer: Buffer) {
195+
return buffer.compare(Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0x41]), 0, 5, 0, 5) === 0;
196+
}
197+
180198
private _parseInfoBuffer(buffer: Buffer): InfoResponse {
181199
const infoResponse: Partial<InfoResponse> = {};
182200
buffer = buffer.slice(5);

0 commit comments

Comments
 (0)