@@ -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_CUSTOMSETTINGS ,
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,67 @@ 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 ( nsetting < IDX_SETTINGS_FLAGS ) {
367+ set = true ;
368+ switch ( nsetting ) {
369+ case IDX_SETTINGS_HEADER_TABLE_SIZE :
370+ flags |= ( 1 << IDX_SETTINGS_HEADER_TABLE_SIZE ) ;
371+ settingsBuffer [ IDX_SETTINGS_HEADER_TABLE_SIZE ] =
372+ val ;
373+ break ;
374+ case IDX_SETTINGS_ENABLE_PUSH :
375+ flags |= ( 1 << IDX_SETTINGS_ENABLE_PUSH ) ;
376+ settingsBuffer [ IDX_SETTINGS_ENABLE_PUSH ] = val ;
377+ break ;
378+ case IDX_SETTINGS_INITIAL_WINDOW_SIZE :
379+ flags |= ( 1 << IDX_SETTINGS_INITIAL_WINDOW_SIZE ) ;
380+ settingsBuffer [ IDX_SETTINGS_INITIAL_WINDOW_SIZE ] =
381+ val ;
382+ break ;
383+ case IDX_SETTINGS_MAX_FRAME_SIZE :
384+ flags |= ( 1 << IDX_SETTINGS_MAX_FRAME_SIZE ) ;
385+ settingsBuffer [ IDX_SETTINGS_MAX_FRAME_SIZE ] =
386+ val ;
387+ break ;
388+ case IDX_SETTINGS_MAX_CONCURRENT_STREAMS :
389+ flags |= ( 1 << IDX_SETTINGS_MAX_CONCURRENT_STREAMS ) ;
390+ settingsBuffer [ IDX_SETTINGS_MAX_CONCURRENT_STREAMS ] = val ;
391+ break ;
392+ case IDX_SETTINGS_MAX_HEADER_LIST_SIZE :
393+ flags |= ( 1 << IDX_SETTINGS_MAX_HEADER_LIST_SIZE ) ;
394+ settingsBuffer [ IDX_SETTINGS_MAX_HEADER_LIST_SIZE ] =
395+ val ;
396+ break ;
397+ case IDX_SETTINGS_ENABLE_CONNECT_PROTOCOL :
398+ flags |= ( 1 << IDX_SETTINGS_ENABLE_CONNECT_PROTOCOL ) ;
399+ settingsBuffer [ IDX_SETTINGS_ENABLE_CONNECT_PROTOCOL ] = val ;
400+ break ;
401+ default :
402+ set = false ;
403+ break ;
404+ }
405+ }
406+ if ( ! set ) { // not supported
407+ if ( numCustomSettings === MAX_ADDITIONAL_SETTINGS )
408+ throw new ERR_HTTP2_TOO_MANY_CUSTOMSETTINGS ( ) ;
409+ settingsBuffer [ IDX_SETTINGS_FLAGS + 1 + 2 * numCustomSettings + 1 ] = nsetting ;
410+ settingsBuffer [ IDX_SETTINGS_FLAGS + 1 + 2 * numCustomSettings + 2 ] = val ;
411+ numCustomSettings ++ ;
412+ }
413+ }
414+ }
415+ }
416+ settingsBuffer [ IDX_SETTINGS_FLAGS + 1 ] = numCustomSettings ;
417+
353418 if ( typeof settings . headerTableSize === 'number' ) {
354419 flags |= ( 1 << IDX_SETTINGS_HEADER_TABLE_SIZE ) ;
355420 settingsBuffer [ IDX_SETTINGS_HEADER_TABLE_SIZE ] =
0 commit comments