diff options
author | Stefan Eissing <icing@apache.org> | 2021-02-22 15:11:09 +0100 |
---|---|---|
committer | Stefan Eissing <icing@apache.org> | 2021-02-22 15:11:09 +0100 |
commit | 309e0838934e8a1f94fca24a7a3881f5bc5a3af0 (patch) | |
tree | 3a36b5551b91e75d37730e764f9ff229d5c5f8a3 /modules/http2 | |
parent | mod_http2: Fix workers synchronization on pchild cleanup. (diff) | |
download | apache2-309e0838934e8a1f94fca24a7a3881f5bc5a3af0.tar.xz apache2-309e0838934e8a1f94fca24a7a3881f5bc5a3af0.zip |
mod_htt2, synch with changes from github module version:
- logio: improvements to reporting of sent bytes for http2 responses
- directive H2OutputBuffering, controls if any output should be sent immediately.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1886792 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/http2')
-rw-r--r-- | modules/http2/h2_bucket_beam.c | 1 | ||||
-rw-r--r-- | modules/http2/h2_config.c | 24 | ||||
-rw-r--r-- | modules/http2/h2_config.h | 1 | ||||
-rw-r--r-- | modules/http2/h2_h2.c | 1 | ||||
-rw-r--r-- | modules/http2/h2_headers.c | 15 | ||||
-rw-r--r-- | modules/http2/h2_headers.h | 5 | ||||
-rw-r--r-- | modules/http2/h2_mplx.c | 17 | ||||
-rw-r--r-- | modules/http2/h2_request.c | 58 | ||||
-rw-r--r-- | modules/http2/h2_stream.h | 3 | ||||
-rw-r--r-- | modules/http2/h2_task.c | 18 | ||||
-rw-r--r-- | modules/http2/h2_task.h | 1 | ||||
-rw-r--r-- | modules/http2/h2_version.h | 5 |
12 files changed, 121 insertions, 28 deletions
diff --git a/modules/http2/h2_bucket_beam.c b/modules/http2/h2_bucket_beam.c index 607ac1e382..b857afcddc 100644 --- a/modules/http2/h2_bucket_beam.c +++ b/modules/http2/h2_bucket_beam.c @@ -1042,6 +1042,7 @@ transfer: H2_BLIST_INSERT_TAIL(&beam->hold_list, bsender); remain -= bsender->length; + beam->received_bytes += bsender->length; ++transferred; ++transferred_buckets; continue; diff --git a/modules/http2/h2_config.c b/modules/http2/h2_config.c index 53415024b5..06368fd53b 100644 --- a/modules/http2/h2_config.c +++ b/modules/http2/h2_config.c @@ -78,6 +78,7 @@ typedef struct h2_config { int early_hints; /* support status code 103 */ int padding_bits; int padding_always; + int output_buffered; } h2_config; typedef struct h2_dir_config { @@ -115,6 +116,7 @@ static h2_config defconf = { 0, /* early hints, http status 103 */ 0, /* padding bits */ 1, /* padding always */ + 1, /* strean output buffered */ }; static h2_dir_config defdconf = { @@ -159,6 +161,7 @@ void *h2_config_create_svr(apr_pool_t *pool, server_rec *s) conf->early_hints = DEF_VAL; conf->padding_bits = DEF_VAL; conf->padding_always = DEF_VAL; + conf->output_buffered = DEF_VAL; return conf; } @@ -193,6 +196,7 @@ static void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv) } n->push_diary_size = H2_CONFIG_GET(add, base, push_diary_size); n->copy_files = H2_CONFIG_GET(add, base, copy_files); + n->output_buffered = H2_CONFIG_GET(add, base, output_buffered); if (add->push_list && base->push_list) { n->push_list = apr_array_append(pool, base->push_list, add->push_list); } @@ -286,6 +290,8 @@ static apr_int64_t h2_srv_config_geti64(const h2_config *conf, h2_config_var_t v return H2_CONFIG_GET(conf, &defconf, padding_bits); case H2_CONF_PADDING_ALWAYS: return H2_CONFIG_GET(conf, &defconf, padding_always); + case H2_CONF_OUTPUT_BUFFER: + return H2_CONFIG_GET(conf, &defconf, output_buffered); default: return DEF_VAL; } @@ -351,6 +357,9 @@ static void h2_srv_config_seti(h2_config *conf, h2_config_var_t var, int val) case H2_CONF_PADDING_ALWAYS: H2_CONFIG_SET(conf, padding_always, val); break; + case H2_CONF_OUTPUT_BUFFER: + H2_CONFIG_SET(conf, output_buffered, val); + break; default: break; } @@ -905,6 +914,19 @@ static const char *h2_conf_set_padding(cmd_parms *cmd, void *dirconf, const char return NULL; } +static const char *h2_conf_set_output_buffer(cmd_parms *cmd, + void *dirconf, const char *value) +{ + if (!strcasecmp(value, "On")) { + CONFIG_CMD_SET(cmd, dirconf, H2_CONF_OUTPUT_BUFFER, 1); + return NULL; + } + else if (!strcasecmp(value, "Off")) { + CONFIG_CMD_SET(cmd, dirconf, H2_CONF_OUTPUT_BUFFER, 0); + return NULL; + } + return "value must be On or Off"; +} void h2_get_num_workers(server_rec *s, int *minw, int *maxw) { @@ -976,6 +998,8 @@ const command_rec h2_cmds[] = { RSRC_CONF, "on to enable interim status 103 responses"), AP_INIT_TAKE1("H2Padding", h2_conf_set_padding, NULL, RSRC_CONF, "set payload padding"), + AP_INIT_TAKE1("H2OutputBuffering", h2_conf_set_output_buffer, NULL, + RSRC_CONF, "set stream output buffer on/off"), AP_END_CMD }; diff --git a/modules/http2/h2_config.h b/modules/http2/h2_config.h index e940c8a715..7d7d8aa897 100644 --- a/modules/http2/h2_config.h +++ b/modules/http2/h2_config.h @@ -44,6 +44,7 @@ typedef enum { H2_CONF_EARLY_HINTS, H2_CONF_PADDING_BITS, H2_CONF_PADDING_ALWAYS, + H2_CONF_OUTPUT_BUFFER, } h2_config_var_t; struct apr_hash_t; diff --git a/modules/http2/h2_h2.c b/modules/http2/h2_h2.c index a934a63f75..2256842d05 100644 --- a/modules/http2/h2_h2.c +++ b/modules/http2/h2_h2.c @@ -749,6 +749,7 @@ static int h2_h2_late_fixups(request_rec *r) if (task) { /* check if we copy vs. setaside files in this location */ task->output.copy_files = h2_config_rgeti(r, H2_CONF_COPY_FILES); + task->output.buffered = h2_config_rgeti(r, H2_CONF_OUTPUT_BUFFER); if (task->output.copy_files) { ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c, "h2_secondary_out(%s): copy_files on", task->id); diff --git a/modules/http2/h2_headers.c b/modules/http2/h2_headers.c index 1ef89d9f73..271b1f1c61 100644 --- a/modules/http2/h2_headers.c +++ b/modules/http2/h2_headers.c @@ -64,6 +64,7 @@ apr_bucket * h2_bucket_headers_make(apr_bucket *b, h2_headers *r) b = apr_bucket_shared_make(b, br, 0, 0); b->type = &h2_bucket_type_headers; + b->length = h2_headers_length(r); return b; } @@ -125,6 +126,20 @@ h2_headers *h2_headers_create(int status, apr_table_t *headers_in, return headers; } +static int add_header_lengths(void *ctx, const char *name, const char *value) +{ + apr_size_t *plen = ctx; + *plen += strlen(name) + strlen(value); + return 1; +} + +apr_size_t h2_headers_length(h2_headers *headers) +{ + apr_size_t len = 0; + apr_table_do(add_header_lengths, &len, headers->headers, NULL); + return len; +} + h2_headers *h2_headers_rcreate(request_rec *r, int status, apr_table_t *header, apr_pool_t *pool) { diff --git a/modules/http2/h2_headers.h b/modules/http2/h2_headers.h index 46bbab9c3f..3f6ecd07ae 100644 --- a/modules/http2/h2_headers.h +++ b/modules/http2/h2_headers.h @@ -81,4 +81,9 @@ h2_headers *h2_headers_die(apr_status_t type, int h2_headers_are_response(h2_headers *headers); +/** + * Give the number of bytes of all contained header strings. + */ +apr_size_t h2_headers_length(h2_headers *headers); + #endif /* defined(__mod_h2__h2_headers__) */ diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c index 4f8219f425..d787e0d09d 100644 --- a/modules/http2/h2_mplx.c +++ b/modules/http2/h2_mplx.c @@ -91,10 +91,6 @@ apr_status_t h2_mplx_m_child_init(apr_pool_t *pool, server_rec *s) static void mst_check_data_for(h2_mplx *m, h2_stream *stream, int mplx_is_locked); -static void mst_stream_output_consumed(void *ctx, h2_bucket_beam *beam, apr_off_t length) -{ -} - static void mst_stream_input_ev(void *ctx, h2_bucket_beam *beam) { h2_stream *stream = ctx; @@ -299,18 +295,6 @@ static int m_stream_destroy_iter(void *ctx, void *val) stream->task = NULL; secondary = task->c; if (secondary) { - /* On non-serialized requests, the IO logging has not accounted for any - * meta data send over the network: response headers and h2 frame headers. we - * counted this on the stream and need to add this now. - * This is supposed to happen before the EOR bucket triggers the - * logging of the transaction. *fingers crossed* */ - if (task->request && !task->request->serialize && h2_task_logio_add_bytes_out) { - apr_off_t unaccounted = stream->out_frame_octets - stream->out_data_octets; - if (unaccounted > 0) { - h2_task_logio_add_bytes_out(secondary, unaccounted); - } - } - if (m->s->keep_alive_max == 0 || secondary->keepalives < m->s->keep_alive_max) { reuse_secondary = ((m->spare_secondary->nelts < (m->limit_active * 3 / 2)) && !task->rst_error); @@ -540,7 +524,6 @@ static apr_status_t t_out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam) "h2_mplx(%s): out open", stream->task->id); } - h2_beam_on_consumed(stream->output, NULL, mst_stream_output_consumed, stream); h2_beam_on_produced(stream->output, mst_output_produced, stream); if (stream->task->output.copy_files) { h2_beam_on_file_beam(stream->output, h2_beam_no_files, NULL); diff --git a/modules/http2/h2_request.c b/modules/http2/h2_request.c index 485b29aac3..45df9b153e 100644 --- a/modules/http2/h2_request.c +++ b/modules/http2/h2_request.c @@ -278,11 +278,12 @@ request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c) request_rec *r = my_ap_create_request(c); #endif +#if AP_MODULE_MAGIC_AT_LEAST(20200331, 3) ap_run_pre_read_request(r, c); - + /* Time to populate r with the data we have. */ r->request_time = req->request_time; - r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0", + r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0", req->method, req->path ? req->path : ""); r->headers_in = apr_table_clone(r->pool, req->headers); @@ -306,7 +307,50 @@ request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c) r->status = HTTP_OK; goto die; } - +#else + { + const char *s; + + 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 = 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') { + r->header_only = 1; + } + ap_parse_uri(r, req->path ? req->path : ""); + r->protocol = (char*)"HTTP/2.0"; + r->proto_num = HTTP_VERSION(2, 0); + r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0", + r->method, req->path ? req->path : ""); + + /* Start with r->hostname = NULL, ap_check_request_header() will get it + * form Host: header, otherwise we get complains about port numbers. + */ + r->hostname = NULL; + ap_update_vhost_from_headers(r); + + /* we may have switched to another server */ + r->per_dir_config = r->server->lookup_defaults; + + s = apr_table_get(r->headers_in, "Expect"); + if (s && s[0]) { + if (ap_cstr_casecmp(s, "100-continue") == 0) { + r->expecting_100 = 1; + } + else { + r->status = HTTP_EXPECTATION_FAILED; + access_status = r->status; + goto die; + } + } + } +#endif + /* we may have switched to another server */ r->per_dir_config = r->server->lookup_defaults; @@ -350,11 +394,19 @@ die: */ { apr_bucket_brigade *eor_bb; +#if AP_MODULE_MAGIC_AT_LEAST(20180905, 1) eor_bb = ap_acquire_brigade(c); APR_BRIGADE_INSERT_TAIL(eor_bb, ap_bucket_eor_create(c->bucket_alloc, r)); ap_pass_brigade(c->output_filters, eor_bb); ap_release_brigade(c, eor_bb); +#else + eor_bb = apr_brigade_create(c->pool, c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(eor_bb, + ap_bucket_eor_create(c->bucket_alloc, r)); + ap_pass_brigade(c->output_filters, eor_bb); + apr_brigade_destroy(eor_bb); +#endif } r = NULL; diff --git a/modules/http2/h2_stream.h b/modules/http2/h2_stream.h index 9761ed7411..08f7888fe4 100644 --- a/modules/http2/h2_stream.h +++ b/modules/http2/h2_stream.h @@ -92,7 +92,8 @@ struct h2_stream { unsigned int input_eof : 1; /* no more request data coming */ unsigned int out_checked : 1; /* output eof was double checked */ unsigned int push_policy; /* which push policy to use for this request */ - + unsigned int input_buffering : 1; /* buffer request bodies for efficiency */ + struct h2_task *task; /* assigned task to fullfill request */ const h2_priority *pref_priority; /* preferred priority for this stream */ diff --git a/modules/http2/h2_task.c b/modules/http2/h2_task.c index 0581a30f2a..4edaf92cda 100644 --- a/modules/http2/h2_task.c +++ b/modules/http2/h2_task.c @@ -89,6 +89,14 @@ static apr_status_t open_output(h2_task *task) return h2_mplx_t_out_open(task->mplx, task->stream_id, task->output.beam); } +static void output_consumed(void *ctx, h2_bucket_beam *beam, apr_off_t length) +{ + h2_task *task = ctx; + if (task && h2_task_logio_add_bytes_out) { + h2_task_logio_add_bytes_out(task->c, length); + } +} + static apr_status_t send_out(h2_task *task, apr_bucket_brigade* bb, int block) { apr_off_t written, left; @@ -108,9 +116,6 @@ static apr_status_t send_out(h2_task *task, apr_bucket_brigade* bb, int block) status = APR_SUCCESS; } if (status == APR_SUCCESS) { - if (h2_task_logio_add_bytes_out) { - h2_task_logio_add_bytes_out(task->c, written); - } ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, task->c, "h2_task(%s): send_out done", task->id); } @@ -183,7 +188,9 @@ send: } } - if (APR_SUCCESS == rv && !task->output.opened && flush) { + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, task->c, + "h2_secondary_out(%s): buffered=%d", task->id, task->output.buffered); + if (APR_SUCCESS == rv && !task->output.opened && (flush || !task->output.buffered)) { /* got a flush or could not write all, time to tell someone to read */ rv = open_output(task); } @@ -598,7 +605,8 @@ apr_status_t h2_task_do(h2_task *task, apr_thread_t *thread, int worker_id) h2_beam_buffer_size_set(task->output.beam, task->output.max_buffer); h2_beam_send_from(task->output.beam, task->pool); - + h2_beam_on_consumed(task->output.beam, NULL, output_consumed, task); + h2_ctx_create_for(c, task); apr_table_setn(c->notes, H2_TASK_ID_NOTE, task->id); diff --git a/modules/http2/h2_task.h b/modules/http2/h2_task.h index 2f411791cb..50f41b8255 100644 --- a/modules/http2/h2_task.h +++ b/modules/http2/h2_task.h @@ -71,6 +71,7 @@ struct h2_task { unsigned int opened : 1; unsigned int sent_response : 1; unsigned int copy_files : 1; + unsigned int buffered : 1; struct h2_response_parser *rparser; apr_bucket_brigade *bb; apr_size_t max_buffer; diff --git a/modules/http2/h2_version.h b/modules/http2/h2_version.h index 68fd223985..03651c998d 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 "1.15.14" +#define MOD_HTTP2_VERSION "1.15.17" /** * @macro @@ -35,6 +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 0x010f0e +#define MOD_HTTP2_VERSION_NUM 0x010f11 + #endif /* mod_h2_h2_version_h */ |