httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ic...@apache.org
Subject svn commit: r1701655 [2/4] - in /httpd/httpd/branches/2.4.17-protocols-http2: ./ build/ docs/conf/ docs/conf/extra/ docs/manual/mod/ include/ modules/ modules/http/ modules/http2/ modules/http2/m4/ modules/http2/mod-h2.xcodeproj/ modules/http2/mod_h2/ ...
Date Mon, 07 Sep 2015 17:37:21 GMT
Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/config.m4 (from r1690248, httpd/httpd/trunk/modules/http2/config.m4)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/config.m4?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/config.m4&p1=httpd/httpd/trunk/modules/http2/config.m4&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/config.m4 (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/config.m4 Mon Sep  7 17:37:19 2015
@@ -19,7 +19,6 @@ APACHE_MODPATH_INIT(http2)
 dnl #  list of module object files
 h2_objs="dnl
 mod_h2.lo dnl
-h2_alpn.lo dnl
 h2_alt_svc.lo dnl
 h2_config.lo dnl
 h2_conn.lo dnl
@@ -35,17 +34,139 @@ h2_response.lo dnl
 h2_session.lo dnl
 h2_stream.lo dnl
 h2_stream_set.lo dnl
+h2_switch.lo dnl
 h2_task.lo dnl
 h2_task_input.lo dnl
 h2_task_output.lo dnl
 h2_task_queue.lo dnl
 h2_to_h1.lo dnl
-h2_upgrade.lo dnl
 h2_util.lo dnl
 h2_worker.lo dnl
 h2_workers.lo dnl
 "
 
+dnl
+dnl APACHE_CHECK_NGHTTP2
+dnl
+dnl Configure for nghttp2, giving preference to
+dnl "--with-nghttp2=<path>" if it was specified.
+dnl
+AC_DEFUN(APACHE_CHECK_NGHTTP2,[
+  AC_CACHE_CHECK([for nghttp2], [ac_cv_nghttp2], [
+    dnl initialise the variables we use
+    ac_cv_nghttp2=no
+    ap_nghttp2_found=""
+    ap_nghttp2_base=""
+    ap_nghttp2_libs=""
+
+    dnl Determine the nghttp2 base directory, if any
+    AC_MSG_CHECKING([for user-provided nghttp2 base directory])
+    AC_ARG_WITH(nghttp2, APACHE_HELP_STRING(--with-nghttp2=PATH, nghttp2 installation directory), [
+      dnl If --with-nghttp2 specifies a directory, we use that directory
+      if test "x$withval" != "xyes" -a "x$withval" != "x"; then
+        dnl This ensures $withval is actually a directory and that it is absolute
+        ap_nghttp2_base="`cd $withval ; pwd`"
+      fi
+    ])
+    if test "x$ap_nghttp2_base" = "x"; then
+      AC_MSG_RESULT(none)
+    else
+      AC_MSG_RESULT($ap_nghttp2_base)
+    fi
+
+    dnl Run header and version checks
+    saved_CPPFLAGS="$CPPFLAGS"
+    saved_LIBS="$LIBS"
+    saved_LDFLAGS="$LDFLAGS"
+
+    dnl Before doing anything else, load in pkg-config variables
+    if test -n "$PKGCONFIG"; then
+      saved_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
+      AC_MSG_CHECKING([for pkg-config along $PKG_CONFIG_PATH])
+      if test "x$ap_nghttp2_base" != "x" -a \
+              -f "${ap_nghttp2_base}/lib/pkgconfig/libnghttp2.pc"; then
+        dnl Ensure that the given path is used by pkg-config too, otherwise
+        dnl the system libnghttp2.pc might be picked up instead.
+        PKG_CONFIG_PATH="${ap_nghttp2_base}/lib/pkgconfig${PKG_CONFIG_PATH+:}${PKG_CONFIG_PATH}"
+        export PKG_CONFIG_PATH
+      fi
+      AC_ARG_ENABLE(nghttp2-staticlib-deps,APACHE_HELP_STRING(--enable-nghttp2-staticlib-deps,[link mod_h2 with dependencies of libnghttp2's static libraries (as indicated by "pkg-config --static"). Must be specified in addition to --enable-h2.]), [
+        if test "$enableval" = "yes"; then
+          PKGCONFIG_LIBOPTS="--static"
+        fi
+      ])
+      ap_nghttp2_libs="`$PKGCONFIG $PKGCONFIG_LIBOPTS --libs-only-l --silence-errors libnghttp2`"
+      if test $? -eq 0; then
+        ap_nghttp2_found="yes"
+        pkglookup="`$PKGCONFIG --cflags-only-I libnghttp2`"
+        APR_ADDTO(CPPFLAGS, [$pkglookup])
+        APR_ADDTO(MOD_CFLAGS, [$pkglookup])
+        APR_ADDTO(ab_CFLAGS, [$pkglookup])
+        pkglookup="`$PKGCONFIG $PKGCONFIG_LIBOPTS --libs-only-L libnghttp2`"
+        APR_ADDTO(LDFLAGS, [$pkglookup])
+        APR_ADDTO(MOD_LDFLAGS, [$pkglookup])
+        pkglookup="`$PKGCONFIG $PKGCONFIG_LIBOPTS --libs-only-other libnghttp2`"
+        APR_ADDTO(LDFLAGS, [$pkglookup])
+        APR_ADDTO(MOD_LDFLAGS, [$pkglookup])
+      fi
+      PKG_CONFIG_PATH="$saved_PKG_CONFIG_PATH"
+    fi
+
+    dnl fall back to the user-supplied directory if not found via pkg-config
+    if test "x$ap_nghttp2_base" != "x" -a "x$ap_nghttp2_found" = "x"; then
+      APR_ADDTO(CPPFLAGS, [-I$ap_nghttp2_base/include])
+      APR_ADDTO(MOD_CFLAGS, [-I$ap_nghttp2_base/include])
+      APR_ADDTO(ab_CFLAGS, [-I$ap_nghttp2_base/include])
+      APR_ADDTO(LDFLAGS, [-L$ap_nghttp2_base/lib])
+      APR_ADDTO(MOD_LDFLAGS, [-L$ap_nghttp2_base/lib])
+      if test "x$ap_platform_runtime_link_flag" != "x"; then
+        APR_ADDTO(LDFLAGS, [$ap_platform_runtime_link_flag$ap_nghttp2_base/lib])
+        APR_ADDTO(MOD_LDFLAGS, [$ap_platform_runtime_link_flag$ap_nghttp2_base/lib])
+      fi
+    fi
+
+    AC_MSG_CHECKING([for nghttp2 version >= 1.0.0])
+    AC_TRY_COMPILE([#include <nghttp2/nghttp2ver.h>],[
+#if !defined(NGHTTP2_VERSION_NUM)
+#error "Missing nghttp2 version"
+#endif
+#if NGHTTP2_VERSION_NUM < 0x010000
+#error "Unsupported nghttp2 version " NGHTTP2_VERSION_TEXT
+#endif],
+      [AC_MSG_RESULT(OK)
+       ac_cv_nghttp2=yes],
+      [AC_MSG_RESULT(FAILED)])
+
+    if test "x$ac_cv_nghttp2" = "xyes"; then
+      ap_nghttp2_libs="${ap_nghttp2_libs:--lnghttp2} `$apr_config --libs`"
+      APR_ADDTO(MOD_LDFLAGS, [$ap_nghttp2_libs])
+      APR_ADDTO(LIBS, [$ap_nghttp2_libs])
+      APR_SETVAR(ab_LDFLAGS, [$MOD_LDFLAGS])
+      APACHE_SUBST(ab_CFLAGS)
+      APACHE_SUBST(ab_LDFLAGS)
+
+      dnl Run library and function checks
+      liberrors=""
+      AC_CHECK_HEADERS([nghttp2/nghttp2.h])
+      AC_CHECK_FUNCS([nghttp2_session_server_new2], [], [liberrors="yes"])
+      if test "x$liberrors" != "x"; then
+        AC_MSG_WARN([nghttp2 library is unusable])
+      fi
+    else
+      AC_MSG_WARN([nghttp2 version is too old])
+    fi
+
+    dnl restore
+    CPPFLAGS="$saved_CPPFLAGS"
+    LIBS="$saved_LIBS"
+    LDFLAGS="$saved_LDFLAGS"
+  ])
+  if test "x$ac_cv_nghttp2" = "xyes"; then
+    AC_DEFINE(HAVE_NGHTTP2, 1, [Define if nghttp2 is available])
+  fi
+])
+
+
 dnl #  hook module into the Autoconf mechanism (--enable-h2 option)
 APACHE_MODULE(h2, [HTTP/2 support (mod_h2)], $h2_objs, , most, [
     APACHE_CHECK_NGHTTP2

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/config.m4
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_alt_svc.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_alt_svc.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_alt_svc.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_alt_svc.c&p1=httpd/httpd/trunk/modules/http2/h2_alt_svc.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_alt_svc.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_alt_svc.c Mon Sep  7 17:37:19 2015
@@ -16,6 +16,8 @@
 #include <apr_strings.h>
 #include <httpd.h>
 #include <http_core.h>
+#include <http_connection.h>
+#include <http_protocol.h>
 #include <http_log.h>
 
 #include "h2_private.h"
@@ -25,11 +27,11 @@
 #include "h2_h2.h"
 #include "h2_util.h"
 
-static int h2_alt_svc_request_handler(request_rec *r);
+static int h2_alt_svc_handler(request_rec *r);
 
 void h2_alt_svc_register_hooks(void)
 {
-    ap_hook_handler(h2_alt_svc_request_handler, NULL, NULL, APR_HOOK_LAST);
+    ap_hook_post_read_request(h2_alt_svc_handler, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
 /**
@@ -40,13 +42,13 @@ void h2_alt_svc_register_hooks(void)
  * - do not use quotation marks
  */
 h2_alt_svc *h2_alt_svc_parse(const char *s, apr_pool_t *pool) {
-    const char *sep = strchr(s, '=');
+    const char *sep = ap_strchr_c(s, '=');
     if (sep) {
         const char *alpn = apr_pstrndup(pool, s, sep - s);
         const char *host = NULL;
         int port = 0;
         s = sep + 1;
-        sep = strchr(s, ':');  /* mandatory : */
+        sep = ap_strchr_c(s, ':');  /* mandatory : */
         if (sep) {
             if (sep != s) {    /* optional host */
                 host = apr_pstrndup(pool, s, sep - s);
@@ -69,18 +71,26 @@ h2_alt_svc *h2_alt_svc_parse(const char
 
 #define h2_alt_svc_IDX(list, i) ((h2_alt_svc**)(list)->elts)[i]
 
-static int h2_alt_svc_request_handler(request_rec *r)
+static int h2_alt_svc_handler(request_rec *r)
 {
-    h2_ctx *ctx = h2_ctx_rget(r);
+    h2_ctx *ctx;
+    h2_config *cfg;
+    int i;
     
+    if (r->connection->keepalives > 0) {
+        /* Only announce Alt-Svc on the first response */
+        return DECLINED;
+    }
+    
+    ctx = h2_ctx_rget(r);
     if (h2_ctx_is_active(ctx) || h2_ctx_is_task(ctx)) {
         return DECLINED;
     }
     
-    h2_config *cfg = h2_config_rget(r);
+    cfg = h2_config_rget(r);
     if (r->hostname && cfg && cfg->alt_svcs && cfg->alt_svcs->nelts > 0) {
         const char *alt_svc_used = apr_table_get(r->headers_in, "Alt-Svc-Used");
-        if (!alt_svc_used /*|| (alt_svc_used[0] == '0')*/) {
+        if (!alt_svc_used) {
             /* We have alt-svcs defined and client is not already using
              * one, announce the services that were configured and match. 
              * The security of this connection determines if we allow
@@ -97,7 +107,7 @@ static int h2_alt_svc_request_handler(re
                           "h2_alt_svc: announce %s for %s:%d", 
                           (secure? "secure" : "insecure"), 
                           r->hostname, (int)r->server->port);
-            for (int i = 0; i < cfg->alt_svcs->nelts; ++i) {
+            for (i = 0; i < cfg->alt_svcs->nelts; ++i) {
                 h2_alt_svc *as = h2_alt_svc_IDX(cfg->alt_svcs, i);
                 const char *ahost = as->host;
                 if (ahost && !apr_strnatcasecmp(ahost, r->hostname)) {

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_alt_svc.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_alt_svc.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_config.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.c&p1=httpd/httpd/trunk/modules/http2/h2_config.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_config.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.c Mon Sep  7 17:37:19 2015
@@ -21,6 +21,8 @@
 #include <http_log.h>
 #include <http_vhost.h>
 
+#include <ap_mpm.h>
+
 #include <apr_strings.h>
 
 #include "h2_alt_svc.h"
@@ -36,9 +38,7 @@
 
 static h2_config defconf = {
     "default",
-    0,                /* enabled */
     100,              /* max_streams */
-    16 * 1024,        /* max_hl_size */
     64 * 1024,        /* window_size */
     -1,               /* min workers */
     -1,               /* max workers */
@@ -47,30 +47,50 @@ static h2_config defconf = {
     NULL,             /* no alt-svcs */
     -1,               /* alt-svc max age */
     0,                /* serialize headers */
-    1,                /* hack mpm event */
-    1,                /* h2 direct mode */
-    -1,               /* buffer output, by default only for TLS */
-    64*1024,          /* buffer size */
-    16*1024,          /* out write max */
-    5,                /* # session extra files */
+    -1,               /* h2 direct mode */
+    -1,               /* # session extra files */
 };
 
+static int files_per_session = 0;
+
+void h2_config_init(apr_pool_t *pool) {
+    /* Determine a good default for this platform and mpm?
+     * TODO: not sure how APR wants to hand out this piece of 
+     * information.
+     */
+    int max_files = 256;
+    int conn_threads = 1;
+    int tx_files = max_files / 4;
+    
+    (void)pool;
+    ap_mpm_query(AP_MPMQ_MAX_THREADS, &conn_threads);
+    switch (h2_conn_mpm_type()) {
+        case H2_MPM_PREFORK:
+        case H2_MPM_WORKER:
+        case H2_MPM_EVENT:
+            /* allow that many transfer open files per mplx */
+            files_per_session = (tx_files / conn_threads);
+            break;
+        default:
+            /* don't know anything about it, stay safe */
+            break;
+    }
+}
+
 static void *h2_config_create(apr_pool_t *pool,
                               const char *prefix, const char *x)
 {
     h2_config *conf = (h2_config *)apr_pcalloc(pool, sizeof(h2_config));
     
     const char *s = x? x : "unknown";
-    char *name = (char *)apr_pcalloc(pool, strlen(prefix) + strlen(s) + 20);
+    char *name = apr_pcalloc(pool, strlen(prefix) + strlen(s) + 20);
     strcpy(name, prefix);
     strcat(name, "[");
     strcat(name, s);
     strcat(name, "]");
     
     conf->name                 = name;
-    conf->h2_enabled           = DEF_VAL;
     conf->h2_max_streams       = DEF_VAL;
-    conf->h2_max_hl_size       = DEF_VAL;
     conf->h2_window_size       = DEF_VAL;
     conf->min_workers          = DEF_VAL;
     conf->max_workers          = DEF_VAL;
@@ -78,12 +98,7 @@ static void *h2_config_create(apr_pool_t
     conf->stream_max_mem_size  = DEF_VAL;
     conf->alt_svc_max_age      = DEF_VAL;
     conf->serialize_headers    = DEF_VAL;
-    conf->hack_mpm_event       = DEF_VAL;
     conf->h2_direct            = DEF_VAL;
-    conf->buffer_output        = DEF_VAL;
-    conf->buffer_output        = DEF_VAL;
-    conf->buffer_size          = DEF_VAL;
-    conf->write_max            = DEF_VAL;
     conf->session_extra_files  = DEF_VAL;
     return conf;
 }
@@ -104,8 +119,7 @@ void *h2_config_merge(apr_pool_t *pool,
     h2_config *add = (h2_config *)addv;
     h2_config *n = (h2_config *)apr_pcalloc(pool, sizeof(h2_config));
 
-    char *name = (char *)apr_pcalloc(pool,
-        20 + strlen(add->name) + strlen(base->name));
+    char *name = apr_pcalloc(pool, 20 + strlen(add->name) + strlen(base->name));
     strcpy(name, "merged[");
     strcat(name, add->name);
     strcat(name, ", ");
@@ -113,9 +127,7 @@ void *h2_config_merge(apr_pool_t *pool,
     strcat(name, "]");
     n->name = name;
 
-    n->h2_enabled     = H2_CONFIG_GET(add, base, h2_enabled);
     n->h2_max_streams = H2_CONFIG_GET(add, base, h2_max_streams);
-    n->h2_max_hl_size = H2_CONFIG_GET(add, base, h2_max_hl_size);
     n->h2_window_size = H2_CONFIG_GET(add, base, h2_window_size);
     n->min_workers    = H2_CONFIG_GET(add, base, min_workers);
     n->max_workers    = H2_CONFIG_GET(add, base, max_workers);
@@ -124,11 +136,7 @@ void *h2_config_merge(apr_pool_t *pool,
     n->alt_svcs = add->alt_svcs? add->alt_svcs : base->alt_svcs;
     n->alt_svc_max_age = H2_CONFIG_GET(add, base, alt_svc_max_age);
     n->serialize_headers = H2_CONFIG_GET(add, base, serialize_headers);
-    n->hack_mpm_event = H2_CONFIG_GET(add, base, hack_mpm_event);
     n->h2_direct      = H2_CONFIG_GET(add, base, h2_direct);
-    n->buffer_output  = H2_CONFIG_GET(add, base, buffer_output);
-    n->buffer_size    = H2_CONFIG_GET(add, base, buffer_size);
-    n->write_max      = H2_CONFIG_GET(add, base, write_max);
     n->session_extra_files = H2_CONFIG_GET(add, base, session_extra_files);
     
     return n;
@@ -136,13 +144,10 @@ void *h2_config_merge(apr_pool_t *pool,
 
 int h2_config_geti(h2_config *conf, h2_config_var_t var)
 {
+    int n;
     switch(var) {
-        case H2_CONF_ENABLED:
-            return H2_CONFIG_GET(conf, &defconf, h2_enabled);
         case H2_CONF_MAX_STREAMS:
             return H2_CONFIG_GET(conf, &defconf, h2_max_streams);
-        case H2_CONF_MAX_HL_SIZE:
-            return H2_CONFIG_GET(conf, &defconf, h2_max_hl_size);
         case H2_CONF_WIN_SIZE:
             return H2_CONFIG_GET(conf, &defconf, h2_window_size);
         case H2_CONF_MIN_WORKERS:
@@ -157,18 +162,14 @@ int h2_config_geti(h2_config *conf, h2_c
             return H2_CONFIG_GET(conf, &defconf, alt_svc_max_age);
         case H2_CONF_SER_HEADERS:
             return H2_CONFIG_GET(conf, &defconf, serialize_headers);
-        case H2_CONF_HACK_MPM_EVENT:
-            return H2_CONFIG_GET(conf, &defconf, hack_mpm_event);
         case H2_CONF_DIRECT:
             return H2_CONFIG_GET(conf, &defconf, h2_direct);
-        case H2_CONF_BUFFER_OUTPUT:
-            return H2_CONFIG_GET(conf, &defconf, buffer_output);
-        case H2_CONF_BUFFER_SIZE:
-            return H2_CONFIG_GET(conf, &defconf, buffer_size);
-        case H2_CONF_WRITE_MAX:
-            return H2_CONFIG_GET(conf, &defconf, write_max);
         case H2_CONF_SESSION_FILES:
-            return H2_CONFIG_GET(conf, &defconf, session_extra_files);
+            n = H2_CONFIG_GET(conf, &defconf, session_extra_files);
+            if (n < 0) {
+                n = files_per_session;
+            }
+            return n;
         default:
             return DEF_VAL;
     }
@@ -183,23 +184,6 @@ h2_config *h2_config_sget(server_rec *s)
 }
 
 
-static const char *h2_conf_set_engine(cmd_parms *parms,
-                                      void *arg, const char *value)
-{
-    h2_config *cfg = h2_config_sget(parms->server);
-    if (!strcasecmp(value, "On")) {
-        cfg->h2_enabled = 1;
-        return NULL;
-    }
-    else if (!strcasecmp(value, "Off")) {
-        cfg->h2_enabled = 0;
-        return NULL;
-    }
-    
-    (void)arg;
-    return "value must be On or Off";
-}
-
 static const char *h2_conf_set_max_streams(cmd_parms *parms,
                                            void *arg, const char *value)
 {
@@ -224,18 +208,6 @@ static const char *h2_conf_set_window_si
     return NULL;
 }
 
-static const char *h2_conf_set_max_hl_size(cmd_parms *parms,
-                                           void *arg, const char *value)
-{
-    h2_config *cfg = h2_config_sget(parms->server);
-    cfg->h2_max_hl_size = (int)apr_atoi64(value);
-    (void)arg;
-    if (cfg->h2_max_hl_size < 1024) {
-        return "value must be > 1k";
-    }
-    return NULL;
-}
-
 static const char *h2_conf_set_min_workers(cmd_parms *parms,
                                            void *arg, const char *value)
 {
@@ -313,35 +285,6 @@ static const char *h2_conf_set_alt_svc_m
     return NULL;
 }
 
-static const char *h2_conf_set_buffer_size(cmd_parms *parms,
-                                           void *arg, const char *value)
-{
-    h2_config *cfg = h2_config_sget(parms->server);
-    apr_int64_t len = (int)apr_atoi64(value);
-    if (len < (16*1024)) {
-        return "value must be a positive number, at least 16k";
-    }
-    cfg->buffer_size = (int)len;
-    (void)arg;
-    return NULL;
-}
-
-static const char *h2_conf_set_write_max(cmd_parms *parms,
-                                             void *arg, const char *value)
-{
-    h2_config *cfg = h2_config_sget(parms->server);
-    apr_int64_t max = (int)apr_atoi64(value);
-    if (max <= 0) {
-        return "value must be a positive number";
-    }
-    else if (max > cfg->buffer_size) {
-        return "value must be less than H2BufferSize";
-    }
-    cfg->write_max = (int)max;
-    (void)arg;
-    return NULL;
-}
-
 static const char *h2_conf_set_session_extra_files(cmd_parms *parms,
                                                    void *arg, const char *value)
 {
@@ -372,23 +315,6 @@ static const char *h2_conf_set_serialize
     return "value must be On or Off";
 }
 
-static const char *h2_conf_set_hack_mpm_event(cmd_parms *parms,
-                                              void *arg, const char *value)
-{
-    h2_config *cfg = h2_config_sget(parms->server);
-    if (!strcasecmp(value, "On")) {
-        cfg->hack_mpm_event = 1;
-        return NULL;
-    }
-    else if (!strcasecmp(value, "Off")) {
-        cfg->hack_mpm_event = 0;
-        return NULL;
-    }
-    
-    (void)arg;
-    return "value must be On or Off";
-}
-
 static const char *h2_conf_set_direct(cmd_parms *parms,
                                       void *arg, const char *value)
 {
@@ -406,33 +332,14 @@ static const char *h2_conf_set_direct(cm
     return "value must be On or Off";
 }
 
-static const char *h2_conf_set_buffer_output(cmd_parms *parms,
-                                             void *arg, const char *value)
-{
-    h2_config *cfg = h2_config_sget(parms->server);
-    if (!strcasecmp(value, "On")) {
-        cfg->buffer_output = 1;
-        return NULL;
-    }
-    else if (!strcasecmp(value, "Off")) {
-        cfg->buffer_output = 0;
-        return NULL;
-    }
-    
-    (void)arg;
-    return "value must be On or Off";
-}
+#define AP_END_CMD     AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL)
+
 
-#pragma GCC diagnostic ignored "-Wmissing-braces"
 const command_rec h2_cmds[] = {
-    AP_INIT_TAKE1("H2Engine", h2_conf_set_engine, NULL,
-                  RSRC_CONF, "on to enable HTTP/2 protocol handling"),
     AP_INIT_TAKE1("H2MaxSessionStreams", h2_conf_set_max_streams, NULL,
                   RSRC_CONF, "maximum number of open streams per session"),
-    AP_INIT_TAKE1("H2InitialWindowSize", h2_conf_set_window_size, NULL,
-                  RSRC_CONF, "initial window size on client DATA"),
-    AP_INIT_TAKE1("H2MaxHeaderListSize", h2_conf_set_max_hl_size, NULL, 
-                  RSRC_CONF, "maximum acceptable size of request headers"),
+    AP_INIT_TAKE1("H2WindowSize", h2_conf_set_window_size, NULL,
+                  RSRC_CONF, "window size on client DATA"),
     AP_INIT_TAKE1("H2MinWorkers", h2_conf_set_min_workers, NULL,
                   RSRC_CONF, "minimum number of worker threads per child"),
     AP_INIT_TAKE1("H2MaxWorkers", h2_conf_set_max_workers, NULL,
@@ -447,19 +354,11 @@ const command_rec h2_cmds[] = {
                   RSRC_CONF, "set the maximum age (in seconds) that client can rely on alt-svc information"),
     AP_INIT_TAKE1("H2SerializeHeaders", h2_conf_set_serialize_headers, NULL,
                   RSRC_CONF, "on to enable header serialization for compatibility"),
-    AP_INIT_TAKE1("H2HackMpmEvent", h2_conf_set_hack_mpm_event, NULL,
-                  RSRC_CONF, "on to enable a hack that makes mpm_event working with mod_h2"),
     AP_INIT_TAKE1("H2Direct", h2_conf_set_direct, NULL,
                   RSRC_CONF, "on to enable direct HTTP/2 mode"),
-    AP_INIT_TAKE1("H2BufferOutput", h2_conf_set_buffer_output, NULL,
-                  RSRC_CONF, "on to enable output buffering, default for TLS"),
-    AP_INIT_TAKE1("H2BufferSize", h2_conf_set_buffer_size, NULL,
-                  RSRC_CONF, "size of outgoing buffer in bytes"),
-    AP_INIT_TAKE1("H2BufferWriteMax", h2_conf_set_write_max, NULL,
-                  RSRC_CONF, "maximum number of bytes in a outgoing write"),
     AP_INIT_TAKE1("H2SessionExtraFiles", h2_conf_set_session_extra_files, NULL,
                   RSRC_CONF, "number of extra file a session might keep open"),
-    { NULL, NULL, NULL, 0, 0, NULL }
+    AP_END_CMD
 };
 
 
@@ -485,6 +384,7 @@ h2_config *h2_config_get(conn_rec *c)
          * the vhost matching stuff.
          */
         apr_uri_t uri;
+        request_rec r;
         memset(&uri, 0, sizeof(uri));
         uri.scheme = (char*)"https";
         uri.hostinfo = (char*)ctx->hostname;
@@ -493,7 +393,6 @@ h2_config *h2_config_get(conn_rec *c)
         uri.port = c->local_addr->port;
         uri.path = (char*)"/";
         
-        request_rec r;
         memset(&r, 0, sizeof(r));
         r.uri = (char*)"/";
         r.connection = c;

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.c
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.h (from r1690248, httpd/httpd/trunk/modules/http2/h2_config.h)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.h?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.h&p1=httpd/httpd/trunk/modules/http2/h2_config.h&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_config.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.h Mon Sep  7 17:37:19 2015
@@ -23,9 +23,7 @@
 #undef PACKAGE_BUGREPORT
 
 typedef enum {
-    H2_CONF_ENABLED,
     H2_CONF_MAX_STREAMS,
-    H2_CONF_MAX_HL_SIZE,
     H2_CONF_WIN_SIZE,
     H2_CONF_MIN_WORKERS,
     H2_CONF_MAX_WORKERS,
@@ -34,20 +32,14 @@ typedef enum {
     H2_CONF_ALT_SVCS,
     H2_CONF_ALT_SVC_MAX_AGE,
     H2_CONF_SER_HEADERS,
-    H2_CONF_HACK_MPM_EVENT,
     H2_CONF_DIRECT,
-    H2_CONF_BUFFER_OUTPUT,
-    H2_CONF_BUFFER_SIZE,
-    H2_CONF_WRITE_MAX,
     H2_CONF_SESSION_FILES,
 } h2_config_var_t;
 
 /* Apache httpd module configuration for h2. */
 typedef struct h2_config {
     const char *name;
-    int h2_enabled;               /* if mod_h2 is active at all here */
     int h2_max_streams;           /* max concurrent # streams (http2) */
-    int h2_max_hl_size;           /* max header list size (http2) */
     int h2_window_size;           /* stream window size (http2) */
     int min_workers;              /* min # of worker threads/child */
     int max_workers;              /* max # of worker threads/child */
@@ -57,12 +49,7 @@ typedef struct h2_config {
     int alt_svc_max_age;          /* seconds clients can rely on alt-svc info*/
     int serialize_headers;        /* Use serialized HTTP/1.1 headers for 
                                      processing, better compatibility */
-    int hack_mpm_event;           /* If mpm_event is detected, perform a hack
-                                     on stream connections to make it work */
-    int h2_direct;                /* if mod_h2 is active on non-TLS directly */
-    int buffer_output;            /* if output buffering shall be used */  
-    int buffer_size;              /* size of buffer for outgoing data */  
-    int write_max;                /* max number of bytes for a write op */  
+    int h2_direct;                /* if mod_h2 is active directly */
     int session_extra_files;      /* # of extra files a session may keep open */  
 } h2_config;
 
@@ -81,5 +68,7 @@ h2_config *h2_config_rget(request_rec *r
 
 int h2_config_geti(h2_config *conf, h2_config_var_t var);
 
+void h2_config_init(apr_pool_t *pool);
+
 #endif /* __mod_h2__h2_config_h__ */
 

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_config.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_conn.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.c&p1=httpd/httpd/trunk/modules/http2/h2_conn.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_conn.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.c Mon Sep  7 17:37:19 2015
@@ -46,10 +46,11 @@ static module *mpm_module;
 static module *ssl_module;
 static int checked;
 
-static void check_modules() 
+static void check_modules(void) 
 {
+    int i;
     if (!checked) {
-        for (int i = 0; ap_loaded_modules[i]; ++i) {
+        for (i = 0; ap_loaded_modules[i]; ++i) {
             module *m = ap_loaded_modules[i];
             if (!strcmp("event.c", m->name)) {
                 mpm_type = H2_MPM_EVENT;
@@ -79,21 +80,16 @@ apr_status_t h2_conn_child_init(apr_pool
     int maxw = h2_config_geti(config, H2_CONF_MAX_WORKERS);
     
     int max_threads_per_child = 0;
-    ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
     int threads_limit = 0;
-    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &threads_limit);
+    int idle_secs = 0;
+    int i;
+
+    h2_config_init(pool);
     
-    if (minw <= 0) {
-        minw = max_threads_per_child;
-    }
-    if (maxw <= 0) {
-        maxw = threads_limit;
-        if (maxw < minw) {
-            maxw = minw;
-        }
-    }
+    ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
+    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &threads_limit);
     
-    for (int i = 0; ap_loaded_modules[i]; ++i) {
+    for (i = 0; ap_loaded_modules[i]; ++i) {
         module *m = ap_loaded_modules[i];
         if (!strcmp("event.c", m->name)) {
             mpm_type = H2_MPM_EVENT;
@@ -112,12 +108,22 @@ apr_status_t h2_conn_child_init(apr_pool
         }
     }
     
+    if (minw <= 0) {
+        minw = max_threads_per_child;
+    }
+    if (maxw <= 0) {
+        maxw = threads_limit;
+        if (maxw < minw) {
+            maxw = minw;
+        }
+    }
+    
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "h2_workers: min=%d max=%d, mthrpchild=%d, thr_limit=%d", 
                  minw, maxw, max_threads_per_child, threads_limit);
     
     workers = h2_workers_create(s, pool, minw, maxw);
-    int idle_secs = h2_config_geti(config, H2_CONF_MAX_WORKER_IDLE_SECS);
+    idle_secs = h2_config_geti(config, H2_CONF_MAX_WORKER_IDLE_SECS);
     h2_workers_set_max_idle_secs(workers, idle_secs);
     
     return status;
@@ -128,7 +134,7 @@ h2_mpm_type_t h2_conn_mpm_type(void) {
     return mpm_type;
 }
 
-module *h2_conn_mpm_module(void) {
+static module *h2_conn_mpm_module(void) {
     check_modules();
     return mpm_module;
 }
@@ -136,14 +142,16 @@ module *h2_conn_mpm_module(void) {
 apr_status_t h2_conn_rprocess(request_rec *r)
 {
     h2_config *config = h2_config_rget(r);
+    h2_session *session;
     
     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "h2_conn_process start");
     if (!workers) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "workers not initialized");
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02911) 
+                      "workers not initialized");
         return APR_EGENERAL;
     }
     
-    h2_session *session = h2_session_rcreate(r, config, workers);
+    session = h2_session_rcreate(r, config, workers);
     if (!session) {
         return APR_EGENERAL;
     }
@@ -154,25 +162,38 @@ apr_status_t h2_conn_rprocess(request_re
 apr_status_t h2_conn_main(conn_rec *c)
 {
     h2_config *config = h2_config_get(c);
+    h2_session *session;
+    apr_status_t status;
     
     ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "h2_conn_main start");
     if (!workers) {
-        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, "workers not initialized");
+        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02912) 
+                      "workers not initialized");
         return APR_EGENERAL;
     }
     
-    h2_session *session = h2_session_create(c, config, workers);
+    session = h2_session_create(c, config, workers);
     if (!session) {
         return APR_EGENERAL;
     }
     
-    return h2_session_process(session);
+    status = h2_session_process(session);
+
+    /* Make sure this connection gets closed properly. */
+    c->keepalive = AP_CONN_CLOSE;
+    if (c->cs) {
+        c->cs->state = CONN_STATE_WRITE_COMPLETION;
+    }
+
+    return status;
 }
 
 apr_status_t h2_session_process(h2_session *session)
 {
     apr_status_t status = APR_SUCCESS;
     int rv = 0;
+    apr_interval_time_t wait_micros = 0;
+    static const int MAX_WAIT_MICROS = 200 * 1000;
     
     /* Start talking to the client. Apart from protocol meta data,
      * we mainly will see new http/2 streams opened by the client, which
@@ -224,12 +245,10 @@ apr_status_t h2_session_process(h2_sessi
         return status;
     }
     
-    apr_interval_time_t wait_micros = 0;
-    static const int MAX_WAIT_MICROS = 200 * 1000;
-    
     while (!h2_session_is_done(session)) {
         int have_written = 0;
         int have_read = 0;
+        int got_streams;
         
         status = h2_session_write(session, wait_micros);
         if (status == APR_SUCCESS) {
@@ -263,7 +282,7 @@ apr_status_t h2_session_process(h2_sessi
          *   * h2c will count the header settings as one frame and we
          *     submit our settings and need the ACK.
          */
-        int got_streams = !h2_stream_set_is_empty(session->streams);
+        got_streams = !h2_stream_set_is_empty(session->streams);
         status = h2_session_read(session, 
                                  (!got_streams 
                                   || session->frames_received <= 1)?
@@ -279,7 +298,7 @@ apr_status_t h2_session_process(h2_sessi
             case APR_EBADF:
             case APR_EOF:
             case APR_ECONNABORTED:
-            case ECONNRESET:
+            case APR_ECONNRESET:
                 ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
                               "h2_session(%ld): reading",
                               session->id);
@@ -287,6 +306,7 @@ apr_status_t h2_session_process(h2_sessi
                 break;
             default:
                 ap_log_cerror( APLOG_MARK, APLOG_WARNING, status, session->c,
+                              APLOGNO(02950) 
                               "h2_session(%ld): error reading, terminating",
                               session->id);
                 h2_session_abort(session, status, 0);
@@ -320,9 +340,32 @@ apr_status_t h2_session_process(h2_sessi
 
 static void fix_event_conn(conn_rec *c, conn_rec *master);
 
+/*
+ * We would like to create the connection more lightweight like
+ * slave connections in 2.5-DEV. But we get 500 responses on long
+ * cgi tests in modules/h2.t as the script parsing seems to see an
+ * EOF from the cgi before anything is sent. 
+ *
+conn_rec *h2_conn_create(conn_rec *master, apr_pool_t *pool)
+{
+    conn_rec *c = (conn_rec *) apr_palloc(pool, sizeof(conn_rec));
+    
+    memcpy(c, master, sizeof(conn_rec));
+    c->id = (master->id & (long)pool);
+    c->slaves = NULL;
+    c->master = master;
+    c->input_filters = NULL;
+    c->output_filters = NULL;
+    c->pool = pool;
+    
+    return c;
+}
+*/
+
 conn_rec *h2_conn_create(conn_rec *master, apr_pool_t *pool)
 {
     apr_socket_t *socket;
+    conn_rec *c;
     
     AP_DEBUG_ASSERT(master);
     
@@ -340,29 +383,22 @@ conn_rec *h2_conn_create(conn_rec *maste
      * TODO
      */
     socket = ap_get_module_config(master->conn_config, &core_module);
-    conn_rec *c = ap_run_create_connection(pool, master->base_server,
-                                           socket,
-                                           master->id^((long)pool), 
-                                           master->sbh,
-                                           master->bucket_alloc);
+    c = ap_run_create_connection(pool, master->base_server,
+                                 socket,
+                                 master->id^((long)pool), 
+                                 master->sbh,
+                                 master->bucket_alloc);
     if (c == NULL) {
-        ap_log_perror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, pool,
-                      "h2_task: creating conn");
+        ap_log_perror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, pool, 
+                      APLOGNO(02913) "h2_task: creating conn");
         return NULL;
     }
-    /* TODO: we simulate that we had already a request on this connection.
-     * This keeps the mod_ssl SNI vs. Host name matcher from answering 
-     * 400 Bad Request
-     * when names do not match. We prefer a predictable 421 status.
-     */
-    c->keepalives = 1;
-
     return c;
 }
 
-apr_status_t h2_conn_prep(h2_task_env *env, conn_rec *master, h2_worker *worker)
+apr_status_t h2_conn_setup(h2_task_env *env, struct h2_worker *worker)
 {
-    h2_config *cfg = h2_config_get(master);
+    conn_rec *master = env->mplx->c;
     
     ap_log_perror(APLOG_MARK, APLOG_TRACE3, 0, env->pool,
                   "h2_conn(%ld): created from master", master->id);
@@ -383,7 +419,10 @@ apr_status_t h2_conn_prep(h2_task_env *e
     ap_set_module_config(env->c.conn_config, &core_module, 
                          h2_worker_get_socket(worker));
     
-    if (ssl_module) {
+    /* If we serve http:// requests over a TLS connection, we do
+     * not want any mod_ssl vars to be visible.
+     */
+    if (ssl_module && (!env->scheme || strcmp("http", env->scheme))) {
         /* See #19, there is a range of SSL variables to be gotten from
          * the main connection that should be available in request handlers
          */
@@ -402,73 +441,19 @@ apr_status_t h2_conn_prep(h2_task_env *e
             /* all fine */
             break;
         case H2_MPM_EVENT: 
-            if (h2_config_geti(cfg, H2_CONF_HACK_MPM_EVENT)) {
-                fix_event_conn(&env->c, master);
-            }
+            fix_event_conn(&env->c, master);
             break;
         default:
             /* fingers crossed */
             break;
     }
     
-    return APR_SUCCESS;
-}
-
-apr_status_t h2_conn_setup(struct h2_task_env *env, struct h2_worker *worker)
-{
-    return h2_conn_prep(env, env->mplx->c, worker);
-}
-
-apr_status_t h2_conn_init(struct h2_task_env *env, struct h2_worker *worker)
-{
-    conn_rec *master = env->mplx->c;
-    h2_config *cfg = h2_config_get(master);
-    
-    apr_socket_t *socket = ap_get_module_config(master->conn_config, 
-                                                &core_module);
-    conn_rec *c = ap_run_create_connection(env->pool, master->base_server,
-                                           socket,
-                                           master->id^((long)env->pool), 
-                                           master->sbh,
-                                           master->bucket_alloc);
-    if (c == NULL) {
-        ap_log_perror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, env->pool,
-                      "h2_task: creating conn");
-        return APR_ENOMEM;
-    }
-    
-    env->c = *c;
-    env->c.bucket_alloc = h2_worker_get_bucket_alloc(worker);
-    env->c.current_thread = h2_worker_get_thread(worker);
-    
-    ap_set_module_config(env->c.conn_config, &core_module, socket);
-    if (ssl_module) {
-        /* See #19, there is a range of SSL variables to be gotten from
-         * the main connection that should be available in request handlers
-         */
-        void *sslcfg = ap_get_module_config(master->conn_config, ssl_module);
-        if (sslcfg) {
-            ap_set_module_config(env->c.conn_config, ssl_module, sslcfg);
-        }
-    }
-    
-    /* This works for mpm_worker so far. Other mpm modules have 
-     * different needs, unfortunately. The most interesting one 
-     * being mpm_event...
+    /* TODO: we simulate that we had already a request on this connection.
+     * This keeps the mod_ssl SNI vs. Host name matcher from answering 
+     * 400 Bad Request
+     * when names do not match. We prefer a predictable 421 status.
      */
-    switch (h2_conn_mpm_type()) {
-        case H2_MPM_WORKER:
-            /* all fine */
-            break;
-        case H2_MPM_EVENT: 
-            if (h2_config_geti(cfg, H2_CONF_HACK_MPM_EVENT)) {
-                fix_event_conn(&env->c, master);
-            }
-            break;
-        default:
-            /* fingers crossed */
-            break;
-    }
+    env->c.keepalives = 1;
     
     return APR_SUCCESS;
 }

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.c
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.h (from r1690248, httpd/httpd/trunk/modules/http2/h2_conn.h)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.h?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.h&p1=httpd/httpd/trunk/modules/http2/h2_conn.h&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_conn.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.h Mon Sep  7 17:37:19 2015
@@ -46,23 +46,13 @@ typedef enum {
     H2_MPM_PREFORK,
 } h2_mpm_type_t;
 
-h2_mpm_type_t h2_conn_mpm_type();
-module *h2_conn_mpm_module();
-
 /* Returns the type of MPM module detected */
 h2_mpm_type_t h2_conn_mpm_type(void);
 
-/* Gives the detected module itself or NULL if unknown */
-module *h2_conn_mpm_module(void);
-
 
 conn_rec *h2_conn_create(conn_rec *master, apr_pool_t *stream_pool);
 
-apr_status_t h2_conn_init(struct h2_task_env *env, struct h2_worker *worker);
-
 apr_status_t h2_conn_setup(struct h2_task_env *env, struct h2_worker *worker);
-apr_status_t h2_conn_prep(struct h2_task_env *env, conn_rec *master, 
-                          struct h2_worker *worker);
 apr_status_t h2_conn_post(conn_rec *c, struct h2_worker *worker);
 
 apr_status_t h2_conn_process(conn_rec *c, apr_socket_t *socket);

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_conn_io.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.c&p1=httpd/httpd/trunk/modules/http2/h2_conn_io.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_conn_io.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.c Mon Sep  7 17:37:19 2015
@@ -28,20 +28,23 @@
 #include "h2_h2.h"
 #include "h2_util.h"
 
+#define WRITE_BUFFER_SIZE     (64*1024)
+#define WRITE_SIZE_INITIAL    1300
+#define WRITE_SIZE_MAX        (16*1024)
+#define WRITE_SIZE_IDLE_USEC  (1*APR_USEC_PER_SEC)
+#define WRITE_SIZE_THRESHOLD  (1*1024*1024)
+
 apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c)
 {
-    h2_config *cfg = h2_config_get(c);
-    
     io->connection = c;
     io->input = apr_brigade_create(c->pool, c->bucket_alloc);
     io->output = apr_brigade_create(c->pool, c->bucket_alloc);
     io->buflen = 0;
-    io->max_write_size = h2_config_geti(cfg, H2_CONF_WRITE_MAX);
-    io->buffer_output = h2_config_geti(cfg, H2_CONF_BUFFER_OUTPUT);
-    
-    if (io->buffer_output < 0) {
-        io->buffer_output = h2_h2_is_tls(c);
-    }
+    /* That is where we start with, 
+     * see https://issues.apache.org/jira/browse/TS-2503 */
+    io->write_size = WRITE_SIZE_INITIAL; 
+    io->last_write = 0;
+    io->buffer_output = h2_h2_is_tls(c);
 
     /* Currently we buffer only for TLS output. The reason this gives
      * improved performance is that buckets send to the mod_ssl network
@@ -51,7 +54,7 @@ apr_status_t h2_conn_io_init(h2_conn_io
      * chunks.
      */
     if (io->buffer_output) {
-        io->bufsize = h2_config_geti(cfg, H2_CONF_BUFFER_SIZE);
+        io->bufsize = WRITE_BUFFER_SIZE;
         io->buffer = apr_pcalloc(c->pool, io->bufsize);
     }
     else {
@@ -174,26 +177,53 @@ apr_status_t h2_conn_io_read(h2_conn_io
 static apr_status_t flush_out(apr_bucket_brigade *bb, void *ctx) 
 {
     h2_conn_io *io = (h2_conn_io*)ctx;
+    apr_status_t status;
+    apr_off_t bblen;
     
     ap_update_child_status(io->connection->sbh, SERVER_BUSY_WRITE, NULL);
-    
-    apr_status_t status = ap_pass_brigade(io->connection->output_filters, bb);
-    apr_brigade_cleanup(bb);
+    status = apr_brigade_length(bb, 1, &bblen);
+    if (status == APR_SUCCESS) {
+        status = ap_pass_brigade(io->connection->output_filters, bb);
+        if (status == APR_SUCCESS) {
+            io->bytes_written += (apr_size_t)bblen;
+            io->last_write = apr_time_now();
+        }
+        apr_brigade_cleanup(bb);
+    }
     return status;
 }
 
 static apr_status_t bucketeer_buffer(h2_conn_io *io) {
     const char *data = io->buffer;
     apr_size_t remaining = io->buflen;
-    int bcount = (int)(remaining / io->max_write_size);
     apr_bucket *b;
-    
-    for (int i = 0; i < bcount; ++i) {
-        b = apr_bucket_transient_create(data, io->max_write_size, 
+    int bcount, i;
+
+    if (io->write_size > WRITE_SIZE_INITIAL
+        && (apr_time_now() - io->last_write) >= WRITE_SIZE_IDLE_USEC) {
+        /* long time not written, reset write size */
+        io->write_size = WRITE_SIZE_INITIAL;
+        io->bytes_written = 0;
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, io->connection,
+                      "h2_conn_io(%ld): timeout write size reset to %ld", 
+                      (long)io->connection->id, (long)io->write_size);
+    }
+    else if (io->write_size < WRITE_SIZE_MAX 
+             && io->bytes_written >= WRITE_SIZE_THRESHOLD) {
+        /* connection is hot, use max size */
+        io->write_size = WRITE_SIZE_MAX;
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, io->connection,
+                      "h2_conn_io(%ld): threshold reached, write size now %ld", 
+                      (long)io->connection->id, (long)io->write_size);
+    }
+    
+    bcount = (int)(remaining / io->write_size);
+    for (i = 0; i < bcount; ++i) {
+        b = apr_bucket_transient_create(data, io->write_size, 
                                         io->output->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(io->output, b);
-        data += io->max_write_size;
-        remaining -= io->max_write_size;
+        data += io->write_size;
+        remaining -= io->write_size;
     }
     
     if (remaining > 0) {
@@ -257,12 +287,11 @@ apr_status_t h2_conn_io_write(h2_conn_io
 apr_status_t h2_conn_io_flush(h2_conn_io *io)
 {
     if (io->unflushed) {
+        apr_status_t status; 
         if (io->buflen > 0) {
             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
                           "h2_conn_io: flush, flushing %ld bytes", (long)io->buflen);
-            apr_bucket *b = apr_bucket_transient_create(io->buffer, io->buflen, 
-                                                        io->output->bucket_alloc);
-            APR_BRIGADE_INSERT_TAIL(io->output, b);
+            bucketeer_buffer(io);
             io->buflen = 0;
         }
         /* Append flush.
@@ -271,7 +300,7 @@ apr_status_t h2_conn_io_flush(h2_conn_io
                                 apr_bucket_flush_create(io->output->bucket_alloc));
         
         /* Send it out through installed filters (TLS) to the client */
-        apr_status_t status = flush_out(io->output, io);
+        status = flush_out(io->output, io);
         
         if (status == APR_SUCCESS
             || APR_STATUS_IS_ECONNABORTED(status)

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.c
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.h (from r1690248, httpd/httpd/trunk/modules/http2/h2_conn_io.h)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.h?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.h&p1=httpd/httpd/trunk/modules/http2/h2_conn_io.h&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_conn_io.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.h Mon Sep  7 17:37:19 2015
@@ -27,7 +27,9 @@ typedef struct {
     apr_bucket_brigade *input;
     apr_bucket_brigade *output;
     int buffer_output;
-    int max_write_size;
+    int write_size;
+    apr_time_t last_write;
+    apr_size_t bytes_written;
     
     char *buffer;
     apr_size_t buflen;

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_conn_io.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_ctx.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.c&p1=httpd/httpd/trunk/modules/http2/h2_ctx.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_ctx.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.c Mon Sep  7 17:37:19 2015
@@ -24,16 +24,15 @@
 #include "h2_ctx.h"
 #include "h2_private.h"
 
-static h2_ctx *h2_ctx_create(conn_rec *c)
+static h2_ctx *h2_ctx_create(const conn_rec *c)
 {
     h2_ctx *ctx = apr_pcalloc(c->pool, sizeof(h2_ctx));
     AP_DEBUG_ASSERT(ctx);
-    ctx->pnego_state = H2_PNEGO_NONE;
     ap_set_module_config(c->conn_config, &h2_module, ctx);
     return ctx;
 }
 
-h2_ctx *h2_ctx_create_for(conn_rec *c, h2_task_env *env)
+h2_ctx *h2_ctx_create_for(const conn_rec *c, h2_task_env *env)
 {
     h2_ctx *ctx = h2_ctx_create(c);
     if (ctx) {
@@ -42,7 +41,7 @@ h2_ctx *h2_ctx_create_for(conn_rec *c, h
     return ctx;
 }
 
-h2_ctx *h2_ctx_get(conn_rec *c)
+h2_ctx *h2_ctx_get(const conn_rec *c)
 {
     h2_ctx *ctx = (h2_ctx*)ap_get_module_config(c->conn_config, &h2_module);
     if (ctx == NULL) {
@@ -51,25 +50,20 @@ h2_ctx *h2_ctx_get(conn_rec *c)
     return ctx;
 }
 
-h2_ctx *h2_ctx_rget(request_rec *r)
+h2_ctx *h2_ctx_rget(const request_rec *r)
 {
     return h2_ctx_get(r->connection);
 }
 
-const char *h2_ctx_pnego_get(h2_ctx *ctx)
+const char *h2_ctx_protocol_get(const conn_rec *c)
 {
+    h2_ctx *ctx = (h2_ctx*)ap_get_module_config(c->conn_config, &h2_module);
     return ctx? ctx->protocol : NULL;
 }
 
-void h2_ctx_pnego_set_started(h2_ctx *ctx)
-{
-    ctx->pnego_state = H2_PNEGO_STARTED;
-}
-
-h2_ctx *h2_ctx_pnego_set_done(h2_ctx *ctx, const char *proto)
+h2_ctx *h2_ctx_protocol_set(h2_ctx *ctx, const char *proto)
 {
     ctx->protocol = proto;
-    ctx->pnego_state = H2_PNEGO_DONE;
     ctx->is_h2 = (proto != NULL);
     return ctx;
 }
@@ -79,16 +73,6 @@ int h2_ctx_is_task(h2_ctx *ctx)
     return ctx && !!ctx->task_env;
 }
 
-int h2_ctx_pnego_is_ongoing(h2_ctx *ctx)
-{
-    return ctx && (ctx->pnego_state == H2_PNEGO_STARTED);
-}
-
-int h2_ctx_pnego_is_done(h2_ctx *ctx)
-{
-    return ctx && (ctx->pnego_state == H2_PNEGO_DONE);
-}
-
 int h2_ctx_is_active(h2_ctx *ctx)
 {
     return ctx && ctx->is_h2;

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.c
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.h (from r1690248, httpd/httpd/trunk/modules/http2/h2_ctx.h)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.h?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.h&p1=httpd/httpd/trunk/modules/http2/h2_ctx.h&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_ctx.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.h Mon Sep  7 17:37:19 2015
@@ -19,12 +19,6 @@
 struct h2_task_env;
 struct h2_config;
 
-typedef enum {
-    H2_PNEGO_NONE,
-    H2_PNEGO_STARTED,
-    H2_PNEGO_DONE,    
-} h2_pnego_state_t;
-
 /**
  * The h2 module context associated with a connection. 
  *
@@ -35,7 +29,6 @@ typedef enum {
  */
 typedef struct h2_ctx {
     int is_h2;                    /* h2 engine is used */
-    h2_pnego_state_t pnego_state; /* protocol negotiation state */
     const char *protocol;         /* the protocol negotiated */
     struct h2_task_env *task_env; /* the h2_task environment or NULL */
     const char *hostname;         /* hostname negotiated via SNI, optional */
@@ -43,28 +36,20 @@ typedef struct h2_ctx {
     struct h2_config *config;     /* effective config in this context */
 } h2_ctx;
 
-h2_ctx *h2_ctx_get(conn_rec *c);
-h2_ctx *h2_ctx_rget(request_rec *r);
-h2_ctx *h2_ctx_create_for(conn_rec *c, struct h2_task_env *env);
+h2_ctx *h2_ctx_get(const conn_rec *c);
+h2_ctx *h2_ctx_rget(const request_rec *r);
+h2_ctx *h2_ctx_create_for(const conn_rec *c, struct h2_task_env *env);
 
 
-void h2_ctx_pnego_set_started(h2_ctx *ctx);
-h2_ctx *h2_ctx_pnego_set_done(h2_ctx *ctx, const char *proto);
-/**
- * Returns != 0 iff protocol negitiation did happen, not matter
- * what the outcome was.
- */
-int h2_ctx_pnego_is_done(h2_ctx *ctx);
-/**
- * Returns != 0 iff protocol negotiation has started but is not
- * done yet.
+/* Set the h2 protocol established on this connection context or
+ * NULL when other protocols are in place.
  */
-int h2_ctx_pnego_is_ongoing(h2_ctx *ctx);
+h2_ctx *h2_ctx_protocol_set(h2_ctx *ctx, const char *proto);
 
 /**
  * Get the h2 protocol negotiated for this connection, or NULL.
  */
-const char *h2_ctx_pnego_get(h2_ctx *ctx);
+const char *h2_ctx_protocol_get(const conn_rec *c);
 
 int h2_ctx_is_task(h2_ctx *ctx);
 int h2_ctx_is_active(h2_ctx *ctx);

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_ctx.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_from_h1.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.c&p1=httpd/httpd/trunk/modules/http2/h2_from_h1.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_from_h1.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.c Mon Sep  7 17:37:19 2015
@@ -83,6 +83,7 @@ static apr_status_t make_h2_headers(h2_f
                                        from_h1->pool);
     if (from_h1->response == NULL) {
         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EINVAL, r->connection,
+                      APLOGNO(02915) 
                       "h2_from_h1(%d): unable to create resp_head",
                       from_h1->stream_id);
         return APR_EINVAL;
@@ -107,12 +108,13 @@ static apr_status_t parse_header(h2_from
     (void)f;
     
     if (line[0] == ' ' || line[0] == '\t') {
+        char **plast;
         /* continuation line from the header before this */
         while (line[0] == ' ' || line[0] == '\t') {
             ++line;
         }
         
-        char **plast = apr_array_pop(from_h1->hlines);
+        plast = apr_array_pop(from_h1->hlines);
         if (plast == NULL) {
             /* not well formed */
             return APR_EINVAL;
@@ -129,13 +131,14 @@ static apr_status_t parse_header(h2_from
 static apr_status_t get_line(h2_from_h1 *from_h1, apr_bucket_brigade *bb,
                              ap_filter_t* f, char *line, apr_size_t len)
 {
+    apr_status_t status;
     if (!from_h1->bb) {
         from_h1->bb = apr_brigade_create(from_h1->pool, f->c->bucket_alloc);
     }
     else {
         apr_brigade_cleanup(from_h1->bb);                
     }
-    apr_status_t status = apr_brigade_split_line(from_h1->bb, bb, 
+    status = apr_brigade_split_line(from_h1->bb, bb, 
                                                  APR_BLOCK_READ, 
                                                  HUGE_STRING_LEN);
     if (status == APR_SUCCESS) {
@@ -310,86 +313,6 @@ static void fix_vary(request_rec *r)
     }
 }
 
-/* Confirm that the status line is well-formed and matches r->status.
- * If they don't match, a filter may have negated the status line set by a
- * handler.
- * Zap r->status_line if bad.
- */
-static apr_status_t validate_status_line(request_rec *r)
-{
-    char *end;
-    
-    if (r->status_line) {
-        apr_size_t len = strlen(r->status_line);
-        if (len < 3
-            || apr_strtoi64(r->status_line, &end, 10) != r->status
-            || (end - 3) != r->status_line
-            || (len >= 4 && ! apr_isspace(r->status_line[3]))) {
-            r->status_line = NULL;
-            return APR_EGENERAL;
-        }
-        /* Since we passed the above check, we know that length three
-         * is equivalent to only a 3 digit numeric http status.
-         * RFC2616 mandates a trailing space, let's add it.
-         */
-        if (len == 3) {
-            r->status_line = apr_pstrcat(r->pool, r->status_line, " ", NULL);
-            return APR_EGENERAL;
-        }
-        return APR_SUCCESS;
-    }
-    return APR_EGENERAL;
-}
-
-/*
- * Determine the protocol to use for the response. Potentially downgrade
- * to HTTP/1.0 in some situations and/or turn off keepalives.
- *
- * also prepare r->status_line.
- */
-static void basic_http_header_check(request_rec *r,
-                                    const char **protocol)
-{
-    apr_status_t rv;
-    
-    if (r->assbackwards) {
-        /* no such thing as a response protocol */
-        return;
-    }
-    
-    rv = validate_status_line(r);
-    
-    if (!r->status_line) {
-        r->status_line = ap_get_status_line(r->status);
-    } else if (rv != APR_SUCCESS) {
-        /* Status line is OK but our own reason phrase
-         * would be preferred if defined
-         */
-        const char *tmp = ap_get_status_line(r->status);
-        if (!strncmp(tmp, r->status_line, 3)) {
-            r->status_line = tmp;
-        }
-    }
-    
-    /* Note that we must downgrade before checking for force responses. */
-    if (r->proto_num > HTTP_VERSION(1,0)
-        && apr_table_get(r->subprocess_env, "downgrade-1.0")) {
-        r->proto_num = HTTP_VERSION(1,0);
-    }
-    
-    /* kludge around broken browsers when indicated by force-response-1.0
-     */
-    if (r->proto_num == HTTP_VERSION(1,0)
-        && apr_table_get(r->subprocess_env, "force-response-1.0")) {
-        *protocol = "HTTP/1.0";
-        r->connection->keepalive = AP_CONN_CLOSE;
-    }
-    else {
-        *protocol = AP_SERVER_PROTOCOL;
-    }
-    
-}
-
 static void set_basic_http_header(request_rec *r, apr_table_t *headers)
 {
     char *date = NULL;
@@ -441,9 +364,9 @@ static int copy_header(void *ctx, const
 
 static h2_response *create_response(h2_from_h1 *from_h1, request_rec *r)
 {
-    apr_status_t status = APR_SUCCESS;
     const char *clheader;
     const char *ctype;
+    apr_table_t *headers;
     /*
      * Now that we are ready to send a response, we need to combine the two
      * header field tables into a single table.  If we don't do this, our
@@ -541,7 +464,7 @@ static h2_response *create_response(h2_f
         apr_table_unset(r->headers_out, "Content-Length");
     }
     
-    apr_table_t *headers = apr_table_make(r->pool, 10);
+    headers = apr_table_make(r->pool, 10);
     
     set_basic_http_header(r, headers);
     if (r->status == HTTP_NOT_MODIFIED) {
@@ -645,9 +568,3 @@ apr_status_t h2_response_output_filter(a
     }
     return ap_pass_brigade(f->next, bb);
 }
-
-void h2_from_h1_die(h2_from_h1 *from_h1, int status, request_rec *r)
-{
-    r->status = status;
-    from_h1->response = create_response(from_h1, r);
-}

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.c
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.h (from r1690248, httpd/httpd/trunk/modules/http2/h2_from_h1.h)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.h?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.h&p1=httpd/httpd/trunk/modules/http2/h2_from_h1.h&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_from_h1.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.h Mon Sep  7 17:37:19 2015
@@ -75,8 +75,6 @@ apr_status_t h2_from_h1_read_response(h2
 
 struct h2_response *h2_from_h1_get_response(h2_from_h1 *from_h1);
 
-void h2_from_h1_die(h2_from_h1 *from_h1, int status, request_rec *r);
-
 h2_from_h1_state_t h2_from_h1_get_state(h2_from_h1 *from_h1);
 
 apr_status_t h2_response_output_filter(ap_filter_t *f, apr_bucket_brigade *bb);

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_from_h1.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_h2.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.c&p1=httpd/httpd/trunk/modules/http2/h2_h2.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_h2.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.c Mon Sep  7 17:37:19 2015
@@ -33,20 +33,15 @@
 #include "h2_config.h"
 #include "h2_ctx.h"
 #include "h2_conn.h"
-#include "h2_alpn.h"
 #include "h2_h2.h"
 
-const char *h2_alpn_protos[] = {
-    "h2",
+const char *h2_tls_protos[] = {
+    "h2", NULL
 };
-apr_size_t h2_alpn_protos_len = (sizeof(h2_alpn_protos)
-                                 / sizeof(h2_alpn_protos[0]));
 
-const char *h2_upgrade_protos[] = {
-    "h2c",
+const char *h2_clear_protos[] = {
+    "h2c", NULL
 };
-apr_size_t h2_upgrade_protos_len = (sizeof(h2_upgrade_protos)
-                                    / sizeof(h2_upgrade_protos[0]));
 
 const char *H2_MAGIC_TOKEN = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
 
@@ -80,7 +75,7 @@ apr_status_t h2_h2_init(apr_pool_t *pool
     
     if (!opt_ssl_is_https) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
-                     "mod_ssl does not seem to be enabled");
+                     APLOGNO(02951) "mod_ssl does not seem to be enabled");
     }
     
     return APR_SUCCESS;
@@ -107,7 +102,7 @@ static const char *const mod_reqtimeout[
 void h2_h2_register_hooks(void)
 {
     /* When the connection processing actually starts, we might to
-     * take over, if h2* was selected by ALPN on a TLS connection.
+     * take over, if h2* was selected as protocol.
      */
     ap_hook_process_connection(h2_h2_process_conn, 
                                NULL, NULL, APR_HOOK_FIRST);
@@ -116,26 +111,19 @@ void h2_h2_register_hooks(void)
     ap_hook_process_connection(h2_h2_remove_timeout, 
                                mod_reqtimeout, NULL, APR_HOOK_LAST);
     
-    ap_hook_post_read_request(h2_h2_post_read_req, NULL, NULL, APR_HOOK_MIDDLE);
+    /* With "H2SerializeHeaders On", we install the filter in this hook
+     * that parses the response. This needs to happen before any other post
+     * read function terminates the request with an error. Otherwise we will
+     * never see the response.
+     */
+    ap_hook_post_read_request(h2_h2_post_read_req, NULL, NULL, APR_HOOK_REALLY_FIRST);
 }
 
 int h2_h2_remove_timeout(conn_rec* c)
 {
     h2_ctx *ctx = h2_ctx_get(c);
     
-    if (h2_ctx_is_task(ctx)) {
-        /* cleanup on task connections */
-        /* we once removed the reqtimeout filter on task connections,
-         * but timeouts here might have been a side effect of other things.
-         * Ideally mod_reqtimeout would do its work on task connections
-         * as it basically is a HTTP/1.1 request/response and it's made
-         * for that.
-         * So, let the filter stay for now and see if we ever encounter
-         * unexpected timeouts on tasks again.
-         */
-        //ap_remove_input_filter_byhandle(c->input_filters, "reqtimeout");
-    }
-    else if (h2_ctx_is_active(ctx)) {
+    if (h2_ctx_is_active(ctx) && !h2_ctx_is_task(ctx)) {
         /* cleanup on master h2 connections */
         ap_remove_input_filter_byhandle(c->input_filters, "reqtimeout");
     }
@@ -148,39 +136,58 @@ int h2_h2_process_conn(conn_rec* c)
     h2_ctx *ctx = h2_ctx_get(c);
     h2_config *cfg = h2_config_get(c);
     apr_bucket_brigade* temp;
-
+    int is_tls = h2_h2_is_tls(c);
+    
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, process_conn");
     if (h2_ctx_is_task(ctx)) {
-        /* out stream pseudo connection */
+        /* our stream pseudo connection */
         return DECLINED;
     }
 
-    /* Protocol negoation, if started, may need some speculative reading
-     * to get triggered.
+    /* If we have not already switched to a h2* protocol and the connection 
+     * is on "http/1.1"
+     * -> sniff for the magic PRIamble. On TLS, this might trigger the ALPN.
      */
-    if (h2_ctx_pnego_is_ongoing(ctx)) {
-        temp = apr_brigade_create(c->pool, c->bucket_alloc);
-        ap_get_brigade(c->input_filters, temp,
-                       AP_MODE_SPECULATIVE, APR_BLOCK_READ, 1);
-        apr_brigade_destroy(temp);
-    }
-
-    /* If we still do not know the protocol and H2Direct is enabled, check
-     * if we receive the magic PRIamble. A client sending this on connection
-     * start should know what it is doing.
-     */
-    if (!h2_ctx_pnego_is_done(ctx) && h2_config_geti(cfg, H2_CONF_DIRECT)) {
+    if (!h2_ctx_protocol_get(c) 
+        && !strcmp(AP_PROTOCOL_HTTP1, ap_get_protocol(c))) {
         apr_status_t status;
+        
         temp = apr_brigade_create(c->pool, c->bucket_alloc);
         status = ap_get_brigade(c->input_filters, temp,
                                 AP_MODE_SPECULATIVE, APR_BLOCK_READ, 24);
+
         if (status == APR_SUCCESS) {
-            char *s = NULL;
-            apr_size_t slen;
-            
-            apr_brigade_pflatten(temp, &s, &slen, c->pool);
-            if ((slen == 24) && !memcmp(H2_MAGIC_TOKEN, s, 24)) {
-                h2_ctx_pnego_set_done(ctx, "h2");
+            if (h2_ctx_protocol_get(c) 
+                || strcmp(AP_PROTOCOL_HTTP1, ap_get_protocol(c))) {
+                /* h2 or another protocol has been selected. */
             }
+            else {
+                /* ALPN might have been triggered, but we're still on
+                 * http/1.1. Check the actual bytes read for the H2 Magic
+                 * Token, *if* H2Direct mode is enabled here. 
+                 */
+                int direct_mode = h2_config_geti(cfg, H2_CONF_DIRECT);
+                if (direct_mode > 0 || (direct_mode < 0 && !is_tls)) {
+                    char *s = NULL;
+                    apr_size_t slen;
+                    
+                    apr_brigade_pflatten(temp, &s, &slen, c->pool);
+                    if ((slen >= 24) && !memcmp(H2_MAGIC_TOKEN, s, 24)) {
+                        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
+                                      "h2_h2, direct mode detected");
+                        h2_ctx_protocol_set(ctx, is_tls? "h2" : "h2c");
+                    }
+                    else {
+                        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
+                                      "h2_h2, not detected in %d bytes: %s", 
+                                      (int)slen, s);
+                    }
+                }
+            }
+        }
+        else {
+            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c,
+                          "h2_h2, error reading 24 bytes speculative");
         }
         apr_brigade_destroy(temp);
     }
@@ -189,12 +196,13 @@ int h2_h2_process_conn(conn_rec* c)
      * the connection.
      */
     if (h2_ctx_is_active(ctx)) {
-        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                       "h2_h2, connection, h2 active");
         
         return h2_conn_main(c);
     }
     
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, declined");
     return DECLINED;
 }
 
@@ -207,12 +215,14 @@ static int h2_h2_post_read_req(request_r
         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                       "adding h1_to_h2_resp output filter");
         if (env->serialize_headers) {
+            ap_remove_output_filter_byhandle(r->output_filters, "H1_TO_H2_RESP");
             ap_add_output_filter("H1_TO_H2_RESP", env, r, r->connection);
         }
         else {
             /* replace the core http filter that formats response headers
              * in HTTP/1 with our own that collects status and headers */
             ap_remove_output_filter_byhandle(r->output_filters, "HTTP_HEADER");
+            ap_remove_output_filter_byhandle(r->output_filters, "H2_RESPONSE");
             ap_add_output_filter("H2_RESPONSE", env, r, r->connection);
         }
     }

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.c
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.h (from r1690248, httpd/httpd/trunk/modules/http2/h2_h2.h)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.h?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.h&p1=httpd/httpd/trunk/modules/http2/h2_h2.h&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_h2.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.h Mon Sep  7 17:37:19 2015
@@ -17,18 +17,16 @@
 #define __mod_h2__h2_h2__
 
 /**
- * List of ALPN protocol identifiers that we support in ALPN/NPN 
- * negotiations.
+ * List of ALPN protocol identifiers that we suport in cleartext
+ * negotiations. NULL terminated.
  */
-extern const char *h2_alpn_protos[];
-extern apr_size_t h2_alpn_protos_len;
+extern const char *h2_clear_protos[];
 
 /**
- * List of ALPN protocol identifiers that we suport in HTTP/1 Upgrade:
- * negotiations.
+ * List of ALPN protocol identifiers that we support in TLS encrypted 
+ * negotiations. NULL terminated.
  */
-extern const char *h2_upgrade_protos[];
-extern apr_size_t h2_upgrade_protos_len;
+extern const char *h2_tls_protos[];
 
 /**
  * The magic PRIamble of RFC 7540 that is always sent when starting

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_h2.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_io.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.c&p1=httpd/httpd/trunk/modules/http2/h2_io.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_io.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.c Mon Sep  7 17:37:19 2015
@@ -30,6 +30,7 @@ h2_io *h2_io_create(int id, apr_pool_t *
     h2_io *io = apr_pcalloc(pool, sizeof(*io));
     if (io) {
         io->id = id;
+        io->pool = pool;
         io->bbin = NULL;
         io->bbout = apr_brigade_create(pool, bucket_alloc);
         io->response = apr_pcalloc(pool, sizeof(h2_response));
@@ -39,9 +40,7 @@ h2_io *h2_io_create(int id, apr_pool_t *
 
 static void h2_io_cleanup(h2_io *io)
 {
-    if (io->response) {
-        h2_response_cleanup(io->response);
-    }
+    (void)io;
 }
 
 void h2_io_destroy(h2_io *io)
@@ -73,14 +72,16 @@ apr_status_t h2_io_in_read(h2_io *io, ap
                            apr_size_t maxlen)
 {
     apr_off_t start_len = 0;
+    apr_bucket *last;
+    apr_status_t status;
 
     if (!io->bbin || APR_BRIGADE_EMPTY(io->bbin)) {
         return io->eos_in? APR_EOF : APR_EAGAIN;
     }
     
     apr_brigade_length(bb, 1, &start_len);
-    apr_bucket *last = APR_BRIGADE_LAST(bb);
-    apr_status_t status = h2_util_move(bb, io->bbin, maxlen, 0, 
+    last = APR_BRIGADE_LAST(bb);
+    status = h2_util_move(bb, io->bbin, maxlen, 0, 
                                        "h2_io_in_read");
     if (status == APR_SUCCESS) {
         apr_bucket *nlast = APR_BRIGADE_LAST(bb);

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.c
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.h (from r1690248, httpd/httpd/trunk/modules/http2/h2_io.h)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.h?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.h&p1=httpd/httpd/trunk/modules/http2/h2_io.h&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_io.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.h Mon Sep  7 17:37:19 2015
@@ -29,6 +29,7 @@ typedef struct h2_io h2_io;
 
 struct h2_io {
     int id;                      /* stream identifier */
+    apr_pool_t *pool;            /* stream pool */
     apr_bucket_brigade *bbin;    /* input data for stream */
     int eos_in;
     int task_done;

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io_set.c (from r1690248, httpd/httpd/trunk/modules/http2/h2_io_set.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io_set.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io_set.c&p1=httpd/httpd/trunk/modules/http2/h2_io_set.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_io_set.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io_set.c Mon Sep  7 17:37:19 2015
@@ -47,7 +47,8 @@ h2_io_set *h2_io_set_create(apr_pool_t *
 
 void h2_io_set_destroy(h2_io_set *sp)
 {
-    for (int i = 0; i < sp->list->nelts; ++i) {
+    int i;
+    for (i = 0; i < sp->list->nelts; ++i) {
         h2_io *io = h2_io_IDX(sp->list, i);
         h2_io_destroy(io);
     }
@@ -66,9 +67,13 @@ h2_io *h2_io_set_get(h2_io_set *sp, int
     /* we keep the array sorted by id, so lookup can be done
      * by bsearch.
      */
-    h2_io key = { stream_id, NULL, 0, 0, 0, NULL, NULL, NULL, NULL, 0 };
+    h2_io **ps;
+    h2_io key;
     h2_io *pkey = &key;
-    h2_io **ps = bsearch(&pkey, sp->list->elts, sp->list->nelts, 
+
+    memset(&key, 0, sizeof(key));
+    key.id = stream_id;
+    ps = bsearch(&pkey, sp->list->elts, sp->list->nelts, 
                          sp->list->elt_size, h2_stream_id_cmp);
     return ps? *ps : NULL;
 }
@@ -76,7 +81,8 @@ h2_io *h2_io_set_get(h2_io_set *sp, int
 h2_io *h2_io_set_get_highest_prio(h2_io_set *set)
 {
     h2_io *highest = NULL;
-    for (int i = 0; i < set->list->nelts; ++i) {
+    int i;
+    for (i = 0; i < set->list->nelts; ++i) {
         h2_io *io = h2_io_IDX(set->list, i);
         if (!highest /*|| io-prio even higher */ ) {
             highest = io;
@@ -95,13 +101,14 @@ apr_status_t h2_io_set_add(h2_io_set *sp
 {
     h2_io *existing = h2_io_set_get(sp, io->id);
     if (!existing) {
+        int last;
         APR_ARRAY_PUSH(sp->list, h2_io*) = io;
         /* Normally, streams get added in ascending order if id. We
          * keep the array sorted, so we just need to check of the newly
          * appended stream has a lower id than the last one. if not,
          * sorting is not necessary.
          */
-        int last = sp->list->nelts - 1;
+        last = sp->list->nelts - 1;
         if (last > 0 
             && (h2_io_IDX(sp->list, last)->id 
                 < h2_io_IDX(sp->list, last-1)->id)) {
@@ -113,11 +120,13 @@ apr_status_t h2_io_set_add(h2_io_set *sp
 
 h2_io *h2_io_set_remove(h2_io_set *sp, h2_io *io)
 {
-    for (int i = 0; i < sp->list->nelts; ++i) {
+    int i;
+    for (i = 0; i < sp->list->nelts; ++i) {
         h2_io *e = h2_io_IDX(sp->list, i);
         if (e == io) {
+            int n;
             --sp->list->nelts;
-            int n = sp->list->nelts - i;
+            n = sp->list->nelts - i;
             if (n > 0) {
                 /* Close the hole in the array by moving the upper
                  * parts down one step.
@@ -133,7 +142,8 @@ h2_io *h2_io_set_remove(h2_io_set *sp, h
 
 void h2_io_set_destroy_all(h2_io_set *sp)
 {
-    for (int i = 0; i < sp->list->nelts; ++i) {
+    int i;
+    for (i = 0; i < sp->list->nelts; ++i) {
         h2_io *io = h2_io_IDX(sp->list, i);
         h2_io_destroy(io);
     }
@@ -154,7 +164,8 @@ int h2_io_set_is_empty(h2_io_set *sp)
 void h2_io_set_iter(h2_io_set *sp,
                         h2_io_set_iter_fn *iter, void *ctx)
 {
-    for (int i = 0; i < sp->list->nelts; ++i) {
+    int i;
+    for (i = 0; i < sp->list->nelts; ++i) {
         h2_io *s = h2_io_IDX(sp->list, i);
         if (!iter(ctx, s)) {
             break;

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io_set.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_io_set.h
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message