]> granicus.if.org Git - apache/blob - server/core_filters.c
Move two variable assignments off the fast path.
[apache] / server / core_filters.c
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 /**
18  * @file  core_filters.c
19  * @brief Core input/output network filters.
20  */
21
22 #include "apr.h"
23 #include "apr_strings.h"
24 #include "apr_lib.h"
25 #include "apr_fnmatch.h"
26 #include "apr_hash.h"
27 #include "apr_thread_proc.h"    /* for RLIMIT stuff */
28
29 #define APR_WANT_IOVEC
30 #define APR_WANT_STRFUNC
31 #define APR_WANT_MEMFUNC
32 #include "apr_want.h"
33
34 #include "ap_config.h"
35 #include "httpd.h"
36 #include "http_config.h"
37 #include "http_core.h"
38 #include "http_protocol.h" /* For index_of_response().  Grump. */
39 #include "http_request.h"
40 #include "http_vhost.h"
41 #include "http_main.h"     /* For the default_handler below... */
42 #include "http_log.h"
43 #include "util_md5.h"
44 #include "http_connection.h"
45 #include "apr_buckets.h"
46 #include "util_filter.h"
47 #include "util_ebcdic.h"
48 #include "mpm_common.h"
49 #include "scoreboard.h"
50 #include "mod_core.h"
51 #include "mod_proxy.h"
52 #include "ap_listen.h"
53
54 #include "mod_so.h" /* for ap_find_loaded_module_symbol */
55
56 #define AP_MIN_SENDFILE_BYTES           (256)
57
58 /**
59  * Remove all zero length buckets from the brigade.
60  */
61 #define BRIGADE_NORMALIZE(b) \
62 do { \
63     apr_bucket *e = APR_BRIGADE_FIRST(b); \
64     do {  \
65         if (e->length == 0 && !APR_BUCKET_IS_METADATA(e)) { \
66             apr_bucket *d; \
67             d = APR_BUCKET_NEXT(e); \
68             apr_bucket_delete(e); \
69             e = d; \
70         } \
71         else { \
72             e = APR_BUCKET_NEXT(e); \
73         } \
74     } while (!APR_BRIGADE_EMPTY(b) && (e != APR_BRIGADE_SENTINEL(b))); \
75 } while (0)
76
77 /* we know core's module_index is 0 */
78 #undef APLOG_MODULE_INDEX
79 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
80
81 struct core_output_filter_ctx {
82     apr_bucket_brigade *buffered_bb;
83     apr_bucket_brigade *tmp_flush_bb;
84     apr_pool_t *deferred_write_pool;
85     apr_size_t bytes_written;
86 };
87
88 struct core_filter_ctx {
89     apr_bucket_brigade *b;
90     apr_bucket_brigade *tmpbb;
91 };
92
93
94 apr_status_t ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b,
95                                   ap_input_mode_t mode, apr_read_type_e block,
96                                   apr_off_t readbytes)
97 {
98     apr_status_t rv;
99     core_net_rec *net = f->ctx;
100     core_ctx_t *ctx = net->in_ctx;
101     const char *str;
102     apr_size_t len;
103
104     if (mode == AP_MODE_INIT) {
105         /*
106          * this mode is for filters that might need to 'initialize'
107          * a connection before reading request data from a client.
108          * NNTP over SSL for example needs to handshake before the
109          * server sends the welcome message.
110          * such filters would have changed the mode before this point
111          * is reached.  however, protocol modules such as NNTP should
112          * not need to know anything about SSL.  given the example, if
113          * SSL is not in the filter chain, AP_MODE_INIT is a noop.
114          */
115         return APR_SUCCESS;
116     }
117
118     if (!ctx)
119     {
120         net->in_ctx = ctx = apr_palloc(f->c->pool, sizeof(*ctx));
121         ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
122         ctx->tmpbb = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
123         /* seed the brigade with the client socket. */
124         rv = ap_run_insert_network_bucket(f->c, ctx->b, net->client_socket);
125         if (rv != APR_SUCCESS)
126             return rv;
127     }
128     else if (APR_BRIGADE_EMPTY(ctx->b)) {
129         return APR_EOF;
130     }
131
132     /* ### This is bad. */
133     BRIGADE_NORMALIZE(ctx->b);
134
135     /* check for empty brigade again *AFTER* BRIGADE_NORMALIZE()
136      * If we have lost our socket bucket (see above), we are EOF.
137      *
138      * Ideally, this should be returning SUCCESS with EOS bucket, but
139      * some higher-up APIs (spec. read_request_line via ap_rgetline)
140      * want an error code. */
141     if (APR_BRIGADE_EMPTY(ctx->b)) {
142         return APR_EOF;
143     }
144
145     if (mode == AP_MODE_GETLINE) {
146         /* we are reading a single LF line, e.g. the HTTP headers */
147         rv = apr_brigade_split_line(b, ctx->b, block, HUGE_STRING_LEN);
148         /* We should treat EAGAIN here the same as we do for EOF (brigade is
149          * empty).  We do this by returning whatever we have read.  This may
150          * or may not be bogus, but is consistent (for now) with EOF logic.
151          */
152         if (APR_STATUS_IS_EAGAIN(rv) && block == APR_NONBLOCK_READ) {
153             rv = APR_SUCCESS;
154         }
155         return rv;
156     }
157
158     /* ### AP_MODE_PEEK is a horrific name for this mode because we also
159      * eat any CRLFs that we see.  That's not the obvious intention of
160      * this mode.  Determine whether anyone actually uses this or not. */
161     if (mode == AP_MODE_EATCRLF) {
162         apr_bucket *e;
163         const char *c;
164
165         /* The purpose of this loop is to ignore any CRLF (or LF) at the end
166          * of a request.  Many browsers send extra lines at the end of POST
167          * requests.  We use the PEEK method to determine if there is more
168          * data on the socket, so that we know if we should delay sending the
169          * end of one request until we have served the second request in a
170          * pipelined situation.  We don't want to actually delay sending a
171          * response if the server finds a CRLF (or LF), becuause that doesn't
172          * mean that there is another request, just a blank line.
173          */
174         while (1) {
175             if (APR_BRIGADE_EMPTY(ctx->b))
176                 return APR_EOF;
177
178             e = APR_BRIGADE_FIRST(ctx->b);
179
180             rv = apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
181
182             if (rv != APR_SUCCESS)
183                 return rv;
184
185             c = str;
186             while (c < str + len) {
187                 if (*c == APR_ASCII_LF)
188                     c++;
189                 else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF)
190                     c += 2;
191                 else
192                     return APR_SUCCESS;
193             }
194
195             /* If we reach here, we were a bucket just full of CRLFs, so
196              * just toss the bucket. */
197             /* FIXME: Is this the right thing to do in the core? */
198             apr_bucket_delete(e);
199         }
200         return APR_SUCCESS;
201     }
202
203     /* If mode is EXHAUSTIVE, we want to just read everything until the end
204      * of the brigade, which in this case means the end of the socket.
205      * To do this, we attach the brigade that has currently been setaside to
206      * the brigade that was passed down, and send that brigade back.
207      *
208      * NOTE:  This is VERY dangerous to use, and should only be done with
209      * extreme caution.  FWLIW, this would be needed by an MPM like Perchild;
210      * such an MPM can easily request the socket and all data that has been
211      * read, which means that it can pass it to the correct child process.
212      */
213     if (mode == AP_MODE_EXHAUSTIVE) {
214         apr_bucket *e;
215
216         /* Tack on any buckets that were set aside. */
217         APR_BRIGADE_CONCAT(b, ctx->b);
218
219         /* Since we've just added all potential buckets (which will most
220          * likely simply be the socket bucket) we know this is the end,
221          * so tack on an EOS too. */
222         /* We have read until the brigade was empty, so we know that we
223          * must be EOS. */
224         e = apr_bucket_eos_create(f->c->bucket_alloc);
225         APR_BRIGADE_INSERT_TAIL(b, e);
226         return APR_SUCCESS;
227     }
228
229     /* read up to the amount they specified. */
230     if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE) {
231         apr_bucket *e;
232
233         AP_DEBUG_ASSERT(readbytes > 0);
234
235         e = APR_BRIGADE_FIRST(ctx->b);
236         rv = apr_bucket_read(e, &str, &len, block);
237
238         if (APR_STATUS_IS_EAGAIN(rv) && block == APR_NONBLOCK_READ) {
239             /* getting EAGAIN for a blocking read is an error; for a
240              * non-blocking read, return an empty brigade. */
241             return APR_SUCCESS;
242         }
243         else if (rv != APR_SUCCESS) {
244             return rv;
245         }
246         else if (block == APR_BLOCK_READ && len == 0) {
247             /* We wanted to read some bytes in blocking mode.  We read
248              * 0 bytes.  Hence, we now assume we are EOS.
249              *
250              * When we are in normal mode, return an EOS bucket to the
251              * caller.
252              * When we are in speculative mode, leave ctx->b empty, so
253              * that the next call returns an EOS bucket.
254              */
255             apr_bucket_delete(e);
256
257             if (mode == AP_MODE_READBYTES) {
258                 e = apr_bucket_eos_create(f->c->bucket_alloc);
259                 APR_BRIGADE_INSERT_TAIL(b, e);
260             }
261             return APR_SUCCESS;
262         }
263
264         /* Have we read as much data as we wanted (be greedy)? */
265         if (len < readbytes) {
266             apr_size_t bucket_len;
267
268             rv = APR_SUCCESS;
269             /* We already registered the data in e in len */
270             e = APR_BUCKET_NEXT(e);
271             while ((len < readbytes) && (rv == APR_SUCCESS)
272                    && (e != APR_BRIGADE_SENTINEL(ctx->b))) {
273                 /* Check for the availability of buckets with known length */
274                 if (e->length != -1) {
275                     len += e->length;
276                     e = APR_BUCKET_NEXT(e);
277                 }
278                 else {
279                     /*
280                      * Read from bucket, but non blocking. If there isn't any
281                      * more data, well than this is fine as well, we will
282                      * not wait for more since we already got some and we are
283                      * only checking if there isn't more.
284                      */
285                     rv = apr_bucket_read(e, &str, &bucket_len,
286                                          APR_NONBLOCK_READ);
287                     if (rv == APR_SUCCESS) {
288                         len += bucket_len;
289                         e = APR_BUCKET_NEXT(e);
290                     }
291                 }
292             }
293         }
294
295         /* We can only return at most what we read. */
296         if (len < readbytes) {
297             readbytes = len;
298         }
299
300         rv = apr_brigade_partition(ctx->b, readbytes, &e);
301         if (rv != APR_SUCCESS) {
302             return rv;
303         }
304
305         /* Must do move before CONCAT */
306         ctx->tmpbb = apr_brigade_split_ex(ctx->b, e, ctx->tmpbb);
307
308         if (mode == AP_MODE_READBYTES) {
309             APR_BRIGADE_CONCAT(b, ctx->b);
310         }
311         else if (mode == AP_MODE_SPECULATIVE) {
312             apr_bucket *copy_bucket;
313
314             for (e = APR_BRIGADE_FIRST(ctx->b);
315                  e != APR_BRIGADE_SENTINEL(ctx->b);
316                  e = APR_BUCKET_NEXT(e))
317             {
318                 rv = apr_bucket_copy(e, &copy_bucket);
319                 if (rv != APR_SUCCESS) {
320                     return rv;
321                 }
322                 APR_BRIGADE_INSERT_TAIL(b, copy_bucket);
323             }
324         }
325
326         /* Take what was originally there and place it back on ctx->b */
327         APR_BRIGADE_CONCAT(ctx->b, ctx->tmpbb);
328     }
329     return APR_SUCCESS;
330 }
331
332 static void setaside_remaining_output(ap_filter_t *f,
333                                       core_output_filter_ctx_t *ctx,
334                                       apr_bucket_brigade *bb,
335                                       conn_rec *c);
336
337 static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
338                                              apr_bucket_brigade *bb,
339                                              apr_size_t *bytes_written,
340                                              conn_rec *c);
341
342 static void remove_empty_buckets(apr_bucket_brigade *bb);
343
344 static apr_status_t send_brigade_blocking(apr_socket_t *s,
345                                           apr_bucket_brigade *bb,
346                                           apr_size_t *bytes_written,
347                                           conn_rec *c);
348
349 static apr_status_t writev_nonblocking(apr_socket_t *s,
350                                        struct iovec *vec, apr_size_t nvec,
351                                        apr_bucket_brigade *bb,
352                                        apr_size_t *cumulative_bytes_written,
353                                        conn_rec *c);
354
355 #if APR_HAS_SENDFILE
356 static apr_status_t sendfile_nonblocking(apr_socket_t *s,
357                                          apr_bucket *bucket,
358                                          apr_size_t *cumulative_bytes_written,
359                                          conn_rec *c);
360 #endif
361
362 /* XXX: Should these be configurable parameters? */
363 #define THRESHOLD_MIN_WRITE 4096
364 #define THRESHOLD_MAX_BUFFER 65536
365 #define MAX_REQUESTS_IN_PIPELINE 5
366
367 /* Optional function coming from mod_logio, used for logging of output
368  * traffic
369  */
370 extern APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *ap__logio_add_bytes_out;
371
372 apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
373 {
374     conn_rec *c = f->c;
375     core_net_rec *net = f->ctx;
376     core_output_filter_ctx_t *ctx = net->out_ctx;
377     apr_bucket_brigade *bb = NULL;
378     apr_bucket *bucket, *next, *flush_upto = NULL;
379     apr_size_t bytes_in_brigade, non_file_bytes_in_brigade;
380     int eor_buckets_in_brigade, morphing_bucket_in_brigade;
381     apr_status_t rv;
382     int loglevel = ap_get_conn_module_loglevel(c, APLOG_MODULE_INDEX);
383
384     /* Fail quickly if the connection has already been aborted. */
385     if (c->aborted) {
386         if (new_bb != NULL) {
387             apr_brigade_cleanup(new_bb);
388         }
389         return APR_ECONNABORTED;
390     }
391
392     if (ctx == NULL) {
393         ctx = apr_pcalloc(c->pool, sizeof(*ctx));
394         net->out_ctx = (core_output_filter_ctx_t *)ctx;
395         /*
396          * Need to create tmp brigade with correct lifetime. Passing
397          * NULL to apr_brigade_split_ex would result in a brigade
398          * allocated from bb->pool which might be wrong.
399          */
400         ctx->tmp_flush_bb = apr_brigade_create(c->pool, c->bucket_alloc);
401         /* same for buffered_bb and ap_save_brigade */
402         ctx->buffered_bb = apr_brigade_create(c->pool, c->bucket_alloc);
403     }
404
405     if (new_bb != NULL)
406         bb = new_bb;
407
408     if ((ctx->buffered_bb != NULL) &&
409         !APR_BRIGADE_EMPTY(ctx->buffered_bb)) {
410         if (new_bb != NULL) {
411             APR_BRIGADE_PREPEND(bb, ctx->buffered_bb);
412         }
413         else {
414             bb = ctx->buffered_bb;
415         }
416         c->data_in_output_filters = 0;
417     }
418     else if (new_bb == NULL) {
419         return APR_SUCCESS;
420     }
421
422     /* Scan through the brigade and decide whether to attempt a write,
423      * and how much to write, based on the following rules:
424      *
425      *  1) The new_bb is null: Do a nonblocking write of as much as
426      *     possible: do a nonblocking write of as much data as possible,
427      *     then save the rest in ctx->buffered_bb.  (If new_bb == NULL,
428      *     it probably means that the MPM is doing asynchronous write
429      *     completion and has just determined that this connection
430      *     is writable.)
431      *
432      *  2) Determine if and up to which bucket we need to do a blocking
433      *     write:
434      *
435      *  a) The brigade contains a flush bucket: Do a blocking write
436      *     of everything up that point.
437      *
438      *  b) The request is in CONN_STATE_HANDLER state, and the brigade
439      *     contains at least THRESHOLD_MAX_BUFFER bytes in non-file
440      *     buckets: Do blocking writes until the amount of data in the
441      *     buffer is less than THRESHOLD_MAX_BUFFER.  (The point of this
442      *     rule is to provide flow control, in case a handler is
443      *     streaming out lots of data faster than the data can be
444      *     sent to the client.)
445      *
446      *  c) The request is in CONN_STATE_HANDLER state, and the brigade
447      *     contains at least MAX_REQUESTS_IN_PIPELINE EOR buckets:
448      *     Do blocking writes until less than MAX_REQUESTS_IN_PIPELINE EOR
449      *     buckets are left. (The point of this rule is to prevent too many
450      *     FDs being kept open by pipelined requests, possibly allowing a
451      *     DoS).
452      *
453      *  d) The brigade contains a morphing bucket: If there was no other
454      *     reason to do a blocking write yet, try reading the bucket. If its
455      *     contents fit into memory before THRESHOLD_MAX_BUFFER is reached,
456      *     everything is fine. Otherwise we need to do a blocking write the
457      *     up to and including the morphing bucket, because ap_save_brigade()
458      *     would read the whole bucket into memory later on.
459      *
460      *  3) Actually do the blocking write up to the last bucket determined
461      *     by rules 2a-d. The point of doing only one flush is to make as
462      *     few calls to writev() as possible.
463      *
464      *  4) If the brigade contains at least THRESHOLD_MIN_WRITE
465      *     bytes: Do a nonblocking write of as much data as possible,
466      *     then save the rest in ctx->buffered_bb.
467      */
468
469     if (new_bb == NULL) {
470         rv = send_brigade_nonblocking(net->client_socket, bb,
471                                       &(ctx->bytes_written), c);
472         if (APR_STATUS_IS_EAGAIN(rv)) {
473             rv = APR_SUCCESS;
474         }
475         else if (rv != APR_SUCCESS) {
476             /* The client has aborted the connection */
477             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
478                           "core_output_filter: writing data to the network");
479             c->aborted = 1;
480         }
481         setaside_remaining_output(f, ctx, bb, c);
482         return rv;
483     }
484
485     bytes_in_brigade = 0;
486     non_file_bytes_in_brigade = 0;
487     eor_buckets_in_brigade = 0;
488     morphing_bucket_in_brigade = 0;
489
490     for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb);
491          bucket = next) {
492         next = APR_BUCKET_NEXT(bucket);
493
494         if (!APR_BUCKET_IS_METADATA(bucket)) {
495             if (bucket->length == (apr_size_t)-1) {
496                 /*
497                  * A setaside of morphing buckets would read everything into
498                  * memory. Instead, we will flush everything up to and
499                  * including this bucket.
500                  */
501                 morphing_bucket_in_brigade = 1;
502             }
503             else {
504                 bytes_in_brigade += bucket->length;
505                 if (!APR_BUCKET_IS_FILE(bucket))
506                     non_file_bytes_in_brigade += bucket->length;
507             }
508         }
509         else if (AP_BUCKET_IS_EOR(bucket)) {
510             eor_buckets_in_brigade++;
511         }
512
513         if (APR_BUCKET_IS_FLUSH(bucket)
514             || non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER
515             || morphing_bucket_in_brigade
516             || eor_buckets_in_brigade > MAX_REQUESTS_IN_PIPELINE) {
517             /* this segment of the brigade MUST be sent before returning. */
518
519             if (loglevel >= APLOG_TRACE6) {
520                 char *reason = APR_BUCKET_IS_FLUSH(bucket) ?
521                                "FLUSH bucket" :
522                                (non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER) ?
523                                "THRESHOLD_MAX_BUFFER" :
524                                morphing_bucket_in_brigade ? "morphing bucket" :
525                                "MAX_REQUESTS_IN_PIPELINE";
526                 ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, c,
527                               "will flush because of %s", reason);
528                 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
529                               "seen in brigade%s: bytes: %" APR_SIZE_T_FMT
530                               ", non-file bytes: %" APR_SIZE_T_FMT ", eor "
531                               "buckets: %d, morphing buckets: %d",
532                               flush_upto == NULL ? " so far"
533                                                  : " since last flush point",
534                               bytes_in_brigade,
535                               non_file_bytes_in_brigade,
536                               eor_buckets_in_brigade,
537                               morphing_bucket_in_brigade);
538             }
539             /*
540              * Defer the actual blocking write to avoid doing many writes.
541              */
542             flush_upto = next;
543
544             bytes_in_brigade = 0;
545             non_file_bytes_in_brigade = 0;
546             eor_buckets_in_brigade = 0;
547             morphing_bucket_in_brigade = 0;
548         }
549     }
550
551     if (flush_upto != NULL) {
552         ctx->tmp_flush_bb = apr_brigade_split_ex(bb, flush_upto,
553                                                  ctx->tmp_flush_bb);
554         if (loglevel >= APLOG_TRACE8) {
555                 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
556                               "flushing now");
557         }
558         rv = send_brigade_blocking(net->client_socket, bb,
559                                    &(ctx->bytes_written), c);
560         if (rv != APR_SUCCESS) {
561             /* The client has aborted the connection */
562             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
563                           "core_output_filter: writing data to the network");
564             c->aborted = 1;
565             return rv;
566         }
567         if (loglevel >= APLOG_TRACE8) {
568                 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
569                               "total bytes written: %" APR_SIZE_T_FMT,
570                               ctx->bytes_written);
571         }
572         APR_BRIGADE_CONCAT(bb, ctx->tmp_flush_bb);
573     }
574
575     if (loglevel >= APLOG_TRACE8) {
576         ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
577                       "brigade contains: bytes: %" APR_SIZE_T_FMT
578                       ", non-file bytes: %" APR_SIZE_T_FMT
579                       ", eor buckets: %d, morphing buckets: %d",
580                       bytes_in_brigade, non_file_bytes_in_brigade,
581                       eor_buckets_in_brigade, morphing_bucket_in_brigade);
582     }
583
584     if (bytes_in_brigade >= THRESHOLD_MIN_WRITE) {
585         rv = send_brigade_nonblocking(net->client_socket, bb,
586                                       &(ctx->bytes_written), c);
587         if ((rv != APR_SUCCESS) && (!APR_STATUS_IS_EAGAIN(rv))) {
588             /* The client has aborted the connection */
589             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
590                           "core_output_filter: writing data to the network");
591             c->aborted = 1;
592             return rv;
593         }
594         if (loglevel >= APLOG_TRACE8) {
595                 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
596                               "tried nonblocking write, total bytes "
597                               "written: %" APR_SIZE_T_FMT,
598                               ctx->bytes_written);
599         }
600     }
601
602     setaside_remaining_output(f, ctx, bb, c);
603     return APR_SUCCESS;
604 }
605
606 /*
607  * This function assumes that either ctx->buffered_bb == NULL, or
608  * ctx->buffered_bb is empty, or ctx->buffered_bb == bb
609  */
610 static void setaside_remaining_output(ap_filter_t *f,
611                                       core_output_filter_ctx_t *ctx,
612                                       apr_bucket_brigade *bb,
613                                       conn_rec *c)
614 {
615     if (bb == NULL) {
616         return;
617     }
618     remove_empty_buckets(bb);
619     if (!APR_BRIGADE_EMPTY(bb)) {
620         c->data_in_output_filters = 1;
621         if (bb != ctx->buffered_bb) {
622             if (!ctx->deferred_write_pool) {
623                 apr_pool_create(&ctx->deferred_write_pool, c->pool);
624                 apr_pool_tag(ctx->deferred_write_pool, "deferred_write");
625             }
626             ap_save_brigade(f, &(ctx->buffered_bb), &bb,
627                             ctx->deferred_write_pool);
628             apr_brigade_cleanup(bb);
629         }
630     }
631     else if (ctx->deferred_write_pool) {
632         /*
633          * There are no more requests in the pipeline. We can just clear the
634          * pool.
635          */
636         apr_pool_clear(ctx->deferred_write_pool);
637     }
638 }
639
640 #ifndef APR_MAX_IOVEC_SIZE
641 #define MAX_IOVEC_TO_WRITE 16
642 #else
643 #if APR_MAX_IOVEC_SIZE > 16
644 #define MAX_IOVEC_TO_WRITE 16
645 #else
646 #define MAX_IOVEC_TO_WRITE APR_MAX_IOVEC_SIZE
647 #endif
648 #endif
649
650 static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
651                                              apr_bucket_brigade *bb,
652                                              apr_size_t *bytes_written,
653                                              conn_rec *c)
654 {
655     apr_bucket *bucket, *next;
656     apr_status_t rv;
657     struct iovec vec[MAX_IOVEC_TO_WRITE];
658     apr_size_t nvec = 0;
659
660     remove_empty_buckets(bb);
661
662     for (bucket = APR_BRIGADE_FIRST(bb);
663          bucket != APR_BRIGADE_SENTINEL(bb);
664          bucket = next) {
665         next = APR_BUCKET_NEXT(bucket);
666 #if APR_HAS_SENDFILE
667         if (APR_BUCKET_IS_FILE(bucket)) {
668             apr_bucket_file *file_bucket = (apr_bucket_file *)(bucket->data);
669             apr_file_t *fd = file_bucket->fd;
670             /* Use sendfile to send this file unless:
671              *   - the platform doesn't support sendfile,
672              *   - the file is too small for sendfile to be useful, or
673              *   - sendfile is disabled in the httpd config via "EnableSendfile off"
674              */
675
676             if ((apr_file_flags_get(fd) & APR_SENDFILE_ENABLED) &&
677                 (bucket->length >= AP_MIN_SENDFILE_BYTES)) {
678                 if (nvec > 0) {
679                     (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);
680                     rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
681                     nvec = 0;
682                     if (rv != APR_SUCCESS) {
683                         (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
684                         return rv;
685                     }
686                 }
687                 rv = sendfile_nonblocking(s, bucket, bytes_written, c);
688                 if (nvec > 0) {
689                     (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
690                 }
691                 if (rv != APR_SUCCESS) {
692                     return rv;
693                 }
694                 break;
695             }
696         }
697 #endif /* APR_HAS_SENDFILE */
698         /* didn't sendfile */
699         if (!APR_BUCKET_IS_METADATA(bucket)) {
700             const char *data;
701             apr_size_t length;
702             
703             /* Non-blocking read first, in case this is a morphing
704              * bucket type. */
705             rv = apr_bucket_read(bucket, &data, &length, APR_NONBLOCK_READ);
706             if (APR_STATUS_IS_EAGAIN(rv)) {
707                 /* Read would block; flush any pending data and retry. */
708                 if (nvec) {
709                     rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
710                     if (rv) {
711                         return rv;
712                     }
713                     nvec = 0;
714                 }
715                 
716                 rv = apr_bucket_read(bucket, &data, &length, APR_BLOCK_READ);
717             }
718             if (rv != APR_SUCCESS) {
719                 return rv;
720             }
721
722             /* reading may have split the bucket, so recompute next: */
723             next = APR_BUCKET_NEXT(bucket);
724             vec[nvec].iov_base = (char *)data;
725             vec[nvec].iov_len = length;
726             nvec++;
727             if (nvec == MAX_IOVEC_TO_WRITE) {
728                 rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
729                 nvec = 0;
730                 if (rv != APR_SUCCESS) {
731                     return rv;
732                 }
733                 break;
734             }
735         }
736     }
737
738     if (nvec > 0) {
739         rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
740         if (rv != APR_SUCCESS) {
741             return rv;
742         }
743     }
744
745     remove_empty_buckets(bb);
746
747     return APR_SUCCESS;
748 }
749
750 static void remove_empty_buckets(apr_bucket_brigade *bb)
751 {
752     apr_bucket *bucket;
753     while (((bucket = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) &&
754            (APR_BUCKET_IS_METADATA(bucket) || (bucket->length == 0))) {
755         APR_BUCKET_REMOVE(bucket);
756         apr_bucket_destroy(bucket);
757     }
758 }
759
760 static apr_status_t send_brigade_blocking(apr_socket_t *s,
761                                           apr_bucket_brigade *bb,
762                                           apr_size_t *bytes_written,
763                                           conn_rec *c)
764 {
765     apr_status_t rv;
766
767     rv = APR_SUCCESS;
768     while (!APR_BRIGADE_EMPTY(bb)) {
769         rv = send_brigade_nonblocking(s, bb, bytes_written, c);
770         if (rv != APR_SUCCESS) {
771             if (APR_STATUS_IS_EAGAIN(rv)) {
772                 /* Wait until we can send more data */
773                 apr_int32_t nsds;
774                 apr_interval_time_t timeout;
775                 apr_pollfd_t pollset;
776
777                 pollset.p = c->pool;
778                 pollset.desc_type = APR_POLL_SOCKET;
779                 pollset.reqevents = APR_POLLOUT;
780                 pollset.desc.s = s;
781                 apr_socket_timeout_get(s, &timeout);
782                 do {
783                     rv = apr_poll(&pollset, 1, &nsds, timeout);
784                 } while (APR_STATUS_IS_EINTR(rv));
785                 if (rv != APR_SUCCESS) {
786                     break;
787                 }
788             }
789             else {
790                 break;
791             }
792         }
793     }
794     return rv;
795 }
796
797 static apr_status_t writev_nonblocking(apr_socket_t *s,
798                                        struct iovec *vec, apr_size_t nvec,
799                                        apr_bucket_brigade *bb,
800                                        apr_size_t *cumulative_bytes_written,
801                                        conn_rec *c)
802 {
803     apr_status_t rv = APR_SUCCESS, arv;
804     apr_size_t bytes_written = 0, bytes_to_write = 0;
805     apr_size_t i, offset;
806     apr_interval_time_t old_timeout;
807
808     arv = apr_socket_timeout_get(s, &old_timeout);
809     if (arv != APR_SUCCESS) {
810         return arv;
811     }
812     arv = apr_socket_timeout_set(s, 0);
813     if (arv != APR_SUCCESS) {
814         return arv;
815     }
816
817     for (i = 0; i < nvec; i++) {
818         bytes_to_write += vec[i].iov_len;
819     }
820     offset = 0;
821     while (bytes_written < bytes_to_write) {
822         apr_size_t n = 0;
823         rv = apr_socket_sendv(s, vec + offset, nvec - offset, &n);
824         if (n > 0) {
825             bytes_written += n;
826             for (i = offset; i < nvec; ) {
827                 apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
828                 if (APR_BUCKET_IS_METADATA(bucket)) {
829                     APR_BUCKET_REMOVE(bucket);
830                     apr_bucket_destroy(bucket);
831                 }
832                 else if (n >= vec[i].iov_len) {
833                     APR_BUCKET_REMOVE(bucket);
834                     apr_bucket_destroy(bucket);
835                     offset++;
836                     n -= vec[i++].iov_len;
837                 }
838                 else {
839                     apr_bucket_split(bucket, n);
840                     APR_BUCKET_REMOVE(bucket);
841                     apr_bucket_destroy(bucket);
842                     vec[i].iov_len -= n;
843                     vec[i].iov_base = (char *) vec[i].iov_base + n;
844                     break;
845                 }
846             }
847         }
848         if (rv != APR_SUCCESS) {
849             break;
850         }
851     }
852     if ((ap__logio_add_bytes_out != NULL) && (bytes_written > 0)) {
853         ap__logio_add_bytes_out(c, bytes_written);
854     }
855     *cumulative_bytes_written += bytes_written;
856
857     arv = apr_socket_timeout_set(s, old_timeout);
858     if ((arv != APR_SUCCESS) && (rv == APR_SUCCESS)) {
859         return arv;
860     }
861     else {
862         return rv;
863     }
864 }
865
866 #if APR_HAS_SENDFILE
867
868 static apr_status_t sendfile_nonblocking(apr_socket_t *s,
869                                          apr_bucket *bucket,
870                                          apr_size_t *cumulative_bytes_written,
871                                          conn_rec *c)
872 {
873     apr_status_t rv = APR_SUCCESS;
874     apr_bucket_file *file_bucket;
875     apr_file_t *fd;
876     apr_size_t file_length;
877     apr_off_t file_offset;
878     apr_size_t bytes_written = 0;
879
880     if (!APR_BUCKET_IS_FILE(bucket)) {
881         ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server, APLOGNO(00006)
882                      "core_filter: sendfile_nonblocking: "
883                      "this should never happen");
884         return APR_EGENERAL;
885     }
886     file_bucket = (apr_bucket_file *)(bucket->data);
887     fd = file_bucket->fd;
888     file_length = bucket->length;
889     file_offset = bucket->start;
890
891     if (bytes_written < file_length) {
892         apr_size_t n = file_length - bytes_written;
893         apr_status_t arv;
894         apr_interval_time_t old_timeout;
895
896         arv = apr_socket_timeout_get(s, &old_timeout);
897         if (arv != APR_SUCCESS) {
898             return arv;
899         }
900         arv = apr_socket_timeout_set(s, 0);
901         if (arv != APR_SUCCESS) {
902             return arv;
903         }
904         rv = apr_socket_sendfile(s, fd, NULL, &file_offset, &n, 0);
905         if (rv == APR_SUCCESS) {
906             bytes_written += n;
907             file_offset += n;
908         }
909         arv = apr_socket_timeout_set(s, old_timeout);
910         if ((arv != APR_SUCCESS) && (rv == APR_SUCCESS)) {
911             rv = arv;
912         }
913     }
914     if ((ap__logio_add_bytes_out != NULL) && (bytes_written > 0)) {
915         ap__logio_add_bytes_out(c, bytes_written);
916     }
917     *cumulative_bytes_written += bytes_written;
918     if ((bytes_written < file_length) && (bytes_written > 0)) {
919         apr_bucket_split(bucket, bytes_written);
920         APR_BUCKET_REMOVE(bucket);
921         apr_bucket_destroy(bucket);
922     }
923     else if (bytes_written == file_length) {
924         APR_BUCKET_REMOVE(bucket);
925         apr_bucket_destroy(bucket);
926     }
927     return rv;
928 }
929
930 #endif