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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file core_filters.c
19 * @brief Core input/output network filters.
23 #include "apr_strings.h"
25 #include "apr_fnmatch.h"
27 #include "apr_thread_proc.h" /* for RLIMIT stuff */
29 #define APR_WANT_IOVEC
30 #define APR_WANT_STRFUNC
31 #define APR_WANT_MEMFUNC
34 #include "ap_config.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... */
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"
51 #include "mod_proxy.h"
52 #include "ap_listen.h"
54 #include "mod_so.h" /* for ap_find_loaded_module_symbol */
56 #define AP_MIN_SENDFILE_BYTES (256)
59 * Remove all zero length buckets from the brigade.
61 #define BRIGADE_NORMALIZE(b) \
63 apr_bucket *e = APR_BRIGADE_FIRST(b); \
65 if (e->length == 0 && !APR_BUCKET_IS_METADATA(e)) { \
67 d = APR_BUCKET_NEXT(e); \
68 apr_bucket_delete(e); \
72 e = APR_BUCKET_NEXT(e); \
74 } while (!APR_BRIGADE_EMPTY(b) && (e != APR_BRIGADE_SENTINEL(b))); \
77 /* we know core's module_index is 0 */
78 #undef APLOG_MODULE_INDEX
79 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
81 struct core_output_filter_ctx {
82 apr_bucket_brigade *buffered_bb;
83 apr_bucket_brigade *tmp_flush_bb;
84 apr_pool_t *deferred_write_pool;
85 apr_size_t bytes_written;
88 struct core_filter_ctx {
89 apr_bucket_brigade *b;
90 apr_bucket_brigade *tmpbb;
94 apr_status_t ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b,
95 ap_input_mode_t mode, apr_read_type_e block,
99 core_net_rec *net = f->ctx;
100 core_ctx_t *ctx = net->in_ctx;
104 if (mode == AP_MODE_INIT) {
106 * this mode is for filters that might need to 'initialize'
107 * a connection before reading request data from a client.
108 * NNTP over SSL for example needs to handshake before the
109 * server sends the welcome message.
110 * such filters would have changed the mode before this point
111 * is reached. however, protocol modules such as NNTP should
112 * not need to know anything about SSL. given the example, if
113 * SSL is not in the filter chain, AP_MODE_INIT is a noop.
120 net->in_ctx = ctx = apr_palloc(f->c->pool, sizeof(*ctx));
121 ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
122 ctx->tmpbb = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
123 /* seed the brigade with the client socket. */
124 rv = ap_run_insert_network_bucket(f->c, ctx->b, net->client_socket);
125 if (rv != APR_SUCCESS)
128 else if (APR_BRIGADE_EMPTY(ctx->b)) {
132 /* ### This is bad. */
133 BRIGADE_NORMALIZE(ctx->b);
135 /* check for empty brigade again *AFTER* BRIGADE_NORMALIZE()
136 * If we have lost our socket bucket (see above), we are EOF.
138 * Ideally, this should be returning SUCCESS with EOS bucket, but
139 * some higher-up APIs (spec. read_request_line via ap_rgetline)
140 * want an error code. */
141 if (APR_BRIGADE_EMPTY(ctx->b)) {
145 if (mode == AP_MODE_GETLINE) {
146 /* we are reading a single LF line, e.g. the HTTP headers */
147 rv = apr_brigade_split_line(b, ctx->b, block, HUGE_STRING_LEN);
148 /* We should treat EAGAIN here the same as we do for EOF (brigade is
149 * empty). We do this by returning whatever we have read. This may
150 * or may not be bogus, but is consistent (for now) with EOF logic.
152 if (APR_STATUS_IS_EAGAIN(rv) && block == APR_NONBLOCK_READ) {
158 /* ### AP_MODE_PEEK is a horrific name for this mode because we also
159 * eat any CRLFs that we see. That's not the obvious intention of
160 * this mode. Determine whether anyone actually uses this or not. */
161 if (mode == AP_MODE_EATCRLF) {
165 /* The purpose of this loop is to ignore any CRLF (or LF) at the end
166 * of a request. Many browsers send extra lines at the end of POST
167 * requests. We use the PEEK method to determine if there is more
168 * data on the socket, so that we know if we should delay sending the
169 * end of one request until we have served the second request in a
170 * pipelined situation. We don't want to actually delay sending a
171 * response if the server finds a CRLF (or LF), becuause that doesn't
172 * mean that there is another request, just a blank line.
175 if (APR_BRIGADE_EMPTY(ctx->b))
178 e = APR_BRIGADE_FIRST(ctx->b);
180 rv = apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
182 if (rv != APR_SUCCESS)
186 while (c < str + len) {
187 if (*c == APR_ASCII_LF)
189 else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF)
195 /* If we reach here, we were a bucket just full of CRLFs, so
196 * just toss the bucket. */
197 /* FIXME: Is this the right thing to do in the core? */
198 apr_bucket_delete(e);
203 /* If mode is EXHAUSTIVE, we want to just read everything until the end
204 * of the brigade, which in this case means the end of the socket.
205 * To do this, we attach the brigade that has currently been setaside to
206 * the brigade that was passed down, and send that brigade back.
208 * NOTE: This is VERY dangerous to use, and should only be done with
209 * extreme caution. FWLIW, this would be needed by an MPM like Perchild;
210 * such an MPM can easily request the socket and all data that has been
211 * read, which means that it can pass it to the correct child process.
213 if (mode == AP_MODE_EXHAUSTIVE) {
216 /* Tack on any buckets that were set aside. */
217 APR_BRIGADE_CONCAT(b, ctx->b);
219 /* Since we've just added all potential buckets (which will most
220 * likely simply be the socket bucket) we know this is the end,
221 * so tack on an EOS too. */
222 /* We have read until the brigade was empty, so we know that we
224 e = apr_bucket_eos_create(f->c->bucket_alloc);
225 APR_BRIGADE_INSERT_TAIL(b, e);
229 /* read up to the amount they specified. */
230 if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE) {
233 AP_DEBUG_ASSERT(readbytes > 0);
235 e = APR_BRIGADE_FIRST(ctx->b);
236 rv = apr_bucket_read(e, &str, &len, block);
238 if (APR_STATUS_IS_EAGAIN(rv) && block == APR_NONBLOCK_READ) {
239 /* getting EAGAIN for a blocking read is an error; for a
240 * non-blocking read, return an empty brigade. */
243 else if (rv != APR_SUCCESS) {
246 else if (block == APR_BLOCK_READ && len == 0) {
247 /* We wanted to read some bytes in blocking mode. We read
248 * 0 bytes. Hence, we now assume we are EOS.
250 * When we are in normal mode, return an EOS bucket to the
252 * When we are in speculative mode, leave ctx->b empty, so
253 * that the next call returns an EOS bucket.
255 apr_bucket_delete(e);
257 if (mode == AP_MODE_READBYTES) {
258 e = apr_bucket_eos_create(f->c->bucket_alloc);
259 APR_BRIGADE_INSERT_TAIL(b, e);
264 /* Have we read as much data as we wanted (be greedy)? */
265 if (len < readbytes) {
266 apr_size_t bucket_len;
269 /* We already registered the data in e in len */
270 e = APR_BUCKET_NEXT(e);
271 while ((len < readbytes) && (rv == APR_SUCCESS)
272 && (e != APR_BRIGADE_SENTINEL(ctx->b))) {
273 /* Check for the availability of buckets with known length */
274 if (e->length != -1) {
276 e = APR_BUCKET_NEXT(e);
280 * Read from bucket, but non blocking. If there isn't any
281 * more data, well than this is fine as well, we will
282 * not wait for more since we already got some and we are
283 * only checking if there isn't more.
285 rv = apr_bucket_read(e, &str, &bucket_len,
287 if (rv == APR_SUCCESS) {
289 e = APR_BUCKET_NEXT(e);
295 /* We can only return at most what we read. */
296 if (len < readbytes) {
300 rv = apr_brigade_partition(ctx->b, readbytes, &e);
301 if (rv != APR_SUCCESS) {
305 /* Must do move before CONCAT */
306 ctx->tmpbb = apr_brigade_split_ex(ctx->b, e, ctx->tmpbb);
308 if (mode == AP_MODE_READBYTES) {
309 APR_BRIGADE_CONCAT(b, ctx->b);
311 else if (mode == AP_MODE_SPECULATIVE) {
312 apr_bucket *copy_bucket;
314 for (e = APR_BRIGADE_FIRST(ctx->b);
315 e != APR_BRIGADE_SENTINEL(ctx->b);
316 e = APR_BUCKET_NEXT(e))
318 rv = apr_bucket_copy(e, ©_bucket);
319 if (rv != APR_SUCCESS) {
322 APR_BRIGADE_INSERT_TAIL(b, copy_bucket);
326 /* Take what was originally there and place it back on ctx->b */
327 APR_BRIGADE_CONCAT(ctx->b, ctx->tmpbb);
332 static void setaside_remaining_output(ap_filter_t *f,
333 core_output_filter_ctx_t *ctx,
334 apr_bucket_brigade *bb,
337 static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
338 apr_bucket_brigade *bb,
339 apr_size_t *bytes_written,
342 static void remove_empty_buckets(apr_bucket_brigade *bb);
344 static apr_status_t send_brigade_blocking(apr_socket_t *s,
345 apr_bucket_brigade *bb,
346 apr_size_t *bytes_written,
349 static apr_status_t writev_nonblocking(apr_socket_t *s,
350 struct iovec *vec, apr_size_t nvec,
351 apr_bucket_brigade *bb,
352 apr_size_t *cumulative_bytes_written,
356 static apr_status_t sendfile_nonblocking(apr_socket_t *s,
358 apr_size_t *cumulative_bytes_written,
362 /* XXX: Should these be configurable parameters? */
363 #define THRESHOLD_MIN_WRITE 4096
364 #define THRESHOLD_MAX_BUFFER 65536
365 #define MAX_REQUESTS_IN_PIPELINE 5
367 /* Optional function coming from mod_logio, used for logging of output
370 extern APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *ap__logio_add_bytes_out;
372 apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
375 core_net_rec *net = f->ctx;
376 core_output_filter_ctx_t *ctx = net->out_ctx;
377 apr_bucket_brigade *bb = NULL;
378 apr_bucket *bucket, *next, *flush_upto = NULL;
379 apr_size_t bytes_in_brigade, non_file_bytes_in_brigade;
380 int eor_buckets_in_brigade, morphing_bucket_in_brigade;
382 int loglevel = ap_get_conn_module_loglevel(c, APLOG_MODULE_INDEX);
384 /* Fail quickly if the connection has already been aborted. */
386 if (new_bb != NULL) {
387 apr_brigade_cleanup(new_bb);
389 return APR_ECONNABORTED;
393 ctx = apr_pcalloc(c->pool, sizeof(*ctx));
394 net->out_ctx = (core_output_filter_ctx_t *)ctx;
396 * Need to create tmp brigade with correct lifetime. Passing
397 * NULL to apr_brigade_split_ex would result in a brigade
398 * allocated from bb->pool which might be wrong.
400 ctx->tmp_flush_bb = apr_brigade_create(c->pool, c->bucket_alloc);
401 /* same for buffered_bb and ap_save_brigade */
402 ctx->buffered_bb = apr_brigade_create(c->pool, c->bucket_alloc);
408 if ((ctx->buffered_bb != NULL) &&
409 !APR_BRIGADE_EMPTY(ctx->buffered_bb)) {
410 if (new_bb != NULL) {
411 APR_BRIGADE_PREPEND(bb, ctx->buffered_bb);
414 bb = ctx->buffered_bb;
416 c->data_in_output_filters = 0;
418 else if (new_bb == NULL) {
422 /* Scan through the brigade and decide whether to attempt a write,
423 * and how much to write, based on the following rules:
425 * 1) The new_bb is null: Do a nonblocking write of as much as
426 * possible: do a nonblocking write of as much data as possible,
427 * then save the rest in ctx->buffered_bb. (If new_bb == NULL,
428 * it probably means that the MPM is doing asynchronous write
429 * completion and has just determined that this connection
432 * 2) Determine if and up to which bucket we need to do a blocking
435 * a) The brigade contains a flush bucket: Do a blocking write
436 * of everything up that point.
438 * b) The request is in CONN_STATE_HANDLER state, and the brigade
439 * contains at least THRESHOLD_MAX_BUFFER bytes in non-file
440 * buckets: Do blocking writes until the amount of data in the
441 * buffer is less than THRESHOLD_MAX_BUFFER. (The point of this
442 * rule is to provide flow control, in case a handler is
443 * streaming out lots of data faster than the data can be
444 * sent to the client.)
446 * c) The request is in CONN_STATE_HANDLER state, and the brigade
447 * contains at least MAX_REQUESTS_IN_PIPELINE EOR buckets:
448 * Do blocking writes until less than MAX_REQUESTS_IN_PIPELINE EOR
449 * buckets are left. (The point of this rule is to prevent too many
450 * FDs being kept open by pipelined requests, possibly allowing a
453 * d) The brigade contains a morphing bucket: If there was no other
454 * reason to do a blocking write yet, try reading the bucket. If its
455 * contents fit into memory before THRESHOLD_MAX_BUFFER is reached,
456 * everything is fine. Otherwise we need to do a blocking write the
457 * up to and including the morphing bucket, because ap_save_brigade()
458 * would read the whole bucket into memory later on.
460 * 3) Actually do the blocking write up to the last bucket determined
461 * by rules 2a-d. The point of doing only one flush is to make as
462 * few calls to writev() as possible.
464 * 4) If the brigade contains at least THRESHOLD_MIN_WRITE
465 * bytes: Do a nonblocking write of as much data as possible,
466 * then save the rest in ctx->buffered_bb.
469 if (new_bb == NULL) {
470 rv = send_brigade_nonblocking(net->client_socket, bb,
471 &(ctx->bytes_written), c);
472 if (APR_STATUS_IS_EAGAIN(rv)) {
475 else if (rv != APR_SUCCESS) {
476 /* The client has aborted the connection */
477 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
478 "core_output_filter: writing data to the network");
481 setaside_remaining_output(f, ctx, bb, c);
485 bytes_in_brigade = 0;
486 non_file_bytes_in_brigade = 0;
487 eor_buckets_in_brigade = 0;
488 morphing_bucket_in_brigade = 0;
490 for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb);
492 next = APR_BUCKET_NEXT(bucket);
494 if (!APR_BUCKET_IS_METADATA(bucket)) {
495 if (bucket->length == (apr_size_t)-1) {
497 * A setaside of morphing buckets would read everything into
498 * memory. Instead, we will flush everything up to and
499 * including this bucket.
501 morphing_bucket_in_brigade = 1;
504 bytes_in_brigade += bucket->length;
505 if (!APR_BUCKET_IS_FILE(bucket))
506 non_file_bytes_in_brigade += bucket->length;
509 else if (AP_BUCKET_IS_EOR(bucket)) {
510 eor_buckets_in_brigade++;
513 if (APR_BUCKET_IS_FLUSH(bucket)
514 || non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER
515 || morphing_bucket_in_brigade
516 || eor_buckets_in_brigade > MAX_REQUESTS_IN_PIPELINE) {
517 /* this segment of the brigade MUST be sent before returning. */
519 if (loglevel >= APLOG_TRACE6) {
520 char *reason = APR_BUCKET_IS_FLUSH(bucket) ?
522 (non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER) ?
523 "THRESHOLD_MAX_BUFFER" :
524 morphing_bucket_in_brigade ? "morphing bucket" :
525 "MAX_REQUESTS_IN_PIPELINE";
526 ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, c,
527 "will flush because of %s", reason);
528 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
529 "seen in brigade%s: bytes: %" APR_SIZE_T_FMT
530 ", non-file bytes: %" APR_SIZE_T_FMT ", eor "
531 "buckets: %d, morphing buckets: %d",
532 flush_upto == NULL ? " so far"
533 : " since last flush point",
535 non_file_bytes_in_brigade,
536 eor_buckets_in_brigade,
537 morphing_bucket_in_brigade);
540 * Defer the actual blocking write to avoid doing many writes.
544 bytes_in_brigade = 0;
545 non_file_bytes_in_brigade = 0;
546 eor_buckets_in_brigade = 0;
547 morphing_bucket_in_brigade = 0;
551 if (flush_upto != NULL) {
552 ctx->tmp_flush_bb = apr_brigade_split_ex(bb, flush_upto,
554 if (loglevel >= APLOG_TRACE8) {
555 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
558 rv = send_brigade_blocking(net->client_socket, bb,
559 &(ctx->bytes_written), c);
560 if (rv != APR_SUCCESS) {
561 /* The client has aborted the connection */
562 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
563 "core_output_filter: writing data to the network");
567 if (loglevel >= APLOG_TRACE8) {
568 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
569 "total bytes written: %" APR_SIZE_T_FMT,
572 APR_BRIGADE_CONCAT(bb, ctx->tmp_flush_bb);
575 if (loglevel >= APLOG_TRACE8) {
576 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
577 "brigade contains: bytes: %" APR_SIZE_T_FMT
578 ", non-file bytes: %" APR_SIZE_T_FMT
579 ", eor buckets: %d, morphing buckets: %d",
580 bytes_in_brigade, non_file_bytes_in_brigade,
581 eor_buckets_in_brigade, morphing_bucket_in_brigade);
584 if (bytes_in_brigade >= THRESHOLD_MIN_WRITE) {
585 rv = send_brigade_nonblocking(net->client_socket, bb,
586 &(ctx->bytes_written), c);
587 if ((rv != APR_SUCCESS) && (!APR_STATUS_IS_EAGAIN(rv))) {
588 /* The client has aborted the connection */
589 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
590 "core_output_filter: writing data to the network");
594 if (loglevel >= APLOG_TRACE8) {
595 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c,
596 "tried nonblocking write, total bytes "
597 "written: %" APR_SIZE_T_FMT,
602 setaside_remaining_output(f, ctx, bb, c);
607 * This function assumes that either ctx->buffered_bb == NULL, or
608 * ctx->buffered_bb is empty, or ctx->buffered_bb == bb
610 static void setaside_remaining_output(ap_filter_t *f,
611 core_output_filter_ctx_t *ctx,
612 apr_bucket_brigade *bb,
618 remove_empty_buckets(bb);
619 if (!APR_BRIGADE_EMPTY(bb)) {
620 c->data_in_output_filters = 1;
621 if (bb != ctx->buffered_bb) {
622 if (!ctx->deferred_write_pool) {
623 apr_pool_create(&ctx->deferred_write_pool, c->pool);
624 apr_pool_tag(ctx->deferred_write_pool, "deferred_write");
626 ap_save_brigade(f, &(ctx->buffered_bb), &bb,
627 ctx->deferred_write_pool);
628 apr_brigade_cleanup(bb);
631 else if (ctx->deferred_write_pool) {
633 * There are no more requests in the pipeline. We can just clear the
636 apr_pool_clear(ctx->deferred_write_pool);
640 #ifndef APR_MAX_IOVEC_SIZE
641 #define MAX_IOVEC_TO_WRITE 16
643 #if APR_MAX_IOVEC_SIZE > 16
644 #define MAX_IOVEC_TO_WRITE 16
646 #define MAX_IOVEC_TO_WRITE APR_MAX_IOVEC_SIZE
650 static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
651 apr_bucket_brigade *bb,
652 apr_size_t *bytes_written,
655 apr_bucket *bucket, *next;
657 struct iovec vec[MAX_IOVEC_TO_WRITE];
660 remove_empty_buckets(bb);
662 for (bucket = APR_BRIGADE_FIRST(bb);
663 bucket != APR_BRIGADE_SENTINEL(bb);
665 next = APR_BUCKET_NEXT(bucket);
667 if (APR_BUCKET_IS_FILE(bucket)) {
668 apr_bucket_file *file_bucket = (apr_bucket_file *)(bucket->data);
669 apr_file_t *fd = file_bucket->fd;
670 /* Use sendfile to send this file unless:
671 * - the platform doesn't support sendfile,
672 * - the file is too small for sendfile to be useful, or
673 * - sendfile is disabled in the httpd config via "EnableSendfile off"
676 if ((apr_file_flags_get(fd) & APR_SENDFILE_ENABLED) &&
677 (bucket->length >= AP_MIN_SENDFILE_BYTES)) {
679 (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);
680 rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
682 if (rv != APR_SUCCESS) {
683 (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
687 rv = sendfile_nonblocking(s, bucket, bytes_written, c);
689 (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
691 if (rv != APR_SUCCESS) {
697 #endif /* APR_HAS_SENDFILE */
698 /* didn't sendfile */
699 if (!APR_BUCKET_IS_METADATA(bucket)) {
703 /* Non-blocking read first, in case this is a morphing
705 rv = apr_bucket_read(bucket, &data, &length, APR_NONBLOCK_READ);
706 if (APR_STATUS_IS_EAGAIN(rv)) {
707 /* Read would block; flush any pending data and retry. */
709 rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
716 rv = apr_bucket_read(bucket, &data, &length, APR_BLOCK_READ);
718 if (rv != APR_SUCCESS) {
722 /* reading may have split the bucket, so recompute next: */
723 next = APR_BUCKET_NEXT(bucket);
724 vec[nvec].iov_base = (char *)data;
725 vec[nvec].iov_len = length;
727 if (nvec == MAX_IOVEC_TO_WRITE) {
728 rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
730 if (rv != APR_SUCCESS) {
739 rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
740 if (rv != APR_SUCCESS) {
745 remove_empty_buckets(bb);
750 static void remove_empty_buckets(apr_bucket_brigade *bb)
753 while (((bucket = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) &&
754 (APR_BUCKET_IS_METADATA(bucket) || (bucket->length == 0))) {
755 APR_BUCKET_REMOVE(bucket);
756 apr_bucket_destroy(bucket);
760 static apr_status_t send_brigade_blocking(apr_socket_t *s,
761 apr_bucket_brigade *bb,
762 apr_size_t *bytes_written,
768 while (!APR_BRIGADE_EMPTY(bb)) {
769 rv = send_brigade_nonblocking(s, bb, bytes_written, c);
770 if (rv != APR_SUCCESS) {
771 if (APR_STATUS_IS_EAGAIN(rv)) {
772 /* Wait until we can send more data */
774 apr_interval_time_t timeout;
775 apr_pollfd_t pollset;
778 pollset.desc_type = APR_POLL_SOCKET;
779 pollset.reqevents = APR_POLLOUT;
781 apr_socket_timeout_get(s, &timeout);
783 rv = apr_poll(&pollset, 1, &nsds, timeout);
784 } while (APR_STATUS_IS_EINTR(rv));
785 if (rv != APR_SUCCESS) {
797 static apr_status_t writev_nonblocking(apr_socket_t *s,
798 struct iovec *vec, apr_size_t nvec,
799 apr_bucket_brigade *bb,
800 apr_size_t *cumulative_bytes_written,
803 apr_status_t rv = APR_SUCCESS, arv;
804 apr_size_t bytes_written = 0, bytes_to_write = 0;
805 apr_size_t i, offset;
806 apr_interval_time_t old_timeout;
808 arv = apr_socket_timeout_get(s, &old_timeout);
809 if (arv != APR_SUCCESS) {
812 arv = apr_socket_timeout_set(s, 0);
813 if (arv != APR_SUCCESS) {
817 for (i = 0; i < nvec; i++) {
818 bytes_to_write += vec[i].iov_len;
821 while (bytes_written < bytes_to_write) {
823 rv = apr_socket_sendv(s, vec + offset, nvec - offset, &n);
826 for (i = offset; i < nvec; ) {
827 apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
828 if (APR_BUCKET_IS_METADATA(bucket)) {
829 APR_BUCKET_REMOVE(bucket);
830 apr_bucket_destroy(bucket);
832 else if (n >= vec[i].iov_len) {
833 APR_BUCKET_REMOVE(bucket);
834 apr_bucket_destroy(bucket);
836 n -= vec[i++].iov_len;
839 apr_bucket_split(bucket, n);
840 APR_BUCKET_REMOVE(bucket);
841 apr_bucket_destroy(bucket);
843 vec[i].iov_base = (char *) vec[i].iov_base + n;
848 if (rv != APR_SUCCESS) {
852 if ((ap__logio_add_bytes_out != NULL) && (bytes_written > 0)) {
853 ap__logio_add_bytes_out(c, bytes_written);
855 *cumulative_bytes_written += bytes_written;
857 arv = apr_socket_timeout_set(s, old_timeout);
858 if ((arv != APR_SUCCESS) && (rv == APR_SUCCESS)) {
868 static apr_status_t sendfile_nonblocking(apr_socket_t *s,
870 apr_size_t *cumulative_bytes_written,
873 apr_status_t rv = APR_SUCCESS;
874 apr_bucket_file *file_bucket;
876 apr_size_t file_length;
877 apr_off_t file_offset;
878 apr_size_t bytes_written = 0;
880 if (!APR_BUCKET_IS_FILE(bucket)) {
881 ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server, APLOGNO(00006)
882 "core_filter: sendfile_nonblocking: "
883 "this should never happen");
886 file_bucket = (apr_bucket_file *)(bucket->data);
887 fd = file_bucket->fd;
888 file_length = bucket->length;
889 file_offset = bucket->start;
891 if (bytes_written < file_length) {
892 apr_size_t n = file_length - bytes_written;
894 apr_interval_time_t old_timeout;
896 arv = apr_socket_timeout_get(s, &old_timeout);
897 if (arv != APR_SUCCESS) {
900 arv = apr_socket_timeout_set(s, 0);
901 if (arv != APR_SUCCESS) {
904 rv = apr_socket_sendfile(s, fd, NULL, &file_offset, &n, 0);
905 if (rv == APR_SUCCESS) {
909 arv = apr_socket_timeout_set(s, old_timeout);
910 if ((arv != APR_SUCCESS) && (rv == APR_SUCCESS)) {
914 if ((ap__logio_add_bytes_out != NULL) && (bytes_written > 0)) {
915 ap__logio_add_bytes_out(c, bytes_written);
917 *cumulative_bytes_written += bytes_written;
918 if ((bytes_written < file_length) && (bytes_written > 0)) {
919 apr_bucket_split(bucket, bytes_written);
920 APR_BUCKET_REMOVE(bucket);
921 apr_bucket_destroy(bucket);
923 else if (bytes_written == file_length) {
924 APR_BUCKET_REMOVE(bucket);
925 apr_bucket_destroy(bucket);