File apache2-mod_http2-1.14.1.patch of Package apache2.18661
Index: httpd-2.4.23/modules/http2/config2.m4
===================================================================
--- httpd-2.4.23.orig/modules/http2/config2.m4 2019-04-02 13:39:34.060792511 +0200
+++ httpd-2.4.23/modules/http2/config2.m4 2019-04-02 13:39:34.256793490 +0200
@@ -31,7 +31,6 @@ h2_from_h1.lo dnl
h2_h2.lo dnl
h2_headers.lo dnl
h2_mplx.lo dnl
-h2_ngn_shed.lo dnl
h2_push.lo dnl
h2_request.lo dnl
h2_session.lo dnl
Index: httpd-2.4.23/modules/http2/h2_alt_svc.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_alt_svc.c 2019-04-02 13:39:34.064792531 +0200
+++ httpd-2.4.23/modules/http2/h2_alt_svc.c 2019-04-02 13:39:34.256793490 +0200
@@ -74,7 +74,7 @@ h2_alt_svc *h2_alt_svc_parse(const char
static int h2_alt_svc_handler(request_rec *r)
{
- const h2_config *cfg;
+ apr_array_header_t *alt_svcs;
int i;
if (r->connection->keepalives > 0) {
@@ -86,8 +86,8 @@ static int h2_alt_svc_handler(request_re
return DECLINED;
}
- cfg = h2_config_sget(r->server);
- if (r->hostname && cfg && cfg->alt_svcs && cfg->alt_svcs->nelts > 0) {
+ alt_svcs = h2_config_alt_svcs(r);
+ if (r->hostname && alt_svcs && alt_svcs->nelts > 0) {
const char *alt_svc_used = apr_table_get(r->headers_in, "Alt-Svc-Used");
if (!alt_svc_used) {
/* We have alt-svcs defined and client is not already using
@@ -98,7 +98,7 @@ static int h2_alt_svc_handler(request_re
const char *alt_svc = "";
const char *svc_ma = "";
int secure = h2_h2_is_tls(r->connection);
- int ma = h2_config_geti(cfg, H2_CONF_ALT_SVC_MAX_AGE);
+ int ma = h2_config_rgeti(r, H2_CONF_ALT_SVC_MAX_AGE);
if (ma >= 0) {
svc_ma = apr_psprintf(r->pool, "; ma=%d", ma);
}
@@ -106,8 +106,8 @@ static int h2_alt_svc_handler(request_re
"h2_alt_svc: announce %s for %s:%d",
(secure? "secure" : "insecure"),
r->hostname, (int)r->server->port);
- for (i = 0; i < cfg->alt_svcs->nelts; ++i) {
- h2_alt_svc *as = h2_alt_svc_IDX(cfg->alt_svcs, i);
+ for (i = 0; i < alt_svcs->nelts; ++i) {
+ h2_alt_svc *as = h2_alt_svc_IDX(alt_svcs, i);
const char *ahost = as->host;
if (ahost && !apr_strnatcasecmp(ahost, r->hostname)) {
ahost = NULL;
Index: httpd-2.4.23/modules/http2/h2_config.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_config.c 2019-04-02 13:39:34.192793170 +0200
+++ httpd-2.4.23/modules/http2/h2_config.c 2019-04-02 13:42:32.649683136 +0200
@@ -41,6 +41,55 @@
#define H2_CONFIG_GET(a, b, n) \
(((a)->n == DEF_VAL)? (b) : (a))->n
+#define H2_CONFIG_SET(a, n, v) \
+ ((a)->n = v)
+
+#define CONFIG_CMD_SET(cmd,dir,var,val) \
+ h2_config_seti(((cmd)->path? (dir) : NULL), h2_config_sget((cmd)->server), var, val)
+
+#define CONFIG_CMD_SET64(cmd,dir,var,val) \
+ h2_config_seti64(((cmd)->path? (dir) : NULL), h2_config_sget((cmd)->server), var, val)
+
+/* Apache httpd module configuration for h2. */
+typedef struct h2_config {
+ const char *name;
+ int h2_max_streams; /* max concurrent # streams (http2) */
+ int h2_window_size; /* stream window size (http2) */
+ int min_workers; /* min # of worker threads/child */
+ int max_workers; /* max # of worker threads/child */
+ int max_worker_idle_secs; /* max # of idle seconds for worker */
+ int stream_max_mem_size; /* max # bytes held in memory/stream */
+ apr_array_header_t *alt_svcs; /* h2_alt_svc specs for this server */
+ int alt_svc_max_age; /* seconds clients can rely on alt-svc info*/
+ int serialize_headers; /* Use serialized HTTP/1.1 headers for
+ processing, better compatibility */
+ int h2_direct; /* if mod_h2 is active directly */
+ int modern_tls_only; /* Accept only modern TLS in HTTP/2 connections */
+ int h2_upgrade; /* Allow HTTP/1 upgrade to h2/h2c */
+ apr_int64_t tls_warmup_size; /* Amount of TLS data to send before going full write size */
+ int tls_cooldown_secs; /* Seconds of idle time before going back to small TLS records */
+ int h2_push; /* if HTTP/2 server push is enabled */
+ struct apr_hash_t *priorities;/* map of content-type to h2_priority records */
+
+ int push_diary_size; /* # of entries in push diary */
+ 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 padding_bits;
+ int padding_always;
+} h2_config;
+
+typedef struct h2_dir_config {
+ const char *name;
+ apr_array_header_t *alt_svcs; /* h2_alt_svc specs for this server */
+ int alt_svc_max_age; /* seconds clients can rely on alt-svc info*/
+ int h2_upgrade; /* Allow HTTP/1 upgrade to h2/h2c */
+ int h2_push; /* if HTTP/2 server push is enabled */
+ apr_array_header_t *push_list;/* list of h2_push_res configurations */
+ int early_hints; /* support status code 103 */
+} h2_dir_config;
+
+
static h2_config defconf = {
"default",
100, /* max_streams */
@@ -63,6 +112,18 @@ static h2_config defconf = {
0, /* copy files across threads */
NULL, /* push list */
0, /* early hints, http status 103 */
+ 0, /* padding bits */
+ 1, /* padding always */
+};
+
+static h2_dir_config defdconf = {
+ "default",
+ NULL, /* no alt-svcs */
+ -1, /* alt-svc max age */
+ -1, /* HTTP/1 Upgrade support */
+ -1, /* HTTP/2 server push enabled */
+ NULL, /* push list */
+ -1, /* early hints, http status 103 */
};
void h2_config_init(apr_pool_t *pool)
@@ -70,12 +131,10 @@ void h2_config_init(apr_pool_t *pool)
(void)pool;
}
-static void *h2_config_create(apr_pool_t *pool,
- const char *prefix, const char *x)
+void *h2_config_create_svr(apr_pool_t *pool, server_rec *s)
{
h2_config *conf = (h2_config *)apr_pcalloc(pool, sizeof(h2_config));
- const char *s = x? x : "unknown";
- char *name = apr_pstrcat(pool, prefix, "[", s, "]", NULL);
+ char *name = apr_pstrcat(pool, "srv[", s->defn_name, "]", NULL);
conf->name = name;
conf->h2_max_streams = DEF_VAL;
@@ -97,19 +156,11 @@ static void *h2_config_create(apr_pool_t
conf->copy_files = DEF_VAL;
conf->push_list = NULL;
conf->early_hints = DEF_VAL;
+ conf->padding_bits = DEF_VAL;
+ conf->padding_always = DEF_VAL;
return conf;
}
-void *h2_config_create_svr(apr_pool_t *pool, server_rec *s)
-{
- return h2_config_create(pool, "srv", s->defn_name);
-}
-
-void *h2_config_create_dir(apr_pool_t *pool, char *x)
-{
- return h2_config_create(pool, "dir", x);
-}
-
static void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
{
h2_config *base = (h2_config *)basev;
@@ -148,25 +199,52 @@ static void *h2_config_merge(apr_pool_t
n->push_list = add->push_list? add->push_list : base->push_list;
}
n->early_hints = H2_CONFIG_GET(add, base, early_hints);
+ n->padding_bits = H2_CONFIG_GET(add, base, padding_bits);
+ n->padding_always = H2_CONFIG_GET(add, base, padding_always);
return n;
}
-void *h2_config_merge_dir(apr_pool_t *pool, void *basev, void *addv)
+void *h2_config_merge_svr(apr_pool_t *pool, void *basev, void *addv)
{
return h2_config_merge(pool, basev, addv);
}
-void *h2_config_merge_svr(apr_pool_t *pool, void *basev, void *addv)
+void *h2_config_create_dir(apr_pool_t *pool, char *x)
{
- return h2_config_merge(pool, basev, addv);
+ h2_dir_config *conf = (h2_dir_config *)apr_pcalloc(pool, sizeof(h2_dir_config));
+ const char *s = x? x : "unknown";
+ char *name = apr_pstrcat(pool, "dir[", s, "]", NULL);
+
+ conf->name = name;
+ conf->alt_svc_max_age = DEF_VAL;
+ conf->h2_upgrade = DEF_VAL;
+ conf->h2_push = DEF_VAL;
+ conf->early_hints = DEF_VAL;
+ return conf;
}
-int h2_config_geti(const h2_config *conf, h2_config_var_t var)
+void *h2_config_merge_dir(apr_pool_t *pool, void *basev, void *addv)
{
- return (int)h2_config_geti64(conf, var);
+ h2_dir_config *base = (h2_dir_config *)basev;
+ h2_dir_config *add = (h2_dir_config *)addv;
+ h2_dir_config *n = (h2_dir_config *)apr_pcalloc(pool, sizeof(h2_dir_config));
+
+ n->name = apr_pstrcat(pool, "merged[", add->name, ", ", base->name, "]", NULL);
+ n->alt_svcs = add->alt_svcs? add->alt_svcs : base->alt_svcs;
+ n->alt_svc_max_age = H2_CONFIG_GET(add, base, alt_svc_max_age);
+ n->h2_upgrade = H2_CONFIG_GET(add, base, h2_upgrade);
+ n->h2_push = H2_CONFIG_GET(add, base, h2_push);
+ if (add->push_list && base->push_list) {
+ n->push_list = apr_array_append(pool, base->push_list, add->push_list);
+ }
+ else {
+ n->push_list = add->push_list? add->push_list : base->push_list;
+ }
+ n->early_hints = H2_CONFIG_GET(add, base, early_hints);
+ return n;
}
-apr_int64_t h2_config_geti64(const h2_config *conf, h2_config_var_t var)
+static apr_int64_t h2_srv_config_geti64(const h2_config *conf, h2_config_var_t var)
{
switch(var) {
case H2_CONF_MAX_STREAMS:
@@ -190,7 +268,8 @@ apr_int64_t h2_config_geti64(const h2_co
case H2_CONF_UPGRADE:
return H2_CONFIG_GET(conf, &defconf, h2_upgrade);
case H2_CONF_DIRECT:
- return H2_CONFIG_GET(conf, &defconf, h2_direct);
+ return 1;
+ /*return H2_CONFIG_GET(conf, &defconf, h2_direct);*/
case H2_CONF_TLS_WARMUP_SIZE:
return H2_CONFIG_GET(conf, &defconf, tls_warmup_size);
case H2_CONF_TLS_COOLDOWN_SECS:
@@ -203,12 +282,93 @@ apr_int64_t h2_config_geti64(const h2_co
return H2_CONFIG_GET(conf, &defconf, copy_files);
case H2_CONF_EARLY_HINTS:
return H2_CONFIG_GET(conf, &defconf, early_hints);
+ case H2_CONF_PADDING_BITS:
+ return H2_CONFIG_GET(conf, &defconf, padding_bits);
+ case H2_CONF_PADDING_ALWAYS:
+ return H2_CONFIG_GET(conf, &defconf, padding_always);
default:
return DEF_VAL;
}
}
-const h2_config *h2_config_sget(server_rec *s)
+static void h2_srv_config_seti(h2_config *conf, h2_config_var_t var, int val)
+{
+ switch(var) {
+ case H2_CONF_MAX_STREAMS:
+ H2_CONFIG_SET(conf, h2_max_streams, val);
+ break;
+ case H2_CONF_WIN_SIZE:
+ H2_CONFIG_SET(conf, h2_window_size, val);
+ break;
+ case H2_CONF_MIN_WORKERS:
+ H2_CONFIG_SET(conf, min_workers, val);
+ break;
+ case H2_CONF_MAX_WORKERS:
+ H2_CONFIG_SET(conf, max_workers, val);
+ break;
+ case H2_CONF_MAX_WORKER_IDLE_SECS:
+ H2_CONFIG_SET(conf, max_worker_idle_secs, val);
+ break;
+ case H2_CONF_STREAM_MAX_MEM:
+ H2_CONFIG_SET(conf, stream_max_mem_size, val);
+ break;
+ case H2_CONF_ALT_SVC_MAX_AGE:
+ H2_CONFIG_SET(conf, alt_svc_max_age, val);
+ break;
+ case H2_CONF_SER_HEADERS:
+ H2_CONFIG_SET(conf, serialize_headers, val);
+ break;
+ case H2_CONF_MODERN_TLS_ONLY:
+ H2_CONFIG_SET(conf, modern_tls_only, val);
+ break;
+ case H2_CONF_UPGRADE:
+ H2_CONFIG_SET(conf, h2_upgrade, val);
+ break;
+ case H2_CONF_DIRECT:
+ H2_CONFIG_SET(conf, h2_direct, val);
+ break;
+ case H2_CONF_TLS_WARMUP_SIZE:
+ H2_CONFIG_SET(conf, tls_warmup_size, val);
+ break;
+ case H2_CONF_TLS_COOLDOWN_SECS:
+ H2_CONFIG_SET(conf, tls_cooldown_secs, val);
+ break;
+ case H2_CONF_PUSH:
+ H2_CONFIG_SET(conf, h2_push, val);
+ break;
+ case H2_CONF_PUSH_DIARY_SIZE:
+ H2_CONFIG_SET(conf, push_diary_size, val);
+ break;
+ case H2_CONF_COPY_FILES:
+ H2_CONFIG_SET(conf, copy_files, val);
+ break;
+ case H2_CONF_EARLY_HINTS:
+ H2_CONFIG_SET(conf, early_hints, val);
+ break;
+ case H2_CONF_PADDING_BITS:
+ H2_CONFIG_SET(conf, padding_bits, val);
+ break;
+ case H2_CONF_PADDING_ALWAYS:
+ H2_CONFIG_SET(conf, padding_always, val);
+ break;
+ default:
+ break;
+ }
+}
+
+static void h2_srv_config_seti64(h2_config *conf, h2_config_var_t var, apr_int64_t val)
+{
+ switch(var) {
+ case H2_CONF_TLS_WARMUP_SIZE:
+ H2_CONFIG_SET(conf, tls_warmup_size, val);
+ break;
+ default:
+ h2_srv_config_seti(conf, var, (int)val);
+ break;
+ }
+}
+
+static h2_config *h2_config_sget(server_rec *s)
{
h2_config *cfg = (h2_config *)ap_get_module_config(s->module_config,
&http2_module);
@@ -216,9 +376,162 @@ const h2_config *h2_config_sget(server_r
return cfg;
}
-const struct h2_priority *h2_config_get_priority(const h2_config *conf,
- const char *content_type)
+static const h2_dir_config *h2_config_rget(request_rec *r)
+{
+ h2_dir_config *cfg = (h2_dir_config *)ap_get_module_config(r->per_dir_config,
+ &http2_module);
+ ap_assert(cfg);
+ return cfg;
+}
+
+static apr_int64_t h2_dir_config_geti64(const h2_dir_config *conf, h2_config_var_t var)
+{
+ switch(var) {
+ case H2_CONF_ALT_SVC_MAX_AGE:
+ return H2_CONFIG_GET(conf, &defdconf, alt_svc_max_age);
+ case H2_CONF_UPGRADE:
+ return H2_CONFIG_GET(conf, &defdconf, h2_upgrade);
+ case H2_CONF_PUSH:
+ return H2_CONFIG_GET(conf, &defdconf, h2_push);
+ case H2_CONF_EARLY_HINTS:
+ return H2_CONFIG_GET(conf, &defdconf, early_hints);
+
+ default:
+ return DEF_VAL;
+ }
+}
+
+static void h2_config_seti(h2_dir_config *dconf, h2_config *conf, h2_config_var_t var, int val)
+{
+ int set_srv = !dconf;
+ if (dconf) {
+ switch(var) {
+ case H2_CONF_ALT_SVC_MAX_AGE:
+ H2_CONFIG_SET(dconf, alt_svc_max_age, val);
+ break;
+ case H2_CONF_UPGRADE:
+ H2_CONFIG_SET(dconf, h2_upgrade, val);
+ break;
+ case H2_CONF_PUSH:
+ H2_CONFIG_SET(dconf, h2_push, val);
+ break;
+ case H2_CONF_EARLY_HINTS:
+ H2_CONFIG_SET(dconf, early_hints, val);
+ break;
+ default:
+ /* not handled in dir_conf */
+ set_srv = 1;
+ break;
+ }
+ }
+
+ if (set_srv) {
+ h2_srv_config_seti(conf, var, val);
+ }
+}
+
+static void h2_config_seti64(h2_dir_config *dconf, h2_config *conf, h2_config_var_t var, apr_int64_t val)
{
+ int set_srv = !dconf;
+ if (dconf) {
+ switch(var) {
+ default:
+ /* not handled in dir_conf */
+ set_srv = 1;
+ break;
+ }
+ }
+
+ if (set_srv) {
+ h2_srv_config_seti64(conf, var, val);
+ }
+}
+
+static const h2_config *h2_config_get(conn_rec *c)
+{
+ h2_ctx *ctx = h2_ctx_get(c, 0);
+
+ if (ctx) {
+ if (ctx->config) {
+ return ctx->config;
+ }
+ else if (ctx->server) {
+ ctx->config = h2_config_sget(ctx->server);
+ return ctx->config;
+ }
+ }
+
+ return h2_config_sget(c->base_server);
+}
+
+int h2_config_cgeti(conn_rec *c, h2_config_var_t var)
+{
+ return (int)h2_srv_config_geti64(h2_config_get(c), var);
+}
+
+apr_int64_t h2_config_cgeti64(conn_rec *c, h2_config_var_t var)
+{
+ return h2_srv_config_geti64(h2_config_get(c), var);
+}
+
+int h2_config_sgeti(server_rec *s, h2_config_var_t var)
+{
+ return (int)h2_srv_config_geti64(h2_config_sget(s), var);
+}
+
+apr_int64_t h2_config_sgeti64(server_rec *s, h2_config_var_t var)
+{
+ return h2_srv_config_geti64(h2_config_sget(s), var);
+}
+
+int h2_config_geti(request_rec *r, server_rec *s, h2_config_var_t var)
+{
+ return (int)h2_config_geti64(r, s, var);
+}
+
+apr_int64_t h2_config_geti64(request_rec *r, server_rec *s, h2_config_var_t var)
+{
+ apr_int64_t mode = r? (int)h2_dir_config_geti64(h2_config_rget(r), var) : DEF_VAL;
+ return (mode != DEF_VAL)? mode : h2_config_sgeti64(s, var);
+}
+
+int h2_config_rgeti(request_rec *r, h2_config_var_t var)
+{
+ return h2_config_geti(r, r->server, var);
+}
+
+apr_int64_t h2_config_rgeti64(request_rec *r, h2_config_var_t var)
+{
+ return h2_config_geti64(r, r->server, var);
+}
+
+apr_array_header_t *h2_config_push_list(request_rec *r)
+{
+ const h2_config *sconf;
+ const h2_dir_config *conf = h2_config_rget(r);
+
+ if (conf && conf->push_list) {
+ return conf->push_list;
+ }
+ sconf = h2_config_sget(r->server);
+ return sconf? sconf->push_list : NULL;
+}
+
+apr_array_header_t *h2_config_alt_svcs(request_rec *r)
+{
+ const h2_config *sconf;
+ const h2_dir_config *conf = h2_config_rget(r);
+
+ if (conf && conf->alt_svcs) {
+ return conf->alt_svcs;
+ }
+ sconf = h2_config_sget(r->server);
+ return sconf? sconf->alt_svcs : NULL;
+}
+
+const struct h2_priority *h2_cconfig_get_priority(conn_rec *c, const char *content_type)
+{
+ const h2_config *conf = h2_config_get(c);
if (content_type && conf->priorities) {
size_t len = strcspn(content_type, "; \t");
h2_priority *prio = apr_hash_get(conf->priorities, content_type, len);
@@ -227,166 +540,156 @@ const struct h2_priority *h2_config_get_
return NULL;
}
-static const char *h2_conf_set_max_streams(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_max_streams(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- cfg->h2_max_streams = (int)apr_atoi64(value);
- (void)arg;
- if (cfg->h2_max_streams < 1) {
+ apr_int64_t ival = (int)apr_atoi64(value);
+ if (ival < 1) {
return "value must be > 0";
}
+ CONFIG_CMD_SET64(cmd, dirconf, H2_CONF_MAX_STREAMS, ival);
return NULL;
}
-static const char *h2_conf_set_window_size(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_window_size(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- cfg->h2_window_size = (int)apr_atoi64(value);
- (void)arg;
- if (cfg->h2_window_size < 1024) {
+ int val = (int)apr_atoi64(value);
+ if (val < 1024) {
return "value must be >= 1024";
}
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_WIN_SIZE, val);
return NULL;
}
-static const char *h2_conf_set_min_workers(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_min_workers(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- cfg->min_workers = (int)apr_atoi64(value);
- (void)arg;
- if (cfg->min_workers < 1) {
+ int val = (int)apr_atoi64(value);
+ if (val < 1) {
return "value must be > 0";
}
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_MIN_WORKERS, val);
return NULL;
}
-static const char *h2_conf_set_max_workers(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_max_workers(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- cfg->max_workers = (int)apr_atoi64(value);
- (void)arg;
- if (cfg->max_workers < 1) {
+ int val = (int)apr_atoi64(value);
+ if (val < 1) {
return "value must be > 0";
}
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_MAX_WORKERS, val);
return NULL;
}
-static const char *h2_conf_set_max_worker_idle_secs(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_max_worker_idle_secs(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- cfg->max_worker_idle_secs = (int)apr_atoi64(value);
- (void)arg;
- if (cfg->max_worker_idle_secs < 1) {
+ int val = (int)apr_atoi64(value);
+ if (val < 1) {
return "value must be > 0";
}
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_MAX_WORKER_IDLE_SECS, val);
return NULL;
}
-static const char *h2_conf_set_stream_max_mem_size(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_stream_max_mem_size(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
-
-
- cfg->stream_max_mem_size = (int)apr_atoi64(value);
- (void)arg;
- if (cfg->stream_max_mem_size < 1024) {
+ int val = (int)apr_atoi64(value);
+ if (val < 1024) {
return "value must be >= 1024";
}
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_STREAM_MAX_MEM, val);
return NULL;
}
-static const char *h2_add_alt_svc(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_add_alt_svc(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
if (value && *value) {
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- h2_alt_svc *as = h2_alt_svc_parse(value, parms->pool);
+ h2_alt_svc *as = h2_alt_svc_parse(value, cmd->pool);
if (!as) {
return "unable to parse alt-svc specifier";
}
- if (!cfg->alt_svcs) {
- cfg->alt_svcs = apr_array_make(parms->pool, 5, sizeof(h2_alt_svc*));
+
+ if (cmd->path) {
+ h2_dir_config *dcfg = (h2_dir_config *)dirconf;
+ if (!dcfg->alt_svcs) {
+ dcfg->alt_svcs = apr_array_make(cmd->pool, 5, sizeof(h2_alt_svc*));
+ }
+ APR_ARRAY_PUSH(dcfg->alt_svcs, h2_alt_svc*) = as;
+ }
+ else {
+ h2_config *cfg = (h2_config *)h2_config_sget(cmd->server);
+ if (!cfg->alt_svcs) {
+ cfg->alt_svcs = apr_array_make(cmd->pool, 5, sizeof(h2_alt_svc*));
+ }
+ APR_ARRAY_PUSH(cfg->alt_svcs, h2_alt_svc*) = as;
}
- APR_ARRAY_PUSH(cfg->alt_svcs, h2_alt_svc*) = as;
}
- (void)arg;
return NULL;
}
-static const char *h2_conf_set_alt_svc_max_age(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_alt_svc_max_age(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- cfg->alt_svc_max_age = (int)apr_atoi64(value);
- (void)arg;
+ int val = (int)apr_atoi64(value);
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_ALT_SVC_MAX_AGE, val);
return NULL;
}
-static const char *h2_conf_set_session_extra_files(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_session_extra_files(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
/* deprecated, ignore */
- (void)arg;
+ (void)dirconf;
(void)value;
- ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, parms->pool, /* NO LOGNO */
+ ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, cmd->pool, /* NO LOGNO */
"H2SessionExtraFiles is obsolete and will be ignored");
return NULL;
}
-static const char *h2_conf_set_serialize_headers(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_serialize_headers(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
if (!strcasecmp(value, "On")) {
- cfg->serialize_headers = 1;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_SER_HEADERS, 1);
return NULL;
}
else if (!strcasecmp(value, "Off")) {
- cfg->serialize_headers = 0;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_SER_HEADERS, 0);
return NULL;
}
-
- (void)arg;
return "value must be On or Off";
}
-static const char *h2_conf_set_direct(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_direct(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
if (!strcasecmp(value, "On")) {
- cfg->h2_direct = 1;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_DIRECT, 1);
return NULL;
}
else if (!strcasecmp(value, "Off")) {
- cfg->h2_direct = 0;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_DIRECT, 0);
return NULL;
}
-
- (void)arg;
return "value must be On or Off";
}
-static const char *h2_conf_set_push(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_push(cmd_parms *cmd, void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
if (!strcasecmp(value, "On")) {
- cfg->h2_push = 1;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_PUSH, 1);
return NULL;
}
else if (!strcasecmp(value, "Off")) {
- cfg->h2_push = 0;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_PUSH, 0);
return NULL;
}
-
- (void)arg;
return "value must be On or Off";
}
@@ -446,100 +749,88 @@ static const char *h2_conf_add_push_prio
return NULL;
}
-static const char *h2_conf_set_modern_tls_only(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_modern_tls_only(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
if (!strcasecmp(value, "On")) {
- cfg->modern_tls_only = 1;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_MODERN_TLS_ONLY, 1);
return NULL;
}
else if (!strcasecmp(value, "Off")) {
- cfg->modern_tls_only = 0;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_MODERN_TLS_ONLY, 0);
return NULL;
}
-
- (void)arg;
return "value must be On or Off";
}
-static const char *h2_conf_set_upgrade(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_upgrade(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
if (!strcasecmp(value, "On")) {
- cfg->h2_upgrade = 1;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_UPGRADE, 1);
return NULL;
}
else if (!strcasecmp(value, "Off")) {
- cfg->h2_upgrade = 0;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_UPGRADE, 0);
return NULL;
}
-
- (void)arg;
return "value must be On or Off";
}
-static const char *h2_conf_set_tls_warmup_size(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_tls_warmup_size(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- cfg->tls_warmup_size = apr_atoi64(value);
- (void)arg;
+ apr_int64_t val = apr_atoi64(value);
+ CONFIG_CMD_SET64(cmd, dirconf, H2_CONF_TLS_WARMUP_SIZE, val);
return NULL;
}
-static const char *h2_conf_set_tls_cooldown_secs(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_tls_cooldown_secs(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- cfg->tls_cooldown_secs = (int)apr_atoi64(value);
- (void)arg;
+ apr_int64_t val = (int)apr_atoi64(value);
+ CONFIG_CMD_SET64(cmd, dirconf, H2_CONF_TLS_COOLDOWN_SECS, val);
return NULL;
}
-static const char *h2_conf_set_push_diary_size(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_push_diary_size(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- (void)arg;
- cfg->push_diary_size = (int)apr_atoi64(value);
- if (cfg->push_diary_size < 0) {
+ int val = (int)apr_atoi64(value);
+ if (val < 0) {
return "value must be >= 0";
}
- if (cfg->push_diary_size > 0 && (cfg->push_diary_size & (cfg->push_diary_size-1))) {
+ if (val > 0 && (val & (val-1))) {
return "value must a power of 2";
}
- if (cfg->push_diary_size > (1 << 15)) {
+ if (val > (1 << 15)) {
return "value must <= 65536";
}
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_PUSH_DIARY_SIZE, val);
return NULL;
}
-static const char *h2_conf_set_copy_files(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_copy_files(cmd_parms *cmd,
+ void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)arg;
if (!strcasecmp(value, "On")) {
- cfg->copy_files = 1;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_COPY_FILES, 1);
return NULL;
}
else if (!strcasecmp(value, "Off")) {
- cfg->copy_files = 0;
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_COPY_FILES, 0);
return NULL;
}
-
- (void)arg;
return "value must be On or Off";
}
-static void add_push(apr_pool_t *pool, h2_config *conf, h2_push_res *push)
+static void add_push(apr_array_header_t **plist, apr_pool_t *pool, h2_push_res *push)
{
h2_push_res *new;
- if (!conf->push_list) {
- conf->push_list = apr_array_make(pool, 10, sizeof(*push));
+ if (!*plist) {
+ *plist = apr_array_make(pool, 10, sizeof(*push));
}
- new = apr_array_push(conf->push_list);
+ new = apr_array_push(*plist);
new->uri_ref = push->uri_ref;
new->critical = push->critical;
}
@@ -548,8 +839,6 @@ static const char *h2_conf_add_push_res(
const char *arg1, const char *arg2,
const char *arg3)
{
- h2_config *dconf = (h2_config*)dirconf ;
- h2_config *sconf = (h2_config*)h2_config_sget(cmd->server);
h2_push_res push;
const char *last = arg3;
@@ -574,42 +863,54 @@ static const char *h2_conf_add_push_res(
}
}
- /* server command? set both */
- if (cmd->path == NULL) {
- add_push(cmd->pool, sconf, &push);
- add_push(cmd->pool, dconf, &push);
+ if (cmd->path) {
+ add_push(&(((h2_dir_config*)dirconf)->push_list), cmd->pool, &push);
}
else {
- add_push(cmd->pool, dconf, &push);
+ add_push(&(h2_config_sget(cmd->server)->push_list), cmd->pool, &push);
}
+ return NULL;
+}
+static const char *h2_conf_set_early_hints(cmd_parms *cmd,
+ void *dirconf, const char *value)
+{
+ int val;
+
+ if (!strcasecmp(value, "On")) val = 1;
+ else if (!strcasecmp(value, "Off")) val = 0;
+ else return "value must be On or Off";
+
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_EARLY_HINTS, val);
+ if (cmd->path) {
+ ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, cmd->pool,
+ "H2EarlyHints = %d on path %s", val, cmd->path);
+ }
return NULL;
}
-static const char *h2_conf_set_early_hints(cmd_parms *parms,
- void *arg, const char *value)
+static const char *h2_conf_set_padding(cmd_parms *cmd, void *dirconf, const char *value)
{
- h2_config *cfg = (h2_config *)h2_config_sget(parms->server);
- if (!strcasecmp(value, "On")) {
- cfg->early_hints = 1;
- return NULL;
+ int val;
+
+ val = (int)apr_atoi64(value);
+ if (val < 0) {
+ return "number of bits must be >= 0";
}
- else if (!strcasecmp(value, "Off")) {
- cfg->early_hints = 0;
- return NULL;
+ if (val > 8) {
+ return "number of bits must be <= 8";
}
-
- (void)arg;
- return "value must be On or Off";
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_PADDING_BITS, val);
+ return NULL;
}
+
void h2_get_num_workers(server_rec *s, int *minw, int *maxw)
{
int threads_per_child = 0;
- const h2_config *config = h2_config_sget(s);
- *minw = h2_config_geti(config, H2_CONF_MIN_WORKERS);
- *maxw = h2_config_geti(config, H2_CONF_MAX_WORKERS);
+ *minw = h2_config_sgeti(s, H2_CONF_MIN_WORKERS);
+ *maxw = h2_config_sgeti(s, H2_CONF_MAX_WORKERS);
ap_mpm_query(AP_MPMQ_MAX_THREADS, &threads_per_child);
if (*minw <= 0) {
@@ -651,7 +952,7 @@ const command_rec h2_cmds[] = {
AP_INIT_TAKE1("H2ModernTLSOnly", h2_conf_set_modern_tls_only, NULL,
RSRC_CONF, "off to not impose RFC 7540 restrictions on TLS"),
AP_INIT_TAKE1("H2Upgrade", h2_conf_set_upgrade, NULL,
- RSRC_CONF, "on to allow HTTP/1 Upgrades to h2/h2c"),
+ RSRC_CONF|OR_AUTHCFG, "on to allow HTTP/1 Upgrades to h2/h2c"),
AP_INIT_TAKE1("H2Direct", h2_conf_set_direct, NULL,
RSRC_CONF, "on to enable direct HTTP/2 mode"),
AP_INIT_TAKE1("H2SessionExtraFiles", h2_conf_set_session_extra_files, NULL,
@@ -661,7 +962,7 @@ const command_rec h2_cmds[] = {
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("H2Push", h2_conf_set_push, NULL,
- RSRC_CONF, "off to disable HTTP/2 server push"),
+ RSRC_CONF|OR_AUTHCFG, "off to disable HTTP/2 server push"),
AP_INIT_TAKE23("H2PushPriority", h2_conf_add_push_priority, NULL,
RSRC_CONF, "define priority of PUSHed resources per content type"),
AP_INIT_TAKE1("H2PushDiarySize", h2_conf_set_push_diary_size, NULL,
@@ -669,33 +970,12 @@ const command_rec h2_cmds[] = {
AP_INIT_TAKE1("H2CopyFiles", h2_conf_set_copy_files, NULL,
OR_FILEINFO, "on to perform copy of file data"),
AP_INIT_TAKE123("H2PushResource", h2_conf_add_push_res, NULL,
- OR_FILEINFO, "add a resource to be pushed in this location/on this server."),
+ OR_FILEINFO|OR_AUTHCFG, "add a resource to be pushed in this location/on this server."),
AP_INIT_TAKE1("H2EarlyHints", h2_conf_set_early_hints, NULL,
RSRC_CONF, "on to enable interim status 103 responses"),
+ AP_INIT_TAKE1("H2Padding", h2_conf_set_padding, NULL,
+ RSRC_CONF, "set payload padding"),
AP_END_CMD
};
-const h2_config *h2_config_rget(request_rec *r)
-{
- h2_config *cfg = (h2_config *)ap_get_module_config(r->per_dir_config,
- &http2_module);
- return cfg? cfg : h2_config_sget(r->server);
-}
-
-const h2_config *h2_config_get(conn_rec *c)
-{
- h2_ctx *ctx = h2_ctx_get(c, 0);
-
- if (ctx) {
- if (ctx->config) {
- return ctx->config;
- }
- else if (ctx->server) {
- ctx->config = h2_config_sget(ctx->server);
- return ctx->config;
- }
- }
-
- return h2_config_sget(c->base_server);
-}
Index: httpd-2.4.23/modules/http2/h2_config.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_config.h 2019-04-02 13:39:34.192793170 +0200
+++ httpd-2.4.23/modules/http2/h2_config.h 2019-04-02 13:42:32.649683136 +0200
@@ -41,6 +41,8 @@ typedef enum {
H2_CONF_PUSH_DIARY_SIZE,
H2_CONF_COPY_FILES,
H2_CONF_EARLY_HINTS,
+ H2_CONF_PADDING_BITS,
+ H2_CONF_PADDING_ALWAYS,
} h2_config_var_t;
struct apr_hash_t;
@@ -52,33 +54,6 @@ typedef struct h2_push_res {
int critical;
} h2_push_res;
-/* Apache httpd module configuration for h2. */
-typedef struct h2_config {
- const char *name;
- int h2_max_streams; /* max concurrent # streams (http2) */
- int h2_window_size; /* stream window size (http2) */
- int min_workers; /* min # of worker threads/child */
- int max_workers; /* max # of worker threads/child */
- int max_worker_idle_secs; /* max # of idle seconds for worker */
- int stream_max_mem_size; /* max # bytes held in memory/stream */
- apr_array_header_t *alt_svcs; /* h2_alt_svc specs for this server */
- int alt_svc_max_age; /* seconds clients can rely on alt-svc info*/
- int serialize_headers; /* Use serialized HTTP/1.1 headers for
- processing, better compatibility */
- int h2_direct; /* if mod_h2 is active directly */
- int modern_tls_only; /* Accept only modern TLS in HTTP/2 connections */
- int h2_upgrade; /* Allow HTTP/1 upgrade to h2/h2c */
- apr_int64_t tls_warmup_size; /* Amount of TLS data to send before going full write size */
- int tls_cooldown_secs; /* Seconds of idle time before going back to small TLS records */
- int h2_push; /* if HTTP/2 server push is enabled */
- struct apr_hash_t *priorities;/* map of content-type to h2_priority records */
-
- int push_diary_size; /* # of entries in push diary */
- 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 */
-} h2_config;
-
void *h2_config_create_dir(apr_pool_t *pool, char *x);
void *h2_config_merge_dir(apr_pool_t *pool, void *basev, void *addv);
@@ -87,19 +62,37 @@ void *h2_config_merge_svr(apr_pool_t *po
extern const command_rec h2_cmds[];
-const h2_config *h2_config_get(conn_rec *c);
-const h2_config *h2_config_sget(server_rec *s);
-const h2_config *h2_config_rget(request_rec *r);
+int h2_config_geti(request_rec *r, server_rec *s, h2_config_var_t var);
+apr_int64_t h2_config_geti64(request_rec *r, server_rec *s, h2_config_var_t var);
-int h2_config_geti(const h2_config *conf, h2_config_var_t var);
-apr_int64_t h2_config_geti64(const h2_config *conf, h2_config_var_t var);
+/**
+ * Get the configured value for variable <var> at the given connection.
+ */
+int h2_config_cgeti(conn_rec *c, h2_config_var_t var);
+apr_int64_t h2_config_cgeti64(conn_rec *c, h2_config_var_t var);
+
+/**
+ * Get the configured value for variable <var> at the given server.
+ */
+int h2_config_sgeti(server_rec *s, h2_config_var_t var);
+apr_int64_t h2_config_sgeti64(server_rec *s, h2_config_var_t var);
+
+/**
+ * Get the configured value for variable <var> at the given request,
+ * if configured for the request location.
+ * Fallback to request server config otherwise.
+ */
+int h2_config_rgeti(request_rec *r, h2_config_var_t var);
+apr_int64_t h2_config_rgeti64(request_rec *r, h2_config_var_t var);
-void h2_get_num_workers(server_rec *s, int *minw, int *maxw);
+apr_array_header_t *h2_config_push_list(request_rec *r);
+apr_array_header_t *h2_config_alt_svcs(request_rec *r);
+
+void h2_get_num_workers(server_rec *s, int *minw, int *maxw);
void h2_config_init(apr_pool_t *pool);
-const struct h2_priority *h2_config_get_priority(const h2_config *conf,
- const char *content_type);
+const struct h2_priority *h2_cconfig_get_priority(conn_rec *c, const char *content_type);
#endif /* __mod_h2__h2_config_h__ */
Index: httpd-2.4.23/modules/http2/h2_conn.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_conn.c 2019-04-02 13:39:34.220793310 +0200
+++ httpd-2.4.23/modules/http2/h2_conn.c 2019-04-02 13:42:32.649683136 +0200
@@ -17,6 +17,7 @@
#include <apr_strings.h>
#include <ap_mpm.h>
+#include <ap_mmn.h>
#include <httpd.h>
#include <http_core.h>
@@ -108,7 +109,6 @@ static void check_modules(int force)
apr_status_t h2_conn_child_init(apr_pool_t *pool, server_rec *s)
{
- const h2_config *config = h2_config_sget(s);
apr_status_t status = APR_SUCCESS;
int minw, maxw;
int max_threads_per_child = 0;
@@ -128,7 +128,7 @@ apr_status_t h2_conn_child_init(apr_pool
h2_get_num_workers(s, &minw, &maxw);
- idle_secs = h2_config_geti(config, H2_CONF_MAX_WORKER_IDLE_SECS);
+ idle_secs = h2_config_sgeti(s, H2_CONF_MAX_WORKER_IDLE_SECS);
ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
"h2_workers: min=%d max=%d, mthrpchild=%d, idle_secs=%d",
minw, maxw, max_threads_per_child, idle_secs);
@@ -171,9 +171,10 @@ static module *h2_conn_mpm_module(void)
return mpm_module;
}
-apr_status_t h2_conn_setup(h2_ctx *ctx, conn_rec *c, request_rec *r)
+apr_status_t h2_conn_setup(conn_rec *c, request_rec *r, server_rec *s)
{
h2_session *session;
+ h2_ctx *ctx;
apr_status_t status;
if (!workers) {
@@ -182,24 +183,19 @@ apr_status_t h2_conn_setup(h2_ctx *ctx,
return APR_EGENERAL;
}
- if (r) {
- status = h2_session_rcreate(&session, r, ctx, workers);
- }
- else {
- status = h2_session_create(&session, c, ctx, workers);
- }
-
- if (status == APR_SUCCESS) {
+ if (APR_SUCCESS == (status = h2_session_create(&session, c, r, s, workers))) {
+ ctx = h2_ctx_get(c, 1);
h2_ctx_session_set(ctx, session);
}
+
return status;
}
-apr_status_t h2_conn_run(struct h2_ctx *ctx, conn_rec *c)
+apr_status_t h2_conn_run(conn_rec *c)
{
apr_status_t status;
int mpm_state = 0;
- h2_session *session = h2_ctx_session_get(ctx);
+ h2_session *session = h2_ctx_get_session(c);
ap_assert(session);
do {
@@ -248,7 +244,7 @@ apr_status_t h2_conn_run(struct h2_ctx *
apr_status_t h2_conn_pre_close(struct h2_ctx *ctx, conn_rec *c)
{
- h2_session *session = h2_ctx_session_get(ctx);
+ h2_session *session = h2_ctx_get_session(c);
if (session) {
apr_status_t status = h2_session_pre_close(session, async_mpm);
return (status == APR_SUCCESS)? DONE : status;
@@ -304,9 +300,15 @@ conn_rec *h2_slave_create(conn_rec *mast
c->notes = apr_table_make(pool, 5);
c->input_filters = NULL;
c->output_filters = NULL;
+ c->keepalives = 0;
+#if AP_MODULE_MAGIC_AT_LEAST(20180903, 1)
+ c->filter_conn_ctx = NULL;
+#endif
c->bucket_alloc = apr_bucket_alloc_create(pool);
- c->data_in_input_filters = 0;
- c->data_in_output_filters = 0;
+#if !AP_MODULE_MAGIC_AT_LEAST(20180720, 1)
+ c->data_in_input_filters = 0;
+ c->data_in_output_filters = 0;
+#endif
/* prevent mpm_event from making wrong assumptions about this connection,
* like e.g. using its socket for an async read check. */
c->clogging_input_filters = 1;
@@ -331,16 +333,15 @@ conn_rec *h2_slave_create(conn_rec *mast
ap_set_module_config(c->conn_config, mpm, cfg);
}
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- "h2_stream(%ld-%d): created slave", master->id, slave_id);
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c,
+ "h2_slave(%s): created", c->log_id);
return c;
}
void h2_slave_destroy(conn_rec *slave)
{
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, slave,
- "h2_stream(%s): destroy slave",
- apr_table_get(slave->notes, H2_TASK_ID_NOTE));
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, slave,
+ "h2_slave(%s): destroy", slave->log_id);
slave->sbh = NULL;
apr_pool_destroy(slave->pool);
}
@@ -364,6 +365,7 @@ apr_status_t h2_slave_run_pre_connection
slave->keepalive = AP_CONN_CLOSE;
return ap_run_pre_connection(slave, csd);
}
+ ap_assert(slave->output_filters);
return APR_SUCCESS;
}
Index: httpd-2.4.23/modules/http2/h2_conn.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_conn.h 2019-04-02 13:39:34.068792551 +0200
+++ httpd-2.4.23/modules/http2/h2_conn.h 2019-04-02 13:39:34.256793490 +0200
@@ -22,21 +22,21 @@ struct h2_task;
/**
* Setup the connection and our context for HTTP/2 processing
*
- * @param ctx the http2 context to setup
* @param c the connection HTTP/2 is starting on
* @param r the upgrade request that still awaits an answer, optional
+ * @param s the server selected for this connection (can be != c->base_server)
*/
-apr_status_t h2_conn_setup(struct h2_ctx *ctx, conn_rec *c, request_rec *r);
+apr_status_t h2_conn_setup(conn_rec *c, request_rec *r, server_rec *s);
/**
* Run the HTTP/2 connection in synchronous fashion.
* Return when the HTTP/2 session is done
* and the connection will close or a fatal error occurred.
*
- * @param ctx the http2 context to run
+ * @param c the http2 connection to run
* @return APR_SUCCESS when session is done.
*/
-apr_status_t h2_conn_run(struct h2_ctx *ctx, conn_rec *c);
+apr_status_t h2_conn_run(conn_rec *c);
/**
* The connection is about to close. If we have not send a GOAWAY
Index: httpd-2.4.23/modules/http2/h2_conn_io.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_conn_io.c 2019-04-02 13:39:34.068792551 +0200
+++ httpd-2.4.23/modules/http2/h2_conn_io.c 2019-04-02 13:42:32.649683136 +0200
@@ -39,12 +39,17 @@
* ~= 1300 bytes */
#define WRITE_SIZE_INITIAL 1300
-/* Calculated like this: max TLS record size 16*1024
- * - 40 (IP) - 20 (TCP) - 40 (TCP options)
- * - TLS overhead (60-100)
- * which seems to create less TCP packets overall
+/* The maximum we'd like to write in one chunk is
+ * the max size of a TLS record. When pushing
+ * many frames down the h2 connection, this might
+ * align differently because of headers and other
+ * frames or simply as not sufficient data is
+ * in a response body.
+ * However keeping frames at or below this limit
+ * should make optimizations at the layer that writes
+ * to TLS easier.
*/
-#define WRITE_SIZE_MAX (TLS_DATA_MAX - 100)
+#define WRITE_SIZE_MAX (TLS_DATA_MAX)
static void h2_conn_io_bb_log(conn_rec *c, int stream_id, int level,
@@ -122,21 +127,20 @@ static void h2_conn_io_bb_log(conn_rec *
}
-apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c,
- const h2_config *cfg)
+apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c, server_rec *s)
{
io->c = c;
io->output = apr_brigade_create(c->pool, c->bucket_alloc);
io->is_tls = h2_h2_is_tls(c);
io->buffer_output = io->is_tls;
- io->flush_threshold = (apr_size_t)h2_config_geti64(cfg, H2_CONF_STREAM_MAX_MEM);
+ io->flush_threshold = (apr_size_t)h2_config_sgeti64(s, H2_CONF_STREAM_MAX_MEM);
if (io->is_tls) {
/* This is what we start with,
* see https://issues.apache.org/jira/browse/TS-2503
*/
- io->warmup_size = h2_config_geti64(cfg, H2_CONF_TLS_WARMUP_SIZE);
- io->cooldown_usecs = (h2_config_geti(cfg, H2_CONF_TLS_COOLDOWN_SECS)
+ io->warmup_size = h2_config_sgeti64(s, H2_CONF_TLS_WARMUP_SIZE);
+ io->cooldown_usecs = (h2_config_sgeti(s, H2_CONF_TLS_COOLDOWN_SECS)
* APR_USEC_PER_SEC);
io->write_size = (io->cooldown_usecs > 0?
WRITE_SIZE_INITIAL : WRITE_SIZE_MAX);
Index: httpd-2.4.23/modules/http2/h2_conn_io.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_conn_io.h 2019-04-02 13:39:34.068792551 +0200
+++ httpd-2.4.23/modules/http2/h2_conn_io.h 2019-04-02 13:39:34.256793490 +0200
@@ -47,8 +47,7 @@ typedef struct {
apr_size_t slen;
} h2_conn_io;
-apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c,
- const struct h2_config *cfg);
+apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c, server_rec *s);
/**
* Append data to the buffered output.
Index: httpd-2.4.23/modules/http2/h2_ctx.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_ctx.c 2019-04-02 13:39:34.068792551 +0200
+++ httpd-2.4.23/modules/http2/h2_ctx.c 2019-04-02 13:39:34.256793490 +0200
@@ -28,8 +28,8 @@ static h2_ctx *h2_ctx_create(const conn_
{
h2_ctx *ctx = apr_pcalloc(c->pool, sizeof(h2_ctx));
ap_assert(ctx);
+ h2_ctx_server_update(ctx, c->base_server);
ap_set_module_config(c->conn_config, &http2_module, ctx);
- h2_ctx_server_set(ctx, c->base_server);
return ctx;
}
@@ -78,8 +78,9 @@ h2_ctx *h2_ctx_protocol_set(h2_ctx *ctx,
return ctx;
}
-h2_session *h2_ctx_session_get(h2_ctx *ctx)
+h2_session *h2_ctx_get_session(conn_rec *c)
{
+ h2_ctx *ctx = h2_ctx_get(c, 0);
return ctx? ctx->session : NULL;
}
@@ -88,33 +89,17 @@ void h2_ctx_session_set(h2_ctx *ctx, str
ctx->session = session;
}
-server_rec *h2_ctx_server_get(h2_ctx *ctx)
+h2_ctx *h2_ctx_server_update(h2_ctx *ctx, server_rec *s)
{
- return ctx? ctx->server : NULL;
-}
-
-h2_ctx *h2_ctx_server_set(h2_ctx *ctx, server_rec *s)
-{
- ctx->server = s;
+ if (ctx->server != s) {
+ ctx->server = s;
+ }
return ctx;
}
-int h2_ctx_is_task(h2_ctx *ctx)
-{
- return ctx && ctx->task;
-}
-
-h2_task *h2_ctx_get_task(h2_ctx *ctx)
+h2_task *h2_ctx_get_task(conn_rec *c)
{
+ h2_ctx *ctx = h2_ctx_get(c, 0);
return ctx? ctx->task : NULL;
}
-h2_task *h2_ctx_cget_task(conn_rec *c)
-{
- return h2_ctx_get_task(h2_ctx_get(c, 0));
-}
-
-h2_task *h2_ctx_rget_task(request_rec *r)
-{
- return h2_ctx_get_task(h2_ctx_rget(r));
-}
Index: httpd-2.4.23/modules/http2/h2_ctx.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_ctx.h 2016-03-02 12:21:28.000000000 +0100
+++ httpd-2.4.23/modules/http2/h2_ctx.h 2019-04-02 13:39:34.256793490 +0200
@@ -55,12 +55,11 @@ h2_ctx *h2_ctx_create_for(const conn_rec
*/
h2_ctx *h2_ctx_protocol_set(h2_ctx *ctx, const char *proto);
-/* Set the server_rec relevant for this context.
+/* Update the server_rec relevant for this context. A server for
+ * a connection may change during SNI handling, for example.
*/
-h2_ctx *h2_ctx_server_set(h2_ctx *ctx, server_rec *s);
-server_rec *h2_ctx_server_get(h2_ctx *ctx);
+h2_ctx *h2_ctx_server_update(h2_ctx *ctx, server_rec *s);
-struct h2_session *h2_ctx_session_get(h2_ctx *ctx);
void h2_ctx_session_set(h2_ctx *ctx, struct h2_session *session);
/**
@@ -68,10 +67,8 @@ void h2_ctx_session_set(h2_ctx *ctx, str
*/
const char *h2_ctx_protocol_get(const conn_rec *c);
-int h2_ctx_is_task(h2_ctx *ctx);
+struct h2_session *h2_ctx_get_session(conn_rec *c);
+struct h2_task *h2_ctx_get_task(conn_rec *c);
-struct h2_task *h2_ctx_get_task(h2_ctx *ctx);
-struct h2_task *h2_ctx_cget_task(conn_rec *c);
-struct h2_task *h2_ctx_rget_task(request_rec *r);
#endif /* defined(__mod_h2__h2_ctx__) */
Index: httpd-2.4.23/modules/http2/h2_filter.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_filter.c 2019-04-02 13:39:34.192793170 +0200
+++ httpd-2.4.23/modules/http2/h2_filter.c 2019-04-02 13:42:32.649683136 +0200
@@ -53,6 +53,7 @@ static apr_status_t recv_RAW_DATA(conn_r
const char *data;
ssize_t n;
+ (void)c;
status = apr_bucket_read(b, &data, &len, block);
while (status == APR_SUCCESS && len > 0) {
@@ -70,10 +71,10 @@ static apr_status_t recv_RAW_DATA(conn_r
}
else {
session->io.bytes_read += n;
- if (len <= n) {
+ if ((apr_ssize_t)len <= n) {
break;
}
- len -= n;
+ len -= (apr_size_t)n;
data += n;
}
}
@@ -276,6 +277,7 @@ apr_bucket *h2_bucket_observer_beam(stru
apr_bucket_brigade *dest,
const apr_bucket *src)
{
+ (void)beam;
if (H2_BUCKET_IS_OBSERVER(src)) {
h2_bucket_observer *l = (h2_bucket_observer *)src->data;
apr_bucket *b = h2_bucket_observer_create(dest->bucket_alloc,
@@ -310,8 +312,7 @@ static void add_settings(apr_bucket_brig
bbout(bb, " \"settings\": {\n");
bbout(bb, " \"SETTINGS_MAX_CONCURRENT_STREAMS\": %d,\n", m->max_streams);
bbout(bb, " \"SETTINGS_MAX_FRAME_SIZE\": %d,\n", 16*1024);
- bbout(bb, " \"SETTINGS_INITIAL_WINDOW_SIZE\": %d,\n",
- h2_config_geti(s->config, H2_CONF_WIN_SIZE));
+ bbout(bb, " \"SETTINGS_INITIAL_WINDOW_SIZE\": %d,\n", h2_config_sgeti(s->s, H2_CONF_WIN_SIZE));
bbout(bb, " \"SETTINGS_ENABLE_PUSH\": %d\n", h2_session_push_enabled(s));
bbout(bb, " }%s\n", last? "" : ",");
}
@@ -430,41 +431,38 @@ static void add_stats(apr_bucket_brigade
static apr_status_t h2_status_insert(h2_task *task, apr_bucket *b)
{
- conn_rec *c = task->c->master;
- h2_ctx *h2ctx = h2_ctx_get(c, 0);
- h2_session *session;
- h2_stream *stream;
+ h2_mplx *m = task->mplx;
+ h2_stream *stream = h2_mplx_stream_get(m, task->stream_id);
+ h2_session *s;
+ conn_rec *c;
+
apr_bucket_brigade *bb;
apr_bucket *e;
int32_t connFlowIn, connFlowOut;
-
- if (!h2ctx || (session = h2_ctx_session_get(h2ctx)) == NULL) {
- return APR_SUCCESS;
- }
-
- stream = h2_session_stream_get(session, task->stream_id);
if (!stream) {
/* stream already done */
return APR_SUCCESS;
}
+ s = stream->session;
+ c = s->c;
bb = apr_brigade_create(stream->pool, c->bucket_alloc);
- connFlowIn = nghttp2_session_get_effective_local_window_size(session->ngh2);
- connFlowOut = nghttp2_session_get_remote_window_size(session->ngh2);
+ connFlowIn = nghttp2_session_get_effective_local_window_size(s->ngh2);
+ connFlowOut = nghttp2_session_get_remote_window_size(s->ngh2);
bbout(bb, "{\n");
bbout(bb, " \"version\": \"draft-01\",\n");
- add_settings(bb, session, 0);
- add_peer_settings(bb, session, 0);
+ add_settings(bb, s, 0);
+ add_peer_settings(bb, s, 0);
bbout(bb, " \"connFlowIn\": %d,\n", connFlowIn);
bbout(bb, " \"connFlowOut\": %d,\n", connFlowOut);
- bbout(bb, " \"sentGoAway\": %d,\n", session->local.shutdown);
+ bbout(bb, " \"sentGoAway\": %d,\n", s->local.shutdown);
- add_streams(bb, session, 0);
+ add_streams(bb, s, 0);
- add_stats(bb, session, stream, 1);
+ add_stats(bb, s, stream, 1);
bbout(bb, "}\n");
while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) {
@@ -496,7 +494,6 @@ static apr_status_t status_event(void *c
int h2_filter_h2_status_handler(request_rec *r)
{
- h2_ctx *ctx = h2_ctx_rget(r);
conn_rec *c = r->connection;
h2_task *task;
apr_bucket_brigade *bb;
@@ -510,7 +507,7 @@ int h2_filter_h2_status_handler(request_
return DECLINED;
}
- task = ctx? h2_ctx_get_task(ctx) : NULL;
+ task = h2_ctx_get_task(r->connection);
if (task) {
if ((status = ap_discard_request_body(r)) != OK) {
Index: httpd-2.4.23/modules/http2/h2_from_h1.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_from_h1.c 2019-04-02 13:39:34.244793430 +0200
+++ httpd-2.4.23/modules/http2/h2_from_h1.c 2019-04-02 13:39:34.256793490 +0200
@@ -21,8 +21,6 @@
#include <apr_strings.h>
#include <httpd.h>
-#define AP_STATUS_IS_HEADER_ONLY(x) ((x) == HTTP_NO_CONTENT || \
- (x) == HTTP_NOT_MODIFIED)
#include <http_core.h>
#include <http_log.h>
#include <http_connection.h>
Index: httpd-2.4.23/modules/http2/h2.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2.h 2019-04-02 13:39:34.192793170 +0200
+++ httpd-2.4.23/modules/http2/h2.h 2019-04-02 13:42:32.649683136 +0200
@@ -47,12 +47,12 @@ extern const char *H2_MAGIC_TOKEN;
#define H2_HEADER_PATH_LEN 5
#define H2_CRLF "\r\n"
-/* Max data size to write so it fits inside a TLS record */
-#define H2_DATA_CHUNK_SIZE ((16*1024) - 100 - 9)
-
/* Size of the frame header itself in HTTP/2 */
#define H2_FRAME_HDR_LEN 9
+/* Max data size to write so it fits inside a TLS record */
+#define H2_DATA_CHUNK_SIZE ((16*1024) - 100 - H2_FRAME_HDR_LEN)
+
/* Maximum number of padding bytes in a frame, rfc7540 */
#define H2_MAX_PADLEN 256
/* Initial default window size, RFC 7540 ch. 6.5.2 */
@@ -161,5 +161,6 @@ typedef int h2_stream_pri_cmp(int stream
#define H2_FILTER_DEBUG_NOTE "http2-debug"
#define H2_HDR_CONFORMANCE "http2-hdr-conformance"
#define H2_HDR_CONFORMANCE_UNSAFE "unsafe"
+#define H2_PUSH_MODE_NOTE "http2-push-mode"
#endif /* defined(__mod_h2__h2__) */
Index: httpd-2.4.23/modules/http2/h2_h2.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_h2.c 2019-04-02 13:39:34.220793310 +0200
+++ httpd-2.4.23/modules/http2/h2_h2.c 2019-04-02 13:42:32.649683136 +0200
@@ -462,19 +462,18 @@ int h2_h2_is_tls(conn_rec *c)
return opt_ssl_is_https && opt_ssl_is_https(c);
}
-int h2_is_acceptable_connection(conn_rec *c, int require_all)
+int h2_is_acceptable_connection(conn_rec *c, request_rec *r, int require_all)
{
int is_tls = h2_h2_is_tls(c);
- const h2_config *cfg = h2_config_get(c);
- if (is_tls && h2_config_geti(cfg, H2_CONF_MODERN_TLS_ONLY) > 0) {
+ if (is_tls && h2_config_cgeti(c, H2_CONF_MODERN_TLS_ONLY) > 0) {
/* Check TLS connection for modern TLS parameters, as defined in
* RFC 7540 and https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
*/
apr_pool_t *pool = c->pool;
server_rec *s = c->base_server;
char *val;
-
+
if (!opt_ssl_var_lookup) {
/* unable to check */
return 0;
@@ -520,26 +519,22 @@ int h2_is_acceptable_connection(conn_rec
return 1;
}
-int h2_allows_h2_direct(conn_rec *c)
+static int h2_allows_h2_direct(conn_rec *c)
{
- const h2_config *cfg = h2_config_get(c);
int is_tls = h2_h2_is_tls(c);
const char *needed_protocol = is_tls? "h2" : "h2c";
- int h2_direct = h2_config_geti(cfg, H2_CONF_DIRECT);
+ int h2_direct = h2_config_cgeti(c, H2_CONF_DIRECT);
if (h2_direct < 0) {
h2_direct = is_tls? 0 : 1;
}
- return (h2_direct
- && ap_is_allowed_protocol(c, NULL, NULL, needed_protocol));
+ return (h2_direct && ap_is_allowed_protocol(c, NULL, NULL, needed_protocol));
}
-int h2_allows_h2_upgrade(conn_rec *c)
+int h2_allows_h2_upgrade(request_rec *r)
{
- const h2_config *cfg = h2_config_get(c);
- int h2_upgrade = h2_config_geti(cfg, H2_CONF_UPGRADE);
-
- return h2_upgrade > 0 || (h2_upgrade < 0 && !h2_h2_is_tls(c));
+ int h2_upgrade = h2_config_rgeti(r, H2_CONF_UPGRADE);
+ return h2_upgrade > 0 || (h2_upgrade < 0 && !h2_h2_is_tls(r->connection));
}
/*******************************************************************************
@@ -580,14 +575,17 @@ int h2_h2_process_conn(conn_rec* c)
{
apr_status_t status;
h2_ctx *ctx;
+ server_rec *s;
if (c->master) {
return DECLINED;
}
ctx = h2_ctx_get(c, 0);
+ s = ctx? ctx->server : c->base_server;
+
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, process_conn");
- if (h2_ctx_is_task(ctx)) {
+ if (ctx && ctx->task) {
/* our stream pseudo connection */
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "h2_h2, task, declined");
return DECLINED;
@@ -600,19 +598,19 @@ int h2_h2_process_conn(conn_rec* c)
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, process_conn, "
"new connection using protocol '%s', direct=%d, "
"tls acceptable=%d", proto, h2_allows_h2_direct(c),
- h2_is_acceptable_connection(c, 1));
+ h2_is_acceptable_connection(c, NULL, 1));
}
if (!strcmp(AP_PROTOCOL_HTTP1, proto)
&& h2_allows_h2_direct(c)
- && h2_is_acceptable_connection(c, 1)) {
+ && h2_is_acceptable_connection(c, NULL, 1)) {
/* Fresh connection still is on http/1.1 and H2Direct is enabled.
* Otherwise connection is in a fully acceptable state.
* -> peek at the first 24 incoming bytes
*/
apr_bucket_brigade *temp;
- char *s = NULL;
- apr_size_t slen;
+ char *peek = NULL;
+ apr_size_t peeklen;
temp = apr_brigade_create(c->pool, c->bucket_alloc);
status = ap_get_brigade(c->input_filters, temp,
@@ -625,8 +623,8 @@ int h2_h2_process_conn(conn_rec* c)
return DECLINED;
}
- apr_brigade_pflatten(temp, &s, &slen, c->pool);
- if ((slen >= 24) && !memcmp(H2_MAGIC_TOKEN, s, 24)) {
+ apr_brigade_pflatten(temp, &peek, &peeklen, c->pool);
+ if ((peeklen >= 24) && !memcmp(H2_MAGIC_TOKEN, peek, 24)) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
"h2_h2, direct mode detected");
if (!ctx) {
@@ -637,7 +635,7 @@ int h2_h2_process_conn(conn_rec* c)
else if (APLOGctrace2(c)) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
"h2_h2, not detected in %d bytes(base64): %s",
- (int)slen, h2_util_base64url_encode(s, slen, c->pool));
+ (int)peeklen, h2_util_base64url_encode(peek, peeklen, c->pool));
}
apr_brigade_destroy(temp);
@@ -646,15 +644,16 @@ int h2_h2_process_conn(conn_rec* c)
if (ctx) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "process_conn");
- if (!h2_ctx_session_get(ctx)) {
- status = h2_conn_setup(ctx, c, NULL);
+
+ if (!h2_ctx_get_session(c)) {
+ status = h2_conn_setup(c, NULL, s);
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, c, "conn_setup");
if (status != APR_SUCCESS) {
h2_ctx_clear(c);
return !OK;
}
}
- h2_conn_run(ctx, c);
+ h2_conn_run(c);
return OK;
}
@@ -683,16 +682,17 @@ static int h2_h2_pre_close_conn(conn_rec
static void check_push(request_rec *r, const char *tag)
{
- const h2_config *conf = h2_config_rget(r);
- if (!r->expecting_100
- && conf && conf->push_list && conf->push_list->nelts > 0) {
+ apr_array_header_t *push_list = h2_config_push_list(r);
+
+ if (!r->expecting_100 && push_list && push_list->nelts > 0) {
int i, old_status;
const char *old_line;
+
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"%s, early announcing %d resources for push",
- tag, conf->push_list->nelts);
- for (i = 0; i < conf->push_list->nelts; ++i) {
- h2_push_res *push = &APR_ARRAY_IDX(conf->push_list, i, h2_push_res);
+ tag, push_list->nelts);
+ for (i = 0; i < push_list->nelts; ++i) {
+ h2_push_res *push = &APR_ARRAY_IDX(push_list, i, h2_push_res);
apr_table_add(r->headers_out, "Link",
apr_psprintf(r->pool, "<%s>; rel=preload%s",
push->uri_ref, push->critical? "; critical" : ""));
@@ -711,8 +711,7 @@ static int h2_h2_post_read_req(request_r
{
/* slave connection? */
if (r->connection->master) {
- h2_ctx *ctx = h2_ctx_rget(r);
- struct h2_task *task = h2_ctx_get_task(ctx);
+ struct h2_task *task = h2_ctx_get_task(r->connection);
/* This hook will get called twice on internal redirects. Take care
* that we manipulate filters only once. */
if (task && !task->filters_set) {
@@ -745,12 +744,10 @@ static int h2_h2_late_fixups(request_rec
{
/* slave connection? */
if (r->connection->master) {
- h2_ctx *ctx = h2_ctx_rget(r);
- struct h2_task *task = h2_ctx_get_task(ctx);
+ struct h2_task *task = h2_ctx_get_task(r->connection);
if (task) {
/* check if we copy vs. setaside files in this location */
- task->output.copy_files = h2_config_geti(h2_config_rget(r),
- H2_CONF_COPY_FILES);
+ task->output.copy_files = h2_config_rgeti(r, H2_CONF_COPY_FILES);
if (task->output.copy_files) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c,
"h2_slave_out(%s): copy_files on", task->id);
Index: httpd-2.4.23/modules/http2/h2_h2.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_h2.h 2019-04-02 13:39:34.072792571 +0200
+++ httpd-2.4.23/modules/http2/h2_h2.h 2019-04-02 13:39:34.260793510 +0200
@@ -56,23 +56,15 @@ void h2_h2_register_hooks(void);
* the handshake is still ongoing.
* @return != 0 iff connection requirements are met
*/
-int h2_is_acceptable_connection(conn_rec *c, int require_all);
-
-/**
- * Check if the "direct" HTTP/2 mode of protocol handling is enabled
- * for the given connection.
- * @param c the connection to check
- * @return != 0 iff direct mode is enabled
- */
-int h2_allows_h2_direct(conn_rec *c);
+int h2_is_acceptable_connection(conn_rec *c, request_rec *r, int require_all);
/**
* Check if the "Upgrade" HTTP/1.1 mode of protocol switching is enabled
- * for the given connection.
- * @param c the connection to check
+ * for the given request.
+ * @param r the request to check
* @return != 0 iff Upgrade switching is enabled
*/
-int h2_allows_h2_upgrade(conn_rec *c);
+int h2_allows_h2_upgrade(request_rec *r);
#endif /* defined(__mod_h2__h2_h2__) */
Index: httpd-2.4.23/modules/http2/h2_headers.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_headers.c 2019-04-02 13:39:34.220793310 +0200
+++ httpd-2.4.23/modules/http2/h2_headers.c 2019-04-02 13:39:34.260793510 +0200
@@ -27,6 +27,7 @@
#include "h2_private.h"
#include "h2_h2.h"
+#include "h2_config.h"
#include "h2_util.h"
#include "h2_request.h"
#include "h2_headers.h"
@@ -127,21 +128,27 @@ h2_headers *h2_headers_rcreate(request_r
{
h2_headers *headers = h2_headers_create(status, header, r->notes, 0, pool);
if (headers->status == HTTP_FORBIDDEN) {
- const char *cause = apr_table_get(r->notes, "ssl-renegotiate-forbidden");
- if (cause) {
- /* This request triggered a TLS renegotiation that is now allowed
- * in HTTP/2. Tell the client that it should use HTTP/1.1 for this.
- */
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, headers->status, r,
- APLOGNO(03061)
- "h2_headers(%ld): renegotiate forbidden, cause: %s",
- (long)r->connection->id, cause);
- headers->status = H2_ERR_HTTP_1_1_REQUIRED;
+ request_rec *r_prev;
+ for (r_prev = r; r_prev != NULL; r_prev = r_prev->prev) {
+ const char *cause = apr_table_get(r_prev->notes, "ssl-renegotiate-forbidden");
+ if (cause) {
+ /* This request triggered a TLS renegotiation that is not allowed
+ * in HTTP/2. Tell the client that it should use HTTP/1.1 for this.
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, headers->status, r,
+ APLOGNO(03061)
+ "h2_headers(%ld): renegotiate forbidden, cause: %s",
+ (long)r->connection->id, cause);
+ headers->status = H2_ERR_HTTP_1_1_REQUIRED;
+ break;
+ }
}
}
if (is_unsafe(r->server)) {
- apr_table_setn(headers->notes, H2_HDR_CONFORMANCE,
- H2_HDR_CONFORMANCE_UNSAFE);
+ apr_table_setn(headers->notes, H2_HDR_CONFORMANCE, H2_HDR_CONFORMANCE_UNSAFE);
+ }
+ if (h2_config_rgeti(r, H2_CONF_PUSH) == 0 && h2_config_sgeti(r->server, H2_CONF_PUSH) != 0) {
+ apr_table_setn(headers->notes, H2_PUSH_MODE_NOTE, "0");
}
return headers;
}
Index: httpd-2.4.23/modules/http2/h2_mplx.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_mplx.c 2019-04-02 13:39:34.220793310 +0200
+++ httpd-2.4.23/modules/http2/h2_mplx.c 2019-04-02 13:42:32.649683136 +0200
@@ -39,7 +39,6 @@
#include "h2_ctx.h"
#include "h2_h2.h"
#include "h2_mplx.h"
-#include "h2_ngn_shed.h"
#include "h2_request.h"
#include "h2_stream.h"
#include "h2_session.h"
@@ -82,12 +81,6 @@ static void check_data_for(h2_mplx *m, h
static void stream_output_consumed(void *ctx,
h2_bucket_beam *beam, apr_off_t length)
{
- h2_stream *stream = ctx;
- h2_task *task = stream->task;
-
- if (length > 0 && task && task->assigned) {
- h2_req_engine_out_consumed(task->assigned, task->c, length);
- }
}
static void stream_input_ev(void *ctx, h2_bucket_beam *beam)
@@ -135,7 +128,6 @@ static void stream_cleanup(h2_mplx *m, h
}
else if (stream->task) {
stream->task->c->aborted = 1;
- apr_thread_cond_broadcast(m->task_thawed);
}
}
@@ -150,25 +142,19 @@ static void stream_cleanup(h2_mplx *m, h
* their HTTP/1 cousins, the separate allocator seems to work better
* than protecting a shared h2_session one with an own lock.
*/
-h2_mplx *h2_mplx_create(conn_rec *c, apr_pool_t *parent,
- const h2_config *conf,
+h2_mplx *h2_mplx_create(conn_rec *c, server_rec *s, apr_pool_t *parent,
h2_workers *workers)
{
apr_status_t status = APR_SUCCESS;
apr_allocator_t *allocator;
apr_thread_mutex_t *mutex;
h2_mplx *m;
- h2_ctx *ctx = h2_ctx_get(c, 0);
- ap_assert(conf);
m = apr_pcalloc(parent, sizeof(h2_mplx));
if (m) {
m->id = c->id;
m->c = c;
- m->s = (ctx? h2_ctx_server_get(ctx) : NULL);
- if (!m->s) {
- m->s = c->base_server;
- }
+ m->s = s;
/* We create a pool with its own allocator to be used for
* processing slave connections. This is the only way to have the
@@ -203,14 +189,8 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr
return NULL;
}
- status = apr_thread_cond_create(&m->task_thawed, m->pool);
- if (status != APR_SUCCESS) {
- apr_pool_destroy(m->pool);
- return NULL;
- }
-
- m->max_streams = h2_config_geti(conf, H2_CONF_MAX_STREAMS);
- m->stream_max_mem = h2_config_geti(conf, H2_CONF_STREAM_MAX_MEM);
+ m->max_streams = h2_config_sgeti(s, H2_CONF_MAX_STREAMS);
+ m->stream_max_mem = h2_config_sgeti(s, H2_CONF_STREAM_MAX_MEM);
m->streams = h2_ihash_create(m->pool, offsetof(h2_stream,id));
m->sredo = h2_ihash_create(m->pool, offsetof(h2_stream,id));
@@ -231,10 +211,6 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr
m->limit_change_interval = apr_time_from_msec(100);
m->spare_slaves = apr_array_make(m->pool, 10, sizeof(conn_rec*));
-
- m->ngn_shed = h2_ngn_shed_create(m->pool, m->c, m->max_streams,
- m->stream_max_mem);
- h2_ngn_shed_set_ctx(m->ngn_shed , m);
}
return m;
}
@@ -326,7 +302,8 @@ static int stream_destroy_iter(void *ctx
&& !task->rst_error);
}
- if (reuse_slave && slave->keepalive == AP_CONN_KEEPALIVE) {
+ task->c = NULL;
+ if (reuse_slave) {
h2_beam_log(task->output.beam, m->c, APLOG_DEBUG,
APLOGNO(03385) "h2_task_destroy, reuse slave");
h2_task_destroy(task);
@@ -392,10 +369,10 @@ static int report_stream_iter(void *ctx,
if (task) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c, /* NO APLOGNO */
H2_STRM_MSG(stream, "->03198: %s %s %s"
- "[started=%d/done=%d/frozen=%d]"),
+ "[started=%d/done=%d]"),
task->request->method, task->request->authority,
task->request->path, task->worker_started,
- task->worker_done, task->frozen);
+ task->worker_done);
}
else {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c, /* NO APLOGNO */
@@ -434,8 +411,10 @@ static int stream_cancel_iter(void *ctx,
void h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
{
apr_status_t status;
- int i, wait_secs = 60;
+ int i, wait_secs = 60, old_aborted;
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
+ "h2_mplx(%ld): start release", m->id);
/* How to shut down a h2 connection:
* 0. abort and tell the workers that no more tasks will come from us */
m->aborted = 1;
@@ -443,15 +422,19 @@ void h2_mplx_release_and_join(h2_mplx *m
H2_MPLX_ENTER_ALWAYS(m);
+ /* While really terminating any slave connections, treat the master
+ * connection as aborted. It's not as if we could send any more data
+ * at this point. */
+ old_aborted = m->c->aborted;
+ m->c->aborted = 1;
+
/* How to shut down a h2 connection:
* 1. cancel all streams still active */
while (!h2_ihash_iter(m->streams, stream_cancel_iter, m)) {
/* until empty */
}
- /* 2. terminate ngn_shed, no more streams
- * should be scheduled or in the active set */
- h2_ngn_shed_abort(m->ngn_shed);
+ /* 2. no more streams should be scheduled or in the active set */
ap_assert(h2_ihash_empty(m->streams));
ap_assert(h2_iq_empty(m->q));
@@ -475,10 +458,6 @@ void h2_mplx_release_and_join(h2_mplx *m
ap_assert(m->tasks_active == 0);
m->join_wait = NULL;
- /* 4. close the h2_req_enginge shed */
- h2_ngn_shed_destroy(m->ngn_shed);
- m->ngn_shed = NULL;
-
/* 4. With all workers done, all streams should be in spurge */
if (!h2_ihash_empty(m->shold)) {
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(03516)
@@ -487,6 +466,7 @@ void h2_mplx_release_and_join(h2_mplx *m
h2_ihash_iter(m->shold, unexpected_stream_iter, m);
}
+ m->c->aborted = old_aborted;
H2_MPLX_LEAVE(m);
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
@@ -783,47 +763,14 @@ apr_status_t h2_mplx_pop_task(h2_mplx *m
return rv;
}
-static void task_done(h2_mplx *m, h2_task *task, h2_req_engine *ngn)
+static void task_done(h2_mplx *m, h2_task *task)
{
h2_stream *stream;
- if (task->frozen) {
- /* this task was handed over to an engine for processing
- * and the original worker has finished. That means the
- * engine may start processing now. */
- h2_task_thaw(task);
- apr_thread_cond_broadcast(m->task_thawed);
- return;
- }
-
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
"h2_mplx(%ld): task(%s) done", m->id, task->id);
out_close(m, task);
- if (ngn) {
- apr_off_t bytes = 0;
- h2_beam_send(task->output.beam, NULL, APR_NONBLOCK_READ);
- bytes += h2_beam_get_buffered(task->output.beam);
- if (bytes > 0) {
- /* we need to report consumed and current buffered output
- * to the engine. The request will be streamed out or cancelled,
- * no more data is coming from it and the engine should update
- * its calculations before we destroy this information. */
- h2_req_engine_out_consumed(ngn, task->c, bytes);
- }
- }
-
- if (task->engine) {
- if (!m->aborted && !task->c->aborted
- && !h2_req_engine_is_shutdown(task->engine)) {
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c, APLOGNO(10022)
- "h2_mplx(%ld): task(%s) has not-shutdown "
- "engine(%s)", m->id, task->id,
- h2_req_engine_get_id(task->engine));
- }
- h2_ngn_shed_done_ngn(m->ngn_shed, task->engine);
- }
-
task->worker_done = 1;
task->done_at = apr_time_now();
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
@@ -845,18 +792,24 @@ static void task_done(h2_mplx *m, h2_tas
m->id, m->limit_active);
}
}
-
+
+ ap_assert(task->done_done == 0);
+
stream = h2_ihash_get(m->streams, task->stream_id);
if (stream) {
/* stream not done yet. */
if (!m->aborted && h2_ihash_get(m->sredo, stream->id)) {
/* reset and schedule again */
+ task->worker_done = 0;
h2_task_redo(task);
h2_ihash_remove(m->sredo, stream->id);
h2_iq_add(m->q, stream->id, NULL, NULL);
+ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, m->c,
+ H2_STRM_MSG(stream, "redo, added to q"));
}
else {
/* stream not cleaned up, stay around */
+ task->done_done = 1;
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
H2_STRM_MSG(stream, "task_done, stream open"));
if (stream->input) {
@@ -869,6 +822,7 @@ static void task_done(h2_mplx *m, h2_tas
}
else if ((stream = h2_ihash_get(m->shold, task->stream_id)) != NULL) {
/* stream is done, was just waiting for this. */
+ task->done_done = 1;
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
H2_STRM_MSG(stream, "task_done, in hold"));
if (stream->input) {
@@ -893,7 +847,7 @@ void h2_mplx_task_done(h2_mplx *m, h2_ta
{
H2_MPLX_ENTER_ALWAYS(m);
- task_done(m, task, NULL);
+ task_done(m, task);
--m->tasks_active;
if (m->join_wait) {
@@ -976,6 +930,9 @@ static apr_status_t unschedule_slow_task
*/
n = (m->tasks_active - m->limit_active - (int)h2_ihash_count(m->sredo));
while (n > 0 && (stream = get_latest_repeatable_unsubmitted_stream(m))) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
+ "h2_mplx(%s): unschedule, resetting task for redo later",
+ stream->task->id);
h2_task_rst(stream->task, H2_ERR_CANCEL);
h2_ihash_add(m->sredo, stream);
--n;
@@ -1084,142 +1041,6 @@ apr_status_t h2_mplx_idle(h2_mplx *m)
}
/*******************************************************************************
- * HTTP/2 request engines
- ******************************************************************************/
-
-typedef struct {
- h2_mplx * m;
- h2_req_engine *ngn;
- int streams_updated;
-} ngn_update_ctx;
-
-static int ngn_update_window(void *ctx, void *val)
-{
- ngn_update_ctx *uctx = ctx;
- h2_stream *stream = val;
- if (stream->task && stream->task->assigned == uctx->ngn
- && output_consumed_signal(uctx->m, stream->task)) {
- ++uctx->streams_updated;
- }
- return 1;
-}
-
-static apr_status_t ngn_out_update_windows(h2_mplx *m, h2_req_engine *ngn)
-{
- ngn_update_ctx ctx;
-
- ctx.m = m;
- ctx.ngn = ngn;
- ctx.streams_updated = 0;
- h2_ihash_iter(m->streams, ngn_update_window, &ctx);
-
- return ctx.streams_updated? APR_SUCCESS : APR_EAGAIN;
-}
-
-apr_status_t h2_mplx_req_engine_push(const char *ngn_type,
- request_rec *r,
- http2_req_engine_init *einit)
-{
- apr_status_t status;
- h2_mplx *m;
- h2_task *task;
- h2_stream *stream;
-
- task = h2_ctx_rget_task(r);
- if (!task) {
- return APR_ECONNABORTED;
- }
- m = task->mplx;
-
- H2_MPLX_ENTER(m);
-
- stream = h2_ihash_get(m->streams, task->stream_id);
- if (stream) {
- status = h2_ngn_shed_push_request(m->ngn_shed, ngn_type, r, einit);
- }
- else {
- status = APR_ECONNABORTED;
- }
-
- H2_MPLX_LEAVE(m);
- return status;
-}
-
-apr_status_t h2_mplx_req_engine_pull(h2_req_engine *ngn,
- apr_read_type_e block,
- int capacity,
- request_rec **pr)
-{
- h2_ngn_shed *shed = h2_ngn_shed_get_shed(ngn);
- h2_mplx *m = h2_ngn_shed_get_ctx(shed);
- apr_status_t status;
- int want_shutdown;
-
- H2_MPLX_ENTER(m);
-
- want_shutdown = (block == APR_BLOCK_READ);
-
- /* Take this opportunity to update output consummation
- * for this engine */
- ngn_out_update_windows(m, ngn);
-
- if (want_shutdown && !h2_iq_empty(m->q)) {
- /* For a blocking read, check first if requests are to be
- * had and, if not, wait a short while before doing the
- * blocking, and if unsuccessful, terminating read.
- */
- status = h2_ngn_shed_pull_request(shed, ngn, capacity, 1, pr);
- if (APR_STATUS_IS_EAGAIN(status)) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
- "h2_mplx(%ld): start block engine pull", m->id);
- apr_thread_cond_timedwait(m->task_thawed, m->lock,
- apr_time_from_msec(20));
- status = h2_ngn_shed_pull_request(shed, ngn, capacity, 1, pr);
- }
- }
- else {
- status = h2_ngn_shed_pull_request(shed, ngn, capacity,
- want_shutdown, pr);
- }
-
- H2_MPLX_LEAVE(m);
- return status;
-}
-
-void h2_mplx_req_engine_done(h2_req_engine *ngn, conn_rec *r_conn,
- apr_status_t status)
-{
- h2_task *task = h2_ctx_cget_task(r_conn);
-
- if (task) {
- h2_mplx *m = task->mplx;
- h2_stream *stream;
-
- H2_MPLX_ENTER_ALWAYS(m);
-
- stream = h2_ihash_get(m->streams, task->stream_id);
-
- ngn_out_update_windows(m, ngn);
- h2_ngn_shed_done_task(m->ngn_shed, ngn, task);
-
- if (status != APR_SUCCESS && stream
- && h2_task_can_redo(task)
- && !h2_ihash_get(m->sredo, stream->id)) {
- h2_ihash_add(m->sredo, stream);
- }
-
- if (task->engine) {
- /* cannot report that as done until engine returns */
- }
- else {
- task_done(m, task, ngn);
- }
-
- H2_MPLX_LEAVE(m);
- }
-}
-
-/*******************************************************************************
* mplx master events dispatching
******************************************************************************/
Index: httpd-2.4.23/modules/http2/h2_mplx.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_mplx.h 2019-04-02 13:39:34.072792571 +0200
+++ httpd-2.4.23/modules/http2/h2_mplx.h 2019-04-02 13:42:32.649683136 +0200
@@ -46,8 +46,6 @@ struct h2_request;
struct apr_thread_cond_t;
struct h2_workers;
struct h2_iqueue;
-struct h2_ngn_shed;
-struct h2_req_engine;
#include <apr_queue.h>
@@ -85,7 +83,6 @@ struct h2_mplx {
apr_thread_mutex_t *lock;
struct apr_thread_cond_t *added_output;
- struct apr_thread_cond_t *task_thawed;
struct apr_thread_cond_t *join_wait;
apr_size_t stream_max_mem;
@@ -94,8 +91,6 @@ struct h2_mplx {
apr_array_header_t *spare_slaves; /* spare slave connections */
struct h2_workers *workers;
-
- struct h2_ngn_shed *ngn_shed;
};
@@ -110,8 +105,7 @@ apr_status_t h2_mplx_child_init(apr_pool
* Create the multiplexer for the given HTTP2 session.
* Implicitly has reference count 1.
*/
-h2_mplx *h2_mplx_create(conn_rec *c, apr_pool_t *master,
- const struct h2_config *conf,
+h2_mplx *h2_mplx_create(conn_rec *c, server_rec *s, apr_pool_t *master,
struct h2_workers *workers);
/**
@@ -302,28 +296,4 @@ APR_RING_INSERT_TAIL((b), ap__b, h2_mplx
*/
apr_status_t h2_mplx_idle(h2_mplx *m);
-/*******************************************************************************
- * h2_req_engine handling
- ******************************************************************************/
-
-typedef void h2_output_consumed(void *ctx, conn_rec *c, apr_off_t consumed);
-typedef apr_status_t h2_mplx_req_engine_init(struct h2_req_engine *engine,
- const char *id,
- const char *type,
- apr_pool_t *pool,
- apr_size_t req_buffer_size,
- request_rec *r,
- h2_output_consumed **pconsumed,
- void **pbaton);
-
-apr_status_t h2_mplx_req_engine_push(const char *ngn_type,
- request_rec *r,
- h2_mplx_req_engine_init *einit);
-apr_status_t h2_mplx_req_engine_pull(struct h2_req_engine *ngn,
- apr_read_type_e block,
- int capacity,
- request_rec **pr);
-void h2_mplx_req_engine_done(struct h2_req_engine *ngn, conn_rec *r_conn,
- apr_status_t status);
-
#endif /* defined(__mod_h2__h2_mplx__) */
Index: httpd-2.4.23/modules/http2/h2_proxy_session.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_proxy_session.c 2019-04-02 13:39:34.224793330 +0200
+++ httpd-2.4.23/modules/http2/h2_proxy_session.c 2019-04-02 13:39:34.260793510 +0200
@@ -428,12 +428,6 @@ static int stream_response_data(nghttp2_
stream_id, NGHTTP2_STREAM_CLOSED);
return NGHTTP2_ERR_STREAM_CLOSING;
}
- if (stream->standalone) {
- nghttp2_session_consume(ngh2, stream_id, len);
- ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, stream->r,
- "h2_proxy_session(%s): stream %d, win_update %d bytes",
- session->id, stream_id, (int)len);
- }
return 0;
}
@@ -640,7 +634,7 @@ h2_proxy_session *h2_proxy_session_setup
nghttp2_option_new(&option);
nghttp2_option_set_peer_max_concurrent_streams(option, 100);
- nghttp2_option_set_no_auto_window_update(option, 1);
+ nghttp2_option_set_no_auto_window_update(option, 0);
nghttp2_session_client_new2(&session->ngh2, cbs, session, option);
@@ -652,10 +646,12 @@ h2_proxy_session *h2_proxy_session_setup
}
else {
h2_proxy_session *session = p_conn->data;
- apr_interval_time_t age = apr_time_now() - session->last_frame_received;
- if (age > apr_time_from_sec(1)) {
- session->check_ping = 1;
- nghttp2_submit_ping(session->ngh2, 0, (const uint8_t *)"nevergonnagiveyouup");
+ if (!session->check_ping) {
+ apr_interval_time_t age = apr_time_now() - session->last_frame_received;
+ if (age > apr_time_from_sec(1)) {
+ session->check_ping = 1;
+ nghttp2_submit_ping(session->ngh2, 0, (const uint8_t *)"nevergonnagiveyouup");
+ }
}
}
return p_conn->data;
@@ -1542,42 +1538,3 @@ typedef struct {
int updated;
} win_update_ctx;
-static int win_update_iter(void *udata, void *val)
-{
- win_update_ctx *ctx = udata;
- h2_proxy_stream *stream = val;
-
- if (stream->r && stream->r->connection == ctx->c) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, ctx->session->c,
- "h2_proxy_session(%s-%d): win_update %ld bytes",
- ctx->session->id, (int)stream->id, (long)ctx->bytes);
- nghttp2_session_consume(ctx->session->ngh2, stream->id, ctx->bytes);
- ctx->updated = 1;
- return 0;
- }
- return 1;
-}
-
-
-void h2_proxy_session_update_window(h2_proxy_session *session,
- conn_rec *c, apr_off_t bytes)
-{
- if (!h2_proxy_ihash_empty(session->streams)) {
- win_update_ctx ctx;
- ctx.session = session;
- ctx.c = c;
- ctx.bytes = bytes;
- ctx.updated = 0;
- h2_proxy_ihash_iter(session->streams, win_update_iter, &ctx);
-
- if (!ctx.updated) {
- /* could not find the stream any more, possibly closed, update
- * the connection window at least */
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
- "h2_proxy_session(%s): win_update conn %ld bytes",
- session->id, (long)bytes);
- nghttp2_session_consume_connection(session->ngh2, (size_t)bytes);
- }
- }
-}
-
Index: httpd-2.4.23/modules/http2/h2_proxy_session.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_proxy_session.h 2019-04-02 13:39:34.072792571 +0200
+++ httpd-2.4.23/modules/http2/h2_proxy_session.h 2019-04-02 13:39:34.260793510 +0200
@@ -119,9 +119,6 @@ void h2_proxy_session_cancel_all(h2_prox
void h2_proxy_session_cleanup(h2_proxy_session *s, h2_proxy_request_done *done);
-void h2_proxy_session_update_window(h2_proxy_session *s,
- conn_rec *c, apr_off_t bytes);
-
#define H2_PROXY_REQ_URL_NOTE "h2-proxy-req-url"
#endif /* h2_proxy_session_h */
Index: httpd-2.4.23/modules/http2/h2_request.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_request.c 2019-04-02 13:39:34.196793190 +0200
+++ httpd-2.4.23/modules/http2/h2_request.c 2019-04-02 13:42:32.649683136 +0200
@@ -16,6 +16,7 @@
#include <assert.h>
#include <apr_strings.h>
+#include <ap_mmn.h>
#include <httpd.h>
#include <http_core.h>
@@ -83,8 +84,7 @@ apr_status_t h2_request_rcreate(h2_reque
req->path = path;
req->headers = apr_table_make(pool, 10);
if (r->server) {
- req->serialize = h2_config_geti(h2_config_sget(r->server),
- H2_CONF_SER_HEADERS);
+ req->serialize = h2_config_rgeti(r, H2_CONF_SER_HEADERS);
}
x.pool = pool;
@@ -205,13 +205,11 @@ h2_request *h2_request_clone(apr_pool_t
return dst;
}
-request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c)
+#if !AP_MODULE_MAGIC_AT_LEAST(20150222, 13)
+static request_rec *my_ap_create_request(conn_rec *c)
{
- int access_status = HTTP_OK;
- const char *rpath;
apr_pool_t *p;
request_rec *r;
- const char *s;
apr_pool_create(&p, c->pool);
apr_pool_tag(p, "request");
@@ -225,8 +223,8 @@ request_rec *h2_request_create_rec(const
r->ap_auth_type = NULL;
r->allowed_methods = ap_make_method_list(p, 2);
-
- r->headers_in = apr_table_clone(r->pool, req->headers);
+
+ r->headers_in = apr_table_make(r->pool, 5);
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);
@@ -261,11 +259,29 @@ request_rec *h2_request_create_rec(const
r->useragent_addr = c->client_addr;
r->useragent_ip = c->client_ip;
+ return r;
+}
+#endif
+
+request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c)
+{
+ int access_status = HTTP_OK;
+ const char *rpath;
+ const char *s;
+
+#if AP_MODULE_MAGIC_AT_LEAST(20150222, 13)
+ request_rec *r = ap_create_request(c);
+#else
+ request_rec *r = my_ap_create_request(c);
+#endif
+
+ r->headers_in = apr_table_clone(r->pool, req->headers);
+
ap_run_pre_read_request(r, c);
/* Time to populate r with the data we have. */
r->request_time = req->request_time;
- r->method = req->method;
+ r->method = apr_pstrdup(r->pool, req->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') {
@@ -336,3 +352,4 @@ traceout:
}
+
Index: httpd-2.4.23/modules/http2/h2_session.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_session.c 2019-04-02 13:39:34.224793330 +0200
+++ httpd-2.4.23/modules/http2/h2_session.c 2019-04-02 13:42:32.653683156 +0200
@@ -494,9 +494,7 @@ static int on_send_data_cb(nghttp2_sessi
return NGHTTP2_ERR_WOULDBLOCK;
}
- if (frame->data.padlen > H2_MAX_PADLEN) {
- return NGHTTP2_ERR_PROTO;
- }
+ ap_assert(frame->data.padlen <= (H2_MAX_PADLEN+1));
padlen = (unsigned char)frame->data.padlen;
stream = h2_session_stream_get(session, stream_id);
@@ -512,8 +510,9 @@ static int on_send_data_cb(nghttp2_sessi
H2_STRM_MSG(stream, "send_data_cb for %ld bytes"),
(long)length);
- status = h2_conn_io_write(&session->io, (const char *)framehd, 9);
+ status = h2_conn_io_write(&session->io, (const char *)framehd, H2_FRAME_HDR_LEN);
if (padlen && status == APR_SUCCESS) {
+ --padlen;
status = h2_conn_io_write(&session->io, (const char *)&padlen, 1);
}
@@ -621,6 +620,39 @@ static int on_invalid_header_cb(nghttp2_
}
#endif
+static ssize_t select_padding_cb(nghttp2_session *ngh2,
+ const nghttp2_frame *frame,
+ size_t max_payloadlen, void *user_data)
+{
+ h2_session *session = user_data;
+ ssize_t frame_len = frame->hd.length + H2_FRAME_HDR_LEN; /* the total length without padding */
+ ssize_t padded_len = frame_len;
+
+ /* Determine # of padding bytes to append to frame. Unless session->padding_always
+ * the number my be capped by the ui.write_size that currently applies.
+ */
+ if (session->padding_max) {
+ int n = ap_random_pick(0, session->padding_max);
+ padded_len = H2MIN(max_payloadlen + H2_FRAME_HDR_LEN, frame_len + n);
+ }
+
+ if (padded_len != frame_len) {
+ if (!session->padding_always && session->io.write_size
+ && (padded_len > session->io.write_size)
+ && (frame_len <= session->io.write_size)) {
+ padded_len = session->io.write_size;
+ }
+ if (APLOGctrace2(session->c)) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
+ "select padding from [%d, %d]: %d (frame length: 0x%04x, write size: %d)",
+ (int)frame_len, (int)max_payloadlen+H2_FRAME_HDR_LEN,
+ (int)(padded_len - frame_len), (int)padded_len, (int)session->io.write_size);
+ }
+ return padded_len - H2_FRAME_HDR_LEN;
+ }
+ return frame->hd.length;
+}
+
#define NGH2_SET_CALLBACK(callbacks, name, fn)\
nghttp2_session_callbacks_set_##name##_callback(callbacks, fn)
@@ -646,6 +678,7 @@ static apr_status_t init_callbacks(conn_
#ifdef H2_NG2_INVALID_HEADER_CB
NGH2_SET_CALLBACK(*pcb, on_invalid_header, on_invalid_header_cb);
#endif
+ NGH2_SET_CALLBACK(*pcb, select_padding, select_padding_cb);
return APR_SUCCESS;
}
@@ -756,9 +789,8 @@ static apr_status_t session_pool_cleanup
{
conn_rec *c = data;
h2_session *session;
- h2_ctx *ctx = h2_ctx_get(c, 0);
- if (ctx && (session = h2_ctx_session_get(ctx))) {
+ if ((session = h2_ctx_get_session(c))) {
/* if the session is still there, now is the last chance
* to perform cleanup. Normally, cleanup should have happened
* earlier in the connection pre_close. Main reason is that
@@ -774,11 +806,8 @@ static apr_status_t session_pool_cleanup
return APR_SUCCESS;
}
-static apr_status_t h2_session_create_int(h2_session **psession,
- conn_rec *c,
- request_rec *r,
- h2_ctx *ctx,
- h2_workers *workers)
+apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec *r,
+ server_rec *s, h2_workers *workers)
{
nghttp2_session_callbacks *callbacks = NULL;
nghttp2_option *options = NULL;
@@ -819,19 +848,16 @@ static apr_status_t h2_session_create_in
session->id = c->id;
session->c = c;
session->r = r;
- session->s = h2_ctx_server_get(ctx);
+ session->s = s;
session->pool = pool;
- session->config = h2_config_sget(session->s);
session->workers = workers;
session->state = H2_SESSION_ST_INIT;
session->local.accepting = 1;
session->remote.accepting = 1;
- session->max_stream_count = h2_config_geti(session->config,
- H2_CONF_MAX_STREAMS);
- session->max_stream_mem = h2_config_geti(session->config,
- H2_CONF_STREAM_MAX_MEM);
+ session->max_stream_count = h2_config_sgeti(s, H2_CONF_MAX_STREAMS);
+ session->max_stream_mem = h2_config_sgeti(s, H2_CONF_STREAM_MAX_MEM);
status = apr_thread_cond_create(&session->iowait, session->pool);
if (status != APR_SUCCESS) {
@@ -861,14 +887,18 @@ static apr_status_t h2_session_create_in
session->monitor->on_state_event = on_stream_state_event;
session->monitor->on_event = on_stream_event;
- session->mplx = h2_mplx_create(c, session->pool, session->config,
- workers);
+ session->mplx = h2_mplx_create(c, s, session->pool, workers);
/* connection input filter that feeds the session */
session->cin = h2_filter_cin_create(session);
ap_add_input_filter("H2_IN", session->cin, r, c);
- h2_conn_io_init(&session->io, c, session->config);
+ h2_conn_io_init(&session->io, c, s);
+ session->padding_max = h2_config_sgeti(s, H2_CONF_PADDING_BITS);
+ if (session->padding_max) {
+ session->padding_max = (0x01 << session->padding_max) - 1;
+ }
+ session->padding_always = h2_config_sgeti(s, H2_CONF_PADDING_ALWAYS);
session->bbtmp = apr_brigade_create(session->pool, c->bucket_alloc);
status = init_callbacks(c, &callbacks);
@@ -887,8 +917,7 @@ static apr_status_t h2_session_create_in
apr_pool_destroy(pool);
return status;
}
- nghttp2_option_set_peer_max_concurrent_streams(
- options, (uint32_t)session->max_stream_count);
+ nghttp2_option_set_peer_max_concurrent_streams(options, (uint32_t)session->max_stream_count);
/* We need to handle window updates ourself, otherwise we
* get flooded by nghttp2. */
nghttp2_option_set_no_auto_window_update(options, 1);
@@ -906,7 +935,7 @@ static apr_status_t h2_session_create_in
return APR_ENOMEM;
}
- n = h2_config_geti(session->config, H2_CONF_PUSH_DIARY_SIZE);
+ n = h2_config_sgeti(s, H2_CONF_PUSH_DIARY_SIZE);
session->push_diary = h2_push_diary_create(session->pool, n);
if (APLOGcdebug(c)) {
@@ -923,20 +952,9 @@ static apr_status_t h2_session_create_in
(int)session->push_diary->N);
}
- apr_pool_pre_cleanup_register(pool, c, session_pool_cleanup);
- return APR_SUCCESS;
-}
-
-apr_status_t h2_session_create(h2_session **psession,
- conn_rec *c, h2_ctx *ctx, h2_workers *workers)
-{
- return h2_session_create_int(psession, c, NULL, ctx, workers);
-}
+ apr_pool_pre_cleanup_register(pool, c, session_pool_cleanup);
-apr_status_t h2_session_rcreate(h2_session **psession,
- request_rec *r, h2_ctx *ctx, h2_workers *workers)
-{
- return h2_session_create_int(psession, r->connection, r, ctx, workers);
+ return APR_SUCCESS;
}
static apr_status_t h2_session_start(h2_session *session, int *rv)
@@ -1003,7 +1021,7 @@ static apr_status_t h2_session_start(h2_
settings[slen].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
settings[slen].value = (uint32_t)session->max_stream_count;
++slen;
- win_size = h2_config_geti(session->config, H2_CONF_WIN_SIZE);
+ win_size = h2_config_sgeti(session->s, H2_CONF_WIN_SIZE);
if (win_size != H2_INITIAL_WINDOW_SIZE) {
settings[slen].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
settings[slen].value = win_size;
@@ -1279,7 +1297,7 @@ int h2_session_push_enabled(h2_session *
{
/* iff we can and they can and want */
return (session->remote.accepting /* remote GOAWAY received */
- && h2_config_geti(session->config, H2_CONF_PUSH)
+ && h2_config_sgeti(session->s, H2_CONF_PUSH)
&& nghttp2_session_get_remote_settings(session->ngh2,
NGHTTP2_SETTINGS_ENABLE_PUSH));
}
@@ -1323,6 +1341,7 @@ static apr_status_t on_stream_headers(h2
int eos)
{
apr_status_t status = APR_SUCCESS;
+ const char *s;
int rv = 0;
ap_assert(session);
@@ -1390,8 +1409,12 @@ static apr_status_t on_stream_headers(h2
&& (headers->status < 400)
&& (headers->status != 304)
&& h2_session_push_enabled(session)) {
-
- h2_stream_submit_pushes(stream, headers);
+ /* PUSH is possibe and enabled on server, unless the request
+ * denies it, submit resources to push */
+ s = apr_table_get(headers->notes, H2_PUSH_MODE_NOTE);
+ if (!s || strcmp(s, "0")) {
+ h2_stream_submit_pushes(stream, headers);
+ }
}
if (!stream->pref_priority) {
@@ -1413,7 +1436,7 @@ static apr_status_t on_stream_headers(h2
}
if (headers->status == 103
- && !h2_config_geti(session->config, H2_CONF_EARLY_HINTS)) {
+ && !h2_config_sgeti(session->s, H2_CONF_EARLY_HINTS)) {
/* suppress sending this to the client, it might have triggered
* pushes and served its purpose nevertheless */
rv = 0;
@@ -2088,7 +2111,7 @@ apr_status_t h2_session_process(h2_sessi
switch (session->state) {
case H2_SESSION_ST_INIT:
ap_update_child_status_from_conn(c->sbh, SERVER_BUSY_READ, c);
- if (!h2_is_acceptable_connection(c, 1)) {
+ if (!h2_is_acceptable_connection(c, session->r, 1)) {
update_child_status(session, SERVER_BUSY_READ,
"inadequate security");
h2_session_shutdown(session,
Index: httpd-2.4.23/modules/http2/h2_session.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_session.h 2019-04-02 13:39:34.196793190 +0200
+++ httpd-2.4.23/modules/http2/h2_session.h 2019-04-02 13:42:32.653683156 +0200
@@ -79,12 +79,13 @@ typedef struct h2_session {
request_rec *r; /* the request that started this in case
* of 'h2c', NULL otherwise */
server_rec *s; /* server/vhost we're starting on */
- const struct h2_config *config; /* Relevant config for this session */
apr_pool_t *pool; /* pool to use in session */
struct h2_mplx *mplx; /* multiplexer for stream data */
struct h2_workers *workers; /* for executing stream tasks */
struct h2_filter_cin *cin; /* connection input filter context */
h2_conn_io io; /* io on httpd conn filters */
+ int padding_max; /* max number of padding bytes */
+ int padding_always; /* padding has precedence over I/O optimizations */
struct nghttp2_session *ngh2; /* the nghttp2 session (internal use) */
h2_session_state state; /* state session is in */
@@ -141,27 +142,15 @@ const char *h2_session_state_str(h2_sess
* The session will apply the configured parameter.
* @param psession pointer receiving the created session on success or NULL
* @param c the connection to work on
+ * @param r optional request when protocol was upgraded
* @param cfg the module config to apply
* @param workers the worker pool to use
* @return the created session
*/
apr_status_t h2_session_create(h2_session **psession,
- conn_rec *c, struct h2_ctx *ctx,
+ conn_rec *c, request_rec *r, server_rec *,
struct h2_workers *workers);
-/**
- * Create a new h2_session for the given request.
- * The session will apply the configured parameter.
- * @param psession pointer receiving the created session on success or NULL
- * @param r the request that was upgraded
- * @param cfg the module config to apply
- * @param workers the worker pool to use
- * @return the created session
- */
-apr_status_t h2_session_rcreate(h2_session **psession,
- request_rec *r, struct h2_ctx *ctx,
- struct h2_workers *workers);
-
void h2_session_event(h2_session *session, h2_session_event_t ev,
int err, const char *msg);
Index: httpd-2.4.23/modules/http2/h2_stream.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_stream.c 2019-04-02 13:39:34.224793330 +0200
+++ httpd-2.4.23/modules/http2/h2_stream.c 2019-04-02 13:42:32.653683156 +0200
@@ -364,9 +364,8 @@ void h2_stream_dispatch(h2_stream *strea
static void set_policy_for(h2_stream *stream, h2_request *r)
{
int enabled = h2_session_push_enabled(stream->session);
- stream->push_policy = h2_push_policy_determine(r->headers, stream->pool,
- enabled);
- r->serialize = h2_config_geti(stream->session->config, H2_CONF_SER_HEADERS);
+ stream->push_policy = h2_push_policy_determine(r->headers, stream->pool, enabled);
+ r->serialize = h2_config_sgeti(stream->session->s, H2_CONF_SER_HEADERS);
}
apr_status_t h2_stream_send_frame(h2_stream *stream, int ftype, int flags, size_t frame_len)
@@ -854,7 +853,7 @@ apr_status_t h2_stream_out_prepare(h2_st
* is requested. But we can reduce the size in case the master
* connection operates in smaller chunks. (TSL warmup) */
if (stream->session->io.write_size > 0) {
- max_chunk = stream->session->io.write_size - 9; /* header bits */
+ max_chunk = stream->session->io.write_size - H2_FRAME_HDR_LEN;
}
requested = (*plen > 0)? H2MIN(*plen, max_chunk) : max_chunk;
@@ -986,7 +985,7 @@ const h2_priority *h2_stream_get_priorit
const char *ctype = apr_table_get(response->headers, "content-type");
if (ctype) {
/* FIXME: Not good enough, config needs to come from request->server */
- return h2_config_get_priority(stream->session->config, ctype);
+ return h2_cconfig_get_priority(stream->session->c, ctype);
}
}
return NULL;
Index: httpd-2.4.23/modules/http2/h2_switch.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_switch.c 2019-04-02 13:39:34.196793190 +0200
+++ httpd-2.4.23/modules/http2/h2_switch.c 2019-04-02 13:42:32.653683156 +0200
@@ -54,7 +54,6 @@ static int h2_protocol_propose(conn_rec
int is_tls = h2_h2_is_tls(c);
const char **protos = is_tls? h2_tls_protos : h2_clear_protos;
- (void)s;
if (!h2_mpm_supported()) {
return DECLINED;
}
@@ -67,7 +66,7 @@ static int h2_protocol_propose(conn_rec
return DECLINED;
}
- if (!h2_is_acceptable_connection(c, 0)) {
+ if (!h2_is_acceptable_connection(c, r, 0)) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03084)
"protocol propose: connection requirements not met");
return DECLINED;
@@ -80,7 +79,7 @@ static int h2_protocol_propose(conn_rec
*/
const char *p;
- if (!h2_allows_h2_upgrade(c)) {
+ if (!h2_allows_h2_upgrade(r)) {
return DECLINED;
}
@@ -149,7 +148,7 @@ static int h2_protocol_switch(conn_rec *
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
"switching protocol to '%s'", protocol);
h2_ctx_protocol_set(ctx, protocol);
- h2_ctx_server_set(ctx, s);
+ h2_ctx_server_update(ctx, s);
if (r != NULL) {
apr_status_t status;
@@ -163,8 +162,8 @@ static int h2_protocol_switch(conn_rec *
ap_remove_output_filter_byhandle(r->output_filters, "HTTP_HEADER");
/* Ok, start an h2_conn on this one. */
- h2_ctx_server_set(ctx, r->server);
- status = h2_conn_setup(ctx, r->connection, r);
+ status = h2_conn_setup(c, r, s);
+
if (status != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r, APLOGNO(03088)
"session setup");
@@ -172,7 +171,7 @@ static int h2_protocol_switch(conn_rec *
return !OK;
}
- h2_conn_run(ctx, c);
+ h2_conn_run(c);
}
return OK;
}
Index: httpd-2.4.23/modules/http2/h2_task.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_task.c 2019-04-02 13:39:34.196793190 +0200
+++ httpd-2.4.23/modules/http2/h2_task.c 2019-04-02 13:39:34.264793530 +0200
@@ -96,7 +96,7 @@ static apr_status_t send_out(h2_task *ta
apr_brigade_length(bb, 0, &written);
H2_TASK_OUT_LOG(APLOG_TRACE2, task, bb, "h2_task send_out");
h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "send_out(before)");
- /* engines send unblocking */
+
status = h2_beam_send(task->output.beam, bb,
block? APR_BLOCK_READ : APR_NONBLOCK_READ);
h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "send_out(after)");
@@ -132,26 +132,9 @@ static apr_status_t slave_out(h2_task *t
apr_status_t rv = APR_SUCCESS;
int flush = 0, blocking;
- if (task->frozen) {
- h2_util_bb_log(task->c, task->stream_id, APLOG_TRACE2,
- "frozen task output write, ignored", bb);
- while (!APR_BRIGADE_EMPTY(bb)) {
- b = APR_BRIGADE_FIRST(bb);
- if (AP_BUCKET_IS_EOR(b)) {
- APR_BUCKET_REMOVE(b);
- task->eor = b;
- }
- else {
- apr_bucket_delete(b);
- }
- }
- return APR_SUCCESS;
- }
-
send:
- /* we send block once we opened the output, so someone is there
- * reading it *and* the task is not assigned to a h2_req_engine */
- blocking = (!task->assigned && task->output.opened);
+ /* we send block once we opened the output, so someone is there reading it */
+ blocking = task->output.opened;
for (b = APR_BRIGADE_FIRST(bb);
b != APR_BRIGADE_SENTINEL(bb);
b = APR_BUCKET_NEXT(b)) {
@@ -235,7 +218,7 @@ static apr_status_t h2_filter_slave_in(a
apr_size_t rmax = ((readbytes <= APR_SIZE_MAX)?
(apr_size_t)readbytes : APR_SIZE_MAX);
- task = h2_ctx_cget_task(f->c);
+ task = h2_ctx_get_task(f->c);
ap_assert(task);
if (trace1) {
@@ -309,11 +292,9 @@ static apr_status_t h2_filter_slave_in(a
}
}
- /* Nothing there, no more data to get. Return APR_EAGAIN on
- * speculative reads, this is ap_check_pipeline()'s trick to
- * see if the connection needs closing. */
+ /* Nothing there, no more data to get. Return. */
if (status == APR_EOF && APR_BRIGADE_EMPTY(task->input.bb)) {
- return (mode == AP_MODE_SPECULATIVE)? APR_EAGAIN : APR_EOF;
+ return status;
}
if (trace1) {
@@ -378,7 +359,7 @@ static apr_status_t h2_filter_slave_in(a
static apr_status_t h2_filter_slave_output(ap_filter_t* filter,
apr_bucket_brigade* brigade)
{
- h2_task *task = h2_ctx_cget_task(filter->c);
+ h2_task *task = h2_ctx_get_task(filter->c);
apr_status_t status;
ap_assert(task);
@@ -391,7 +372,7 @@ static apr_status_t h2_filter_slave_outp
static apr_status_t h2_filter_parse_h1(ap_filter_t* f, apr_bucket_brigade* bb)
{
- h2_task *task = h2_ctx_cget_task(f->c);
+ h2_task *task = h2_ctx_get_task(f->c);
apr_status_t status;
ap_assert(task);
@@ -501,9 +482,9 @@ static int h2_task_pre_conn(conn_rec* c,
ctx = h2_ctx_get(c, 0);
(void)arg;
- if (h2_ctx_is_task(ctx)) {
+ if (ctx->task) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- "h2_h2, pre_connection, found stream task");
+ "h2_slave(%s), pre_connection, adding filters", c->log_id);
ap_add_input_filter("H2_SLAVE_IN", NULL, NULL, c);
ap_add_output_filter("H2_PARSE_H1", NULL, NULL, c);
ap_add_output_filter("H2_SLAVE_OUT", NULL, NULL, c);
@@ -524,6 +505,7 @@ h2_task *h2_task_create(conn_rec *slave,
ap_assert(req);
apr_pool_create(&pool, slave->pool);
+ apr_pool_tag(pool, "h2_task");
task = apr_pcalloc(pool, sizeof(h2_task));
if (task == NULL) {
return NULL;
@@ -544,7 +526,6 @@ h2_task *h2_task_create(conn_rec *slave,
void h2_task_destroy(h2_task *task)
{
if (task->output.beam) {
- h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "task_destroy");
h2_beam_destroy(task->output.beam);
task->output.beam = NULL;
}
@@ -598,7 +579,6 @@ apr_status_t h2_task_do(h2_task *task, a
slave_id = worker_id;
}
task->c->id = (c->master->id << free_bits)^slave_id;
- c->keepalive = AP_CONN_KEEPALIVE;
}
h2_beam_create(&task->output.beam, c->pool, task->stream_id, "output",
@@ -633,18 +613,9 @@ apr_status_t h2_task_do(h2_task *task, a
task->c->current_thread = thread;
ap_run_process_connection(c);
- if (task->frozen) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
- "h2_task(%s): process_conn returned frozen task",
- task->id);
- /* cleanup delayed */
- return APR_EAGAIN;
- }
- else {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
- "h2_task(%s): processing done", task->id);
- return output_finish(task);
- }
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
+ "h2_task(%s): processing done", task->id);
+ return output_finish(task);
}
static apr_status_t h2_task_process_request(h2_task *task, conn_rec *c)
@@ -682,14 +653,8 @@ static apr_status_t h2_task_process_requ
ap_process_request(r);
- if (task->frozen) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
- "h2_task(%s): process_request frozen", task->id);
- }
- else {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
- "h2_task(%s): process_request done", task->id);
- }
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
+ "h2_task(%s): process_request done", task->id);
/* After the call to ap_process_request, the
* request pool may have been deleted. We set
@@ -724,7 +689,7 @@ static int h2_task_process_conn(conn_rec
}
ctx = h2_ctx_get(c, 0);
- if (h2_ctx_is_task(ctx)) {
+ if (ctx->task) {
if (!ctx->task->request->serialize) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
"h2_h2, processing request directly");
@@ -741,28 +706,3 @@ static int h2_task_process_conn(conn_rec
return DECLINED;
}
-apr_status_t h2_task_freeze(h2_task *task)
-{
- if (!task->frozen) {
- task->frozen = 1;
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, task->c, APLOGNO(03406)
- "h2_task(%s), frozen", task->id);
- }
- return APR_SUCCESS;
-}
-
-apr_status_t h2_task_thaw(h2_task *task)
-{
- if (task->frozen) {
- task->frozen = 0;
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, task->c, APLOGNO(03407)
- "h2_task(%s), thawed", task->id);
- }
- task->thawed = 1;
- return APR_SUCCESS;
-}
-
-int h2_task_has_thawed(h2_task *task)
-{
- return task->thawed;
-}
Index: httpd-2.4.23/modules/http2/h2_task.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_task.h 2019-04-02 13:39:34.076792591 +0200
+++ httpd-2.4.23/modules/http2/h2_task.h 2019-04-02 13:42:32.653683156 +0200
@@ -41,7 +41,6 @@ struct h2_bucket_beam;
struct h2_conn;
struct h2_mplx;
struct h2_task;
-struct h2_req_engine;
struct h2_request;
struct h2_response_parser;
struct h2_stream;
@@ -79,17 +78,14 @@ struct h2_task {
struct h2_mplx *mplx;
unsigned int filters_set : 1;
- unsigned int frozen : 1;
- unsigned int thawed : 1;
unsigned int worker_started : 1; /* h2_worker started processing */
- unsigned int worker_done : 1; /* h2_worker finished */
+
+ int worker_done; /* h2_worker finished */
+ int done_done; /* task_done has been handled */
apr_time_t started_at; /* when processing started */
apr_time_t done_at; /* when processing was done */
apr_bucket *eor;
-
- struct h2_req_engine *engine; /* engine hosted by this task */
- struct h2_req_engine *assigned; /* engine that task has been assigned to */
};
h2_task *h2_task_create(conn_rec *slave, int stream_id,
@@ -119,8 +115,4 @@ apr_status_t h2_task_init(apr_pool_t *po
extern APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_in) *h2_task_logio_add_bytes_in;
extern APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *h2_task_logio_add_bytes_out;
-apr_status_t h2_task_freeze(h2_task *task);
-apr_status_t h2_task_thaw(h2_task *task);
-int h2_task_has_thawed(h2_task *task);
-
#endif /* defined(__mod_h2__h2_task__) */
Index: httpd-2.4.23/modules/http2/h2_version.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/h2_version.h 2019-04-02 13:39:34.224793330 +0200
+++ httpd-2.4.23/modules/http2/h2_version.h 2019-04-02 13:39:34.264793530 +0200
@@ -26,7 +26,7 @@
* @macro
* Version number of the http2 module as c string
*/
-#define MOD_HTTP2_VERSION "1.11.4"
+#define MOD_HTTP2_VERSION "1.14.1"
/**
* @macro
@@ -34,7 +34,6 @@
* 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 0x010b04
-
+#define MOD_HTTP2_VERSION_NUM 0x010e01
#endif /* mod_h2_h2_version_h */
Index: httpd-2.4.23/modules/http2/mod_http2.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/mod_http2.c 2019-04-02 13:39:34.196793190 +0200
+++ httpd-2.4.23/modules/http2/mod_http2.c 2019-04-02 13:42:32.653683156 +0200
@@ -171,27 +171,6 @@ static char *http2_var_lookup(apr_pool_t
conn_rec *, request_rec *, char *name);
static int http2_is_h2(conn_rec *);
-static apr_status_t http2_req_engine_push(const char *ngn_type,
- request_rec *r,
- http2_req_engine_init *einit)
-{
- return h2_mplx_req_engine_push(ngn_type, r, einit);
-}
-
-static apr_status_t http2_req_engine_pull(h2_req_engine *ngn,
- apr_read_type_e block,
- int capacity,
- request_rec **pr)
-{
- return h2_mplx_req_engine_pull(ngn, block, capacity, pr);
-}
-
-static void http2_req_engine_done(h2_req_engine *ngn, conn_rec *r_conn,
- apr_status_t status)
-{
- h2_mplx_req_engine_done(ngn, r_conn, status);
-}
-
static void http2_get_num_workers(server_rec *s, int *minw, int *maxw)
{
h2_get_num_workers(s, minw, maxw);
@@ -219,9 +198,6 @@ static void h2_hooks(apr_pool_t *pool)
APR_REGISTER_OPTIONAL_FN(http2_is_h2);
APR_REGISTER_OPTIONAL_FN(http2_var_lookup);
- APR_REGISTER_OPTIONAL_FN(http2_req_engine_push);
- APR_REGISTER_OPTIONAL_FN(http2_req_engine_pull);
- APR_REGISTER_OPTIONAL_FN(http2_req_engine_done);
APR_REGISTER_OPTIONAL_FN(http2_get_num_workers);
ap_log_perror(APLOG_MARK, APLOG_TRACE1, 0, pool, "installing hooks");
@@ -259,9 +235,8 @@ static const char *val_H2_PUSH(apr_pool_
{
if (ctx) {
if (r) {
- h2_task *task = h2_ctx_get_task(ctx);
- if (task) {
- h2_stream *stream = h2_mplx_stream_get(task->mplx, task->stream_id);
+ if (ctx->task) {
+ h2_stream *stream = h2_mplx_stream_get(ctx->task->mplx, ctx->task->stream_id);
if (stream && stream->push_policy != H2_PUSH_NONE) {
return "on";
}
@@ -272,8 +247,7 @@ static const char *val_H2_PUSH(apr_pool_
}
}
else if (s) {
- const h2_config *cfg = h2_config_sget(s);
- if (cfg && h2_config_geti(cfg, H2_CONF_PUSH)) {
+ if (h2_config_geti(r, s, H2_CONF_PUSH)) {
return "on";
}
}
@@ -284,8 +258,7 @@ static const char *val_H2_PUSHED(apr_poo
conn_rec *c, request_rec *r, h2_ctx *ctx)
{
if (ctx) {
- h2_task *task = h2_ctx_get_task(ctx);
- if (task && !H2_STREAM_CLIENT_INITIATED(task->stream_id)) {
+ if (ctx->task && !H2_STREAM_CLIENT_INITIATED(ctx->task->stream_id)) {
return "PUSHED";
}
}
@@ -296,9 +269,8 @@ static const char *val_H2_PUSHED_ON(apr_
conn_rec *c, request_rec *r, h2_ctx *ctx)
{
if (ctx) {
- h2_task *task = h2_ctx_get_task(ctx);
- if (task && !H2_STREAM_CLIENT_INITIATED(task->stream_id)) {
- h2_stream *stream = h2_mplx_stream_get(task->mplx, task->stream_id);
+ if (ctx->task && !H2_STREAM_CLIENT_INITIATED(ctx->task->stream_id)) {
+ h2_stream *stream = h2_mplx_stream_get(ctx->task->mplx, ctx->task->stream_id);
if (stream) {
return apr_itoa(p, stream->initiated_on);
}
@@ -311,9 +283,8 @@ static const char *val_H2_STREAM_TAG(apr
conn_rec *c, request_rec *r, h2_ctx *ctx)
{
if (ctx) {
- h2_task *task = h2_ctx_get_task(ctx);
- if (task) {
- return task->id;
+ if (ctx->task) {
+ return ctx->task->id;
}
}
return "";
@@ -365,7 +336,7 @@ static char *http2_var_lookup(apr_pool_t
for (i = 0; i < H2_ALEN(H2_VARS); ++i) {
h2_var_def *vdef = &H2_VARS[i];
if (!strcmp(vdef->name, name)) {
- h2_ctx *ctx = (r? h2_ctx_rget(r) :
+ h2_ctx *ctx = (r? h2_ctx_get(c, 0) :
h2_ctx_get(c->master? c->master : c, 0));
return (char *)vdef->lookup(p, s, c, r, ctx);
}
@@ -376,7 +347,7 @@ static char *http2_var_lookup(apr_pool_t
static int h2_h2_fixups(request_rec *r)
{
if (r->connection->master) {
- h2_ctx *ctx = h2_ctx_rget(r);
+ h2_ctx *ctx = h2_ctx_get(r->connection, 0);
int i;
for (i = 0; ctx && i < H2_ALEN(H2_VARS); ++i) {
Index: httpd-2.4.23/modules/http2/mod_http2.dep
===================================================================
--- httpd-2.4.23.orig/modules/http2/mod_http2.dep 2019-04-02 13:39:34.080792611 +0200
+++ httpd-2.4.23/modules/http2/mod_http2.dep 2019-04-02 13:39:34.264793530 +0200
@@ -694,7 +694,6 @@
".\h2_ctx.h"\
".\h2_h2.h"\
".\h2_mplx.h"\
- ".\h2_ngn_shed.h"\
".\h2_private.h"\
".\h2_request.h"\
".\h2_stream.h"\
@@ -754,7 +753,6 @@
".\h2_ctx.h"\
".\h2_h2.h"\
".\h2_mplx.h"\
- ".\h2_ngn_shed.h"\
".\h2_private.h"\
".\h2_request.h"\
".\h2_task.h"\
Index: httpd-2.4.23/modules/http2/mod_http2.dsp
===================================================================
--- httpd-2.4.23.orig/modules/http2/mod_http2.dsp 2019-04-02 13:39:34.080792611 +0200
+++ httpd-2.4.23/modules/http2/mod_http2.dsp 2019-04-02 13:39:34.264793530 +0200
@@ -145,10 +145,6 @@ SOURCE=./h2_mplx.c
# End Source File
# Begin Source File
-SOURCE=./h2_ngn_shed.c
-# End Source File
-# Begin Source File
-
SOURCE=./h2_push.c
# End Source File
# Begin Source File
Index: httpd-2.4.23/modules/http2/mod_http2.h
===================================================================
--- httpd-2.4.23.orig/modules/http2/mod_http2.h 2019-04-02 13:39:34.196793190 +0200
+++ httpd-2.4.23/modules/http2/mod_http2.h 2019-04-02 13:42:32.653683156 +0200
@@ -29,22 +29,20 @@ APR_DECLARE_OPTIONAL_FN(int,
/*******************************************************************************
- * HTTP/2 request engines
+ * START HTTP/2 request engines (DEPRECATED)
******************************************************************************/
+
+/* The following functions were introduced for the experimental mod_proxy_http2
+ * support, but have been abandoned since.
+ * They are still declared here for backward compatibiliy, in case someone
+ * tries to build an old mod_proxy_http2 against it, but will disappear
+ * completely sometime in the future.
+ */
struct apr_thread_cond_t;
-
typedef struct h2_req_engine h2_req_engine;
-
typedef void http2_output_consumed(void *ctx, conn_rec *c, apr_off_t consumed);
-/**
- * Initialize a h2_req_engine. The structure will be passed in but
- * only the name and master are set. The function should initialize
- * all fields.
- * @param engine the allocated, partially filled structure
- * @param r the first request to process, or NULL
- */
typedef apr_status_t http2_req_engine_init(h2_req_engine *engine,
const char *id,
const char *type,
@@ -54,35 +52,11 @@ typedef apr_status_t http2_req_engine_in
http2_output_consumed **pconsumed,
void **pbaton);
-/**
- * Push a request to an engine with the specified name for further processing.
- * If no such engine is available, einit is not NULL, einit is called
- * with a new engine record and the caller is responsible for running the
- * new engine instance.
- * @param engine_type the type of the engine to add the request to
- * @param r the request to push to an engine for processing
- * @param einit an optional initialization callback for a new engine
- * of the requested type, should no instance be available.
- * By passing a non-NULL callback, the caller is willing
- * to init and run a new engine itself.
- * @return APR_SUCCESS iff slave was successfully added to an engine
- */
APR_DECLARE_OPTIONAL_FN(apr_status_t,
http2_req_engine_push, (const char *engine_type,
request_rec *r,
http2_req_engine_init *einit));
-/**
- * Get a new request for processing in this engine.
- * @param engine the engine which is done processing the slave
- * @param block if call should block waiting for request to come
- * @param capacity how many parallel requests are acceptable
- * @param pr the request that needs processing or NULL
- * @return APR_SUCCESS if new request was assigned
- * APR_EAGAIN if no new request is available
- * APR_EOF if engine may shut down, as no more request will be scheduled
- * APR_ECONNABORTED if the engine needs to shut down immediately
- */
APR_DECLARE_OPTIONAL_FN(apr_status_t,
http2_req_engine_pull, (h2_req_engine *engine,
apr_read_type_e block,
@@ -97,4 +71,8 @@ APR_DECLARE_OPTIONAL_FN(void,
http2_get_num_workers, (server_rec *s,
int *minw, int *max));
+/*******************************************************************************
+ * END HTTP/2 request engines (DEPRECATED)
+ ******************************************************************************/
+
#endif
Index: httpd-2.4.23/modules/http2/mod_http2.mak
===================================================================
--- httpd-2.4.23.orig/modules/http2/mod_http2.mak 2019-04-02 13:39:34.080792611 +0200
+++ httpd-2.4.23/modules/http2/mod_http2.mak 2019-04-02 13:39:34.264793530 +0200
@@ -61,7 +61,6 @@ CLEAN :
-@erase "$(INTDIR)\h2_h2.obj"
-@erase "$(INTDIR)\h2_headers.obj"
-@erase "$(INTDIR)\h2_mplx.obj"
- -@erase "$(INTDIR)\h2_ngn_shed.obj"
-@erase "$(INTDIR)\h2_push.obj"
-@erase "$(INTDIR)\h2_request.obj"
-@erase "$(INTDIR)\h2_session.obj"
@@ -138,7 +137,6 @@ LINK32_OBJS= \
"$(INTDIR)\h2_h2.obj" \
"$(INTDIR)\h2_headers.obj" \
"$(INTDIR)\h2_mplx.obj" \
- "$(INTDIR)\h2_ngn_shed.obj" \
"$(INTDIR)\h2_push.obj" \
"$(INTDIR)\h2_request.obj" \
"$(INTDIR)\h2_session.obj" \
@@ -207,7 +205,6 @@ CLEAN :
-@erase "$(INTDIR)\h2_h2.obj"
-@erase "$(INTDIR)\h2_headers.obj"
-@erase "$(INTDIR)\h2_mplx.obj"
- -@erase "$(INTDIR)\h2_ngn_shed.obj"
-@erase "$(INTDIR)\h2_push.obj"
-@erase "$(INTDIR)\h2_request.obj"
-@erase "$(INTDIR)\h2_session.obj"
@@ -284,7 +281,6 @@ LINK32_OBJS= \
"$(INTDIR)\h2_h2.obj" \
"$(INTDIR)\h2_headers.obj" \
"$(INTDIR)\h2_mplx.obj" \
- "$(INTDIR)\h2_ngn_shed.obj" \
"$(INTDIR)\h2_push.obj" \
"$(INTDIR)\h2_request.obj" \
"$(INTDIR)\h2_session.obj" \
@@ -469,11 +465,6 @@ SOURCE=./h2_mplx.c
"$(INTDIR)\h2_mplx.obj" : $(SOURCE) "$(INTDIR)"
-SOURCE=./h2_ngn_shed.c
-
-"$(INTDIR)\h2_ngn_shed.obj" : $(SOURCE) "$(INTDIR)"
-
-
SOURCE=./h2_push.c
"$(INTDIR)\h2_push.obj" : $(SOURCE) "$(INTDIR)"
Index: httpd-2.4.23/modules/http2/mod_proxy_http2.c
===================================================================
--- httpd-2.4.23.orig/modules/http2/mod_proxy_http2.c 2019-04-02 13:39:34.196793190 +0200
+++ httpd-2.4.23/modules/http2/mod_proxy_http2.c 2019-04-02 13:42:32.653683156 +0200
@@ -15,13 +15,14 @@
#include <nghttp2/nghttp2.h>
+#include <ap_mmn.h>
#include <httpd.h>
#include <mod_proxy.h>
#include "mod_http2.h"
#include "mod_proxy_http2.h"
-#include "h2_request.h"
+#include "h2.h"
#include "h2_proxy_util.h"
#include "h2_version.h"
#include "h2_proxy_session.h"
@@ -45,19 +46,12 @@ AP_DECLARE_MODULE(proxy_http2) = {
/* Optional functions from mod_http2 */
static int (*is_h2)(conn_rec *c);
-static apr_status_t (*req_engine_push)(const char *name, request_rec *r,
- http2_req_engine_init *einit);
-static apr_status_t (*req_engine_pull)(h2_req_engine *engine,
- apr_read_type_e block,
- int capacity,
- request_rec **pr);
-static void (*req_engine_done)(h2_req_engine *engine, conn_rec *r_conn,
- apr_status_t status);
-
+
typedef struct h2_proxy_ctx {
+ const char *id;
+ conn_rec *master;
conn_rec *owner;
apr_pool_t *pool;
- request_rec *rbase;
server_rec *server;
const char *proxy_func;
char server_portstr[32];
@@ -65,19 +59,16 @@ typedef struct h2_proxy_ctx {
proxy_worker *worker;
proxy_server_conf *conf;
- h2_req_engine *engine;
- const char *engine_id;
- const char *engine_type;
- apr_pool_t *engine_pool;
apr_size_t req_buffer_size;
- h2_proxy_fifo *requests;
int capacity;
- unsigned standalone : 1;
unsigned is_ssl : 1;
unsigned flushall : 1;
- apr_status_t r_status; /* status of our first request work */
+ request_rec *r; /* the request processed in this ctx */
+ apr_status_t r_status; /* status of request work */
+ int r_done; /* request was processed, not necessarily successfully */
+ int r_may_retry; /* request may be retried */
h2_proxy_session *session; /* current http2 session against backend */
} h2_proxy_ctx;
@@ -103,16 +94,6 @@ static int h2_proxy_post_config(apr_pool
MOD_HTTP2_VERSION, ngh2? ngh2->version_str : "unknown");
is_h2 = APR_RETRIEVE_OPTIONAL_FN(http2_is_h2);
- req_engine_push = APR_RETRIEVE_OPTIONAL_FN(http2_req_engine_push);
- req_engine_pull = APR_RETRIEVE_OPTIONAL_FN(http2_req_engine_pull);
- req_engine_done = APR_RETRIEVE_OPTIONAL_FN(http2_req_engine_done);
-
- /* we need all of them */
- if (!req_engine_push || !req_engine_pull || !req_engine_done) {
- req_engine_push = NULL;
- req_engine_pull = NULL;
- req_engine_done = NULL;
- }
return status;
}
@@ -203,45 +184,6 @@ static int proxy_http2_canon(request_rec
return OK;
}
-static void out_consumed(void *baton, conn_rec *c, apr_off_t bytes)
-{
- h2_proxy_ctx *ctx = baton;
-
- if (ctx->session) {
- h2_proxy_session_update_window(ctx->session, c, bytes);
- }
-}
-
-static apr_status_t proxy_engine_init(h2_req_engine *engine,
- const char *id,
- const char *type,
- apr_pool_t *pool,
- apr_size_t req_buffer_size,
- request_rec *r,
- http2_output_consumed **pconsumed,
- void **pctx)
-{
- h2_proxy_ctx *ctx = ap_get_module_config(r->connection->conn_config,
- &proxy_http2_module);
- if (!ctx) {
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(03368)
- "h2_proxy_session, engine init, no ctx found");
- return APR_ENOTIMPL;
- }
-
- ctx->pool = pool;
- ctx->engine = engine;
- ctx->engine_id = id;
- ctx->engine_type = type;
- ctx->engine_pool = pool;
- ctx->req_buffer_size = req_buffer_size;
- ctx->capacity = H2MIN(100, h2_proxy_fifo_capacity(ctx->requests));
-
- *pconsumed = out_consumed;
- *pctx = ctx;
- return APR_SUCCESS;
-}
-
static apr_status_t add_request(h2_proxy_session *session, request_rec *r)
{
h2_proxy_ctx *ctx = session->user_data;
@@ -251,7 +193,7 @@ static apr_status_t add_request(h2_proxy
url = apr_table_get(r->notes, H2_PROXY_REQ_URL_NOTE);
apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu",
ctx->p_conn->connection->local_addr->port));
- status = h2_proxy_session_submit(session, url, r, ctx->standalone);
+ status = h2_proxy_session_submit(session, url, r, 1);
if (status != APR_SUCCESS) {
ap_log_cerror(APLOG_MARK, APLOG_ERR, status, r->connection, APLOGNO(03351)
"pass request body failed to %pI (%s) from %s (%s)",
@@ -265,43 +207,15 @@ static apr_status_t add_request(h2_proxy
static void request_done(h2_proxy_ctx *ctx, request_rec *r,
apr_status_t status, int touched)
{
- const char *task_id = apr_table_get(r->connection->notes, H2_TASK_ID_NOTE);
-
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, r->connection,
- "h2_proxy_session(%s): request done %s, touched=%d",
- ctx->engine_id, task_id, touched);
- if (status != APR_SUCCESS) {
- if (!touched) {
- /* untouched request, need rescheduling */
- status = h2_proxy_fifo_push(ctx->requests, r);
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, r->connection,
- APLOGNO(03369)
- "h2_proxy_session(%s): rescheduled request %s",
- ctx->engine_id, task_id);
- return;
- }
- else {
- const char *uri;
- uri = apr_uri_unparse(r->pool, &r->parsed_uri, 0);
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, r->connection,
- APLOGNO(03471) "h2_proxy_session(%s): request %s -> %s "
- "not complete, cannot repeat",
- ctx->engine_id, task_id, uri);
- }
- }
-
- if (r == ctx->rbase) {
+ if (r == ctx->r) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, r->connection,
+ "h2_proxy_session(%s): request done, touched=%d",
+ ctx->id, touched);
+ ctx->r_done = 1;
+ if (touched) ctx->r_may_retry = 0;
ctx->r_status = ((status == APR_SUCCESS)? APR_SUCCESS
: HTTP_SERVICE_UNAVAILABLE);
}
-
- if (req_engine_done && ctx->engine) {
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, r->connection,
- APLOGNO(03370)
- "h2_proxy_session(%s): finished request %s",
- ctx->engine_id, task_id);
- req_engine_done(ctx->engine, r->connection, status);
- }
}
static void session_req_done(h2_proxy_session *session, request_rec *r,
@@ -310,43 +224,15 @@ static void session_req_done(h2_proxy_se
request_done(session->user_data, r, status, touched);
}
-static apr_status_t next_request(h2_proxy_ctx *ctx, int before_leave)
-{
- if (h2_proxy_fifo_count(ctx->requests) > 0) {
- return APR_SUCCESS;
- }
- else if (req_engine_pull && ctx->engine) {
- apr_status_t status;
- request_rec *r = NULL;
-
- status = req_engine_pull(ctx->engine, before_leave?
- APR_BLOCK_READ: APR_NONBLOCK_READ,
- ctx->capacity, &r);
- if (status == APR_SUCCESS && r) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, ctx->owner,
- "h2_proxy_engine(%s): pulled request (%s) %s",
- ctx->engine_id,
- before_leave? "before leave" : "regular",
- r->the_request);
- h2_proxy_fifo_push(ctx->requests, r);
- }
- return APR_STATUS_IS_EAGAIN(status)? APR_SUCCESS : status;
- }
- return APR_EOF;
-}
-
-static apr_status_t proxy_engine_run(h2_proxy_ctx *ctx) {
+static apr_status_t ctx_run(h2_proxy_ctx *ctx) {
apr_status_t status = OK;
int h2_front;
- request_rec *r;
/* Step Four: Send the Request in a new HTTP/2 stream and
* loop until we got the response or encounter errors.
*/
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctx->owner,
- "eng(%s): setup session", ctx->engine_id);
h2_front = is_h2? is_h2(ctx->owner) : 0;
- ctx->session = h2_proxy_session_setup(ctx->engine_id, ctx->p_conn, ctx->conf,
+ ctx->session = h2_proxy_session_setup(ctx->id, ctx->p_conn, ctx->conf,
h2_front, 30,
h2_proxy_log2((int)ctx->req_buffer_size),
session_req_done);
@@ -357,105 +243,45 @@ static apr_status_t proxy_engine_run(h2_
}
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->owner, APLOGNO(03373)
- "eng(%s): run session %s", ctx->engine_id, ctx->session->id);
+ "eng(%s): run session %s", ctx->id, ctx->session->id);
ctx->session->user_data = ctx;
- while (!ctx->owner->aborted) {
- if (APR_SUCCESS == h2_proxy_fifo_try_pull(ctx->requests, (void**)&r)) {
- add_request(ctx->session, r);
- }
-
+ ctx->r_done = 0;
+ add_request(ctx->session, ctx->r);
+
+ while (!ctx->master->aborted && !ctx->r_done) {
+
status = h2_proxy_session_process(ctx->session);
-
- if (status == APR_SUCCESS) {
- apr_status_t s2;
- /* ongoing processing, call again */
- if (ctx->session->remote_max_concurrent > 0
- && ctx->session->remote_max_concurrent != ctx->capacity) {
- ctx->capacity = H2MIN((int)ctx->session->remote_max_concurrent,
- h2_proxy_fifo_capacity(ctx->requests));
- }
- s2 = next_request(ctx, 0);
- if (s2 == APR_ECONNABORTED) {
- /* master connection gone */
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, s2, ctx->owner,
- APLOGNO(03374) "eng(%s): pull request",
- ctx->engine_id);
- /* give notice that we're leaving and cancel all ongoing
- * streams. */
- next_request(ctx, 1);
- h2_proxy_session_cancel_all(ctx->session);
- h2_proxy_session_process(ctx->session);
- status = ctx->r_status = APR_SUCCESS;
- break;
- }
- if ((h2_proxy_fifo_count(ctx->requests) == 0)
- && h2_proxy_ihash_empty(ctx->session->streams)) {
- break;
- }
- }
- else {
- /* end of processing, maybe error */
+ if (status != APR_SUCCESS) {
+ /* Encountered an error during session processing */
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->owner,
APLOGNO(03375) "eng(%s): end of session %s",
- ctx->engine_id, ctx->session->id);
- /*
- * Any open stream of that session needs to
+ ctx->id, ctx->session->id);
+ /* Any open stream of that session needs to
* a) be reopened on the new session iff safe to do so
* b) reported as done (failed) otherwise
*/
h2_proxy_session_cleanup(ctx->session, session_req_done);
- break;
+ goto out;
}
}
- ctx->session->user_data = NULL;
- ctx->session = NULL;
-
- return status;
-}
-
-static apr_status_t push_request_somewhere(h2_proxy_ctx *ctx, request_rec *r)
-{
- conn_rec *c = ctx->owner;
- const char *engine_type, *hostname;
-
- hostname = (ctx->p_conn->ssl_hostname?
- ctx->p_conn->ssl_hostname : ctx->p_conn->hostname);
- engine_type = apr_psprintf(ctx->pool, "proxy_http2 %s%s", hostname,
- ctx->server_portstr);
-
- if (c->master && req_engine_push && r && is_h2 && is_h2(c)) {
- /* If we are have req_engine capabilities, push the handling of this
- * request (e.g. slave connection) to a proxy_http2 engine which
- * uses the same backend. We may be called to create an engine
- * ourself. */
- if (req_engine_push(engine_type, r, proxy_engine_init) == APR_SUCCESS) {
- if (ctx->engine == NULL) {
- /* request has been assigned to an engine in another thread */
- return SUSPENDED;
- }
+out:
+ if (ctx->master->aborted) {
+ /* master connection gone */
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->owner,
+ APLOGNO(03374) "eng(%s): master connection gone", ctx->id);
+ /* cancel all ongoing requests */
+ h2_proxy_session_cancel_all(ctx->session);
+ h2_proxy_session_process(ctx->session);
+ if (!ctx->master->aborted) {
+ status = ctx->r_status = APR_SUCCESS;
}
}
- if (!ctx->engine) {
- /* No engine was available or has been initialized, handle this
- * request just by ourself. */
- ctx->engine_id = apr_psprintf(ctx->pool, "eng-proxy-%ld", c->id);
- ctx->engine_type = engine_type;
- ctx->engine_pool = ctx->pool;
- ctx->req_buffer_size = (32*1024);
- ctx->standalone = 1;
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
- "h2_proxy_http2(%ld): setup standalone engine for type %s",
- c->id, engine_type);
- }
- else {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
- "H2: hosting engine %s", ctx->engine_id);
- }
-
- return h2_proxy_fifo_push(ctx->requests, r);
+ ctx->session->user_data = NULL;
+ ctx->session = NULL;
+ return status;
}
static int proxy_http2_handler(request_rec *r,
@@ -465,7 +291,7 @@ static int proxy_http2_handler(request_r
const char *proxyname,
apr_port_t proxyport)
{
- const char *proxy_func;
+ const char *proxy_func, *task_id;
char *locurl = url, *u;
apr_size_t slen;
int is_ssl = 0;
@@ -497,29 +323,36 @@ static int proxy_http2_handler(request_r
default:
return DECLINED;
}
+
+ task_id = apr_table_get(r->connection->notes, H2_TASK_ID_NOTE);
ctx = apr_pcalloc(r->pool, sizeof(*ctx));
- ctx->owner = r->connection;
- ctx->pool = r->pool;
- ctx->rbase = r;
- ctx->server = r->server;
+ ctx->master = r->connection->master? r->connection->master : r->connection;
+ ctx->id = task_id? task_id : apr_psprintf(r->pool, "%ld", (long)ctx->master->id);
+ ctx->owner = r->connection;
+ ctx->pool = r->pool;
+ ctx->server = r->server;
ctx->proxy_func = proxy_func;
- ctx->is_ssl = is_ssl;
- ctx->worker = worker;
- ctx->conf = conf;
- ctx->flushall = apr_table_get(r->subprocess_env, "proxy-flushall")? 1 : 0;
- ctx->r_status = HTTP_SERVICE_UNAVAILABLE;
-
- h2_proxy_fifo_set_create(&ctx->requests, ctx->pool, 100);
+ ctx->is_ssl = is_ssl;
+ ctx->worker = worker;
+ ctx->conf = conf;
+ ctx->flushall = apr_table_get(r->subprocess_env, "proxy-flushall")? 1 : 0;
+ ctx->req_buffer_size = (32*1024);
+ ctx->r = r;
+ ctx->r_status = status = HTTP_SERVICE_UNAVAILABLE;
+ ctx->r_done = 0;
+ ctx->r_may_retry = 1;
ap_set_module_config(ctx->owner->conn_config, &proxy_http2_module, ctx);
/* scheme says, this is for us. */
- apr_table_setn(ctx->rbase->notes, H2_PROXY_REQ_URL_NOTE, url);
- ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, ctx->rbase,
+ apr_table_setn(ctx->r->notes, H2_PROXY_REQ_URL_NOTE, url);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, ctx->r,
"H2: serving URL %s", url);
run_connect:
+ if (ctx->master->aborted) goto cleanup;
+
/* Get a proxy_conn_rec from the worker, might be a new one, might
* be one still open from another request, or it might fail if the
* worker is stopped or in error. */
@@ -529,25 +362,11 @@ run_connect:
}
ctx->p_conn->is_ssl = ctx->is_ssl;
- if (ctx->is_ssl && ctx->p_conn->connection) {
- /* If there are some metadata on the connection (e.g. TLS alert),
- * let mod_ssl detect them, and create a new connection below.
- */
- apr_bucket_brigade *tmp_bb;
- tmp_bb = apr_brigade_create(ctx->rbase->pool,
- ctx->rbase->connection->bucket_alloc);
- status = ap_get_brigade(ctx->p_conn->connection->input_filters, tmp_bb,
- AP_MODE_SPECULATIVE, APR_NONBLOCK_READ, 1);
- if (status != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(status)) {
- ctx->p_conn->close = 1;
- }
- apr_brigade_cleanup(tmp_bb);
- }
/* Step One: Determine the URL to connect to (might be a proxy),
* initialize the backend accordingly and determine the server
* port string we can expect in responses. */
- if ((status = ap_proxy_determine_connection(ctx->pool, ctx->rbase, conf, worker,
+ if ((status = ap_proxy_determine_connection(ctx->pool, ctx->r, conf, worker,
ctx->p_conn, &uri, &locurl,
proxyname, proxyport,
ctx->server_portstr,
@@ -555,17 +374,6 @@ run_connect:
goto cleanup;
}
- /* If we are not already hosting an engine, try to push the request
- * to an already existing engine or host a new engine here. */
- if (r && !ctx->engine) {
- ctx->r_status = push_request_somewhere(ctx, r);
- r = NULL;
- if (ctx->r_status == SUSPENDED) {
- /* request was pushed to another thread, leave processing here */
- goto cleanup;
- }
- }
-
/* Step Two: Make the Connection (or check that an already existing
* socket is still usable). On success, we have a socket connected to
* backend->hostname. */
@@ -574,70 +382,58 @@ run_connect:
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->owner, APLOGNO(03352)
"H2: failed to make connection to backend: %s",
ctx->p_conn->hostname);
- goto reconnect;
+ goto cleanup;
}
/* Step Three: Create conn_rec for the socket we have open now. */
if (!ctx->p_conn->connection) {
- status = ap_proxy_connection_create_ex(ctx->proxy_func,
- ctx->p_conn, ctx->rbase);
+ status = ap_proxy_connection_create_ex(ctx->proxy_func, ctx->p_conn, ctx->r);
if (status != OK) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->owner, APLOGNO(03353)
"setup new connection: is_ssl=%d %s %s %s",
ctx->p_conn->is_ssl, ctx->p_conn->ssl_hostname,
locurl, ctx->p_conn->hostname);
- goto reconnect;
+ ctx->r_status = status;
+ goto cleanup;
}
- if (!ctx->p_conn->data) {
- /* New conection: set a note on the connection what CN is
- * requested and what protocol we want */
+ if (!ctx->p_conn->data && ctx->is_ssl) {
+ /* New SSL connection: set a note on the connection about what
+ * protocol we want.
+ */
+ apr_table_setn(ctx->p_conn->connection->notes,
+ "proxy-request-alpn-protos", "h2");
if (ctx->p_conn->ssl_hostname) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, ctx->owner,
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctx->owner,
"set SNI to %s for (%s)",
ctx->p_conn->ssl_hostname,
ctx->p_conn->hostname);
apr_table_setn(ctx->p_conn->connection->notes,
"proxy-request-hostname", ctx->p_conn->ssl_hostname);
}
- if (ctx->is_ssl) {
- apr_table_setn(ctx->p_conn->connection->notes,
- "proxy-request-alpn-protos", "h2");
- }
}
}
-run_session:
- status = proxy_engine_run(ctx);
- if (status == APR_SUCCESS) {
- /* session and connection still ok */
- if (next_request(ctx, 1) == APR_SUCCESS) {
- /* more requests, run again */
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->owner, APLOGNO(03376)
- "run_session, again");
- goto run_session;
- }
- /* done */
- ctx->engine = NULL;
- }
+ if (ctx->master->aborted) goto cleanup;
+ status = ctx_run(ctx);
-reconnect:
- if (next_request(ctx, 1) == APR_SUCCESS) {
- /* Still more to do, tear down old conn and start over */
+ if (ctx->r_status != APR_SUCCESS && ctx->r_may_retry && !ctx->master->aborted) {
+ /* Not successfully processed, but may retry, tear down old conn and start over */
if (ctx->p_conn) {
ctx->p_conn->close = 1;
- /*only in trunk so far */
- /*proxy_run_detach_backend(r, ctx->p_conn);*/
+#if AP_MODULE_MAGIC_AT_LEAST(20140207, 2)
+ proxy_run_detach_backend(r, ctx->p_conn);
+#endif
ap_proxy_release_connection(ctx->proxy_func, ctx->p_conn, ctx->server);
ctx->p_conn = NULL;
}
++reconnects;
- if (reconnects < 5 && !ctx->owner->aborted) {
+ if (reconnects < 5) {
goto run_connect;
}
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->owner, APLOGNO(10023)
- "giving up after %d reconnects, %d requests todo",
- reconnects, h2_proxy_fifo_count(ctx->requests));
+ "giving up after %d reconnects, request-done=%d",
+ reconnects, ctx->r_done);
}
cleanup:
@@ -646,17 +442,13 @@ cleanup:
/* close socket when errors happened or session shut down (EOF) */
ctx->p_conn->close = 1;
}
- /*only in trunk so far */
- /*proxy_run_detach_backend(ctx->rbase, ctx->p_conn);*/
+#if AP_MODULE_MAGIC_AT_LEAST(20140207, 2)
+ proxy_run_detach_backend(ctx->r, ctx->p_conn);
+#endif
ap_proxy_release_connection(ctx->proxy_func, ctx->p_conn, ctx->server);
ctx->p_conn = NULL;
}
- /* Any requests will still have need to fail */
- while (APR_SUCCESS == h2_proxy_fifo_try_pull(ctx->requests, (void**)&r)) {
- request_done(ctx, r, HTTP_SERVICE_UNAVAILABLE, 1);
- }
-
ap_set_module_config(ctx->owner->conn_config, &proxy_http2_module, NULL);
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->owner,
APLOGNO(03377) "leaving handler");