2017-08-09 11:05:55 +02:00
|
|
|
const dgram = require('dgram'),
|
2017-08-10 13:49:42 +02:00
|
|
|
TypeResolver = require('./typeresolver'),
|
|
|
|
HexUtil = require('./HexUtil');
|
2014-10-29 08:02:03 +01:00
|
|
|
|
2019-01-07 07:52:29 +01:00
|
|
|
const activeQueries = new Set();
|
2014-10-29 08:02:03 +01:00
|
|
|
|
2017-08-09 11:05:55 +02:00
|
|
|
const udpSocket = dgram.createSocket('udp4');
|
2014-10-29 08:02:03 +01:00
|
|
|
udpSocket.unref();
|
2018-01-31 07:43:11 +01:00
|
|
|
udpSocket.bind();
|
2017-08-09 11:05:55 +02:00
|
|
|
udpSocket.on('message', (buffer, rinfo) => {
|
2017-08-10 13:49:42 +02:00
|
|
|
if(Gamedig.debug) {
|
|
|
|
console.log(rinfo.address+':'+rinfo.port+" <--UDP");
|
|
|
|
console.log(HexUtil.debugDump(buffer));
|
|
|
|
}
|
2017-08-09 12:32:09 +02:00
|
|
|
for(const query of activeQueries) {
|
2019-01-07 07:52:29 +01:00
|
|
|
if(query.options.address !== rinfo.address) continue;
|
2017-08-09 12:32:09 +02:00
|
|
|
if(query.options.port_query !== rinfo.port) continue;
|
2019-01-07 07:52:29 +01:00
|
|
|
query._udpIncoming(buffer);
|
2017-08-09 12:32:09 +02:00
|
|
|
break;
|
|
|
|
}
|
2014-10-29 08:02:03 +01:00
|
|
|
});
|
2017-08-09 11:05:55 +02:00
|
|
|
udpSocket.on('error', (e) => {
|
2017-08-09 12:32:09 +02:00
|
|
|
if(Gamedig.debug) console.log("UDP ERROR: "+e);
|
2014-10-29 08:02:03 +01:00
|
|
|
});
|
|
|
|
|
2017-08-09 11:05:55 +02:00
|
|
|
class Gamedig {
|
2014-10-29 08:02:03 +01:00
|
|
|
|
2017-08-09 12:32:09 +02:00
|
|
|
static query(options,callback) {
|
2019-01-07 07:52:29 +01:00
|
|
|
const promise = (async () => {
|
2017-08-09 11:05:55 +02:00
|
|
|
for (const key of Object.keys(options)) {
|
2017-08-09 12:32:09 +02:00
|
|
|
if (['port_query', 'port'].includes(key)) {
|
|
|
|
options[key] = parseInt(options[key]);
|
|
|
|
}
|
|
|
|
}
|
2017-08-09 11:05:55 +02:00
|
|
|
|
2019-01-07 07:52:29 +01:00
|
|
|
let query = TypeResolver.lookup(options.type);
|
2017-08-09 12:32:09 +02:00
|
|
|
query.debug = Gamedig.debug;
|
|
|
|
query.udpSocket = udpSocket;
|
|
|
|
query.type = options.type;
|
2014-10-29 08:02:03 +01:00
|
|
|
|
2017-08-09 12:32:09 +02:00
|
|
|
if(!('port' in query.options) && ('port_query' in query.options)) {
|
|
|
|
if(Gamedig.isCommandLine) {
|
|
|
|
process.stderr.write(
|
|
|
|
"Warning! This game is so old, that we don't know"
|
|
|
|
+" what the server's connection port is. We've guessed that"
|
|
|
|
+" the query port for "+query.type+" is "+query.options.port_query+"."
|
|
|
|
+" If you know the connection port for this type of server, please let"
|
|
|
|
+" us know on the GameDig issue tracker, thanks!\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
query.options.port = query.options.port_query;
|
|
|
|
delete query.options.port_query;
|
|
|
|
}
|
2014-10-29 08:02:03 +01:00
|
|
|
|
2017-08-09 12:32:09 +02:00
|
|
|
// copy over options
|
|
|
|
for(const key of Object.keys(options)) {
|
|
|
|
query.options[key] = options[key];
|
2017-08-09 11:05:55 +02:00
|
|
|
}
|
2017-03-14 09:40:02 +01:00
|
|
|
|
2019-01-07 07:52:29 +01:00
|
|
|
activeQueries.add(query);
|
|
|
|
try {
|
|
|
|
return await query.runAll();
|
|
|
|
} finally {
|
|
|
|
activeQueries.delete(query);
|
|
|
|
}
|
|
|
|
})();
|
2014-10-29 08:02:03 +01:00
|
|
|
|
2017-08-09 12:32:09 +02:00
|
|
|
if (callback && callback instanceof Function) {
|
|
|
|
if(callback.length === 2) {
|
|
|
|
promise
|
|
|
|
.then((state) => callback(null,state))
|
|
|
|
.catch((error) => callback(error));
|
|
|
|
} else if (callback.length === 1) {
|
|
|
|
promise
|
|
|
|
.then((state) => callback(state))
|
|
|
|
.catch((error) => callback({error:error}));
|
|
|
|
}
|
|
|
|
}
|
2017-03-14 09:40:02 +01:00
|
|
|
|
2017-08-09 12:32:09 +02:00
|
|
|
return promise;
|
|
|
|
}
|
2014-10-29 08:02:03 +01:00
|
|
|
|
2017-08-09 11:05:55 +02:00
|
|
|
}
|
2019-01-07 01:52:03 +01:00
|
|
|
Gamedig.debug = false;
|
|
|
|
Gamedig.isCommandLine = false;
|
2014-10-29 08:02:03 +01:00
|
|
|
|
|
|
|
module.exports = Gamedig;
|