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