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