diff options
author | Stefan Eissing <icing@apache.org> | 2022-09-26 14:29:47 +0200 |
---|---|---|
committer | Stefan Eissing <icing@apache.org> | 2022-09-26 14:29:47 +0200 |
commit | 8476af1eb6c7618e561fbb790dddde885ac56b5e (patch) | |
tree | a819c3431375c7666ac43da04adb3881ed5a42e3 /modules/http2/h2_session.c | |
parent | *) mod_http2: removing bucket splitting into an extra recv brigade. (diff) | |
download | apache2-8476af1eb6c7618e561fbb790dddde885ac56b5e.tar.xz apache2-8476af1eb6c7618e561fbb790dddde885ac56b5e.zip |
*) mod_http2: new directive "H2HeaderStrictness" to control the compliance
level of header checks as defined in the HTTP/2 RFCs. Default is 7540.
9113 activates the checks for forbidden leading/trailing whitespace in
field values (available from nghttp2 v1.50.0 on).
- source sync with github version
- fix for keepalive idle wait in mpm_worker setup
- ensuring EOS when secondary connection has been handled
- fixed race in late input EOS arrival when stream was
already scheduled for execution.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1904269 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/http2/h2_session.c')
-rw-r--r-- | modules/http2/h2_session.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c index 20c35beef1..1056d4b356 100644 --- a/modules/http2/h2_session.c +++ b/modules/http2/h2_session.c @@ -32,6 +32,10 @@ #include <mpm_common.h> +#if APR_HAVE_UNISTD_H +#include <unistd.h> /* for getpid() */ +#endif + #include "h2_private.h" #include "h2.h" #include "h2_bucket_beam.h" @@ -546,6 +550,9 @@ static int on_send_data_cb(nghttp2_session *ngh2, if (status == APR_SUCCESS) { stream->out_data_frames++; stream->out_data_octets += length; + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c1, + H2_STRM_MSG(stream, "sent data length=%ld, total=%ld"), + (long)length, (long)stream->out_data_octets); return 0; } else { @@ -875,7 +882,12 @@ apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec * * h2 streams can live through keepalive periods. While double id * will not lead to processing failures, it will confuse log analysis. */ +#if AP_MODULE_MAGIC_AT_LEAST(20211221, 8) ap_sb_get_child_thread(c->sbh, &session->child_num, &thread_num); +#else + (void)thread_num; + session->child_num = (int)getpid(); +#endif session->id = apr_atomic_inc32(&next_id); session->c1 = c; session->r = r; @@ -942,6 +954,15 @@ apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec * * setting in relation to older streams non-working. */ nghttp2_option_set_no_closed_streams(options, 1); #endif +#ifdef H2_NG2_RFC9113_STRICTNESS + /* nghttp2 v1.50.0 introduces the strictness checks on leading/trailing + * whitespace of RFC 9113. */ + ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, + "nghttp2_session_server_new: header strictness is %d", + h2_config_sgeti(s, H2_CONF_HEADER_STRICTNESS)); + nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(options, + h2_config_sgeti(s, H2_CONF_HEADER_STRICTNESS) < 9113); +#endif rv = nghttp2_session_server_new2(&session->ngh2, callbacks, session, options); nghttp2_session_callbacks_del(callbacks); @@ -1843,10 +1864,35 @@ apr_status_t h2_session_process(h2_session *session, int async) * connection handling when nothing really happened. */ h2_c1_read(session); if (H2_SESSION_ST_IDLE == session->state) { - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c, - H2_SSSN_LOG(APLOGNO(10306), session, - "returning to mpm c1 monitoring")); - goto leaving; + if (async) { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c, + H2_SSSN_LOG(APLOGNO(10306), session, + "returning to mpm c1 monitoring")); + goto leaving; + } + else { + /* Not an async mpm, we must continue waiting + * for client data to arrive until the configured + * server Timeout/KeepAliveTimeout happens */ + apr_time_t timeout = (session->open_streams == 0)? + session->s->keep_alive_timeout : + session->s->timeout; + status = h2_mplx_c1_poll(session->mplx, timeout, + on_stream_input, + on_stream_output, session); + if (APR_STATUS_IS_TIMEUP(status)) { + if (session->open_streams == 0) { + h2_session_dispatch_event(session, + H2_SESSION_EV_CONN_TIMEOUT, status, NULL); + break; + } + } + else if (APR_SUCCESS != status) { + h2_session_dispatch_event(session, + H2_SESSION_EV_CONN_ERROR, status, NULL); + break; + } + } } } else { @@ -1872,14 +1918,20 @@ apr_status_t h2_session_process(h2_session *session, int async) h2_session_dispatch_event(session, H2_SESSION_EV_CONN_ERROR, status, NULL); break; } + if (session->open_streams == 0) { + h2_session_dispatch_event(session, H2_SESSION_EV_NO_MORE_STREAMS, + 0, "streams really done"); + } /* No IO happening and input is exhausted. Make sure we have * flushed any possibly pending output and then wait with * the c1 connection timeout for sth to happen in our c1/c2 sockets/pipes */ status = h2_mplx_c1_poll(session->mplx, session->s->timeout, on_stream_input, on_stream_output, session); if (APR_STATUS_IS_TIMEUP(status)) { - h2_session_dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, status, NULL); - break; + if (session->open_streams == 0) { + h2_session_dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, status, NULL); + break; + } } else if (APR_SUCCESS != status) { h2_session_dispatch_event(session, H2_SESSION_EV_CONN_ERROR, status, NULL); |