@@ -61,6 +61,8 @@ static void transit(h2_session *session, const char *action,
6161static void on_stream_state_enter (void * ctx , h2_stream * stream );
6262static void on_stream_state_event (void * ctx , h2_stream * stream , h2_stream_event_t ev );
6363static void on_stream_event (void * ctx , h2_stream * stream , h2_stream_event_t ev );
64+ static apr_status_t h2_session_shutdown (h2_session * session , int error ,
65+ const char * msg , int force_close );
6466
6567static int h2_session_status_from_apr_status (apr_status_t rv )
6668{
@@ -290,6 +292,7 @@ static int on_stream_close_cb(nghttp2_session *ngh2, int32_t stream_id,
290292 "closing with err=%d %s" ),
291293 (int )error_code , h2_protocol_err_description (error_code ));
292294 h2_stream_rst (stream , error_code );
295+ h2_mplx_c1_client_rst (session -> mplx , stream_id , stream );
293296 }
294297 }
295298 return 0 ;
@@ -608,7 +611,11 @@ static int on_frame_send_cb(nghttp2_session *ngh2,
608611 /* PUSH_PROMISE we report on the promised stream */
609612 stream_id = frame -> push_promise .promised_stream_id ;
610613 break ;
611- default :
614+ case NGHTTP2_RST_STREAM :
615+ if (frame -> rst_stream .error_code == NGHTTP2_FLOW_CONTROL_ERROR )
616+ ++ session -> stream_errors ;
617+ break ;
618+ default :
612619 break ;
613620 }
614621
@@ -652,10 +659,11 @@ static int on_frame_not_send_cb(nghttp2_session *ngh2,
652659
653660 stream = get_stream (session , stream_id );
654661 h2_util_frame_print (frame , buffer , sizeof (buffer )/sizeof (buffer [0 ]));
655- ap_log_cerror (APLOG_MARK , APLOG_ERR , 0 , session -> c1 ,
656- H2_SSSN_LOG (APLOGNO (10509 ), session ,
657- "not sent FRAME[%s], error %d: %s" ),
658- buffer , ngh2_err , nghttp2_strerror (ngh2_err ));
662+ if (!stream || !stream -> rst_error )
663+ ap_log_cerror (APLOG_MARK , APLOG_DEBUG , 0 , session -> c1 ,
664+ H2_SSSN_LOG (APLOGNO (10509 ), session ,
665+ "not sent FRAME[%s], error %d: %s" ),
666+ buffer , ngh2_err , nghttp2_strerror (ngh2_err ));
659667 if (stream ) {
660668 h2_stream_rst (stream , NGHTTP2_PROTOCOL_ERROR );
661669 return 0 ;
@@ -968,6 +976,7 @@ apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec *
968976 session -> max_stream_count = h2_config_sgeti (s , H2_CONF_MAX_STREAMS );
969977 session -> max_stream_mem = h2_config_sgeti (s , H2_CONF_STREAM_MAX_MEM );
970978 session -> max_data_frame_len = h2_config_sgeti (s , H2_CONF_MAX_DATA_FRAME_LEN );
979+ session -> max_stream_errors = h2_config_sgeti (s , H2_CONF_MAX_STREAM_ERRORS );
971980
972981 session -> out_c1_blocked = h2_iq_create (session -> pool , (int )session -> max_stream_count );
973982 session -> ready_to_process = h2_iq_create (session -> pool , (int )session -> max_stream_count );
@@ -1063,14 +1072,16 @@ apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec *
10631072 "created, max_streams=%d, stream_mem=%d, "
10641073 "workers_limit=%d, workers_max=%d, "
10651074 "push_diary(type=%d,N=%d), "
1066- "max_data_frame_len=%d" ),
1075+ "max_data_frame_len=%d, "
1076+ "max_stream_errors=%d" ),
10671077 (int )session -> max_stream_count ,
10681078 (int )session -> max_stream_mem ,
10691079 session -> mplx -> processing_limit ,
10701080 session -> mplx -> processing_max ,
10711081 session -> push_diary -> dtype ,
10721082 (int )session -> push_diary -> N ,
1073- (int )session -> max_data_frame_len );
1083+ (int )session -> max_data_frame_len ,
1084+ session -> max_stream_errors );
10741085 }
10751086
10761087 apr_pool_pre_cleanup_register (pool , c , session_pool_cleanup );
@@ -1609,6 +1620,14 @@ static void h2_session_ev_mpm_stopping(h2_session *session, int arg, const char
16091620 }
16101621}
16111622
1623+ static void h2_session_ev_bad_client (h2_session * session , int arg , const char * msg )
1624+ {
1625+ transit (session , msg , H2_SESSION_ST_DONE );
1626+ if (!session -> local .shutdown ) {
1627+ h2_session_shutdown (session , arg , msg , 1 );
1628+ }
1629+ }
1630+
16121631static void h2_session_ev_pre_close (h2_session * session , int arg , const char * msg )
16131632{
16141633 h2_session_shutdown (session , arg , msg , 1 );
@@ -1806,6 +1825,9 @@ void h2_session_dispatch_event(h2_session *session, h2_session_event_t ev,
18061825 case H2_SESSION_EV_NO_MORE_STREAMS :
18071826 h2_session_ev_no_more_streams (session );
18081827 break ;
1828+ case H2_SESSION_EV_BAD_CLIENT :
1829+ h2_session_ev_bad_client (session , arg , msg );
1830+ break ;
18091831 default :
18101832 ap_log_cerror (APLOG_MARK , APLOG_TRACE1 , 0 , session -> c1 ,
18111833 H2_SSSN_MSG (session , "unknown event %d" ), ev );
@@ -1884,6 +1906,12 @@ apr_status_t h2_session_process(h2_session *session, int async,
18841906 }
18851907 }
18861908
1909+ if (session -> max_stream_errors &&
1910+ session -> stream_errors > session -> max_stream_errors ) {
1911+ h2_session_dispatch_event (session , H2_SESSION_EV_BAD_CLIENT ,
1912+ NGHTTP2_PROTOCOL_ERROR , NULL );
1913+ }
1914+
18871915 session -> status [0 ] = '\0' ;
18881916
18891917 if (h2_session_want_send (session )) {
0 commit comments