blob: 3f0de8ca7e223a39a27c2622a6a8c27a7a49c95b [file] [log] [blame]
function FrameParser() {
this.readFrameBytes = 0
this.frameBodyLength = 0
this.frameBody = null
this.cursor = 0
this.chunk = null
}
FrameParser.prototype.push = function(chunk) {
if (this.chunk) {
throw new Error('Must consume pending frames before pushing more chunks')
}
this.chunk = chunk
}
FrameParser.prototype.nextFrame = function() {
if (!this.chunk) {
return null
}
for (var len = this.chunk.length; this.cursor < len;) {
if (this.readFrameBytes < 4) {
this.frameBodyLength +=
(this.chunk[this.cursor] << (this.readFrameBytes * 8)) >>> 0
this.cursor += 1
this.readFrameBytes += 1
}
else {
var bytesLeft = len - this.cursor
if (bytesLeft >= this.frameBodyLength) {
var completeBody
if (this.frameBody) {
completeBody = Buffer.concat([
this.frameBody
, this.chunk.slice(this.cursor, this.cursor + this.frameBodyLength)
])
}
else {
completeBody = this.chunk.slice(this.cursor,
this.cursor + this.frameBodyLength)
}
this.cursor += this.frameBodyLength
this.frameBodyLength = this.readFrameBytes = 0
this.frameBody = null
return completeBody
}
else {
// @todo Consider/benchmark continuation frames to prevent
// potential Buffer thrashing.
if (this.frameBody) {
this.frameBody =
Buffer.concat([this.frameBody, this.chunk.slice(this.cursor, len)])
}
else {
this.frameBody = this.chunk.slice(this.cursor, len)
}
this.frameBodyLength -= bytesLeft
this.readFrameBytes += bytesLeft
this.cursor = len
}
}
}
this.cursor = 0
this.chunk = null
return null
}
module.exports = FrameParser