compressor.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. var hpack = require('../hpack');
  2. var utils = hpack.utils;
  3. var encoder = hpack.encoder;
  4. var table = hpack.table;
  5. var assert = utils.assert;
  6. var inherits = require('inherits');
  7. var Duplex = require('readable-stream').Duplex;
  8. function Compressor(options) {
  9. Duplex.call(this, {
  10. writableObjectMode: true
  11. });
  12. this._encoder = null;
  13. this._table = table.create(options.table);
  14. }
  15. inherits(Compressor, Duplex);
  16. module.exports = Compressor;
  17. Compressor.create = function create(options) {
  18. return new Compressor(options);
  19. };
  20. Compressor.prototype._read = function _read() {
  21. // We only push!
  22. };
  23. Compressor.prototype._write = function _write(data, enc, cb) {
  24. assert(Array.isArray(data), 'Compressor.write() expects list of headers');
  25. this._encoder = encoder.create();
  26. for (var i = 0; i < data.length; i++)
  27. this._encodeHeader(data[i]);
  28. var data = this._encoder.render();
  29. this._encoder = null;
  30. cb(null);
  31. for (var i = 0; i < data.length; i++)
  32. this.push(data[i]);
  33. };
  34. Compressor.prototype.updateTableSize = function updateTableSize(size) {
  35. if (size >= this._table.protocolMaxSize) {
  36. size = this._table.protocolMaxSize;
  37. var enc = encoder.create();
  38. // indexed = 0
  39. // incremental = 0
  40. // update = 1
  41. enc.encodeBits(1, 3);
  42. enc.encodeInt(size);
  43. var data = enc.render();
  44. for (var i = 0; i < data.length; i++)
  45. this.push(data[i]);
  46. }
  47. this._table.updateSize(size);
  48. };
  49. Compressor.prototype.reset = function reset() {
  50. var enc = encoder.create();
  51. var size = this._table.maxSize;
  52. // indexed = 0
  53. // incremental = 0
  54. // update = 1
  55. enc.encodeBits(1, 3);
  56. enc.encodeInt(0);
  57. // Evict everything
  58. this._table.updateSize(0);
  59. // indexed = 0
  60. // incremental = 0
  61. // update = 1
  62. enc.encodeBits(1, 3);
  63. enc.encodeInt(size);
  64. // Revert size
  65. this._table.updateSize(size);
  66. var data = enc.render();
  67. for (var i = 0; i < data.length; i++)
  68. this.push(data[i]);
  69. };
  70. Compressor.prototype._encodeHeader = function _encodeHeader(header) {
  71. if (header.neverIndex) {
  72. var index = 0;
  73. var neverIndex = 1;
  74. var isIndexed = 0;
  75. var isIncremental = 0;
  76. } else {
  77. var index = this._table.reverseLookup(header.name, header.value);
  78. var isIndexed = index > 0;
  79. var isIncremental = header.incremental !== false;
  80. var neverIndex = 0;
  81. }
  82. this._encoder.encodeBit(isIndexed);
  83. if (isIndexed) {
  84. this._encoder.encodeInt(index);
  85. return;
  86. }
  87. var name = utils.toArray(header.name);
  88. var value = utils.toArray(header.value);
  89. this._encoder.encodeBit(isIncremental);
  90. if (isIncremental) {
  91. this._table.add(header.name, header.value, name.length, value.length);
  92. } else {
  93. // Update = false
  94. this._encoder.encodeBit(0);
  95. this._encoder.encodeBit(neverIndex);
  96. }
  97. // index is negative for `name`-only headers
  98. this._encoder.encodeInt(-index);
  99. if (index === 0)
  100. this._encoder.encodeStr(name, header.huffman !== false);
  101. this._encoder.encodeStr(value, header.huffman !== false);
  102. };