diff --git a/src/responses/parser.js b/src/responses/parser.js index 6d5b1a9a..bdfaf3dc 100644 --- a/src/responses/parser.js +++ b/src/responses/parser.js @@ -23,45 +23,65 @@ class Parser extends EventEmitter { super(); this.buffer = null; } - + + parseLoop(buffer) { + while(true) { + const ber = new BerReader(buffer); + + try { + ber.readSequence(); + } catch (e) { + this.emit('error', e); + return buffer; + } + + if (ber.remain < ber.length || ber.length === 0) { + return buffer; + } + + let nextMessages = null; + if (ber.remain > ber.length) { + nextMessages = buffer.slice(ber.offset + ber.length); + ber._size = ber.offset + ber.length; + assert.equal(ber.remain, ber.length); + } + + try { + const message = getMessage(ber); + message.parse(ber); + this.emit('message', message); + } catch (e) { + this.emit('error', e); + } + + if (nextMessages === null) { + return null; + } else { + buffer = nextMessages; + } + } + } + parse(data) { assert.buffer(data, 'data'); - + this.buffer = this.buffer ? Buffer.concat([this.buffer, data]) : data; - + const ber = new BerReader(this.buffer); - + try { ber.readSequence(); } catch (e) { this.emit('error', e); return; } - - if (ber.remain < ber.length) { + + // If the chunk is not full, we continue accumulating the buffer. + if (ber.remain < ber.length || ber.length === 0) { return; } - - let nextMessage = null; - if (ber.remain > ber.length) { - nextMessage = this.buffer.slice(ber.offset + ber.length); - ber._size = ber.offset + ber.length; - assert.equal(ber.remain, ber.length); - } - - this.buffer = null; - - try { - const message = getMessage(ber); - message.parse(ber); - this.emit('message', message); - } catch (e) { - this.emit('error', e); - } - - if (nextMessage) { - this.parse(nextMessage); - } + + this.buffer = this.parseLoop(this.buffer); } }