1'use strict';
2
3const common = require('../common');
4if (!common.hasCrypto)
5  common.skip('missing crypto');
6const assert = require('assert');
7const http2 = require('http2');
8
9const check = Buffer.from([0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
10                           0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
11                           0x00, 0x03, 0xff, 0xff, 0xff, 0xff,
12                           0x00, 0x04, 0x00, 0x00, 0xff, 0xff,
13                           0x00, 0x05, 0x00, 0x00, 0x40, 0x00,
14                           0x00, 0x06, 0x00, 0x00, 0xff, 0xff,
15                           0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
16const val = http2.getPackedSettings(http2.getDefaultSettings());
17assert.deepStrictEqual(val, check);
18
19[
20  ['headerTableSize', 0],
21  ['headerTableSize', 2 ** 32 - 1],
22  ['initialWindowSize', 0],
23  ['initialWindowSize', 2 ** 32 - 1],
24  ['maxFrameSize', 16384],
25  ['maxFrameSize', 2 ** 24 - 1],
26  ['maxConcurrentStreams', 0],
27  ['maxConcurrentStreams', 2 ** 31 - 1],
28  ['maxHeaderListSize', 0],
29  ['maxHeaderListSize', 2 ** 32 - 1],
30  ['maxHeaderSize', 0],
31  ['maxHeaderSize', 2 ** 32 - 1],
32].forEach((i) => {
33  // Valid options should not throw.
34  http2.getPackedSettings({ [i[0]]: i[1] });
35});
36
37http2.getPackedSettings({ enablePush: true });
38http2.getPackedSettings({ enablePush: false });
39
40[
41  ['headerTableSize', -1],
42  ['headerTableSize', 2 ** 32],
43  ['initialWindowSize', -1],
44  ['initialWindowSize', 2 ** 32],
45  ['maxFrameSize', 16383],
46  ['maxFrameSize', 2 ** 24],
47  ['maxConcurrentStreams', -1],
48  ['maxConcurrentStreams', 2 ** 32],
49  ['maxHeaderListSize', -1],
50  ['maxHeaderListSize', 2 ** 32],
51  ['maxHeaderSize', -1],
52  ['maxHeaderSize', 2 ** 32],
53].forEach((i) => {
54  assert.throws(() => {
55    http2.getPackedSettings({ [i[0]]: i[1] });
56  }, {
57    code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
58    name: 'RangeError',
59    message: `Invalid value for setting "${i[0]}": ${i[1]}`
60  });
61});
62
63[
64  1, null, '', Infinity, new Date(), {}, NaN, [false],
65].forEach((i) => {
66  assert.throws(() => {
67    http2.getPackedSettings({ enablePush: i });
68  }, {
69    code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
70    name: 'TypeError',
71    message: `Invalid value for setting "enablePush": ${i}`
72  });
73});
74
75[
76  1, null, '', Infinity, new Date(), {}, NaN, [false],
77].forEach((i) => {
78  assert.throws(() => {
79    http2.getPackedSettings({ enableConnectProtocol: i });
80  }, {
81    code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
82    name: 'TypeError',
83    message: `Invalid value for setting "enableConnectProtocol": ${i}`
84  });
85});
86
87{
88  const check = Buffer.from([
89    0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
90    0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
91    0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
92    0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
93    0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
94    0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
95    0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
96  ]);
97
98  const packed = http2.getPackedSettings({
99    headerTableSize: 100,
100    initialWindowSize: 100,
101    maxFrameSize: 20000,
102    maxConcurrentStreams: 200,
103    maxHeaderListSize: 100,
104    maxHeaderSize: 100,
105    enablePush: true,
106    enableConnectProtocol: false,
107    foo: 'ignored'
108  });
109  assert.strictEqual(packed.length, 42);
110  assert.deepStrictEqual(packed, check);
111}
112
113// Check for not passing settings.
114{
115  const packed = http2.getPackedSettings();
116  assert.strictEqual(packed.length, 0);
117}
118
119{
120  const packed = Buffer.from([
121    0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
122    0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
123    0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
124    0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
125    0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
126    0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
127    0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
128
129  [1, true, '', [], {}, NaN].forEach((input) => {
130    assert.throws(() => {
131      http2.getUnpackedSettings(input);
132    }, {
133      code: 'ERR_INVALID_ARG_TYPE',
134      name: 'TypeError',
135      message:
136        'The "buf" argument must be an instance of Buffer or TypedArray.' +
137        common.invalidArgTypeHelper(input)
138    });
139  });
140
141  assert.throws(() => {
142    http2.getUnpackedSettings(packed.slice(5));
143  }, {
144    code: 'ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH',
145    name: 'RangeError',
146    message: 'Packed settings length must be a multiple of six'
147  });
148
149  const settings = http2.getUnpackedSettings(packed);
150
151  assert(settings);
152  assert.strictEqual(settings.headerTableSize, 100);
153  assert.strictEqual(settings.initialWindowSize, 100);
154  assert.strictEqual(settings.maxFrameSize, 20000);
155  assert.strictEqual(settings.maxConcurrentStreams, 200);
156  assert.strictEqual(settings.maxHeaderListSize, 100);
157  assert.strictEqual(settings.maxHeaderSize, 100);
158  assert.strictEqual(settings.enablePush, true);
159  assert.strictEqual(settings.enableConnectProtocol, false);
160}
161
162{
163  const packed = new Uint16Array([
164    0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
165    0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
166    0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
167    0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
168    0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
169    0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
170    0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
171
172  assert.throws(() => {
173    http2.getUnpackedSettings(packed.slice(5));
174  }, {
175    code: 'ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH',
176    name: 'RangeError',
177    message: 'Packed settings length must be a multiple of six'
178  });
179
180  const settings = http2.getUnpackedSettings(packed);
181
182  assert(settings);
183  assert.strictEqual(settings.headerTableSize, 100);
184  assert.strictEqual(settings.initialWindowSize, 100);
185  assert.strictEqual(settings.maxFrameSize, 20000);
186  assert.strictEqual(settings.maxConcurrentStreams, 200);
187  assert.strictEqual(settings.maxHeaderListSize, 100);
188  assert.strictEqual(settings.maxHeaderSize, 100);
189  assert.strictEqual(settings.enablePush, true);
190  assert.strictEqual(settings.enableConnectProtocol, false);
191}
192
193{
194  const packed = new DataView(Buffer.from([
195    0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
196    0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
197    0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
198    0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
199    0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
200    0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
201    0x00, 0x08, 0x00, 0x00, 0x00, 0x00]).buffer);
202
203  assert.throws(() => {
204    http2.getUnpackedSettings(packed);
205  }, {
206    code: 'ERR_INVALID_ARG_TYPE',
207    name: 'TypeError',
208    message:
209        'The "buf" argument must be an instance of Buffer or TypedArray.' +
210        common.invalidArgTypeHelper(packed)
211  });
212}
213
214{
215  const packed = Buffer.from([
216    0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
217    0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
218
219  const settings = http2.getUnpackedSettings(packed, { validate: true });
220  assert.strictEqual(settings.enablePush, false);
221  assert.strictEqual(settings.enableConnectProtocol, false);
222}
223{
224  const packed = Buffer.from([
225    0x00, 0x02, 0x00, 0x00, 0x00, 0x64,
226    0x00, 0x08, 0x00, 0x00, 0x00, 0x64]);
227
228  const settings = http2.getUnpackedSettings(packed, { validate: true });
229  assert.strictEqual(settings.enablePush, true);
230  assert.strictEqual(settings.enableConnectProtocol, true);
231}
232
233// Verify that passing {validate: true} does not throw.
234{
235  const packed = Buffer.from([
236    0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
237    0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
238    0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
239    0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
240    0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
241    0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
242    0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
243
244  http2.getUnpackedSettings(packed, { validate: true });
245}
246
247// Check for maxFrameSize failing the max number.
248{
249  const packed = Buffer.from([0x00, 0x05, 0x01, 0x00, 0x00, 0x00]);
250
251  assert.throws(() => {
252    http2.getUnpackedSettings(packed, { validate: true });
253  }, {
254    code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
255    name: 'RangeError',
256    message: 'Invalid value for setting "maxFrameSize": 16777216'
257  });
258}
259