1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define APR_WANT_STRFUNC
21 #include "apr_strings.h"
24 #include "http_config.h"
25 #include "http_core.h"
27 #include "http_request.h"
28 #include "util_filter.h"
30 /* NOTE: Apache's current design doesn't allow a pool to be passed thru,
31 so we depend on a global to hold the correct pool
33 #define FILTER_POOL apr_hook_global_pool
34 #include "ap_hooks.h" /* for apr_hook_global_pool */
36 /* XXX: Should these be configurable parameters? */
37 #define THRESHOLD_MAX_BUFFER 65536
38 #define MAX_REQUESTS_IN_PIPELINE 5
41 ** This macro returns true/false if a given filter should be inserted BEFORE
42 ** another filter. This will happen when one of: 1) there isn't another
43 ** filter; 2) that filter has a higher filter type (class); 3) that filter
44 ** corresponds to a different request.
46 #define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
47 || (before_this)->frec->ftype > (f)->frec->ftype \
48 || (before_this)->r != (f)->r)
50 /* Trie structure to hold the mapping from registered
51 * filter names to filters
54 /* we know core's module_index is 0 */
55 #undef APLOG_MODULE_INDEX
56 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
58 typedef struct filter_trie_node filter_trie_node;
62 filter_trie_node *child;
63 } filter_trie_child_ptr;
65 /* Each trie node has an array of pointers to its children.
66 * The array is kept in sorted order so that add_any_filter()
67 * can do a binary search
69 struct filter_trie_node {
70 ap_filter_rec_t *frec;
71 filter_trie_child_ptr *children;
76 #define TRIE_INITIAL_SIZE 4
78 /* Link a trie node to its parent
80 static void trie_node_link(apr_pool_t *p, filter_trie_node *parent,
81 filter_trie_node *child, int c)
85 if (parent->nchildren == parent->size) {
86 filter_trie_child_ptr *new;
88 new = (filter_trie_child_ptr *)apr_palloc(p, parent->size *
89 sizeof(filter_trie_child_ptr));
90 memcpy(new, parent->children, parent->nchildren *
91 sizeof(filter_trie_child_ptr));
92 parent->children = new;
95 for (i = 0; i < parent->nchildren; i++) {
96 if (c == parent->children[i].c) {
99 else if (c < parent->children[i].c) {
103 for (j = parent->nchildren; j > i; j--) {
104 parent->children[j].c = parent->children[j - 1].c;
105 parent->children[j].child = parent->children[j - 1].child;
107 parent->children[i].c = c;
108 parent->children[i].child = child;
113 /* Allocate a new node for a trie.
114 * If parent is non-NULL, link the new node under the parent node with
115 * key 'c' (or, if an existing child node matches, return that one)
117 static filter_trie_node *trie_node_alloc(apr_pool_t *p,
118 filter_trie_node *parent, char c)
120 filter_trie_node *new_node;
123 for (i = 0; i < parent->nchildren; i++) {
124 if (c == parent->children[i].c) {
125 return parent->children[i].child;
127 else if (c < parent->children[i].c) {
132 (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node));
133 trie_node_link(p, parent, new_node, c);
135 else { /* No parent node */
136 new_node = (filter_trie_node *)apr_palloc(p,
137 sizeof(filter_trie_node));
140 new_node->frec = NULL;
141 new_node->nchildren = 0;
142 new_node->size = TRIE_INITIAL_SIZE;
143 new_node->children = (filter_trie_child_ptr *)apr_palloc(p,
144 new_node->size * sizeof(filter_trie_child_ptr));
148 static filter_trie_node *registered_output_filters = NULL;
149 static filter_trie_node *registered_input_filters = NULL;
152 static apr_status_t filter_cleanup(void *ctx)
154 registered_output_filters = NULL;
155 registered_input_filters = NULL;
159 static ap_filter_rec_t *get_filter_handle(const char *name,
160 const filter_trie_node *filter_set)
164 const filter_trie_node *node;
167 for (n = name; *n; n++) {
170 end = node->nchildren - 1;
171 while (end >= start) {
172 int middle = (end + start) / 2;
173 char ch = node->children[middle].c;
175 node = node->children[middle].child;
191 if (node && node->frec) {
198 AP_DECLARE(ap_filter_rec_t *)ap_get_output_filter_handle(const char *name)
200 return get_filter_handle(name, registered_output_filters);
203 AP_DECLARE(ap_filter_rec_t *)ap_get_input_filter_handle(const char *name)
205 return get_filter_handle(name, registered_input_filters);
208 static ap_filter_rec_t *register_filter(const char *name,
209 ap_filter_func filter_func,
210 ap_init_filter_func filter_init,
211 ap_filter_type ftype,
212 ap_filter_direction_e direction,
213 filter_trie_node **reg_filter_set)
215 ap_filter_rec_t *frec;
216 char *normalized_name;
218 filter_trie_node *node;
220 if (!*reg_filter_set) {
221 *reg_filter_set = trie_node_alloc(FILTER_POOL, NULL, 0);
224 normalized_name = apr_pstrdup(FILTER_POOL, name);
225 ap_str_tolower(normalized_name);
227 node = *reg_filter_set;
228 for (n = normalized_name; *n; n++) {
229 filter_trie_node *child = trie_node_alloc(FILTER_POOL, node, *n);
230 if (apr_isalpha(*n)) {
231 trie_node_link(FILTER_POOL, node, child, apr_toupper(*n));
239 frec = apr_pcalloc(FILTER_POOL, sizeof(*frec));
241 frec->name = normalized_name;
243 frec->filter_func = filter_func;
244 frec->filter_init_func = filter_init;
246 frec->direction = direction;
248 apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup,
249 apr_pool_cleanup_null);
253 AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
254 ap_in_filter_func filter_func,
255 ap_init_filter_func filter_init,
256 ap_filter_type ftype)
259 f.in_func = filter_func;
260 return register_filter(name, f, filter_init, ftype, AP_FILTER_INPUT,
261 ®istered_input_filters);
264 AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
265 ap_out_filter_func filter_func,
266 ap_init_filter_func filter_init,
267 ap_filter_type ftype)
269 return ap_register_output_filter_protocol(name, filter_func,
270 filter_init, ftype, 0);
273 AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter_protocol(
275 ap_out_filter_func filter_func,
276 ap_init_filter_func filter_init,
277 ap_filter_type ftype,
278 unsigned int proto_flags)
280 ap_filter_rec_t* ret ;
282 f.out_func = filter_func;
283 ret = register_filter(name, f, filter_init, ftype, AP_FILTER_OUTPUT,
284 ®istered_output_filters);
285 ret->proto_flags = proto_flags ;
289 static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,
290 request_rec *r, conn_rec *c,
291 ap_filter_t **r_filters,
292 ap_filter_t **p_filters,
293 ap_filter_t **c_filters)
295 apr_pool_t *p = frec->ftype < AP_FTYPE_CONNECTION && r ? r->pool : c->pool;
296 ap_filter_t *f = apr_palloc(p, sizeof(*f));
299 if (frec->ftype < AP_FTYPE_PROTOCOL) {
304 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(00080)
305 "a content filter was added without a request: %s", frec->name);
309 else if (frec->ftype < AP_FTYPE_CONNECTION) {
314 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(00081)
315 "a protocol filter was added without a request: %s", frec->name);
325 /* f->r must always be NULL for connection filters */
326 f->r = frec->ftype < AP_FTYPE_CONNECTION ? r : NULL;
330 f->deferred_pool = NULL;
332 if (INSERT_BEFORE(f, *outf)) {
336 ap_filter_t *first = NULL;
339 /* If we are adding our first non-connection filter,
340 * Then don't try to find the right location, it is
341 * automatically first.
343 if (*r_filters != *c_filters) {
345 while (first && (first->next != (*outf))) {
350 if (first && first != (*outf)) {
357 ap_filter_t *fscan = *outf;
358 while (!INSERT_BEFORE(f, fscan->next))
361 f->next = fscan->next;
365 if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
366 *r_filters = *p_filters;
371 static ap_filter_t *add_any_filter(const char *name, void *ctx,
372 request_rec *r, conn_rec *c,
373 const filter_trie_node *reg_filter_set,
374 ap_filter_t **r_filters,
375 ap_filter_t **p_filters,
376 ap_filter_t **c_filters)
378 if (reg_filter_set) {
380 const filter_trie_node *node;
382 node = reg_filter_set;
383 for (n = name; *n; n++) {
386 end = node->nchildren - 1;
387 while (end >= start) {
388 int middle = (end + start) / 2;
389 char ch = node->children[middle].c;
391 node = node->children[middle].child;
407 if (node && node->frec) {
408 return add_any_filter_handle(node->frec, ctx, r, c, r_filters,
409 p_filters, c_filters);
413 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, r ? r->connection : c, APLOGNO(00082)
414 "an unknown filter was not added: %s", name);
418 AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
419 request_rec *r, conn_rec *c)
421 return add_any_filter(name, ctx, r, c, registered_input_filters,
422 r ? &r->input_filters : NULL,
423 r ? &r->proto_input_filters : NULL, &c->input_filters);
426 AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f,
431 return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL,
432 r ? &r->proto_input_filters : NULL,
436 AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
437 request_rec *r, conn_rec *c)
439 return add_any_filter(name, ctx, r, c, registered_output_filters,
440 r ? &r->output_filters : NULL,
441 r ? &r->proto_output_filters : NULL, &c->output_filters);
444 AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f,
449 return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL,
450 r ? &r->proto_output_filters : NULL,
454 static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt,
455 ap_filter_t **c_filt)
457 ap_filter_t **curr = r_filt ? r_filt : c_filt;
458 ap_filter_t *fscan = *curr;
460 if (p_filt && *p_filt == f)
461 *p_filt = (*p_filt)->next;
464 *curr = (*curr)->next;
468 while (fscan->next != f) {
469 if (!(fscan = fscan->next)) {
474 fscan->next = f->next;
477 AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
479 remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
480 f->r ? &f->r->proto_input_filters : NULL,
481 &f->c->input_filters);
484 AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
487 if ((f->bb) && !APR_BRIGADE_EMPTY(f->bb)) {
488 apr_brigade_cleanup(f->bb);
491 if (f->deferred_pool) {
492 apr_pool_destroy(f->deferred_pool);
493 f->deferred_pool = NULL;
496 remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
497 f->r ? &f->r->proto_output_filters : NULL,
498 &f->c->output_filters);
501 AP_DECLARE(apr_status_t) ap_remove_input_filter_byhandle(ap_filter_t *next,
504 ap_filter_t *found = NULL;
505 ap_filter_rec_t *filter;
510 filter = ap_get_input_filter_handle(handle);
516 if (next->frec == filter) {
523 ap_remove_input_filter(found);
529 AP_DECLARE(apr_status_t) ap_remove_output_filter_byhandle(ap_filter_t *next,
532 ap_filter_t *found = NULL;
533 ap_filter_rec_t *filter;
538 filter = ap_get_output_filter_handle(handle);
544 if (next->frec == filter) {
551 ap_remove_output_filter(found);
559 * Read data from the next filter in the filter stack. Data should be
560 * modified in the bucket brigade that is passed in. The core allocates the
561 * bucket brigade, modules that wish to replace large chunks of data or to
562 * save data off to the side should probably create their own temporary
563 * brigade especially for that use.
565 AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
566 apr_bucket_brigade *bb,
567 ap_input_mode_t mode,
568 apr_read_type_e block,
572 return next->frec->filter_func.in_func(next, bb, mode, block,
575 return AP_NOBODY_READ;
578 /* Pass the buckets to the next filter in the filter stack. If the
579 * current filter is a handler, we should get NULL passed in instead of
580 * the current filter. At that point, we can just call the first filter in
581 * the stack, or r->output_filters.
583 AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next,
584 apr_bucket_brigade *bb)
589 if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
590 /* This is only safe because HTTP_HEADER filter is always in
591 * the filter stack. This ensures that there is ALWAYS a
592 * request-based filter that we can attach this to. If the
593 * HTTP_FILTER is removed, and another filter is not put in its
594 * place, then handlers like mod_cgi, which attach their own
595 * EOS bucket to the brigade will be broken, because we will
596 * get two EOS buckets on the same request.
598 next->r->eos_sent = 1;
600 /* remember the eos for internal redirects, too */
602 request_rec *prev = next->r->prev;
610 return next->frec->filter_func.out_func(next, bb);
612 return AP_NOBODY_WROTE;
615 /* Pass the buckets to the next filter in the filter stack
616 * checking return status for filter errors.
617 * returns: OK if ap_pass_brigade returns APR_SUCCESS
618 * AP_FILTER_ERROR if filter error exists
619 * HTTP_INTERNAL_SERVER_ERROR for all other cases
620 * logged with optional errmsg
622 AP_DECLARE(apr_status_t) ap_pass_brigade_fchk(request_rec *r,
623 apr_bucket_brigade *bb,
629 rv = ap_pass_brigade(r->output_filters, bb);
630 if (rv != APR_SUCCESS) {
631 if (rv != AP_FILTER_ERROR) {
633 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(00083)
634 "ap_pass_brigade returned %d", rv);
639 res = apr_pvsprintf(r->pool, fmt, ap);
641 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(03158)
644 return HTTP_INTERNAL_SERVER_ERROR;
646 return AP_FILTER_ERROR;
651 AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
652 apr_bucket_brigade **saveto,
653 apr_bucket_brigade **b, apr_pool_t *p)
656 apr_status_t rv, srv = APR_SUCCESS;
658 /* If have never stored any data in the filter, then we had better
659 * create an empty bucket brigade so that we can concat. Register
660 * a cleanup to zero out the pointer if the pool is cleared.
663 *saveto = apr_brigade_create(p, f->c->bucket_alloc);
666 for (e = APR_BRIGADE_FIRST(*b);
667 e != APR_BRIGADE_SENTINEL(*b);
668 e = APR_BUCKET_NEXT(e))
670 rv = apr_bucket_setaside(e, p);
672 /* If the bucket type does not implement setaside, then
673 * (hopefully) morph it into a bucket type which does, and set
675 if (rv == APR_ENOTIMPL) {
679 rv = apr_bucket_read(e, &s, &n, APR_BLOCK_READ);
680 if (rv == APR_SUCCESS) {
681 rv = apr_bucket_setaside(e, p);
685 if (rv != APR_SUCCESS) {
687 /* Return an error but still save the brigade if
688 * ->setaside() is really not implemented. */
689 if (rv != APR_ENOTIMPL) {
694 APR_BRIGADE_CONCAT(*saveto, *b);
698 static apr_status_t filters_cleanup(void *data)
700 ap_filter_t **key = data;
702 apr_hash_set((*key)->c->filters, key, sizeof(ap_filter_t **), NULL);
707 AP_DECLARE(int) ap_filter_prepare_brigade(ap_filter_t *f, apr_pool_t **p)
714 pool = f->r ? f->r->pool : f->c->pool;
716 key = apr_pmemdup(pool, &f, sizeof f);
717 apr_hash_set(f->c->filters, key, sizeof key, f);
719 f->bb = apr_brigade_create(pool, f->c->bucket_alloc);
721 apr_pool_pre_cleanup_register(pool, key, filters_cleanup);
733 AP_DECLARE(apr_status_t) ap_filter_setaside_brigade(ap_filter_t *f,
734 apr_bucket_brigade *bb)
736 int loglevel = ap_get_conn_module_loglevel(f->c, APLOG_MODULE_INDEX);
738 if (loglevel >= APLOG_TRACE6) {
740 APLOG_MARK, APLOG_TRACE6, 0, f->c,
741 "setaside %s brigade to %s brigade in '%s' output filter",
742 (APR_BRIGADE_EMPTY(bb) ? "empty" : "full"),
743 (!f->bb || APR_BRIGADE_EMPTY(f->bb) ? "empty" : "full"), f->frec->name);
746 if (!APR_BRIGADE_EMPTY(bb)) {
747 apr_pool_t *pool = NULL;
749 * Set aside the brigade bb within f->bb.
751 ap_filter_prepare_brigade(f, &pool);
753 /* decide what pool we setaside to, request pool or deferred pool? */
756 for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); e =
757 APR_BUCKET_NEXT(e)) {
758 if (APR_BUCKET_IS_TRANSIENT(e)) {
759 int rv = apr_bucket_setaside(e, f->r->pool);
760 if (rv != APR_SUCCESS) {
766 APR_BRIGADE_CONCAT(f->bb, bb);
769 if (!f->deferred_pool) {
770 apr_pool_create(&f->deferred_pool, f->c->pool);
771 apr_pool_tag(f->deferred_pool, "deferred_pool");
773 pool = f->deferred_pool;
774 return ap_save_brigade(f, &f->bb, &bb, pool);
778 else if (f->deferred_pool) {
780 * There are no more requests in the pipeline. We can just clear the
783 apr_brigade_cleanup(f->bb);
784 apr_pool_clear(f->deferred_pool);
789 AP_DECLARE(apr_status_t) ap_filter_reinstate_brigade(ap_filter_t *f,
790 apr_bucket_brigade *bb,
791 apr_bucket **flush_upto)
793 apr_bucket *bucket, *next;
794 apr_size_t bytes_in_brigade, non_file_bytes_in_brigade;
795 int eor_buckets_in_brigade, morphing_bucket_in_brigade;
796 int loglevel = ap_get_conn_module_loglevel(f->c, APLOG_MODULE_INDEX);
798 if (loglevel >= APLOG_TRACE6) {
800 APLOG_MARK, APLOG_TRACE6, 0, f->c,
801 "reinstate %s brigade to %s brigade in '%s' output filter",
802 (!f->bb || APR_BRIGADE_EMPTY(f->bb) ? "empty" : "full"),
803 (APR_BRIGADE_EMPTY(bb) ? "empty" : "full"), f->frec->name);
806 if (f->bb && !APR_BRIGADE_EMPTY(f->bb)) {
807 APR_BRIGADE_PREPEND(bb, f->bb);
811 * Determine if and up to which bucket we need to do a blocking write:
813 * a) The brigade contains a flush bucket: Do a blocking write
814 * of everything up that point.
816 * b) The request is in CONN_STATE_HANDLER state, and the brigade
817 * contains at least THRESHOLD_MAX_BUFFER bytes in non-file
818 * buckets: Do blocking writes until the amount of data in the
819 * buffer is less than THRESHOLD_MAX_BUFFER. (The point of this
820 * rule is to provide flow control, in case a handler is
821 * streaming out lots of data faster than the data can be
822 * sent to the client.)
824 * c) The request is in CONN_STATE_HANDLER state, and the brigade
825 * contains at least MAX_REQUESTS_IN_PIPELINE EOR buckets:
826 * Do blocking writes until less than MAX_REQUESTS_IN_PIPELINE EOR
827 * buckets are left. (The point of this rule is to prevent too many
828 * FDs being kept open by pipelined requests, possibly allowing a
831 * d) The request is being served by a connection filter and the
832 * brigade contains a morphing bucket: If there was no other
833 * reason to do a blocking write yet, try reading the bucket. If its
834 * contents fit into memory before THRESHOLD_MAX_BUFFER is reached,
835 * everything is fine. Otherwise we need to do a blocking write the
836 * up to and including the morphing bucket, because ap_save_brigade()
837 * would read the whole bucket into memory later on.
842 bytes_in_brigade = 0;
843 non_file_bytes_in_brigade = 0;
844 eor_buckets_in_brigade = 0;
845 morphing_bucket_in_brigade = 0;
847 for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb);
849 next = APR_BUCKET_NEXT(bucket);
851 if (!APR_BUCKET_IS_METADATA(bucket)) {
852 if (bucket->length == (apr_size_t)-1) {
854 * A setaside of morphing buckets would read everything into
855 * memory. Instead, we will flush everything up to and
856 * including this bucket.
858 morphing_bucket_in_brigade = 1;
861 bytes_in_brigade += bucket->length;
862 if (!APR_BUCKET_IS_FILE(bucket))
863 non_file_bytes_in_brigade += bucket->length;
866 else if (AP_BUCKET_IS_EOR(bucket)) {
867 eor_buckets_in_brigade++;
870 if (APR_BUCKET_IS_FLUSH(bucket)
871 || non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER
872 || (!f->r && morphing_bucket_in_brigade)
873 || eor_buckets_in_brigade > MAX_REQUESTS_IN_PIPELINE) {
874 /* this segment of the brigade MUST be sent before returning. */
876 if (loglevel >= APLOG_TRACE6) {
877 char *reason = APR_BUCKET_IS_FLUSH(bucket) ?
879 (non_file_bytes_in_brigade >= THRESHOLD_MAX_BUFFER) ?
880 "THRESHOLD_MAX_BUFFER" :
881 (!f->r && morphing_bucket_in_brigade) ? "morphing bucket" :
882 "MAX_REQUESTS_IN_PIPELINE";
883 ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, f->c,
884 "will flush because of %s", reason);
885 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, f->c,
886 "seen in brigade%s: bytes: %" APR_SIZE_T_FMT
887 ", non-file bytes: %" APR_SIZE_T_FMT ", eor "
888 "buckets: %d, morphing buckets: %d",
889 *flush_upto == NULL ? " so far"
890 : " since last flush point",
892 non_file_bytes_in_brigade,
893 eor_buckets_in_brigade,
894 morphing_bucket_in_brigade);
897 * Defer the actual blocking write to avoid doing many writes.
901 bytes_in_brigade = 0;
902 non_file_bytes_in_brigade = 0;
903 eor_buckets_in_brigade = 0;
904 morphing_bucket_in_brigade = 0;
908 if (loglevel >= APLOG_TRACE8) {
909 ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, f->c,
910 "brigade contains: bytes: %" APR_SIZE_T_FMT
911 ", non-file bytes: %" APR_SIZE_T_FMT
912 ", eor buckets: %d, morphing buckets: %d",
913 bytes_in_brigade, non_file_bytes_in_brigade,
914 eor_buckets_in_brigade, morphing_bucket_in_brigade);
920 AP_DECLARE(int) ap_filter_should_yield(ap_filter_t *f)
923 * Handle the AsyncFilter directive. We limit the filters that are
924 * eligible for asynchronous handling here.
926 if (f->frec->ftype < f->c->async_filter) {
931 * This function decides whether a filter should yield due to buffered
932 * data in a downstream filter. If a downstream filter buffers we
933 * must back off so we don't overwhelm the server. If this function
934 * returns true, the filter should call ap_filter_setaside_brigade()
935 * to save unprocessed buckets, and then reinstate those buckets on
936 * the next call with ap_filter_reinstate_brigade() and continue
939 * If this function is forced to return zero, we return back to
940 * synchronous filter behaviour.
942 * Subrequests present us with a problem - we don't know how much data
943 * they will produce and therefore how much buffering we'll need, and
944 * if a subrequest had to trigger buffering, but next subrequest wouldn't
945 * know when the previous one had finished sending data and buckets
946 * could be sent out of order.
948 * In the case of subrequests, deny the ability to yield. When the data
949 * reaches the filters from the main request, they will be setaside
950 * there in the right order and the request will be given the
951 * opportunity to yield.
953 if (f->r && f->r->main) {
958 * This is either a main request or internal redirect, or it is a
959 * connection filter. Yield if there is any buffered data downstream
963 if (f->bb && !APR_BRIGADE_EMPTY(f->bb)) {
971 AP_DECLARE(int) ap_filter_output_pending(conn_rec *c)
973 apr_hash_index_t *rindex;
974 int data_in_output_filters = DECLINED;
976 rindex = apr_hash_first(NULL, c->filters);
978 ap_filter_t *f = apr_hash_this_val(rindex);
980 if (f->frec->direction == AP_FILTER_OUTPUT && f->bb
981 && !APR_BRIGADE_EMPTY(f->bb)) {
985 rv = ap_pass_brigade(f, c->empty);
986 apr_brigade_cleanup(c->empty);
987 if (APR_SUCCESS != rv) {
989 APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(00470)
990 "write failure in '%s' output filter", f->frec->name);
994 if (ap_filter_should_yield(f)) {
995 data_in_output_filters = OK;
999 rindex = apr_hash_next(rindex);
1002 return data_in_output_filters;
1005 AP_DECLARE(int) ap_filter_input_pending(conn_rec *c)
1007 apr_hash_index_t *rindex;
1009 rindex = apr_hash_first(NULL, c->filters);
1011 ap_filter_t *f = apr_hash_this_val(rindex);
1013 if (f->frec->direction == AP_FILTER_INPUT && f->bb) {
1014 apr_bucket *e = APR_BRIGADE_FIRST(f->bb);
1016 /* if there is at least one non-morphing bucket
1017 * in place, then we have data pending
1019 if (e != APR_BRIGADE_SENTINEL(f->bb)
1020 && e->length != (apr_size_t)(-1)) {
1026 rindex = apr_hash_next(rindex);
1032 AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
1035 ap_filter_t *f = ctx;
1038 rv = ap_pass_brigade(f, bb);
1040 /* Before invocation of the flush callback, apr_brigade_write et
1041 * al may place transient buckets in the brigade, which will fall
1042 * out of scope after returning. Empty the brigade here, to avoid
1043 * issues with leaving such buckets in the brigade if some filter
1044 * fails and leaves a non-empty brigade. */
1045 apr_brigade_cleanup(bb);
1050 AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
1054 b = apr_bucket_flush_create(f->c->bucket_alloc);
1055 APR_BRIGADE_INSERT_TAIL(bb, b);
1056 return ap_pass_brigade(f, bb);
1059 AP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
1060 apr_bucket_brigade *bb, ...)
1066 rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
1071 AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
1072 apr_bucket_brigade *bb,
1079 va_start(args, fmt);
1080 rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
1084 AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
1086 f->frec->proto_flags = flags ;