From 911e0e890febc00102cd1e5406731e66f7bad0ef Mon Sep 17 00:00:00 2001 From: LucienHH <66429271+LucienHH@users.noreply.github.com> Date: Tue, 3 Dec 2024 22:23:32 +0000 Subject: [PATCH] Dynamic compression & batch header (#544) --- src/client.js | 1 + src/connection.js | 4 ++-- src/server.js | 4 ++++ src/serverPlayer.js | 2 ++ src/transforms/framer.js | 11 +++++++---- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/client.js b/src/client.js index 87e3705..2d798e6 100644 --- a/src/client.js +++ b/src/client.js @@ -26,6 +26,7 @@ class Client extends Connection { this.compressionAlgorithm = this.versionGreaterThanOrEqualTo('1.19.30') ? 'none' : 'deflate' this.compressionThreshold = 512 this.compressionLevel = this.options.compressionLevel + this.batchHeader = 0xfe if (isDebug) { this.inLog = (...args) => debug('C ->', ...args) diff --git a/src/connection.js b/src/connection.js index ca862ee..eb01f7f 100644 --- a/src/connection.js +++ b/src/connection.js @@ -153,7 +153,7 @@ class Connection extends EventEmitter { // These are callbacks called from encryption.js onEncryptedPacket = (buf) => { - const packet = Buffer.concat([Buffer.from([0xfe]), buf]) // add header + const packet = this.batchHeader ? Buffer.concat([Buffer.from([this.batchHeader]), buf]) : buf this.sendMCPE(packet) } @@ -165,7 +165,7 @@ class Connection extends EventEmitter { } handle (buffer) { // handle encapsulated - if (buffer[0] === 0xfe) { // wrapper + if (!this.batchHeader || buffer[0] === this.batchHeader) { // wrapper if (this.encryptionEnabled) { this.decrypt(buffer.slice(1)) } else { diff --git a/src/server.js b/src/server.js index 355e79a..6d9aa79 100644 --- a/src/server.js +++ b/src/server.js @@ -24,6 +24,7 @@ class Server extends EventEmitter { this.clients = {} this.clientCount = 0 this.conLog = debug + this.batchHeader = 0xfe this.setCompressor(this.options.compressionAlgorithm, this.options.compressionLevel, this.options.compressionThreshold) } @@ -44,16 +45,19 @@ class Server extends EventEmitter { case 'none': this.compressionAlgorithm = 'none' this.compressionLevel = 0 + this.compressionHeader = 255 break case 'deflate': this.compressionAlgorithm = 'deflate' this.compressionLevel = level this.compressionThreshold = threshold + this.compressionHeader = 0 break case 'snappy': this.compressionAlgorithm = 'snappy' this.compressionLevel = level this.compressionThreshold = threshold + this.compressionHeader = 1 break default: throw new Error(`Unknown compression algorithm: ${algorithm}`) diff --git a/src/serverPlayer.js b/src/serverPlayer.js index 4ef5243..b7ef02d 100644 --- a/src/serverPlayer.js +++ b/src/serverPlayer.js @@ -28,10 +28,12 @@ class Player extends Connection { this.outLog = (...args) => debug('<- S', ...args) } + this.batchHeader = this.server.batchHeader // Compression is server-wide this.compressionAlgorithm = this.server.compressionAlgorithm this.compressionLevel = this.server.compressionLevel this.compressionThreshold = this.server.compressionThreshold + this.compressionHeader = this.server.compressionHeader this._sentNetworkSettings = false // 1.19.30+ } diff --git a/src/transforms/framer.js b/src/transforms/framer.js index c59dd4e..a2d9c4f 100644 --- a/src/transforms/framer.js +++ b/src/transforms/framer.js @@ -6,9 +6,11 @@ class Framer { constructor (client) { // Encoding this.packets = [] + this.batchHeader = client.batchHeader this.compressor = client.compressionAlgorithm || 'none' this.compressionLevel = client.compressionLevel this.compressionThreshold = client.compressionThreshold + this.compressionHeader = client.compressionHeader || 0 this.writeCompressor = client.features.compressorInHeader && client.compressionReady } @@ -38,7 +40,7 @@ class Framer { static decode (client, buf) { // Read header - if (buf[0] !== 0xfe) throw Error('bad batch packet header ' + buf[0]) + if (this.batchHeader && buf[0] !== this.batchHeader) throw Error(`bad batch packet header, received: ${buf[0]}, expected: ${this.batchHeader}`) const buffer = buf.slice(1) // Decompress let decompressed @@ -58,9 +60,10 @@ class Framer { encode () { const buf = Buffer.concat(this.packets) - const compressed = (buf.length > this.compressionThreshold) ? this.compress(buf) : buf - const header = this.writeCompressor ? [0xfe, 0] : [0xfe] - return Buffer.concat([Buffer.from(header), compressed]) + const shouldCompress = buf.length > this.compressionThreshold + const header = this.batchHeader ? [this.batchHeader] : [] + if (this.writeCompressor) header.push(shouldCompress ? this.compressionHeader : 255) + return Buffer.concat([Buffer.from(header), shouldCompress ? this.compress(buf) : buf]) } addEncodedPacket (chunk) {