@@ -25,6 +25,7 @@ const {
2525 ERR_HTTP2_INVALID_CONNECTION_HEADERS ,
2626 ERR_HTTP2_INVALID_PSEUDOHEADER ,
2727 ERR_HTTP2_INVALID_SETTING_VALUE ,
28+ ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS ,
2829 ERR_INVALID_ARG_TYPE ,
2930 ERR_INVALID_HTTP_TOKEN ,
3031 } ,
@@ -192,6 +193,9 @@ const IDX_SETTINGS_MAX_HEADER_LIST_SIZE = 5;
192193const IDX_SETTINGS_ENABLE_CONNECT_PROTOCOL = 6 ;
193194const IDX_SETTINGS_FLAGS = 7 ;
194195
196+ // Maximum number of allowed additional settings
197+ const MAX_ADDITIONAL_SETTINGS = 10 ;
198+
195199const IDX_SESSION_STATE_EFFECTIVE_LOCAL_WINDOW_SIZE = 0 ;
196200const IDX_SESSION_STATE_EFFECTIVE_RECV_DATA_LENGTH = 1 ;
197201const IDX_SESSION_STATE_NEXT_STREAM_ID = 2 ;
@@ -350,6 +354,80 @@ function getSettings(session, remote) {
350354
351355function updateSettingsBuffer ( settings ) {
352356 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+
353431 if ( typeof settings . headerTableSize === 'number' ) {
354432 flags |= ( 1 << IDX_SETTINGS_HEADER_TABLE_SIZE ) ;
355433 settingsBuffer [ IDX_SETTINGS_HEADER_TABLE_SIZE ] =
0 commit comments