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