Minetrack/lib/ping.js
2015-11-02 00:01:04 -06:00

97 lines
2.4 KiB
JavaScript

var mcpc = require('./mcpc_buffer');
var net = require('net');
function pingMinecraftPC(host, port, timeout, callback) {
var client = new net.Socket();
var milliseconds = (new Date).getTime();
client.setTimeout(timeout, function() {
client.destroy();
callback(new Error('timeout'), null);
});
client.connect(port, host, function() {
// Write out handshake packet.
var handshakeBuffer = mcpc.createBuffer();
handshakeBuffer.writeVarInt(0);
handshakeBuffer.writeVarInt(47);
handshakeBuffer.writeString(host);
handshakeBuffer.writeUShort(port);
handshakeBuffer.writeVarInt(1);
writePCBuffer(client, handshakeBuffer);
// Write the set connection state packet, we should get the MOTD after this.
var setModeBuffer = mcpc.createBuffer();
setModeBuffer.writeVarInt(0);
writePCBuffer(client, setModeBuffer);
});
var readingBuffer = new Buffer(0);
client.on('data', function(data) {
readingBuffer = Buffer.concat([readingBuffer, data]);
var buffer = mcpc.createBuffer(readingBuffer);
var length;
try {
length = buffer.readVarInt();
} catch(err) {
// The buffer isn't long enough yet, wait for more data!
return;
}
// Make sure we have the data we need!
if (readingBuffer.length < length - buffer.offset() ) {
return;
}
// Read the packet ID, throw it away.
buffer.readVarInt();
try {
var json = JSON.parse(buffer.readString());
json.latency = (new Date).getTime() - milliseconds;
// We parsed it, send it along!
callback(null, json);
} catch (err) {
// Our data is corrupt? Fail hard.
callback(err, null);
return;
}
// We're done here.
client.destroy();
});
client.on('error', function(err) {
callback(err, null);
});
}
// Wraps our Buffer into another to fit the Minecraft protocol.
function writePCBuffer(client, buffer) {
var length = mcpc.createBuffer();
length.writeVarInt(buffer.buffer().length);
client.write(Buffer.concat([length.buffer(), buffer.buffer()]));
}
exports.ping = function(host, port, type, timeout, callback) {
if (type === 'PC') {
pingMinecraftPC(host, port, timeout, callback);
} else if (type === 'PE') {
} else {
throw new Error('Unsupported type: ' + type);
}
};