/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "httpd.h"
#include "http_config.h"
#include "http_request.h"
#include "http_connection.h"
#include "http_protocol.h"
#include "http_log.h"
#include "http_core.h"
#include "util_filter.h"
#define APR_WANT_STRFUNC
#include "apr_strings.h"
#include "apr_version.h"
#define MRT_DEFAULT_BODY_MAX_TIMEOUT 0
typedef struct
{
/* this struct is used both as conn_config and as filter context */
typedef struct
{
int min_rate;
int new_timeout;
int new_max_timeout;
int in_keep_alive;
char *type;
static int default_header_rate_factor;
static int default_body_rate_factor;
{
return;
}
else {
}
}
{
if (!now)
now = apr_time_now();
if (*time_left_p <= 0)
return APR_TIMEUP;
}
return APR_SUCCESS;
}
{
const char *str;
if (APR_BUCKET_IS_EOS(b))
return APR_SUCCESS;
if (APR_BUCKET_IS_METADATA(b))
continue;
if (rv != APR_SUCCESS)
return rv;
if (len == 0)
continue;
return APR_SUCCESS;
}
return APR_INCOMPLETE;
}
/*
* Append bbIn to bbOut and merge small buckets, to avoid DoS by high memory
* usage
*/
{
while (!APR_BRIGADE_EMPTY(bbIn)) {
const char *str;
if (rv != APR_SUCCESS) {
return rv;
}
}
else {
if (len > 0) {
if (rv != APR_SUCCESS) {
return rv;
}
}
}
}
return APR_SUCCESS;
}
#define MIN(x,y) ((x) < (y) ? (x) : (y))
{
if (ccfg->in_keep_alive) {
/* For this read, the normal keep-alive timeout must be used */
ccfg->in_keep_alive = 0;
}
/* The source of these above us in the core is check_pipeline(), which
* is between requests but before this filter knows to reset timeouts
* during log_transaction(). If they appear elsewhere, just don't
* check or extend the time since they won't block and we'll see the
* bytes again later
*/
}
if (ccfg->new_timeout > 0) {
/* set new timeout */
now = apr_time_now();
ccfg->new_timeout = 0;
if (ccfg->new_max_timeout > 0) {
ccfg->new_max_timeout = 0;
}
}
else if (ccfg->timeout_at == 0) {
/* no timeout set */
}
}
if (rv != APR_SUCCESS)
goto out;
|| mode == AP_MODE_EATCRLF) {
}
return rv;
}
if (mode == AP_MODE_GETLINE) {
/*
* For a blocking AP_MODE_GETLINE read, apr_brigade_split_line()
* would loop until a whole line has been read. As this would make it
* impossible to enforce a total timeout, we only do non-blocking
* reads.
*/
do {
#if APR_MAJOR_VERSION < 2
#endif
break;
}
if (!APR_BRIGADE_EMPTY(bb)) {
}
if (rv != APR_INCOMPLETE) {
break;
}
if (rv != APR_SUCCESS) {
break;
}
if (remaining <= 0) {
break;
}
/* Haven't got a whole line yet, save what we have ... */
}
if (rv != APR_SUCCESS)
break;
}
/* ... and wait for more */
#if APR_MAJOR_VERSION < 2
#else
#endif
if (rv != APR_SUCCESS)
break;
if (rv != APR_SUCCESS)
break;
} while (1);
}
else {
/* mode != AP_MODE_GETLINE */
/* Don't extend the timeout in speculative mode, wait for
* the real (relevant) bytes to be asked later, within the
* currently alloted time.
*/
&& mode != AP_MODE_SPECULATIVE) {
}
}
out:
if (APR_STATUS_IS_TIMEUP(rv)) {
/*
* If we allow a normal lingering close, the client may keep this
* Therefore we tell ap_lingering_close() to shorten this period to
* 2s (SECONDS_TO_LINGER).
*/
/*
* Also, we must not allow keep-alive requests, as
* ap_finalize_protocol() may ignore our error status (if the timeout
* happened on a request body that is discarded).
*/
f->c->keepalive = AP_CONN_CLOSE;
}
return rv;
}
{
/* disabled for this vhost */
return DECLINED;
}
}
else {
/* subsequent request under event-like MPM */
}
}
else {
}
/* we are not handling the connection, we just do initialization */
return DECLINED;
}
{
/* either disabled for this connection or a CONNECT request */
return OK;
}
ccfg->timeout_at = 0;
ccfg->max_timeout_at = 0;
}
else {
}
return OK;
}
{
/* not configured for this connection */
return OK;
}
ccfg->timeout_at = 0;
ccfg->max_timeout_at = 0;
}
else {
}
return OK;
}
{
return cfg;
}
{
return cfg;
}
char *endptr;
}
if (*endptr != '\0') {
}
if (*val < 0) {
return "Value must be non-negative";
}
return NULL;
}
apr_pool_t *p,
const char *key,
const char *val)
{
type = PARAM_HEADER;
}
type = PARAM_BODY;
}
else {
return "Unknown RequestReadTimeout parameter";
}
if (ret)
return ret;
if (rate == 0)
return "Minimum data rate must be larger than 0";
*max_str++ = '\0';
if (ret)
return ret;
}
}
else {
return "Must set MinRate option if using timeout range";
}
if (ret)
return ret;
return "Maximum timeout must be larger than initial timeout";
}
if (type == PARAM_HEADER) {
if (rate)
}
else {
if (rate)
}
return ret;
}
const char *arg)
{
while (*arg) {
const char *err;
if (!val) {
return "Invalid RequestReadTimeout parameter. Parameter must be "
"in the form 'key=value'";
}
else
*val++ = '\0';
if (err)
}
return NULL;
}
{
/*
* mod_ssl is AP_FTYPE_CONNECTION + 5 and mod_reqtimeout needs to
* be called before mod_ssl. Otherwise repeated reads during the ssl
* handshake can prevent the timeout from triggering.
*/
AP_FTYPE_CONNECTION + 8);
/*
* mod_reqtimeout needs to be called before ap_process_http_request (which
* is run at APR_HOOK_REALLY_LAST) but after all other protocol modules.
* This ensures that it only influences normal http connections and not
* e.g. mod_ftp. Also, if mod_reqtimeout used the pre_connection hook, it
* would be inserted on mod_proxy's backend connections.
*/
#if MRT_DEFAULT_HEADER_MIN_RATE > 0
#endif
#if MRT_DEFAULT_BODY_MIN_RATE > 0
#endif
}
"Set various timeout parameters for reading request "
"headers and body"),
{NULL}
};
NULL, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
reqtimeout_create_srv_config, /* create per-server config structures */
reqtimeout_merge_srv_config, /* merge per-server config structures */
reqtimeout_cmds, /* table of config file commands */
};