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) */