httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ic...@apache.org
Subject svn commit: r1747550 - in /httpd/httpd/trunk: ./ modules/http2/
Date Thu, 09 Jun 2016 14:03:07 GMT
Author: icing
Date: Thu Jun  9 14:03:07 2016
New Revision: 1747550

URL: http://svn.apache.org/viewvc?rev=1747550&view=rev
Log:
mod_proxy_http2: own h2_proxy_util.c source file to avoid duplicate use of h2_util.c, updated
dsp and cmake as well as configure files

Added:
    httpd/httpd/trunk/modules/http2/h2_proxy_util.c
    httpd/httpd/trunk/modules/http2/h2_proxy_util.h
Modified:
    httpd/httpd/trunk/CMakeLists.txt
    httpd/httpd/trunk/modules/http2/config2.m4
    httpd/httpd/trunk/modules/http2/h2_mplx.h
    httpd/httpd/trunk/modules/http2/h2_proxy_session.c
    httpd/httpd/trunk/modules/http2/h2_util.c
    httpd/httpd/trunk/modules/http2/h2_util.h
    httpd/httpd/trunk/modules/http2/mod_proxy_http2.c
    httpd/httpd/trunk/modules/http2/mod_proxy_http2.dsp

Modified: httpd/httpd/trunk/CMakeLists.txt
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CMakeLists.txt?rev=1747550&r1=1747549&r2=1747550&view=diff
==============================================================================
--- httpd/httpd/trunk/CMakeLists.txt (original)
+++ httpd/httpd/trunk/CMakeLists.txt Thu Jun  9 14:03:07 2016
@@ -455,7 +455,7 @@ SET(mod_proxy_http2_extra_defines
 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

Modified: httpd/httpd/trunk/modules/http2/config2.m4
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/config2.m4?rev=1747550&r1=1747549&r2=1747550&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/config2.m4 (original)
+++ httpd/httpd/trunk/modules/http2/config2.m4 Thu Jun  9 14:03:07 2016
@@ -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)

Modified: httpd/httpd/trunk/modules/http2/h2_mplx.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.h?rev=1747550&r1=1747549&r2=1747550&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_mplx.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_mplx.h Thu Jun  9 14:03:07 2016
@@ -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;

Modified: httpd/httpd/trunk/modules/http2/h2_proxy_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_proxy_session.c?rev=1747550&r1=1747549&r2=1747550&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_proxy_session.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_proxy_session.c Thu Jun  9 14:03:07 2016
@@ -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);

Added: httpd/httpd/trunk/modules/http2/h2_proxy_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_proxy_util.c?rev=1747550&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_proxy_util.c (added)
+++ httpd/httpd/trunk/modules/http2/h2_proxy_util.c Thu Jun  9 14:03:07 2016
@@ -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);
+    }
+}

Added: httpd/httpd/trunk/modules/http2/h2_proxy_util.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_proxy_util.h?rev=1747550&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_proxy_util.h (added)
+++ httpd/httpd/trunk/modules/http2/h2_proxy_util.h Thu Jun  9 14:03:07 2016
@@ -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__) */

Modified: httpd/httpd/trunk/modules/http2/h2_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_util.c?rev=1747550&r1=1747549&r2=1747550&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_util.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_util.c Thu Jun  9 14:03:07 2016
@@ -404,131 +404,6 @@ size_t h2_ihash_ishift(h2_ihash_t *ih, i
 }
 
 /*******************************************************************************
- * 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
  ******************************************************************************/
 

Modified: httpd/httpd/trunk/modules/http2/h2_util.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_util.h?rev=1747550&r1=1747549&r2=1747550&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_util.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_util.h Thu Jun  9 14:03:07 2016
@@ -71,33 +71,6 @@ size_t h2_ihash_shift(h2_ihash_t *ih, vo
 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
  ******************************************************************************/
 typedef struct h2_iqueue {

Modified: httpd/httpd/trunk/modules/http2/mod_proxy_http2.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/mod_proxy_http2.c?rev=1747550&r1=1747549&r2=1747550&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/mod_proxy_http2.c (original)
+++ httpd/httpd/trunk/modules/http2/mod_proxy_http2.c Thu Jun  9 14:03:07 2016
@@ -22,7 +22,7 @@
 
 #include "mod_proxy_http2.h"
 #include "h2.h"
-#include "h2_util.h"
+#include "h2_proxy_util.h"
 #include "h2_version.h"
 #include "h2_proxy_session.h"
 

Modified: httpd/httpd/trunk/modules/http2/mod_proxy_http2.dsp
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/mod_proxy_http2.dsp?rev=1747550&r1=1747549&r2=1747550&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/mod_proxy_http2.dsp (original)
+++ httpd/httpd/trunk/modules/http2/mod_proxy_http2.dsp Thu Jun  9 14:03:07 2016
@@ -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
 




Mime
View raw message