summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2023-02-16 11:58:45 +0000
committerStefan Eissing <icing@apache.org>2023-02-16 11:58:45 +0000
commitff6b8026acb8610e4faf10ee345141a3da85946e (patch)
treed6d061d4d73d3b48252be65464a2d024a49c7db2 /modules
parent46fff96dd2b8163c27a6003beb1e0d57a367cbca (diff)
downloadhttpd-ff6b8026acb8610e4faf10ee345141a3da85946e.tar.gz
*) mod_http2: new directive 'H2MaxDataFrameLen n' to limit the maximum
amount of response body bytes put into a single HTTP/2 DATA frame. Setting this to 0 places no limit (but the max size allowed by the protocol is observed). The module, by default, tries to use the maximum size possible, which is somewhat around 16KB. This sets the maximum. When less response data is available, smaller frames will be sent. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1907697 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules')
-rw-r--r--modules/http2/h2_config.c22
-rw-r--r--modules/http2/h2_config.h1
-rw-r--r--modules/http2/h2_session.c9
-rw-r--r--modules/http2/h2_session.h3
-rw-r--r--modules/http2/h2_stream.c5
-rw-r--r--modules/http2/h2_version.h4
6 files changed, 38 insertions, 6 deletions
diff --git a/modules/http2/h2_config.c b/modules/http2/h2_config.c
index eea4be2c59..f6dd1065db 100644
--- a/modules/http2/h2_config.c
+++ b/modules/http2/h2_config.c
@@ -75,6 +75,7 @@ typedef struct h2_config {
int padding_always;
int output_buffered;
apr_interval_time_t stream_timeout;/* beam timeout */
+ int max_data_frame_len; /* max # bytes in a single h2 DATA frame */
} h2_config;
typedef struct h2_dir_config {
@@ -110,6 +111,7 @@ static h2_config defconf = {
1, /* padding always */
1, /* stream output buffered */
-1, /* beam timeout */
+ 0, /* max DATA frame len, 0 == no extra limit */
};
static h2_dir_config defdconf = {
@@ -153,6 +155,7 @@ void *h2_config_create_svr(apr_pool_t *pool, server_rec *s)
conf->padding_always = DEF_VAL;
conf->output_buffered = DEF_VAL;
conf->stream_timeout = DEF_VAL;
+ conf->max_data_frame_len = DEF_VAL;
return conf;
}
@@ -195,6 +198,7 @@ static void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
n->padding_bits = H2_CONFIG_GET(add, base, padding_bits);
n->padding_always = H2_CONFIG_GET(add, base, padding_always);
n->stream_timeout = H2_CONFIG_GET(add, base, stream_timeout);
+ n->max_data_frame_len = H2_CONFIG_GET(add, base, max_data_frame_len);
return n;
}
@@ -278,6 +282,8 @@ static apr_int64_t h2_srv_config_geti64(const h2_config *conf, h2_config_var_t v
return H2_CONFIG_GET(conf, &defconf, output_buffered);
case H2_CONF_STREAM_TIMEOUT:
return H2_CONFIG_GET(conf, &defconf, stream_timeout);
+ case H2_CONF_MAX_DATA_FRAME_LEN:
+ return H2_CONFIG_GET(conf, &defconf, max_data_frame_len);
default:
return DEF_VAL;
}
@@ -337,6 +343,9 @@ static void h2_srv_config_seti(h2_config *conf, h2_config_var_t var, int val)
case H2_CONF_OUTPUT_BUFFER:
H2_CONFIG_SET(conf, output_buffered, val);
break;
+ case H2_CONF_MAX_DATA_FRAME_LEN:
+ H2_CONFIG_SET(conf, max_data_frame_len, val);
+ break;
default:
break;
}
@@ -583,6 +592,17 @@ static const char *h2_conf_set_stream_max_mem_size(cmd_parms *cmd,
return NULL;
}
+static const char *h2_conf_set_max_data_frame_len(cmd_parms *cmd,
+ void *dirconf, const char *value)
+{
+ int val = (int)apr_atoi64(value);
+ if (val < 0) {
+ return "value must be 0 or larger";
+ }
+ CONFIG_CMD_SET(cmd, dirconf, H2_CONF_MAX_DATA_FRAME_LEN, val);
+ return NULL;
+}
+
static const char *h2_conf_set_session_extra_files(cmd_parms *cmd,
void *dirconf, const char *value)
{
@@ -937,6 +957,8 @@ const command_rec h2_cmds[] = {
RSRC_CONF, "set stream output buffer on/off"),
AP_INIT_TAKE1("H2StreamTimeout", h2_conf_set_stream_timeout, NULL,
RSRC_CONF, "set stream timeout"),
+ AP_INIT_TAKE1("H2MaxDataFrameLen", h2_conf_set_max_data_frame_len, NULL,
+ RSRC_CONF, "maximum number of bytes in a single HTTP/2 DATA frame"),
AP_END_CMD
};
diff --git a/modules/http2/h2_config.h b/modules/http2/h2_config.h
index 6d2e65f926..018be64883 100644
--- a/modules/http2/h2_config.h
+++ b/modules/http2/h2_config.h
@@ -43,6 +43,7 @@ typedef enum {
H2_CONF_PADDING_ALWAYS,
H2_CONF_OUTPUT_BUFFER,
H2_CONF_STREAM_TIMEOUT,
+ H2_CONF_MAX_DATA_FRAME_LEN,
} h2_config_var_t;
struct apr_hash_t;
diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c
index 7ba49cf8d5..1d99ae61f2 100644
--- a/modules/http2/h2_session.c
+++ b/modules/http2/h2_session.c
@@ -902,7 +902,8 @@ apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec *
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);
-
+ session->max_data_frame_len = h2_config_sgeti(s, H2_CONF_MAX_DATA_FRAME_LEN);
+
session->out_c1_blocked = h2_iq_create(session->pool, (int)session->max_stream_count);
session->ready_to_process = h2_iq_create(session->pool, (int)session->max_stream_count);
@@ -983,13 +984,15 @@ apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec *
H2_SSSN_LOG(APLOGNO(03200), session,
"created, max_streams=%d, stream_mem=%d, "
"workers_limit=%d, workers_max=%d, "
- "push_diary(type=%d,N=%d)"),
+ "push_diary(type=%d,N=%d), "
+ "max_data_frame_len=%d"),
(int)session->max_stream_count,
(int)session->max_stream_mem,
session->mplx->processing_limit,
session->mplx->processing_max,
session->push_diary->dtype,
- (int)session->push_diary->N);
+ (int)session->push_diary->N,
+ (int)session->max_data_frame_len);
}
apr_pool_pre_cleanup_register(pool, c, session_pool_cleanup);
diff --git a/modules/http2/h2_session.h b/modules/http2/h2_session.h
index fbddfdd2a3..3328509de8 100644
--- a/modules/http2/h2_session.h
+++ b/modules/http2/h2_session.h
@@ -103,7 +103,8 @@ typedef struct h2_session {
apr_size_t max_stream_count; /* max number of open streams */
apr_size_t max_stream_mem; /* max buffer memory for a single stream */
-
+ apr_size_t max_data_frame_len; /* max amount of bytes for a single DATA frame */
+
apr_size_t idle_frames; /* number of rcvd frames that kept session in idle state */
apr_interval_time_t idle_delay; /* Time we delay processing rcvd frames in idle state */
diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c
index cf6f79897d..c514df6499 100644
--- a/modules/http2/h2_stream.c
+++ b/modules/http2/h2_stream.c
@@ -1361,6 +1361,11 @@ static ssize_t stream_data_cb(nghttp2_session *ng2s,
length = chunk_len;
}
}
+ /* We allow configurable max DATA frame length. */
+ if (stream->session->max_data_frame_len > 0
+ && length > stream->session->max_data_frame_len) {
+ length = stream->session->max_data_frame_len;
+ }
/* How much data do we have in our buffers that we can write?
* if not enough, receive more. */
diff --git a/modules/http2/h2_version.h b/modules/http2/h2_version.h
index 0caa800387..380818bbc4 100644
--- a/modules/http2/h2_version.h
+++ b/modules/http2/h2_version.h
@@ -27,7 +27,7 @@
* @macro
* Version number of the http2 module as c string
*/
-#define MOD_HTTP2_VERSION "2.0.12"
+#define MOD_HTTP2_VERSION "2.0.13"
/**
* @macro
@@ -35,7 +35,7 @@
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
-#define MOD_HTTP2_VERSION_NUM 0x02000c
+#define MOD_HTTP2_VERSION_NUM 0x02000d
#endif /* mod_h2_h2_version_h */