~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to modules/http/http_core.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
 
2
 * contributor license agreements.  See the NOTICE file distributed with
 
3
 * this work for additional information regarding copyright ownership.
 
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
5
 * (the "License"); you may not use this file except in compliance with
 
6
 * the License.  You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include "apr_strings.h"
 
18
#include "apr_thread_proc.h"    /* for RLIMIT stuff */
 
19
 
 
20
#define APR_WANT_STRFUNC
 
21
#include "apr_want.h"
 
22
 
 
23
#define CORE_PRIVATE
 
24
#include "httpd.h"
 
25
#include "http_config.h"
 
26
#include "http_connection.h"
 
27
#include "http_core.h"
 
28
#include "http_protocol.h"   /* For index_of_response().  Grump. */
 
29
#include "http_request.h"
 
30
 
 
31
#include "util_filter.h"
 
32
#include "util_ebcdic.h"
 
33
#include "ap_mpm.h"
 
34
#include "scoreboard.h"
 
35
 
 
36
#include "mod_core.h"
 
37
 
 
38
/* Handles for core filters */
 
39
AP_DECLARE_DATA ap_filter_rec_t *ap_http_input_filter_handle;
 
40
AP_DECLARE_DATA ap_filter_rec_t *ap_http_header_filter_handle;
 
41
AP_DECLARE_DATA ap_filter_rec_t *ap_chunk_filter_handle;
 
42
AP_DECLARE_DATA ap_filter_rec_t *ap_http_outerror_filter_handle;
 
43
AP_DECLARE_DATA ap_filter_rec_t *ap_byterange_filter_handle;
 
44
 
 
45
static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy,
 
46
                                          const char *arg)
 
47
{
 
48
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
49
    if (err != NULL) {
 
50
        return err;
 
51
    }
 
52
 
 
53
    cmd->server->keep_alive_timeout = apr_time_from_sec(atoi(arg));
 
54
    return NULL;
 
55
}
 
56
 
 
57
static const char *set_keep_alive(cmd_parms *cmd, void *dummy,
 
58
                                  const char *arg)
 
59
{
 
60
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
61
    if (err != NULL) {
 
62
        return err;
 
63
    }
 
64
 
 
65
    /* We've changed it to On/Off, but used to use numbers
 
66
     * so we accept anything but "Off" or "0" as "On"
 
67
     */
 
68
    if (!strcasecmp(arg, "off") || !strcmp(arg, "0")) {
 
69
        cmd->server->keep_alive = 0;
 
70
    }
 
71
    else {
 
72
        cmd->server->keep_alive = 1;
 
73
    }
 
74
    return NULL;
 
75
}
 
76
 
 
77
static const char *set_keep_alive_max(cmd_parms *cmd, void *dummy,
 
78
                                      const char *arg)
 
79
{
 
80
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
81
    if (err != NULL) {
 
82
        return err;
 
83
    }
 
84
 
 
85
    cmd->server->keep_alive_max = atoi(arg);
 
86
    return NULL;
 
87
}
 
88
 
 
89
static const command_rec http_cmds[] = {
 
90
    AP_INIT_TAKE1("KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF,
 
91
                  "Keep-Alive timeout duration (sec)"),
 
92
    AP_INIT_TAKE1("MaxKeepAliveRequests", set_keep_alive_max, NULL, RSRC_CONF,
 
93
                  "Maximum number of Keep-Alive requests per connection, "
 
94
                  "or 0 for infinite"),
 
95
    AP_INIT_TAKE1("KeepAlive", set_keep_alive, NULL, RSRC_CONF,
 
96
                  "Whether persistent connections should be On or Off"),
 
97
    { NULL }
 
98
};
 
99
 
 
100
static const char *http_scheme(const request_rec *r)
 
101
{
 
102
    /* 
 
103
     * The http module shouldn't return anything other than 
 
104
     * "http" (the default) or "https".
 
105
     */
 
106
    if (r->server->server_scheme &&
 
107
        (strcmp(r->server->server_scheme, "https") == 0))
 
108
        return "https";
 
109
    
 
110
    return "http";
 
111
}
 
112
 
 
113
static apr_port_t http_port(const request_rec *r)
 
114
{
 
115
    if (r->server->server_scheme &&
 
116
        (strcmp(r->server->server_scheme, "https") == 0))
 
117
        return DEFAULT_HTTPS_PORT;
 
118
    
 
119
    return DEFAULT_HTTP_PORT;
 
120
}
 
121
 
 
122
static int ap_process_http_async_connection(conn_rec *c)
 
123
{
 
124
    request_rec *r;
 
125
    conn_state_t *cs = c->cs;
 
126
 
 
127
    AP_DEBUG_ASSERT(cs->state == CONN_STATE_READ_REQUEST_LINE);
 
128
 
 
129
    while (cs->state == CONN_STATE_READ_REQUEST_LINE) {
 
130
        ap_update_child_status(c->sbh, SERVER_BUSY_READ, NULL);
 
131
 
 
132
        if ((r = ap_read_request(c))) {
 
133
 
 
134
            c->keepalive = AP_CONN_UNKNOWN;
 
135
            /* process the request if it was read without error */
 
136
 
 
137
            ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r);
 
138
            if (r->status == HTTP_OK)
 
139
                ap_process_request(r);
 
140
 
 
141
            if (ap_extended_status)
 
142
                ap_increment_counts(c->sbh, r);
 
143
 
 
144
            if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted
 
145
                    || ap_graceful_stop_signalled()) {
 
146
                cs->state = CONN_STATE_LINGER;
 
147
            }
 
148
            else if (!c->data_in_input_filters) {
 
149
                cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
 
150
            }
 
151
 
 
152
            /* else we are pipelining.  Stay in READ_REQUEST_LINE state
 
153
             *  and stay in the loop
 
154
             */
 
155
 
 
156
            apr_pool_destroy(r->pool);
 
157
        }
 
158
        else {   /* ap_read_request failed - client may have closed */
 
159
            cs->state = CONN_STATE_LINGER;
 
160
        }
 
161
    }
 
162
 
 
163
    return OK;
 
164
}
 
165
 
 
166
static int ap_process_http_connection(conn_rec *c)
 
167
{
 
168
    request_rec *r;
 
169
    apr_socket_t *csd = NULL;
 
170
 
 
171
    /*
 
172
     * Read and process each request found on our connection
 
173
     * until no requests are left or we decide to close.
 
174
     */
 
175
 
 
176
    ap_update_child_status(c->sbh, SERVER_BUSY_READ, NULL);
 
177
    while ((r = ap_read_request(c)) != NULL) {
 
178
 
 
179
        c->keepalive = AP_CONN_UNKNOWN;
 
180
        /* process the request if it was read without error */
 
181
 
 
182
        ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r);
 
183
        if (r->status == HTTP_OK)
 
184
            ap_process_request(r);
 
185
 
 
186
        if (ap_extended_status)
 
187
            ap_increment_counts(c->sbh, r);
 
188
 
 
189
        if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted)
 
190
            break;
 
191
 
 
192
        ap_update_child_status(c->sbh, SERVER_BUSY_KEEPALIVE, r);
 
193
        apr_pool_destroy(r->pool);
 
194
 
 
195
        if (ap_graceful_stop_signalled())
 
196
            break;
 
197
 
 
198
        if (!csd) {
 
199
            csd = ap_get_module_config(c->conn_config, &core_module);
 
200
        }
 
201
        apr_socket_opt_set(csd, APR_INCOMPLETE_READ, 1);
 
202
        apr_socket_timeout_set(csd, c->base_server->keep_alive_timeout);
 
203
        /* Go straight to select() to wait for the next request */
 
204
    }
 
205
 
 
206
    return OK;
 
207
}
 
208
 
 
209
static int http_create_request(request_rec *r)
 
210
{
 
211
    if (!r->main && !r->prev) {
 
212
        ap_add_output_filter_handle(ap_byterange_filter_handle,
 
213
                                    NULL, r, r->connection);
 
214
        ap_add_output_filter_handle(ap_content_length_filter_handle,
 
215
                                    NULL, r, r->connection);
 
216
        ap_add_output_filter_handle(ap_http_header_filter_handle,
 
217
                                    NULL, r, r->connection);
 
218
        ap_add_output_filter_handle(ap_http_outerror_filter_handle,
 
219
                                    NULL, r, r->connection);
 
220
    }
 
221
 
 
222
    return OK;
 
223
}
 
224
 
 
225
static void register_hooks(apr_pool_t *p)
 
226
{
 
227
    /**
 
228
     * If we ae using an MPM That Supports Async Connections,
 
229
     * use a different processing function
 
230
     */
 
231
    int async_mpm = 0;
 
232
    if (ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm) == APR_SUCCESS
 
233
        && async_mpm == 1) {
 
234
        ap_hook_process_connection(ap_process_http_async_connection, NULL,
 
235
                                   NULL, APR_HOOK_REALLY_LAST);
 
236
    }
 
237
    else {
 
238
        ap_hook_process_connection(ap_process_http_connection, NULL, NULL,
 
239
                                   APR_HOOK_REALLY_LAST);
 
240
    }
 
241
 
 
242
    ap_hook_map_to_storage(ap_send_http_trace,NULL,NULL,APR_HOOK_MIDDLE);
 
243
    ap_hook_http_scheme(http_scheme,NULL,NULL,APR_HOOK_REALLY_LAST);
 
244
    ap_hook_default_port(http_port,NULL,NULL,APR_HOOK_REALLY_LAST);
 
245
    ap_hook_create_request(http_create_request, NULL, NULL, APR_HOOK_REALLY_LAST);
 
246
    ap_http_input_filter_handle =
 
247
        ap_register_input_filter("HTTP_IN", ap_http_filter,
 
248
                                 NULL, AP_FTYPE_PROTOCOL);
 
249
    ap_http_header_filter_handle =
 
250
        ap_register_output_filter("HTTP_HEADER", ap_http_header_filter,
 
251
                                  NULL, AP_FTYPE_PROTOCOL);
 
252
    ap_chunk_filter_handle =
 
253
        ap_register_output_filter("CHUNK", ap_http_chunk_filter,
 
254
                                  NULL, AP_FTYPE_TRANSCODE);
 
255
    ap_http_outerror_filter_handle =
 
256
        ap_register_output_filter("HTTP_OUTERROR", ap_http_outerror_filter,
 
257
                                  NULL, AP_FTYPE_PROTOCOL);
 
258
    ap_byterange_filter_handle =
 
259
        ap_register_output_filter("BYTERANGE", ap_byterange_filter,
 
260
                                  NULL, AP_FTYPE_PROTOCOL);
 
261
    ap_method_registry_init(p);
 
262
}
 
263
 
 
264
module AP_MODULE_DECLARE_DATA http_module = {
 
265
    STANDARD20_MODULE_STUFF,
 
266
    NULL,              /* create per-directory config structure */
 
267
    NULL,              /* merge per-directory config structures */
 
268
    NULL,              /* create per-server config structure */
 
269
    NULL,              /* merge per-server config structures */
 
270
    http_cmds,         /* command apr_table_t */
 
271
    register_hooks     /* register hooks */
 
272
};