summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2016-12-31 13:11:59 +0000
committerStefan Eissing <icing@apache.org>2016-12-31 13:11:59 +0000
commit85900b7fd8faf51fad3a2410556bfe71b7c53896 (patch)
treea61e49c798894a00b00b41d93f1126b2d922a65a
parent1d7573a0f8ad2a069d62a52c94aa8ae9605dbf2a (diff)
downloadhttpd-85900b7fd8faf51fad3a2410556bfe71b7c53896.tar.gz
On the trunk:
mod_http2: adding support for MergeTrailers directive. mod_http2: limiting DATA frame sizes by TLS record sizes in use on the connection. Flushing outgoing frames earlier. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1776735 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES5
-rw-r--r--modules/http2/h2_config.c16
-rw-r--r--modules/http2/h2_config.h2
-rw-r--r--modules/http2/h2_conn.c6
-rw-r--r--modules/http2/h2_conn_io.c16
-rw-r--r--modules/http2/h2_conn_io.h1
-rw-r--r--modules/http2/h2_from_h1.c9
-rw-r--r--modules/http2/h2_session.c6
-rw-r--r--modules/http2/h2_stream.c11
9 files changed, 57 insertions, 15 deletions
diff --git a/CHANGES b/CHANGES
index 40bfa5d52d..bb9b761c61 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.0
+ *) mod_http2: adding support for MergeTrailers directive. [Stefan Eissing]
+
+ *) mod_http2: limiting DATA frame sizes by TLS record sizes in use on the
+ connection. Flushing outgoing frames earlier. [Stefan Eissing]
+
*) mod_remoteip: Add support for PROXY protocol (code donated by Cloudzilla).
Add ability for PROXY protocol processing to be optional to donated code.
See also: http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
diff --git a/modules/http2/h2_config.c b/modules/http2/h2_config.c
index 669d20e75c..f91c8c257a 100644
--- a/modules/http2/h2_config.c
+++ b/modules/http2/h2_config.c
@@ -64,6 +64,7 @@ static h2_config defconf = {
0, /* copy files across threads */
NULL, /* push list */
0, /* early hints, http status 103 */
+ 2, /* TLS records flush count */
};
void h2_config_init(apr_pool_t *pool)
@@ -99,6 +100,7 @@ static void *h2_config_create(apr_pool_t *pool,
conf->copy_files = DEF_VAL;
conf->push_list = NULL;
conf->early_hints = DEF_VAL;
+ conf->tls_flush_count = DEF_VAL;
return conf;
}
@@ -151,6 +153,7 @@ static void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
n->push_list = add->push_list? add->push_list : base->push_list;
}
n->early_hints = H2_CONFIG_GET(add, base, early_hints);
+ n->tls_flush_count = H2_CONFIG_GET(add, base, tls_flush_count);
return n;
}
@@ -208,6 +211,8 @@ apr_int64_t h2_config_geti64(const h2_config *conf, h2_config_var_t var)
return H2_CONFIG_GET(conf, &defconf, copy_files);
case H2_CONF_EARLY_HINTS:
return H2_CONFIG_GET(conf, &defconf, early_hints);
+ case H2_CONF_TLS_FLUSH_COUNT:
+ return H2_CONFIG_GET(conf, &defconf, tls_flush_count);
default:
return DEF_VAL;
}
@@ -505,6 +510,15 @@ static const char *h2_conf_set_tls_cooldown_secs(cmd_parms *parms,
return NULL;
}
+static const char *h2_conf_set_tls_flush_count(cmd_parms *parms,
+ void *arg, const char *value)
+{
+ h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
+ cfg->tls_flush_count = (int)apr_atoi64(value);
+ (void)arg;
+ return NULL;
+}
+
static const char *h2_conf_set_push_diary_size(cmd_parms *parms,
void *arg, const char *value)
{
@@ -643,6 +657,8 @@ const command_rec h2_cmds[] = {
RSRC_CONF, "number of bytes on TLS connection before doing max writes"),
AP_INIT_TAKE1("H2TLSCoolDownSecs", h2_conf_set_tls_cooldown_secs, NULL,
RSRC_CONF, "seconds of idle time on TLS before shrinking writes"),
+ AP_INIT_TAKE1("H2TLSFlushCount", h2_conf_set_tls_flush_count, NULL,
+ RSRC_CONF, "number of max TLS records before output is flushed"),
AP_INIT_TAKE1("H2Push", h2_conf_set_push, NULL,
RSRC_CONF, "off to disable HTTP/2 server push"),
AP_INIT_TAKE23("H2PushPriority", h2_conf_add_push_priority, NULL,
diff --git a/modules/http2/h2_config.h b/modules/http2/h2_config.h
index 1f2fe309d0..60257df427 100644
--- a/modules/http2/h2_config.h
+++ b/modules/http2/h2_config.h
@@ -42,6 +42,7 @@ typedef enum {
H2_CONF_PUSH_DIARY_SIZE,
H2_CONF_COPY_FILES,
H2_CONF_EARLY_HINTS,
+ H2_CONF_TLS_FLUSH_COUNT,
} h2_config_var_t;
struct apr_hash_t;
@@ -79,6 +80,7 @@ typedef struct h2_config {
int copy_files; /* if files shall be copied vs setaside on output */
apr_array_header_t *push_list;/* list of h2_push_res configurations */
int early_hints; /* support status code 103 */
+ int tls_flush_count; /* max # of TLS records until output flushed */
} h2_config;
diff --git a/modules/http2/h2_conn.c b/modules/http2/h2_conn.c
index 6f3a8cfe8e..81d2b7f5f3 100644
--- a/modules/http2/h2_conn.c
+++ b/modules/http2/h2_conn.c
@@ -208,7 +208,9 @@ apr_status_t h2_conn_run(struct h2_ctx *ctx, conn_rec *c)
do {
if (c->cs) {
c->cs->sense = CONN_SENSE_DEFAULT;
+ c->cs->state = CONN_STATE_HANDLER;
}
+
status = h2_session_process(h2_ctx_session_get(ctx), async_mpm);
if (APR_STATUS_IS_EOF(status)) {
@@ -227,6 +229,10 @@ apr_status_t h2_conn_run(struct h2_ctx *ctx, conn_rec *c)
&& c->keepalive == AP_CONN_KEEPALIVE
&& mpm_state != AP_MPMQ_STOPPING);
+ if (c->cs) {
+ c->cs->state = CONN_STATE_WRITE_COMPLETION;
+ }
+
return DONE;
}
diff --git a/modules/http2/h2_conn_io.c b/modules/http2/h2_conn_io.c
index 303860eeb8..13d29913df 100644
--- a/modules/http2/h2_conn_io.c
+++ b/modules/http2/h2_conn_io.c
@@ -133,6 +133,7 @@ apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c,
io->is_tls = h2_h2_is_tls(c);
io->buffer_output = io->is_tls;
io->pass_threshold = (apr_size_t)h2_config_geti64(cfg, H2_CONF_STREAM_MAX_MEM) / 2;
+ io->flush_factor = h2_config_geti(cfg, H2_CONF_TLS_FLUSH_COUNT);
if (io->is_tls) {
/* This is what we start with,
@@ -420,9 +421,18 @@ apr_status_t h2_conn_io_pass(h2_conn_io *io, apr_bucket_brigade *bb)
if (status == APR_SUCCESS) {
if (!APR_BRIGADE_EMPTY(io->output)) {
- apr_off_t len = h2_brigade_mem_size(io->output);
- if (len >= io->pass_threshold) {
- return pass_output(io, 0, NULL);
+ apr_off_t len;
+ if (io->buffer_output) {
+ apr_brigade_length(io->output, 0, &len);
+ if (len >= (io->flush_factor * io->write_size)) {
+ return pass_output(io, 1, NULL);
+ }
+ }
+ else {
+ len = h2_brigade_mem_size(io->output);
+ if (len >= io->pass_threshold) {
+ return pass_output(io, 0, NULL);
+ }
}
}
}
diff --git a/modules/http2/h2_conn_io.h b/modules/http2/h2_conn_io.h
index 4ccf007086..bda0c8ff6d 100644
--- a/modules/http2/h2_conn_io.h
+++ b/modules/http2/h2_conn_io.h
@@ -40,6 +40,7 @@ typedef struct {
int buffer_output;
apr_size_t pass_threshold;
+ int flush_factor;
char *scratch;
apr_size_t ssize;
diff --git a/modules/http2/h2_from_h1.c b/modules/http2/h2_from_h1.c
index 108e318276..64cfb76778 100644
--- a/modules/http2/h2_from_h1.c
+++ b/modules/http2/h2_from_h1.c
@@ -730,6 +730,9 @@ apr_status_t h2_filter_request_in(ap_filter_t* f,
request_rec *r = f->r;
apr_status_t status = APR_SUCCESS;
apr_bucket *b, *next;
+ core_server_config *conf =
+ (core_server_config *) ap_get_module_config(r->server->module_config,
+ &core_module);
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, f->r,
"h2_task(%s): request filter, exp=%d", task->id, r->expecting_100);
@@ -744,7 +747,11 @@ apr_status_t h2_filter_request_in(ap_filter_t* f,
ap_assert(headers);
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
"h2_task(%s): receiving trailers", task->id);
- r->trailers_in = apr_table_clone(r->pool, headers->headers);
+ r->trailers_in = headers->headers;
+ if (conf && conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE) {
+ r->headers_in = apr_table_overlay(r->pool, r->headers_in,
+ r->trailers_in);
+ }
APR_BUCKET_REMOVE(b);
apr_bucket_destroy(b);
ap_remove_input_filter(f);
diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c
index 44eed63325..f2db2997f7 100644
--- a/modules/http2/h2_session.c
+++ b/modules/http2/h2_session.c
@@ -1394,6 +1394,8 @@ static apr_status_t h2_session_send(h2_session *session)
apr_socket_timeout_set(socket, session->s->timeout);
}
+ /* This sends one round of frames from every able stream, plus
+ * settings etc. if accumulated */
rv = nghttp2_session_send(session->ngh2);
if (socket) {
@@ -2040,10 +2042,6 @@ apr_status_t h2_session_process(h2_session *session, int async)
session->id, async);
}
- if (c->cs) {
- c->cs->state = CONN_STATE_WRITE_COMPLETION;
- }
-
while (session->state != H2_SESSION_ST_DONE) {
trace = APLOGctrace3(c);
session->have_read = session->have_written = 0;
diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c
index 815b6e313b..6fe5ed46cd 100644
--- a/modules/http2/h2_stream.c
+++ b/modules/http2/h2_stream.c
@@ -602,7 +602,7 @@ apr_status_t h2_stream_out_prepare(h2_stream *stream, apr_off_t *plen,
{
conn_rec *c = stream->session->c;
apr_status_t status = APR_SUCCESS;
- apr_off_t requested;
+ apr_off_t requested, max_chunk = H2_DATA_CHUNK_SIZE;
apr_bucket *b, *e;
if (presponse) {
@@ -620,13 +620,10 @@ apr_status_t h2_stream_out_prepare(h2_stream *stream, apr_off_t *plen,
}
prep_output(stream);
- if (*plen > 0) {
- requested = H2MIN(*plen, H2_DATA_CHUNK_SIZE);
+ if (stream->session->io.write_size > 0) {
+ max_chunk = stream->session->io.write_size - 9; /* header bits */
}
- else {
- requested = H2_DATA_CHUNK_SIZE;
- }
- *plen = requested;
+ *plen = requested = (*plen > 0)? H2MIN(*plen, max_chunk) : max_chunk;
H2_STREAM_OUT_LOG(APLOG_TRACE2, stream, "h2_stream_out_prepare_pre");
h2_util_bb_avail(stream->out_buffer, plen, peos);