2023-09-14 22:28:31 +02:00
|
|
|
import GameResolver from "./GameResolver.js";
|
|
|
|
import {getProtocol} from './ProtocolResolver.js';
|
|
|
|
import GlobalUdpSocket from "./GlobalUdpSocket.js";
|
2019-01-12 11:43:36 +01:00
|
|
|
|
|
|
|
const defaultOptions = {
|
|
|
|
socketTimeout: 2000,
|
|
|
|
attemptTimeout: 10000,
|
2022-12-13 10:46:43 +01:00
|
|
|
maxAttempts: 1,
|
|
|
|
ipFamily: 0
|
2019-01-12 11:43:36 +01:00
|
|
|
};
|
|
|
|
|
2023-09-14 22:28:31 +02:00
|
|
|
export default class QueryRunner {
|
2021-05-19 06:13:18 +02:00
|
|
|
constructor(runnerOpts = {}) {
|
|
|
|
this.udpSocket = new GlobalUdpSocket({
|
|
|
|
port: runnerOpts.listenUdpPort
|
|
|
|
});
|
2019-01-12 11:43:36 +01:00
|
|
|
this.gameResolver = new GameResolver();
|
|
|
|
}
|
2023-09-13 16:31:58 +02:00
|
|
|
|
2019-01-12 11:43:36 +01:00
|
|
|
async run(userOptions) {
|
|
|
|
for (const key of Object.keys(userOptions)) {
|
|
|
|
const value = userOptions[key];
|
2022-12-13 10:46:43 +01:00
|
|
|
if (['port', 'ipFamily'].includes(key)) {
|
2019-01-12 11:43:36 +01:00
|
|
|
userOptions[key] = parseInt(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const {
|
|
|
|
port_query: gameQueryPort,
|
|
|
|
port_query_offset: gameQueryPortOffset,
|
|
|
|
...gameOptions
|
|
|
|
} = this.gameResolver.lookup(userOptions.type);
|
2023-09-13 16:31:58 +02:00
|
|
|
let attempts = [];
|
2019-01-12 11:43:36 +01:00
|
|
|
|
2023-09-13 16:31:58 +02:00
|
|
|
const optionsCollection = {
|
|
|
|
...defaultOptions,
|
|
|
|
...gameOptions,
|
|
|
|
...userOptions
|
|
|
|
};
|
|
|
|
|
|
|
|
const addAttemptWithPort = port => {
|
2019-01-12 11:43:36 +01:00
|
|
|
attempts.push({
|
2023-09-13 16:31:58 +02:00
|
|
|
...optionsCollection,
|
|
|
|
port
|
2019-01-12 11:43:36 +01:00
|
|
|
});
|
2023-09-13 16:31:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (userOptions.port) {
|
|
|
|
if(!userOptions.givenPortOnly) {
|
|
|
|
if (gameQueryPortOffset)
|
|
|
|
addAttemptWithPort(userOptions.port + gameQueryPortOffset);
|
|
|
|
|
|
|
|
if (userOptions.port === gameOptions.port && gameQueryPort)
|
|
|
|
addAttemptWithPort(gameQueryPort);
|
|
|
|
}
|
|
|
|
|
|
|
|
attempts.push(optionsCollection);
|
2019-01-12 11:43:36 +01:00
|
|
|
} else if (gameQueryPort) {
|
2023-09-13 16:31:58 +02:00
|
|
|
addAttemptWithPort(gameQueryPort);
|
2019-01-12 11:43:36 +01:00
|
|
|
} else if (gameOptions.port) {
|
2023-09-13 16:31:58 +02:00
|
|
|
addAttemptWithPort(gameOptions.port + (gameQueryPortOffset || 0));
|
2019-01-12 11:43:36 +01:00
|
|
|
} else {
|
2021-05-19 05:33:36 +02:00
|
|
|
// Hopefully the request doesn't need a port. If it does, it'll fail when making the request.
|
2023-09-13 16:31:58 +02:00
|
|
|
attempts.push(optionsCollection);
|
2019-01-12 11:43:36 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 05:46:13 +01:00
|
|
|
const numRetries = userOptions.maxAttempts || gameOptions.maxAttempts || defaultOptions.maxAttempts;
|
|
|
|
|
|
|
|
let attemptNum = 0;
|
|
|
|
const errors = [];
|
|
|
|
for (const attempt of attempts) {
|
|
|
|
for (let retry = 0; retry < numRetries; retry++) {
|
|
|
|
attemptNum++;
|
2019-01-12 11:43:36 +01:00
|
|
|
try {
|
|
|
|
return await this._attempt(attempt);
|
2019-02-14 05:46:13 +01:00
|
|
|
} catch (e) {
|
|
|
|
e.stack = 'Attempt #' + attemptNum + ' - Port=' + attempt.port + ' Retry=' + (retry) + ':\n' + e.stack;
|
|
|
|
errors.push(e);
|
2019-01-12 11:43:36 +01:00
|
|
|
}
|
|
|
|
}
|
2019-02-14 05:46:13 +01:00
|
|
|
}
|
2019-01-12 11:43:36 +01:00
|
|
|
|
2019-02-14 05:46:13 +01:00
|
|
|
const err = new Error('Failed all ' + errors.length + ' attempts');
|
|
|
|
for (const e of errors) {
|
|
|
|
err.stack += '\n' + e.stack;
|
2019-01-12 11:43:36 +01:00
|
|
|
}
|
2023-09-13 16:31:58 +02:00
|
|
|
|
2019-02-14 05:46:13 +01:00
|
|
|
throw err;
|
2019-01-12 11:43:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
async _attempt(options) {
|
2023-09-14 22:28:31 +02:00
|
|
|
const core = getProtocol(options.protocol);
|
2019-01-12 11:43:36 +01:00
|
|
|
core.options = options;
|
|
|
|
core.udpSocket = this.udpSocket;
|
2019-02-14 05:46:13 +01:00
|
|
|
return await core.runOnceSafe();
|
2019-01-12 11:43:36 +01:00
|
|
|
}
|
|
|
|
}
|