all files / lib/spdy-transport/protocol/base/ parser.js

100% Statements 59/59
100% Branches 18/18
100% Functions 8/8
100% Lines 58/58
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107        642×       642× 642× 642×   642×   642× 642× 642×       32×     6361×   6361×     17289×   10956× 28×     10928× 33× 66×   10895× 5291×       10928× 470×     10458× 10458×       17289× 31×     17258×   6306× 5999×       307×         303×     10952×   10952× 10952×   10952× 10925×     728× 728×     642×    
'use strict'
 
var transport = require('../../../spdy-transport')
 
var util = require('util')
var utils = require('./').utils
var OffsetBuffer = require('obuf')
var Transform = require('readable-stream').Transform
 
function Parser (options) {
  Transform.call(this, {
    readableObjectMode: true
  })
 
  this.buffer = new OffsetBuffer()
  this.partial = false
  this.waiting = 0
 
  this.window = options.window
 
  this.version = null
  this.decompress = null
  this.dead = false
}
module.exports = Parser
util.inherits(Parser, Transform)
 
Parser.prototype.error = utils.error
 
Parser.prototype.kill = function kill () {
  this.dead = true
}
 
Parser.prototype._transform = function transform (data, encoding, cb) {
  if (!this.dead) { this.buffer.push(data) }
 
  this._consume(cb)
}
 
Parser.prototype._consume = function _consume (cb) {
  var self = this
 
  function next (err, frame) {
    if (err) {
      return cb(err)
    }
 
    if (Array.isArray(frame)) {
      for (var i = 0; i < frame.length; i++) {
        self.push(frame[i])
      }
    } else if (frame) {
      self.push(frame)
    }
 
    // Consume more packets
    if (!sync) {
      return self._consume(cb)
    }
 
    process.nextTick(function () {
      self._consume(cb)
    })
  }
 
  if (this.dead) {
    return cb()
  }
 
  if (this.buffer.size < this.waiting) {
    // No data at all
    if (this.buffer.size === 0) {
      return cb()
    }
 
    // Partial DATA frame or something that we can process partially
    if (this.partial) {
      var partial = this.buffer.clone(this.buffer.size)
      this.buffer.skip(partial.size)
      this.waiting -= partial.size
 
      this.executePartial(partial, next)
      return
    }
 
    // We shall not do anything until we get all expected data
    return cb()
  }
 
  var sync = true
 
  var content = this.buffer.clone(this.waiting)
  this.buffer.skip(this.waiting)
 
  this.execute(content, next)
  sync = false
}
 
Parser.prototype.setVersion = function setVersion (version) {
  this.version = version
  this.emit('version', version)
}
 
Parser.prototype.setCompression = function setCompresion (pair) {
  this.decompress = new transport.utils.LockStream(pair.decompress)
}