@@ -25,6 +25,7 @@ const {
25
25
ERR_HTTP2_INVALID_CONNECTION_HEADERS ,
26
26
ERR_HTTP2_INVALID_PSEUDOHEADER ,
27
27
ERR_HTTP2_INVALID_SETTING_VALUE ,
28
+ ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS ,
28
29
ERR_INVALID_ARG_TYPE ,
29
30
ERR_INVALID_HTTP_TOKEN ,
30
31
} ,
@@ -192,6 +193,9 @@ const IDX_SETTINGS_MAX_HEADER_LIST_SIZE = 5;
192
193
const IDX_SETTINGS_ENABLE_CONNECT_PROTOCOL = 6 ;
193
194
const IDX_SETTINGS_FLAGS = 7 ;
194
195
196
+ // Maximum number of allowed additional settings
197
+ const MAX_ADDITIONAL_SETTINGS = 10 ;
198
+
195
199
const IDX_SESSION_STATE_EFFECTIVE_LOCAL_WINDOW_SIZE = 0 ;
196
200
const IDX_SESSION_STATE_EFFECTIVE_RECV_DATA_LENGTH = 1 ;
197
201
const IDX_SESSION_STATE_NEXT_STREAM_ID = 2 ;
@@ -350,6 +354,80 @@ function getSettings(session, remote) {
350
354
351
355
function updateSettingsBuffer ( settings ) {
352
356
let flags = 0 ;
357
+ let numCustomSettings = 0 ;
358
+
359
+ if ( typeof settings . customSettings === 'object' ) {
360
+ const customSettings = settings . customSettings ;
361
+ for ( const setting in customSettings ) {
362
+ const val = customSettings [ setting ] ;
363
+ if ( typeof val === 'number' ) {
364
+ let set = false ;
365
+ const nsetting = Number ( setting ) ;
366
+ if ( Number . isNaN ( nsetting ) ||
367
+ typeof nsetting !== 'number' ||
368
+ 0 >= nsetting ||
369
+ nsetting > 0xffff )
370
+ throw new ERR_HTTP2_INVALID_SETTING_VALUE . RangeError (
371
+ 'Range Error' , nsetting , 0 , 0xffff ) ;
372
+ if ( Number . isNaN ( val ) ||
373
+ typeof val !== 'number' ||
374
+ 0 >= val ||
375
+ val > 0xffffffff )
376
+ throw new ERR_HTTP2_INVALID_SETTING_VALUE . RangeError (
377
+ 'Range Error' , val , 0 , 0xffffffff ) ;
378
+ if ( nsetting < IDX_SETTINGS_FLAGS ) {
379
+ set = true ;
380
+ switch ( nsetting ) {
381
+ case IDX_SETTINGS_HEADER_TABLE_SIZE :
382
+ flags |= ( 1 << IDX_SETTINGS_HEADER_TABLE_SIZE ) ;
383
+ settingsBuffer [ IDX_SETTINGS_HEADER_TABLE_SIZE ] =
384
+ val ;
385
+ break ;
386
+ case IDX_SETTINGS_ENABLE_PUSH :
387
+ flags |= ( 1 << IDX_SETTINGS_ENABLE_PUSH ) ;
388
+ settingsBuffer [ IDX_SETTINGS_ENABLE_PUSH ] = val ;
389
+ break ;
390
+ case IDX_SETTINGS_INITIAL_WINDOW_SIZE :
391
+ flags |= ( 1 << IDX_SETTINGS_INITIAL_WINDOW_SIZE ) ;
392
+ settingsBuffer [ IDX_SETTINGS_INITIAL_WINDOW_SIZE ] =
393
+ val ;
394
+ break ;
395
+ case IDX_SETTINGS_MAX_FRAME_SIZE :
396
+ flags |= ( 1 << IDX_SETTINGS_MAX_FRAME_SIZE ) ;
397
+ settingsBuffer [ IDX_SETTINGS_MAX_FRAME_SIZE ] =
398
+ val ;
399
+ break ;
400
+ case IDX_SETTINGS_MAX_CONCURRENT_STREAMS :
401
+ flags |= ( 1 << IDX_SETTINGS_MAX_CONCURRENT_STREAMS ) ;
402
+ settingsBuffer [ IDX_SETTINGS_MAX_CONCURRENT_STREAMS ] = val ;
403
+ break ;
404
+ case IDX_SETTINGS_MAX_HEADER_LIST_SIZE :
405
+ flags |= ( 1 << IDX_SETTINGS_MAX_HEADER_LIST_SIZE ) ;
406
+ settingsBuffer [ IDX_SETTINGS_MAX_HEADER_LIST_SIZE ] =
407
+ val ;
408
+ break ;
409
+ case IDX_SETTINGS_ENABLE_CONNECT_PROTOCOL :
410
+ flags |= ( 1 << IDX_SETTINGS_ENABLE_CONNECT_PROTOCOL ) ;
411
+ settingsBuffer [ IDX_SETTINGS_ENABLE_CONNECT_PROTOCOL ] = val ;
412
+ break ;
413
+ default :
414
+ set = false ;
415
+ break ;
416
+ }
417
+ }
418
+ if ( ! set ) { // not supported
419
+ if ( numCustomSettings === MAX_ADDITIONAL_SETTINGS )
420
+ throw new ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS ( ) ;
421
+
422
+ settingsBuffer [ IDX_SETTINGS_FLAGS + 1 + 2 * numCustomSettings + 1 ] = nsetting ;
423
+ settingsBuffer [ IDX_SETTINGS_FLAGS + 1 + 2 * numCustomSettings + 2 ] = val ;
424
+ numCustomSettings ++ ;
425
+ }
426
+ }
427
+ }
428
+ }
429
+ settingsBuffer [ IDX_SETTINGS_FLAGS + 1 ] = numCustomSettings ;
430
+
353
431
if ( typeof settings . headerTableSize === 'number' ) {
354
432
flags |= ( 1 << IDX_SETTINGS_HEADER_TABLE_SIZE ) ;
355
433
settingsBuffer [ IDX_SETTINGS_HEADER_TABLE_SIZE ] =
0 commit comments