]> granicus.if.org Git - apache/commitdiff
Session cache interface redesign, Part 9:
authorJoe Orton <jorton@apache.org>
Tue, 8 Apr 2008 14:21:24 +0000 (14:21 +0000)
committerJoe Orton <jorton@apache.org>
Tue, 8 Apr 2008 14:21:24 +0000 (14:21 +0000)
Switch mod_ssl to use the ap_socache interface.

* modules/ssl/ssl_scache_shmcb.c, modules/ssl/ssl_scache_memcache.c,
  modules/ssl/ssl_scache_dc.c, modules/ssl/ssl_scache_dbm.c: Remove
  files.

* modules/ssl/mod_ssl.c (modssl_register_scache): Remove function.

* modules/ssl/ssl_private.h: Remove modssl_sesscache_provider etc.
  (SSLModConfigRec): Switch to using socache types.

* modules/ssl/ssl_engine_config.c (ssl_cmd_SSLSessionCache): Switch to
  use socache provider.

* modules/ssl/ssl_engine_mutex.c, modules/ssl/ssl_scache.c: Switch to
  using socache constants.

* modules/ssl/config.m4: Drop distache/memcache configuration, remove
  old objects.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@645940 13f79535-47bb-0310-9956-ffa450edef68

modules/ssl/config.m4
modules/ssl/mod_ssl.c
modules/ssl/ssl_engine_config.c
modules/ssl/ssl_engine_mutex.c
modules/ssl/ssl_private.h
modules/ssl/ssl_scache.c
modules/ssl/ssl_scache_dbm.c [deleted file]
modules/ssl/ssl_scache_dc.c [deleted file]
modules/ssl/ssl_scache_memcache.c [deleted file]
modules/ssl/ssl_scache_shmcb.c [deleted file]

index f95e1d4b27f38b3d82dc25a922718699c8fad62f..841dbf1f6180622c3e6c39f5bb580a170df687bc 100644 (file)
@@ -13,128 +13,6 @@ dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 dnl See the License for the specific language governing permissions and
 dnl limitations under the License.
 
-AC_DEFUN([CHECK_DISTCACHE], [
-  AC_MSG_CHECKING(whether Distcache is required)
-  ap_ssltk_dc="no"
-  tmp_nomessage=""
-  tmp_forced="no"
-  AC_ARG_ENABLE(distcache,
-    APACHE_HELP_STRING(--enable-distcache,Select distcache support in mod_ssl),
-    ap_ssltk_dc="$enableval"
-    tmp_nomessage=""
-    tmp_forced="yes"
-    if test "x$ap_ssltk_dc" = "x"; then
-      ap_ssltk_dc="yes"
-      dnl our "error"s become "tests revealed that..."
-      tmp_forced="no"
-    fi
-    if test "$ap_ssltk_dc" != "yes" -a "$ap_ssltk_dc" != "no"; then
-      tmp_nomessage="--enable-distcache had illegal syntax - disabling"
-      ap_ssltk_dc="no"
-    fi)
-  if test "$tmp_forced" = "no"; then
-    AC_MSG_RESULT($ap_ssltk_dc (default))
-  else
-    AC_MSG_RESULT($ap_ssltk_dc (specified))
-  fi
-  if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno" -a "x$tmp_nomessage" != "x"; then
-    AC_MSG_ERROR(distcache support failed: $tmp_nomessage)
-  fi
-  if test "$ap_ssltk_dc" = "yes"; then
-    AC_CHECK_HEADER(
-      [distcache/dc_client.h],
-      [],
-      [tmp_nomessage="can't include distcache headers"
-      ap_ssltk_dc="no"])
-    if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then
-      AC_MSG_ERROR(distcache support failed: $tmp_nomessage)
-    fi
-  fi
-  if test "$ap_ssltk_dc" = "yes"; then
-    AC_MSG_CHECKING(for Distcache version)
-    AC_TRY_COMPILE(
-[#include <distcache/dc_client.h>],
-[#if DISTCACHE_CLIENT_API != 0x0001
-#error "distcache API version is unrecognised"
-#endif],
-[],
-[tmp_nomessage="distcache has an unsupported API version"
-ap_ssltk_dc="no"])
-    AC_MSG_RESULT($ap_ssltk_dc)
-    if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then
-      AC_MSG_ERROR(distcache support failed: $tmp_nomessage)
-    fi
-  fi
-  if test "$ap_ssltk_dc" = "yes"; then
-    AC_MSG_CHECKING(for Distcache libraries)
-    save_libs=$LIBS
-    LIBS="$LIBS -ldistcache -lnal"
-    AC_TRY_LINK(
-      [#include <distcache/dc_client.h>],
-      [DC_CTX *foo = DC_CTX_new((const char *)0,0);],
-      [],
-      [tmp_no_message="failed to link with distcache libraries"
-      ap_ssltk_dc="no"])
-    LIBS=$save_libs
-    AC_MSG_RESULT($ap_ssltk_dc)
-    if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then
-      AC_MSG_ERROR(distcache support failed: $tmp_nomessage)
-    else
-      APR_ADDTO(MOD_SSL_LDADD, [-ldistcache -lnal])
-      AC_DEFINE(HAVE_DISTCACHE, 1, [Define if distcache support is enabled])
-    fi
-  fi
-])
-
-
-
-AC_DEFUN([CHECK_SSL_MEMCACHE], [
-  AC_MSG_CHECKING(for ssl session caching in memcache)
-  ap_ssltk_mc="no"
-  tmp_nomessage=""
-  tmp_forced="no"
-  AC_ARG_ENABLE(ssl-memcache,
-    APACHE_HELP_STRING(--enable-ssl-memcache,Select memcache support in mod_ssl),
-    ap_ssltk_mc="$enableval"
-    tmp_nomessage=""
-    tmp_forced="yes"
-    if test "x$ap_ssltk_mc" = "x"; then
-      ap_ssltk_mc="yes"
-      dnl our "error"s become "tests revealed that..."
-      tmp_forced="no"
-    fi
-    if test "$ap_ssltk_mc" != "yes" -a "$ap_ssltk_mc" != "no"; then
-      tmp_nomessage="--enable-ssl-cache-memcache had illegal syntax - disabling"
-      ap_ssltk_mc="no"
-    fi)
-  if test "$tmp_forced" = "no"; then
-    AC_MSG_RESULT($ap_ssltk_mc (default))
-  else
-    AC_MSG_RESULT($ap_ssltk_mc (specified))
-  fi
-  if test "$tmp_forced" = "yes" -a "x$ap_ssltk_mc" = "xno" -a "x$tmp_nomessage" != "x"; then
-    AC_MSG_ERROR(ssl memcache support failed: $tmp_nomessage)
-  fi
-  if test "$ap_ssltk_mc" = "yes"; then
-    save_cpp=$CPPFLAGS
-    CPPFLAGS="$CPPFLAGS $APR_INCLUDES $APU_INCLUDES"
-    AC_CHECK_HEADER(
-      [apr_memcache.h],
-      [],
-      [tmp_nomessage="can't include apr_memcache headers"
-      ap_ssltk_mc="no"])
-
-    CPPFLAGS=$save_cpp
-
-    if test "$tmp_forced" = "yes" -a "x$ap_ssltk_mc" = "xno"; then
-      AC_MSG_ERROR(ssl memcache support failed: $tmp_nomessage)
-    fi
-  fi
-  if test "$ap_ssltk_mc" = "yes"; then
-      AC_DEFINE(HAVE_SSL_CACHE_MEMCACHE, 1, [Define if ssl-memcache support is enabled])
-  fi
-])
-
 AC_DEFUN([CHECK_OCSP], [
 AC_CHECK_HEADERS(openssl/ocsp.h, 
   [AC_DEFINE([HAVE_OCSP], 1, [Define if OCSP is supported by OpenSSL])]
@@ -162,10 +40,6 @@ ssl_expr_eval.lo dnl
 ssl_expr_parse.lo dnl
 ssl_expr_scan.lo dnl
 ssl_scache.lo dnl
-ssl_scache_dbm.lo dnl
-ssl_scache_shmcb.lo dnl
-ssl_scache_dc.lo dnl
-ssl_scache_memcache.lo dnl
 ssl_util.lo dnl
 ssl_util_ssl.lo dnl
 ssl_engine_ocsp.lo dnl
@@ -175,8 +49,6 @@ dnl #  hook module into the Autoconf mechanism (--enable-ssl option)
 APACHE_MODULE(ssl, [SSL/TLS support (mod_ssl)], $ssl_objs, , no, [
     APACHE_CHECK_SSL_TOOLKIT
     APR_SETVAR(MOD_SSL_LDADD, [\$(SSL_LIBS)])
-    CHECK_DISTCACHE
-    CHECK_SSL_MEMCACHE
     CHECK_OCSP
     if test "x$enable_ssl" = "xshared"; then
        # The only symbol which needs to be exported is the module
index 379c8274715d48bbb38feb0b9b0566649ac2e47a..43d031d88436ed407634c3ab451fa03033a863ba 100644 (file)
@@ -454,34 +454,6 @@ static int ssl_hook_pre_connection(conn_rec *c, void *csd)
     return ssl_init_ssl_connection(c, NULL);
 }
 
-/* Register all session cache providers. */
-static void modssl_register_scache(apr_pool_t *p)
-{
-    /* shmcb is a cache of many names. */
-    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "shmcb", 
-                         MODSSL_SESSCACHE_PROVIDER_VERSION,
-                         &modssl_sesscache_shmcb);
-    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "shmht", 
-                         MODSSL_SESSCACHE_PROVIDER_VERSION,
-                         &modssl_sesscache_shmcb);
-    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "shm", 
-                         MODSSL_SESSCACHE_PROVIDER_VERSION,
-                         &modssl_sesscache_shmcb);
-    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "dbm",
-                         MODSSL_SESSCACHE_PROVIDER_VERSION,
-                         &modssl_sesscache_dbm);
-#ifdef HAVE_DISTCACHE
-    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "dc",
-                         MODSSL_SESSCACHE_PROVIDER_VERSION,
-                         &modssl_sesscache_dc);
-#endif
-#ifdef HAVE_SSL_CACHE_MEMCACHE
-    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "mc",
-                         MODSSL_SESSCACHE_PROVIDER_VERSION,
-                         &modssl_sesscache_mc);
-#endif
-}
-
 /*
  *  the module registration phase
  */
@@ -512,8 +484,6 @@ static void ssl_register_hooks(apr_pool_t *p)
 
     ssl_var_register(p);
 
-    modssl_register_scache(p);
-
     APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
     APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
 }
index 18acb83c775471c5ac590d590641bf7e5eedddd8..1a9ed212ebd7dc9500e3ef5dd823a0b6f2ab6325 100644 (file)
@@ -985,9 +985,9 @@ const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd,
         char *name = apr_pstrmemdup(cmd->pool, arg, sep - arg);
 
         /* Find the provider of given name. */
-        mc->sesscache = ap_lookup_provider(MODSSL_SESSCACHE_PROVIDER_GROUP,
+        mc->sesscache = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP,
                                            name,
-                                           MODSSL_SESSCACHE_PROVIDER_VERSION);
+                                           AP_SOCACHE_PROVIDER_VERSION);
         if (mc->sesscache) {
             /* Cache found; create it, passing anything beyond the colon. */
             mc->sesscache_mode = enabled_flags;
@@ -1001,8 +1001,8 @@ const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd,
             /* Build a comma-separated list of all registered provider
              * names: */
             name_list = ap_list_provider_names(cmd->pool, 
-                                               MODSSL_SESSCACHE_PROVIDER_GROUP,
-                                               MODSSL_SESSCACHE_PROVIDER_VERSION);
+                                               AP_SOCACHE_PROVIDER_GROUP,
+                                               AP_SOCACHE_PROVIDER_VERSION);
             all_names = apr_array_pstrcat(cmd->pool, name_list, ',');
 
             err = apr_psprintf(cmd->pool, "'%s' session cache not supported "
index 649c324311fefe561d941e74ee505574bd0a2b9a..533a25289df1a1ed88134f4f0acb6945c1f0a8ee 100644 (file)
@@ -43,7 +43,7 @@ int ssl_mutex_init(server_rec *s, apr_pool_t *p)
      * the provider used is not internally multi-process/thread
      * safe. */
     if (!mc->sesscache
-        || (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) == 0) {
+        || (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) == 0) {
         return TRUE;
     }
 
@@ -88,7 +88,7 @@ int ssl_mutex_reinit(server_rec *s, apr_pool_t *p)
     apr_status_t rv;
 
     if (mc->nMutexMode == SSL_MUTEXMODE_NONE || !mc->sesscache
-        || (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) == 0) {
+        || (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) == 0) {
         return TRUE;
     }
 
index a28471403ad984eb04d2421d4acbf4dd6e10e5c2..1bbbcb2ab94c6c063f479380531437bd954d64ef 100644 (file)
 #include "apr_lib.h"
 #include "apr_fnmatch.h"
 #include "apr_strings.h"
-#include "apr_dbm.h"
-#include "apr_rmm.h"
-#include "apr_shm.h"
 #include "apr_global_mutex.h"
 #include "apr_optional.h"
+#include "ap_socache.h"
 
 #define MOD_SSL_VERSION AP_SERVER_BASEREVISION
 
@@ -158,25 +156,6 @@ typedef enum {
  */
 #define SSL_MM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
 
-/**
- * Support for DBM library
- */
-#define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
-
-#if !defined(SSL_DBM_FILE_SUFFIX_DIR) && !defined(SSL_DBM_FILE_SUFFIX_PAG)
-#if defined(DBM_SUFFIX)
-#define SSL_DBM_FILE_SUFFIX_DIR DBM_SUFFIX
-#define SSL_DBM_FILE_SUFFIX_PAG DBM_SUFFIX
-#elif defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM))
-#define SSL_DBM_FILE_SUFFIX_DIR ".db"
-#define SSL_DBM_FILE_SUFFIX_PAG ".db"
-#else
-#define SSL_DBM_FILE_SUFFIX_DIR ".dir"
-#define SSL_DBM_FILE_SUFFIX_PAG ".pag"
-#endif
-#endif
-
-
 /**
  * Define the certificate algorithm types
  */
@@ -351,59 +330,6 @@ typedef struct {
     int non_ssl_request;
 } SSLConnRec;
 
-#define MODSSL_SESSCACHE_PROVIDER_GROUP "mod_ssl-sesscache"
-#define MODSSL_SESSCACHE_PROVIDER_VERSION "0"
-
-/* If this flag is set, the store/retrieve/delete/status interfaces of
- * the provider are NOT safe to be called concurrently from multiple
- * processes or threads, and an external global mutex must be used to
- * serialize access to the provider. */
-#define MODSSL_SESSCACHE_FLAG_NOTMPSAFE (0x0001)
-
-/* Session cache provider vtable. */
-typedef struct {
-    /* Canonical provider name: */
-    const char *name;
-
-    /* Bitmask of MODSSL_SESSCACHE_FLAG_* flags: */
-    unsigned int flags;
-
-    /* Create a session cache based on the given configuration string
-     * ARG.  Returns NULL on success, or an error string on failure.
-     * Pool TMP should be used for any temporary allocations, pool P
-     * should be used for any allocations lasting as long as the
-     * lifetime of the return context.
-     *
-     * The context pointer returned in *CONTEXT will be passed as the
-     * first argument to subsequent invocations. */
-    const char *(*create)(void **context, const char *arg, 
-                          apr_pool_t *tmp, apr_pool_t *p);
-    /* Initialize the cache.  Return APR error code.   */
-    apr_status_t (*init)(void *context, server_rec *s, apr_pool_t *pool);
-    /* Destroy a given cache context. */    
-    void (*destroy)(void *context, server_rec *s);
-    /* Store an object in the cache. */
-    apr_status_t (*store)(void *context, server_rec *s, 
-                          const unsigned char *id, unsigned int idlen, 
-                          time_t expiry, 
-                          unsigned char *data, unsigned int datalen);
-    /* Retrieve cached data with key ID of length IDLEN,
-     * returning TRUE on success or FALSE otherwise.  If
-     * TRUE, the data must be placed in DEST, which has length
-     * on entry of *DESTLEN.  *DESTLEN must be updated to 
-     * equal the length of data written on exit. */
-    apr_status_t (*retrieve)(void *context, server_rec *s,
-                             const unsigned char *id, unsigned int idlen,
-                             unsigned char *dest, unsigned int *destlen,
-                             apr_pool_t *pool);
-    /* Remove an object from the cache. */
-    void (*delete)(void *context, server_rec *s,
-                   const unsigned char *id, unsigned int idlen,
-                   apr_pool_t *pool);
-    /* Dump cache status for mod_status output. */
-    void (*status)(void *context, request_rec *r, int flags);
-} modssl_sesscache_provider;
-
 typedef struct {
     pid_t           pid;
     apr_pool_t     *pPool;
@@ -414,8 +340,8 @@ typedef struct {
 
     /* The configured provider, and associated private data
      * structure. */
-    const modssl_sesscache_provider *sesscache;
-    void *sesscache_context;
+    const ap_socache_provider_t *sesscache;
+    ap_socache_instance_t *sesscache_context;
 
     ssl_mutexmode_t nMutexMode;
     apr_lockmech_e  nMutexMech;
@@ -638,17 +564,6 @@ SSL_SESSION *ssl_scache_retrieve(server_rec *, UCHAR *, int, apr_pool_t *);
 void         ssl_scache_remove(server_rec *, UCHAR *, int,
                                apr_pool_t *);
 
-extern const modssl_sesscache_provider modssl_sesscache_shmcb;
-extern const modssl_sesscache_provider modssl_sesscache_dbm;
-
-#ifdef HAVE_DISTCACHE
-extern const modssl_sesscache_provider modssl_sesscache_dc;
-#endif
-
-#ifdef HAVE_SSL_CACHE_MEMCACHE
-extern const modssl_sesscache_provider modssl_sesscache_mc;
-#endif
-
 /** Proxy Support */
 int ssl_proxy_enable(conn_rec *c);
 int ssl_engine_disable(conn_rec *c);
@@ -732,8 +647,6 @@ apr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer, const cha
 
 void         ssl_var_log_config_register(apr_pool_t *p);
 
-#define APR_SHM_MAXSIZE (64 * 1024 * 1024)
-
 #ifdef HAVE_OCSP
 /* Perform OCSP validation of the current cert in the given context.
  * Returns non-zero on success or zero on failure.  On failure, the
index d096b7b929bf2904258f823bc3ef173750fa45de..120ef0a02782737b4dcf9440c1ba26a53899d74e 100644 (file)
@@ -151,13 +151,13 @@ void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen,
 {
     SSLModConfigRec *mc = myModConfig(s);
 
-    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+    if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) {
         ssl_mutex_on(s);
     }
 
     mc->sesscache->delete(mc->sesscache_context, s, id, idlen, p);
 
-    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+    if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) {
         ssl_mutex_off(s);
     }
 }
diff --git a/modules/ssl/ssl_scache_dbm.c b/modules/ssl/ssl_scache_dbm.c
deleted file mode 100644 (file)
index bbed2fb..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*                      _             _
- *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
- * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
- * | | | | | | (_) | (_| |   \__ \__ \ |
- * |_| |_| |_|\___/ \__,_|___|___/___/_|
- *                      |_____|
- *  ssl_scache_dbm.c
- *  Session Cache via DBM
- */
-
-#include "ssl_private.h"
-
-/* Use of the context structure must be thread-safe after the initial
- * create/init; callers must hold the mutex. */
-struct context {
-    const char *data_file;
-    /* Pool must only be used with the mutex held. */
-    apr_pool_t *pool;
-    time_t last_expiry;
-};
-
-static void ssl_scache_dbm_expire(struct context *ctx, server_rec *s);
-
-static void ssl_scache_dbm_remove(void *context, server_rec *s,
-                                  const unsigned char *id, unsigned int idlen,
-                                  apr_pool_t *p);
-
-static const char *ssl_scache_dbm_create(void **context, const char *arg, 
-                                         apr_pool_t *tmp, apr_pool_t *p)
-{
-    struct context *ctx;
-
-    *context = ctx = apr_pcalloc(p, sizeof *ctx);
-
-    ctx->data_file = ap_server_root_relative(p, arg);
-    if (!ctx->data_file) {
-        return apr_psprintf(tmp, "Invalid cache file path %s", arg);
-    }
-    
-    apr_pool_create(&ctx->pool, p);
-
-    return NULL;
-}
-
-static apr_status_t ssl_scache_dbm_init(void *context, server_rec *s, apr_pool_t *p)
-{
-    struct context *ctx = context;
-    apr_dbm_t *dbm;
-    apr_status_t rv;
-
-    /* for the DBM we need the data file */
-    if (ctx->data_file == NULL) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
-                     "SSLSessionCache required");
-        return APR_EINVAL;
-    }
-
-    /* open it once to create it and to make sure it _can_ be created */
-    apr_pool_clear(ctx->pool);
-
-    if ((rv = apr_dbm_open(&dbm, ctx->data_file,
-            APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                     "Cannot create SSLSessionCache DBM file `%s'",
-                     ctx->data_file);
-        return rv;
-    }
-    apr_dbm_close(dbm);
-
-#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
-    /*
-     * We have to make sure the Apache child processes have access to
-     * the DBM file. But because there are brain-dead platforms where we
-     * cannot exactly determine the suffixes we try all possibilities.
-     */
-    if (geteuid() == 0 /* is superuser */) {
-        chown(ctx->data_file, unixd_config.user_id, -1 /* no gid change */);
-        if (chown(apr_pstrcat(p, ctx->data_file, SSL_DBM_FILE_SUFFIX_DIR, NULL),
-                  unixd_config.user_id, -1) == -1) {
-            if (chown(apr_pstrcat(p, ctx->data_file, ".db", NULL),
-                      unixd_config.user_id, -1) == -1)
-                chown(apr_pstrcat(p, ctx->data_file, ".dir", NULL),
-                      unixd_config.user_id, -1);
-        }
-        if (chown(apr_pstrcat(p, ctx->data_file, SSL_DBM_FILE_SUFFIX_PAG, NULL),
-                  unixd_config.user_id, -1) == -1) {
-            if (chown(apr_pstrcat(p, ctx->data_file, ".db", NULL),
-                      unixd_config.user_id, -1) == -1)
-                chown(apr_pstrcat(p, ctx->data_file, ".pag", NULL),
-                      unixd_config.user_id, -1);
-        }
-    }
-#endif
-    ssl_scache_dbm_expire(ctx, s);
-
-    return APR_SUCCESS;
-}
-
-static void ssl_scache_dbm_kill(void *context, server_rec *s)
-{
-    struct context *ctx = context;
-
-    /* the correct way */
-    unlink(apr_pstrcat(ctx->pool, ctx->data_file, SSL_DBM_FILE_SUFFIX_DIR, NULL));
-    unlink(apr_pstrcat(ctx->pool, ctx->data_file, SSL_DBM_FILE_SUFFIX_PAG, NULL));
-    /* the additional ways to be sure */
-    unlink(apr_pstrcat(ctx->pool, ctx->data_file, ".dir", NULL));
-    unlink(apr_pstrcat(ctx->pool, ctx->data_file, ".pag", NULL));
-    unlink(apr_pstrcat(ctx->pool, ctx->data_file, ".db", NULL));
-    unlink(ctx->data_file);
-
-    return;
-}
-
-static apr_status_t ssl_scache_dbm_store(void *context, server_rec *s, 
-                                         const unsigned char *id, unsigned int idlen,
-                                         time_t expiry, 
-                                         unsigned char *ucaData, unsigned int nData)
-{
-    struct context *ctx = context;
-    apr_dbm_t *dbm;
-    apr_datum_t dbmkey;
-    apr_datum_t dbmval;
-    apr_status_t rv;
-
-    /* be careful: do not try to store too much bytes in a DBM file! */
-#ifdef PAIRMAX
-    if ((idlen + nData) >= PAIRMAX) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "data size too large for DBM session cache: %d >= %d",
-                 (idlen + nData), PAIRMAX);
-        return APR_ENOSPC;
-    }
-#else
-    if ((idlen + nData) >= 950 /* at least less than approx. 1KB */) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "data size too large for DBM session cache: %d >= %d",
-                 (idlen + nData), 950);
-        return APR_ENOSPC;
-    }
-#endif
-
-    /* create DBM key */
-    dbmkey.dptr  = (char *)id;
-    dbmkey.dsize = idlen;
-
-    /* create DBM value */
-    dbmval.dsize = sizeof(time_t) + nData;
-    dbmval.dptr  = (char *)malloc(dbmval.dsize);
-    if (dbmval.dptr == NULL) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "malloc error creating DBM value");
-        return APR_ENOMEM;
-    }
-    memcpy((char *)dbmval.dptr, &expiry, sizeof(time_t));
-    memcpy((char *)dbmval.dptr+sizeof(time_t), ucaData, nData);
-
-    /* and store it to the DBM file */
-    apr_pool_clear(ctx->pool);
-
-    if ((rv = apr_dbm_open(&dbm, ctx->data_file,
-                           APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                     "Cannot open SSLSessionCache DBM file `%s' for writing "
-                     "(store)",
-                     ctx->data_file);
-        free(dbmval.dptr);
-        return rv;
-    }
-    if ((rv = apr_dbm_store(dbm, dbmkey, dbmval)) != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                     "Cannot store SSL session to DBM file `%s'",
-                     ctx->data_file);
-        apr_dbm_close(dbm);
-        free(dbmval.dptr);
-        return rv;
-    }
-    apr_dbm_close(dbm);
-
-    /* free temporary buffers */
-    free(dbmval.dptr);
-
-    /* allow the regular expiring to occur */
-    ssl_scache_dbm_expire(ctx, s);
-
-    return APR_SUCCESS;
-}
-
-static apr_status_t ssl_scache_dbm_retrieve(void *context, server_rec *s, 
-                                            const unsigned char *id, unsigned int idlen,
-                                            unsigned char *dest, unsigned int *destlen,
-                                            apr_pool_t *p)
-{
-    struct context *ctx = context;
-    apr_dbm_t *dbm;
-    apr_datum_t dbmkey;
-    apr_datum_t dbmval;
-    unsigned int nData;
-    time_t expiry;
-    time_t now;
-    apr_status_t rc;
-
-    /* allow the regular expiring to occur */
-    ssl_scache_dbm_expire(ctx, s);
-
-    /* create DBM key and values */
-    dbmkey.dptr  = (char *)id;
-    dbmkey.dsize = idlen;
-
-    /* and fetch it from the DBM file
-     * XXX: Should we open the dbm against r->pool so the cleanup will
-     * do the apr_dbm_close? This would make the code a bit cleaner.
-     */
-    apr_pool_clear(ctx->pool);
-    if ((rc = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, 
-                           SSL_DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rc, s,
-                     "Cannot open SSLSessionCache DBM file `%s' for reading "
-                     "(fetch)",
-                     ctx->data_file);
-        return rc;
-    }
-    rc = apr_dbm_fetch(dbm, dbmkey, &dbmval);
-    if (rc != APR_SUCCESS) {
-        apr_dbm_close(dbm);
-        return rc;
-    }
-    if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t)) {
-        apr_dbm_close(dbm);
-        return rc;
-    }
-
-    /* parse resulting data */
-    nData = dbmval.dsize-sizeof(time_t);
-    if (nData > *destlen) {
-        apr_dbm_close(dbm);
-        return APR_ENOSPC;
-    }    
-
-    *destlen = nData;
-    memcpy(&expiry, dbmval.dptr, sizeof(time_t));
-    memcpy(dest, (char *)dbmval.dptr + sizeof(time_t), nData);
-
-    apr_dbm_close(dbm);
-
-    /* make sure the stuff is still not expired */
-    now = time(NULL);
-    if (expiry <= now) {
-        ssl_scache_dbm_remove(context, s, id, idlen, p);
-        return APR_EGENERAL;
-    }
-
-    return APR_SUCCESS;
-}
-
-static void ssl_scache_dbm_remove(void *context, server_rec *s, 
-                                  const unsigned char *id, unsigned int idlen,
-                                  apr_pool_t *p)
-{
-    struct context *ctx = context;
-    apr_dbm_t *dbm;
-    apr_datum_t dbmkey;
-    apr_status_t rv;
-
-    /* create DBM key and values */
-    dbmkey.dptr  = (char *)id;
-    dbmkey.dsize = idlen;
-
-    /* and delete it from the DBM file */
-    apr_pool_clear(ctx->pool);
-
-    if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, 
-                           SSL_DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                     "Cannot open SSLSessionCache DBM file `%s' for writing "
-                     "(delete)",
-                     ctx->data_file);
-        return;
-    }
-    apr_dbm_delete(dbm, dbmkey);
-    apr_dbm_close(dbm);
-
-    return;
-}
-
-static void ssl_scache_dbm_expire(struct context *ctx, server_rec *s)
-{
-    SSLSrvConfigRec *sc = mySrvConfig(s);
-    apr_dbm_t *dbm;
-    apr_datum_t dbmkey;
-    apr_datum_t dbmval;
-    time_t tExpiresAt;
-    int nElements = 0;
-    int nDeleted = 0;
-    int bDelete;
-    apr_datum_t *keylist;
-    int keyidx;
-    int i;
-    time_t tNow;
-    apr_status_t rv;
-
-    /*
-     * make sure the expiration for still not-accessed session
-     * cache entries is done only from time to time
-     */
-    tNow = time(NULL);
-
-    if (tNow < ctx->last_expiry + sc->session_cache_timeout) {
-        return;
-    }
-
-    ctx->last_expiry = tNow;
-
-    /*
-     * Here we have to be very carefully: Not all DBM libraries are
-     * smart enough to allow one to iterate over the elements and at the
-     * same time delete expired ones. Some of them get totally crazy
-     * while others have no problems. So we have to do it the slower but
-     * more safe way: we first iterate over all elements and remember
-     * those which have to be expired. Then in a second pass we delete
-     * all those expired elements. Additionally we reopen the DBM file
-     * to be really safe in state.
-     */
-
-#define KEYMAX 1024
-
-    for (;;) {
-        /* allocate the key array in a memory sub pool */
-        apr_pool_clear(ctx->pool);
-
-        if ((keylist = apr_palloc(ctx->pool, sizeof(dbmkey)*KEYMAX)) == NULL) {
-            break;
-        }
-
-        /* pass 1: scan DBM database */
-        keyidx = 0;
-        if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE,
-                               SSL_DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) {
-            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                         "Cannot open SSLSessionCache DBM file `%s' for "
-                         "scanning",
-                         ctx->data_file);
-            break;
-        }
-        apr_dbm_firstkey(dbm, &dbmkey);
-        while (dbmkey.dptr != NULL) {
-            nElements++;
-            bDelete = FALSE;
-            apr_dbm_fetch(dbm, dbmkey, &dbmval);
-            if (dbmval.dsize <= sizeof(time_t) || dbmval.dptr == NULL)
-                bDelete = TRUE;
-            else {
-                memcpy(&tExpiresAt, dbmval.dptr, sizeof(time_t));
-                if (tExpiresAt <= tNow)
-                    bDelete = TRUE;
-            }
-            if (bDelete) {
-                if ((keylist[keyidx].dptr = apr_pmemdup(ctx->pool, dbmkey.dptr, dbmkey.dsize)) != NULL) {
-                    keylist[keyidx].dsize = dbmkey.dsize;
-                    keyidx++;
-                    if (keyidx == KEYMAX)
-                        break;
-                }
-            }
-            apr_dbm_nextkey(dbm, &dbmkey);
-        }
-        apr_dbm_close(dbm);
-
-        /* pass 2: delete expired elements */
-        if (apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE,
-                         SSL_DBM_FILE_MODE, ctx->pool) != APR_SUCCESS) {
-            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                         "Cannot re-open SSLSessionCache DBM file `%s' for "
-                         "expiring",
-                         ctx->data_file);
-            break;
-        }
-        for (i = 0; i < keyidx; i++) {
-            apr_dbm_delete(dbm, keylist[i]);
-            nDeleted++;
-        }
-        apr_dbm_close(dbm);
-
-        if (keyidx < KEYMAX)
-            break;
-    }
-
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "Inter-Process Session Cache (DBM) Expiry: "
-                 "old: %d, new: %d, removed: %d",
-                 nElements, nElements-nDeleted, nDeleted);
-}
-
-static void ssl_scache_dbm_status(void *context, request_rec *r, int flags)
-{
-    struct context *ctx = context;
-    apr_dbm_t *dbm;
-    apr_datum_t dbmkey;
-    apr_datum_t dbmval;
-    int nElem;
-    int nSize;
-    int nAverage;
-    apr_status_t rv;
-
-    nElem = 0;
-    nSize = 0;
-
-    apr_pool_clear(ctx->pool);
-    if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, 
-                           SSL_DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-                     "Cannot open SSLSessionCache DBM file `%s' for status "
-                     "retrival",
-                     ctx->data_file);
-        return;
-    }
-    /*
-     * XXX - Check the return value of apr_dbm_firstkey, apr_dbm_fetch - TBD
-     */
-    apr_dbm_firstkey(dbm, &dbmkey);
-    for ( ; dbmkey.dptr != NULL; apr_dbm_nextkey(dbm, &dbmkey)) {
-        apr_dbm_fetch(dbm, dbmkey, &dbmval);
-        if (dbmval.dptr == NULL)
-            continue;
-        nElem += 1;
-        nSize += dbmval.dsize;
-    }
-    apr_dbm_close(dbm);
-    if (nSize > 0 && nElem > 0)
-        nAverage = nSize / nElem;
-    else
-        nAverage = 0;
-    ap_rprintf(r, "cache type: <b>DBM</b>, maximum size: <b>unlimited</b><br>");
-    ap_rprintf(r, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize);
-    ap_rprintf(r, "average session size: <b>%d</b> bytes<br>", nAverage);
-    return;
-}
-
-const modssl_sesscache_provider modssl_sesscache_dbm = {
-    "dbm",
-    MODSSL_SESSCACHE_FLAG_NOTMPSAFE,
-    ssl_scache_dbm_create,
-    ssl_scache_dbm_init,
-    ssl_scache_dbm_kill,
-    ssl_scache_dbm_store,
-    ssl_scache_dbm_retrieve,
-    ssl_scache_dbm_remove,
-    ssl_scache_dbm_status
-};
diff --git a/modules/ssl/ssl_scache_dc.c b/modules/ssl/ssl_scache_dc.c
deleted file mode 100644 (file)
index 086fd41..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*                      _             _
- *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
- * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
- * | | | | | | (_) | (_| |   \__ \__ \ |
- * |_| |_| |_|\___/ \__,_|___|___/___/_|
- *                      |_____|
- *  ssl_scache_dc.c
- *  Distributed Session Cache (client support)
- */
-
-#include "ssl_private.h"
-
-/* Only build this code if it's enabled at configure-time. */
-#ifdef HAVE_DISTCACHE
-
-#include "distcache/dc_client.h"
-
-#if !defined(DISTCACHE_CLIENT_API) || (DISTCACHE_CLIENT_API < 0x0001)
-#error "You must compile with a more recent version of the distcache-base package"
-#endif
-
-/*
- * This cache implementation allows modssl to access 'distcache' servers (or
- * proxies) to facilitate distributed session caching. It is based on code
- * released as open source by Cryptographic Appliances Inc, and was developed by
- * Geoff Thorpe, Steve Robb, and Chris Zimmerman.
- */
-
-/*
-**
-** High-Level "handlers" as per ssl_scache.c
-**
-*/
-
-struct context {
-    /* Configured target server: */
-    const char *target;
-    /* distcache client context: */
-    DC_CTX *dc;
-};
-
-static const char *ssl_scache_dc_create(void **context, const char *arg, 
-                                        apr_pool_t *tmp, apr_pool_t *p)
-{
-    struct context *ctx;
-
-    ctx = *context = apr_palloc(p, sizeof *ctx);
-    
-    ctx->target = apr_pstrdup(p, arg);
-
-    return NULL;
-}
-
-static apr_status_t ssl_scache_dc_init(void *context, server_rec *s, apr_pool_t *p)
-{
-    struct context *ctx = ctx;
-
-#if 0
-    /* If a "persistent connection" mode of operation is preferred, you *must*
-     * also use the PIDCHECK flag to ensure fork()'d processes don't interlace
-     * comms on the same connection as each other. */
-#define SESSION_CTX_FLAGS        SESSION_CTX_FLAG_PERSISTENT | \
-                                 SESSION_CTX_FLAG_PERSISTENT_PIDCHECK | \
-                                 SESSION_CTX_FLAG_PERSISTENT_RETRY | \
-                                 SESSION_CTX_FLAG_PERSISTENT_LATE
-#else
-    /* This mode of operation will open a temporary connection to the 'target'
-     * for each cache operation - this makes it safe against fork()
-     * automatically. This mode is preferred when running a local proxy (over
-     * unix domain sockets) because overhead is negligable and it reduces the
-     * performance/stability danger of file-descriptor bloatage. */
-#define SESSION_CTX_FLAGS        0
-#endif
-    ctx->dc = DC_CTX_new(ctx->target, SESSION_CTX_FLAGS);
-    if (!ctx->dc) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache failed to obtain context");
-        return APR_EGENERAL;
-    }
-    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "distributed scache context initialised");
-
-    return APR_SUCCESS;
-}
-
-static void ssl_scache_dc_kill(void *context, server_rec *s)
-{
-    struct context *ctx = context;
-
-    if (ctx && ctx->dc) {
-        DC_CTX_free(ctx->dc);
-        ctx->dc = NULL;
-    }
-}
-
-static apr_status_t ssl_scache_dc_store(void *context, server_rec *s, 
-                                        const unsigned char *id, unsigned int idlen,
-                                        time_t timeout,
-                                        unsigned char *der, unsigned int der_len)
-{
-    struct context *ctx = context;
-
-    /* !@#$%^ - why do we deal with *absolute* time anyway??? */
-    timeout -= time(NULL);
-    /* Send the serialised session to the distributed cache context */
-    if (!DC_CTX_add_session(ctx->dc, id, idlen, der, der_len,
-                            (unsigned long)timeout * 1000)) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'add_session' failed");
-        return APR_EGENERAL;
-    }
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'add_session' successful");
-    return APR_SUCCESS;
-}
-
-static apr_status_t ssl_scache_dc_retrieve(void *context, server_rec *s, 
-                                           const unsigned char *id, unsigned int idlen,
-                                           unsigned char *dest, unsigned int *destlen,
-                                           apr_pool_t *p)
-{
-    unsigned int data_len;
-    struct context *ctx = context;
-
-    /* Retrieve any corresponding session from the distributed cache context */
-    if (!DC_CTX_get_session(ctx->dc, id, idlen, dest, *destlen, &data_len)) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' MISS");
-        return APR_EGENERAL;
-    }
-    if (data_len > *destlen) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' OVERFLOW");
-        return APR_ENOSPC;
-    }
-    *destlen = data_len;
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' HIT");
-    return APR_SUCCESS;
-}
-
-static void ssl_scache_dc_remove(void *context, server_rec *s, 
-                                 const unsigned char *id, unsigned int idlen, 
-                                 apr_pool_t *p)
-{
-    struct context *ctx = context;
-
-    /* Remove any corresponding session from the distributed cache context */
-    if (!DC_CTX_remove_session(ctx->dc, id, idlen)) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'remove_session' MISS");
-    } else {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'remove_session' HIT");
-    }
-}
-
-static void ssl_scache_dc_status(void *context, request_rec *r, int flags)
-{
-    struct context *ctx = context;
-
-    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                  "distributed scache 'ssl_scache_dc_status'");
-    ap_rprintf(r, "cache type: <b>DC (Distributed Cache)</b>, "
-               " target: <b>%s</b><br>", ctx->target);
-}
-
-const modssl_sesscache_provider modssl_sesscache_dc = {
-    "distcache",
-    0,
-    ssl_scache_dc_create,
-    ssl_scache_dc_init,
-    ssl_scache_dc_kill,
-    ssl_scache_dc_store,
-    ssl_scache_dc_retrieve,
-    ssl_scache_dc_remove,
-    ssl_scache_dc_status
-};
-
-#endif
-
diff --git a/modules/ssl/ssl_scache_memcache.c b/modules/ssl/ssl_scache_memcache.c
deleted file mode 100644 (file)
index f542e07..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements.  See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You under the Apache License, Version 2.0
-* (the "License"); you may not use this file except in compliance with
-* the License.  You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-
-/*                      _             _
- *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
- * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
- * | | | | | | (_) | (_| |   \__ \__ \ |
- * |_| |_| |_|\___/ \__,_|___|___/___/_|
- *                      |_____|
- *  ssl_scache_memcache.c
- *  Distributed Session Cache on top of memcached
- */
-
-#include "ssl_private.h"
-
-#ifdef HAVE_SSL_CACHE_MEMCACHE
-
-#include "apr_memcache.h"
-#include "ap_mpm.h"
-
-/*
- * SSL Session Caching using memcached as a backend.
- */
-
-/*
-**
-** High-Level "handlers" as per ssl_scache.c
-**
-*/
-
-
-/* The underlying apr_memcache system is thread safe.. */
-#define MC_TAG "mod_ssl:"
-#define MC_TAG_LEN \
-    (sizeof(MC_TAG))
-
-#define MC_KEY_LEN 254
-
-#ifndef MC_DEFAULT_SERVER_PORT
-#define MC_DEFAULT_SERVER_PORT 11211
-#endif
-
-
-#ifndef MC_DEFAULT_SERVER_MIN
-#define MC_DEFAULT_SERVER_MIN 0
-#endif
-
-#ifndef MC_DEFAULT_SERVER_SMAX
-#define MC_DEFAULT_SERVER_SMAX 1
-#endif
-
-#ifndef MC_DEFAULT_SERVER_TTL
-#define MC_DEFAULT_SERVER_TTL 600
-#endif
-
-struct context {
-    const char *servers;
-    apr_memcache_t *mc;
-};
-
-static const char *ssl_scache_mc_create(void **context, const char *arg, 
-                                        apr_pool_t *tmp, apr_pool_t *p)
-{
-    struct context *ctx;
-    
-    *context = ctx = apr_palloc(p, sizeof *ctx);
-
-    ctx->servers = apr_pstrdup(p, arg);
-
-    return NULL;
-}
-
-static apr_status_t ssl_scache_mc_init(void *context, server_rec *s, apr_pool_t *p)
-{
-    apr_status_t rv;
-    int thread_limit = 0;
-    int nservers = 0;
-    char *cache_config;
-    char *split;
-    char *tok;
-    struct context *ctx = context;
-
-    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
-
-    /* Find all the servers in the first run to get a total count */
-    cache_config = apr_pstrdup(p, ctx->servers);
-    split = apr_strtok(cache_config, ",", &tok);
-    while (split) {
-        nservers++;
-        split = apr_strtok(NULL,",", &tok);
-    }
-
-    rv = apr_memcache_create(p, nservers, 0, &ctx->mc);
-    if (rv != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
-                     "SSLSessionCache: Failed to create Memcache Object of '%d' size.", 
-                     nservers);
-        return rv;
-    }
-
-    /* Now add each server to the memcache */
-    cache_config = apr_pstrdup(p, ctx->servers);
-    split = apr_strtok(cache_config, ",", &tok);
-    while (split) {
-        apr_memcache_server_t *st;
-        char *host_str;
-        char *scope_id;
-        apr_port_t port;
-
-        rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p);
-        if (rv != APR_SUCCESS) {
-            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
-                         "SSLSessionCache: Failed to Parse Server: '%s'", split);
-            return rv;
-        }
-
-        if (host_str == NULL) {
-            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
-                         "SSLSessionCache: Failed to Parse Server, "
-                         "no hostname specified: '%s'", split);
-            return APR_EINVAL;
-        }
-
-        if (port == 0) {
-            port = MC_DEFAULT_SERVER_PORT;
-        }
-
-        rv = apr_memcache_server_create(p,
-                                        host_str, port,
-                                        MC_DEFAULT_SERVER_MIN,
-                                        MC_DEFAULT_SERVER_SMAX,
-                                        thread_limit,
-                                        MC_DEFAULT_SERVER_TTL,
-                                        &st);
-        if (rv != APR_SUCCESS) {
-            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
-                         "SSLSessionCache: Failed to Create Server: %s:%d", 
-                         host_str, port);
-            return rv;
-        }
-
-        rv = apr_memcache_add_server(ctx->mc, st);
-        if (rv != APR_SUCCESS) {
-            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
-                         "SSLSessionCache: Failed to Add Server: %s:%d", 
-                         host_str, port);
-            return rv;
-        }
-
-        split = apr_strtok(NULL,",", &tok);
-    }
-
-    return APR_SUCCESS;
-}
-
-static void ssl_scache_mc_kill(void *context, server_rec *s)
-{
-    /* noop. */
-}
-
-static char *mc_session_id2sz(const unsigned char *id, unsigned int idlen,
-                              char *str, int strsize)
-{
-    char *cp;
-    int n;
-    int maxlen = (strsize - MC_TAG_LEN)/2;
-
-    cp = apr_cpystrn(str, MC_TAG, MC_TAG_LEN);
-    for (n = 0; n < idlen && n < maxlen; n++) {
-        apr_snprintf(cp, 3, "%02X", (unsigned) id[n]);
-        cp += 2;
-    }
-
-    *cp = '\0';
-
-    return str;
-}
-
-static apr_status_t ssl_scache_mc_store(void *context, server_rec *s, 
-                                        const unsigned char *id, unsigned int idlen,
-                                        time_t timeout,
-                                        unsigned char *ucaData, unsigned int nData)
-{
-    struct context *ctx = context;
-    char buf[MC_KEY_LEN];
-    char *strkey = NULL;
-    apr_status_t rv;
-
-    strkey = mc_session_id2sz(id, idlen, buf, sizeof(buf));
-    if(!strkey) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "scache_mc: Key generation borked.");
-        return APR_EGENERAL;
-    }
-
-    rv = apr_memcache_set(ctx->mc, strkey, (char*)ucaData, nData, timeout, 0);
-
-    if (rv != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
-                     "scache_mc: error setting key '%s' "
-                     "with %d bytes of data", strkey, nData);
-        return rv;
-    }
-
-    return APR_SUCCESS;
-}
-
-static apr_status_t ssl_scache_mc_retrieve(void *context, server_rec *s, 
-                                           const unsigned char *id, unsigned int idlen,
-                                           unsigned char *dest, unsigned int *destlen,
-                                           apr_pool_t *p)
-{
-    struct context *ctx = context;
-    apr_size_t der_len;
-    char buf[MC_KEY_LEN], *der;
-    char *strkey = NULL;
-    apr_status_t rv;
-
-    strkey = mc_session_id2sz(id, idlen, buf, sizeof(buf));
-
-    if (!strkey) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                     "scache_mc: Key generation borked.");
-        return APR_EGENERAL;
-    }
-
-    /* ### this could do with a subpool, but _getp looks like it will
-     * eat memory like it's going out of fashion anyway. */
-
-    rv = apr_memcache_getp(ctx->mc, p, strkey,
-                           &der, &der_len, NULL);
-    if (rv) {
-        if (rv != APR_NOTFOUND) {
-            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                         "scache_mc: 'get_session' FAIL");
-        }
-        return rv;
-    }
-    else if (der_len > *destlen) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                     "scache_mc: 'get_session' OVERFLOW");
-        return rv;
-    }    
-
-    memcpy(dest, der, der_len);
-    *destlen = der_len;
-
-    return APR_SUCCESS;
-}
-
-static void ssl_scache_mc_remove(void *context, server_rec *s, 
-                                 const unsigned char *id, unsigned int idlen,
-                                 apr_pool_t *p)
-{
-    struct context *ctx = context;
-    char buf[MC_KEY_LEN];
-    char* strkey = NULL;
-    apr_status_t rv;
-
-    strkey = mc_session_id2sz(id, idlen, buf, sizeof(buf));
-    if(!strkey) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "scache_mc: Key generation borked.");
-        return;
-    }
-
-    rv = apr_memcache_delete(ctx->mc, strkey, 0);
-
-    if (rv != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s,
-                     "scache_mc: error deleting key '%s' ",
-                     strkey);
-        return;
-    }
-}
-
-static void ssl_scache_mc_status(void *context, request_rec *r, int flags)
-{
-    /* SSLModConfigRec *mc = myModConfig(r->server); */
-    /* TODO: Make a mod_status handler. meh. */
-}
-
-const modssl_sesscache_provider modssl_sesscache_mc = {
-    "memcache",
-    0,
-    ssl_scache_mc_create,
-    ssl_scache_mc_init,
-    ssl_scache_mc_kill,
-    ssl_scache_mc_store,
-    ssl_scache_mc_retrieve,
-    ssl_scache_mc_remove,
-    ssl_scache_mc_status
-};
-#endif
diff --git a/modules/ssl/ssl_scache_shmcb.c b/modules/ssl/ssl_scache_shmcb.c
deleted file mode 100644 (file)
index 6cf5f3f..0000000
+++ /dev/null
@@ -1,833 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*                      _             _
- *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
- * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
- * | | | | | | (_) | (_| |   \__ \__ \ |
- * |_| |_| |_|\___/ \__,_|___|___/___/_|
- *                      |_____|
- *  ssl_scache_shmcb.c
- *  Session Cache via Shared Memory (Cyclic Buffer Variant)
- */
-
-#include "ssl_private.h"
-
-/* 
- * This shared memory based SSL session cache implementation was
- * originally written by Geoff Thorpe <geoff geoffthorpe.net> for C2Net
- * Europe as a contribution to Ralf Engelschall's mod_ssl project.
- *
- * Since rewritten by GT to not use alignment-fudging memcpys and reduce
- * complexity.
- */
-
-/*
- * Header structure - the start of the shared-mem segment
- */
-typedef struct {
-    /* Stats for cache operations */
-    unsigned long stat_stores;
-    unsigned long stat_expiries;
-    unsigned long stat_scrolled;
-    unsigned long stat_retrieves_hit;
-    unsigned long stat_retrieves_miss;
-    unsigned long stat_removes_hit;
-    unsigned long stat_removes_miss;
-    /* Number of subcaches */
-    unsigned int subcache_num;
-    /* How many indexes each subcache's queue has */
-    unsigned int index_num;
-    /* How large each subcache is, including the queue and data */
-    unsigned int subcache_size;
-    /* How far into each subcache the data area is (optimisation) */
-    unsigned int subcache_data_offset;
-    /* How large the data area in each subcache is (optimisation) */
-    unsigned int subcache_data_size;
-} SHMCBHeader;
-
-/* 
- * Subcache structure - the start of each subcache, followed by
- * indexes then data
- */
-typedef struct {
-    /* The start position and length of the cyclic buffer of indexes */
-    unsigned int idx_pos, idx_used;
-    /* Same for the data area */
-    unsigned int data_pos, data_used;
-} SHMCBSubcache;
-
-/* 
- * Index structure - each subcache has an array of these
- */
-typedef struct {
-    /* absolute time this entry expires */
-    time_t expires;
-    /* location within the subcache's data area */
-    unsigned int data_pos;
-    /* size (most logic ignores this, we keep it only to minimise memcpy) */
-    unsigned int data_used;
-    /* length of the used data which contains the id */
-    unsigned int id_len;
-    /* Used to mark explicitly-removed sessions */
-    unsigned char removed;
-} SHMCBIndex;
-
-struct context {
-    const char *data_file;
-    apr_size_t shm_size;
-    apr_shm_t *shm;
-    SHMCBHeader *header;
-};
-
-/* The SHM data segment is of fixed size and stores data as follows.
- *
- *   [ SHMCBHeader | Subcaches ]
- *
- * The SHMCBHeader header structure stores metadata concerning the
- * cache and the contained subcaches.
- *
- * Subcaches is a hash table of header->subcache_num SHMCBSubcache
- * structures.  The hash table is indexed by SHMCB_MASK(id). Each
- * SHMCBSubcache structure has a fixed size (header->subcache_size),
- * which is determined at creation time, and looks like the following:
- *
- *   [ SHMCBSubcache | Indexes | Data ]
- *
- * Each subcache is prefixed by the SHMCBSubcache structure.
- *
- * The subcache's "Data" segment is a single cyclic data buffer, of
- * total size header->subcache_data_size; data inside is referenced
- * using byte offsets. The offset marking the beginning of the cyclic
- * buffer is subcache->data_pos the buffer's length is
- * subcache->data_used.
- *
- * "Indexes" is an array of header->index_num SHMCBIndex structures,
- * which is used as a cyclic queue; subcache->idx_pos gives the array
- * index of the first in use, subcache->idx_used gives the number in
- * use.  Both ->idx_* values have a range of [0, header->index_num)
- *
- * Each in-use SHMCBIndex structure represents a single SSL session.
- * The ID and data segment are stored consecutively in the subcache's
- * cyclic data buffer.  The "Data" segment can thus be seen to 
- * look like this, for example
- *
- * offset:  [ 0     1     2     3     4     5     6    ...
- * contents:[ ID1   Data1       ID2   Data2       ID3  ...
- *
- * where the corresponding indices would look like:
- *
- * idx1 = { data_pos = 0, data_used = 3, id_len = 1, ...}
- * idx2 = { data_pos = 3, data_used = 3, id_len = 1, ...}
- * ...
- */
-
-/* This macro takes a pointer to the header and a zero-based index and returns
- * a pointer to the corresponding subcache. */
-#define SHMCB_SUBCACHE(pHeader, num) \
-                (SHMCBSubcache *)(((unsigned char *)(pHeader)) + \
-                        sizeof(SHMCBHeader) + \
-                        (num) * ((pHeader)->subcache_size))
-
-/* This macro takes a pointer to the header and a session id and returns a
- * pointer to the corresponding subcache. */
-#define SHMCB_MASK(pHeader, id) \
-                SHMCB_SUBCACHE((pHeader), *(id) & ((pHeader)->subcache_num - 1))
-
-/* This macro takes the same params as the last, generating two outputs for use
- * in ap_log_error(...). */
-#define SHMCB_MASK_DBG(pHeader, id) \
-                *(id), (*(id) & ((pHeader)->subcache_num - 1))
-
-/* This macro takes a pointer to a subcache and a zero-based index and returns
- * a pointer to the corresponding SHMCBIndex. */
-#define SHMCB_INDEX(pSubcache, num) \
-                ((SHMCBIndex *)(((unsigned char *)pSubcache) + \
-                                sizeof(SHMCBSubcache)) + num)
-
-/* This macro takes a pointer to the header and a subcache and returns a
- * pointer to the corresponding data area. */
-#define SHMCB_DATA(pHeader, pSubcache) \
-                ((unsigned char *)(pSubcache) + (pHeader)->subcache_data_offset)
-
-/*
- * Cyclic functions - assists in "wrap-around"/modulo logic
- */
-
-/* Addition modulo 'mod' */
-#define SHMCB_CYCLIC_INCREMENT(val,inc,mod) \
-                (((val) + (inc)) % (mod))
-
-/* Subtraction (or "distance between") modulo 'mod' */
-#define SHMCB_CYCLIC_SPACE(val1,val2,mod) \
-                ((val2) >= (val1) ? ((val2) - (val1)) : \
-                        ((val2) + (mod) - (val1)))
-
-/* A "normal-to-cyclic" memcpy. */
-static void shmcb_cyclic_ntoc_memcpy(unsigned int buf_size, unsigned char *data,
-                                     unsigned int dest_offset, const unsigned char *src,
-                                     unsigned int src_len)
-{
-    if (dest_offset + src_len < buf_size)
-        /* It be copied all in one go */
-        memcpy(data + dest_offset, src, src_len);
-    else {
-        /* Copy the two splits */
-        memcpy(data + dest_offset, src, buf_size - dest_offset);
-        memcpy(data, src + buf_size - dest_offset,
-               src_len + dest_offset - buf_size);
-    }
-}
-
-/* A "cyclic-to-normal" memcpy. */
-static void shmcb_cyclic_cton_memcpy(unsigned int buf_size, unsigned char *dest,
-                                     const unsigned char *data, unsigned int src_offset,
-                                     unsigned int src_len)
-{
-    if (src_offset + src_len < buf_size)
-        /* It be copied all in one go */
-        memcpy(dest, data + src_offset, src_len);
-    else {
-        /* Copy the two splits */
-        memcpy(dest, data + src_offset, buf_size - src_offset);
-        memcpy(dest + buf_size - src_offset, data,
-               src_len + src_offset - buf_size);
-    }
-}
-
-/* A memcmp against a cyclic data buffer.  Compares SRC of length
- * SRC_LEN against the contents of cyclic buffer DATA (which is of
- * size BUF_SIZE), starting at offset DEST_OFFSET. Got that?  Good. */
-static int shmcb_cyclic_memcmp(unsigned int buf_size, unsigned char *data,
-                               unsigned int dest_offset, 
-                               const unsigned char *src,
-                               unsigned int src_len)
-{
-    if (dest_offset + src_len < buf_size)
-        /* It be compared all in one go */
-        return memcmp(data + dest_offset, src, src_len);
-    else {
-        /* Compare the two splits */
-        int diff;
-        
-        diff = memcmp(data + dest_offset, src, buf_size - dest_offset);
-        if (diff) {
-            return diff;
-        }
-        return memcmp(data, src + buf_size - dest_offset,
-                      src_len + dest_offset - buf_size);
-    }
-}
-
-
-/* Prototypes for low-level subcache operations */
-static void shmcb_subcache_expire(server_rec *, SHMCBHeader *, SHMCBSubcache *);
-/* Returns zero on success, non-zero on failure. */   
-static int shmcb_subcache_store(server_rec *s, SHMCBHeader *header,
-                                SHMCBSubcache *subcache, 
-                                unsigned char *data, unsigned int data_len,
-                                const unsigned char *id, unsigned int id_len,
-                                time_t expiry);
-/* Returns zero on success, non-zero on failure. */   
-static int shmcb_subcache_retrieve(server_rec *, SHMCBHeader *, SHMCBSubcache *,
-                                   const unsigned char *id, unsigned int idlen,
-                                   unsigned char *data, unsigned int *datalen);
-/* Returns zero on success, non-zero on failure. */   
-static int shmcb_subcache_remove(server_rec *, SHMCBHeader *, SHMCBSubcache *,
-                                 const unsigned char *, unsigned int);
-
-/*
- * High-Level "handlers" as per ssl_scache.c
- * subcache internals are deferred to shmcb_subcache_*** functions lower down
- */
-
-static const char *ssl_scache_shmcb_create(void **context, const char *arg, 
-                                           apr_pool_t *tmp, apr_pool_t *p)
-{
-    struct context *ctx;
-    char *path, *cp, *cp2;
-
-    /* Allocate the context. */
-    *context = ctx = apr_pcalloc(p, sizeof *ctx);
-    
-    ctx->data_file = path = ap_server_root_relative(p, arg);
-    ctx->shm_size  = 1024*512; /* 512KB */
-
-    cp = strchr(path, '(');
-    if (cp) {
-        *cp++ = NUL;
-
-        if (!(cp2 = strchr(cp, ')'))) {
-            return "Invalid argument: no closing parenthesis";
-        }
-            
-        *cp2 = NUL;
-        
-        ctx->shm_size = atoi(cp);
-        
-        if (ctx->shm_size < 8192) {
-            return "Invalid argument: size has to be >= 8192 bytes";
-            
-        }
-        
-        if (ctx->shm_size >= APR_SHM_MAXSIZE) {
-            return apr_psprintf(tmp,
-                                "Invalid argument: size has "
-                                "to be < %d bytes on this platform", 
-                                APR_SHM_MAXSIZE);
-            
-        }
-    }
-
-    return NULL;
-}
-
-static apr_status_t ssl_scache_shmcb_init(void *context, server_rec *s, apr_pool_t *p)
-{
-    void *shm_segment;
-    apr_size_t shm_segsize;
-    apr_status_t rv;
-    SHMCBHeader *header;
-    unsigned int num_subcache, num_idx, loop;
-    struct context *ctx = context;
-
-    /* Create shared memory segment */
-    if (ctx->data_file == NULL) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
-                     "SSLSessionCache required");
-        return APR_EINVAL;
-    }
-
-    /* Use anonymous shm by default, fall back on name-based. */
-    rv = apr_shm_create(&ctx->shm, ctx->shm_size, NULL, p);
-    if (APR_STATUS_IS_ENOTIMPL(rv)) {
-        /* For a name-based segment, remove it first in case of a
-         * previous unclean shutdown. */
-        apr_shm_remove(ctx->data_file, p);
-
-        rv = apr_shm_create(&ctx->shm, ctx->shm_size, ctx->data_file, p);
-    }
-
-    if (rv != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-                     "could not allocate shared memory for shmcb "
-                     "session cache");
-        return rv;
-    }
-
-    shm_segment = apr_shm_baseaddr_get(ctx->shm);
-    shm_segsize = apr_shm_size_get(ctx->shm);
-    if (shm_segsize < (5 * sizeof(SHMCBHeader))) {
-        /* the segment is ridiculously small, bail out */
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
-                     "shared memory segment too small");
-        return APR_ENOSPC;
-    }
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "shmcb_init allocated %" APR_SIZE_T_FMT
-                 " bytes of shared memory",
-                 shm_segsize);
-    /* Discount the header */
-    shm_segsize -= sizeof(SHMCBHeader);
-    /* Select the number of subcaches to create and how many indexes each
-     * should contain based on the size of the memory (the header has already
-     * been subtracted). Typical non-client-auth sslv3/tlsv1 sessions are
-     * around 180 bytes (148 bytes data and 32 bytes for the id), so
-     * erring to division by 150 helps ensure we would exhaust data
-     * storage before index storage (except sslv2, where it's
-     * *slightly* the other way). From there, we select the number of
-     * subcaches to be a power of two, such that the number of indexes
-     * per subcache at least twice the number of subcaches. */
-    num_idx = (shm_segsize) / 150;
-    num_subcache = 256;
-    while ((num_idx / num_subcache) < (2 * num_subcache))
-        num_subcache /= 2;
-    num_idx /= num_subcache;
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "for %" APR_SIZE_T_FMT " bytes (%" APR_SIZE_T_FMT 
-                 " including header), recommending %u subcaches, "
-                 "%u indexes each", shm_segsize,
-                 shm_segsize + sizeof(SHMCBHeader), num_subcache, num_idx);
-    if (num_idx < 5) {
-        /* we're still too small, bail out */
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
-                     "shared memory segment too small");
-        return APR_ENOSPC;
-    }
-    /* OK, we're sorted */
-    ctx->header = header = shm_segment;
-    header->stat_stores = 0;
-    header->stat_expiries = 0;
-    header->stat_scrolled = 0;
-    header->stat_retrieves_hit = 0;
-    header->stat_retrieves_miss = 0;
-    header->stat_removes_hit = 0;
-    header->stat_removes_miss = 0;
-    header->subcache_num = num_subcache;
-    /* Convert the subcache size (in bytes) to a value that is suitable for
-     * structure alignment on the host platform, by rounding down if necessary.
-     * This assumes that sizeof(unsigned long) provides an appropriate
-     * alignment unit.  */
-    header->subcache_size = ((size_t)(shm_segsize / num_subcache) &
-                             ~(size_t)(sizeof(unsigned long) - 1));
-    header->subcache_data_offset = sizeof(SHMCBSubcache) +
-                                   num_idx * sizeof(SHMCBIndex);
-    header->subcache_data_size = header->subcache_size -
-                                 header->subcache_data_offset;
-    header->index_num = num_idx;
-
-    /* Output trace info */
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "shmcb_init_memory choices follow");
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "subcache_num = %u", header->subcache_num);
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "subcache_size = %u", header->subcache_size);
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "subcache_data_offset = %u", header->subcache_data_offset);
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "subcache_data_size = %u", header->subcache_data_size);
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "index_num = %u", header->index_num);
-    /* The header is done, make the caches empty */
-    for (loop = 0; loop < header->subcache_num; loop++) {
-        SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop);
-        subcache->idx_pos = subcache->idx_used = 0;
-        subcache->data_pos = subcache->data_used = 0;
-    }
-    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
-                 "Shared memory session cache initialised");
-    /* Success ... */
-
-    return APR_SUCCESS;
-}
-
-static void ssl_scache_shmcb_kill(void *context, server_rec *s)
-{
-    struct context *ctx = context;
-
-    if (ctx && ctx->shm) {
-        apr_shm_destroy(ctx->shm);
-        ctx->shm = NULL;
-    }
-}
-
-static apr_status_t ssl_scache_shmcb_store(void *context, server_rec *s, 
-                                           const unsigned char *id, unsigned int idlen,
-                                           time_t timeout, 
-                                           unsigned char *encoded,
-                                           unsigned int len_encoded)
-{
-    struct context *ctx = context;
-    SHMCBHeader *header = ctx->header;
-    SHMCBSubcache *subcache = SHMCB_MASK(header, id);
-
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "ssl_scache_shmcb_store (0x%02x -> subcache %d)",
-                 SHMCB_MASK_DBG(header, id));
-    if (idlen < 4) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided "
-                "(%u bytes)", idlen);
-        return APR_EINVAL;
-    }
-    if (shmcb_subcache_store(s, header, subcache, encoded,
-                             len_encoded, id, idlen, timeout)) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
-                     "can't store a session!");
-        return APR_ENOSPC;
-    }
-    header->stat_stores++;
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "leaving ssl_scache_shmcb_store successfully");
-    return APR_SUCCESS;
-}
-
-static apr_status_t ssl_scache_shmcb_retrieve(void *context, server_rec *s, 
-                                              const unsigned char *id, unsigned int idlen,
-                                              unsigned char *dest, unsigned int *destlen,
-                                              apr_pool_t *p)
-{
-    struct context *ctx = context;
-    SHMCBHeader *header = ctx->header;
-    SHMCBSubcache *subcache = SHMCB_MASK(header, id);
-    int rv;
-
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "ssl_scache_shmcb_retrieve (0x%02x -> subcache %d)",
-                 SHMCB_MASK_DBG(header, id));
-
-    /* Get the session corresponding to the session_id, if it exists. */
-    rv = shmcb_subcache_retrieve(s, header, subcache, id, idlen,
-                                 dest, destlen);
-    if (rv == 0)
-        header->stat_retrieves_hit++;
-    else
-        header->stat_retrieves_miss++;
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "leaving ssl_scache_shmcb_retrieve successfully");
-
-    return rv == 0 ? APR_SUCCESS : APR_EGENERAL;
-}
-
-static void ssl_scache_shmcb_remove(void *context, server_rec *s, 
-                                    const unsigned char *id, unsigned int idlen,
-                                    apr_pool_t *p)
-{
-    struct context *ctx = context;
-    SHMCBHeader *header = ctx->header;
-    SHMCBSubcache *subcache = SHMCB_MASK(header, id);
-
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "ssl_scache_shmcb_remove (0x%02x -> subcache %d)",
-                 SHMCB_MASK_DBG(header, id));
-    if (idlen < 4) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided "
-                "(%u bytes)", idlen);
-        return;
-    }
-    if (shmcb_subcache_remove(s, header, subcache, id, idlen))
-        header->stat_removes_hit++;
-    else
-        header->stat_removes_miss++;
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "leaving ssl_scache_shmcb_remove successfully");
-}
-
-static void ssl_scache_shmcb_status(void *context, request_rec *r, int flags)
-{
-    server_rec *s = r->server;
-    struct context *ctx = context;
-    SHMCBHeader *header = ctx->header;
-    unsigned int loop, total = 0, cache_total = 0, non_empty_subcaches = 0;
-    time_t idx_expiry, min_expiry = 0, max_expiry = 0, average_expiry = 0;
-    time_t now = time(NULL);
-    double expiry_total = 0;
-    int index_pct, cache_pct;
-
-    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "inside shmcb_status");
-    /* Perform the iteration inside the mutex to avoid corruption or invalid
-     * pointer arithmetic. The rest of our logic uses read-only header data so
-     * doesn't need the lock. */
-    /* Iterate over the subcaches */
-    for (loop = 0; loop < header->subcache_num; loop++) {
-        SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop);
-        shmcb_subcache_expire(s, header, subcache);
-        total += subcache->idx_used;
-        cache_total += subcache->data_used;
-        if (subcache->idx_used) {
-            SHMCBIndex *idx = SHMCB_INDEX(subcache, subcache->idx_pos);
-            non_empty_subcaches++;
-            idx_expiry = idx->expires;
-            expiry_total += (double)idx_expiry;
-            max_expiry = ((idx_expiry > max_expiry) ? idx_expiry : max_expiry);
-            if (!min_expiry)
-                min_expiry = idx_expiry;
-            else
-                min_expiry = ((idx_expiry < min_expiry) ? idx_expiry : min_expiry);
-        }
-    }
-    index_pct = (100 * total) / (header->index_num *
-                                 header->subcache_num);
-    cache_pct = (100 * cache_total) / (header->subcache_data_size *
-                                       header->subcache_num);
-    /* Generate HTML */
-    ap_rprintf(r, "cache type: <b>SHMCB</b>, shared memory: <b>%" APR_SIZE_T_FMT "</b> "
-               "bytes, current sessions: <b>%d</b><br>",
-               ctx->shm_size, total);
-    ap_rprintf(r, "subcaches: <b>%d</b>, indexes per subcache: <b>%d</b><br>",
-               header->subcache_num, header->index_num);
-    if (non_empty_subcaches) {
-        average_expiry = (time_t)(expiry_total / (double)non_empty_subcaches);
-        ap_rprintf(r, "time left on oldest entries' SSL sessions: ");
-        if (now < average_expiry)
-            ap_rprintf(r, "avg: <b>%d</b> seconds, (range: %d...%d)<br>",
-                       (int)(average_expiry - now),
-                       (int)(min_expiry - now),
-                       (int)(max_expiry - now));
-        else
-            ap_rprintf(r, "expiry_threshold: <b>Calculation error!</b><br>");
-    }
-
-    ap_rprintf(r, "index usage: <b>%d%%</b>, cache usage: <b>%d%%</b><br>",
-               index_pct, cache_pct);
-    ap_rprintf(r, "total sessions stored since starting: <b>%lu</b><br>",
-               header->stat_stores);
-    ap_rprintf(r, "total sessions expired since starting: <b>%lu</b><br>",
-               header->stat_expiries);
-    ap_rprintf(r, "total (pre-expiry) sessions scrolled out of the cache: "
-               "<b>%lu</b><br>", header->stat_scrolled);
-    ap_rprintf(r, "total retrieves since starting: <b>%lu</b> hit, "
-               "<b>%lu</b> miss<br>", header->stat_retrieves_hit,
-               header->stat_retrieves_miss);
-    ap_rprintf(r, "total removes since starting: <b>%lu</b> hit, "
-               "<b>%lu</b> miss<br>", header->stat_removes_hit,
-               header->stat_removes_miss);
-    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "leaving shmcb_status");
-}
-
-/*
- * Subcache-level cache operations 
- */
-
-static void shmcb_subcache_expire(server_rec *s, SHMCBHeader *header,
-                                  SHMCBSubcache *subcache)
-{
-    time_t now = time(NULL);
-    unsigned int loop = 0;
-    unsigned int new_idx_pos = subcache->idx_pos;
-    SHMCBIndex *idx = NULL;
-
-    while (loop < subcache->idx_used) {
-        idx = SHMCB_INDEX(subcache, new_idx_pos);
-        if (idx->expires > now)
-            /* it hasn't expired yet, we're done iterating */
-            break;
-        loop++;
-        new_idx_pos = SHMCB_CYCLIC_INCREMENT(new_idx_pos, 1, header->index_num);
-    }
-    if (!loop)
-        /* Nothing to do */
-        return;
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "will be expiring %u sessions", loop);
-    if (loop == subcache->idx_used) {
-        /* We're expiring everything, piece of cake */
-        subcache->idx_used = 0;
-        subcache->data_used = 0;
-    } else {
-        /* There remain other indexes, so we can use idx to adjust 'data' */
-        unsigned int diff = SHMCB_CYCLIC_SPACE(subcache->data_pos,
-                                               idx->data_pos,
-                                               header->subcache_data_size);
-        /* Adjust the indexes */
-        subcache->idx_used -= loop;
-        subcache->idx_pos = new_idx_pos;
-        /* Adjust the data area */
-        subcache->data_used -= diff;
-        subcache->data_pos = idx->data_pos;
-    }
-    header->stat_expiries += loop;
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "we now have %u sessions", subcache->idx_used);
-}
-
-static int shmcb_subcache_store(server_rec *s, SHMCBHeader *header,
-                                SHMCBSubcache *subcache, 
-                                unsigned char *data, unsigned int data_len,
-                                const unsigned char *id, unsigned int id_len,
-                                time_t expiry)
-{
-    unsigned int data_offset, new_idx, id_offset;
-    SHMCBIndex *idx;
-    unsigned int total_len = id_len + data_len;
-
-    /* Sanity check the input */
-    if (total_len > header->subcache_data_size) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
-                     "inserting session larger (%d) than subcache data area (%d)",
-                     total_len, header->subcache_data_size);
-        return -1;
-    }
-
-    /* If there are entries to expire, ditch them first. */
-    shmcb_subcache_expire(s, header, subcache);
-
-    /* Loop until there is enough space to insert */
-    if (header->subcache_data_size - subcache->data_used < total_len
-        || subcache->idx_used == header->index_num) {
-        unsigned int loop = 0;
-
-        idx = SHMCB_INDEX(subcache, subcache->idx_pos);
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                     "about to force-expire, subcache: idx_used=%d, "
-                     "data_used=%d", subcache->idx_used, subcache->data_used);
-        do {
-            SHMCBIndex *idx2;
-
-            /* Adjust the indexes by one */
-            subcache->idx_pos = SHMCB_CYCLIC_INCREMENT(subcache->idx_pos, 1,
-                                                       header->index_num);
-            subcache->idx_used--;
-            if (!subcache->idx_used) {
-                /* There's nothing left */
-                subcache->data_used = 0;
-                break;
-            }
-            /* Adjust the data */
-            idx2 = SHMCB_INDEX(subcache, subcache->idx_pos);
-            subcache->data_used -= SHMCB_CYCLIC_SPACE(idx->data_pos, idx2->data_pos,
-                                                      header->subcache_data_size);
-            subcache->data_pos = idx2->data_pos;
-            /* Stats */
-            header->stat_scrolled++;
-            /* Loop admin */
-            idx = idx2;
-            loop++;
-        } while (header->subcache_data_size - subcache->data_used < total_len);
-
-        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                     "finished force-expire, subcache: idx_used=%d, "
-                     "data_used=%d", subcache->idx_used, subcache->data_used);
-    }
-
-    /* HERE WE ASSUME THAT THE NEW SESSION SHOULD GO ON THE END! I'M NOT
-     * CHECKING WHETHER IT SHOULD BE GENUINELY "INSERTED" SOMEWHERE.
-     *
-     * We either fix that, or find out at a "higher" (read "mod_ssl")
-     * level whether it is possible to have distinct session caches for
-     * any attempted tomfoolery to do with different session timeouts.
-     * Knowing in advance that we can have a cache-wide constant timeout
-     * would make this stuff *MUCH* more efficient. Mind you, it's very
-     * efficient right now because I'm ignoring this problem!!!
-     */
-    /* Insert the id */
-    id_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used,
-                                       header->subcache_data_size);
-    shmcb_cyclic_ntoc_memcpy(header->subcache_data_size,
-                             SHMCB_DATA(header, subcache), id_offset,
-                             id, id_len);
-    subcache->data_used += id_len;
-    /* Insert the data */
-    data_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used,
-                                         header->subcache_data_size);
-    shmcb_cyclic_ntoc_memcpy(header->subcache_data_size,
-                             SHMCB_DATA(header, subcache), data_offset,
-                             data, data_len);
-    subcache->data_used += data_len;
-    /* Insert the index */
-    new_idx = SHMCB_CYCLIC_INCREMENT(subcache->idx_pos, subcache->idx_used,
-                                     header->index_num);
-    idx = SHMCB_INDEX(subcache, new_idx);
-    idx->expires = expiry;
-    idx->data_pos = id_offset;
-    idx->data_used = total_len;
-    idx->id_len = id_len;
-    idx->removed = 0;
-    subcache->idx_used++;
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "insert happened at idx=%d, data=(%u:%u)", new_idx, 
-                 id_offset, data_offset);
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "finished insert, subcache: idx_pos/idx_used=%d/%d, "
-                 "data_pos/data_used=%d/%d",
-                 subcache->idx_pos, subcache->idx_used,
-                 subcache->data_pos, subcache->data_used);
-    return 0;
-}
-
-static int shmcb_subcache_retrieve(server_rec *s, SHMCBHeader *header,
-                                   SHMCBSubcache *subcache, 
-                                   const unsigned char *id, unsigned int idlen,
-                                   unsigned char *dest, unsigned int *destlen)
-{
-    unsigned int pos;
-    unsigned int loop = 0;
-
-    /* If there are entries to expire, ditch them first. */
-    shmcb_subcache_expire(s, header, subcache);
-    pos = subcache->idx_pos;
-
-    while (loop < subcache->idx_used) {
-        SHMCBIndex *idx = SHMCB_INDEX(subcache, pos);
-
-        /* Only consider 'idx' if the id matches, and the "removed"
-         * flag isn't set; check the data length too to avoid a buffer
-         * overflow in case of corruption, which should be impossible,
-         * but it's cheap to be safe. */
-        if (!idx->removed
-            && idx->id_len == idlen && (idx->data_used - idx->id_len) < *destlen
-            && shmcb_cyclic_memcmp(header->subcache_data_size,
-                                   SHMCB_DATA(header, subcache),
-                                   idx->data_pos, id, idx->id_len) == 0) {
-            unsigned int data_offset;
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                         "match at idx=%d, data=%d", pos, idx->data_pos);
-
-            /* Find the offset of the data segment, after the id */
-            data_offset = SHMCB_CYCLIC_INCREMENT(idx->data_pos, 
-                                                 idx->id_len,
-                                                 header->subcache_data_size);
-
-            *destlen = idx->data_used - idx->id_len;
-
-            /* Copy out the data */
-            shmcb_cyclic_cton_memcpy(header->subcache_data_size,
-                                     dest, SHMCB_DATA(header, subcache),
-                                     data_offset, *destlen);
-
-            return 0;
-        }
-        /* Increment */
-        loop++;
-        pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num);
-    }
-
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "shmcb_subcache_retrieve found no match");
-    return -1;
-
-}
-
-static int shmcb_subcache_remove(server_rec *s, SHMCBHeader *header,
-                                 SHMCBSubcache *subcache,
-                                 const unsigned char *id, unsigned int idlen)
-{
-    unsigned int pos;
-    unsigned int loop = 0;
-
-    /* Unlike the others, we don't do an expire-run first. This is to keep
-     * consistent statistics where a "remove" operation may actually be the
-     * higher layer spotting an expiry issue prior to us. Our caller is
-     * handling stats, so a failure return would be inconsistent if the
-     * intended session was in fact removed by an expiry run. */
-
-    pos = subcache->idx_pos;
-    while (loop < subcache->idx_used) {
-        SHMCBIndex *idx = SHMCB_INDEX(subcache, pos);
-
-        /* Only consider 'idx' if the id matches, and the "removed"
-         * flag isn't set. */
-        if (!idx->removed && idx->id_len == idlen
-            && shmcb_cyclic_memcmp(header->subcache_data_size,
-                                   SHMCB_DATA(header, subcache),
-                                   idx->data_pos, id, idx->id_len) == 0) {
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                         "possible match at idx=%d, data=%d", pos, idx->data_pos);
-            /* Found the matching session, remove it quietly. */
-            idx->removed = 1;
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                             "shmcb_subcache_remove removing matching session");
-            return 0;
-        }
-        /* Increment */
-        loop++;
-        pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num);
-    }
-
-    return -1; /* failure */
-}
-
-const modssl_sesscache_provider modssl_sesscache_shmcb = {
-    "shmcb",
-    MODSSL_SESSCACHE_FLAG_NOTMPSAFE,
-    ssl_scache_shmcb_create,
-    ssl_scache_shmcb_init,
-    ssl_scache_shmcb_kill,
-    ssl_scache_shmcb_store,
-    ssl_scache_shmcb_retrieve,
-    ssl_scache_shmcb_remove,
-    ssl_scache_shmcb_status
-};