You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2015/11/19 18:14:04 UTC

svn commit: r1715218 [4/4] - in /httpd/httpd/branches/2.4-http2-alpha: ./ docs/manual/mod/ modules/aaa/ modules/http2/ modules/ssl/ server/

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_stream_set.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_stream_set.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_stream_set.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_stream_set.c Thu Nov 19 17:14:03 2015
@@ -16,34 +16,31 @@
 #include <assert.h>
 #include <stddef.h>
 
+#include <apr_hash.h>
 #include <apr_strings.h>
 
 #include <httpd.h>
-#include <http_core.h>
-#include <http_connection.h>
 #include <http_log.h>
 
 #include "h2_private.h"
-#include "h2_session.h"
 #include "h2_stream.h"
-#include "h2_task.h"
 #include "h2_stream_set.h"
 
-#define H2_STREAM_IDX(list, i) ((h2_stream**)(list)->elts)[i]
 
 struct h2_stream_set {
-    apr_array_header_t *list;
+    apr_hash_t *hash;
 };
 
-h2_stream_set *h2_stream_set_create(apr_pool_t *pool)
+static unsigned int stream_hash(const char *key, apr_ssize_t *klen)
+{
+    return (unsigned int)(*((int*)key));
+}
+
+h2_stream_set *h2_stream_set_create(apr_pool_t *pool, int max)
 {
     h2_stream_set *sp = apr_pcalloc(pool, sizeof(h2_stream_set));
-    if (sp) {
-        sp->list = apr_array_make(pool, 100, sizeof(h2_stream*));
-        if (!sp->list) {
-            return NULL;
-        }
-    }
+    sp->hash = apr_hash_make_custom(pool, stream_hash);
+
     return sp;
 }
 
@@ -52,111 +49,97 @@ void h2_stream_set_destroy(h2_stream_set
     (void)sp;
 }
 
-static int h2_stream_id_cmp(const void *s1, const void *s2)
+h2_stream *h2_stream_set_get(h2_stream_set *sp, int stream_id)
 {
-    return (*((h2_stream **)s1))->id - (*((h2_stream **)s2))->id;
+    return apr_hash_get(sp->hash, &stream_id, sizeof(stream_id));
 }
 
-h2_stream *h2_stream_set_get(h2_stream_set *sp, int stream_id)
+void h2_stream_set_add(h2_stream_set *sp, h2_stream *stream)
 {
-    /* we keep the array sorted by id, so lookup can be done
-     * by bsearch.
-     */
-    h2_stream key;
-    h2_stream *pkey, **ps;
-    memset(&key, 0, sizeof(key));
-    key.id = stream_id;
-    pkey = &key;
-    ps = bsearch(&pkey, sp->list->elts, sp->list->nelts, 
-                             sp->list->elt_size, h2_stream_id_cmp);
-    return ps? *ps : NULL;
-}
-
-static void h2_stream_set_sort(h2_stream_set *sp)
-{
-    qsort(sp->list->elts, sp->list->nelts, sp->list->elt_size, 
-          h2_stream_id_cmp);
-}
-
-apr_status_t h2_stream_set_add(h2_stream_set *sp, h2_stream *stream)
-{
-    h2_stream *existing = h2_stream_set_get(sp, stream->id);
-    if (!existing) {
-        int last;
-        APR_ARRAY_PUSH(sp->list, h2_stream*) = stream;
-        /* Normally, streams get added in ascending order if id. We
-         * keep the array sorted, so we just need to check of the newly
-         * appended stream has a lower id than the last one. if not,
-         * sorting is not necessary.
-         */
-        last = sp->list->nelts - 1;
-        if (last > 0 
-            && (H2_STREAM_IDX(sp->list, last)->id 
-                < H2_STREAM_IDX(sp->list, last-1)->id)) {
-            h2_stream_set_sort(sp);
-        }
-    }
-    return APR_SUCCESS;
+    apr_hash_set(sp->hash, &stream->id, sizeof(stream->id), stream);
 }
 
-h2_stream *h2_stream_set_remove(h2_stream_set *sp, int stream_id)
+void h2_stream_set_remove(h2_stream_set *sp, int stream_id)
 {
-    int i;
-    for (i = 0; i < sp->list->nelts; ++i) {
-        h2_stream *s = H2_STREAM_IDX(sp->list, i);
-        if (s->id == stream_id) {
-            int n;
-            --sp->list->nelts;
-            n = sp->list->nelts - i;
-            if (n > 0) {
-                /* Close the hole in the array by moving the upper
-                 * parts down one step.
-                 */
-                h2_stream **selts = (h2_stream**)sp->list->elts;
-                memmove(selts+i, selts+i+1, n * sizeof(h2_stream*));
-            }
-            return s;
-        }
-    }
-    return NULL;
+    apr_hash_set(sp->hash, &stream_id, sizeof(stream_id), NULL);
 }
 
-void h2_stream_set_remove_all(h2_stream_set *sp)
+int h2_stream_set_is_empty(h2_stream_set *sp)
 {
-    sp->list->nelts = 0;
+    return apr_hash_count(sp->hash) == 0;
 }
 
-int h2_stream_set_is_empty(h2_stream_set *sp)
+apr_size_t h2_stream_set_size(h2_stream_set *sp)
 {
-    AP_DEBUG_ASSERT(sp);
-    return sp->list->nelts == 0;
+    return apr_hash_count(sp->hash);
 }
 
-h2_stream *h2_stream_set_find(h2_stream_set *sp,
-                              h2_stream_set_match_fn *match, void *ctx)
+typedef struct {
+    h2_stream_set_iter_fn *iter;
+    void *ctx;
+} iter_ctx;
+
+static int hash_iter(void *ctx, const void *key, apr_ssize_t klen, 
+                     const void *val)
 {
-    h2_stream *s = NULL;
-    int i;
-    for (i = 0; !s && i < sp->list->nelts; ++i) {
-        s = match(ctx, H2_STREAM_IDX(sp->list, i));
-    }
-    return s;
+    iter_ctx *ictx = ctx;
+    return ictx->iter(ictx->ctx, (h2_stream*)val);
 }
 
 void h2_stream_set_iter(h2_stream_set *sp,
                         h2_stream_set_iter_fn *iter, void *ctx)
 {
-    int i;
-    for (i = 0; i < sp->list->nelts; ++i) {
-        h2_stream *s = H2_STREAM_IDX(sp->list, i);
-        if (!iter(ctx, s)) {
-            break;
-        }
+    iter_ctx ictx;
+    ictx.iter = iter;
+    ictx.ctx = ctx;
+    apr_hash_do(hash_iter, &ictx, sp->hash);
+}
+
+static int unsubmitted_iter(void *ctx, h2_stream *stream)
+{
+    if (h2_stream_needs_submit(stream)) {
+        *((int *)ctx) = 1;
+        return 0;
     }
+    return 1;
 }
 
-apr_size_t h2_stream_set_size(h2_stream_set *sp)
+int h2_stream_set_has_unsubmitted(h2_stream_set *sp)
+{
+    int has_unsubmitted = 0;
+    h2_stream_set_iter(sp, unsubmitted_iter, &has_unsubmitted);
+    return has_unsubmitted;
+}
+
+static int input_open_iter(void *ctx, h2_stream *stream)
+{
+    if (h2_stream_input_is_open(stream)) {
+        *((int *)ctx) = 1;
+        return 0;
+    }
+    return 1;
+}
+
+int h2_stream_set_has_open_input(h2_stream_set *sp)
+{
+    int has_input_open = 0;
+    h2_stream_set_iter(sp, input_open_iter, &has_input_open);
+    return has_input_open;
+}
+
+static int suspended_iter(void *ctx, h2_stream *stream)
+{
+    if (h2_stream_is_suspended(stream)) {
+        *((int *)ctx) = 1;
+        return 0;
+    }
+    return 1;
+}
+
+int h2_stream_set_has_suspended(h2_stream_set *sp)
 {
-    return sp->list->nelts;
+    int has_suspended = 0;
+    h2_stream_set_iter(sp, suspended_iter, &has_suspended);
+    return has_suspended;
 }
 

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_stream_set.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_stream_set.h?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_stream_set.h (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_stream_set.h Thu Nov 19 17:14:03 2015
@@ -27,26 +27,25 @@ typedef int h2_stream_set_iter_fn(void *
 typedef struct h2_stream_set h2_stream_set;
 
 
-h2_stream_set *h2_stream_set_create(apr_pool_t *pool);
+h2_stream_set *h2_stream_set_create(apr_pool_t *pool, int max);
 
 void h2_stream_set_destroy(h2_stream_set *sp);
 
-apr_status_t h2_stream_set_add(h2_stream_set *sp, h2_stream *stream);
+void h2_stream_set_add(h2_stream_set *sp, h2_stream *stream);
 
 h2_stream *h2_stream_set_get(h2_stream_set *sp, int stream_id);
 
-h2_stream *h2_stream_set_remove(h2_stream_set *sp, int stream_id);
+void h2_stream_set_remove(h2_stream_set *sp, int stream_id);
 
-void h2_stream_set_remove_all(h2_stream_set *sp);
+void h2_stream_set_iter(h2_stream_set *sp,
+                        h2_stream_set_iter_fn *iter, void *ctx);
 
 int h2_stream_set_is_empty(h2_stream_set *sp);
 
 apr_size_t h2_stream_set_size(h2_stream_set *sp);
 
-h2_stream *h2_stream_set_find(h2_stream_set *sp,
-                              h2_stream_set_match_fn *match, void *ctx);
-
-void h2_stream_set_iter(h2_stream_set *sp,
-                        h2_stream_set_iter_fn *iter, void *ctx);
+int h2_stream_set_has_unsubmitted(h2_stream_set *sp);
+int h2_stream_set_has_open_input(h2_stream_set *sp);
+int h2_stream_set_has_suspended(h2_stream_set *sp);
 
 #endif /* defined(__mod_h2__h2_stream_set__) */

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_switch.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_switch.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_switch.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_switch.c Thu Nov 19 17:14:03 2015
@@ -154,7 +154,7 @@ static int h2_protocol_switch(conn_rec *
             ap_remove_input_filter_byhandle(r->input_filters, "reqtimeout");
             
             /* Ok, start an h2_conn on this one. */
-            status = h2_conn_rprocess(r);
+            status = h2_conn_process(r->connection, r);
             if (status != DONE) {
                 /* Nothing really to do about this. */
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task.c Thu Nov 19 17:14:03 2015
@@ -38,6 +38,7 @@
 #include "h2_from_h1.h"
 #include "h2_h2.h"
 #include "h2_mplx.h"
+#include "h2_request.h"
 #include "h2_session.h"
 #include "h2_stream.h"
 #include "h2_task_input.h"
@@ -152,46 +153,30 @@ static int h2_task_process_conn(conn_rec
 }
 
 
-h2_task *h2_task_create(long session_id,
-                        int stream_id,
-                        apr_pool_t *stream_pool,
-                        h2_mplx *mplx, conn_rec *c)
+h2_task *h2_task_create(long session_id, const h2_request *req, 
+                        apr_pool_t *pool, h2_mplx *mplx, int eos)
 {
-    h2_task *task = apr_pcalloc(stream_pool, sizeof(h2_task));
+    h2_task *task = apr_pcalloc(pool, sizeof(h2_task));
     if (task == NULL) {
-        ap_log_perror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, stream_pool,
+        ap_log_perror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, pool,
                       APLOGNO(02941) "h2_task(%ld-%d): create stream task", 
-                      session_id, stream_id);
-        h2_mplx_out_close(mplx, stream_id);
+                      session_id, req->id);
+        h2_mplx_out_close(mplx, req->id);
         return NULL;
     }
     
-    task->id = apr_psprintf(stream_pool, "%ld-%d", session_id, stream_id);
-    task->stream_id = stream_id;
+    task->id = apr_psprintf(pool, "%ld-%d", session_id, req->id);
+    task->stream_id = req->id;
+    task->pool = pool;
     task->mplx = mplx;
+    task->c = h2_conn_create(mplx->c, task->pool);
+
+    task->request = req;
+    task->input_eos = eos;    
     
-    task->c = c;
-    
-    ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, stream_pool,
-                  "h2_task(%s): created", task->id);
     return task;
 }
 
-void h2_task_set_request(h2_task *task, 
-                         const char *method, 
-                         const char *scheme, 
-                         const char *authority, 
-                         const char *path, 
-                         apr_table_t *headers, int eos)
-{
-    task->method = method;
-    task->scheme = scheme;
-    task->authority = authority;
-    task->path = path;
-    task->headers = headers;
-    task->input_eos = eos;
-}
-
 apr_status_t h2_task_destroy(h2_task *task)
 {
     (void)task;
@@ -206,29 +191,20 @@ apr_status_t h2_task_do(h2_task *task, h
     AP_DEBUG_ASSERT(task);
     
     task->serialize_headers = h2_config_geti(cfg, H2_CONF_SER_HEADERS);
-    
-    /* Create a subpool from the worker one to be used for all things
-     * with life-time of this task execution.
-     */
-    apr_pool_create(&task->pool, h2_worker_get_pool(worker));
 
-    /* Link the task to the worker which provides useful things such
-     * as mutex, a socket etc. */
-    task->io = h2_worker_get_cond(worker);
-    
-    status = h2_conn_setup(task, worker);
+    status = h2_worker_setup_task(worker, task);
     
-    /* save in connection that this one is a pseudo connection, prevents
-     * other hooks from messing with it. */
+    /* save in connection that this one is a pseudo connection */
     h2_ctx_create_for(task->c, task);
 
     if (status == APR_SUCCESS) {
         task->input = h2_task_input_create(task, task->pool, 
                                            task->c->bucket_alloc);
-        task->output = h2_task_output_create(task, task->pool,
-                                             task->c->bucket_alloc);
-        status = h2_conn_process(task->c, h2_worker_get_socket(worker));
-        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, task->c,
+        task->output = h2_task_output_create(task, task->pool);
+        
+        ap_process_connection(task->c, h2_worker_get_socket(worker));
+        
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c,
                       "h2_task(%s): processing done", task->id);
     }
     else {
@@ -252,16 +228,8 @@ apr_status_t h2_task_do(h2_task *task, h
         apr_thread_cond_signal(task->io);
     }
     
-    if (task->pool) {
-        apr_pool_destroy(task->pool);
-        task->pool = NULL;
-    }
-    
-    if (task->c->id) {
-        h2_conn_post(task->c, worker);
-    }
-    
     h2_mplx_task_done(task->mplx, task->stream_id);
+    h2_worker_release_task(worker, task);
     
     return status;
 }
@@ -286,7 +254,7 @@ static request_rec *h2_task_create_reque
     
     r->allowed_methods = ap_make_method_list(p, 2);
     
-    r->headers_in = apr_table_copy(r->pool, task->headers);
+    r->headers_in      = apr_table_copy(r->pool, task->request->headers);
     r->trailers_in     = apr_table_make(r->pool, 5);
     r->subprocess_env  = apr_table_make(r->pool, 25);
     r->headers_out     = apr_table_make(r->pool, 12);
@@ -325,19 +293,19 @@ static request_rec *h2_task_create_reque
     
     /* Time to populate r with the data we have. */
     r->request_time = apr_time_now();
-    r->method = task->method;
+    r->method = task->request->method;
     /* Provide quick information about the request method as soon as known */
     r->method_number = ap_method_number_of(r->method);
     if (r->method_number == M_GET && r->method[0] == 'H') {
         r->header_only = 1;
     }
 
-    ap_parse_uri(r, task->path);
+    ap_parse_uri(r, task->request->path);
     r->protocol = (char*)"HTTP/2";
     r->proto_num = HTTP_VERSION(2, 0);
 
     r->the_request = apr_psprintf(r->pool, "%s %s %s", 
-                                  r->method, task->path, r->protocol);
+                                  r->method, task->request->path, r->protocol);
     
     /* update what we think the virtual host is based on the headers we've
      * now read. may update status.
@@ -401,6 +369,8 @@ static apr_status_t h2_task_process_requ
          * will result in a segfault immediately instead
          * of nondeterministic failures later.
          */
+        if (cs)
+            cs->state = CONN_STATE_WRITE_COMPLETION;
         r = NULL;
     }
     ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, NULL);

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task.h?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task.h (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task.h Thu Nov 19 17:14:03 2015
@@ -39,6 +39,7 @@ struct apr_thread_cond_t;
 struct h2_conn;
 struct h2_mplx;
 struct h2_task;
+struct h2_request;
 struct h2_resp_head;
 struct h2_worker;
 
@@ -49,11 +50,7 @@ struct h2_task {
     int stream_id;
     struct h2_mplx *mplx;
     
-    const char *method;
-    const char *scheme;
-    const char *authority;
-    const char *path;
-    apr_table_t *headers;
+    const struct h2_request *request;
     int input_eos;
 
     int serialize_headers;
@@ -68,20 +65,11 @@ struct h2_task {
     struct apr_thread_cond_t *io;   /* used to wait for events on */
 };
 
-h2_task *h2_task_create(long session_id, int stream_id, 
-                        apr_pool_t *pool, struct h2_mplx *mplx,
-                        conn_rec *c);
+h2_task *h2_task_create(long session_id, const struct h2_request *req, 
+                        apr_pool_t *pool, struct h2_mplx *mplx, int eos);
 
 apr_status_t h2_task_destroy(h2_task *task);
 
-void h2_task_set_request(h2_task *task, 
-                         const char *method, 
-                         const char *scheme, 
-                         const char *authority, 
-                         const char *path, 
-                         apr_table_t *headers, int eos);
-
-
 apr_status_t h2_task_do(h2_task *task, struct h2_worker *worker);
 
 void h2_task_register_hooks(void);

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_input.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_input.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_input.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_input.c Thu Nov 19 17:14:03 2015
@@ -23,6 +23,7 @@
 #include "h2_private.h"
 #include "h2_conn.h"
 #include "h2_mplx.h"
+#include "h2_request.h"
 #include "h2_session.h"
 #include "h2_stream.h"
 #include "h2_task_input.h"
@@ -53,11 +54,11 @@ h2_task_input *h2_task_input_create(h2_t
         if (task->serialize_headers) {
             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c,
                           "h2_task_input(%s): serialize request %s %s", 
-                          task->id, task->method, task->path);
+                          task->id, task->request->method, task->request->path);
             input->bb = apr_brigade_create(pool, bucket_alloc);
             apr_brigade_printf(input->bb, NULL, NULL, "%s %s HTTP/1.1\r\n", 
-                               task->method, task->path);
-            apr_table_do(ser_header, input, task->headers, NULL);
+                               task->request->method, task->request->path);
+            apr_table_do(ser_header, input, task->request->headers, NULL);
             apr_brigade_puts(input->bb, NULL, NULL, "\r\n");
             if (input->task->input_eos) {
                 APR_BRIGADE_INSERT_TAIL(input->bb, apr_bucket_eos_create(bucket_alloc));
@@ -70,21 +71,6 @@ h2_task_input *h2_task_input_create(h2_t
             /* We do not serialize and have eos already, no need to
              * create a bucket brigade. */
         }
-        
-        if (APLOGcdebug(task->c)) {
-            char buffer[1024];
-            apr_size_t len = sizeof(buffer)-1;
-            if (input->bb) {
-                apr_brigade_flatten(input->bb, buffer, &len);
-            }
-            else {
-                len = 0;
-            }
-            buffer[len] = 0;
-            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, task->c,
-                          "h2_task_input(%s): request is: %s", 
-                          task->id, buffer);
-        }
     }
     return input;
 }
@@ -104,21 +90,20 @@ apr_status_t h2_task_input_read(h2_task_
     apr_status_t status = APR_SUCCESS;
     apr_off_t bblen = 0;
     
-    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c,
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, f->c,
                   "h2_task_input(%s): read, block=%d, mode=%d, readbytes=%ld", 
                   input->task->id, block, mode, (long)readbytes);
     
+    if (mode == AP_MODE_INIT) {
+        return ap_get_brigade(f->c->input_filters, bb, mode, block, readbytes);
+    }
+    
     if (is_aborted(f)) {
         ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, f->c,
-                      "h2_task_input(%s): is aborted", 
-                      input->task->id);
+                      "h2_task_input(%s): is aborted", input->task->id);
         return APR_ECONNABORTED;
     }
     
-    if (mode == AP_MODE_INIT) {
-        return ap_get_brigade(f->c->input_filters, bb, mode, block, readbytes);
-    }
-    
     if (input->bb) {
         status = apr_brigade_length(input->bb, 1, &bblen);
         if (status != APR_SUCCESS) {
@@ -160,7 +145,7 @@ apr_status_t h2_task_input_read(h2_task_
             return status;
         }
         if ((bblen == 0) && (block == APR_NONBLOCK_READ)) {
-            return h2_util_has_eos(input->bb, 0)? APR_EOF : APR_EAGAIN;
+            return h2_util_has_eos(input->bb, -1)? APR_EOF : APR_EAGAIN;
         }
         ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, f->c,
                       "h2_task_input(%s): mplx in read, %ld bytes in brigade",

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_output.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_output.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_output.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_output.c Thu Nov 19 17:14:03 2015
@@ -24,6 +24,7 @@
 #include "h2_private.h"
 #include "h2_conn.h"
 #include "h2_mplx.h"
+#include "h2_request.h"
 #include "h2_session.h"
 #include "h2_stream.h"
 #include "h2_from_h1.h"
@@ -33,12 +34,10 @@
 #include "h2_util.h"
 
 
-h2_task_output *h2_task_output_create(h2_task *task, apr_pool_t *pool,
-                                      apr_bucket_alloc_t *bucket_alloc)
+h2_task_output *h2_task_output_create(h2_task *task, apr_pool_t *pool)
 {
     h2_task_output *output = apr_pcalloc(pool, sizeof(h2_task_output));
     
-    (void)bucket_alloc;
     if (output) {
         output->task = task;
         output->state = H2_TASK_OUT_INIT;
@@ -73,8 +72,9 @@ static apr_status_t open_if_needed(h2_ta
                 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c,
                               "h2_task_output(%s): write without response "
                               "for %s %s %s",
-                              output->task->id, output->task->method, 
-                              output->task->authority, output->task->path);
+                              output->task->id, output->task->request->method, 
+                              output->task->request->authority, 
+                              output->task->request->path);
                 f->c->aborted = 1;
             }
             if (output->task->io) {

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_output.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_output.h?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_output.h (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_output.h Thu Nov 19 17:14:03 2015
@@ -40,8 +40,7 @@ struct h2_task_output {
     struct h2_from_h1 *from_h1;
 };
 
-h2_task_output *h2_task_output_create(struct h2_task *task, apr_pool_t *pool,
-                                      apr_bucket_alloc_t *bucket_alloc);
+h2_task_output *h2_task_output_create(struct h2_task *task, apr_pool_t *pool);
 
 void h2_task_output_destroy(h2_task_output *output);
 

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_queue.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_queue.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_queue.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_queue.c Thu Nov 19 17:14:03 2015
@@ -46,8 +46,7 @@ int h2_tq_empty(h2_task_queue *q)
     return q->nelts == 0;
 }
 
-void h2_tq_add(h2_task_queue *q, struct h2_task *task,
-               h2_tq_cmp *cmp, void *ctx)
+void h2_tq_add(h2_task_queue *q, int sid, h2_tq_cmp *cmp, void *ctx)
 {
     int i;
     
@@ -56,13 +55,33 @@ void h2_tq_add(h2_task_queue *q, struct
     }
     
     i = (q->head + q->nelts) % q->nalloc;
-    q->elts[i] = task;
+    q->elts[i] = sid;
     ++q->nelts;
     
     /* bubble it to the front of the queue */
     tq_bubble_up(q, i, q->head, cmp, ctx);
 }
 
+int h2_tq_remove(h2_task_queue *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_tq_sort(h2_task_queue *q, h2_tq_cmp *cmp, void *ctx)
 {
     /* Assume that changes in ordering are minimal. This needs,
@@ -91,34 +110,34 @@ void h2_tq_sort(h2_task_queue *q, h2_tq_
 }
 
 
-h2_task *h2_tq_shift(h2_task_queue *q)
+int h2_tq_shift(h2_task_queue *q)
 {
-    h2_task *t;
+    int sid;
     
     if (q->nelts <= 0) {
-        return NULL;
+        return 0;
     }
     
-    t = q->elts[q->head];
+    sid = q->elts[q->head];
     q->head = (q->head + 1) % q->nalloc;
     q->nelts--;
     
-    return t;
+    return sid;
 }
 
 static void tq_grow(h2_task_queue *q, int nlen)
 {
     AP_DEBUG_ASSERT(q->nalloc <= nlen);
     if (nlen > q->nalloc) {
-        h2_task **nq = apr_pcalloc(q->pool, sizeof(h2_task *) * nlen);
+        int *nq = apr_pcalloc(q->pool, sizeof(h2_task *) * nlen);
         if (q->nelts > 0) {
             int l = ((q->head + q->nelts) % q->nalloc) - q->head;
             
-            memmove(nq, q->elts + q->head, sizeof(h2_task *) * l);
+            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(h2_task *) * remain);
+                memmove(nq + l, q->elts, sizeof(int) * remain);
             }
         }
         q->elts = nq;
@@ -129,9 +148,9 @@ static void tq_grow(h2_task_queue *q, in
 
 static void tq_swap(h2_task_queue *q, int i, int j)
 {
-    h2_task *t = q->elts[i];
+    int x = q->elts[i];
     q->elts[i] = q->elts[j];
-    q->elts[j] = t;
+    q->elts[j] = x;
 }
 
 static int tq_bubble_up(h2_task_queue *q, int i, int top, 

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_queue.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_queue.h?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_queue.h (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_task_queue.h Thu Nov 19 17:14:03 2015
@@ -24,7 +24,7 @@ struct h2_task;
 typedef struct h2_task_queue h2_task_queue;
 
 struct h2_task_queue {
-    struct h2_task **elts;
+    int *elts;
     int head;
     int nelts;
     int nalloc;
@@ -34,15 +34,15 @@ struct h2_task_queue {
 /**
  * Comparator for two task to determine their order.
  *
- * @param t1 task to compare
- * @param t2 task to compare
+ * @param s1 stream id to compare
+ * @param s2 stream id to compare
  * @param ctx provided user data
  * @return value is the same as for strcmp() and has the effect:
- *    == 0: t1 and t2 are treated equal in ordering
- *     < 0: t1 should be sorted before t2
- *     > 0: t2 should be sorted before t1
+ *    == 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_tq_cmp(struct h2_task *t1, struct h2_task *t2, void *ctx);
+typedef int h2_tq_cmp(int s1, int s2, void *ctx);
 
 
 /**
@@ -59,18 +59,26 @@ h2_task_queue *h2_tq_create(apr_pool_t *
 int h2_tq_empty(h2_task_queue *q);
 
 /**
- * Add the task to the queue. 
+ * Add a stream idto the queue. 
  *
  * @param q the queue to append the task to
- * @param task the task to add
+ * @param sid the stream id to add
  * @param cmp the comparator for sorting
  * @param ctx user data for comparator 
  */
-void h2_tq_add(h2_task_queue *q, struct h2_task *task,
-               h2_tq_cmp *cmp, void *ctx);
+void h2_tq_add(h2_task_queue *q, int sid, h2_tq_cmp *cmp, void *ctx);
 
 /**
- * Sort the tasks queue again. Call if the task ordering
+ * 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_tq_remove(h2_task_queue *q, int sid);
+
+/**
+ * Sort the stream idqueue again. Call if the task ordering
  * has changed.
  *
  * @param q the queue to sort
@@ -80,12 +88,12 @@ void h2_tq_add(h2_task_queue *q, struct
 void h2_tq_sort(h2_task_queue *q, h2_tq_cmp *cmp, void *ctx);
 
 /**
- * Get the first task from the queue or NULL if the queue is empty. 
+ * 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 task of the queue, NULL if empty
+ * @return the first stream id of the queue, 0 if empty
  */
-h2_task *h2_tq_shift(h2_task_queue *q);
+int h2_tq_shift(h2_task_queue *q);
 
 #endif /* defined(__mod_h2__h2_task_queue__) */

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_util.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_util.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_util.c Thu Nov 19 17:14:03 2015
@@ -25,6 +25,7 @@
 #include <nghttp2/nghttp2.h>
 
 #include "h2_private.h"
+#include "h2_request.h"
 #include "h2_util.h"
 
 size_t h2_util_hex_dump(char *buffer, size_t maxlen,
@@ -205,6 +206,10 @@ const char *h2_util_first_token_match(ap
     return NULL;
 }
 
+/*******************************************************************************
+ * h2_util for bucket brigades
+ ******************************************************************************/
+
 /* DEEP_COPY==0 crashes under load. I think the setaside is fine, 
  * however buckets moved to another thread will still be
  * free'd against the old bucket_alloc. *And* if the old
@@ -215,7 +220,7 @@ static const int DEEP_COPY = 1;
 static const int FILE_MOVE = 1;
 
 static apr_status_t last_not_included(apr_bucket_brigade *bb, 
-                                      apr_size_t maxlen, 
+                                      apr_off_t maxlen, 
                                       int same_alloc,
                                       int *pfile_buckets_allowed,
                                       apr_bucket **pend)
@@ -224,7 +229,7 @@ static apr_status_t last_not_included(ap
     apr_status_t status = APR_SUCCESS;
     int files_allowed = pfile_buckets_allowed? *pfile_buckets_allowed : 0;
     
-    if (maxlen > 0) {
+    if (maxlen >= 0) {
         /* Find the bucket, up to which we reach maxlen/mem bytes */
         for (b = APR_BRIGADE_FIRST(bb); 
              (b != APR_BRIGADE_SENTINEL(bb));
@@ -275,7 +280,7 @@ static apr_status_t last_not_included(ap
 #define LOG_LEVEL APLOG_INFO
 
 apr_status_t h2_util_move(apr_bucket_brigade *to, apr_bucket_brigade *from, 
-                          apr_size_t maxlen, int *pfile_handles_allowed, 
+                          apr_off_t maxlen, int *pfile_handles_allowed, 
                           const char *msg)
 {
     apr_status_t status = APR_SUCCESS;
@@ -407,7 +412,7 @@ apr_status_t h2_util_move(apr_bucket_bri
 }
 
 apr_status_t h2_util_copy(apr_bucket_brigade *to, apr_bucket_brigade *from, 
-                          apr_size_t maxlen, const char *msg)
+                          apr_off_t maxlen, const char *msg)
 {
     apr_status_t status = APR_SUCCESS;
     int same_alloc;
@@ -483,7 +488,7 @@ int h2_util_has_flush_or_eos(apr_bucket_
     return 0;
 }
 
-int h2_util_has_eos(apr_bucket_brigade *bb, apr_size_t len)
+int h2_util_has_eos(apr_bucket_brigade *bb, apr_off_t len)
 {
     apr_bucket *b, *end;
     
@@ -537,7 +542,7 @@ int h2_util_bb_has_data_or_eos(apr_bucke
 }
 
 apr_status_t h2_util_bb_avail(apr_bucket_brigade *bb, 
-                              apr_size_t *plen, int *peos)
+                              apr_off_t *plen, int *peos)
 {
     apr_status_t status;
     apr_off_t blen = 0;
@@ -550,36 +555,29 @@ apr_status_t h2_util_bb_avail(apr_bucket
     else if (blen == 0) {
         /* empty brigade, does it have an EOS bucket somwhere? */
         *plen = 0;
-        *peos = h2_util_has_eos(bb, 0);
+        *peos = h2_util_has_eos(bb, -1);
     }
-    else if (blen > 0) {
+    else {
         /* data in the brigade, limit the length returned. Check for EOS
          * bucket only if we indicate data. This is required since plen == 0
          * means "the whole brigade" for h2_util_hash_eos()
          */
-        if (blen < (apr_off_t)*plen) {
+        if (blen < *plen || *plen < 0) {
             *plen = blen;
         }
-        *peos = (*plen > 0)? h2_util_has_eos(bb, *plen) : 0;
-    }
-    else if (blen < 0) {
-        /* famous SHOULD NOT HAPPEN, sinc we told apr_brigade_length to readall
-         */
-        *plen = 0;
-        *peos = h2_util_has_eos(bb, 0);
-        return APR_EINVAL;
+        *peos = h2_util_has_eos(bb, *plen);
     }
     return APR_SUCCESS;
 }
 
 apr_status_t h2_util_bb_readx(apr_bucket_brigade *bb, 
                               h2_util_pass_cb *cb, void *ctx, 
-                              apr_size_t *plen, int *peos)
+                              apr_off_t *plen, int *peos)
 {
     apr_status_t status = APR_SUCCESS;
     int consume = (cb != NULL);
-    apr_size_t written = 0;
-    apr_size_t avail = *plen;
+    apr_off_t written = 0;
+    apr_off_t avail = *plen;
     apr_bucket *next, *b;
     
     /* Pass data in our brigade through the callback until the length
@@ -607,8 +605,7 @@ apr_status_t h2_util_bb_readx(apr_bucket
             
             if (b->length == ((apr_size_t)-1)) {
                 /* read to determine length */
-                status = apr_bucket_read(b, &data, &data_len, 
-                                         APR_NONBLOCK_READ);
+                status = apr_bucket_read(b, &data, &data_len, APR_NONBLOCK_READ);
             }
             else {
                 data_len = b->length;
@@ -722,11 +719,11 @@ void h2_util_bb_log(conn_rec *c, int str
 apr_status_t h2_transfer_brigade(apr_bucket_brigade *to,
                                  apr_bucket_brigade *from, 
                                  apr_pool_t *p,
-                                 apr_size_t *plen,
+                                 apr_off_t *plen,
                                  int *peos)
 {
     apr_bucket *e;
-    apr_size_t len = 0, remain = *plen;
+    apr_off_t len = 0, remain = *plen;
     apr_status_t rv;
 
     *peos = 0;
@@ -790,3 +787,95 @@ apr_status_t h2_transfer_brigade(apr_buc
     return APR_SUCCESS;
 }
 
+/*******************************************************************************
+ * h2_ngheader
+ ******************************************************************************/
+ 
+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_res(apr_pool_t *p, 
+                                       int http_status, 
+                                       apr_table_t *header)
+{
+    h2_ngheader *ngh;
+    size_t n;
+    
+    n = 1;
+    apr_table_do(count_header, &n, header, NULL);
+    
+    ngh = apr_pcalloc(p, sizeof(h2_ngheader));
+    ngh->nv =  apr_pcalloc(p, n * sizeof(nghttp2_nv));
+    NV_ADD_LIT_CS(ngh, ":status", apr_psprintf(p, "%d", http_status));
+    apr_table_do(add_table_header, ngh, header, NULL);
+
+    return ngh;
+}
+
+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;
+}
+

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_util.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_util.h?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_util.h (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_util.h Thu Nov 19 17:14:03 2015
@@ -16,6 +16,7 @@
 #ifndef __mod_h2__h2_util__
 #define __mod_h2__h2_util__
 
+struct h2_request;
 struct nghttp2_frame;
 
 size_t h2_util_hex_dump(char *buffer, size_t maxlen,
@@ -67,19 +68,32 @@ apr_size_t h2_util_base64url_decode(cons
                                             nv->value = (uint8_t *)VALUE;     \
                                             nv->valuelen = strlen(VALUE)
 
+int h2_util_ignore_header(const char *name);
+
+typedef struct h2_ngheader {
+    nghttp2_nv *nv;
+    apr_size_t nvlen;
+} h2_ngheader;
+
+h2_ngheader *h2_util_ngheader_make_res(apr_pool_t *p, 
+                                       int http_status, 
+                                       apr_table_t *header);
+h2_ngheader *h2_util_ngheader_make_req(apr_pool_t *p, 
+                                       const struct h2_request *req);
+
 /**
  * Moves data from one brigade into another. If maxlen > 0, it only
  * moves up to maxlen bytes into the target brigade, making bucket splits
  * if needed.
  * @param to the brigade to move the data to
  * @param from the brigade to get the data from
- * @param maxlen of bytes to move, 0 for all
+ * @param maxlen of bytes to move, <= 0 for all
  * @param pfile_buckets_allowed how many file buckets may be moved, 
  *        may be 0 or NULL
  * @param msg message for use in logging
  */
 apr_status_t h2_util_move(apr_bucket_brigade *to, apr_bucket_brigade *from, 
-                          apr_size_t maxlen, int *pfile_buckets_allowed, 
+                          apr_off_t maxlen, int *pfile_buckets_allowed, 
                           const char *msg);
 
 /**
@@ -88,11 +102,11 @@ apr_status_t h2_util_move(apr_bucket_bri
  * if needed.
  * @param to the brigade to copy the data to
  * @param from the brigade to get the data from
- * @param maxlen of bytes to copy, 0 for all
+ * @param maxlen of bytes to copy, <= 0 for all
  * @param msg message for use in logging
  */
 apr_status_t h2_util_copy(apr_bucket_brigade *to, apr_bucket_brigade *from, 
-                          apr_size_t maxlen, const char *msg);
+                          apr_off_t maxlen, const char *msg);
 
 /**
  * Return != 0 iff there is a FLUSH or EOS bucket in the brigade.
@@ -100,7 +114,7 @@ apr_status_t h2_util_copy(apr_bucket_bri
  * @return != 0 iff brigade holds FLUSH or EOS bucket (or both)
  */
 int h2_util_has_flush_or_eos(apr_bucket_brigade *bb);
-int h2_util_has_eos(apr_bucket_brigade *bb, apr_size_t len);
+int h2_util_has_eos(apr_bucket_brigade *bb, apr_off_t len);
 int h2_util_bb_has_data(apr_bucket_brigade *bb);
 int h2_util_bb_has_data_or_eos(apr_bucket_brigade *bb);
 
@@ -112,10 +126,10 @@ int h2_util_bb_has_data_or_eos(apr_bucke
  * @param on return, if eos has been reached
  */
 apr_status_t h2_util_bb_avail(apr_bucket_brigade *bb, 
-                              apr_size_t *plen, int *peos);
+                              apr_off_t *plen, int *peos);
 
 typedef apr_status_t h2_util_pass_cb(void *ctx, 
-                                       const char *data, apr_size_t len);
+                                     const char *data, apr_off_t len);
 
 /**
  * Read at most *plen bytes from the brigade and pass them into the
@@ -131,7 +145,7 @@ typedef apr_status_t h2_util_pass_cb(voi
  */
 apr_status_t h2_util_bb_readx(apr_bucket_brigade *bb, 
                               h2_util_pass_cb *cb, void *ctx, 
-                              apr_size_t *plen, int *peos);
+                              apr_off_t *plen, int *peos);
 
 /**
  * Logs the bucket brigade (which bucket types with what length)
@@ -157,7 +171,7 @@ void h2_util_bb_log(conn_rec *c, int str
 apr_status_t h2_transfer_brigade(apr_bucket_brigade *to,
                                  apr_bucket_brigade *from, 
                                  apr_pool_t *p,
-                                 apr_size_t *plen,
+                                 apr_off_t *plen,
                                  int *peos);
 
 #endif /* defined(__mod_h2__h2_util__) */

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_version.h?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_version.h (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_version.h Thu Nov 19 17:14:03 2015
@@ -20,7 +20,7 @@
  * @macro
  * Version number of the h2 module as c string
  */
-#define MOD_HTTP2_VERSION "1.0.3-DEV"
+#define MOD_HTTP2_VERSION "1.0.5-DEV"
 
 /**
  * @macro
@@ -28,7 +28,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 0x010003
+#define MOD_HTTP2_VERSION_NUM 0x010005
 
 
 #endif /* mod_h2_h2_version_h */

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_worker.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_worker.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_worker.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_worker.c Thu Nov 19 17:14:03 2015
@@ -22,7 +22,9 @@
 #include <http_log.h>
 
 #include "h2_private.h"
+#include "h2_conn.h"
 #include "h2_mplx.h"
+#include "h2_request.h"
 #include "h2_task.h"
 #include "h2_worker.h"
 
@@ -55,7 +57,7 @@ static void* APR_THREAD_FUNC execute(apr
         if (worker->task) {            
             h2_task_do(worker->task, worker);
             worker->task = NULL;
-            apr_thread_cond_signal(h2_worker_get_cond(worker));
+            apr_thread_cond_signal(worker->io);
         }
     }
 
@@ -112,7 +114,6 @@ h2_worker *h2_worker_create(int id,
         
         w->id = id;
         w->pool = pool;
-        w->bucket_alloc = apr_bucket_alloc_create(pool);
 
         w->get_next = get_next;
         w->worker_done = worker_done;
@@ -123,8 +124,9 @@ h2_worker *h2_worker_create(int id,
             return NULL;
         }
         
-        apr_pool_pre_cleanup_register(pool, w, cleanup_join_thread);
-        apr_thread_create(&w->thread, attr, execute, w, pool);
+        apr_pool_pre_cleanup_register(w->pool, w, cleanup_join_thread);
+        apr_thread_create(&w->thread, attr, execute, w, w->pool);
+        apr_pool_create(&w->task_pool, w->pool);
     }
     return w;
 }
@@ -157,28 +159,42 @@ int h2_worker_is_aborted(h2_worker *work
     return worker->aborted;
 }
 
-apr_thread_t *h2_worker_get_thread(h2_worker *worker)
+h2_task *h2_worker_create_task(h2_worker *worker, h2_mplx *m, 
+                               const h2_request *req, int eos)
 {
-    return worker->thread;
+    h2_task *task;
+    
+    /* Create a subpool from the worker one to be used for all things
+     * with life-time of this task execution.
+     */
+    task = h2_task_create(m->id, req, worker->task_pool, m, eos);
+    /* Link the task to the worker which provides useful things such
+     * as mutex, a socket etc. */
+    task->io = worker->io;
+    
+    return task;
 }
 
-apr_thread_cond_t *h2_worker_get_cond(h2_worker *worker)
-{
-    return worker->io;
+apr_status_t h2_worker_setup_task(h2_worker *worker, h2_task *task) {
+    apr_status_t status;
+    
+    
+    status = h2_conn_setup(task, apr_bucket_alloc_create(task->pool),
+                           worker->thread, worker->socket);
+    
+    return status;
 }
 
-apr_socket_t *h2_worker_get_socket(h2_worker *worker)
+void h2_worker_release_task(h2_worker *worker, struct h2_task *task)
 {
-    return worker->socket;
+    task->io = NULL;
+    task->pool = NULL;
+    apr_pool_clear(worker->task_pool);
 }
 
-apr_pool_t *h2_worker_get_pool(h2_worker *worker)
+apr_socket_t *h2_worker_get_socket(h2_worker *worker)
 {
-    return worker->pool;
+    return worker->socket;
 }
 
-apr_bucket_alloc_t *h2_worker_get_bucket_alloc(h2_worker *worker)
-{
-    return worker->bucket_alloc;
-}
 

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_worker.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_worker.h?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_worker.h (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_worker.h Thu Nov 19 17:14:03 2015
@@ -18,6 +18,7 @@
 
 struct apr_thread_cond_t;
 struct h2_mplx;
+struct h2_request;
 struct h2_task;
 
 /* h2_worker is a basically a apr_thread_t that reads fromt he h2_workers
@@ -44,7 +45,7 @@ struct h2_worker {
     int id;
     apr_thread_t *thread;
     apr_pool_t *pool;
-    apr_bucket_alloc_t *bucket_alloc;
+    apr_pool_t *task_pool;
     struct apr_thread_cond_t *io;
     apr_socket_t *socket;
     
@@ -142,14 +143,11 @@ int h2_worker_get_id(h2_worker *worker);
 
 int h2_worker_is_aborted(h2_worker *worker);
 
-apr_pool_t *h2_worker_get_pool(h2_worker *worker);
-
-apr_bucket_alloc_t *h2_worker_get_bucket_alloc(h2_worker *worker);
+struct h2_task *h2_worker_create_task(h2_worker *worker, struct h2_mplx *m, 
+                                      const struct h2_request *req, int eos);
+apr_status_t h2_worker_setup_task(h2_worker *worker, struct h2_task *task);
+void h2_worker_release_task(h2_worker *worker, struct h2_task *task);
 
 apr_socket_t *h2_worker_get_socket(h2_worker *worker);
 
-apr_thread_t *h2_worker_get_thread(h2_worker *worker);
-
-struct apr_thread_cond_t *h2_worker_get_cond(h2_worker *worker);
-
 #endif /* defined(__mod_h2__h2_worker__) */

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_workers.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_workers.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_workers.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/h2_workers.c Thu Nov 19 17:14:03 2015
@@ -79,7 +79,7 @@ static apr_status_t get_mplx_next(h2_wor
     if (*pm && ptask != NULL) {
         /* We have a h2_mplx instance and the worker wants the next task. 
          * Try to get one from the given mplx. */
-        *ptask = h2_mplx_pop_task(*pm, &has_more);
+        *ptask = h2_mplx_pop_task(*pm, worker, &has_more);
         if (*ptask) {
             return APR_SUCCESS;
         }
@@ -124,7 +124,7 @@ static apr_status_t get_mplx_next(h2_wor
                 m = H2_MPLX_LIST_FIRST(&workers->mplxs);
                 H2_MPLX_REMOVE(m);
                 
-                task = h2_mplx_pop_task(m, &has_more);
+                task = h2_mplx_pop_task(m, worker, &has_more);
                 if (task) {
                     if (has_more) {
                         H2_MPLX_LIST_INSERT_TAIL(&workers->mplxs, m);
@@ -174,7 +174,7 @@ static apr_status_t get_mplx_next(h2_wor
          * needed to give up with more than enough workers.
          */
         if (task) {
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, workers->s,
+            ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, workers->s,
                          "h2_worker(%d): start task(%s)",
                          h2_worker_get_id(worker), task->id);
             /* Since we hand out a reference to the worker, we increase
@@ -326,7 +326,7 @@ apr_status_t h2_workers_register(h2_work
 {
     apr_status_t status = apr_thread_mutex_lock(workers->lock);
     if (status == APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, status, workers->s,
+        ap_log_error(APLOG_MARK, APLOG_TRACE2, status, workers->s,
                      "h2_workers: register mplx(%ld)", m->id);
         if (in_list(workers, m)) {
             status = APR_EAGAIN;

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/http2/mod_http2.dsp
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/http2/mod_http2.dsp?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/http2/mod_http2.dsp (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/http2/mod_http2.dsp Thu Nov 19 17:14:03 2015
@@ -149,6 +149,10 @@ SOURCE=./h2_mplx.c
 # End Source File
 # Begin Source File
 
+SOURCE=./h2_push.c
+# End Source File
+# Begin Source File
+
 SOURCE=./h2_request.c
 # End Source File
 # Begin Source File
@@ -189,10 +193,6 @@ SOURCE=./h2_task_queue.c
 # End Source File
 # Begin Source File
 
-SOURCE=./h2_to_h1.c
-# End Source File
-# Begin Source File
-
 SOURCE=./h2_util.c
 # End Source File
 # Begin Source File

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/ssl/ssl_engine_io.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/ssl/ssl_engine_io.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/ssl/ssl_engine_io.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/ssl/ssl_engine_io.c Thu Nov 19 17:14:03 2015
@@ -187,6 +187,7 @@ static int bio_filter_out_write(BIO *bio
 {
     bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr);
     apr_bucket *e;
+    int need_flush;
 
     /* Abort early if the client has initiated a renegotiation. */
     if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
@@ -205,6 +206,26 @@ static int bio_filter_out_write(BIO *bio
     e = apr_bucket_transient_create(in, inl, outctx->bb->bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(outctx->bb, e);
 
+    /* In theory, OpenSSL should flush as necessary, but it is known
+     * not to do so correctly in some cases (< 0.9.8m; see PR 46952),
+     * or on the proxy/client side (after ssl23_client_hello(), e.g.
+     * ssl/proxy.t test suite).
+     *
+     * Historically, this flush call was performed only for an SSLv2
+     * connection or for a proxy connection.  Calling _out_flush can
+     * be expensive in cases where requests/reponses are pipelined,
+     * so limit the performance impact to handshake time.
+     */
+#if OPENSSL_VERSION_NUMBER < 0x0009080df
+     need_flush = !SSL_is_init_finished(outctx->filter_ctx->pssl)
+#else
+     need_flush = SSL_in_connect_init(outctx->filter_ctx->pssl);
+#endif
+    if (need_flush) {
+        e = apr_bucket_flush_create(outctx->bb->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(outctx->bb, e);
+    }
+
     if (bio_filter_out_pass(outctx) < 0) {
         return -1;
     }
@@ -445,21 +466,6 @@ static int bio_filter_in_read(BIO *bio,
         return -1;
     }
 
-    /* In theory, OpenSSL should flush as necessary, but it is known
-     * not to do so correctly in some cases; see PR 46952.
-     *
-     * Historically, this flush call was performed only for an SSLv2
-     * connection or for a proxy connection.  Calling _out_flush
-     * should be very cheap in cases where it is unnecessary (and no
-     * output is buffered) so the performance impact of doing it
-     * unconditionally should be minimal.
-     */
-    if (bio_filter_out_flush(inctx->bio_out) < 0) {
-        bio_filter_out_ctx_t *outctx = inctx->bio_out->ptr;
-        inctx->rc = outctx->rc;
-        return -1;
-    }
-
     BIO_clear_retry_flags(bio);
 
     if (!inctx->bb) {
@@ -857,7 +863,8 @@ static void ssl_io_filter_disable(SSLCon
 
 static apr_status_t ssl_io_filter_error(ap_filter_t *f,
                                         apr_bucket_brigade *bb,
-                                        apr_status_t status)
+                                        apr_status_t status,
+                                        int is_init)
 {
     SSLConnRec *sslconn = myConnConfig(f->c);
     apr_bucket *bucket;
@@ -871,8 +878,13 @@ static apr_status_t ssl_io_filter_error(
                          "trying to send HTML error page");
             ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, sslconn->server);
 
-            sslconn->non_ssl_request = NON_SSL_SEND_HDR_SEP;
             ssl_io_filter_disable(sslconn, f);
+            f->c->keepalive = AP_CONN_CLOSE;
+            if (is_init) {
+                sslconn->non_ssl_request = NON_SSL_SEND_REQLINE;
+                return APR_EGENERAL;
+            }
+            sslconn->non_ssl_request = NON_SSL_SEND_HDR_SEP;
 
             /* fake the request line */
             bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);
@@ -1326,11 +1338,22 @@ static apr_status_t ssl_io_filter_input(
     }
 
     if (!inctx->ssl) {
+        apr_bucket *bucket;
         SSLConnRec *sslconn = myConnConfig(f->c);
+        if (sslconn->non_ssl_request == NON_SSL_SEND_REQLINE) {
+            bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);
+            APR_BRIGADE_INSERT_TAIL(bb, bucket);
+            if (mode != AP_MODE_SPECULATIVE) {
+                sslconn->non_ssl_request = NON_SSL_SEND_HDR_SEP;
+            }
+            return APR_SUCCESS;
+        }
         if (sslconn->non_ssl_request == NON_SSL_SEND_HDR_SEP) {
-            apr_bucket *bucket = apr_bucket_immortal_create(CRLF, 2, f->c->bucket_alloc);
+            bucket = apr_bucket_immortal_create(CRLF, 2, f->c->bucket_alloc);
             APR_BRIGADE_INSERT_TAIL(bb, bucket);
-            sslconn->non_ssl_request = NON_SSL_SET_ERROR_MSG;
+            if (mode != AP_MODE_SPECULATIVE) {
+                sslconn->non_ssl_request = NON_SSL_SET_ERROR_MSG;
+            }
             return APR_SUCCESS;
         }
         return ap_get_brigade(f->next, bb, mode, block, readbytes);
@@ -1351,7 +1374,7 @@ static apr_status_t ssl_io_filter_input(
      * rather than have SSLEngine On configured.
      */
     if ((status = ssl_io_filter_handshake(inctx->filter_ctx)) != APR_SUCCESS) {
-        return ssl_io_filter_error(f, bb, status);
+        return ssl_io_filter_error(f, bb, status, is_init);
     }
 
     if (is_init) {
@@ -1405,7 +1428,7 @@ static apr_status_t ssl_io_filter_input(
 
     /* Handle custom errors. */
     if (status != APR_SUCCESS) {
-        return ssl_io_filter_error(f, bb, status);
+        return ssl_io_filter_error(f, bb, status, 0);
     }
 
     /* Create a transient bucket out of the decrypted data. */
@@ -1591,52 +1614,33 @@ static apr_status_t ssl_io_filter_output
     inctx->block = APR_BLOCK_READ;
 
     if ((status = ssl_io_filter_handshake(filter_ctx)) != APR_SUCCESS) {
-        return ssl_io_filter_error(f, bb, status);
+        return ssl_io_filter_error(f, bb, status, 0);
     }
 
-    while (!APR_BRIGADE_EMPTY(bb)) {
+    while (!APR_BRIGADE_EMPTY(bb) && status == APR_SUCCESS) {
         apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
 
-        /* If it is a flush or EOS, we need to pass this down.
-         * These types do not require translation by OpenSSL.
-         */
-        if (APR_BUCKET_IS_EOS(bucket) || APR_BUCKET_IS_FLUSH(bucket)) {
-            if (bio_filter_out_flush(filter_ctx->pbioWrite) < 0) {
-                status = outctx->rc;
-                break;
-            }
-
-            if (APR_BUCKET_IS_EOS(bucket)) {
-                /*
-                 * By definition, nothing can come after EOS.
-                 * which also means we can pass the rest of this brigade
-                 * without creating a new one since it only contains the
-                 * EOS bucket.
-                 */
-
-                if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
-                    return status;
-                }
-                break;
-            }
-            else {
-                /* bio_filter_out_flush() already passed down a flush bucket
-                 * if there was any data to be flushed.
-                 */
-                apr_bucket_delete(bucket);
-            }
-        }
-        else if (AP_BUCKET_IS_EOC(bucket)) {
-            /* The EOC bucket indicates connection closure, so SSL
-             * shutdown must now be performed.  */
-            ssl_filter_io_shutdown(filter_ctx, f->c, 0);
-            if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
-                return status;
-            }
-            break;
+        if (APR_BUCKET_IS_METADATA(bucket)) {
+            /* Pass through metadata buckets untouched.  EOC is
+             * special; terminate the SSL layer first. */
+            if (AP_BUCKET_IS_EOC(bucket)) {
+                ssl_filter_io_shutdown(filter_ctx, f->c, 0);
+            }
+            AP_DEBUG_ASSERT(APR_BRIGADE_EMPTY(outctx->bb));
+
+            /* Metadata buckets are passed one per brigade; it might
+             * be more efficient (but also more complex) to use
+             * outctx->bb as a true buffer and interleave these with
+             * data buckets. */
+            APR_BUCKET_REMOVE(bucket);
+            APR_BRIGADE_INSERT_HEAD(outctx->bb, bucket);
+            status = ap_pass_brigade(f->next, outctx->bb);
+            if (status == APR_SUCCESS && f->c->aborted)
+                status = APR_ECONNRESET;
+            apr_brigade_cleanup(outctx->bb);
         }
         else {
-            /* filter output */
+            /* Filter a data bucket. */
             const char *data;
             apr_size_t len;
 
@@ -1649,7 +1653,9 @@ static apr_status_t ssl_io_filter_output
                     break;
                 }
                 rblock = APR_BLOCK_READ;
-                continue; /* and try again with a blocking read. */
+                /* and try again with a blocking read. */
+                status = APR_SUCCESS;
+                continue;
             }
 
             rblock = APR_NONBLOCK_READ;
@@ -1660,11 +1666,8 @@ static apr_status_t ssl_io_filter_output
 
             status = ssl_filter_write(f, data, len);
             apr_bucket_delete(bucket);
-
-            if (status != APR_SUCCESS) {
-                break;
-            }
         }
+
     }
 
     return status;

Modified: httpd/httpd/branches/2.4-http2-alpha/modules/ssl/ssl_private.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/modules/ssl/ssl_private.h?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/modules/ssl/ssl_private.h (original)
+++ httpd/httpd/branches/2.4-http2-alpha/modules/ssl/ssl_private.h Thu Nov 19 17:14:03 2015
@@ -442,6 +442,7 @@ typedef struct {
     int disabled;
     enum {
         NON_SSL_OK = 0,        /* is SSL request, or error handling completed */
+        NON_SSL_SEND_REQLINE,  /* Need to send the fake request line */
         NON_SSL_SEND_HDR_SEP,  /* Need to send the header separator */
         NON_SSL_SET_ERROR_MSG  /* Need to set the error message */
     } non_ssl_request;

Modified: httpd/httpd/branches/2.4-http2-alpha/server/core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4-http2-alpha/server/core.c?rev=1715218&r1=1715217&r2=1715218&view=diff
==============================================================================
--- httpd/httpd/branches/2.4-http2-alpha/server/core.c (original)
+++ httpd/httpd/branches/2.4-http2-alpha/server/core.c Thu Nov 19 17:14:03 2015
@@ -1736,7 +1736,7 @@ static const char *set_override_list(cmd
 
     d->override_list = apr_table_make(cmd->pool, argc);
 
-    for (i=0;i<argc;i++){
+    for (i = 0; i < argc; i++) {
         if (!strcasecmp(argv[i], "None")) {
             if (argc != 1) {
                 return "'None' not allowed with other directives in "
@@ -1747,6 +1747,7 @@ static const char *set_override_list(cmd
         else {
             const command_rec *result = NULL;
             module *mod = ap_top_module;
+
             result = ap_find_command_in_modules(argv[i], &mod);
             if (result == NULL) {
                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
@@ -1765,7 +1766,7 @@ static const char *set_override_list(cmd
                 continue;
             }
             else {
-                apr_table_set(d->override_list, argv[i], "1");
+                apr_table_setn(d->override_list, argv[i], "1");
             }
         }
     }