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