httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ic...@apache.org
Subject svn commit: r1729209 [1/2] - in /httpd/httpd/trunk: ./ modules/http2/
Date Mon, 08 Feb 2016 16:53:46 GMT
Author: icing
Date: Mon Feb  8 16:53:45 2016
New Revision: 1729209

URL: http://svn.apache.org/viewvc?rev=1729209&view=rev
Log:
new experimental http2 proxy module for h2: and h2c: proxy urls

Added:
    httpd/httpd/trunk/modules/http2/h2.h
    httpd/httpd/trunk/modules/http2/h2_proxy_session.c
    httpd/httpd/trunk/modules/http2/h2_proxy_session.h
    httpd/httpd/trunk/modules/http2/mod_proxy_http2.c
    httpd/httpd/trunk/modules/http2/mod_proxy_http2.h
Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/modules/http2/config.m4
    httpd/httpd/trunk/modules/http2/h2_config.c
    httpd/httpd/trunk/modules/http2/h2_conn.c
    httpd/httpd/trunk/modules/http2/h2_filter.c
    httpd/httpd/trunk/modules/http2/h2_h2.c
    httpd/httpd/trunk/modules/http2/h2_h2.h
    httpd/httpd/trunk/modules/http2/h2_io.h
    httpd/httpd/trunk/modules/http2/h2_mplx.c
    httpd/httpd/trunk/modules/http2/h2_mplx.h
    httpd/httpd/trunk/modules/http2/h2_private.h
    httpd/httpd/trunk/modules/http2/h2_push.c
    httpd/httpd/trunk/modules/http2/h2_push.h
    httpd/httpd/trunk/modules/http2/h2_request.c
    httpd/httpd/trunk/modules/http2/h2_request.h
    httpd/httpd/trunk/modules/http2/h2_response.h
    httpd/httpd/trunk/modules/http2/h2_session.c
    httpd/httpd/trunk/modules/http2/h2_session.h
    httpd/httpd/trunk/modules/http2/h2_stream.c
    httpd/httpd/trunk/modules/http2/h2_stream.h
    httpd/httpd/trunk/modules/http2/h2_task.c
    httpd/httpd/trunk/modules/http2/h2_util.c
    httpd/httpd/trunk/modules/http2/h2_util.h
    httpd/httpd/trunk/modules/http2/mod_http2.c
    httpd/httpd/trunk/modules/http2/mod_http2.h

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Mon Feb  8 16:53:45 2016
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) mod_proxy_http2: new experimental http2 proxy module for h2: and h2c: proxy
+     urls. Uses, so far, one connection per request, reuses connections.
+  
   *) event: use pre_connection hook to properly initialize connection state for
      slave connections. use protocol_switch hook to initialize server config
      early based on SNI selected vhost. 

Modified: httpd/httpd/trunk/modules/http2/config.m4
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/config.m4?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/config.m4 (original)
+++ httpd/httpd/trunk/modules/http2/config.m4 Mon Feb  8 16:53:45 2016
@@ -201,6 +201,32 @@ is usually linked shared and requires lo
 # Ensure that other modules can pick up mod_http2.h
 APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current])
 
+
+
+dnl #  list of module object files
+proxy_http2_objs="dnl
+mod_proxy_http2.lo dnl
+h2_proxy_session.lo dnl
+h2_request.lo dnl
+h2_util.lo dnl
+"
+
+dnl # hook module into the Autoconf mechanism (--enable-proxy_http2)
+APACHE_MODULE(proxy_http2, [HTTP/2 proxy module. This module requires a libnghttp2 installation. 
+See --with-nghttp2 on how to manage non-standard locations. ], $proxy_http2_objs, , no, [
+    APACHE_CHECK_NGHTTP2
+    if test "$ac_cv_nghttp2" = "yes" ; then
+        if test "x$enable_http2" = "xshared"; then
+           # The only symbol which needs to be exported is the module
+           # structure, so ask libtool to hide everything else:
+           APR_ADDTO(MOD_PROXY_HTTP2_LDADD, [-export-symbols-regex proxy_http2_module])
+        fi
+    else
+        enable_proxy_http2=no
+    fi
+])
+
+
 dnl #  end of module specific part
 APACHE_MODPATH_FINISH
 

Added: httpd/httpd/trunk/modules/http2/h2.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2.h?rev=1729209&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2.h (added)
+++ httpd/httpd/trunk/modules/http2/h2.h Mon Feb  8 16:53:45 2016
@@ -0,0 +1,142 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __mod_h2__h2__
+#define __mod_h2__h2__
+
+/**
+ * The magic PRIamble of RFC 7540 that is always sent when starting
+ * a h2 communication.
+ */
+extern const char *H2_MAGIC_TOKEN;
+
+#define H2_ERR_NO_ERROR             (0x00)
+#define H2_ERR_PROTOCOL_ERROR       (0x01)
+#define H2_ERR_INTERNAL_ERROR       (0x02)
+#define H2_ERR_FLOW_CONTROL_ERROR   (0x03)
+#define H2_ERR_SETTINGS_TIMEOUT     (0x04)
+#define H2_ERR_STREAM_CLOSED        (0x05)
+#define H2_ERR_FRAME_SIZE_ERROR     (0x06)
+#define H2_ERR_REFUSED_STREAM       (0x07)
+#define H2_ERR_CANCEL               (0x08)
+#define H2_ERR_COMPRESSION_ERROR    (0x09)
+#define H2_ERR_CONNECT_ERROR        (0x0a)
+#define H2_ERR_ENHANCE_YOUR_CALM    (0x0b)
+#define H2_ERR_INADEQUATE_SECURITY  (0x0c)
+#define H2_ERR_HTTP_1_1_REQUIRED    (0x0d)
+
+#define H2_HEADER_METHOD     ":method"
+#define H2_HEADER_METHOD_LEN 7
+#define H2_HEADER_SCHEME     ":scheme"
+#define H2_HEADER_SCHEME_LEN 7
+#define H2_HEADER_AUTH       ":authority"
+#define H2_HEADER_AUTH_LEN   10
+#define H2_HEADER_PATH       ":path"
+#define H2_HEADER_PATH_LEN   5
+#define H2_CRLF             "\r\n"
+
+/* Maximum number of padding bytes in a frame, rfc7540 */
+#define H2_MAX_PADLEN               256
+/* Initial default window size, RFC 7540 ch. 6.5.2 */
+#define H2_INITIAL_WINDOW_SIZE      ((64*1024)-1)
+
+#define H2_HTTP_2XX(a)      ((a) >= 200 && (a) < 300)
+
+#define H2_STREAM_CLIENT_INITIATED(id)      (id&0x01)
+
+#define H2_ALEN(a)          (sizeof(a)/sizeof((a)[0]))
+
+#define H2MAX(x,y) ((x) > (y) ? (x) : (y))
+#define H2MIN(x,y) ((x) < (y) ? (x) : (y))
+
+typedef enum {
+    H2_DEPENDANT_AFTER,
+    H2_DEPENDANT_INTERLEAVED,
+    H2_DEPENDANT_BEFORE,
+} h2_dependency;
+
+typedef struct h2_priority {
+    h2_dependency dependency;
+    int           weight;
+} h2_priority;
+
+typedef enum {
+    H2_PUSH_NONE,
+    H2_PUSH_DEFAULT,
+    H2_PUSH_HEAD,
+    H2_PUSH_FAST_LOAD,
+} h2_push_policy;
+
+typedef enum {
+    H2_STREAM_ST_IDLE,
+    H2_STREAM_ST_OPEN,
+    H2_STREAM_ST_RESV_LOCAL,
+    H2_STREAM_ST_RESV_REMOTE,
+    H2_STREAM_ST_CLOSED_INPUT,
+    H2_STREAM_ST_CLOSED_OUTPUT,
+    H2_STREAM_ST_CLOSED,
+} h2_stream_state_t;
+
+typedef enum {
+    H2_SESSION_ST_INIT,             /* send initial SETTINGS, etc. */
+    H2_SESSION_ST_DONE,             /* finished, connection close */
+    H2_SESSION_ST_IDLE,             /* nothing to write, expecting data inc */
+    H2_SESSION_ST_BUSY,             /* read/write without stop */
+    H2_SESSION_ST_WAIT,             /* waiting for tasks reporting back */
+    H2_SESSION_ST_LOCAL_SHUTDOWN,   /* we announced GOAWAY */
+    H2_SESSION_ST_REMOTE_SHUTDOWN,  /* client announced GOAWAY */
+} h2_session_state;
+
+/* h2_request is the transformer of HTTP2 streams into HTTP/1.1 internal
+ * format that will be fed to various httpd input filters to finally
+ * become a request_rec to be handled by soemone.
+ */
+typedef struct h2_request h2_request;
+
+struct h2_request {
+    int id;             /* stream id */
+
+    const char *method; /* pseudo header values, see ch. 8.1.2.3 */
+    const char *scheme;
+    const char *authority;
+    const char *path;
+    
+    apr_table_t *headers;
+    apr_table_t *trailers;
+
+    apr_time_t request_time;
+    apr_off_t content_length;
+    
+    unsigned int chunked : 1; /* iff requst body needs to be forwarded as chunked */
+    unsigned int eoh     : 1; /* iff end-of-headers has been seen and request is complete */
+    unsigned int body    : 1; /* iff this request has a body */
+    unsigned int serialize : 1; /* iff this request is written in HTTP/1.1 serialization */
+    unsigned int push_policy; /* which push policy to use for this request */
+};
+
+typedef struct h2_response h2_response;
+
+struct h2_response {
+    int         stream_id;
+    int         rst_error;
+    int         http_status;
+    apr_off_t   content_length;
+    apr_table_t *headers;
+    apr_table_t *trailers;
+    const char  *sos_filter;
+};
+
+
+#endif /* defined(__mod_h2__h2__) */

Modified: httpd/httpd/trunk/modules/http2/h2_config.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_config.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_config.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_config.c Mon Feb  8 16:53:45 2016
@@ -28,6 +28,7 @@
 
 #include <apr_strings.h>
 
+#include "h2.h"
 #include "h2_alt_svc.h"
 #include "h2_ctx.h"
 #include "h2_conn.h"

Modified: httpd/httpd/trunk/modules/http2/h2_conn.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_conn.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_conn.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_conn.c Mon Feb  8 16:53:45 2016
@@ -134,6 +134,8 @@ apr_status_t h2_conn_child_init(apr_pool
     ap_register_input_filter("H2_IN", h2_filter_core_input,
                              NULL, AP_FTYPE_CONNECTION);
    
+    status = h2_mplx_child_init(pool, s);
+    
     return status;
 }
 

Modified: httpd/httpd/trunk/modules/http2/h2_filter.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_filter.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_filter.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_filter.c Mon Feb  8 16:53:45 2016
@@ -51,7 +51,7 @@ static apr_status_t consume_brigade(h2_f
         
         apr_bucket* bucket = APR_BRIGADE_FIRST(bb);
         if (APR_BUCKET_IS_METADATA(bucket)) {
-            /* we do nothing regardih2_filter_cin_timeout_setng any meta here */
+            /* we do nothing regarding any meta here */
         }
         else {
             const char *bucket_data = NULL;

Modified: httpd/httpd/trunk/modules/http2/h2_h2.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_h2.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_h2.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_h2.c Mon Feb  8 16:53:45 2016
@@ -27,6 +27,8 @@
 #include <http_request.h>
 #include <http_log.h>
 
+#include "mod_ssl.h"
+
 #include "mod_http2.h"
 #include "h2_private.h"
 
@@ -54,18 +56,8 @@ const char *H2_MAGIC_TOKEN = "PRI * HTTP
 /*******************************************************************************
  * The optional mod_ssl functions we need. 
  */
-APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec*));
-APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec*));
-
 static int (*opt_ssl_engine_disable)(conn_rec*);
 static int (*opt_ssl_is_https)(conn_rec*);
-/*******************************************************************************
- * SSL var lookup
- */
-APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup,
-                        (apr_pool_t *, server_rec *,
-                         conn_rec *, request_rec *,
-                         char *));
 static char *(*opt_ssl_var_lookup)(apr_pool_t *, server_rec *,
                                    conn_rec *, request_rec *,
                                    char *);

Modified: httpd/httpd/trunk/modules/http2/h2_h2.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_h2.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_h2.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_h2.h Mon Feb  8 16:53:45 2016
@@ -29,47 +29,6 @@ extern const char *h2_clear_protos[];
 extern const char *h2_tls_protos[];
 
 /**
- * The magic PRIamble of RFC 7540 that is always sent when starting
- * a h2 communication.
- */
-extern const char *H2_MAGIC_TOKEN;
-
-#define H2_ERR_NO_ERROR             (0x00)
-#define H2_ERR_PROTOCOL_ERROR       (0x01)
-#define H2_ERR_INTERNAL_ERROR       (0x02)
-#define H2_ERR_FLOW_CONTROL_ERROR   (0x03)
-#define H2_ERR_SETTINGS_TIMEOUT     (0x04)
-#define H2_ERR_STREAM_CLOSED        (0x05)
-#define H2_ERR_FRAME_SIZE_ERROR     (0x06)
-#define H2_ERR_REFUSED_STREAM       (0x07)
-#define H2_ERR_CANCEL               (0x08)
-#define H2_ERR_COMPRESSION_ERROR    (0x09)
-#define H2_ERR_CONNECT_ERROR        (0x0a)
-#define H2_ERR_ENHANCE_YOUR_CALM    (0x0b)
-#define H2_ERR_INADEQUATE_SECURITY  (0x0c)
-#define H2_ERR_HTTP_1_1_REQUIRED    (0x0d)
-
-/* Maximum number of padding bytes in a frame, rfc7540 */
-#define H2_MAX_PADLEN               256
-/* Initial default window size, RFC 7540 ch. 6.5.2 */
-#define H2_INITIAL_WINDOW_SIZE      ((64*1024)-1)
-
-#define H2_HTTP_2XX(a)      ((a) >= 200 && (a) < 300)
-
-#define H2_STREAM_CLIENT_INITIATED(id)      (id&0x01)
-
-typedef enum {
-    H2_DEPENDANT_AFTER,
-    H2_DEPENDANT_INTERLEAVED,
-    H2_DEPENDANT_BEFORE,
-} h2_dependency;
-
-typedef struct h2_priority {
-    h2_dependency dependency;
-    int           weight;
-} h2_priority;
-
-/**
  * Provide a user readable description of the HTTP/2 error code-
  * @param h2_error http/2 error code, as in rfc 7540, ch. 7
  * @return textual description of code or that it is unknown.

Modified: httpd/httpd/trunk/modules/http2/h2_io.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_io.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_io.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_io.h Mon Feb  8 16:53:45 2016
@@ -30,8 +30,7 @@ typedef enum {
     H2_IO_READ,
     H2_IO_WRITE,
     H2_IO_ANY,
-}
-h2_io_op;
+} h2_io_op;
 
 typedef struct h2_io h2_io;
 

Modified: httpd/httpd/trunk/modules/http2/h2_mplx.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_mplx.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_mplx.c Mon Feb  8 16:53:45 2016
@@ -60,6 +60,48 @@
     } while(0)
 
 
+/* NULL or the mutex hold by this thread, used for recursive calls
+ */
+static apr_threadkey_t *thread_lock;
+
+apr_status_t h2_mplx_child_init(apr_pool_t *pool, server_rec *s)
+{
+    return apr_threadkey_private_create(&thread_lock, NULL, pool);
+}
+
+static apr_status_t enter_mutex(h2_mplx *m, int *pacquired)
+{
+    apr_status_t status;
+    void *mutex = NULL;
+    
+    /* Enter the mutex if this thread already holds the lock or
+     * if we can acquire it. Only on the later case do we unlock
+     * onleaving the mutex.
+     * This allow recursive entering of the mutex from the saem thread,
+     * which is what we need in certain situations involving callbacks
+     */
+    apr_threadkey_private_get(&mutex, thread_lock);
+    if (mutex == m->lock) {
+        *pacquired = 0;
+        return APR_SUCCESS;
+    }
+        
+    status = apr_thread_mutex_lock(m->lock);
+    *pacquired = (status == APR_SUCCESS);
+    if (*pacquired) {
+        apr_threadkey_private_set(m->lock, thread_lock);
+    }
+    return status;
+}
+
+static void leave_mutex(h2_mplx *m, int acquired)
+{
+    if (acquired) {
+        apr_threadkey_private_set(NULL, thread_lock);
+        apr_thread_mutex_unlock(m->lock);
+    }
+}
+
 static int is_aborted(h2_mplx *m, apr_status_t *pstatus)
 {
     AP_DEBUG_ASSERT(m);
@@ -177,10 +219,11 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr
 int h2_mplx_get_max_stream_started(h2_mplx *m)
 {
     int stream_id = 0;
+    int acquired;
     
-    apr_thread_mutex_lock(m->lock);
+    enter_mutex(m, &acquired);
     stream_id = m->max_stream_started;
-    apr_thread_mutex_unlock(m->lock);
+    leave_mutex(m, acquired);
     
     return stream_id;
 }
@@ -269,10 +312,10 @@ static int stream_done_iter(void *ctx, h
 apr_status_t h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
 {
     apr_status_t status;
-    
+    int acquired;
+
     h2_workers_unregister(m->workers, m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         int i, wait_secs = 5;
         
         /* disable WINDOW_UPDATE callbacks */
@@ -309,7 +352,7 @@ apr_status_t h2_mplx_release_and_join(h2
         }
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c, APLOGNO(03056)
                       "h2_mplx(%ld): release_join -> destroy", m->id);
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
         h2_mplx_destroy(m);
         /* all gone */
     }
@@ -319,24 +362,28 @@ apr_status_t h2_mplx_release_and_join(h2
 void h2_mplx_abort(h2_mplx *m)
 {
     apr_status_t status;
+    int acquired;
     
     AP_DEBUG_ASSERT(m);
     if (!m->aborted) {
-        status = apr_thread_mutex_lock(m->lock);
-        if (APR_SUCCESS == status) {
+        if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
             m->aborted = 1;
-            apr_thread_mutex_unlock(m->lock);
+            leave_mutex(m, acquired);
         }
     }
 }
 
 apr_status_t h2_mplx_stream_done(h2_mplx *m, int stream_id, int rst_error)
 {
-    apr_status_t status;
+    apr_status_t status = APR_SUCCESS;
+    int acquired;
     
+    /* This maybe called from inside callbacks that already hold the lock.
+     * E.g. when we are streaming out DATA and the EOF triggers the stream
+     * release.
+     */
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
 
         /* there should be an h2_io, once the stream has been scheduled
@@ -345,8 +392,8 @@ apr_status_t h2_mplx_stream_done(h2_mplx
         if (io) {
             io_stream_done(m, io, rst_error);
         }
-        
-        apr_thread_mutex_unlock(m->lock);
+
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -371,9 +418,9 @@ static const h2_request *pop_request(h2_
 void h2_mplx_request_done(h2_mplx **pm, int stream_id, const h2_request **preq)
 {
     h2_mplx *m = *pm;
+    int acquired;
     
-    apr_status_t status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if (enter_mutex(m, &acquired) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
                       "h2_mplx(%ld): request(%d) done", m->id, stream_id);
@@ -399,7 +446,7 @@ void h2_mplx_request_done(h2_mplx **pm,
              * and decrement count */
             *pm = NULL;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
 }
 
@@ -409,9 +456,10 @@ apr_status_t h2_mplx_in_read(h2_mplx *m,
                              struct apr_thread_cond_t *iowait)
 {
     apr_status_t status; 
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_read_pre");
@@ -435,7 +483,7 @@ apr_status_t h2_mplx_in_read(h2_mplx *m,
         else {
             status = APR_EOF;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -444,9 +492,10 @@ apr_status_t h2_mplx_in_write(h2_mplx *m
                               apr_bucket_brigade *bb)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_write_pre");
@@ -458,7 +507,7 @@ apr_status_t h2_mplx_in_write(h2_mplx *m
         else {
             status = APR_ECONNABORTED;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -466,9 +515,10 @@ apr_status_t h2_mplx_in_write(h2_mplx *m
 apr_status_t h2_mplx_in_close(h2_mplx *m, int stream_id)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             status = h2_io_in_close(io);
@@ -479,7 +529,7 @@ apr_status_t h2_mplx_in_close(h2_mplx *m
         else {
             status = APR_ECONNABORTED;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -507,12 +557,13 @@ void h2_mplx_set_consumed_cb(h2_mplx *m,
 apr_status_t h2_mplx_in_update_windows(h2_mplx *m)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
     if (m->aborted) {
         return APR_ECONNABORTED;
     }
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         update_ctx ctx;
         
         ctx.m               = m;
@@ -524,7 +575,7 @@ apr_status_t h2_mplx_in_update_windows(h
         if (ctx.streams_updated) {
             status = APR_SUCCESS;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -535,9 +586,10 @@ apr_status_t h2_mplx_out_readx(h2_mplx *
                                apr_table_t **ptrailers)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_out_readx_pre");
@@ -553,7 +605,7 @@ apr_status_t h2_mplx_out_readx(h2_mplx *
         }
         
         *ptrailers = (*peos && io->response)? io->response->trailers : NULL;
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -564,9 +616,10 @@ apr_status_t h2_mplx_out_read_to(h2_mplx
                                  apr_table_t **ptrailers)
 {
     apr_status_t status;
+    int acquired;
+
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_out_read_to_pre");
@@ -582,7 +635,7 @@ apr_status_t h2_mplx_out_read_to(h2_mplx
             status = APR_ECONNABORTED;
         }
         *ptrailers = (*peos && io->response)? io->response->trailers : NULL;
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -591,10 +644,10 @@ h2_stream *h2_mplx_next_submit(h2_mplx *
 {
     apr_status_t status;
     h2_stream *stream = NULL;
+    int acquired;
 
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_pop_highest_prio(m->ready_ios);
         if (io && !m->aborted) {
             stream = h2_stream_set_get(streams, io->id);
@@ -633,7 +686,7 @@ h2_stream *h2_mplx_next_submit(h2_mplx *
             
             h2_io_signal(io, H2_IO_WRITE);
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return stream;
 }
@@ -716,9 +769,10 @@ apr_status_t h2_mplx_out_open(h2_mplx *m
                               struct apr_thread_cond_t *iowait)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         if (m->aborted) {
             status = APR_ECONNABORTED;
         }
@@ -728,7 +782,7 @@ apr_status_t h2_mplx_out_open(h2_mplx *m
                 h2_util_bb_log(m->c, stream_id, APLOG_TRACE1, "h2_mplx_out_open", bb);
             }
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -739,9 +793,10 @@ apr_status_t h2_mplx_out_write(h2_mplx *
                                struct apr_thread_cond_t *iowait)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             status = out_write(m, io, f, bb, trailers, iowait);
@@ -755,7 +810,7 @@ apr_status_t h2_mplx_out_write(h2_mplx *
         else {
             status = APR_ECONNABORTED;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -763,9 +818,10 @@ apr_status_t h2_mplx_out_write(h2_mplx *
 apr_status_t h2_mplx_out_close(h2_mplx *m, int stream_id, apr_table_t *trailers)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             if (!io->response && !io->rst_error) {
@@ -791,7 +847,7 @@ apr_status_t h2_mplx_out_close(h2_mplx *
         else {
             status = APR_ECONNABORTED;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -799,9 +855,10 @@ apr_status_t h2_mplx_out_close(h2_mplx *
 apr_status_t h2_mplx_out_rst(h2_mplx *m, int stream_id, int error)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->rst_error && !io->orphaned) {
             h2_io_rst(io, error);
@@ -816,7 +873,7 @@ apr_status_t h2_mplx_out_rst(h2_mplx *m,
         else {
             status = APR_ECONNABORTED;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -824,10 +881,11 @@ apr_status_t h2_mplx_out_rst(h2_mplx *m,
 int h2_mplx_in_has_eos_for(h2_mplx *m, int stream_id)
 {
     int has_eos = 0;
+    int acquired;
+    
     apr_status_t status;
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             has_eos = h2_io_in_has_eos_for(io);
@@ -835,7 +893,7 @@ int h2_mplx_in_has_eos_for(h2_mplx *m, i
         else {
             has_eos = 1;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return has_eos;
 }
@@ -844,9 +902,10 @@ int h2_mplx_out_has_data_for(h2_mplx *m,
 {
     apr_status_t status;
     int has_data = 0;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
         if (io && !io->orphaned) {
             has_data = h2_io_out_has_data(io);
@@ -854,7 +913,7 @@ int h2_mplx_out_has_data_for(h2_mplx *m,
         else {
             has_data = 0;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return has_data;
 }
@@ -863,9 +922,10 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
                                  apr_thread_cond_t *iowait)
 {
     apr_status_t status;
+    int acquired;
+    
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         if (m->aborted) {
             status = APR_ECONNABORTED;
         }
@@ -879,7 +939,7 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
             }
             m->added_output = NULL;
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -896,10 +956,10 @@ static void have_out_data_for(h2_mplx *m
 apr_status_t h2_mplx_reprioritize(h2_mplx *m, h2_stream_pri_cmp *cmp, void *ctx)
 {
     apr_status_t status;
+    int acquired;
     
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         if (m->aborted) {
             status = APR_ECONNABORTED;
         }
@@ -909,7 +969,7 @@ apr_status_t h2_mplx_reprioritize(h2_mpl
             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
                           "h2_mplx(%ld): reprioritize tasks", m->id);
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return status;
 }
@@ -938,10 +998,10 @@ apr_status_t h2_mplx_process(h2_mplx *m,
 {
     apr_status_t status;
     int was_empty = 0;
+    int acquired;
     
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         if (m->aborted) {
             status = APR_ECONNABORTED;
         }
@@ -960,7 +1020,7 @@ apr_status_t h2_mplx_process(h2_mplx *m,
                           "h2_mplx(%ld-%d): process", m->c->id, stream_id);
             H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_process");
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     if (status == APR_SUCCESS && was_empty) {
         workers_register(m);
@@ -972,10 +1032,10 @@ const h2_request *h2_mplx_pop_request(h2
 {
     const h2_request *req = NULL;
     apr_status_t status;
+    int acquired;
     
     AP_DEBUG_ASSERT(m);
-    status = apr_thread_mutex_lock(m->lock);
-    if (APR_SUCCESS == status) {
+    if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
         if (m->aborted) {
             req = NULL;
             *has_more = 0;
@@ -984,7 +1044,7 @@ const h2_request *h2_mplx_pop_request(h2
             req = pop_request(m);
             *has_more = !h2_tq_empty(m->q);
         }
-        apr_thread_mutex_unlock(m->lock);
+        leave_mutex(m, acquired);
     }
     return req;
 }

Modified: httpd/httpd/trunk/modules/http2/h2_mplx.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_mplx.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_mplx.h Mon Feb  8 16:53:45 2016
@@ -95,6 +95,8 @@ struct h2_mplx {
  * Object lifecycle and information.
  ******************************************************************************/
 
+apr_status_t h2_mplx_child_init(apr_pool_t *pool, server_rec *s);
+
 /**
  * Create the multiplexer for the given HTTP2 session. 
  * Implicitly has reference count 1.

Modified: httpd/httpd/trunk/modules/http2/h2_private.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_private.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_private.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_private.h Mon Feb  8 16:53:45 2016
@@ -25,19 +25,4 @@ extern module AP_MODULE_DECLARE_DATA htt
 APLOG_USE_MODULE(http2);
 
 
-#define H2_HEADER_METHOD     ":method"
-#define H2_HEADER_METHOD_LEN 7
-#define H2_HEADER_SCHEME     ":scheme"
-#define H2_HEADER_SCHEME_LEN 7
-#define H2_HEADER_AUTH       ":authority"
-#define H2_HEADER_AUTH_LEN   10
-#define H2_HEADER_PATH       ":path"
-#define H2_HEADER_PATH_LEN   5
-#define H2_CRLF             "\r\n"
-
-#define H2_ALEN(a)          (sizeof(a)/sizeof((a)[0]))
-
-#define H2MAX(x,y) ((x) > (y) ? (x) : (y))
-#define H2MIN(x,y) ((x) < (y) ? (x) : (y))
-
 #endif

Added: httpd/httpd/trunk/modules/http2/h2_proxy_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_proxy_session.c?rev=1729209&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_proxy_session.c (added)
+++ httpd/httpd/trunk/modules/http2/h2_proxy_session.c Mon Feb  8 16:53:45 2016
@@ -0,0 +1,639 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <apr_strings.h>
+#include <nghttp2/nghttp2.h>
+
+#include <httpd.h>
+#include <mod_proxy.h>
+
+#include "h2.h"
+#include "h2_request.h"
+#include "h2_util.h"
+#include "h2_proxy_session.h"
+
+APLOG_USE_MODULE(proxy_http2);
+
+static int ngstatus_from_apr_status(apr_status_t rv)
+{
+    if (rv == APR_SUCCESS) {
+        return NGHTTP2_NO_ERROR;
+    }
+    else if (APR_STATUS_IS_EAGAIN(rv)) {
+        return NGHTTP2_ERR_WOULDBLOCK;
+    }
+    else if (APR_STATUS_IS_EOF(rv)) {
+            return NGHTTP2_ERR_EOF;
+    }
+    return NGHTTP2_ERR_PROTO;
+}
+
+
+static apr_status_t proxy_session_shutdown(void *theconn)
+{
+    proxy_conn_rec *p_conn = (proxy_conn_rec *)theconn;
+    h2_proxy_session *session = p_conn->data;
+
+    if (session && session->ngh2) {
+        if (session->c && !session->c->aborted && !session->goaway_sent) {
+            nghttp2_submit_goaway(session->ngh2, NGHTTP2_FLAG_NONE, 
+                                  session->max_stream_recv, 0, NULL, 0);
+            nghttp2_session_send(session->ngh2);
+        }
+
+        nghttp2_session_del(session->ngh2);
+        session->ngh2 = NULL;
+        p_conn->data = NULL;
+    }
+    return APR_SUCCESS;
+}
+
+static ssize_t raw_send(nghttp2_session *ngh2, const uint8_t *data,
+                        size_t length, int flags, void *user_data)
+{
+    h2_proxy_session *session = user_data;
+    apr_bucket *b;
+    apr_status_t status;
+    int flush = 1;
+
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, 
+                  "h2_proxy_sesssion(%ld): raw_send %d bytes, flush=%d", 
+                  session->c->id, (int)length, flush);
+    b = apr_bucket_transient_create((const char*)data, length, 
+                                    session->c->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(session->output, b);
+
+    status = ap_proxy_pass_brigade(session->c->bucket_alloc, session->r, 
+                                   session->p_conn, session->c, 
+                                   session->output, flush);
+    if (status != APR_SUCCESS) {
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, session->c, 
+                      "h2_proxy_sesssion(%ld): sending", session->c->id);
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
+    }
+    return length;
+}
+
+static int on_frame_recv(nghttp2_session *ngh2, const nghttp2_frame *frame,
+                         void *user_data) 
+{
+    h2_proxy_session *session = user_data;
+    h2_proxy_stream *stream;
+    int eos;
+    
+    if (APLOGcdebug(session->c)) {
+        char buffer[256];
+        
+        h2_util_frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0]));
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO()
+                      "h2_session(%ld): recv FRAME[%s]",
+                      session->c->id, buffer);
+    }
+
+    switch (frame->hd.type) {
+        case NGHTTP2_HEADERS:
+            stream = nghttp2_session_get_stream_user_data(ngh2, frame->hd.stream_id);
+            eos = (frame->hd.flags & NGHTTP2_FLAG_END_STREAM);
+
+            break;
+        case NGHTTP2_PUSH_PROMISE:
+            break;
+        case NGHTTP2_GOAWAY:
+            session->goaway_recvd = 1;
+            /* TODO: close handling */
+            break;
+        default:
+            break;
+    }
+    return 0;
+}
+
+static int before_frame_send(nghttp2_session *ngh2,
+                             const nghttp2_frame *frame, void *user_data)
+{
+    h2_proxy_session *session = user_data;
+    if (APLOGcdebug(session->c)) {
+        char buffer[256];
+        
+        h2_util_frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0]));
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03068)
+                      "h2_session(%ld): sent FRAME[%s]",
+                      session->c->id, buffer);
+    }
+    return 0;
+}
+
+static int add_header(void *table, const char *n, const char *v)
+{
+    apr_table_addn(table, n, v);
+    return 1;
+}
+
+static void process_proxy_header(request_rec *r, const char *n, const char *v)
+{
+    static const struct {
+        const char *name;
+        ap_proxy_header_reverse_map_fn func;
+    } transform_hdrs[] = {
+        { "Location", ap_proxy_location_reverse_map },
+        { "Content-Location", ap_proxy_location_reverse_map },
+        { "URI", ap_proxy_location_reverse_map },
+        { "Destination", ap_proxy_location_reverse_map },
+        { "Set-Cookie", ap_proxy_cookie_reverse_map },
+        { NULL, NULL }
+    };
+    proxy_dir_conf *dconf;
+    int i;
+    
+    for (i = 0; transform_hdrs[i].name; ++i) {
+        if (!ap_casecmpstr(transform_hdrs[i].name, n)) {
+            dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
+            apr_table_add(r->headers_out, n,
+                          (*transform_hdrs[i].func)(r, dconf, v));
+            return;
+       }
+    }
+    apr_table_add(r->headers_out, n, v);
+}
+
+static apr_status_t h2_proxy_stream_add_header_out(h2_proxy_stream *stream,
+                                                   const char *n, apr_size_t nlen,
+                                                   const char *v, apr_size_t vlen)
+{
+    if (n[0] == ':') {
+        if (!stream->data_received && !strncmp(":status", n, nlen)) {
+            char *s = apr_pstrndup(stream->pool, v, vlen);
+            
+            ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, stream->session->c, 
+                          "h2_proxy_stream(%ld-%d): got status %s", 
+                          stream->session->c->id, stream->id, s);
+            stream->r->status = (int)apr_atoi64(s);
+            if (stream->r->status <= 0) {
+                stream->r->status = 500;
+                return APR_EGENERAL;
+            }
+        }
+        return APR_SUCCESS;
+    }
+    
+    if (!h2_proxy_res_ignore_header(n, nlen)) {
+        char *hname, *hvalue;
+    
+        hname = apr_pstrndup(stream->pool, n, nlen);
+        h2_util_camel_case_header(hname, nlen);
+        hvalue = apr_pstrndup(stream->pool, v, vlen);
+        
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, stream->session->c, 
+                      "h2_proxy_stream(%ld-%d): got header %s: %s", 
+                      stream->session->c->id, stream->id, hname, hvalue);
+        process_proxy_header(stream->r, hname, hvalue);
+    }
+    return APR_SUCCESS;
+}
+
+static void h2_proxy_stream_end_headers_out(h2_proxy_stream *stream) 
+{
+    h2_proxy_session *session = stream->session;
+    request_rec *r = stream->r;
+    apr_pool_t *p = r->pool;
+    
+    /* Now, add in the cookies from the response to the ones already saved */
+    apr_table_do(add_header, stream->saves, r->headers_out, "Set-Cookie", NULL);
+    
+    /* and now load 'em all in */
+    if (!apr_is_empty_table(stream->saves)) {
+        apr_table_unset(r->headers_out, "Set-Cookie");
+        r->headers_out = apr_table_overlay(p, r->headers_out, stream->saves);
+    }
+    
+    /* handle Via header in response */
+    if (session->conf->viaopt != via_off 
+        && session->conf->viaopt != via_block) {
+        const char *server_name = ap_get_server_name(stream->r);
+        apr_port_t port = ap_get_server_port(stream->r);
+        char portstr[32];
+        
+        /* 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)
+         * so we use the proxy vhost's name instead.
+         */
+        if (server_name == stream->r->hostname) {
+            server_name = stream->r->server->server_hostname;
+        }
+        if (ap_is_default_port(port, stream->r)) {
+            portstr[0] = '\0';
+        }
+        else {
+            apr_snprintf(portstr, sizeof(portstr), ":%d", port);
+        }
+
+        /* create a "Via:" response header entry and merge it */
+        apr_table_addn(r->headers_out, "Via",
+                       (session->conf->viaopt == via_full)
+                       ? apr_psprintf(p, "%d.%d %s%s (%s)",
+                                      HTTP_VERSION_MAJOR(r->proto_num),
+                                      HTTP_VERSION_MINOR(r->proto_num),
+                                      server_name, portstr,
+                                      AP_SERVER_BASEVERSION)
+                       : apr_psprintf(p, "%d.%d %s%s",
+                                      HTTP_VERSION_MAJOR(r->proto_num),
+                                      HTTP_VERSION_MINOR(r->proto_num),
+                                      server_name, portstr)
+                       );
+    }
+}
+
+static int on_data_chunk_recv(nghttp2_session *ngh2, uint8_t flags,
+                              int32_t stream_id, const uint8_t *data,
+                              size_t len, void *user_data) 
+{
+    h2_proxy_session *session = user_data;
+    h2_proxy_stream *stream;
+    apr_bucket *b;
+    apr_status_t status;
+    
+    nghttp2_session_consume(ngh2, stream_id, len);
+    stream = nghttp2_session_get_stream_user_data(ngh2, stream_id);
+    if (!stream) {
+        return 0;
+    }
+    
+    if (!stream->data_received) {
+        /* last chance to manipulate response headers.
+         * after this, only trailers */
+        h2_proxy_stream_end_headers_out(stream);
+        stream->data_received = 1;
+    }
+    
+    b = apr_bucket_transient_create((const char*)data, len, session->c->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(stream->output, b);
+    status = ap_pass_brigade(stream->r->output_filters, stream->output);
+    if (status != APR_SUCCESS) {
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, session->c, APLOGNO()
+                      "h2_session(%ld-%d): passing output", 
+                      session->c->id, stream->id);
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
+    }
+    return 0;
+}
+
+static int on_stream_close(nghttp2_session *ngh2, int32_t stream_id,
+                           uint32_t error_code, void *user_data) 
+{
+    h2_proxy_session *session = user_data;
+    h2_proxy_stream *stream;
+    
+    stream = nghttp2_session_get_stream_user_data(ngh2, stream_id);
+    if (!stream) {
+        return 0;
+    }
+    
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, 
+                  "h2_proxy_sesssion(%ld): closing stream(%d)", 
+                  session->c->id, stream_id);
+
+    if (!stream->data_received) {
+        /* last chance to manipulate response headers.
+         * after this, only trailers */
+        stream->data_received = 1;
+    }
+    stream->state = H2_STREAM_ST_CLOSED;
+    return 0;
+}
+
+static int on_header(nghttp2_session *ngh2, const nghttp2_frame *frame,
+                     const uint8_t *namearg, size_t nlen,
+                     const uint8_t *valuearg, size_t vlen, uint8_t flags,
+                     void *user_data) 
+{
+    h2_proxy_session *session = user_data;
+    h2_proxy_stream *stream;
+    const char *n = (const char*)namearg;
+    const char *v = (const char*)valuearg;
+    
+    (void)session;
+    if (frame->hd.type == NGHTTP2_HEADERS && nlen) {
+        stream = nghttp2_session_get_stream_user_data(ngh2, frame->hd.stream_id);
+        if (stream) {
+            if (h2_proxy_stream_add_header_out(stream, n, nlen, v, vlen)) {
+                return NGHTTP2_ERR_CALLBACK_FAILURE;
+            }
+        }
+    }
+    else if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+    }
+    
+    return 0;
+}
+
+static ssize_t stream_data_read(nghttp2_session *ngh2, int32_t stream_id, 
+                                uint8_t *buf, size_t length,
+                                uint32_t *data_flags, 
+                                nghttp2_data_source *source, void *user_data)
+{
+    h2_proxy_session *session = user_data;
+    h2_proxy_stream *stream;
+    apr_status_t status = APR_SUCCESS;
+    
+    *data_flags = 0;
+    stream = nghttp2_session_get_stream_user_data(ngh2, stream_id);
+    if (!stream) {
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
+    }
+    
+    if (APR_BRIGADE_EMPTY(stream->input)) {
+        status = ap_get_brigade(stream->r->input_filters, stream->input,
+                                AP_MODE_READBYTES, APR_BLOCK_READ,
+                                H2MIN(APR_BUCKET_BUFF_SIZE, length));
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, session->c, 
+                      "h2_proxy_stream(%ld-%d): request body read", 
+                      session->c->id, stream->id);
+    }
+
+    if (status == APR_SUCCESS) {
+        ssize_t readlen = 0;
+        while (status == APR_SUCCESS 
+               && (readlen < length)
+               && !APR_BRIGADE_EMPTY(stream->input)) {
+            apr_bucket* b = APR_BRIGADE_FIRST(stream->input);
+            if (APR_BUCKET_IS_METADATA(b)) {
+                if (APR_BUCKET_IS_EOS(b)) {
+                    *data_flags |= NGHTTP2_DATA_FLAG_EOF;
+                }
+                else {
+                    /* we do nothing more regarding any meta here */
+                }
+            }
+            else {
+                const char *bdata = NULL;
+                apr_size_t blen = 0;
+                status = apr_bucket_read(b, &bdata, &blen, APR_BLOCK_READ);
+                
+                if (status == APR_SUCCESS && blen > 0) {
+                    ssize_t copylen = H2MIN(length - readlen, blen);
+                    memcpy(buf, bdata, copylen);
+                    buf += copylen;
+                    readlen += copylen;
+                    if (copylen < blen) {
+                        /* We have data left in the bucket. Split it. */
+                        status = apr_bucket_split(b, copylen);
+                    }
+                }
+            }
+            apr_bucket_delete(b);
+        }
+
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, session->c, 
+                      "h2_proxy_stream(%ld-%d): request body read %ld bytes, flags=%d", 
+                      session->c->id, stream->id, (long)readlen, (int)*data_flags);
+        return readlen;
+    }
+    else if (APR_STATUS_IS_EAGAIN(status)) {
+        return NGHTTP2_ERR_DEFERRED;
+    }
+    return ngstatus_from_apr_status(status);
+}
+
+h2_proxy_session *h2_proxy_session_setup(request_rec *r, proxy_conn_rec *p_conn,
+                                         proxy_server_conf *conf)
+{
+    if (!p_conn->data) {
+        h2_proxy_session *session;
+        nghttp2_settings_entry settings[2];
+        nghttp2_session_callbacks *cbs;
+        int add_conn_window;
+        int rv;
+        
+        session = apr_pcalloc(p_conn->scpool, sizeof(*session));
+        apr_pool_pre_cleanup_register(p_conn->scpool, p_conn, proxy_session_shutdown);
+        p_conn->data = session;
+        
+        session->c = p_conn->connection;
+        session->p_conn = p_conn;
+        session->conf = conf;
+        session->r = r;
+        session->pool = p_conn->scpool;
+        session->window_bits_default    = 30;
+        session->window_bits_connection = 30;
+    
+        session->input = apr_brigade_create(session->pool, session->c->bucket_alloc);
+        session->output = apr_brigade_create(session->pool, session->c->bucket_alloc);
+    
+        nghttp2_session_callbacks_new(&cbs);
+        nghttp2_session_callbacks_set_on_frame_recv_callback(cbs, on_frame_recv);
+        nghttp2_session_callbacks_set_on_data_chunk_recv_callback(cbs, on_data_chunk_recv);
+        nghttp2_session_callbacks_set_on_stream_close_callback(cbs, on_stream_close);
+        nghttp2_session_callbacks_set_on_header_callback(cbs, on_header);
+        nghttp2_session_callbacks_set_before_frame_send_callback(cbs, before_frame_send);
+        nghttp2_session_callbacks_set_send_callback(cbs, raw_send);
+        
+        nghttp2_session_client_new(&session->ngh2, cbs, session);
+        nghttp2_session_callbacks_del(cbs);
+
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, 
+                      "setup session for %s", p_conn->hostname);
+        
+        settings[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
+        settings[0].value = 0;
+        settings[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
+        settings[1].value = (1 << session->window_bits_default) - 1;
+        
+        rv = nghttp2_submit_settings(session->ngh2, NGHTTP2_FLAG_NONE, settings, 
+                                     H2_ALEN(settings));
+
+        /* If the connection window is larger than our default, trigger a WINDOW_UPDATE */
+        add_conn_window = ((1 << session->window_bits_connection) - 1 -
+                           NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE);
+        if (!rv && add_conn_window != 0) {
+            rv = nghttp2_submit_window_update(session->ngh2, NGHTTP2_FLAG_NONE, 0, add_conn_window);
+        }
+    }
+    return p_conn->data;
+}
+
+
+apr_status_t h2_proxy_session_open_stream(h2_proxy_session *session, const char *url,
+                                          request_rec *r, h2_proxy_stream **pstream)
+{
+    h2_proxy_stream *stream;
+    apr_uri_t puri;
+    const char *authority, *scheme, *path;
+    
+    stream = apr_pcalloc(r->pool, sizeof(*stream));
+
+    stream->pool = r->pool;
+    stream->url = url;
+    stream->r = r;
+    stream->session = session;
+    stream->state = H2_STREAM_ST_IDLE;
+    
+    stream->input = apr_brigade_create(stream->pool, session->c->bucket_alloc);
+    stream->output = apr_brigade_create(stream->pool, session->c->bucket_alloc);
+    
+    stream->req = h2_request_create(1, stream->pool, 0);
+
+    apr_uri_parse(stream->pool, url, &puri);
+    scheme = (strcmp(puri.scheme, "h2")? "http" : "https");
+    authority = puri.hostname;
+    if (!ap_strchr_c(authority, ':') && puri.port
+        && apr_uri_port_of_scheme(scheme) != puri.port) {
+        /* port info missing and port is not default for scheme: append */
+        authority = apr_psprintf(stream->pool, "%s:%d", authority, puri.port);
+    }
+    path = apr_uri_unparse(stream->pool, &puri, APR_URI_UNP_OMITSITEPART);
+    h2_request_make(stream->req, stream->pool, r->method, scheme,
+                    authority, path, r->headers_in);
+
+    /* Tuck away all already existing cookies */
+    stream->saves = apr_table_make(r->pool, 2);
+    apr_table_do(add_header, stream->saves, r->headers_out,"Set-Cookie", NULL);
+
+    *pstream = stream;
+    
+    return APR_SUCCESS;
+}
+
+static apr_status_t feed_brigade(h2_proxy_session *session, apr_bucket_brigade *bb)
+{
+    apr_status_t status = APR_SUCCESS;
+    apr_size_t readlen = 0;
+    ssize_t n;
+    
+    while (status == APR_SUCCESS && !APR_BRIGADE_EMPTY(bb)) {
+        apr_bucket* b = APR_BRIGADE_FIRST(bb);
+        
+        if (!APR_BUCKET_IS_METADATA(b)) {
+            const char *bdata = NULL;
+            apr_size_t blen = 0;
+            
+            status = apr_bucket_read(b, &bdata, &blen, APR_NONBLOCK_READ);
+            if (status == APR_SUCCESS && blen > 0) {
+                n = nghttp2_session_mem_recv(session->ngh2, (const uint8_t *)bdata, blen);
+                if (n < 0) {
+                    if (nghttp2_is_fatal((int)n)) {
+                        return APR_EGENERAL;
+                    }
+                }
+                else {
+                    readlen += n;
+                    if (n < blen) {
+                        apr_bucket_split(b, n);
+                    }
+                }
+            }
+        }
+        apr_bucket_delete(b);
+    }
+    
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, session->c, 
+                  "h2_session(%ld): fed %ld bytes of input", session->c->id, (long)readlen);
+    if (readlen == 0 && status == APR_SUCCESS) {
+        return APR_EAGAIN;
+    }
+    return status;
+}
+
+
+static apr_status_t stream_loop(h2_proxy_stream *stream) 
+{
+    h2_proxy_session *session = stream->session;
+    apr_status_t status = APR_SUCCESS;
+    int want_read, want_write;
+    
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, session->c, 
+                  "h2_session(%ld): start loop for stream %d", 
+                  session->c->id, stream->id);
+    while ((status == APR_SUCCESS || APR_STATUS_IS_EAGAIN(status))
+           && stream->state != H2_STREAM_ST_CLOSED) {
+           
+        want_read = nghttp2_session_want_read(session->ngh2);
+        want_write = nghttp2_session_want_write(session->ngh2);
+               
+        if (want_write) {
+            int rv = nghttp2_session_send(session->ngh2);
+            if (rv < 0 && nghttp2_is_fatal(rv)) {
+                status = APR_EGENERAL;
+                ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, session->c, 
+                              "h2_session(%ld): write, rv=%d", session->c->id, rv);
+                break;
+            }
+        }
+
+        if (want_read) {
+            status = ap_get_brigade(session->c->input_filters, session->input, 
+                                    AP_MODE_READBYTES, 
+                                    (want_write? APR_NONBLOCK_READ : APR_BLOCK_READ), 
+                                    APR_BUCKET_BUFF_SIZE);
+            if (status == APR_SUCCESS) {
+                status = feed_brigade(session, session->input);
+            }
+            else if (!APR_STATUS_IS_EAGAIN(status)) {
+                ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, session->c, 
+                              "h2_session(%ld): read", session->c->id);
+                break;
+            }
+        }
+        
+        if (!want_read && !want_write) {
+            status = APR_EGENERAL;
+            break;
+        }
+    }
+    
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, session->c, 
+                  "h2_session(%ld): end loop for stream %d", 
+                  session->c->id, stream->id);
+    return status;
+}
+
+apr_status_t h2_proxy_stream_process(h2_proxy_stream *stream)
+{
+    h2_proxy_session *session = stream->session;
+    h2_ngheader *hd;
+    nghttp2_data_provider *pp = NULL;
+    nghttp2_data_provider provider;
+    int rv;
+    apr_status_t status;
+
+    hd = h2_util_ngheader_make_req(stream->pool, stream->req);
+    
+    status = ap_get_brigade(stream->r->input_filters, stream->input,
+                            AP_MODE_READBYTES, APR_NONBLOCK_READ,
+                            APR_BUCKET_BUFF_SIZE);
+    if ((status == APR_SUCCESS && !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(stream->input)))
+        || APR_STATUS_IS_EAGAIN(status)) {
+        /* there might be data coming */
+        provider.source.fd = 0;
+        provider.source.ptr = NULL;
+        provider.read_callback = stream_data_read;
+        pp = &provider;
+    }
+
+    rv = nghttp2_submit_request(session->ngh2, NULL, 
+                                hd->nv, hd->nvlen, pp, stream);
+                                
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c, 
+                  "h2_session(%ld): submit request -> %d", 
+                  session->c->id, rv);
+    if (rv > 0) {
+        stream->id = rv;
+        stream->state = H2_STREAM_ST_OPEN;
+        
+        return stream_loop(stream);
+    }
+    return APR_EGENERAL;
+}
+

Added: httpd/httpd/trunk/modules/http2/h2_proxy_session.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_proxy_session.h?rev=1729209&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_proxy_session.h (added)
+++ httpd/httpd/trunk/modules/http2/h2_proxy_session.h Mon Feb  8 16:53:45 2016
@@ -0,0 +1,69 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef h2_proxy_session_h
+#define h2_proxy_session_h
+
+#define H2_ALEN(a)          (sizeof(a)/sizeof((a)[0]))
+
+#include <nghttp2/nghttp2.h>
+
+typedef struct h2_proxy_session {
+    conn_rec *c;
+    proxy_conn_rec *p_conn;
+    proxy_server_conf *conf;
+    request_rec *r;
+    apr_pool_t *pool;
+    nghttp2_session *ngh2;   /* the nghttp2 session itself */
+    
+    int window_bits_default;
+    int window_bits_connection;
+
+    unsigned int goaway_recvd : 1;
+    unsigned int goaway_sent : 1;
+    
+    int max_stream_recv;
+    
+    apr_bucket_brigade *input;
+    apr_bucket_brigade *output;
+} h2_proxy_session;
+
+typedef struct h2_proxy_stream {
+    int id;
+    apr_pool_t *pool;
+    h2_proxy_session *session;
+
+    const char *url;
+    request_rec *r;
+    h2_request *req;
+
+    h2_stream_state_t state;
+    unsigned int data_received : 1;
+
+    apr_bucket_brigade *input;
+    apr_bucket_brigade *output;
+    
+    apr_table_t *saves;
+} h2_proxy_stream;
+
+
+h2_proxy_session *h2_proxy_session_setup(request_rec *r, proxy_conn_rec *p_connm,
+                                         proxy_server_conf *conf);
+
+apr_status_t h2_proxy_session_open_stream(h2_proxy_session *s, const char *url,
+                                          request_rec *r, h2_proxy_stream **pstream);
+apr_status_t h2_proxy_stream_process(h2_proxy_stream *stream);
+
+#endif /* h2_proxy_session_h */

Modified: httpd/httpd/trunk/modules/http2/h2_push.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_push.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_push.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_push.c Mon Feb  8 16:53:45 2016
@@ -345,10 +345,9 @@ static int add_push(link_ctx *ctx)
                              "Cache-Control",
                              "Accept-Language",
                              NULL);
-                req = h2_request_createn(0, ctx->pool, ctx->req->config, 
-                                         method, ctx->req->scheme,
-                                         ctx->req->authority, 
-                                         path, headers);
+                req = h2_request_createn(0, ctx->pool, method, ctx->req->scheme,
+                                         ctx->req->authority, path, headers,
+                                         ctx->req->serialize);
                 /* atm, we do not push on pushes */
                 h2_request_end_headers(req, ctx->pool, 1, 0);
                 push->req = req;
@@ -456,36 +455,6 @@ apr_array_header_t *h2_push_collect(apr_
     return NULL;
 }
 
-void h2_push_policy_determine(struct h2_request *req, apr_pool_t *p, int push_enabled)
-{
-    h2_push_policy policy = H2_PUSH_NONE;
-    if (push_enabled) {
-        const char *val = apr_table_get(req->headers, "accept-push-policy");
-        if (val) {
-            if (ap_find_token(p, val, "fast-load")) {
-                policy = H2_PUSH_FAST_LOAD;
-            }
-            else if (ap_find_token(p, val, "head")) {
-                policy = H2_PUSH_HEAD;
-            }
-            else if (ap_find_token(p, val, "default")) {
-                policy = H2_PUSH_DEFAULT;
-            }
-            else if (ap_find_token(p, val, "none")) {
-                policy = H2_PUSH_NONE;
-            }
-            else {
-                /* nothing known found in this header, go by default */
-                policy = H2_PUSH_DEFAULT;
-            }
-        }
-        else {
-            policy = H2_PUSH_DEFAULT;
-        }
-    }
-    req->push_policy = policy;
-}
-
 /*******************************************************************************
  * push diary 
  *

Modified: httpd/httpd/trunk/modules/http2/h2_push.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_push.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_push.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_push.h Mon Feb  8 16:53:45 2016
@@ -15,19 +15,14 @@
 #ifndef __mod_h2__h2_push__
 #define __mod_h2__h2_push__
 
+#include "h2.h"
+
 struct h2_request;
 struct h2_response;
 struct h2_ngheader;
 struct h2_session;
 struct h2_stream;
 
-typedef enum {
-    H2_PUSH_NONE,
-    H2_PUSH_DEFAULT,
-    H2_PUSH_HEAD,
-    H2_PUSH_FAST_LOAD,
-} h2_push_policy;
-
 typedef struct h2_push {
     const struct h2_request *req;
 } h2_push;
@@ -66,17 +61,6 @@ apr_array_header_t *h2_push_collect(apr_
                                     const struct h2_response *res);
 
 /**
- * Set the push policy for the given request. Takes request headers into 
- * account, see draft https://tools.ietf.org/html/draft-ruellan-http-accept-push-policy-00
- * for details.
- * 
- * @param req the request to determine the policy for
- * @param p the pool to use
- * @param push_enabled if HTTP/2 server push is generally enabled for this request
- */
-void h2_push_policy_determine(struct h2_request *req, apr_pool_t *p, int push_enabled);
-
-/**
  * Create a new push diary for the given maximum number of entries.
  * 
  * @oaram p the pool to use

Modified: httpd/httpd/trunk/modules/http2/h2_request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_request.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_request.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_request.c Mon Feb  8 16:53:45 2016
@@ -30,38 +30,33 @@
 #include <scoreboard.h>
 
 #include "h2_private.h"
-#include "h2_config.h"
-#include "h2_mplx.h"
 #include "h2_push.h"
 #include "h2_request.h"
-#include "h2_task.h"
 #include "h2_util.h"
 
 
-h2_request *h2_request_create(int id, apr_pool_t *pool,
-                              const struct h2_config *config)
+h2_request *h2_request_create(int id, apr_pool_t *pool, int serialize)
 {
-    return h2_request_createn(id, pool, config, 
-                              NULL, NULL, NULL, NULL, NULL);
+    return h2_request_createn(id, pool, NULL, NULL, NULL, NULL, NULL,
+                              serialize);
 }
 
 h2_request *h2_request_createn(int id, apr_pool_t *pool,
-                               const struct h2_config *config, 
                                const char *method, const char *scheme,
                                const char *authority, const char *path,
-                               apr_table_t *header)
+                               apr_table_t *header, int serialize)
 {
     h2_request *req = apr_pcalloc(pool, sizeof(h2_request));
     
     req->id             = id;
-    req->config         = config;
     req->method         = method;
     req->scheme         = scheme;
     req->authority      = authority;
     req->path           = path;
     req->headers        = header? header : apr_table_make(pool, 10);
     req->request_time   = apr_time_now();
-
+    req->serialize      = serialize;
+    
     return req;
 }
 
@@ -139,38 +134,48 @@ static apr_status_t add_all_h1_header(h2
 }
 
 
+apr_status_t h2_request_make(h2_request *req, apr_pool_t *pool,
+                             const char *method, const char *scheme, 
+                             const char *authority, const char *path, 
+                             apr_table_t *headers)
+{
+    req->method    = method;
+    req->scheme    = scheme;
+    req->authority = authority;
+    req->path      = path;
+
+    AP_DEBUG_ASSERT(req->scheme);
+    AP_DEBUG_ASSERT(req->authority);
+    AP_DEBUG_ASSERT(req->path);
+    AP_DEBUG_ASSERT(req->method);
+
+    return add_all_h1_header(req, pool, headers);
+}
+
 apr_status_t h2_request_rwrite(h2_request *req, request_rec *r)
 {
     apr_status_t status;
+    const char *scheme, *authority;
     
-    req->config    = h2_config_rget(r);
-    req->method    = r->method;
-    req->scheme    = (r->parsed_uri.scheme? r->parsed_uri.scheme
-                      : ap_http_scheme(r));
-    req->authority = r->hostname;
-    req->path      = apr_uri_unparse(r->pool, &r->parsed_uri, 
-                                     APR_URI_UNP_OMITSITEPART);
-
-    if (!ap_strchr_c(req->authority, ':') && r->server && r->server->port) {
-        apr_port_t defport = apr_uri_port_of_scheme(req->scheme);
+    scheme = (r->parsed_uri.scheme? r->parsed_uri.scheme
+              : ap_http_scheme(r));
+    authority = r->hostname;
+    if (!ap_strchr_c(authority, ':') && r->server && r->server->port) {
+        apr_port_t defport = apr_uri_port_of_scheme(scheme);
         if (defport != r->server->port) {
             /* port info missing and port is not default for scheme: append */
-            req->authority = apr_psprintf(r->pool, "%s:%d", req->authority,
-                                          (int)r->server->port);
+            authority = apr_psprintf(r->pool, "%s:%d", authority,
+                                     (int)r->server->port);
         }
     }
     
-    AP_DEBUG_ASSERT(req->scheme);
-    AP_DEBUG_ASSERT(req->authority);
-    AP_DEBUG_ASSERT(req->path);
-    AP_DEBUG_ASSERT(req->method);
-
-    status = add_all_h1_header(req, r->pool, r->headers_in);
-
+    status = h2_request_make(req, r->pool,  r->method, scheme, authority,
+                             apr_uri_unparse(r->pool, &r->parsed_uri, 
+                                             APR_URI_UNP_OMITSITEPART),
+                             r->headers_in);
     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r, APLOGNO(03058)
                   "h2_request(%d): rwrite %s host=%s://%s%s",
                   req->id, req->method, req->scheme, req->authority, req->path);
-                  
     return status;
 }
 

Modified: httpd/httpd/trunk/modules/http2/h2_request.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_request.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_request.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_request.h Mon Feb  8 16:53:45 2016
@@ -16,46 +16,19 @@
 #ifndef __mod_h2__h2_request__
 #define __mod_h2__h2_request__
 
-/* h2_request is the transformer of HTTP2 streams into HTTP/1.1 internal
- * format that will be fed to various httpd input filters to finally
- * become a request_rec to be handled by soemone.
- */
-struct h2_config;
-struct h2_to_h1;
-struct h2_mplx;
-struct h2_task;
-
-typedef struct h2_request h2_request;
-
-struct h2_request {
-    int id;             /* stream id */
-
-    const char *method; /* pseudo header values, see ch. 8.1.2.3 */
-    const char *scheme;
-    const char *authority;
-    const char *path;
-    
-    apr_table_t *headers;
-    apr_table_t *trailers;
-
-    apr_time_t request_time;
-    apr_off_t content_length;
-    
-    unsigned int chunked : 1; /* iff requst body needs to be forwarded as chunked */
-    unsigned int eoh     : 1; /* iff end-of-headers has been seen and request is complete */
-    unsigned int body    : 1; /* iff this request has a body */
-    unsigned int push_policy; /* which push policy to use for this request */
-    const struct h2_config *config;
-};
+#include "h2.h"
 
-h2_request *h2_request_create(int id, apr_pool_t *pool, 
-                              const struct h2_config *config);
+h2_request *h2_request_create(int id, apr_pool_t *pool, int serialize);
 
 h2_request *h2_request_createn(int id, apr_pool_t *pool,
-                               const struct h2_config *config, 
                                const char *method, const char *scheme,
                                const char *authority, const char *path,
-                               apr_table_t *headers);
+                               apr_table_t *headers, int serialize);
+
+apr_status_t h2_request_make(h2_request *req, apr_pool_t *pool,
+                             const char *method, const char *scheme, 
+                             const char *authority, const char *path, 
+                             apr_table_t *headers);
 
 void h2_request_destroy(h2_request *req);
 

Modified: httpd/httpd/trunk/modules/http2/h2_response.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_response.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_response.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_response.h Mon Feb  8 16:53:45 2016
@@ -16,18 +16,7 @@
 #ifndef __mod_h2__h2_response__
 #define __mod_h2__h2_response__
 
-struct h2_request;
-struct h2_push;
-
-typedef struct h2_response {
-    int         stream_id;
-    int         rst_error;
-    int         http_status;
-    apr_off_t   content_length;
-    apr_table_t *headers;
-    apr_table_t *trailers;
-    const char  *sos_filter;
-} h2_response;
+#include "h2.h"
 
 /**
  * Create the response from the status and parsed header lines.

Modified: httpd/httpd/trunk/modules/http2/h2_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_session.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_session.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_session.c Mon Feb  8 16:53:45 2016
@@ -47,8 +47,6 @@
 #include "h2_workers.h"
 
 
-static int frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen);
-
 static int h2_session_status_from_apr_status(apr_status_t rv)
 {
     if (rv == APR_SUCCESS) {
@@ -216,7 +214,7 @@ static int on_invalid_frame_recv_cb(nght
     if (APLOGcdebug(session->c)) {
         char buffer[256];
         
-        frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0]));
+        h2_util_frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0]));
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03063)
                       "h2_session(%ld): recv unknown FRAME[%s], frames=%ld/%ld (r/s)",
                       session->id, buffer, (long)session->frames_received,
@@ -377,7 +375,7 @@ static int on_frame_recv_cb(nghttp2_sess
     if (APLOGcdebug(session->c)) {
         char buffer[256];
         
-        frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0]));
+        h2_util_frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0]));
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03066)
                       "h2_session(%ld): recv FRAME[%s], frames=%ld/%ld (r/s)",
                       session->id, buffer, (long)session->frames_received,
@@ -466,8 +464,8 @@ static int on_frame_recv_cb(nghttp2_sess
             if (APLOGctrace2(session->c)) {
                 char buffer[256];
                 
-                frame_print(frame, buffer,
-                            sizeof(buffer)/sizeof(buffer[0]));
+                h2_util_frame_print(frame, buffer,
+                                    sizeof(buffer)/sizeof(buffer[0]));
                 ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
                               "h2_session: on_frame_rcv %s", buffer);
             }
@@ -607,7 +605,7 @@ static int on_frame_send_cb(nghttp2_sess
     if (APLOGcdebug(session->c)) {
         char buffer[256];
         
-        frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0]));
+        h2_util_frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0]));
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03068)
                       "h2_session(%ld): sent FRAME[%s], frames=%ld/%ld (r/s)",
                       session->id, buffer, (long)session->frames_received,
@@ -690,7 +688,8 @@ static void h2_session_destroy(h2_sessio
     }
 }
 
-static apr_status_t h2_session_shutdown(h2_session *session, int reason, const char *msg)
+static apr_status_t h2_session_shutdown(h2_session *session, int reason, 
+                                        const char *msg, int force_close)
 {
     apr_status_t status = APR_SUCCESS;
     const char *err = msg;
@@ -708,6 +707,11 @@ static apr_status_t h2_session_shutdown(
                   "session(%ld): sent GOAWAY, err=%d, msg=%s", 
                   session->id, reason, err? err : "");
     dispatch_event(session, H2_SESSION_EV_LOCAL_GOAWAY, reason, err);
+    
+    if (force_close) {
+        h2_mplx_abort(session->mplx);
+    }
+    
     return status;
 }
 
@@ -1437,14 +1441,14 @@ apr_status_t h2_session_stream_destroy(h
     apr_pool_t *pool = h2_stream_detach_pool(stream);
 
     /* this may be called while the session has already freed
-     * some internal structures. */
+     * some internal structures or even when the mplx is locked. */
     if (session->mplx) {
         h2_mplx_stream_done(session->mplx, stream->id, stream->rst_error);
-        if (session->last_stream == stream) {
-            session->last_stream = NULL;
-        }
     }
     
+    if (session->last_stream == stream) {
+        session->last_stream = NULL;
+    }
     if (session->streams) {
         h2_stream_set_remove(session->streams, stream->id);
     }
@@ -1460,84 +1464,6 @@ apr_status_t h2_session_stream_destroy(h
     return APR_SUCCESS;
 }
 
-static int frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen)
-{
-    char scratch[128];
-    size_t s_len = sizeof(scratch)/sizeof(scratch[0]);
-    
-    switch (frame->hd.type) {
-        case NGHTTP2_DATA: {
-            return apr_snprintf(buffer, maxlen,
-                                "DATA[length=%d, flags=%d, stream=%d, padlen=%d]",
-                                (int)frame->hd.length, frame->hd.flags,
-                                frame->hd.stream_id, (int)frame->data.padlen);
-        }
-        case NGHTTP2_HEADERS: {
-            return apr_snprintf(buffer, maxlen,
-                                "HEADERS[length=%d, hend=%d, stream=%d, eos=%d]",
-                                (int)frame->hd.length,
-                                !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
-                                frame->hd.stream_id,
-                                !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM));
-        }
-        case NGHTTP2_PRIORITY: {
-            return apr_snprintf(buffer, maxlen,
-                                "PRIORITY[length=%d, flags=%d, stream=%d]",
-                                (int)frame->hd.length,
-                                frame->hd.flags, frame->hd.stream_id);
-        }
-        case NGHTTP2_RST_STREAM: {
-            return apr_snprintf(buffer, maxlen,
-                                "RST_STREAM[length=%d, flags=%d, stream=%d]",
-                                (int)frame->hd.length,
-                                frame->hd.flags, frame->hd.stream_id);
-        }
-        case NGHTTP2_SETTINGS: {
-            if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
-                return apr_snprintf(buffer, maxlen,
-                                    "SETTINGS[ack=1, stream=%d]",
-                                    frame->hd.stream_id);
-            }
-            return apr_snprintf(buffer, maxlen,
-                                "SETTINGS[length=%d, stream=%d]",
-                                (int)frame->hd.length, frame->hd.stream_id);
-        }
-        case NGHTTP2_PUSH_PROMISE: {
-            return apr_snprintf(buffer, maxlen,
-                                "PUSH_PROMISE[length=%d, hend=%d, stream=%d]",
-                                (int)frame->hd.length,
-                                !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
-                                frame->hd.stream_id);
-        }
-        case NGHTTP2_PING: {
-            return apr_snprintf(buffer, maxlen,
-                                "PING[length=%d, ack=%d, stream=%d]",
-                                (int)frame->hd.length,
-                                frame->hd.flags&NGHTTP2_FLAG_ACK,
-                                frame->hd.stream_id);
-        }
-        case NGHTTP2_GOAWAY: {
-            size_t len = (frame->goaway.opaque_data_len < s_len)?
-            frame->goaway.opaque_data_len : s_len-1;
-            memcpy(scratch, frame->goaway.opaque_data, len);
-            scratch[len+1] = '\0';
-            return apr_snprintf(buffer, maxlen, "GOAWAY[error=%d, reason='%s']",
-                                frame->goaway.error_code, scratch);
-        }
-        case NGHTTP2_WINDOW_UPDATE: {
-            return apr_snprintf(buffer, maxlen,
-                                "WINDOW_UPDATE[stream=%d, incr=%d]",
-                                frame->hd.stream_id, 
-                                frame->window_update.window_size_increment);
-        }
-        default:
-            return apr_snprintf(buffer, maxlen,
-                                "type=%d[length=%d, flags=%d, stream=%d]",
-                                frame->hd.type, (int)frame->hd.length,
-                                frame->hd.flags, frame->hd.stream_id);
-    }
-}
-
 int h2_session_push_enabled(h2_session *session)
 {
     /* iff we can and they can */
@@ -1791,7 +1717,7 @@ static void h2_session_ev_conn_error(h2_
         default:
             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
                           "h2_session(%ld): conn error -> shutdown", session->id);
-            h2_session_shutdown(session, arg, msg);
+            h2_session_shutdown(session, arg, msg, 0);
             break;
     }
 }
@@ -1808,7 +1734,7 @@ static void h2_session_ev_proto_error(h2
         default:
             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
                           "h2_session(%ld): proto error -> shutdown", session->id);
-            h2_session_shutdown(session, arg, msg);
+            h2_session_shutdown(session, arg, msg, 0);
             break;
     }
 }
@@ -1820,7 +1746,7 @@ static void h2_session_ev_conn_timeout(h
             transit(session, "conn timeout", H2_SESSION_ST_DONE);
             break;
         default:
-            h2_session_shutdown(session, arg, msg);
+            h2_session_shutdown(session, arg, msg, 1);
             transit(session, "conn timeout", H2_SESSION_ST_DONE);
             break;
     }
@@ -1841,7 +1767,7 @@ static void h2_session_ev_no_io(h2_sessi
                 if (!is_accepting_streams(session)) {
                     /* We are no longer accepting new streams and have
                      * finished processing existing ones. Time to leave. */
-                    h2_session_shutdown(session, arg, msg);
+                    h2_session_shutdown(session, arg, msg, 0);
                     transit(session, "no io", H2_SESSION_ST_DONE);
                 }
                 else {
@@ -1919,7 +1845,7 @@ static void h2_session_ev_mpm_stopping(h
             /* nop */
             break;
         default:
-            h2_session_shutdown(session, arg, msg);
+            h2_session_shutdown(session, arg, msg, 0);
             break;
     }
 }
@@ -1932,7 +1858,7 @@ static void h2_session_ev_pre_close(h2_s
             /* nop */
             break;
         default:
-            h2_session_shutdown(session, arg, msg);
+            h2_session_shutdown(session, arg, msg, 1);
             h2_conn_io_flush(&session->io);
             break;
     }
@@ -2035,7 +1961,7 @@ apr_status_t h2_session_process(h2_sessi
                 ap_update_child_status_from_conn(c->sbh, SERVER_BUSY_READ, c);
                 if (!h2_is_acceptable_connection(c, 1)) {
                     update_child_status(session, SERVER_BUSY_READ, "inadequate security");
-                    h2_session_shutdown(session, NGHTTP2_INADEQUATE_SECURITY, NULL);
+                    h2_session_shutdown(session, NGHTTP2_INADEQUATE_SECURITY, NULL, 1);
                 } 
                 else {
                     update_child_status(session, SERVER_BUSY_READ, "init");
@@ -2079,7 +2005,7 @@ apr_status_t h2_session_process(h2_sessi
                         ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, c,
                                       "h2_session(%ld): idle, no data, error", 
                                       session->id);
-                        dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, NULL);
+                        dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, "timeout");
                     }
                 }
                 else {
@@ -2101,7 +2027,7 @@ apr_status_t h2_session_process(h2_sessi
                         /* continue reading handling */
                     }
                     else {
-                        dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, NULL);
+                        dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, "error");
                     }
                 }
                 
@@ -2208,7 +2134,7 @@ apr_status_t h2_session_process(h2_sessi
                     transit(session, "wait cycle", H2_SESSION_ST_BUSY);
                 }
                 else {
-                    h2_session_shutdown(session, H2_ERR_INTERNAL_ERROR, "cond wait error");
+                    h2_session_shutdown(session, H2_ERR_INTERNAL_ERROR, "cond wait error", 0);
                 }
                 break;
                 

Modified: httpd/httpd/trunk/modules/http2/h2_session.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_session.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_session.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_session.h Mon Feb  8 16:53:45 2016
@@ -37,6 +37,8 @@
  *
  */
 
+#include "h2.h"
+
 struct apr_thread_mutext_t;
 struct apr_thread_cond_t;
 struct h2_ctx;
@@ -55,16 +57,6 @@ struct h2_workers;
 struct nghttp2_session;
 
 typedef enum {
-    H2_SESSION_ST_INIT,             /* send initial SETTINGS, etc. */
-    H2_SESSION_ST_DONE,             /* finished, connection close */
-    H2_SESSION_ST_IDLE,             /* nothing to write, expecting data inc */
-    H2_SESSION_ST_BUSY,             /* read/write without stop */
-    H2_SESSION_ST_WAIT,             /* waiting for tasks reporting back */
-    H2_SESSION_ST_LOCAL_SHUTDOWN,   /* we announced GOAWAY */
-    H2_SESSION_ST_REMOTE_SHUTDOWN,  /* client announced GOAWAY */
-} h2_session_state;
-
-typedef enum {
     H2_SESSION_EV_INIT,             /* session was initialized */
     H2_SESSION_EV_LOCAL_GOAWAY,     /* we send a GOAWAY */
     H2_SESSION_EV_REMOTE_GOAWAY,    /* remote send us a GOAWAY */

Modified: httpd/httpd/trunk/modules/http2/h2_stream.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_stream.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_stream.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_stream.c Mon Feb  8 16:53:45 2016
@@ -158,7 +158,8 @@ h2_stream *h2_stream_open(int id, apr_po
 {
     h2_stream *stream = h2_stream_create(id, pool, session);
     set_state(stream, H2_STREAM_ST_OPEN);
-    stream->request   = h2_request_create(id, pool, session->config);
+    stream->request   = h2_request_create(id, pool, 
+        h2_config_geti(session->config, H2_CONF_SER_HEADERS));
     
     ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03082)
                   "h2_stream(%ld-%d): opened", session->id, stream->id);
@@ -242,6 +243,9 @@ apr_status_t h2_stream_set_request(h2_st
     }
     set_state(stream, H2_STREAM_ST_OPEN);
     status = h2_request_rwrite(stream->request, r);
+    stream->request->serialize = h2_config_geti(h2_config_rget(r), 
+                                                H2_CONF_SER_HEADERS);
+
     return status;
 }
 

Modified: httpd/httpd/trunk/modules/http2/h2_stream.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_stream.h?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_stream.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_stream.h Mon Feb  8 16:53:45 2016
@@ -16,6 +16,8 @@
 #ifndef __mod_h2__h2_stream__
 #define __mod_h2__h2_stream__
 
+#include "h2.h"
+
 /**
  * A HTTP/2 stream, e.g. a client request+response in HTTP/1.1 terms.
  * 
@@ -30,16 +32,6 @@
  */
 #include "h2_io.h"
 
-typedef enum {
-    H2_STREAM_ST_IDLE,
-    H2_STREAM_ST_OPEN,
-    H2_STREAM_ST_RESV_LOCAL,
-    H2_STREAM_ST_RESV_REMOTE,
-    H2_STREAM_ST_CLOSED_INPUT,
-    H2_STREAM_ST_CLOSED_OUTPUT,
-    H2_STREAM_ST_CLOSED,
-} h2_stream_state_t;
-
 struct h2_mplx;
 struct h2_priority;
 struct h2_request;

Modified: httpd/httpd/trunk/modules/http2/h2_task.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_task.c?rev=1729209&r1=1729208&r2=1729209&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_task.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_task.c Mon Feb  8 16:53:45 2016
@@ -171,7 +171,7 @@ h2_task *h2_task_create(long session_id,
     task->mplx        = mplx;
     task->request     = req;
     task->input_eos   = !req->body;
-    task->ser_headers = h2_config_geti(req->config, H2_CONF_SER_HEADERS);
+    task->ser_headers = req->serialize;
 
     return task;
 }
@@ -206,9 +206,14 @@ static apr_status_t h2_task_process_requ
     if (r && (r->status == HTTP_OK)) {
         ap_update_child_status(c->sbh, SERVER_BUSY_READ, r);
         
-        if (cs)
+        if (cs) {
             cs->state = CONN_STATE_HANDLER;
+        }
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
+                      "h2_task(%ld-%d): start process_request", c->id, req->id);
         ap_process_request(r);
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
+                      "h2_task(%ld-%d): process_request done", c->id, req->id);
         /* After the call to ap_process_request, the
          * request pool will have been deleted.  We set
          * r=NULL here to ensure that any dereference




Mime
View raw message