node-gamedig/protocols/gamespy3.js

102 lines
2.2 KiB
JavaScript

module.exports = require('./core').extend({
init: function() {
this._super();
this.sessionId = 1;
this.encoding = 'latin1';
this.byteorder = 'be';
},
run: function() {
var self = this;
this.sendPacket(9,false,false,false,function(buffer) {
var reader = self.reader(buffer);
reader.skip(5);
var challenge = reader.string();
self.sendPacket(0,challenge,new Buffer([0,0,0,0]),true,function(buffer) {
var reader = self.reader(buffer);
var state = {
players:[]
};
while(!reader.done()) {
var key = reader.string();
if(!key) break;
var value = reader.string();
state[key] = value;
}
var mode = '';
while(!reader.done()) {
var mode = reader.string();
reader.skip(1);
while(!reader.done()) {
var item = reader.string();
if(!item) break;
if(mode.substr(-1) == '_') {
// players
state.players.push({name:item})
}
}
}
self.finish(state);
});
});
},
sendPacket: function(type,challenge,payload,assemble,c) {
var self = this;
var challengeLength = challenge === false ? 0 : 4;
var payloadLength = payload ? payload.length : 0;
var b = new Buffer(7 + challengeLength + payloadLength);
b.writeUInt8(0xFE, 0);
b.writeUInt8(0xFD, 1);
b.writeUInt8(type, 2);
b.writeUInt32BE(this.sessionId, 3);
if(challengeLength) b.writeUInt32BE(challenge, 7);
if(payloadLength) payload.copy(b, 7+challengeLength);
var numPackets = 0;
var packets = {};
this.udpSend(b,function(buffer) {
var iType = buffer.readUInt8(0);
if(iType != type) return;
var iSessionId = buffer.readUInt32BE(1);
if(iSessionId != self.sessionId) return;
if(!assemble) {
c(buffer);
return true;
}
var id = buffer.readUInt16LE(14);
var last = (id & 0x80);
id = id & 0x7f;
if(last) numPackets = id+1;
packets[id] = buffer.slice(16);
if(!numPackets || Object.keys(packets).length != numPackets) return;
// assemble the parts
var list = [];
for(var i = 0; i < numPackets; i++) {
if(!(i in packets)) {
self.error('Missing packet #'+i);
return true;
}
list.push(packets[i]);
}
var assembled = Buffer.concat(list);
c(assembled);
return true;
});
}
});