~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to server/core_filters.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#define CORE_PRIVATE
 
36
#include "ap_config.h"
 
37
#include "httpd.h"
 
38
#include "http_config.h"
 
39
#include "http_core.h"
 
40
#include "http_protocol.h" /* For index_of_response().  Grump. */
 
41
#include "http_request.h"
 
42
#include "http_vhost.h"
 
43
#include "http_main.h"     /* For the default_handler below... */
 
44
#include "http_log.h"
 
45
#include "util_md5.h"
 
46
#include "http_connection.h"
 
47
#include "apr_buckets.h"
 
48
#include "util_filter.h"
 
49
#include "util_ebcdic.h"
 
50
#include "mpm.h"
 
51
#include "mpm_common.h"
 
52
#include "scoreboard.h"
 
53
#include "mod_core.h"
 
54
#include "mod_proxy.h"
 
55
#include "ap_listen.h"
 
56
 
 
57
#include "mod_so.h" /* for ap_find_loaded_module_symbol */
 
58
 
 
59
#define AP_MIN_SENDFILE_BYTES           (256)
 
60
 
 
61
/**
 
62
 * Remove all zero length buckets from the brigade.
 
63
 */
 
64
#define BRIGADE_NORMALIZE(b) \
 
65
do { \
 
66
    apr_bucket *e = APR_BRIGADE_FIRST(b); \
 
67
    do {  \
 
68
        if (e->length == 0 && !APR_BUCKET_IS_METADATA(e)) { \
 
69
            apr_bucket *d; \
 
70
            d = APR_BUCKET_NEXT(e); \
 
71
            apr_bucket_delete(e); \
 
72
            e = d; \
 
73
        } \
 
74
        else { \
 
75
            e = APR_BUCKET_NEXT(e); \
 
76
        } \
 
77
    } while (!APR_BRIGADE_EMPTY(b) && (e != APR_BRIGADE_SENTINEL(b))); \
 
78
} while (0)
 
79
 
 
80
 
 
81
/**
 
82
 * Split the contents of a brigade after bucket 'e' to an existing brigade
 
83
 *
 
84
 * XXXX: Should this function be added to APR-Util?
 
85
 */
 
86
static void brigade_move(apr_bucket_brigade *b, apr_bucket_brigade *a,
 
87
                         apr_bucket *e)
 
88
{
 
89
    apr_bucket *f;
 
90
 
 
91
    if (e != APR_BRIGADE_SENTINEL(b)) {
 
92
        f = APR_RING_LAST(&b->list);
 
93
        APR_RING_UNSPLICE(e, f, link);
 
94
        APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link);
 
95
    }
 
96
 
 
97
    APR_BRIGADE_CHECK_CONSISTENCY(a);
 
98
    APR_BRIGADE_CHECK_CONSISTENCY(b);
 
99
}
 
100
 
 
101
int ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b,
 
102
                         ap_input_mode_t mode, apr_read_type_e block,
 
103
                         apr_off_t readbytes)
 
104
{
 
105
    apr_bucket *e;
 
106
    apr_status_t rv;
 
107
    core_net_rec *net = f->ctx;
 
108
    core_ctx_t *ctx = net->in_ctx;
 
109
    const char *str;
 
110
    apr_size_t len;
 
111
 
 
112
    if (mode == AP_MODE_INIT) {
 
113
        /*
 
114
         * this mode is for filters that might need to 'initialize'
 
115
         * a connection before reading request data from a client.
 
116
         * NNTP over SSL for example needs to handshake before the
 
117
         * server sends the welcome message.
 
118
         * such filters would have changed the mode before this point
 
119
         * is reached.  however, protocol modules such as NNTP should
 
120
         * not need to know anything about SSL.  given the example, if
 
121
         * SSL is not in the filter chain, AP_MODE_INIT is a noop.
 
122
         */
 
123
        return APR_SUCCESS;
 
124
    }
 
125
 
 
126
    if (!ctx)
 
127
    {
 
128
        ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
 
129
        ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
 
130
        ctx->tmpbb = apr_brigade_create(ctx->b->p, ctx->b->bucket_alloc);
 
131
        /* seed the brigade with the client socket. */
 
132
        e = apr_bucket_socket_create(net->client_socket, f->c->bucket_alloc);
 
133
        APR_BRIGADE_INSERT_TAIL(ctx->b, e);
 
134
        net->in_ctx = ctx;
 
135
    }
 
136
    else if (APR_BRIGADE_EMPTY(ctx->b)) {
 
137
        return APR_EOF;
 
138
    }
 
139
 
 
140
    /* ### This is bad. */
 
141
    BRIGADE_NORMALIZE(ctx->b);
 
142
 
 
143
    /* check for empty brigade again *AFTER* BRIGADE_NORMALIZE()
 
144
     * If we have lost our socket bucket (see above), we are EOF.
 
145
     *
 
146
     * Ideally, this should be returning SUCCESS with EOS bucket, but
 
147
     * some higher-up APIs (spec. read_request_line via ap_rgetline)
 
148
     * want an error code. */
 
149
    if (APR_BRIGADE_EMPTY(ctx->b)) {
 
150
        return APR_EOF;
 
151
    }
 
152
 
 
153
    if (mode == AP_MODE_GETLINE) {
 
154
        /* we are reading a single LF line, e.g. the HTTP headers */
 
155
        rv = apr_brigade_split_line(b, ctx->b, block, HUGE_STRING_LEN);
 
156
        /* We should treat EAGAIN here the same as we do for EOF (brigade is
 
157
         * empty).  We do this by returning whatever we have read.  This may
 
158
         * or may not be bogus, but is consistent (for now) with EOF logic.
 
159
         */
 
160
        if (APR_STATUS_IS_EAGAIN(rv)) {
 
161
            rv = APR_SUCCESS;
 
162
        }
 
163
        return rv;
 
164
    }
 
165
 
 
166
    /* ### AP_MODE_PEEK is a horrific name for this mode because we also
 
167
     * eat any CRLFs that we see.  That's not the obvious intention of
 
168
     * this mode.  Determine whether anyone actually uses this or not. */
 
169
    if (mode == AP_MODE_EATCRLF) {
 
170
        apr_bucket *e;
 
171
        const char *c;
 
172
 
 
173
        /* The purpose of this loop is to ignore any CRLF (or LF) at the end
 
174
         * of a request.  Many browsers send extra lines at the end of POST
 
175
         * requests.  We use the PEEK method to determine if there is more
 
176
         * data on the socket, so that we know if we should delay sending the
 
177
         * end of one request until we have served the second request in a
 
178
         * pipelined situation.  We don't want to actually delay sending a
 
179
         * response if the server finds a CRLF (or LF), becuause that doesn't
 
180
         * mean that there is another request, just a blank line.
 
181
         */
 
182
        while (1) {
 
183
            if (APR_BRIGADE_EMPTY(ctx->b))
 
184
                return APR_EOF;
 
185
 
 
186
            e = APR_BRIGADE_FIRST(ctx->b);
 
187
 
 
188
            rv = apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
 
189
 
 
190
            if (rv != APR_SUCCESS)
 
191
                return rv;
 
192
 
 
193
            c = str;
 
194
            while (c < str + len) {
 
195
                if (*c == APR_ASCII_LF)
 
196
                    c++;
 
197
                else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF)
 
198
                    c += 2;
 
199
                else
 
200
                    return APR_SUCCESS;
 
201
            }
 
202
 
 
203
            /* If we reach here, we were a bucket just full of CRLFs, so
 
204
             * just toss the bucket. */
 
205
            /* FIXME: Is this the right thing to do in the core? */
 
206
            apr_bucket_delete(e);
 
207
        }
 
208
        return APR_SUCCESS;
 
209
    }
 
210
 
 
211
    /* If mode is EXHAUSTIVE, we want to just read everything until the end
 
212
     * of the brigade, which in this case means the end of the socket.
 
213
     * To do this, we attach the brigade that has currently been setaside to
 
214
     * the brigade that was passed down, and send that brigade back.
 
215
     *
 
216
     * NOTE:  This is VERY dangerous to use, and should only be done with
 
217
     * extreme caution.  However, the Perchild MPM needs this feature
 
218
     * if it is ever going to work correctly again.  With this, the Perchild
 
219
     * MPM can easily request the socket and all data that has been read,
 
220
     * which means that it can pass it to the correct child process.
 
221
     */
 
222
    if (mode == AP_MODE_EXHAUSTIVE) {
 
223
        apr_bucket *e;
 
224
 
 
225
        /* Tack on any buckets that were set aside. */
 
226
        APR_BRIGADE_CONCAT(b, ctx->b);
 
227
 
 
228
        /* Since we've just added all potential buckets (which will most
 
229
         * likely simply be the socket bucket) we know this is the end,
 
230
         * so tack on an EOS too. */
 
231
        /* We have read until the brigade was empty, so we know that we
 
232
         * must be EOS. */
 
233
        e = apr_bucket_eos_create(f->c->bucket_alloc);
 
234
        APR_BRIGADE_INSERT_TAIL(b, e);
 
235
        return APR_SUCCESS;
 
236
    }
 
237
 
 
238
    /* read up to the amount they specified. */
 
239
    if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE) {
 
240
        apr_bucket *e;
 
241
 
 
242
        AP_DEBUG_ASSERT(readbytes > 0);
 
243
 
 
244
        e = APR_BRIGADE_FIRST(ctx->b);
 
245
        rv = apr_bucket_read(e, &str, &len, block);
 
246
 
 
247
        if (APR_STATUS_IS_EAGAIN(rv)) {
 
248
            return APR_SUCCESS;
 
249
        }
 
250
        else if (rv != APR_SUCCESS) {
 
251
            return rv;
 
252
        }
 
253
        else if (block == APR_BLOCK_READ && len == 0) {
 
254
            /* We wanted to read some bytes in blocking mode.  We read
 
255
             * 0 bytes.  Hence, we now assume we are EOS.
 
256
             *
 
257
             * When we are in normal mode, return an EOS bucket to the
 
258
             * caller.
 
259
             * When we are in speculative mode, leave ctx->b empty, so
 
260
             * that the next call returns an EOS bucket.
 
261
             */
 
262
            apr_bucket_delete(e);
 
263
 
 
264
            if (mode == AP_MODE_READBYTES) {
 
265
                e = apr_bucket_eos_create(f->c->bucket_alloc);
 
266
                APR_BRIGADE_INSERT_TAIL(b, e);
 
267
            }
 
268
            return APR_SUCCESS;
 
269
        }
 
270
 
 
271
        /* We can only return at most what we read. */
 
272
        if (len < readbytes) {
 
273
            readbytes = len;
 
274
        }
 
275
 
 
276
        rv = apr_brigade_partition(ctx->b, readbytes, &e);
 
277
        if (rv != APR_SUCCESS) {
 
278
            return rv;
 
279
        }
 
280
 
 
281
        /* Must do move before CONCAT */
 
282
        brigade_move(ctx->b, ctx->tmpbb, e);
 
283
 
 
284
        if (mode == AP_MODE_READBYTES) {
 
285
            APR_BRIGADE_CONCAT(b, ctx->b);
 
286
        }
 
287
        else if (mode == AP_MODE_SPECULATIVE) {
 
288
            apr_bucket *copy_bucket;
 
289
 
 
290
            for (e = APR_BRIGADE_FIRST(ctx->b);
 
291
                 e != APR_BRIGADE_SENTINEL(ctx->b);
 
292
                 e = APR_BUCKET_NEXT(e))
 
293
            {
 
294
                rv = apr_bucket_copy(e, &copy_bucket);
 
295
                if (rv != APR_SUCCESS) {
 
296
                    return rv;
 
297
                }
 
298
                APR_BRIGADE_INSERT_TAIL(b, copy_bucket);
 
299
            }
 
300
        }
 
301
 
 
302
        /* Take what was originally there and place it back on ctx->b */
 
303
        APR_BRIGADE_CONCAT(ctx->b, ctx->tmpbb);
 
304
    }
 
305
    return APR_SUCCESS;
 
306
}
 
307
 
 
308
static apr_status_t writev_it_all(apr_socket_t *s,
 
309
                                  struct iovec *vec, int nvec,
 
310
                                  apr_size_t len, apr_size_t *nbytes)
 
311
{
 
312
    apr_size_t bytes_written = 0;
 
313
    apr_status_t rv;
 
314
    apr_size_t n = len;
 
315
    int i = 0;
 
316
 
 
317
    *nbytes = 0;
 
318
 
 
319
    /* XXX handle checking for non-blocking socket */
 
320
    while (bytes_written != len) {
 
321
        rv = apr_socket_sendv(s, vec + i, nvec - i, &n);
 
322
        *nbytes += n;
 
323
        bytes_written += n;
 
324
        if (rv != APR_SUCCESS)
 
325
            return rv;
 
326
 
 
327
        /* If the write did not complete, adjust the iovecs and issue
 
328
         * apr_socket_sendv again
 
329
         */
 
330
        if (bytes_written < len) {
 
331
            /* Skip over the vectors that have already been written */
 
332
            apr_size_t cnt = vec[i].iov_len;
 
333
            while (n >= cnt && i + 1 < nvec) {
 
334
                i++;
 
335
                cnt += vec[i].iov_len;
 
336
            }
 
337
 
 
338
            if (n < cnt) {
 
339
                /* Handle partial write of vec i */
 
340
                vec[i].iov_base = (char *) vec[i].iov_base +
 
341
                    (vec[i].iov_len - (cnt - n));
 
342
                vec[i].iov_len = cnt -n;
 
343
            }
 
344
        }
 
345
 
 
346
        n = len - bytes_written;
 
347
    }
 
348
 
 
349
    return APR_SUCCESS;
 
350
}
 
351
 
 
352
/* sendfile_it_all()
 
353
 *  send the entire file using sendfile()
 
354
 *  handle partial writes
 
355
 *  return only when all bytes have been sent or an error is encountered.
 
356
 */
 
357
 
 
358
#if APR_HAS_SENDFILE
 
359
static apr_status_t sendfile_it_all(core_net_rec *c,
 
360
                                    apr_file_t *fd,
 
361
                                    apr_hdtr_t *hdtr,
 
362
                                    apr_off_t   file_offset,
 
363
                                    apr_size_t  file_bytes_left,
 
364
                                    apr_size_t  total_bytes_left,
 
365
                                    apr_size_t  *bytes_sent,
 
366
                                    apr_int32_t flags)
 
367
{
 
368
    apr_status_t rv;
 
369
#ifdef AP_DEBUG
 
370
    apr_interval_time_t timeout = 0;
 
371
#endif
 
372
 
 
373
    AP_DEBUG_ASSERT((apr_socket_timeout_get(c->client_socket, &timeout)
 
374
                         == APR_SUCCESS)
 
375
                    && timeout > 0);  /* socket must be in timeout mode */
 
376
 
 
377
    /* Reset the bytes_sent field */
 
378
    *bytes_sent = 0;
 
379
 
 
380
    do {
 
381
        apr_size_t tmplen = file_bytes_left;
 
382
 
 
383
        rv = apr_socket_sendfile(c->client_socket, fd, hdtr, &file_offset, &tmplen,
 
384
                                 flags);
 
385
        *bytes_sent += tmplen;
 
386
        total_bytes_left -= tmplen;
 
387
        if (!total_bytes_left || rv != APR_SUCCESS) {
 
388
            return rv;        /* normal case & error exit */
 
389
        }
 
390
 
 
391
        AP_DEBUG_ASSERT(total_bytes_left > 0 && tmplen > 0);
 
392
 
 
393
        /* partial write, oooh noooo...
 
394
         * Skip over any header data which was written
 
395
         */
 
396
        while (tmplen && hdtr->numheaders) {
 
397
            if (tmplen >= hdtr->headers[0].iov_len) {
 
398
                tmplen -= hdtr->headers[0].iov_len;
 
399
                --hdtr->numheaders;
 
400
                ++hdtr->headers;
 
401
            }
 
402
            else {
 
403
                char *iov_base = (char *)hdtr->headers[0].iov_base;
 
404
 
 
405
                hdtr->headers[0].iov_len -= tmplen;
 
406
                iov_base += tmplen;
 
407
                hdtr->headers[0].iov_base = iov_base;
 
408
                tmplen = 0;
 
409
            }
 
410
        }
 
411
 
 
412
        /* Skip over any file data which was written */
 
413
 
 
414
        if (tmplen <= file_bytes_left) {
 
415
            file_offset += tmplen;
 
416
            file_bytes_left -= tmplen;
 
417
            continue;
 
418
        }
 
419
 
 
420
        tmplen -= file_bytes_left;
 
421
        file_bytes_left = 0;
 
422
        file_offset = 0;
 
423
 
 
424
        /* Skip over any trailer data which was written */
 
425
 
 
426
        while (tmplen && hdtr->numtrailers) {
 
427
            if (tmplen >= hdtr->trailers[0].iov_len) {
 
428
                tmplen -= hdtr->trailers[0].iov_len;
 
429
                --hdtr->numtrailers;
 
430
                ++hdtr->trailers;
 
431
            }
 
432
            else {
 
433
                char *iov_base = (char *)hdtr->trailers[0].iov_base;
 
434
 
 
435
                hdtr->trailers[0].iov_len -= tmplen;
 
436
                iov_base += tmplen;
 
437
                hdtr->trailers[0].iov_base = iov_base;
 
438
                tmplen = 0;
 
439
            }
 
440
        }
 
441
    } while (1);
 
442
}
 
443
#endif
 
444
 
 
445
/*
 
446
 * emulate_sendfile()
 
447
 * Sends the contents of file fd along with header/trailer bytes, if any,
 
448
 * to the network. emulate_sendfile will return only when all the bytes have been
 
449
 * sent (i.e., it handles partial writes) or on a network error condition.
 
450
 */
 
451
static apr_status_t emulate_sendfile(core_net_rec *c, apr_file_t *fd,
 
452
                                     apr_hdtr_t *hdtr, apr_off_t offset,
 
453
                                     apr_size_t length, apr_size_t *nbytes)
 
454
{
 
455
    apr_status_t rv = APR_SUCCESS;
 
456
    apr_size_t togo;        /* Remaining number of bytes in the file to send */
 
457
    apr_size_t sendlen = 0;
 
458
    apr_size_t bytes_sent;
 
459
    apr_int32_t i;
 
460
    apr_off_t o;             /* Track the file offset for partial writes */
 
461
    char buffer[8192];
 
462
 
 
463
    *nbytes = 0;
 
464
 
 
465
    /* Send the headers
 
466
     * writev_it_all handles partial writes.
 
467
     * XXX: optimization... if headers are less than MIN_WRITE_SIZE, copy
 
468
     * them into buffer
 
469
     */
 
470
    if (hdtr && hdtr->numheaders > 0 ) {
 
471
        for (i = 0; i < hdtr->numheaders; i++) {
 
472
            sendlen += hdtr->headers[i].iov_len;
 
473
        }
 
474
 
 
475
        rv = writev_it_all(c->client_socket, hdtr->headers, hdtr->numheaders,
 
476
                           sendlen, &bytes_sent);
 
477
        *nbytes += bytes_sent;     /* track total bytes sent */
 
478
    }
 
479
 
 
480
    /* Seek the file to 'offset' */
 
481
    if (offset >= 0 && rv == APR_SUCCESS) {
 
482
        rv = apr_file_seek(fd, APR_SET, &offset);
 
483
    }
 
484
 
 
485
    /* Send the file, making sure to handle partial writes */
 
486
    togo = length;
 
487
    while (rv == APR_SUCCESS && togo) {
 
488
        sendlen = togo > sizeof(buffer) ? sizeof(buffer) : togo;
 
489
        o = 0;
 
490
        rv = apr_file_read(fd, buffer, &sendlen);
 
491
        while (rv == APR_SUCCESS && sendlen) {
 
492
            bytes_sent = sendlen;
 
493
            rv = apr_socket_send(c->client_socket, &buffer[o], &bytes_sent);
 
494
            *nbytes += bytes_sent;
 
495
            if (rv == APR_SUCCESS) {
 
496
                sendlen -= bytes_sent; /* sendlen != bytes_sent ==> partial write */
 
497
                o += bytes_sent;       /* o is where we are in the buffer */
 
498
                togo -= bytes_sent;    /* track how much of the file we've sent */
 
499
            }
 
500
        }
 
501
    }
 
502
 
 
503
    /* Send the trailers
 
504
     * XXX: optimization... if it will fit, send this on the last send in the
 
505
     * loop above
 
506
     */
 
507
    sendlen = 0;
 
508
    if ( rv == APR_SUCCESS && hdtr && hdtr->numtrailers > 0 ) {
 
509
        for (i = 0; i < hdtr->numtrailers; i++) {
 
510
            sendlen += hdtr->trailers[i].iov_len;
 
511
        }
 
512
        rv = writev_it_all(c->client_socket, hdtr->trailers, hdtr->numtrailers,
 
513
                           sendlen, &bytes_sent);
 
514
        *nbytes += bytes_sent;
 
515
    }
 
516
 
 
517
    return rv;
 
518
}
 
519
 
 
520
#ifndef APR_MAX_IOVEC_SIZE
 
521
#define MAX_IOVEC_TO_WRITE 16
 
522
#else
 
523
#if APR_MAX_IOVEC_SIZE > 16
 
524
#define MAX_IOVEC_TO_WRITE 16
 
525
#else
 
526
#define MAX_IOVEC_TO_WRITE APR_MAX_IOVEC_SIZE
 
527
#endif
 
528
#endif
 
529
 
 
530
/* Optional function coming from mod_logio, used for logging of output
 
531
 * traffic
 
532
 */
 
533
extern APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *logio_add_bytes_out;
 
534
 
 
535
apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
 
536
{
 
537
    apr_status_t rv;
 
538
    apr_bucket_brigade *more;
 
539
    conn_rec *c = f->c;
 
540
    core_net_rec *net = f->ctx;
 
541
    core_output_filter_ctx_t *ctx = net->out_ctx;
 
542
    apr_read_type_e eblock = APR_NONBLOCK_READ;
 
543
    apr_pool_t *input_pool = b->p;
 
544
 
 
545
    if (ctx == NULL) {
 
546
        ctx = apr_pcalloc(c->pool, sizeof(*ctx));
 
547
        net->out_ctx = ctx;
 
548
    }
 
549
 
 
550
    /* If we have a saved brigade, concatenate the new brigade to it */
 
551
    if (ctx->b) {
 
552
        APR_BRIGADE_CONCAT(ctx->b, b);
 
553
        b = ctx->b;
 
554
        ctx->b = NULL;
 
555
    }
 
556
 
 
557
    /* Perform multiple passes over the brigade, sending batches of output
 
558
       to the connection. */
 
559
    while (b && !APR_BRIGADE_EMPTY(b)) {
 
560
        apr_size_t nbytes = 0;
 
561
        apr_bucket *last_e = NULL; /* initialized for debugging */
 
562
        apr_bucket *e;
 
563
 
 
564
        /* one group of iovecs per pass over the brigade */
 
565
        apr_size_t nvec = 0;
 
566
        apr_size_t nvec_trailers = 0;
 
567
        struct iovec vec[MAX_IOVEC_TO_WRITE];
 
568
        struct iovec vec_trailers[MAX_IOVEC_TO_WRITE];
 
569
 
 
570
        /* one file per pass over the brigade */
 
571
        apr_file_t *fd = NULL;
 
572
        apr_size_t flen = 0;
 
573
        apr_off_t foffset = 0;
 
574
 
 
575
        /* keep track of buckets that we've concatenated
 
576
         * to avoid small writes
 
577
         */
 
578
        apr_bucket *last_merged_bucket = NULL;
 
579
 
 
580
        /* tail of brigade if we need another pass */
 
581
        more = NULL;
 
582
 
 
583
        /* Iterate over the brigade: collect iovecs and/or a file */
 
584
        for (e = APR_BRIGADE_FIRST(b);
 
585
             e != APR_BRIGADE_SENTINEL(b);
 
586
             e = APR_BUCKET_NEXT(e))
 
587
        {
 
588
            /* keep track of the last bucket processed */
 
589
            last_e = e;
 
590
            if (APR_BUCKET_IS_EOS(e) || AP_BUCKET_IS_EOC(e)) {
 
591
                break;
 
592
            }
 
593
            else if (APR_BUCKET_IS_FLUSH(e)) {
 
594
                if (e != APR_BRIGADE_LAST(b)) {
 
595
                    more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
 
596
                }
 
597
                break;
 
598
            }
 
599
 
 
600
            /* It doesn't make any sense to use sendfile for a file bucket
 
601
             * that represents 10 bytes.
 
602
             */
 
603
            else if (APR_BUCKET_IS_FILE(e)
 
604
                     && (e->length >= AP_MIN_SENDFILE_BYTES)) {
 
605
                apr_bucket_file *a = e->data;
 
606
 
 
607
                /* We can't handle more than one file bucket at a time
 
608
                 * so we split here and send the file we have already
 
609
                 * found.
 
610
                 */
 
611
                if (fd) {
 
612
                    more = apr_brigade_split(b, e);
 
613
                    break;
 
614
                }
 
615
 
 
616
                fd = a->fd;
 
617
                flen = e->length;
 
618
                foffset = e->start;
 
619
            }
 
620
            else {
 
621
                const char *str;
 
622
                apr_size_t n;
 
623
 
 
624
                rv = apr_bucket_read(e, &str, &n, eblock);
 
625
                if (APR_STATUS_IS_EAGAIN(rv)) {
 
626
                    /* send what we have so far since we shouldn't expect more
 
627
                     * output for a while...  next time we read, block
 
628
                     */
 
629
                    more = apr_brigade_split(b, e);
 
630
                    eblock = APR_BLOCK_READ;
 
631
                    break;
 
632
                }
 
633
                eblock = APR_NONBLOCK_READ;
 
634
                if (n) {
 
635
                    if (!fd) {
 
636
                        if (nvec == MAX_IOVEC_TO_WRITE) {
 
637
                            /* woah! too many. buffer them up, for use later. */
 
638
                            apr_bucket *temp, *next;
 
639
                            apr_bucket_brigade *temp_brig;
 
640
 
 
641
                            if (nbytes >= AP_MIN_BYTES_TO_WRITE) {
 
642
                                /* We have enough data in the iovec
 
643
                                 * to justify doing a writev
 
644
                                 */
 
645
                                more = apr_brigade_split(b, e);
 
646
                                break;
 
647
                            }
 
648
 
 
649
                            /* Create a temporary brigade as a means
 
650
                             * of concatenating a bunch of buckets together
 
651
                             */
 
652
                            if (last_merged_bucket) {
 
653
                                /* If we've concatenated together small
 
654
                                 * buckets already in a previous pass,
 
655
                                 * the initial buckets in this brigade
 
656
                                 * are heap buckets that may have extra
 
657
                                 * space left in them (because they
 
658
                                 * were created by apr_brigade_write()).
 
659
                                 * We can take advantage of this by
 
660
                                 * building the new temp brigade out of
 
661
                                 * these buckets, so that the content
 
662
                                 * in them doesn't have to be copied again.
 
663
                                 */
 
664
                                apr_bucket_brigade *bb;
 
665
                                bb = apr_brigade_split(b,
 
666
                                         APR_BUCKET_NEXT(last_merged_bucket));
 
667
                                temp_brig = b;
 
668
                                b = bb;
 
669
                            }
 
670
                            else {
 
671
                                temp_brig = apr_brigade_create(f->c->pool,
 
672
                                                           f->c->bucket_alloc);
 
673
                            }
 
674
 
 
675
                            temp = APR_BRIGADE_FIRST(b);
 
676
                            while (temp != e) {
 
677
                                apr_bucket *d;
 
678
                                rv = apr_bucket_read(temp, &str, &n, APR_BLOCK_READ);
 
679
                                apr_brigade_write(temp_brig, NULL, NULL, str, n);
 
680
                                d = temp;
 
681
                                temp = APR_BUCKET_NEXT(temp);
 
682
                                apr_bucket_delete(d);
 
683
                            }
 
684
 
 
685
                            nvec = 0;
 
686
                            nbytes = 0;
 
687
                            temp = APR_BRIGADE_FIRST(temp_brig);
 
688
                            APR_BUCKET_REMOVE(temp);
 
689
                            APR_BRIGADE_INSERT_HEAD(b, temp);
 
690
                            apr_bucket_read(temp, &str, &n, APR_BLOCK_READ);
 
691
                            vec[nvec].iov_base = (char*) str;
 
692
                            vec[nvec].iov_len = n;
 
693
                            nvec++;
 
694
 
 
695
                            /* Just in case the temporary brigade has
 
696
                             * multiple buckets, recover the rest of
 
697
                             * them and put them in the brigade that
 
698
                             * we're sending.
 
699
                             */
 
700
                            for (next = APR_BRIGADE_FIRST(temp_brig);
 
701
                                 next != APR_BRIGADE_SENTINEL(temp_brig);
 
702
                                 next = APR_BRIGADE_FIRST(temp_brig)) {
 
703
                                APR_BUCKET_REMOVE(next);
 
704
                                APR_BUCKET_INSERT_AFTER(temp, next);
 
705
                                temp = next;
 
706
                                apr_bucket_read(next, &str, &n,
 
707
                                                APR_BLOCK_READ);
 
708
                                vec[nvec].iov_base = (char*) str;
 
709
                                vec[nvec].iov_len = n;
 
710
                                nvec++;
 
711
                            }
 
712
 
 
713
                            apr_brigade_destroy(temp_brig);
 
714
 
 
715
                            last_merged_bucket = temp;
 
716
                            e = temp;
 
717
                            last_e = e;
 
718
                        }
 
719
                        else {
 
720
                            vec[nvec].iov_base = (char*) str;
 
721
                            vec[nvec].iov_len = n;
 
722
                            nvec++;
 
723
                        }
 
724
                    }
 
725
                    else {
 
726
                        /* The bucket is a trailer to a file bucket */
 
727
 
 
728
                        if (nvec_trailers == MAX_IOVEC_TO_WRITE) {
 
729
                            /* woah! too many. stop now. */
 
730
                            more = apr_brigade_split(b, e);
 
731
                            break;
 
732
                        }
 
733
 
 
734
                        vec_trailers[nvec_trailers].iov_base = (char*) str;
 
735
                        vec_trailers[nvec_trailers].iov_len = n;
 
736
                        nvec_trailers++;
 
737
                    }
 
738
 
 
739
                    nbytes += n;
 
740
                }
 
741
            }
 
742
        }
 
743
 
 
744
 
 
745
        /* Completed iterating over the brigade, now determine if we want
 
746
         * to buffer the brigade or send the brigade out on the network.
 
747
         *
 
748
         * Save if we haven't accumulated enough bytes to send, the connection
 
749
         * is not about to be closed, and:
 
750
         *
 
751
         *   1) we didn't see a file, we don't have more passes over the
 
752
         *      brigade to perform,  AND we didn't stop at a FLUSH bucket.
 
753
         *      (IOW, we will save plain old bytes such as HTTP headers)
 
754
         * or
 
755
         *   2) we hit the EOS and have a keep-alive connection
 
756
         *      (IOW, this response is a bit more complex, but we save it
 
757
         *       with the hope of concatenating with another response)
 
758
         */
 
759
        if (nbytes + flen < AP_MIN_BYTES_TO_WRITE
 
760
            && !AP_BUCKET_IS_EOC(last_e)
 
761
            && ((!fd && !more && !APR_BUCKET_IS_FLUSH(last_e))
 
762
                || (APR_BUCKET_IS_EOS(last_e)
 
763
                    && c->keepalive == AP_CONN_KEEPALIVE))) {
 
764
 
 
765
            /* NEVER save an EOS in here.  If we are saving a brigade with
 
766
             * an EOS bucket, then we are doing keepalive connections, and
 
767
             * we want to process to second request fully.
 
768
             */
 
769
            if (APR_BUCKET_IS_EOS(last_e)) {
 
770
                apr_bucket *bucket;
 
771
                int file_bucket_saved = 0;
 
772
                apr_bucket_delete(last_e);
 
773
                for (bucket = APR_BRIGADE_FIRST(b);
 
774
                     bucket != APR_BRIGADE_SENTINEL(b);
 
775
                     bucket = APR_BUCKET_NEXT(bucket)) {
 
776
 
 
777
                    /* Do a read on each bucket to pull in the
 
778
                     * data from pipe and socket buckets, so
 
779
                     * that we don't leave their file descriptors
 
780
                     * open indefinitely.  Do the same for file
 
781
                     * buckets, with one exception: allow the
 
782
                     * first file bucket in the brigade to remain
 
783
                     * a file bucket, so that we don't end up
 
784
                     * doing an mmap+memcpy every time a client
 
785
                     * requests a <8KB file over a keepalive
 
786
                     * connection.
 
787
                     */
 
788
                    if (APR_BUCKET_IS_FILE(bucket) && !file_bucket_saved) {
 
789
                        file_bucket_saved = 1;
 
790
                    }
 
791
                    else {
 
792
                        const char *buf;
 
793
                        apr_size_t len = 0;
 
794
                        rv = apr_bucket_read(bucket, &buf, &len,
 
795
                                             APR_BLOCK_READ);
 
796
                        if (rv != APR_SUCCESS) {
 
797
                            ap_log_cerror(APLOG_MARK, APLOG_ERR, rv,
 
798
                                          c, "core_output_filter:"
 
799
                                          " Error reading from bucket.");
 
800
                            return HTTP_INTERNAL_SERVER_ERROR;
 
801
                        }
 
802
                    }
 
803
                }
 
804
            }
 
805
            if (!ctx->deferred_write_pool) {
 
806
                apr_pool_create(&ctx->deferred_write_pool, c->pool);
 
807
                apr_pool_tag(ctx->deferred_write_pool, "deferred_write");
 
808
            }
 
809
            ap_save_brigade(f, &ctx->b, &b, ctx->deferred_write_pool);
 
810
 
 
811
            return APR_SUCCESS;
 
812
        }
 
813
 
 
814
        if (fd) {
 
815
            apr_hdtr_t hdtr;
 
816
            apr_size_t bytes_sent;
 
817
 
 
818
#if APR_HAS_SENDFILE
 
819
            apr_int32_t flags = 0;
 
820
#endif
 
821
 
 
822
            memset(&hdtr, '\0', sizeof(hdtr));
 
823
            if (nvec) {
 
824
                hdtr.numheaders = nvec;
 
825
                hdtr.headers = vec;
 
826
            }
 
827
 
 
828
            if (nvec_trailers) {
 
829
                hdtr.numtrailers = nvec_trailers;
 
830
                hdtr.trailers = vec_trailers;
 
831
            }
 
832
 
 
833
#if APR_HAS_SENDFILE
 
834
            if (apr_file_flags_get(fd) & APR_SENDFILE_ENABLED) {
 
835
 
 
836
                if (c->keepalive == AP_CONN_CLOSE && APR_BUCKET_IS_EOS(last_e)) {
 
837
                    /* Prepare the socket to be reused */
 
838
                    flags |= APR_SENDFILE_DISCONNECT_SOCKET;
 
839
                }
 
840
 
 
841
                rv = sendfile_it_all(net,      /* the network information   */
 
842
                                     fd,       /* the file to send          */
 
843
                                     &hdtr,    /* header and trailer iovecs */
 
844
                                     foffset,  /* offset in the file to begin
 
845
                                                  sending from              */
 
846
                                     flen,     /* length of file            */
 
847
                                     nbytes + flen, /* total length including
 
848
                                                       headers              */
 
849
                                     &bytes_sent,   /* how many bytes were
 
850
                                                       sent                 */
 
851
                                     flags);   /* apr_sendfile flags        */
 
852
            }
 
853
            else
 
854
#endif
 
855
            {
 
856
                rv = emulate_sendfile(net, fd, &hdtr, foffset, flen,
 
857
                                      &bytes_sent);
 
858
            }
 
859
 
 
860
            if (logio_add_bytes_out && bytes_sent > 0)
 
861
                logio_add_bytes_out(c, bytes_sent);
 
862
 
 
863
            fd = NULL;
 
864
        }
 
865
        else {
 
866
            apr_size_t bytes_sent;
 
867
 
 
868
            rv = writev_it_all(net->client_socket,
 
869
                               vec, nvec,
 
870
                               nbytes, &bytes_sent);
 
871
 
 
872
            if (logio_add_bytes_out && bytes_sent > 0)
 
873
                logio_add_bytes_out(c, bytes_sent);
 
874
        }
 
875
 
 
876
        apr_brigade_destroy(b);
 
877
 
 
878
        /* drive cleanups for resources which were set aside
 
879
         * this may occur before or after termination of the request which
 
880
         * created the resource
 
881
         */
 
882
        if (ctx->deferred_write_pool) {
 
883
            if (more && more->p == ctx->deferred_write_pool) {
 
884
                /* "more" belongs to the deferred_write_pool,
 
885
                 * which is about to be cleared.
 
886
                 */
 
887
                if (APR_BRIGADE_EMPTY(more)) {
 
888
                    more = NULL;
 
889
                }
 
890
                else {
 
891
                    /* uh oh... change more's lifetime
 
892
                     * to the input brigade's lifetime
 
893
                     */
 
894
                    apr_bucket_brigade *tmp_more = more;
 
895
                    more = NULL;
 
896
                    ap_save_brigade(f, &more, &tmp_more, input_pool);
 
897
                }
 
898
            }
 
899
            apr_pool_clear(ctx->deferred_write_pool);
 
900
        }
 
901
 
 
902
        if (rv != APR_SUCCESS) {
 
903
            ap_log_cerror(APLOG_MARK, APLOG_INFO, rv, c,
 
904
                          "core_output_filter: writing data to the network");
 
905
 
 
906
            if (more)
 
907
                apr_brigade_destroy(more);
 
908
 
 
909
            /* No need to check for SUCCESS, we did that above. */
 
910
            if (!APR_STATUS_IS_EAGAIN(rv)) {
 
911
                c->aborted = 1;
 
912
            }
 
913
 
 
914
            /* The client has aborted, but the request was successful. We
 
915
             * will report success, and leave it to the access and error
 
916
             * logs to note that the connection was aborted.
 
917
             */
 
918
            return APR_SUCCESS;
 
919
        }
 
920
 
 
921
        b = more;
 
922
        more = NULL;
 
923
    }  /* end while () */
 
924
 
 
925
    return APR_SUCCESS;
 
926
}