core_filters.c revision 7184de27ec1d62a83c41cdeac0953ca9fd661e8c
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * http://www.apache.org/licenses/LICENSE-2.0
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick/**
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * @file core_filters.c
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * @brief Core input/output network filters.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "apr.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "apr_strings.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "apr_lib.h"
d6e81217d873dc3b87fc4ffa5fbac2fad4191a15pquerna#include "apr_fnmatch.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "apr_hash.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "apr_thread_proc.h" /* for RLIMIT stuff */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define APR_WANT_IOVEC
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick#define APR_WANT_STRFUNC
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define APR_WANT_MEMFUNC
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "apr_want.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "ap_config.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "httpd.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "http_config.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "http_core.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "http_protocol.h" /* For index_of_response(). Grump. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "http_request.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "http_vhost.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "http_main.h" /* For the default_handler below... */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "http_log.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "util_md5.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "http_connection.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "apr_buckets.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "util_filter.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "util_ebcdic.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "mpm_common.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "scoreboard.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "mod_core.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "mod_proxy.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "ap_listen.h"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#include "mod_so.h" /* for ap_find_loaded_module_symbol */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define AP_MIN_SENDFILE_BYTES (256)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick/**
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * Remove all zero length buckets from the brigade.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define BRIGADE_NORMALIZE(b) \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickdo { \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *e = APR_BRIGADE_FIRST(b); \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick do { \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (e->length == 0 && !APR_BUCKET_IS_METADATA(e)) { \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *d; \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick d = APR_BUCKET_NEXT(e); \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_delete(e); \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = d; \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick } \
762d10071eea0a55eed24e7c3da72c693db2d944trawick else { \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = APR_BUCKET_NEXT(e); \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick } \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick } while (!APR_BRIGADE_EMPTY(b) && (e != APR_BRIGADE_SENTINEL(b))); \
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick} while (0)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick/* we know core's module_index is 0 */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#undef APLOG_MODULE_INDEX
e8f95a682820a599fe41b22977010636be5c2717jim#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
e8f95a682820a599fe41b22977010636be5c2717jim
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawickint ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ap_input_mode_t mode, apr_read_type_e block,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_off_t readbytes)
1d509de8742bc4904aad80d982650393cd5bc1f3trawick{
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *e;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_status_t rv;
1d509de8742bc4904aad80d982650393cd5bc1f3trawick core_net_rec *net = f->ctx;
1d509de8742bc4904aad80d982650393cd5bc1f3trawick core_ctx_t *ctx = net->in_ctx;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick const char *str;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t len;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (mode == AP_MODE_INIT) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /*
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * this mode is for filters that might need to 'initialize'
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * a connection before reading request data from a client.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * NNTP over SSL for example needs to handshake before the
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * server sends the welcome message.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * such filters would have changed the mode before this point
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * is reached. however, protocol modules such as NNTP should
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * not need to know anything about SSL. given the example, if
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * SSL is not in the filter chain, AP_MODE_INIT is a noop.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (!ctx)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx->tmpbb = apr_brigade_create(ctx->b->p, ctx->b->bucket_alloc);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* seed the brigade with the client socket. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = apr_bucket_socket_create(net->client_socket, f->c->bucket_alloc);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BRIGADE_INSERT_TAIL(ctx->b, e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick net->in_ctx = ctx;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (APR_BRIGADE_EMPTY(ctx->b)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_EOF;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* ### This is bad. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick BRIGADE_NORMALIZE(ctx->b);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* check for empty brigade again *AFTER* BRIGADE_NORMALIZE()
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * If we have lost our socket bucket (see above), we are EOF.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * Ideally, this should be returning SUCCESS with EOS bucket, but
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * some higher-up APIs (spec. read_request_line via ap_rgetline)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * want an error code. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (APR_BRIGADE_EMPTY(ctx->b)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_EOF;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (mode == AP_MODE_GETLINE) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* we are reading a single LF line, e.g. the HTTP headers */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = apr_brigade_split_line(b, ctx->b, block, HUGE_STRING_LEN);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* We should treat EAGAIN here the same as we do for EOF (brigade is
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * empty). We do this by returning whatever we have read. This may
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * or may not be bogus, but is consistent (for now) with EOF logic.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (APR_STATUS_IS_EAGAIN(rv)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
e8f95a682820a599fe41b22977010636be5c2717jim /* ### AP_MODE_PEEK is a horrific name for this mode because we also
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * eat any CRLFs that we see. That's not the obvious intention of
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * this mode. Determine whether anyone actually uses this or not. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (mode == AP_MODE_EATCRLF) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *e;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick const char *c;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* The purpose of this loop is to ignore any CRLF (or LF) at the end
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * of a request. Many browsers send extra lines at the end of POST
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * requests. We use the PEEK method to determine if there is more
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * data on the socket, so that we know if we should delay sending the
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * end of one request until we have served the second request in a
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * pipelined situation. We don't want to actually delay sending a
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * response if the server finds a CRLF (or LF), becuause that doesn't
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * mean that there is another request, just a blank line.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick while (1) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (APR_BRIGADE_EMPTY(ctx->b))
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_EOF;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = APR_BRIGADE_FIRST(ctx->b);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick c = str;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick while (c < str + len) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (*c == APR_ASCII_LF)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick c++;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick c += 2;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* If we reach here, we were a bucket just full of CRLFs, so
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * just toss the bucket. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* FIXME: Is this the right thing to do in the core? */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_delete(e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
6e128d9c91437b22850d19fc166a6165e3c4831ctrawick
6e128d9c91437b22850d19fc166a6165e3c4831ctrawick /* If mode is EXHAUSTIVE, we want to just read everything until the end
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * of the brigade, which in this case means the end of the socket.
6e128d9c91437b22850d19fc166a6165e3c4831ctrawick * To do this, we attach the brigade that has currently been setaside to
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * the brigade that was passed down, and send that brigade back.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * NOTE: This is VERY dangerous to use, and should only be done with
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * extreme caution. FWLIW, this would be needed by an MPM like Perchild;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * such an MPM can easily request the socket and all data that has been
e8f95a682820a599fe41b22977010636be5c2717jim * read, which means that it can pass it to the correct child process.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (mode == AP_MODE_EXHAUSTIVE) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *e;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Tack on any buckets that were set aside. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BRIGADE_CONCAT(b, ctx->b);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Since we've just added all potential buckets (which will most
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * likely simply be the socket bucket) we know this is the end,
fafad9231a6b47368d4b690346f90698542caa50trawick * so tack on an EOS too. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* We have read until the brigade was empty, so we know that we
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * must be EOS. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = apr_bucket_eos_create(f->c->bucket_alloc);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BRIGADE_INSERT_TAIL(b, e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
fafad9231a6b47368d4b690346f90698542caa50trawick /* read up to the amount they specified. */
fafad9231a6b47368d4b690346f90698542caa50trawick if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE) {
fafad9231a6b47368d4b690346f90698542caa50trawick apr_bucket *e;
fafad9231a6b47368d4b690346f90698542caa50trawick
fafad9231a6b47368d4b690346f90698542caa50trawick AP_DEBUG_ASSERT(readbytes > 0);
fafad9231a6b47368d4b690346f90698542caa50trawick
fafad9231a6b47368d4b690346f90698542caa50trawick e = APR_BRIGADE_FIRST(ctx->b);
fafad9231a6b47368d4b690346f90698542caa50trawick rv = apr_bucket_read(e, &str, &len, block);
fafad9231a6b47368d4b690346f90698542caa50trawick
fafad9231a6b47368d4b690346f90698542caa50trawick if (APR_STATUS_IS_EAGAIN(rv)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (block == APR_BLOCK_READ && len == 0) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* We wanted to read some bytes in blocking mode. We read
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * 0 bytes. Hence, we now assume we are EOS.
fafad9231a6b47368d4b690346f90698542caa50trawick *
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * When we are in normal mode, return an EOS bucket to the
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * caller.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * When we are in speculative mode, leave ctx->b empty, so
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * that the next call returns an EOS bucket.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_delete(e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (mode == AP_MODE_READBYTES) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = apr_bucket_eos_create(f->c->bucket_alloc);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BRIGADE_INSERT_TAIL(b, e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Have we read as much data as we wanted (be greedy)? */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (len < readbytes) {
e8f95a682820a599fe41b22977010636be5c2717jim apr_size_t bucket_len;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* We already registered the data in e in len */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = APR_BUCKET_NEXT(e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick while ((len < readbytes) && (rv == APR_SUCCESS)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick && (e != APR_BRIGADE_SENTINEL(ctx->b))) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Check for the availability of buckets with known length */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (e->length != -1) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick len += e->length;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = APR_BUCKET_NEXT(e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /*
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * Read from bucket, but non blocking. If there isn't any
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * more data, well than this is fine as well, we will
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * not wait for more since we already got some and we are
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * only checking if there isn't more.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = apr_bucket_read(e, &str, &bucket_len,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_NONBLOCK_READ);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv == APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick len += bucket_len;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = APR_BUCKET_NEXT(e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* We can only return at most what we read. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (len < readbytes) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick readbytes = len;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = apr_brigade_partition(ctx->b, readbytes, &e);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
e8f95a682820a599fe41b22977010636be5c2717jim return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Must do move before CONCAT */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx->tmpbb = apr_brigade_split_ex(ctx->b, e, ctx->tmpbb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (mode == AP_MODE_READBYTES) {
e8f95a682820a599fe41b22977010636be5c2717jim APR_BRIGADE_CONCAT(b, ctx->b);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (mode == AP_MODE_SPECULATIVE) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *copy_bucket;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick for (e = APR_BRIGADE_FIRST(ctx->b);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e != APR_BRIGADE_SENTINEL(ctx->b);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick e = APR_BUCKET_NEXT(e))
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = apr_bucket_copy(e, &copy_bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BRIGADE_INSERT_TAIL(b, copy_bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Take what was originally there and place it back on ctx->b */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BRIGADE_CONCAT(ctx->b, ctx->tmpbb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick}
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickstatic void setaside_remaining_output(ap_filter_t *f,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick core_output_filter_ctx_t *ctx,
e8f95a682820a599fe41b22977010636be5c2717jim apr_bucket_brigade *bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickstatic apr_status_t send_brigade_nonblocking(apr_socket_t *s,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_brigade *bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t *bytes_written,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawickstatic void remove_empty_buckets(apr_bucket_brigade *bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickstatic apr_status_t send_brigade_blocking(apr_socket_t *s,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_brigade *bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t *bytes_written,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickstatic apr_status_t writev_nonblocking(apr_socket_t *s,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick struct iovec *vec, apr_size_t nvec,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_brigade *bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t *cumulative_bytes_written,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#if APR_HAS_SENDFILE
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickstatic apr_status_t sendfile_nonblocking(apr_socket_t *s,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *bucket,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t *cumulative_bytes_written,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#endif
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick/* XXX: Should these be configurable parameters? */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define THRESHOLD_MIN_WRITE 4096
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define THRESHOLD_MAX_BUFFER 65536
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define MAX_REQUESTS_IN_PIPELINE 5
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick/* Optional function coming from mod_logio, used for logging of output
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * traffic
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickextern APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *ap__logio_add_bytes_out;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickapr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick{
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c = f->c;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick core_net_rec *net = f->ctx;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick core_output_filter_ctx_t *ctx = net->out_ctx;
e8f95a682820a599fe41b22977010636be5c2717jim apr_bucket_brigade *bb = NULL;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *bucket, *next, *flush_upto = NULL;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t bytes_in_brigade, non_file_bytes_in_brigade;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick int eor_buckets_in_brigade;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_status_t rv;
e8f95a682820a599fe41b22977010636be5c2717jim
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Fail quickly if the connection has already been aborted. */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (c->aborted) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (new_bb != NULL) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_brigade_cleanup(new_bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_ECONNABORTED;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (ctx == NULL) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx = apr_pcalloc(c->pool, sizeof(*ctx));
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick net->out_ctx = (core_output_filter_ctx_t *)ctx;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = apr_socket_opt_set(net->client_socket, APR_SO_NONBLOCK, 1);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /*
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * Need to create tmp brigade with correct lifetime. Passing
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * NULL to apr_brigade_split_ex would result in a brigade
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * allocated from bb->pool which might be wrong.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx->tmp_flush_bb = apr_brigade_create(c->pool, c->bucket_alloc);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* same for buffered_bb and ap_save_brigade */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx->buffered_bb = apr_brigade_create(c->pool, c->bucket_alloc);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (new_bb != NULL) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick for (bucket = APR_BRIGADE_FIRST(new_bb); bucket != APR_BRIGADE_SENTINEL(new_bb); bucket = APR_BUCKET_NEXT(bucket)) {
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick if (bucket->length > 0) {
1d509de8742bc4904aad80d982650393cd5bc1f3trawick ctx->bytes_in += bucket->length;
1d509de8742bc4904aad80d982650393cd5bc1f3trawick }
1d509de8742bc4904aad80d982650393cd5bc1f3trawick }
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick bb = new_bb;
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick }
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick
1d509de8742bc4904aad80d982650393cd5bc1f3trawick if ((ctx->buffered_bb != NULL) &&
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick !APR_BRIGADE_EMPTY(ctx->buffered_bb)) {
1d509de8742bc4904aad80d982650393cd5bc1f3trawick if (new_bb != NULL) {
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick APR_BRIGADE_PREPEND(bb, ctx->buffered_bb);
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick }
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick else {
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick bb = ctx->buffered_bb;
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick }
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick c->data_in_output_filters = 0;
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick }
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick else if (new_bb == NULL) {
9efe68be3c81ee85225972195fb725dbfc2e8b24trawick return APR_SUCCESS;
1d509de8742bc4904aad80d982650393cd5bc1f3trawick }
1d509de8742bc4904aad80d982650393cd5bc1f3trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Scan through the brigade and decide whether to attempt a write,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * based on the following rules:
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * 1) The new_bb is null: Do a nonblocking write of as much as
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * possible: do a nonblocking write of as much data as possible,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * then save the rest in ctx->buffered_bb. (If new_bb == NULL,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * it probably means that the MPM is doing asynchronous write
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * completion and has just determined that this connection
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * is writable.)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * 2) The brigade contains a flush bucket: Do a blocking write
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * of everything up that point.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * 3) The request is in CONN_STATE_HANDLER state, and the brigade
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * contains at least THRESHOLD_MAX_BUFFER bytes in non-file
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * buckets: Do blocking writes until the amount of data in the
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * buffer is less than THRESHOLD_MAX_BUFFER. (The point of this
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * rule is to provide flow control, in case a handler is
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * streaming out lots of data faster than the data can be
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * sent to the client.)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * 4) The request is in CONN_STATE_HANDLER state, and the brigade
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * contains at least MAX_REQUESTS_IN_PIPELINE EOR buckets:
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * Do blocking writes until less than MAX_REQUESTS_IN_PIPELINE EOR
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * buckets are left. (The point of this rule is to prevent too many
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * FDs being kept open by pipelined requests, possibly allowing a
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * DoS).
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * 5) The brigade contains at least THRESHOLD_MIN_WRITE
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * bytes: Do a nonblocking write of as much data as possible,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * then save the rest in ctx->buffered_bb.
1d509de8742bc4904aad80d982650393cd5bc1f3trawick */
1d509de8742bc4904aad80d982650393cd5bc1f3trawick
1d509de8742bc4904aad80d982650393cd5bc1f3trawick if (new_bb == NULL) {
e8f95a682820a599fe41b22977010636be5c2717jim rv = send_brigade_nonblocking(net->client_socket, bb,
1d509de8742bc4904aad80d982650393cd5bc1f3trawick &(ctx->bytes_written), c);
1d509de8742bc4904aad80d982650393cd5bc1f3trawick if (APR_STATUS_IS_EAGAIN(rv)) {
1d509de8742bc4904aad80d982650393cd5bc1f3trawick rv = APR_SUCCESS;
1d509de8742bc4904aad80d982650393cd5bc1f3trawick }
e8f95a682820a599fe41b22977010636be5c2717jim else if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* The client has aborted the connection */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick c->aborted = 1;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick setaside_remaining_output(f, ctx, bb, c);
a16ca336064074171bffc3a6da3444243a06b62btrawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick bytes_in_brigade = 0;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick non_file_bytes_in_brigade = 0;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick eor_buckets_in_brigade = 0;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick bucket = next) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick next = APR_BUCKET_NEXT(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (!APR_BUCKET_IS_METADATA(bucket)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (bucket->length == (apr_size_t)-1) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick const char *data;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t length;
e8f95a682820a599fe41b22977010636be5c2717jim /* XXX support nonblocking read here? */
e8f95a682820a599fe41b22977010636be5c2717jim rv = apr_bucket_read(bucket, &data, &length, APR_BLOCK_READ);
e8f95a682820a599fe41b22977010636be5c2717jim if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
e8f95a682820a599fe41b22977010636be5c2717jim }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* reading may have split the bucket, so recompute next: */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick next = APR_BUCKET_NEXT(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick bytes_in_brigade += bucket->length;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (!APR_BUCKET_IS_FILE(bucket)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick non_file_bytes_in_brigade += bucket->length;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (AP_BUCKET_IS_EOR(bucket)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick eor_buckets_in_brigade++;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (APR_BUCKET_IS_FLUSH(bucket) ||
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick (non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER) ||
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick (eor_buckets_in_brigade > MAX_REQUESTS_IN_PIPELINE) )
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick {
e8f95a682820a599fe41b22977010636be5c2717jim if (APLOGctrace6(c)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick char *reason = APR_BUCKET_IS_FLUSH(bucket) ?
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick "FLUSH bucket" :
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick (non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER) ?
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick "THRESHOLD_MAX_BUFFER" :
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick "MAX_REQUESTS_IN_PIPELINE";
762d10071eea0a55eed24e7c3da72c693db2d944trawick ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, c,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick "core_output_filter: flushing because of %s",
762d10071eea0a55eed24e7c3da72c693db2d944trawick reason);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
762d10071eea0a55eed24e7c3da72c693db2d944trawick /*
762d10071eea0a55eed24e7c3da72c693db2d944trawick * Defer the actual blocking write to avoid doing many writes.
762d10071eea0a55eed24e7c3da72c693db2d944trawick */
762d10071eea0a55eed24e7c3da72c693db2d944trawick flush_upto = next;
762d10071eea0a55eed24e7c3da72c693db2d944trawick
762d10071eea0a55eed24e7c3da72c693db2d944trawick bytes_in_brigade = 0;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick non_file_bytes_in_brigade = 0;
762d10071eea0a55eed24e7c3da72c693db2d944trawick eor_buckets_in_brigade = 0;
762d10071eea0a55eed24e7c3da72c693db2d944trawick }
762d10071eea0a55eed24e7c3da72c693db2d944trawick }
762d10071eea0a55eed24e7c3da72c693db2d944trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (flush_upto != NULL) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx->tmp_flush_bb = apr_brigade_split_ex(bb, flush_upto,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx->tmp_flush_bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = send_brigade_blocking(net->client_socket, bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick &(ctx->bytes_written), c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* The client has aborted the connection */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick c->aborted = 1;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
e8f95a682820a599fe41b22977010636be5c2717jim }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BRIGADE_CONCAT(bb, ctx->tmp_flush_bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (bytes_in_brigade >= THRESHOLD_MIN_WRITE) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = send_brigade_nonblocking(net->client_socket, bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick &(ctx->bytes_written), c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if ((rv != APR_SUCCESS) && (!APR_STATUS_IS_EAGAIN(rv))) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* The client has aborted the connection */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick c->aborted = 1;
e8f95a682820a599fe41b22977010636be5c2717jim return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick setaside_remaining_output(f, ctx, bb, c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick}
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick/*
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * This function assumes that either ctx->buffered_bb == NULL, or
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * ctx->buffered_bb is empty, or ctx->buffered_bb == bb
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickstatic void setaside_remaining_output(ap_filter_t *f,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick core_output_filter_ctx_t *ctx,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_brigade *bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick{
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (bb == NULL) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick remove_empty_buckets(bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (!APR_BRIGADE_EMPTY(bb)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick c->data_in_output_filters = 1;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (bb != ctx->buffered_bb) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (!ctx->deferred_write_pool) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_pool_create(&ctx->deferred_write_pool, c->pool);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_pool_tag(ctx->deferred_write_pool, "deferred_write");
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ap_save_brigade(f, &(ctx->buffered_bb), &bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ctx->deferred_write_pool);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_brigade_cleanup(bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (ctx->deferred_write_pool) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /*
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * There are no more requests in the pipeline. We can just clear the
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * pool.
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_pool_clear(ctx->deferred_write_pool);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick}
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#ifndef APR_MAX_IOVEC_SIZE
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define MAX_IOVEC_TO_WRITE 16
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick#else
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick#if APR_MAX_IOVEC_SIZE > 16
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick#define MAX_IOVEC_TO_WRITE 16
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick#else
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#define MAX_IOVEC_TO_WRITE APR_MAX_IOVEC_SIZE
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#endif
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick#endif
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawickstatic apr_status_t send_brigade_nonblocking(apr_socket_t *s,
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick apr_bucket_brigade *bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t *bytes_written,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick{
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *bucket, *next;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_status_t rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick struct iovec vec[MAX_IOVEC_TO_WRITE];
e8f95a682820a599fe41b22977010636be5c2717jim apr_size_t nvec = 0;
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick remove_empty_buckets(bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick for (bucket = APR_BRIGADE_FIRST(bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick bucket != APR_BRIGADE_SENTINEL(bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick bucket = next) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick next = APR_BUCKET_NEXT(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#if APR_HAS_SENDFILE
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (APR_BUCKET_IS_FILE(bucket)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_file *file_bucket = (apr_bucket_file *)(bucket->data);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_file_t *fd = file_bucket->fd;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Use sendfile to send this file unless:
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * - the platform doesn't support sendfile,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * - the file is too small for sendfile to be useful, or
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick * - sendfile is disabled in the httpd config via "EnableSendfile off"
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if ((apr_file_flags_get(fd) & APR_SENDFILE_ENABLED) &&
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick (bucket->length >= AP_MIN_SENDFILE_BYTES)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (nvec > 0) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick nvec = 0;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
e8f95a682820a599fe41b22977010636be5c2717jim (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = sendfile_nonblocking(s, bucket, bytes_written, c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (nvec > 0) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick break;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#endif /* APR_HAS_SENDFILE */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* didn't sendfile */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (!APR_BUCKET_IS_METADATA(bucket)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick const char *data;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t length;
e8f95a682820a599fe41b22977010636be5c2717jim rv = apr_bucket_read(bucket, &data, &length, APR_BLOCK_READ);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick return rv;
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* reading may have split the bucket, so recompute next: */
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick next = APR_BUCKET_NEXT(bucket);
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick vec[nvec].iov_base = (char *)data;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick vec[nvec].iov_len = length;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick nvec++;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (nvec == MAX_IOVEC_TO_WRITE) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick nvec = 0;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick break;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (nvec > 0) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick remove_empty_buckets(bb);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick}
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawickstatic void remove_empty_buckets(apr_bucket_brigade *bb)
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick{
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket *bucket;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick while (((bucket = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) &&
e8f95a682820a599fe41b22977010636be5c2717jim (APR_BUCKET_IS_METADATA(bucket) || (bucket->length == 0))) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BUCKET_REMOVE(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_destroy(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick}
e8f95a682820a599fe41b22977010636be5c2717jim
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawickstatic apr_status_t send_brigade_blocking(apr_socket_t *s,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_brigade *bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t *bytes_written,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick{
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_status_t rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
e8f95a682820a599fe41b22977010636be5c2717jim rv = APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick while (!APR_BRIGADE_EMPTY(bb)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = send_brigade_nonblocking(s, bb, bytes_written, c);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (APR_STATUS_IS_EAGAIN(rv)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick /* Wait until we can send more data */
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_int32_t nsds;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_interval_time_t timeout;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_pollfd_t pollset;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick pollset.p = c->pool;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick pollset.desc_type = APR_POLL_SOCKET;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick pollset.reqevents = APR_POLLOUT;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick pollset.desc.s = s;
e8f95a682820a599fe41b22977010636be5c2717jim apr_socket_timeout_get(s, &timeout);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = apr_poll(&pollset, 1, &nsds, timeout);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick break;
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick break;
762d10071eea0a55eed24e7c3da72c693db2d944trawick }
e8f95a682820a599fe41b22977010636be5c2717jim }
762d10071eea0a55eed24e7c3da72c693db2d944trawick }
762d10071eea0a55eed24e7c3da72c693db2d944trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick}
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
762d10071eea0a55eed24e7c3da72c693db2d944trawickstatic apr_status_t writev_nonblocking(apr_socket_t *s,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick struct iovec *vec, apr_size_t nvec,
e8f95a682820a599fe41b22977010636be5c2717jim apr_bucket_brigade *bb,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t *cumulative_bytes_written,
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick conn_rec *c)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick{
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_status_t rv = APR_SUCCESS, arv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t bytes_written = 0, bytes_to_write = 0;
e8f95a682820a599fe41b22977010636be5c2717jim apr_size_t i, offset;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_interval_time_t old_timeout;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick arv = apr_socket_timeout_get(s, &old_timeout);
e8f95a682820a599fe41b22977010636be5c2717jim if (arv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return arv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick arv = apr_socket_timeout_set(s, 0);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (arv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return arv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick for (i = 0; i < nvec; i++) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick bytes_to_write += vec[i].iov_len;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick offset = 0;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick while (bytes_written < bytes_to_write) {
e8f95a682820a599fe41b22977010636be5c2717jim apr_size_t n = 0;
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick rv = apr_socket_sendv(s, vec + offset, nvec - offset, &n);
e8f95a682820a599fe41b22977010636be5c2717jim if (n > 0) {
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick bytes_written += n;
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick for (i = offset; i < nvec; ) {
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick if (APR_BUCKET_IS_METADATA(bucket)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BUCKET_REMOVE(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_destroy(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (n >= vec[i].iov_len) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BUCKET_REMOVE(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_destroy(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick offset++;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick n -= vec[i++].iov_len;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_split(bucket, n);
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick APR_BUCKET_REMOVE(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_destroy(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick vec[i].iov_len -= n;
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick vec[i].iov_base = (char *) vec[i].iov_base + n;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick break;
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley }
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley }
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley }
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley if (rv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick break;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if ((ap__logio_add_bytes_out != NULL) && (bytes_written > 0)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ap__logio_add_bytes_out(c, bytes_written);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *cumulative_bytes_written += bytes_written;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick arv = apr_socket_timeout_set(s, old_timeout);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if ((arv != APR_SUCCESS) && (rv == APR_SUCCESS)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return arv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else {
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick return rv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick}
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick#if APR_HAS_SENDFILE
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawickstatic apr_status_t sendfile_nonblocking(apr_socket_t *s,
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick apr_bucket *bucket,
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick apr_size_t *cumulative_bytes_written,
e8f95a682820a599fe41b22977010636be5c2717jim conn_rec *c)
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick{
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_status_t rv = APR_SUCCESS;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_file *file_bucket;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_file_t *fd;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t file_length;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_off_t file_offset;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t bytes_written = 0;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (!APR_BUCKET_IS_FILE(bucket)) {
e8f95a682820a599fe41b22977010636be5c2717jim ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server,
e8f95a682820a599fe41b22977010636be5c2717jim "core_filter: sendfile_nonblocking: "
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick "this should never happen");
e8f95a682820a599fe41b22977010636be5c2717jim return APR_EGENERAL;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick file_bucket = (apr_bucket_file *)(bucket->data);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick fd = file_bucket->fd;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick file_length = bucket->length;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick file_offset = bucket->start;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (bytes_written < file_length) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_size_t n = file_length - bytes_written;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_status_t arv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_interval_time_t old_timeout;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick arv = apr_socket_timeout_get(s, &old_timeout);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (arv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return arv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick arv = apr_socket_timeout_set(s, 0);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (arv != APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick return arv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick rv = apr_socket_sendfile(s, fd, NULL, &file_offset, &n, 0);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if (rv == APR_SUCCESS) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick bytes_written += n;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick file_offset += n;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick arv = apr_socket_timeout_set(s, old_timeout);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if ((arv != APR_SUCCESS) && (rv == APR_SUCCESS)) {
e8f95a682820a599fe41b22977010636be5c2717jim rv = arv;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if ((ap__logio_add_bytes_out != NULL) && (bytes_written > 0)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick ap__logio_add_bytes_out(c, bytes_written);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick *cumulative_bytes_written += bytes_written;
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick if ((bytes_written < file_length) && (bytes_written > 0)) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_split(bucket, bytes_written);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BUCKET_REMOVE(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick apr_bucket_destroy(bucket);
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick }
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick else if (bytes_written == file_length) {
acc9093ae1f3c97acc635bd5b2c7c0969da21183trawick APR_BUCKET_REMOVE(bucket);
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick apr_bucket_destroy(bucket);
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick }
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick return rv;
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick}
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick#endif
aa9b03a5f32732c0caaef03a7ed78ffb290e29e4trawick