]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge of r1747550 from trunk:
authorStefan Eissing <icing@apache.org>
Tue, 14 Jun 2016 08:51:31 +0000 (08:51 +0000)
committerStefan Eissing <icing@apache.org>
Tue, 14 Jun 2016 08:51:31 +0000 (08:51 +0000)
mod_proxy_http2 no longer shares objects with mod_http2
h2_casecmpstr eliminated, uses backported ap_cstr_casecmp*

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

CMakeLists.txt
modules/http2/NWGNUmod_http2
modules/http2/config2.m4
modules/http2/h2_mplx.h
modules/http2/h2_proxy_session.c
modules/http2/h2_proxy_util.c [new file with mode: 0644]
modules/http2/h2_proxy_util.h [new file with mode: 0644]
modules/http2/h2_util.c
modules/http2/h2_util.h
modules/http2/mod_proxy_http2.c
modules/http2/mod_proxy_http2.dsp

index b5da0b616627946724644adb5542ee8a6b9c990e..3f4b6d57e0d5c30a5d60aaa1cf9d4518e614b675 100644 (file)
@@ -436,7 +436,7 @@ 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
+  modules/http2/h2_proxy_session.c   modules/http2/h2_proxy_util.c
 )
 SET(mod_ratelimit_extra_defines      AP_RL_DECLARE_EXPORT)
 SET(mod_sed_extra_sources
index 755537cd85cabfe0a0d0b986d77d77e9510e9f3d..e9c48a4009bfe2d7bb9bf6f5a23babef473e5df9 100644 (file)
@@ -355,7 +355,6 @@ $(OBJDIR)/mod_http2.imp : NWGNUmod_http2
        @echo $(DL)GEN  $@$(DL)
        @echo $(DL) (HTTP2)$(DL) > $@
        @echo $(DL) http2_module,$(DL) >> $@
-       @echo $(DL) h2_casecmpstrn,$(DL) >> $@
        @echo $(DL) h2_ihash_add,$(DL) >> $@
        @echo $(DL) h2_ihash_clear,$(DL) >> $@
        @echo $(DL) h2_ihash_count,$(DL) >> $@
index b17387c9ed2ead462ec44c63df77fab174ecdb92..a77ad8089980c12aead7b6e3b56cf316692d0f87 100644 (file)
@@ -201,7 +201,7 @@ dnl #  list of module object files
 proxy_http2_objs="dnl
 mod_proxy_http2.lo dnl
 h2_proxy_session.lo dnl
-h2_util.lo dnl
+h2_proxy_util.lo dnl
 "
 
 dnl # hook module into the Autoconf mechanism (--enable-proxy_http2)
index f2f60fc9b34645cf622d4e4631ede6ab542a516a..821e6d65dfcb9773d1dc8ea21770b15c1dbd0ecb 100644 (file)
@@ -40,7 +40,6 @@ struct apr_thread_cond_t;
 struct h2_bucket_beam;
 struct h2_config;
 struct h2_ihash_t;
-struct h2_ilist_t;
 struct h2_response;
 struct h2_task;
 struct h2_stream;
index 919fe4a4c36a6ab6fbed46b25bc523e85dbcf621..b7dadca147d15dcc0acd82ccaad46c6755983c20 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "mod_http2.h"
 #include "h2.h"
-#include "h2_util.h"
+#include "h2_proxy_util.h"
 #include "h2_proxy_session.h"
 
 APLOG_USE_MODULE(proxy_http2);
@@ -211,7 +211,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 (!h2_casecmpstr(transform_hdrs[i].name, n)) {
+        if (!ap_cstr_casecmp(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));
diff --git a/modules/http2/h2_proxy_util.c b/modules/http2/h2_proxy_util.c
new file mode 100644 (file)
index 0000000..839f4a5
--- /dev/null
@@ -0,0 +1,705 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <apr_strings.h>
+
+#include <httpd.h>
+#include <http_core.h>
+#include <http_log.h>
+#include <http_request.h>
+
+#include <nghttp2/nghttp2.h>
+
+#include "h2.h"
+#include "h2_proxy_util.h"
+
+/* h2_log2(n) iff n is a power of 2 */
+unsigned char h2_log2(apr_uint32_t n)
+{
+    int lz = 0;
+    if (!n) {
+        return 0;
+    }
+    if (!(n & 0xffff0000u)) {
+        lz += 16;
+        n = (n << 16);
+    }
+    if (!(n & 0xff000000u)) {
+        lz += 8;
+        n = (n << 8);
+    }
+    if (!(n & 0xf0000000u)) {
+        lz += 4;
+        n = (n << 4);
+    }
+    if (!(n & 0xc0000000u)) {
+        lz += 2;
+        n = (n << 2);
+    }
+    if (!(n & 0x80000000u)) {
+        lz += 1;
+    }
+    
+    return 31 - lz;
+}
+
+/*******************************************************************************
+ * ihash - hash for structs with int identifier
+ ******************************************************************************/
+struct h2_ihash_t {
+    apr_hash_t *hash;
+    size_t ioff;
+};
+
+static unsigned int ihash(const char *key, apr_ssize_t *klen)
+{
+    return (unsigned int)(*((int*)key));
+}
+
+h2_ihash_t *h2_ihash_create(apr_pool_t *pool, size_t offset_of_int)
+{
+    h2_ihash_t *ih = apr_pcalloc(pool, sizeof(h2_ihash_t));
+    ih->hash = apr_hash_make_custom(pool, ihash);
+    ih->ioff = offset_of_int;
+    return ih;
+}
+
+size_t h2_ihash_count(h2_ihash_t *ih)
+{
+    return apr_hash_count(ih->hash);
+}
+
+int h2_ihash_empty(h2_ihash_t *ih)
+{
+    return apr_hash_count(ih->hash) == 0;
+}
+
+void *h2_ihash_get(h2_ihash_t *ih, int id)
+{
+    return apr_hash_get(ih->hash, &id, sizeof(id));
+}
+
+typedef struct {
+    h2_ihash_iter_t *iter;
+    void *ctx;
+} iter_ctx;
+
+static int ihash_iter(void *ctx, const void *key, apr_ssize_t klen, 
+                     const void *val)
+{
+    iter_ctx *ictx = ctx;
+    return ictx->iter(ictx->ctx, (void*)val); /* why is this passed const?*/
+}
+
+int h2_ihash_iter(h2_ihash_t *ih, h2_ihash_iter_t *fn, void *ctx)
+{
+    iter_ctx ictx;
+    ictx.iter = fn;
+    ictx.ctx = ctx;
+    return apr_hash_do(ihash_iter, &ictx, ih->hash);
+}
+
+void h2_ihash_add(h2_ihash_t *ih, void *val)
+{
+    apr_hash_set(ih->hash, ((char *)val + ih->ioff), sizeof(int), val);
+}
+
+void h2_ihash_remove(h2_ihash_t *ih, int id)
+{
+    apr_hash_set(ih->hash, &id, sizeof(id), NULL);
+}
+
+void h2_ihash_remove_val(h2_ihash_t *ih, void *val)
+{
+    int id = *((int*)((char *)val + ih->ioff));
+    apr_hash_set(ih->hash, &id, sizeof(id), NULL);
+}
+
+
+void h2_ihash_clear(h2_ihash_t *ih)
+{
+    apr_hash_clear(ih->hash);
+}
+
+typedef struct {
+    h2_ihash_t *ih;
+    void **buffer;
+    size_t max;
+    size_t len;
+} collect_ctx;
+
+static int collect_iter(void *x, void *val)
+{
+    collect_ctx *ctx = x;
+    if (ctx->len < ctx->max) {
+        ctx->buffer[ctx->len++] = val;
+        return 1;
+    }
+    return 0;
+}
+
+size_t h2_ihash_shift(h2_ihash_t *ih, void **buffer, size_t max)
+{
+    collect_ctx ctx;
+    size_t i;
+    
+    ctx.ih = ih;
+    ctx.buffer = buffer;
+    ctx.max = max;
+    ctx.len = 0;
+    h2_ihash_iter(ih, collect_iter, &ctx);
+    for (i = 0; i < ctx.len; ++i) {
+        h2_ihash_remove_val(ih, buffer[i]);
+    }
+    return ctx.len;
+}
+
+typedef struct {
+    h2_ihash_t *ih;
+    int *buffer;
+    size_t max;
+    size_t len;
+} icollect_ctx;
+
+static int icollect_iter(void *x, void *val)
+{
+    icollect_ctx *ctx = x;
+    if (ctx->len < ctx->max) {
+        ctx->buffer[ctx->len++] = *((int*)((char *)val + ctx->ih->ioff));
+        return 1;
+    }
+    return 0;
+}
+
+size_t h2_ihash_ishift(h2_ihash_t *ih, int *buffer, size_t max)
+{
+    icollect_ctx ctx;
+    size_t i;
+    
+    ctx.ih = ih;
+    ctx.buffer = buffer;
+    ctx.max = max;
+    ctx.len = 0;
+    h2_ihash_iter(ih, icollect_iter, &ctx);
+    for (i = 0; i < ctx.len; ++i) {
+        h2_ihash_remove(ih, buffer[i]);
+    }
+    return ctx.len;
+}
+
+/*******************************************************************************
+ * iqueue - sorted list of int
+ ******************************************************************************/
+
+static void iq_grow(h2_iqueue *q, int nlen);
+static void iq_swap(h2_iqueue *q, int i, int j);
+static int iq_bubble_up(h2_iqueue *q, int i, int top, 
+                        h2_iq_cmp *cmp, void *ctx);
+static int iq_bubble_down(h2_iqueue *q, int i, int bottom, 
+                          h2_iq_cmp *cmp, void *ctx);
+
+h2_iqueue *h2_iq_create(apr_pool_t *pool, int capacity)
+{
+    h2_iqueue *q = apr_pcalloc(pool, sizeof(h2_iqueue));
+    if (q) {
+        q->pool = pool;
+        iq_grow(q, capacity);
+        q->nelts = 0;
+    }
+    return q;
+}
+
+int h2_iq_empty(h2_iqueue *q)
+{
+    return q->nelts == 0;
+}
+
+int h2_iq_count(h2_iqueue *q)
+{
+    return q->nelts;
+}
+
+
+void h2_iq_add(h2_iqueue *q, int sid, h2_iq_cmp *cmp, void *ctx)
+{
+    int i;
+    
+    if (q->nelts >= q->nalloc) {
+        iq_grow(q, q->nalloc * 2);
+    }
+    
+    i = (q->head + q->nelts) % q->nalloc;
+    q->elts[i] = sid;
+    ++q->nelts;
+    
+    if (cmp) {
+        /* bubble it to the front of the queue */
+        iq_bubble_up(q, i, q->head, cmp, ctx);
+    }
+}
+
+int h2_iq_remove(h2_iqueue *q, int sid)
+{
+    int i;
+    for (i = 0; i < q->nelts; ++i) {
+        if (sid == q->elts[(q->head + i) % q->nalloc]) {
+            break;
+        }
+    }
+    
+    if (i < q->nelts) {
+        ++i;
+        for (; i < q->nelts; ++i) {
+            q->elts[(q->head+i-1)%q->nalloc] = q->elts[(q->head+i)%q->nalloc];
+        }
+        --q->nelts;
+        return 1;
+    }
+    return 0;
+}
+
+void h2_iq_clear(h2_iqueue *q)
+{
+    q->nelts = 0;
+}
+
+void h2_iq_sort(h2_iqueue *q, h2_iq_cmp *cmp, void *ctx)
+{
+    /* Assume that changes in ordering are minimal. This needs,
+     * best case, q->nelts - 1 comparisions to check that nothing
+     * changed.
+     */
+    if (q->nelts > 0) {
+        int i, ni, prev, last;
+        
+        /* Start at the end of the queue and create a tail of sorted
+         * entries. Make that tail one element longer in each iteration.
+         */
+        last = i = (q->head + q->nelts - 1) % q->nalloc;
+        while (i != q->head) {
+            prev = (q->nalloc + i - 1) % q->nalloc;
+            
+            ni = iq_bubble_up(q, i, prev, cmp, ctx);
+            if (ni == prev) {
+                /* i bubbled one up, bubble the new i down, which
+                 * keeps all tasks below i sorted. */
+                iq_bubble_down(q, i, last, cmp, ctx);
+            }
+            i = prev;
+        };
+    }
+}
+
+
+int h2_iq_shift(h2_iqueue *q)
+{
+    int sid;
+    
+    if (q->nelts <= 0) {
+        return 0;
+    }
+    
+    sid = q->elts[q->head];
+    q->head = (q->head + 1) % q->nalloc;
+    q->nelts--;
+    
+    return sid;
+}
+
+static void iq_grow(h2_iqueue *q, int nlen)
+{
+    if (nlen > q->nalloc) {
+        int *nq = apr_pcalloc(q->pool, sizeof(int) * nlen);
+        if (q->nelts > 0) {
+            int l = ((q->head + q->nelts) % q->nalloc) - q->head;
+            
+            memmove(nq, q->elts + q->head, sizeof(int) * l);
+            if (l < q->nelts) {
+                /* elts wrapped, append elts in [0, remain] to nq */
+                int remain = q->nelts - l;
+                memmove(nq + l, q->elts, sizeof(int) * remain);
+            }
+        }
+        q->elts = nq;
+        q->nalloc = nlen;
+        q->head = 0;
+    }
+}
+
+static void iq_swap(h2_iqueue *q, int i, int j)
+{
+    int x = q->elts[i];
+    q->elts[i] = q->elts[j];
+    q->elts[j] = x;
+}
+
+static int iq_bubble_up(h2_iqueue *q, int i, int top, 
+                        h2_iq_cmp *cmp, void *ctx) 
+{
+    int prev;
+    while (((prev = (q->nalloc + i - 1) % q->nalloc), i != top) 
+           && (*cmp)(q->elts[i], q->elts[prev], ctx) < 0) {
+        iq_swap(q, prev, i);
+        i = prev;
+    }
+    return i;
+}
+
+static int iq_bubble_down(h2_iqueue *q, int i, int bottom, 
+                          h2_iq_cmp *cmp, void *ctx)
+{
+    int next;
+    while (((next = (q->nalloc + i + 1) % q->nalloc), i != bottom) 
+           && (*cmp)(q->elts[i], q->elts[next], ctx) > 0) {
+        iq_swap(q, next, i);
+        i = next;
+    }
+    return i;
+}
+
+/*******************************************************************************
+ * h2_ngheader
+ ******************************************************************************/
+#define H2_HD_MATCH_LIT_CS(l, name)  \
+    ((strlen(name) == sizeof(l) - 1) && !apr_strnatcasecmp(l, name))
+
+static int h2_util_ignore_header(const char *name) 
+{
+    /* never forward, ch. 8.1.2.2 */
+    return (H2_HD_MATCH_LIT_CS("connection", name)
+            || H2_HD_MATCH_LIT_CS("proxy-connection", name)
+            || H2_HD_MATCH_LIT_CS("upgrade", name)
+            || H2_HD_MATCH_LIT_CS("keep-alive", name)
+            || H2_HD_MATCH_LIT_CS("transfer-encoding", name));
+}
+
+static int count_header(void *ctx, const char *key, const char *value)
+{
+    if (!h2_util_ignore_header(key)) {
+        (*((size_t*)ctx))++;
+    }
+    return 1;
+}
+
+#define NV_ADD_LIT_CS(nv, k, v)     add_header(nv, k, sizeof(k) - 1, v, strlen(v))
+#define NV_ADD_CS_CS(nv, k, v)      add_header(nv, k, strlen(k), v, strlen(v))
+
+static int add_header(h2_ngheader *ngh, 
+                      const char *key, size_t key_len,
+                      const char *value, size_t val_len)
+{
+    nghttp2_nv *nv = &ngh->nv[ngh->nvlen++];
+    
+    nv->name = (uint8_t*)key;
+    nv->namelen = key_len;
+    nv->value = (uint8_t*)value;
+    nv->valuelen = val_len;
+    return 1;
+}
+
+static int add_table_header(void *ctx, const char *key, const char *value)
+{
+    if (!h2_util_ignore_header(key)) {
+        add_header(ctx, key, strlen(key), value, strlen(value));
+    }
+    return 1;
+}
+
+h2_ngheader *h2_util_ngheader_make_req(apr_pool_t *p, 
+                                       const struct h2_request *req)
+{
+    
+    h2_ngheader *ngh;
+    size_t n;
+    
+    AP_DEBUG_ASSERT(req);
+    AP_DEBUG_ASSERT(req->scheme);
+    AP_DEBUG_ASSERT(req->authority);
+    AP_DEBUG_ASSERT(req->path);
+    AP_DEBUG_ASSERT(req->method);
+
+    n = 4;
+    apr_table_do(count_header, &n, req->headers, NULL);
+    
+    ngh = apr_pcalloc(p, sizeof(h2_ngheader));
+    ngh->nv =  apr_pcalloc(p, n * sizeof(nghttp2_nv));
+    NV_ADD_LIT_CS(ngh, ":scheme", req->scheme);
+    NV_ADD_LIT_CS(ngh, ":authority", req->authority);
+    NV_ADD_LIT_CS(ngh, ":path", req->path);
+    NV_ADD_LIT_CS(ngh, ":method", req->method);
+    apr_table_do(add_table_header, ngh, req->headers, NULL);
+
+    return ngh;
+}
+
+/*******************************************************************************
+ * header HTTP/1 <-> HTTP/2 conversions
+ ******************************************************************************/
+typedef struct {
+    const char *name;
+    size_t len;
+} literal;
+
+#define H2_DEF_LITERAL(n)   { (n), (sizeof(n)-1) }
+#define H2_LIT_ARGS(a)      (a),H2_ALEN(a)
+
+static literal IgnoredRequestHeaders[] = {
+    H2_DEF_LITERAL("expect"),
+    H2_DEF_LITERAL("upgrade"),
+    H2_DEF_LITERAL("connection"),
+    H2_DEF_LITERAL("keep-alive"),
+    H2_DEF_LITERAL("http2-settings"),
+    H2_DEF_LITERAL("proxy-connection"),
+    H2_DEF_LITERAL("transfer-encoding"),
+};
+static literal IgnoredProxyRespHds[] = {
+    H2_DEF_LITERAL("alt-svc"),
+};
+
+static int ignore_header(const literal *lits, size_t llen,
+                         const char *name, size_t nlen)
+{
+    const literal *lit;
+    int i;
+    
+    for (i = 0; i < llen; ++i) {
+        lit = &lits[i];
+        if (lit->len == nlen && !apr_strnatcasecmp(lit->name, name)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static int h2_req_ignore_header(const char *name, size_t len)
+{
+    return ignore_header(H2_LIT_ARGS(IgnoredRequestHeaders), name, len);
+}
+
+int h2_proxy_res_ignore_header(const char *name, size_t len)
+{
+    return (h2_req_ignore_header(name, len) 
+            || ignore_header(H2_LIT_ARGS(IgnoredProxyRespHds), name, len));
+}
+
+void h2_util_camel_case_header(char *s, size_t len)
+{
+    size_t start = 1;
+    size_t i;
+    for (i = 0; i < len; ++i) {
+        if (start) {
+            if (s[i] >= 'a' && s[i] <= 'z') {
+                s[i] -= 'a' - 'A';
+            }
+            
+            start = 0;
+        }
+        else if (s[i] == '-') {
+            start = 1;
+        }
+    }
+}
+
+/*******************************************************************************
+ * h2 request handling
+ ******************************************************************************/
+
+/** Match a header value against a string constance, case insensitive */
+#define H2_HD_MATCH_LIT(l, name, nlen)  \
+    ((nlen == sizeof(l) - 1) && !apr_strnatcasecmp(l, name))
+
+static apr_status_t h2_headers_add_h1(apr_table_t *headers, apr_pool_t *pool, 
+                                      const char *name, size_t nlen,
+                                      const char *value, size_t vlen)
+{
+    char *hname, *hvalue;
+    
+    if (h2_req_ignore_header(name, nlen)) {
+        return APR_SUCCESS;
+    }
+    else if (H2_HD_MATCH_LIT("cookie", name, nlen)) {
+        const char *existing = apr_table_get(headers, "cookie");
+        if (existing) {
+            char *nval;
+            
+            /* Cookie header come separately in HTTP/2, but need
+             * to be merged by "; " (instead of default ", ")
+             */
+            hvalue = apr_pstrndup(pool, value, vlen);
+            nval = apr_psprintf(pool, "%s; %s", existing, hvalue);
+            apr_table_setn(headers, "Cookie", nval);
+            return APR_SUCCESS;
+        }
+    }
+    else if (H2_HD_MATCH_LIT("host", name, nlen)) {
+        if (apr_table_get(headers, "Host")) {
+            return APR_SUCCESS; /* ignore duplicate */
+        }
+    }
+    
+    hname = apr_pstrndup(pool, name, nlen);
+    hvalue = apr_pstrndup(pool, value, vlen);
+    h2_util_camel_case_header(hname, nlen);
+    apr_table_mergen(headers, hname, hvalue);
+    
+    return APR_SUCCESS;
+}
+
+static h2_request *h2_req_createn(int id, apr_pool_t *pool, const char *method, 
+                                  const char *scheme, const char *authority, 
+                                  const char *path, apr_table_t *header, 
+                                  int serialize)
+{
+    h2_request *req = apr_pcalloc(pool, sizeof(h2_request));
+    
+    req->id             = id;
+    req->method         = method;
+    req->scheme         = scheme;
+    req->authority      = authority;
+    req->path           = path;
+    req->headers        = header? header : apr_table_make(pool, 10);
+    req->request_time   = apr_time_now();
+    req->serialize      = serialize;
+    
+    return req;
+}
+
+h2_request *h2_req_create(int id, apr_pool_t *pool, int serialize)
+{
+    return h2_req_createn(id, pool, NULL, NULL, NULL, NULL, NULL, serialize);
+}
+
+typedef struct {
+    apr_table_t *headers;
+    apr_pool_t *pool;
+} h1_ctx;
+
+static int set_h1_header(void *ctx, const char *key, const char *value)
+{
+    h1_ctx *x = ctx;
+    size_t klen = strlen(key);
+    if (!h2_req_ignore_header(key, klen)) {
+        h2_headers_add_h1(x->headers, x->pool, key, klen, value, strlen(value));
+    }
+    return 1;
+}
+
+apr_status_t h2_req_make(h2_request *req, apr_pool_t *pool,
+                         const char *method, const char *scheme, 
+                         const char *authority, const char *path, 
+                         apr_table_t *headers)
+{
+    h1_ctx x;
+
+    req->method    = method;
+    req->scheme    = scheme;
+    req->authority = authority;
+    req->path      = path;
+
+    AP_DEBUG_ASSERT(req->scheme);
+    AP_DEBUG_ASSERT(req->authority);
+    AP_DEBUG_ASSERT(req->path);
+    AP_DEBUG_ASSERT(req->method);
+
+    x.pool = pool;
+    x.headers = req->headers;
+    apr_table_do(set_h1_header, &x, headers, NULL);
+    return APR_SUCCESS;
+}
+
+/*******************************************************************************
+ * frame logging
+ ******************************************************************************/
+
+int h2_util_frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen)
+{
+    char scratch[128];
+    size_t s_len = sizeof(scratch)/sizeof(scratch[0]);
+    
+    switch (frame->hd.type) {
+        case NGHTTP2_DATA: {
+            return apr_snprintf(buffer, maxlen,
+                                "DATA[length=%d, flags=%d, stream=%d, padlen=%d]",
+                                (int)frame->hd.length, frame->hd.flags,
+                                frame->hd.stream_id, (int)frame->data.padlen);
+        }
+        case NGHTTP2_HEADERS: {
+            return apr_snprintf(buffer, maxlen,
+                                "HEADERS[length=%d, hend=%d, stream=%d, eos=%d]",
+                                (int)frame->hd.length,
+                                !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
+                                frame->hd.stream_id,
+                                !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM));
+        }
+        case NGHTTP2_PRIORITY: {
+            return apr_snprintf(buffer, maxlen,
+                                "PRIORITY[length=%d, flags=%d, stream=%d]",
+                                (int)frame->hd.length,
+                                frame->hd.flags, frame->hd.stream_id);
+        }
+        case NGHTTP2_RST_STREAM: {
+            return apr_snprintf(buffer, maxlen,
+                                "RST_STREAM[length=%d, flags=%d, stream=%d]",
+                                (int)frame->hd.length,
+                                frame->hd.flags, frame->hd.stream_id);
+        }
+        case NGHTTP2_SETTINGS: {
+            if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
+                return apr_snprintf(buffer, maxlen,
+                                    "SETTINGS[ack=1, stream=%d]",
+                                    frame->hd.stream_id);
+            }
+            return apr_snprintf(buffer, maxlen,
+                                "SETTINGS[length=%d, stream=%d]",
+                                (int)frame->hd.length, frame->hd.stream_id);
+        }
+        case NGHTTP2_PUSH_PROMISE: {
+            return apr_snprintf(buffer, maxlen,
+                                "PUSH_PROMISE[length=%d, hend=%d, stream=%d]",
+                                (int)frame->hd.length,
+                                !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
+                                frame->hd.stream_id);
+        }
+        case NGHTTP2_PING: {
+            return apr_snprintf(buffer, maxlen,
+                                "PING[length=%d, ack=%d, stream=%d]",
+                                (int)frame->hd.length,
+                                frame->hd.flags&NGHTTP2_FLAG_ACK,
+                                frame->hd.stream_id);
+        }
+        case NGHTTP2_GOAWAY: {
+            size_t len = (frame->goaway.opaque_data_len < s_len)?
+                frame->goaway.opaque_data_len : s_len-1;
+            memcpy(scratch, frame->goaway.opaque_data, len);
+            scratch[len] = '\0';
+            return apr_snprintf(buffer, maxlen, "GOAWAY[error=%d, reason='%s', "
+                                "last_stream=%d]", frame->goaway.error_code, 
+                                scratch, frame->goaway.last_stream_id);
+        }
+        case NGHTTP2_WINDOW_UPDATE: {
+            return apr_snprintf(buffer, maxlen,
+                                "WINDOW_UPDATE[stream=%d, incr=%d]",
+                                frame->hd.stream_id, 
+                                frame->window_update.window_size_increment);
+        }
+        default:
+            return apr_snprintf(buffer, maxlen,
+                                "type=%d[length=%d, flags=%d, stream=%d]",
+                                frame->hd.type, (int)frame->hd.length,
+                                frame->hd.flags, frame->hd.stream_id);
+    }
+}
diff --git a/modules/http2/h2_proxy_util.h b/modules/http2/h2_proxy_util.h
new file mode 100644 (file)
index 0000000..98f297f
--- /dev/null
@@ -0,0 +1,181 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __mod_h2__h2_proxy_util__
+#define __mod_h2__h2_proxy_util__
+
+/*******************************************************************************
+ * some debugging/format helpers
+ ******************************************************************************/
+struct h2_request;
+struct nghttp2_frame;
+
+int h2_util_frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen);
+
+/*******************************************************************************
+ * ihash - hash for structs with int identifier
+ ******************************************************************************/
+typedef struct h2_ihash_t h2_ihash_t;
+typedef int h2_ihash_iter_t(void *ctx, void *val);
+
+/**
+ * Create a hash for structures that have an identifying int member.
+ * @param pool the pool to use
+ * @param offset_of_int the offsetof() the int member in the struct
+ */
+h2_ihash_t *h2_ihash_create(apr_pool_t *pool, size_t offset_of_int);
+
+size_t h2_ihash_count(h2_ihash_t *ih);
+int h2_ihash_empty(h2_ihash_t *ih);
+void *h2_ihash_get(h2_ihash_t *ih, int id);
+
+/**
+ * Iterate over the hash members (without defined order) and invoke
+ * fn for each member until 0 is returned.
+ * @param ih the hash to iterate over
+ * @param fn the function to invoke on each member
+ * @param ctx user supplied data passed into each iteration call
+ * @return 0 if one iteration returned 0, otherwise != 0
+ */
+int h2_ihash_iter(h2_ihash_t *ih, h2_ihash_iter_t *fn, void *ctx);
+
+void h2_ihash_add(h2_ihash_t *ih, void *val);
+void h2_ihash_remove(h2_ihash_t *ih, int id);
+void h2_ihash_remove_val(h2_ihash_t *ih, void *val);
+void h2_ihash_clear(h2_ihash_t *ih);
+
+size_t h2_ihash_shift(h2_ihash_t *ih, void **buffer, size_t max);
+size_t h2_ihash_ishift(h2_ihash_t *ih, int *buffer, size_t max);
+
+/*******************************************************************************
+ * iqueue - sorted list of int with user defined ordering
+ ******************************************************************************/
+typedef struct h2_iqueue {
+    int *elts;
+    int head;
+    int nelts;
+    int nalloc;
+    apr_pool_t *pool;
+} h2_iqueue;
+
+/**
+ * Comparator for two int to determine their order.
+ *
+ * @param i1 first int to compare
+ * @param i2 second int to compare
+ * @param ctx provided user data
+ * @return value is the same as for strcmp() and has the effect:
+ *    == 0: s1 and s2 are treated equal in ordering
+ *     < 0: s1 should be sorted before s2
+ *     > 0: s2 should be sorted before s1
+ */
+typedef int h2_iq_cmp(int i1, int i2, void *ctx);
+
+/**
+ * Allocate a new queue from the pool and initialize.
+ * @param id the identifier of the queue
+ * @param pool the memory pool
+ */
+h2_iqueue *h2_iq_create(apr_pool_t *pool, int capacity);
+
+/**
+ * Return != 0 iff there are no tasks in the queue.
+ * @param q the queue to check
+ */
+int h2_iq_empty(h2_iqueue *q);
+
+/**
+ * Return the number of int in the queue.
+ * @param q the queue to get size on
+ */
+int h2_iq_count(h2_iqueue *q);
+
+/**
+ * Add a stream id to the queue. 
+ *
+ * @param q the queue to append the task to
+ * @param sid the stream id to add
+ * @param cmp the comparator for sorting
+ * @param ctx user data for comparator 
+ */
+void h2_iq_add(h2_iqueue *q, int sid, h2_iq_cmp *cmp, void *ctx);
+
+/**
+ * Remove the stream id from the queue. Return != 0 iff task
+ * was found in queue.
+ * @param q the task queue
+ * @param sid the stream id to remove
+ * @return != 0 iff task was found in queue
+ */
+int h2_iq_remove(h2_iqueue *q, int sid);
+
+/**
+ * Remove all entries in the queue.
+ */
+void h2_iq_clear(h2_iqueue *q);
+
+/**
+ * Sort the stream idqueue again. Call if the task ordering
+ * has changed.
+ *
+ * @param q the queue to sort
+ * @param cmp the comparator for sorting
+ * @param ctx user data for the comparator 
+ */
+void h2_iq_sort(h2_iqueue *q, h2_iq_cmp *cmp, void *ctx);
+
+/**
+ * Get the first stream id from the queue or NULL if the queue is empty. 
+ * The task will be removed.
+ *
+ * @param q the queue to get the first task from
+ * @return the first stream id of the queue, 0 if empty
+ */
+int h2_iq_shift(h2_iqueue *q);
+
+/*******************************************************************************
+ * common helpers
+ ******************************************************************************/
+/* h2_log2(n) iff n is a power of 2 */
+unsigned char h2_log2(apr_uint32_t n);
+
+/*******************************************************************************
+ * HTTP/2 header helpers
+ ******************************************************************************/
+void h2_util_camel_case_header(char *s, size_t len);
+int h2_proxy_res_ignore_header(const char *name, size_t len);
+
+/*******************************************************************************
+ * nghttp2 helpers
+ ******************************************************************************/
+typedef struct h2_ngheader {
+    nghttp2_nv *nv;
+    apr_size_t nvlen;
+} h2_ngheader;
+h2_ngheader *h2_util_ngheader_make_req(apr_pool_t *p, 
+                                       const struct h2_request *req);
+
+/*******************************************************************************
+ * h2_request helpers
+ ******************************************************************************/
+struct h2_request *h2_req_create(int id, apr_pool_t *pool, int serialize);
+apr_status_t h2_req_make(struct h2_request *req, apr_pool_t *pool,
+                         const char *method, const char *scheme, 
+                         const char *authority, const char *path, 
+                         apr_table_t *headers);
+
+
+
+#endif /* defined(__mod_h2__h2_proxy_util__) */
index f8575fa7e10a4b31c5ac7fc295a6ad8adc7a7f2f..8d1060e579a16b2585b665fae23c1975bd74cac1 100644 (file)
@@ -403,131 +403,6 @@ size_t h2_ihash_ishift(h2_ihash_t *ih, int *buffer, size_t max)
     return ctx.len;
 }
 
-/*******************************************************************************
- * ilist - sorted list for structs with int identifier
- ******************************************************************************/
-
-#define h2_ilist_IDX(list, i) ((int**)(list)->elts)[i]
-
-struct h2_ilist_t {
-    apr_array_header_t *l;
-};
-
-h2_ilist_t *h2_ilist_create(apr_pool_t *pool)
-{
-    h2_ilist_t *list = apr_pcalloc(pool, sizeof(h2_ilist_t));
-    if (list) {
-        list->l = apr_array_make(pool, 100, sizeof(int*));
-        if (!list->l) {
-            return NULL;
-        }
-    }
-    return list;
-}
-
-static int h2_ilist_cmp(const void *s1, const void *s2)
-{
-    int **pi1 = (int **)s1;
-    int **pi2 = (int **)s2;
-    return *(*pi1) - *(*pi2);
-}
-
-void *h2_ilist_get(h2_ilist_t *list, int id)
-{
-    /* we keep the array sorted by id, so lookup can be done
-     * by bsearch.
-     */
-    int **pi;
-    int *pkey = &id;
-
-    pi = bsearch(&pkey, list->l->elts, list->l->nelts, 
-                 list->l->elt_size, h2_ilist_cmp);
-    return pi? *pi : NULL;
-}
-
-static void h2_ilist_sort(h2_ilist_t *list)
-{
-    qsort(list->l->elts, list->l->nelts, list->l->elt_size, h2_ilist_cmp);
-}
-
-apr_status_t h2_ilist_add(h2_ilist_t *list, void *val)
-{
-    int *pi = val;
-    void *existing = h2_ilist_get(list, *pi);
-    if (!existing) {
-        int last;
-        APR_ARRAY_PUSH(list->l, void*) = val;
-        /* Often, values get added in ascending order of id. We
-         * keep the array sorted, so we just need to check if the newly
-         * appended stream has a lower id than the last one. if not,
-         * sorting is not necessary.
-         */
-        last = list->l->nelts - 1;
-        if (last > 0 
-            && *h2_ilist_IDX(list->l, last) < *h2_ilist_IDX(list->l, last-1)) {
-            h2_ilist_sort(list);
-        }
-    }
-    return APR_SUCCESS;
-}
-
-static void remove_idx(h2_ilist_t *list, int idx)
-{
-    int n;
-    --list->l->nelts;
-    n = list->l->nelts - idx;
-    if (n > 0) {
-        /* There are n h2_io* behind idx. Move the rest down */
-        int **selts = (int**)list->l->elts;
-        memmove(selts + idx, selts + idx + 1, n * sizeof(int*));
-    }
-}
-
-void *h2_ilist_remove(h2_ilist_t *list, int id)
-{
-    int i;
-    for (i = 0; i < list->l->nelts; ++i) {
-        int *e = h2_ilist_IDX(list->l, i);
-        if (id == *e) {
-            remove_idx(list, i);
-            return e;
-        }
-    }
-    return NULL;
-}
-
-void *h2_ilist_shift(h2_ilist_t *list)
-{
-    if (list->l->nelts > 0) {
-        int *pi = h2_ilist_IDX(list->l, 0);
-        remove_idx(list, 0);
-        return pi;
-    }
-    return NULL;
-}
-
-int h2_ilist_empty(h2_ilist_t *list)
-{
-    return list->l->nelts == 0;
-}
-
-int h2_ilist_iter(h2_ilist_t *list, h2_ilist_iter_t *iter, void *ctx)
-{
-    int i;
-    for (i = 0; i < list->l->nelts; ++i) {
-        int *pi = h2_ilist_IDX(list->l, i);
-        if (!iter(ctx, pi)) {
-            return 0;
-        }
-    }
-    return 1;
-}
-
-apr_size_t h2_ilist_count(h2_ilist_t *list)
-{
-    return list->l->nelts;
-}
-
 /*******************************************************************************
  * iqueue - sorted list of int
  ******************************************************************************/
@@ -1578,123 +1453,3 @@ void h2_push_policy_determine(struct h2_request *req, apr_pool_t *p, int push_en
     req->push_policy = policy;
 }
 
-/*******************************************************************************
- * ap_casecmpstr, when will it be backported?
- ******************************************************************************/
-#if !APR_CHARSET_EBCDIC
-/*
- * Provide our own known-fast implementation of str[n]casecmp()
- * NOTE: Only ASCII alpha characters 41-5A are folded to 61-7A,
- * other 8-bit latin alphabetics are never case-folded!
- */
-static const unsigned char ucharmap[] = {
-    0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7,
-    0x8,  0x9,  0xa,  0xb,  0xc,  0xd,  0xe,  0xf,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-    0x40,  'a',  'b',  'c',  'd',  'e',  'f',  'g',
-     'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
-     'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
-     'x',  'y',  'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-    0x60,  'a',  'b',  'c',  'd',  'e',  'f',  'g',
-     'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
-     'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
-     'x',  'y',  'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
-};
-
-#else /* APR_CHARSET_EBCDIC */
-/* Derived from apr-iconv/ccs/cp037.c for EBCDIC case comparison,
-   provides unique identity of every char value (strict ISO-646
-   conformance, arbitrary election of an ISO-8859-1 ordering, and
-   very arbitrary control code assignments into C1 to achieve
-   identity and a reversible mapping of code points),
-   then folding the equivalences of ASCII 41-5A into 61-7A, 
-   presenting comparison results in a somewhat ISO/IEC 10646
-   (ASCII-like) order, depending on the EBCDIC code page in use.
- */
-static const unsigned char ucharmap[] = {
-       0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
-       0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-       0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
-       0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
-       0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
-       0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
-       0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
-       0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
-       0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,
-       0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
-       0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,
-       0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
-       0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,
-       0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
-       0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
-       0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
-       0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-       0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
-       0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
-       0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
-       0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,
-       0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,
-       0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,
-       0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-       0x68, 0x69, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
-       0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
-       0x71, 0x72, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
-       0x5C, 0xF7, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
-       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-       0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F
-};
-#endif
-
-int h2_casecmpstr(const char *s1, const char *s2)
-{
-    const unsigned char *ps1 = (const unsigned char *) s1;
-    const unsigned char *ps2 = (const unsigned char *) s2;
-
-    while (ucharmap[*ps1] == ucharmap[*ps2]) {
-        if (*ps1++ == '\0') {
-            return (0);
-        }
-        ps2++;
-    }
-    return (ucharmap[*ps1] - ucharmap[*ps2]);
-}
-
-int h2_casecmpstrn(const char *s1, const char *s2, apr_size_t n)
-{
-    const unsigned char *ps1 = (const unsigned char *) s1;
-    const unsigned char *ps2 = (const unsigned char *) s2;
-    while (n--) {
-        if (ucharmap[*ps1] != ucharmap[*ps2]) {
-            return (ucharmap[*ps1] - ucharmap[*ps2]);
-        }
-        if (*ps1++ == '\0') {
-            break;
-        }
-        ps2++;
-    }
-    return (0);
-}
-
index 61ffdbcbea6a7a4ceebe8e6c85602984b9cd95c3..7cae0ac0164a42c41a51df01686372e1915cb90a 100644 (file)
@@ -70,33 +70,6 @@ void h2_ihash_clear(h2_ihash_t *ih);
 size_t h2_ihash_shift(h2_ihash_t *ih, void **buffer, size_t max);
 size_t h2_ihash_ishift(h2_ihash_t *ih, int *buffer, size_t max);
 
-/*******************************************************************************
- * ilist - sorted list for structs with int identifier as first member
- ******************************************************************************/
-typedef struct h2_ilist_t h2_ilist_t;
-typedef int h2_ilist_iter_t(void *ctx, void *val);
-
-h2_ilist_t *h2_ilist_create(apr_pool_t *pool);
-
-apr_status_t h2_ilist_add(h2_ilist_t *list, void *val);
-void *h2_ilist_get(h2_ilist_t *list, int id);
-void *h2_ilist_shift(h2_ilist_t *list);
-void *h2_ilist_remove(h2_ilist_t *list, int id);
-
-int h2_ilist_empty(h2_ilist_t *list);
-apr_size_t h2_ilist_count(h2_ilist_t *list);
-
-/* Iterator over all h2_io* in the set or until a
- * callback returns 0. It is not safe to add or remove
- * set members during iteration.
- *
- * @param set the set of h2_io to iterate over
- * @param iter the function to call for each io
- * @param ctx user data for the callback
- * @return 1 iff iteration completed for all members
- */
-int h2_ilist_iter(h2_ilist_t *lis, h2_ilist_iter_t *iter, void *ctx);
-
 /*******************************************************************************
  * iqueue - sorted list of int with user defined ordering
  ******************************************************************************/
@@ -413,8 +386,4 @@ apr_status_t h2_append_brigade(apr_bucket_brigade *to,
  */
 apr_off_t h2_brigade_mem_size(apr_bucket_brigade *bb);
 
-/* when will ap_casecmpstr() be backported finally? */
-int h2_casecmpstr(const char *s1, const char *s2);
-int h2_casecmpstrn(const char *s1, const char *s2, apr_size_t n);
-
 #endif /* defined(__mod_h2__h2_util__) */
index 7dfee7083af435b356d86eaa08b3881bc8a87084..c0e4bf17655c1dc19cae82088cb14538e6de358b 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "mod_proxy_http2.h"
 #include "h2_request.h"
-#include "h2_util.h"
+#include "h2_proxy_util.h"
 #include "h2_version.h"
 #include "h2_proxy_session.h"
 
@@ -125,12 +125,12 @@ static int proxy_http2_canon(request_rec *r, char *url)
     apr_port_t port, def_port;
 
     /* ap_port_of_scheme() */
-    if (h2_casecmpstrn(url, "h2c:", 4) == 0) {
+    if (ap_cstr_casecmpn(url, "h2c:", 4) == 0) {
         url += 4;
         scheme = "h2c";
         http_scheme = "http";
     }
-    else if (h2_casecmpstrn(url, "h2:", 3) == 0) {
+    else if (ap_cstr_casecmpn(url, "h2:", 3) == 0) {
         url += 3;
         scheme = "h2";
         http_scheme = "https";
index 31b91b55e6ea92ce59ad59b5cfb73c7200cdfe18..5d6305fdf71da5d42ed5f37648bfbdb574c9de7f 100644 (file)
@@ -105,7 +105,7 @@ SOURCE=./h2_proxy_session.c
 # End Source File
 # Begin Source File
 
-SOURCE=./h2_util.c
+SOURCE=./h2_proxy_util.c
 # End Source File
 # Begin Source File