From ea92ba42bb01b150aae6c1a179a9e0a167e4d9a1 Mon Sep 17 00:00:00 2001 From: Richard Wesley Date: Tue, 30 May 2017 09:02:17 -0700 Subject: [PATCH 1/4] Add support for variable size headers and lengths (<= 6 bytes). Add support for little-endian packet headers. --- index.js | 20 ++++++++++++++------ test/index.js | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 6ca60fd..4b63fbb 100644 --- a/index.js +++ b/index.js @@ -12,8 +12,11 @@ var Reader = module.exports = function(options) { this.chunkLength = 0 this.headerSize = options.headerSize || 0 this.lengthPadding = options.lengthPadding || 0 + this.lengthBE = options.lengthBE || true + this.lengthSize = options.lengthSize || 4 + assert( this.lengthSize <= 6, 'lengths of more than 6 bytes are not currently supported' ) this.header = null - assert(this.headerSize < 2, 'pre-length header of more than 1 byte length not currently supported') + assert(this.headerSize <= 6 , 'pre-length header with more than a 6 byte length not currently supported') } Reader.prototype.addChunk = function(chunk) { @@ -41,24 +44,29 @@ Reader.prototype.addChunk = function(chunk) { } Reader.prototype.read = function() { - if(this.chunkLength < (this.headerSize + 4 + this.offset)) { + if(this.chunkLength < (this.headerSize + this.lengthSize + this.offset)) { return false } if(this.headerSize) { - this.header = this.chunk[this.offset] + if ( this.lengthBE ) + this.header += this.chunk.readUIntBE( this.offset, this.headerSize ); + else this.header += this.chunk.readUIntLE( this.offset, this.headerSize ); } //read length of next item - var length = this.chunk.readUInt32BE(this.offset + this.headerSize) + this.lengthPadding + var length = this.lengthPadding; + if ( this.lengthBE ) + length += this.chunk.readUIntBE( this.offset + this.headerSize, this.lengthSize ); + else length += this.chunk.readUIntLE( this.offset + this.headerSize, this.lengthSize ); //next item spans more chunks than we have - var remaining = this.chunkLength - (this.offset + 4 + this.headerSize) + var remaining = this.chunkLength - (this.offset + this.lengthSize + this.headerSize) if(length > remaining) { return false } - this.offset += (this.headerSize + 4) + this.offset += (this.headerSize + this.lengthSize) var result = this.chunk.slice(this.offset, this.offset + length) this.offset += length return result diff --git a/test/index.js b/test/index.js index 5bb400d..fcf8a13 100644 --- a/test/index.js +++ b/test/index.js @@ -146,3 +146,23 @@ describe('postgres style packet', function() { assert.equal(result[3], 0) }) }) + + +describe('little-endian style packet', function() { + beforeEach(function() { + this.reader = new Reader({ + headerSize: 4, + lengthBE: false + }) + }) + + it('reads 4-byte LE header', function() { + this.reader.addChunk(new Buffer([0x06, 0xEA, 0xB1, 0x7A, 0, 0, 0, 2, 7, 11])) + var result = this.reader.read() + assert(result) + assert.equal(this.reader.header, 0x06EAB17A) + assert.equal(result.length, 2) + assert.equal(result[0], 7) + assert.equal(result[1], 11) + }) +}) From 9f0415db0e41ecbb78c68a49cf39740132a5a2bf Mon Sep 17 00:00:00 2001 From: Richard Wesley Date: Tue, 6 Jun 2017 15:38:28 -0700 Subject: [PATCH 2/4] Fix little-endian code to read config correctly. This required changing the sense of the missing parameter. Fix the test to provide actual LE data. --- index.js | 14 +++++++------- test/index.js | 14 ++++++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/index.js b/index.js index 4b63fbb..8dd8da1 100644 --- a/index.js +++ b/index.js @@ -12,7 +12,7 @@ var Reader = module.exports = function(options) { this.chunkLength = 0 this.headerSize = options.headerSize || 0 this.lengthPadding = options.lengthPadding || 0 - this.lengthBE = options.lengthBE || true + this.lengthLE = options.lengthLE || false this.lengthSize = options.lengthSize || 4 assert( this.lengthSize <= 6, 'lengths of more than 6 bytes are not currently supported' ) this.header = null @@ -49,16 +49,16 @@ Reader.prototype.read = function() { } if(this.headerSize) { - if ( this.lengthBE ) - this.header += this.chunk.readUIntBE( this.offset, this.headerSize ); - else this.header += this.chunk.readUIntLE( this.offset, this.headerSize ); + if ( this.lengthLE ) + this.header += this.chunk.readUIntLE( this.offset, this.headerSize ); + else this.header += this.chunk.readUIntBE( this.offset, this.headerSize ); } //read length of next item var length = this.lengthPadding; - if ( this.lengthBE ) - length += this.chunk.readUIntBE( this.offset + this.headerSize, this.lengthSize ); - else length += this.chunk.readUIntLE( this.offset + this.headerSize, this.lengthSize ); + if ( this.lengthLE ) + length += this.chunk.readUIntLE( this.offset + this.headerSize, this.lengthSize ); + else length += this.chunk.readUIntBE( this.offset + this.headerSize, this.lengthSize ); //next item spans more chunks than we have var remaining = this.chunkLength - (this.offset + this.lengthSize + this.headerSize) diff --git a/test/index.js b/test/index.js index fcf8a13..42d4236 100644 --- a/test/index.js +++ b/test/index.js @@ -152,17 +152,19 @@ describe('little-endian style packet', function() { beforeEach(function() { this.reader = new Reader({ headerSize: 4, - lengthBE: false + lengthLE: true, + lengthPadding: 8, }) }) - it('reads 4-byte LE header', function() { - this.reader.addChunk(new Buffer([0x06, 0xEA, 0xB1, 0x7A, 0, 0, 0, 2, 7, 11])) + it('reads 4-byte LE size with a 4 byte LE header and 8 byte padding', function() { + var buf = new Buffer([0x7A, 0xB1, 0xEA, 0x06, 4, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0x00, 0xA4, 0xD3, 0xF1]); + this.reader.addChunk( buf ) var result = this.reader.read() assert(result) assert.equal(this.reader.header, 0x06EAB17A) - assert.equal(result.length, 2) - assert.equal(result[0], 7) - assert.equal(result[1], 11) + assert.equal(result.length, 12) + for ( i = 0; i < result.length; ++i ) + assert.equal(result[i], buf[i+8]) }) }) From 1bbfce297183314a4e8808c0b477111a684f4cde Mon Sep 17 00:00:00 2001 From: Richard Wesley Date: Wed, 7 Jun 2017 13:23:52 -0700 Subject: [PATCH 3/4] Don't add to the header. --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 8dd8da1..0730071 100644 --- a/index.js +++ b/index.js @@ -50,8 +50,8 @@ Reader.prototype.read = function() { if(this.headerSize) { if ( this.lengthLE ) - this.header += this.chunk.readUIntLE( this.offset, this.headerSize ); - else this.header += this.chunk.readUIntBE( this.offset, this.headerSize ); + this.header = this.chunk.readUIntLE( this.offset, this.headerSize ); + else this.header = this.chunk.readUIntBE( this.offset, this.headerSize ); } //read length of next item From 0d1488b3a2c6ba76ac0f409a8e80c090231c8edc Mon Sep 17 00:00:00 2001 From: Richard Wesley Date: Thu, 3 Dec 2020 16:15:37 -0800 Subject: [PATCH 4/4] Fix new Buffer depreciation warnings --- test/index.js | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/index.js b/test/index.js index 42d4236..b1ae678 100644 --- a/test/index.js +++ b/test/index.js @@ -6,7 +6,7 @@ describe('packet-reader', function() { }) it('reads perfect 1 length buffer', function() { - this.reader.addChunk(new Buffer([0, 0, 0, 0, 1, 1])) + this.reader.addChunk(Buffer.from([0, 0, 0, 0, 1, 1])) var result = this.reader.read() assert.equal(result.length, 1) assert.equal(result[0], 1) @@ -14,17 +14,17 @@ describe('packet-reader', function() { }) it('reads perfect longer buffer', function() { - this.reader.addChunk(new Buffer([0, 0, 0, 0, 4, 1, 2, 3, 4])) + this.reader.addChunk(Buffer.from([0, 0, 0, 0, 4, 1, 2, 3, 4])) var result = this.reader.read() assert.equal(result.length, 4) assert.strictEqual(false, this.reader.read()) }) it('reads two parts', function() { - this.reader.addChunk(new Buffer([0, 0, 0, 0, 1])) + this.reader.addChunk(Buffer.from([0, 0, 0, 0, 1])) var result = this.reader.read() assert.strictEqual(false, result) - this.reader.addChunk(new Buffer([2])) + this.reader.addChunk(Buffer.from([2])) var result = this.reader.read() assert.equal(result.length, 1, 'should return 1 length buffer') assert.equal(result[0], 2) @@ -32,30 +32,30 @@ describe('packet-reader', function() { }) it('reads multi-part', function() { - this.reader.addChunk(new Buffer([0, 0, 0, 0, 16])) + this.reader.addChunk(Buffer.from([0, 0, 0, 0, 16])) assert.equal(false, this.reader.read()) - this.reader.addChunk(new Buffer([1, 2, 3, 4, 5, 6, 7, 8])) + this.reader.addChunk(Buffer.from([1, 2, 3, 4, 5, 6, 7, 8])) assert.equal(false, this.reader.read()) - this.reader.addChunk(new Buffer([9, 10, 11, 12, 13, 14, 15, 16])) + this.reader.addChunk(Buffer.from([9, 10, 11, 12, 13, 14, 15, 16])) var result = this.reader.read() assert.equal(result.length, 16) }) it('resets internal buffer at end of packet', function() { - this.reader.addChunk(new Buffer([0, 0, 0, 0, 16])) - this.reader.addChunk(new Buffer([1, 2, 3, 4, 5, 6, 7, 8])) - this.reader.addChunk(new Buffer([9, 10, 11, 12, 13, 14, 15, 16])) + this.reader.addChunk(Buffer.from([0, 0, 0, 0, 16])) + this.reader.addChunk(Buffer.from([1, 2, 3, 4, 5, 6, 7, 8])) + this.reader.addChunk(Buffer.from([9, 10, 11, 12, 13, 14, 15, 16])) var result = this.reader.read() assert.equal(result.length, 16) - var newChunk = new Buffer([0, 0, 0, 0, 16]) + var newChunk = Buffer.from([0, 0, 0, 0, 16]) this.reader.addChunk(newChunk) assert.equal(this.reader.offset, 0, 'should have been reset to 0.') assert.strictEqual(this.reader.chunk, newChunk) }) it('reads multiple messages from single chunk', function() { - this.reader.addChunk(new Buffer([0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 2, 1, 2])) + this.reader.addChunk(Buffer.from([0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 2, 1, 2])) var result = this.reader.read() assert.equal(result.length, 1, 'should have 1 length buffer') assert.equal(result[0], 1) @@ -67,14 +67,14 @@ describe('packet-reader', function() { }) it('reads 1 and a split', function() { - this.reader.addChunk(new Buffer([0, 0, 0, 0, 1, 1, 0, 0]))//, 0, 0, 2, 1, 2])) + this.reader.addChunk(Buffer.from([0, 0, 0, 0, 1, 1, 0, 0]))//, 0, 0, 2, 1, 2])) var result = this.reader.read() assert.equal(result.length, 1, 'should have 1 length buffer') assert.equal(result[0], 1) var result = this.reader.read() assert.strictEqual(result, false) - this.reader.addChunk(new Buffer([0, 0, 2, 1, 2])) + this.reader.addChunk(Buffer.from([0, 0, 2, 1, 2])) var result = this.reader.read() assert.equal(result.length, 2, 'should have 2 length buffer but was ' + result.length) assert.equal(result[0], 1) @@ -89,7 +89,7 @@ describe('variable length header', function() { }) it('reads double message buffers', function() { - this.reader.addChunk(new Buffer([ + this.reader.addChunk(Buffer.from([ 0, 0, 0, 1, 1, 0, 0, 0, 2, 1, 2])) var result = this.reader.read() @@ -111,7 +111,7 @@ describe('1 length code', function() { }) it('reads code', function() { - this.reader.addChunk(new Buffer([9, 0, 0, 0, 1, 1])) + this.reader.addChunk(Buffer.from([9, 0, 0, 0, 1, 1])) var result = this.reader.read() assert(result) assert.equal(this.reader.header, 9) @@ -121,7 +121,7 @@ describe('1 length code', function() { it('is set on uncompleted read', function() { assert.equal(this.reader.header, null) - this.reader.addChunk(new Buffer([2, 0, 0, 0, 1])) + this.reader.addChunk(Buffer.from([2, 0, 0, 0, 1])) assert.strictEqual(this.reader.read(), false) assert.equal(this.reader.header, 2) }) @@ -136,7 +136,7 @@ describe('postgres style packet', function() { }) it('reads with padded length', function() { - this.reader.addChunk(new Buffer([1, 0, 0, 0, 8, 0, 0, 2, 0])) + this.reader.addChunk(Buffer.from([1, 0, 0, 0, 8, 0, 0, 2, 0])) var result = this.reader.read() assert(result) assert.equal(result.length, 4) @@ -158,7 +158,7 @@ describe('little-endian style packet', function() { }) it('reads 4-byte LE size with a 4 byte LE header and 8 byte padding', function() { - var buf = new Buffer([0x7A, 0xB1, 0xEA, 0x06, 4, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0x00, 0xA4, 0xD3, 0xF1]); + var buf = Buffer.from([0x7A, 0xB1, 0xEA, 0x06, 4, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0x00, 0xA4, 0xD3, 0xF1]); this.reader.addChunk( buf ) var result = this.reader.read() assert(result)