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