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 *
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf * http://www.apache.org/licenses/LICENSE-2.0
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf *
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.
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf */
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf#include "httpd.h"
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf#include "http_config.h"
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf#include "http_request.h"
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf#include "http_connection.h"
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf#include "http_protocol.h"
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf#include "http_log.h"
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf#include "util_filter.h"
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
3231873d0ba8064a1c90307d810a83ec01a88675jimmodule AP_MODULE_DECLARE_DATA reqtimeout_module;
3231873d0ba8064a1c90307d810a83ec01a88675jim
31affcba3c7c40456e1941b046feb7a717407a57bjhtypedef struct
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf int header_timeout;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf int header_max_timeout;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf int header_min_rate;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf int body_timeout;
3231873d0ba8064a1c90307d810a83ec01a88675jim int body_max_timeout;
3231873d0ba8064a1c90307d810a83ec01a88675jim int body_min_rate;
3231873d0ba8064a1c90307d810a83ec01a88675jim} reqtimeout_srv_cfg;
a4a16f26af59370661ea5f890502cf32146e0947jim
3231873d0ba8064a1c90307d810a83ec01a88675jimtypedef struct
3231873d0ba8064a1c90307d810a83ec01a88675jim{
3231873d0ba8064a1c90307d810a83ec01a88675jim apr_time_t timeout_at;
a4a16f26af59370661ea5f890502cf32146e0947jim apr_time_t max_timeout_at;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf int min_rate;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf int new_timeout;
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf int new_max_timeout;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf int in_keep_alive;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf char *type;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf} reqtimeout_con_cfg;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsftypedef struct
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf apr_socket_t *socket;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf} reqtimeout_ctx;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsfstatic const char *const reqtimeout_filter_name = "reqtimeout";
a4a16f26af59370661ea5f890502cf32146e0947jim
8973e168b1301132b47bc718d75013ee35f49c2csfstatic void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf apr_off_t len;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf apr_time_t new_timeout_at;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (apr_brigade_length(bb, 0, &len) != APR_SUCCESS || len <= 0)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
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) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ccfg->timeout_at = ccfg->max_timeout_at;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf else {
a4a16f26af59370661ea5f890502cf32146e0947jim ccfg->timeout_at = new_timeout_at;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf}
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic apr_status_t reqtimeout_filter(ap_filter_t *f,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf apr_bucket_brigade *bb,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_input_mode_t mode,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf apr_read_type_e block,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf apr_off_t readbytes)
8973e168b1301132b47bc718d75013ee35f49c2csf{
8973e168b1301132b47bc718d75013ee35f49c2csf reqtimeout_ctx *ctx;
8973e168b1301132b47bc718d75013ee35f49c2csf apr_time_t time_left;
8973e168b1301132b47bc718d75013ee35f49c2csf apr_time_t now;
8973e168b1301132b47bc718d75013ee35f49c2csf apr_status_t rv;
8973e168b1301132b47bc718d75013ee35f49c2csf apr_interval_time_t saved_sock_timeout = -1;
8973e168b1301132b47bc718d75013ee35f49c2csf reqtimeout_con_cfg *ccfg;
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf ctx = f->ctx;
8973e168b1301132b47bc718d75013ee35f49c2csf AP_DEBUG_ASSERT(ctx != NULL);
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg = ap_get_module_config(f->c->conn_config, &reqtimeout_module);
8973e168b1301132b47bc718d75013ee35f49c2csf AP_DEBUG_ASSERT(ccfg != NULL);
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf if (ccfg->in_keep_alive) {
8973e168b1301132b47bc718d75013ee35f49c2csf /* For this read, the normal keep-alive timeout must be used */
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->in_keep_alive = 0;
8973e168b1301132b47bc718d75013ee35f49c2csf return ap_get_brigade(f->next, bb, mode, block, readbytes);
8973e168b1301132b47bc718d75013ee35f49c2csf }
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf now = apr_time_now();
8973e168b1301132b47bc718d75013ee35f49c2csf if (ccfg->new_timeout > 0) {
8973e168b1301132b47bc718d75013ee35f49c2csf /* set new timeout */
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->timeout_at = now + apr_time_from_sec(ccfg->new_timeout);
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->new_timeout = 0;
8973e168b1301132b47bc718d75013ee35f49c2csf if (ccfg->new_max_timeout > 0) {
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->max_timeout_at = now + apr_time_from_sec(ccfg->new_max_timeout);
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->new_max_timeout = 0;
8973e168b1301132b47bc718d75013ee35f49c2csf }
8973e168b1301132b47bc718d75013ee35f49c2csf }
8973e168b1301132b47bc718d75013ee35f49c2csf else if (ccfg->timeout_at == 0) {
8973e168b1301132b47bc718d75013ee35f49c2csf /* no timeout set */
8973e168b1301132b47bc718d75013ee35f49c2csf return ap_get_brigade(f->next, bb, mode, block, readbytes);
8973e168b1301132b47bc718d75013ee35f49c2csf }
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf time_left = ccfg->timeout_at - now;
8973e168b1301132b47bc718d75013ee35f49c2csf if (time_left <= 0) {
8973e168b1301132b47bc718d75013ee35f49c2csf ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c,
8973e168b1301132b47bc718d75013ee35f49c2csf "Request %s read timeout", ccfg->type);
8973e168b1301132b47bc718d75013ee35f49c2csf return APR_TIMEUP;
8973e168b1301132b47bc718d75013ee35f49c2csf }
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf if (block == APR_NONBLOCK_READ || mode == AP_MODE_INIT
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf || mode == AP_MODE_EATCRLF) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (ccfg->min_rate > 0 && rv == APR_SUCCESS) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf extend_timeout(ccfg, bb);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return rv;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (time_left < apr_time_from_sec(1)) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf time_left = apr_time_from_sec(1);
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf rv = apr_socket_timeout_get(ctx->socket, &saved_sock_timeout);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf AP_DEBUG_ASSERT(rv == APR_SUCCESS);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (saved_sock_timeout >= time_left) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf rv = apr_socket_timeout_set(ctx->socket, time_left);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf AP_DEBUG_ASSERT(rv == APR_SUCCESS);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf else {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf saved_sock_timeout = -1;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (saved_sock_timeout != -1) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf apr_socket_timeout_set(ctx->socket, saved_sock_timeout);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (ccfg->min_rate > 0 && rv == APR_SUCCESS) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf extend_timeout(ccfg, bb);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf if (rv == APR_TIMEUP) {
bb1afc531935821f63267ccf12cccc7e981ce4d1sf ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c,
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf "Request %s read timeout", ccfg->type);
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf }
8973e168b1301132b47bc718d75013ee35f49c2csf return rv;
8973e168b1301132b47bc718d75013ee35f49c2csf}
8973e168b1301132b47bc718d75013ee35f49c2csf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic int reqtimeout_pre_conn(conn_rec *c, void *csd)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_ctx *ctx;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_con_cfg *ccfg;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_srv_cfg *cfg;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf cfg = ap_get_module_config(c->base_server->module_config,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf &reqtimeout_module);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf AP_DEBUG_ASSERT(cfg != NULL);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (cfg->header_timeout <= 0 && cfg->body_timeout <= 0) {
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf /* not configured for this vhost */
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return OK;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf ctx = apr_pcalloc(c->pool, sizeof(reqtimeout_ctx));
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ctx->socket = csd;
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg = apr_pcalloc(c->pool, sizeof(reqtimeout_con_cfg));
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->new_timeout = cfg->header_timeout;
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->new_max_timeout = cfg->header_max_timeout;
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->type = "header";
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->min_rate = cfg->header_min_rate;
8973e168b1301132b47bc718d75013ee35f49c2csf ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg);
592a6803fcf6d490795de9dcad02ede1d4c2f62bwrowe
8973e168b1301132b47bc718d75013ee35f49c2csf ap_add_input_filter("reqtimeout", ctx, NULL, c);
8973e168b1301132b47bc718d75013ee35f49c2csf return OK;
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf}
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf
674d9706109b3bc5b235a94ee6e62c31a9a52cddsfstatic int reqtimeout_after_headers(request_rec *r)
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf{
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf reqtimeout_srv_cfg *cfg;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_con_cfg *ccfg =
8973e168b1301132b47bc718d75013ee35f49c2csf ap_get_module_config(r->connection->conn_config, &reqtimeout_module);
a54fe31ace4d933f4fe691ed07cd986f6bfdfd5fsf
8973e168b1301132b47bc718d75013ee35f49c2csf if (ccfg == NULL) {
8973e168b1301132b47bc718d75013ee35f49c2csf /* not configured for this vhost */
8973e168b1301132b47bc718d75013ee35f49c2csf return OK;
8973e168b1301132b47bc718d75013ee35f49c2csf }
3b5fbf686c2c0e2e69716a073173a5c50539410csf
3b5fbf686c2c0e2e69716a073173a5c50539410csf cfg = ap_get_module_config(r->connection->base_server->module_config,
3b5fbf686c2c0e2e69716a073173a5c50539410csf &reqtimeout_module);
3b5fbf686c2c0e2e69716a073173a5c50539410csf AP_DEBUG_ASSERT(cfg != NULL);
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->timeout_at = 0;
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->max_timeout_at = 0;
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->new_timeout = cfg->body_timeout;
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->new_max_timeout = cfg->body_max_timeout;
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->min_rate = cfg->body_min_rate;
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->type = "body";
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf return OK;
8973e168b1301132b47bc718d75013ee35f49c2csf}
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csfstatic int reqtimeout_after_body(request_rec *r)
8973e168b1301132b47bc718d75013ee35f49c2csf{
8973e168b1301132b47bc718d75013ee35f49c2csf reqtimeout_srv_cfg *cfg;
8973e168b1301132b47bc718d75013ee35f49c2csf reqtimeout_con_cfg *ccfg =
8973e168b1301132b47bc718d75013ee35f49c2csf ap_get_module_config(r->connection->conn_config, &reqtimeout_module);
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf if (ccfg == NULL) {
8973e168b1301132b47bc718d75013ee35f49c2csf /* not configured for this vhost */
8973e168b1301132b47bc718d75013ee35f49c2csf return OK;
8973e168b1301132b47bc718d75013ee35f49c2csf }
8973e168b1301132b47bc718d75013ee35f49c2csf
31affcba3c7c40456e1941b046feb7a717407a57bjh cfg = ap_get_module_config(r->connection->base_server->module_config,
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf &reqtimeout_module);
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf AP_DEBUG_ASSERT(cfg != NULL);
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf ccfg->timeout_at = 0;
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf ccfg->max_timeout_at = 0;
674d9706109b3bc5b235a94ee6e62c31a9a52cddsf ccfg->in_keep_alive = 1;
31affcba3c7c40456e1941b046feb7a717407a57bjh ccfg->new_timeout = cfg->header_timeout;
b9cac1a7680839ed17fded260d74ec4d87af501dbjh ccfg->new_max_timeout = cfg->header_max_timeout;
31affcba3c7c40456e1941b046feb7a717407a57bjh ccfg->min_rate = cfg->header_min_rate;
8973e168b1301132b47bc718d75013ee35f49c2csf ccfg->type = "header";
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf return OK;
8973e168b1301132b47bc718d75013ee35f49c2csf}
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csfstatic void *reqtimeout_create_srv_config(apr_pool_t *p, server_rec *s)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
8973e168b1301132b47bc718d75013ee35f49c2csf reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf cfg->header_timeout = -1;
8973e168b1301132b47bc718d75013ee35f49c2csf cfg->header_max_timeout = -1;
8973e168b1301132b47bc718d75013ee35f49c2csf cfg->header_min_rate = -1;
8973e168b1301132b47bc718d75013ee35f49c2csf cfg->body_timeout = -1;
8973e168b1301132b47bc718d75013ee35f49c2csf cfg->body_max_timeout = -1;
8973e168b1301132b47bc718d75013ee35f49c2csf cfg->body_min_rate = -1;
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf return cfg;
8973e168b1301132b47bc718d75013ee35f49c2csf}
8973e168b1301132b47bc718d75013ee35f49c2csf
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_)
8973e168b1301132b47bc718d75013ee35f49c2csf{
8973e168b1301132b47bc718d75013ee35f49c2csf reqtimeout_srv_cfg *base = base_;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_srv_cfg *add = add_;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
8973e168b1301132b47bc718d75013ee35f49c2csf
8973e168b1301132b47bc718d75013ee35f49c2csf MERGE_INT(cfg, base, add, header_timeout);
8973e168b1301132b47bc718d75013ee35f49c2csf MERGE_INT(cfg, base, add, header_max_timeout);
2fda441ba865b7bb53eb425a91f8177c1e7a01ffrpluem MERGE_INT(cfg, base, add, header_min_rate);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf MERGE_INT(cfg, base, add, body_timeout);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf MERGE_INT(cfg, base, add, body_max_timeout);
8973e168b1301132b47bc718d75013ee35f49c2csf MERGE_INT(cfg, base, add, body_min_rate);
5eabcf9bc3875db35c0e62a2202d63768c10168dsf
8973e168b1301132b47bc718d75013ee35f49c2csf return cfg;
5eabcf9bc3875db35c0e62a2202d63768c10168dsf}
5eabcf9bc3875db35c0e62a2202d63768c10168dsf
8973e168b1301132b47bc718d75013ee35f49c2csfstatic const char *parse_int(const char *arg, int *val) {
5eabcf9bc3875db35c0e62a2202d63768c10168dsf char *endptr;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf *val = strtol(arg, &endptr, 10);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if ((arg == endptr) || (*endptr != '\0')) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return "Value not numerical";
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (*val < 0) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return "Value must be non-negative";
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return NULL;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf}
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *parse_timeouts(const char *arg1, int *val1,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf const char *arg2, int *val2)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf const char *errstr;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf errstr = parse_int(arg1, val1);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (errstr) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return errstr;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (arg2 != NULL) {
a4a16f26af59370661ea5f890502cf32146e0947jim errstr = parse_int(arg2, val2);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf if (errstr) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return errstr;
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf }
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf if (*val2 != 0 &&
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf *val2 <= *val1) {
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return "Max timeout must be larger than initial timeout";
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf }
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return NULL;
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf}
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *headertimeout_cmd(cmd_parms *parms, void *mconfig,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf const char *arg1, const char *arg2)
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf{
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_srv_cfg *conf =
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_get_module_config(parms->server->module_config,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf &reqtimeout_module);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return parse_timeouts(arg1, &conf->header_timeout,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf arg2, &conf->header_max_timeout);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf}
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *headerminrate_cmd(cmd_parms *parms, void *mconfig,
9bea0d2b2f3b91bf4b613eecdb63699942bc6e44sf const char *arg)
9bea0d2b2f3b91bf4b613eecdb63699942bc6e44sf{
9bea0d2b2f3b91bf4b613eecdb63699942bc6e44sf reqtimeout_srv_cfg *conf =
9bea0d2b2f3b91bf4b613eecdb63699942bc6e44sf ap_get_module_config(parms->server->module_config,
9bea0d2b2f3b91bf4b613eecdb63699942bc6e44sf &reqtimeout_module);
9bea0d2b2f3b91bf4b613eecdb63699942bc6e44sf
9bea0d2b2f3b91bf4b613eecdb63699942bc6e44sf return parse_int(arg, &conf->header_min_rate);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf}
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *bodytimeout_cmd(cmd_parms *parms, void *mconfig,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf const char *arg1, const char *arg2)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_srv_cfg *conf =
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_get_module_config(parms->server->module_config,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf &reqtimeout_module);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return parse_timeouts(arg1, &conf->body_timeout,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf arg2, &conf->body_max_timeout);
14e5a8cc15b1dcc26ad5420973304e53a9e5406bsf}
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const char *bodyminrate_cmd(cmd_parms *parms, void *mconfig,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf const char *arg)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf reqtimeout_srv_cfg *conf =
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_get_module_config(parms->server->module_config,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf &reqtimeout_module);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf return parse_int(arg, &conf->body_min_rate);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf}
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic void reqtimeout_hooks(apr_pool_t *pool)
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf{
a4a16f26af59370661ea5f890502cf32146e0947jim /*
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 */
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_register_input_filter(reqtimeout_filter_name, reqtimeout_filter, NULL,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf AP_FTYPE_CONNECTION + 8);
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 APR_HOOK_MIDDLE);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf ap_hook_log_transaction(reqtimeout_after_body, NULL, NULL,
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf APR_HOOK_MIDDLE);
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf}
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsfstatic const command_rec reqtimeout_cmds[] = {
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"),
4dee28b6fc8fff5efde4e7821aeb6defed3fb84dsf {NULL}
a4a16f26af59370661ea5f890502cf32146e0947jim};
a4a16f26af59370661ea5f890502cf32146e0947jim
a4a16f26af59370661ea5f890502cf32146e0947jimmodule AP_MODULE_DECLARE_DATA reqtimeout_module = {
a4a16f26af59370661ea5f890502cf32146e0947jim STANDARD20_MODULE_STUFF,
a4a16f26af59370661ea5f890502cf32146e0947jim NULL, /* create per-dir config structures */
a4a16f26af59370661ea5f890502cf32146e0947jim NULL, /* merge per-dir config structures */
a4a16f26af59370661ea5f890502cf32146e0947jim reqtimeout_create_srv_config, /* create per-server config structures */
a4a16f26af59370661ea5f890502cf32146e0947jim reqtimeout_merge_srv_config, /* merge per-server config structures */
a4a16f26af59370661ea5f890502cf32146e0947jim reqtimeout_cmds, /* table of config file commands */
a4a16f26af59370661ea5f890502cf32146e0947jim reqtimeout_hooks
a4a16f26af59370661ea5f890502cf32146e0947jim};
a4a16f26af59370661ea5f890502cf32146e0947jim