httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jor...@apache.org
Subject svn commit: r1781045 [48/50] - in /httpd/httpd/branches/2.4.x-openssl-1.1.0-compat: ./ build/ docs/man/ docs/manual/ docs/manual/developer/ docs/manual/faq/ docs/manual/howto/ docs/manual/misc/ docs/manual/mod/ docs/manual/platform/ docs/manual/program...
Date Tue, 31 Jan 2017 09:52:09 GMT
Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_conn_io.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_conn_io.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_conn_io.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_conn_io.c Tue Jan 31 09:52:02 2017
@@ -24,7 +24,6 @@
 #include <http_request.h>
 
 #include "h2_private.h"
-#include "h2_bucket_eoc.h"
 #include "h2_bucket_eos.h"
 #include "h2_config.h"
 #include "h2_conn_io.h"
@@ -72,9 +71,6 @@ static void h2_conn_io_bb_log(conn_rec *
                 else if (AP_BUCKET_IS_EOR(b)) {
                     off += apr_snprintf(buffer+off, bmax-off, "eor ");
                 }
-                else if (H2_BUCKET_IS_H2EOC(b)) {
-                    off += apr_snprintf(buffer+off, bmax-off, "h2eoc ");
-                }
                 else if (H2_BUCKET_IS_H2EOS(b)) {
                     off += apr_snprintf(buffer+off, bmax-off, "h2eos ");
                 }
@@ -128,12 +124,12 @@ static void h2_conn_io_bb_log(conn_rec *
 apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c, 
                              const h2_config *cfg)
 {
-    io->c             = c;
-    io->output        = apr_brigade_create(c->pool, c->bucket_alloc);
-    io->is_tls        = h2_h2_is_tls(c);
-    io->buffer_output = io->is_tls;
-    io->pass_threshold = (apr_size_t)h2_config_geti64(cfg, H2_CONF_STREAM_MAX_MEM) / 2;
-    
+    io->c              = c;
+    io->output         = apr_brigade_create(c->pool, c->bucket_alloc);
+    io->is_tls         = h2_h2_is_tls(c);
+    io->buffer_output  = io->is_tls;
+    io->flush_threshold = (apr_size_t)h2_config_geti64(cfg, H2_CONF_STREAM_MAX_MEM);
+
     if (io->is_tls) {
         /* This is what we start with, 
          * see https://issues.apache.org/jira/browse/TS-2503 
@@ -269,8 +265,7 @@ static void check_write_size(h2_conn_io
     }
 }
 
-static apr_status_t pass_output(h2_conn_io *io, int flush,
-                                h2_session *session_eoc)
+static apr_status_t pass_output(h2_conn_io *io, int flush)
 {
     conn_rec *c = io->c;
     apr_bucket_brigade *bb = io->output;
@@ -279,7 +274,7 @@ static apr_status_t pass_output(h2_conn_
     apr_status_t status;
     
     append_scratch(io);
-    if (flush) {
+    if (flush && !io->is_flushed) {
         b = apr_bucket_flush_create(c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(bb, b);
     }
@@ -297,23 +292,12 @@ static apr_status_t pass_output(h2_conn_
     if (status == APR_SUCCESS) {
         io->bytes_written += (apr_size_t)bblen;
         io->last_write = apr_time_now();
+        if (flush) {
+            io->is_flushed = 1;
+        }
     }
     apr_brigade_cleanup(bb);
 
-    if (session_eoc) {
-        apr_status_t tmp;
-        b = h2_bucket_eoc_create(c->bucket_alloc, session_eoc);
-        APR_BRIGADE_INSERT_TAIL(bb, b);
-        h2_conn_io_bb_log(c, 0, APLOG_TRACE2, "master conn pass", bb);
-        tmp = ap_pass_brigade(c->output_filters, bb);
-        if (status == APR_SUCCESS) {
-            status = tmp;
-        }
-        /* careful with access to io after this, we have flushed an EOC bucket
-         * that de-allocated us all. */
-        apr_brigade_cleanup(bb);
-    }
-    
     if (status != APR_SUCCESS) {
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c, APLOGNO(03044)
                       "h2_conn_io(%ld): pass_out brigade %ld bytes",
@@ -322,14 +306,27 @@ static apr_status_t pass_output(h2_conn_
     return status;
 }
 
-apr_status_t h2_conn_io_flush(h2_conn_io *io)
+int h2_conn_io_needs_flush(h2_conn_io *io)
 {
-    return pass_output(io, 1, NULL);
+    if (!io->is_flushed) {
+        apr_off_t len = h2_brigade_mem_size(io->output);
+        if (len > io->flush_threshold) {
+            return 1;
+        }
+        /* if we do not exceed flush length due to memory limits,
+         * we want at least flush when we have that amount of data. */
+        apr_brigade_length(io->output, 0, &len);
+        return len > (4 * io->flush_threshold);
+    }
+    return 0;
 }
 
-apr_status_t h2_conn_io_write_eoc(h2_conn_io *io, h2_session *session)
+apr_status_t h2_conn_io_flush(h2_conn_io *io)
 {
-    return pass_output(io, 1, session);
+    apr_status_t status;
+    status = pass_output(io, 1);
+    check_write_size(io);
+    return status;
 }
 
 apr_status_t h2_conn_io_write(h2_conn_io *io, const char *data, size_t length)
@@ -337,6 +334,10 @@ apr_status_t h2_conn_io_write(h2_conn_io
     apr_status_t status = APR_SUCCESS;
     apr_size_t remain;
     
+    if (length > 0) {
+        io->is_flushed = 0;
+    }
+    
     if (io->buffer_output) {
         while (length > 0) {
             remain = assure_scratch_space(io);
@@ -374,7 +375,10 @@ apr_status_t h2_conn_io_pass(h2_conn_io
     apr_bucket *b;
     apr_status_t status = APR_SUCCESS;
     
-    check_write_size(io);
+    if (!APR_BRIGADE_EMPTY(bb)) {
+        io->is_flushed = 0;
+    }
+
     while (!APR_BRIGADE_EMPTY(bb) && status == APR_SUCCESS) {
         b = APR_BRIGADE_FIRST(bb);
         
@@ -417,15 +421,6 @@ apr_status_t h2_conn_io_pass(h2_conn_io
             APR_BRIGADE_INSERT_TAIL(io->output, b);
         }
     }
-    
-    if (status == APR_SUCCESS) {
-        if (!APR_BRIGADE_EMPTY(io->output)) {
-            apr_off_t len = h2_brigade_mem_size(io->output);
-            if (len >= io->pass_threshold) {
-                return pass_output(io, 0, NULL);
-            }
-        }
-    }
     return status;
 }
 

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_conn_io.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_conn_io.h?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_conn_io.h (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_conn_io.h Tue Jan 31 09:52:02 2017
@@ -39,7 +39,8 @@ typedef struct {
     apr_int64_t bytes_written;
     
     int buffer_output;
-    apr_size_t pass_threshold;
+    apr_size_t flush_threshold;
+    unsigned int is_flushed : 1;
     
     char *scratch;
     apr_size_t ssize;
@@ -61,16 +62,15 @@ apr_status_t h2_conn_io_write(h2_conn_io
 apr_status_t h2_conn_io_pass(h2_conn_io *io, apr_bucket_brigade *bb);
 
 /**
- * Append an End-Of-Connection bucket to the output that, once destroyed,
- * will tear down the complete http2 session.
- */
-apr_status_t h2_conn_io_write_eoc(h2_conn_io *io, struct h2_session *session);
-
-/**
  * Pass any buffered data on to the connection output filters.
  * @param io the connection io
  * @param flush if a flush bucket should be appended to any output
  */
 apr_status_t h2_conn_io_flush(h2_conn_io *io);
 
+/**
+ * Check if the buffered amount of data needs flushing.
+ */
+int h2_conn_io_needs_flush(h2_conn_io *io);
+
 #endif /* defined(__mod_h2__h2_conn_io__) */

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_from_h1.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_from_h1.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_from_h1.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_from_h1.c Tue Jan 31 09:52:02 2017
@@ -513,11 +513,11 @@ apr_status_t h2_filter_headers_out(ap_fi
     apr_bucket *b, *bresp, *body_bucket = NULL, *next;
     ap_bucket_error *eb = NULL;
     h2_headers *response = NULL;
-
+    int headers_passing = 0;
     ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, f->c,
                   "h2_task(%s): output_filter called", task->id);
     
-    if (!task->output.sent_response) {
+    if (!task->output.sent_response && !f->c->aborted) {
         /* check, if we need to send the response now. Until we actually
          * see a DATA bucket or some EOS/EOR, we do not do so. */
         for (b = APR_BRIGADE_FIRST(bb);
@@ -536,7 +536,10 @@ apr_status_t h2_filter_headers_out(ap_fi
                               "h2_task(%s): eoc bucket passed", task->id);
                 return ap_pass_brigade(f->next, bb);
             }
-            else if (!H2_BUCKET_IS_HEADERS(b) && !APR_BUCKET_IS_FLUSH(b)) { 
+            else if (H2_BUCKET_IS_HEADERS(b)) {
+                headers_passing = 1;
+            }
+            else if (!APR_BUCKET_IS_FLUSH(b)) { 
                 body_bucket = b;
                 break;
             }
@@ -553,8 +556,9 @@ apr_status_t h2_filter_headers_out(ap_fi
             return AP_FILTER_ERROR;
         }
         
-        if (body_bucket) {
-            /* time to insert the response bucket before the body */
+        if (body_bucket || !headers_passing) {
+            /* time to insert the response bucket before the body or if
+             * no h2_headers is passed, e.g. the response is empty */
             response = create_response(task, r);
             if (response == NULL) {
                 ap_log_cerror(APLOG_MARK, APLOG_NOTICE, 0, f->c, APLOGNO(03048)
@@ -563,7 +567,12 @@ apr_status_t h2_filter_headers_out(ap_fi
             }
             
             bresp = h2_bucket_headers_create(f->c->bucket_alloc, response);
-            APR_BUCKET_INSERT_BEFORE(body_bucket, bresp);
+            if (body_bucket) {
+                APR_BUCKET_INSERT_BEFORE(body_bucket, bresp);
+            }
+            else {
+                APR_BRIGADE_INSERT_HEAD(bb, bresp);
+            }
             task->output.sent_response = 1;
             r->sent_bodyct = 1;
         }
@@ -730,6 +739,9 @@ apr_status_t h2_filter_request_in(ap_fil
     request_rec *r = f->r;
     apr_status_t status = APR_SUCCESS;
     apr_bucket *b, *next;
+    core_server_config *conf =
+        (core_server_config *) ap_get_module_config(r->server->module_config,
+                                                    &core_module);
 
     ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, f->r,
                   "h2_task(%s): request filter, exp=%d", task->id, r->expecting_100);
@@ -744,7 +756,11 @@ apr_status_t h2_filter_request_in(ap_fil
                 ap_assert(headers);
                 ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
                               "h2_task(%s): receiving trailers", task->id);
-                r->trailers_in = apr_table_clone(r->pool, headers->headers);
+                r->trailers_in = headers->headers;
+                if (conf && conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE) {
+                    r->headers_in = apr_table_overlay(r->pool, r->headers_in,
+                                                      r->trailers_in);                    
+                }
                 APR_BUCKET_REMOVE(b);
                 apr_bucket_destroy(b);
                 ap_remove_input_filter(f);

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_h2.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_h2.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_h2.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_h2.c Tue Jan 31 09:52:02 2017
@@ -684,7 +684,8 @@ static int h2_h2_pre_close_conn(conn_rec
 static void check_push(request_rec *r, const char *tag)
 {
     const h2_config *conf = h2_config_rget(r);
-    if (conf && conf->push_list && conf->push_list->nelts > 0) {
+    if (!r->expecting_100 
+        && conf && conf->push_list && conf->push_list->nelts > 0) {
         int i, old_status;
         const char *old_line;
         ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, 

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_mplx.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_mplx.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_mplx.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_mplx.c Tue Jan 31 09:52:02 2017
@@ -17,6 +17,7 @@
 #include <stddef.h>
 #include <stdlib.h>
 
+#include <apr_atomic.h>
 #include <apr_thread_mutex.h>
 #include <apr_thread_cond.h>
 #include <apr_strings.h>
@@ -53,8 +54,8 @@ static void h2_beam_log(h2_bucket_beam *
         apr_size_t off = 0;
         
         off += apr_snprintf(buffer+off, H2_ALEN(buffer)-off, "cl=%d, ", beam->closed);
-        off += h2_util_bl_print(buffer+off, H2_ALEN(buffer)-off, "red", ", ", &beam->send_list);
-        off += h2_util_bb_print(buffer+off, H2_ALEN(buffer)-off, "green", ", ", beam->recv_buffer);
+        off += h2_util_bl_print(buffer+off, H2_ALEN(buffer)-off, "to_send", ", ", &beam->send_list);
+        off += h2_util_bb_print(buffer+off, H2_ALEN(buffer)-off, "recv_buffer", ", ", beam->recv_buffer);
         off += h2_util_bl_print(buffer+off, H2_ALEN(buffer)-off, "hold", ", ", &beam->hold_list);
         off += h2_util_bl_print(buffer+off, H2_ALEN(buffer)-off, "purge", "", &beam->purge_list);
 
@@ -143,6 +144,12 @@ static void stream_output_consumed(void
     }
 }
 
+static void stream_input_ev(void *ctx, h2_bucket_beam *beam)
+{
+    h2_mplx *m = ctx;
+    apr_atomic_set32(&m->event_pending, 1);
+}
+
 static void stream_input_consumed(void *ctx, 
                                   h2_bucket_beam *beam, apr_off_t length)
 {
@@ -192,9 +199,13 @@ static void check_tx_free(h2_mplx *m)
     }
 }
 
+typedef struct {
+    h2_mplx *m;
+} purge_ctx;
+
 static int purge_stream(void *ctx, void *val) 
 {
-    h2_mplx *m = ctx;
+    purge_ctx *pctx = ctx;
     h2_stream *stream = val;
     int stream_id = stream->id;
     h2_task *task;
@@ -204,20 +215,22 @@ static int purge_stream(void *ctx, void
      * before task destruction, otherwise it will complain. */
     h2_stream_cleanup(stream);
     
-    task = h2_ihash_get(m->tasks, stream_id);    
+    task = h2_ihash_get(pctx->m->tasks, stream_id);    
     if (task) {
-        task_destroy(m, task, 1);
+        task_destroy(pctx->m, task, 1);
     }
     
     h2_stream_destroy(stream);
-    h2_ihash_remove(m->spurge, stream_id);
+    h2_ihash_remove(pctx->m->spurge, stream_id);
     return 0;
 }
 
 static void purge_streams(h2_mplx *m)
 {
     if (!h2_ihash_empty(m->spurge)) {
-        while(!h2_ihash_iter(m->spurge, purge_stream, m)) {
+        purge_ctx ctx;
+        ctx.m = m;
+        while(!h2_ihash_iter(m->spurge, purge_stream, &ctx)) {
             /* repeat until empty */
         }
         h2_ihash_clear(m->spurge);
@@ -226,20 +239,13 @@ static void purge_streams(h2_mplx *m)
 
 static void h2_mplx_destroy(h2_mplx *m)
 {
-    conn_rec **pslave;
     ap_assert(m);
     ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
                   "h2_mplx(%ld): destroy, tasks=%d", 
                   m->id, (int)h2_ihash_count(m->tasks));
     check_tx_free(m);
-    
-    while (m->spare_slaves->nelts > 0) {
-        pslave = (conn_rec **)apr_array_pop(m->spare_slaves);
-        h2_slave_destroy(*pslave);
-    }
-    if (m->pool) {
-        apr_pool_destroy(m->pool);
-    }
+    /* pool will be destroyed as child of h2_session->pool,
+       slave connection pools are children of m->pool */
 }
 
 /**
@@ -337,18 +343,18 @@ int h2_mplx_shutdown(h2_mplx *m)
     return max_stream_started;
 }
 
-static void input_consumed_signal(h2_mplx *m, h2_stream *stream)
+static int input_consumed_signal(h2_mplx *m, h2_stream *stream)
 {
-    if (stream->input && stream->started) {
-        h2_beam_send(stream->input, NULL, 0); /* trigger updates */
+    if (stream->input) {
+        return h2_beam_report_consumption(stream->input);
     }
+    return 0;
 }
 
 static int output_consumed_signal(h2_mplx *m, h2_task *task)
 {
-    if (task->output.beam && task->worker_started && task->assigned) {
-        /* trigger updates */
-        h2_beam_send(task->output.beam, NULL, APR_NONBLOCK_READ);
+    if (task->output.beam) {
+        return h2_beam_report_consumption(task->output.beam);
     }
     return 0;
 }
@@ -435,10 +441,11 @@ static void stream_done(h2_mplx *m, h2_s
      */
     h2_iq_remove(m->q, stream->id);
     h2_ihash_remove(m->streams, stream->id);
+    h2_ihash_remove(m->shold, stream->id);
     
     h2_stream_cleanup(stream);
     m->tx_handles_reserved += h2_beam_get_files_beamed(stream->input);
-    h2_beam_on_consumed(stream->input, NULL, NULL);
+    h2_beam_on_consumed(stream->input, NULL, NULL, NULL);
     /* Let anyone blocked reading know that there is no more to come */
     h2_beam_abort(stream->input);
     /* Remove mutex after, so that abort still finds cond to signal */
@@ -460,7 +467,7 @@ static void stream_done(h2_mplx *m, h2_s
             task_destroy(m, task, 1);
         }
     }
-    h2_stream_destroy(stream);
+    h2_ihash_add(m->spurge, stream);
 }
 
 static int stream_done_iter(void *ctx, void *val)
@@ -561,7 +568,7 @@ apr_status_t h2_mplx_release_and_join(h2
         h2_mplx_set_consumed_cb(m, NULL, NULL);
         h2_mplx_abort(m);
         h2_iq_clear(m->q);
-        purge_streams(m);
+        h2_ihash_clear(m->spurge);
 
         /* 3. wakeup all sleeping tasks. Mark all still active streams as 'done'. 
          *    m->streams has to be empty afterwards with streams either in
@@ -574,10 +581,7 @@ apr_status_t h2_mplx_release_and_join(h2
         }
         ap_assert(h2_ihash_empty(m->streams));
 
-        /* 4. purge all streams we collected by marking them 'done' */
-        purge_streams(m);
-        
-        /* 5. while workers are busy on this connection, meaning they
+        /* 4. while workers are busy on this connection, meaning they
          *    are processing tasks from this connection, wait on them finishing
          *    to wake us and check again. Eventually, this has to succeed. */    
         m->join_wait = wait;
@@ -595,11 +599,10 @@ apr_status_t h2_mplx_release_and_join(h2
                 h2_ihash_iter(m->shold, report_stream_iter, m);
                 h2_ihash_iter(m->tasks, task_print, m);
             }
-            purge_streams(m);
         }
         m->join_wait = NULL;
         
-        /* 6. All workers for this connection are done, we are in 
+        /* 5. All workers for this connection are done, we are in 
          * single-threaded processing now effectively. */
         leave_mutex(m, acquired);
 
@@ -618,12 +621,10 @@ apr_status_t h2_mplx_release_and_join(h2
             }
         }
 
-        /* 7. With all tasks done, the stream hold should be empty and all
-         *    remaining streams are ready for purging */
+        /* 6. With all tasks done, the stream hold should be empty now. */
         ap_assert(h2_ihash_empty(m->shold));
-        purge_streams(m);
         
-        /* 8. close the h2_req_enginge shed and self destruct */
+        /* 7. close the h2_req_enginge shed and self destruct */
         h2_ngn_shed_destroy(m->ngn_shed);
         m->ngn_shed = NULL;
         h2_mplx_destroy(m);
@@ -703,10 +704,15 @@ static apr_status_t out_open(h2_mplx *m,
         return APR_ECONNABORTED;
     }
     
-    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, m->c,
-                  "h2_mplx(%s): out open", task->id);
-                      
-    h2_beam_on_consumed(stream->output, stream_output_consumed, task);
+    if (APLOGctrace2(m->c)) {
+        h2_beam_log(beam, stream_id, "out_open", m->c, APLOG_TRACE2);
+    }
+    else {
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, m->c,
+                      "h2_mplx(%s): out open", task->id);
+    }
+    
+    h2_beam_on_consumed(stream->output, NULL, stream_output_consumed, task);
     h2_beam_on_produced(stream->output, output_produced, m);
     beamed_count = h2_beam_get_files_beamed(stream->output);
     if (m->tx_handles_reserved >= beamed_count) {
@@ -780,7 +786,7 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
         if (m->aborted) {
             status = APR_ECONNABORTED;
         }
-        else if (!h2_iq_empty(m->readyq)) {
+        else if (apr_atomic_read32(&m->event_pending) > 0) {
             status = APR_SUCCESS;
         }
         else {
@@ -804,6 +810,7 @@ static void have_out_data_for(h2_mplx *m
     ap_assert(m);
     ap_assert(stream);
     h2_iq_append(m->readyq, stream->id);
+    apr_atomic_set32(&m->event_pending, 1);
     if (m->added_output) {
         apr_thread_cond_signal(m->added_output);
     }
@@ -842,6 +849,7 @@ apr_status_t h2_mplx_process(h2_mplx *m,
         else {
             h2_ihash_add(m->streams, stream);
             if (h2_stream_is_ready(stream)) {
+                apr_atomic_set32(&m->event_pending, 1);
                 h2_iq_append(m->readyq, stream->id);
             }
             else {
@@ -906,7 +914,8 @@ static h2_task *next_stream_task(h2_mplx
             }
 
             h2_beam_timeout_set(stream->input, m->stream_timeout);
-            h2_beam_on_consumed(stream->input, stream_input_consumed, m);
+            h2_beam_on_consumed(stream->input, stream_input_ev, 
+                                stream_input_consumed, m);
             h2_beam_on_file_beam(stream->input, can_beam_file, m);
             h2_beam_mutex_set(stream->input, beam_enter, task->cond, m);
             
@@ -1021,7 +1030,7 @@ static void task_done(h2_mplx *m, h2_tas
                           task->id);
             /* more data will not arrive, resume the stream */
             have_out_data_for(m, stream, 0);
-            h2_beam_on_consumed(stream->output, NULL, NULL);
+            h2_beam_on_consumed(stream->output, NULL, NULL, NULL);
             h2_beam_mutex_set(stream->output, NULL, NULL, NULL);
         }
         else {
@@ -1035,7 +1044,7 @@ static void task_done(h2_mplx *m, h2_tas
                  * called from a worker thread and freeing memory pools
                  * is only safe in the only thread using it (and its
                  * parent pool / allocator) */
-                h2_beam_on_consumed(stream->output, NULL, NULL);
+                h2_beam_on_consumed(stream->output, NULL, NULL, NULL);
                 h2_beam_mutex_set(stream->output, NULL, NULL, NULL);
                 h2_ihash_remove(m->shold, stream->id);
                 h2_ihash_add(m->spurge, stream);
@@ -1345,7 +1354,12 @@ void h2_mplx_req_engine_done(h2_req_engi
  * mplx master events dispatching
  ******************************************************************************/
 
-static int update_window(void *ctx, void *val)
+int h2_mplx_has_master_events(h2_mplx *m)
+{
+    return apr_atomic_read32(&m->event_pending) > 0;
+}
+
+static int report_consumption_iter(void *ctx, void *val)
 {
     input_consumed_signal(ctx, val);
     return 1;
@@ -1361,25 +1375,30 @@ apr_status_t h2_mplx_dispatch_master_eve
     h2_stream *stream;
     size_t i, n;
     
+    if (!h2_mplx_has_master_events(m)) {
+        return APR_EAGAIN;
+    }
+    
     if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, m->c, 
-                      "h2_mplx(%ld): dispatch events", m->id);
-                      
+                      "h2_mplx(%ld): dispatch events", m->id);        
+        apr_atomic_set32(&m->event_pending, 0);
         /* update input windows for streams */
-        h2_ihash_iter(m->streams, update_window, m);
-        if (on_resume && !h2_iq_empty(m->readyq)) {
+        h2_ihash_iter(m->streams, report_consumption_iter, m);
+        purge_streams(m);
+        
+        if (!h2_iq_empty(m->readyq)) {
             n = h2_iq_mshift(m->readyq, ids, H2_ALEN(ids));
             for (i = 0; i < n; ++i) {
                 stream = h2_ihash_get(m->streams, ids[i]);
                 if (stream) {
-                    ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, m->c, 
-                                  "h2_mplx(%ld-%d): on_resume", 
-                                  m->id, stream->id);
                     on_resume(on_ctx, stream);
                 }
             }
         }
-        
+        if (!h2_iq_empty(m->readyq)) {
+            apr_atomic_set32(&m->event_pending, 1);
+        } 
         leave_mutex(m, acquired);
     }
     return status;
@@ -1394,6 +1413,7 @@ apr_status_t h2_mplx_keep_active(h2_mplx
         h2_stream *s = h2_ihash_get(m->streams, stream_id);
         if (s) {
             h2_iq_append(m->readyq, stream_id);
+            apr_atomic_set32(&m->event_pending, 1);
         }
         leave_mutex(m, acquired);
     }

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_mplx.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_mplx.h?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_mplx.h (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_mplx.h Tue Jan 31 09:52:02 2017
@@ -67,6 +67,7 @@ struct h2_mplx {
 
     APR_RING_ENTRY(h2_mplx) link;
 
+    unsigned int event_pending;
     unsigned int aborted : 1;
     unsigned int need_registration : 1;
 
@@ -222,6 +223,12 @@ void h2_mplx_set_consumed_cb(h2_mplx *m,
 typedef apr_status_t stream_ev_callback(void *ctx, struct h2_stream *stream);
 
 /**
+ * Check if the multiplexer has events for the master connection pending.
+ * @return != 0 iff there are events pending
+ */
+int h2_mplx_has_master_events(h2_mplx *m);
+
+/**
  * Dispatch events for the master connection, such as
  ± @param m the multiplexer
  * @param on_resume new output data has arrived for a suspended stream 

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_proxy_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_proxy_session.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_proxy_session.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_proxy_session.c Tue Jan 31 09:52:02 2017
@@ -160,10 +160,17 @@ static int on_frame_recv(nghttp2_session
             }
             r = stream->r;
             if (r->status >= 100 && r->status < 200) {
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
-                              "h2_proxy_session(%s): got interim HEADERS, status=%d",
-                              session->id, r->status);
+                /* By default, we will forward all interim responses when
+                 * we are sitting on a HTTP/2 connection to the client */
+                int forward = session->h2_front;
                 switch(r->status) {
+                    case 100:
+                        if (stream->waiting_on_100) {
+                            stream->waiting_on_100 = 0;
+                            r->status_line = ap_get_status_line(r->status);
+                            forward = 1;
+                        } 
+                        break;
                     case 103:
                         /* workaround until we get this into http protocol base
                          * parts. without this, unknown codes are converted to
@@ -174,9 +181,14 @@ static int on_frame_recv(nghttp2_session
                         r->status_line = ap_get_status_line(r->status);
                         break;
                 }
-                ap_send_interim_response(r, 1);
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03487) 
+                              "h2_proxy_session(%s): got interim HEADERS, "
+                              "status=%d, will forward=%d",
+                              session->id, r->status, forward);
+                if (forward) {
+                    ap_send_interim_response(r, 1);
+                }
             }
-            stream->waiting_on_100 = 0;
             stream_resume(stream);
             break;
         case NGHTTP2_PING:
@@ -332,7 +344,7 @@ static void h2_proxy_stream_end_headers_
         
         /* If USE_CANONICAL_NAME_OFF was configured for the proxy virtual host,
          * then the server name returned by ap_get_server_name() is the
-         * origin server name (which does make too much sense with Via: headers)
+         * origin server name (which doesn't make sense with Via: headers)
          * so we use the proxy vhost's name instead.
          */
         if (server_name == stream->r->hostname) {
@@ -582,6 +594,7 @@ static int on_invalid_header_cb(nghttp2_
 
 h2_proxy_session *h2_proxy_session_setup(const char *id, proxy_conn_rec *p_conn,
                                          proxy_server_conf *conf,
+                                         int h2_front, 
                                          unsigned char window_bits_connection,
                                          unsigned char window_bits_stream,
                                          h2_proxy_request_done *done)
@@ -602,6 +615,7 @@ h2_proxy_session *h2_proxy_session_setup
         session->conf = conf;
         session->pool = p_conn->scpool;
         session->state = H2_PROXYS_ST_INIT;
+        session->h2_front = h2_front;
         session->window_bits_stream = window_bits_stream;
         session->window_bits_connection = window_bits_connection;
         session->streams = h2_proxy_ihash_create(pool, offsetof(h2_proxy_stream, id));

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_proxy_session.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_proxy_session.h?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_proxy_session.h (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_proxy_session.h Tue Jan 31 09:52:02 2017
@@ -64,6 +64,7 @@ struct h2_proxy_session {
     
     unsigned int aborted : 1;
     unsigned int check_ping : 1;
+    unsigned int h2_front : 1; /* if front-end connection is HTTP/2 */
 
     h2_proxy_request_done *done;
     void *user_data;
@@ -86,6 +87,7 @@ struct h2_proxy_session {
 
 h2_proxy_session *h2_proxy_session_setup(const char *id, proxy_conn_rec *p_conn,
                                          proxy_server_conf *conf,
+                                         int h2_front, 
                                          unsigned char window_bits_connection,
                                          unsigned char window_bits_stream,
                                          h2_proxy_request_done *done);

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_session.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_session.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_session.c Tue Jan 31 09:52:02 2017
@@ -29,7 +29,6 @@
 
 #include "h2_private.h"
 #include "h2.h"
-#include "h2_bucket_eoc.h"
 #include "h2_bucket_eos.h"
 #include "h2_config.h"
 #include "h2_ctx.h"
@@ -47,6 +46,9 @@
 #include "h2_workers.h"
 
 
+static apr_status_t dispatch_master(h2_session *session);
+static apr_status_t h2_session_read(h2_session *session, int block);
+
 static int h2_session_status_from_apr_status(apr_status_t rv)
 {
     if (rv == APR_SUCCESS) {
@@ -93,7 +95,7 @@ typedef struct stream_sel_ctx {
     h2_stream *candidate;
 } stream_sel_ctx;
 
-static int find_cleanup_stream(h2_stream *stream, void *ictx)
+static int find_unprocessed_stream(h2_stream *stream, void *ictx)
 {
     stream_sel_ctx *ctx = ictx;
     if (H2_STREAM_CLIENT_INITIATED(stream->id)) {
@@ -113,20 +115,17 @@ static int find_cleanup_stream(h2_stream
     return 1;
 }
 
-static void cleanup_streams(h2_session *session)
+static void cleanup_unprocessed_streams(h2_session *session)
 {
     stream_sel_ctx ctx;
     ctx.session = session;
-    ctx.candidate = NULL;
     while (1) {
-        h2_mplx_stream_do(session->mplx, find_cleanup_stream, &ctx);
-        if (ctx.candidate) {
-            h2_session_stream_done(session, ctx.candidate);
-            ctx.candidate = NULL;
-        }
-        else {
+        ctx.candidate = NULL;
+        h2_mplx_stream_do(session->mplx, find_unprocessed_stream, &ctx);
+        if (!ctx.candidate) {
             break;
         }
+        h2_session_stream_done(session, ctx.candidate);
     }
 }
 
@@ -315,9 +314,9 @@ static int on_data_chunk_recv_cb(nghttp2
     return 0;
 }
 
-static apr_status_t stream_release(h2_session *session, 
-                                   h2_stream *stream,
-                                   uint32_t error_code) 
+static apr_status_t stream_closed(h2_session *session, 
+                                  h2_stream *stream,
+                                  uint32_t error_code) 
 {
     conn_rec *c = session->c;
     apr_bucket *b;
@@ -327,10 +326,9 @@ static apr_status_t stream_release(h2_se
         ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                       "h2_stream(%ld-%d): handled, closing", 
                       session->id, (int)stream->id);
-        if (H2_STREAM_CLIENT_INITIATED(stream->id)) {
-            if (stream->id > session->local.completed_max) {
-                session->local.completed_max = stream->id;
-            }
+        if (H2_STREAM_CLIENT_INITIATED(stream->id)
+            && stream->id > session->local.completed_max) {
+            session->local.completed_max = stream->id;
         }
     }
     else {
@@ -340,7 +338,11 @@ static apr_status_t stream_release(h2_se
                       h2_h2_err_description(error_code));
         h2_stream_rst(stream, error_code);
     }
-    
+    /* The stream might have data in the buffers of the main connection.
+     * We can only free the allocated resources once all had been written.
+     * Send a special buckets on the connection that gets destroyed when
+     * all preceding data has been handled. On its destruction, it is safe
+     * to purge all resources of the stream. */
     b = h2_bucket_eos_create(c->bucket_alloc, stream);
     APR_BRIGADE_INSERT_TAIL(session->bbtmp, b);
     status = h2_conn_io_pass(&session->io, session->bbtmp);
@@ -357,7 +359,7 @@ static int on_stream_close_cb(nghttp2_se
     (void)ngh2;
     stream = get_stream(session, stream_id);
     if (stream) {
-        stream_release(session, stream, error_code);
+        stream_closed(session, stream, error_code);
     }
     return 0;
 }
@@ -394,7 +396,7 @@ static int on_header_cb(nghttp2_session
     (void)flags;
     stream = get_stream(session, frame->hd.stream_id);
     if (!stream) {
-        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c,
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
                       APLOGNO(02920) 
                       "h2_session:  stream(%ld-%d): on_header unknown stream",
                       session->id, (int)frame->hd.stream_id);
@@ -403,7 +405,14 @@ static int on_header_cb(nghttp2_session
     
     status = h2_stream_add_header(stream, (const char *)name, namelen,
                                   (const char *)value, valuelen);
-    if (status != APR_SUCCESS && !h2_stream_is_ready(stream)) {
+    if (status == APR_ECONNRESET) {
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, session->c,
+                      "h2-stream(%ld-%d): on_header, reset stream",
+                      session->id, stream->id);
+        nghttp2_submit_rst_stream(ngh2, NGHTTP2_FLAG_NONE, stream->id,
+                                  NGHTTP2_INTERNAL_ERROR);
+    }
+    else if (status != APR_SUCCESS && !h2_stream_is_ready(stream)) {
         return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
     }
     return 0;
@@ -549,6 +558,16 @@ static int on_frame_recv_cb(nghttp2_sess
     return 0;
 }
 
+static int h2_session_continue_data(h2_session *session) {
+    if (h2_mplx_has_master_events(session->mplx)) {
+        return 0;
+    }
+    if (h2_conn_io_needs_flush(&session->io)) {
+        return 0;
+    }
+    return 1;
+}
+
 static char immortal_zeros[H2_MAX_PADLEN];
 
 static int on_send_data_cb(nghttp2_session *ngh2, 
@@ -569,6 +588,10 @@ static int on_send_data_cb(nghttp2_sessi
     
     (void)ngh2;
     (void)source;
+    if (!h2_session_continue_data(session)) {
+        return NGHTTP2_ERR_WOULDBLOCK;
+    }
+
     if (frame->data.padlen > H2_MAX_PADLEN) {
         return NGHTTP2_ERR_PROTO;
     }
@@ -706,35 +729,6 @@ static apr_status_t init_callbacks(conn_
     return APR_SUCCESS;
 }
 
-static void h2_session_destroy(h2_session *session)
-{
-    ap_assert(session);    
-
-    if (session->mplx) {
-        h2_mplx_set_consumed_cb(session->mplx, NULL, NULL);
-        h2_mplx_release_and_join(session->mplx, session->iowait);
-        session->mplx = NULL;
-    }
-
-    ap_remove_input_filter_byhandle((session->r? session->r->input_filters :
-                                     session->c->input_filters), "H2_IN");
-    if (session->ngh2) {
-        nghttp2_session_del(session->ngh2);
-        session->ngh2 = NULL;
-    }
-    if (session->c) {
-        h2_ctx_clear(session->c);
-    }
-
-    if (APLOGctrace1(session->c)) {
-        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
-                      "h2_session(%ld): destroy", session->id);
-    }
-    if (session->pool) {
-        apr_pool_destroy(session->pool);
-    }
-}
-
 static apr_status_t h2_session_shutdown_notice(h2_session *session)
 {
     apr_status_t status;
@@ -809,17 +803,11 @@ static apr_status_t h2_session_shutdown(
 static apr_status_t session_pool_cleanup(void *data)
 {
     h2_session *session = data;
-    /* On a controlled connection shutdown, this gets never
-     * called as we deregister and destroy our pool manually.
-     * However when we have an async mpm, and handed it our idle
-     * connection, it will just cleanup once the connection is closed
-     * from the other side (and sometimes even from out side) and
-     * here we arrive then.
-     */
     ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
                   "session(%ld): pool_cleanup", session->id);
     
-    if (session->state != H2_SESSION_ST_DONE) {
+    if (session->state != H2_SESSION_ST_DONE
+        && session->state != H2_SESSION_ST_INIT) {
         /* Not good. The connection is being torn down and we have
          * not sent a goaway. This is considered a protocol error and
          * the client has to assume that any streams "in flight" may have
@@ -833,9 +821,16 @@ static apr_status_t session_pool_cleanup
                       "goodbye, clients will be confused, should not happen", 
                       session->id);
     }
-    /* keep us from destroying the pool, since that is already ongoing. */
-    session->pool = NULL;
-    h2_session_destroy(session);
+
+    if (session->mplx) {
+        h2_mplx_set_consumed_cb(session->mplx, NULL, NULL);
+        h2_mplx_release_and_join(session->mplx, session->iowait);
+        session->mplx = NULL;
+    }
+    if (session->ngh2) {
+        nghttp2_session_del(session->ngh2);
+        session->ngh2 = NULL;
+    }
     return APR_SUCCESS;
 }
 
@@ -894,7 +889,9 @@ static h2_session *h2_session_create_int
     }
     apr_pool_tag(pool, "h2_session");
 
-    session = apr_pcalloc(pool, sizeof(h2_session));
+    /* get h2_session a lifetime beyond its pool and everything
+     * connected to it. */
+    session = apr_pcalloc(c->pool, sizeof(h2_session));
     if (session) {
         int rv;
         nghttp2_mem *mem;
@@ -940,7 +937,6 @@ static h2_session *h2_session_create_int
         if (status != APR_SUCCESS) {
             ap_log_cerror(APLOG_MARK, APLOG_ERR, status, c, APLOGNO(02927) 
                           "nghttp2: error in init_callbacks");
-            h2_session_destroy(session);
             return NULL;
         }
         
@@ -949,7 +945,6 @@ static h2_session *h2_session_create_int
             ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c,
                           APLOGNO(02928) "nghttp2_option_new: %s", 
                           nghttp2_strerror(rv));
-            h2_session_destroy(session);
             return NULL;
         }
         nghttp2_option_set_peer_max_concurrent_streams(
@@ -980,10 +975,9 @@ static h2_session *h2_session_create_int
             ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c,
                           APLOGNO(02929) "nghttp2_session_server_new: %s",
                           nghttp2_strerror(rv));
-            h2_session_destroy(session);
             return NULL;
         }
-         
+        
         n = h2_config_geti(session->config, H2_CONF_PUSH_DIARY_SIZE);
         session->push_diary = h2_push_diary_create(session->pool, n);
         
@@ -1013,14 +1007,6 @@ h2_session *h2_session_rcreate(request_r
     return h2_session_create_int(r->connection, r, ctx, workers);
 }
 
-void h2_session_eoc_callback(h2_session *session)
-{
-    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
-                  "session(%ld): cleanup and destroy", session->id);
-    apr_pool_cleanup_kill(session->pool, session, session_pool_cleanup);
-    h2_session_destroy(session);
-}
-
 static apr_status_t h2_session_start(h2_session *session, int *rv)
 {
     apr_status_t status = APR_SUCCESS;
@@ -1393,7 +1379,7 @@ static apr_status_t h2_session_send(h2_s
         apr_socket_timeout_set(socket, saved_timeout);
     }
     session->have_written = 1;
-    if (rv != 0) {
+    if (rv != 0 && rv != NGHTTP2_ERR_WOULDBLOCK) {
         if (nghttp2_is_fatal(rv)) {
             dispatch_event(session, H2_SESSION_EV_PROTO_ERROR, rv, nghttp2_strerror(rv));
             return APR_EGENERAL;
@@ -1473,6 +1459,8 @@ static apr_status_t on_stream_headers(h2
          */
         if (!stream->initiated_on
             && !stream->has_response
+            && stream->request && stream->request->method
+            && !strcmp("GET", stream->request->method)
             && (headers->status < 400)
             && (headers->status != 304)
             && h2_session_push_enabled(session)) {
@@ -1499,6 +1487,14 @@ static apr_status_t on_stream_headers(h2
                            apr_itoa(stream->pool, connFlowOut));
         }
         
+        if (headers->status == 103 
+            && !h2_config_geti(session->config, H2_CONF_EARLY_HINTS)) {
+            /* suppress sending this to the client, it might have triggered 
+             * pushes and served its purpose nevertheless */
+            rv = 0;
+            goto leave;
+        }
+        
         ngh = h2_util_ngheader_make_res(stream->pool, headers->status, hout);
         rv = nghttp2_submit_response(session->ngh2, stream->id,
                                      ngh->nv, ngh->nvlen, pprovider);
@@ -1754,7 +1750,7 @@ static void h2_session_ev_init(h2_sessio
 
 static void h2_session_ev_local_goaway(h2_session *session, int arg, const char *msg)
 {
-    cleanup_streams(session);
+    cleanup_unprocessed_streams(session);
     if (!session->remote.shutdown) {
         update_child_status(session, SERVER_CLOSING, "local goaway");
     }
@@ -1767,7 +1763,7 @@ static void h2_session_ev_remote_goaway(
         session->remote.error = arg;
         session->remote.accepting = 0;
         session->remote.shutdown = 1;
-        cleanup_streams(session);
+        cleanup_unprocessed_streams(session);
         update_child_status(session, SERVER_CLOSING, "remote goaway");
         transit(session, "remote goaway", H2_SESSION_ST_DONE);
     }
@@ -2009,6 +2005,25 @@ static void dispatch_event(h2_session *s
     }
 }
 
+/* trigger window updates, stream resumes and submits */
+static apr_status_t dispatch_master(h2_session *session) {
+    apr_status_t status;
+    
+    status = h2_mplx_dispatch_master_events(session->mplx, 
+                                            on_stream_resume, session);
+    if (status == APR_EAGAIN) {
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, session->c,
+                      "h2_session(%ld): no master event available", session->id);
+    }
+    else if (status != APR_SUCCESS) {
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, session->c,
+                      "h2_session(%ld): dispatch error", session->id);
+        dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 
+                       H2_ERR_INTERNAL_ERROR, "dispatch error");
+    }
+    return status;
+}
+
 static const int MAX_WAIT_MICROS = 200 * 1000;
 
 apr_status_t h2_session_process(h2_session *session, int async)
@@ -2023,10 +2038,6 @@ apr_status_t h2_session_process(h2_sessi
                       session->id, async);
     }
                   
-    if (c->cs) {
-        c->cs->state = CONN_STATE_WRITE_COMPLETION;
-    }
-    
     while (session->state != H2_SESSION_ST_DONE) {
         trace = APLOGctrace3(c);
         session->have_read = session->have_written = 0;
@@ -2064,6 +2075,14 @@ apr_status_t h2_session_process(h2_sessi
             case H2_SESSION_ST_IDLE:
                 /* make certain, we send everything before we idle */
                 h2_conn_io_flush(&session->io);
+                /* We trust our connection into the default timeout/keepalive
+                 * handling of the core filters/mpm iff:
+                 * - keep_sync_until is not set
+                 * - we have an async mpm
+                 * - we have no open streams to process
+                 * - we are not sitting on a Upgrade: request
+                 * - we already have seen at least one request
+                 */
                 if (!session->keep_sync_until && async && !session->open_streams
                     && !session->r && session->remote.emitted_count) {
                     if (trace) {
@@ -2072,15 +2091,6 @@ apr_status_t h2_session_process(h2_sessi
                                       "%d streams open", session->id, 
                                       session->open_streams);
                     }
-                    /* We do not return to the async mpm immediately, since under
-                     * load, mpms show the tendency to throw keep_alive connections
-                     * away very rapidly.
-                     * So, if we are still processing streams, we wait for the
-                     * normal timeout first and, on timeout, close.
-                     * If we have no streams, we still wait a short amount of
-                     * time here for the next frame to arrive, before handing
-                     * it to keep_alive processing of the mpm.
-                     */
                     status = h2_session_read(session, 0);
                     
                     if (status == APR_SUCCESS) {
@@ -2165,7 +2175,6 @@ apr_status_t h2_session_process(h2_sessi
                         dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, "error");
                     }
                 }
-                
                 break;
                 
             case H2_SESSION_ST_BUSY:
@@ -2188,24 +2197,18 @@ apr_status_t h2_session_process(h2_sessi
                         dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, NULL);
                     }
                 }
-                
-                /* trigger window updates, stream resumes and submits */
-                status = h2_mplx_dispatch_master_events(session->mplx, 
-                                                        on_stream_resume,
-                                                        session);
-                if (status != APR_SUCCESS) {
-                    ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, c,
-                                  "h2_session(%ld): dispatch error", 
-                                  session->id);
-                    dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 
-                                   H2_ERR_INTERNAL_ERROR, 
-                                   "dispatch error");
+
+                status = dispatch_master(session);
+                if (status != APR_SUCCESS && status != APR_EAGAIN) {
                     break;
                 }
                 
                 if (nghttp2_session_want_write(session->ngh2)) {
                     ap_update_child_status(session->c->sbh, SERVER_BUSY_WRITE, NULL);
                     status = h2_session_send(session);
+                    if (status == APR_SUCCESS) {
+                        status = h2_conn_io_flush(&session->io);
+                    }
                     if (status != APR_SUCCESS) {
                         dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 
                                        H2_ERR_INTERNAL_ERROR, "writing");
@@ -2249,8 +2252,8 @@ apr_status_t h2_session_process(h2_sessi
                 }
                 else if (APR_STATUS_IS_TIMEUP(status)) {
                     /* go back to checking all inputs again */
-                    transit(session, "wait cycle", session->local.accepting? 
-                            H2_SESSION_ST_BUSY : H2_SESSION_ST_DONE);
+                    transit(session, "wait cycle", session->local.shutdown? 
+                            H2_SESSION_ST_DONE : H2_SESSION_ST_BUSY);
                 }
                 else if (APR_STATUS_IS_ECONNRESET(status) 
                          || APR_STATUS_IS_ECONNABORTED(status)) {
@@ -2301,10 +2304,6 @@ out:
     status = APR_SUCCESS;
     if (session->state == H2_SESSION_ST_DONE) {
         status = APR_EOF;
-        if (!session->eoc_written) {
-            session->eoc_written = 1;
-            h2_conn_io_write_eoc(&session->io, session);
-        }
     }
     
     return status;

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_session.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_session.h?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_session.h (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_session.h Tue Jan 31 09:52:02 2017
@@ -94,7 +94,6 @@ typedef struct h2_session {
     h2_session_props remote;        /* properites of remote session */
     
     unsigned int reprioritize  : 1; /* scheduled streams priority changed */
-    unsigned int eoc_written   : 1; /* h2 eoc bucket written */
     unsigned int flush         : 1; /* flushing output necessary */
     unsigned int have_read     : 1; /* session has read client data */
     unsigned int have_written  : 1; /* session did write data to client */
@@ -102,9 +101,9 @@ typedef struct h2_session {
     
     struct h2_push_diary *push_diary; /* remember pushes, avoid duplicates */
     
-    int open_streams;               /* number of streams open */
+    int open_streams;               /* number of client streams open */
     int unsent_submits;             /* number of submitted, but not yet written responses. */
-    int unsent_promises;            /* number of submitted, but not yet written push promised */
+    int unsent_promises;            /* number of submitted, but not yet written push promises */
                                          
     int responses_submitted;        /* number of http/2 responses submitted */
     int streams_reset;              /* number of http/2 streams reset by client */
@@ -166,13 +165,6 @@ apr_status_t h2_session_process(h2_sessi
 apr_status_t h2_session_pre_close(h2_session *session, int async);
 
 /**
- * Cleanup the session and all objects it still contains. This will not
- * destroy h2_task instances that have not finished yet. 
- * @param session the session to destroy
- */
-void h2_session_eoc_callback(h2_session *session);
-
-/**
  * Called when a serious error occurred and the session needs to terminate
  * without further connection io.
  * @param session the session to abort

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_stream.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_stream.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_stream.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_stream.c Tue Jan 31 09:52:02 2017
@@ -168,27 +168,6 @@ static void prepend_response(h2_stream *
     APR_BRIGADE_INSERT_HEAD(stream->out_buffer, b);
 }
 
-static apr_status_t stream_pool_cleanup(void *ctx)
-{
-    h2_stream *stream = ctx;
-    apr_status_t status;
-    
-    ap_assert(stream->can_be_cleaned);
-    if (stream->files) {
-        apr_file_t *file;
-        int i;
-        for (i = 0; i < stream->files->nelts; ++i) {
-            file = APR_ARRAY_IDX(stream->files, i, apr_file_t*);
-            status = apr_file_close(file);
-            ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, stream->session->c, 
-                          "h2_stream(%ld-%d): destroy, closed file %d", 
-                          stream->session->id, stream->id, i);
-        }
-        stream->files = NULL;
-    }
-    return APR_SUCCESS;
-}
-
 h2_stream *h2_stream_open(int id, apr_pool_t *pool, h2_session *session,
                           int initiated_on)
 {
@@ -200,13 +179,12 @@ h2_stream *h2_stream_open(int id, apr_po
     stream->state        = H2_STREAM_ST_IDLE;
     stream->pool         = pool;
     stream->session      = session;
-
+    
     h2_beam_create(&stream->input, pool, id, "input", H2_BEAM_OWNER_SEND, 0);
+    h2_beam_send_from(stream->input, stream->pool);
     h2_beam_create(&stream->output, pool, id, "output", H2_BEAM_OWNER_RECV, 0);
     
     set_state(stream, H2_STREAM_ST_OPEN);
-    apr_pool_cleanup_register(pool, stream, stream_pool_cleanup, 
-                              apr_pool_cleanup_null);
     ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03082)
                   "h2_stream(%ld-%d): opened", session->id, stream->id);
     return stream;
@@ -238,13 +216,12 @@ void h2_stream_cleanup(h2_stream *stream
 void h2_stream_destroy(h2_stream *stream)
 {
     ap_assert(stream);
-    ap_assert(!h2_mplx_stream_get(stream->session->mplx, stream->id));
     ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, stream->session->c, 
                   "h2_stream(%ld-%d): destroy", 
                   stream->session->id, stream->id);
-    stream->can_be_cleaned = 1;
     if (stream->pool) {
         apr_pool_destroy(stream->pool);
+        stream->pool = NULL;
     }
 }
 
@@ -332,45 +309,50 @@ apr_status_t h2_stream_add_header(h2_str
                                   const char *name, size_t nlen,
                                   const char *value, size_t vlen)
 {
+    int error = 0;
     ap_assert(stream);
     
-    if (!stream->has_response) {
-        if (name[0] == ':') {
-            if ((vlen) > stream->session->s->limit_req_line) {
-                /* pseudo header: approximation of request line size check */
-                ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
-                              "h2_stream(%ld-%d): pseudo header %s too long", 
-                              stream->session->id, stream->id, name);
-                return h2_stream_set_error(stream, 
-                                           HTTP_REQUEST_URI_TOO_LARGE);
-            }
-        }
-        else if ((nlen + 2 + vlen) > stream->session->s->limit_req_fieldsize) {
-            /* header too long */
+    if (stream->has_response) {
+        return APR_EINVAL;    
+    }
+    ++stream->request_headers_added;
+    if (name[0] == ':') {
+        if ((vlen) > stream->session->s->limit_req_line) {
+            /* pseudo header: approximation of request line size check */
             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
-                          "h2_stream(%ld-%d): header %s too long", 
+                          "h2_stream(%ld-%d): pseudo header %s too long", 
                           stream->session->id, stream->id, name);
-            return h2_stream_set_error(stream, 
-                                       HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
+            error = HTTP_REQUEST_URI_TOO_LARGE;
         }
-        
-        if (name[0] != ':') {
-            ++stream->request_headers_added;
-            if (stream->request_headers_added 
-                > stream->session->s->limit_req_fields) {
-                /* too many header lines */
-                ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
-                              "h2_stream(%ld-%d): too many header lines", 
-                              stream->session->id, stream->id);
-                return h2_stream_set_error(stream, 
-                                           HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
-            }
+    }
+    else if ((nlen + 2 + vlen) > stream->session->s->limit_req_fieldsize) {
+        /* header too long */
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
+                      "h2_stream(%ld-%d): header %s too long", 
+                      stream->session->id, stream->id, name);
+        error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
+    }
+    
+    if (stream->request_headers_added 
+        > stream->session->s->limit_req_fields + 4) {
+        /* too many header lines, include 4 pseudo headers */
+        if (stream->request_headers_added 
+            > stream->session->s->limit_req_fields + 4 + 100) {
+            /* yeah, right */
+            return APR_ECONNRESET;
         }
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
+                      "h2_stream(%ld-%d): too many header lines", 
+                      stream->session->id, stream->id);
+        error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
     }
     
     if (h2_stream_is_scheduled(stream)) {
         return add_trailer(stream, name, nlen, value, vlen);
     }
+    else if (error) {
+        return h2_stream_set_error(stream, error); 
+    }
     else {
         if (!stream->rtmp) {
             stream->rtmp = h2_req_create(stream->id, stream->pool, 
@@ -412,6 +394,7 @@ apr_status_t h2_stream_schedule(h2_strea
                 stream->request = stream->rtmp;
                 stream->rtmp = NULL;
                 stream->scheduled = 1;
+
                 stream->push_policy = h2_push_policy_determine(stream->request->headers, 
                                                                stream->pool, push_enabled);
             
@@ -473,6 +456,7 @@ apr_status_t h2_stream_close_input(h2_st
     APR_BRIGADE_INSERT_TAIL(tmp, b);
     status = h2_beam_send(stream->input, tmp, APR_BLOCK_READ);
     apr_brigade_destroy(tmp);
+    h2_beam_close(stream->input);
     return status;
 }
 
@@ -516,8 +500,6 @@ apr_status_t h2_stream_write_data(h2_str
 
 static apr_status_t fill_buffer(h2_stream *stream, apr_size_t amount)
 {
-    conn_rec *c = stream->session->c;
-    apr_bucket *b;
     apr_status_t status;
     
     if (!stream->output) {
@@ -528,33 +510,6 @@ static apr_status_t fill_buffer(h2_strea
     ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, stream->session->c,
                   "h2_stream(%ld-%d): beam_received",
                   stream->session->id, stream->id);
-    /* The buckets we reveive are using the stream->out_buffer pool as
-     * lifetime which is exactly what we want since this is stream->pool.
-     *
-     * However: when we send these buckets down the core output filters, the
-     * filter might decide to setaside them into a pool of its own. And it
-     * might decide, after having sent the buckets, to clear its pool.
-     *
-     * This is problematic for file buckets because it then closed the contained
-     * file. Any split off buckets we sent afterwards will result in a 
-     * APR_EBADF.
-     */
-    for (b = APR_BRIGADE_FIRST(stream->out_buffer);
-         b != APR_BRIGADE_SENTINEL(stream->out_buffer);
-         b = APR_BUCKET_NEXT(b)) {
-        if (APR_BUCKET_IS_FILE(b)) {
-            apr_bucket_file *f = (apr_bucket_file *)b->data;
-            apr_pool_t *fpool = apr_file_pool_get(f->fd);
-            if (fpool != c->pool) {
-                apr_bucket_setaside(b, c->pool);
-                if (!stream->files) {
-                    stream->files = apr_array_make(stream->pool, 
-                                                   5, sizeof(apr_file_t*));
-                }
-                APR_ARRAY_PUSH(stream->files, apr_file_t*) = f->fd;
-            }
-        }
-    }
     return status;
 }
 
@@ -592,10 +547,10 @@ static apr_bucket *get_first_headers_buc
 apr_status_t h2_stream_out_prepare(h2_stream *stream, apr_off_t *plen, 
                                    int *peos, h2_headers **presponse)
 {
-    conn_rec *c = stream->session->c;
     apr_status_t status = APR_SUCCESS;
-    apr_off_t requested;
+    apr_off_t requested, max_chunk = H2_DATA_CHUNK_SIZE;
     apr_bucket *b, *e;
+    conn_rec *c;
 
     if (presponse) {
         *presponse = NULL;
@@ -606,19 +561,17 @@ apr_status_t h2_stream_out_prepare(h2_st
         *peos = 1;
         return APR_ECONNRESET;
     }
-    
-    if (!output_open(stream)) {
+    else if (!output_open(stream)) {
         return APR_ECONNRESET;
     }
+    
+    c = stream->session->c;
     prep_output(stream);
 
-    if (*plen > 0) {
-        requested = H2MIN(*plen, H2_DATA_CHUNK_SIZE);
-    }
-    else {
-        requested = H2_DATA_CHUNK_SIZE;
+    if (stream->session->io.write_size > 0) {
+        max_chunk = stream->session->io.write_size - 9; /* header bits */ 
     }
-    *plen = requested;
+    *plen = requested = (*plen > 0)? H2MIN(*plen, max_chunk) : max_chunk;
     
     H2_STREAM_OUT_LOG(APLOG_TRACE2, stream, "h2_stream_out_prepare_pre");
     h2_util_bb_avail(stream->out_buffer, plen, peos);

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_stream.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_stream.h?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_stream.h (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_stream.h Tue Jan 31 09:52:02 2017
@@ -57,7 +57,6 @@ struct h2_stream {
     struct h2_bucket_beam *input;
     struct h2_bucket_beam *output;
     apr_bucket_brigade *out_buffer;
-    apr_array_header_t *files;  /* apr_file_t* we collected during I/O */
 
     int rst_error;              /* stream error for RST_STREAM */
     unsigned int aborted   : 1; /* was aborted */
@@ -65,7 +64,6 @@ struct h2_stream {
     unsigned int started   : 1; /* stream has started processing */
     unsigned int has_response : 1; /* response headers are known */
     unsigned int push_policy;   /* which push policy to use for this request */
-    unsigned int can_be_cleaned : 1; /* stream pool can be cleaned */
     
     const h2_priority *pref_priority; /* preferred priority for this stream */
     apr_off_t out_data_frames;  /* # of DATA frames sent */

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_task.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_task.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_task.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_task.c Tue Jan 31 09:52:02 2017
@@ -64,6 +64,24 @@ static void H2_TASK_OUT_LOG(int lvl, h2_
     }
 }
 
+static void h2_beam_log(h2_bucket_beam *beam, int id, const char *msg, 
+                        conn_rec *c, int level)
+{
+    if (beam && APLOG_C_IS_LEVEL(c,level)) {
+        char buffer[2048];
+        apr_size_t off = 0;
+        
+        off += apr_snprintf(buffer+off, H2_ALEN(buffer)-off, "cl=%d, ", beam->closed);
+        off += h2_util_bl_print(buffer+off, H2_ALEN(buffer)-off, "red", ", ", &beam->send_list);
+        off += h2_util_bb_print(buffer+off, H2_ALEN(buffer)-off, "green", ", ", beam->recv_buffer);
+        off += h2_util_bl_print(buffer+off, H2_ALEN(buffer)-off, "hold", ", ", &beam->hold_list);
+        off += h2_util_bl_print(buffer+off, H2_ALEN(buffer)-off, "purge", "", &beam->purge_list);
+
+        ap_log_cerror(APLOG_MARK, level, 0, c, "beam(%ld-%d): %s %s", 
+                      c->id, id, msg, buffer);
+    }
+}
+
 /*******************************************************************************
  * task input handling
  ******************************************************************************/
@@ -97,9 +115,12 @@ static apr_status_t send_out(h2_task *ta
 
     apr_brigade_length(bb, 0, &written);
     H2_TASK_OUT_LOG(APLOG_TRACE2, task, bb, "h2_task send_out");
+    h2_beam_log(task->output.beam, task->stream_id, "send_out(before)", task->c, APLOG_TRACE2);
     /* engines send unblocking */
     status = h2_beam_send(task->output.beam, bb, 
                           block? APR_BLOCK_READ : APR_NONBLOCK_READ);
+    h2_beam_log(task->output.beam, task->stream_id, "send_out(after)", task->c, APLOG_TRACE2);
+    
     if (APR_STATUS_IS_EAGAIN(status)) {
         apr_brigade_length(bb, 0, &left);
         written -= left;
@@ -508,9 +529,10 @@ h2_task *h2_task_create(conn_rec *c, int
     task->input.beam  = input;
     task->output.beam = output;
     
+    h2_beam_send_from(output, task->pool);
     apr_thread_cond_create(&task->cond, pool);
-
     h2_ctx_create_for(c, task);
+    
     return task;
 }
 

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_version.h?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_version.h (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/h2_version.h Tue Jan 31 09:52:02 2017
@@ -26,7 +26,7 @@
  * @macro
  * Version number of the http2 module as c string
  */
-#define MOD_HTTP2_VERSION "1.8.0"
+#define MOD_HTTP2_VERSION "1.8.11"
 
 /**
  * @macro
@@ -34,7 +34,7 @@
  * release. This is a 24 bit number with 8 bits for major number, 8 bits
  * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
  */
-#define MOD_HTTP2_VERSION_NUM 0x010800
+#define MOD_HTTP2_VERSION_NUM 0x01080b
 
 
 #endif /* mod_h2_h2_version_h */

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/mod_http2.dsp
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/mod_http2.dsp?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/mod_http2.dsp (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/mod_http2.dsp Tue Jan 31 09:52:02 2017
@@ -109,10 +109,6 @@ SOURCE=./h2_bucket_beam.c
 # End Source File
 # Begin Source File
 
-SOURCE=./h2_bucket_eoc.c
-# End Source File
-# Begin Source File
-
 SOURCE=./h2_bucket_eos.c
 # End Source File
 # Begin Source File

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/mod_proxy_http2.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/mod_proxy_http2.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/mod_proxy_http2.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/http2/mod_proxy_http2.c Tue Jan 31 09:52:02 2017
@@ -335,14 +335,17 @@ static apr_status_t next_request(h2_prox
 
 static apr_status_t proxy_engine_run(h2_proxy_ctx *ctx) {
     apr_status_t status = OK;
+    int h2_front;
     
     /* Step Four: Send the Request in a new HTTP/2 stream and
      * loop until we got the response or encounter errors.
      */
     ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctx->owner, 
                   "eng(%s): setup session", ctx->engine_id);
-    ctx->session = h2_proxy_session_setup(ctx->engine_id, ctx->p_conn, ctx->conf, 
-                                          30, h2_proxy_log2((int)ctx->req_buffer_size), 
+    h2_front = is_h2? is_h2(ctx->owner) : 0;
+    ctx->session = h2_proxy_session_setup(ctx->engine_id, ctx->p_conn, ctx->conf,
+                                          h2_front, 30, 
+                                          h2_proxy_log2((int)ctx->req_buffer_size), 
                                           request_done);
     if (!ctx->session) {
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->owner, 

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/lua/mod_lua.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/lua/mod_lua.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/lua/mod_lua.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/lua/mod_lua.c Tue Jan 31 09:52:02 2017
@@ -87,7 +87,8 @@ apr_global_mutex_t *lua_ivm_mutex;
 apr_shm_t *lua_ivm_shm;
 char *lua_ivm_shmfile;
 
-static apr_status_t shm_cleanup_wrapper(void *unused) {
+static apr_status_t shm_cleanup_wrapper(void *unused)
+{
     if (lua_ivm_shm) {
         return apr_shm_destroy(lua_ivm_shm);
     }
@@ -149,9 +150,11 @@ static const char *scope_to_string(unsig
     }
 }
 
-static void ap_lua_release_state(lua_State* L, ap_lua_vm_spec* spec, request_rec* r) {
+static void ap_lua_release_state(lua_State* L, ap_lua_vm_spec* spec, request_rec* r)
+{
     char *hash;
     apr_reslist_t* reslist = NULL;
+
     if (spec->scope == AP_LUA_SCOPE_SERVER) {
         ap_lua_server_spec* sspec = NULL;
         lua_settop(L, 0);
@@ -332,7 +335,8 @@ static int lua_handler(request_rec *r)
 /* ------------------- Input/output content filters ------------------- */
 
 
-static apr_status_t lua_setup_filter_ctx(ap_filter_t* f, request_rec* r, lua_filter_ctx** c) {
+static apr_status_t lua_setup_filter_ctx(ap_filter_t* f, request_rec* r, lua_filter_ctx** c)
+{
     apr_pool_t *pool;
     ap_lua_vm_spec *spec;
     int n, rc;
@@ -422,7 +426,8 @@ static apr_status_t lua_setup_filter_ctx
     return APR_ENOENT;
 }
 
-static apr_status_t lua_output_filter_handle(ap_filter_t *f, apr_bucket_brigade *pbbIn) {
+static apr_status_t lua_output_filter_handle(ap_filter_t *f, apr_bucket_brigade *pbbIn)
+{
     request_rec *r = f->r;
     int rc;
     lua_State *L;
@@ -591,7 +596,7 @@ static apr_status_t lua_input_filter_han
     /* While the Lua function is still yielding, pass buckets to the coroutine */
     if (!ctx->broken) {
         lastCall = 0;
-        while(!APR_BRIGADE_EMPTY(ctx->tmpBucket)) {
+        while (!APR_BRIGADE_EMPTY(ctx->tmpBucket)) {
             apr_bucket *pbktIn = APR_BRIGADE_FIRST(ctx->tmpBucket);
             apr_bucket *pbktOut;
             const char *data;
@@ -1956,6 +1961,7 @@ static void *create_dir_config(apr_pool_
     cfg->codecache = AP_LUA_CACHE_UNSET;
     cfg->vm_min = 0;
     cfg->vm_max = 0;
+    cfg->inherit = AP_LUA_INHERIT_UNSET;
 
     return cfg;
 }

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/mappers/mod_rewrite.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/mappers/mod_rewrite.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/mappers/mod_rewrite.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/mappers/mod_rewrite.c Tue Jan 31 09:52:02 2017
@@ -4295,6 +4295,17 @@ static int apply_rewrite_list(request_re
         rc = apply_rewrite_rule(p, ctx);
 
         if (rc) {
+
+            /* Catch looping rules with pathinfo growing unbounded */
+            if ( strlen( r->filename ) > 2*r->server->limit_req_line ) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "RewriteRule '%s' and URI '%s' "
+                              "exceeded maximum length (%d)", 
+                              p->pattern, r->uri, 2*r->server->limit_req_line );
+                r->status = HTTP_INTERNAL_SERVER_ERROR;
+                return ACTION_STATUS;
+            }
+
             /* Regardless of what we do next, we've found a match. Check to see
              * if any of the request header fields were involved, and add them
              * to the Vary field of the response.

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/mod_proxy.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/mod_proxy.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/mod_proxy.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/mod_proxy.c Tue Jan 31 09:52:02 2017
@@ -771,18 +771,29 @@ static int proxy_trans(request_rec *r)
      */
 
     dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
-
+    conf = (proxy_server_conf *) ap_get_module_config(r->server->module_config,
+                                                      &proxy_module);
     /* short way - this location is reverse proxied? */
     if (dconf->alias) {
         int rv = ap_proxy_trans_match(r, dconf->alias, dconf);
+        if (OK == rv) { 
+            /* Got a hit. Need to make sure it's not explicitly declined */
+            if (conf->aliases->nelts) {
+                ent = (struct proxy_alias *) conf->aliases->elts;
+                for (i = 0; i < conf->aliases->nelts; i++) {
+                    int rv = ap_proxy_trans_match(r, &ent[i], dconf);
+                    if (DECLINED == rv) { 
+                        return DECLINED;
+                    }
+                }
+            }
+            return OK; 
+        }
         if (DONE != rv) {
             return rv;
         }
     }
 
-    conf = (proxy_server_conf *) ap_get_module_config(r->server->module_config,
-                                                      &proxy_module);
-
     /* long way - walk the list of aliases, find a match */
     if (conf->aliases->nelts) {
         ent = (struct proxy_alias *) conf->aliases->elts;

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/mod_proxy_express.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/mod_proxy_express.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/mod_proxy_express.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/mod_proxy_express.c Tue Jan 31 09:52:02 2017
@@ -108,7 +108,7 @@ static int xlate_name(request_rec *r)
 {
     int i;
     const char *name;
-    char *backend;
+    char *backend = NULL;
     apr_dbm_t *db;
     apr_status_t rv;
     apr_datum_t key, val;

Modified: httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/proxy_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/proxy_util.c?rev=1781045&r1=1781044&r2=1781045&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/proxy_util.c (original)
+++ httpd/httpd/branches/2.4.x-openssl-1.1.0-compat/modules/proxy/proxy_util.c Tue Jan 31 09:52:02 2017
@@ -2693,10 +2693,13 @@ PROXY_DECLARE(apr_status_t) ap_proxy_che
     }
 
     if (rv == APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, server,
-                     "%s: reusing backend connection %pI<>%pI",
-                     scheme, conn->connection->local_addr,
-                     conn->connection->client_addr);
+        if (APLOGtrace2(server)) {
+            apr_sockaddr_t *local_addr = NULL;
+            apr_socket_addr_get(&local_addr, APR_LOCAL, conn->sock);
+            ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, server,
+                         "%s: reusing backend connection %pI<>%pI",
+                         scheme, local_addr, conn->addr);
+        }
     }
     else if (conn->sock) {
         /* This clears conn->scpool (and associated data), so backup and



Mime
View raw message