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