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 | };
|
---|