node-gamedig/protocols/core.js

137 lines
3.2 KiB
JavaScript

var EventEmitter = require('events').EventEmitter,
dns = require('dns'),
async = require('async'),
Class = require('../Class'),
Bignum = require('bignum'),
Reader = require('../reader');
module.exports = Class.extend(EventEmitter,{
init: function() {
this._super();
this.options = {};
this.maxAttempts = 1;
this.attempt = 1;
this.finished = false;
this.encoding = 'utf8';
this.byteorder = 'le';
this.delimiter = '\0';
var self = this;
this.globalTimeoutTimer = setTimeout(function() {
self.fatal('timeout');
},10000);
},
fatal: function(err) {
this.error(err,true);
},
error: function(err,fatal) {
if(!fatal && this.attempt < this.maxAttempts) {
this.attempt++;
this.start();
return;
}
this.done({error: err.toString()});
},
finish: function(result) {
this.done(result);
},
done: function(result) {
if(this.finished) return;
clearTimeout(this.globalTimeoutTimer);
if(this.options.notes)
result.notes = this.options.notes;
this.reset();
this.finished = true;
this.emit('finished',result);
},
reset: function() {
if(this.timers) {
this.timers.forEach(function(timer) {
clearTimeout(timer);
});
}
this.timers = [];
this.udpTimeoutTimer = false;
this.udpCallback = false;
},
start: function() {
var self = this;
this.reset();
async.series([
function(c) {
// resolve host names
if(!('host' in self.options)) return c();
if(self.options.host.match(/\d+\.\d+\.\d+\.\d+/)) {
self.options.address = self.options.host;
c();
} else {
dns.lookup(self.options.host, function(err,address,family) {
if(err) return self.error(err);
self.options.address = address;
c();
});
}
}, function(c) {
self.run();
}
]);
},
reader: function(buffer) {
return new Reader(this,buffer);
},
setTimeout: function(c,t) {
if(this.finished) return 0;
var id = setTimeout(c,t);
this.timers.push(id);
return id;
},
udpSend: function(buffer,onpacket,ontimeout) {
var self = this;
process.nextTick(function() {
if(self.udpCallback) return self.fatal('Attempted to send UDP packet while still waiting on a managed response');
self._udpSendNow(buffer);
if(!onpacket) return;
self.udpTimeoutTimer = self.setTimeout(function() {
self.udpCallback = false;
var timeout = false;
if(!ontimeout || ontimeout() !== true) timeout = true;
if(timeout) self.error('timeout');
},1000);
self.udpCallback = onpacket;
});
},
_udpSendNow: function(buffer) {
if(!('port' in this.options)) return this.fatal('Attempted to send without setting a port');
if(!('address' in this.options)) return this.fatal('Attempted to send without setting an address');
if(typeof buffer == 'string') buffer = new Buffer(buffer,'binary');
this.udpSocket.send(buffer,0,buffer.length,this.options.port,this.options.address);
},
_udpResponse: function(buffer) {
if(this.udpCallback) {
var result = this.udpCallback(buffer);
if(result === true) {
// we're done with this udp session
clearTimeout(this.udpTimeoutTimer);
this.udpCallback = false;
}
} else {
this.udpResponse(buffer);
}
},
udpResponse: function() {}
});