Loading CMakeLists.txt +11 −10 Original line number Diff line number Diff line Loading @@ -382,16 +382,17 @@ SET(mod_http2_extra_sources modules/http2/h2_alt_svc.c modules/http2/h2_bucket_eoc.c modules/http2/h2_bucket_eos.c modules/http2/h2_config.c modules/http2/h2_conn.c modules/http2/h2_conn_io.c modules/http2/h2_ctx.c modules/http2/h2_from_h1.c modules/http2/h2_h2.c modules/http2/h2_io.c modules/http2/h2_io_set.c modules/http2/h2_mplx.c modules/http2/h2_push.c modules/http2/h2_request.c modules/http2/h2_response.c modules/http2/h2_session.c modules/http2/h2_stream.c modules/http2/h2_stream_set.c modules/http2/h2_switch.c modules/http2/h2_task.c modules/http2/h2_task_input.c modules/http2/h2_task_output.c modules/http2/h2_task_queue.c modules/http2/h2_util.c modules/http2/h2_worker.c modules/http2/h2_workers.c modules/http2/h2_ctx.c modules/http2/h2_filter.c modules/http2/h2_from_h1.c modules/http2/h2_h2.c modules/http2/h2_io.c modules/http2/h2_io_set.c modules/http2/h2_mplx.c modules/http2/h2_push.c modules/http2/h2_request.c modules/http2/h2_response.c modules/http2/h2_session.c modules/http2/h2_stream.c modules/http2/h2_stream_set.c modules/http2/h2_switch.c modules/http2/h2_task.c modules/http2/h2_task_input.c modules/http2/h2_task_output.c modules/http2/h2_task_queue.c modules/http2/h2_util.c modules/http2/h2_worker.c modules/http2/h2_workers.c ) SET(mod_ldap_extra_defines LDAP_DECLARE_EXPORT) SET(mod_ldap_extra_libs wldap32) Loading docs/manual/mod/mod_http2.xml +158 −2 Original line number Diff line number Diff line Loading @@ -53,6 +53,26 @@ </summary> <section id="envvars"><title>Environment Variables</title> <p>This module can be configured to provide HTTP/2 related information as additional environment variables to the SSI and CGI namespace. </p> <table border="1"> <columnspec><column width=".3"/><column width=".2"/><column width=".5"/> </columnspec> <tr> <th><a name="table3">Variable Name:</a></th> <th>Value Type:</th> <th>Description:</th> </tr> <tr><td><code>HTTPe</code></td> <td>flag</td> <td>HTTP/2 is being used.</td></tr> <tr><td><code>H2PUSH</code></td> <td>flag</td> <td>HTTP/2 Server Push is enabled for this request and also supported by the client.</td></tr> </table> </section> <directivesynopsis> <name>H2Direct</name> <description>H2 Direct Protocol Switch</description> Loading Loading @@ -173,6 +193,43 @@ </usage> </directivesynopsis> <directivesynopsis> <name>H2PushDiarySize</name> <description>H2 Server Push Diary Size</description> <syntax>H2PushDiarySize n</syntax> <default>H2PushDiarySize 256</default> <contextlist> <context>server config</context> <context>virtual host</context> </contextlist> <compatibility>Available in version 2.4.19 and later.</compatibility> <usage> <p> This directive toggles the maximum number of HTTP/2 server pushes that are remembered per HTTP/2 connection. This can be used inside the <directive module="core" type="section">VirtualHost</directive> section to influence the number for all connections to that virtual host. </p> <p> The push diary records a digest (currently using a 64 bit number) of pushed resources (their URL) to avoid duplicate pushes on the same connection. These value are not persisted, so clients openeing a new connection will experience known pushes again. There is ongoing work to enable a client to disclose a digest of the resources it already has, so the diary maybe initialized by the client on each connection setup. </p> <p> If the maximum size is reached, newer entries replace the oldest ones. A diary entry uses 8 bytes, letting a default diary with 256 entries consume around 2 KB of memory. </p> <p> A size of 0 will effectively disable the push diary. </p> </usage> </directivesynopsis> <directivesynopsis> <name>H2PushPriority</name> <description>H2 Server Push Priority</description> Loading Loading @@ -404,7 +461,7 @@ H2PushPriority text/css interleaved # weight 256 default <name>H2WindowSize</name> <description>Size of Stream Window for upstream data.</description> <syntax>H2WindowSize <em>bytes</em></syntax> <default>H2WindowSize 65536</default> <default>H2WindowSize 65535</default> <contextlist> <context>server config</context> <context>virtual host</context> Loading Loading @@ -498,7 +555,6 @@ H2PushPriority text/css interleaved # weight 256 default <name>H2SessionExtraFiles</name> <description>Number of Extra File Handles</description> <syntax>H2SessionExtraFiles <em>n</em></syntax> <default>H2SessionExtraFiles 5</default> <contextlist> <context>server config</context> <context>virtual host</context> Loading Loading @@ -528,6 +584,11 @@ H2PushPriority text/css interleaved # weight 256 default H2SessionExtraFiles 10 </highlight> </example> <p> If nothing is configured, the module tries to make a conservative guess how many files are safe to use. This depends largely on the MPM chosen. </p> </usage> </directivesynopsis> Loading Loading @@ -705,4 +766,99 @@ H2PushPriority text/css interleaved # weight 256 default </usage> </directivesynopsis> <directivesynopsis> <name>H2Timeout</name> <description>Timeout (in seconds) for HTTP/2 connections</description> <syntax>H2Timeout seconds</syntax> <default>H2Timeout 5</default> <contextlist> <context>server config</context> <context>virtual host</context> </contextlist> <compatibility>Available in version 2.4.19 and later.</compatibility> <usage> <p> This directive sets the timeout for read/write operations on connections where HTTP/2 is negotiated. This can be used server wide or for specific <directive module="core" type="section">VirtualHost</directive>s. </p> <p> This directive is similar to the <directive module="core" type="section">Timeout</directive>, but applies only to HTTP/2 connections. </p> <p> A value of 0 enforces no timeout. </p> </usage> </directivesynopsis> <directivesynopsis> <name>H2KeepAliveTimeout</name> <description>Timeout (in seconds) for idle HTTP/2 connections</description> <syntax>H2KeepAliveTimeout seconds</syntax> <contextlist> <context>server config</context> <context>virtual host</context> </contextlist> <compatibility>Available in version 2.4.19 and later.</compatibility> <usage> <p> This directive sets the timeout for read/write operations on idle connections where HTTP/2 is negotiated. This can be used server wide or for specific <directive module="core" type="section">VirtualHost</directive>s. </p> <p> This directive is similar to the <directive module="core" type="section">KeepAliveTimeout</directive>, but applies only to HTTP/2 connections. A HTTP/2 connection is considered idle when no streams are open, e.g. no requests are ongoing. </p> <p> By default, for non-async MPMs (prefork, worker) the keepalive timeout will be the same as H2Timeout. For async MPMs, the keepalive handling for HTTP/1 connections applies as no special action is taken. </p> </usage> </directivesynopsis> <directivesynopsis> <name>H2StreamTimeout</name> <description>Timeout (in seconds) for idle HTTP/2 connections</description> <syntax>H2StreamTimeout seconds</syntax> <default>H2StreamTimeout 0</default> <contextlist> <context>server config</context> <context>virtual host</context> </contextlist> <compatibility>Available in version 2.4.19 and later.</compatibility> <usage> <p> This directive sets the timeout for read/write operations on HTTP/2 streams, e.g. individual requests. This can be used server wide or for specific <directive module="core" type="section">VirtualHost</directive>s. </p> <p> Due to the nature of HTTP/2, which sends multiple requests over a single connection and has priority scheduling, individual streams might not see input for much longer times than HTTP/1.1 requests would. </p> <p> A value of 0 enforces no timeout, so could wait on chances to receive input or write data indefinitely. This expose a server to risks of thread exhaustion. </p> <p> Depending on your handling of pushed streams, priorities and general responsiveness, a site might need to increase this value. For example, if you PUSH a large resource <em>before</em> the requested one, the initial stream will not write until the pushed resource is fully sent. </p> </usage> </directivesynopsis> </modulesynopsis> modules/http2/config.m4 +9 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ h2_config.lo dnl h2_conn.lo dnl h2_conn_io.lo dnl h2_ctx.lo dnl h2_filter.lo dnl h2_from_h1.lo dnl h2_h2.lo dnl h2_io.lo dnl Loading Loading @@ -180,6 +181,11 @@ APACHE_MODULE(http2, [HTTP/2 protocol handling in addition to HTTP protocol handling. Implemented by mod_http2. This module requires a libnghttp2 installation. See --with-nghttp2 on how to manage non-standard locations. This module is usually linked shared and requires loading. ], $http2_objs, , most, [ APACHE_CHECK_OPENSSL if test "$ac_cv_openssl" = "yes" ; then APR_ADDTO(MOD_CPPFLAGS, ["-DH2_OPENSSL"]) fi APACHE_CHECK_NGHTTP2 if test "$ac_cv_nghttp2" = "yes" ; then if test "x$enable_http2" = "xshared"; then Loading @@ -192,6 +198,9 @@ is usually linked shared and requires loading. ], $http2_objs, , most, [ fi ]) # Ensure that other modules can pick up mod_http2.h APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current]) dnl # end of module specific part APACHE_MODPATH_FINISH modules/http2/h2_alt_svc.c +6 −8 Original line number Diff line number Diff line Loading @@ -41,17 +41,18 @@ void h2_alt_svc_register_hooks(void) * - do not percent encode token values * - do not use quotation marks */ h2_alt_svc *h2_alt_svc_parse(const char *s, apr_pool_t *pool) { h2_alt_svc *h2_alt_svc_parse(const char *s, apr_pool_t *pool) { const char *sep = ap_strchr_c(s, '='); if (sep) { const char *alpn = apr_pstrndup(pool, s, sep - s); const char *alpn = apr_pstrmemdup(pool, s, sep - s); const char *host = NULL; int port = 0; s = sep + 1; sep = ap_strchr_c(s, ':'); /* mandatory : */ if (sep) { if (sep != s) { /* optional host */ host = apr_pstrndup(pool, s, sep - s); host = apr_pstrmemdup(pool, s, sep - s); } s = sep + 1; if (*s) { /* must be a port number */ Loading @@ -73,7 +74,6 @@ h2_alt_svc *h2_alt_svc_parse(const char *s, apr_pool_t *pool) { static int h2_alt_svc_handler(request_rec *r) { h2_ctx *ctx; const h2_config *cfg; int i; Loading @@ -82,8 +82,7 @@ static int h2_alt_svc_handler(request_rec *r) return DECLINED; } ctx = h2_ctx_rget(r); if (h2_ctx_is_active(ctx) || h2_ctx_is_task(ctx)) { if (h2_ctx_rget(r)) { return DECLINED; } Loading Loading @@ -122,11 +121,10 @@ static int h2_alt_svc_handler(request_rec *r) } } if (*alt_svc) { apr_table_set(r->headers_out, "Alt-Svc", alt_svc); apr_table_setn(r->headers_out, "Alt-Svc", alt_svc); } } } return DECLINED; } modules/http2/h2_config.c +101 −53 Original line number Diff line number Diff line Loading @@ -59,32 +59,16 @@ static h2_config defconf = { 1, /* TLS cooldown secs */ 1, /* HTTP/2 server push enabled */ NULL, /* map of content-type to priorities */ }; static int files_per_session = 0; -1, /* connection timeout */ -1, /* keepalive timeout */ 0, /* stream timeout */ 256, /* push diary size */ void h2_config_init(apr_pool_t *pool) { /* Determine a good default for this platform and mpm? * TODO: not sure how APR wants to hand out this piece of * information. */ int max_files = 256; int conn_threads = 1; int tx_files = max_files / 4; }; void h2_config_init(apr_pool_t *pool) { (void)pool; ap_mpm_query(AP_MPMQ_MAX_THREADS, &conn_threads); switch (h2_conn_mpm_type()) { case H2_MPM_PREFORK: case H2_MPM_WORKER: case H2_MPM_EVENT: /* allow that many transfer open files per mplx */ files_per_session = (tx_files / conn_threads); break; default: /* don't know anything about it, stay safe */ break; } } static void *h2_config_create(apr_pool_t *pool, Loading @@ -93,11 +77,7 @@ static void *h2_config_create(apr_pool_t *pool, h2_config *conf = (h2_config *)apr_pcalloc(pool, sizeof(h2_config)); const char *s = x? x : "unknown"; char *name = apr_pcalloc(pool, strlen(prefix) + strlen(s) + 20); strcpy(name, prefix); strcat(name, "["); strcat(name, s); strcat(name, "]"); char *name = apr_pstrcat(pool, prefix, "[", s, "]", NULL); conf->name = name; conf->h2_max_streams = DEF_VAL; Loading @@ -116,6 +96,10 @@ static void *h2_config_create(apr_pool_t *pool, conf->tls_cooldown_secs = DEF_VAL; conf->h2_push = DEF_VAL; conf->priorities = NULL; conf->h2_timeout = DEF_VAL; conf->h2_keepalive = DEF_VAL; conf->h2_stream_timeout = DEF_VAL; conf->push_diary_size = DEF_VAL; return conf; } Loading @@ -136,12 +120,7 @@ void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv) h2_config *add = (h2_config *)addv; h2_config *n = (h2_config *)apr_pcalloc(pool, sizeof(h2_config)); char *name = apr_pcalloc(pool, 20 + strlen(add->name) + strlen(base->name)); strcpy(name, "merged["); strcat(name, add->name); strcat(name, ", "); strcat(name, base->name); strcat(name, "]"); char *name = apr_pstrcat(pool, "merged[", add->name, ", ", base->name, "]", NULL); n->name = name; n->h2_max_streams = H2_CONFIG_GET(add, base, h2_max_streams); Loading @@ -166,6 +145,10 @@ void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv) else { n->priorities = add->priorities? add->priorities : base->priorities; } n->h2_timeout = H2_CONFIG_GET(add, base, h2_timeout); n->h2_keepalive = H2_CONFIG_GET(add, base, h2_keepalive); n->h2_stream_timeout = H2_CONFIG_GET(add, base, h2_stream_timeout); n->push_diary_size = H2_CONFIG_GET(add, base, push_diary_size); return n; } Loading @@ -177,7 +160,6 @@ 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) { int n; switch(var) { case H2_CONF_MAX_STREAMS: return H2_CONFIG_GET(conf, &defconf, h2_max_streams); Loading @@ -202,17 +184,21 @@ apr_int64_t h2_config_geti64(const h2_config *conf, h2_config_var_t var) case H2_CONF_DIRECT: return H2_CONFIG_GET(conf, &defconf, h2_direct); case H2_CONF_SESSION_FILES: n = H2_CONFIG_GET(conf, &defconf, session_extra_files); if (n < 0) { n = files_per_session; } return n; return H2_CONFIG_GET(conf, &defconf, session_extra_files); case H2_CONF_TLS_WARMUP_SIZE: return H2_CONFIG_GET(conf, &defconf, tls_warmup_size); case H2_CONF_TLS_COOLDOWN_SECS: return H2_CONFIG_GET(conf, &defconf, tls_cooldown_secs); case H2_CONF_PUSH: return H2_CONFIG_GET(conf, &defconf, h2_push); case H2_CONF_TIMEOUT_SECS: return H2_CONFIG_GET(conf, &defconf, h2_timeout); case H2_CONF_KEEPALIVE_SECS: return H2_CONFIG_GET(conf, &defconf, h2_keepalive); case H2_CONF_STREAM_TIMEOUT_SECS: return H2_CONFIG_GET(conf, &defconf, h2_stream_timeout); case H2_CONF_PUSH_DIARY_SIZE: return H2_CONFIG_GET(conf, &defconf, push_diary_size); default: return DEF_VAL; } Loading Loading @@ -256,7 +242,7 @@ static const char *h2_conf_set_window_size(cmd_parms *parms, cfg->h2_window_size = (int)apr_atoi64(value); (void)arg; if (cfg->h2_window_size < 1024) { return "value must be > 1k"; return "value must be >= 1024"; } return NULL; } Loading @@ -268,7 +254,7 @@ static const char *h2_conf_set_min_workers(cmd_parms *parms, cfg->min_workers = (int)apr_atoi64(value); (void)arg; if (cfg->min_workers < 1) { return "value must be > 1"; return "value must be > 0"; } return NULL; } Loading @@ -280,7 +266,7 @@ static const char *h2_conf_set_max_workers(cmd_parms *parms, cfg->max_workers = (int)apr_atoi64(value); (void)arg; if (cfg->max_workers < 1) { return "value must be > 1"; return "value must be > 0"; } return NULL; } Loading @@ -292,7 +278,7 @@ static const char *h2_conf_set_max_worker_idle_secs(cmd_parms *parms, cfg->max_worker_idle_secs = (int)apr_atoi64(value); (void)arg; if (cfg->max_worker_idle_secs < 1) { return "value must be > 1"; return "value must be > 0"; } return NULL; } Loading @@ -306,7 +292,7 @@ static const char *h2_conf_set_stream_max_mem_size(cmd_parms *parms, cfg->stream_max_mem_size = (int)apr_atoi64(value); (void)arg; if (cfg->stream_max_mem_size < 1024) { return "value must be > 1k"; return "value must be >= 1024"; } return NULL; } Loading Loading @@ -510,6 +496,59 @@ static const char *h2_conf_set_tls_cooldown_secs(cmd_parms *parms, return NULL; } static const char *h2_conf_set_timeout(cmd_parms *parms, void *arg, const char *value) { h2_config *cfg = (h2_config *)h2_config_sget(parms->server); (void)arg; cfg->h2_timeout = (int)apr_atoi64(value); if (cfg->h2_timeout < 0) { return "value must be >= 0"; } return NULL; } static const char *h2_conf_set_keepalive(cmd_parms *parms, void *arg, const char *value) { h2_config *cfg = (h2_config *)h2_config_sget(parms->server); (void)arg; cfg->h2_keepalive = (int)apr_atoi64(value); if (cfg->h2_keepalive < 0) { return "value must be >= 0"; } return NULL; } static const char *h2_conf_set_stream_timeout(cmd_parms *parms, void *arg, const char *value) { h2_config *cfg = (h2_config *)h2_config_sget(parms->server); (void)arg; cfg->h2_stream_timeout = (int)apr_atoi64(value); if (cfg->h2_stream_timeout < 0) { return "value must be >= 0"; } return NULL; } static const char *h2_conf_set_push_diary_size(cmd_parms *parms, void *arg, 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) { return "value must be >= 0"; } if (cfg->push_diary_size > 0 && (cfg->push_diary_size & (cfg->push_diary_size-1))) { return "value must a power of 2"; } if (cfg->push_diary_size > (1 << 15)) { return "value must <= 65536"; } return NULL; } #define AP_END_CMD AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL) Loading Loading @@ -548,6 +587,14 @@ const command_rec h2_cmds[] = { RSRC_CONF, "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("H2Timeout", h2_conf_set_timeout, NULL, RSRC_CONF, "read/write timeout (seconds) for HTTP/2 connections"), AP_INIT_TAKE1("H2KeepAliveTimeout", h2_conf_set_keepalive, NULL, RSRC_CONF, "timeout (seconds) for idle HTTP/2 connections, no streams open"), AP_INIT_TAKE1("H2StreamTimeout", h2_conf_set_stream_timeout, NULL, RSRC_CONF, "read/write timeout (seconds) for HTTP/2 streams"), AP_INIT_TAKE1("H2PushDiarySize", h2_conf_set_push_diary_size, NULL, RSRC_CONF, "size of push diary"), AP_END_CMD }; Loading @@ -561,8 +608,9 @@ const h2_config *h2_config_rget(request_rec *r) const h2_config *h2_config_get(conn_rec *c) { h2_ctx *ctx = h2_ctx_get(c); h2_ctx *ctx = h2_ctx_get(c, 0); if (ctx) { if (ctx->config) { return ctx->config; } Loading @@ -570,7 +618,7 @@ const h2_config *h2_config_get(conn_rec *c) ctx->config = h2_config_sget(ctx->server); return ctx->config; } } return h2_config_sget(c->base_server); } Loading
CMakeLists.txt +11 −10 Original line number Diff line number Diff line Loading @@ -382,16 +382,17 @@ SET(mod_http2_extra_sources modules/http2/h2_alt_svc.c modules/http2/h2_bucket_eoc.c modules/http2/h2_bucket_eos.c modules/http2/h2_config.c modules/http2/h2_conn.c modules/http2/h2_conn_io.c modules/http2/h2_ctx.c modules/http2/h2_from_h1.c modules/http2/h2_h2.c modules/http2/h2_io.c modules/http2/h2_io_set.c modules/http2/h2_mplx.c modules/http2/h2_push.c modules/http2/h2_request.c modules/http2/h2_response.c modules/http2/h2_session.c modules/http2/h2_stream.c modules/http2/h2_stream_set.c modules/http2/h2_switch.c modules/http2/h2_task.c modules/http2/h2_task_input.c modules/http2/h2_task_output.c modules/http2/h2_task_queue.c modules/http2/h2_util.c modules/http2/h2_worker.c modules/http2/h2_workers.c modules/http2/h2_ctx.c modules/http2/h2_filter.c modules/http2/h2_from_h1.c modules/http2/h2_h2.c modules/http2/h2_io.c modules/http2/h2_io_set.c modules/http2/h2_mplx.c modules/http2/h2_push.c modules/http2/h2_request.c modules/http2/h2_response.c modules/http2/h2_session.c modules/http2/h2_stream.c modules/http2/h2_stream_set.c modules/http2/h2_switch.c modules/http2/h2_task.c modules/http2/h2_task_input.c modules/http2/h2_task_output.c modules/http2/h2_task_queue.c modules/http2/h2_util.c modules/http2/h2_worker.c modules/http2/h2_workers.c ) SET(mod_ldap_extra_defines LDAP_DECLARE_EXPORT) SET(mod_ldap_extra_libs wldap32) Loading
docs/manual/mod/mod_http2.xml +158 −2 Original line number Diff line number Diff line Loading @@ -53,6 +53,26 @@ </summary> <section id="envvars"><title>Environment Variables</title> <p>This module can be configured to provide HTTP/2 related information as additional environment variables to the SSI and CGI namespace. </p> <table border="1"> <columnspec><column width=".3"/><column width=".2"/><column width=".5"/> </columnspec> <tr> <th><a name="table3">Variable Name:</a></th> <th>Value Type:</th> <th>Description:</th> </tr> <tr><td><code>HTTPe</code></td> <td>flag</td> <td>HTTP/2 is being used.</td></tr> <tr><td><code>H2PUSH</code></td> <td>flag</td> <td>HTTP/2 Server Push is enabled for this request and also supported by the client.</td></tr> </table> </section> <directivesynopsis> <name>H2Direct</name> <description>H2 Direct Protocol Switch</description> Loading Loading @@ -173,6 +193,43 @@ </usage> </directivesynopsis> <directivesynopsis> <name>H2PushDiarySize</name> <description>H2 Server Push Diary Size</description> <syntax>H2PushDiarySize n</syntax> <default>H2PushDiarySize 256</default> <contextlist> <context>server config</context> <context>virtual host</context> </contextlist> <compatibility>Available in version 2.4.19 and later.</compatibility> <usage> <p> This directive toggles the maximum number of HTTP/2 server pushes that are remembered per HTTP/2 connection. This can be used inside the <directive module="core" type="section">VirtualHost</directive> section to influence the number for all connections to that virtual host. </p> <p> The push diary records a digest (currently using a 64 bit number) of pushed resources (their URL) to avoid duplicate pushes on the same connection. These value are not persisted, so clients openeing a new connection will experience known pushes again. There is ongoing work to enable a client to disclose a digest of the resources it already has, so the diary maybe initialized by the client on each connection setup. </p> <p> If the maximum size is reached, newer entries replace the oldest ones. A diary entry uses 8 bytes, letting a default diary with 256 entries consume around 2 KB of memory. </p> <p> A size of 0 will effectively disable the push diary. </p> </usage> </directivesynopsis> <directivesynopsis> <name>H2PushPriority</name> <description>H2 Server Push Priority</description> Loading Loading @@ -404,7 +461,7 @@ H2PushPriority text/css interleaved # weight 256 default <name>H2WindowSize</name> <description>Size of Stream Window for upstream data.</description> <syntax>H2WindowSize <em>bytes</em></syntax> <default>H2WindowSize 65536</default> <default>H2WindowSize 65535</default> <contextlist> <context>server config</context> <context>virtual host</context> Loading Loading @@ -498,7 +555,6 @@ H2PushPriority text/css interleaved # weight 256 default <name>H2SessionExtraFiles</name> <description>Number of Extra File Handles</description> <syntax>H2SessionExtraFiles <em>n</em></syntax> <default>H2SessionExtraFiles 5</default> <contextlist> <context>server config</context> <context>virtual host</context> Loading Loading @@ -528,6 +584,11 @@ H2PushPriority text/css interleaved # weight 256 default H2SessionExtraFiles 10 </highlight> </example> <p> If nothing is configured, the module tries to make a conservative guess how many files are safe to use. This depends largely on the MPM chosen. </p> </usage> </directivesynopsis> Loading Loading @@ -705,4 +766,99 @@ H2PushPriority text/css interleaved # weight 256 default </usage> </directivesynopsis> <directivesynopsis> <name>H2Timeout</name> <description>Timeout (in seconds) for HTTP/2 connections</description> <syntax>H2Timeout seconds</syntax> <default>H2Timeout 5</default> <contextlist> <context>server config</context> <context>virtual host</context> </contextlist> <compatibility>Available in version 2.4.19 and later.</compatibility> <usage> <p> This directive sets the timeout for read/write operations on connections where HTTP/2 is negotiated. This can be used server wide or for specific <directive module="core" type="section">VirtualHost</directive>s. </p> <p> This directive is similar to the <directive module="core" type="section">Timeout</directive>, but applies only to HTTP/2 connections. </p> <p> A value of 0 enforces no timeout. </p> </usage> </directivesynopsis> <directivesynopsis> <name>H2KeepAliveTimeout</name> <description>Timeout (in seconds) for idle HTTP/2 connections</description> <syntax>H2KeepAliveTimeout seconds</syntax> <contextlist> <context>server config</context> <context>virtual host</context> </contextlist> <compatibility>Available in version 2.4.19 and later.</compatibility> <usage> <p> This directive sets the timeout for read/write operations on idle connections where HTTP/2 is negotiated. This can be used server wide or for specific <directive module="core" type="section">VirtualHost</directive>s. </p> <p> This directive is similar to the <directive module="core" type="section">KeepAliveTimeout</directive>, but applies only to HTTP/2 connections. A HTTP/2 connection is considered idle when no streams are open, e.g. no requests are ongoing. </p> <p> By default, for non-async MPMs (prefork, worker) the keepalive timeout will be the same as H2Timeout. For async MPMs, the keepalive handling for HTTP/1 connections applies as no special action is taken. </p> </usage> </directivesynopsis> <directivesynopsis> <name>H2StreamTimeout</name> <description>Timeout (in seconds) for idle HTTP/2 connections</description> <syntax>H2StreamTimeout seconds</syntax> <default>H2StreamTimeout 0</default> <contextlist> <context>server config</context> <context>virtual host</context> </contextlist> <compatibility>Available in version 2.4.19 and later.</compatibility> <usage> <p> This directive sets the timeout for read/write operations on HTTP/2 streams, e.g. individual requests. This can be used server wide or for specific <directive module="core" type="section">VirtualHost</directive>s. </p> <p> Due to the nature of HTTP/2, which sends multiple requests over a single connection and has priority scheduling, individual streams might not see input for much longer times than HTTP/1.1 requests would. </p> <p> A value of 0 enforces no timeout, so could wait on chances to receive input or write data indefinitely. This expose a server to risks of thread exhaustion. </p> <p> Depending on your handling of pushed streams, priorities and general responsiveness, a site might need to increase this value. For example, if you PUSH a large resource <em>before</em> the requested one, the initial stream will not write until the pushed resource is fully sent. </p> </usage> </directivesynopsis> </modulesynopsis>
modules/http2/config.m4 +9 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ h2_config.lo dnl h2_conn.lo dnl h2_conn_io.lo dnl h2_ctx.lo dnl h2_filter.lo dnl h2_from_h1.lo dnl h2_h2.lo dnl h2_io.lo dnl Loading Loading @@ -180,6 +181,11 @@ APACHE_MODULE(http2, [HTTP/2 protocol handling in addition to HTTP protocol handling. Implemented by mod_http2. This module requires a libnghttp2 installation. See --with-nghttp2 on how to manage non-standard locations. This module is usually linked shared and requires loading. ], $http2_objs, , most, [ APACHE_CHECK_OPENSSL if test "$ac_cv_openssl" = "yes" ; then APR_ADDTO(MOD_CPPFLAGS, ["-DH2_OPENSSL"]) fi APACHE_CHECK_NGHTTP2 if test "$ac_cv_nghttp2" = "yes" ; then if test "x$enable_http2" = "xshared"; then Loading @@ -192,6 +198,9 @@ is usually linked shared and requires loading. ], $http2_objs, , most, [ fi ]) # Ensure that other modules can pick up mod_http2.h APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current]) dnl # end of module specific part APACHE_MODPATH_FINISH
modules/http2/h2_alt_svc.c +6 −8 Original line number Diff line number Diff line Loading @@ -41,17 +41,18 @@ void h2_alt_svc_register_hooks(void) * - do not percent encode token values * - do not use quotation marks */ h2_alt_svc *h2_alt_svc_parse(const char *s, apr_pool_t *pool) { h2_alt_svc *h2_alt_svc_parse(const char *s, apr_pool_t *pool) { const char *sep = ap_strchr_c(s, '='); if (sep) { const char *alpn = apr_pstrndup(pool, s, sep - s); const char *alpn = apr_pstrmemdup(pool, s, sep - s); const char *host = NULL; int port = 0; s = sep + 1; sep = ap_strchr_c(s, ':'); /* mandatory : */ if (sep) { if (sep != s) { /* optional host */ host = apr_pstrndup(pool, s, sep - s); host = apr_pstrmemdup(pool, s, sep - s); } s = sep + 1; if (*s) { /* must be a port number */ Loading @@ -73,7 +74,6 @@ h2_alt_svc *h2_alt_svc_parse(const char *s, apr_pool_t *pool) { static int h2_alt_svc_handler(request_rec *r) { h2_ctx *ctx; const h2_config *cfg; int i; Loading @@ -82,8 +82,7 @@ static int h2_alt_svc_handler(request_rec *r) return DECLINED; } ctx = h2_ctx_rget(r); if (h2_ctx_is_active(ctx) || h2_ctx_is_task(ctx)) { if (h2_ctx_rget(r)) { return DECLINED; } Loading Loading @@ -122,11 +121,10 @@ static int h2_alt_svc_handler(request_rec *r) } } if (*alt_svc) { apr_table_set(r->headers_out, "Alt-Svc", alt_svc); apr_table_setn(r->headers_out, "Alt-Svc", alt_svc); } } } return DECLINED; }
modules/http2/h2_config.c +101 −53 Original line number Diff line number Diff line Loading @@ -59,32 +59,16 @@ static h2_config defconf = { 1, /* TLS cooldown secs */ 1, /* HTTP/2 server push enabled */ NULL, /* map of content-type to priorities */ }; static int files_per_session = 0; -1, /* connection timeout */ -1, /* keepalive timeout */ 0, /* stream timeout */ 256, /* push diary size */ void h2_config_init(apr_pool_t *pool) { /* Determine a good default for this platform and mpm? * TODO: not sure how APR wants to hand out this piece of * information. */ int max_files = 256; int conn_threads = 1; int tx_files = max_files / 4; }; void h2_config_init(apr_pool_t *pool) { (void)pool; ap_mpm_query(AP_MPMQ_MAX_THREADS, &conn_threads); switch (h2_conn_mpm_type()) { case H2_MPM_PREFORK: case H2_MPM_WORKER: case H2_MPM_EVENT: /* allow that many transfer open files per mplx */ files_per_session = (tx_files / conn_threads); break; default: /* don't know anything about it, stay safe */ break; } } static void *h2_config_create(apr_pool_t *pool, Loading @@ -93,11 +77,7 @@ static void *h2_config_create(apr_pool_t *pool, h2_config *conf = (h2_config *)apr_pcalloc(pool, sizeof(h2_config)); const char *s = x? x : "unknown"; char *name = apr_pcalloc(pool, strlen(prefix) + strlen(s) + 20); strcpy(name, prefix); strcat(name, "["); strcat(name, s); strcat(name, "]"); char *name = apr_pstrcat(pool, prefix, "[", s, "]", NULL); conf->name = name; conf->h2_max_streams = DEF_VAL; Loading @@ -116,6 +96,10 @@ static void *h2_config_create(apr_pool_t *pool, conf->tls_cooldown_secs = DEF_VAL; conf->h2_push = DEF_VAL; conf->priorities = NULL; conf->h2_timeout = DEF_VAL; conf->h2_keepalive = DEF_VAL; conf->h2_stream_timeout = DEF_VAL; conf->push_diary_size = DEF_VAL; return conf; } Loading @@ -136,12 +120,7 @@ void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv) h2_config *add = (h2_config *)addv; h2_config *n = (h2_config *)apr_pcalloc(pool, sizeof(h2_config)); char *name = apr_pcalloc(pool, 20 + strlen(add->name) + strlen(base->name)); strcpy(name, "merged["); strcat(name, add->name); strcat(name, ", "); strcat(name, base->name); strcat(name, "]"); char *name = apr_pstrcat(pool, "merged[", add->name, ", ", base->name, "]", NULL); n->name = name; n->h2_max_streams = H2_CONFIG_GET(add, base, h2_max_streams); Loading @@ -166,6 +145,10 @@ void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv) else { n->priorities = add->priorities? add->priorities : base->priorities; } n->h2_timeout = H2_CONFIG_GET(add, base, h2_timeout); n->h2_keepalive = H2_CONFIG_GET(add, base, h2_keepalive); n->h2_stream_timeout = H2_CONFIG_GET(add, base, h2_stream_timeout); n->push_diary_size = H2_CONFIG_GET(add, base, push_diary_size); return n; } Loading @@ -177,7 +160,6 @@ 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) { int n; switch(var) { case H2_CONF_MAX_STREAMS: return H2_CONFIG_GET(conf, &defconf, h2_max_streams); Loading @@ -202,17 +184,21 @@ apr_int64_t h2_config_geti64(const h2_config *conf, h2_config_var_t var) case H2_CONF_DIRECT: return H2_CONFIG_GET(conf, &defconf, h2_direct); case H2_CONF_SESSION_FILES: n = H2_CONFIG_GET(conf, &defconf, session_extra_files); if (n < 0) { n = files_per_session; } return n; return H2_CONFIG_GET(conf, &defconf, session_extra_files); case H2_CONF_TLS_WARMUP_SIZE: return H2_CONFIG_GET(conf, &defconf, tls_warmup_size); case H2_CONF_TLS_COOLDOWN_SECS: return H2_CONFIG_GET(conf, &defconf, tls_cooldown_secs); case H2_CONF_PUSH: return H2_CONFIG_GET(conf, &defconf, h2_push); case H2_CONF_TIMEOUT_SECS: return H2_CONFIG_GET(conf, &defconf, h2_timeout); case H2_CONF_KEEPALIVE_SECS: return H2_CONFIG_GET(conf, &defconf, h2_keepalive); case H2_CONF_STREAM_TIMEOUT_SECS: return H2_CONFIG_GET(conf, &defconf, h2_stream_timeout); case H2_CONF_PUSH_DIARY_SIZE: return H2_CONFIG_GET(conf, &defconf, push_diary_size); default: return DEF_VAL; } Loading Loading @@ -256,7 +242,7 @@ static const char *h2_conf_set_window_size(cmd_parms *parms, cfg->h2_window_size = (int)apr_atoi64(value); (void)arg; if (cfg->h2_window_size < 1024) { return "value must be > 1k"; return "value must be >= 1024"; } return NULL; } Loading @@ -268,7 +254,7 @@ static const char *h2_conf_set_min_workers(cmd_parms *parms, cfg->min_workers = (int)apr_atoi64(value); (void)arg; if (cfg->min_workers < 1) { return "value must be > 1"; return "value must be > 0"; } return NULL; } Loading @@ -280,7 +266,7 @@ static const char *h2_conf_set_max_workers(cmd_parms *parms, cfg->max_workers = (int)apr_atoi64(value); (void)arg; if (cfg->max_workers < 1) { return "value must be > 1"; return "value must be > 0"; } return NULL; } Loading @@ -292,7 +278,7 @@ static const char *h2_conf_set_max_worker_idle_secs(cmd_parms *parms, cfg->max_worker_idle_secs = (int)apr_atoi64(value); (void)arg; if (cfg->max_worker_idle_secs < 1) { return "value must be > 1"; return "value must be > 0"; } return NULL; } Loading @@ -306,7 +292,7 @@ static const char *h2_conf_set_stream_max_mem_size(cmd_parms *parms, cfg->stream_max_mem_size = (int)apr_atoi64(value); (void)arg; if (cfg->stream_max_mem_size < 1024) { return "value must be > 1k"; return "value must be >= 1024"; } return NULL; } Loading Loading @@ -510,6 +496,59 @@ static const char *h2_conf_set_tls_cooldown_secs(cmd_parms *parms, return NULL; } static const char *h2_conf_set_timeout(cmd_parms *parms, void *arg, const char *value) { h2_config *cfg = (h2_config *)h2_config_sget(parms->server); (void)arg; cfg->h2_timeout = (int)apr_atoi64(value); if (cfg->h2_timeout < 0) { return "value must be >= 0"; } return NULL; } static const char *h2_conf_set_keepalive(cmd_parms *parms, void *arg, const char *value) { h2_config *cfg = (h2_config *)h2_config_sget(parms->server); (void)arg; cfg->h2_keepalive = (int)apr_atoi64(value); if (cfg->h2_keepalive < 0) { return "value must be >= 0"; } return NULL; } static const char *h2_conf_set_stream_timeout(cmd_parms *parms, void *arg, const char *value) { h2_config *cfg = (h2_config *)h2_config_sget(parms->server); (void)arg; cfg->h2_stream_timeout = (int)apr_atoi64(value); if (cfg->h2_stream_timeout < 0) { return "value must be >= 0"; } return NULL; } static const char *h2_conf_set_push_diary_size(cmd_parms *parms, void *arg, 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) { return "value must be >= 0"; } if (cfg->push_diary_size > 0 && (cfg->push_diary_size & (cfg->push_diary_size-1))) { return "value must a power of 2"; } if (cfg->push_diary_size > (1 << 15)) { return "value must <= 65536"; } return NULL; } #define AP_END_CMD AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL) Loading Loading @@ -548,6 +587,14 @@ const command_rec h2_cmds[] = { RSRC_CONF, "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("H2Timeout", h2_conf_set_timeout, NULL, RSRC_CONF, "read/write timeout (seconds) for HTTP/2 connections"), AP_INIT_TAKE1("H2KeepAliveTimeout", h2_conf_set_keepalive, NULL, RSRC_CONF, "timeout (seconds) for idle HTTP/2 connections, no streams open"), AP_INIT_TAKE1("H2StreamTimeout", h2_conf_set_stream_timeout, NULL, RSRC_CONF, "read/write timeout (seconds) for HTTP/2 streams"), AP_INIT_TAKE1("H2PushDiarySize", h2_conf_set_push_diary_size, NULL, RSRC_CONF, "size of push diary"), AP_END_CMD }; Loading @@ -561,8 +608,9 @@ const h2_config *h2_config_rget(request_rec *r) const h2_config *h2_config_get(conn_rec *c) { h2_ctx *ctx = h2_ctx_get(c); h2_ctx *ctx = h2_ctx_get(c, 0); if (ctx) { if (ctx->config) { return ctx->config; } Loading @@ -570,7 +618,7 @@ const h2_config *h2_config_get(conn_rec *c) ctx->config = h2_config_sget(ctx->server); return ctx->config; } } return h2_config_sget(c->base_server); }