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");
}
}
}