node-gamedig/lib/QueryRunner.js

108 lines
3.3 KiB
JavaScript
Raw Normal View History

2019-01-12 11:43:36 +01:00
const GameResolver = require('./GameResolver'),
ProtocolResolver = require('./ProtocolResolver'),
2019-01-20 11:21:40 +01:00
GlobalUdpSocket = require('./GlobalUdpSocket'),
Logger = require('./Logger');
2019-01-12 11:43:36 +01:00
const defaultOptions = {
socketTimeout: 2000,
attemptTimeout: 10000,
maxAttempts: 1
};
class QueryRunner {
constructor() {
this.udpSocket = new GlobalUdpSocket();
2019-01-12 11:43:36 +01:00
this.gameResolver = new GameResolver();
this.protocolResolver = new ProtocolResolver();
}
async run(userOptions) {
for (const key of Object.keys(userOptions)) {
const value = userOptions[key];
if (['port'].includes(key)) {
userOptions[key] = parseInt(value);
}
}
const {
port_query: gameQueryPort,
port_query_offset: gameQueryPortOffset,
...gameOptions
} = this.gameResolver.lookup(userOptions.type);
const attempts = [];
if (userOptions.port) {
if (gameQueryPortOffset) {
attempts.push({
...defaultOptions,
...gameOptions,
...userOptions,
port: userOptions.port + gameQueryPortOffset
});
}
if (userOptions.port === gameOptions.port && gameQueryPort) {
attempts.push({
...defaultOptions,
...gameOptions,
...userOptions,
port: gameQueryPort
});
}
attempts.push({
...defaultOptions,
...gameOptions,
...userOptions
});
} else if (gameQueryPort) {
attempts.push({
...defaultOptions,
...gameOptions,
...userOptions,
port: gameQueryPort
});
} else if (gameOptions.port) {
attempts.push({
...defaultOptions,
...gameOptions,
2019-01-12 12:45:09 +01:00
...userOptions,
port: gameOptions.port + (gameQueryPortOffset || 0)
2019-01-12 11:43:36 +01:00
});
} else {
throw new Error("Could not determine port to query. Did you provide a port or gameid?");
}
if (attempts.length === 1) {
return await this._attempt(attempts[0]);
} else {
const errors = [];
for (const attempt of attempts) {
try {
return await this._attempt(attempt);
} catch(e) {
const e2 = new Error('Failed to query port ' + attempt.port);
e2.stack += "\nCaused by:\n" + e.stack;
errors.push(e2);
}
}
const err = new Error('Failed all port attempts');
err.stack = errors.map(e => e.stack).join('\n');
throw err;
}
}
async _attempt(options) {
if (options.debug) {
2019-01-20 11:21:40 +01:00
const logger = new Logger();
logger.debugEnabled = true;
logger.debug("Running attempt with options:");
logger.debug(options);
2019-01-12 11:43:36 +01:00
}
const core = this.protocolResolver.create(options.protocol);
core.options = options;
core.udpSocket = this.udpSocket;
return await core.runAllAttempts();
}
}
module.exports = QueryRunner;