]> granicus.if.org Git - apache/commitdiff
Merge of 1742260,1742359,1742444,1742445,1742446,1742447,1742460,1743335,1743517...
authorStefan Eissing <icing@apache.org>
Sat, 14 May 2016 11:49:01 +0000 (11:49 +0000)
committerStefan Eissing <icing@apache.org>
Sat, 14 May 2016 11:49:01 +0000 (11:49 +0000)
mod_http2/mod_proxy_http2 update with latest changes from trunk to 1.5.4.
Update of CMake and Netware makefiles.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1743815 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
CMakeLists.txt
modules/http2/NWGNUmod_http2
modules/http2/h2_h2.c
modules/http2/h2_mplx.c
modules/http2/h2_proxy_session.c
modules/http2/h2_proxy_session.h
modules/http2/h2_session.c
modules/http2/h2_util.c
modules/http2/h2_version.h
modules/http2/mod_proxy_http2.c

diff --git a/CHANGES b/CHANGES
index e1a3b49d45d8598f92d672bcd954c4df455e5d6f..58f7712adb7c5a537372539abef7ef638f3f4904 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,12 @@
 
 Changes with Apache 2.4.21
 
+  *) mod_proxy_http2: new experimental http2 proxy module for h2: and h2c: proxy
+     urls. Part of the httpd mod_proxy framework, common settings apply.
+     Requests from the same HTTP/2 frontend connection against the same backend
+     are aggregated on a single connection.
+     [Stefan Eissing]
+  
   *) mod_http2: slave connections have conn_rec->aborted flag set when a stream
      has been reset by the client. [Stefan Eissing]
 
index fd45a27c467006633d3627d9d8769edf525efb59..b5da0b616627946724644adb5542ee8a6b9c990e 100644 (file)
@@ -319,6 +319,7 @@ SET(MODULE_LIST
   "modules/proxy/mod_proxy_http+I+Apache proxy HTTP module.  Requires and is enabled by --enable-proxy."
   "modules/proxy/mod_proxy_scgi+I+Apache proxy SCGI module.  Requires and is enabled by --enable-proxy."
   "modules/proxy/mod_proxy_wstunnel+I+Apache proxy Websocket Tunnel module.  Requires and is enabled by --enable-proxy."
+  "modules/http2/mod_proxy_http2+i+Apache proxy HTTP/2 module.  Requires --enable-proxy."
   "modules/session/mod_session+I+session module"
   "modules/session/mod_session_cookie+I+session cookie module"
   "modules/session/mod_session_crypto+i+session crypto module"
@@ -430,6 +431,13 @@ IF(LIBXML2_FOUND)
 ENDIF()
 SET(mod_proxy_scgi_extra_libs        mod_proxy)
 SET(mod_proxy_wstunnel_extra_libs    mod_proxy)
+SET(mod_proxy_http2_requires               NGHTTP2_FOUND)
+SET(mod_proxy_http2_extra_defines          ssize_t=long)
+SET(mod_proxy_http2_extra_includes         ${NGHTTP2_INCLUDE_DIR})
+SET(mod_proxy_http2_extra_libs             ${NGHTTP2_LIBRARIES} mod_proxy)
+SET(mod_proxy_http2_extra_sources
+  modules/http2/h2_proxy_session.c   modules/http2/h2_util.c
+)
 SET(mod_ratelimit_extra_defines      AP_RL_DECLARE_EXPORT)
 SET(mod_sed_extra_sources
   modules/filters/regexp.c           modules/filters/sed0.c
index 5a6a60b36fa3ba34760188296746bfa4a63b5d42..e9c48a4009bfe2d7bb9bf6f5a23babef473e5df9 100644 (file)
@@ -389,6 +389,7 @@ $(OBJDIR)/mod_http2.imp : NWGNUmod_http2
        @echo $(DL) nghttp2_session_callbacks_set_send_callback,$(DL) >> $@
        @echo $(DL) nghttp2_session_client_new2,$(DL) >> $@
        @echo $(DL) nghttp2_session_consume,$(DL) >> $@
+       @echo $(DL) nghttp2_session_consume_connection,$(DL) >> $@
        @echo $(DL) nghttp2_session_del,$(DL) >> $@
        @echo $(DL) nghttp2_session_get_remote_settings,$(DL) >> $@
        @echo $(DL) nghttp2_session_get_stream_user_data,$(DL) >> $@
index 5329f3171a50319365307b6dcdd3b18178a46b17..825cd77e78581eeffd76cc5d0e10216d2b5708d0 100644 (file)
@@ -485,9 +485,9 @@ int h2_is_acceptable_connection(conn_rec *c, int require_all)
             if (strncmp("TLS", val, 3) 
                 || !strcmp("TLSv1", val) 
                 || !strcmp("TLSv1.1", val)) {
-            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03050)
-                          "h2_h2(%ld): tls protocol not suitable: %s", 
-                          (long)c->id, val);
+                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03050)
+                              "h2_h2(%ld): tls protocol not suitable: %s", 
+                              (long)c->id, val);
                 return 0;
             }
         }
index 3ae02f4fd2ebdf56319403be47670aad4372c7cf..da5829f3a99661e48dac8b0c5e0cbe3e9121e583 100644 (file)
@@ -465,8 +465,10 @@ static int task_print(void *ctx, void *val)
 {
     h2_mplx *m = ctx;
     h2_task *task = val;
-    h2_stream *stream = h2_ihash_get(m->streams, task->stream_id);
-    if (task->request) {
+
+    if (task && task->request) {
+        h2_stream *stream = h2_ihash_get(m->streams, task->stream_id);
+
         ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, /* NO APLOGNO */
                       "->03198: h2_stream(%s): %s %s %s -> %s %d"
                       "[orph=%d/started=%d/done=%d]", 
@@ -488,6 +490,15 @@ static int task_print(void *ctx, void *val)
     return 1;
 }
 
+static int task_abort_connection(void *ctx, void *val)
+{
+    h2_task *task = val;
+    if (task->c) {
+        task->c->aborted = 1;
+    }
+    return 1;
+}
+
 apr_status_t h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
 {
     apr_status_t status;
@@ -537,6 +548,8 @@ apr_status_t h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
          * and workers *should* return in a timely fashion.
          */
         for (i = 0; m->workers_busy > 0; ++i) {
+            h2_ihash_iter(m->tasks, task_abort_connection, m);
+            
             m->join_wait = wait;
             status = apr_thread_cond_timedwait(wait, m->lock, apr_time_from_sec(wait_secs));
             
@@ -762,12 +775,17 @@ apr_status_t h2_mplx_out_open(h2_mplx *m, int stream_id, h2_response *response)
 static apr_status_t out_close(h2_mplx *m, h2_task *task)
 {
     apr_status_t status = APR_SUCCESS;
-    h2_stream *stream = h2_ihash_get(m->streams, task->stream_id);
+    h2_stream *stream;
     
-    if (!task || !stream) {
+    if (!task) {
         return APR_ECONNABORTED;
     }
-    
+
+    stream = h2_ihash_get(m->streams, task->stream_id);
+    if (!stream) {
+        return APR_ECONNABORTED;
+    }
+
     if (!task->response && !task->rst_error) {
         /* In case a close comes before a response was created,
          * insert an error one so that our streams can properly
index 27aa440af11998d5a1de3d7e998b164ad71aa2c7..34b584909d04e97d12ee0ffcde660d1a376fc9cb 100644 (file)
@@ -23,8 +23,6 @@
 
 #include "mod_http2.h"
 #include "h2.h"
-#include "h2_int_queue.h"
-#include "h2_request.h"
 #include "h2_util.h"
 #include "h2_proxy_session.h"
 
@@ -212,7 +210,7 @@ static void process_proxy_header(request_rec *r, const char *n, const char *v)
     int i;
     
     for (i = 0; transform_hdrs[i].name; ++i) {
-        if (!strcasecmp(transform_hdrs[i].name, n)) {
+        if (!h2_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));
@@ -338,10 +336,10 @@ static int on_data_chunk_recv(nghttp2_session *ngh2, uint8_t flags,
     
     stream = nghttp2_session_get_stream_user_data(ngh2, stream_id);
     if (!stream) {
-        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, stream->r, APLOGNO(03358)
-                      "h2_proxy_session(%s): recv data chunk for "
-                      "unknown stream %d, ignored", 
-                      session->id, stream_id);
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(03358)
+                     "h2_proxy_session(%s): recv data chunk for "
+                     "unknown stream %d, ignored", 
+                     session->id, stream_id);
         return 0;
     }
     
@@ -355,10 +353,10 @@ static int on_data_chunk_recv(nghttp2_session *ngh2, uint8_t flags,
     b = apr_bucket_transient_create((const char*)data, len, 
                                     stream->r->connection->bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(stream->output, b);
-    if (flags & NGHTTP2_DATA_FLAG_EOF) {
-        b = apr_bucket_flush_create(stream->r->connection->bucket_alloc);
-        APR_BRIGADE_INSERT_TAIL(stream->output, b);
-    }
+    /* always flush after a DATA frame, as we have no other indication
+     * of buffer use */
+    b = apr_bucket_flush_create(stream->r->connection->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(stream->output, b);
     
     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, stream->r, APLOGNO(03359)
                   "h2_proxy_session(%s): pass response data for "
@@ -424,9 +422,9 @@ static ssize_t stream_data_read(nghttp2_session *ngh2, int32_t stream_id,
     *data_flags = 0;
     stream = nghttp2_session_get_stream_user_data(ngh2, stream_id);
     if (!stream) {
-        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, stream->r, APLOGNO(03361)
-                      "h2_proxy_stream(%s): data_read, stream %d not found", 
-                      stream->session->id, stream_id);
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(03361)
+                     "h2_proxy_stream(%s): data_read, stream %d not found", 
+                     stream->session->id, stream_id);
         return NGHTTP2_ERR_CALLBACK_FAILURE;
     }
     
@@ -554,9 +552,11 @@ static apr_status_t session_start(h2_proxy_session *session)
     apr_socket_t *s;
     
     s = ap_get_conn_socket(session->c);
+#if (!defined(WIN32) && !defined(NETWARE)) || defined(DOXYGEN)
     if (s) {
         ap_sock_disable_nagle(s);
     }
+#endif
     
     settings[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
     settings[0].value = 0;
@@ -581,6 +581,7 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,
     h2_proxy_stream *stream;
     apr_uri_t puri;
     const char *authority, *scheme, *path;
+    apr_status_t status;
 
     stream = apr_pcalloc(r->pool, sizeof(*stream));
 
@@ -593,9 +594,12 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,
     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);
+    stream->req = h2_req_create(1, stream->pool, 0);
+
+    status = apr_uri_parse(stream->pool, url, &puri);
+    if (status != APR_SUCCESS)
+        return status;
 
-    apr_uri_parse(stream->pool, url, &puri);
     scheme = (strcmp(puri.scheme, "h2")? "http" : "https");
     authority = puri.hostname;
     if (!ap_strchr_c(authority, ':') && puri.port
@@ -604,8 +608,8 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,
         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);
+    h2_req_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);
@@ -647,11 +651,6 @@ static apr_status_t submit_stream(h2_proxy_session *session, h2_proxy_stream *st
                       session->id, stream->req->authority, stream->req->path,
                       rv);
     }
-    else {
-        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, 
-                      "h2_proxy_session(%s-%d): submit %s%s", 
-                      session->id, rv, stream->req->authority, stream->req->path);
-    }
     
     if (rv > 0) {
         stream->id = rv;
@@ -768,7 +767,7 @@ apr_status_t h2_proxy_session_submit(h2_proxy_session *session,
     apr_status_t status;
     
     status = open_stream(session, url, r, &stream);
-    if (status == OK) {
+    if (status == APR_SUCCESS) {
         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03381)
                       "process stream(%d): %s %s%s, original: %s", 
                       stream->id, stream->req->method, 
@@ -884,7 +883,7 @@ static void ev_init(h2_proxy_session *session, int arg, const char *msg)
 {
     switch (session->state) {
         case H2_PROXYS_ST_INIT:
-            if (h2_ihash_is_empty(session->streams)) {
+            if (h2_ihash_empty(session->streams)) {
                 transit(session, "init", H2_PROXYS_ST_IDLE);
             }
             else {
@@ -991,7 +990,7 @@ static void ev_no_io(h2_proxy_session *session, int arg, const char *msg)
              * CPU cycles. Ideally, we'd like to do a blocking read, but that
              * is not possible if we have scheduled tasks and wait
              * for them to produce something. */
-            if (h2_ihash_is_empty(session->streams)) {
+            if (h2_ihash_empty(session->streams)) {
                 if (!is_accepting_streams(session)) {
                     /* We are no longer accepting new streams and have
                      * finished processing existing ones. Time to leave. */
@@ -1295,7 +1294,7 @@ static int done_iter(void *udata, void *val)
 void h2_proxy_session_cleanup(h2_proxy_session *session, 
                               h2_proxy_request_done *done)
 {
-    if (session->streams && !h2_ihash_is_empty(session->streams)) {
+    if (session->streams && !h2_ihash_empty(session->streams)) {
         cleanup_iter_ctx ctx;
         ctx.session = session;
         ctx.done = done;
@@ -1334,7 +1333,7 @@ static int win_update_iter(void *udata, void *val)
 void h2_proxy_session_update_window(h2_proxy_session *session, 
                                     conn_rec *c, apr_off_t bytes)
 {
-    if (session->streams && !h2_ihash_is_empty(session->streams)) {
+    if (session->streams && !h2_ihash_empty(session->streams)) {
         win_update_ctx ctx;
         ctx.session = session;
         ctx.c = c;
index 7078981c7a61ba6c473ce391683f7dbdacc9b64b..52be5c6b37b6207085921e0b509ddb81cc25f718 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <nghttp2/nghttp2.h>
 
-struct h2_int_queue;
+struct h2_iqueue;
 struct h2_ihash_t;
 
 typedef enum {
@@ -74,7 +74,7 @@ struct h2_proxy_session {
     apr_interval_time_t wait_timeout;
 
     struct h2_ihash_t *streams;
-    struct h2_int_queue *suspended;
+    struct h2_iqueue *suspended;
     apr_size_t remote_max_concurrent;
     int last_stream_id;     /* last stream id processed by backend, or 0 */
     
index 79b3fbc563a578f63a05497224dc5c10eccdc224..ce5c5c771bb33efa548ff18e63227500d49a6f41 100644 (file)
@@ -57,7 +57,7 @@ static int h2_session_status_from_apr_status(apr_status_t rv)
         return NGHTTP2_ERR_WOULDBLOCK;
     }
     else if (APR_STATUS_IS_EOF(rv)) {
-            return NGHTTP2_ERR_EOF;
+        return NGHTTP2_ERR_EOF;
     }
     return NGHTTP2_ERR_PROTO;
 }
index e6fe45965f54faed457e097731b8c554cac09e3f..4cfa1649e4018ac442c96df6b48285d222dcd435 100644 (file)
@@ -1465,7 +1465,7 @@ int h2_util_frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen)
         }
         case NGHTTP2_GOAWAY: {
             size_t len = (frame->goaway.opaque_data_len < s_len)?
-            frame->goaway.opaque_data_len : s_len-1;
+                frame->goaway.opaque_data_len : s_len-1;
             memcpy(scratch, frame->goaway.opaque_data, len);
             scratch[len] = '\0';
             return apr_snprintf(buffer, maxlen, "GOAWAY[error=%d, reason='%s', "
index 13cd3df244a7ea9879c57869813f7c1bb6278eec..a3c13d9a46125e3a08c26866ded5f822a544706c 100644 (file)
@@ -26,7 +26,7 @@
  * @macro
  * Version number of the http2 module as c string
  */
-#define MOD_HTTP2_VERSION "1.5.3"
+#define MOD_HTTP2_VERSION "1.5.4"
 
 /**
  * @macro
@@ -34,7 +34,7 @@
  * release. This is a 24 bit number with 8 bits for major number, 8 bits
  * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
  */
-#define MOD_HTTP2_VERSION_NUM 0x010503
+#define MOD_HTTP2_VERSION_NUM 0x010504
 
 
 #endif /* mod_h2_h2_version_h */
index 6722cb7333145c54921b80f3878e7be6d55ab461..d551f24e818f400999b23b02812a83955c17494b 100644 (file)
@@ -21,7 +21,6 @@
 
 
 #include "mod_proxy_http2.h"
-#include "h2_int_queue.h"
 #include "h2_request.h"
 #include "h2_util.h"
 #include "h2_version.h"
@@ -126,12 +125,12 @@ static int proxy_http2_canon(request_rec *r, char *url)
     apr_port_t port, def_port;
 
     /* ap_port_of_scheme() */
-    if (strncasecmp(url, "h2c:", 4) == 0) {
+    if (h2_casecmpstrn(url, "h2c:", 4) == 0) {
         url += 4;
         scheme = "h2c";
         http_scheme = "http";
     }
-    else if (strncasecmp(url, "h2:", 3) == 0) {
+    else if (h2_casecmpstrn(url, "h2:", 3) == 0) {
         url += 3;
         scheme = "h2";
         http_scheme = "https";
@@ -260,7 +259,7 @@ static apr_status_t add_request(h2_proxy_session *session, request_rec *r)
     apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu",
                    ctx->p_conn->connection->local_addr->port));
     status = h2_proxy_session_submit(session, url, r);
-    if (status != OK) {
+    if (status != APR_SUCCESS) {
         ap_log_cerror(APLOG_MARK, APLOG_ERR, status, r->connection, APLOGNO(03351)
                       "pass request body failed to %pI (%s) from %s (%s)",
                       ctx->p_conn->addr, ctx->p_conn->hostname ? 
@@ -378,7 +377,7 @@ static apr_status_t proxy_engine_run(h2_proxy_ctx *ctx) {
                 status = s2;
                 break;
             }
-            if (!ctx->next && h2_ihash_is_empty(ctx->session->streams)) {
+            if (!ctx->next && h2_ihash_empty(ctx->session->streams)) {
                 break;
             }
         }
@@ -605,6 +604,7 @@ cleanup:
         /* Still more to do, tear down old conn and start over */
         if (ctx->p_conn) {
             ctx->p_conn->close = 1;
+            /*only in trunk so far */
             /*proxy_run_detach_backend(r, ctx->p_conn);*/
             ap_proxy_release_connection(ctx->proxy_func, ctx->p_conn, ctx->server);
             ctx->p_conn = NULL;
@@ -618,7 +618,8 @@ cleanup:
             /* close socket when errors happened or session shut down (EOF) */
             ctx->p_conn->close = 1;
         }
-/*        proxy_run_detach_backend(ctx->rbase, ctx->p_conn);*/
+        /*only in trunk so far */
+        /*proxy_run_detach_backend(ctx->rbase, ctx->p_conn);*/
         ap_proxy_release_connection(ctx->proxy_func, ctx->p_conn, ctx->server);
         ctx->p_conn = NULL;
     }