You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rb...@locus.apache.org on 2000/07/13 02:07:44 UTC
cvs commit: apache-2.0/src/lib/apr/buckets ryan.patch util_filter.c util_filter.h
rbb 00/07/12 17:07:44
Added: src/lib/apr/buckets ryan.patch util_filter.c util_filter.h
Log:
Add my most recent patch and the other files necessary to make it work.
This patch brings Apache to a point, where most pages are sent without
using BUFF except for the headers. All legacy modules will work with this
patch, although they will all require a memcopy just to be on the safe
side.
Revision Changes Path
1.1 apache-2.0/src/lib/apr/buckets/ryan.patch
Index: ryan.patch
===================================================================
? build.log
? build.err
? .inslog2
? include/util_filter.h
? lib/apr/build.log
? lib/apr/build.err
? lib/apr/shmem/config.cache
? main/util_filter.c
Index: configure.in
===================================================================
RCS file: /home/cvs/apache-2.0/src/configure.in,v
retrieving revision 1.72
diff -u -d -b -w -u -r1.72 configure.in
--- configure.in 2000/07/01 14:08:21 1.72
+++ configure.in 2000/07/12 23:26:38
@@ -78,7 +78,7 @@
netdb.h \
pwd.h \
grp.h \
-strings.h
+strings.h \
)
AC_HEADER_SYS_WAIT
Index: ap/Makefile.in
===================================================================
RCS file: /home/cvs/apache-2.0/src/ap/Makefile.in,v
retrieving revision 1.4
diff -u -d -b -w -u -r1.4 Makefile.in
--- ap/Makefile.in 2000/06/12 20:41:13 1.4
+++ ap/Makefile.in 2000/07/12 23:26:38
@@ -1,5 +1,5 @@
LTLIBRARY_NAME = libap.la
-LTLIBRARY_SOURCES = ap_cache.c ap_base64.c ap_sha1.c ap_buf.c ap_hooks.c
+LTLIBRARY_SOURCES = ap_cache.c ap_base64.c ap_sha1.c ap_hooks.c
include $(top_srcdir)/build/ltlib.mk
Index: include/ap_iol.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/include/ap_iol.h,v
retrieving revision 1.19
diff -u -d -b -w -u -r1.19 ap_iol.h
--- include/ap_iol.h 2000/05/29 04:22:02 1.19
+++ include/ap_iol.h 2000/07/12 23:26:39
@@ -58,6 +58,7 @@
#define AP_IOL_H
#include "apr_general.h" /* For ap_s?size_t */
+#include "apr_network_io.h" /* For ap_hdtr_t */
#include "apr_errno.h" /* For ap_status_t and the APR_errnos */
typedef struct ap_iol ap_iol;
Index: include/buff.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/include/buff.h,v
retrieving revision 1.30
diff -u -d -b -w -u -r1.30 buff.h
--- include/buff.h 2000/06/29 14:34:24 1.30
+++ include/buff.h 2000/07/12 23:26:39
@@ -63,7 +63,7 @@
extern "C" {
#endif
-#ifdef HAVE_STDARG_H
+#ifdef APR_HAVE_STDARG_H
#include <stdarg.h>
#endif
#include "ap.h"
Index: include/http_protocol.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/include/http_protocol.h,v
retrieving revision 1.19
diff -u -d -b -w -u -r1.19 http_protocol.h
--- include/http_protocol.h 2000/07/11 03:48:17 1.19
+++ include/http_protocol.h 2000/07/12 23:26:39
@@ -89,8 +89,15 @@
API_EXPORT(void) ap_basic_http_header(request_rec *r);
/* Send the Status-Line and header fields for HTTP response */
+API_EXPORT(void) ap_send_http_header_real(request_rec *l);
-API_EXPORT(void) ap_send_http_header(request_rec *l);
+/* this is the old function that used to send headers to the network. We
+ * don't want handlers using it anymore, becuase the filter that actually
+ * writes to the network has to send the headers. I am defining it to be
+ * NULL, because everybody seems to want to not break existing modules.
+ * The new function ap_send_http_header_real() actually sends the data.
+ */
+#define ap_send_http_header(l) /* No-op*/
/* Send the response to special method requests */
Index: include/httpd.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/include/httpd.h,v
retrieving revision 1.64
diff -u -d -b -w -u -r1.64 httpd.h
--- include/httpd.h 2000/06/30 21:18:13 1.64
+++ include/httpd.h 2000/07/12 23:26:39
@@ -596,6 +596,11 @@
* pointer back to the main request.
*/
+ ap_array_header_t *filters; /* The array of filters to call */
+ int headers_sent; /* Have we sent the headers for this request
+ * yet.
+ */
+
/* Info about the request itself... we begin with stuff that only
* protocol.c should ever touch...
*/
Index: main/Makefile.in
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/Makefile.in,v
retrieving revision 1.16
diff -u -d -b -w -u -r1.16 Makefile.in
--- main/Makefile.in 2000/07/01 14:14:15 1.16
+++ main/Makefile.in 2000/07/12 23:26:48
@@ -8,7 +8,7 @@
http_protocol.c http_request.c http_vhost.c util.c util_date.c \
util_script.c util_uri.c util_md5.c util_cfgtree.c util_ebcdic.c \
rfc1413.c http_connection.c iol_file.c iol_socket.c listen.c \
- mpm_common.c util_charset.c util_debug.c util_xml.c
+ mpm_common.c util_charset.c util_debug.c util_xml.c util_filter.c
include $(top_srcdir)/build/ltlib.mk
Index: main/http_core.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_core.c,v
retrieving revision 1.88
diff -u -d -b -w -u -r1.88 http_core.c
--- main/http_core.c 2000/07/11 03:48:18 1.88
+++ main/http_core.c 2000/07/12 23:26:48
@@ -71,6 +71,8 @@
#include "util_md5.h"
#include "apr_fnmatch.h"
#include "http_connection.h"
+#include "apr_buf.h"
+#include "util_filter.h"
#include "util_ebcdic.h"
#include "mpm.h"
#ifdef HAVE_NETDB_H
@@ -86,6 +88,10 @@
#include <strings.h>
#endif
+/* Make sure we don't write less than 4096 bytes at any one time.
+ */
+#define MIN_SIZE_TO_WRITE 4096
+
/* Allow Apache to use ap_mmap */
#ifdef USE_MMAP_FILES
#include "apr_mmap.h"
@@ -2872,6 +2878,51 @@
return OK;
}
+/* Default filter. This filter should almost always be used. It's only job
+ * is to send the headers if they haven't already been sent, and then send
+ * the actual data. To send the data, we create an iovec out of the bucket
+ * brigade and then call the iol's writev function. On platforms that don't
+ * have writev, we have the problem of creating a lot of potentially small
+ * packets that we are sending to the network.
+ *
+ * This can be solved later by making the buckets buffer everything into a
+ * single memory block that can be written using write (on those systems
+ * without writev only !)
+ */
+static int core_filter(request_rec *r, ap_filter_t *f, ap_bucket_brigade *b)
+{
+ ap_ssize_t bytes_sent;
+ ap_bucket_list *dptr;
+ int len = 0;
+
+ if (!r->headers_sent) {
+ ap_send_http_header_real(r);
+ r->headers_sent = 1;
+ }
+
+ /* At this point we need to discover if there was any data saved from
+ * the last call to core_filter.
+ */
+ b = ap_get_saved_data(r, f, &b);
+
+ /* It is very obvious that we need to make sure it makes sense to send data
+ * out at this point.
+ */
+ dptr = b->head;
+ while (dptr) {
+ len += ap_get_bucket_len(dptr->bucket);
+ dptr = dptr->next;
+ }
+ if (len < MIN_SIZE_TO_WRITE && b->tail->bucket->color != AP_BUCKET_eos) {
+ ap_save_data_to_filter(r, f, b);
+ return 0;
+ }
+ else {
+ ap_bucket_brigade_to_iol(&bytes_sent, b, r->connection->client->iol);
+ return bytes_sent;
+ }
+}
+
static const handler_rec core_handlers[] = {
{ "*/*", default_handler },
{ "default-handler", default_handler },
@@ -2894,6 +2945,11 @@
static unsigned short core_port(const request_rec *r)
{ return DEFAULT_HTTP_PORT; }
+static void core_register_filter(request_rec *r)
+{
+ ap_hook_filter(core_filter, r, NULL, NULL, AP_HOOK_TRANSPORT_LAST);
+}
+
static void register_hooks(void)
{
ap_hook_post_config(core_post_config,NULL,NULL,AP_HOOK_REALLY_FIRST);
@@ -2906,6 +2962,8 @@
/* FIXME: I suspect we can eliminate the need for these - Ben */
ap_hook_type_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST);
ap_hook_access_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST);
+
+ ap_hook_insert_filter(core_register_filter, NULL, NULL, AP_HOOK_MIDDLE);
}
API_VAR_EXPORT module core_module = {
Index: main/http_protocol.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
retrieving revision 1.95
diff -u -d -b -w -u -r1.95 http_protocol.c
--- main/http_protocol.c 2000/07/11 03:48:18 1.95
+++ main/http_protocol.c 2000/07/12 23:26:49
@@ -64,6 +64,8 @@
*/
#define CORE_PRIVATE
+#include "apr_buf.h"
+#include "util_filter.h"
#include "ap_config.h"
#include "httpd.h"
#include "http_config.h"
@@ -1720,7 +1722,7 @@
}
}
-API_EXPORT(void) ap_send_http_header(request_rec *r)
+API_EXPORT(void) ap_send_http_header_real(request_rec *r)
{
int i;
const long int zero = 0L;
@@ -2443,15 +2445,23 @@
size_t length)
{
size_t total_bytes_sent = 0;
- int n;
- ap_ssize_t w;
- char *addr;
+ ap_bucket_brigade *bb = NULL;
+ ap_bucket *b = NULL;
+ ap_filter_t *f;
+
+ /* if you are using the older API's, then Apache will initiate the
+ * filtering for you.
+ */
+ f = ap_init_filter(r->pool);
if (length == 0)
return 0;
-
length += offset;
+/* We can remove all of the MMAP_SEGMENT_SIZE stuff from Apache, because
+ * it is an optimization to be used for sending data. Since we are using
+ * bucket-brigades we need to move this optimization down to the bucket
+ * brigade stuff, but that can wait for a day or two.
while (!r->connection->aborted && offset < length) {
if (length - offset > MMAP_SEGMENT_SIZE) {
n = MMAP_SEGMENT_SIZE;
@@ -2467,76 +2477,142 @@
total_bytes_sent += w;
offset += w;
}
+ */
- SET_BYTES_SENT(r);
+ /* This is far too complex for a final API, but it is an okay
+ * start. To finish this off, we will need a very clean API
+ * that does all of this for us.
+ */
+ bb = ap_bucket_brigade_create(r->pool);
+ bb->head = bb->tail = ap_bucket_list_create();
+ ap_bucket_list_init(bb->head);
+ b = ap_bucket_new(AP_BUCKET_mmap);
+ ap_mmap_bucket_insert((ap_bucket_mmap *)b->data, mm);
+ bb->head->bucket = b;
+ total_bytes_sent = ap_pass_brigade(r, f, bb);
+
return total_bytes_sent;
}
#endif /* USE_MMAP_FILES */
API_EXPORT(int) ap_rputc(int c, request_rec *r)
{
+ ap_bucket_brigade *bb = NULL;
+ ap_bucket *b = NULL;
+ ap_ssize_t written;
+ ap_filter_t *f;
+
if (r->connection->aborted)
return EOF;
- if (ap_bputc(c, r->connection->client) < 0) {
- check_first_conn_error(r, "rputc", 0);
- return EOF;
- }
- SET_BYTES_SENT(r);
+ /* if you are using the older API's, then Apache will initiate the
+ * filtering for you.
+ */
+ f = ap_init_filter(r->pool);
+
+ /* This is far too complex for a final API, but it is an okay
+ * start. To finish this off, we will need a very clean API
+ * that does all of this for us.
+ */
+ bb = ap_bucket_brigade_create(r->pool);
+ bb->head = bb->tail = ap_bucket_list_create();
+ ap_bucket_list_init(bb->head);
+ b = ap_bucket_new(AP_BUCKET_rwmem);
+ ap_rwmem_write(b->data, &c, 1, &written);
+ bb->head->bucket = b;
+ ap_pass_brigade(r, f, bb);
+
return c;
}
API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
{
- int rcode;
+ ap_bucket_brigade *bb = NULL;
+ ap_bucket *b = NULL;
+ ap_ssize_t written;
+ ap_filter_t *f;
if (r->connection->aborted)
return EOF;
- rcode = ap_bputs(str, r->connection->client);
- if (rcode < 0) {
- check_first_conn_error(r, "rputs", 0);
- return EOF;
- }
- SET_BYTES_SENT(r);
- return rcode;
+ /* if you are using the older API's, then Apache will initiate the
+ * filtering for you.
+ */
+ f = ap_init_filter(r->pool);
+
+ /* This is far too complex for a final API, but it is an okay
+ * start. To finish this off, we will need a very clean API
+ * that does all of this for us.
+ */
+ bb = ap_bucket_brigade_create(r->pool);
+ bb->head = bb->tail = ap_bucket_list_create();
+ ap_bucket_list_init(bb->head);
+ b = ap_bucket_new(AP_BUCKET_rwmem);
+ ap_rwmem_write(b->data, str, strlen(str), &written);
+ bb->head->bucket = b;
+ ap_pass_brigade(r, f, bb);
+
+ return written;
}
API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
{
- ap_ssize_t n;
- ap_status_t rv;
+ ap_bucket_brigade *bb = NULL;
+ ap_bucket *b = NULL;
+ ap_ssize_t written;
+ ap_filter_t *f;
if (r->connection->aborted)
return EOF;
- /* ### should loop to avoid partial writes */
- rv = ap_bwrite(r->connection->client, buf, nbyte, &n);
- if (rv != APR_SUCCESS) {
- check_first_conn_error(r, "rwrite", rv);
- return EOF;
- }
- SET_BYTES_SENT(r);
- return n;
+ /* if you are using the older API's, then Apache will initiate the
+ * filtering for you.
+ */
+ f = ap_init_filter(r->pool);
+
+ /* This is far too complex for a final API, but it is an okay
+ * start. To finish this off, we will need a very clean API
+ * that does all of this for us.
+ */
+ bb = ap_bucket_brigade_create(r->pool);
+ bb->head = bb->tail = ap_bucket_list_create();
+ ap_bucket_list_init(bb->head);
+ b = ap_bucket_new(AP_BUCKET_rwmem);
+ ap_rwmem_write(b->data, buf, nbyte, &written);
+ bb->head->bucket = b;
+ ap_pass_brigade(r, f, bb);
+ return written;
}
API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list va)
{
- int n;
+ ap_bucket_brigade *bb = NULL;
+ ap_ssize_t written;
+ ap_filter_t *f;
if (r->connection->aborted)
return EOF;
- n = ap_vbprintf(r->connection->client, fmt, va);
+ /* if you are using the older API's, then Apache will initiate the
+ * filtering for you.
+ */
+ f = ap_init_filter(r->pool);
- if (n < 0) {
- check_first_conn_error(r, "vrprintf", 0);
- return EOF;
- }
- SET_BYTES_SENT(r);
- return n;
+ /* This is far too complex for a final API, but it is an okay
+ * start. To finish this off, we will need a very clean API
+ * that does all of this for us.
+ */
+ bb = ap_bucket_brigade_create(r->pool);
+ bb->head = bb->tail = ap_bucket_list_create();
+ ap_bucket_list_init(bb->head);
+ written = ap_brigade_vprintf(bb, fmt, va);
+ ap_pass_brigade(r, f, bb);
+ return written;
}
+/* TODO: Make ap pa_bucket_vprintf that printfs directly into a
+ * bucket.
+ */
API_EXPORT_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt, ...)
{
va_list va;
@@ -2546,46 +2622,62 @@
return EOF;
va_start(va, fmt);
- n = ap_vbprintf(r->connection->client, fmt, va);
+ n = ap_vrprintf(r, fmt, va);
va_end(va);
- if (n < 0) {
- check_first_conn_error(r, "rprintf", 0);
- return EOF;
- }
- SET_BYTES_SENT(r);
return n;
}
API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r, ...)
{
+ ap_bucket_brigade *bb = NULL;
+ ap_ssize_t written;
+ ap_filter_t *f;
va_list va;
- int n;
if (r->connection->aborted)
return EOF;
+ /* if you are using the older API's, then Apache will initiate the
+ * filtering for you.
+ */
+ f = ap_init_filter(r->pool);
+
+ /* This is far too complex for a final API, but it is an okay
+ * start. To finish this off, we will need a very clean API
+ * that does all of this for us.
+ */
+ bb = ap_bucket_brigade_create(r->pool);
+ bb->head = bb->tail = ap_bucket_list_create();
+ ap_bucket_list_init(bb->head);
va_start(va, r);
- n = ap_vbputstrs(r->connection->client, va);
+ written = ap_brigade_vputstrs(bb, va);
va_end(va);
-
- if (n < 0) {
- check_first_conn_error(r, "rvputs", 0);
- return EOF;
- }
-
- SET_BYTES_SENT(r);
- return n;
+ ap_pass_brigade(r, f, bb);
+ return written;
}
API_EXPORT(int) ap_rflush(request_rec *r)
{
- ap_status_t rv;
+ ap_bucket_brigade *bb;
+ ap_bucket *b;
+ ap_filter_t *f;
- if ((rv = ap_bflush(r->connection->client)) != APR_SUCCESS) {
- check_first_conn_error(r, "rflush", rv);
- return EOF;
- }
+ /* if you are using the older API's, then Apache will initiate the
+ * filtering for you.
+ */
+ f = ap_init_filter(r->pool);
+
+ /* This is far too complex for a final API, but it is an okay
+ * start. To finish this off, we will need a very clean API
+ * that does all of this for us.
+ */
+ bb = ap_bucket_brigade_create(r->pool);
+ bb->head = bb->tail = ap_bucket_list_create();
+ ap_bucket_list_init(bb->head);
+ b = ap_bucket_new(AP_BUCKET_eos);
+ bb->head->bucket = b;
+ ap_pass_brigade(r, f, bb);
return 0;
}
Index: main/http_request.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_request.c,v
retrieving revision 1.35
diff -u -d -b -w -u -r1.35 http_request.c
--- main/http_request.c 2000/06/24 17:33:57 1.35
+++ main/http_request.c 2000/07/12 23:26:49
@@ -1263,6 +1263,12 @@
return;
}
+ /* We need to flush the data out at this point. We probably only want to
+ * do this on the main request, but this is fine for an initial patch.
+ * Once we look into this more, we won't flush sub-requests.
+ */
+ ap_rflush(r);
+
/* Take care of little things that need to happen when we're done */
ap_finalize_request_protocol(r);
}
Index: modules/mpm/config.m4
===================================================================
RCS file: /home/cvs/apache-2.0/src/modules/mpm/config.m4,v
retrieving revision 1.23
diff -u -d -b -w -u -r1.23 config.m4
--- modules/mpm/config.m4 2000/07/11 19:00:16 1.23
+++ modules/mpm/config.m4 2000/07/12 23:26:51
@@ -3,7 +3,6 @@
[ --with-mpm=MPM Choose the process model for Apache to use.
MPM={dexter,mpmt_beos,mpmt_pthread,prefork,spmt_os2}],[
APACHE_MPM=$withval
- mpm_explicit="yes"
],[
APACHE_MPM=mpmt_pthread
PLAT=`$ac_config_guess`
@@ -14,7 +13,6 @@
*os2_emx*)
APACHE_MPM=spmt_os2;;
esac
- mpm_explicit="no"
])
AC_MSG_RESULT($APACHE_MPM)
@@ -41,10 +39,11 @@
MPM_DIR=modules/mpm/$MPM_NAME
MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la
-if test "$mpm_explicit" = "no"; then
if test "$MPM_NAME" = "prefork" ; then
MPM_NAME="prefork"
MPM_FAKE_NAME=prefork.c
+ ln -s mpmt.c modules/mpm/mpmt/prefork.c
+
EXTRA_CFLAGS="$EXTRA_CFLAGS -DPREFORK"
ac_cv_enable_threads="no"
@@ -78,7 +77,6 @@
MPM_DIR=modules/mpm/$MPM_NAME
MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la
fi
-fi
APACHE_SUBST(MPM_NAME)
APACHE_SUBST(MPM_FAKE_NAME)
1.1 apache-2.0/src/lib/apr/buckets/util_filter.c
Index: util_filter.c
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* Portions of this software are based upon public domain software
* originally written at the National Center for Supercomputing Applications,
* University of Illinois, Urbana-Champaign.
*/
#include "httpd.h"
#include "util_filter.h"
API_EXPORT(ap_filter_t *) ap_init_filter(ap_pool_t *p)
{
ap_filter_t *f = ap_pcalloc(p, sizeof(f));
return f;
}
API_EXPORT(int) ap_pass_brigade(request_rec *r, ap_filter_t *next,
ap_bucket_brigade *buf)
{
int rv;
LINK_filter *hook;
if (next->current_filter > r->filters->nelts) {
return AP_ENOBODY_WROTE;
}
hook = (LINK_filter *)r->filters->elts;
rv = hook[next->current_filter++].pFunc(r, next, buf);
next->current_filter--;
return rv;
}
API_EXPORT(void) ap_save_data_to_filter(request_rec *r, ap_filter_t *next,
ap_bucket_brigade *data)
{
LINK_filter *hook;
hook = ((LINK_filter *)r->filters->elts);
if (hook->filter_data) {
ap_bucket_brigade_catenate(hook->filter_data, data);
}
else {
hook->filter_data = data;
}
}
API_EXPORT(ap_bucket_brigade *) ap_get_saved_data(request_rec *r,
ap_filter_t *next,
ap_bucket_brigade **data)
{
LINK_filter *hook;
hook = ((LINK_filter *)r->filters->elts);
if (hook->filter_data) {
ap_bucket_brigade_catenate(hook->filter_data, *data);
*data = hook->filter_data;
}
hook->filter_data = NULL;
return *data;
}
API_EXPORT(void) ap_hook_filter(HOOK_filter *pf, request_rec *r,
const char * const *aszPre,
const char * const *aszSucc, int nOrder)
{
LINK_filter *hook;
if(!r->filters) {
r->filters=ap_make_array(ap_global_hook_pool,1,sizeof(LINK_filter));
ap_hook_sort_register("filter",&r->filters);
}
hook = (LINK_filter *)r->filters->elts;
hook=ap_push_array(r->filters);
hook->pFunc=pf;
hook->aszPredecessors=aszPre;
hook->aszSuccessors=aszSucc;
hook->nOrder=nOrder;
hook->szName=ap_debug_module_name;
hook->filter_data = ap_bucket_brigade_create(r->pool);
if(ap_debug_module_hooks) {
ap_show_hook("filter",aszPre,aszSucc);
}
}
1.1 apache-2.0/src/lib/apr/buckets/util_filter.h
Index: util_filter.h
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#ifndef APACHE_FILTER_H
#define APACHE_FILTER_H
#include "ap_config.h"
/* For ap_array_header_t */
#include "apr_lib.h"
#include "httpd.h"
#include "apr_buf.h"
#include "ap_hooks.h" /* For the hooks ordering stuff */
typedef struct ap_filter_t {
int current_filter;
} ap_filter_t;
typedef int HOOK_filter(request_rec *r, ap_filter_t *next, ap_bucket_brigade *buckets);
typedef struct _LINK_filter {
HOOK_filter *pFunc;
const char *szName;
const char * const *aszPredecessors;
const char * const *aszSuccessors;
int nOrder;
ap_bucket_brigade *filter_data;
} LINK_filter;
#define AP_HOOK_FILTER 0 /* content-filter/munger/processor */
#define AP_HOOK_ENCODING 10 /* content-encoding */
#define AP_HOOK_PROCESSOR 20 /* digest/message processor */
#define AP_HOOK_TRANSPORT 30 /* transport-encoding */
/* This is usually the core filter. This ensures that there is always a
* filter that can/will write out to the network. If some other module
* wants to actually do the writing, they just insert themselves before
* this filter. This is just like the default handler in 1.3. If no other
* handler took care of the request, then the default took it. Same thing, if
* no other Transport filter writes this to the network, then the default
* (core) filter will be used.
*/
#define AP_HOOK_TRANSPORT_LAST 40
/* If we go past the end of the filter stack, we have a big problem. */
#define AP_ENOBODY_WROTE (-1)
API_EXPORT(ap_filter_t *) ap_init_filter(ap_pool_t *p);
API_EXPORT(void) ap_hook_filter(HOOK_filter *pf, request_rec *r,
const char * const *aszPre,
const char * const *aszSucc, int nOrder);
API_EXPORT(int) ap_pass_brigade(request_rec *r, ap_filter_t *next,
ap_bucket_brigade *bucket);
API_EXPORT(void) ap_save_data_to_filter(request_rec *r, ap_filter_t *next,
ap_bucket_brigade *data);
API_EXPORT(ap_bucket_brigade *) ap_get_saved_data(request_rec *r,
ap_filter_t *next,
ap_bucket_brigade **data);
#endif /* ndef(AP_FILTER_H) */