@@ -62,7 +62,16 @@ static 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 );
6464static apr_status_t h2_session_shutdown (h2_session * session , int error ,
65- const char * msg , int force_close );
65+ uint32_t h2_error , const char * msg ,
66+ int force_close );
67+
68+ /* The error code of a GOAWAY frame is one of RFC 9113, section 7. The
69+ * reasons for a shutdown are APR or nghttp2 status values that must not
70+ * end up on the wire. */
71+ static uint32_t h2_error_from_status (int status )
72+ {
73+ return status ? H2_ERR_INTERNAL_ERROR : H2_ERR_NO_ERROR ;
74+ }
6675
6776static int h2_session_status_from_apr_status (apr_status_t rv )
6877{
@@ -789,7 +798,8 @@ static apr_status_t h2_session_shutdown_notice(h2_session *session)
789798}
790799
791800static apr_status_t h2_session_shutdown (h2_session * session , int error ,
792- const char * msg , int force_close )
801+ uint32_t h2_error , const char * msg ,
802+ int force_close )
793803{
794804 apr_status_t status = APR_SUCCESS ;
795805
@@ -827,14 +837,15 @@ static apr_status_t h2_session_shutdown(h2_session *session, int error,
827837 if (!session -> c1 -> aborted ) {
828838 nghttp2_submit_goaway (session -> ngh2 , NGHTTP2_FLAG_NONE ,
829839 session -> local .accepted_max ,
830- error , (uint8_t * )msg , msg ? strlen (msg ):0 );
840+ h2_error , (uint8_t * )msg , msg ? strlen (msg ):0 );
831841 status = nghttp2_session_send (session -> ngh2 );
832842 if (status == APR_SUCCESS ) {
833843 status = h2_c1_io_assure_flushed (& session -> io );
834844 }
835845 ap_log_cerror (APLOG_MARK , APLOG_DEBUG , 0 , session -> c1 ,
836846 H2_SSSN_LOG (APLOGNO (03069 ), session ,
837- "sent GOAWAY, err=%d, msg=%s" ), error , msg ? msg : "" );
847+ "sent GOAWAY, err=%u, status=%d, msg=%s" ),
848+ (unsigned int )h2_error , error , msg ? msg : "" );
838849 }
839850 h2_session_dispatch_event (session , H2_SESSION_EV_LOCAL_GOAWAY , error , msg );
840851 return status ;
@@ -1592,7 +1603,7 @@ static void h2_session_ev_conn_error(h2_session *session, int arg, const char *m
15921603 H2_SSSN_LOG (APLOGNO (03401 ), session ,
15931604 "conn error -> shutdown, remote.emitted=%d" ),
15941605 (int )session -> remote .emitted_count );
1595- h2_session_shutdown (session , arg , msg , 0 );
1606+ h2_session_shutdown (session , arg , h2_error_from_status ( arg ), msg , 0 );
15961607 break ;
15971608 }
15981609}
@@ -1603,15 +1614,15 @@ static void h2_session_ev_proto_error(h2_session *session, int arg, const char *
16031614 ap_log_cerror (APLOG_MARK , APLOG_DEBUG , 0 , session -> c1 ,
16041615 H2_SSSN_LOG (APLOGNO (03402 ), session ,
16051616 "proto error -> shutdown" ));
1606- h2_session_shutdown (session , arg , msg , 0 );
1617+ h2_session_shutdown (session , arg , h2_error_from_status ( arg ), msg , 0 );
16071618 }
16081619}
16091620
16101621static void h2_session_ev_conn_timeout (h2_session * session , int arg , const char * msg )
16111622{
16121623 transit (session , msg , H2_SESSION_ST_DONE );
16131624 if (!session -> local .shutdown ) {
1614- h2_session_shutdown (session , arg , msg , 1 );
1625+ h2_session_shutdown (session , arg , H2_ERR_NO_ERROR , msg , 1 );
16151626 }
16161627}
16171628
@@ -1646,13 +1657,13 @@ static void h2_session_ev_bad_client(h2_session *session, int arg, const char *m
16461657{
16471658 transit (session , msg , H2_SESSION_ST_DONE );
16481659 if (!session -> local .shutdown ) {
1649- h2_session_shutdown (session , arg , msg , 1 );
1660+ h2_session_shutdown (session , arg , ( uint32_t ) arg , msg , 1 );
16501661 }
16511662}
16521663
16531664static void h2_session_ev_pre_close (h2_session * session , int arg , const char * msg )
16541665{
1655- h2_session_shutdown (session , arg , msg , 1 );
1666+ h2_session_shutdown (session , arg , H2_ERR_NO_ERROR , msg , 1 );
16561667}
16571668
16581669static void h2_session_ev_no_more_streams (h2_session * session )
@@ -1670,7 +1681,7 @@ static void h2_session_ev_no_more_streams(h2_session *session)
16701681 else {
16711682 /* We are no longer accepting new streams.
16721683 * Time to leave. */
1673- h2_session_shutdown (session , 0 , "done" , 0 );
1684+ h2_session_shutdown (session , 0 , H2_ERR_NO_ERROR , "done" , 0 );
16741685 transit (session , "c1 done after goaway" , H2_SESSION_ST_DONE );
16751686 }
16761687 }
@@ -1895,7 +1906,8 @@ apr_status_t h2_session_process(h2_session *session, int async,
18951906 if (!h2_protocol_is_acceptable_c1 (c , session -> r , 1 )) {
18961907 const char * msg = nghttp2_strerror (NGHTTP2_INADEQUATE_SECURITY );
18971908 update_child_status (session , SERVER_BUSY_READ , msg , NULL );
1898- h2_session_shutdown (session , APR_EINVAL , msg , 1 );
1909+ h2_session_shutdown (session , APR_EINVAL , H2_ERR_INADEQUATE_SECURITY ,
1910+ msg , 1 );
18991911 }
19001912 else {
19011913 update_child_status (session , SERVER_BUSY_READ , "init" , NULL );
@@ -1999,7 +2011,7 @@ apr_status_t h2_session_process(h2_session *session, int async,
19992011 * (Checked before the want_read assert below: after receiving a
20002012 * GOAWAY nghttp2 may no longer want to read.) */
20012013 if (!session -> local .shutdown ) {
2002- h2_session_shutdown (session , 0 , "done" , 0 );
2014+ h2_session_shutdown (session , 0 , H2_ERR_NO_ERROR , "done" , 0 );
20032015 }
20042016 transit (session , "remote goaway, streams drained" ,
20052017 H2_SESSION_ST_DONE );
0 commit comments