From 675d358dec51d1d3e56068768062881c51b681d1 Mon Sep 17 00:00:00 2001 From: Will Franzen Date: Tue, 30 Dec 2014 02:55:04 -0600 Subject: [PATCH] Finish adding compression to pipeline (see note) It's 3 AM and I know theres a pretty big chance none of this code makes sense. Everything needs to be tested, as well as I need to figure out if encryption comes after compression or not. --- lib/client.js | 35 ++++++++++++++++++++++++++++------- lib/protocol.js | 15 +++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/lib/client.js b/lib/client.js index bb9b501..c9f20dd 100644 --- a/lib/client.js +++ b/lib/client.js @@ -4,6 +4,7 @@ var net = require('net') , protocol = require('./protocol') , dns = require('dns') , createPacketBuffer = protocol.createPacketBuffer + , compressPacketBuffer = protocol.compressPacketBuffer , parsePacket = protocol.parsePacket , states = protocol.states , debug = protocol.debug @@ -154,18 +155,38 @@ Client.prototype.write = function(packetId, params) { packetId = packetId[1]; } + // TODO: Which comes first, encryption or compression? + + var finishWriting = function(buffer) { + debug("writing packetId " + packetId + " (0x" + packetId.toString(16) + ")"); + debug(params); + var out = this.encryptionEnabled ? new Buffer(this.cipher.update(buffer), 'binary') : buffer; + this.socket.write(out); + return true; + } + var buffer = createPacketBuffer(packetId, this.state, params, this.isServer); - debug("writing packetId " + packetId + " (0x" + packetId.toString(16) + ")"); - debug(params); - var out = this.encryptionEnabled ? new Buffer(this.cipher.update(buffer), 'binary') : buffer; - this.socket.write(out); - return true; + if(this.compressionThreshold != -1 && buffer.length > this.compressionThreshold) { + compressPacketBuffer(buffer, finishWriting); + } else { + finishWriting(buffer); + } + }; Client.prototype.writeRaw = function(buffer, shouldEncrypt) { if (shouldEncrypt === null) { shouldEncrypt = true; } - var out = (shouldEncrypt && this.encryptionEnabled) ? new Buffer(this.cipher.update(buffer), 'binary') : buffer; - this.socket.write(out); + + var finishWriting = function(buffer) { + var out = (shouldEncrypt && this.encryptionEnabled) ? new Buffer(this.cipher.update(buffer), 'binary') : buffer; + this.socket.write(out); + }; + + if(this.compressionThreshold != -1 && buffer.length > this.compressionThreshold) { + compressPacketBuffer(buffer, finishWriting); + } else { + finishWriting(buffer); + } }; diff --git a/lib/protocol.js b/lib/protocol.js index 87cb3d3..ec417c9 100644 --- a/lib/protocol.js +++ b/lib/protocol.js @@ -1,5 +1,6 @@ var assert = require('assert'); var util = require('util'); +var zlib = require('zlib'); var STRING_MAX_LENGTH = 240; var SRV_STRING_MAX_LENGTH = 32767; @@ -1289,6 +1290,19 @@ function createPacketBuffer(packetId, state, params, isServer) { return buffer; } +function compressPacketBuffer(buffer, callback) { + var dataLength = buffer.length; + var packetLength = dataLength + sizeOfVarInt(dataLength); + var data = zlib.deflateRaw(buffer, function(compressedBuffer) { + var size = sizeOfVarInt(packetLength) + sizeOfVarInt(packetLength) + compressedBuffer.length; + var packetBuffer = new Buffer(size); + var offset = writeVarInt(packetLength, packetBuffer, 0); + offset = writeVarInt(dataLength, packetBuffer, offset); + writeVarInt(compressedBuffer, packetBuffer, offset); + callback(packetBuffer); + }); +} + function parsePacket(buffer, state, isServer, packetsToParse) { if (state == null) state = states.PLAY; var cursor = 0; @@ -1365,6 +1379,7 @@ module.exports = { sessionVersion: 13, parsePacket: parsePacket, createPacketBuffer: createPacketBuffer, + compressPacketBuffer: compressPacketBuffer, STRING_MAX_LENGTH: STRING_MAX_LENGTH, packetIds: packetIds, packetNames: packetNames,