mod_reqtimeout.c revision 4dee28b6fc8fff5efde4e7821aeb6defed3fb84d
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf/* Licensed to the Apache Software Foundation (ASF) under one or more
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * contributor license agreements. See the NOTICE file distributed with
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * this work for additional information regarding copyright ownership.
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * The ASF licenses this file to You under the Apache License, Version 2.0
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * (the "License"); you may not use this file except in compliance with
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * the License. You may obtain a copy of the License at
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * Unless required by applicable law or agreed to in writing, software
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * distributed under the License is distributed on an "AS IS" BASIS,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * See the License for the specific language governing permissions and
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * limitations under the License.
31affcba3c7c40456e1941b046feb7a717407a57bjhtypedef struct
3231873d0ba8064a1c90307d810a83ec01a88675jimtypedef struct
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsftypedef struct
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsfstatic const char *const reqtimeout_filter_name = "reqtimeout";
8973e168b1301132b47bc718d75013ee35f49c2csfstatic void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (apr_brigade_length(bb, 0, &len) != APR_SUCCESS || len <= 0)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf new_timeout_at = ccfg->timeout_at + len * apr_time_from_sec(1) / ccfg->min_rate;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (ccfg->max_timeout_at > 0 && new_timeout_at > ccfg->max_timeout_at) {
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg = ap_get_module_config(f->c->conn_config, &reqtimeout_module);
8973e168b1301132b47bc718d75013ee35f49c2csf /* For this read, the normal keep-alive timeout must be used */
8973e168b1301132b47bc718d75013ee35f49c2csf return ap_get_brigade(f->next, bb, mode, block, readbytes);
8973e168b1301132b47bc718d75013ee35f49c2csf /* set new timeout */
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->timeout_at = now + apr_time_from_sec(ccfg->new_timeout);
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->max_timeout_at = now + apr_time_from_sec(ccfg->new_max_timeout);
8973e168b1301132b47bc718d75013ee35f49c2csf /* no timeout set */
8973e168b1301132b47bc718d75013ee35f49c2csf return ap_get_brigade(f->next, bb, mode, block, readbytes);
8973e168b1301132b47bc718d75013ee35f49c2csf if (time_left <= 0) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf rv = apr_socket_timeout_get(ctx->socket, &saved_sock_timeout);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf cfg = ap_get_module_config(c->base_server->module_config,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (cfg->header_timeout <= 0 && cfg->body_timeout <= 0) {
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf /* not configured for this vhost */
8973e168b1301132b47bc718d75013ee35f49c2csf ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg);
8973e168b1301132b47bc718d75013ee35f49c2csf ap_get_module_config(r->connection->conn_config, &reqtimeout_module);
8973e168b1301132b47bc718d75013ee35f49c2csf /* not configured for this vhost */
3b5fbf686c2c0e2e69716a073173a5c50539410csf cfg = ap_get_module_config(r->connection->base_server->module_config,
8973e168b1301132b47bc718d75013ee35f49c2csf ap_get_module_config(r->connection->conn_config, &reqtimeout_module);
8973e168b1301132b47bc718d75013ee35f49c2csf /* not configured for this vhost */
31affcba3c7c40456e1941b046feb7a717407a57bjh cfg = ap_get_module_config(r->connection->base_server->module_config,
8973e168b1301132b47bc718d75013ee35f49c2csfstatic void *reqtimeout_create_srv_config(apr_pool_t *p, server_rec *s)
8973e168b1301132b47bc718d75013ee35f49c2csf reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
8973e168b1301132b47bc718d75013ee35f49c2csf#define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == -1) ? b->val : a->val;
8973e168b1301132b47bc718d75013ee35f49c2csfstatic void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return "Value not numerical";
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (*val < 0) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return "Value must be non-negative";
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *parse_timeouts(const char *arg1, int *val1,
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf const char *errstr;
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf if (*val2 != 0 &&
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return "Max timeout must be larger than initial timeout";
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *headertimeout_cmd(cmd_parms *parms, void *mconfig,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *headerminrate_cmd(cmd_parms *parms, void *mconfig,
9bea0d2b2f3b91bf4b613eecdb63699942bc6e44sf const char *arg)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *bodytimeout_cmd(cmd_parms *parms, void *mconfig,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *bodyminrate_cmd(cmd_parms *parms, void *mconfig,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf const char *arg)
a4a16f26af59370661ea5f890502cf32146e0947jim * mod_ssl is AP_FTYPE_CONNECTION + 5 and mod_reqtimeout needs to
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * be called before mod_ssl. Otherwise repeated reads during the ssl
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * handshake can prevent the timeout from triggering.
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_register_input_filter(reqtimeout_filter_name, reqtimeout_filter, NULL,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_hook_pre_connection(reqtimeout_pre_conn, NULL, NULL, APR_HOOK_MIDDLE);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_hook_post_read_request(reqtimeout_after_headers, NULL, NULL,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_hook_log_transaction(reqtimeout_after_body, NULL, NULL,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf AP_INIT_TAKE12("RequestHeaderTimeout", headertimeout_cmd, NULL, RSRC_CONF,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf "Initial (and maximal) timeouts for reading the request headers in seconds"),
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf AP_INIT_TAKE1("RequestHeaderMinRate", headerminrate_cmd, NULL, RSRC_CONF,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf "Minimal transfer rate for reading the request headers in bytes/s"),
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf AP_INIT_TAKE12("RequestBodyTimeout", bodytimeout_cmd, NULL, RSRC_CONF,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf "Initial (and maximal) timeouts for reading the request body in seconds"),
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf AP_INIT_TAKE1("RequestBodyMinRate", bodyminrate_cmd, NULL, RSRC_CONF,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf "Minimal transfer rate for reading the request body in bytes/s"),
a4a16f26af59370661ea5f890502cf32146e0947jim reqtimeout_create_srv_config, /* create per-server config structures */
a4a16f26af59370661ea5f890502cf32146e0947jim reqtimeout_merge_srv_config, /* merge per-server config structures */