summaryrefslogtreecommitdiffstats
path: root/modules/http2/h2_proxy_session.c
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2016-11-01 20:40:37 +0100
committerStefan Eissing <icing@apache.org>2016-11-01 20:40:37 +0100
commit29d168102556c119f62a3f28f5a3695fe93e9a96 (patch)
treeeb8b608b33c0e634f3229a426d4e142a37a2c28d /modules/http2/h2_proxy_session.c
parentRebuild. (diff)
downloadapache2-29d168102556c119f62a3f28f5a3695fe93e9a96.tar.xz
apache2-29d168102556c119f62a3f28f5a3695fe93e9a96.zip
mod_http2: proper parsing and forwarding of multiple or unnaounce 1xx responses
mod_proxy_http2: improved robustness when main connection gets aborted git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1767553 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/http2/h2_proxy_session.c')
-rw-r--r--modules/http2/h2_proxy_session.c57
1 files changed, 43 insertions, 14 deletions
diff --git a/modules/http2/h2_proxy_session.c b/modules/http2/h2_proxy_session.c
index a79c5da479..59ae9d48e2 100644
--- a/modules/http2/h2_proxy_session.c
+++ b/modules/http2/h2_proxy_session.c
@@ -1137,13 +1137,13 @@ static void ev_stream_done(h2_proxy_session *session, int stream_id,
if (stream) {
int touched = (stream->data_sent ||
stream_id <= session->last_stream_id);
- int complete = (stream->error_code == 0);
+ apr_status_t status = (stream->error_code == 0)? APR_SUCCESS : APR_EINVAL;
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03364)
"h2_proxy_sesssion(%s): stream(%d) closed "
"(touched=%d, error=%d)",
session->id, stream_id, touched, stream->error_code);
- if (!complete) {
+ if (status != APR_SUCCESS) {
stream->r->status = 500;
}
else if (!stream->data_received) {
@@ -1164,7 +1164,7 @@ static void ev_stream_done(h2_proxy_session *session, int stream_id,
h2_proxy_ihash_remove(session->streams, stream_id);
h2_proxy_iq_remove(session->suspended, stream_id);
if (session->done) {
- session->done(session, stream->r, complete, touched);
+ session->done(session, stream->r, status, touched);
}
}
@@ -1276,6 +1276,21 @@ static void dispatch_event(h2_proxy_session *session, h2_proxys_event_t ev,
}
}
+static int send_loop(h2_proxy_session *session)
+{
+ while (nghttp2_session_want_write(session->ngh2)) {
+ int rv = nghttp2_session_send(session->ngh2);
+ if (rv < 0 && nghttp2_is_fatal(rv)) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
+ "h2_proxy_session(%s): write, rv=%d", session->id, rv);
+ dispatch_event(session, H2_PROXYS_EV_CONN_ERROR, rv, NULL);
+ break;
+ }
+ return 1;
+ }
+ return 0;
+}
+
apr_status_t h2_proxy_session_process(h2_proxy_session *session)
{
apr_status_t status;
@@ -1300,16 +1315,7 @@ run_loop:
case H2_PROXYS_ST_BUSY:
case H2_PROXYS_ST_LOCAL_SHUTDOWN:
case H2_PROXYS_ST_REMOTE_SHUTDOWN:
- while (nghttp2_session_want_write(session->ngh2)) {
- int rv = nghttp2_session_send(session->ngh2);
- if (rv < 0 && nghttp2_is_fatal(rv)) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
- "h2_proxy_session(%s): write, rv=%d", session->id, rv);
- dispatch_event(session, H2_PROXYS_EV_CONN_ERROR, rv, NULL);
- break;
- }
- have_written = 1;
- }
+ have_written = send_loop(session);
if (nghttp2_session_want_read(session->ngh2)) {
status = h2_proxy_session_read(session, 0, 0);
@@ -1386,13 +1392,36 @@ typedef struct {
h2_proxy_request_done *done;
} cleanup_iter_ctx;
+static int cancel_iter(void *udata, void *val)
+{
+ cleanup_iter_ctx *ctx = udata;
+ h2_proxy_stream *stream = val;
+ nghttp2_submit_rst_stream(ctx->session->ngh2, NGHTTP2_FLAG_NONE,
+ stream->id, 0);
+ return 1;
+}
+
+void h2_proxy_session_cancel_all(h2_proxy_session *session)
+{
+ if (!h2_proxy_ihash_empty(session->streams)) {
+ cleanup_iter_ctx ctx;
+ ctx.session = session;
+ ctx.done = session->done;
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03366)
+ "h2_proxy_session(%s): cancel %d streams",
+ session->id, (int)h2_proxy_ihash_count(session->streams));
+ h2_proxy_ihash_iter(session->streams, cancel_iter, &ctx);
+ session_shutdown(session, 0, NULL);
+ }
+}
+
static int done_iter(void *udata, void *val)
{
cleanup_iter_ctx *ctx = udata;
h2_proxy_stream *stream = val;
int touched = (stream->data_sent ||
stream->id <= ctx->session->last_stream_id);
- ctx->done(ctx->session, stream->r, 0, touched);
+ ctx->done(ctx->session, stream->r, APR_ECONNABORTED, touched);
return 1;
}