]> granicus.if.org Git - apache/blob - server/core_filters.c
Update copyright year to 2005 and standardize on current copyright owner line.
[apache] / server / core_filters.c
1 /* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
2  * applicable.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * 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 /*
18  * core_filters.c --- Core input/output network filters.
19  */
20
21 #include "apr.h"
22 #include "apr_strings.h"
23 #include "apr_lib.h"
24 #include "apr_fnmatch.h"
25 #include "apr_hash.h"
26 #include "apr_thread_proc.h"    /* for RLIMIT stuff */
27 #include "apr_hooks.h"
28
29 #define APR_WANT_IOVEC
30 #define APR_WANT_STRFUNC
31 #define APR_WANT_MEMFUNC
32 #include "apr_want.h"
33
34 #define CORE_PRIVATE
35 #include "ap_config.h"
36 #include "httpd.h"
37 #include "http_config.h"
38 #include "http_core.h"
39 #include "http_protocol.h" /* For index_of_response().  Grump. */
40 #include "http_request.h"
41 #include "http_vhost.h"
42 #include "http_main.h"     /* For the default_handler below... */
43 #include "http_log.h"
44 #include "util_md5.h"
45 #include "http_connection.h"
46 #include "apr_buckets.h"
47 #include "util_filter.h"
48 #include "util_ebcdic.h"
49 #include "mpm.h"
50 #include "mpm_common.h"
51 #include "scoreboard.h"
52 #include "mod_core.h"
53 #include "mod_proxy.h"
54 #include "ap_listen.h"
55
56 #include "mod_so.h" /* for ap_find_loaded_module_symbol */
57
58 #define AP_MIN_SENDFILE_BYTES           (256)
59
60 typedef struct net_time_filter_ctx {
61     apr_socket_t *csd;
62     int           first_line;
63 } net_time_filter_ctx_t;
64
65 int ap_net_time_filter(ap_filter_t *f, apr_bucket_brigade *b,
66                        ap_input_mode_t mode, apr_read_type_e block,
67                        apr_off_t readbytes)
68 {
69     net_time_filter_ctx_t *ctx = f->ctx;
70     int keptalive = f->c->keepalive == AP_CONN_KEEPALIVE;
71
72     if (!ctx) {
73         f->ctx = ctx = apr_palloc(f->r->pool, sizeof(*ctx));
74         ctx->first_line = 1;
75         ctx->csd = ap_get_module_config(f->c->conn_config, &core_module);        
76     }
77
78     if (mode != AP_MODE_INIT && mode != AP_MODE_EATCRLF) {
79         if (ctx->first_line) {
80             apr_socket_timeout_set(ctx->csd, 
81                                    keptalive
82                                       ? f->c->base_server->keep_alive_timeout
83                                       : f->c->base_server->timeout);
84             ctx->first_line = 0;
85         }
86         else {
87             if (keptalive) {
88                 apr_socket_timeout_set(ctx->csd, f->c->base_server->timeout);
89             }
90         }
91     }
92     return ap_get_brigade(f->next, b, mode, block, readbytes);
93 }
94
95 /**
96  * Remove all zero length buckets from the brigade.
97  */
98 #define BRIGADE_NORMALIZE(b) \
99 do { \
100     apr_bucket *e = APR_BRIGADE_FIRST(b); \
101     do {  \
102         if (e->length == 0 && !APR_BUCKET_IS_METADATA(e)) { \
103             apr_bucket *d; \
104             d = APR_BUCKET_NEXT(e); \
105             apr_bucket_delete(e); \
106             e = d; \
107         } \
108         e = APR_BUCKET_NEXT(e); \
109     } while (!APR_BRIGADE_EMPTY(b) && (e != APR_BRIGADE_SENTINEL(b))); \
110 } while (0)
111
112 int ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b,
113                          ap_input_mode_t mode, apr_read_type_e block,
114                          apr_off_t readbytes)
115 {
116     apr_bucket *e;
117     apr_status_t rv;
118     core_net_rec *net = f->ctx;
119     core_ctx_t *ctx = net->in_ctx;
120     const char *str;
121     apr_size_t len;
122
123     if (mode == AP_MODE_INIT) {
124         /*
125          * this mode is for filters that might need to 'initialize'
126          * a connection before reading request data from a client.
127          * NNTP over SSL for example needs to handshake before the
128          * server sends the welcome message.
129          * such filters would have changed the mode before this point
130          * is reached.  however, protocol modules such as NNTP should
131          * not need to know anything about SSL.  given the example, if
132          * SSL is not in the filter chain, AP_MODE_INIT is a noop.
133          */
134         return APR_SUCCESS;
135     }
136
137     if (!ctx)
138     {
139         ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
140         ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
141
142         /* seed the brigade with the client socket. */
143         e = apr_bucket_socket_create(net->client_socket, f->c->bucket_alloc);
144         APR_BRIGADE_INSERT_TAIL(ctx->b, e);
145         net->in_ctx = ctx;
146     }
147     else if (APR_BRIGADE_EMPTY(ctx->b)) {
148         return APR_EOF;
149     }
150
151     /* ### This is bad. */
152     BRIGADE_NORMALIZE(ctx->b);
153
154     /* check for empty brigade again *AFTER* BRIGADE_NORMALIZE()
155      * If we have lost our socket bucket (see above), we are EOF.
156      *
157      * Ideally, this should be returning SUCCESS with EOS bucket, but
158      * some higher-up APIs (spec. read_request_line via ap_rgetline)
159      * want an error code. */
160     if (APR_BRIGADE_EMPTY(ctx->b)) {
161         return APR_EOF;
162     }
163
164     if (mode == AP_MODE_GETLINE) {
165         /* we are reading a single LF line, e.g. the HTTP headers */
166         rv = apr_brigade_split_line(b, ctx->b, block, HUGE_STRING_LEN);
167         /* We should treat EAGAIN here the same as we do for EOF (brigade is
168          * empty).  We do this by returning whatever we have read.  This may
169          * or may not be bogus, but is consistent (for now) with EOF logic.
170          */
171         if (APR_STATUS_IS_EAGAIN(rv)) {
172             rv = APR_SUCCESS;
173         }
174         return rv;
175     }
176
177     /* ### AP_MODE_PEEK is a horrific name for this mode because we also
178      * eat any CRLFs that we see.  That's not the obvious intention of
179      * this mode.  Determine whether anyone actually uses this or not. */
180     if (mode == AP_MODE_EATCRLF) {
181         apr_bucket *e;
182         const char *c;
183
184         /* The purpose of this loop is to ignore any CRLF (or LF) at the end
185          * of a request.  Many browsers send extra lines at the end of POST
186          * requests.  We use the PEEK method to determine if there is more
187          * data on the socket, so that we know if we should delay sending the
188          * end of one request until we have served the second request in a
189          * pipelined situation.  We don't want to actually delay sending a
190          * response if the server finds a CRLF (or LF), becuause that doesn't
191          * mean that there is another request, just a blank line.
192          */
193         while (1) {
194             if (APR_BRIGADE_EMPTY(ctx->b))
195                 return APR_EOF;
196
197             e = APR_BRIGADE_FIRST(ctx->b);
198
199             rv = apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
200
201             if (rv != APR_SUCCESS)
202                 return rv;
203
204             c = str;
205             while (c < str + len) {
206                 if (*c == APR_ASCII_LF)
207                     c++;
208                 else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF)
209                     c += 2;
210                 else
211                     return APR_SUCCESS;
212             }
213
214             /* If we reach here, we were a bucket just full of CRLFs, so
215              * just toss the bucket. */
216             /* FIXME: Is this the right thing to do in the core? */
217             apr_bucket_delete(e);
218         }
219         return APR_SUCCESS;
220     }
221
222     /* If mode is EXHAUSTIVE, we want to just read everything until the end
223      * of the brigade, which in this case means the end of the socket.
224      * To do this, we attach the brigade that has currently been setaside to
225      * the brigade that was passed down, and send that brigade back.
226      *
227      * NOTE:  This is VERY dangerous to use, and should only be done with
228      * extreme caution.  However, the Perchild MPM needs this feature
229      * if it is ever going to work correctly again.  With this, the Perchild
230      * MPM can easily request the socket and all data that has been read,
231      * which means that it can pass it to the correct child process.
232      */
233     if (mode == AP_MODE_EXHAUSTIVE) {
234         apr_bucket *e;
235
236         /* Tack on any buckets that were set aside. */
237         APR_BRIGADE_CONCAT(b, ctx->b);
238
239         /* Since we've just added all potential buckets (which will most
240          * likely simply be the socket bucket) we know this is the end,
241          * so tack on an EOS too. */
242         /* We have read until the brigade was empty, so we know that we
243          * must be EOS. */
244         e = apr_bucket_eos_create(f->c->bucket_alloc);
245         APR_BRIGADE_INSERT_TAIL(b, e);
246         return APR_SUCCESS;
247     }
248
249     /* read up to the amount they specified. */
250     if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE) {
251         apr_bucket *e;
252         apr_bucket_brigade *newbb;
253
254         AP_DEBUG_ASSERT(readbytes > 0);
255
256         e = APR_BRIGADE_FIRST(ctx->b);
257         rv = apr_bucket_read(e, &str, &len, block);
258
259         if (APR_STATUS_IS_EAGAIN(rv)) {
260             return APR_SUCCESS;
261         }
262         else if (rv != APR_SUCCESS) {
263             return rv;
264         }
265         else if (block == APR_BLOCK_READ && len == 0) {
266             /* We wanted to read some bytes in blocking mode.  We read
267              * 0 bytes.  Hence, we now assume we are EOS.
268              *
269              * When we are in normal mode, return an EOS bucket to the
270              * caller.
271              * When we are in speculative mode, leave ctx->b empty, so
272              * that the next call returns an EOS bucket.
273              */
274             apr_bucket_delete(e);
275
276             if (mode == AP_MODE_READBYTES) {
277                 e = apr_bucket_eos_create(f->c->bucket_alloc);
278                 APR_BRIGADE_INSERT_TAIL(b, e);
279             }
280             return APR_SUCCESS;
281         }
282
283         /* We can only return at most what we read. */
284         if (len < readbytes) {
285             readbytes = len;
286         }
287
288         rv = apr_brigade_partition(ctx->b, readbytes, &e);
289         if (rv != APR_SUCCESS) {
290             return rv;
291         }
292
293         /* Must do split before CONCAT */
294         newbb = apr_brigade_split(ctx->b, e);
295
296         if (mode == AP_MODE_READBYTES) {
297             APR_BRIGADE_CONCAT(b, ctx->b);
298         }
299         else if (mode == AP_MODE_SPECULATIVE) {
300             apr_bucket *copy_bucket;
301
302             for (e = APR_BRIGADE_FIRST(ctx->b);
303                  e != APR_BRIGADE_SENTINEL(ctx->b);
304                  e = APR_BUCKET_NEXT(e))
305             {
306                 rv = apr_bucket_copy(e, &copy_bucket);
307                 if (rv != APR_SUCCESS) {
308                     return rv;
309                 }
310                 APR_BRIGADE_INSERT_TAIL(b, copy_bucket);
311             }
312         }
313
314         /* Take what was originally there and place it back on ctx->b */
315         APR_BRIGADE_CONCAT(ctx->b, newbb);
316     }
317     return APR_SUCCESS;
318 }
319
320 static apr_status_t writev_it_all(apr_socket_t *s,
321                                   struct iovec *vec, int nvec,
322                                   apr_size_t len, apr_size_t *nbytes)
323 {
324     apr_size_t bytes_written = 0;
325     apr_status_t rv;
326     apr_size_t n = len;
327     int i = 0;
328
329     *nbytes = 0;
330
331     /* XXX handle checking for non-blocking socket */
332     while (bytes_written != len) {
333         rv = apr_socket_sendv(s, vec + i, nvec - i, &n);
334         *nbytes += n;
335         bytes_written += n;
336         if (rv != APR_SUCCESS)
337             return rv;
338
339         /* If the write did not complete, adjust the iovecs and issue
340          * apr_socket_sendv again
341          */
342         if (bytes_written < len) {
343             /* Skip over the vectors that have already been written */
344             apr_size_t cnt = vec[i].iov_len;
345             while (n >= cnt && i + 1 < nvec) {
346                 i++;
347                 cnt += vec[i].iov_len;
348             }
349
350             if (n < cnt) {
351                 /* Handle partial write of vec i */
352                 vec[i].iov_base = (char *) vec[i].iov_base +
353                     (vec[i].iov_len - (cnt - n));
354                 vec[i].iov_len = cnt -n;
355             }
356         }
357
358         n = len - bytes_written;
359     }
360
361     return APR_SUCCESS;
362 }
363
364 /* sendfile_it_all()
365  *  send the entire file using sendfile()
366  *  handle partial writes
367  *  return only when all bytes have been sent or an error is encountered.
368  */
369
370 #if APR_HAS_SENDFILE
371 static apr_status_t sendfile_it_all(core_net_rec *c,
372                                     apr_file_t *fd,
373                                     apr_hdtr_t *hdtr,
374                                     apr_off_t   file_offset,
375                                     apr_size_t  file_bytes_left,
376                                     apr_size_t  total_bytes_left,
377                                     apr_size_t  *bytes_sent,
378                                     apr_int32_t flags)
379 {
380     apr_status_t rv;
381 #ifdef AP_DEBUG
382     apr_interval_time_t timeout = 0;
383 #endif
384
385     AP_DEBUG_ASSERT((apr_socket_timeout_get(c->client_socket, &timeout) 
386                          == APR_SUCCESS)
387                     && timeout > 0);  /* socket must be in timeout mode */
388
389     /* Reset the bytes_sent field */
390     *bytes_sent = 0;
391
392     do {
393         apr_size_t tmplen = file_bytes_left;
394
395         rv = apr_socket_sendfile(c->client_socket, fd, hdtr, &file_offset, &tmplen,
396                                  flags);
397         *bytes_sent += tmplen;
398         total_bytes_left -= tmplen;
399         if (!total_bytes_left || rv != APR_SUCCESS) {
400             return rv;        /* normal case & error exit */
401         }
402
403         AP_DEBUG_ASSERT(total_bytes_left > 0 && tmplen > 0);
404
405         /* partial write, oooh noooo...
406          * Skip over any header data which was written
407          */
408         while (tmplen && hdtr->numheaders) {
409             if (tmplen >= hdtr->headers[0].iov_len) {
410                 tmplen -= hdtr->headers[0].iov_len;
411                 --hdtr->numheaders;
412                 ++hdtr->headers;
413             }
414             else {
415                 char *iov_base = (char *)hdtr->headers[0].iov_base;
416
417                 hdtr->headers[0].iov_len -= tmplen;
418                 iov_base += tmplen;
419                 hdtr->headers[0].iov_base = iov_base;
420                 tmplen = 0;
421             }
422         }
423
424         /* Skip over any file data which was written */
425
426         if (tmplen <= file_bytes_left) {
427             file_offset += tmplen;
428             file_bytes_left -= tmplen;
429             continue;
430         }
431
432         tmplen -= file_bytes_left;
433         file_bytes_left = 0;
434         file_offset = 0;
435
436         /* Skip over any trailer data which was written */
437
438         while (tmplen && hdtr->numtrailers) {
439             if (tmplen >= hdtr->trailers[0].iov_len) {
440                 tmplen -= hdtr->trailers[0].iov_len;
441                 --hdtr->numtrailers;
442                 ++hdtr->trailers;
443             }
444             else {
445                 char *iov_base = (char *)hdtr->trailers[0].iov_base;
446
447                 hdtr->trailers[0].iov_len -= tmplen;
448                 iov_base += tmplen;
449                 hdtr->trailers[0].iov_base = iov_base;
450                 tmplen = 0;
451             }
452         }
453     } while (1);
454 }
455 #endif
456
457 /*
458  * emulate_sendfile()
459  * Sends the contents of file fd along with header/trailer bytes, if any,
460  * to the network. emulate_sendfile will return only when all the bytes have been
461  * sent (i.e., it handles partial writes) or on a network error condition.
462  */
463 static apr_status_t emulate_sendfile(core_net_rec *c, apr_file_t *fd,
464                                      apr_hdtr_t *hdtr, apr_off_t offset,
465                                      apr_size_t length, apr_size_t *nbytes)
466 {
467     apr_status_t rv = APR_SUCCESS;
468     apr_size_t togo;        /* Remaining number of bytes in the file to send */
469     apr_size_t sendlen = 0;
470     apr_size_t bytes_sent;
471     apr_int32_t i;
472     apr_off_t o;             /* Track the file offset for partial writes */
473     char buffer[8192];
474
475     *nbytes = 0;
476
477     /* Send the headers
478      * writev_it_all handles partial writes.
479      * XXX: optimization... if headers are less than MIN_WRITE_SIZE, copy
480      * them into buffer
481      */
482     if (hdtr && hdtr->numheaders > 0 ) {
483         for (i = 0; i < hdtr->numheaders; i++) {
484             sendlen += hdtr->headers[i].iov_len;
485         }
486
487         rv = writev_it_all(c->client_socket, hdtr->headers, hdtr->numheaders,
488                            sendlen, &bytes_sent);
489         *nbytes += bytes_sent;     /* track total bytes sent */
490     }
491
492     /* Seek the file to 'offset' */
493     if (offset >= 0 && rv == APR_SUCCESS) {
494         rv = apr_file_seek(fd, APR_SET, &offset);
495     }
496
497     /* Send the file, making sure to handle partial writes */
498     togo = length;
499     while (rv == APR_SUCCESS && togo) {
500         sendlen = togo > sizeof(buffer) ? sizeof(buffer) : togo;
501         o = 0;
502         rv = apr_file_read(fd, buffer, &sendlen);
503         while (rv == APR_SUCCESS && sendlen) {
504             bytes_sent = sendlen;
505             rv = apr_socket_send(c->client_socket, &buffer[o], &bytes_sent);
506             *nbytes += bytes_sent;
507             if (rv == APR_SUCCESS) {
508                 sendlen -= bytes_sent; /* sendlen != bytes_sent ==> partial write */
509                 o += bytes_sent;       /* o is where we are in the buffer */
510                 togo -= bytes_sent;    /* track how much of the file we've sent */
511             }
512         }
513     }
514
515     /* Send the trailers
516      * XXX: optimization... if it will fit, send this on the last send in the
517      * loop above
518      */
519     sendlen = 0;
520     if ( rv == APR_SUCCESS && hdtr && hdtr->numtrailers > 0 ) {
521         for (i = 0; i < hdtr->numtrailers; i++) {
522             sendlen += hdtr->trailers[i].iov_len;
523         }
524         rv = writev_it_all(c->client_socket, hdtr->trailers, hdtr->numtrailers,
525                            sendlen, &bytes_sent);
526         *nbytes += bytes_sent;
527     }
528
529     return rv;
530 }
531
532 #ifndef APR_MAX_IOVEC_SIZE 
533 #define MAX_IOVEC_TO_WRITE 16
534 #else
535 #if APR_MAX_IOVEC_SIZE > 16
536 #define MAX_IOVEC_TO_WRITE 16
537 #else
538 #define MAX_IOVEC_TO_WRITE APR_MAX_IOVEC_SIZE
539 #endif
540 #endif
541
542 /* Optional function coming from mod_logio, used for logging of output
543  * traffic
544  */
545 extern APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *logio_add_bytes_out;
546
547 apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
548 {
549     apr_status_t rv;
550     apr_bucket_brigade *more;
551     conn_rec *c = f->c;
552     core_net_rec *net = f->ctx;
553     core_output_filter_ctx_t *ctx = net->out_ctx;
554     apr_read_type_e eblock = APR_NONBLOCK_READ;
555     apr_pool_t *input_pool = b->p;
556
557     if (ctx == NULL) {
558         ctx = apr_pcalloc(c->pool, sizeof(*ctx));
559         net->out_ctx = ctx;
560     }
561
562     /* If we have a saved brigade, concatenate the new brigade to it */
563     if (ctx->b) {
564         APR_BRIGADE_CONCAT(ctx->b, b);
565         b = ctx->b;
566         ctx->b = NULL;
567     }
568
569     /* Perform multiple passes over the brigade, sending batches of output
570        to the connection. */
571     while (b && !APR_BRIGADE_EMPTY(b)) {
572         apr_size_t nbytes = 0;
573         apr_bucket *last_e = NULL; /* initialized for debugging */
574         apr_bucket *e;
575
576         /* one group of iovecs per pass over the brigade */
577         apr_size_t nvec = 0;
578         apr_size_t nvec_trailers = 0;
579         struct iovec vec[MAX_IOVEC_TO_WRITE];
580         struct iovec vec_trailers[MAX_IOVEC_TO_WRITE];
581
582         /* one file per pass over the brigade */
583         apr_file_t *fd = NULL;
584         apr_size_t flen = 0;
585         apr_off_t foffset = 0;
586
587         /* keep track of buckets that we've concatenated
588          * to avoid small writes
589          */
590         apr_bucket *last_merged_bucket = NULL;
591
592         /* tail of brigade if we need another pass */
593         more = NULL;
594
595         /* Iterate over the brigade: collect iovecs and/or a file */
596         for (e = APR_BRIGADE_FIRST(b);
597              e != APR_BRIGADE_SENTINEL(b);
598              e = APR_BUCKET_NEXT(e))
599         {
600             /* keep track of the last bucket processed */
601             last_e = e;
602             if (APR_BUCKET_IS_EOS(e) || AP_BUCKET_IS_EOC(e)) {
603                 break;
604             }
605             else if (APR_BUCKET_IS_FLUSH(e)) {
606                 if (e != APR_BRIGADE_LAST(b)) {
607                     more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
608                 }
609                 break;
610             }
611
612             /* It doesn't make any sense to use sendfile for a file bucket
613              * that represents 10 bytes.
614              */
615             else if (APR_BUCKET_IS_FILE(e)
616                      && (e->length >= AP_MIN_SENDFILE_BYTES)) {
617                 apr_bucket_file *a = e->data;
618
619                 /* We can't handle more than one file bucket at a time
620                  * so we split here and send the file we have already
621                  * found.
622                  */
623                 if (fd) {
624                     more = apr_brigade_split(b, e);
625                     break;
626                 }
627
628                 fd = a->fd;
629                 flen = e->length;
630                 foffset = e->start;
631             }
632             else {
633                 const char *str;
634                 apr_size_t n;
635
636                 rv = apr_bucket_read(e, &str, &n, eblock);
637                 if (APR_STATUS_IS_EAGAIN(rv)) {
638                     /* send what we have so far since we shouldn't expect more
639                      * output for a while...  next time we read, block
640                      */
641                     more = apr_brigade_split(b, e);
642                     eblock = APR_BLOCK_READ;
643                     break;
644                 }
645                 eblock = APR_NONBLOCK_READ;
646                 if (n) {
647                     if (!fd) {
648                         if (nvec == MAX_IOVEC_TO_WRITE) {
649                             /* woah! too many. buffer them up, for use later. */
650                             apr_bucket *temp, *next;
651                             apr_bucket_brigade *temp_brig;
652
653                             if (nbytes >= AP_MIN_BYTES_TO_WRITE) {
654                                 /* We have enough data in the iovec
655                                  * to justify doing a writev
656                                  */
657                                 more = apr_brigade_split(b, e);
658                                 break;
659                             }
660
661                             /* Create a temporary brigade as a means
662                              * of concatenating a bunch of buckets together
663                              */
664                             if (last_merged_bucket) {
665                                 /* If we've concatenated together small
666                                  * buckets already in a previous pass,
667                                  * the initial buckets in this brigade
668                                  * are heap buckets that may have extra
669                                  * space left in them (because they
670                                  * were created by apr_brigade_write()).
671                                  * We can take advantage of this by
672                                  * building the new temp brigade out of
673                                  * these buckets, so that the content
674                                  * in them doesn't have to be copied again.
675                                  */
676                                 apr_bucket_brigade *bb;
677                                 bb = apr_brigade_split(b,
678                                          APR_BUCKET_NEXT(last_merged_bucket));
679                                 temp_brig = b;
680                                 b = bb;
681                             }
682                             else {
683                                 temp_brig = apr_brigade_create(f->c->pool,
684                                                            f->c->bucket_alloc);
685                             }
686
687                             temp = APR_BRIGADE_FIRST(b);
688                             while (temp != e) {
689                                 apr_bucket *d;
690                                 rv = apr_bucket_read(temp, &str, &n, APR_BLOCK_READ);
691                                 apr_brigade_write(temp_brig, NULL, NULL, str, n);
692                                 d = temp;
693                                 temp = APR_BUCKET_NEXT(temp);
694                                 apr_bucket_delete(d);
695                             }
696
697                             nvec = 0;
698                             nbytes = 0;
699                             temp = APR_BRIGADE_FIRST(temp_brig);
700                             APR_BUCKET_REMOVE(temp);
701                             APR_BRIGADE_INSERT_HEAD(b, temp);
702                             apr_bucket_read(temp, &str, &n, APR_BLOCK_READ);
703                             vec[nvec].iov_base = (char*) str;
704                             vec[nvec].iov_len = n;
705                             nvec++;
706
707                             /* Just in case the temporary brigade has
708                              * multiple buckets, recover the rest of
709                              * them and put them in the brigade that
710                              * we're sending.
711                              */
712                             for (next = APR_BRIGADE_FIRST(temp_brig);
713                                  next != APR_BRIGADE_SENTINEL(temp_brig);
714                                  next = APR_BRIGADE_FIRST(temp_brig)) {
715                                 APR_BUCKET_REMOVE(next);
716                                 APR_BUCKET_INSERT_AFTER(temp, next);
717                                 temp = next;
718                                 apr_bucket_read(next, &str, &n,
719                                                 APR_BLOCK_READ);
720                                 vec[nvec].iov_base = (char*) str;
721                                 vec[nvec].iov_len = n;
722                                 nvec++;
723                             }
724
725                             apr_brigade_destroy(temp_brig);
726
727                             last_merged_bucket = temp;
728                             e = temp;
729                             last_e = e;
730                         }
731                         else {
732                             vec[nvec].iov_base = (char*) str;
733                             vec[nvec].iov_len = n;
734                             nvec++;
735                         }
736                     }
737                     else {
738                         /* The bucket is a trailer to a file bucket */
739
740                         if (nvec_trailers == MAX_IOVEC_TO_WRITE) {
741                             /* woah! too many. stop now. */
742                             more = apr_brigade_split(b, e);
743                             break;
744                         }
745
746                         vec_trailers[nvec_trailers].iov_base = (char*) str;
747                         vec_trailers[nvec_trailers].iov_len = n;
748                         nvec_trailers++;
749                     }
750
751                     nbytes += n;
752                 }
753             }
754         }
755
756
757         /* Completed iterating over the brigade, now determine if we want
758          * to buffer the brigade or send the brigade out on the network.
759          *
760          * Save if we haven't accumulated enough bytes to send, the connection
761          * is not about to be closed, and:
762          *
763          *   1) we didn't see a file, we don't have more passes over the
764          *      brigade to perform,  AND we didn't stop at a FLUSH bucket.
765          *      (IOW, we will save plain old bytes such as HTTP headers)
766          * or
767          *   2) we hit the EOS and have a keep-alive connection
768          *      (IOW, this response is a bit more complex, but we save it
769          *       with the hope of concatenating with another response)
770          */
771         if (nbytes + flen < AP_MIN_BYTES_TO_WRITE
772             && !AP_BUCKET_IS_EOC(last_e)
773             && ((!fd && !more && !APR_BUCKET_IS_FLUSH(last_e))
774                 || (APR_BUCKET_IS_EOS(last_e)
775                     && c->keepalive == AP_CONN_KEEPALIVE))) {
776
777             /* NEVER save an EOS in here.  If we are saving a brigade with
778              * an EOS bucket, then we are doing keepalive connections, and
779              * we want to process to second request fully.
780              */
781             if (APR_BUCKET_IS_EOS(last_e)) {
782                 apr_bucket *bucket;
783                 int file_bucket_saved = 0;
784                 apr_bucket_delete(last_e);
785                 for (bucket = APR_BRIGADE_FIRST(b);
786                      bucket != APR_BRIGADE_SENTINEL(b);
787                      bucket = APR_BUCKET_NEXT(bucket)) {
788
789                     /* Do a read on each bucket to pull in the
790                      * data from pipe and socket buckets, so
791                      * that we don't leave their file descriptors
792                      * open indefinitely.  Do the same for file
793                      * buckets, with one exception: allow the
794                      * first file bucket in the brigade to remain
795                      * a file bucket, so that we don't end up
796                      * doing an mmap+memcpy every time a client
797                      * requests a <8KB file over a keepalive
798                      * connection.
799                      */
800                     if (APR_BUCKET_IS_FILE(bucket) && !file_bucket_saved) {
801                         file_bucket_saved = 1;
802                     }
803                     else {
804                         const char *buf;
805                         apr_size_t len = 0;
806                         rv = apr_bucket_read(bucket, &buf, &len,
807                                              APR_BLOCK_READ);
808                         if (rv != APR_SUCCESS) {
809                             ap_log_cerror(APLOG_MARK, APLOG_ERR, rv,
810                                           c, "core_output_filter:"
811                                           " Error reading from bucket.");
812                             return HTTP_INTERNAL_SERVER_ERROR;
813                         }
814                     }
815                 }
816             }
817             if (!ctx->deferred_write_pool) {
818                 apr_pool_create(&ctx->deferred_write_pool, c->pool);
819                 apr_pool_tag(ctx->deferred_write_pool, "deferred_write");
820             }
821             ap_save_brigade(f, &ctx->b, &b, ctx->deferred_write_pool);
822
823             return APR_SUCCESS;
824         }
825
826         if (fd) {
827             apr_hdtr_t hdtr;
828             apr_size_t bytes_sent;
829
830 #if APR_HAS_SENDFILE
831             apr_int32_t flags = 0;
832 #endif
833
834             memset(&hdtr, '\0', sizeof(hdtr));
835             if (nvec) {
836                 hdtr.numheaders = nvec;
837                 hdtr.headers = vec;
838             }
839
840             if (nvec_trailers) {
841                 hdtr.numtrailers = nvec_trailers;
842                 hdtr.trailers = vec_trailers;
843             }
844
845 #if APR_HAS_SENDFILE
846             if (apr_file_flags_get(fd) & APR_SENDFILE_ENABLED) {
847
848                 if (c->keepalive == AP_CONN_CLOSE && APR_BUCKET_IS_EOS(last_e)) {
849                     /* Prepare the socket to be reused */
850                     flags |= APR_SENDFILE_DISCONNECT_SOCKET;
851                 }
852
853                 rv = sendfile_it_all(net,      /* the network information   */
854                                      fd,       /* the file to send          */
855                                      &hdtr,    /* header and trailer iovecs */
856                                      foffset,  /* offset in the file to begin
857                                                   sending from              */
858                                      flen,     /* length of file            */
859                                      nbytes + flen, /* total length including
860                                                        headers              */
861                                      &bytes_sent,   /* how many bytes were
862                                                        sent                 */
863                                      flags);   /* apr_sendfile flags        */
864             }
865             else
866 #endif
867             {
868                 rv = emulate_sendfile(net, fd, &hdtr, foffset, flen,
869                                       &bytes_sent);
870             }
871
872             if (logio_add_bytes_out && bytes_sent > 0)
873                 logio_add_bytes_out(c, bytes_sent);
874
875             fd = NULL;
876         }
877         else {
878             apr_size_t bytes_sent;
879
880             rv = writev_it_all(net->client_socket,
881                                vec, nvec,
882                                nbytes, &bytes_sent);
883
884             if (logio_add_bytes_out && bytes_sent > 0)
885                 logio_add_bytes_out(c, bytes_sent);
886         }
887
888         apr_brigade_destroy(b);
889         
890         /* drive cleanups for resources which were set aside 
891          * this may occur before or after termination of the request which
892          * created the resource
893          */
894         if (ctx->deferred_write_pool) {
895             if (more && more->p == ctx->deferred_write_pool) {
896                 /* "more" belongs to the deferred_write_pool,
897                  * which is about to be cleared.
898                  */
899                 if (APR_BRIGADE_EMPTY(more)) {
900                     more = NULL;
901                 }
902                 else {
903                     /* uh oh... change more's lifetime 
904                      * to the input brigade's lifetime 
905                      */
906                     apr_bucket_brigade *tmp_more = more;
907                     more = NULL;
908                     ap_save_brigade(f, &more, &tmp_more, input_pool);
909                 }
910             }
911             apr_pool_clear(ctx->deferred_write_pool);  
912         }
913
914         if (rv != APR_SUCCESS) {
915             ap_log_cerror(APLOG_MARK, APLOG_INFO, rv, c,
916                           "core_output_filter: writing data to the network");
917
918             if (more)
919                 apr_brigade_destroy(more);
920
921             /* No need to check for SUCCESS, we did that above. */
922             if (!APR_STATUS_IS_EAGAIN(rv)) {
923                 c->aborted = 1;
924             }
925
926             /* The client has aborted, but the request was successful. We
927              * will report success, and leave it to the access and error
928              * logs to note that the connection was aborted.
929              */
930             return APR_SUCCESS;
931         }
932
933         b = more;
934         more = NULL;
935     }  /* end while () */
936
937     return APR_SUCCESS;
938 }