feat: port caching (#478)

* feat: port caching

* feat: dont store in cache if disabled
This commit is contained in:
CosminPerRam 2024-01-17 23:23:20 +02:00 committed by GitHub
parent 1f0563f7d2
commit b48a4398cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 24 additions and 7 deletions

View File

@ -31,10 +31,12 @@
* Added code examples.
* New stable field: `queryPort` - this number indicates what was the port that the query was done on, 0 indicates none if not applicable.
* Fixed `numplayers` not having a default value.
* New option: `stripColors` (defaults to `true`) for protocols that strips colors: unreal2, savage2, quake3, nadeo, gamespy2, doom3, armagetron.
* New option: `requestRulesRequired` (defaults to `false`) Valve games only. `requestRules` is always required to have a response or the query will timeout.
* New option: `requestPlayersRequired` (defaults to `false`) Valve games only. Querying players is always required to have a response or the query will timeout. Some [games](GAMES_LIST.md) may not provide a players response.
* New option: `address` (defaults to `undefined`) Override the IP address of the server skipping DNS resolution. When set, host will not be resolved, instead address will be connected to. However, some protocols still use host for other reasons e.g. as part of the query.
* New options:
* `portCache` (defaults to `true`) after you queried a server, the second time you query that exact server (identified by specified ip and port), first add an attempt to query with the last successful port.
* `stripColors` (defaults to `true`) for protocols that strips colors: unreal2, savage2, quake3, nadeo, gamespy2, doom3, armagetron.
* `requestRulesRequired` (defaults to `false`) Valve games only. `requestRules` is always required to have a response or the query will timeout.
* `requestPlayersRequired` (defaults to `false`) Valve games only. Querying players is always required to have a response or the query will timeout. Some [games](GAMES_LIST.md) may not provide a players response.
* `address` (defaults to `undefined`) Override the IP address of the server skipping DNS resolution. When set, host will not be resolved, instead address will be connected to. However, some protocols still use host for other reasons e.g. as part of the query.
#### Games
* Removed the players::setNum method, the library will no longer add empty players as

View File

@ -51,6 +51,7 @@ Confused on how this works, or you want to see more? Checkout the [examples](/ex
| **requestRulesRequired** | boolean | false | Valve games only. `requestRules` is always required to have a response or the query will timeout. |
| **requestPlayersRequired** | boolean | false | Valve games only. Querying players is always required to have a response or the query will timeout. Some [games](GAMES_LIST.md) may not provide a players response. |
| **stripColors** | boolean | true | Enables stripping colors for protocols: unreal2, savage2, quake3, nadeo, gamespy2, doom3, armagetron. |
| **portCache** | boolean | true | After you queried a server, the second time you query that exact server (identified by specified ip and port), first add an attempt to query with the last successful port. |
## Query Response

View File

@ -6,10 +6,11 @@ import Minimist from 'minimist'
import { GameDig } from './../lib/index.js'
const argv = Minimist(process.argv.slice(2), {
boolean: ['pretty', 'debug', 'givenPortOnly', 'requestRules', 'requestRulesRequired', 'requestPlayersRequired', 'stripColors'],
boolean: ['pretty', 'debug', 'givenPortOnly', 'requestRules', 'requestRulesRequired', 'requestPlayersRequired', 'stripColors', 'portCache'],
string: ['guildId', 'listenUdpPort', 'ipFamily'],
default: {
stripColors: true
stripColors: true,
portCache: true
}
})

View File

@ -7,6 +7,7 @@ const defaultOptions = {
attemptTimeout: 10000,
maxAttempts: 1,
stripColors: true,
portCache: true,
ipFamily: 0
}
@ -15,6 +16,7 @@ export default class QueryRunner {
this.udpSocket = new GlobalUdpSocket({
port: runnerOpts.listenUdpPort
})
this.portCache = {}
}
async run (userOptions) {
@ -50,11 +52,18 @@ export default class QueryRunner {
gameQueryPortOffset ? portOffsetArray = [gameQueryPortOffset] : portOffsetArray = [0]
}
const cachedPort = this.portCache[`${userOptions.address}:${userOptions.port}`]
if (cachedPort && optionsCollection.portCache) {
addAttemptWithPort(cachedPort)
}
if (userOptions.port) {
if (!userOptions.givenPortOnly) {
portOffsetArray.forEach((portOffset) => { addAttemptWithPort(userOptions.port + portOffset) })
if (userOptions.port === gameOptions.port && gameQueryPort) { addAttemptWithPort(gameQueryPort) }
}
attempts.push(optionsCollection)
} else if (gameQueryPort) {
addAttemptWithPort(gameQueryPort)
@ -74,7 +83,11 @@ export default class QueryRunner {
attemptNum++
try {
return await this._attempt(attempt)
const response = await this._attempt(attempt)
if (attempt.portCache) {
this.portCache[`${userOptions.address}:${userOptions.port}`] = attempt.port
}
return response
} catch (e) {
e.stack = 'Attempt #' + attemptNum + ' - Port=' + attempt.port + ' Retry=' + (retry) + ':\n' + e.stack
errors.push(e)