2015-03-26 11:26:01 -04:00
|
|
|
var mc = require('../../');
|
2015-02-22 17:13:22 -05:00
|
|
|
|
2015-05-22 21:31:47 -04:00
|
|
|
var states = mc.states;
|
2015-03-18 06:58:20 -04:00
|
|
|
function printHelpAndExit(exitCode) {
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log("usage: node proxy.js [<options>...] <target_srv> <user> [<password>]");
|
|
|
|
console.log("options:");
|
|
|
|
console.log(" --dump ID");
|
|
|
|
console.log(" print to stdout messages with the specified ID.");
|
|
|
|
console.log(" --dump-all");
|
|
|
|
console.log(" print to stdout all messages, except those specified with -x.");
|
|
|
|
console.log(" -x ID");
|
|
|
|
console.log(" do not print messages with this ID.");
|
|
|
|
console.log(" ID");
|
|
|
|
console.log(" an integer in decimal or hex (given to JavaScript's parseInt())");
|
|
|
|
console.log(" optionally prefixed with o for client->server or i for client<-server.");
|
|
|
|
console.log("examples:");
|
|
|
|
console.log(" node proxy.js --dump-all -x 0x0 -x 0x3 -x 0x12 -x 0x015 -x 0x16 -x 0x17 -x 0x18 -x 0x19 localhost Player");
|
|
|
|
console.log(" print all messages except for some of the most prolific.");
|
|
|
|
console.log(" node examples/proxy.js --dump i0x2d --dump i0x2e --dump i0x2f dump i0x30 --dump i0x31 --dump i0x32 --dump o0x0d --dump o0x0e --dump o0x0f --dump o0x10 --dump o0x11 localhost Player");
|
|
|
|
console.log(" print messages relating to inventory management.");
|
2015-03-18 06:58:20 -04:00
|
|
|
|
2015-05-14 16:08:49 -04:00
|
|
|
process.exit(exitCode);
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
|
2015-05-14 16:08:49 -04:00
|
|
|
if(process.argv.length < 4) {
|
|
|
|
console.log("Too few arguments!");
|
|
|
|
printHelpAndExit(1);
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
process.argv.forEach(function(val, index, array) {
|
2015-05-14 16:08:49 -04:00
|
|
|
if(val == "-h") {
|
|
|
|
printHelpAndExit(0);
|
|
|
|
}
|
2015-02-22 17:13:22 -05:00
|
|
|
});
|
|
|
|
|
2015-03-18 06:58:20 -04:00
|
|
|
var args = process.argv.slice(2);
|
|
|
|
var host;
|
2015-02-22 17:13:22 -05:00
|
|
|
var port = 25565;
|
2015-03-18 06:58:20 -04:00
|
|
|
var user;
|
|
|
|
var passwd;
|
|
|
|
|
|
|
|
var printAllIds = false;
|
|
|
|
var printIdWhitelist = {};
|
|
|
|
var printIdBlacklist = {};
|
|
|
|
(function() {
|
2015-05-14 16:08:49 -04:00
|
|
|
for(var i = 0; i < args.length; i++) {
|
|
|
|
var option = args[i];
|
|
|
|
if(!/^-/.test(option)) break;
|
|
|
|
if(option == "--dump-all") {
|
|
|
|
printAllIds = true;
|
|
|
|
continue;
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2015-05-14 16:08:49 -04:00
|
|
|
i++;
|
|
|
|
var match = /^([io]?)(.*)/.exec(args[i]);
|
|
|
|
var prefix = match[1];
|
|
|
|
if(prefix === "") prefix = "io";
|
|
|
|
var number = parseInt(match[2]);
|
|
|
|
if(isNaN(number)) printHelpAndExit(1);
|
|
|
|
if(option == "--dump") {
|
|
|
|
printIdWhitelist[number] = prefix;
|
|
|
|
} else if(option == "-x") {
|
|
|
|
printIdBlacklist[number] = prefix;
|
|
|
|
} else {
|
|
|
|
printHelpAndExit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!(i + 2 <= args.length && args.length <= i + 3)) printHelpAndExit(1);
|
|
|
|
host = args[i++];
|
|
|
|
user = args[i++];
|
|
|
|
passwd = args[i++];
|
2015-03-18 06:58:20 -04:00
|
|
|
})();
|
2015-02-22 17:13:22 -05:00
|
|
|
|
2015-05-14 16:08:49 -04:00
|
|
|
if(host.indexOf(':') != -1) {
|
|
|
|
port = host.substring(host.indexOf(':') + 1);
|
|
|
|
host = host.substring(0, host.indexOf(':'));
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
var srv = mc.createServer({
|
|
|
|
'online-mode': false,
|
|
|
|
port: 25566
|
|
|
|
});
|
2015-05-14 16:08:49 -04:00
|
|
|
srv.on('login', function(client) {
|
2015-02-22 17:13:22 -05:00
|
|
|
var addr = client.socket.remoteAddress;
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log('Incoming connection', '(' + addr + ')');
|
2015-02-22 17:13:22 -05:00
|
|
|
var endedClient = false;
|
|
|
|
var endedTargetClient = false;
|
|
|
|
client.on('end', function() {
|
|
|
|
endedClient = true;
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log('Connection closed by client', '(' + addr + ')');
|
|
|
|
if(!endedTargetClient)
|
2015-02-22 17:13:22 -05:00
|
|
|
targetClient.end("End");
|
|
|
|
});
|
|
|
|
client.on('error', function() {
|
|
|
|
endedClient = true;
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log('Connection error by client', '(' + addr + ')');
|
|
|
|
if(!endedTargetClient)
|
2015-02-24 18:44:59 -05:00
|
|
|
targetClient.end("Error");
|
2015-02-22 17:13:22 -05:00
|
|
|
});
|
|
|
|
var targetClient = mc.createClient({
|
|
|
|
host: host,
|
|
|
|
port: port,
|
|
|
|
username: user,
|
2015-03-03 07:43:46 -05:00
|
|
|
password: passwd,
|
|
|
|
'online-mode': passwd != null ? true : false
|
2015-02-22 17:13:22 -05:00
|
|
|
});
|
2015-03-03 07:43:46 -05:00
|
|
|
var brokenPackets = [/*0x04, 0x2f, 0x30*/];
|
2015-02-22 17:13:22 -05:00
|
|
|
client.on('packet', function(packet) {
|
2015-05-14 16:08:49 -04:00
|
|
|
if(targetClient.state == states.PLAY && packet.state == states.PLAY) {
|
|
|
|
if(shouldDump(packet.id, "o")) {
|
2015-03-18 06:58:20 -04:00
|
|
|
console.log("client->server:",
|
2015-05-14 16:08:49 -04:00
|
|
|
client.state + ".0x" + packet.id.toString(16) + " :",
|
|
|
|
JSON.stringify(packet));
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2015-05-14 16:08:49 -04:00
|
|
|
if(!endedTargetClient)
|
2015-02-22 17:13:22 -05:00
|
|
|
targetClient.write(packet.id, packet);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
targetClient.on('packet', function(packet) {
|
2015-05-14 16:08:49 -04:00
|
|
|
if(packet.state == states.PLAY && client.state == states.PLAY &&
|
|
|
|
brokenPackets.indexOf(packet.id) === -1) {
|
|
|
|
if(shouldDump(packet.id, "i")) {
|
2015-03-18 06:58:20 -04:00
|
|
|
console.log("client<-server:",
|
2015-05-14 16:08:49 -04:00
|
|
|
targetClient.state + ".0x" + packet.id.toString(16) + " :",
|
|
|
|
(packet.id != 38 ? JSON.stringify(packet) : "Packet too big"));
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|
2015-05-14 16:08:49 -04:00
|
|
|
if(!endedClient)
|
2015-02-22 17:13:22 -05:00
|
|
|
client.write(packet.id, packet);
|
2015-05-15 21:08:41 -04:00
|
|
|
if (packet.id === 0x46) // Set compression
|
|
|
|
client.compressionThreshold = packet.threshold;
|
2015-02-22 17:13:22 -05:00
|
|
|
}
|
|
|
|
});
|
2015-03-03 07:43:46 -05:00
|
|
|
var buffertools = require('buffertools');
|
|
|
|
targetClient.on('raw', function(buffer, state) {
|
2015-05-14 16:08:49 -04:00
|
|
|
if(client.state != states.PLAY || state != states.PLAY)
|
2015-03-03 07:43:46 -05:00
|
|
|
return;
|
2015-05-22 21:31:47 -04:00
|
|
|
var packetId = mc.types.varint[0](buffer, 0);
|
|
|
|
var packetData = mc.parsePacketData(buffer, state, false, {"packet": 1}).results;
|
|
|
|
var packetBuff = mc.createPacketBuffer(packetData.id, packetData.state, packetData, true);
|
2015-05-14 16:08:49 -04:00
|
|
|
if(buffertools.compare(buffer, packetBuff) != 0) {
|
2015-03-06 17:58:58 -05:00
|
|
|
console.log("client<-server: Error in packetId " + state + ".0x" + packetId.value.toString(16));
|
2015-03-03 07:43:46 -05:00
|
|
|
console.log(buffer.toString('hex'));
|
|
|
|
console.log(packetBuff.toString('hex'));
|
|
|
|
}
|
|
|
|
/*if (client.state == states.PLAY && brokenPackets.indexOf(packetId.value) !== -1)
|
2015-05-14 16:08:49 -04:00
|
|
|
{
|
|
|
|
console.log(`client<-server: raw packet);
|
|
|
|
console.log(packetData);
|
|
|
|
if (!endedClient)
|
|
|
|
client.writeRaw(buffer);
|
|
|
|
}*/
|
2015-03-03 07:43:46 -05:00
|
|
|
});
|
|
|
|
client.on('raw', function(buffer, state) {
|
2015-05-14 16:08:49 -04:00
|
|
|
if(state != states.PLAY || targetClient.state != states.PLAY)
|
2015-03-03 07:43:46 -05:00
|
|
|
return;
|
2015-05-22 21:31:47 -04:00
|
|
|
var packetId = mc.types.varint[0](buffer, 0);
|
|
|
|
var packetData = mc.parsePacketData(buffer, state, true, {"packet": 1}).results;
|
|
|
|
var packetBuff = mc.createPacketBuffer(packetData.id, packetData.state, packetData, false);
|
2015-05-14 16:08:49 -04:00
|
|
|
if(buffertools.compare(buffer, packetBuff) != 0) {
|
2015-03-06 18:14:36 -05:00
|
|
|
console.log("client->server: Error in packetId " + state + ".0x" + packetId.value.toString(16));
|
2015-03-03 07:43:46 -05:00
|
|
|
console.log(buffer.toString('hex'));
|
|
|
|
console.log(packetBuff.toString('hex'));
|
2015-07-29 20:41:49 -04:00
|
|
|
console.log(buffer.length);
|
|
|
|
console.log(packetBuff.length);
|
2015-03-03 07:43:46 -05:00
|
|
|
}
|
|
|
|
});
|
2015-02-22 17:13:22 -05:00
|
|
|
targetClient.on('end', function() {
|
|
|
|
endedTargetClient = true;
|
2015-05-14 16:08:49 -04:00
|
|
|
console.log('Connection closed by server', '(' + addr + ')');
|
|
|
|
if(!endedClient)
|
2015-02-22 17:13:22 -05:00
|
|
|
client.end("End");
|
|
|
|
});
|
2015-07-29 20:41:49 -04:00
|
|
|
targetClient.on('error', function(err) {
|
2015-02-22 17:13:22 -05:00
|
|
|
endedTargetClient = true;
|
2015-07-29 20:41:49 -04:00
|
|
|
console.log('Connection error by server', '(' + addr + ') ',err);
|
|
|
|
console.log(err.stack);
|
2015-05-14 16:08:49 -04:00
|
|
|
if(!endedClient)
|
2015-02-22 17:13:22 -05:00
|
|
|
client.end("Error");
|
|
|
|
});
|
|
|
|
});
|
2015-03-18 06:58:20 -04:00
|
|
|
|
2015-03-24 19:43:38 -04:00
|
|
|
function shouldDump(id, direction) {
|
2015-05-14 16:08:49 -04:00
|
|
|
if(matches(printIdBlacklist[id])) return false;
|
|
|
|
if(printAllIds) return true;
|
|
|
|
if(matches(printIdWhitelist[id])) return true;
|
2015-03-18 06:58:20 -04:00
|
|
|
return false;
|
2015-03-24 19:43:38 -04:00
|
|
|
function matches(result) {
|
|
|
|
return result != null && result.indexOf(direction) !== -1;
|
|
|
|
}
|
2015-03-18 06:58:20 -04:00
|
|
|
}
|