2015-11-02 04:56:08 +00:00
|
|
|
var net = require('net');
|
2015-11-02 06:57:30 +00:00
|
|
|
var mcpe_ping = require('mcpe-ping');
|
|
|
|
|
|
|
|
var mcpc = require('./mcpc_buffer');
|
2015-11-02 04:56:08 +00:00
|
|
|
|
|
|
|
function pingMinecraftPC(host, port, timeout, callback) {
|
|
|
|
var client = new net.Socket();
|
|
|
|
var milliseconds = (new Date).getTime();
|
|
|
|
|
2015-11-02 06:01:04 +00:00
|
|
|
client.setTimeout(timeout, function() {
|
|
|
|
client.destroy();
|
|
|
|
|
|
|
|
callback(new Error('timeout'), null);
|
|
|
|
});
|
|
|
|
|
2015-11-02 04:56:08 +00:00
|
|
|
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());
|
|
|
|
|
2015-11-02 06:57:30 +00:00
|
|
|
// Remap our JSON into our custom structure.
|
|
|
|
var res = {
|
|
|
|
players: json.players,
|
|
|
|
version: json.version.protocol,
|
|
|
|
latency: (new Date).getTime() - milliseconds
|
|
|
|
};
|
|
|
|
|
|
|
|
if (json.favicon) {
|
|
|
|
res.favicon = json.favicon;
|
|
|
|
}
|
2015-11-02 04:56:08 +00:00
|
|
|
|
|
|
|
// We parsed it, send it along!
|
2015-11-02 06:57:30 +00:00
|
|
|
callback(null, res);
|
2015-11-02 04:56:08 +00:00
|
|
|
} 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);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-11-02 06:57:30 +00:00
|
|
|
function pingMinecraftPE(host, port, timeout, callback) {
|
|
|
|
var milliseconds = (new Date).getTime();
|
|
|
|
|
|
|
|
mcpe_ping(host, port || 19132, function(err, res) {
|
|
|
|
if (err) {
|
|
|
|
callback(err, null);
|
|
|
|
} else {
|
|
|
|
// Remap our JSON into our custom structure.
|
|
|
|
callback(err, {
|
|
|
|
players: {
|
|
|
|
online: res.currentPlayers,
|
|
|
|
max: res.maxPlayers
|
|
|
|
},
|
|
|
|
version: res.version,
|
|
|
|
latency: (new Date).getTime() - milliseconds
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}, timeout);
|
|
|
|
}
|
|
|
|
|
2015-11-02 04:56:08 +00:00
|
|
|
// 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') {
|
2015-11-02 06:57:30 +00:00
|
|
|
pingMinecraftPC(host, port || 25565, timeout, callback);
|
2015-11-02 04:56:08 +00:00
|
|
|
} else if (type === 'PE') {
|
2015-11-02 06:57:30 +00:00
|
|
|
pingMinecraftPE(host, port || 19132, timeout, callback);
|
2015-11-02 04:56:08 +00:00
|
|
|
} else {
|
|
|
|
throw new Error('Unsupported type: ' + type);
|
|
|
|
}
|
|
|
|
};
|