]> granicus.if.org Git - apache/blob - modules/http/http_core.c
76fc9dc4a148f5a0328cac83d999542deb835bec
[apache] / modules / http / http_core.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58
59 #include "apr_strings.h"
60 #include "apr_thread_proc.h"    /* for RLIMIT stuff */
61 #include "apr_lib.h"
62 #include "apr_optional.h"
63
64 #define APR_WANT_STRFUNC
65 #include "apr_want.h"
66
67 #define CORE_PRIVATE
68 #include "httpd.h"
69 #include "http_config.h"
70 #include "http_log.h"
71 #include "http_connection.h"
72 #include "http_protocol.h"      /* For index_of_response().  Grump. */
73 #include "http_request.h"
74
75 #include "util_filter.h"
76 #include "util_ebcdic.h"
77 #include "ap_mpm.h"
78 #include "scoreboard.h"
79
80 #include "mod_core.h"
81 #include "../loggers/mod_log_config.h"
82
83 static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy,
84                                           const char *arg)
85 {
86     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
87     if (err != NULL) {
88         return err;
89     }
90
91     cmd->server->keep_alive_timeout = atoi(arg);
92     return NULL;
93 }
94
95 static const char *set_keep_alive(cmd_parms *cmd, void *dummy,
96                                   const char *arg) 
97 {
98     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
99     if (err != NULL) {
100         return err;
101     }
102
103     /* We've changed it to On/Off, but used to use numbers
104      * so we accept anything but "Off" or "0" as "On"
105      */
106     if (!strcasecmp(arg, "off") || !strcmp(arg, "0")) {
107         cmd->server->keep_alive = 0;
108     }
109     else {
110         cmd->server->keep_alive = 1;
111     }
112     return NULL;
113 }
114
115 static const char *set_keep_alive_max(cmd_parms *cmd, void *dummy,
116                                       const char *arg)
117 {
118     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
119     if (err != NULL) {
120         return err;
121     }
122
123     cmd->server->keep_alive_max = atoi(arg);
124     return NULL;
125 }
126
127 static const command_rec http_cmds[] = {
128     AP_INIT_TAKE1("KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF,
129                   "Keep-Alive timeout duration (sec)"),
130     AP_INIT_TAKE1("MaxKeepAliveRequests", set_keep_alive_max, NULL, RSRC_CONF,
131      "Maximum number of Keep-Alive requests per connection, or 0 for infinite"),
132     AP_INIT_TAKE1("KeepAlive", set_keep_alive, NULL, RSRC_CONF,
133                   "Whether persistent connections should be On or Off"),
134     { NULL }
135 };
136
137 /*
138  * HTTP/1.1 chunked transfer encoding filter.
139  */
140 static apr_status_t chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
141 {
142 #define ASCII_CRLF  "\015\012"
143 #define ASCII_ZERO  "\060"
144     apr_bucket_brigade *more = NULL;
145     apr_bucket *e;
146     apr_status_t rv;
147
148     for (more = NULL; b; b = more, more = NULL) {
149         apr_off_t bytes = 0;
150         apr_bucket *eos = NULL;
151         char chunk_hdr[20]; /* enough space for the snprintf below */
152
153         APR_BRIGADE_FOREACH(e, b) {
154             if (APR_BUCKET_IS_EOS(e)) {
155                 /* there shouldn't be anything after the eos */
156                 eos = e;
157                 break;
158             }
159             else if (e->length == -1) {
160                 /* unknown amount of data (e.g. a pipe) */
161                 const char *data;
162                 apr_size_t len;
163
164                 rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
165                 if (rv != APR_SUCCESS) {
166                     return rv;
167                 }
168                 if (len > 0) {
169                     /*
170                      * There may be a new next bucket representing the
171                      * rest of the data stream on which a read() may
172                      * block so we pass down what we have so far.
173                      */
174                     bytes += len;
175                     more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
176                     break;
177                 }
178                 else {
179                     /* If there was nothing in this bucket then we can
180                      * safely move on to the next one without pausing
181                      * to pass down what we have counted up so far.
182                      */
183                     continue;
184                 }
185             }
186             else {
187                 bytes += e->length;
188             }
189         }
190
191         /*
192          * XXX: if there aren't very many bytes at this point it may
193          * be a good idea to set them aside and return for more,
194          * unless we haven't finished counting this brigade yet.
195          */
196
197         /* if there are content bytes, then wrap them in a chunk */
198         if (bytes > 0) {
199             apr_size_t hdr_len;
200
201             /*
202              * Insert the chunk header, specifying the number of bytes in
203              * the chunk.
204              */
205             /* XXX might be nice to have APR_OFF_T_FMT_HEX */
206             hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr),
207                                    "%qx" CRLF, (apr_uint64_t)bytes);
208             ap_xlate_proto_to_ascii(chunk_hdr, hdr_len);
209             e = apr_bucket_transient_create(chunk_hdr, hdr_len);
210             APR_BRIGADE_INSERT_HEAD(b, e);
211
212             /*
213              * Insert the end-of-chunk CRLF before the EOS bucket, or
214              * appended to the brigade
215              */
216             e = apr_bucket_immortal_create(ASCII_CRLF, 2);
217             if (eos != NULL) {
218                 APR_BUCKET_INSERT_BEFORE(eos, e);
219             }
220             else {
221                 APR_BRIGADE_INSERT_TAIL(b, e);
222             }
223         }
224
225         /* RFC 2616, Section 3.6.1
226          *
227          * If there is an EOS bucket, then prefix it with:
228          *   1) the last-chunk marker ("0" CRLF)
229          *   2) the trailer
230          *   3) the end-of-chunked body CRLF
231          *
232          * If there is no EOS bucket, then do nothing.
233          *
234          * XXX: it would be nice to combine this with the end-of-chunk
235          * marker above, but this is a bit more straight-forward for
236          * now.
237          */
238         if (eos != NULL) {
239             /* XXX: (2) trailers ... does not yet exist */
240             e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF /* <trailers> */ ASCII_CRLF, 5);
241             APR_BUCKET_INSERT_BEFORE(eos, e);
242         }
243
244         /* pass the brigade to the next filter. */
245         rv = ap_pass_brigade(f->next, b);
246         if (rv != APR_SUCCESS || eos != NULL) {
247             return rv;
248         }
249     }
250
251     return APR_SUCCESS;
252 }
253
254 static const char *http_method(const request_rec *r)
255     { return "http"; }
256
257 static unsigned short http_port(const request_rec *r)
258     { return DEFAULT_HTTP_PORT; }
259
260 static int ap_pre_http_connection(conn_rec *c)
261 {
262     ap_add_input_filter("HTTP_IN", NULL, NULL, c);
263     ap_add_input_filter("CORE_IN", NULL, NULL, c);
264     ap_add_output_filter("CORE", NULL, NULL, c);
265     return OK;
266 }
267  
268 static int ap_process_http_connection(conn_rec *c)
269 {
270     request_rec *r;
271  
272     /*
273      * Read and process each request found on our connection
274      * until no requests are left or we decide to close.
275      */
276  
277     ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_READ, NULL);
278     while ((r = ap_read_request(c)) != NULL) {
279  
280         /* process the request if it was read without error */
281  
282         ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_WRITE, NULL);
283         if (r->status == HTTP_OK)
284             ap_process_request(r);
285  
286         if (ap_extended_status)
287             ap_increment_counts(AP_CHILD_THREAD_FROM_ID(c->id), r);
288  
289         if (!c->keepalive || c->aborted)
290             break;
291  
292         ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_KEEPALIVE, NULL);
293         apr_pool_destroy(r->pool);
294  
295         if (ap_graceful_stop_signalled())
296             break;
297     }
298  
299     return OK;
300 }
301
302 static int read_request_line(request_rec *r)
303 {
304     char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 */
305     const char *ll = l;
306     const char *uri;
307     const char *pro;
308  
309     int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
310     int len;
311  
312     /* Read past empty lines until we get a real request line,
313      * a read error, the connection closes (EOF), or we timeout.
314      *
315      * We skip empty lines because browsers have to tack a CRLF on to the end
316      * of POSTs to support old CERN webservers.  But note that we may not
317      * have flushed any previous response completely to the client yet.
318      * We delay the flush as long as possible so that we can improve
319      * performance for clients that are pipelining requests.  If a request
320      * is pipelined then we won't block during the (implicit) read() below.
321      * If the requests aren't pipelined, then the client is still waiting
322      * for the final buffer flush from us, and we will block in the implicit
323      * read().  B_SAFEREAD ensures that the BUFF layer flushes if it will
324      * have to block during a read.
325      */
326  
327     while ((len = ap_getline(l, sizeof(l), r, 0)) <= 0) {
328         if (len < 0) {             /* includes EOF */
329             /* this is a hack to make sure that request time is set,
330              * it's not perfect, but it's better than nothing
331              */
332             r->request_time = apr_time_now();
333             return 0;
334         }
335     }
336     /* we've probably got something to do, ignore graceful restart requests */
337  
338     /* XXX - sigwait doesn't work if the signal has been SIG_IGNed (under
339      * linux 2.0 w/ glibc 2.0, anyway), and this step isn't necessary when
340      * we're running a sigwait thread anyway. If/when unthreaded mode is
341      * put back in, we should make sure to ignore this signal iff a sigwait
342      * thread isn't used. - mvsk
343  
344 #ifdef SIGWINCH
345     apr_signal(SIGWINCH, SIG_IGN);
346 #endif
347     */
348  
349     r->request_time = apr_time_now();
350     r->the_request = apr_pstrdup(r->pool, l);
351     r->method = ap_getword_white(r->pool, &ll);
352  
353 #if 0
354 /* XXX If we want to keep track of the Method, the protocol module should do
355  * it.  That support isn't in the scoreboard yet.  Hopefully next week
356  * sometime.   rbb */
357     ap_update_connection_status(AP_CHILD_THREAD_FROM_ID(conn->id), "Method", r->method);
358 #endif
359     uri = ap_getword_white(r->pool, &ll);
360  
361     /* Provide quick information about the request method as soon as known */
362  
363     r->method_number = ap_method_number_of(r->method);
364     if (r->method_number == M_GET && r->method[0] == 'H') {
365         r->header_only = 1;
366     }
367  
368     ap_parse_uri(r, uri);
369  
370     /* ap_getline returns (size of max buffer - 1) if it fills up the
371      * buffer before finding the end-of-line.  This is only going to
372      * happen if it exceeds the configured limit for a request-line.
373      */
374     if (len > r->server->limit_req_line) {
375         r->status    = HTTP_REQUEST_URI_TOO_LARGE;
376         r->proto_num = HTTP_VERSION(1,0);
377         r->protocol  = apr_pstrdup(r->pool, "HTTP/1.0");
378         return 0;
379     }
380  
381     if (ll[0]) {
382         r->assbackwards = 0;
383         pro = ll;
384         len = strlen(ll);
385     } else {
386         r->assbackwards = 1;
387         pro = "HTTP/0.9";
388         len = 8;
389     }
390     r->protocol = apr_pstrndup(r->pool, pro, len);
391  
392     /* XXX ap_update_connection_status(conn->id, "Protocol", r->protocol); */
393  
394     /* Avoid sscanf in the common case */
395     if (len == 8 &&
396         pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P' &&
397         pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.' &&
398         apr_isdigit(pro[7])) {
399         r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0');
400     } else if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor)
401                && minor < HTTP_VERSION(1,0))    /* don't allow HTTP/0.1000 */
402         r->proto_num = HTTP_VERSION(major, minor);
403     else
404         r->proto_num = HTTP_VERSION(1,0);
405  
406     return 1;
407 }
408
409 static int http_create_request(request_rec *r)
410 {
411     ap_http_conn_rec *hconn = ap_get_module_config(r->connection->conn_config, &http_module);
412     int keptalive;
413
414     hconn = apr_pcalloc(r->pool, sizeof(*hconn));
415     ap_set_module_config(r->connection->conn_config, &http_module, hconn);
416
417     if (!r->main && !r->prev && !r->next) {
418         keptalive = r->connection->keepalive == 1;
419         r->connection->keepalive    = 0;
420  
421         /* XXX can we optimize these timeouts at all? gstein */
422         apr_setsocketopt(r->connection->client_socket, APR_SO_TIMEOUT,
423                          (int)(keptalive
424                          ? r->server->keep_alive_timeout * APR_USEC_PER_SEC
425                          : r->server->timeout * APR_USEC_PER_SEC));
426  
427         /* Get the request... */
428         if (!read_request_line(r)) {
429             if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
430                 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
431                               "request failed: URI too long");
432                 ap_send_error_response(r, 0);
433                 ap_run_log_transaction(r);
434                 return OK;
435             }
436             return DONE;
437         }
438         if (keptalive) {
439             apr_setsocketopt(r->connection->client_socket,
440                              APR_SO_TIMEOUT,
441                              (int)(r->server->timeout * APR_USEC_PER_SEC));
442         }
443     }
444     return OK;
445 }
446
447 static const char *log_connection_status(request_rec *r, char *a)
448 {
449     ap_http_conn_rec *hconn = ap_get_module_config(r->connection->conn_config,
450                                                 &http_module);
451     if (r->connection->aborted)
452         return "X";
453  
454     if ((r->connection->keepalive) &&
455         ((r->server->keep_alive_max - hconn->keepalives) > 0)) {
456         return "+";
457     }
458  
459     return "-";
460 }
461
462 static void http_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
463 {
464     static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
465
466     log_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler);
467
468     if (log_pfn_register) {
469         log_pfn_register(p, "c", log_connection_status, 0); 
470     }
471 }
472
473 static void register_hooks(apr_pool_t *p)
474 {
475     static const char *const pred[] = { "mod_log_config.c", NULL };    
476
477     ap_hook_pre_config(http_pre_config, pred, NULL, APR_HOOK_MIDDLE);
478     ap_hook_pre_connection(ap_pre_http_connection,NULL,NULL,
479                                APR_HOOK_REALLY_LAST);
480     ap_hook_process_connection(ap_process_http_connection,NULL,NULL,
481                                APR_HOOK_REALLY_LAST);
482     ap_hook_http_method(http_method,NULL,NULL,APR_HOOK_REALLY_LAST);
483     ap_hook_default_port(http_port,NULL,NULL,APR_HOOK_REALLY_LAST);
484     ap_hook_create_request(http_create_request, NULL, NULL, APR_HOOK_MIDDLE);
485
486     ap_register_input_filter("HTTP_IN", ap_http_filter, AP_FTYPE_CONNECTION);
487     ap_register_input_filter("DECHUNK", ap_dechunk_filter, AP_FTYPE_TRANSCODE);
488     ap_register_output_filter("HTTP_HEADER", ap_http_header_filter, 
489                               AP_FTYPE_HTTP_HEADER);
490     ap_register_output_filter("CHUNK", chunk_filter, AP_FTYPE_TRANSCODE);
491     ap_register_output_filter("BYTERANGE", ap_byterange_filter,
492                               AP_FTYPE_HTTP_HEADER);
493 }
494
495 AP_DECLARE_DATA module http_module = {
496     STANDARD20_MODULE_STUFF,
497     NULL,                       /* create per-directory config structure */
498     NULL,                       /* merge per-directory config structures */
499     NULL,                       /* create per-server config structure */
500     NULL,                       /* merge per-server config structures */
501     http_cmds,                  /* command apr_table_t */
502     register_hooks              /* register hooks */
503 };