## _____ _ ____ ___ ## | ____| / \ | _ \_ _| ## | _| / _ \ | |_) | | ## | |__ / ___ \| __/| | ## |____/_/ \_\_| |___| Extended API for Apache ## ____________________________________________________________________________ ## ## Annotated patch file: eapi.patch ## Copyright (c) 1998-2007 Ralf S. Engelschall, All Rights Reserved. ## Created on: 08-Feb-2008 ## ## This file assembles changes to existing Apache source files ## between the original Apache and the patched variant. It can be ## automatically applied to a vanilla Apache source tree with the ## 'patch' tool to upgrade those files. Each patch snippet is ## annotated with a short description. ## ## This file contains all patches to the Apache source ## tree which add the Extended API (EAPI) support. ## +--------------------------------------------------------------------------- | Add the EAPI and EAPI_MM configuration entries which triggers the EAPI | patches and configured the shared memory support via the MM library. +--------------------------------------------------------------------------- Index: src/Configuration.tmpl --- src/Configuration.tmpl 11 May 2004 18:28:09 -0000 1.1.1.8 +++ src/Configuration.tmpl 11 May 2004 18:32:15 -0000 1.24 @@ -68,6 +105,24 @@ #TARGET= ################################################################ +# Extended API (EAPI) support: +# +# EAPI: +# The EAPI rule enables more module hooks, a generic low-level hook +# mechanism, a generic context mechanism and shared memory based pools. +# +# EAPI_MM: +# Set the EAPI_MM variable to either the directory of a MM Shared Memory +# Library source tree or the installation tree of MM. Alternatively you can +# also use the value 'SYSTEM' which then indicates that MM is installed +# under various system locations. When the MM library files cannot be found +# the EAPI still can be built, but without shared memory pool support, of +# course. + +Rule EAPI=no +#EAPI_MM=SYSTEM + +################################################################ # Dynamic Shared Object (DSO) support # # There is experimental support for compiling the Apache core and +--------------------------------------------------------------------------- | Patch in implementation of the EAPI rule. +--------------------------------------------------------------------------- Index: src/Configure --- src/Configure 8 Feb 2008 11:15:36 -0000 1.1.1.31 +++ src/Configure 8 Feb 2008 11:17:39 -0000 1.34 @@ -1868,6 +1868,72 @@ fi #################################################################### +## Extended API (EAPI) support: +## +if [ "x$RULE_EAPI" = "x" ]; then + RULE_EAPI=`./helpers/CutRule EAPI $file` +fi +if [ "x$RULE_EAPI" = "xyes" ]; then + echo " + enabling Extended API (EAPI)" + CFLAGS="$CFLAGS -DEAPI" + # some vendor compilers are too restrictive + # for our ap_hook and ap_ctx sources. + case "$OS:$CC" in + *IRIX-32*:*/cc|*IRIX-32*:cc ) + CFLAGS="$CFLAGS -woff 1048,1110,1164" + ;; + esac + # MM Shared Memory Library support for EAPI + if [ "x$EAPI_MM" = "x" ]; then + EAPI_MM=`egrep '^EAPI_MM=' $file | sed -n -e '$p' | awk -F= '{print $2}'` + fi + if [ "x$EAPI_MM" != "x" ]; then + case $EAPI_MM in + SYSTEM|/* ) ;; + * ) for p in . .. ../..; do + if [ -d "$p/$EAPI_MM" ]; then + EAPI_MM="`echo $p/$EAPI_MM | sed -e 's;/\./;/;g'`" + break + fi + done + ;; + esac + if [ "x$EAPI_MM" = "xSYSTEM" ]; then + echo " using MM library for EAPI: (system-wide)" + CFLAGS="$CFLAGS -DEAPI_MM" + __INCLUDES="`mm-config --cflags`" + if [ "x$__INCLUDES" != "x-I/usr/include" ]; then + INCLUDES="$INCLUDES $__INCLUDES" + fi + LDFLAGS="$LDFLAGS `mm-config --ldflags`" + LIBS="$LIBS `mm-config --libs`" + else + if [ -f "$EAPI_MM/.libs/libmm.a" -a -f "$EAPI_MM/mm.h" ]; then + echo " using MM library: $EAPI_MM (source-tree only)" + case $EAPI_MM in + /* ) ;; + * ) EAPI_MM="\$(SRCDIR)/$EAPI_MM" ;; + esac + CFLAGS="$CFLAGS -DEAPI_MM" + INCLUDES="$INCLUDES -I$EAPI_MM" + LDFLAGS="$LDFLAGS -L$EAPI_MM/.libs" + LIBS="$LIBS -lmm" + elif [ -f "$EAPI_MM/bin/mm-config" ]; then + echo " using MM library: $EAPI_MM (installed)" + CFLAGS="$CFLAGS -DEAPI_MM" + INCLUDES="$INCLUDES `$EAPI_MM/bin/mm-config --cflags`" + LDFLAGS="$LDFLAGS `$EAPI_MM/bin/mm-config --ldflags`" + LIBS="$LIBS `$EAPI_MM/bin/mm-config --libs`" + else + echo "Configure:Error: Cannot find MM library under $EAPI_MM" 1>&2 + exit 1 + fi + fi + fi +fi + + +#################################################################### ## Add in the Expat library if needed/wanted. ## +--------------------------------------------------------------------------- | Add the build support for the ap_hook.c and ap_ctx.c sources (Unix) +--------------------------------------------------------------------------- Index: src/ap/Makefile.tmpl --- src/ap/Makefile.tmpl 19 Jun 2002 07:20:22 -0000 1.1.1.8 +++ src/ap/Makefile.tmpl 19 Jun 2002 07:29:08 -0000 1.8 @@ -7,7 +7,7 @@ OBJS=ap_cpystrn.o ap_execve.o ap_fnmatch.o ap_getpass.o ap_md5c.o ap_signal.o \ ap_slack.o ap_snprintf.o ap_sha1.o ap_checkpass.o ap_base64.o ap_ebcdic.o \ - ap_strtol.o + ap_strtol.o ap_hook.o ap_ctx.o ap_mm.o .c.o: $(CC) -c $(INCLUDES) $(CFLAGS) $< +--------------------------------------------------------------------------- | Add the build support for the ap_hook.c and ap_ctx.c sources (Win32) +--------------------------------------------------------------------------- Index: src/ap/ap.mak --- src/ap/ap.mak 18 Oct 2005 06:26:22 -0000 1.1.1.11 +++ src/ap/ap.mak 18 Oct 2005 06:27:34 -0000 1.11 @@ -44,6 +44,9 @@ -@erase "$(INTDIR)\ap_cpystrn.obj" -@erase "$(INTDIR)\ap_fnmatch.obj" -@erase "$(INTDIR)\ap_md5c.obj" + -@erase "$(INTDIR)\ap_hook.obj" + -@erase "$(INTDIR)\ap_ctx.obj" + -@erase "$(INTDIR)\ap_mm.obj" -@erase "$(INTDIR)\ap_sha1.obj" -@erase "$(INTDIR)\ap_signal.obj" -@erase "$(INTDIR)\ap_slack.obj" @@ -99,6 +102,9 @@ "$(INTDIR)\ap_cpystrn.obj" \ "$(INTDIR)\ap_fnmatch.obj" \ "$(INTDIR)\ap_md5c.obj" \ + "$(INTDIR)\ap_hook.obj" \ + "$(INTDIR)\ap_ctx.obj" \ + "$(INTDIR)\ap_mm.obj" \ "$(INTDIR)\ap_sha1.obj" \ "$(INTDIR)\ap_signal.obj" \ "$(INTDIR)\ap_slack.obj" \ @@ -128,6 +134,9 @@ -@erase "$(INTDIR)\ap_cpystrn.obj" -@erase "$(INTDIR)\ap_fnmatch.obj" -@erase "$(INTDIR)\ap_md5c.obj" + -@erase "$(INTDIR)\ap_hook.obj" + -@erase "$(INTDIR)\ap_ctx.obj" + -@erase "$(INTDIR)\ap_mm.obj" -@erase "$(INTDIR)\ap_sha1.obj" -@erase "$(INTDIR)\ap_signal.obj" -@erase "$(INTDIR)\ap_slack.obj" @@ -183,6 +192,9 @@ "$(INTDIR)\ap_cpystrn.obj" \ "$(INTDIR)\ap_fnmatch.obj" \ "$(INTDIR)\ap_md5c.obj" \ + "$(INTDIR)\ap_hook.obj" \ + "$(INTDIR)\ap_ctx.obj" \ + "$(INTDIR)\ap_mm.obj" \ "$(INTDIR)\ap_sha1.obj" \ "$(INTDIR)\ap_signal.obj" \ "$(INTDIR)\ap_slack.obj" \ +--------------------------------------------------------------------------- | Replace the MODULE_MAGIC_COOKIE to allow us to distinguish between | EAPI-aware modules and standard modules. +--------------------------------------------------------------------------- Index: src/include/ap_mmn.h --- src/include/ap_mmn.h 28 Jul 2006 13:55:31 -0000 1.1.1.15 +++ src/include/ap_mmn.h 28 Jul 2006 13:56:29 -0000 1.15 @@ -207,7 +207,23 @@ * 19990320.18 - trace_enable member added to core server_config */ +/* + * Under Extended API situations we replace the magic cookie "AP13" with + * "EAPI" to let us distinguish between the EAPI module structure (which + * contain additional pointers at the end) and standard module structures + * (which lack at least NULL's for the pointers at the end). This is + * important because standard ("AP13") modules would dump core when we + * dispatch over the additional hooks because NULL's are missing at the end of + * the module structure. See also the code in mod_so for details on loading + * (we accept both "AP13" and "EAPI"). + */ +#ifdef EAPI +#define MODULE_MAGIC_COOKIE_AP13 0x41503133UL /* "AP13" */ +#define MODULE_MAGIC_COOKIE_EAPI 0x45415049UL /* "EAPI" */ +#define MODULE_MAGIC_COOKIE MODULE_MAGIC_COOKIE_EAPI +#else #define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */ +#endif #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 19990320 +--------------------------------------------------------------------------- | Add the additional prototypes and defines for the | shared memory pools. +--------------------------------------------------------------------------- Index: src/include/ap_alloc.h --- src/include/ap_alloc.h 28 Jul 2006 13:55:32 -0000 1.1.1.9 +++ src/include/ap_alloc.h 28 Jul 2006 13:56:29 -0000 1.10 @@ -53,6 +53,15 @@ API_EXPORT(pool *) ap_init_alloc(void); /* Set up everything */ void ap_cleanup_alloc(void); API_EXPORT(pool *) ap_make_sub_pool(pool *); /* All pools are subpools of permanent_pool */ +#if defined(EAPI) +typedef enum { AP_POOL_RD, AP_POOL_RW } ap_pool_lock_mode; +int ap_shared_pool_possible(void); +void ap_init_alloc_shared(int); +void ap_kill_alloc_shared(void); +API_EXPORT(pool *) ap_make_shared_sub_pool(pool *); +API_EXPORT(int) ap_acquire_pool(pool *, ap_pool_lock_mode); +API_EXPORT(int) ap_release_pool(pool *); +#endif API_EXPORT(void) ap_destroy_pool(pool *); /* pools have nested lifetimes -- sub_pools are destroyed when the +--------------------------------------------------------------------------- | Add the additional context variable `ctx' for BUFF structures. +--------------------------------------------------------------------------- Index: src/include/buff.h --- src/include/buff.h 28 Jul 2006 13:55:31 -0000 1.1.1.9 +++ src/include/buff.h 28 Jul 2006 13:56:29 -0000 1.13 @@ -83,6 +83,10 @@ /* transport handle, for RPC binding handle or some such */ void *t_handle; +#ifdef EAPI + ap_ctx *ctx; +#endif /* EAPI */ + #ifdef B_SFIO Sfio_t *sf_in; Sfio_t *sf_out; @@ -139,6 +143,10 @@ API_EXPORT(int) ap_bflsbuf(int c, BUFF *fb); API_EXPORT(int) ap_bfilbuf(BUFF *fb); +#ifdef EAPI +#define ap_bpeekc(fb) ( ((fb)->incnt == 0) ? EOF : *((fb)->inptr) ) +#endif + #ifndef CHARSET_EBCDIC #define ap_bgetc(fb) ( ((fb)->incnt == 0) ? ap_bfilbuf(fb) : \ +--------------------------------------------------------------------------- | Add the four additional Apache API module hooks. +--------------------------------------------------------------------------- Index: src/include/http_config.h --- src/include/http_config.h 28 Jul 2006 13:55:31 -0000 1.1.1.15 +++ src/include/http_config.h 28 Jul 2006 13:56:29 -0000 1.17 @@ -234,6 +234,65 @@ void (*child_exit) (server_rec *, pool *); #endif int (*post_read_request) (request_rec *); + +#ifdef EAPI + /* + * ANSI C guarantees us that we can at least _extend_ the module structure + * with additional hooks without the need to change all existing modules. + * Because: ``If there are fewer initializers in the list than members of + * the structure, the trailing members are initialized with 0.'' (The C + * Programming Language, 2nd Ed., A8.7 Initialization). So we just + * have to put our additional hooks here: + * + * add_module: + * Called from within ap_add_module() right after the module structure + * was linked into the Apache internal module list. It is mainly + * intended to be used to define configuration defines () + * which have to be available directly after a LoadModule/AddModule. + * Actually this is the earliest possible hook a module can use. + * + * remove_module: + * Called from within ap_remove_module() right before the module + * structure is kicked out from the Apache internal module list. + * Actually this is last possible hook a module can use and exists for + * consistency with the add_module hook. + * + * rewrite_command: + * Called right after a configuration directive line was read and + * before it is processed. It is mainly intended to be used for + * rewriting directives in order to provide backward compatibility to + * old directive variants. + * + * new_connection: + * Called from within the internal new_connection() function, right + * after the conn_rec structure for the new established connection was + * created and before Apache starts processing the request with + * ap_read_request(). It is mainly intended to be used to setup/run + * connection dependent things like sending start headers for + * on-the-fly compression, etc. + * + * close_connection: + * Called from within the Apache dispatching loop just before any + * ap_bclose() is performed on the socket connection, but a long time + * before any pool cleanups are done for the connection (which can be + * too late for some applications). It is mainly intended to be used + * to close/finalize connection dependent things like sending end + * headers for on-the-fly compression, etc. + */ +#ifdef ULTRIX_BRAIN_DEATH + void (*add_module) (); + void (*remove_module) (); + char *(*rewrite_command) (); + void (*new_connection) (); + void (*close_connection) (); +#else + void (*add_module) (struct module_struct *); + void (*remove_module) (struct module_struct *); + char *(*rewrite_command) (cmd_parms *, void *config, const char *); + void (*new_connection) (conn_rec *); + void (*close_connection) (conn_rec *); +#endif +#endif /* EAPI */ } module; /* Initializer for the first few module slots, which are only +--------------------------------------------------------------------------- | Add the additional variable `ap_global_ctx' for holding | global module context. +--------------------------------------------------------------------------- Index: src/include/http_conf_globals.h --- src/include/http_conf_globals.h 28 Jul 2006 13:55:30 -0000 1.1.1.15 +++ src/include/http_conf_globals.h 28 Jul 2006 13:56:29 -0000 1.16 @@ -53,6 +53,9 @@ #endif extern int ap_dump_settings; extern API_VAR_EXPORT int ap_extended_status; +#ifdef EAPI +extern API_VAR_EXPORT ap_ctx *ap_global_ctx; +#endif /* EAPI */ extern API_VAR_EXPORT char *ap_pid_fname; extern API_VAR_EXPORT char *ap_scoreboard_fname; +--------------------------------------------------------------------------- | First add support for the HTTPS protocol scheme via hooks, | second add the additional context variable `ctx' for the | conn_rec, server_rec and request_rec structures. And third | add a prototype for the additional ap_add_config_define() | function. +--------------------------------------------------------------------------- Index: src/include/httpd.h --- src/include/httpd.h 8 Feb 2008 11:15:38 -0000 1.1.1.31 +++ src/include/httpd.h 8 Feb 2008 11:17:39 -0000 1.41 @@ -28,7 +28,19 @@ /* Headers in which EVERYONE has an interest... */ #include "ap_config.h" +#ifdef EAPI +#include "ap_mm.h" +#endif #include "ap_alloc.h" +/* + * Include the Extended API headers. + * Don't move the position. It has to be after ap_alloc.h because it uses the + * pool stuff but before buff.h because the buffer stuff uses the EAPI, too. + */ +#ifdef EAPI +#include "ap_hook.h" +#include "ap_ctx.h" +#endif /* EAPI */ #include "buff.h" #include "ap.h" @@ -103,8 +115,13 @@ #define ap_http_method(r) ap_os_http_method((void*)r) #define ap_default_port(r) ap_os_default_port((void*)r) #else +#ifdef EAPI +#define ap_http_method(r) (((r)->ctx != NULL && ap_ctx_get((r)->ctx, "ap::http::method") != NULL) ? ((char *)ap_ctx_get((r)->ctx, "ap::http::method")) : "http") +#define ap_default_port(r) (((r)->ctx != NULL && ap_ctx_get((r)->ctx, "ap::default::port") != NULL) ? atoi((char *)ap_ctx_get((r)->ctx, "ap::default::port")) : DEFAULT_HTTP_PORT) +#else /* EAPI */ #define ap_http_method(r) "http" #define ap_default_port(r) DEFAULT_HTTP_PORT +#endif /* EAPI */ #endif /* --------- Default user name and group name running standalone ---------- */ @@ -313,6 +330,19 @@ #define SCOREBOARD_MAINTENANCE_INTERVAL 1000000 #endif +/* + * Unix only: + * Path to Shared Memory Files + */ +#ifdef EAPI +#ifndef EAPI_MM_CORE_PATH +#define EAPI_MM_CORE_PATH "logs/mm" +#endif +#ifndef EAPI_MM_CORE_MAXSIZE +#define EAPI_MM_CORE_MAXSIZE 1024*1024*1 /* max. 1MB */ +#endif +#endif + /* Number of requests to try to handle in a single process. If <= 0, * the children don't die off. That's the default here, since I'm still * interested in finding and stanching leaks. @@ -405,6 +435,9 @@ API_EXPORT(const char *) ap_get_server_version(void); API_EXPORT(void) ap_add_version_component(const char *component); API_EXPORT(const char *) ap_get_server_built(void); +#ifdef EAPI +API_EXPORT(void) ap_add_config_define(const char *define); +#endif /* EAPI */ /* Numeric release version identifier: MMNNFFRBB: major minor fix final beta * Always increases along the same track as the source branch. @@ -808,6 +841,10 @@ * record to improve 64bit alignment the next time we need to break * binary compatibility for some other reason. */ + +#ifdef EAPI + ap_ctx *ctx; +#endif /* EAPI */ }; @@ -856,6 +893,9 @@ char *local_host; /* used for ap_get_server_name when * UseCanonicalName is set to DNS * (ignores setting of HostnameLookups) */ +#ifdef EAPI + ap_ctx *ctx; +#endif /* EAPI */ }; /* Per-vhost config... */ @@ -928,6 +968,10 @@ int limit_req_line; /* limit on size of the HTTP request line */ int limit_req_fieldsize; /* limit on size of any request header field */ int limit_req_fields; /* limit on number of request header fields */ + +#ifdef EAPI + ap_ctx *ctx; +#endif /* EAPI */ }; /* These are more like real hosts than virtual hosts */ +--------------------------------------------------------------------------- | Patch the shared memory pool support into the Apache pool facility. +--------------------------------------------------------------------------- Index: src/main/alloc.c --- src/main/alloc.c 28 Jul 2006 13:55:33 -0000 1.1.1.18 +++ src/main/alloc.c 28 Jul 2006 13:56:29 -0000 1.27 @@ -22,6 +22,10 @@ */ #include "httpd.h" +#ifdef EAPI +#include "http_config.h" +#include "http_conf_globals.h" +#endif #include "multithread.h" #include "http_log.h" @@ -96,6 +100,10 @@ #define BLOCK_MINALLOC 0 #endif +#if defined(EAPI) && defined(EAPI_MM) +static AP_MM *mm = NULL; +#endif + /***************************************************************** * * Managing free storage blocks... @@ -124,6 +132,9 @@ char *endp; union block_hdr *next; char *first_avail; +#if defined(EAPI) && defined(EAPI_MM) + int is_shm; +#endif #ifdef POOL_DEBUG union block_hdr *global_next; struct pool *owning_pool; @@ -174,7 +185,11 @@ /* Get a completely new block from the system pool. Note that we rely on malloc() to provide aligned memory. */ +#if defined(EAPI) && defined(EAPI_MM) +static union block_hdr *malloc_block(int size, int is_shm) +#else static union block_hdr *malloc_block(int size) +#endif { union block_hdr *blok; int request_size; @@ -190,6 +205,11 @@ num_malloc_bytes += size + sizeof(union block_hdr); #endif request_size = size + sizeof(union block_hdr); +#if defined(EAPI) && defined(EAPI_MM) + if (is_shm) + blok = (union block_hdr *)ap_mm_malloc(mm, request_size); + else +#endif blok = (union block_hdr *) malloc(request_size); if (blok == NULL) { fprintf(stderr, "Ouch! malloc(%d) failed in malloc_block()\n", @@ -197,6 +217,9 @@ exit(1); } debug_fill(blok, size + sizeof(union block_hdr)); +#if defined(EAPI) && defined(EAPI_MM) + blok->h.is_shm = is_shm; +#endif blok->h.next = NULL; blok->h.first_avail = (char *) (blok + 1); blok->h.endp = size + blok->h.first_avail; @@ -257,6 +280,10 @@ if (blok == NULL) return; /* Sanity check --- freeing empty pool? */ +#if defined(EAPI) && defined(EAPI_MM) + if (blok->h.is_shm) + (void)ap_mm_lock(mm, AP_MM_LOCK_RW); +#endif (void) ap_acquire_mutex(alloc_mutex); old_free_list = block_freelist; block_freelist = blok; @@ -303,6 +330,10 @@ #endif (void) ap_release_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + if (blok->h.is_shm) + (void)ap_mm_unlock(mm); +#endif #endif } @@ -311,7 +342,11 @@ * if necessary. Must be called with alarms blocked. */ +#if defined(EAPI) && defined(EAPI_MM) +static union block_hdr *new_block(int min_size, int is_shm) +#else static union block_hdr *new_block(int min_size) +#endif { union block_hdr **lastptr = &block_freelist; union block_hdr *blok = block_freelist; @@ -321,7 +356,12 @@ */ while (blok != NULL) { +#if defined(EAPI) && defined(EAPI_MM) + if (blok->h.is_shm == is_shm && + min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) { +#else if (min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) { +#endif *lastptr = blok->h.next; blok->h.next = NULL; debug_verify_filled(blok->h.first_avail, blok->h.endp, @@ -337,7 +377,11 @@ /* Nope. */ min_size += BLOCK_MINFREE; +#if defined(EAPI) && defined(EAPI_MM) + blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC, is_shm); +#else blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC); +#endif return blok; } @@ -387,6 +431,9 @@ #ifdef POOL_DEBUG struct pool *joined; #endif +#if defined(EAPI) && defined(EAPI_MM) + int is_shm; +#endif }; static pool *permanent_pool; @@ -401,16 +448,28 @@ #define POOL_HDR_CLICKS (1 + ((sizeof(struct pool) - 1) / CLICK_SZ)) #define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ) +#if defined(EAPI) && defined(EAPI_MM) +static struct pool *make_sub_pool_internal(struct pool *p, int is_shm) +#else API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p) +#endif { union block_hdr *blok; pool *new_pool; ap_block_alarms(); +#if defined(EAPI) && defined(EAPI_MM) + if (is_shm) + (void)ap_mm_lock(mm, AP_MM_LOCK_RW); +#endif (void) ap_acquire_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + blok = new_block(POOL_HDR_BYTES, is_shm); +#else blok = new_block(POOL_HDR_BYTES); +#endif new_pool = (pool *) blok->h.first_avail; blok->h.first_avail += POOL_HDR_BYTES; #ifdef POOL_DEBUG @@ -429,12 +488,38 @@ p->sub_pools = new_pool; } +#if defined(EAPI) && defined(EAPI_MM) + new_pool->is_shm = is_shm; +#endif + (void) ap_release_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + if (is_shm) + (void)ap_mm_unlock(mm); +#endif ap_unblock_alarms(); return new_pool; } +#if defined(EAPI) +#if defined(EAPI_MM) +API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p) +{ + return make_sub_pool_internal(p, 0); +} +API_EXPORT(struct pool *) ap_make_shared_sub_pool(struct pool *p) +{ + return make_sub_pool_internal(p, 1); +} +#else +API_EXPORT(struct pool *) ap_make_shared_sub_pool(struct pool *p) +{ + return NULL; +} +#endif +#endif + #ifdef POOL_DEBUG static void stack_var_init(char *s) { @@ -449,6 +534,13 @@ } #endif +#if defined(EAPI) +int ap_shared_pool_possible(void) +{ + return ap_mm_useable(); +} +#endif + #ifdef ALLOC_STATS static void dump_stats(void) { @@ -481,6 +573,58 @@ return permanent_pool; } +#if defined(EAPI) +void ap_init_alloc_shared(int early) +{ +#if defined(EAPI_MM) + int mm_size; + char *mm_path; + char *err1, *err2; + + if (early) { + /* process very early on startup */ + mm_size = ap_mm_maxsize(); + if (mm_size > EAPI_MM_CORE_MAXSIZE) + mm_size = EAPI_MM_CORE_MAXSIZE; + mm_path = ap_server_root_relative(permanent_pool, + ap_psprintf(permanent_pool, "%s.%ld", + EAPI_MM_CORE_PATH, (long)getpid())); + if ((mm = ap_mm_create(mm_size, mm_path)) == NULL) { + fprintf(stderr, "Ouch! ap_mm_create(%d, \"%s\") failed\n", mm_size, mm_path); + err1 = ap_mm_error(); + if (err1 == NULL) + err1 = "-unknown-"; + err2 = strerror(errno); + if (err2 == NULL) + err2 = "-unknown-"; + fprintf(stderr, "Error: MM: %s: OS: %s\n", err1, err2); + exit(1); + } + } + else { + /* process a lot later on startup */ +#ifdef WIN32 + ap_mm_permission(mm, (_S_IREAD|_S_IWRITE), ap_user_id, -1); +#else + ap_mm_permission(mm, (S_IRUSR|S_IWUSR), ap_user_id, -1); +#endif + } +#endif /* EAPI_MM */ + return; +} + +void ap_kill_alloc_shared(void) +{ +#if defined(EAPI_MM) + if (mm != NULL) { + ap_mm_destroy(mm); + mm = NULL; + } +#endif /* EAPI_MM */ + return; +} +#endif /* EAPI */ + void ap_cleanup_alloc(void) { ap_destroy_mutex(alloc_mutex); @@ -491,10 +635,18 @@ { ap_block_alarms(); +#if defined(EAPI) && defined(EAPI_MM) + if (a->is_shm) + (void)ap_mm_lock(mm, AP_MM_LOCK_RW); +#endif (void) ap_acquire_mutex(alloc_mutex); while (a->sub_pools) ap_destroy_pool(a->sub_pools); (void) ap_release_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + if (a->is_shm) + (void)ap_mm_unlock(mm); +#endif /* Don't hold the mutex during cleanups. */ run_cleanups(a->cleanups); a->cleanups = NULL; @@ -528,6 +680,10 @@ ap_block_alarms(); ap_clear_pool(a); +#if defined(EAPI) && defined(EAPI_MM) + if (a->is_shm) + (void)ap_mm_lock(mm, AP_MM_LOCK_RW); +#endif (void) ap_acquire_mutex(alloc_mutex); if (a->parent) { if (a->parent->sub_pools == a) @@ -538,6 +694,10 @@ a->sub_next->sub_prev = a->sub_prev; } (void) ap_release_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + if (a->is_shm) + (void)ap_mm_unlock(mm); +#endif free_blocks(a->first); ap_unblock_alarms(); @@ -552,6 +712,30 @@ return bytes_in_block_list(block_freelist); } +#if defined(EAPI) +API_EXPORT(int) ap_acquire_pool(pool *p, ap_pool_lock_mode mode) +{ +#if defined(EAPI_MM) + if (!p->is_shm) + return 1; + return ap_mm_lock(mm, mode == AP_POOL_RD ? AP_MM_LOCK_RD : AP_MM_LOCK_RW); +#else + return 1; +#endif +} + +API_EXPORT(int) ap_release_pool(pool *p) +{ +#if defined(EAPI_MM) + if (!p->is_shm) + return 1; + return ap_mm_unlock(mm); +#else + return 1; +#endif +} +#endif /* EAPI */ + /***************************************************************** * POOL_DEBUG support */ @@ -717,16 +901,31 @@ ap_block_alarms(); +#if defined(EAPI) && defined(EAPI_MM) + if (a->is_shm) + (void)ap_mm_lock(mm, AP_MM_LOCK_RW); +#endif (void) ap_acquire_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + blok = new_block(size, a->is_shm); +#else blok = new_block(size); +#endif a->last->h.next = blok; a->last = blok; #ifdef POOL_DEBUG blok->h.owning_pool = a; #endif +#if defined(EAPI) && defined(EAPI_MM) + blok->h.is_shm = a->is_shm; +#endif (void) ap_release_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + if (a->is_shm) + (void)ap_mm_unlock(mm); +#endif ap_unblock_alarms(); @@ -843,6 +1042,11 @@ size = cur_len << 1; if (size < AP_PSPRINTF_MIN_SIZE) size = AP_PSPRINTF_MIN_SIZE; +#if defined(EAPI) && defined(EAPI_MM) + if (ps->block->h.is_shm) + ptr = ap_mm_realloc(ps->base, size); + else +#endif ptr = realloc(ps->base, size); if (ptr == NULL) { fputs("Ouch! Out of memory!\n", stderr); @@ -866,9 +1070,21 @@ size = AP_PSPRINTF_MIN_SIZE; /* must try another blok */ +#if defined(EAPI) && defined(EAPI_MM) + if (blok->h.is_shm) + (void)ap_mm_lock(mm, AP_MM_LOCK_RW); +#endif (void) ap_acquire_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + nblok = new_block(size, blok->h.is_shm); +#else nblok = new_block(size); +#endif (void) ap_release_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + if (blok->h.is_shm) + (void)ap_mm_unlock(mm); +#endif memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len); ps->vbuff.curpos = nblok->h.first_avail + cur_len; /* save a byte for the NUL terminator */ @@ -877,10 +1093,18 @@ /* did we allocate the current blok? if so free it up */ if (ps->got_a_new_block) { debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail); +#if defined(EAPI) && defined(EAPI_MM) + if (blok->h.is_shm) + (void)ap_mm_lock(mm, AP_MM_LOCK_RW); +#endif (void) ap_acquire_mutex(alloc_mutex); blok->h.next = block_freelist; block_freelist = blok; (void) ap_release_mutex(alloc_mutex); +#if defined(EAPI) && defined(EAPI_MM) + if (blok->h.is_shm) + (void)ap_mm_unlock(mm); +#endif } ps->blok = nblok; ps->got_a_new_block = 1; @@ -899,6 +1123,11 @@ void *ptr; ap_block_alarms(); +#if defined(EAPI) && defined(EAPI_MM) + if (p->is_shm) + ps.base = ap_mm_malloc(mm, 512); + else +#endif ps.base = malloc(512); if (ps.base == NULL) { fputs("Ouch! Out of memory!\n", stderr); @@ -911,6 +1140,11 @@ *ps.vbuff.curpos++ = '\0'; ptr = ps.base; /* shrink */ +#if defined(EAPI) && defined(EAPI_MM) + if (p->is_shm) + ptr = ap_mm_realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr); + else +#endif ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr); if (ptr == NULL) { fputs("Ouch! Out of memory!\n", stderr); +--------------------------------------------------------------------------- | Patch the low-level buffer routines to additionally allow | modules to intercept the I/O processing via hooks. +--------------------------------------------------------------------------- Index: src/main/buff.c --- src/main/buff.c 28 Jul 2006 13:55:34 -0000 1.1.1.17 +++ src/main/buff.c 28 Jul 2006 13:56:29 -0000 1.25 @@ -251,6 +251,9 @@ } else #endif +#ifdef EAPI + if (!ap_hook_call("ap::buff::read", &rv, fb, buf, nbyte)) +#endif /* EAPI */ rv = read(fb->fd_in, buf, nbyte); return rv; @@ -262,6 +265,9 @@ #if defined (WIN32) || defined(NETWARE) || defined(CYGWIN_WINSOCK) if (fb->flags & B_SOCKET) { +#ifdef EAPI + if (!ap_hook_call("ap::buff::recvwithtimeout", &rv, fb, buf, nbyte)) +#endif /* EAPI */ rv = ap_recvwithtimeout(fb->fd_in, buf, nbyte, 0); if (rv == SOCKET_ERROR) errno = WSAGetLastError(); @@ -312,6 +318,9 @@ } else #endif +#ifdef EAPI + if (!ap_hook_call("ap::buff::write", &rv, fb, buf, nbyte)) +#endif /* EAPI */ #if defined (B_SFIO) rv = sfwrite(fb->sf_out, buf, nbyte); #else @@ -342,6 +351,9 @@ #if defined(WIN32) || defined(NETWARE) if (fb->flags & B_SOCKET) { +#ifdef EAPI + if (!ap_hook_call("ap::buff::sendwithtimeout", &rv, fb, buf, nbyte)) +#endif /* EAPI */ rv = ap_sendwithtimeout(fb->fd, buf, nbyte, 0); if (rv == SOCKET_ERROR) errno = WSAGetLastError(); @@ -425,6 +437,10 @@ fb->callback_data = NULL; fb->filter_callback = NULL; +#ifdef EAPI + fb->ctx = ap_ctx_new(p); +#endif /* EAPI */ + return fb; } @@ -1077,6 +1093,9 @@ i = 0; while (i < nvec) { do +#ifdef EAPI + if (!ap_hook_call("ap::buff::writev", &rv, fb, &vec[i], nvec -i)) +#endif /* EAPI */ rv = writev(fb->fd, &vec[i], nvec - i); while (rv == -1 && (errno == EINTR || errno == EAGAIN) && !(fb->flags & B_EOUT)); +--------------------------------------------------------------------------- | Add the implementation of the additional `add_module' and | `rewrite_command' module hooks. Additionally the `ctx' | variables are initialized. +--------------------------------------------------------------------------- Index: src/main/http_config.c --- src/main/http_config.c 28 Jul 2006 13:55:33 -0000 1.1.1.21 +++ src/main/http_config.c 28 Jul 2006 13:56:29 -0000 1.24 @@ -558,6 +558,20 @@ m->name = tmp; } #endif /*_OSD_POSIX*/ + +#ifdef EAPI + /* + * Invoke the `add_module' hook inside the now existing set + * of modules to let them all now that this module was added. + */ + { + module *m2; + for (m2 = top_module; m2 != NULL; m2 = m2->next) + if (m2->magic == MODULE_MAGIC_COOKIE_EAPI) + if (m2->add_module != NULL) + (*m2->add_module)(m); + } +#endif /* EAPI */ } /* @@ -572,6 +586,21 @@ { module *modp; +#ifdef EAPI + /* + * Invoke the `remove_module' hook inside the now existing + * set of modules to let them all now that this module is + * beeing removed. + */ + { + module *m2; + for (m2 = top_module; m2 != NULL; m2 = m2->next) + if (m2->magic == MODULE_MAGIC_COOKIE_EAPI) + if (m2->remove_module != NULL) + (*m2->remove_module)(m); + } +#endif /* EAPI */ + modp = top_module; if (modp == m) { /* We are the top module, special case */ @@ -965,6 +994,27 @@ const command_rec *cmd; module *mod = top_module; +#ifdef EAPI + /* + * Invoke the `rewrite_command' of modules to allow + * they to rewrite the directive line before we + * process it. + */ + { + module *m; + char *cp; + for (m = top_module; m != NULL; m = m->next) { + if (m->magic == MODULE_MAGIC_COOKIE_EAPI) { + if (m->rewrite_command != NULL) { + cp = (m->rewrite_command)(parms, config, l); + if (cp != NULL) + l = cp; + } + } + } + } +#endif /* EAPI */ + if ((l[0] == '#') || (!l[0])) return NULL; @@ -1429,6 +1479,10 @@ s->limit_req_fieldsize = main_server->limit_req_fieldsize; s->limit_req_fields = main_server->limit_req_fields; +#ifdef EAPI + s->ctx = ap_ctx_new(p); +#endif /* EAPI */ + *ps = s; return ap_parse_vhost_addrs(p, hostname, s); @@ -1540,6 +1594,10 @@ s->module_config = create_server_config(p, s); s->lookup_defaults = create_default_per_dir_config(p); +#ifdef EAPI + s->ctx = ap_ctx_new(p); +#endif /* EAPI */ + return s; } +--------------------------------------------------------------------------- | Add the ap_global_ctx variable and the new | ap_add_config_define() function. Additionally the | implementation of the additional `new_connection' module hook | is added plus the initialization of one more `ctx' variable. +--------------------------------------------------------------------------- Index: src/main/http_main.c --- src/main/http_main.c 8 Feb 2008 11:15:39 -0000 1.1.1.28 +++ src/main/http_main.c 8 Feb 2008 11:17:39 -0000 1.51 @@ -243,6 +243,9 @@ int ap_dump_settings = 0; API_VAR_EXPORT int ap_extended_status = 0; +#ifdef EAPI +API_VAR_EXPORT ap_ctx *ap_global_ctx; +#endif /* EAPI */ /* * The max child slot ever assigned, preserved across restarts. Necessary @@ -479,6 +482,30 @@ } } +#ifdef EAPI +API_EXPORT(void) ap_add_config_define(const char *define) +{ + char **var; + var = (char **)ap_push_array(ap_server_config_defines); + *var = ap_pstrdup(pcommands, define); + return; +} + +/* + * Invoke the `close_connection' hook of modules to let them do + * some connection dependent actions before we close it. + */ +static void ap_call_close_connection_hook(conn_rec *c) +{ + module *m; + for (m = top_module; m != NULL; m = m->next) + if (m->magic == MODULE_MAGIC_COOKIE_EAPI) + if (m->close_connection != NULL) + (*m->close_connection)(c); + return; +} +#endif /* EAPI */ + #ifndef NETWARE static APACHE_TLS int volatile exit_after_unblock = 0; #endif @@ -1594,6 +1621,9 @@ } ap_bsetflag(save_req->connection->client, B_EOUT, 1); +#ifdef EAPI + ap_call_close_connection_hook(save_req->connection); +#endif /* EAPI */ ap_bclose(save_req->connection->client); if (!ap_standalone) @@ -1602,6 +1632,9 @@ } else { /* abort the connection */ ap_bsetflag(current_conn->client, B_EOUT, 1); +#ifdef EAPI + ap_call_close_connection_hook(current_conn); +#endif /* EAPI */ ap_bclose(current_conn->client); current_conn->aborted = 1; } @@ -1923,10 +1956,16 @@ /* Send any leftover data to the client, but never try to again */ if (ap_bflush(r->connection->client) == -1) { +#ifdef EAPI + ap_call_close_connection_hook(r->connection); +#endif /* EAPI */ ap_kill_timeout(r); ap_bclose(r->connection->client); return; } +#ifdef EAPI + ap_call_close_connection_hook(r->connection); +#endif /* EAPI */ ap_bsetflag(r->connection->client, B_EOUT, 1); /* Close our half of the connection --- send the client a FIN */ @@ -2625,6 +2664,9 @@ /* Clear the pool - including any registered cleanups */ ap_destroy_pool(pglobal); #endif +#ifdef EAPI + ap_kill_alloc_shared(); +#endif exit(code); } @@ -3722,6 +3764,24 @@ conn->remote_addr = *remaddr; conn->remote_ip = ap_pstrdup(conn->pool, inet_ntoa(conn->remote_addr.sin_addr)); +#ifdef EAPI + conn->ctx = ap_ctx_new(conn->pool); +#endif /* EAPI */ + +#ifdef EAPI + /* + * Invoke the `new_connection' hook of modules to let them do + * some connection dependent actions before we go on with + * processing the request on this connection. + */ + { + module *m; + for (m = top_module; m != NULL; m = m->next) + if (m->magic == MODULE_MAGIC_COOKIE_EAPI) + if (m->new_connection != NULL) + (*m->new_connection)(conn); + } +#endif /* EAPI */ return conn; } @@ -4232,6 +4292,15 @@ printf("Server's Module Magic Number: %u:%u\n", MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR); printf("Server compiled with....\n"); +#ifdef EAPI + printf(" -D EAPI\n"); +#endif +#ifdef EAPI_MM + printf(" -D EAPI_MM\n"); +#ifdef EAPI_MM_CORE_PATH + printf(" -D EAPI_MM_CORE_PATH=\"" EAPI_MM_CORE_PATH "\"\n"); +#endif +#endif #ifdef TPF show_os_specific_compile_settings(); #endif @@ -4407,6 +4476,23 @@ ap_server_pre_read_config = ap_make_array(pcommands, 1, sizeof(char *)); ap_server_post_read_config = ap_make_array(pcommands, 1, sizeof(char *)); ap_server_config_defines = ap_make_array(pcommands, 1, sizeof(char *)); + +#ifdef EAPI + ap_hook_init(); + ap_hook_configure("ap::buff::read", + AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST); + ap_hook_configure("ap::buff::write", + AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST); + ap_hook_configure("ap::buff::writev", + AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST); + ap_hook_configure("ap::buff::sendwithtimeout", + AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST); + ap_hook_configure("ap::buff::recvwithtimeout", + AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST); + + ap_global_ctx = ap_ctx_new(NULL); +#endif /* EAPI */ + /* overkill since static */ for (i = 0; i < HARD_SERVER_LIMIT; i++) { pid_table[i] = 0; @@ -4907,6 +4993,9 @@ ap_sync_scoreboard_image(); if (ap_scoreboard_image->global.running_generation != ap_my_generation) { +#ifdef EAPI + ap_call_close_connection_hook(current_conn); +#endif /* EAPI */ ap_bclose(conn_io); clean_child_exit(0); } @@ -4935,6 +5024,9 @@ */ #ifdef NO_LINGCLOSE +#ifdef EAPI + ap_call_close_connection_hook(current_conn); +#endif /* EAPI */ ap_bclose(conn_io); /* just close it */ #else if (r && r->connection @@ -4945,6 +5037,9 @@ lingering_close(r); } else { +#ifdef EAPI + ap_call_close_connection_hook(current_conn); +#endif /* EAPI */ ap_bsetflag(conn_io, B_EOUT, 1); ap_bclose(conn_io); } @@ -5745,16 +5840,31 @@ usage(argv[0]); } } +#ifdef EAPI + ap_init_alloc_shared(TRUE); +#endif ap_suexec_enabled = init_suexec(); server_conf = ap_read_config(pconf, ptrans, ap_server_confname); +#ifdef EAPI + ap_init_alloc_shared(FALSE); +#endif + if (ap_configtestonly) { fprintf(stderr, "Syntax OK\n"); +#ifdef EAPI + clean_parent_exit(0); +#else exit(0); +#endif } if (ap_dump_settings) { +#ifdef EAPI + clean_parent_exit(0); +#else exit(0); +#endif } child_timeouts = !ap_standalone || one_process; @@ -5902,6 +6012,10 @@ ap_destroy_pool(r->pool); } +#ifdef EAPI + ap_call_close_connection_hook(conn); +#endif /* EAPI */ + ap_bclose(cio); } exit(0); @@ -6278,6 +6392,9 @@ ap_kill_cleanups_for_socket(ptrans, csd); #ifdef NO_LINGCLOSE +#ifdef EAPI + ap_call_close_connection_hook(current_conn); +#endif /* EAPI */ ap_bclose(conn_io); /* just close it */ #else if (r && r->connection @@ -6288,6 +6405,9 @@ lingering_close(r); } else { +#ifdef EAPI + ap_call_close_connection_hook(current_conn); +#endif /* EAPI */ ap_bsetflag(conn_io, B_EOUT, 1); ap_bclose(conn_io); } @@ -7863,6 +7983,10 @@ if (!conf_specified) ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname)); +#ifdef EAPI + ap_init_alloc_shared(TRUE); +#endif + if (!ap_os_is_path_absolute(ap_server_confname)) ap_cpystrn(ap_server_confname, ap_server_root_relative(pcommands, ap_server_confname), @@ -7903,6 +8027,9 @@ #else /* ndef WIN32 */ server_conf = ap_read_config(pconf, ptrans, ap_server_confname); #endif +#ifdef EAPI + ap_init_alloc_shared(FALSE); +#endif if (ap_configtestonly) { fprintf(stderr, "%s: Syntax OK\n", ap_server_root_relative(pcommands, ap_server_confname)); +--------------------------------------------------------------------------- | Just add the initialization of the `ctx' variable for | conn_rec structures. +--------------------------------------------------------------------------- Index: src/main/http_request.c --- src/main/http_request.c 28 Jul 2006 13:55:34 -0000 1.1.1.20 +++ src/main/http_request.c 28 Jul 2006 13:56:29 -0000 1.20 @@ -1373,6 +1373,10 @@ new->method = r->method; new->method_number = r->method_number; +#ifdef EAPI + /* initialize context _BEFORE_ ap_parse_uri() call */ + new->ctx = r->ctx; +#endif /* EAPI */ ap_parse_uri(new, new_uri); new->request_config = ap_create_request_config(r->pool); new->per_dir_config = r->server->lookup_defaults; +--------------------------------------------------------------------------- | Just add the initialization of the `ctx' variable for | request_rec structures. +--------------------------------------------------------------------------- Index: src/main/http_protocol.c --- src/main/http_protocol.c 28 Jul 2006 13:55:34 -0000 1.1.1.24 +++ src/main/http_protocol.c 28 Jul 2006 13:56:29 -0000 1.24 @@ -1173,6 +1173,10 @@ r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */ r->the_request = NULL; +#ifdef EAPI + r->ctx = ap_ctx_new(r->pool); +#endif /* EAPI */ + #ifdef CHARSET_EBCDIC ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, r->ebcdic.conv_in = 1); ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1); @@ -1341,6 +1345,11 @@ rnew->read_body = REQUEST_NO_BODY; rnew->main = (request_rec *) r; + +#ifdef EAPI + rnew->ctx = r->ctx; +#endif /* EAPI */ + } API_EXPORT(void) ap_finalize_sub_req_protocol(request_rec *sub) +--------------------------------------------------------------------------- | Add support for loading both EAPI and AP13 modules. +--------------------------------------------------------------------------- Index: src/modules/standard/mod_so.c --- src/modules/standard/mod_so.c 28 Jul 2006 13:55:28 -0000 1.1.1.13 +++ src/modules/standard/mod_so.c 28 Jul 2006 13:56:29 -0000 1.14 @@ -267,11 +267,24 @@ * Make sure the found module structure is really a module structure * */ +#ifdef EAPI + if ( modp->magic != MODULE_MAGIC_COOKIE_AP13 + && modp->magic != MODULE_MAGIC_COOKIE_EAPI) { +#else if (modp->magic != MODULE_MAGIC_COOKIE) { +#endif return ap_pstrcat(cmd->pool, "API module structure `", modname, "' in file ", szModuleFile, " is garbled -" " perhaps this is not an Apache module DSO?", NULL); } +#ifdef EAPI + if (modp->magic == MODULE_MAGIC_COOKIE_AP13) { + ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, NULL, + "Loaded DSO %s uses plain Apache 1.3 API, " + "this module might crash under EAPI! " + "(please recompile it with -DEAPI)", filename); + } +#endif /* * Add this module to the Apache core structures +--------------------------------------------------------------------------- | Add additional logging functions to the CustomLog directive | which can be used by other modules to create additional | logfile tags. Actually we add two types of hooks: One hook | for intercepting the new and generic %x (eXtension) tag and | one hook for creating new %x tags at all. +--------------------------------------------------------------------------- Index: src/modules/standard/mod_log_config.c --- src/modules/standard/mod_log_config.c 28 Jul 2006 13:55:27 -0000 1.1.1.16 +++ src/modules/standard/mod_log_config.c 28 Jul 2006 13:56:29 -0000 1.29 @@ -221,6 +221,9 @@ typedef const char *(*item_key_func) (request_rec *, char *); typedef struct { +#ifdef EAPI + char ch; +#endif item_key_func func; char *arg; int condition_sense; @@ -542,15 +545,36 @@ } }; +#ifdef EAPI +static struct log_item_list *find_log_func(pool *p, char k) +#else /* EAPI */ static struct log_item_list *find_log_func(char k) +#endif /* EAPI */ { int i; +#ifdef EAPI + struct log_item_list *lil; +#endif /* EAPI */ for (i = 0; log_item_keys[i].ch; ++i) if (k == log_item_keys[i].ch) { return &log_item_keys[i]; } +#ifdef EAPI + if (ap_hook_status(ap_psprintf(p, "ap::mod_log_config::log_%c", k)) + != AP_HOOK_STATE_NOTEXISTANT) { + lil = (struct log_item_list *) + ap_pcalloc(p, sizeof(struct log_item_list)); + if (lil == NULL) + return NULL; + lil->ch = k; + lil->func = NULL; + lil->want_orig_default = 0; + return lil; + } +#endif /* EAPI */ + return NULL; } @@ -676,7 +700,11 @@ break; default: +#ifdef EAPI + l = find_log_func(p, *s++); +#else /* EAPI */ l = find_log_func(*s++); +#endif /* EAPI */ if (!l) { char dummy[2]; @@ -685,6 +713,9 @@ return ap_pstrcat(p, "Unrecognized LogFormat directive %", dummy, NULL); } +#ifdef EAPI + it->ch = s[-1]; +#endif it->func = l->func; if (it->want_orig == -1) { it->want_orig = l->want_orig_default; @@ -746,6 +777,15 @@ /* We do. Do it... */ +#ifdef EAPI + if (item->func == NULL) { + cp = NULL; + ap_hook_use(ap_psprintf(r->pool, "ap::mod_log_config::log_%c", item->ch), + AP_HOOK_SIG3(ptr,ptr,ptr), AP_HOOK_DECLINE(NULL), + &cp, r, item->arg); + } + else +#endif cp = (*item->func) (item->want_orig ? orig : r, item->arg); return cp ? cp : "-"; } +--------------------------------------------------------------------------- | Allow RewriteCond and RewriteRule directives to lookup | variables from other modules. +--------------------------------------------------------------------------- Index: src/modules/standard/mod_rewrite.c --- src/modules/standard/mod_rewrite.c 28 Jul 2006 13:55:29 -0000 1.1.1.22 +++ src/modules/standard/mod_rewrite.c 28 Jul 2006 13:56:29 -0000 1.20 @@ -3864,6 +3864,15 @@ } #endif /* ndef WIN32 && NETWARE*/ +#ifdef EAPI + else { + ap_hook_use("ap::mod_rewrite::lookup_variable", + AP_HOOK_SIG3(ptr,ptr,ptr), + AP_HOOK_DECLINE(NULL), + &result, r, var); + } +#endif + if (result == NULL) { return ap_pstrdup(r->pool, ""); } +--------------------------------------------------------------------------- | Add an EAPI hook to allow other modules to add content to | the status HTML page. +--------------------------------------------------------------------------- Index: src/modules/standard/mod_status.c --- src/modules/standard/mod_status.c 8 Feb 2008 11:15:41 -0000 1.1.1.19 +++ src/modules/standard/mod_status.c 8 Feb 2008 11:17:39 -0000 1.16 @@ -696,6 +733,12 @@ #endif } +#ifdef EAPI + ap_hook_use("ap::mod_status::display", + AP_HOOK_SIG4(void,ptr,int,int), AP_HOOK_ALL, + r, no_table_report, short_report); +#endif + } else { if (!short_report) { +--------------------------------------------------------------------------- | Add hooks to the scheme processing to allow other modules to | recognize more schemes by intercepting this processing. +--------------------------------------------------------------------------- Index: src/modules/proxy/mod_proxy.c --- src/modules/proxy/mod_proxy.c 28 Jul 2006 13:55:25 -0000 1.1.1.16 +++ src/modules/proxy/mod_proxy.c 28 Jul 2006 13:56:29 -0000 1.23 @@ -177,6 +177,9 @@ static int proxy_fixup(request_rec *r) { char *url, *p; +#ifdef EAPI + int rc; +#endif /* EAPI */ if (r->proxyreq == NOT_PROXY || strncmp(r->filename, "proxy:", 6) != 0) return DECLINED; @@ -184,6 +187,14 @@ url = &r->filename[6]; /* canonicalise each specific scheme */ +#ifdef EAPI + if (ap_hook_use("ap::mod_proxy::canon", + AP_HOOK_SIG3(int,ptr,ptr), + AP_HOOK_DECLINE(DECLINED), + &rc, r, url) && rc != DECLINED) + return rc; + else +#endif /* EAPI */ if (strncasecmp(url, "http:", 5) == 0) return ap_proxy_http_canon(r, url + 5, "http", DEFAULT_HTTP_PORT); else if (strncasecmp(url, "ftp:", 4) == 0) @@ -199,9 +210,44 @@ static void proxy_init(server_rec *r, pool *p) { ap_proxy_garbage_init(r, p); +#ifdef EAPI + ap_hook_use("ap::mod_proxy::init", + AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, r, p); +#endif } - +#ifdef EAPI +static void proxy_addmod(module *m) +{ + /* export: ap_proxy_http_canon() as `ap::mod_proxy::http::canon' */ + ap_hook_configure("ap::mod_proxy::http::canon", + AP_HOOK_SIG5(int,ptr,ptr,ptr,int), AP_HOOK_TOPMOST); + ap_hook_register("ap::mod_proxy::http::canon", + ap_proxy_http_canon, AP_HOOK_NOCTX); + + /* export: ap_proxy_http_handler() as `ap::mod_proxy::http::handler' */ + ap_hook_configure("ap::mod_proxy::http::handler", + AP_HOOK_SIG6(int,ptr,ptr,ptr,ptr,int), AP_HOOK_TOPMOST); + ap_hook_register("ap::mod_proxy::http::handler", + ap_proxy_http_handler, AP_HOOK_NOCTX); + + /* export: ap_proxyerror() as `ap::mod_proxy::error' */ + ap_hook_configure("ap::mod_proxy::error", + AP_HOOK_SIG3(int,ptr,ptr), AP_HOOK_TOPMOST); + ap_hook_register("ap::mod_proxy::error", + ap_proxyerror, AP_HOOK_NOCTX); + return; +} + +static void proxy_remmod(module *m) +{ + /* remove the hook references */ + ap_hook_unregister("ap::mod_proxy::http::canon", ap_proxy_http_canon); + ap_hook_unregister("ap::mod_proxy::http::handler", ap_proxy_http_handler); + ap_hook_unregister("ap::mod_proxy::error", ap_proxyerror); + return; +} +#endif /* EAPI */ /* Send a redirection if the request contains a hostname which is not */ /* fully qualified, i.e. doesn't have a domain name appended. Some proxy */ @@ -365,6 +411,14 @@ * CONNECT is a special method that bypasses the normal proxy * code. */ +#ifdef EAPI + if (!ap_hook_use("ap::mod_proxy::handler", + AP_HOOK_SIG7(int,ptr,ptr,ptr,ptr,int,ptr), + AP_HOOK_DECLINE(DECLINED), + &rc, r, cr, url, + ents[i].hostname, ents[i].port, + ents[i].protocol) || rc == DECLINED) { +#endif /* EAPI */ if (r->method_number == M_CONNECT) rc = ap_proxy_connect_handler(r, cr, url, ents[i].hostname, ents[i].port); @@ -374,6 +428,9 @@ ents[i].port); else rc = DECLINED; +#ifdef EAPI + } +#endif /* EAPI */ /* an error or success */ if (rc != DECLINED && rc != HTTP_BAD_GATEWAY) @@ -388,6 +445,14 @@ */ /* handle the scheme */ +#ifdef EAPI + if (ap_hook_use("ap::mod_proxy::handler", + AP_HOOK_SIG7(int,ptr,ptr,ptr,ptr,int,ptr), + AP_HOOK_DECLINE(DECLINED), + &rc, r, cr, url, + NULL, 0, scheme) && rc != DECLINED) + return rc; +#endif /* EAPI */ if (r->method_number == M_CONNECT) { return ap_proxy_connect_handler(r, cr, url, NULL, 0); } @@ -985,4 +1050,10 @@ NULL, /* child_init */ NULL, /* child_exit */ proxy_detect /* post read-request */ +#ifdef EAPI + ,proxy_addmod, /* EAPI: add_module */ + proxy_remmod, /* EAPI: remove_module */ + NULL, /* EAPI: rewrite_command */ + NULL /* EAPI: new_connection */ +#endif }; +--------------------------------------------------------------------------- | Add hooks to the HTTP processing to allow other modules | to enhance it by intercepting this processing. +--------------------------------------------------------------------------- Index: src/modules/proxy/proxy_http.c --- src/modules/proxy/proxy_http.c 28 Jul 2006 13:55:25 -0000 1.1.1.20 +++ src/modules/proxy/proxy_http.c 28 Jul 2006 13:56:29 -0000 1.28 @@ -128,6 +128,9 @@ const char *datestr, *urlstr; int result, major, minor; const char *content_length; +#ifdef EAPI + char *peer; +#endif void *sconf = r->server->module_config; proxy_server_conf *conf = @@ -149,6 +152,12 @@ return HTTP_BAD_REQUEST; urlptr += 3; destport = DEFAULT_HTTP_PORT; +#ifdef EAPI + ap_hook_use("ap::mod_proxy::http::handler::set_destport", + AP_HOOK_SIG2(int,ptr), + AP_HOOK_TOPMOST, + &destport, r); +#endif /* EAPI */ strp = strchr(urlptr, '/'); if (strp == NULL) { desthost = ap_pstrdup(p, urlptr); @@ -186,12 +195,18 @@ err = ap_proxy_host2addr(proxyhost, &server_hp); if (err != NULL) return DECLINED; /* try another */ +#ifdef EAPI + peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport); +#endif } else { server.sin_port = htons((unsigned short)destport); err = ap_proxy_host2addr(desthost, &server_hp); if (err != NULL) return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err); +#ifdef EAPI + peer = ap_psprintf(p, "%s:%u", desthost, destport); +#endif } @@ -276,14 +291,42 @@ f = ap_bcreate(p, B_RDWR | B_SOCKET); ap_bpushfd(f, sock, sock); +#ifdef EAPI + { + char *errmsg = NULL; + ap_hook_use("ap::mod_proxy::http::handler::new_connection", + AP_HOOK_SIG4(ptr,ptr,ptr,ptr), + AP_HOOK_DECLINE(NULL), + &errmsg, r, f, peer); + if (errmsg != NULL) + return ap_proxyerror(r, HTTP_BAD_GATEWAY, errmsg); + } +#endif /* EAPI */ + ap_hard_timeout("proxy send", r); ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" CRLF, NULL); +#ifdef EAPI + { + int rc = DECLINED; + ap_hook_use("ap::mod_proxy::http::handler::write_host_header", + AP_HOOK_SIG6(int,ptr,ptr,ptr,int,ptr), + AP_HOOK_DECLINE(DECLINED), + &rc, r, f, desthost, destport, destportstr); + if (rc == DECLINED) { + if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) + ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL); + else + ap_bvputs(f, "Host: ", desthost, CRLF, NULL); + } + } +#else /* EAPI */ /* Send Host: now, adding it to req_hdrs wouldn't be much better */ if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL); else ap_bvputs(f, "Host: ", desthost, CRLF, NULL); +#endif /* EAPI */ if (conf->viaopt == via_block) { /* Block all outgoing Via: headers */ +--------------------------------------------------------------------------- | Add EAPI hooks in module structure for APXS generated samples. +--------------------------------------------------------------------------- Index: src/support/apxs.pl --- src/support/apxs.pl 28 Jul 2006 13:55:24 -0000 1.1.1.15 +++ src/support/apxs.pl 28 Jul 2006 13:56:29 -0000 1.15 @@ -753,5 +753,11 @@ NULL, /* child_init */ NULL, /* child_exit */ NULL /* [#0] post read-request */ +#ifdef EAPI + ,NULL, /* EAPI: add_module */ + NULL, /* EAPI: remove_module */ + NULL, /* EAPI: rewrite_command */ + NULL /* EAPI: new_connection */ +#endif }; +--------------------------------------------------------------------------- | Add the EAPI functions, so the stuff can be built under AIX | and similar braindead platforms as DSO. +--------------------------------------------------------------------------- Index: src/support/httpd.exp --- src/support/httpd.exp 11 May 2004 18:28:26 -0000 1.1.1.13 +++ src/support/httpd.exp 11 May 2004 18:32:16 -0000 1.15 @@ -431,3 +431,59 @@ XML_SetUnparsedEntityDeclHandler XML_SetUserData XML_UseParserAsHandlerArg +ap_add_config_define +ap_make_shared_sub_pool +ap_global_ctx +ap_ctx_new +ap_ctx_get +ap_ctx_set +ap_hook_init +ap_hook_kill +ap_hook_configure +ap_hook_register_I +ap_hook_unregister_I +ap_hook_status +ap_hook_use +ap_hook_call +ap_mm_useable +ap_MM_create +ap_MM_permission +ap_MM_destroy +ap_MM_lock +ap_MM_unlock +ap_MM_malloc +ap_MM_realloc +ap_MM_free +ap_MM_calloc +ap_MM_strdup +ap_MM_sizeof +ap_MM_maxsize +ap_MM_available +ap_MM_error +ap_mm_create +ap_mm_permission +ap_mm_destroy +ap_mm_lock +ap_mm_unlock +ap_mm_malloc +ap_mm_realloc +ap_mm_free +ap_mm_calloc +ap_mm_strdup +ap_mm_sizeof +ap_mm_maxsize +ap_mm_available +ap_mm_error +ap_mm_display_info +ap_mm_core_create +ap_mm_core_permission +ap_mm_core_delete +ap_mm_core_size +ap_mm_core_lock +ap_mm_core_unlock +ap_mm_core_maxsegsize +ap_mm_core_align2page +ap_mm_core_align2word +ap_mm_lib_error_set +ap_mm_lib_error_get +ap_mm_lib_version +--------------------------------------------------------------------------- | Add the EAPI functions, so the stuff can be built under | Windows 95 and similar braindead platforms as DDL. +--------------------------------------------------------------------------- Index: src/ApacheCore.def --- src/ApacheCore.def 11 May 2004 18:28:08 -0000 1.1.1.11 +++ src/ApacheCore.def 11 May 2004 18:32:15 -0000 1.15 @@ -448,3 +448,67 @@ ap_get_chunk_size @440 ap_escape_logitem @441 ap_auth_nonce @442 + + ; EAPI extended symbols + ; note; no ID's, so these all bind by name rather than ordinal since + ; their ordinals would change with symbol changes in the distribution + ap_add_config_define + ap_global_ctx DATA + ap_ctx_new + ap_ctx_get + ap_ctx_overlay + ap_ctx_set + ap_hook_init + ap_hook_kill + ap_hook_configure + ap_hook_register_I + ap_hook_unregister_I + ap_hook_status + ap_hook_use + ap_hook_call + ap_set_callback_and_alarm + ap_acquire_pool + ap_make_shared_sub_pool + ap_release_pool + ap_mm_useable + ap_MM_create + ap_MM_permission + ap_MM_destroy + ap_MM_lock + ap_MM_unlock + ap_MM_malloc + ap_MM_realloc + ap_MM_free + ap_MM_calloc + ap_MM_strdup + ap_MM_sizeof + ap_MM_maxsize + ap_MM_available + ap_MM_error + ap_mm_create + ap_mm_permission + ap_mm_destroy + ap_mm_lock + ap_mm_unlock + ap_mm_malloc + ap_mm_realloc + ap_mm_free + ap_mm_calloc + ap_mm_strdup + ap_mm_sizeof + ap_mm_maxsize + ap_mm_available + ap_mm_error + ap_mm_display_info + ap_mm_core_create + ap_mm_core_permission + ap_mm_core_delete + ap_mm_core_size + ap_mm_core_lock + ap_mm_core_unlock + ap_mm_core_align2page + ap_mm_core_align2word + ap_mm_lib_error_set + ap_mm_lib_error_get + ap_mm_lib_version +