Merge pull request #334 from deathcap/legacyping

Server response to legacy ping (fe and fe01) packets
This commit is contained in:
Romain Beaumont 2016-02-01 10:07:40 +01:00
commit bf029d3698
4 changed files with 49 additions and 1 deletions

View File

@ -29,6 +29,7 @@
"browser": "browser.js",
"devDependencies": {
"babel-preset-es2015": "^6.3.13",
"endian-toggle": "0.0.0",
"espower-loader": "^1.0.0",
"gulp": "^3.9.0",
"gulp-babel": "^6.1.1",

View File

@ -14,6 +14,7 @@ class Client extends EventEmitter
super();
this.version=version;
this.isServer = !!isServer;
this.splitter=framing.createSplitter();
this.setSerializer(states.HANDSHAKING);
this.packetsToParse={};
this.serializer;
@ -21,7 +22,6 @@ class Client extends EventEmitter
this.framer=framing.createFramer();
this.cipher=null;
this.decipher=null;
this.splitter=framing.createSplitter();
this.decompressor=null;
this.deserializer;
this.isServer;
@ -51,6 +51,7 @@ class Client extends EventEmitter
this.deserializer = createDeserializer({ isServer:this.isServer, version:this.version, state: state, packetsToParse:
this.packetsToParse});
this.splitter.recognizeLegacyPing = state === states.HANDSHAKING;
this.serializer.on('error', (e) => {
var parts=e.field.split(".");

View File

@ -5,6 +5,7 @@ var states = require("./states");
var bufferEqual = require('buffer-equal');
var Server = require('./server');
var UUID = require('uuid-1345');
var endianToggle = require('endian-toggle');
module.exports=createServer;
@ -40,6 +41,7 @@ function createServer(options) {
client.once('set_protocol', onHandshake);
client.once('login_start', onLogin);
client.once('ping_start', onPing);
client.once('legacy_server_list_ping', onLegacyPing);
client.on('end', onEnd);
var keepAlive = false;
@ -126,6 +128,35 @@ function createServer(options) {
});
}
function onLegacyPing(packet) {
if (packet.payload === 1) {
var pingVersion = 1;
sendPingResponse('\xa7' + [pingVersion, version.version, version.minecraftVersion,
server.motd, server.playerCount.toString(), server.maxPlayers.toString()].join('\0'));
} else {
// ping type 0
sendPingResponse([server.motd, server.playerCount.toString(), server.maxPlayers.toString()].join('\xa7'));
}
function sendPingResponse(responseString) {
function utf16be(s) {
return endianToggle(new Buffer(s, 'utf16le'), 16);
}
var responseBuffer = utf16be(responseString);
var length = responseString.length; // UCS2 characters, not bytes
var lengthBuffer = new Buffer(2);
lengthBuffer.writeUInt16BE(length);
var raw = Buffer.concat([new Buffer('ff', 'hex'), lengthBuffer, responseBuffer]);
//client.writeRaw(raw); // not raw enough, it includes length
client.socket.write(raw);
}
}
function onLogin(packet) {
client.username = packet.username;
var isException = !!server.onlineModeExceptions[client.username.toLowerCase()];

View File

@ -23,13 +23,28 @@ class Framer extends Transform {
}
}
const LEGACY_PING_PACKET_ID = 0xfe;
class Splitter extends Transform {
constructor() {
super();
this.buffer = new Buffer(0);
this.recognizeLegacyPing = false;
}
_transform(chunk, enc, cb) {
this.buffer = Buffer.concat([this.buffer, chunk]);
if (this.recognizeLegacyPing && this.buffer[0] === LEGACY_PING_PACKET_ID) {
// legacy_server_list_ping packet follows a different protocol format
// prefix the encoded varint packet id for the deserializer
var header = new Buffer(sizeOfVarInt(LEGACY_PING_PACKET_ID));
writeVarInt(LEGACY_PING_PACKET_ID, header, 0);
var payload = this.buffer.slice(1); // remove 0xfe packet id
if (payload.length === 0) payload = new Buffer('\0'); // TODO: update minecraft-data to recognize a lone 0xfe, https://github.com/PrismarineJS/minecraft-data/issues/95
this.push(Buffer.concat([header, payload]));
return cb();
}
var offset = 0;
var { value, size, error } = readVarInt(this.buffer, offset) || { error: "Not enough data" };