summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorolavmrk <olavmrk@a716ebb1-153a-0410-b759-cfb97c6a1b53>2014-06-20 11:24:38 +0000
committerolavmrk <olavmrk@a716ebb1-153a-0410-b759-cfb97c6a1b53>2014-06-20 11:24:38 +0000
commit8dacb0388763ec4da5198b2d6063b45067e16c21 (patch)
treec026be0b1da1e8ccd0c954f34776aa29018c83fd
parent66f6d2cb087e471d8599c8e221745b6e055f5d12 (diff)
downloadmod_auth_mellon-8dacb0388763ec4da5198b2d6063b45067e16c21.zip
mod_auth_mellon-8dacb0388763ec4da5198b2d6063b45067e16c21.tar.gz
mod_auth_mellon-8dacb0388763ec4da5198b2d6063b45067e16c21.tar.xz
Introduce dynamic memory pool for sessions
This pool has a fixed size and the aim is to avoid arbitrary limits on entry's components, while maintaining an overall fixed entry size. Accessors function for a storage unit are provided for future use. Signed-off-by: Simo Sorce <simo@redhat.com> git-svn-id: https://modmellon.googlecode.com/svn/trunk@231 a716ebb1-153a-0410-b759-cfb97c6a1b53
-rw-r--r--README7
-rw-r--r--auth_mellon.h14
-rw-r--r--auth_mellon_cache.c94
-rw-r--r--auth_mellon_config.c12
-rw-r--r--mod_auth_mellon.c6
5 files changed, 132 insertions, 1 deletions
diff --git a/README b/README
index eb48deb..2381713 100644
--- a/README
+++ b/README
@@ -97,6 +97,13 @@ for mod_auth_mellon. The following is an example configuration:
# Default: MellonCacheSize 100
MellonCacheSize 100
+# MellonCacheEntrySize sets the maximum size for a single session entry in
+# bytes. When mod_auth_mellon reaches this limit, it cannot store any more
+# data in the session and will return an error. The minimum entry size is
+# 65536 bytes, values lower than that will be ignored and the minimum will
+# be used.
+# Default: MellonCacheEntrySize 196608
+
# MellonLockFile is the full path to a file used for synchronizing access
# to the session data. The path should only be used by one instance of
# apache at a time. The server must be restarted before any changes to this
diff --git a/auth_mellon.h b/auth_mellon.h
index 8347013..5156851 100644
--- a/auth_mellon.h
+++ b/auth_mellon.h
@@ -78,6 +78,8 @@
#define AM_CACHE_MAX_LASSO_IDENTITY_SIZE 1024
#define AM_CACHE_MAX_LASSO_SESSION_SIZE 32768
#define AM_CACHE_MAX_LASSO_SAML_RESPONSE_SIZE 65536
+#define AM_CACHE_DEFAULT_ENTRY_SIZE 196608
+#define AM_CACHE_MIN_ENTRY_SIZE 65536
/* This is the length of the id we use (for session IDs and
@@ -101,12 +103,15 @@ typedef struct am_mod_cfg_rec {
int post_count;
apr_size_t post_size;
+ int entry_size;
+
/* These variables can't be allowed to change after the session store
* has been initialized. Therefore we copy them before initializing
* the session store.
*/
int init_cache_size;
const char *init_lock_file;
+ apr_size_t init_entry_size;
apr_shm_t *cache;
apr_global_mutex_t *lock;
@@ -240,6 +245,9 @@ typedef struct am_dir_cfg_rec {
LassoServer *server;
} am_dir_cfg_rec;
+typedef struct am_cache_storage_t {
+ apr_uintptr_t ptr;
+} am_cache_storage_t;
typedef struct am_cache_env_t {
char varname[AM_CACHE_VARSIZE];
@@ -262,6 +270,10 @@ typedef struct am_cache_entry_t {
char lasso_saml_response[AM_CACHE_MAX_LASSO_SAML_RESPONSE_SIZE];
am_cache_env_t env[AM_CACHE_ENVSIZE];
+
+ apr_size_t pool_size;
+ apr_size_t pool_used;
+ char pool[];
} am_cache_entry_t;
typedef enum {
@@ -322,6 +334,8 @@ void am_cookie_delete(request_rec *r);
am_cache_entry_t *am_cache_lock(server_rec *s,
am_cache_key_t type, const char *key);
+const char *am_cache_entry_get_string(am_cache_entry_t *e,
+ am_cache_storage_t *slot);
am_cache_entry_t *am_cache_new(server_rec *s, const char *key);
void am_cache_unlock(server_rec *s, am_cache_entry_t *entry);
diff --git a/auth_mellon_cache.c b/auth_mellon_cache.c
index 3923569..0d64a82 100644
--- a/auth_mellon_cache.c
+++ b/auth_mellon_cache.c
@@ -113,6 +113,96 @@ am_cache_entry_t *am_cache_lock(server_rec *s,
return NULL;
}
+static inline void am_cache_storage_null(am_cache_storage_t *slot)
+{
+ slot->ptr = 0;
+}
+
+static inline apr_size_t am_cache_entry_pool_left(am_cache_entry_t *e)
+{
+ return e->pool_size - e->pool_used;
+}
+
+static inline apr_size_t am_cache_entry_pool_size(am_mod_cfg_rec *cfg)
+{
+ return cfg->init_entry_size - sizeof(am_cache_entry_t);
+}
+
+/* This function sets a string into the specified storage on the entry.
+ *
+ * NOTE: The string pointer may be NULL, in that case storage is freed
+ * and set to NULL.
+ *
+ * Parametrs:
+ * am_cache_entry_t *entry Pointer to an entry
+ * am_cache_storage_t *slot Pointer to storage
+ * const char *string Pointer to a replacement string
+ *
+ * Returns:
+ * 0 on success, HTTP_INTERNAL_SERVER_ERROR on error.
+ */
+static int am_cache_entry_store_string(am_cache_entry_t *entry,
+ am_cache_storage_t *slot,
+ const char *string)
+{
+ char *datastr = NULL;
+ apr_size_t datalen = 0;
+ apr_size_t str_len = 0;
+
+ if (string == NULL) return 0;
+
+ if (slot->ptr != 0) {
+ datastr = &entry->pool[slot->ptr];
+ datalen = strlen(datastr) + 1;
+ }
+ str_len = strlen(string) + 1;
+ if (str_len - datalen <= 0) {
+ memcpy(datastr, string, str_len);
+ return 0;
+ }
+
+ /* recover space if slot happens to point to the last allocated space */
+ if (slot->ptr + datalen == entry->pool_used) {
+ entry->pool_used -= datalen;
+ slot->ptr = 0;
+ }
+
+ if (am_cache_entry_pool_left(entry) < str_len) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "apr_cache_entry_store_string() asked %zd available: %zd. "
+ "It may be a good idea to increase MellonCacheEntrySize.",
+ str_len, am_cache_entry_pool_left(entry));
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ slot->ptr = entry->pool_used;
+ datastr = &entry->pool[slot->ptr];
+ memcpy(datastr, string, str_len);
+ entry->pool_used += str_len;
+ return 0;
+}
+
+/* Returns a pointer to the string in the storage slot specified
+ *
+ *
+ * Parametrs:
+ * am_cache_entry_t *entry Pointer to an entry
+ * am_cache_storage_t *slot Pointer to storage slot
+ *
+ * Returns:
+ * A string or NULL if the slot is empty.
+ */
+const char *am_cache_entry_get_string(am_cache_entry_t *e,
+ am_cache_storage_t *slot)
+{
+ char *ret = NULL;
+
+ if (slot->ptr != 0) {
+ ret = &e->pool[slot->ptr];
+ }
+
+ return ret;
+}
/* This function locks the session table and creates a new session entry.
* It will first attempt to locate a free session. If it doesn't find a
@@ -227,6 +317,10 @@ am_cache_entry_t *am_cache_new(server_rec *s, const char *key)
t->lasso_identity[0] = '\0';
t->lasso_session[0] = '\0';
+ t->pool_size = am_cache_entry_pool_size(mod_cfg);
+ t->pool[0] = '\0';
+ t->pool_used = 1;
+
return t;
}
diff --git a/auth_mellon_config.c b/auth_mellon_config.c
index 36f6b96..0de3f96 100644
--- a/auth_mellon_config.c
+++ b/auth_mellon_config.c
@@ -863,6 +863,15 @@ const command_rec auth_mellon_commands[] = {
" take effect. The default value is 100."
),
AP_INIT_TAKE1(
+ "MellonCacheEntrySize",
+ am_set_module_config_int_slot,
+ (void *)APR_OFFSETOF(am_mod_cfg_rec, entry_size),
+ RSRC_CONF,
+ "The maximum size for a single session entry. You must"
+ " restart the server before any changes to this directive will"
+ " take effect. The default value is 192KiB."
+ ),
+ AP_INIT_TAKE1(
"MellonLockFile",
am_set_module_config_file_slot,
(void *)APR_OFFSETOF(am_mod_cfg_rec, lock_file),
@@ -1571,8 +1580,11 @@ void *auth_mellon_server_config(apr_pool_t *p, server_rec *s)
mod->post_count = post_count;
mod->post_size = post_size;
+ mod->entry_size = AM_CACHE_DEFAULT_ENTRY_SIZE;
+
mod->init_cache_size = 0;
mod->init_lock_file = NULL;
+ mod->init_entry_size = 0;
mod->cache = NULL;
mod->lock = NULL;
diff --git a/mod_auth_mellon.c b/mod_auth_mellon.c
index 86949a4..fc34962 100644
--- a/mod_auth_mellon.c
+++ b/mod_auth_mellon.c
@@ -88,9 +88,13 @@ static int am_global_init(apr_pool_t *conf, apr_pool_t *log,
*/
mod->init_cache_size = mod->cache_size;
mod->init_lock_file = apr_pstrdup(conf, mod->lock_file);
+ mod->init_entry_size = mod->entry_size;
+ if (mod->init_entry_size < AM_CACHE_MIN_ENTRY_SIZE) {
+ mod->init_entry_size = AM_CACHE_MIN_ENTRY_SIZE;
+ }
/* find out the memory size of the cache */
- mem_size = sizeof(am_cache_entry_t) * mod->init_cache_size;
+ mem_size = mod->init_entry_size * mod->init_cache_size;
/* Create the shared memory, exit if it fails. */